X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/cb8988eb4ab8147ef832c03bc01902ce3be4dcf5..7359a58b5390106df7e4037ec4513055844e1952:/generator.c diff --git a/generator.c b/generator.c index ff31e063..4a3e65ba 100644 --- a/generator.c +++ b/generator.c @@ -58,6 +58,7 @@ extern int update_only; extern int ignore_existing; extern int ignore_non_existing; extern int inplace; +extern int tweak_attrs; extern int append_mode; extern int make_backups; extern int csum_length; @@ -1210,6 +1211,11 @@ static void list_file_entry(struct file_struct *f) } } +static int may_tweak(STRUCT_STAT *st) +{ + return tweak_attrs == 2 || (tweak_attrs == 1 && st->st_nlink == 1); +} + static int phase = 0; static int dflt_perms; @@ -1501,6 +1507,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, if (preserve_links && S_ISLNK(file->mode)) { #ifdef SUPPORT_LINKS + int iflags = 0; const char *sl = F_SYMLINK(file); if (safe_symlinks && unsafe_symlink(sl, fname)) { if (verbose) { @@ -1521,7 +1528,15 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, else if ((len = readlink(fname, lnk, MAXPATHLEN-1)) > 0 && strncmp(lnk, sl, len) == 0 && sl[len] == '\0') { /* The link is pointing to the right place. */ - set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT); + if (may_tweak(&sx.st)) { + if (verbose > 2) + rprintf(FINFO, "possibly tweaking attributes of %s\n", fname); + set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT); + } else if (!unchanged_attrs(fname, file, &sx)) { + if (verbose > 2) + rprintf(FINFO, "recreating %s due to changed attributes\n", fname); + goto recreate_symlink; + } if (itemizing) itemize(fname, file, ndx, 0, &sx, 0, 0, NULL); #if defined SUPPORT_HARD_LINKS && defined CAN_HARDLINK_SYMLINK @@ -1531,7 +1546,9 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, if (remove_source_files == 1) goto return_with_success; goto cleanup; - } + } else + iflags = ITEM_REPORT_CHANGE; + recreate_symlink: /* Not the right symlink (or not a symlink), so * delete it. */ if (delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_SYMLINK) != 0) @@ -1565,18 +1582,20 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, set_file_attrs(fname, file, NULL, NULL, 0); if (itemizing) { itemize(fname, file, ndx, statret, &sx, - ITEM_LOCAL_CHANGE|ITEM_REPORT_CHANGE, 0, NULL); + ITEM_LOCAL_CHANGE|iflags, 0, NULL); } - if (code != FNONE && verbose) + if ((iflags & ITEM_REPORT_CHANGE) && code != FNONE && verbose) rprintf(code, "%s -> %s\n", fname, sl); #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && F_IS_HLINKED(file)) 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 - * --remove-sent-files option would remove. */ - if (remove_source_files) + /* When the symlink value changed, we do not check + * remove_source_files == 1 because this is one of the + * items that the old --remove-sent-files option would + * remove. */ + if ((iflags & ITEM_REPORT_CHANGE) ? remove_source_files + : remove_source_files == 1) goto return_with_success; } #endif @@ -1585,6 +1604,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, if ((am_root && preserve_devices && IS_DEVICE(file->mode)) || (preserve_specials && IS_SPECIAL(file->mode))) { + int iflags = 0; uint32 *devp = F_RDEV_P(file); dev_t rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)); if (statret == 0) { @@ -1602,7 +1622,15 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, && BITS_EQUAL(sx.st.st_mode, file->mode, _S_IFMT) && sx.st.st_rdev == rdev) { /* The device or special file is identical. */ - set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT); + if (may_tweak(&sx.st)) { + if (verbose > 2) + rprintf(FINFO, "possibly tweaking attributes of %s\n", fname); + set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT); + } else if (!unchanged_attrs(fname, file, &sx)) { + if (verbose > 2) + rprintf(FINFO, "recreating %s due to changed attributes\n", fname); + goto recreate_D; + } if (itemizing) itemize(fname, file, ndx, 0, &sx, 0, 0, NULL); #ifdef SUPPORT_HARD_LINKS @@ -1612,7 +1640,9 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, if (remove_source_files == 1) goto return_with_success; goto cleanup; - } + } else + iflags = ITEM_REPORT_CHANGE; + recreate_D: if (delete_item(fname, sx.st.st_mode, del_opts | del_for_flag) != 0) goto cleanup; } else if (basis_dir[0] != NULL) { @@ -1649,9 +1679,9 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, set_file_attrs(fname, file, NULL, NULL, 0); if (itemizing) { itemize(fname, file, ndx, statret, &sx, - ITEM_LOCAL_CHANGE|ITEM_REPORT_CHANGE, 0, NULL); + ITEM_LOCAL_CHANGE|iflags, 0, NULL); } - if (code != FNONE && verbose) + if ((iflags & ITEM_REPORT_CHANGE) && code != FNONE && verbose) rprintf(code, "%s\n", fname); #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && F_IS_HLINKED(file)) @@ -1769,13 +1799,31 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, else if (fnamecmp_type == FNAMECMP_FUZZY) ; else if (unchanged_file(fnamecmp, file, &sx.st)) { + /* fnamecmp == fname, fnamecmp_type == FNAMECMP_FNAME */ + int iflags = 0; + if (partialptr) { do_unlink(partialptr); handle_partial_dir(partialptr, PDIR_DELETE); } - set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT); + if (may_tweak(&sx.st)) { + /* Currently, we call set_file_attrs on all tweakable + * files, though ideally it would have no effect when + * unchanged_attrs returns true. */ + if (verbose > 2) + rprintf(FINFO, "possibly tweaking attributes of %s\n", fname); + set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT); + } else if (!unchanged_attrs(fname, file, &sx)) { + /* Need to recreate the file. + * copy_altdest_file sets its attributes, etc. */ + if (verbose > 2) + rprintf(FINFO, "recreating %s due to changed attributes\n", fname); + if (!dry_run && copy_altdest_file(fnamecmp, fname, file)) + goto cleanup; + iflags |= ITEM_LOCAL_CHANGE; + } if (itemizing) - itemize(fnamecmp, file, ndx, statret, &sx, 0, 0, NULL); + itemize(fnamecmp, file, ndx, statret, &sx, iflags, 0, NULL); #ifdef SUPPORT_HARD_LINKS if (preserve_hard_links && F_IS_HLINKED(file)) finish_hard_link(file, fname, ndx, &sx.st, itemizing, code, -1);