Renamed flags.diff fileflags.diff.
[rsync/rsync-patches.git] / checksum-updating.diff
CommitLineData
cc3e685d 1This builds on the sender optimization feature of the checksum-reading
213d4328
WD
2patch and adds the ability to create and/or updates the .rsyncsums files
3when --checksum-updating (or "checksum updating = true") is specified.
ae10e51e
WD
4
5To use this patch, run these commands for a successful build:
6
cc3e685d 7 patch -p1 <patches/checksum-reading.diff
ae10e51e
WD
8 patch -p1 <patches/checksum-updating.diff
9 ./configure (optional if already run)
10 make
11
cc3e685d
WD
12diff --git a/clientserver.c b/clientserver.c
13--- a/clientserver.c
14+++ b/clientserver.c
85096e5e 15@@ -39,6 +39,7 @@ extern int numeric_ids;
ae10e51e
WD
16 extern int filesfrom_fd;
17 extern int remote_protocol;
18 extern int protocol_version;
19+extern int checksum_updating;
20 extern int io_timeout;
21 extern int no_detach;
cc3e685d 22 extern int write_batch;
85096e5e 23@@ -746,6 +747,8 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
ae10e51e
WD
24 else if (am_root < 0) /* Treat --fake-super from client as --super. */
25 am_root = 2;
26
27+ checksum_updating = lp_checksum_updating(i);
28+
29 if (filesfrom_fd == 0)
30 filesfrom_fd = f_in;
31
cc3e685d
WD
32diff --git a/flist.c b/flist.c
33--- a/flist.c
34+++ b/flist.c
7e420a3e 35@@ -26,6 +26,7 @@
ae10e51e
WD
36 #include "io.h"
37
38 extern int verbose;
39+extern int dry_run;
ae10e51e
WD
40 extern int am_root;
41 extern int am_server;
cdcd2137
WD
42 extern int am_daemon;
43@@ -58,6 +59,7 @@ extern int implied_dirs;
ae10e51e
WD
44 extern int file_extra_cnt;
45 extern int ignore_perishable;
46 extern int non_perishable_cnt;
47+extern int checksum_updating;
48 extern int prune_empty_dirs;
49 extern int copy_links;
50 extern int copy_unsafe_links;
cc3e685d 51@@ -83,6 +85,9 @@ extern iconv_t ic_send, ic_recv;
56522462
WD
52
53 #define PTR_SIZE (sizeof (struct file_struct *))
54
edf38a9d
WD
55+#define FLAG_SUM_MISSING (1<<1) /* F_SUM() data is undefined */
56+#define FLAG_SUM_KEEP (1<<2) /* keep entry when rewriting */
56522462
WD
57+
58 int io_error;
59 int checksum_len;
60 dev_t filesystem_dev; /* used to implement -x */
f2863bc0
WD
61@@ -121,6 +126,9 @@ static char tmp_sum[MAX_DIGEST_LEN];
62 static char empty_sum[MAX_DIGEST_LEN];
ae10e51e
WD
63 static int flist_count_offset; /* for --delete --progress */
64 static int dir_count = 0;
ae10e51e 65+static int checksum_matches = 0;
071bf6df 66+static int checksum_updates = 0;
7200c744 67+static int regular_skipped = 0;
213d4328 68 static struct file_list *checksum_flist = NULL;
ae10e51e 69
f2863bc0
WD
70 static void flist_sort_and_clean(struct file_list *flist, int strip_root);
71@@ -316,7 +324,8 @@ static void flist_done_allocating(struct file_list *flist)
ae10e51e 72
213d4328
WD
73 /* The len count is the length of the basename + 1 for the null. */
74 static int add_checksum(const char *dirname, const char *basename, int len,
75- OFF_T file_length, time_t mtime, const char *sum)
e2bccb59
WD
76+ OFF_T file_length, time_t mtime, int32 ctime, int32 inode,
77+ const char *sum, const char *alt_sum, int flags)
213d4328
WD
78 {
79 struct file_struct *file;
80 int alloc_len, extra_len;
f2863bc0 81@@ -327,13 +336,14 @@ static int add_checksum(const char *dirname, const char *basename, int len,
213d4328
WD
82 if (file_length == 0)
83 return 0;
84
85- extra_len = (file_extra_cnt + (file_length > 0xFFFFFFFFu) + SUM_EXTRA_CNT)
e2bccb59
WD
86+ /* "2" is for a 32-bit ctime num and an 32-bit inode num. */
87+ extra_len = (file_extra_cnt + (file_length > 0xFFFFFFFFu) + SUM_EXTRA_CNT + 2)
213d4328
WD
88 * EXTRA_LEN;
89 #if EXTRA_ROUNDING > 0
90 if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN))
91 extra_len = (extra_len | (EXTRA_ROUNDING * EXTRA_LEN)) + EXTRA_LEN;
92 #endif
93- alloc_len = FILE_STRUCT_LEN + extra_len + len;
56522462 94+ alloc_len = FILE_STRUCT_LEN + extra_len + len + checksum_len*2 + 1;
213d4328
WD
95 bp = pool_alloc(checksum_flist->file_pool, alloc_len, "add_checksum");
96
97 memset(bp, 0, extra_len + FILE_STRUCT_LEN);
f2863bc0 98@@ -342,7 +352,14 @@ static int add_checksum(const char *dirname, const char *basename, int len,
213d4328
WD
99 bp += FILE_STRUCT_LEN;
100
101 memcpy(bp, basename, len);
56522462
WD
102+ if (alt_sum)
103+ strlcpy(bp+len, alt_sum, checksum_len*2 + 1);
104+ else {
105+ memset(bp+len, '=', checksum_len*2);
106+ bp[len+checksum_len*2] = '\0';
107+ }
213d4328 108
ae10e51e 109+ file->flags = flags;
213d4328
WD
110 file->mode = S_IFREG;
111 file->modtime = mtime;
112 file->len32 = (uint32)file_length;
f2863bc0 113@@ -353,6 +370,8 @@ static int add_checksum(const char *dirname, const char *basename, int len,
213d4328
WD
114 file->dirname = dirname;
115 bp = F_SUM(file);
116 memcpy(bp, sum, checksum_len);
e2bccb59
WD
117+ F_CTIME(file) = ctime;
118+ F_INODE(file) = inode;
213d4328
WD
119
120 flist_expand(checksum_flist, 1);
121 checksum_flist->files[checksum_flist->used++] = file;
f2863bc0 122@@ -362,17 +381,104 @@ static int add_checksum(const char *dirname, const char *basename, int len,
213d4328
WD
123 return 1;
124 }
125
071bf6df
WD
126+static void write_checksums(const char *next_dirname, int whole_dir)
127+{
128+ static const char *dirname_save;
129+ char fbuf[MAXPATHLEN];
130+ const char *dirname;
e2bccb59 131+ int used, new_entries, counts_match, no_skipped;
071bf6df
WD
132+ FILE *out_fp;
133+ int i;
134+
135+ dirname = dirname_save;
136+ dirname_save = next_dirname;
137+
138+ if (!dirname)
139+ return;
140+
e2bccb59 141+ used = checksum_flist->used;
071bf6df 142+ new_entries = checksum_updates != 0;
e2bccb59 143+ counts_match = used == checksum_matches;
071bf6df
WD
144+ no_skipped = whole_dir && regular_skipped == 0;
145+
85096e5e 146+ flist_sort_and_clean(checksum_flist, 0);
071bf6df 147+
e2bccb59 148+ checksum_flist->used = 0;
071bf6df
WD
149+ checksum_matches = 0;
150+ checksum_updates = 0;
151+ regular_skipped = 0;
152+
153+ if (dry_run)
154+ return;
155+
156+ if (*dirname) {
157+ if (pathjoin(fbuf, sizeof fbuf, dirname, ".rsyncsums") >= sizeof fbuf)
158+ return;
159+ } else
160+ strlcpy(fbuf, ".rsyncsums", sizeof fbuf);
161+
162+ if (checksum_flist->high - checksum_flist->low < 0 && no_skipped) {
163+ unlink(fbuf);
164+ return;
165+ }
166+
167+ if (!new_entries && (counts_match || !whole_dir))
168+ return;
169+
170+ if (!(out_fp = fopen(fbuf, "w")))
171+ return;
172+
173+ new_entries = 0;
174+ for (i = checksum_flist->low; i <= checksum_flist->high; i++) {
175+ struct file_struct *file = checksum_flist->sorted[i];
176+ const char *cp = F_SUM(file);
177+ const char *end = cp + checksum_len;
178+ const char *alt_sum = file->basename + strlen(file->basename) + 1;
e2bccb59 179+ int32 ctime, inode;
071bf6df
WD
180+ if (whole_dir && !(file->flags & FLAG_SUM_KEEP))
181+ continue;
e2bccb59
WD
182+ ctime = F_CTIME(file);
183+ inode = F_INODE(file);
071bf6df
WD
184+ if (protocol_version >= 30)
185+ fprintf(out_fp, "%s ", alt_sum);
186+ if (file->flags & FLAG_SUM_MISSING) {
187+ new_entries++;
188+ do {
189+ fprintf(out_fp, "==");
190+ } while (++cp != end);
191+ } else {
192+ do {
505968ea 193+ fprintf(out_fp, "%02x", (int)CVAL(cp, 0));
071bf6df
WD
194+ } while (++cp != end);
195+ }
196+ if (protocol_version < 30)
197+ fprintf(out_fp, " %s", alt_sum);
198+ if (*alt_sum == '=')
199+ new_entries++;
e2bccb59 200+ fprintf(out_fp, " %10.0f %10.0f %10lu %10lu %s\n",
071bf6df 201+ (double)F_LENGTH(file), (double)file->modtime,
e2bccb59 202+ (long)ctime, (long)inode, file->basename);
071bf6df
WD
203+ }
204+
205+ fclose(out_fp);
071bf6df
WD
206+}
207+
213d4328
WD
208 /* The direname value must remain unchanged during the lifespan of the
209 * created checksum_flist object because we use it directly. */
210 static void read_checksums(const char *dirname)
211 {
212 char line[MAXPATHLEN+1024], fbuf[MAXPATHLEN], sum[MAX_DIGEST_LEN];
56522462 213+ const char *alt_sum = NULL;
213d4328
WD
214 OFF_T file_length;
215 time_t mtime;
216- int len, dlen, i;
e2bccb59 217+ int32 ctime, inode;
ae10e51e 218+ int len, dlen, i, flags;
213d4328
WD
219 char *cp;
220 FILE *fp;
221
e2bccb59
WD
222+ if (checksum_updating)
223+ write_checksums(dirname, 0);
071bf6df 224+
213d4328
WD
225 if (checksum_flist) {
226 /* Reset the pool memory and empty the file-list array. */
227 pool_free_old(checksum_flist->file_pool,
f2863bc0 228@@ -383,6 +489,9 @@ static void read_checksums(const char *dirname)
213d4328
WD
229
230 checksum_flist->low = 0;
231 checksum_flist->high = -1;
ae10e51e 232+ checksum_matches = 0;
071bf6df 233+ checksum_updates = 0;
7200c744 234+ regular_skipped = 0;
213d4328
WD
235
236 if (!dirname)
237 return;
f2863bc0 238@@ -401,7 +510,7 @@ static void read_checksums(const char *dirname)
213d4328
WD
239 while (fgets(line, sizeof line, fp)) {
240 cp = line;
241 if (protocol_version >= 30) {
242- char *alt_sum = cp;
56522462 243+ alt_sum = cp;
213d4328
WD
244 if (*cp == '=')
245 while (*++cp == '=') {}
246 else
f2863bc0 247@@ -412,7 +521,14 @@ static void read_checksums(const char *dirname)
213d4328
WD
248 }
249
250 if (*cp == '=') {
251- continue;
56522462
WD
252+ for (i = 0; i < checksum_len*2; i++, cp++) {
253+ if (*cp != '=') {
ae10e51e
WD
254+ cp = "";
255+ break;
256+ }
ae10e51e 257+ }
56522462
WD
258+ memset(sum, 0, checksum_len);
259+ flags = FLAG_SUM_MISSING;
213d4328
WD
260 } else {
261 for (i = 0; i < checksum_len*2; i++, cp++) {
262 int x;
f2863bc0 263@@ -430,13 +546,14 @@ static void read_checksums(const char *dirname)
213d4328
WD
264 else
265 sum[i/2] = x << 4;
266 }
56522462 267+ flags = 0;
213d4328
WD
268 }
269 if (*cp != ' ')
270 break;
271 while (*++cp == ' ') {}
272
273 if (protocol_version < 30) {
274- char *alt_sum = cp;
56522462 275+ alt_sum = cp;
213d4328
WD
276 if (*cp == '=')
277 while (*++cp == '=') {}
278 else
f2863bc0 279@@ -460,16 +577,16 @@ static void read_checksums(const char *dirname)
213d4328
WD
280 break;
281 while (*++cp == ' ') {}
282
283- /* Ignore ctime. */
7200c744 284+ ctime = 0;
213d4328
WD
285 while (isDigit(cp))
286- cp++;
7200c744 287+ ctime = ctime * 10 + *cp++ - '0';
213d4328
WD
288 if (*cp != ' ')
289 break;
290 while (*++cp == ' ') {}
291
292- /* Ignore inode. */
e2bccb59 293+ inode = 0;
213d4328
WD
294 while (isDigit(cp))
295- cp++;
e2bccb59 296+ inode = inode * 10 + *cp++ - '0';
213d4328
WD
297 if (*cp != ' ')
298 break;
299 while (*++cp == ' ') {}
f2863bc0 300@@ -486,8 +603,13 @@ static void read_checksums(const char *dirname)
213d4328
WD
301 continue;
302
303 strlcpy(fbuf+dlen, cp, sizeof fbuf - dlen);
ae10e51e 304+ if (is_excluded(fbuf, 0, ALL_FILTERS)) {
edf38a9d 305+ flags |= FLAG_SUM_KEEP;
ae10e51e 306+ checksum_matches++;
56522462 307+ }
213d4328
WD
308
309- add_checksum(dirname, cp, len, file_length, mtime, sum);
e2bccb59 310+ add_checksum(dirname, cp, len, file_length, mtime, ctime, inode,
56522462 311+ sum, alt_sum, flags);
213d4328
WD
312 }
313 fclose(fp);
314
a5e6228a 315@@ -1278,6 +1400,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
7200c744
WD
316 if (is_excluded(thisname, S_ISDIR(st.st_mode) != 0, filter_level)) {
317 if (ignore_perishable)
318 non_perishable_cnt++;
319+ if (S_ISREG(st.st_mode))
320+ regular_skipped++;
321 return NULL;
322 }
323
a5e6228a 324@@ -1408,13 +1532,36 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
213d4328
WD
325 int j;
326 if (flist && (j = flist_find(checksum_flist, file)) >= 0) {
327 struct file_struct *fp = checksum_flist->sorted[j];
e2bccb59
WD
328+ int32 ctime = F_CTIME(fp);
329+ int32 inode = F_INODE(fp);
213d4328
WD
330 if (F_LENGTH(fp) == st.st_size
331- && fp->modtime == st.st_mtime)
332- memcpy(tmp_sum, F_SUM(fp), MAX_DIGEST_LEN);
333- else
334- file_checksum(thisname, tmp_sum, st.st_size);
335- } else
e2bccb59
WD
336+ && fp->modtime == st.st_mtime
337+ && ctime == (int32)st.st_ctime
338+ && inode == (int32)st.st_ino) {
56522462
WD
339+ if (fp->flags & FLAG_SUM_MISSING) {
340+ fp->flags &= ~FLAG_SUM_MISSING;
e2bccb59 341+ checksum_updates++;
56522462 342+ file_checksum(thisname, tmp_sum, st.st_size);
a3ba6627 343+ memcpy(F_SUM(fp), tmp_sum, MAX_DIGEST_LEN);
56522462
WD
344+ } else {
345+ checksum_matches++;
346+ memcpy(tmp_sum, F_SUM(fp), MAX_DIGEST_LEN);
347+ }
edf38a9d 348+ fp->flags |= FLAG_SUM_KEEP;
ae10e51e
WD
349+ } else {
350+ clear_file(fp);
edf38a9d 351+ goto compute_new_checksum;
ae10e51e
WD
352+ }
353+ } else {
edf38a9d 354+ compute_new_checksum:
213d4328 355 file_checksum(thisname, tmp_sum, st.st_size);
ae10e51e 356+ if (checksum_updating && flist) {
e2bccb59
WD
357+ checksum_updates +=
358+ add_checksum(file->dirname, basename, basename_len,
359+ st.st_size, st.st_mtime, st.st_ctime,
360+ st.st_ino, tmp_sum, NULL, FLAG_SUM_KEEP);
ae10e51e
WD
361+ }
362+ }
213d4328
WD
363 }
364
ae10e51e 365 /* This code is only used by the receiver when it is building
a5e6228a 366@@ -1709,6 +1856,9 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len,
ae10e51e
WD
367
368 closedir(d);
369
370+ if (checksum_updating && always_checksum && am_sender && f >= 0)
071bf6df 371+ write_checksums(NULL, 1);
ae10e51e
WD
372+
373 if (f >= 0 && recurse && !divert_dirs) {
9c85142a
WD
374 int i, end = flist->used - 1;
375 /* send_if_directory() bumps flist->used, so use "end". */
85096e5e
WD
376@@ -2274,6 +2424,9 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
377 }
378 } else
6e9495c7 379 flist_eof = 1;
85096e5e
WD
380+
381+ if (checksum_updating && always_checksum && flist_eof)
071bf6df
WD
382+ read_checksums(NULL); /* writes any last updates */
383
384 return flist;
385 }
cc3e685d
WD
386diff --git a/loadparm.c b/loadparm.c
387--- a/loadparm.c
388+++ b/loadparm.c
85096e5e 389@@ -154,6 +154,7 @@ typedef struct
ae10e51e
WD
390 int syslog_facility;
391 int timeout;
392
393+ BOOL checksum_updating;
394 BOOL fake_super;
395 BOOL ignore_errors;
396 BOOL ignore_nonreadable;
85096e5e 397@@ -205,6 +206,7 @@ static service sDefault =
ae10e51e
WD
398 /* syslog_facility; */ LOG_DAEMON,
399 /* timeout; */ 0,
400
401+ /* checksum_updating; */ False,
402 /* fake_super; */ False,
403 /* ignore_errors; */ False,
404 /* ignore_nonreadable; */ False,
85096e5e 405@@ -306,6 +308,7 @@ static struct parm_struct parm_table[] =
cc3e685d
WD
406
407 {"auth users", P_STRING, P_LOCAL, &sDefault.auth_users, NULL,0},
85096e5e 408 {"charset", P_STRING, P_LOCAL, &sDefault.charset, NULL,0},
ae10e51e 409+ {"checksum updating", P_BOOL, P_LOCAL, &sDefault.checksum_updating, NULL,0},
cc3e685d
WD
410 {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL,0},
411 {"dont compress", P_STRING, P_LOCAL, &sDefault.dont_compress, NULL,0},
412 {"exclude from", P_STRING, P_LOCAL, &sDefault.exclude_from, NULL,0},
85096e5e
WD
413@@ -428,6 +431,7 @@ FN_LOCAL_INTEGER(lp_max_verbosity, max_verbosity)
414 FN_LOCAL_INTEGER(lp_syslog_facility, syslog_facility)
cc3e685d
WD
415 FN_LOCAL_INTEGER(lp_timeout, timeout)
416
417+FN_LOCAL_BOOL(lp_checksum_updating, checksum_updating)
418 FN_LOCAL_BOOL(lp_fake_super, fake_super)
ae10e51e
WD
419 FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors)
420 FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable)
cc3e685d
WD
421diff --git a/options.c b/options.c
422--- a/options.c
423+++ b/options.c
f2863bc0 424@@ -112,6 +112,7 @@ size_t bwlimit_writemax = 0;
ae10e51e
WD
425 int ignore_existing = 0;
426 int ignore_non_existing = 0;
427 int need_messages_from_generator = 0;
428+int checksum_updating = 0;
99650e0d 429 int max_delete = INT_MIN;
ae10e51e
WD
430 OFF_T max_size = 0;
431 OFF_T min_size = 0;
85096e5e 432@@ -316,6 +317,7 @@ void usage(enum logcode F)
ae10e51e
WD
433 rprintf(F," -q, --quiet suppress non-error messages\n");
434 rprintf(F," --no-motd suppress daemon-mode MOTD (see manpage caveat)\n");
435 rprintf(F," -c, --checksum skip based on checksum, not mod-time & size\n");
56522462 436+ rprintf(F," --checksum-updating sender updates .rsyncsums files\n");
ae10e51e
WD
437 rprintf(F," -a, --archive archive mode; equals -rlptgoD (no -H,-A,-X)\n");
438 rprintf(F," --no-OPTION turn off an implied OPTION (e.g. --no-D)\n");
439 rprintf(F," -r, --recursive recurse into directories\n");
85096e5e 440@@ -566,6 +568,7 @@ static struct poptOption long_options[] = {
ae10e51e
WD
441 {"checksum", 'c', POPT_ARG_VAL, &always_checksum, 1, 0, 0 },
442 {"no-checksum", 0, POPT_ARG_VAL, &always_checksum, 0, 0, 0 },
443 {"no-c", 0, POPT_ARG_VAL, &always_checksum, 0, 0, 0 },
444+ {"checksum-updating",0, POPT_ARG_NONE, &checksum_updating, 0, 0, 0 },
445 {"block-size", 'B', POPT_ARG_LONG, &block_size, 0, 0, 0 },
446 {"compare-dest", 0, POPT_ARG_STRING, 0, OPT_COMPARE_DEST, 0, 0 },
447 {"copy-dest", 0, POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 },
85096e5e 448@@ -1988,7 +1991,9 @@ void server_options(char **args, int *argc_p)
ae10e51e
WD
449 args[ac++] = basis_dir[i];
450 }
451 }
452- }
453+ } else if (checksum_updating)
454+ args[ac++] = "--checksum-updating";
455+
456
505968ea
WD
457 if (append_mode) {
458 if (append_mode > 1)
cc3e685d
WD
459diff --git a/rsync.h b/rsync.h
460--- a/rsync.h
461+++ b/rsync.h
85096e5e 462@@ -680,6 +680,10 @@ extern int xattrs_ndx;
e2bccb59
WD
463 #define F_SUM(f) ((char*)OPT_EXTRA(f, LEN64_BUMP(f) + HLINK_BUMP(f) \
464 + SUM_EXTRA_CNT - 1))
7200c744 465
e2bccb59
WD
466+/* These are only valid on an entry read from a checksum file. */
467+#define F_CTIME(f) OPT_EXTRA(f, LEN64_BUMP(f) + SUM_EXTRA_CNT)->num
468+#define F_INODE(f) OPT_EXTRA(f, LEN64_BUMP(f) + SUM_EXTRA_CNT + 1)->num
469+
470 /* Some utility defines: */
471 #define F_IS_ACTIVE(f) (f)->basename[0]
472 #define F_IS_HLINKED(f) ((f)->flags & FLAG_HLINKED)
cc3e685d
WD
473diff --git a/rsync.yo b/rsync.yo
474--- a/rsync.yo
475+++ b/rsync.yo
476@@ -317,6 +317,7 @@ to the detailed description below for a complete description. verb(
ae10e51e
WD
477 -q, --quiet suppress non-error messages
478 --no-motd suppress daemon-mode MOTD (see caveat)
479 -c, --checksum skip based on checksum, not mod-time & size
56522462 480+ --checksum-updating sender updates .rsyncsums files
ae10e51e
WD
481 -a, --archive archive mode; equals -rlptgoD (no -H,-A,-X)
482 --no-OPTION turn off an implied OPTION (e.g. --no-D)
483 -r, --recursive recurse into directories
cc3e685d 484@@ -516,9 +517,9 @@ uses a "quick check" that (by default) checks if each file's size and time
ae10e51e
WD
485 of last modification match between the sender and receiver. This option
486 changes this to compare a 128-bit MD4 checksum for each file that has a
487 matching size. Generating the checksums means that both sides will expend
488-a lot of disk I/O reading all the data in the files in the transfer (and
489-this is prior to any reading that will be done to transfer changed files),
490-so this can slow things down significantly.
491+a lot of disk I/O reading the data in all the files in the transfer, so
492+this can slow things down significantly (and this is prior to any reading
493+that will be done to transfer the files that have changed).
494
495 The sending side generates its checksums while it is doing the file-system
496 scan that builds the list of the available files. The receiver generates
cc3e685d 497@@ -526,12 +527,42 @@ its checksums when it is scanning for changed files, and will checksum any
ae10e51e
WD
498 file that has the same size as the corresponding sender's file: files with
499 either a changed size or a changed checksum are selected for transfer.
500
501+Starting with version 3.0.0, the sending side will look for a checksum
502+summary file and use a pre-generated checksum that it reads out of the file
503+(as long as it matches the file's size and modified time). This allows a
504+server to support the --checksum option to clients without having to
505+recompute the checksums for each client. See the bf(--checksum-updating)
56522462 506+option for a way to have rsync create/update these checksum files.
ae10e51e
WD
507+
508 Note that rsync always verifies that each em(transferred) file was
509 correctly reconstructed on the receiving side by checking a whole-file
85096e5e 510 checksum that is generated as the file is transferred, but that
ae10e51e
WD
511 automatic after-the-transfer verification has nothing to do with this
512 option's before-the-transfer "Does this file need to be updated?" check.
513
514+dit(bf(--checksum-updating)) This option tells the sending side to create
515+and/or update per-directory checksum files that are used by the
56522462
WD
516+bf(--checksum) option. The file that is updated is named .rsyncsums. If
517+pre-transfer checksums are not being computed, this option has no effect.
ae10e51e
WD
518+
519+The checksum files stores the computed checksum, last-known size,
520+modification time, and name for each file in the current directory. If a
521+later transfer finds that a file matches its prior size and modification
522+time, the checksum is assumed to still be correct. Otherwise it is
523+recomputed and udpated in the file.
524+
525+To avoid transferring the system's checksum files, you can use an exclude
56522462 526+(e.g. bf(--exclude=.rsyncsums)). To make this easier to type, you can use
ae10e51e
WD
527+a popt alias. For instance, adding the following line in your ~/.popt file
528+defines a bf(-cc) option that enables checksum updating and excludes the
529+checksum files:
530+
56522462 531+verb( rsync alias --cc --checksum-updating --exclude=.rsyncsums)
ae10e51e
WD
532+
533+An rsync daemon does not allow the client to control this setting, so see
534+the "checksum updating" daemon config option for information on how to make
535+a daemon maintain these checksum files.
536+
537 dit(bf(-a, --archive)) This is equivalent to bf(-rlptgoD). It is a quick
538 way of saying you want recursion and want to preserve almost
539 everything (with -H being a notable omission).
cc3e685d
WD
540diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo
541--- a/rsyncd.conf.yo
542+++ b/rsyncd.conf.yo
85096e5e 543@@ -281,6 +281,20 @@ locking on this file to ensure that the max connections limit is not
ae10e51e
WD
544 exceeded for the modules sharing the lock file.
545 The default is tt(/var/run/rsyncd.lock).
546
547+dit(bf(checksum updating)) This option tells rsync to update/create the
548+checksum information in the per-directory checksum files when users copy
549+files using the bf(--checksum) option. Any file that has changed since it
550+was last checksummed (or is not mentioned) has its data updated in the
56522462 551+.rsyncsums file.
ae10e51e
WD
552+
553+Note that this updating will occur even if the module is listed as being
554+read-only. If you want to hide these files (and you will almost always
56522462 555+want to do), add ".rsyncsums" to the module's exclude setting.
ae10e51e
WD
556+
557+Note also that the client's command-line option, bf(--checksum-updating),
558+has no effect on a daemon. A daemon will only update/create checksum files
559+if this config option is true.
560+
561 dit(bf(read only)) The "read only" option determines whether clients
562 will be able to upload files or not. If "read only" is true then any
563 attempted uploads will fail. If "read only" is false then uploads will