Diff for /embedaddon/rsync/receiver.c between versions 1.1 and 1.1.1.3

version 1.1, 2012/02/17 15:09:30 version 1.1.1.3, 2016/11/01 09:54:32
Line 3 Line 3
  *   *
  * Copyright (C) 1996-2000 Andrew Tridgell   * Copyright (C) 1996-2000 Andrew Tridgell
  * Copyright (C) 1996 Paul Mackerras   * Copyright (C) 1996 Paul Mackerras
 * Copyright (C) 2003-2009 Wayne Davison * Copyright (C) 2003-2015 Wayne Davison
  *   *
  * This program is free software; you can redistribute it and/or modify   * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by   * it under the terms of the GNU General Public License as published by
Line 20 Line 20
  */   */
   
 #include "rsync.h"  #include "rsync.h"
   #include "inums.h"
   
 extern int verbose;  
 extern int dry_run;  extern int dry_run;
 extern int do_xfers;  extern int do_xfers;
 extern int am_root;  extern int am_root;
 extern int am_server;  extern int am_server;
 extern int do_progress;  
 extern int inc_recurse;  extern int inc_recurse;
 extern int log_before_transfer;  extern int log_before_transfer;
 extern int stdout_format_has_i;  extern int stdout_format_has_i;
 extern int logfile_format_has_i;  extern int logfile_format_has_i;
   extern int want_xattr_optim;
 extern int csum_length;  extern int csum_length;
 extern int read_batch;  extern int read_batch;
 extern int write_batch;  extern int write_batch;
Line 46  extern int cleanup_got_literal; Line 46  extern int cleanup_got_literal;
 extern int remove_source_files;  extern int remove_source_files;
 extern int append_mode;  extern int append_mode;
 extern int sparse_files;  extern int sparse_files;
   extern int preallocate_files;
 extern int keep_partial;  extern int keep_partial;
   extern int checksum_len;
 extern int checksum_seed;  extern int checksum_seed;
 extern int inplace;  extern int inplace;
   extern int allowed_lull;
 extern int delay_updates;  extern int delay_updates;
 extern mode_t orig_umask;  extern mode_t orig_umask;
 extern struct stats stats;  extern struct stats stats;
 extern char *tmpdir;  extern char *tmpdir;
 extern char *partial_dir;  extern char *partial_dir;
 extern char *basis_dir[MAX_BASIS_DIRS+1];  extern char *basis_dir[MAX_BASIS_DIRS+1];
   extern char sender_file_sum[MAX_DIGEST_LEN];
 extern struct file_list *cur_flist, *first_flist, *dir_flist;  extern struct file_list *cur_flist, *first_flist, *dir_flist;
extern struct filter_list_struct daemon_filter_list;extern filter_rule_list daemon_filter_list;
   
   BOOL want_progress_now;
   
 static struct bitbag *delayed_bits = NULL;  static struct bitbag *delayed_bits = NULL;
 static int phase = 0, redoing = 0;  static int phase = 0, redoing = 0;
 static flist_ndx_list batch_redo_list;  static flist_ndx_list batch_redo_list;
Line 66  static int updating_basis_or_equiv; Line 72  static int updating_basis_or_equiv;
   
 #define TMPNAME_SUFFIX ".XXXXXX"  #define TMPNAME_SUFFIX ".XXXXXX"
 #define TMPNAME_SUFFIX_LEN ((int)sizeof TMPNAME_SUFFIX - 1)  #define TMPNAME_SUFFIX_LEN ((int)sizeof TMPNAME_SUFFIX - 1)
   #define MAX_UNIQUE_NUMBER 999999
   #define MAX_UNIQUE_LOOP 100
   
 /* get_tmpname() - create a tmp filename for a given filename  /* get_tmpname() - create a tmp filename for a given filename
  *   *
Line 79  static int updating_basis_or_equiv; Line 87  static int updating_basis_or_equiv;
  * the basename basically becomes 8 characters longer.  In such a case, the   * the basename basically becomes 8 characters longer.  In such a case, the
  * original name is shortened sufficiently to make it all fit.   * original name is shortened sufficiently to make it all fit.
  *   *
    * If the make_unique arg is True, the XXXXXX string is replaced with a unique
    * string that doesn't exist at the time of the check.  This is intended to be
    * used for creating hard links, symlinks, devices, and special files, since
    * normal files should be handled by mkstemp() for safety.
    *
  * Of course, the only reason the file is based on the original name is to   * Of course, the only reason the file is based on the original name is to
  * make it easier to figure out what purpose a temp file is serving when a   * make it easier to figure out what purpose a temp file is serving when a
  * transfer is in progress. */   * transfer is in progress. */
