1 Depends-On-Patch: g2r-basis-filename.diff
3 The changes to generator.c were greatly simplified, making the patch
4 easier to maintain and fixing the failing test in the testsuite.
7 Be sure to run "make proto" before "make".
9 --- orig/generator.c 2004-07-03 20:08:07
10 +++ generator.c 2004-07-03 20:09:05
11 @@ -41,6 +41,7 @@ extern int ignore_times;
13 extern int io_timeout;
14 extern int protocol_version;
16 extern int always_checksum;
17 extern char *compare_dest;
19 @@ -257,6 +258,94 @@ static void generate_and_send_sums(struc
23 +static void split_names(char *fname, char **dirname, char **basename)
25 + char *slash = strrchr(fname, '/');
29 + *basename = slash+1;
37 +static unsigned int measure_name(const char *name, const char *basename,
40 + int namelen = strlen(name);
41 + int extlen = strlen(ext);
42 + unsigned int score = 0;
44 + /* Extensions must match */
45 + if (namelen <= extlen || strcmp(name + namelen - extlen, ext) != 0)
48 + /* Now score depends on similarity of prefix */
49 + for (; *name == *basename && *name; name++, basename++)
55 +static int find_fuzzy(char **fname_ptr, char *buf, STRUCT_STAT *st_ptr)
59 + char *basename, *dirname;
60 + char mangled_name[MAXPATHLEN];
61 + char bestname[MAXPATHLEN];
62 + unsigned int bestscore = 0;
65 + strlcpy(mangled_name, *fname_ptr, sizeof mangled_name);
67 + split_names(mangled_name, &dirname, &basename);
68 + if (!(d = opendir(dirname))) {
69 + rsyserr(FERROR, errno, "recv_generator opendir(%s)", dirname);
73 + /* Get final extension, eg. .gz; never full basename though. */
74 + ext = strrchr(basename + 1, '.');
76 + ext = basename + strlen(basename); /* ext = "" */
78 + while ((di = readdir(d)) != NULL) {
79 + const char *dname = d_name(di);
82 + if (dname[0] == '.' && (dname[1] == '\0'
83 + || (dname[1] == '.' && dname[2] == '\0')))
86 + score = measure_name(dname, basename, ext);
88 + rprintf(FINFO, "[%s] fuzzy score for %s = %u\n",
89 + who_am_i(), dname, score);
91 + if (score > bestscore) {
92 + strlcpy(bestname, dname, sizeof bestname);
98 + /* Found a candidate. */
99 + if (bestscore != 0) {
100 + pathjoin(buf, MAXPATHLEN, dirname, bestname);
102 + rprintf(FINFO, "[%s] fuzzy match %s->%s\n",
103 + who_am_i(), *fname_ptr, buf);
106 + return link_stat(buf, st_ptr, 0);
113 * Acts on file number @p i from @p flist, whose name is @p fname.
114 @@ -272,7 +361,7 @@ static void recv_generator(char *fname,
117 struct map_struct *mapbuf;
119 + int statret, fuzzy_file = 0;
121 char fnamecmpbuf[MAXPATHLEN];
123 @@ -452,6 +541,14 @@ static void recv_generator(char *fname,
127 + if (statret == -1 && fuzzy) {
128 + statret = find_fuzzy(&fnamecmp, fnamecmpbuf, &st);
129 + if (!S_ISREG(st.st_mode))
136 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
138 @@ -498,7 +595,7 @@ static void recv_generator(char *fname,
142 - if (skip_file(fname, file, &st)) {
143 + if (!fuzzy_file && skip_file(fname, file, &st)) {
145 set_perms(fname, file, &st, PERMS_REPORT);
147 --- orig/options.c 2004-06-20 19:30:00
148 +++ options.c 2004-07-03 19:27:25
149 @@ -94,6 +94,7 @@ int ignore_errors = 0;
150 int modify_window = 0;
151 int blocking_io = -1;
152 int checksum_seed = 0;
154 unsigned int block_size = 0;
157 @@ -270,6 +271,7 @@ void usage(enum logcode F)
158 rprintf(F," -T --temp-dir=DIR create temporary files in directory DIR\n");
159 rprintf(F," --compare-dest=DIR also compare destination files relative to DIR\n");
160 rprintf(F," --link-dest=DIR create hardlinks to DIR for unchanged files\n");
161 + rprintf(F," --fuzzy use similar file as basis if basis doesn't exist\n");
162 rprintf(F," -P equivalent to --partial --progress\n");
163 rprintf(F," -z, --compress compress file data\n");
164 rprintf(F," -C, --cvs-exclude auto ignore files in the same way CVS does\n");
165 @@ -368,6 +370,7 @@ static struct poptOption long_options[]
166 {"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
167 {"compare-dest", 0, POPT_ARG_STRING, &compare_dest, 0, 0, 0 },
168 {"link-dest", 0, POPT_ARG_STRING, &compare_dest, OPT_LINK_DEST, 0, 0 },
169 + {"fuzzy", 0, POPT_ARG_NONE, &fuzzy, 0, 0, 0 },
170 /* TODO: Should this take an optional int giving the compression level? */
171 {"compress", 'z', POPT_ARG_NONE, &do_compression, 0, 0, 0 },
172 {"daemon", 0, POPT_ARG_NONE, &daemon_opt, 0, 0, 0 },
173 @@ -989,6 +992,9 @@ void server_options(char **args,int *arg
177 + if (fuzzy && am_sender)
178 + args[ac++] = "--fuzzy";
183 --- orig/receiver.c 2004-07-03 20:08:07
184 +++ receiver.c 2004-07-03 20:09:05
185 @@ -36,7 +36,6 @@ extern int preserve_perms;
186 extern int cvs_exclude;
189 -extern char *compare_dest;
190 extern int make_backups;
191 extern int do_progress;
192 extern char *backup_dir;
193 --- orig/rsync.yo 2004-06-17 06:32:00
194 +++ rsync.yo 2004-07-03 19:27:25
195 @@ -325,6 +325,7 @@ verb(
196 -T --temp-dir=DIR create temporary files in directory DIR
197 --compare-dest=DIR also compare received files relative to DIR
198 --link-dest=DIR create hardlinks to DIR for unchanged files
199 + --fuzzy use similar file as basis if basis is gone
200 -P equivalent to --partial --progress
201 -z, --compress compress file data
202 -C, --cvs-exclude auto ignore files in the same way CVS does