X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/4e42173508ccb02a1610b40456f778ee9cecabc3..b58f5e17ed35c68e10b88869d1e10d5378bd40e0:/flist.c diff --git a/flist.c b/flist.c index 733344cc..b8cc9fef 100644 --- a/flist.c +++ b/flist.c @@ -63,6 +63,9 @@ extern int copy_links; extern int copy_unsafe_links; extern int protocol_version; extern int sanitize_paths; +extern int munge_symlinks; +extern int need_unsorted_flist; +extern int unsort_ndx; extern struct stats stats; extern char *filesfrom_host; @@ -74,9 +77,7 @@ extern struct filter_list_struct filter_list; extern struct filter_list_struct server_filter_list; #ifdef ICONV_OPTION -extern int ic_ndx; extern int filesfrom_convert; -extern int need_unsorted_flist; extern iconv_t ic_send, ic_recv; #endif @@ -200,6 +201,11 @@ static int readlink_stat(const char *path, STRUCT_STAT *stp, char *linkbuf) } return x_stat(path, stp, NULL); } + if (munge_symlinks && am_sender && llen > SYMLINK_PREFIX_LEN + && strncmp(linkbuf, SYMLINK_PREFIX, SYMLINK_PREFIX_LEN) == 0) { + memmove(linkbuf, linkbuf + SYMLINK_PREFIX_LEN, + llen - SYMLINK_PREFIX_LEN + 1); + } } return 0; #else @@ -671,7 +677,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist, clean_fname(thisname, 0); if (sanitize_paths) - sanitize_path(thisname, thisname, "", 0, NULL); + sanitize_path(thisname, thisname, "", 0); if ((basename = strrchr(thisname, '/')) != NULL) { int len = basename++ - thisname; @@ -725,8 +731,8 @@ static struct file_struct *recv_file_entry(struct file_list *flist, if (protocol_version >= 30) { modtime = read_varlong(f, 4); #if SIZEOF_TIME_T < SIZEOF_INT64 - if ((modtime > INT_MAX || modtime < INT_MIN) && !am_generator) { - rprintf(FERROR, + if (!am_generator && (int64)(time_t)modtime != modtime) { + rprintf(FERROR_XFER, "Time value of %s truncated on receiver.\n", lastname); } @@ -794,6 +800,8 @@ static struct file_struct *recv_file_entry(struct file_list *flist, linkname_len - 1); overflow_exit("recv_file_entry"); } + if (munge_symlinks) + linkname_len += SYMLINK_PREFIX_LEN; } else #endif @@ -821,11 +829,6 @@ static struct file_struct *recv_file_entry(struct file_list *flist, if (file_length > 0xFFFFFFFFu && S_ISREG(mode)) extra_len += EXTRA_LEN; -#if EXTRA_ROUNDING > 0 - if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN)) - extra_len = (extra_len | (EXTRA_ROUNDING * EXTRA_LEN)) + EXTRA_LEN; -#endif - if (inc_recurse && S_ISDIR(mode)) { if (one_file_system) { /* Room to save the dir's device for -x */ @@ -835,6 +838,11 @@ static struct file_struct *recv_file_entry(struct file_list *flist, } else pool = flist->file_pool; +#if EXTRA_ROUNDING > 0 + if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN)) + extra_len = (extra_len | (EXTRA_ROUNDING * EXTRA_LEN)) + EXTRA_LEN; +#endif + alloc_len = FILE_STRUCT_LEN + extra_len + basename_len + linkname_len; bp = pool_alloc(pool, alloc_len, "recv_file_entry"); @@ -864,10 +872,8 @@ static struct file_struct *recv_file_entry(struct file_list *flist, F_GROUP(file) = gid; file->flags |= gid_flags; } -#ifdef ICONV_OPTION - if (ic_ndx) + if (unsort_ndx) F_NDX(file) = flist->used + flist->ndx_start; -#endif if (basename != thisname) { file->dirname = lastdir; @@ -916,10 +922,16 @@ static struct file_struct *recv_file_entry(struct file_list *flist, if (first_hlink_ndx >= flist->ndx_start) { struct file_struct *first = flist->files[first_hlink_ndx - flist->ndx_start]; memcpy(bp, F_SYMLINK(first), linkname_len); - } else + } else if (munge_symlinks) { + strlcpy(bp, SYMLINK_PREFIX, linkname_len); + bp += SYMLINK_PREFIX_LEN; + linkname_len -= SYMLINK_PREFIX_LEN; + read_sbuf(f, bp, linkname_len - 1); + } else { read_sbuf(f, bp, linkname_len - 1); - if (sanitize_paths) - sanitize_path(bp, bp, "", lastdir_depth, NULL); + if (sanitize_paths) + sanitize_path(bp, bp, "", lastdir_depth); + } } #endif @@ -1010,7 +1022,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, } clean_fname(thisname, 0); if (sanitize_paths) - sanitize_path(thisname, thisname, "", 0, NULL); + sanitize_path(thisname, thisname, "", 0); if (stp && S_ISDIR(stp->st_mode)) { st = *stp; /* Needed for "symlink/." with --relative. */ @@ -1031,20 +1043,20 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, if (copy_links && x_lstat(thisname, &st, NULL) == 0 && S_ISLNK(st.st_mode)) { io_error |= IOERR_GENERAL; - rprintf(FERROR, "symlink has no referent: %s\n", + rprintf(FERROR_XFER, "symlink has no referent: %s\n", full_fname(thisname)); } else #endif { enum logcode c = am_daemon && protocol_version < 28 - ? FERROR : FINFO; + ? FERROR : FWARNING; io_error |= IOERR_VANISHED; rprintf(c, "file has vanished: %s\n", full_fname(thisname)); } } else { io_error |= IOERR_GENERAL; - rsyserr(FERROR, save_errno, "readlink %s failed", + rsyserr(FERROR_XFER, save_errno, "readlink %s failed", full_fname(thisname)); } return NULL; @@ -1226,10 +1238,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, if (basename_len == 0+1) return NULL; -#ifdef ICONV_OPTION - if (ic_ndx) + if (unsort_ndx) F_NDX(file) = dir_count - 1; -#endif return file; } @@ -1314,7 +1324,7 @@ static void send_if_directory(int f, struct file_list *flist, fbuf[--len] = '\0'; if (len >= MAXPATHLEN - 1) { io_error |= IOERR_GENERAL; - rprintf(FERROR, "skipping long-named directory: %s\n", + rprintf(FERROR_XFER, "skipping long-named directory: %s\n", full_fname(fbuf)); return; } @@ -1453,7 +1463,7 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len, if (!(d = opendir(fbuf))) { io_error |= IOERR_GENERAL; - rsyserr(FERROR, errno, "opendir %s failed", full_fname(fbuf)); + rsyserr(FERROR_XFER, errno, "opendir %s failed", full_fname(fbuf)); return; } @@ -1490,7 +1500,7 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len, if (errno) { io_error |= IOERR_GENERAL; - rsyserr(FERROR, errno, "readdir(%s)", full_fname(fbuf)); + rsyserr(FERROR_XFER, errno, "readdir(%s)", full_fname(fbuf)); } closedir(d); @@ -1600,7 +1610,7 @@ static void send1extra(int f, struct file_struct *file, struct file_list *flist) STRUCT_STAT st; if (link_stat(fbuf, &st, copy_dirlinks) != 0) { io_error |= IOERR_GENERAL; - rsyserr(FERROR, errno, "link_stat %s failed", + rsyserr(FERROR_XFER, errno, "link_stat %s failed", full_fname(fbuf)); return; } @@ -1637,7 +1647,7 @@ static void send1extra(int f, struct file_struct *file, struct file_list *flist) STRUCT_STAT st; if (link_stat(fbuf, &st, 1) != 0) { io_error |= IOERR_GENERAL; - rsyserr(FERROR, errno, "link_stat %s failed", + rsyserr(FERROR_XFER, errno, "link_stat %s failed", full_fname(fbuf)); continue; } @@ -1654,19 +1664,17 @@ void send_extra_file_list(int f, int at_least) struct file_list *flist; int64 start_write; uint16 prev_flags; - int future_cnt, save_io_error = io_error; + int old_cnt, save_io_error = io_error; if (flist_eof) return; /* Keep sending data until we have the requested number of * files in the upcoming file-lists. */ - if (cur_flist->next) { - flist = first_flist->prev; /* the newest flist */ - future_cnt = flist->ndx_end - cur_flist->next->ndx_start + 1; - } else - future_cnt = 0; - while (future_cnt < at_least) { + old_cnt = cur_flist->used; + for (flist = first_flist; flist != cur_flist; flist = flist->next) + old_cnt += flist->used; + while (file_total - old_cnt < at_least) { struct file_struct *file = dir_flist->sorted[send_dir_ndx]; int dir_ndx, dstart = dir_count; const char *pathname = F_PATHNAME(file); @@ -1675,11 +1683,9 @@ void send_extra_file_list(int f, int at_least) flist = flist_new(0, "send_extra_file_list"); start_write = stats.total_written; -#ifdef ICONV_OPTION - if (ic_ndx) + if (unsort_ndx) dir_ndx = F_NDX(file); else -#endif dir_ndx = send_dir_ndx; write_ndx(f, NDX_FLIST_OFFSET - dir_ndx); flist->parent_ndx = dir_ndx; @@ -1705,26 +1711,24 @@ void send_extra_file_list(int f, int at_least) write_byte(f, 0); -#ifdef ICONV_OPTION if (need_unsorted_flist) { if (!(flist->sorted = new_array(struct file_struct *, flist->used))) out_of_memory("send_extra_file_list"); memcpy(flist->sorted, flist->files, flist->used * sizeof (struct file_struct*)); } else -#endif flist->sorted = flist->files; clean_flist(flist, 0); - flist->ndx_end = flist->ndx_start + flist->used - 1 - - (dir_count - dstart); + flist->ndx_end = flist->ndx_start + flist->used - 1; + if (!need_unsorted_flist) + flist->ndx_end -= (dir_count - dstart); add_dirs_to_tree(send_dir_ndx, flist, dir_count - dstart); flist_done_allocating(flist); file_total += flist->used; - future_cnt += flist->used; stats.flist_size += stats.total_written - start_write; stats.num_files += flist->used; if (verbose > 3) @@ -1801,7 +1805,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) disable_buffering = io_start_buffering_out(f); if (filesfrom_fd >= 0) { if (argv[0] && !push_dir(argv[0], 0)) { - rsyserr(FERROR, errno, "push_dir %s failed in %s", + rsyserr(FERROR_XFER, errno, "push_dir %s failed in %s", full_fname(argv[0]), curr_dir); exit_cleanup(RERR_FILESELECT); } @@ -1814,13 +1818,13 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) if (use_ff_fd) { if (read_line(filesfrom_fd, fbuf, sizeof fbuf, rl_flags) == 0) break; - sanitize_path(fbuf, fbuf, "", 0, NULL); + sanitize_path(fbuf, fbuf, "", 0); } else { if (argc-- == 0) break; strlcpy(fbuf, *argv++, MAXPATHLEN); if (sanitize_paths) - sanitize_path(fbuf, fbuf, "", 0, NULL); + sanitize_path(fbuf, fbuf, "", 0); } len = strlen(fbuf); @@ -1928,7 +1932,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) if (link_stat(fbuf, &st, copy_dirlinks || name_type != NORMAL_NAME) != 0) { io_error |= IOERR_GENERAL; - rsyserr(FERROR, errno, "link_stat %s failed", + rsyserr(FERROR_XFER, errno, "link_stat %s failed", full_fname(fbuf)); continue; } @@ -2016,7 +2020,6 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) * receiving side to ask for whatever name it kept. For incremental * recursion mode, the sender marks duplicate dirs so that it can * send them together in a single file-list. */ -#ifdef ICONV_OPTION if (need_unsorted_flist) { if (inc_recurse) { if (!(flist->sorted = new_array(struct file_struct *, flist->used))) @@ -2029,9 +2032,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) flist->low = 0; flist->high = flist->used - 1; } - } else -#endif - { + } else { flist->sorted = flist->files; clean_flist(flist, 0); } @@ -2140,7 +2141,7 @@ struct file_list *recv_file_list(int f) file_total += flist->used; flist->ndx_end = flist->ndx_start + flist->used - 1; - if (inc_recurse && flist->ndx_start > 1) + if (inc_recurse && !need_unsorted_flist && flist->ndx_start > 1) flist->ndx_end -= dir_flist->used - dstart; if (verbose > 2) @@ -2149,7 +2150,6 @@ struct file_list *recv_file_list(int f) if (show_filelist_p()) finish_filelist_progress(flist); -#ifdef ICONV_OPTION if (need_unsorted_flist) { /* Create an extra array of index pointers that we can sort for * the generator's use (for wading through the files in sorted @@ -2168,9 +2168,7 @@ struct file_list *recv_file_list(int f) (dir_flist->used - dstart) * sizeof (struct file_struct*)); fsort(dir_flist->sorted + dstart, dir_flist->used - dstart); } - } else -#endif - { + } else { flist->sorted = flist->files; if (inc_recurse && dir_flist->used > dstart) { dir_flist->sorted = dir_flist->files; @@ -2323,7 +2321,7 @@ struct file_list *flist_new(int flags, char *msg) if (!flist->file_pool) out_of_memory(msg); - flist->ndx_start = 1; + flist->ndx_start = inc_recurse ? 1 : 0; first_flist = cur_flist = flist->prev = flist; } else { @@ -2563,7 +2561,7 @@ static void output_flist(struct file_list *flist) rprintf(FINFO, "[%s] flist start=%d, end=%d, used=%d, low=%d, high=%d\n", who, flist->ndx_start, flist->ndx_end, flist->used, flist->low, flist->high); for (i = 0; i < flist->used; i++) { - file = flist->sorted[i]; + file = flist->files[i]; if ((am_root || am_sender) && uid_ndx) { snprintf(uidbuf, sizeof uidbuf, " uid=%u", F_OWNER(file));