Diff for /embedaddon/rsync/generator.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2012/02/17 15:09:30 version 1.1.1.2, 2013/10/14 07:51:14
Line 4 Line 4
  * Copyright (C) 1996-2000 Andrew Tridgell   * Copyright (C) 1996-2000 Andrew Tridgell
  * Copyright (C) 1996 Paul Mackerras   * Copyright (C) 1996 Paul Mackerras
  * Copyright (C) 2002 Martin Pool <mbp@samba.org>   * Copyright (C) 2002 Martin Pool <mbp@samba.org>
 * Copyright (C) 2003-2009 Wayne Davison * Copyright (C) 2003-2013 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 21 Line 21
  */   */
   
 #include "rsync.h"  #include "rsync.h"
   #include "inums.h"
   #include "ifuncs.h"
   
 extern int verbose;  
 extern int dry_run;  extern int dry_run;
 extern int do_xfers;  extern int do_xfers;
 extern int stdout_format_has_i;  extern int stdout_format_has_i;
Line 31  extern int am_root; Line 32  extern int am_root;
 extern int am_server;  extern int am_server;
 extern int am_daemon;  extern int am_daemon;
 extern int inc_recurse;  extern int inc_recurse;
 extern int do_progress;  
 extern int relative_paths;  extern int relative_paths;
 extern int implied_dirs;  extern int implied_dirs;
 extern int keep_dirlinks;  extern int keep_dirlinks;
Line 48  extern int delete_mode; Line 48  extern int delete_mode;
 extern int delete_before;  extern int delete_before;
 extern int delete_during;  extern int delete_during;
 extern int delete_after;  extern int delete_after;
   extern int missing_args;
 extern int msgdone_cnt;  extern int msgdone_cnt;
 extern int ignore_errors;  extern int ignore_errors;
 extern int remove_source_files;  extern int remove_source_files;
 extern int delay_updates;  extern int delay_updates;
 extern int update_only;  extern int update_only;
   extern int human_readable;
 extern int ignore_existing;  extern int ignore_existing;
 extern int ignore_non_existing;  extern int ignore_non_existing;
 extern int inplace;  extern int inplace;
Line 67  extern int io_error; Line 69  extern int io_error;
 extern int flist_eof;  extern int flist_eof;
 extern int allowed_lull;  extern int allowed_lull;
 extern int sock_f_out;  extern int sock_f_out;
 extern int ignore_timeout;  
 extern int protocol_version;  extern int protocol_version;
 extern int file_total;  extern int file_total;
 extern int fuzzy_basis;  extern int fuzzy_basis;
 extern int always_checksum;  extern int always_checksum;
 extern int checksum_len;  extern int checksum_len;
 extern char *partial_dir;  extern char *partial_dir;
 extern char *basis_dir[MAX_BASIS_DIRS+1];  
 extern int compare_dest;  extern int compare_dest;
 extern int copy_dest;  extern int copy_dest;
 extern int link_dest;  extern int link_dest;
 extern int whole_file;  extern int whole_file;
 extern int list_only;  extern int list_only;
 extern int read_batch;  extern int read_batch;
   extern int write_batch;
 extern int safe_symlinks;  extern int safe_symlinks;
 extern long block_size; /* "long" because popt can't set an int32. */  extern long block_size; /* "long" because popt can't set an int32. */
 extern int unsort_ndx;  extern int unsort_ndx;
 extern int max_delete;  extern int max_delete;
 extern int force_delete;  extern int force_delete;
 extern int one_file_system;  extern int one_file_system;
extern struct stats stats;extern int skipped_deletes;
 extern dev_t filesystem_dev;  extern dev_t filesystem_dev;
 extern mode_t orig_umask;  extern mode_t orig_umask;
 extern uid_t our_uid;  extern uid_t our_uid;
extern char *backup_dir;extern char *tmpdir;
extern char *backup_suffix;extern char *basis_dir[MAX_BASIS_DIRS+1];
extern int backup_suffix_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 filter_list, daemon_filter_list;
   
 int ignore_perishable = 0;  
 int non_perishable_cnt = 0;  
 int maybe_ATTRS_REPORT = 0;  int maybe_ATTRS_REPORT = 0;
   
 static dev_t dev_zero;  static dev_t dev_zero;
 static int deletion_count = 0; /* used to implement --max-delete */  
 static int deldelay_size = 0, deldelay_cnt = 0;  static int deldelay_size = 0, deldelay_cnt = 0;
 static char *deldelay_buf = NULL;  static char *deldelay_buf = NULL;
 static int deldelay_fd = -1;  static int deldelay_fd = -1;
Line 113  static int need_retouch_dir_times; Line 110  static int need_retouch_dir_times;
 static int need_retouch_dir_perms;  static int need_retouch_dir_perms;
 static const char *solo_file = NULL;  static const char *solo_file = NULL;
   
 /* For calling delete_item() and delete_dir_contents(). */  
 #define DEL_NO_UID_WRITE        (1<<0) /* file/dir has our uid w/o write perm */  
 #define DEL_RECURSE             (1<<1) /* if dir, delete all contents */  
 #define DEL_DIR_IS_EMPTY        (1<<2) /* internal delete_FUNCTIONS use only */  
 #define DEL_FOR_FILE            (1<<3) /* making room for a replacement file */  
 #define DEL_FOR_DIR             (1<<4) /* making room for a replacement dir */  
 #define DEL_FOR_SYMLINK         (1<<5) /* making room for a replacement symlink */  
 #define DEL_FOR_DEVICE          (1<<6) /* making room for a replacement device */  
 #define DEL_FOR_SPECIAL         (1<<7) /* making room for a replacement special */  
   
 #define DEL_MAKE_ROOM (DEL_FOR_FILE|DEL_FOR_DIR|DEL_FOR_SYMLINK|DEL_FOR_DEVICE|DEL_FOR_SPECIAL)  
   
 enum nonregtype {  enum nonregtype {
     TYPE_DIR, TYPE_SPECIAL, TYPE_DEVICE, TYPE_SYMLINK      TYPE_DIR, TYPE_SPECIAL, TYPE_DEVICE, TYPE_SYMLINK
 };  };
   
 enum delret {  
     DR_SUCCESS = 0, DR_FAILURE, DR_AT_LIMIT, DR_NOT_EMPTY  
 };  
   
 /* Forward declarations. */  /* Forward declarations. */
 static enum delret delete_dir_contents(char *fname, uint16 flags);  
 #ifdef SUPPORT_HARD_LINKS  #ifdef SUPPORT_HARD_LINKS
 static void handle_skipped_hlink(struct file_struct *file, int itemizing,  static void handle_skipped_hlink(struct file_struct *file, int itemizing,
                                  enum logcode code, int f_out);                                   enum logcode code, int f_out);
 #endif  #endif
   