int get_tmpname(char *fnametmp, const char *fname)int get_tmpname(char *fnametmp, const char *fname, BOOL make_unique)
 {  {
        int maxname, added, length = 0;        int maxname, length = 0;
         const char *f;          const char *f;
         char *suf;          char *suf;
   
Line 103  int get_tmpname(char *fnametmp, const char *fname) Line 116  int get_tmpname(char *fnametmp, const char *fname)
                 }                  }
         } else          } else
                 f = fname;                  f = fname;
         fnametmp[length++] = '.';  
   
           if (!tmpdir) { /* using a tmpdir avoids the leading dot on our temp names */
                   if (*f == '.') /* avoid an extra leading dot for OS X's sake */
                           f++;
                   fnametmp[length++] = '.';
           }
   
         /* The maxname value is bufsize, and includes space for the '\0'.          /* The maxname value is bufsize, and includes space for the '\0'.
          * NAME_MAX needs an extra -1 for the name's leading dot. */           * NAME_MAX needs an extra -1 for the name's leading dot. */
         maxname = MIN(MAXPATHLEN - length - TMPNAME_SUFFIX_LEN,          maxname = MIN(MAXPATHLEN - length - TMPNAME_SUFFIX_LEN,
                       NAME_MAX - 1 - TMPNAME_SUFFIX_LEN);                        NAME_MAX - 1 - TMPNAME_SUFFIX_LEN);
   
        if (maxname < 1) {        if (maxname < 0) {
                 rprintf(FERROR_XFER, "temporary filename too long: %s\n", fname);                  rprintf(FERROR_XFER, "temporary filename too long: %s\n", fname);
                 fnametmp[0] = '\0';                  fnametmp[0] = '\0';
                 return 0;                  return 0;
         }          }
   
        added = strlcpy(fnametmp + length, f, maxname);        if (maxname) {
        if (added >= maxname)                int added = strlcpy(fnametmp + length, f, maxname);
                added = maxname - 1;                if (added >= maxname)
        suf = fnametmp + length + added;                        added = maxname - 1;
                 suf = fnametmp + length + added;
   
        /* Trim any dangling high-bit chars if the first-trimmed char (if any) is                /* Trim any dangling high-bit chars if the first-trimmed char (if any) is
         * also a high-bit char, just in case we cut into a multi-byte sequence.                 * also a high-bit char, just in case we cut into a multi-byte sequence.
         * We are guaranteed to stop because of the leading '.' we added. */                 * We are guaranteed to stop because of the leading '.' we added. */
        if ((int)f[added] & 0x80) {                if ((int)f[added] & 0x80) {
                while ((int)suf[-1] & 0x80)                        while ((int)suf[-1] & 0x80)
                                 suf--;
                 }
                 /* trim one trailing dot before our suffix's dot */
                 if (suf[-1] == '.')
                         suf--;                          suf--;
        }        } else
                 suf = fnametmp + length - 1; /* overwrite the leading dot with suffix's dot */
   
        memcpy(suf, TMPNAME_SUFFIX, TMPNAME_SUFFIX_LEN+1);        if (make_unique) {
                 static unsigned counter_limit;
                 unsigned counter;
   
                   if (!counter_limit) {
                           counter_limit = (unsigned)getpid() + MAX_UNIQUE_LOOP;
                           if (counter_limit > MAX_UNIQUE_NUMBER || counter_limit < MAX_UNIQUE_LOOP)
                                   counter_limit = MAX_UNIQUE_LOOP;
                   }
                   counter = counter_limit - MAX_UNIQUE_LOOP;
   
                   /* This doesn't have to be very good because we don't need
                    * to worry about someone trying to guess the values:  all
                    * a conflict will do is cause a device, special file, hard
                    * link, or symlink to fail to be created.  Also: avoid
                    * using mktemp() due to gcc's annoying warning. */
                   while (1) {
                           snprintf(suf, TMPNAME_SUFFIX_LEN+1, ".%d", counter);
                           if (access(fnametmp, 0) < 0)
                                   break;
                           if (++counter >= counter_limit)
                                   return 0;
                   }
           } else
                   memcpy(suf, TMPNAME_SUFFIX, TMPNAME_SUFFIX_LEN+1);
   
         return 1;          return 1;
 }  }
   
