Updated to latest source.
[rsync-patches.git] / detect-renamed-lax.diff
1 This patch adds the options --detect-renamed-lax and --detect-moved.
2 These modify the --detect-renamed algorithm to adopt a matching file
3 without verifying that the content is as expected.  The former blindly
4 accepts a file that matches in size and modified time.  The latter
5 requires that the filename also match (ignoring any renamed files).
6
7 This patch is EXPERIMENTAL, though it did work correctly in my light
8 testing.
9
10 To use this patch, run these commands for a successful build:
11
12     patch -p1 <patches/detect-renamed.diff
13     patch -p1 <patches/detect-renamed-lax.diff
14     ./configure                                 (optional if already run)
15     make
16
17 FIXME: If a run with --detect-renamed-lax stages a different-basename
18 destination file and then gets interrupted, a subsequent run that
19 switches to --detect-moved blindly accepts the staged file.
20
21 -- Matt McCutchen <hashproduct+rsync@gmail.com>
22
23 based-on: patch/master/detect-renamed
24 diff --git a/generator.c b/generator.c
25 --- a/generator.c
26 +++ b/generator.c
27 @@ -465,7 +465,9 @@ static int fattr_find(struct file_struct *f, char *fname)
28                                 continue;
29                         }
30                 }
31 -               ok_match = mid;
32 +               /* --detect-moved doesn't allow non-basename matches */
33 +               if (detect_renamed != 3)
34 +                       ok_match = mid;
35                 diff = u_strcmp(fmid->basename, f->basename);
36                 if (diff == 0) {
37                         good_match = mid;
38 @@ -1958,6 +1960,21 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
39                 fnamecmp = partialptr;
40                 fnamecmp_type = FNAMECMP_PARTIAL_DIR;
41                 statret = 0;
42 +               if (detect_renamed > 1 && unchanged_file(fnamecmp, file, &sx.st)) {
43 +                       /* Adopt the partial file. */
44 +                       finish_transfer(fname, fnamecmp, NULL, NULL, file, 1, 1);
45 +                       handle_partial_dir(partialptr, PDIR_DELETE);
46 +                       if (itemizing)
47 +                               itemize(fnamecmp, file, ndx, -1, &sx,
48 +                                               ITEM_LOCAL_CHANGE, fnamecmp_type, NULL);
49 +#ifdef SUPPORT_HARD_LINKS
50 +                       if (preserve_hard_links && F_IS_HLINKED(file))
51 +                               finish_hard_link(file, fname, ndx, &sx.st, itemizing, code, -1);
52 +#endif
53 +                       if (remove_source_files == 1)
54 +                               goto return_with_success;
55 +                       goto cleanup;
56 +               }
57         }
58  
59         if (!do_xfers)
60 diff --git a/options.c b/options.c
61 --- a/options.c
62 +++ b/options.c
63 @@ -828,6 +828,8 @@ void usage(enum logcode F)
64    rprintf(F," -T, --temp-dir=DIR          create temporary files in directory DIR\n");
65    rprintf(F," -y, --fuzzy                 find similar file for basis if no dest file\n");
66    rprintf(F,"     --detect-renamed        try to find renamed files to speed up the transfer\n");
67 +  rprintf(F,"     --detect-renamed-lax    ... and assume identical to source files (risky!)\n");
68 +  rprintf(F,"     --detect-moved          ... only if basenames match (less risky)\n");
69    rprintf(F,"     --compare-dest=DIR      also compare destination files relative to DIR\n");
70    rprintf(F,"     --copy-dest=DIR         ... and include copies of unchanged files\n");
71    rprintf(F,"     --link-dest=DIR         hardlink to files in DIR when unchanged\n");
72 @@ -1043,7 +1045,9 @@ static struct poptOption long_options[] = {
73    {"compare-dest",     0,  POPT_ARG_STRING, 0, OPT_COMPARE_DEST, 0, 0 },
74    {"copy-dest",        0,  POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 },
75    {"link-dest",        0,  POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 },
76 -  {"detect-renamed",   0,  POPT_ARG_NONE,   &detect_renamed, 0, 0, 0 },
77 +  {"detect-renamed",   0,  POPT_ARG_VAL,    &detect_renamed, 1, 0, 0 },
78 +  {"detect-renamed-lax",0, POPT_ARG_VAL,    &detect_renamed, 2, 0, 0 },
79 +  {"detect-moved",     0,  POPT_ARG_VAL,    &detect_renamed, 3, 0, 0 },
80    {"fuzzy",           'y', POPT_ARG_NONE,   0, 'y', 0, 0 },
81    {"no-fuzzy",         0,  POPT_ARG_VAL,    &fuzzy_basis, 0, 0, 0 },
82    {"no-y",             0,  POPT_ARG_VAL,    &fuzzy_basis, 0, 0, 0 },
83 @@ -2855,8 +2859,14 @@ void server_options(char **args, int *argc_p)
84                         args[ac++] = "--super";
85                 if (size_only)
86                         args[ac++] = "--size-only";
87 -               if (detect_renamed)
88 -                       args[ac++] = "--detect-renamed";
89 +               if (detect_renamed) {
90 +                       if (detect_renamed == 1)
91 +                               args[ac++] = "--detect-renamed";
92 +                       else if (detect_renamed == 2)
93 +                               args[ac++] = "--detect-renamed-lax";
94 +                       else
95 +                               args[ac++] = "--detect-moved";
96 +               }
97                 if (do_stats)
98                         args[ac++] = "--stats";
99         } else {
100 diff --git a/rsync.1.md b/rsync.1.md
101 --- a/rsync.1.md
102 +++ b/rsync.1.md
103 @@ -416,6 +416,8 @@ detailed description below for a complete description.
104  --temp-dir=DIR, -T          create temporary files in directory DIR
105  --fuzzy, -y                 find similar file for basis if no dest file
106  --detect-renamed            try to find renamed files to speed the xfer
107 +--detect-renamed-lax        ...& assume identical to src files (risky!)
108 +--detect-moved              ... only if basenames match (less risky)
109  --compare-dest=DIR          also compare received files relative to DIR
110  --copy-dest=DIR             ... and include copies of unchanged files
111  --link-dest=DIR             hardlink to files in DIR when unchanged
112 @@ -2167,6 +2169,17 @@ your home directory (remove the '=' for that).
113      otential alternate-basis files will be removed as the transfer progresses.
114      This option conflicts with `--inplace` and `--append`.
115  
116 +0.  ``--detect-renamed-lax`) This version of `--detect-renamed` makes rsync
117 +    hard-link em(dest/D) to em(dest/S) without verifying that em(src/S) and
118 +    em(dest/S) have the same data.  This poses a significant risk of corrupting
119 +    the destination by representing a new source file by an unrelated
120 +    destination file that coincidentally passes the quick check with the source
121 +    file.  Use this option only if you accept the risk and disk I/O is a
122 +    bottleneck.
123 +
124 +0.  ``--detect-moved`` A less risky variant of `--detect-renamed-lax` that only
125 +    uses a destination file that has the same basename as the new source file.
126 +
127  0.  `--compare-dest=DIR`
128  
129      This option instructs rsync to use _DIR_ on the destination machine as an