Some improvements from Chris Shoemaker.
[rsync/rsync-patches.git] / fuzzy.diff
... / ...
CommitLineData
1From: Rusty Russell <rusty@rustcorp.com.au>
2Date: Wed, 03 Apr 2002 17:08:57 +1000
3
4Found old patch on google, and updated it for 2.5.4 (I know, but that's what
5apt-get source gave me).
6
7Compiles, otherwise untested.
8Rusty.
9
10[Updated for current CVS version by Wayne Davison. Passes *MOST* of the
11test suite, but otherwise UNTESTED.]
12--
13 Anyone who quotes me in their sig is an idiot. -- Rusty Russell.
14
15--- Makefile.in 15 May 2004 00:48:11 -0000 1.101
16+++ Makefile.in 21 May 2004 09:51:19 -0000
17@@ -32,7 +32,7 @@ ZLIBOBJ=zlib/deflate.o zlib/infblock.o z
18 zlib/inflate.o zlib/inftrees.o zlib/infutil.o zlib/trees.o \
19 zlib/zutil.o zlib/adler32.o
20 OBJS1=rsync.o generator.o receiver.o cleanup.o sender.o exclude.o util.o \
21- main.o checksum.o match.o syscall.o log.o backup.o
22+ main.o checksum.o match.o syscall.o log.o backup.o alternate.o
23 OBJS2=options.o flist.o io.o compat.o hlink.o token.o uidlist.o socket.o \
24 fileio.o batch.o clientname.o
25 OBJS3=progress.o pipe.o
26--- generator.c 18 May 2004 08:50:17 -0000 1.85
27+++ generator.c 21 May 2004 09:51:19 -0000
28@@ -51,6 +51,7 @@ extern int list_only;
29 extern int only_existing;
30 extern int orig_umask;
31 extern int safe_symlinks;
32+extern int fuzzy;
33
34 extern struct exclude_list_struct server_exclude_list;
35
36@@ -258,7 +259,61 @@ static void generate_and_send_sums(struc
37 }
38 }
39
40+/* Returns -1 for can't open (null file), -2 for skip */
41+static int open_base_file(struct file_struct *file, char *fname, int statret,
42+ STRUCT_STAT *st)
43+{
44+ int fd = -1;
45+
46+ if (statret == 0) {
47+ if (S_ISREG(st->st_mode)) {
48+ if (update_only
49+ && cmp_modtime(st->st_mtime, file->modtime) > 0) {
50+ if (verbose > 1)
51+ rprintf(FINFO, "%s is newer\n", fname);
52+ return -2;
53+ }
54+ if (skip_file(fname, file, st)) {
55+ set_perms(fname, file, st, PERMS_REPORT);
56+ return -2;
57+ }
58+ fd = do_open(fname, O_RDONLY, 0);
59+ if (fd == -1) {
60+ rsyserr(FERROR, errno, "failed to open %s, continuing",
61+ full_fname(fname));
62+ return -1;
63+ }
64+ return fd;
65+ } else {
66+ /* Try to use symlink contents */
67+ if (S_ISLNK(st->st_mode)) {
68+ fd = do_open_regular(fname);
69+ /* Don't delete yet; receiver will need it */
70+ } else {
71+ if (delete_file(fname) != 0) {
72+ if (fd != -1)
73+ close(fd);
74+ return -2;
75+ }
76+ }
77+ }
78+ }
79+
80+ if (fd == -1 && compare_dest != NULL)
81+ fd = open_alternate_base_comparedir(fname);
82+
83+ if (fd == -1 && fuzzy)
84+ fd = open_alternate_base_fuzzy(fname);
85+
86+ /* Update stat to understand size */
87+ if (fd != -1) {
88+ if (do_fstat(fd, st) != 0) {
89+ rsyserr(FERROR, errno, "fstat %s", full_fname(fname));
90+ }
91+ }
92
93+ return fd;
94+}
95
96 /**
97 * Acts on file number @p i from @p flist, whose name is @p fname.
98@@ -274,8 +329,6 @@ void recv_generator(char *fname, struct
99 STRUCT_STAT st;
100 struct map_struct *mapbuf;
101 int statret;
102- char *fnamecmp;
103- char fnamecmpbuf[MAXPATHLEN];
104
105 if (list_only)
106 return;
107@@ -413,107 +466,39 @@ void recv_generator(char *fname, struct
108 }
109 #endif
110
111- if (preserve_hard_links && hard_link_check(file, HL_CHECK_MASTER))
112- return;
113-
114- if (!S_ISREG(file->mode)) {
115- rprintf(FINFO, "skipping non-regular file \"%s\"\n",fname);
116- return;
117- }
118-
119- fnamecmp = fname;
120-
121- if (statret == -1 && compare_dest != NULL) {
122- /* try the file at compare_dest instead */
123- int saveerrno = errno;
124- pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, compare_dest, fname);
125- statret = link_stat(fnamecmpbuf,&st);
126- if (!S_ISREG(st.st_mode))
127- statret = -1;
128- if (statret == -1)
129- errno = saveerrno;
130-#if HAVE_LINK
131- else if (link_dest && !dry_run) {
132- if (do_link(fnamecmpbuf, fname) != 0) {
133- if (verbose > 0) {
134- rsyserr(FINFO, errno, "link %s => %s",
135- fnamecmpbuf, fname);
136- }
137- }
138- fnamecmp = fnamecmpbuf;
139- }
140-#endif
141- else
142- fnamecmp = fnamecmpbuf;
143- }
144-
145- if (statret == -1) {
146- if (preserve_hard_links && hard_link_check(file, HL_SKIP))
147- return;
148- if (errno == ENOENT) {
149- write_int(f_out,i);
150- if (!dry_run) write_sum_head(f_out, NULL);
151- } else if (verbose > 1) {
152+ /* Failed to stat for some reason besides "not found". */
153+ if (statret == -1 && errno != ENOENT) {
154+ if (verbose > 1) {
155 rsyserr(FERROR, errno,
156- "recv_generator: failed to open %s",
157+ "recv_generator failed to stat %s",
158 full_fname(fname));
159 }
160 return;
161 }
162
163- if (!S_ISREG(st.st_mode)) {
164- if (delete_file(fname) != 0) {
165- return;
166- }
167-
168- /* now pretend the file didn't exist */
169- if (preserve_hard_links && hard_link_check(file, HL_SKIP))
170- return;
171- write_int(f_out,i);
172- if (!dry_run) write_sum_head(f_out, NULL);
173- return;
174- }
175-
176- if (opt_ignore_existing && fnamecmp == fname) {
177- if (verbose > 1)
178- rprintf(FINFO,"%s exists\n",fname);
179- return;
180- }
181-
182- if (update_only && cmp_modtime(st.st_mtime,file->modtime)>0 && fnamecmp == fname) {
183- if (verbose > 1)
184- rprintf(FINFO,"%s is newer\n",fname);
185- return;
186- }
187-
188- if (skip_file(fname, file, &st)) {
189- if (fnamecmp == fname)
190- set_perms(fname, file, &st, PERMS_REPORT);
191- return;
192- }
193-
194- if (dry_run) {
195- write_int(f_out,i);
196+ if ((fd = open_base_file(file, fname, statret, &st)) == -2)
197 return;
198- }
199
200- if (disable_deltas_p()) {
201- write_int(f_out,i);
202- write_sum_head(f_out, NULL);
203- return;
204+ if ((disable_deltas_p() || dry_run) && fd != -1) {
205+ close(fd);
206+ fd = -1;
207 }
208
209- /* open the file */
210- fd = do_open(fnamecmp, O_RDONLY, 0);
211-
212 if (fd == -1) {
213- rsyserr(FERROR, errno, "failed to open %s, continuing",
214- full_fname(fnamecmp));
215- /* pretend the file didn't exist */
216+ /* the file didn't exist, or we can pretend it doesn't */
217 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
218 return;
219- write_int(f_out,i);
220- write_sum_head(f_out, NULL);
221+ write_int(f_out, i);
222+ if (!dry_run)
223+ write_sum_head(f_out, NULL);
224+ return;
225+ }
226+
227+ if (preserve_hard_links && hard_link_check(file, HL_CHECK_MASTER))
228+ return;
229+
230+ if (!S_ISREG(file->mode)) {
231+ rprintf(FINFO, "skipping non-regular file \"%s\"\n",fname);
232 return;
233 }
234
235@@ -523,7 +508,7 @@ void recv_generator(char *fname, struct
236 mapbuf = NULL;
237
238 if (verbose > 3) {
239- rprintf(FINFO,"gen mapped %s of size %.0f\n", fnamecmp,
240+ rprintf(FINFO, "gen mapped %s of size %.0f\n", fname,
241 (double)st.st_size);
242 }
243
244--- options.c 21 May 2004 09:44:32 -0000 1.150
245+++ options.c 21 May 2004 09:51:20 -0000
246@@ -91,6 +91,7 @@ int ignore_errors = 0;
247 int modify_window = 0;
248 int blocking_io = -1;
249 int checksum_seed = 0;
250+int fuzzy = 0;
251 unsigned int block_size = 0;
252
253
254@@ -266,6 +267,7 @@ void usage(enum logcode F)
255 rprintf(F," -T --temp-dir=DIR create temporary files in directory DIR\n");
256 rprintf(F," --compare-dest=DIR also compare destination files relative to DIR\n");
257 rprintf(F," --link-dest=DIR create hardlinks to DIR for unchanged files\n");
258+ rprintf(F," --fuzzy use similar file as basis if basis doesn't exist\n");
259 rprintf(F," -P equivalent to --partial --progress\n");
260 rprintf(F," -z, --compress compress file data\n");
261 rprintf(F," -C, --cvs-exclude auto ignore files in the same way CVS does\n");
262@@ -363,6 +365,7 @@ static struct poptOption long_options[]
263 {"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
264 {"compare-dest", 0, POPT_ARG_STRING, &compare_dest, 0, 0, 0 },
265 {"link-dest", 0, POPT_ARG_STRING, &compare_dest, OPT_LINK_DEST, 0, 0 },
266+ {"fuzzy", 0, POPT_ARG_NONE, &fuzzy, 0, 0, 0 },
267 /* TODO: Should this take an optional int giving the compression level? */
268 {"compress", 'z', POPT_ARG_NONE, &do_compression, 0, 0, 0 },
269 {"daemon", 0, POPT_ARG_NONE, &daemon_opt, 0, 0, 0 },
270@@ -972,6 +975,9 @@ void server_options(char **args,int *arg
271 }
272 }
273
274+ if (fuzzy && am_sender)
275+ args[ac++] = "--fuzzy";
276+
277 *argc = ac;
278 return;
279
280--- receiver.c 21 May 2004 08:27:04 -0000 1.79
281+++ receiver.c 21 May 2004 09:51:20 -0000
282@@ -47,6 +47,7 @@ extern int ignore_errors;
283 extern int orig_umask;
284 extern int keep_partial;
285 extern int checksum_seed;
286+extern int fuzzy;
287
288 static void delete_one(char *fn, int is_dir)
289 {
290@@ -295,8 +296,6 @@ int recv_files(int f_in,struct file_list
291 char *fname, fbuf[MAXPATHLEN];
292 char template[MAXPATHLEN];
293 char fnametmp[MAXPATHLEN];
294- char *fnamecmp;
295- char fnamecmpbuf[MAXPATHLEN];
296 struct map_struct *mapbuf;
297 int i;
298 struct file_struct *file;
299@@ -359,35 +358,31 @@ int recv_files(int f_in,struct file_list
300 if (verbose > 2)
301 rprintf(FINFO,"recv_files(%s)\n",fname);
302
303- fnamecmp = fname;
304-
305 /* open the file */
306- fd1 = do_open(fnamecmp, O_RDONLY, 0);
307+ fd1 = do_open(fname, O_RDONLY, 0);
308
309- if (fd1 == -1 && compare_dest != NULL) {
310- /* try the file at compare_dest instead */
311- pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
312- compare_dest, fname);
313- fnamecmp = fnamecmpbuf;
314- fd1 = do_open(fnamecmp, O_RDONLY, 0);
315- }
316+ if (fd1 == -1 && compare_dest != NULL)
317+ fd1 = open_alternate_base_comparedir(fname);
318+
319+ if (fd1 == -1 && fuzzy)
320+ fd1 = open_alternate_base_fuzzy(fname);
321
322 if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
323 rsyserr(FERROR, errno, "fstat %s failed",
324- full_fname(fnamecmp));
325+ full_fname(fname));
326 receive_data(f_in,NULL,-1,NULL,file->length);
327 close(fd1);
328 continue;
329 }
330
331- if (fd1 != -1 && S_ISDIR(st.st_mode) && fnamecmp == fname) {
332+ if (fd1 != -1 && S_ISDIR(st.st_mode)) {
333 /* this special handling for directories
334 * wouldn't be necessary if robust_rename()
335 * and the underlying robust_unlink could cope
336 * with directories
337 */
338 rprintf(FERROR,"recv_files: %s is a directory\n",
339- full_fname(fnamecmp));
340+ full_fname(fname));
341 receive_data(f_in, NULL, -1, NULL, file->length);
342 close(fd1);
343 continue;
344@@ -408,8 +403,10 @@ int recv_files(int f_in,struct file_list
345
346 if (fd1 != -1 && st.st_size > 0) {
347 mapbuf = map_file(fd1,st.st_size);
348- if (verbose > 2)
349- rprintf(FINFO,"recv mapped %s of size %.0f\n",fnamecmp,(double)st.st_size);
350+ if (verbose > 2) {
351+ rprintf(FINFO, "recv mapped %s of size %.0f\n",
352+ fname, (double)st.st_size);
353+ }
354 } else
355 mapbuf = NULL;
356
357--- rsync.yo 21 May 2004 09:44:32 -0000 1.170
358+++ rsync.yo 21 May 2004 09:51:21 -0000
359@@ -324,6 +324,7 @@ verb(
360 -T --temp-dir=DIR create temporary files in directory DIR
361 --compare-dest=DIR also compare received files relative to DIR
362 --link-dest=DIR create hardlinks to DIR for unchanged files
363+ --fuzzy use similar file as basis if basis is gone
364 -P equivalent to --partial --progress
365 -z, --compress compress file data
366 -C, --cvs-exclude auto ignore files in the same way CVS does