X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/f9998046a3b0898810f8ed3b6368643b4c5874d9..6191429b509f0bb055a27f44a30b6b0711c4a82d:/generator.c diff --git a/generator.c b/generator.c index e91e3a6f..d93529cf 100644 --- a/generator.c +++ b/generator.c @@ -81,7 +81,6 @@ extern int copy_dest; extern int link_dest; extern int whole_file; extern int list_only; -extern int new_root_dir; extern int read_batch; extern int safe_symlinks; extern long block_size; /* "long" because popt can't set an int32. */ @@ -881,7 +880,7 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx, if (!hard_link_one(file, fname, cmpbuf, 1)) goto try_a_copy; if (preserve_hard_links && F_IS_HLINKED(file)) - finish_hard_link(file, fname, &sxp->st, itemizing, code, j); + finish_hard_link(file, fname, ndx, &sxp->st, itemizing, code, j); if (itemizing && (verbose > 1 || stdout_format_has_i > 1)) { itemize(cmpbuf, file, ndx, 1, sxp, ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS, @@ -923,7 +922,7 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx, } #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && F_IS_HLINKED(file)) - finish_hard_link(file, fname, &sxp->st, itemizing, code, -1); + finish_hard_link(file, fname, ndx, &sxp->st, itemizing, code, -1); #endif return -2; } @@ -1051,7 +1050,7 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx, return j; } if (preserve_hard_links && F_IS_HLINKED(file)) - finish_hard_link(file, fname, NULL, itemizing, code, -1); + finish_hard_link(file, fname, ndx, NULL, itemizing, code, -1); } else #endif match_level = 2; @@ -1103,6 +1102,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, char *fnamecmp, *partialptr, *backupptr = NULL; char fnamecmpbuf[MAXPATHLEN]; uchar fnamecmp_type; + int implied_dirs_are_missing = relative_paths && !implied_dirs && !inc_recurse; int del_opts = delete_mode || force_delete ? DEL_RECURSE : 0; if (list_only) @@ -1114,7 +1114,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, if (server_filter_list.head) { if (excluded_below >= 0) { if (F_DEPTH(file) > excluded_below - && (implied_dirs || f_name_has_prefix(file, excluded_dir))) + && (!implied_dirs_are_missing || f_name_has_prefix(file, excluded_dir))) goto skipping; excluded_below = -1; } @@ -1136,7 +1136,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, if (missing_below >= 0) { if (F_DEPTH(file) <= missing_below - || (!implied_dirs && !f_name_has_prefix(file, missing_dir))) { + || (implied_dirs_are_missing && !f_name_has_prefix(file, missing_dir))) { if (dry_run) dry_run--; missing_below = -1; @@ -1213,6 +1213,22 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, } if (S_ISDIR(file->mode)) { + if (!implied_dirs && !(file->flags & FLAG_XFER_DIR)) + goto cleanup; + if (inc_recurse && ndx != cur_flist->ndx_start - 1) { + /* In inc_recurse mode we want ot make sure any missing + * directories get created while we're still processing + * the parent dir (which allows us to touch the parent + * dir's mtime right away). We will handle the dir in + * full later (right before we handle its contents). */ + if (statret == 0 + && (S_ISDIR(sx.st.st_mode) + || delete_item(fname, sx.st.st_mode, "directory", del_opts) != 0)) + goto cleanup; /* Any errors get reported later. */ + if (do_mkdir(fname, file->mode & 0700) == 0) + file->flags |= FLAG_DIR_CREATED; + goto cleanup; + } /* The file to be received is a directory, so we need * to prepare appropriately. If there is already a * file of that name and it is *not* a directory, then @@ -1230,11 +1246,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, } real_ret = statret; real_sx = sx; - if (new_root_dir) { - if (*fname == '.' && fname[1] == '\0') - statret = -1; - new_root_dir = 0; - } + if (file->flags & FLAG_DIR_CREATED) + statret = -1; if (!preserve_perms) { /* See comment in non-dir code below. */ file->mode = dest_mode(file->mode, sx.st.st_mode, dflt_perms, statret == 0); @@ -1343,7 +1356,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, itemize(fname, file, ndx, 0, &sx, 0, 0, NULL); #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && F_IS_HLINKED(file)) - finish_hard_link(file, fname, &sx.st, itemizing, code, -1); + finish_hard_link(file, fname, ndx, &sx.st, itemizing, code, -1); #endif if (remove_source_files == 1) goto return_with_success; @@ -1370,8 +1383,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, statret = 1; } #ifdef SUPPORT_HARD_LINKS - if (preserve_hard_links && F_HLINK_NOT_LAST(file)) + if (preserve_hard_links && F_HLINK_NOT_LAST(file)) { + cur_flist->in_progress++; goto cleanup; + } #endif if (do_symlink(sl, fname) != 0) { rsyserr(FERROR, errno, "symlink %s -> \"%s\" failed", @@ -1386,7 +1401,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, rprintf(code, "%s -> %s\n", fname, sl); #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && F_IS_HLINKED(file)) - finish_hard_link(file, fname, NULL, itemizing, code, -1); + finish_hard_link(file, fname, ndx, NULL, itemizing, code, -1); #endif /* This does not check remove_source_files == 1 * because this is one of the items that the old @@ -1422,7 +1437,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, itemize(fname, file, ndx, 0, &sx, 0, 0, NULL); #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && F_IS_HLINKED(file)) - finish_hard_link(file, fname, &sx.st, itemizing, code, -1); + finish_hard_link(file, fname, ndx, &sx.st, itemizing, code, -1); #endif if (remove_source_files == 1) goto return_with_success; @@ -1447,8 +1462,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, statret = 1; } #ifdef SUPPORT_HARD_LINKS - if (preserve_hard_links && F_HLINK_NOT_LAST(file)) + if (preserve_hard_links && F_HLINK_NOT_LAST(file)) { + cur_flist->in_progress++; goto cleanup; + } #endif if (verbose > 2) { rprintf(FINFO, "mknod(%s, 0%o, [%ld,%ld])\n", @@ -1468,7 +1485,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, rprintf(code, "%s\n", fname); #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && F_IS_HLINKED(file)) - finish_hard_link(file, fname, NULL, itemizing, code, -1); + finish_hard_link(file, fname, ndx, NULL, itemizing, code, -1); #endif if (remove_source_files == 1) goto return_with_success; @@ -1567,8 +1584,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, if (statret != 0) { #ifdef SUPPORT_HARD_LINKS - if (preserve_hard_links && F_HLINK_NOT_LAST(file)) + if (preserve_hard_links && F_HLINK_NOT_LAST(file)) { + cur_flist->in_progress++; goto cleanup; + } #endif if (stat_errno == ENOENT) goto notify_others; @@ -1594,7 +1613,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, itemize(fnamecmp, file, ndx, statret, &sx, 0, 0, NULL); #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && F_IS_HLINKED(file)) - finish_hard_link(file, fname, &sx.st, itemizing, code, -1); + finish_hard_link(file, fname, ndx, &sx.st, itemizing, code, -1); #endif if (remove_source_files != 1) goto cleanup; @@ -1630,8 +1649,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, pretend_missing: /* pretend the file didn't exist */ #ifdef SUPPORT_HARD_LINKS - if (preserve_hard_links && F_HLINK_NOT_LAST(file)) + if (preserve_hard_links && F_HLINK_NOT_LAST(file)) { + cur_flist->in_progress++; goto cleanup; + } #endif statret = real_ret = -1; goto notify_others; @@ -1705,7 +1726,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, if (!do_xfers) { #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && F_IS_HLINKED(file)) - finish_hard_link(file, fname, &sx.st, itemizing, code, -1); + finish_hard_link(file, fname, ndx, &sx.st, itemizing, code, -1); #endif goto cleanup; } @@ -1760,7 +1781,8 @@ static void touch_up_dirs(struct file_list *flist, int ndx) * transfer and/or re-set any tweaked modified-time values. */ for (i = start; i <= end; i++, counter++) { file = flist->files[i]; - if (!S_ISDIR(file->mode)) + if (!S_ISDIR(file->mode) + || (relative_paths && !implied_dirs && !(file->flags & FLAG_XFER_DIR))) continue; if (verbose > 3) { fname = f_name(file, NULL); @@ -1793,9 +1815,9 @@ void check_for_finished_files(int itemizing, enum logcode code, int check_redo) while (preserve_hard_links && (ndx = get_hlink_num()) != -1) { flist = flist_for_ndx(ndx); assert(flist != NULL); - file = flist->files[ndx]; + file = flist->files[ndx - flist->ndx_start]; assert(file->flags & FLAG_HLINKED); - finish_hard_link(file, f_name(file, fbuf), NULL, itemizing, code, -1); + finish_hard_link(file, f_name(file, fbuf), ndx, NULL, itemizing, code, -1); } #endif @@ -1847,6 +1869,11 @@ void check_for_finished_files(int itemizing, enum logcode code, int check_redo) maybe_flush_socket(1); } + if (delete_during == 2 || !dir_tweaking) { + /* Skip directory touch-up. */ + } else if (first_flist->ndx_start != 0) + touch_up_dirs(dir_flist, first_flist->parent_ndx); + flist_free(first_flist); /* updates first_flist */ } } @@ -1912,6 +1939,13 @@ void generate_files(int f_out, const char *local_name) dflt_perms = (ACCESSPERMS & ~orig_umask); do { +#ifdef SUPPORT_HARD_LINKS + if (preserve_hard_links && inc_recurse) { + while (!flist_eof && file_total < FILECNT_LOOKAHEAD/2) + wait_for_receiver(); + } +#endif + if (inc_recurse && cur_flist->ndx_start) { struct file_struct *fp = dir_flist->files[cur_flist->parent_ndx]; f_name(fp, fbuf); @@ -1935,14 +1969,6 @@ void generate_files(int f_out, const char *local_name) if (!F_IS_ACTIVE(file)) continue; - if (inc_recurse && S_ISDIR(file->mode)) { - /* Regular dirs are at the end, so we can stop. */ - if (F_DEPTH(file)) - break; - /* A dot-dir is at the start, so just skip it. */ - continue; - } - #ifdef ICONV_OPTION if (ic_ndx) ndx = F_NDX(file); @@ -2024,7 +2050,8 @@ void generate_files(int f_out, const char *local_name) if (delete_after && !solo_file && file_total > 0) do_delete_pass(); - if ((need_retouch_dir_perms || need_retouch_dir_times) && dir_tweaking) + if ((need_retouch_dir_perms || need_retouch_dir_times) + && dir_tweaking && (!inc_recurse || delete_during == 2)) touch_up_dirs(dir_flist, -1); if (max_delete >= 0 && deletion_count > max_delete) {