Carl E. Thompson
2008-May-08 01:26 UTC
Patch to not modify files in place unless "--inplace" option specified
Skipped content of type multipart/alternative-------------- next part -------------- diff -urN rsync-3.0.2-orig/generator.c rsync-3.0.2/generator.c --- rsync-3.0.2-orig/generator.c 2008-03-28 10:30:11.000000000 -0700 +++ rsync-3.0.2/generator.c 2008-05-07 15:35:08.317364774 -0700 @@ -1508,6 +1508,7 @@ 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) { @@ -1528,7 +1529,15 @@ 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 (inplace) { + 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 @@ -1538,7 +1547,9 @@ 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) @@ -1572,18 +1583,20 @@ 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 @@ -1592,6 +1605,7 @@ 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) { @@ -1609,7 +1623,15 @@ && 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 (inplace) { + 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 @@ -1619,7 +1641,9 @@ 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) { @@ -1656,9 +1680,9 @@ 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)) @@ -1776,13 +1800,31 @@ 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 (inplace) { + /* 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);
Wayne Davison
2008-May-08 03:13 UTC
Patch to not modify files in place unless "--inplace" option specified
On Wed, May 07, 2008 at 06:25:36PM -0700, Carl E. Thompson wrote:> This patch causes rsync to honor the absence of the "--inplace" option > for permission, owner and group changes.Unfortunately, that's not what the --inplace option is for. Its purpose is to control how data updates occur, not attribute updates. If I make rsync break hard-links to make attribute updates, it will need to be a new option, as is done in Matt's patch. The problems you list with the --link-dest option only affect a client that contacts the server to do a backup. If you instead have your backup server contact the client machines, things are much safer. You can still use an rsync daemon (one per client) for the transfers, if you like. There was a suggest to rsync allow a daemon to be configured with a link-dest option in the config file. That also solves some of the problems, but would also require that the daemon use a pre-transfer script to move any old content out of the way for the current copy (since it is intended that a --link-dest copy goes into an empty hierarchy). e.g. it could manage a symlink for the current and prior dir and have the daemon config file used the symlink names to get to the right directories. ..wayne..
Reasonably Related Threads
- DO NOT REPLY [Bug 5820] New: rsync does not replace symlink atomically
- Rsync 2.6.9pre2 tries to read ACLs of nonexistent files
- Problem with exact moment of issuing transfer log entry for a [recv] action
- Revised flags patch
- DO NOT REPLY [Bug 4138] New: Incoming chmod can't override inherited directory setgid