static int is_backup_file(char *fn)#define EARLY_DELAY_DONE_MSG() (!delay_updates)
{#define EARLY_DELETE_DONE_MSG() (!(delete_during == 2 || delete_after))
        int k = strlen(fn) - backup_suffix_len; 
        return k > 0 && strcmp(fn+k, backup_suffix) == 0; 
} 
   
 /* Delete a file or directory.  If DEL_RECURSE is set in the flags, this will  
  * delete recursively.  
  *  
  * Note that fbuf must point to a MAXPATHLEN buffer if the mode indicates it's  
  * a directory! (The buffer is used for recursion, but returned unchanged.)  
  */  
 static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)  
 {  
         enum delret ret;  
         char *what;  
         int ok;  
   
         if (verbose > 2) {  
                 rprintf(FINFO, "delete_item(%s) mode=%o flags=%d\n",  
                         fbuf, (int)mode, (int)flags);  
         }  
   
         if (flags & DEL_NO_UID_WRITE)  
                 do_chmod(fbuf, mode | S_IWUSR);  
   
         if (S_ISDIR(mode) && !(flags & DEL_DIR_IS_EMPTY)) {  
                 /* This only happens on the first call to delete_item() since  
                  * delete_dir_contents() always calls us w/DEL_DIR_IS_EMPTY. */  
                 ignore_perishable = 1;  
                 /* If DEL_RECURSE is not set, this just reports emptiness. */  
                 ret = delete_dir_contents(fbuf, flags);  
                 ignore_perishable = 0;  
                 if (ret == DR_NOT_EMPTY || ret == DR_AT_LIMIT)  
                         goto check_ret;  
                 /* OK: try to delete the directory. */  
         }  
   
         if (!(flags & DEL_MAKE_ROOM) && max_delete >= 0 && ++deletion_count > max_delete)  
                 return DR_AT_LIMIT;  
   
         if (S_ISDIR(mode)) {  
                 what = "rmdir";  
                 ok = do_rmdir(fbuf) == 0;  
         } else if (make_backups > 0 && (backup_dir || !is_backup_file(fbuf))) {  
                 what = "make_backup";  
                 ok = make_backup(fbuf);  
         } else {  
                 what = "unlink";  
                 ok = robust_unlink(fbuf) == 0;  
         }  
   
         if (ok) {  
                 if (!(flags & DEL_MAKE_ROOM))  
                         log_delete(fbuf, mode);  
                 ret = DR_SUCCESS;  
         } else {  
                 if (S_ISDIR(mode) && errno == ENOTEMPTY) {  
                         rprintf(FINFO, "cannot delete non-empty directory: %s\n",  
                                 fbuf);  
                         ret = DR_NOT_EMPTY;  
                 } else if (errno != ENOENT) {  
                         rsyserr(FERROR, errno, "delete_file: %s(%s) failed",  
                                 what, fbuf);  
                         ret = DR_FAILURE;  
                 } else {  
                         deletion_count--;  
                         ret = DR_SUCCESS;  
                 }  
         }  
   
   check_ret:  
         if (ret != DR_SUCCESS && flags & DEL_MAKE_ROOM) {  
                 const char *desc;  
                 switch (flags & DEL_MAKE_ROOM) {  
                 case DEL_FOR_FILE: desc = "regular file"; break;  
                 case DEL_FOR_DIR: desc = "directory"; break;  
                 case DEL_FOR_SYMLINK: desc = "symlink"; break;  
                 case DEL_FOR_DEVICE: desc = "device file"; break;  
                 case DEL_FOR_SPECIAL: desc = "special file"; break;  
                 default: exit_cleanup(RERR_UNSUPPORTED); /* IMPOSSIBLE */  
                 }  
                 rprintf(FERROR_XFER, "could not make way for new %s: %s\n",  
                         desc, fbuf);  
         }  
         return ret;  
 }  
   
 /* The directory is about to be deleted: if DEL_RECURSE is given, delete all  
  * its contents, otherwise just checks for content.  Returns DR_SUCCESS or  
  * DR_NOT_EMPTY.  Note that fname must point to a MAXPATHLEN buffer!  (The  
  * buffer is used for recursion, but returned unchanged.)  
  */  
 static enum delret delete_dir_contents(char *fname, uint16 flags)  
 {  
         struct file_list *dirlist;  
         enum delret ret;  
         unsigned remainder;  
         void *save_filters;  
         int j, dlen;  
         char *p;  
   
         if (verbose > 3) {  
                 rprintf(FINFO, "delete_dir_contents(%s) flags=%d\n",  
                         fname, flags);  
         }  
   
         dlen = strlen(fname);  
         save_filters = push_local_filters(fname, dlen);  
   
         non_perishable_cnt = 0;  
         dirlist = get_dirlist(fname, dlen, 0);  
         ret = non_perishable_cnt ? DR_NOT_EMPTY : DR_SUCCESS;  
   
         if (!dirlist->used)  
                 goto done;  
   
         if (!(flags & DEL_RECURSE)) {  
                 ret = DR_NOT_EMPTY;  
                 goto done;  
         }  
   
         p = fname + dlen;  
         if (dlen != 1 || *fname != '/')  
                 *p++ = '/';  
         remainder = MAXPATHLEN - (p - fname);  
   
         /* We do our own recursion, so make delete_item() non-recursive. */  
         flags = (flags & ~(DEL_RECURSE|DEL_MAKE_ROOM|DEL_NO_UID_WRITE))  
               | DEL_DIR_IS_EMPTY;  
   
         for (j = dirlist->used; j--; ) {  
                 struct file_struct *fp = dirlist->files[j];  
   
                 if (fp->flags & FLAG_MOUNT_DIR && S_ISDIR(fp->mode)) {  
                         if (verbose > 1) {  
                                 rprintf(FINFO,  
                                     "mount point, %s, pins parent directory\n",  
                                     f_name(fp, NULL));  
                         }  
                         ret = DR_NOT_EMPTY;  
                         continue;  
                 }  
   
                 strlcpy(p, fp->basename, remainder);  
                 if (!(fp->mode & S_IWUSR) && !am_root && fp->flags & FLAG_OWNED_BY_US)  
                         do_chmod(fname, fp->mode | S_IWUSR);  
                 /* Save stack by recursing to ourself directly. */  
                 if (S_ISDIR(fp->mode)) {  
                         if (delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS)  
                                 ret = DR_NOT_EMPTY;  
                 }  
                 if (delete_item(fname, fp->mode, flags) != DR_SUCCESS)  
                         ret = DR_NOT_EMPTY;  
         }  
   
         fname[dlen] = '\0';  
   
   done:  
         flist_free(dirlist);  
         pop_local_filters(save_filters);  
   
         if (ret == DR_NOT_EMPTY) {  
                 rprintf(FINFO, "cannot delete non-empty directory: %s\n",  
                         fname);  
         }  
         return ret;  
 }  
   
 static int start_delete_delay_temp(void)  static int start_delete_delay_temp(void)
 {  {
         char fnametmp[MAXPATHLEN];          char fnametmp[MAXPATHLEN];
         int save_dry_run = dry_run;          int save_dry_run = dry_run;
   
         dry_run = 0;          dry_run = 0;
        if (!get_tmpname(fnametmp, "deldelay")        if (!get_tmpname(fnametmp, "deldelay", False)
          || (deldelay_fd = do_mkstemp(fnametmp, 0600)) < 0) {           || (deldelay_fd = do_mkstemp(fnametmp, 0600)) < 0) {
                 rprintf(FINFO, "NOTE: Unable to create delete-delay temp file%s.\n",                  rprintf(FINFO, "NOTE: Unable to create delete-delay temp file%s.\n",
                         inc_recurse ? "" : " -- switching to --delete-after");                          inc_recurse ? "" : " -- switching to --delete-after");
Line 469  static void delete_in_dir(char *fbuf, struct file_stru Line 283  static void delete_in_dir(char *fbuf, struct file_stru
                 return;                  return;
         }          }
   
        if (verbose > 2)        if (DEBUG_GTE(DEL, 2))
                 rprintf(FINFO, "delete_in_dir(%s)\n", fbuf);                  rprintf(FINFO, "delete_in_dir(%s)\n", fbuf);
   
         if (allowed_lull)          if (allowed_lull)
                maybe_send_keepalive();                maybe_send_keepalive(time(NULL), MSK_ALLOW_FLUSH);
   
        if (io_error && !ignore_errors) {        if (io_error & IOERR_GENERAL && !ignore_errors) {
                 if (already_warned)                  if (already_warned)
                         return;                          return;
                 rprintf(FINFO,                  rprintf(FINFO,
Line 503  static void delete_in_dir(char *fbuf, struct file_stru Line 317  static void delete_in_dir(char *fbuf, struct file_stru
                 if (!F_IS_ACTIVE(fp))                  if (!F_IS_ACTIVE(fp))
                         continue;                          continue;
                 if (fp->flags & FLAG_MOUNT_DIR && S_ISDIR(fp->mode)) {                  if (fp->flags & FLAG_MOUNT_DIR && S_ISDIR(fp->mode)) {
                        if (verbose > 1)                        if (INFO_GTE(MOUNT, 1))
                                 rprintf(FINFO, "cannot delete mount point: %s\n",                                  rprintf(FINFO, "cannot delete mount point: %s\n",
                                         f_name(fp, NULL));                                          f_name(fp, NULL));
                         continue;                          continue;
Line 549  static void do_delete_pass(void) Line 363  static void do_delete_pass(void)
                         continue;                          continue;
                 }                  }
   
                if (verbose > 1 && file->flags & FLAG_TOP_DIR)                if (DEBUG_GTE(DEL, 1) && file->flags & FLAG_TOP_DIR)
                         rprintf(FINFO, "deleting in %s\n", fbuf);                          rprintf(FINFO, "deleting in %s\n", fbuf);
   
                 if (link_stat(fbuf, &st, keep_dirlinks) < 0                  if (link_stat(fbuf, &st, keep_dirlinks) < 0
Line 560  static void do_delete_pass(void) Line 374  static void do_delete_pass(void)
         }          }
         delete_in_dir(NULL, NULL, &dev_zero);          delete_in_dir(NULL, NULL, &dev_zero);
   
        if (do_progress && !am_server)        if (INFO_GTE(FLIST, 2) && !am_server)
                 rprintf(FINFO, "                    \r");                  rprintf(FINFO, "                    \r");
 }  }
   
Line 723  void itemize(const char *fnamecmp, struct file_struct  Line 537  void itemize(const char *fnamecmp, struct file_struct 
         }          }
   
         iflags &= 0xffff;          iflags &= 0xffff;
        if ((iflags & (SIGNIFICANT_ITEM_FLAGS|ITEM_REPORT_XATTR) || verbose > 1        if ((iflags & (SIGNIFICANT_ITEM_FLAGS|ITEM_REPORT_XATTR) || INFO_GTE(NAME, 2)
           || stdout_format_has_i > 1 || (xname && *xname)) && !read_batch) {            || stdout_format_has_i > 1 || (xname && *xname)) && !read_batch) {
                 if (protocol_version >= 29) {                  if (protocol_version >= 29) {
                         if (ndx >= 0)                          if (ndx >= 0)
Line 736  void itemize(const char *fnamecmp, struct file_struct  Line 550  void itemize(const char *fnamecmp, struct file_struct 
 #ifdef SUPPORT_XATTRS  #ifdef SUPPORT_XATTRS
                         if (preserve_xattrs && do_xfers                          if (preserve_xattrs && do_xfers
                          && iflags & (ITEM_REPORT_XATTR|ITEM_TRANSFER)) {                           && iflags & (ITEM_REPORT_XATTR|ITEM_TRANSFER)) {
                                send_xattr_request(NULL, file,                                int fd = iflags & ITEM_REPORT_XATTR
                                        iflags & ITEM_REPORT_XATTR ? sock_f_out : -1);                                      && (protocol_version < 31 || !BITS_SET(iflags, ITEM_XNAME_FOLLOWS|ITEM_LOCAL_CHANGE))
                                        ? sock_f_out : -1;
                                 send_xattr_request(NULL, file, fd);
                         }                          }
 #endif  #endif
                 } else if (ndx >= 0) {                  } else if (ndx >= 0) {
                         enum logcode code = logfile_format_has_i ? FINFO : FCLIENT;                          enum logcode code = logfile_format_has_i ? FINFO : FCLIENT;
                        log_item(code, file, &stats, iflags, xname);                        log_item(code, file, iflags, xname);
                 }                  }
         }          }
 }  }
Line 848  static void sum_sizes_sqroot(struct sum_struct *sum, i Line 664  static void sum_sizes_sqroot(struct sum_struct *sum, i
         if ((int64)sum->count != l)          if ((int64)sum->count != l)
                 sum->count = -1;                  sum->count = -1;
   
        if (sum->count && verbose > 2) {        if (sum->count && DEBUG_GTE(DELTASUM, 2)) {
                 rprintf(FINFO,                  rprintf(FINFO,
                        "count=%.0f rem=%ld blength=%ld s2length=%d flength=%.0f\n",                        "count=%s rem=%ld blength=%ld s2length=%d flength=%s\n",
                        (double)sum->count, (long)sum->remainder, (long)sum->blength,                        big_num(sum->count), (long)sum->remainder, (long)sum->blength,
                        sum->s2length, (double)sum->flength);                        sum->s2length, big_num(sum->flength));
         }          }
 }  }
   
Line 900  static int generate_and_send_sums(int fd, OFF_T len, i Line 716  static int generate_and_send_sums(int fd, OFF_T len, i
                 sum1 = get_checksum1(map, n1);                  sum1 = get_checksum1(map, n1);
                 get_checksum2(map, n1, sum2);                  get_checksum2(map, n1, sum2);
   
                if (verbose > 3) {                if (DEBUG_GTE(DELTASUM, 3)) {
                         rprintf(FINFO,                          rprintf(FINFO,
                                "chunk[%.0f] offset=%.0f len=%ld sum1=%08lx\n",                                "chunk[%s] offset=%s len=%ld sum1=%08lx\n",
                                (double)i, (double)offset - n1, (long)n1,                                big_num(i), big_num(offset - n1), (long)n1,
                                 (unsigned long)sum1);                                  (unsigned long)sum1);
                 }                  }
                 write_int(f_out, sum1);                  write_int(f_out, sum1);
Line 918  static int generate_and_send_sums(int fd, OFF_T len, i Line 734  static int generate_and_send_sums(int fd, OFF_T len, i
   
   
 /* Try to find a filename in the same dir as "fname" with a similar name. */  /* Try to find a filename in the same dir as "fname" with a similar name. */
static int find_fuzzy(struct file_struct *file, struct file_list *dirlist)static struct file_struct *find_fuzzy(struct file_struct *file, struct file_list *dirlist_array[], uchar *fnamecmp_type_ptr)
 {  {
         int fname_len, fname_suf_len;          int fname_len, fname_suf_len;
         const char *fname_suf, *fname = file->basename;          const char *fname_suf, *fname = file->basename;
         uint32 lowest_dist = 25 << 16; /* ignore a distance greater than 25 */          uint32 lowest_dist = 25 << 16; /* ignore a distance greater than 25 */
        int j, lowest_j = -1;        int i, j;
         struct file_struct *lowest_fp = NULL;
   
         fname_len = strlen(fname);          fname_len = strlen(fname);
         fname_suf = find_filename_suffix(fname, fname_len, &fname_suf_len);          fname_suf = find_filename_suffix(fname, fname_len, &fname_suf_len);
   
        for (j = 0; j < dirlist->used; j++) {        /* Try to find an exact size+mtime match first. */
                struct file_struct *fp = dirlist->files[j];        for (i = 0; i < fuzzy_basis; i++) {
                const char *suf, *name;                struct file_list *dirlist = dirlist_array[i];
                int len, suf_len; 
                uint32 dist; 
   
                if (!S_ISREG(fp->mode) || !F_LENGTH(fp)                if (!dirlist)
                 || fp->flags & FLAG_FILE_SENT) 
                         continue;                          continue;
   
                name = fp->basename;                for (j = 0; j < dirlist->used; j++) {
                         struct file_struct *fp = dirlist->files[j];
   
                if (F_LENGTH(fp) == F_LENGTH(file)                        if (!S_ISREG(fp->mode) || !F_LENGTH(fp) || fp->flags & FLAG_FILE_SENT)
                    && cmp_time(fp->modtime, file->modtime) == 0) {                                continue;
                        if (verbose > 4) {
                                rprintf(FINFO,                        if (F_LENGTH(fp) == F_LENGTH(file) && cmp_time(fp->modtime, file->modtime) == 0) {
                                        "fuzzy size/modtime match for %s\n",                                if (DEBUG_GTE(FUZZY, 2))
                                        name);                                        rprintf(FINFO, "fuzzy size/modtime match for %s\n", f_name(fp, NULL));
                                 *fnamecmp_type_ptr = FNAMECMP_FUZZY + i;
                                 return fp;
                         }                          }
                        return j;
                 }                  }
           }
   
                len = strlen(name);        for (i = 0; i < fuzzy_basis; i++) {
                suf = find_filename_suffix(name, len, &suf_len);                struct file_list *dirlist = dirlist_array[i];
   
                dist = fuzzy_distance(name, len, fname, fname_len);                if (!dirlist)
                /* Add some extra weight to how well the suffixes match. */                        continue;
                dist += fuzzy_distance(suf, suf_len, fname_suf, fname_suf_len)
                      * 10;                for (j = 0; j < dirlist->used; j++) {
                if (verbose > 4) {                        struct file_struct *fp = dirlist->files[j];
                        rprintf(FINFO, "fuzzy distance for %s = %d.%05d\n",                        const char *suf, *name;
                                name, (int)(dist>>16), (int)(dist&0xFFFF));                        int len, suf_len;
                         uint32 dist;
 
                         if (!S_ISREG(fp->mode) || !F_LENGTH(fp) || fp->flags & FLAG_FILE_SENT)
                                 continue;
 
                         name = fp->basename;
                         len = strlen(name);
                         suf = find_filename_suffix(name, len, &suf_len);
 
                         dist = fuzzy_distance(name, len, fname, fname_len);
                         /* Add some extra weight to how well the suffixes match. */
                         dist += fuzzy_distance(suf, suf_len, fname_suf, fname_suf_len) * 10;
                         if (DEBUG_GTE(FUZZY, 2)) {
                                 rprintf(FINFO, "fuzzy distance for %s = %d.%05d\n",
                                         f_name(fp, NULL), (int)(dist>>16), (int)(dist&0xFFFF));
                         }
                         if (dist <= lowest_dist) {
                                 lowest_dist = dist;
                                 lowest_fp = fp;
                                 *fnamecmp_type_ptr = FNAMECMP_FUZZY + i;
                         }
                 }                  }
                 if (dist <= lowest_dist) {  
                         lowest_dist = dist;  
                         lowest_j = j;  
                 }  
         }          }
   
        return lowest_j;        return lowest_fp;
 }  }
   
 /* Copy a file found in our --copy-dest handling. */  /* Copy a file found in our --copy-dest handling. */
Line 989  static int copy_altdest_file(const char *src, const ch Line 824  static int copy_altdest_file(const char *src, const ch
                 copy_to = buf;                  copy_to = buf;
         }          }
         cleanup_set(copy_to, NULL, NULL, -1, -1);          cleanup_set(copy_to, NULL, NULL, -1, -1);
        if (copy_file(src, copy_to, fd_w, file->mode, 0) < 0) {        if (copy_file(src, copy_to, fd_w, file->mode) < 0) {
                if (verbose) {                if (INFO_GTE(COPY, 1)) {
                         rsyserr(FINFO, errno, "copy_file %s => %s",                          rsyserr(FINFO, errno, "copy_file %s => %s",
                                 full_fname(src), copy_to);                                  full_fname(src), copy_to);
                 }                  }
Line 1009  static int copy_altdest_file(const char *src, const ch Line 844  static int copy_altdest_file(const char *src, const ch
   
 /* This is only called for regular files.  We return -2 if we've finished  /* This is only called for regular files.  We return -2 if we've finished
  * handling the file, -1 if no dest-linking occurred, or a non-negative   * handling the file, -1 if no dest-linking occurred, or a non-negative
 * value if we found an alternate basis file. */ * value if we found an alternate basis file.  If we're called with the
  * find_exact_for_existing flag, the destination file already exists, so
  * we only try to find an exact alt-dest match.  In this case, the returns
  * are only -2 & -1 (both as above). */
 static int try_dests_reg(struct file_struct *file, char *fname, int ndx,  static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
                         char *cmpbuf, stat_x *sxp, int itemizing,                         char *cmpbuf, stat_x *sxp, int find_exact_for_existing,
                         enum logcode code)                         int itemizing, enum logcode code)
 {  {
           STRUCT_STAT real_st = sxp->st;
         int best_match = -1;          int best_match = -1;
         int match_level = 0;          int match_level = 0;
         int j = 0;          int j = 0;
Line 1034  static int try_dests_reg(struct file_struct *file, cha Line 873  static int try_dests_reg(struct file_struct *file, cha
                         match_level = 2;                          match_level = 2;
                         /* FALL THROUGH */                          /* FALL THROUGH */
                 case 2:                  case 2:
                        if (!unchanged_attrs(cmpbuf, file, sxp))                        if (!unchanged_attrs(cmpbuf, file, sxp)) {
                                 free_stat_x(sxp);
                                 continue;                                  continue;
                           }
                         best_match = j;                          best_match = j;
                         match_level = 3;                          match_level = 3;
                         break;                          break;
Line 1054  static int try_dests_reg(struct file_struct *file, cha Line 895  static int try_dests_reg(struct file_struct *file, cha
         }          }
   
         if (match_level == 3 && !copy_dest) {          if (match_level == 3 && !copy_dest) {
                   if (find_exact_for_existing) {
                           if (link_dest && real_st.st_dev == sxp->st.st_dev && real_st.st_ino == sxp->st.st_ino)
                                   return -1;
                           if (do_unlink(fname) < 0 && errno != ENOENT) {
                                   sxp->st = real_st;
                                   return -1;
                           }
                   }
 #ifdef SUPPORT_HARD_LINKS  #ifdef SUPPORT_HARD_LINKS
                 if (link_dest) {                  if (link_dest) {
                         if (!hard_link_one(file, fname, cmpbuf, 1))                          if (!hard_link_one(file, fname, cmpbuf, 1))
                                 goto try_a_copy;                                  goto try_a_copy;
                         if (preserve_hard_links && F_IS_HLINKED(file))                          if (preserve_hard_links && F_IS_HLINKED(file))
                                 finish_hard_link(file, fname, ndx, &sxp->st, itemizing, code, j);                                  finish_hard_link(file, fname, ndx, &sxp->st, itemizing, code, j);
                        if (!maybe_ATTRS_REPORT && (verbose > 1 || stdout_format_has_i > 1)) {                        if (!maybe_ATTRS_REPORT && (INFO_GTE(NAME, 2) || stdout_format_has_i > 1)) {
                                 itemize(cmpbuf, file, ndx, 1, sxp,                                  itemize(cmpbuf, file, ndx, 1, sxp,
                                         ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS,                                          ITEM_LOCAL_CHANGE | ITEM_XNAME_FOLLOWS,
                                         0, "");                                          0, "");
                         }                          }
                 } else                  } else
 #endif  #endif
                if (itemizing)                {
                        itemize(cmpbuf, file, ndx, 0, sxp, 0, 0, NULL);                        if (itemizing)
                if (verbose > 1 && maybe_ATTRS_REPORT)                                itemize(cmpbuf, file, ndx, 0, sxp, 0, 0, NULL);
                 }
                 if (INFO_GTE(NAME, 2) && maybe_ATTRS_REPORT)
                         rprintf(FCLIENT, "%s is uptodate\n", fname);                          rprintf(FCLIENT, "%s is uptodate\n", fname);
                 return -2;                  return -2;
         }          }
   
           if (find_exact_for_existing) {
                   sxp->st = real_st;
                   return -1;
           }
   
         if (match_level >= 2) {          if (match_level >= 2) {
 #ifdef SUPPORT_HARD_LINKS  #ifdef SUPPORT_HARD_LINKS
           try_a_copy: /* Copy the file locally. */            try_a_copy: /* Copy the file locally. */
 #endif  #endif
                if (!dry_run && copy_altdest_file(cmpbuf, fname, file) < 0)                if (!dry_run && copy_altdest_file(cmpbuf, fname, file) < 0) {
                         if (find_exact_for_existing) /* Can get here via hard-link failure */
                                 sxp->st = real_st;
                         return -1;                          return -1;
                   }
                 if (itemizing)                  if (itemizing)
                         itemize(cmpbuf, file, ndx, 0, sxp, ITEM_LOCAL_CHANGE, 0, NULL);                          itemize(cmpbuf, file, ndx, 0, sxp, ITEM_LOCAL_CHANGE, 0, NULL);
                 if (maybe_ATTRS_REPORT                  if (maybe_ATTRS_REPORT
                 && ((!itemizing && verbose && match_level == 2)                 && ((!itemizing && INFO_GTE(NAME, 1) && match_level == 2)
                  || (verbose > 1 && match_level == 3))) {                  || (INFO_GTE(NAME, 2) && match_level == 3))) {
                         code = match_level == 3 ? FCLIENT : FINFO;                          code = match_level == 3 ? FCLIENT : FINFO;
                         rprintf(code, "%s%s\n", fname,                          rprintf(code, "%s%s\n", fname,
                                 match_level == 3 ? " is uptodate" : "");                                  match_level == 3 ? " is uptodate" : "");
Line 1106  static int try_dests_non(struct file_struct *file, cha Line 965  static int try_dests_non(struct file_struct *file, cha
                          char *cmpbuf, stat_x *sxp, int itemizing,                           char *cmpbuf, stat_x *sxp, int itemizing,
                          enum logcode code)                           enum logcode code)
 {  {
         char lnk[MAXPATHLEN];  
         int best_match = -1;          int best_match = -1;
         int match_level = 0;          int match_level = 0;
         enum nonregtype type;          enum nonregtype type;
         uint32 *devp;          uint32 *devp;
        int len, j = 0;#ifdef SUPPORT_LINKS
         char lnk[MAXPATHLEN];
         int len;
 #endif
         int j = 0;
   
 #ifndef SUPPORT_LINKS  #ifndef SUPPORT_LINKS
         if (S_ISLNK(file->mode))          if (S_ISLNK(file->mode))
Line 1151  static int try_dests_non(struct file_struct *file, cha Line 1013  static int try_dests_non(struct file_struct *file, cha
                         if (!IS_DEVICE(sxp->st.st_mode))                          if (!IS_DEVICE(sxp->st.st_mode))
                                 continue;                                  continue;
                         break;                          break;
 #ifdef SUPPORT_LINKS  
                 case TYPE_SYMLINK:                  case TYPE_SYMLINK:
   #ifdef SUPPORT_LINKS
                         if (!S_ISLNK(sxp->st.st_mode))                          if (!S_ISLNK(sxp->st.st_mode))
                                 continue;                                  continue;
                         break;                          break;
   #else
                           return -1;
 #endif  #endif
                 }                  }
                 if (match_level < 1) {                  if (match_level < 1) {
Line 1171  static int try_dests_non(struct file_struct *file, cha Line 1035  static int try_dests_non(struct file_struct *file, cha
                         if (sxp->st.st_rdev != MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)))                          if (sxp->st.st_rdev != MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)))
                                 continue;                                  continue;
                         break;                          break;
 #ifdef SUPPORT_LINKS  
                 case TYPE_SYMLINK:                  case TYPE_SYMLINK:
                        if ((len = readlink(cmpbuf, lnk, MAXPATHLEN-1)) <= 0)#ifdef SUPPORT_LINKS
                         if ((len = do_readlink(cmpbuf, lnk, MAXPATHLEN-1)) <= 0)
                                 continue;                                  continue;
                         lnk[len] = '\0';                          lnk[len] = '\0';
                         if (strcmp(lnk, F_SYMLINK(file)) != 0)                          if (strcmp(lnk, F_SYMLINK(file)) != 0)
                                 continue;                                  continue;
                         break;                          break;
   #else
                           return -1;
 #endif  #endif
                 }                  }
                 if (match_level < 2) {                  if (match_level < 2) {
Line 1224  static int try_dests_non(struct file_struct *file, cha Line 1090  static int try_dests_non(struct file_struct *file, cha
 #endif  #endif
                         match_level = 2;                          match_level = 2;
                 if (itemizing && stdout_format_has_i                  if (itemizing && stdout_format_has_i
                 && (verbose > 1 || stdout_format_has_i > 1)) {                 && (INFO_GTE(NAME, 2) || stdout_format_has_i > 1)) {
                         int chg = compare_dest && type != TYPE_DIR ? 0                          int chg = compare_dest && type != TYPE_DIR ? 0
                             : ITEM_LOCAL_CHANGE + (match_level == 3 ? ITEM_XNAME_FOLLOWS : 0);                              : ITEM_LOCAL_CHANGE + (match_level == 3 ? ITEM_XNAME_FOLLOWS : 0);
                         char *lp = match_level == 3 ? "" : NULL;                          char *lp = match_level == 3 ? "" : NULL;
                         itemize(cmpbuf, file, ndx, 0, sxp, chg + ITEM_MATCHED, 0, lp);                          itemize(cmpbuf, file, ndx, 0, sxp, chg + ITEM_MATCHED, 0, lp);
                 }                  }
                if (verbose > 1 && maybe_ATTRS_REPORT) {                if (INFO_GTE(NAME, 2) && maybe_ATTRS_REPORT) {
                         rprintf(FCLIENT, "%s%s is uptodate\n",                          rprintf(FCLIENT, "%s%s is uptodate\n",
                                 fname, type == TYPE_DIR ? "/" : "");                                  fname, type == TYPE_DIR ? "/" : "");
                 }                  }
Line 1243  static int try_dests_non(struct file_struct *file, cha Line 1109  static int try_dests_non(struct file_struct *file, cha
 static void list_file_entry(struct file_struct *f)  static void list_file_entry(struct file_struct *f)
 {  {
         char permbuf[PERMSTRING_SIZE];          char permbuf[PERMSTRING_SIZE];
        double len;        int64 len;
         int colwidth = human_readable ? 14 : 11;
   
         if (!F_IS_ACTIVE(f)) {          if (!F_IS_ACTIVE(f)) {
                 /* this can happen if duplicate names were removed */                  /* this can happen if duplicate names were removed */
Line 1257  static void list_file_entry(struct file_struct *f) Line 1124  static void list_file_entry(struct file_struct *f)
   
 #ifdef SUPPORT_LINKS  #ifdef SUPPORT_LINKS
         if (preserve_links && S_ISLNK(f->mode)) {          if (preserve_links && S_ISLNK(f->mode)) {
                rprintf(FINFO, "%s %11.0f %s %s -> %s\n",                rprintf(FINFO, "%s %*s %s %s -> %s\n",
                        permbuf, len, timestring(f->modtime),                        permbuf, colwidth, human_num(len),
                        f_name(f, NULL), F_SYMLINK(f));                        timestring(f->modtime), f_name(f, NULL),
                         F_SYMLINK(f));
         } else          } else
 #endif  #endif
        {        if (missing_args == 2 && f->mode == 0) {
                rprintf(FINFO, "%s %11.0f %s %s\n",                rprintf(FINFO, "%-*s %s\n",
                        permbuf, len, timestring(f->modtime),                        colwidth + 31, "*missing",
                         f_name(f, NULL));                          f_name(f, NULL));
           } else {
                   rprintf(FINFO, "%s %*s %s %s\n",
                           permbuf, colwidth, human_num(len),
                           timestring(f->modtime), f_name(f, NULL));
         }          }
 }  }
   
Line 1300  static void recv_generator(char *fname, struct file_st Line 1172  static void recv_generator(char *fname, struct file_st
         /* Missing dir whose contents are skipped altogether due to          /* Missing dir whose contents are skipped altogether due to
          * --ignore-non-existing, daemon exclude, or mkdir failure. */           * --ignore-non-existing, daemon exclude, or mkdir failure. */
         static struct file_struct *skip_dir = NULL;          static struct file_struct *skip_dir = NULL;
        static struct file_list *fuzzy_dirlist = NULL;        static struct file_list *fuzzy_dirlist[MAX_BASIS_DIRS+1];
         static int need_fuzzy_dirlist = 0;          static int need_fuzzy_dirlist = 0;
         struct file_struct *fuzzy_file = NULL;          struct file_struct *fuzzy_file = NULL;
         int fd = -1, f_copy = -1;          int fd = -1, f_copy = -1;
Line 1316  static void recv_generator(char *fname, struct file_st Line 1188  static void recv_generator(char *fname, struct file_st
                    : inc_recurse && ndx != cur_flist->ndx_start - 1 ? -1                     : inc_recurse && ndx != cur_flist->ndx_start - 1 ? -1
                    : 1;                     : 1;
   
        if (verbose > 2)        if (DEBUG_GTE(GENR, 1))
                 rprintf(FINFO, "recv_generator(%s,%d)\n", fname, ndx);                  rprintf(FINFO, "recv_generator(%s,%d)\n", fname, ndx);
   
         if (list_only) {          if (list_only) {
Line 1340  static void recv_generator(char *fname, struct file_st Line 1212  static void recv_generator(char *fname, struct file_st
                 skip_dir = NULL;                  skip_dir = NULL;
         }          }
   
#ifdef SUPPORT_ACLS        init_stat_x(&sx);
        sx.acc_acl = sx.def_acl = NULL; 
#endif 
#ifdef SUPPORT_XATTRS 
        sx.xattr = NULL; 
#endif 
         if (daemon_filter_list.head && (*fname != '.' || fname[1])) {          if (daemon_filter_list.head && (*fname != '.' || fname[1])) {
                 if (check_filter(&daemon_filter_list, FLOG, fname, is_dir) < 0) {                  if (check_filter(&daemon_filter_list, FLOG, fname, is_dir) < 0) {
                         if (is_dir < 0)                          if (is_dir < 0)
Line 1364  static void recv_generator(char *fname, struct file_st Line 1231  static void recv_generator(char *fname, struct file_st
         }          }
   
         if (dry_run > 1 || (dry_missing_dir && is_below(file, dry_missing_dir))) {          if (dry_run > 1 || (dry_missing_dir && is_below(file, dry_missing_dir))) {
                   int i;
           parent_is_dry_missing:            parent_is_dry_missing:
                if (fuzzy_dirlist) {                for (i = 0; i < fuzzy_basis; i++) {
                        flist_free(fuzzy_dirlist);                        if (fuzzy_dirlist[i]) {
                        fuzzy_dirlist = NULL;                                flist_free(fuzzy_dirlist[i]);
                                 fuzzy_dirlist[i] = NULL;
                         }
                 }                  }
                 parent_dirname = "";                  parent_dirname = "";
                 statret = -1;                  statret = -1;
Line 1380  static void recv_generator(char *fname, struct file_st Line 1250  static void recv_generator(char *fname, struct file_st
                          && do_stat(dn, &sx.st) < 0) {                           && do_stat(dn, &sx.st) < 0) {
                                 if (dry_run)                                  if (dry_run)
                                         goto parent_is_dry_missing;                                          goto parent_is_dry_missing;
                                if (create_directory_path(fname) < 0) {                                if (make_path(fname, MKP_DROP_NAME | MKP_SKIP_SLASH) < 0) {
                                         rsyserr(FERROR_XFER, errno,                                          rsyserr(FERROR_XFER, errno,
                                                 "recv_generator: mkdir %s failed",                                                  "recv_generator: mkdir %s failed",
                                                 full_fname(dn));                                                  full_fname(dn));
                                 }                                  }
                         }                          }
                        if (fuzzy_dirlist) {                        if (fuzzy_basis) {
                                flist_free(fuzzy_dirlist);                                int i;
                                fuzzy_dirlist = NULL;                                for (i = 0; i < fuzzy_basis; i++) {
                        }                                        if (fuzzy_dirlist[i]) {
                        if (fuzzy_basis)                                                flist_free(fuzzy_dirlist[i]);
                                                 fuzzy_dirlist[i] = NULL;
                                         }
                                 }
                                 need_fuzzy_dirlist = 1;                                  need_fuzzy_dirlist = 1;
                           }
 #ifdef SUPPORT_ACLS  #ifdef SUPPORT_ACLS
                         if (!preserve_perms)                          if (!preserve_perms)
                                 dflt_perms = default_perms_for_dir(dn);                                  dflt_perms = default_perms_for_dir(dn);
Line 1400  static void recv_generator(char *fname, struct file_st Line 1274  static void recv_generator(char *fname, struct file_st
                 parent_dirname = dn;                  parent_dirname = dn;
   
                 if (need_fuzzy_dirlist && S_ISREG(file->mode)) {                  if (need_fuzzy_dirlist && S_ISREG(file->mode)) {
                           int i;
                         strlcpy(fnamecmpbuf, dn, sizeof fnamecmpbuf);                          strlcpy(fnamecmpbuf, dn, sizeof fnamecmpbuf);
                        fuzzy_dirlist = get_dirlist(fnamecmpbuf, -1, GDL_IGNORE_FILTER_RULES);                        for (i = 0; i < fuzzy_basis; i++) {
                                 if (i && pathjoin(fnamecmpbuf, MAXPATHLEN, basis_dir[i-1], dn) >= MAXPATHLEN)
                                         continue;
                                 fuzzy_dirlist[i] = get_dirlist(fnamecmpbuf, -1, GDL_IGNORE_FILTER_RULES);
                                 if (fuzzy_dirlist[i] && fuzzy_dirlist[i]->used == 0) {
                                         flist_free(fuzzy_dirlist[i]);
                                         fuzzy_dirlist[i] = NULL;
                                 }
                         }
                         need_fuzzy_dirlist = 0;                          need_fuzzy_dirlist = 0;
                 }                  }
   
Line 1409  static void recv_generator(char *fname, struct file_st Line 1292  static void recv_generator(char *fname, struct file_st
                 stat_errno = errno;                  stat_errno = errno;
         }          }
   
           if (missing_args == 2 && file->mode == 0) {
                   if (filter_list.head && check_filter(&filter_list, FINFO, fname, is_dir) < 0)
                           return;
                   if (statret == 0)
                           delete_item(fname, sx.st.st_mode, del_opts);
                   return;
           }
   
         if (ignore_non_existing > 0 && statret == -1 && stat_errno == ENOENT) {          if (ignore_non_existing > 0 && statret == -1 && stat_errno == ENOENT) {
                 if (is_dir) {                  if (is_dir) {
                         if (is_dir < 0)                          if (is_dir < 0)
Line 1420  static void recv_generator(char *fname, struct file_st Line 1311  static void recv_generator(char *fname, struct file_st
                 else if (F_IS_HLINKED(file))                  else if (F_IS_HLINKED(file))
                         handle_skipped_hlink(file, itemizing, code, f_out);                          handle_skipped_hlink(file, itemizing, code, f_out);
 #endif  #endif
                if (verbose > 1) {                if (INFO_GTE(SKIP, 1)) {
                         rprintf(FINFO, "not creating new %s \"%s\"\n",                          rprintf(FINFO, "not creating new %s \"%s\"\n",
                                 is_dir ? "directory" : "file", fname);                                  is_dir ? "directory" : "file", fname);
                 }                  }
Line 1433  static void recv_generator(char *fname, struct file_st Line 1324  static void recv_generator(char *fname, struct file_st
   
         if (ignore_existing > 0 && statret == 0          if (ignore_existing > 0 && statret == 0
          && (!is_dir || !S_ISDIR(sx.st.st_mode))) {           && (!is_dir || !S_ISDIR(sx.st.st_mode))) {
                if (verbose > 1 && is_dir >= 0)                if (INFO_GTE(SKIP, 1) && is_dir >= 0)
                         rprintf(FINFO, "%s exists\n", fname);                          rprintf(FINFO, "%s exists\n", fname);
 #ifdef SUPPORT_HARD_LINKS  #ifdef SUPPORT_HARD_LINKS
                 if (F_IS_HLINKED(file))                  if (F_IS_HLINKED(file))
Line 1483  static void recv_generator(char *fname, struct file_st Line 1374  static void recv_generator(char *fname, struct file_st
                                 dry_missing_dir = file;                                  dry_missing_dir = file;
                         file->flags |= FLAG_MISSING_DIR;                          file->flags |= FLAG_MISSING_DIR;
                 }                  }
                   init_stat_x(&real_sx);
                   real_sx.st = sx.st;
                 real_ret = statret;                  real_ret = statret;
                 real_sx = sx;  
                 if (file->flags & FLAG_DIR_CREATED)                  if (file->flags & FLAG_DIR_CREATED)
                         statret = -1;                          statret = -1;
                 if (!preserve_perms) { /* See comment in non-dir code below. */                  if (!preserve_perms) { /* See comment in non-dir code below. */
Line 1509  static void recv_generator(char *fname, struct file_st Line 1401  static void recv_generator(char *fname, struct file_st
                 }                  }
                 if (real_ret != 0 && do_mkdir(fname,file->mode|added_perms) < 0 && errno != EEXIST) {                  if (real_ret != 0 && do_mkdir(fname,file->mode|added_perms) < 0 && errno != EEXIST) {
                         if (!relative_paths || errno != ENOENT                          if (!relative_paths || errno != ENOENT
                         || create_directory_path(fname) < 0                         || make_path(fname, MKP_DROP_NAME | MKP_SKIP_SLASH) < 0
                          || (do_mkdir(fname, file->mode|added_perms) < 0 && errno != EEXIST)) {                           || (do_mkdir(fname, file->mode|added_perms) < 0 && errno != EEXIST)) {
                                 rsyserr(FERROR_XFER, errno,                                  rsyserr(FERROR_XFER, errno,
                                         "recv_generator: mkdir %s failed",                                          "recv_generator: mkdir %s failed",
Line 1528  static void recv_generator(char *fname, struct file_st Line 1420  static void recv_generator(char *fname, struct file_st
                         copy_xattrs(fnamecmpbuf, fname);                          copy_xattrs(fnamecmpbuf, fname);
 #endif  #endif
                 if (set_file_attrs(fname, file, real_ret ? NULL : &real_sx, NULL, 0)                  if (set_file_attrs(fname, file, real_ret ? NULL : &real_sx, NULL, 0)
                    && verbose && code != FNONE && f_out != -1)                    && INFO_GTE(NAME, 1) && code != FNONE && f_out != -1)
                         rprintf(code, "%s/\n", fname);                          rprintf(code, "%s/\n", fname);
   
                 /* We need to ensure that the dirs in the transfer have both                  /* We need to ensure that the dirs in the transfer have both
Line 1584  static void recv_generator(char *fname, struct file_st Line 1476  static void recv_generator(char *fname, struct file_st
 #ifdef SUPPORT_LINKS  #ifdef SUPPORT_LINKS
                 const char *sl = F_SYMLINK(file);                  const char *sl = F_SYMLINK(file);
                 if (safe_symlinks && unsafe_symlink(sl, fname)) {                  if (safe_symlinks && unsafe_symlink(sl, fname)) {
                        if (verbose) {                        if (INFO_GTE(NAME, 1)) {
                                 if (solo_file) {                                  if (solo_file) {
                                         /* fname contains the destination path, but we                                          /* fname contains the destination path, but we
                                          * want to report the source path. */                                           * want to report the source path. */
Line 1600  static void recv_generator(char *fname, struct file_st Line 1492  static void recv_generator(char *fname, struct file_st
                         char lnk[MAXPATHLEN];                          char lnk[MAXPATHLEN];
                         int len;                          int len;
   
                        if (!S_ISLNK(sx.st.st_mode))                        if (S_ISLNK(sx.st.st_mode)
                                statret = -1;                         && (len = do_readlink(fname, lnk, MAXPATHLEN-1)) > 0
                        else if ((len = readlink(fname, lnk, MAXPATHLEN-1)) > 0                         && strncmp(lnk, sl, len) == 0 && sl[len] == '\0') {
                              && strncmp(lnk, sl, len) == 0 && sl[len] == '\0') { 
                                 /* The link is pointing to the right place. */                                  /* The link is pointing to the right place. */
                                 set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT);                                  set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT);
                                 if (itemizing)                                  if (itemizing)
Line 1616  static void recv_generator(char *fname, struct file_st Line 1507  static void recv_generator(char *fname, struct file_st
                                         goto return_with_success;                                          goto return_with_success;
                                 goto cleanup;                                  goto cleanup;
                         }                          }
                         /* Not the right symlink (or not a symlink), so  
                          * delete it. */  
                         if (delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_SYMLINK) != 0)  
                                 goto cleanup;  
                 } else if (basis_dir[0] != NULL) {                  } else if (basis_dir[0] != NULL) {
                         int j = try_dests_non(file, fname, ndx, fnamecmpbuf, &sx,                          int j = try_dests_non(file, fname, ndx, fnamecmpbuf, &sx,
                                               itemizing, code);                                                itemizing, code);
Line 1636  static void recv_generator(char *fname, struct file_st Line 1523  static void recv_generator(char *fname, struct file_st
                         } else if (j >= 0)                          } else if (j >= 0)
                                 statret = 1;                                  statret = 1;
                 }                  }
#ifdef SUPPORT_HARD_LINKS                if (atomic_create(file, fname, sl, MAKEDEV(0, 0), &sx, statret == 0 ? DEL_FOR_SYMLINK : 0)) {
                if (preserve_hard_links && F_HLINK_NOT_LAST(file)) { 
                        cur_flist->in_progress++; 
                        goto cleanup; 
                } 
#endif 
                if (do_symlink(sl, fname) != 0) { 
                        rsyserr(FERROR_XFER, errno, "symlink %s -> \"%s\" failed", 
                                full_fname(fname), sl); 
                } else { 
                         set_file_attrs(fname, file, NULL, NULL, 0);                          set_file_attrs(fname, file, NULL, NULL, 0);
                         if (itemizing) {                          if (itemizing) {
                                   if (statret == 0 && !S_ISLNK(sx.st.st_mode))
                                           statret = -1;
                                 itemize(fname, file, ndx, statret, &sx,                                  itemize(fname, file, ndx, statret, &sx,
                                         ITEM_LOCAL_CHANGE|ITEM_REPORT_CHANGE, 0, NULL);                                          ITEM_LOCAL_CHANGE|ITEM_REPORT_CHANGE, 0, NULL);
                         }                          }
                        if (code != FNONE && verbose)                        if (code != FNONE && INFO_GTE(NAME, 1))
                                 rprintf(code, "%s -> %s\n", fname, sl);                                  rprintf(code, "%s -> %s\n", fname, sl);
 #ifdef SUPPORT_HARD_LINKS  #ifdef SUPPORT_HARD_LINKS
                         if (preserve_hard_links && F_IS_HLINKED(file))                          if (preserve_hard_links && F_IS_HLINKED(file))
Line 1670  static void recv_generator(char *fname, struct file_st Line 1550  static void recv_generator(char *fname, struct file_st
         if ((am_root && preserve_devices && IS_DEVICE(file->mode))          if ((am_root && preserve_devices && IS_DEVICE(file->mode))
          || (preserve_specials && IS_SPECIAL(file->mode))) {           || (preserve_specials && IS_SPECIAL(file->mode))) {
                 dev_t rdev;                  dev_t rdev;
                   int del_for_flag = 0;
                 if (IS_DEVICE(file->mode)) {                  if (IS_DEVICE(file->mode)) {
                         uint32 *devp = F_RDEV_P(file);                          uint32 *devp = F_RDEV_P(file);
                         rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));                          rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
                 } else                  } else
                         rdev = 0;                          rdev = 0;
                 if (statret == 0) {                  if (statret == 0) {
                         int del_for_flag;  
                         if (IS_DEVICE(file->mode)) {                          if (IS_DEVICE(file->mode)) {
                                 if (!IS_DEVICE(sx.st.st_mode))                                  if (!IS_DEVICE(sx.st.st_mode))
                                         statret = -1;                                          statret = -1;
Line 1701  static void recv_generator(char *fname, struct file_st Line 1581  static void recv_generator(char *fname, struct file_st
                                         goto return_with_success;                                          goto return_with_success;
                                 goto cleanup;                                  goto cleanup;
                         }                          }
                         if (delete_item(fname, sx.st.st_mode, del_opts | del_for_flag) != 0)  
                                 goto cleanup;  
                 } else if (basis_dir[0] != NULL) {                  } else if (basis_dir[0] != NULL) {
                         int j = try_dests_non(file, fname, ndx, fnamecmpbuf, &sx,                          int j = try_dests_non(file, fname, ndx, fnamecmpbuf, &sx,
                                               itemizing, code);                                                itemizing, code);
Line 1719  static void recv_generator(char *fname, struct file_st Line 1597  static void recv_generator(char *fname, struct file_st
                         } else if (j >= 0)                          } else if (j >= 0)
                                 statret = 1;                                  statret = 1;
                 }                  }
#ifdef SUPPORT_HARD_LINKS                if (DEBUG_GTE(GENR, 1)) {
                if (preserve_hard_links && F_HLINK_NOT_LAST(file)) { 
                        cur_flist->in_progress++; 
                        goto cleanup; 
                } 
#endif 
                if (verbose > 2) { 
                         rprintf(FINFO, "mknod(%s, 0%o, [%ld,%ld])\n",                          rprintf(FINFO, "mknod(%s, 0%o, [%ld,%ld])\n",
                                 fname, (int)file->mode,                                  fname, (int)file->mode,
                                 (long)major(rdev), (long)minor(rdev));                                  (long)major(rdev), (long)minor(rdev));
                 }                  }
                if (do_mknod(fname, file->mode, rdev) < 0) {                if (atomic_create(file, fname, NULL, rdev, &sx, del_for_flag)) {
                        rsyserr(FERROR_XFER, errno, "mknod %s failed", 
                                full_fname(fname)); 
                } else { 
                         set_file_attrs(fname, file, NULL, NULL, 0);                          set_file_attrs(fname, file, NULL, NULL, 0);
                         if (itemizing) {                          if (itemizing) {
                                 itemize(fname, file, ndx, statret, &sx,                                  itemize(fname, file, ndx, statret, &sx,
                                         ITEM_LOCAL_CHANGE|ITEM_REPORT_CHANGE, 0, NULL);                                          ITEM_LOCAL_CHANGE|ITEM_REPORT_CHANGE, 0, NULL);
                         }                          }
                        if (code != FNONE && verbose)                        if (code != FNONE && INFO_GTE(NAME, 1))
                                 rprintf(code, "%s\n", fname);                                  rprintf(code, "%s\n", fname);
 #ifdef SUPPORT_HARD_LINKS  #ifdef SUPPORT_HARD_LINKS
                         if (preserve_hard_links && F_IS_HLINKED(file))                          if (preserve_hard_links && F_IS_HLINKED(file))
Line 1758  static void recv_generator(char *fname, struct file_st Line 1627  static void recv_generator(char *fname, struct file_st
                 goto cleanup;                  goto cleanup;
         }          }
   
        if (max_size > 0 && F_LENGTH(file) > max_size) {        if (max_size >= 0 && F_LENGTH(file) > max_size) {
                if (verbose > 1) {                if (INFO_GTE(SKIP, 1)) {
                         if (solo_file)                          if (solo_file)
                                 fname = f_name(file, NULL);                                  fname = f_name(file, NULL);
                         rprintf(FINFO, "%s is over max-size\n", fname);                          rprintf(FINFO, "%s is over max-size\n", fname);
                 }                  }
                 goto cleanup;                  goto cleanup;
         }          }
        if (min_size > 0 && F_LENGTH(file) < min_size) {        if (min_size >= 0 && F_LENGTH(file) < min_size) {
                if (verbose > 1) {                if (INFO_GTE(SKIP, 1)) {
                         if (solo_file)                          if (solo_file)
                                 fname = f_name(file, NULL);                                  fname = f_name(file, NULL);
                         rprintf(FINFO, "%s is under min-size\n", fname);                          rprintf(FINFO, "%s is under min-size\n", fname);
Line 1777  static void recv_generator(char *fname, struct file_st Line 1646  static void recv_generator(char *fname, struct file_st
   
         if (update_only > 0 && statret == 0          if (update_only > 0 && statret == 0
             && cmp_time(sx.st.st_mtime, file->modtime) > 0) {              && cmp_time(sx.st.st_mtime, file->modtime) > 0) {
                if (verbose > 1)                if (INFO_GTE(SKIP, 1))
                         rprintf(FINFO, "%s is newer\n", fname);                          rprintf(FINFO, "%s is newer\n", fname);
 #ifdef SUPPORT_HARD_LINKS  #ifdef SUPPORT_HARD_LINKS
                 if (F_IS_HLINKED(file))                  if (F_IS_HLINKED(file))
Line 1795  static void recv_generator(char *fname, struct file_st Line 1664  static void recv_generator(char *fname, struct file_st
                 stat_errno = ENOENT;                  stat_errno = ENOENT;
         }          }
   
        if (statret != 0 && basis_dir[0] != NULL) {        if (basis_dir[0] != NULL && (statret != 0 || !copy_dest)) {
                 int j = try_dests_reg(file, fname, ndx, fnamecmpbuf, &sx,                  int j = try_dests_reg(file, fname, ndx, fnamecmpbuf, &sx,
                                      itemizing, code);                                      statret == 0, itemizing, code);
                 if (j == -2) {                  if (j == -2) {
                         if (remove_source_files == 1)                          if (remove_source_files == 1)
                                 goto return_with_success;                                  goto return_with_success;
Line 1810  static void recv_generator(char *fname, struct file_st Line 1679  static void recv_generator(char *fname, struct file_st
                 }                  }
         }          }
   
           init_stat_x(&real_sx);
           real_sx.st = sx.st; /* Don't copy xattr/acl pointers, as they would free wrong. */
         real_ret = statret;          real_ret = statret;
         real_sx = sx;  
   
         if (partial_dir && (partialptr = partial_dir_fname(fname)) != NULL          if (partial_dir && (partialptr = partial_dir_fname(fname)) != NULL
             && link_stat(partialptr, &partial_st, 0) == 0              && link_stat(partialptr, &partial_st, 0) == 0
Line 1821  static void recv_generator(char *fname, struct file_st Line 1691  static void recv_generator(char *fname, struct file_st
         } else          } else
                 partialptr = NULL;                  partialptr = NULL;
   
        if (statret != 0 && fuzzy_dirlist) {        if (statret != 0 && fuzzy_basis) {
                int j = find_fuzzy(file, fuzzy_dirlist);                /* Sets fnamecmp_type to FNAMECMP_FUZZY or above. */
                if (j >= 0) {                fuzzy_file = find_fuzzy(file, fuzzy_dirlist, &fnamecmp_type);
                        fuzzy_file = fuzzy_dirlist->files[j];                if (fuzzy_file) {
                         f_name(fuzzy_file, fnamecmpbuf);                          f_name(fuzzy_file, fnamecmpbuf);
                        if (verbose > 2) {                        if (DEBUG_GTE(FUZZY, 1)) {
                                 rprintf(FINFO, "fuzzy basis selected for %s: %s\n",                                  rprintf(FINFO, "fuzzy basis selected for %s: %s\n",
                                         fname, fnamecmpbuf);                                          fname, fnamecmpbuf);
                         }                          }
                         sx.st.st_size = F_LENGTH(fuzzy_file);                          sx.st.st_size = F_LENGTH(fuzzy_file);
                         statret = 0;                          statret = 0;
                         fnamecmp = fnamecmpbuf;                          fnamecmp = fnamecmpbuf;
                         fnamecmp_type = FNAMECMP_FUZZY;  
                 }                  }
         }          }
   
Line 1900  static void recv_generator(char *fname, struct file_st Line 1769  static void recv_generator(char *fname, struct file_st
                                 goto cleanup;                                  goto cleanup;
                         if (!(back_file = make_file(fname, NULL, NULL, 0, NO_FILTERS)))                          if (!(back_file = make_file(fname, NULL, NULL, 0, NO_FILTERS)))
                                 goto pretend_missing;                                  goto pretend_missing;
                        if (copy_file(fname, backupptr, -1, back_file->mode, 1) < 0) {                        if (copy_file(fname, backupptr, -1, back_file->mode) < 0) {
                                 unmake_file(back_file);                                  unmake_file(back_file);
                                 back_file = NULL;                                  back_file = NULL;
                                 goto cleanup;                                  goto cleanup;
Line 1909  static void recv_generator(char *fname, struct file_st Line 1778  static void recv_generator(char *fname, struct file_st
                 goto notify_others;                  goto notify_others;
         }          }
   
        if (fuzzy_dirlist) {        if (fuzzy_dirlist[0]) {
                int j = flist_find(fuzzy_dirlist, file);                int j = flist_find(fuzzy_dirlist[0], file);
                 if (j >= 0) /* don't use changing file as future fuzzy basis */                  if (j >= 0) /* don't use changing file as future fuzzy basis */
                        fuzzy_dirlist->files[j]->flags |= FLAG_FILE_SENT;                        fuzzy_dirlist[0]->files[j]->flags |= FLAG_FILE_SENT;
         }          }
   
         /* open the file */          /* open the file */
Line 1949  static void recv_generator(char *fname, struct file_st Line 1818  static void recv_generator(char *fname, struct file_st
                         goto cleanup;                          goto cleanup;
                 }                  }
                 if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0) {                  if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0) {
                        int save_errno = errno ? errno : EINVAL; /* 0 paranoia */                        rsyserr(FERROR_XFER, errno, "open %s", full_fname(backupptr));
                        if (errno == ENOENT && make_bak_dir(backupptr) == 0) {                        unmake_file(back_file);
                                if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0)                        back_file = NULL;
                                        save_errno = errno ? errno : save_errno;                        close(fd);
                                else                        goto cleanup;
                                        save_errno = 0; 
                        } 
                        if (save_errno) { 
                                rsyserr(FERROR_XFER, save_errno, "open %s", full_fname(backupptr)); 
                                unmake_file(back_file); 
                                back_file = NULL; 
                                close(fd); 
                                goto cleanup; 
                        } 
                 }                  }
                 fnamecmp_type = FNAMECMP_BACKUP;                  fnamecmp_type = FNAMECMP_BACKUP;
         }          }
   
        if (verbose > 3) {        if (DEBUG_GTE(DELTASUM, 3)) {
                rprintf(FINFO, "gen mapped %s of size %.0f\n",                rprintf(FINFO, "gen mapped %s of size %s\n",
                        fnamecmp, (double)sx.st.st_size);                        fnamecmp, big_num(sx.st.st_size));
         }          }
   
        if (verbose > 2)        if (DEBUG_GTE(DELTASUM, 2))
                 rprintf(FINFO, "generating and sending sums for %d\n", ndx);                  rprintf(FINFO, "generating and sending sums for %d\n", ndx);
   
   notify_others:    notify_others:
         if (remove_source_files && !delay_updates && !phase && !dry_run)          if (remove_source_files && !delay_updates && !phase && !dry_run)
                 increment_active_files(ndx, itemizing, code);                  increment_active_files(ndx, itemizing, code);
        if (inc_recurse && !dry_run)        if (inc_recurse && (!dry_run || write_batch < 0))
                 cur_flist->in_progress++;                  cur_flist->in_progress++;
 #ifdef SUPPORT_HARD_LINKS  #ifdef SUPPORT_HARD_LINKS
         if (preserve_hard_links && F_IS_HLINKED(file))          if (preserve_hard_links && F_IS_HLINKED(file))
Line 1991  static void recv_generator(char *fname, struct file_st Line 1851  static void recv_generator(char *fname, struct file_st
                         iflags |= ITEM_REPORT_CHANGE;                          iflags |= ITEM_REPORT_CHANGE;
                 if (fnamecmp_type != FNAMECMP_FNAME)                  if (fnamecmp_type != FNAMECMP_FNAME)
                         iflags |= ITEM_BASIS_TYPE_FOLLOWS;                          iflags |= ITEM_BASIS_TYPE_FOLLOWS;
                if (fnamecmp_type == FNAMECMP_FUZZY)                if (fnamecmp_type >= FNAMECMP_FUZZY)
                         iflags |= ITEM_XNAME_FOLLOWS;                          iflags |= ITEM_XNAME_FOLLOWS;
                 itemize(fnamecmp, file, -1, real_ret, &real_sx, iflags, fnamecmp_type,                  itemize(fnamecmp, file, -1, real_ret, &real_sx, iflags, fnamecmp_type,
                         fuzzy_file ? fuzzy_file->basename : NULL);                          fuzzy_file ? fuzzy_file->basename : NULL);
#ifdef SUPPORT_ACLS                free_stat_x(&real_sx);
                if (preserve_acls) 
                        free_acl(&real_sx); 
#endif 
#ifdef SUPPORT_XATTRS 
                if (preserve_xattrs) 
                        free_xattr(&real_sx); 
#endif 
         }          }
   
         if (!do_xfers) {          if (!do_xfers) {
Line 2043  static void recv_generator(char *fname, struct file_st Line 1896  static void recv_generator(char *fname, struct file_st
 #endif  #endif
                 set_file_attrs(backupptr, back_file, NULL, NULL, 0);                  set_file_attrs(backupptr, back_file, NULL, NULL, 0);
                 preserve_xattrs = save_preserve_xattrs;                  preserve_xattrs = save_preserve_xattrs;
                if (verbose > 1) {                if (INFO_GTE(BACKUP, 1)) {
                         rprintf(FINFO, "backed up %s to %s\n",                          rprintf(FINFO, "backed up %s to %s\n",
                                 fname, backupptr);                                  fname, backupptr);
                 }                  }
                 unmake_file(back_file);                  unmake_file(back_file);
         }          }
   
#ifdef SUPPORT_ACLS        free_stat_x(&sx);
        if (preserve_acls)}
                free_acl(&sx);
 /* If we are replacing an existing hard link, symlink, device, or special file,
  * create a temp-name item and rename it into place.  Only a symlink or hard
  * link puts a non-NULL value into the lnk arg.  Only a device puts a non-0
  * value into the rdev arg.  Specify 0 for the del_for_flag if there is not a
  * file to replace.  This returns 1 on success and 0 on failure. */
 int atomic_create(struct file_struct *file, char *fname, const char *lnk,
                   dev_t rdev, stat_x *sxp, int del_for_flag)
 {
         char tmpname[MAXPATHLEN];
         const char *create_name;
         int skip_atomic, dir_in_the_way = del_for_flag && S_ISDIR(sxp->st.st_mode);
 
         if (!del_for_flag || dir_in_the_way || tmpdir || !get_tmpname(tmpname, fname, True))
                 skip_atomic = 1;
         else
                 skip_atomic = 0;
 
         if (del_for_flag) {
                 if (make_backups > 0 && !dir_in_the_way) {
                         if (!make_backup(fname, skip_atomic))
                                 return 0;
                 } else if (skip_atomic) {
                         int del_opts = delete_mode || force_delete ? DEL_RECURSE : 0;
                         if (delete_item(fname, sxp->st.st_mode, del_opts | del_for_flag) != 0)
                                 return 0;
                 }
         }
 
         create_name = skip_atomic ? fname : tmpname;
 
         if (lnk) {
 #ifdef SUPPORT_LINKS
                 if (S_ISLNK(file->mode)
 #ifdef SUPPORT_HARD_LINKS /* The first symlink in a hard-linked cluster is always created. */
                  && (!F_IS_HLINKED(file) || file->flags & FLAG_HLINK_FIRST)
 #endif  #endif
#ifdef SUPPORT_XATTRS                 ) {
        if (preserve_xattrs)                        if (do_symlink(lnk, create_name) < 0) {
                free_xattr(&sx);                                rsyserr(FERROR_XFER, errno, "symlink %s -> \"%s\" failed",
                                         full_fname(create_name), lnk);
                                 return 0;
                         }
                 } else
 #endif  #endif
        return;#ifdef SUPPORT_HARD_LINKS
                 if (!hard_link_one(file, create_name, lnk, 0))
                         return 0;
 #endif
         } else {
                 if (do_mknod(create_name, file->mode, rdev) < 0) {
                         rsyserr(FERROR_XFER, errno, "mknod %s failed",
                                 full_fname(create_name));
                         return 0;
                 }
         }
 
         if (!skip_atomic) {
                 if (do_rename(tmpname, fname) < 0) {
                         rsyserr(FERROR_XFER, errno, "rename %s -> \"%s\" failed",
                                 full_fname(tmpname), full_fname(fname));
                         do_unlink(tmpname);
                         return 0;
                 }
         }
 
         return 1;
 }  }
   
 #ifdef SUPPORT_HARD_LINKS  #ifdef SUPPORT_HARD_LINKS
Line 2104  static void touch_up_dirs(struct file_list *flist, int Line 2017  static void touch_up_dirs(struct file_list *flist, int
                 if (!S_ISDIR(file->mode)                  if (!S_ISDIR(file->mode)
                  || (!implied_dirs && file->flags & FLAG_IMPLIED_DIR))                   || (!implied_dirs && file->flags & FLAG_IMPLIED_DIR))
                         continue;                          continue;
                if (verbose > 3) {                if (DEBUG_GTE(TIME, 2)) {
                         fname = f_name(file, NULL);                          fname = f_name(file, NULL);
                         rprintf(FINFO, "touch_up_dirs: %s (%d)\n",                          rprintf(FINFO, "touch_up_dirs: %s (%d)\n",
                                 NS(fname), i);                                  NS(fname), i);
Line 2121  static void touch_up_dirs(struct file_list *flist, int Line 2034  static void touch_up_dirs(struct file_list *flist, int
                         STRUCT_STAT st;                          STRUCT_STAT st;
                         if (link_stat(fname, &st, 0) == 0                          if (link_stat(fname, &st, 0) == 0
                          && cmp_time(st.st_mtime, file->modtime) != 0)                           && cmp_time(st.st_mtime, file->modtime) != 0)
                                set_modtime(fname, file->modtime, file->mode);                                set_modtime(fname, file->modtime, F_MOD_NSEC(file), file->mode);
                 }                  }
                 if (counter >= loopchk_limit) {                  if (counter >= loopchk_limit) {
                         if (allowed_lull)                          if (allowed_lull)
                                maybe_send_keepalive();                                maybe_send_keepalive(time(NULL), MSK_ALLOW_FLUSH);
                         else                          else
                                 maybe_flush_socket(0);                                  maybe_flush_socket(0);
                         counter = 0;                          counter = 0;
Line 2159  void check_for_finished_files(int itemizing, enum logc Line 2072  void check_for_finished_files(int itemizing, enum logc
 #endif  #endif
   
                 if (check_redo && (ndx = get_redo_num()) != -1) {                  if (check_redo && (ndx = get_redo_num()) != -1) {
                           OFF_T save_max_size = max_size;
                           OFF_T save_min_size = min_size;
                         csum_length = SUM_LENGTH;                          csum_length = SUM_LENGTH;
                        max_size = -max_size;                        max_size = -1;
                        min_size = -min_size;                        min_size = -1;
                         ignore_existing = -ignore_existing;                          ignore_existing = -ignore_existing;
                         ignore_non_existing = -ignore_non_existing;                          ignore_non_existing = -ignore_non_existing;
                         update_only = -update_only;                          update_only = -update_only;
Line 2185  void check_for_finished_files(int itemizing, enum logc Line 2100  void check_for_finished_files(int itemizing, enum logc
                         cur_flist = flist;                          cur_flist = flist;
   
                         csum_length = SHORT_SUM_LENGTH;                          csum_length = SHORT_SUM_LENGTH;
                        max_size = -max_size;                        max_size = save_max_size;
                        min_size = -min_size;                        min_size = save_min_size;
                         ignore_existing = -ignore_existing;                          ignore_existing = -ignore_existing;
                         ignore_non_existing = -ignore_non_existing;                          ignore_non_existing = -ignore_non_existing;
                         update_only = -update_only;                          update_only = -update_only;
Line 2206  void check_for_finished_files(int itemizing, enum logc Line 2121  void check_for_finished_files(int itemizing, enum logc
                         break;                          break;
   
                 write_ndx(sock_f_out, NDX_DONE);                  write_ndx(sock_f_out, NDX_DONE);
                if (!read_batch)                if (!read_batch && !flist_eof) {
                        maybe_flush_socket(1);                        int old_total = 0;
                         for (flist = first_flist; flist != cur_flist; flist = flist->next)
                                 old_total += flist->used;
                         maybe_flush_socket(!flist_eof && file_total - old_total < MIN_FILECNT_LOOKAHEAD/2);
                 }
   
                 if (delete_during == 2 || !dir_tweaking) {                  if (delete_during == 2 || !dir_tweaking) {
                         /* Skip directory touch-up. */                          /* Skip directory touch-up. */
Line 2224  void generate_files(int f_out, const char *local_name) Line 2143  void generate_files(int f_out, const char *local_name)
         char fbuf[MAXPATHLEN];          char fbuf[MAXPATHLEN];
         int itemizing;          int itemizing;
         enum logcode code;          enum logcode code;
        int save_do_progress = do_progress;        int save_info_flist = info_levels[INFO_FLIST];
         int save_info_progress = info_levels[INFO_PROGRESS];
   
         if (protocol_version >= 29) {          if (protocol_version >= 29) {
                 itemizing = 1;                  itemizing = 1;
Line 2251  void generate_files(int f_out, const char *local_name) Line 2171  void generate_files(int f_out, const char *local_name)
             | (protocol_version >= 30 || !am_server ? ITEM_REPORT_TIMEFAIL : 0);              | (protocol_version >= 30 || !am_server ? ITEM_REPORT_TIMEFAIL : 0);
         implied_dirs_are_missing = relative_paths && !implied_dirs && protocol_version < 30;          implied_dirs_are_missing = relative_paths && !implied_dirs && protocol_version < 30;
   
        if (verbose > 2)        if (DEBUG_GTE(GENR, 1))
                rprintf(FINFO, "generator starting pid=%ld\n", (long)getpid());                rprintf(FINFO, "generator starting pid=%d\n", (int)getpid());
   
         if (delete_before && !solo_file && cur_flist->used > 0)          if (delete_before && !solo_file && cur_flist->used > 0)
                 do_delete_pass();                  do_delete_pass();
Line 2262  void generate_files(int f_out, const char *local_name) Line 2182  void generate_files(int f_out, const char *local_name)
                 if (!deldelay_buf)                  if (!deldelay_buf)
                         out_of_memory("delete-delay");                          out_of_memory("delete-delay");
         }          }
        do_progress = 0;        info_levels[INFO_FLIST] = info_levels[INFO_PROGRESS] = 0;
   
         if (append_mode > 0 || whole_file < 0)          if (append_mode > 0 || whole_file < 0)
                 whole_file = 0;                  whole_file = 0;
        if (verbose >= 2) {        if (DEBUG_GTE(FLIST, 1)) {
                 rprintf(FINFO, "delta-transmission %s\n",                  rprintf(FINFO, "delta-transmission %s\n",
                         whole_file                          whole_file
                         ? "disabled for local transfer or --whole-file"                          ? "disabled for local transfer or --whole-file"
                         : "enabled");                          : "enabled");
         }          }
   
         /* Since we often fill up the outgoing socket and then just sit around  
          * waiting for the other 2 processes to do their thing, we don't want  
          * to exit on a timeout.  If the data stops flowing, the receiver will  
          * notice that and let us know via the message pipe (or its closing). */  
         ignore_timeout = 1;  
   
         dflt_perms = (ACCESSPERMS & ~orig_umask);          dflt_perms = (ACCESSPERMS & ~orig_umask);
   
         do {          do {
 #ifdef SUPPORT_HARD_LINKS  #ifdef SUPPORT_HARD_LINKS
                 if (preserve_hard_links && inc_recurse) {                  if (preserve_hard_links && inc_recurse) {
                        while (!flist_eof && file_total < FILECNT_LOOKAHEAD/2)                        while (!flist_eof && file_total < MIN_FILECNT_LOOKAHEAD/2)
                                 wait_for_receiver();                                  wait_for_receiver();
                 }                  }
 #endif  #endif
Line 2332  void generate_files(int f_out, const char *local_name) Line 2246  void generate_files(int f_out, const char *local_name)
   
                         if (i + cur_flist->ndx_start >= next_loopchk) {                          if (i + cur_flist->ndx_start >= next_loopchk) {
                                 if (allowed_lull)                                  if (allowed_lull)
                                        maybe_send_keepalive();                                        maybe_send_keepalive(time(NULL), MSK_ALLOW_FLUSH);
                                 else                                  else
                                         maybe_flush_socket(0);                                          maybe_flush_socket(0);
                                 next_loopchk += loopchk_limit;                                  next_loopchk += loopchk_limit;
Line 2355  void generate_files(int f_out, const char *local_name) Line 2269  void generate_files(int f_out, const char *local_name)
         if (delete_during)          if (delete_during)
                 delete_in_dir(NULL, NULL, &dev_zero);                  delete_in_dir(NULL, NULL, &dev_zero);
         phase++;          phase++;
        if (verbose > 2)        if (DEBUG_GTE(GENR, 1))
                 rprintf(FINFO, "generate_files phase=%d\n", phase);                  rprintf(FINFO, "generate_files phase=%d\n", phase);
   
         while (1) {          while (1) {
Line 2366  void generate_files(int f_out, const char *local_name) Line 2280  void generate_files(int f_out, const char *local_name)
         }          }
   
         phase++;          phase++;
        if (verbose > 2)        if (DEBUG_GTE(GENR, 1))
                 rprintf(FINFO, "generate_files phase=%d\n", phase);                  rprintf(FINFO, "generate_files phase=%d\n", phase);
   
         write_ndx(f_out, NDX_DONE);          write_ndx(f_out, NDX_DONE);
   
         /* Reduce round-trip lag-time for a useless delay-updates phase. */          /* Reduce round-trip lag-time for a useless delay-updates phase. */
        if (protocol_version >= 29 && !delay_updates)        if (protocol_version >= 29 && EARLY_DELAY_DONE_MSG())
                 write_ndx(f_out, NDX_DONE);                  write_ndx(f_out, NDX_DONE);
   
           if (protocol_version >= 31 && EARLY_DELETE_DONE_MSG()) {
                   if ((INFO_GTE(STATS, 2) && (delete_mode || force_delete)) || read_batch)
                           write_del_stats(f_out);
                   if (EARLY_DELAY_DONE_MSG()) /* Can't send this before delay */
                           write_ndx(f_out, NDX_DONE);
           }
   
         /* Read MSG_DONE for the redo phase (and any prior messages). */          /* Read MSG_DONE for the redo phase (and any prior messages). */
         while (1) {          while (1) {
                 check_for_finished_files(itemizing, code, 0);                  check_for_finished_files(itemizing, code, 0);
Line 2385  void generate_files(int f_out, const char *local_name) Line 2306  void generate_files(int f_out, const char *local_name)
   
         if (protocol_version >= 29) {          if (protocol_version >= 29) {
                 phase++;                  phase++;
                if (verbose > 2)                if (DEBUG_GTE(GENR, 1))
                         rprintf(FINFO, "generate_files phase=%d\n", phase);                          rprintf(FINFO, "generate_files phase=%d\n", phase);
                if (delay_updates)                if (!EARLY_DELAY_DONE_MSG()) {
                         write_ndx(f_out, NDX_DONE);                          write_ndx(f_out, NDX_DONE);
                           if (protocol_version >= 31 && EARLY_DELETE_DONE_MSG())
                                   write_ndx(f_out, NDX_DONE);
                   }
                 /* Read MSG_DONE for delay-updates phase & prior messages. */                  /* Read MSG_DONE for delay-updates phase & prior messages. */
                 while (msgdone_cnt == 2)                  while (msgdone_cnt == 2)
                         wait_for_receiver();                          wait_for_receiver();
         }          }
   
        do_progress = save_do_progress;        info_levels[INFO_FLIST] = save_info_flist;
         info_levels[INFO_PROGRESS] = save_info_progress;
 
         if (delete_during == 2)          if (delete_during == 2)
                 do_delayed_deletions(fbuf);                  do_delayed_deletions(fbuf);
         if (delete_after && !solo_file && file_total > 0)          if (delete_after && !solo_file && file_total > 0)
                 do_delete_pass();                  do_delete_pass();
   
        if ((need_retouch_dir_perms || need_retouch_dir_times)        if (max_delete >= 0 && skipped_deletes) {
         && dir_tweaking && (!inc_recurse || delete_during == 2)) 
                touch_up_dirs(dir_flist, -1); 
 
        if (max_delete >= 0 && deletion_count > max_delete) { 
                 rprintf(FWARNING,                  rprintf(FWARNING,
                         "Deletions stopped due to --max-delete limit (%d skipped)\n",                          "Deletions stopped due to --max-delete limit (%d skipped)\n",
                        deletion_count - max_delete);                        skipped_deletes);
                 io_error |= IOERR_DEL_LIMIT;                  io_error |= IOERR_DEL_LIMIT;
         }          }
   
        if (verbose > 2)        if (protocol_version >= 31) {
                 if (!EARLY_DELETE_DONE_MSG()) {
                         if (INFO_GTE(STATS, 2) || read_batch)
                                 write_del_stats(f_out);
                         write_ndx(f_out, NDX_DONE);
                 }
 
                 /* Read MSG_DONE for late-delete phase & prior messages. */
                 while (msgdone_cnt == 3)
                         wait_for_receiver();
         }
 
         if ((need_retouch_dir_perms || need_retouch_dir_times)
          && dir_tweaking && (!inc_recurse || delete_during == 2))
                 touch_up_dirs(dir_flist, -1);
 
         if (DEBUG_GTE(GENR, 1))
                 rprintf(FINFO, "generate_files finished\n");                  rprintf(FINFO, "generate_files finished\n");
 }  }

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


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