Commit | Line | Data |
---|---|---|
f9df736a WD |
1 | This builds on the checksum-reading patch and adds the ability to |
2 | create and/or update the .rsyncsums files using extended mode args to | |
3 | the --sumfiles=MODE option and the "checksum files = MODE" daemon | |
4 | parameter. | |
5 | ||
6 | CAUTION: This patch is only lightly tested. If you're interested | |
7 | in using it, please help out. | |
ae10e51e WD |
8 | |
9 | To use this patch, run these commands for a successful build: | |
10 | ||
cc3e685d | 11 | patch -p1 <patches/checksum-reading.diff |
ae10e51e WD |
12 | patch -p1 <patches/checksum-updating.diff |
13 | ./configure (optional if already run) | |
14 | make | |
15 | ||
f9df736a WD |
16 | TODO: |
17 | ||
18 | - Fix the code that removes .rsyncsums files when a dir becomes empty. | |
19 | ||
7170ca8d | 20 | based-on: patch/checksum-reading |
cc3e685d WD |
21 | diff --git a/flist.c b/flist.c |
22 | --- a/flist.c | |
23 | +++ b/flist.c | |
fc557362 WD |
24 | @@ -27,6 +27,7 @@ |
25 | #include "inums.h" | |
ae10e51e WD |
26 | #include "io.h" |
27 | ||
ae10e51e | 28 | +extern int dry_run; |
ae10e51e WD |
29 | extern int am_root; |
30 | extern int am_server; | |
cdcd2137 | 31 | extern int am_daemon; |
72e5645e | 32 | @@ -107,6 +108,9 @@ extern iconv_t ic_send, ic_recv; |
56522462 WD |
33 | |
34 | #define PTR_SIZE (sizeof (struct file_struct *)) | |
35 | ||
edf38a9d WD |
36 | +#define FLAG_SUM_MISSING (1<<1) /* F_SUM() data is undefined */ |
37 | +#define FLAG_SUM_KEEP (1<<2) /* keep entry when rewriting */ | |
56522462 WD |
38 | + |
39 | int io_error; | |
40 | int checksum_len; | |
41 | dev_t filesystem_dev; /* used to implement -x */ | |
72e5645e | 42 | @@ -146,8 +150,13 @@ static char tmp_sum[MAX_DIGEST_LEN]; |
fc557362 | 43 | static char empty_sum[MAX_DIGEST_LEN]; |
ae10e51e | 44 | static int flist_count_offset; /* for --delete --progress */ |
213d4328 | 45 | |
f9df736a WD |
46 | +#define REGULAR_SKIPPED(flist) ((flist)->to_redo) |
47 | + | |
48 | static struct csum_cache { | |
49 | struct file_list *flist; | |
50 | + const char *dirname; | |
51 | + int checksum_matches; | |
52 | + int checksum_updates; | |
53 | } *csum_cache = NULL; | |
213d4328 | 54 | |
f9df736a | 55 | static void flist_sort_and_clean(struct file_list *flist, int flags); |
72e5645e | 56 | @@ -365,7 +374,79 @@ static void flist_done_allocating(struct file_list *flist) |
f9df736a | 57 | flist->pool_boundary = ptr; |
213d4328 WD |
58 | } |
59 | ||
f9df736a WD |
60 | -void reset_checksum_cache() |
61 | +static void checksum_filename(int slot, const char *dirname, char *fbuf) | |
071bf6df | 62 | +{ |
f9df736a WD |
63 | + if (dirname && *dirname) { |
64 | + unsigned int len; | |
65 | + if (slot) { | |
66 | + len = strlcpy(fbuf, basis_dir[slot-1], MAXPATHLEN); | |
67 | + if (len >= MAXPATHLEN) | |
68 | + return; | |
69 | + } else | |
70 | + len = 0; | |
71 | + if (pathjoin(fbuf+len, MAXPATHLEN-len, dirname, RSYNCSUMS_FILE) >= MAXPATHLEN-len) | |
72 | + return; | |
73 | + } else | |
74 | + strlcpy(fbuf, RSYNCSUMS_FILE, MAXPATHLEN); | |
75 | +} | |
071bf6df | 76 | + |
f9df736a WD |
77 | +static void write_checksums(int slot, struct file_list *flist, int whole_dir) |
78 | +{ | |
79 | + int i; | |
80 | + FILE *out_fp; | |
81 | + char fbuf[MAXPATHLEN]; | |
82 | + int new_entries = csum_cache[slot].checksum_updates != 0; | |
83 | + int counts_match = flist->used == csum_cache[slot].checksum_matches; | |
84 | + int no_skipped = whole_dir && REGULAR_SKIPPED(flist) == 0; | |
85 | + const char *dirname = csum_cache[slot].dirname; | |
071bf6df | 86 | + |
f9df736a | 87 | + flist_sort_and_clean(flist, 0); |
071bf6df | 88 | + |
f9df736a | 89 | + if (dry_run && !(checksum_files & CSF_AFFECT_DRYRUN)) |
071bf6df WD |
90 | + return; |
91 | + | |
f9df736a | 92 | + checksum_filename(slot, dirname, fbuf); |
071bf6df | 93 | + |
f9df736a | 94 | + if (flist->high - flist->low < 0 && no_skipped) { |
071bf6df WD |
95 | + unlink(fbuf); |
96 | + return; | |
97 | + } | |
98 | + | |
99 | + if (!new_entries && (counts_match || !whole_dir)) | |
100 | + return; | |
101 | + | |
102 | + if (!(out_fp = fopen(fbuf, "w"))) | |
103 | + return; | |
104 | + | |
f9df736a WD |
105 | + for (i = flist->low; i <= flist->high; i++) { |
106 | + struct file_struct *file = flist->sorted[i]; | |
071bf6df WD |
107 | + const char *cp = F_SUM(file); |
108 | + const char *end = cp + checksum_len; | |
109 | + const char *alt_sum = file->basename + strlen(file->basename) + 1; | |
071bf6df WD |
110 | + if (whole_dir && !(file->flags & FLAG_SUM_KEEP)) |
111 | + continue; | |
071bf6df WD |
112 | + if (protocol_version >= 30) |
113 | + fprintf(out_fp, "%s ", alt_sum); | |
114 | + if (file->flags & FLAG_SUM_MISSING) { | |
071bf6df | 115 | + do { |
f9df736a | 116 | + fputs("==", out_fp); |
071bf6df WD |
117 | + } while (++cp != end); |
118 | + } else { | |
119 | + do { | |
505968ea | 120 | + fprintf(out_fp, "%02x", (int)CVAL(cp, 0)); |
071bf6df WD |
121 | + } while (++cp != end); |
122 | + } | |
123 | + if (protocol_version < 30) | |
124 | + fprintf(out_fp, " %s", alt_sum); | |
e2bccb59 | 125 | + fprintf(out_fp, " %10.0f %10.0f %10lu %10lu %s\n", |
071bf6df | 126 | + (double)F_LENGTH(file), (double)file->modtime, |
f9df736a | 127 | + (long)F_CTIME(file), (long)F_INODE(file), file->basename); |
071bf6df WD |
128 | + } |
129 | + | |
130 | + fclose(out_fp); | |
071bf6df WD |
131 | +} |
132 | + | |
f9df736a | 133 | +void reset_checksum_cache(int whole_dir) |
213d4328 | 134 | { |
f9df736a WD |
135 | int slot, slots = am_sender ? 1 : basis_dir_cnt + 1; |
136 | ||
72e5645e | 137 | @@ -379,6 +460,9 @@ void reset_checksum_cache() |
f9df736a WD |
138 | struct file_list *flist = csum_cache[slot].flist; |
139 | ||
140 | if (flist) { | |
141 | + if (checksum_files & CSF_UPDATE && flist->next) | |
142 | + write_checksums(slot, flist, whole_dir); | |
143 | + | |
144 | /* Reset the pool memory and empty the file-list array. */ | |
145 | pool_free_old(flist->file_pool, | |
146 | pool_boundary(flist->file_pool, 0)); | |
72e5645e | 147 | @@ -389,6 +473,10 @@ void reset_checksum_cache() |
f9df736a WD |
148 | flist->low = 0; |
149 | flist->high = -1; | |
150 | flist->next = NULL; | |
151 | + | |
152 | + csum_cache[slot].checksum_matches = 0; | |
153 | + csum_cache[slot].checksum_updates = 0; | |
154 | + REGULAR_SKIPPED(flist) = 0; | |
155 | } | |
156 | } | |
157 | ||
72e5645e | 158 | @@ -396,7 +484,7 @@ void reset_checksum_cache() |
f9df736a WD |
159 | static int add_checksum(struct file_list *flist, const char *dirname, |
160 | const char *basename, int basename_len, OFF_T file_length, | |
161 | time_t mtime, uint32 ctime, uint32 inode, | |
162 | - const char *sum) | |
163 | + const char *sum, const char *alt_sum, int flags) | |
164 | { | |
165 | struct file_struct *file; | |
166 | int alloc_len, extra_len; | |
72e5645e | 167 | @@ -413,7 +501,7 @@ static int add_checksum(struct file_list *flist, const char *dirname, |
f9df736a WD |
168 | if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN)) |
169 | extra_len = (extra_len | (EXTRA_ROUNDING * EXTRA_LEN)) + EXTRA_LEN; | |
170 | #endif | |
171 | - alloc_len = FILE_STRUCT_LEN + extra_len + basename_len; | |
172 | + alloc_len = FILE_STRUCT_LEN + extra_len + basename_len + checksum_len*2 + 1; | |
173 | bp = pool_alloc(flist->file_pool, alloc_len, "add_checksum"); | |
174 | ||
175 | memset(bp, 0, extra_len + FILE_STRUCT_LEN); | |
72e5645e | 176 | @@ -422,7 +510,14 @@ static int add_checksum(struct file_list *flist, const char *dirname, |
f9df736a WD |
177 | bp += FILE_STRUCT_LEN; |
178 | ||
179 | memcpy(bp, basename, basename_len); | |
180 | + if (alt_sum) | |
181 | + strlcpy(bp+basename_len, alt_sum, checksum_len*2 + 1); | |
182 | + else { | |
183 | + memset(bp+basename_len, '=', checksum_len*2); | |
184 | + bp[basename_len+checksum_len*2] = '\0'; | |
185 | + } | |
186 | ||
187 | + file->flags = flags; | |
188 | file->mode = S_IFREG; | |
189 | file->modtime = mtime; | |
190 | file->len32 = (uint32)file_length; | |
72e5645e | 191 | @@ -451,10 +546,11 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam |
213d4328 | 192 | char line[MAXPATHLEN+1024], fbuf[MAXPATHLEN], sum[MAX_DIGEST_LEN]; |
213d4328 | 193 | FILE *fp; |
f9df736a WD |
194 | char *cp; |
195 | - int len, i; | |
196 | time_t mtime; | |
197 | + int len, i, flags; | |
198 | OFF_T file_length; | |
199 | uint32 ctime, inode; | |
200 | + const char *alt_sum = NULL; | |
201 | int dlen = dirname ? strlcpy(fbuf, dirname, sizeof fbuf) : 0; | |
213d4328 | 202 | |
c0c7984e | 203 | if (dlen >= (int)(sizeof fbuf - 1 - RSYNCSUMS_LEN)) |
72e5645e | 204 | @@ -475,7 +571,7 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam |
213d4328 WD |
205 | while (fgets(line, sizeof line, fp)) { |
206 | cp = line; | |
207 | if (protocol_version >= 30) { | |
208 | - char *alt_sum = cp; | |
56522462 | 209 | + alt_sum = cp; |
213d4328 WD |
210 | if (*cp == '=') |
211 | while (*++cp == '=') {} | |
212 | else | |
72e5645e | 213 | @@ -486,7 +582,14 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam |
213d4328 WD |
214 | } |
215 | ||
216 | if (*cp == '=') { | |
217 | - continue; | |
56522462 WD |
218 | + for (i = 0; i < checksum_len*2; i++, cp++) { |
219 | + if (*cp != '=') { | |
ae10e51e WD |
220 | + cp = ""; |
221 | + break; | |
222 | + } | |
ae10e51e | 223 | + } |
56522462 WD |
224 | + memset(sum, 0, checksum_len); |
225 | + flags = FLAG_SUM_MISSING; | |
213d4328 WD |
226 | } else { |
227 | for (i = 0; i < checksum_len*2; i++, cp++) { | |
228 | int x; | |
72e5645e | 229 | @@ -504,13 +607,14 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam |
213d4328 WD |
230 | else |
231 | sum[i/2] = x << 4; | |
232 | } | |
56522462 | 233 | + flags = 0; |
213d4328 WD |
234 | } |
235 | if (*cp != ' ') | |
236 | break; | |
237 | while (*++cp == ' ') {} | |
238 | ||
239 | if (protocol_version < 30) { | |
240 | - char *alt_sum = cp; | |
56522462 | 241 | + alt_sum = cp; |
213d4328 WD |
242 | if (*cp == '=') |
243 | while (*++cp == '=') {} | |
244 | else | |
72e5645e | 245 | @@ -560,24 +664,112 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam |
213d4328 WD |
246 | continue; |
247 | ||
248 | strlcpy(fbuf+dlen, cp, sizeof fbuf - dlen); | |
ae10e51e | 249 | + if (is_excluded(fbuf, 0, ALL_FILTERS)) { |
edf38a9d | 250 | + flags |= FLAG_SUM_KEEP; |
f9df736a | 251 | + csum_cache[slot].checksum_matches++; |
56522462 | 252 | + } |
213d4328 | 253 | |
f9df736a WD |
254 | add_checksum(flist, dirname, cp, len, file_length, |
255 | mtime, ctime, inode, | |
256 | - sum); | |
56522462 | 257 | + sum, alt_sum, flags); |
213d4328 WD |
258 | } |
259 | fclose(fp); | |
260 | ||
f9df736a WD |
261 | flist_sort_and_clean(flist, CLEAN_KEEP_LAST); |
262 | } | |
263 | ||
264 | +void set_cached_checksum(struct file_list *file_flist, struct file_struct *file) | |
265 | +{ | |
266 | + int j; | |
267 | + FILE *out_fp; | |
268 | + STRUCT_STAT st; | |
269 | + char fbuf[MAXPATHLEN]; | |
270 | + const char *fn = f_name(file, NULL); | |
271 | + struct file_list *flist = csum_cache[0].flist; | |
272 | + | |
273 | + if (dry_run && !(checksum_files & CSF_AFFECT_DRYRUN)) | |
274 | + return; | |
275 | + | |
276 | + if (stat(fn, &st) < 0) | |
277 | + return; | |
278 | + | |
279 | + checksum_filename(0, file->dirname, fbuf); | |
280 | + | |
281 | + if (file_flist != flist->next) { | |
282 | + const char *cp = F_SUM(file); | |
283 | + const char *end = cp + checksum_len; | |
284 | + | |
285 | + if (!(out_fp = fopen(fbuf, "a"))) | |
286 | + return; | |
287 | + | |
288 | + if (protocol_version >= 30) { | |
289 | + for (j = 0; j < checksum_len; j++) | |
290 | + fputs("==", out_fp); | |
291 | + fputc(' ', out_fp); | |
292 | + } | |
293 | + do { | |
294 | + fprintf(out_fp, "%02x", (int)CVAL(cp, 0)); | |
295 | + } while (++cp != end); | |
296 | + if (protocol_version < 30) { | |
297 | + fputc(' ', out_fp); | |
298 | + for (j = 0; j < checksum_len; j++) | |
299 | + fputs("==", out_fp); | |
300 | + } | |
301 | + fprintf(out_fp, " %10.0f %10.0f %10lu %10lu %s\n", | |
302 | + (double)st.st_size, (double)st.st_mtime, | |
303 | + (long)(uint32)st.st_ctime, (long)(uint32)st.st_ino, | |
304 | + file->basename); | |
305 | + | |
306 | + fclose(out_fp); | |
307 | + return; | |
308 | + } | |
309 | + | |
310 | + if ((j = flist_find(flist, file)) >= 0) { | |
311 | + struct file_struct *fp = flist->sorted[j]; | |
312 | + int inc = 0; | |
313 | + if (F_LENGTH(fp) != st.st_size) { | |
314 | + fp->len32 = (uint32)st.st_size; | |
315 | + if (st.st_size > 0xFFFFFFFFu) { | |
316 | + OPT_EXTRA(fp, 0)->unum = (uint32)(st.st_size >> 32); | |
317 | + fp->flags |= FLAG_LENGTH64; | |
318 | + } else | |
319 | + fp->flags &= FLAG_LENGTH64; | |
320 | + inc = 1; | |
321 | + } | |
322 | + if (fp->modtime != st.st_mtime) { | |
323 | + fp->modtime = st.st_mtime; | |
324 | + inc = 1; | |
325 | + } | |
326 | + if (F_CTIME(fp) != (uint32)st.st_ctime) { | |
327 | + F_CTIME(fp) = (uint32)st.st_ctime; | |
328 | + inc = 1; | |
329 | + } | |
330 | + if (F_INODE(fp) != (uint32)st.st_ino) { | |
331 | + F_INODE(fp) = (uint32)st.st_ino; | |
332 | + inc = 1; | |
333 | + } | |
334 | + memcpy(F_SUM(fp), F_SUM(file), MAX_DIGEST_LEN); | |
335 | + csum_cache[0].checksum_updates += inc; | |
336 | + fp->flags &= ~FLAG_SUM_MISSING; | |
337 | + fp->flags |= FLAG_SUM_KEEP; | |
338 | + return; | |
339 | + } | |
340 | + | |
341 | + csum_cache[0].checksum_updates += | |
342 | + add_checksum(flist, file->dirname, file->basename, strlen(file->basename) + 1, | |
343 | + st.st_size, (uint32)st.st_mtime, (uint32)st.st_ctime, | |
344 | + st.st_ino, F_SUM(file), NULL, FLAG_SUM_KEEP); | |
345 | +} | |
346 | + | |
347 | void get_cached_checksum(int slot, const char *fname, struct file_struct *file, | |
348 | - STRUCT_STAT *stp, char *sum_buf) | |
349 | + int basename_len, STRUCT_STAT *stp, char *sum_buf) | |
350 | { | |
351 | struct file_list *flist = csum_cache[slot].flist; | |
352 | int j; | |
353 | ||
354 | if (!flist->next) { | |
355 | flist->next = cur_flist; /* next points from checksum flist to file flist */ | |
356 | + csum_cache[slot].dirname = file->dirname; | |
357 | read_checksums(slot, flist, file->dirname); | |
358 | } | |
359 | ||
72e5645e | 360 | @@ -589,12 +781,31 @@ void get_cached_checksum(int slot, const char *fname, struct file_struct *file, |
f9df736a WD |
361 | && (checksum_files & CSF_LAX |
362 | || (F_CTIME(fp) == (uint32)stp->st_ctime | |
363 | && F_INODE(fp) == (uint32)stp->st_ino))) { | |
364 | - memcpy(sum_buf, F_SUM(fp), MAX_DIGEST_LEN); | |
365 | + if (fp->flags & FLAG_SUM_MISSING) { | |
366 | + fp->flags &= ~FLAG_SUM_MISSING; | |
367 | + csum_cache[slot].checksum_updates++; | |
368 | + file_checksum(fname, stp->st_size, sum_buf); | |
369 | + memcpy(F_SUM(fp), sum_buf, MAX_DIGEST_LEN); | |
370 | + } else { | |
371 | + csum_cache[slot].checksum_matches++; | |
372 | + memcpy(sum_buf, F_SUM(fp), MAX_DIGEST_LEN); | |
373 | + } | |
374 | + fp->flags |= FLAG_SUM_KEEP; | |
375 | return; | |
376 | } | |
377 | + clear_file(fp); | |
378 | } | |
379 | ||
380 | file_checksum(fname, stp->st_size, sum_buf); | |
381 | + | |
382 | + if (checksum_files & CSF_UPDATE) { | |
383 | + if (basename_len < 0) | |
384 | + basename_len = strlen(file->basename) + 1; | |
385 | + csum_cache[slot].checksum_updates += | |
386 | + add_checksum(flist, file->dirname, file->basename, basename_len, | |
387 | + stp->st_size, stp->st_mtime, (uint32)stp->st_ctime, | |
388 | + (uint32)stp->st_ino, sum_buf, NULL, FLAG_SUM_KEEP); | |
389 | + } | |
390 | } | |
391 | ||
cbdf862c | 392 | /* Call this with EITHER (1) "file, NULL, 0" to chdir() to the file's |
72e5645e | 393 | @@ -1489,6 +1700,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, |
7f0bf1cb | 394 | if (is_excluded(thisname, S_ISDIR(st.st_mode) != 0, filter_level)) { |
7200c744 WD |
395 | if (ignore_perishable) |
396 | non_perishable_cnt++; | |
397 | + if (S_ISREG(st.st_mode)) | |
f9df736a | 398 | + REGULAR_SKIPPED(flist)++; |
7200c744 WD |
399 | return NULL; |
400 | } | |
401 | ||
72e5645e | 402 | @@ -1535,13 +1748,13 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, |
f9df736a WD |
403 | lastdir[len] = '\0'; |
404 | lastdir_len = len; | |
405 | if (checksum_files && am_sender && flist) | |
406 | - reset_checksum_cache(); | |
407 | + reset_checksum_cache(0); | |
408 | } | |
409 | } else { | |
410 | basename = thisname; | |
411 | if (checksum_files && am_sender && flist && lastdir_len == -2) { | |
412 | lastdir_len = -1; | |
413 | - reset_checksum_cache(); | |
414 | + reset_checksum_cache(0); | |
415 | } | |
213d4328 | 416 | } |
f9df736a | 417 | basename_len = strlen(basename) + 1; /* count the '\0' */ |
72e5645e | 418 | @@ -1647,7 +1860,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist, |
f9df736a WD |
419 | |
420 | if (always_checksum && am_sender && S_ISREG(st.st_mode)) { | |
421 | if (flist && checksum_files) | |
422 | - get_cached_checksum(0, thisname, file, &st, tmp_sum); | |
423 | + get_cached_checksum(0, thisname, file, basename_len, &st, tmp_sum); | |
424 | else | |
425 | file_checksum(thisname, st.st_size, tmp_sum); | |
fc557362 | 426 | if (sender_keeps_checksum) |
72e5645e | 427 | @@ -2020,6 +2233,9 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len, |
ae10e51e WD |
428 | |
429 | closedir(d); | |
430 | ||
f9df736a WD |
431 | + if (checksum_files & CSF_UPDATE && am_sender && f >= 0) |
432 | + reset_checksum_cache(1); | |
ae10e51e WD |
433 | + |
434 | if (f >= 0 && recurse && !divert_dirs) { | |
9c85142a WD |
435 | int i, end = flist->used - 1; |
436 | /* send_if_directory() bumps flist->used, so use "end". */ | |
72e5645e WD |
437 | @@ -2643,6 +2859,9 @@ struct file_list *send_file_list(int f, int argc, char *argv[]) |
438 | rprintf(FINFO, "[%s] flist_eof=1\n", who_am_i()); | |
439 | } | |
e2e42a01 | 440 | |
f9df736a WD |
441 | + if (checksum_files & CSF_UPDATE && flist_eof) |
442 | + reset_checksum_cache(0); /* writes any last updates */ | |
e2e42a01 | 443 | + |
071bf6df WD |
444 | return flist; |
445 | } | |
e2e42a01 | 446 | |
f9df736a WD |
447 | diff --git a/generator.c b/generator.c |
448 | --- a/generator.c | |
449 | +++ b/generator.c | |
72e5645e | 450 | @@ -112,6 +112,7 @@ static int dir_tweaking; |
c0c7984e | 451 | static int symlink_timeset_failed_flags; |
f9df736a WD |
452 | static int need_retouch_dir_times; |
453 | static int need_retouch_dir_perms; | |
454 | +static int started_whole_dir, upcoming_whole_dir; | |
455 | static const char *solo_file = NULL; | |
456 | ||
fc557362 | 457 | enum nonregtype { |
72e5645e | 458 | @@ -534,7 +535,7 @@ int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st, int slot |
f9df736a WD |
459 | if (always_checksum > 0 && S_ISREG(st->st_mode)) { |
460 | char sum[MAX_DIGEST_LEN]; | |
461 | if (checksum_files && slot >= 0) | |
462 | - get_cached_checksum(slot, fn, file, st, sum); | |
463 | + get_cached_checksum(slot, fn, file, -1, st, sum); | |
464 | else | |
465 | file_checksum(fn, st->st_size, sum); | |
466 | return memcmp(sum, F_SUM(file), checksum_len) == 0; | |
72e5645e | 467 | @@ -1185,7 +1186,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, |
f9df736a WD |
468 | fuzzy_dirlist = get_dirlist(fnamecmpbuf, -1, 1); |
469 | } | |
470 | if (checksum_files) { | |
471 | - reset_checksum_cache(); | |
472 | + reset_checksum_cache(started_whole_dir); | |
473 | + started_whole_dir = upcoming_whole_dir; | |
474 | } | |
475 | need_new_dirscan = 0; | |
476 | } | |
72e5645e | 477 | @@ -1343,6 +1345,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, |
cbdf862c | 478 | else |
65ecbe35 | 479 | change_local_filter_dir(fname, strlen(fname), F_DEPTH(file)); |
f9df736a | 480 | } |
65ecbe35 | 481 | + upcoming_whole_dir = file->flags & FLAG_CONTENT_DIR && f_out != -1 ? 1 : 0; |
f9df736a WD |
482 | goto cleanup; |
483 | } | |
484 | ||
72e5645e | 485 | @@ -1616,6 +1619,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, |
f9df736a WD |
486 | handle_partial_dir(partialptr, PDIR_DELETE); |
487 | } | |
488 | set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT); | |
489 | + if (checksum_files & CSF_UPDATE) | |
490 | + set_cached_checksum(cur_flist, file); | |
491 | if (itemizing) | |
492 | itemize(fnamecmp, file, ndx, statret, &sx, 0, 0, NULL); | |
493 | #ifdef SUPPORT_HARD_LINKS | |
72e5645e | 494 | @@ -2120,6 +2125,7 @@ void generate_files(int f_out, const char *local_name) |
65ecbe35 WD |
495 | } else |
496 | change_local_filter_dir(fbuf, strlen(fbuf), F_DEPTH(fp)); | |
f9df736a WD |
497 | } |
498 | + upcoming_whole_dir = fp->flags & FLAG_CONTENT_DIR ? 1 : 0; | |
499 | } | |
500 | for (i = cur_flist->low; i <= cur_flist->high; i++) { | |
501 | struct file_struct *file = cur_flist->sorted[i]; | |
72e5645e | 502 | @@ -2214,6 +2220,9 @@ void generate_files(int f_out, const char *local_name) |
f9df736a WD |
503 | wait_for_receiver(); |
504 | } | |
505 | ||
506 | + if (checksum_files) | |
507 | + reset_checksum_cache(started_whole_dir); | |
508 | + | |
fc557362 WD |
509 | info_levels[INFO_FLIST] = save_info_flist; |
510 | info_levels[INFO_PROGRESS] = save_info_progress; | |
511 | ||
f9df736a WD |
512 | diff --git a/io.c b/io.c |
513 | --- a/io.c | |
514 | +++ b/io.c | |
72e5645e | 515 | @@ -52,6 +52,7 @@ extern int list_only; |
fc557362 | 516 | extern int read_batch; |
f9df736a WD |
517 | extern int protect_args; |
518 | extern int checksum_seed; | |
519 | +extern int checksum_files; | |
520 | extern int protocol_version; | |
521 | extern int remove_source_files; | |
522 | extern int preserve_hard_links; | |
72e5645e | 523 | @@ -875,6 +876,9 @@ static void got_flist_entry_status(enum festatus status, int ndx) |
f9df736a WD |
524 | flist_ndx_push(&hlink_list, ndx); |
525 | flist->in_progress++; | |
526 | } | |
527 | + } else if (checksum_files & CSF_UPDATE) { | |
528 | + struct file_struct *file = flist->files[ndx - flist->ndx_start]; | |
529 | + set_cached_checksum(flist, file); | |
530 | } | |
531 | break; | |
532 | case FES_REDO: | |
cc3e685d WD |
533 | diff --git a/loadparm.c b/loadparm.c |
534 | --- a/loadparm.c | |
535 | +++ b/loadparm.c | |
72e5645e | 536 | @@ -312,6 +312,10 @@ static struct enum_list enum_csum_modes[] = { |
f9df736a WD |
537 | { CSF_IGNORE_FILES, "none" }, |
538 | { CSF_LAX_MODE, "lax" }, | |
539 | { CSF_STRICT_MODE, "strict" }, | |
540 | + { CSF_LAX_MODE|CSF_UPDATE, "+lax" }, | |
541 | + { CSF_STRICT_MODE|CSF_UPDATE, "+strict" }, | |
542 | + { CSF_LAX_MODE|CSF_UPDATE|CSF_AFFECT_DRYRUN, "++lax" }, | |
543 | + { CSF_STRICT_MODE|CSF_UPDATE|CSF_AFFECT_DRYRUN, "++strict" }, | |
544 | { -1, NULL } | |
545 | }; | |
546 | ||
cc3e685d WD |
547 | diff --git a/options.c b/options.c |
548 | --- a/options.c | |
549 | +++ b/options.c | |
72e5645e | 550 | @@ -1637,7 +1637,15 @@ int parse_arguments(int *argc_p, const char ***argv_p) |
f9df736a WD |
551 | |
552 | case OPT_SUMFILES: | |
553 | arg = poptGetOptArg(pc); | |
554 | - checksum_files = 0; | |
555 | + if (*arg == '+') { | |
556 | + arg++; | |
557 | + checksum_files = CSF_UPDATE; | |
558 | + if (*arg == '+') { | |
559 | + arg++; | |
560 | + checksum_files |= CSF_AFFECT_DRYRUN; | |
561 | + } | |
562 | + } else | |
563 | + checksum_files = 0; | |
564 | if (strcmp(arg, "lax") == 0) | |
565 | checksum_files |= CSF_LAX_MODE; | |
566 | else if (strcmp(arg, "strict") == 0) | |
567 | diff --git a/receiver.c b/receiver.c | |
568 | --- a/receiver.c | |
569 | +++ b/receiver.c | |
fc557362 | 570 | @@ -47,6 +47,7 @@ extern int sparse_files; |
f9df736a | 571 | extern int keep_partial; |
fc557362 | 572 | extern int checksum_len; |
f9df736a WD |
573 | extern int checksum_seed; |
574 | +extern int checksum_files; | |
575 | extern int inplace; | |
576 | extern int delay_updates; | |
577 | extern mode_t orig_umask; | |
72e5645e | 578 | @@ -376,7 +377,7 @@ static void handle_delayed_updates(char *local_name) |
f9df736a WD |
579 | "rename failed for %s (from %s)", |
580 | full_fname(fname), partialptr); | |
581 | } else { | |
582 | - if (remove_source_files | |
583 | + if (remove_source_files || checksum_files & CSF_UPDATE | |
584 | || (preserve_hard_links && F_IS_HLINKED(file))) | |
585 | send_msg_int(MSG_SUCCESS, ndx); | |
586 | handle_partial_dir(partialptr, PDIR_DELETE); | |
72e5645e | 587 | @@ -829,7 +830,7 @@ int recv_files(int f_in, int f_out, char *local_name) |
ae306a29 WD |
588 | case 2: |
589 | break; | |
f9df736a WD |
590 | case 1: |
591 | - if (remove_source_files || inc_recurse | |
592 | + if (remove_source_files || inc_recurse || checksum_files & CSF_UPDATE | |
593 | || (preserve_hard_links && F_IS_HLINKED(file))) | |
594 | send_msg_int(MSG_SUCCESS, ndx); | |
595 | break; | |
cc3e685d WD |
596 | diff --git a/rsync.h b/rsync.h |
597 | --- a/rsync.h | |
598 | +++ b/rsync.h | |
72e5645e | 599 | @@ -917,6 +917,8 @@ typedef struct { |
7200c744 | 600 | |
f9df736a WD |
601 | #define CSF_ENABLE (1<<1) |
602 | #define CSF_LAX (1<<2) | |
603 | +#define CSF_UPDATE (1<<3) | |
604 | +#define CSF_AFFECT_DRYRUN (1<<4) | |
605 | ||
606 | #define CSF_IGNORE_FILES 0 | |
607 | #define CSF_LAX_MODE (CSF_ENABLE|CSF_LAX) | |
cc3e685d WD |
608 | diff --git a/rsync.yo b/rsync.yo |
609 | --- a/rsync.yo | |
610 | +++ b/rsync.yo | |
7170ca8d | 611 | @@ -599,9 +599,13 @@ computed just as it would be if bf(--sumfiles) was not specified. |
f9df736a WD |
612 | |
613 | The MODE value is either "lax", for relaxed checking (which compares size | |
614 | and mtime), "strict" (which also compares ctime and inode), or "none" to | |
615 | -ignore any .rsyncsums files ("none" is the default). Rsync does not create | |
616 | -or update these files, but there is a perl script in the support directory | |
617 | -named "rsyncsums" that can be used for that. | |
618 | +ignore any .rsyncsums files ("none" is the default). | |
619 | +If you want rsync to create and/or update these files, specify a prefixed | |
620 | +plus ("+lax" or "+strict"). | |
621 | +Adding a second prefixed '+' causes the checksum-file updates to happen | |
622 | +even when the transfer is in bf(--dry-run) mode ("++lax" or "++strict"). | |
623 | +There is also a perl script in the support directory named "rsyncsums" | |
624 | +that can be used to update the .rsyncsums files. | |
625 | ||
626 | This option has no effect unless bf(--checksum, -c) was also specified. It | |
627 | also only affects the current side of the transfer, so if you want the | |
cc3e685d WD |
628 | diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo |
629 | --- a/rsyncd.conf.yo | |
630 | +++ b/rsyncd.conf.yo | |
72e5645e | 631 | @@ -315,13 +315,15 @@ The default is tt(/var/run/rsyncd.lock). |
e66d6d51 | 632 | dit(bf(checksum files)) This parameter tells rsync to make use of any cached |
f9df736a WD |
633 | checksum information it finds in per-directory .rsyncsums files when the |
634 | current transfer is using the bf(--checksum) option. The value can be set | |
635 | -to either "lax", "strict", or "none" -- see the client's bf(--sumfiles) | |
636 | -option for what these choices do. | |
637 | +to either "lax", "strict", "+lax", "+strict", "++lax", "++strict", or | |
638 | +"none". See the client's bf(--sumfiles) option for what these choices do. | |
639 | ||
640 | Note also that the client's command-line option, bf(--sumfiles), has no | |
641 | effect on a daemon. A daemon will only access checksum files if this | |
642 | -config option tells it to. See also the bf(exclude) directive for a way | |
643 | -to hide the .rsyncsums files from the user. | |
644 | +config option tells it to. You can configure updating of the .rsyncsums | |
645 | +files even if the module itself is configured to be read-only. See also | |
646 | +the bf(exclude) directive for a way to hide the .rsyncsums files from the | |
647 | +user. | |
648 | ||
e66d6d51 | 649 | dit(bf(read only)) This parameter determines whether clients |
ae10e51e | 650 | will be able to upload files or not. If "read only" is true then any |