Annotation of embedaddon/rsync/patches/checksum-updating.diff, revision 1.1
1.1 ! misho 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.
! 8:
! 9: To use this patch, run these commands for a successful build:
! 10:
! 11: patch -p1 <patches/checksum-reading.diff
! 12: patch -p1 <patches/checksum-updating.diff
! 13: ./configure (optional if already run)
! 14: make
! 15:
! 16: TODO:
! 17:
! 18: - Fix the code that removes .rsyncsums files when a dir becomes empty.
! 19:
! 20: based-on: patch/master/checksum-reading
! 21: diff --git a/flist.c b/flist.c
! 22: --- a/flist.c
! 23: +++ b/flist.c
! 24: @@ -27,6 +27,7 @@
! 25: #include "inums.h"
! 26: #include "io.h"
! 27:
! 28: +extern int dry_run;
! 29: extern int am_root;
! 30: extern int am_server;
! 31: extern int am_daemon;
! 32: @@ -110,6 +111,9 @@ extern iconv_t ic_send, ic_recv;
! 33:
! 34: #define PTR_SIZE (sizeof (struct file_struct *))
! 35:
! 36: +#define FLAG_SUM_MISSING (1<<1) /* F_SUM() data is undefined */
! 37: +#define FLAG_SUM_KEEP (1<<2) /* keep entry when rewriting */
! 38: +
! 39: int io_error;
! 40: int flist_csum_len;
! 41: dev_t filesystem_dev; /* used to implement -x */
! 42: @@ -152,8 +156,13 @@ static char empty_sum[MAX_DIGEST_LEN];
! 43: static int flist_count_offset; /* for --delete --progress */
! 44: static int show_filelist_progress;
! 45:
! 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;
! 54:
! 55: static struct file_list *flist_new(int flags, const char *msg);
! 56: @@ -346,7 +355,79 @@ static void flist_done_allocating(struct file_list *flist)
! 57: flist->pool_boundary = ptr;
! 58: }
! 59:
! 60: -void reset_checksum_cache()
! 61: +static void checksum_filename(int slot, const char *dirname, char *fbuf)
! 62: +{
! 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: +}
! 76: +
! 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;
! 86: +
! 87: + flist_sort_and_clean(flist, 0);
! 88: +
! 89: + if (dry_run && !(checksum_files & CSF_AFFECT_DRYRUN))
! 90: + return;
! 91: +
! 92: + checksum_filename(slot, dirname, fbuf);
! 93: +
! 94: + if (flist->high - flist->low < 0 && no_skipped) {
! 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: +
! 105: + for (i = flist->low; i <= flist->high; i++) {
! 106: + struct file_struct *file = flist->sorted[i];
! 107: + const char *cp = F_SUM(file);
! 108: + const char *end = cp + flist_csum_len;
! 109: + const char *alt_sum = file->basename + strlen(file->basename) + 1;
! 110: + if (whole_dir && !(file->flags & FLAG_SUM_KEEP))
! 111: + continue;
! 112: + if (checksum_type == 5)
! 113: + fprintf(out_fp, "%s ", alt_sum);
! 114: + if (file->flags & FLAG_SUM_MISSING) {
! 115: + do {
! 116: + fputs("==", out_fp);
! 117: + } while (++cp != end);
! 118: + } else {
! 119: + do {
! 120: + fprintf(out_fp, "%02x", (int)CVAL(cp, 0));
! 121: + } while (++cp != end);
! 122: + }
! 123: + if (checksum_type != 5)
! 124: + fprintf(out_fp, " %s", alt_sum);
! 125: + fprintf(out_fp, " %10.0f %10.0f %10lu %10lu %s\n",
! 126: + (double)F_LENGTH(file), (double)file->modtime,
! 127: + (long)F_CTIME(file), (long)F_INODE(file), file->basename);
! 128: + }
! 129: +
! 130: + fclose(out_fp);
! 131: +}
! 132: +
! 133: +void reset_checksum_cache(int whole_dir)
! 134: {
! 135: int slot, slots = am_sender ? 1 : basis_dir_cnt + 1;
! 136:
! 137: @@ -357,6 +438,9 @@ void reset_checksum_cache()
! 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));
! 147: @@ -367,6 +451,10 @@ void reset_checksum_cache()
! 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:
! 158: @@ -374,7 +462,7 @@ void reset_checksum_cache()
! 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;
! 167: @@ -391,7 +479,7 @@ static int add_checksum(struct file_list *flist, const char *dirname,
! 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 + flist_csum_len*2 + 1;
! 173: bp = pool_alloc(flist->file_pool, alloc_len, "add_checksum");
! 174:
! 175: memset(bp, 0, extra_len + FILE_STRUCT_LEN);
! 176: @@ -400,7 +488,14 @@ static int add_checksum(struct file_list *flist, const char *dirname,
! 177: bp += FILE_STRUCT_LEN;
! 178:
! 179: memcpy(bp, basename, basename_len);
! 180: + if (alt_sum)
! 181: + strlcpy(bp+basename_len, alt_sum, flist_csum_len*2 + 1);
! 182: + else {
! 183: + memset(bp+basename_len, '=', flist_csum_len*2);
! 184: + bp[basename_len+flist_csum_len*2] = '\0';
! 185: + }
! 186:
! 187: + file->flags = flags;
! 188: file->mode = S_IFREG;
! 189: file->modtime = mtime;
! 190: file->len32 = (uint32)file_length;
! 191: @@ -429,10 +524,11 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
! 192: char line[MAXPATHLEN+1024], fbuf[MAXPATHLEN], sum[MAX_DIGEST_LEN];
! 193: FILE *fp;
! 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;
! 202:
! 203: if (dlen >= (int)(sizeof fbuf - 1 - RSYNCSUMS_LEN))
! 204: @@ -453,7 +549,7 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
! 205: while (fgets(line, sizeof line, fp)) {
! 206: cp = line;
! 207: if (checksum_type == 5) {
! 208: - char *alt_sum = cp;
! 209: + alt_sum = cp;
! 210: if (*cp == '=')
! 211: while (*++cp == '=') {}
! 212: else
! 213: @@ -464,7 +560,14 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
! 214: }
! 215:
! 216: if (*cp == '=') {
! 217: - continue;
! 218: + for (i = 0; i < flist_csum_len*2; i++, cp++) {
! 219: + if (*cp != '=') {
! 220: + cp = "";
! 221: + break;
! 222: + }
! 223: + }
! 224: + memset(sum, 0, flist_csum_len);
! 225: + flags = FLAG_SUM_MISSING;
! 226: } else {
! 227: for (i = 0; i < flist_csum_len*2; i++, cp++) {
! 228: int x;
! 229: @@ -482,13 +585,14 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
! 230: else
! 231: sum[i/2] = x << 4;
! 232: }
! 233: + flags = 0;
! 234: }
! 235: if (*cp != ' ')
! 236: break;
! 237: while (*++cp == ' ') {}
! 238:
! 239: if (checksum_type != 5) {
! 240: - char *alt_sum = cp;
! 241: + alt_sum = cp;
! 242: if (*cp == '=')
! 243: while (*++cp == '=') {}
! 244: else
! 245: @@ -538,24 +642,112 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
! 246: continue;
! 247:
! 248: strlcpy(fbuf+dlen, cp, sizeof fbuf - dlen);
! 249: + if (is_excluded(fbuf, 0, ALL_FILTERS)) {
! 250: + flags |= FLAG_SUM_KEEP;
! 251: + csum_cache[slot].checksum_matches++;
! 252: + }
! 253:
! 254: add_checksum(flist, dirname, cp, len, file_length,
! 255: mtime, ctime, inode,
! 256: - sum);
! 257: + sum, alt_sum, flags);
! 258: }
! 259: fclose(fp);
! 260:
! 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 + flist_csum_len;
! 284: +
! 285: + if (!(out_fp = fopen(fbuf, "a")))
! 286: + return;
! 287: +
! 288: + if (checksum_type == 5) {
! 289: + for (j = 0; j < flist_csum_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 (checksum_type != 5) {
! 297: + fputc(' ', out_fp);
! 298: + for (j = 0; j < flist_csum_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:
! 360: @@ -567,12 +759,31 @@ void get_cached_checksum(int slot, const char *fname, struct file_struct *file,
! 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, 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, 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:
! 392: /* Call this with EITHER (1) "file, NULL, 0" to chdir() to the file's
! 393: @@ -1553,6 +1764,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
! 394: if (is_excluded(thisname, S_ISDIR(st.st_mode) != 0, filter_level)) {
! 395: if (ignore_perishable)
! 396: non_perishable_cnt++;
! 397: + if (S_ISREG(st.st_mode))
! 398: + REGULAR_SKIPPED(flist)++;
! 399: return NULL;
! 400: }
! 401:
! 402: @@ -1599,13 +1812,13 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
! 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: }
! 416: }
! 417: basename_len = strlen(basename) + 1; /* count the '\0' */
! 418: @@ -1717,7 +1930,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
! 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, tmp_sum);
! 426: if (sender_keeps_checksum)
! 427: @@ -2109,6 +2322,9 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len,
! 428:
! 429: closedir(d);
! 430:
! 431: + if (checksum_files & CSF_UPDATE && am_sender && f >= 0)
! 432: + reset_checksum_cache(1);
! 433: +
! 434: if (f >= 0 && recurse && !divert_dirs) {
! 435: int i, end = flist->used - 1;
! 436: /* send_if_directory() bumps flist->used, so use "end". */
! 437: @@ -2772,6 +2988,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: }
! 440:
! 441: + if (checksum_files & CSF_UPDATE && flist_eof)
! 442: + reset_checksum_cache(0); /* writes any last updates */
! 443: +
! 444: return flist;
! 445: }
! 446:
! 447: diff --git a/generator.c b/generator.c
! 448: --- a/generator.c
! 449: +++ b/generator.c
! 450: @@ -111,6 +111,7 @@ static int dir_tweaking;
! 451: static int symlink_timeset_failed_flags;
! 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:
! 457: enum nonregtype {
! 458: @@ -612,7 +613,7 @@ int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st, int slot
! 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, sum);
! 466: return memcmp(sum, F_SUM(file), flist_csum_len) == 0;
! 467: @@ -1364,7 +1365,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
! 468: }
! 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: }
! 477: @@ -1535,6 +1537,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
! 478: else
! 479: change_local_filter_dir(fname, strlen(fname), F_DEPTH(file));
! 480: }
! 481: + upcoming_whole_dir = file->flags & FLAG_CONTENT_DIR && f_out != -1 ? 1 : 0;
! 482: prior_dir_file = file;
! 483: goto cleanup;
! 484: }
! 485: @@ -1810,6 +1813,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
! 486: handle_partial_dir(partialptr, PDIR_DELETE);
! 487: }
! 488: set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT | maybe_ATTRS_ACCURATE_TIME);
! 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
! 494: @@ -2306,6 +2311,7 @@ void generate_files(int f_out, const char *local_name)
! 495: } else
! 496: change_local_filter_dir(fbuf, strlen(fbuf), F_DEPTH(fp));
! 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];
! 502: @@ -2400,6 +2406,9 @@ void generate_files(int f_out, const char *local_name)
! 503: wait_for_receiver();
! 504: }
! 505:
! 506: + if (checksum_files)
! 507: + reset_checksum_cache(started_whole_dir);
! 508: +
! 509: info_levels[INFO_FLIST] = save_info_flist;
! 510: info_levels[INFO_PROGRESS] = save_info_progress;
! 511:
! 512: diff --git a/io.c b/io.c
! 513: --- a/io.c
! 514: +++ b/io.c
! 515: @@ -54,6 +54,7 @@ extern int read_batch;
! 516: extern int compat_flags;
! 517: extern int protect_args;
! 518: extern int checksum_seed;
! 519: +extern int checksum_files;
! 520: extern int daemon_connection;
! 521: extern int protocol_version;
! 522: extern int remove_source_files;
! 523: @@ -1066,6 +1067,9 @@ static void got_flist_entry_status(enum festatus status, int ndx)
! 524: if (inc_recurse)
! 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: #endif
! 532: break;
! 533: diff --git a/loadparm.c b/loadparm.c
! 534: --- a/loadparm.c
! 535: +++ b/loadparm.c
! 536: @@ -166,6 +166,10 @@ static struct enum_list enum_checksum_files[] = {
! 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:
! 547: diff --git a/options.c b/options.c
! 548: --- a/options.c
! 549: +++ b/options.c
! 550: @@ -1726,7 +1726,15 @@ int parse_arguments(int *argc_p, const char ***argv_p)
! 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
! 570: @@ -50,6 +50,7 @@ extern int sparse_files;
! 571: extern int preallocate_files;
! 572: extern int keep_partial;
! 573: extern int checksum_seed;
! 574: +extern int checksum_files;
! 575: extern int whole_file;
! 576: extern int inplace;
! 577: extern int inplace_partial;
! 578: @@ -433,7 +434,7 @@ static void handle_delayed_updates(char *local_name)
! 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);
! 587: @@ -906,7 +907,7 @@ int recv_files(int f_in, int f_out, char *local_name)
! 588: case 2:
! 589: break;
! 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;
! 596: diff --git a/rsync.1.md b/rsync.1.md
! 597: --- a/rsync.1.md
! 598: +++ b/rsync.1.md
! 599: @@ -722,9 +722,13 @@ your home directory (remove the '=' for that).
! 600:
! 601: The MODE value is either "lax", for relaxed checking (which compares size
! 602: and mtime), "strict" (which also compares ctime and inode), or "none" to
! 603: - ignore any .rsyncsums files ("none" is the default). Rsync does not create
! 604: - or update these files, but there is a perl script in the support directory
! 605: - named "rsyncsums" that can be used for that.
! 606: + ignore any .rsyncsums files ("none" is the default).
! 607: + If you want rsync to create and/or update these files, specify a prefixed
! 608: + plus ("+lax" or "+strict"). Adding a second prefixed '+' causes the
! 609: + checksum-file updates to happen even when the transfer is in `--dry-run`
! 610: + mode ("++lax" or "++strict"). There is also a perl script in the support
! 611: + directory named "rsyncsums" that can be used to update the .rsyncsums
! 612: + files.
! 613:
! 614: This option has no effect unless `--checksum`, `-c` was also specified. It
! 615: also only affects the current side of the transfer, so if you want the
! 616: diff --git a/rsync.h b/rsync.h
! 617: --- a/rsync.h
! 618: +++ b/rsync.h
! 619: @@ -1100,6 +1100,8 @@ typedef struct {
! 620:
! 621: #define CSF_ENABLE (1<<1)
! 622: #define CSF_LAX (1<<2)
! 623: +#define CSF_UPDATE (1<<3)
! 624: +#define CSF_AFFECT_DRYRUN (1<<4)
! 625:
! 626: #define CSF_IGNORE_FILES 0
! 627: #define CSF_LAX_MODE (CSF_ENABLE|CSF_LAX)
! 628: diff --git a/rsyncd.conf.5.md b/rsyncd.conf.5.md
! 629: --- a/rsyncd.conf.5.md
! 630: +++ b/rsyncd.conf.5.md
! 631: @@ -424,13 +424,15 @@ the values of parameters. See the GLOBAL PARAMETERS section for more details.
! 632: This parameter tells rsync to make use of any cached checksum information
! 633: it finds in per-directory .rsyncsums files when the current transfer is
! 634: using the `--checksum` option. The value can be set to either "lax",
! 635: - "strict", or "none". See the client's `--sumfiles` option for what these
! 636: - choices do.
! 637: + "strict", "+lax", "+strict", "++lax", "++strict", or +"none". See the
! 638: + client's `--sumfiles` option for what these choices do.
! 639:
! 640: Note also that the client's command-line option, `--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 `exclude` directive for a way to
! 643: - 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 `exclude` directive for a way to hide the .rsyncsums files from the
! 647: + user.
! 648:
! 649: 0. `read only`
! 650:
! 651: diff -Nurp a/rsync.1 b/rsync.1
! 652: --- a/rsync.1
! 653: +++ b/rsync.1
! 654: @@ -788,9 +788,13 @@ would be if \fB\-\-sumfiles\fP was not s
! 655: .IP
! 656: The MODE value is either "lax", for relaxed checking (which compares size
! 657: and mtime), "strict" (which also compares ctime and inode), or "none" to
! 658: -ignore any .rsyncsums files ("none" is the default). Rsync does not create
! 659: -or update these files, but there is a perl script in the support directory
! 660: -named "rsyncsums" that can be used for that.
! 661: +ignore any .rsyncsums files ("none" is the default).
! 662: +If you want rsync to create and/or update these files, specify a prefixed
! 663: +plus ("+lax" or "+strict"). Adding a second prefixed '+' causes the
! 664: +checksum-file updates to happen even when the transfer is in \fB\-\-dry-run\fP
! 665: +mode ("++lax" or "++strict"). There is also a perl script in the support
! 666: +directory named "rsyncsums" that can be used to update the .rsyncsums
! 667: +files.
! 668: .IP
! 669: This option has no effect unless \fB\-\-checksum\fP, \fB\-c\fP was also specified. It
! 670: also only affects the current side of the transfer, so if you want the
! 671: diff -Nurp a/rsync.1.html b/rsync.1.html
! 672: --- a/rsync.1.html
! 673: +++ b/rsync.1.html
! 674: @@ -702,9 +702,13 @@ checksum data is missing or outdated, th
! 675: would be if <code>--sumfiles</code> was not specified.</p>
! 676: <p>The MODE value is either "lax", for relaxed checking (which compares size
! 677: and mtime), "strict" (which also compares ctime and inode), or "none" to
! 678: -ignore any .rsyncsums files ("none" is the default). Rsync does not create
! 679: -or update these files, but there is a perl script in the support directory
! 680: -named "rsyncsums" that can be used for that.</p>
! 681: +ignore any .rsyncsums files ("none" is the default).
! 682: +If you want rsync to create and/or update these files, specify a prefixed
! 683: +plus ("+lax" or "+strict"). Adding a second prefixed '+' causes the
! 684: +checksum-file updates to happen even when the transfer is in <code>--dry-run</code>
! 685: +mode ("++lax" or "++strict"). There is also a perl script in the support
! 686: +directory named "rsyncsums" that can be used to update the .rsyncsums
! 687: +files.</p>
! 688: <p>This option has no effect unless <code>--checksum</code>, <code>-c</code> was also specified. It
! 689: also only affects the current side of the transfer, so if you want the
! 690: remote side to parse its own .rsyncsums files, specify the option via
! 691: diff -Nurp a/rsyncd.conf.5 b/rsyncd.conf.5
! 692: --- a/rsyncd.conf.5
! 693: +++ b/rsyncd.conf.5
! 694: @@ -398,13 +398,15 @@ file. The default is \fB/var/run/rsyncd
! 695: This parameter tells rsync to make use of any cached checksum information
! 696: it finds in per-directory .rsyncsums files when the current transfer is
! 697: using the \fB\-\-checksum\fP option. The value can be set to either "lax",
! 698: -"strict", or "none". See the client's \fB\-\-sumfiles\fP option for what these
! 699: -choices do.
! 700: +"strict", "+lax", "+strict", "++lax", "++strict", or +"none". See the
! 701: +client's \fB\-\-sumfiles\fP option for what these choices do.
! 702: .IP
! 703: Note also that the client's command-line option, \fB\-\-sumfiles\fP, has no
! 704: effect on a daemon. A daemon will only access checksum files if this
! 705: -config option tells it to. See also the \fBexclude\fP directive for a way to
! 706: -hide the .rsyncsums files from the user.
! 707: +config option tells it to. You can configure updating of the .rsyncsums
! 708: +files even if the module itself is configured to be read-only. See also
! 709: +the \fBexclude\fP directive for a way to hide the .rsyncsums files from the
! 710: +user.
! 711: .IP "\fBread\ only\fP"
! 712: This parameter determines whether clients will be able to upload files or
! 713: not. If "read only" is true then any attempted uploads will fail. If
! 714: diff -Nurp a/rsyncd.conf.5.html b/rsyncd.conf.5.html
! 715: --- a/rsyncd.conf.5.html
! 716: +++ b/rsyncd.conf.5.html
! 717: @@ -409,12 +409,14 @@ file. The default is <code>/var/run/rsy
! 718: <p>This parameter tells rsync to make use of any cached checksum information
! 719: it finds in per-directory .rsyncsums files when the current transfer is
! 720: using the <code>--checksum</code> option. The value can be set to either "lax",
! 721: -"strict", or "none". See the client's <code>--sumfiles</code> option for what these
! 722: -choices do.</p>
! 723: +"strict", "+lax", "+strict", "++lax", "++strict", or +"none". See the
! 724: +client's <code>--sumfiles</code> option for what these choices do.</p>
! 725: <p>Note also that the client's command-line option, <code>--sumfiles</code>, has no
! 726: effect on a daemon. A daemon will only access checksum files if this
! 727: -config option tells it to. See also the <code>exclude</code> directive for a way to
! 728: -hide the .rsyncsums files from the user.</p>
! 729: +config option tells it to. You can configure updating of the .rsyncsums
! 730: +files even if the module itself is configured to be read-only. See also
! 731: +the <code>exclude</code> directive for a way to hide the .rsyncsums files from the
! 732: +user.</p>
! 733: </dd>
! 734:
! 735: <dt><code>read only</code></dt><dd>
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>