Line 143  int open_tmpfile(char *fnametmp, const char *fname, st Line 191  int open_tmpfile(char *fnametmp, const char *fname, st
         int fd;          int fd;
         mode_t added_perms;          mode_t added_perms;
   
        if (!get_tmpname(fnametmp, fname))        if (!get_tmpname(fnametmp, fname, False))
                 return -1;                  return -1;
   
         if (am_root < 0) {          if (am_root < 0) {
Line 166  int open_tmpfile(char *fnametmp, const char *fname, st Line 214  int open_tmpfile(char *fnametmp, const char *fname, st
          * information should have been previously transferred, but that may           * information should have been previously transferred, but that may
          * not be the case with -R */           * not be the case with -R */
         if (fd == -1 && relative_paths && errno == ENOENT          if (fd == -1 && relative_paths && errno == ENOENT
            && create_directory_path(fnametmp) == 0) {         && make_path(fnametmp, MKP_SKIP_SLASH | MKP_DROP_NAME) == 0) {
                 /* Get back to name with XXXXXX in it. */                  /* Get back to name with XXXXXX in it. */
                get_tmpname(fnametmp, fname);                get_tmpname(fnametmp, fname, False);
                 fd = do_mkstemp(fnametmp, (file->mode|added_perms) & INITACCESSPERMS);                  fd = do_mkstemp(fnametmp, (file->mode|added_perms) & INITACCESSPERMS);
         }          }
 #endif  #endif
Line 186  static int receive_data(int f_in, char *fname_r, int f Line 234  static int receive_data(int f_in, char *fname_r, int f
                         const char *fname, int fd, OFF_T total_size)                          const char *fname, int fd, OFF_T total_size)
 {  {
         static char file_sum1[MAX_DIGEST_LEN];          static char file_sum1[MAX_DIGEST_LEN];
         static char file_sum2[MAX_DIGEST_LEN];  
         struct map_struct *mapbuf;          struct map_struct *mapbuf;
         struct sum_struct sum;          struct sum_struct sum;
        int32 len, sum_len;        int32 len;
         OFF_T offset = 0;          OFF_T offset = 0;
         OFF_T offset2;          OFF_T offset2;
         char *data;          char *data;
         int32 i;          int32 i;
         char *map = NULL;          char *map = NULL;
   #ifdef SUPPORT_PREALLOCATION
   #ifdef PREALLOCATE_NEEDS_TRUNCATE
           OFF_T preallocated_len = 0;
   #endif
   
           if (preallocate_files && fd != -1 && total_size > 0 && (!inplace || total_size > size_r)) {
                   /* Try to preallocate enough space for file's eventual length.  Can
                    * reduce fragmentation on filesystems like ext4, xfs, and NTFS. */
                   if (do_fallocate(fd, 0, total_size) == 0) {
   #ifdef PREALLOCATE_NEEDS_TRUNCATE
                           preallocated_len = total_size;
   #endif
                   } else
                           rsyserr(FWARNING, errno, "do_fallocate %s", full_fname(fname));
           }
   #endif
   
         read_sum_head(f_in, &sum);          read_sum_head(f_in, &sum);
   
         if (fd_r >= 0 && size_r > 0) {          if (fd_r >= 0 && size_r > 0) {
                 int32 read_size = MAX(sum.blength * 2, 16*1024);                  int32 read_size = MAX(sum.blength * 2, 16*1024);
                 mapbuf = map_file(fd_r, size_r, read_size, sum.blength);                  mapbuf = map_file(fd_r, size_r, read_size, sum.blength);
                if (verbose > 2) {                if (DEBUG_GTE(DELTASUM, 2)) {
                        rprintf(FINFO, "recv mapped %s of size %.0f\n",                        rprintf(FINFO, "recv mapped %s of size %s\n",
                                fname_r, (double)size_r);                                fname_r, big_num(size_r));
                 }                  }
         } else          } else
                 mapbuf = NULL;                  mapbuf = NULL;
Line 215  static int receive_data(int f_in, char *fname_r, int f Line 278  static int receive_data(int f_in, char *fname_r, int f
                 sum.flength = (OFF_T)sum.count * sum.blength;                  sum.flength = (OFF_T)sum.count * sum.blength;
                 if (sum.remainder)                  if (sum.remainder)
                         sum.flength -= sum.blength - sum.remainder;                          sum.flength -= sum.blength - sum.remainder;
                if (append_mode == 2) {                if (append_mode == 2 && mapbuf) {
                         for (j = CHUNK_SIZE; j < sum.flength; j += CHUNK_SIZE) {                          for (j = CHUNK_SIZE; j < sum.flength; j += CHUNK_SIZE) {
                                if (do_progress)                                if (INFO_GTE(PROGRESS, 1))
                                         show_progress(offset, total_size);                                          show_progress(offset, total_size);
                                 sum_update(map_ptr(mapbuf, offset, CHUNK_SIZE),                                  sum_update(map_ptr(mapbuf, offset, CHUNK_SIZE),
                                            CHUNK_SIZE);                                             CHUNK_SIZE);
Line 225  static int receive_data(int f_in, char *fname_r, int f Line 288  static int receive_data(int f_in, char *fname_r, int f
                         }                          }
                         if (offset < sum.flength) {                          if (offset < sum.flength) {
                                 int32 len = (int32)(sum.flength - offset);                                  int32 len = (int32)(sum.flength - offset);
                                if (do_progress)                                if (INFO_GTE(PROGRESS, 1))
                                         show_progress(offset, total_size);                                          show_progress(offset, total_size);
                                 sum_update(map_ptr(mapbuf, offset, len), len);                                  sum_update(map_ptr(mapbuf, offset, len), len);
                         }                          }
                 }                  }
                 offset = sum.flength;                  offset = sum.flength;
                 if (fd != -1 && (j = do_lseek(fd, offset, SEEK_SET)) != offset) {                  if (fd != -1 && (j = do_lseek(fd, offset, SEEK_SET)) != offset) {
                        rsyserr(FERROR_XFER, errno, "lseek of %s returned %.0f, not %.0f",                        rsyserr(FERROR_XFER, errno, "lseek of %s returned %s, not %s",
                                full_fname(fname), (double)j, (double)offset);                                full_fname(fname), big_num(j), big_num(offset));
                         exit_cleanup(RERR_FILEIO);                          exit_cleanup(RERR_FILEIO);
                 }                  }
         }          }
   
         while ((i = recv_token(f_in, &data)) != 0) {          while ((i = recv_token(f_in, &data)) != 0) {
                if (do_progress)                if (INFO_GTE(PROGRESS, 1))
                         show_progress(offset, total_size);                          show_progress(offset, total_size);
                   else if (want_progress_now) {
                           rprintf(FINFO, "%s\n", fname);
                           end_progress(offset);
                   }
                   want_progress_now = False;
   
                   if (allowed_lull)
                           maybe_send_keepalive(time(NULL), MSK_ALLOW_FLUSH | MSK_ACTIVE_RECEIVER);
   
                 if (i > 0) {                  if (i > 0) {
                        if (verbose > 3) {                        if (DEBUG_GTE(DELTASUM, 3)) {
                                rprintf(FINFO,"data recv %d at %.0f\n",                                rprintf(FINFO,"data recv %d at %s\n",
                                        i,(double)offset);                                        i, big_num(offset));
                         }                          }
   
                         stats.literal_data += i;                          stats.literal_data += i;
Line 267  static int receive_data(int f_in, char *fname_r, int f Line 338  static int receive_data(int f_in, char *fname_r, int f
   
                 stats.matched_data += len;                  stats.matched_data += len;
   
                if (verbose > 3) {                if (DEBUG_GTE(DELTASUM, 3)) {
                         rprintf(FINFO,                          rprintf(FINFO,
                                "chunk[%d] of size %ld at %.0f offset=%.0f%s\n",                                "chunk[%d] of size %ld at %s offset=%s%s\n",
                                i, (long)len, (double)offset2, (double)offset,                                i, (long)len, big_num(offset2), big_num(offset),
                                 updating_basis_or_equiv && offset == offset2 ? " (seek)" : "");                                  updating_basis_or_equiv && offset == offset2 ? " (seek)" : "");
                 }                  }
   
Line 289  static int receive_data(int f_in, char *fname_r, int f Line 360  static int receive_data(int f_in, char *fname_r, int f
                                 offset += len;                                  offset += len;
                                 if ((pos = do_lseek(fd, len, SEEK_CUR)) != offset) {                                  if ((pos = do_lseek(fd, len, SEEK_CUR)) != offset) {
                                         rsyserr(FERROR_XFER, errno,                                          rsyserr(FERROR_XFER, errno,
                                                "lseek of %s returned %.0f, not %.0f",                                                "lseek of %s returned %s, not %s",
                                                 full_fname(fname),                                                  full_fname(fname),
                                                (double)pos, (double)offset);                                                big_num(pos), big_num(offset));
                                         exit_cleanup(RERR_FILEIO);                                          exit_cleanup(RERR_FILEIO);
                                 }                                  }
                                 continue;                                  continue;
Line 306  static int receive_data(int f_in, char *fname_r, int f Line 377  static int receive_data(int f_in, char *fname_r, int f
                 goto report_write_error;                  goto report_write_error;
   
 #ifdef HAVE_FTRUNCATE  #ifdef HAVE_FTRUNCATE
        if (inplace && fd != -1 && do_ftruncate(fd, offset) < 0) {        /* inplace: New data could be shorter than old data.
          * preallocate_files: total_size could have been an overestimate.
          *     Cut off any extra preallocated zeros from dest file. */
         if ((inplace
 #ifdef PREALLOCATE_NEEDS_TRUNCATE
           || preallocated_len > offset
 #endif
           ) && fd != -1 && do_ftruncate(fd, offset) < 0) {
                 rsyserr(FERROR_XFER, errno, "ftruncate failed on %s",                  rsyserr(FERROR_XFER, errno, "ftruncate failed on %s",
                         full_fname(fname));                          full_fname(fname));
         }          }
 #endif  #endif
   
        if (do_progress)        if (INFO_GTE(PROGRESS, 1))
                 end_progress(total_size);                  end_progress(total_size);
   
         if (fd != -1 && offset > 0 && sparse_end(fd, offset) != 0) {          if (fd != -1 && offset > 0 && sparse_end(fd, offset) != 0) {
Line 322  static int receive_data(int f_in, char *fname_r, int f Line 400  static int receive_data(int f_in, char *fname_r, int f
                 exit_cleanup(RERR_FILEIO);                  exit_cleanup(RERR_FILEIO);
         }          }
   
        sum_len = sum_end(file_sum1);        if (sum_end(file_sum1) != checksum_len)
                 overflow_exit("checksum_len"); /* Impossible... */
   
         if (mapbuf)          if (mapbuf)
                 unmap_file(mapbuf);                  unmap_file(mapbuf);
   
        read_buf(f_in, file_sum2, sum_len);        read_buf(f_in, sender_file_sum, checksum_len);
        if (verbose > 2)        if (DEBUG_GTE(DELTASUM, 2))
                 rprintf(FINFO,"got file_sum\n");                  rprintf(FINFO,"got file_sum\n");
        if (fd != -1 && memcmp(file_sum1, file_sum2, sum_len) != 0)        if (fd != -1 && memcmp(file_sum1, sender_file_sum, checksum_len) != 0)
                 return 0;                  return 0;
         return 1;          return 1;
 }  }
Line 350  static void handle_delayed_updates(char *local_name) Line 429  static void handle_delayed_updates(char *local_name)
                 struct file_struct *file = cur_flist->files[ndx];                  struct file_struct *file = cur_flist->files[ndx];
                 fname = local_name ? local_name : f_name(file, NULL);                  fname = local_name ? local_name : f_name(file, NULL);
                 if ((partialptr = partial_dir_fname(fname)) != NULL) {                  if ((partialptr = partial_dir_fname(fname)) != NULL) {
                        if (make_backups > 0 && !make_backup(fname))                        if (make_backups > 0 && !make_backup(fname, False))
                                 continue;                                  continue;
                        if (verbose > 2) {                        if (DEBUG_GTE(RECV, 1)) {
                                 rprintf(FINFO, "renaming %s to %s\n",                                  rprintf(FINFO, "renaming %s to %s\n",
                                         partialptr, fname);                                          partialptr, fname);
                         }                          }
Line 403  static int we_want_redo(int desired_ndx) Line 482  static int we_want_redo(int desired_ndx)
         return 0;          return 0;
 }  }
   
static int gen_wants_ndx(int desired_ndx)static int gen_wants_ndx(int desired_ndx, int flist_num)
 {  {
         static int next_ndx = -1;          static int next_ndx = -1;
         static int done_cnt = 0;          static int done_cnt = 0;
         static BOOL got_eof = False;          static BOOL got_eof = False;
         int flist_num = first_flist->flist_num;  
   
         if (got_eof)          if (got_eof)
                 return 0;                  return 0;
   
           /* TODO: integrate gen-reading I/O into perform_io() so this is not needed? */
           io_flush(FULL_FLUSH);
   
         while (next_ndx < desired_ndx) {          while (next_ndx < desired_ndx) {
                 if (inc_recurse && flist_num <= done_cnt)                  if (inc_recurse && flist_num <= done_cnt)
                         return 0;                          return 0;
Line 440  static int gen_wants_ndx(int desired_ndx) Line 521  static int gen_wants_ndx(int desired_ndx)
  * main routine for receiver process.   * main routine for receiver process.
  *   *
  * Receiver process runs on the same host as the generator process. */   * Receiver process runs on the same host as the generator process. */
int recv_files(int f_in, char *local_name)int recv_files(int f_in, int f_out, char *local_name)
 {  {
         int fd1,fd2;          int fd1,fd2;
         STRUCT_STAT st;          STRUCT_STAT st;
Line 452  int recv_files(int f_in, char *local_name) Line 533  int recv_files(int f_in, char *local_name)
         char fnamecmpbuf[MAXPATHLEN];          char fnamecmpbuf[MAXPATHLEN];
         uchar fnamecmp_type;          uchar fnamecmp_type;
         struct file_struct *file;          struct file_struct *file;
         struct stats initial_stats;  
         int itemizing = am_server ? logfile_format_has_i : stdout_format_has_i;          int itemizing = am_server ? logfile_format_has_i : stdout_format_has_i;
         enum logcode log_code = log_before_transfer ? FLOG : FINFO;          enum logcode log_code = log_before_transfer ? FLOG : FINFO;
         int max_phase = protocol_version >= 29 ? 2 : 1;          int max_phase = protocol_version >= 29 ? 2 : 1;
Line 462  int recv_files(int f_in, char *local_name) Line 542  int recv_files(int f_in, char *local_name)
 #endif  #endif
         int ndx, recv_ok;          int ndx, recv_ok;
   
        if (verbose > 2)        if (DEBUG_GTE(RECV, 1))
                 rprintf(FINFO, "recv_files(%d) starting\n", cur_flist->used);                  rprintf(FINFO, "recv_files(%d) starting\n", cur_flist->used);
   
         if (delay_updates)          if (delay_updates)
Line 472  int recv_files(int f_in, char *local_name) Line 552  int recv_files(int f_in, char *local_name)
                 cleanup_disable();                  cleanup_disable();
   
                 /* This call also sets cur_flist. */                  /* This call also sets cur_flist. */
                ndx = read_ndx_and_attrs(f_in, &iflags, &fnamecmp_type,                ndx = read_ndx_and_attrs(f_in, f_out, &iflags, &fnamecmp_type,
                                          xname, &xlen);                                           xname, &xlen);
                 if (ndx == NDX_DONE) {                  if (ndx == NDX_DONE) {
                           if (!am_server && INFO_GTE(PROGRESS, 2) && cur_flist) {
                                   set_current_file_index(NULL, 0);
                                   end_progress(0);
                           }
                         if (inc_recurse && first_flist) {                          if (inc_recurse && first_flist) {
                                if (read_batch)                                if (read_batch) {
                                        gen_wants_ndx(first_flist->used + first_flist->ndx_start);                                        ndx = first_flist->used + first_flist->ndx_start;
                                         gen_wants_ndx(ndx, first_flist->flist_num);
                                 }
                                 flist_free(first_flist);                                  flist_free(first_flist);
                                 if (first_flist)                                  if (first_flist)
                                         continue;                                          continue;
                        } else if (read_batch && first_flist)                        } else if (read_batch && first_flist) {
                                gen_wants_ndx(first_flist->used);                                ndx = first_flist->used;
                                 gen_wants_ndx(ndx, first_flist->flist_num);
                         }
                         if (++phase > max_phase)                          if (++phase > max_phase)
                                 break;                                  break;
                        if (verbose > 2)                        if (DEBUG_GTE(RECV, 1))
                                 rprintf(FINFO, "recv_files phase=%d\n", phase);                                  rprintf(FINFO, "recv_files phase=%d\n", phase);
                         if (phase == 2 && delay_updates)                          if (phase == 2 && delay_updates)
                                 handle_delayed_updates(local_name);                                  handle_delayed_updates(local_name);
                        send_msg(MSG_DONE, "", 0, 0);                        write_int(f_out, NDX_DONE);
                         continue;                          continue;
                 }                  }
   
Line 499  int recv_files(int f_in, char *local_name) Line 587  int recv_files(int f_in, char *local_name)
                         file = dir_flist->files[cur_flist->parent_ndx];                          file = dir_flist->files[cur_flist->parent_ndx];
                 fname = local_name ? local_name : f_name(file, fbuf);                  fname = local_name ? local_name : f_name(file, fbuf);
   
                if (verbose > 2)                if (DEBUG_GTE(RECV, 1))
                         rprintf(FINFO, "recv_files(%s)\n", fname);                          rprintf(FINFO, "recv_files(%s)\n", fname);
   
 #ifdef SUPPORT_XATTRS  #ifdef SUPPORT_XATTRS
                if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers)                if (preserve_xattrs && iflags & ITEM_REPORT_XATTR && do_xfers
                  && !(want_xattr_optim && BITS_SET(iflags, ITEM_XNAME_FOLLOWS|ITEM_LOCAL_CHANGE)))
                         recv_xattr_request(file, f_in);                          recv_xattr_request(file, f_in);
 #endif  #endif
   
Line 514  int recv_files(int f_in, char *local_name) Line 603  int recv_files(int f_in, char *local_name)
                          && !BITS_SET(iflags, ITEM_XNAME_FOLLOWS|ITEM_LOCAL_CHANGE))                           && !BITS_SET(iflags, ITEM_XNAME_FOLLOWS|ITEM_LOCAL_CHANGE))
                                 set_file_attrs(fname, file, NULL, fname, 0);                                  set_file_attrs(fname, file, NULL, fname, 0);
 #endif  #endif
                           if (iflags & ITEM_IS_NEW) {
                                   stats.created_files++;
                                   if (S_ISREG(file->mode)) {
                                           /* Nothing further to count. */
                                   } else if (S_ISDIR(file->mode))
                                           stats.created_dirs++;
   #ifdef SUPPORT_LINKS
                                   else if (S_ISLNK(file->mode))
                                           stats.created_symlinks++;
   #endif
                                   else if (IS_DEVICE(file->mode))
                                           stats.created_devices++;
                                   else
                                           stats.created_specials++;
                           }
                         continue;                          continue;
                 }                  }
                 if (phase == 2) {                  if (phase == 2) {
Line 543  int recv_files(int f_in, char *local_name) Line 647  int recv_files(int f_in, char *local_name)
                                 csum_length = SHORT_SUM_LENGTH;                                  csum_length = SHORT_SUM_LENGTH;
                                 redoing = 0;                                  redoing = 0;
                         }                          }
                           if (iflags & ITEM_IS_NEW)
                                   stats.created_files++;
                 }                  }
   
                if (!am_server && do_progress)                if (!am_server && INFO_GTE(PROGRESS, 1))
                         set_current_file_index(file, ndx);                          set_current_file_index(file, ndx);
                stats.num_transferred_files++;                stats.xferred_files++;
                 stats.total_transferred_size += F_LENGTH(file);                  stats.total_transferred_size += F_LENGTH(file);
   
                 cleanup_got_literal = 0;                  cleanup_got_literal = 0;
Line 561  int recv_files(int f_in, char *local_name) Line 667  int recv_files(int f_in, char *local_name)
                 if (read_batch) {                  if (read_batch) {
                         int wanted = redoing                          int wanted = redoing
                                    ? we_want_redo(ndx)                                     ? we_want_redo(ndx)
                                   : gen_wants_ndx(ndx);                                   : gen_wants_ndx(ndx, cur_flist->flist_num);
                         if (!wanted) {                          if (!wanted) {
                                 rprintf(FINFO,                                  rprintf(FINFO,
                                         "(Skipping batched update for%s \"%s\")\n",                                          "(Skipping batched update for%s \"%s\")\n",
Line 573  int recv_files(int f_in, char *local_name) Line 679  int recv_files(int f_in, char *local_name)
                         }                          }
                 }                  }
   
                   remember_initial_stats();
   
                 if (!do_xfers) { /* log the transfer */                  if (!do_xfers) { /* log the transfer */
                        log_item(FCLIENT, file, &stats, iflags, NULL);                        log_item(FCLIENT, file, iflags, NULL);
                         if (read_batch)                          if (read_batch)
                                 discard_receive_data(f_in, F_LENGTH(file));                                  discard_receive_data(f_in, F_LENGTH(file));
                         continue;                          continue;
                 }                  }
                 if (write_batch < 0) {                  if (write_batch < 0) {
                        log_item(FCLIENT, file, &stats, iflags, NULL);                        log_item(FCLIENT, file, iflags, NULL);
                         if (!am_server)                          if (!am_server)
                                 discard_receive_data(f_in, F_LENGTH(file));                                  discard_receive_data(f_in, F_LENGTH(file));
                           if (inc_recurse)
                                   send_msg_int(MSG_SUCCESS, ndx);
                         continue;                          continue;
                 }                  }
   
Line 601  int recv_files(int f_in, char *local_name) Line 711  int recv_files(int f_in, char *local_name)
                                 break;                                  break;
                         case FNAMECMP_FUZZY:                          case FNAMECMP_FUZZY:
                                 if (file->dirname) {                                  if (file->dirname) {
                                        pathjoin(fnamecmpbuf, MAXPATHLEN,                                        pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, file->dirname, xname);
                                                 file->dirname, xname); 
                                         fnamecmp = fnamecmpbuf;                                          fnamecmp = fnamecmpbuf;
                                 } else                                  } else
                                         fnamecmp = xname;                                          fnamecmp = xname;
                                 break;                                  break;
                         default:                          default:
                                if (fnamecmp_type >= basis_dir_cnt) {                                if (fnamecmp_type > FNAMECMP_FUZZY && fnamecmp_type-FNAMECMP_FUZZY <= basis_dir_cnt) {
                                         fnamecmp_type -= FNAMECMP_FUZZY + 1;
                                         if (file->dirname) {
                                                 stringjoin(fnamecmpbuf, sizeof fnamecmpbuf,
                                                            basis_dir[fnamecmp_type], "/", file->dirname, "/", xname, NULL);
                                         } else
                                                 pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, basis_dir[fnamecmp_type], xname);
                                 } else if (fnamecmp_type >= basis_dir_cnt) {
                                         rprintf(FERROR,                                          rprintf(FERROR,
                                                 "invalid basis_dir index: %d.\n",                                                  "invalid basis_dir index: %d.\n",
                                                 fnamecmp_type);                                                  fnamecmp_type);
                                         exit_cleanup(RERR_PROTOCOL);                                          exit_cleanup(RERR_PROTOCOL);
                                }                                } else
                                pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,                                        pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, basis_dir[fnamecmp_type], fname);
                                         basis_dir[fnamecmp_type], fname); 
                                 fnamecmp = fnamecmpbuf;                                  fnamecmp = fnamecmpbuf;
                                 break;                                  break;
                         }                          }
Line 638  int recv_files(int f_in, char *local_name) Line 753  int recv_files(int f_in, char *local_name)
                                 fnamecmp = fname;                                  fnamecmp = fname;
                 }                  }
   
                 initial_stats = stats;  
   
                 /* open the file */                  /* open the file */
                 fd1 = do_open(fnamecmp, O_RDONLY, 0);                  fd1 = do_open(fnamecmp, O_RDONLY, 0);
   
Line 716  int recv_files(int f_in, char *local_name) Line 829  int recv_files(int f_in, char *local_name)
                         if (fd2 == -1) {                          if (fd2 == -1) {
                                 rsyserr(FERROR_XFER, errno, "open %s failed",                                  rsyserr(FERROR_XFER, errno, "open %s failed",
                                         full_fname(fname));                                          full_fname(fname));
                        }                        } else if (updating_basis_or_equiv)
                                 cleanup_set(NULL, NULL, file, fd1, fd2);
                 } else {                  } else {
                         fd2 = open_tmpfile(fnametmp, fname, file);                          fd2 = open_tmpfile(fnametmp, fname, file);
                         if (fd2 != -1)                          if (fd2 != -1)
Line 734  int recv_files(int f_in, char *local_name) Line 848  int recv_files(int f_in, char *local_name)
   
                 /* log the transfer */                  /* log the transfer */
                 if (log_before_transfer)                  if (log_before_transfer)
                        log_item(FCLIENT, file, &initial_stats, iflags, NULL);                        log_item(FCLIENT, file, iflags, NULL);
                else if (!am_server && verbose && do_progress)                else if (!am_server && INFO_GTE(NAME, 1) && INFO_EQ(PROGRESS, 1))
                         rprintf(FINFO, "%s\n", fname);                          rprintf(FINFO, "%s\n", fname);
   
                 /* recv file data */                  /* recv file data */
                 recv_ok = receive_data(f_in, fnamecmp, fd1, st.st_size,                  recv_ok = receive_data(f_in, fnamecmp, fd1, st.st_size,
                                        fname, fd2, F_LENGTH(file));                                         fname, fd2, F_LENGTH(file));
   
                log_item(log_code, file, &initial_stats, iflags, NULL);                log_item(log_code, file, iflags, NULL);
   
                 if (fd1 != -1)                  if (fd1 != -1)
                         close(fd1);                          close(fd1);
Line 796  int recv_files(int f_in, char *local_name) Line 910  int recv_files(int f_in, char *local_name)
                         break;                          break;
                 case 0: {                  case 0: {
                         enum logcode msgtype = redoing ? FERROR_XFER : FWARNING;                          enum logcode msgtype = redoing ? FERROR_XFER : FWARNING;
                        if (msgtype == FERROR_XFER || verbose) {                        if (msgtype == FERROR_XFER || INFO_GTE(NAME, 1)) {
                                 char *errstr, *redostr, *keptstr;                                  char *errstr, *redostr, *keptstr;
                                 if (!(keep_partial && partialptr) && !inplace)                                  if (!(keep_partial && partialptr) && !inplace)
                                         keptstr = "discarded";                                          keptstr = "discarded";
Line 838  int recv_files(int f_in, char *local_name) Line 952  int recv_files(int f_in, char *local_name)
         if (phase == 2 && delay_updates) /* for protocol_version < 29 */          if (phase == 2 && delay_updates) /* for protocol_version < 29 */
                 handle_delayed_updates(local_name);                  handle_delayed_updates(local_name);
   
        if (verbose > 2)        if (DEBUG_GTE(RECV, 1))
                 rprintf(FINFO,"recv_files finished\n");                  rprintf(FINFO,"recv_files finished\n");
   
         return 0;          return 0;

Removed from v.1.1  
changed lines
  Added in v.1.1.1.3


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>