X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/71903f601a37392eb8ecb737c10fac78d18f5777..8a6f3fead8667434ef08b3c1de2e3c899f1d70ee:/flist.c diff --git a/flist.c b/flist.c index de27934a..8d4defb9 100644 --- a/flist.c +++ b/flist.c @@ -35,7 +35,6 @@ extern int am_root; extern int am_server; extern int am_daemon; extern int am_sender; -extern int delete_during; extern int always_checksum; extern int module_id; extern int ignore_errors; @@ -65,7 +64,6 @@ extern int copy_links; extern int copy_unsafe_links; extern int protocol_version; extern int sanitize_paths; -extern int delete_excluded; extern int max_delete; extern int orig_umask; extern int list_only; @@ -81,7 +79,6 @@ static struct file_list *received_flist; static dev_t filesystem_dev; /* used to implement -x */ static int deletion_count = 0; /* used to implement --max-delete */ -static int flist_find(struct file_list *flist, struct file_struct *f); static void clean_flist(struct file_list *flist, int strip_root, int no_dups); static void output_flist(struct file_list *flist, const char *whose_list); @@ -978,11 +975,7 @@ void send_file_name(int f, struct file_list *flist, char *fname, struct file_struct *file; char fbuf[MAXPATHLEN]; - /* f is set to -1 when calculating deletion file list */ - file = make_file(fname, flist, - f == -1 && delete_excluded? SERVER_FILTERS : ALL_FILTERS); - - if (!file) + if (!(file = make_file(fname, flist, ALL_FILTERS))) return; maybe_emit_filelist_progress(flist); @@ -1014,7 +1007,10 @@ void send_file_name(int f, struct file_list *flist, char *fname, /* Note that the "recurse" value either contains -1, for infinite recursion, - * or a number >= 0 indicating how many levels of recursion we will allow. */ + * or a number >= 0 indicating how many levels of recursion we will allow. + * This function is normally called by the sender, but the receiving side + * also calls it from delete_in_dir() with f set to -1 so that we just + * construct the file list in memory without sending it over the wire. */ static void send_directory(int f, struct file_list *flist, char *fbuf, unsigned int len) { @@ -1058,13 +1054,6 @@ static void send_directory(int f, struct file_list *flist, } -/* This function is normally called by the sender, but the receiving side - * also uses it to construct one or more file lists if one of the --delete - * options have been specified. The delete_files() function sets f to -1 - * so that we just construct the file list in memory without sending it - * over the wire. It also has the side-effect of ignoring user-excludes if - * delete_excluded is set (so that the delete list includes user-excluded - * files). */ struct file_list *send_file_list(int f, int argc, char *argv[]) { int l; @@ -1076,25 +1065,22 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) int64 start_write; int use_ff_fd = 0; - if (show_filelist_p() && f != -1) + if (show_filelist_p()) start_filelist_progress("building file list"); start_write = stats.total_written; gettimeofday(&start_tv, NULL); - flist = flist_new(f == -1 ? WITHOUT_HLINK : WITH_HLINK, - "send_file_list"); + flist = flist_new(WITH_HLINK, "send_file_list"); - if (f != -1) { - io_start_buffering_out(); - if (filesfrom_fd >= 0) { - if (argv[0] && !push_dir(argv[0])) { - rsyserr(FERROR, errno, "push_dir %s failed", - full_fname(argv[0])); - exit_cleanup(RERR_FILESELECT); - } - use_ff_fd = 1; + io_start_buffering_out(); + if (filesfrom_fd >= 0) { + if (argv[0] && !push_dir(argv[0])) { + rsyserr(FERROR, errno, "push_dir %s failed", + full_fname(argv[0])); + exit_cleanup(RERR_FILESELECT); } + use_ff_fd = 1; } while (1) { @@ -1131,11 +1117,9 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) recurse = 0; if (link_stat(fname, &st, keep_dirlinks) != 0) { - if (f != -1) { - io_error |= IOERR_GENERAL; - rsyserr(FERROR, errno, "link_stat %s failed", - full_fname(fname)); - } + io_error |= IOERR_GENERAL; + rsyserr(FERROR, errno, "link_stat %s failed", + full_fname(fname)); continue; } @@ -1158,7 +1142,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) dir = fname; fname = p + 1; } - } else if (f != -1 && implied_dirs && (p=strrchr(fname,'/')) && p != fname) { + } else if (implied_dirs && (p=strrchr(fname,'/')) && p != fname) { /* this ensures we send the intermediate directories, thus getting their permissions right */ char *lp = lastpath, *fn = fname, *slash = fname; @@ -1231,25 +1215,21 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) } } - if (f != -1) { - gettimeofday(&end_tv, NULL); - stats.flist_buildtime = - (int64)(end_tv.tv_sec - start_tv.tv_sec) * 1000 - + (end_tv.tv_usec - start_tv.tv_usec) / 1000; - if (stats.flist_buildtime == 0) - stats.flist_buildtime = 1; - start_tv = end_tv; - - send_file_entry(NULL, f, 0); - - if (show_filelist_p()) - finish_filelist_progress(flist); - - gettimeofday(&end_tv, NULL); - stats.flist_xfertime = - (int64)(end_tv.tv_sec - start_tv.tv_sec) * 1000 - + (end_tv.tv_usec - start_tv.tv_usec) / 1000; - } + gettimeofday(&end_tv, NULL); + stats.flist_buildtime = (int64)(end_tv.tv_sec - start_tv.tv_sec) * 1000 + + (end_tv.tv_usec - start_tv.tv_usec) / 1000; + if (stats.flist_buildtime == 0) + stats.flist_buildtime = 1; + start_tv = end_tv; + + send_file_entry(NULL, f, 0); + + if (show_filelist_p()) + finish_filelist_progress(flist); + + gettimeofday(&end_tv, NULL); + stats.flist_xfertime = (int64)(end_tv.tv_sec - start_tv.tv_sec) * 1000 + + (end_tv.tv_usec - start_tv.tv_usec) / 1000; if (flist->hlink_pool) { pool_destroy(flist->hlink_pool); @@ -1258,21 +1238,19 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) clean_flist(flist, 0, 0); - if (f != -1) { - /* Now send the uid/gid list. This was introduced in - * protocol version 15 */ - send_uid_list(f); + /* Now send the uid/gid list. This was introduced in + * protocol version 15 */ + send_uid_list(f); - /* send the io_error flag */ - write_int(f, lp_ignore_errors(module_id) ? 0 : io_error); + /* send the io_error flag */ + write_int(f, lp_ignore_errors(module_id) ? 0 : io_error); - io_end_buffering(); - stats.flist_size = stats.total_written - start_write; - stats.num_files = flist->count; - } + io_end_buffering(); + stats.flist_size = stats.total_written - start_write; + stats.num_files = flist->count; if (verbose > 3) - output_flist(flist, f < 0 ? "delete" : who_am_i()); + output_flist(flist, who_am_i()); if (verbose > 2) rprintf(FINFO, "send_file_list done\n"); @@ -1374,7 +1352,7 @@ static int file_compare(struct file_struct **file1, struct file_struct **file2) } -static int flist_find(struct file_list *flist, struct file_struct *f) +int flist_find(struct file_list *flist, struct file_struct *f) { int low = flist->low, high = flist->high; int ret, mid, mid_up; @@ -1537,12 +1515,19 @@ static void output_flist(struct file_list *flist, const char *whose_list) } -enum fnc_state { fnc_DIR, fnc_SLASH, fnc_BASE }; +enum fnc_state { fnc_DIR, fnc_SLASH, fnc_BASE, fnc_TRAILING }; -/* Compare the names of two file_struct entities, just like strcmp() - * would do if it were operating on the joined strings. We assume - * that there are no 0-length strings. - */ +/* Compare the names of two file_struct entities, similar to how strcmp() + * would do if it were operating on the joined strings. The only difference + * is that, beginning with protocol_version 29, a directory name will always + * sort immediately prior to its contents (previously "foo." would sort in + * between directory "foo" and "foo/bar"). We do this by assuming that a dir + * has a trailing slash for comparison purposes, but only if we aren't about + * to match a file of the same name (because we need all identically named + * items to match each other). The dirname component can be an empty string, + * but the basename component cannot (and never is in the current codebase). + * The basename component may be NULL, in which case it is sorted to the end + * of the list (as a removed item). */ int f_name_cmp(struct file_struct *f1, struct file_struct *f2) { int dif; @@ -1592,6 +1577,11 @@ int f_name_cmp(struct file_struct *f1, struct file_struct *f2) c1 = (uchar*)f1->basename; break; case fnc_BASE: + state1 = fnc_TRAILING; + if (protocol_version >= 29 && S_ISDIR(f1->mode)) + c1 = (uchar*)"/"; + break; + case fnc_TRAILING: break; } } @@ -1606,8 +1596,13 @@ int f_name_cmp(struct file_struct *f1, struct file_struct *f2) c2 = (uchar*)f2->basename; break; case fnc_BASE: - if (!*c1) + if (state1 == fnc_TRAILING) return 0; + state2 = fnc_TRAILING; + if (protocol_version >= 29 && S_ISDIR(f2->mode)) + c2 = (uchar*)"/"; + break; + case fnc_TRAILING: break; } } @@ -1738,8 +1733,7 @@ void delete_missing(struct file_list *full_list, struct file_list *dir_list, continue; mode = dir_list->files[i]->mode; if ((j = flist_find(full_list, dir_list->files[i])) < 0 - || (delete_during && S_ISDIR(mode) - && !S_ISDIR(full_list->files[j]->mode))) { + || (S_ISDIR(mode) && !S_ISDIR(full_list->files[j]->mode))) { char *f = f_name(dir_list->files[i]); if (make_backups && (backup_dir || !is_backup_file(f)) && !S_ISDIR(mode)) {