Annotation of embedaddon/rsync/patches/checksum-updating.diff, revision 1.1.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 &quot;lax&quot;, for relaxed checking (which compares size
                    677:  and mtime), &quot;strict&quot; (which also compares ctime and inode), or &quot;none&quot; to
                    678: -ignore any .rsyncsums files (&quot;none&quot; is the default).  Rsync does not create
                    679: -or update these files, but there is a perl script in the support directory
                    680: -named &quot;rsyncsums&quot; that can be used for that.</p>
                    681: +ignore any .rsyncsums files (&quot;none&quot; is the default).
                    682: +If you want rsync to create and/or update these files, specify a prefixed
                    683: +plus (&quot;+lax&quot; or &quot;+strict&quot;).  Adding a second prefixed '+' causes the
                    684: +checksum-file updates to happen even when the transfer is in <code>--dry-run</code>
                    685: +mode (&quot;++lax&quot; or &quot;++strict&quot;).  There is also a perl script in the support
                    686: +directory named &quot;rsyncsums&quot; 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 &quot;lax&quot;,
                    721: -&quot;strict&quot;, or &quot;none&quot;.  See the client's <code>--sumfiles</code> option for what these
                    722: -choices do.</p>
                    723: +&quot;strict&quot;, &quot;+lax&quot;, &quot;+strict&quot;, &quot;++lax&quot;, &quot;++strict&quot;, or +&quot;none&quot;.  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>