diff --git a/flist.c b/flist.c index 523a5766..cb24fcdd 100644 --- a/flist.c +++ b/flist.c @@ -221,6 +221,35 @@ static int readlink_stat(const char *path, STRUCT_STAT *stp, char *linkbuf) #endif } +static int readlink_stat_realinfo(const char *path, STRUCT_STAT *stp, char *linkbuf) +{ + int ret = readlink_stat(path, stp, linkbuf); + if(ret != 0){ + return ret; + } + if( S_ISREG(stp->st_mode) && am_daemon && am_sender && lp_real_file_prefix(module_id) ){ + int fd = open(path, O_RDONLY); + if(fd < 0){ + return -1; + } + unsigned char buf[8]; + uint64_t file_size = 0; + ret = read(fd, buf, 8); + close(fd); + if(ret < 0){ + return -1; + } else if(ret != 8){ + errno = EINVAL; + return -1; + } + for (size_t i = 0; i < 8; i++) { + file_size += buf[i] * ((uint64_t) 1 << i * 8); + } + stp->st_size = file_size; + } + return 0; +} + int link_stat(const char *path, STRUCT_STAT *stp, int follow_dirlinks) { #ifdef SUPPORT_LINKS @@ -1173,7 +1202,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, * dir, or a request to delete a specific file. */ st = *stp; *linkname = '\0'; /* make IBM code checker happy */ - } else if (readlink_stat(thisname, &st, linkname) != 0) { + } else if (readlink_stat_realinfo(thisname, &st, linkname) != 0) { int save_errno = errno; /* See if file is excluded before reporting an error. */ if (filter_level != NO_FILTERS @@ -1309,7 +1338,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, if (st.ST_MTIME_NSEC && protocol_version >= 31) extra_len += EXTRA_LEN; #endif - if(S_ISREG(st.st_mode) && am_sender && only_send_attrs){ + if(S_ISREG(st.st_mode) && am_sender && only_send_attrs){ st.st_size = 8; } #if SIZEOF_CAPITAL_OFF_T >= 8 diff --git a/loadparm.c b/loadparm.c index 6d75b4dd..930ec3e3 100644 --- a/loadparm.c +++ b/loadparm.c @@ -131,8 +131,9 @@ typedef struct { char *secrets_file; char *temp_dir; char *uid; + char *real_file_prefix; /* NOTE: update this macro if the last char* variable changes! */ -#define LOCAL_STRING_COUNT() (offsetof(local_vars, uid) / sizeof (char*) + 1) +#define LOCAL_STRING_COUNT() (offsetof(local_vars, real_file_prefix) / sizeof (char*) + 1) int max_connections; int max_verbosity; @@ -207,6 +208,7 @@ static const all_vars Defaults = { /* secrets_file; */ NULL, /* temp_dir; */ NULL, /* uid; */ NULL, + /* real_file_prefix; */ NULL, /* max_connections; */ 0, /* max_verbosity; */ 1, @@ -361,6 +363,7 @@ static struct parm_struct parm_table[] = {"timeout", P_INTEGER,P_LOCAL, &Vars.l.timeout, NULL,0}, {"transfer logging", P_BOOL, P_LOCAL, &Vars.l.transfer_logging, NULL,0}, {"uid", P_STRING, P_LOCAL, &Vars.l.uid, NULL,0}, + {"real file prefix", P_STRING, P_LOCAL, &Vars.l.real_file_prefix, NULL,0}, {"use chroot", P_BOOL, P_LOCAL, &Vars.l.use_chroot, NULL,0}, {"write only", P_BOOL, P_LOCAL, &Vars.l.write_only, NULL,0}, {NULL, P_BOOL, P_NONE, NULL, NULL,0} @@ -476,6 +479,7 @@ FN_LOCAL_STRING(lp_refuse_options, refuse_options) FN_LOCAL_STRING(lp_secrets_file, secrets_file) FN_LOCAL_STRING(lp_temp_dir, temp_dir) FN_LOCAL_STRING(lp_uid, uid) +FN_LOCAL_STRING(lp_real_file_prefix, real_file_prefix) FN_LOCAL_INTEGER(lp_max_connections, max_connections) FN_LOCAL_INTEGER(lp_max_verbosity, max_verbosity) diff --git a/sender.c b/sender.c index e257f62d..9f405549 100644 --- a/sender.c +++ b/sender.c @@ -25,6 +25,7 @@ extern int do_xfers; extern int am_server; extern int am_daemon; +extern int am_sender; extern int inc_recurse; extern int log_before_transfer; extern int stdout_format_has_i; @@ -48,6 +49,8 @@ extern struct stats stats; extern struct file_list *cur_flist, *first_flist, *dir_flist; extern int only_send_attrs; +extern int module_id; + BOOL extra_flist_sending_enabled; /** @@ -335,8 +338,31 @@ void send_files(int f_in, int f_out) rprintf(FERROR_XFER, "receive_sums failed\n"); exit_cleanup(RERR_PROTOCOL); } - - fd = do_open(fname, O_RDONLY, 0); + char (*ptr_real_fname)[] = &fname; + if(am_daemon && am_sender){ + const char *real_path_prefix = lp_real_file_prefix(module_id); + if(real_path_prefix){ + int real_path_prefix_length = strlen(real_path_prefix); + char now_cwd[MAXPATHLEN]; + getcwd(now_cwd, MAXPATHLEN); + int cwd_length = strlen(now_cwd); + if(real_path_prefix_length + cwd_length + strlen(fname) + 1 >= MAXPATHLEN - 1){ + io_error |= IOERR_GENERAL; + rsyserr(FERROR_XFER, ENOENT, + "send_files_real failed to open %s", + full_fname(fname)); + goto file_open_error; + }else{ + char real_fname[MAXPATHLEN+10]; + strncpy(real_fname, real_path_prefix, MAXPATHLEN); + strncat(real_fname, now_cwd, MAXPATHLEN - real_path_prefix_length); + strncat(real_fname, "/", 1); + strncat(real_fname, fname, MAXPATHLEN - real_path_prefix_length - cwd_length); + ptr_real_fname = &real_fname; + } + } + } + fd = do_open(*ptr_real_fname, O_RDONLY, 0); if (fd == -1) { if (errno == ENOENT) { enum logcode c = am_daemon @@ -351,6 +377,7 @@ void send_files(int f_in, int f_out) "send_files failed to open %s", full_fname(fname)); } +file_open_error: free_sums(s); if (protocol_version >= 30) send_msg_int(MSG_NO_SEND, ndx);