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 &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>