1 From: Rusty Russell <rusty@rustcorp.com.au>
2 Date: Wed, 03 Apr 2002 17:08:57 +1000
4 Found old patch on google, and updated it for 2.5.4 (I know, but that's what
5 apt-get source gave me).
7 Compiles, otherwise untested.
10 [Updated for current CVS version by Wayne Davison. Passes *MOST* of the
11 test suite, but otherwise UNTESTED.]
13 Anyone who quotes me in their sig is an idiot. -- Rusty Russell.
15 --- Makefile.in 10 Feb 2004 17:06:11 -0000 1.98
16 +++ Makefile.in 27 Feb 2004 08:57:09 -0000
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 27 Feb 2004 08:03:49 -0000 1.76
27 +++ generator.c 27 Feb 2004 08:57:09 -0000
29 extern int always_checksum;
30 extern char *compare_dest;
35 /* choose whether to skip a particular file */
36 -static int skip_file(char *fname, struct file_struct *file, STRUCT_STAT *st)
37 +static int skip_file(char *fname, struct file_struct *file,
38 + const STRUCT_STAT *st)
40 if (st->st_size != file->length) {
46 +/* Returns -1 for can't open (null file), -2 for skip */
47 +static int open_base_file(struct file_struct *file, char *fname, int statret,
53 + if (S_ISREG(st->st_mode)) {
55 + && cmp_modtime(st->st_mtime, file->modtime) > 0) {
57 + rprintf(FINFO, "%s is newer\n", fname);
60 + if (skip_file(fname, file, st)) {
61 + set_perms(fname, file, st, 1);
64 + fd = do_open(fname, O_RDONLY, 0);
66 + rprintf(FERROR, "failed to open %s, continuing : %s\n",
67 + full_fname(fname), strerror(errno));
72 + /* Try to use symlink contents */
73 + if (S_ISLNK(st->st_mode)) {
74 + fd = do_open_regular(fname);
75 + /* Don't delete yet; receiver will need it */
77 + if (delete_file(fname) != 0) {
86 + if (fd == -1 && compare_dest != NULL)
87 + fd = open_alternate_base_comparedir(fname);
89 + if (fd == -1 && fuzzy)
90 + fd = open_alternate_base_fuzzy(fname);
92 + /* Update stat to understand size */
94 + if (do_fstat(fd, st) != 0) {
95 + rprintf(FERROR, "fstat %s : %s\n",
96 + full_fname(fname), strerror(errno));
104 * Acts on file number @p i from @p flist, whose name is @p fname.
105 @@ -268,9 +325,6 @@ void recv_generator(char *fname, struct
107 struct map_struct *mapbuf;
110 - char fnamecmpbuf[MAXPATHLEN];
111 - extern char *compare_dest;
112 extern int list_only;
113 extern int only_existing;
114 extern int orig_umask;
115 @@ -397,108 +451,38 @@ void recv_generator(char *fname, struct
119 - if (preserve_hard_links && hard_link_check(file, HL_CHECK_MASTER))
122 - if (!S_ISREG(file->mode)) {
123 - rprintf(FINFO, "skipping non-regular file \"%s\"\n",fname);
129 - if (statret == -1 && compare_dest != NULL) {
130 - /* try the file at compare_dest instead */
131 - int saveerrno = errno;
132 - pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, compare_dest, fname);
133 - statret = link_stat(fnamecmpbuf,&st);
134 - if (!S_ISREG(st.st_mode))
139 - else if (link_dest && !dry_run) {
140 - if (do_link(fnamecmpbuf, fname) != 0) {
142 - rprintf(FINFO,"link %s => %s : %s\n",
143 - fnamecmpbuf, fname,
147 - fnamecmp = fnamecmpbuf;
151 - fnamecmp = fnamecmpbuf;
154 - if (statret == -1) {
155 - if (preserve_hard_links && hard_link_check(file, HL_SKIP))
157 - if (errno == ENOENT) {
158 - write_int(f_out,i);
159 - if (!dry_run) write_sum_head(f_out, NULL);
160 - } else if (verbose > 1) {
161 + /* Failed to stat for some reason besides "not found". */
162 + if (statret == -1 && errno != ENOENT) {
165 - "recv_generator: failed to open %s: %s\n",
166 + "recv_generator failed to stat %s: %s\n",
167 full_fname(fname), strerror(errno));
172 - if (!S_ISREG(st.st_mode)) {
173 - if (delete_file(fname) != 0) {
177 - /* now pretend the file didn't exist */
178 - if (preserve_hard_links && hard_link_check(file, HL_SKIP))
180 - write_int(f_out,i);
181 - if (!dry_run) write_sum_head(f_out, NULL);
182 + if ((fd = open_base_file(file, fname, statret, &st)) == -2)
186 - if (opt_ignore_existing && fnamecmp == fname) {
188 - rprintf(FINFO,"%s exists\n",fname);
192 - if (update_only && cmp_modtime(st.st_mtime,file->modtime)>0 && fnamecmp == fname) {
194 - rprintf(FINFO,"%s is newer\n",fname);
196 + if ((disable_deltas_p() || dry_run) && fd != -1) {
201 - if (skip_file(fname, file, &st)) {
202 - if (fnamecmp == fname)
203 - set_perms(fname,file,&st,1);
208 - write_int(f_out,i);
212 - if (disable_deltas_p()) {
213 - write_int(f_out,i);
214 - write_sum_head(f_out, NULL);
218 - /* open the file */
219 - fd = do_open(fnamecmp, O_RDONLY, 0);
222 - rprintf(FERROR, "failed to open %s, continuing: %s\n",
223 - full_fname(fnamecmp), strerror(errno));
224 - /* pretend the file didn't exist */
225 + /* the file didn't exist, or we can pretend it doesn't */
226 if (preserve_hard_links && hard_link_check(file, HL_SKIP))
228 - write_int(f_out,i);
229 - write_sum_head(f_out, NULL);
230 + write_int(f_out, i);
232 + write_sum_head(f_out, NULL);
236 + if (preserve_hard_links && hard_link_check(file, HL_CHECK_MASTER))
239 + if (!S_ISREG(file->mode)) {
240 + rprintf(FINFO, "skipping non-regular file \"%s\"\n",fname);
244 @@ -508,7 +492,7 @@ void recv_generator(char *fname, struct
248 - rprintf(FINFO,"gen mapped %s of size %.0f\n", fnamecmp,
249 + rprintf(FINFO, "gen mapped %s of size %.0f\n", fname,
253 --- options.c 22 Feb 2004 08:56:43 -0000 1.139
254 +++ options.c 27 Feb 2004 08:57:10 -0000
256 int modify_window = 0;
257 int blocking_io = -1;
258 int checksum_seed = 0;
260 unsigned int block_size = 0;
263 @@ -288,6 +289,7 @@ void usage(enum logcode F)
264 rprintf(F," --bwlimit=KBPS limit I/O bandwidth, KBytes per second\n");
265 rprintf(F," --write-batch=PREFIX write batch fileset starting with PREFIX\n");
266 rprintf(F," --read-batch=PREFIX read batch fileset starting with PREFIX\n");
267 + rprintf(F," --fuzzy use similar file as basis if it does't exist\n");
268 rprintf(F," -h, --help show this help screen\n");
270 rprintf(F," -4 prefer IPv4\n");
271 @@ -383,6 +385,7 @@ static struct poptOption long_options[]
272 {"files-from", 0, POPT_ARG_STRING, &files_from, 0, 0, 0 },
273 {"from0", '0', POPT_ARG_NONE, &eol_nulls, 0, 0, 0},
274 {"no-implied-dirs", 0, POPT_ARG_VAL, &implied_dirs, 0, 0, 0 },
275 + {"fuzzy", 0, POPT_ARG_NONE, &fuzzy, 0, 0, 0 },
276 {"protocol", 0, POPT_ARG_INT, &protocol_version, 0, 0, 0 },
278 {0, '4', POPT_ARG_VAL, &default_af_hint, AF_INET, 0, 0 },
279 @@ -945,6 +948,9 @@ void server_options(char **args,int *arg
280 args[ac++] = "--from0";
284 + if (fuzzy && am_sender)
285 + args[ac++] = "--fuzzy";
289 --- proto.h 17 Feb 2004 23:13:06 -0000 1.184
290 +++ proto.h 27 Feb 2004 08:57:10 -0000
292 /* This file is automatically generated with "make proto". DO NOT EDIT */
294 int allow_access(char *addr, char *host, char *allow_list, char *deny_list);
295 +int do_open_regular(char *fname);
296 +int open_alternate_base_fuzzy(const char *fname);
297 +int open_alternate_base_comparedir(const char *fname);
298 void base64_encode(char *buf, int len, char *out);
299 char *auth_server(int f_in, int f_out, int module, char *addr, char *leader);
300 void auth_client(int fd, char *user, char *challenge);
301 --- receiver.c 27 Feb 2004 08:03:49 -0000 1.73
302 +++ receiver.c 27 Feb 2004 08:57:10 -0000
304 extern char *backup_suffix;
305 extern int backup_suffix_len;
306 extern int cleanup_got_literal;
309 static void delete_one(char *fn, int is_dir)
311 @@ -288,8 +289,6 @@ int recv_files(int f_in,struct file_list
312 char *fname, fbuf[MAXPATHLEN];
313 char template[MAXPATHLEN];
314 char fnametmp[MAXPATHLEN];
316 - char fnamecmpbuf[MAXPATHLEN];
317 struct map_struct *mapbuf;
319 struct file_struct *file;
320 @@ -356,35 +355,31 @@ int recv_files(int f_in,struct file_list
322 rprintf(FINFO,"recv_files(%s)\n",fname);
327 - fd1 = do_open(fnamecmp, O_RDONLY, 0);
328 + fd1 = do_open(fname, O_RDONLY, 0);
330 - if (fd1 == -1 && compare_dest != NULL) {
331 - /* try the file at compare_dest instead */
332 - pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
333 - compare_dest, fname);
334 - fnamecmp = fnamecmpbuf;
335 - fd1 = do_open(fnamecmp, O_RDONLY, 0);
337 + if (fd1 == -1 && compare_dest != NULL)
338 + fd1 = open_alternate_base_comparedir(fname);
340 + if (fd1 == -1 && fuzzy)
341 + fd1 = open_alternate_base_fuzzy(fname);
343 if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
344 rprintf(FERROR, "fstat %s failed: %s\n",
345 - full_fname(fnamecmp), strerror(errno));
346 + full_fname(fname), strerror(errno));
347 receive_data(f_in,NULL,-1,NULL,file->length);
352 - if (fd1 != -1 && S_ISDIR(st.st_mode) && fnamecmp == fname) {
353 + if (fd1 != -1 && S_ISDIR(st.st_mode)) {
354 /* this special handling for directories
355 * wouldn't be necessary if robust_rename()
356 * and the underlying robust_unlink could cope
359 rprintf(FERROR,"recv_files: %s is a directory\n",
360 - full_fname(fnamecmp));
361 + full_fname(fname));
362 receive_data(f_in, NULL, -1, NULL, file->length);
365 @@ -405,8 +400,10 @@ int recv_files(int f_in,struct file_list
367 if (fd1 != -1 && st.st_size > 0) {
368 mapbuf = map_file(fd1,st.st_size);
370 - rprintf(FINFO,"recv mapped %s of size %.0f\n",fnamecmp,(double)st.st_size);
372 + rprintf(FINFO, "recv mapped %s of size %.0f\n",
373 + fname, (double)st.st_size);