The patches for 3.0.1pre1.
authorWayne Davison <wayned@samba.org>
Tue, 25 Mar 2008 05:24:02 +0000 (22:24 -0700)
committerWayne Davison <wayned@samba.org>
Tue, 25 Mar 2008 05:24:02 +0000 (22:24 -0700)
35 files changed:
atimes.diff
backup-dir-dels.diff
catch_crash_signals.diff
checksum-reading.diff
checksum-updating.diff
checksum-xattr.diff
copy-devices.diff
crtimes.diff
cvs-entries.diff
date-only.diff
detect-renamed-lax.diff
detect-renamed.diff
downdate.diff
drop-cache.diff
fileflags.diff
fsync.diff
ignore-case.diff
link-by-hash.diff
log-checksum.diff
nameconverter.diff
omit-dir-changes.diff
openssl-support.diff
osx-create-time.diff [deleted file]
preallocate.diff
remote-option.diff [new file with mode: 0644]
slow-down.diff
slp.diff
source-backup.diff
source-filter_dest-filter.diff
sparse-block.diff [new file with mode: 0644]
stdout.diff
time-limit.diff
transliterate.diff
usermap.diff
xattrs.diff

index 9b60c91..8e0f0a9 100644 (file)
@@ -44,7 +44,7 @@ diff --git a/flist.c b/flist.c
  extern int relative_paths;
  extern int implied_dirs;
  extern int file_extra_cnt;
-@@ -344,7 +345,7 @@ int push_pathname(const char *dir, int len)
+@@ -379,7 +380,7 @@ int push_pathname(const char *dir, int len)
  
  static void send_file_entry(int f, struct file_struct *file, int ndx, int first_ndx)
  {
@@ -53,7 +53,7 @@ diff --git a/flist.c b/flist.c
        static mode_t mode;
  #ifdef SUPPORT_HARD_LINKS
        static int64 dev;
-@@ -452,6 +453,13 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
+@@ -487,6 +488,13 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
                xflags |= XMIT_SAME_TIME;
        else
                modtime = file->modtime;
@@ -67,7 +67,7 @@ diff --git a/flist.c b/flist.c
  
  #ifdef SUPPORT_HARD_LINKS
        if (tmp_dev != 0) {
-@@ -524,6 +532,8 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
+@@ -559,6 +567,8 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
        }
        if (!(xflags & XMIT_SAME_MODE))
                write_int(f, to_wire_mode(mode));
@@ -76,7 +76,7 @@ diff --git a/flist.c b/flist.c
        if (preserve_uid && !(xflags & XMIT_SAME_UID)) {
                if (protocol_version < 30)
                        write_int(f, uid);
-@@ -610,7 +620,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
+@@ -645,7 +655,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
  static struct file_struct *recv_file_entry(struct file_list *flist,
                                           int xflags, int f)
  {
@@ -85,7 +85,7 @@ diff --git a/flist.c b/flist.c
        static mode_t mode;
  #ifdef SUPPORT_HARD_LINKS
        static int64 dev;
-@@ -743,6 +753,16 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+@@ -778,6 +788,16 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
        }
        if (!(xflags & XMIT_SAME_MODE))
                mode = from_wire_mode(read_int(f));
@@ -102,7 +102,7 @@ diff --git a/flist.c b/flist.c
  
        if (chmod_modes && !S_ISLNK(mode))
                mode = tweak_mode(mode, chmod_modes);
-@@ -873,6 +893,8 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+@@ -907,6 +927,8 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                F_GROUP(file) = gid;
                file->flags |= gid_flags;
        }
@@ -111,7 +111,7 @@ diff --git a/flist.c b/flist.c
        if (unsort_ndx)
                F_NDX(file) = flist->used + flist->ndx_start;
  
-@@ -1205,6 +1227,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1244,6 +1266,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
                F_OWNER(file) = st.st_uid;
        if (gid_ndx) /* Check gid_ndx instead of preserve_gid for del support */
                F_GROUP(file) = st.st_gid;
@@ -131,9 +131,9 @@ diff --git a/generator.c b/generator.c
  
  extern int verbose;
  extern int dry_run;
-@@ -633,6 +634,9 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+@@ -642,6 +643,9 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+                : iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !(iflags & ITEM_MATCHED)
                  && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
-                || (keep_time && cmp_time(file->modtime, sxp->st.st_mtime) != 0))
                        iflags |= ITEM_REPORT_TIME;
 +              if (atimes_ndx && !S_ISDIR(file->mode) && !S_ISLNK(file->mode)
 +               && cmp_time(f_atime(file), sxp->st.st_atime) != 0)
@@ -141,7 +141,7 @@ diff --git a/generator.c b/generator.c
  #if !defined HAVE_LCHMOD && !defined HAVE_SETATTRLIST
                if (S_ISLNK(file->mode)) {
                        ;
-@@ -987,6 +991,8 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
+@@ -999,6 +1003,8 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
                if (link_dest) {
                        if (!hard_link_one(file, fname, cmpbuf, 1))
                                goto try_a_copy;
@@ -150,7 +150,7 @@ diff --git a/generator.c b/generator.c
                        if (preserve_hard_links && F_IS_HLINKED(file))
                                finish_hard_link(file, fname, ndx, &sxp->st, itemizing, code, j);
                        if (!maybe_ATTRS_REPORT && (verbose > 1 || stdout_format_has_i > 1)) {
-@@ -1173,6 +1179,7 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx,
+@@ -1184,6 +1190,7 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx,
  static void list_file_entry(struct file_struct *f)
  {
        char permbuf[PERMSTRING_SIZE];
@@ -158,7 +158,7 @@ diff --git a/generator.c b/generator.c
        double len;
  
        if (!F_IS_ACTIVE(f)) {
-@@ -1187,14 +1194,16 @@ static void list_file_entry(struct file_struct *f)
+@@ -1198,14 +1205,16 @@ static void list_file_entry(struct file_struct *f)
  
  #ifdef SUPPORT_LINKS
        if (preserve_links && S_ISLNK(f->mode)) {
@@ -177,20 +177,20 @@ diff --git a/generator.c b/generator.c
                        f_name(f, NULL));
        }
  }
-@@ -1950,7 +1959,7 @@ static void touch_up_dirs(struct file_list *flist, int ndx)
-               if (!(file->mode & S_IWUSR))
-                       do_chmod(fname, file->mode);
-               if (need_retouch_dir_times)
--                      set_modtime(fname, file->modtime, file->mode);
-+                      set_times(fname, file->modtime, file->modtime, file->mode);
+@@ -2009,7 +2018,7 @@ static void touch_up_dirs(struct file_list *flist, int ndx)
+                       STRUCT_STAT st;
+                       if (link_stat(fname, &st, 0) == 0
+                        && cmp_time(st.st_mtime, file->modtime) != 0)
+-                              set_modtime(fname, file->modtime, file->mode);
++                              set_times(fname, file->modtime, file->modtime, file->mode);
+               }
                if (allowed_lull && !(counter % lull_mod))
                        maybe_send_keepalive();
-               else if (!(counter & 0xFF))
 diff --git a/ifuncs.h b/ifuncs.h
 --- a/ifuncs.h
 +++ b/ifuncs.h
-@@ -57,6 +57,28 @@ from_wire_mode(int mode)
-       return mode;
+@@ -67,6 +67,28 @@ d_name(struct dirent *di)
+ #endif
  }
  
 +static inline time_t
@@ -221,7 +221,7 @@ diff --git a/ifuncs.h b/ifuncs.h
 diff --git a/log.c b/log.c
 --- a/log.c
 +++ b/log.c
-@@ -644,7 +644,8 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
+@@ -650,7 +650,8 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
                        c[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
                        c[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
                        c[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
@@ -234,7 +234,7 @@ diff --git a/log.c b/log.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -58,6 +58,7 @@ int preserve_specials = 0;
+@@ -59,6 +59,7 @@ int preserve_specials = 0;
  int preserve_uid = 0;
  int preserve_gid = 0;
  int preserve_times = 0;
@@ -242,7 +242,7 @@ diff --git a/options.c b/options.c
  int update_only = 0;
  int cvs_exclude = 0;
  int dry_run = 0;
-@@ -352,6 +353,7 @@ void usage(enum logcode F)
+@@ -353,6 +354,7 @@ void usage(enum logcode F)
    rprintf(F," -D                          same as --devices --specials\n");
    rprintf(F," -t, --times                 preserve modification times\n");
    rprintf(F," -O, --omit-dir-times        omit directories from --times\n");
@@ -250,7 +250,7 @@ diff --git a/options.c b/options.c
    rprintf(F,"     --super                 receiver attempts super-user activities\n");
  #ifdef SUPPORT_XATTRS
    rprintf(F,"     --fake-super            store/recover privileged attrs using xattrs\n");
-@@ -487,6 +489,9 @@ static struct poptOption long_options[] = {
+@@ -490,6 +492,9 @@ static struct poptOption long_options[] = {
    {"times",           't', POPT_ARG_VAL,    &preserve_times, 2, 0, 0 },
    {"no-times",         0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
    {"no-t",             0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
@@ -260,7 +260,7 @@ diff --git a/options.c b/options.c
    {"omit-dir-times",  'O', POPT_ARG_VAL,    &omit_dir_times, 1, 0, 0 },
    {"no-omit-dir-times",0,  POPT_ARG_VAL,    &omit_dir_times, 0, 0, 0 },
    {"no-O",             0,  POPT_ARG_VAL,    &omit_dir_times, 0, 0, 0 },
-@@ -1747,6 +1752,8 @@ void server_options(char **args, int *argc_p)
+@@ -1773,6 +1778,8 @@ void server_options(char **args, int *argc_p)
                argstr[x++] = 'D';
        if (preserve_times)
                argstr[x++] = 't';
@@ -272,7 +272,7 @@ diff --git a/options.c b/options.c
 diff --git a/rsync.c b/rsync.c
 --- a/rsync.c
 +++ b/rsync.c
-@@ -345,6 +345,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
+@@ -380,6 +380,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
        int updated = 0;
        stat_x sx2;
        int change_uid, change_gid;
@@ -280,7 +280,7 @@ diff --git a/rsync.c b/rsync.c
        mode_t new_mode = file->mode;
        int inherit;
  
-@@ -388,20 +389,39 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
+@@ -423,20 +424,38 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
                set_xattr(fname, file, fnamecmp, sxp);
  #endif
  
@@ -315,17 +315,15 @@ diff --git a/rsync.c b/rsync.c
                }
 -              if (ret == 0) /* ret == 1 if symlink could not be set */
 -                      updated = 1;
--              else if (receiver_symlink_times)
--                      file->flags |= FLAG_TIME_FAILED;
+-              else
 +              if (ret > 0) { /* ret == 1 if symlink could not be set */
 +                      updated = 0;
-+                      if (receiver_symlink_times)
-+                              file->flags |= FLAG_TIME_FAILED;
+                       file->flags |= FLAG_TIME_FAILED;
 +              }
        }
  
        change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
-@@ -531,7 +551,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
+@@ -566,7 +585,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
  
        /* Change permissions before putting the file into place. */
        set_file_attrs(fnametmp, file, NULL, fnamecmp,
@@ -334,7 +332,7 @@ diff --git a/rsync.c b/rsync.c
  
        /* move tmp file over real file */
        if (verbose > 2)
-@@ -558,7 +578,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
+@@ -593,7 +612,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
  
    do_set_file_attrs:
        set_file_attrs(fnametmp, file, NULL, fnamecmp,
@@ -354,7 +352,7 @@ diff --git a/rsync.h b/rsync.h
  
  /* These flags are used in the live flist data. */
  
-@@ -149,6 +150,7 @@
+@@ -151,6 +152,7 @@
  
  #define ATTRS_REPORT          (1<<0)
  #define ATTRS_SKIP_MTIME      (1<<1)
@@ -362,7 +360,7 @@ diff --git a/rsync.h b/rsync.h
  
  #define FULL_FLUSH    1
  #define NORMAL_FLUSH  0
-@@ -620,12 +622,14 @@ extern int file_extra_cnt;
+@@ -622,12 +624,14 @@ extern int file_extra_cnt;
  extern int inc_recurse;
  extern int uid_ndx;
  extern int gid_ndx;
@@ -388,7 +386,7 @@ diff --git a/rsync.yo b/rsync.yo
       --super                 receiver attempts super-user activities
       --fake-super            store/recover privileged attrs using xattrs
   -S, --sparse                handle sparse files efficiently
-@@ -987,6 +988,12 @@ it is preserving modification times (see bf(--times)).  If NFS is sharing
+@@ -994,6 +995,12 @@ it is preserving modification times (see bf(--times)).  If NFS is sharing
  the directories on the receiving side, it is a good idea to use bf(-O).
  This option is inferred if you use bf(--backup) without bf(--backup-dir).
  
@@ -401,7 +399,7 @@ diff --git a/rsync.yo b/rsync.yo
  dit(bf(--super)) This tells the receiving side to attempt super-user
  activities even if the receiving rsync wasn't run by the super-user.  These
  activities include: preserving users via the bf(--owner) option, preserving
-@@ -1689,7 +1696,10 @@ quote(itemization(
+@@ -1701,7 +1708,10 @@ quote(itemization(
    sender's value (requires bf(--owner) and super-user privileges).
    it() A bf(g) means the group is different and is being updated to the
    sender's value (requires bf(--group) and the authority to set the group).
index ee24be9..51d8489 100644 (file)
@@ -89,7 +89,12 @@ diff --git a/backup.c b/backup.c
                unmake_file(file);
                return 0;
        }
-@@ -326,3 +351,13 @@ int make_backup(const char *fname)
+@@ -322,7 +347,17 @@ static int keep_backup(const char *fname)
+ /* main backup switch routine */
+ int make_backup(const char *fname)
+ {
+-      if (backup_dir)
++      if (deleting ? backup_dir_dels : backup_dir)
                return keep_backup(fname);
        return make_simple_backup(fname);
  }
@@ -106,7 +111,7 @@ diff --git a/backup.c b/backup.c
 diff --git a/generator.c b/generator.c
 --- a/generator.c
 +++ b/generator.c
-@@ -97,6 +97,9 @@ extern uid_t our_uid;
+@@ -96,6 +96,9 @@ extern uid_t our_uid;
  extern char *backup_dir;
  extern char *backup_suffix;
  extern int backup_suffix_len;
@@ -114,11 +119,11 @@ diff --git a/generator.c b/generator.c
 +extern char *backup_suffix_dels;
 +extern int backup_suffix_dels_len;
  extern struct file_list *cur_flist, *first_flist, *dir_flist;
- extern struct filter_list_struct server_filter_list;
+ extern struct filter_list_struct daemon_filter_list;
  
-@@ -138,10 +141,15 @@ enum delret {
- /* Forward declaration for delete_item(). */
- static enum delret delete_dir_contents(char *fname, uint16 flags);
+@@ -142,10 +145,15 @@ static void handle_skipped_hlink(struct file_struct *file, int itemizing,
+                                enum logcode code, int f_out);
+ #endif
  
 +
 +/* Function now compares both backup_suffix and backup_suffix_dels. */
@@ -133,7 +138,7 @@ diff --git a/generator.c b/generator.c
  }
  
  /* Delete a file or directory.  If DEL_RECURSE is set in the flags, this will
-@@ -189,9 +197,9 @@ static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
+@@ -193,9 +201,9 @@ static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
        if (S_ISDIR(mode)) {
                what = "rmdir";
                ok = do_rmdir(fbuf) == 0;
@@ -148,7 +153,7 @@ diff --git a/generator.c b/generator.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -149,10 +149,14 @@ int no_detach
+@@ -150,10 +150,14 @@ int no_detach
  int write_batch = 0;
  int read_batch = 0;
  int backup_dir_len = 0;
@@ -163,7 +168,7 @@ diff --git a/options.c b/options.c
  char *tmpdir = NULL;
  char *partial_dir = NULL;
  char *basis_dir[MAX_BASIS_DIRS+1];
-@@ -164,7 +168,9 @@ char *stdout_format = NULL;
+@@ -165,7 +169,9 @@ char *stdout_format = NULL;
  char *password_file = NULL;
  char *rsync_path = RSYNC_PATH;
  char *backup_dir = NULL;
@@ -173,16 +178,16 @@ diff --git a/options.c b/options.c
  char *sockopts = NULL;
  int rsync_port = 0;
  int compare_dest = 0;
-@@ -324,6 +330,8 @@ void usage(enum logcode F)
+@@ -325,6 +331,8 @@ void usage(enum logcode F)
    rprintf(F," -b, --backup                make backups (see --suffix & --backup-dir)\n");
    rprintf(F,"     --backup-dir=DIR        make backups into hierarchy based in DIR\n");
    rprintf(F,"     --suffix=SUFFIX         set backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX);
-+  rprintf(F,"     --backup-dir-dels       make backups of removed files into current dir\n");
-+  rprintf(F,"     --suffix-dels=SUFFIX    set removed-files suffix (defaults to --suffix)\n");
++  rprintf(F,"     --backup-dir-dels=DIR   backup removed files into hierarchy based in DIR\n");
++  rprintf(F,"     --suffix-dels=SUFFIX    set removed-files suffix (def. --suffix w/o b-d-d)\n");
    rprintf(F," -u, --update                skip files that are newer on the receiver\n");
    rprintf(F,"     --inplace               update destination files in-place (SEE MAN PAGE)\n");
    rprintf(F,"     --append                append data onto shorter files\n");
-@@ -597,7 +605,9 @@ static struct poptOption long_options[] = {
+@@ -609,7 +617,9 @@ static struct poptOption long_options[] = {
    {"backup",          'b', POPT_ARG_VAL,    &make_backups, 1, 0, 0 },
    {"no-backup",        0,  POPT_ARG_VAL,    &make_backups, 0, 0, 0 },
    {"backup-dir",       0,  POPT_ARG_STRING, &backup_dir, 0, 0, 0 },
@@ -192,17 +197,17 @@ diff --git a/options.c b/options.c
    {"list-only",        0,  POPT_ARG_VAL,    &list_only, 2, 0, 0 },
    {"read-batch",       0,  POPT_ARG_STRING, &batch_name, OPT_READ_BATCH, 0, 0 },
    {"write-batch",      0,  POPT_ARG_STRING, &batch_name, OPT_WRITE_BATCH, 0, 0 },
-@@ -1427,6 +1437,8 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
-                       tmpdir = sanitize_path(NULL, tmpdir, NULL, 0);
+@@ -1453,6 +1463,8 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+                       tmpdir = sanitize_path(NULL, tmpdir, NULL, 0, SP_DEFAULT);
                if (backup_dir)
-                       backup_dir = sanitize_path(NULL, backup_dir, NULL, 0);
+                       backup_dir = sanitize_path(NULL, backup_dir, NULL, 0, SP_DEFAULT);
 +              if (backup_dir_dels)
-+                      backup_dir_dels = sanitize_path(NULL, backup_dir_dels, NULL, 0);
++                      backup_dir_dels = sanitize_path(NULL, backup_dir_dels, NULL, 0, SP_DEFAULT);
        }
-       if (server_filter_list.head && !am_sender) {
-               struct filter_list_struct *elp = &server_filter_list;
-@@ -1448,6 +1460,14 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
-                       if (check_filter(elp, dir, 1) < 0)
+       if (daemon_filter_list.head && !am_sender) {
+               struct filter_list_struct *elp = &daemon_filter_list;
+@@ -1474,6 +1486,14 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+                       if (check_filter(elp, FLOG, dir, 1) < 0)
                                goto options_rejected;
                }
 +              /* Clean backup_dir_dels same as for backup_dir */
@@ -216,10 +221,15 @@ diff --git a/options.c b/options.c
        }
  
        if (!backup_suffix)
-@@ -1459,6 +1479,15 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1485,6 +1505,20 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                        backup_suffix);
                return 0;
        }
++      /* --suffix-dels defaults to --suffix, or empty for a client given an
++       * explicit --backup-dir-dels (just as --suffix defaults to empty when
++       * a --backup-dir is given).  The second case does not apply to the
++       * server for consistency with server_options, which sends --suffix-dels
++       * to the server iff it differs from --suffix. */
 +      if (!backup_suffix_dels)
 +              backup_suffix_dels = backup_dir_dels && !am_server ? "" : backup_suffix;
 +      backup_suffix_dels_len = strlen(backup_suffix_dels);
@@ -232,7 +242,7 @@ diff --git a/options.c b/options.c
        if (backup_dir) {
                backup_dir_len = strlcpy(backup_dir_buf, backup_dir, sizeof backup_dir_buf);
                backup_dir_remainder = sizeof backup_dir_buf - backup_dir_len;
-@@ -1482,6 +1511,30 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1508,6 +1542,34 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                        "P *%s", backup_suffix);
                parse_rule(&filter_list, backup_dir_buf, 0, 0);
        }
@@ -259,11 +269,15 @@ diff --git a/options.c b/options.c
 +              snprintf(err_buf, sizeof err_buf,
 +                      "--suffix-dels cannot be a null string without --backup-dir-dels\n");
 +              return 0;
++      } else if (make_backups && delete_mode && !delete_excluded && !am_server) {
++              snprintf(backup_dir_dels_buf, sizeof backup_dir_dels_buf,
++                      "P *%s", backup_suffix_dels);
++              parse_rule(&filter_list, backup_dir_dels_buf, 0, 0);
 +      }
  
        if (make_backups && !backup_dir) {
                omit_dir_times = 0; /* Implied, so avoid -O to sender. */
-@@ -1875,6 +1928,10 @@ void server_options(char **args, int *argc_p)
+@@ -1901,6 +1963,10 @@ void server_options(char **args, int *argc_p)
                args[ac++] = "--backup-dir";
                args[ac++] = backup_dir;
        }
@@ -274,7 +288,7 @@ diff --git a/options.c b/options.c
  
        /* Only send --suffix if it specifies a non-default value. */
        if (strcmp(backup_suffix, backup_dir ? "" : BACKUP_SUFFIX) != 0) {
-@@ -1883,7 +1940,14 @@ void server_options(char **args, int *argc_p)
+@@ -1909,7 +1975,14 @@ void server_options(char **args, int *argc_p)
                        goto oom;
                args[ac++] = arg;
        }
index 2b7d8be..d7c0e12 100644 (file)
@@ -51,7 +51,7 @@ diff --git a/log.c b/log.c
 diff --git a/main.c b/main.c
 --- a/main.c
 +++ b/main.c
-@@ -166,8 +166,11 @@ static void wait_process_with_flush(pid_t pid, int *exit_code_ptr)
+@@ -163,8 +163,11 @@ static void wait_process_with_flush(pid_t pid, int *exit_code_ptr)
                        *exit_code_ptr = RERR_TERMINATED;
                else
                        *exit_code_ptr = RERR_WAITCHILD;
@@ -64,7 +64,7 @@ diff --git a/main.c b/main.c
  }
  
  /* This function gets called from all 3 processes.  We want the client side
-@@ -1346,6 +1349,14 @@ RETSIGTYPE remember_children(UNUSED(int val))
+@@ -1306,6 +1309,14 @@ RETSIGTYPE remember_children(UNUSED(int val))
                                break;
                        }
                }
@@ -79,7 +79,7 @@ diff --git a/main.c b/main.c
        }
  #endif
  #ifndef HAVE_SIGACTION
-@@ -1404,6 +1415,12 @@ static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
+@@ -1364,6 +1375,12 @@ static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
  }
  #endif
  
@@ -92,7 +92,7 @@ diff --git a/main.c b/main.c
  
  int main(int argc,char *argv[])
  {
-@@ -1426,6 +1443,11 @@ int main(int argc,char *argv[])
+@@ -1386,6 +1403,11 @@ int main(int argc,char *argv[])
        SIGACTMASK(SIGFPE, rsync_panic_handler);
        SIGACTMASK(SIGABRT, rsync_panic_handler);
        SIGACTMASK(SIGBUS, rsync_panic_handler);
index ff96510..6618269 100644 (file)
@@ -31,7 +31,7 @@ diff --git a/checksum.c b/checksum.c
 diff --git a/clientserver.c b/clientserver.c
 --- a/clientserver.c
 +++ b/clientserver.c
-@@ -39,6 +39,8 @@ extern int numeric_ids;
+@@ -42,6 +42,8 @@ extern int numeric_ids;
  extern int filesfrom_fd;
  extern int remote_protocol;
  extern int protocol_version;
@@ -40,8 +40,8 @@ diff --git a/clientserver.c b/clientserver.c
  extern int io_timeout;
  extern int no_detach;
  extern int write_batch;
-@@ -750,6 +752,9 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
-       else if (am_root < 0) /* Treat --fake-super from client as --super. */
+@@ -782,6 +784,9 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
+       else if (am_root < 0) /* Treat --fake-super from client as --super. */
                am_root = 2;
  
 +      checksum_files = always_checksum ? lp_checksum_files(i)
@@ -77,11 +77,12 @@ diff --git a/flist.c b/flist.c
  extern struct stats stats;
  extern char *filesfrom_host;
  
-@@ -83,6 +86,11 @@ extern int filesfrom_convert;
+@@ -83,6 +86,12 @@ extern int filesfrom_convert;
  extern iconv_t ic_send, ic_recv;
  #endif
  
 +#define RSYNCSUMS_FILE ".rsyncsums"
++#define RSYNCSUMS_LEN (sizeof RSYNCSUMS_FILE-1)
 +
 +#define CLEAN_STRIP_ROOT (1<<0)
 +#define CLEAN_KEEP_LAST (1<<1)
@@ -89,7 +90,7 @@ diff --git a/flist.c b/flist.c
  #define PTR_SIZE (sizeof (struct file_struct *))
  
  int io_error;
-@@ -124,7 +132,11 @@ static char empty_sum[MAX_DIGEST_LEN];
+@@ -124,7 +133,11 @@ static char empty_sum[MAX_DIGEST_LEN];
  static int flist_count_offset; /* for --delete --progress */
  static int dir_count = 0;
  
@@ -102,7 +103,7 @@ diff --git a/flist.c b/flist.c
  static void output_flist(struct file_list *flist);
  
  void init_flist(void)
-@@ -315,6 +327,238 @@ static void flist_done_allocating(struct file_list *flist)
+@@ -350,6 +363,238 @@ static void flist_done_allocating(struct file_list *flist)
                flist->pool_boundary = ptr;
  }
  
@@ -133,8 +134,7 @@ diff --git a/flist.c b/flist.c
 +      }
 +}
 +
-+
-+/* The basename_len count is the length of the basename + 1 for the null. */
++/* The basename_len count is the length of the basename + 1 for the '\0'. */
 +static int add_checksum(struct file_list *flist, const char *dirname,
 +                      const char *basename, int basename_len, OFF_T file_length,
 +                      time_t mtime, uint32 ctime, uint32 inode,
@@ -144,7 +144,8 @@ diff --git a/flist.c b/flist.c
 +      int alloc_len, extra_len;
 +      char *bp;
 +
-+      if (basename_len == 10+1 && *basename == '.' && strcmp(basename, RSYNCSUMS_FILE) == 0)
++      if (basename_len == RSYNCSUMS_LEN+1 && *basename == '.'
++       && strcmp(basename, RSYNCSUMS_FILE) == 0)
 +              return 0;
 +
 +      /* "2" is for a 32-bit ctime num and an 32-bit inode num. */
@@ -198,7 +199,7 @@ diff --git a/flist.c b/flist.c
 +      uint32 ctime, inode;
 +      int dlen = dirname ? strlcpy(fbuf, dirname, sizeof fbuf) : 0;
 +
-+      if (dlen >= (int)(sizeof fbuf - sizeof RSYNCSUMS_FILE))
++      if (dlen >= (int)(sizeof fbuf - 1 - RSYNCSUMS_LEN))
 +              return;
 +      if (dlen)
 +              fbuf[dlen++] = '/';
@@ -341,7 +342,7 @@ diff --git a/flist.c b/flist.c
  int push_pathname(const char *dir, int len)
  {
        if (dir == pathname)
-@@ -1005,7 +1249,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1039,7 +1284,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
                              STRUCT_STAT *stp, int flags, int filter_level)
  {
        static char *lastdir;
@@ -350,7 +351,7 @@ diff --git a/flist.c b/flist.c
        struct file_struct *file;
        char thisname[MAXPATHLEN];
        char linkname[MAXPATHLEN];
-@@ -1138,9 +1382,16 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1178,9 +1423,16 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
                        memcpy(lastdir, thisname, len);
                        lastdir[len] = '\0';
                        lastdir_len = len;
@@ -368,14 +369,17 @@ diff --git a/flist.c b/flist.c
        basename_len = strlen(basename) + 1; /* count the '\0' */
  
  #ifdef SUPPORT_LINKS
-@@ -1216,11 +1467,15 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
-       }
+@@ -1253,14 +1505,18 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+               memcpy(bp + basename_len, linkname, linkname_len);
  #endif
  
 -      if (always_checksum && am_sender && S_ISREG(st.st_mode))
 -              file_checksum(thisname, tmp_sum, st.st_size);
 -
-       F_PATHNAME(file) = pathname;
+       if (am_sender)
+               F_PATHNAME(file) = pathname;
+       else if (!pool)
+               F_DEPTH(file) = extra_len / EXTRA_LEN;
  
 +      if (always_checksum && am_sender && S_ISREG(st.st_mode)) {
 +              if (flist && checksum_files)
@@ -387,7 +391,7 @@ diff --git a/flist.c b/flist.c
        /* This code is only used by the receiver when it is building
         * a list of files for a delete pass. */
        if (keep_dirlinks && linkname_len && flist) {
-@@ -2076,7 +2331,8 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
+@@ -2131,7 +2387,8 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
                         * file-list to check if this is a 1-file xfer. */
                        send_extra_file_list(f, 1);
                }
@@ -397,7 +401,7 @@ diff --git a/flist.c b/flist.c
  
        return flist;
  }
-@@ -2178,7 +2434,7 @@ struct file_list *recv_file_list(int f)
+@@ -2233,7 +2490,7 @@ struct file_list *recv_file_list(int f)
        else if (f >= 0)
                recv_id_list(f, flist);
  
@@ -406,7 +410,7 @@ diff --git a/flist.c b/flist.c
  
        if (protocol_version < 30) {
                /* Recv the io_error flag */
-@@ -2376,7 +2632,7 @@ void flist_free(struct file_list *flist)
+@@ -2431,7 +2688,7 @@ void flist_free(struct file_list *flist)
  
  /* This routine ensures we don't have any duplicate names in our file list.
   * duplicate names can cause corruption because of the pipelining. */
@@ -415,7 +419,7 @@ diff --git a/flist.c b/flist.c
  {
        char fbuf[MAXPATHLEN];
        int i, prev_i;
-@@ -2427,7 +2683,7 @@ static void flist_sort_and_clean(struct file_list *flist, int strip_root)
+@@ -2482,7 +2739,7 @@ static void flist_sort_and_clean(struct file_list *flist, int strip_root)
                        /* If one is a dir and the other is not, we want to
                         * keep the dir because it might have contents in the
                         * list.  Otherwise keep the first one. */
@@ -424,7 +428,7 @@ diff --git a/flist.c b/flist.c
                                struct file_struct *fp = flist->sorted[j];
                                if (!S_ISDIR(fp->mode))
                                        keep = i, drop = j;
-@@ -2443,8 +2699,8 @@ static void flist_sort_and_clean(struct file_list *flist, int strip_root)
+@@ -2498,8 +2755,8 @@ static void flist_sort_and_clean(struct file_list *flist, int strip_root)
                        } else
                                keep = j, drop = i;
  
@@ -435,7 +439,7 @@ diff --git a/flist.c b/flist.c
                                        rprintf(FINFO,
                                            "removing duplicate name %s from file list (%d)\n",
                                            f_name(file, fbuf), drop + flist->ndx_start);
-@@ -2466,7 +2722,7 @@ static void flist_sort_and_clean(struct file_list *flist, int strip_root)
+@@ -2521,7 +2778,7 @@ static void flist_sort_and_clean(struct file_list *flist, int strip_root)
        }
        flist->high = prev_i;
  
@@ -447,7 +451,7 @@ diff --git a/flist.c b/flist.c
 diff --git a/generator.c b/generator.c
 --- a/generator.c
 +++ b/generator.c
-@@ -53,6 +53,7 @@ extern int delete_during;
+@@ -52,6 +52,7 @@ extern int delete_during;
  extern int delete_after;
  extern int msgdone_cnt;
  extern int ignore_errors;
@@ -455,7 +459,7 @@ diff --git a/generator.c b/generator.c
  extern int remove_source_files;
  extern int delay_updates;
  extern int update_only;
-@@ -694,7 +695,7 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+@@ -706,7 +707,7 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
  
  
  /* Perform our quick-check heuristic for determining if a file is unchanged. */
@@ -464,7 +468,7 @@ diff --git a/generator.c b/generator.c
  {
        if (st->st_size != F_LENGTH(file))
                return 0;
-@@ -703,7 +704,10 @@ int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st)
+@@ -715,7 +716,10 @@ int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st)
           of the file time to determine whether to sync */
        if (always_checksum > 0 && S_ISREG(st->st_mode)) {
                char sum[MAX_DIGEST_LEN];
@@ -476,7 +480,7 @@ diff --git a/generator.c b/generator.c
                return memcmp(sum, F_SUM(file), checksum_len) == 0;
        }
  
-@@ -957,7 +961,7 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
+@@ -969,7 +973,7 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
                        match_level = 1;
                        /* FALL THROUGH */
                case 1:
@@ -485,16 +489,16 @@ diff --git a/generator.c b/generator.c
                                continue;
                        best_match = j;
                        match_level = 2;
-@@ -1219,7 +1223,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
-       static const char *parent_dirname = "";
-       static struct file_struct *missing_dir = NULL, *excluded_dir = NULL;
+@@ -1242,7 +1246,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+        * --ignore-non-existing, daemon exclude, or mkdir failure. */
+       static struct file_struct *skip_dir = NULL;
        static struct file_list *fuzzy_dirlist = NULL;
 -      static int need_fuzzy_dirlist = 0;
 +      static int need_new_dirscan = 0;
        struct file_struct *fuzzy_file = NULL;
        int fd = -1, f_copy = -1;
        stat_x sx, real_sx;
-@@ -1309,8 +1313,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1331,8 +1335,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                                flist_free(fuzzy_dirlist);
                                fuzzy_dirlist = NULL;
                        }
@@ -505,7 +509,7 @@ diff --git a/generator.c b/generator.c
  #ifdef SUPPORT_ACLS
                        if (!preserve_perms)
                                dflt_perms = default_perms_for_dir(dn);
-@@ -1318,10 +1322,15 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1340,10 +1344,15 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                }
                parent_dirname = dn;
  
@@ -525,7 +529,7 @@ diff --git a/generator.c b/generator.c
                }
  
                statret = link_stat(fname, &sx.st, keep_dirlinks && is_dir);
-@@ -1742,7 +1751,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1768,7 +1777,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                ;
        else if (fnamecmp_type == FNAMECMP_FUZZY)
                ;
@@ -537,7 +541,7 @@ diff --git a/generator.c b/generator.c
 diff --git a/hlink.c b/hlink.c
 --- a/hlink.c
 +++ b/hlink.c
-@@ -351,7 +351,7 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
+@@ -388,7 +388,7 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
                                }
                                break;
                        }
@@ -549,7 +553,7 @@ diff --git a/hlink.c b/hlink.c
 diff --git a/ifuncs.h b/ifuncs.h
 --- a/ifuncs.h
 +++ b/ifuncs.h
-@@ -64,6 +64,12 @@ isDigit(const char *ptr)
+@@ -74,6 +74,12 @@ isDigit(const char *ptr)
  }
  
  static inline int
@@ -613,7 +617,7 @@ diff --git a/loadparm.c b/loadparm.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -112,6 +112,7 @@ size_t bwlimit_writemax = 0;
+@@ -113,6 +113,7 @@ size_t bwlimit_writemax = 0;
  int ignore_existing = 0;
  int ignore_non_existing = 0;
  int need_messages_from_generator = 0;
@@ -621,7 +625,7 @@ diff --git a/options.c b/options.c
  int max_delete = INT_MIN;
  OFF_T max_size = 0;
  OFF_T min_size = 0;
-@@ -316,6 +317,7 @@ void usage(enum logcode F)
+@@ -317,6 +318,7 @@ void usage(enum logcode F)
    rprintf(F," -q, --quiet                 suppress non-error messages\n");
    rprintf(F,"     --no-motd               suppress daemon-mode MOTD (see manpage caveat)\n");
    rprintf(F," -c, --checksum              skip based on checksum, not mod-time & size\n");
@@ -629,7 +633,7 @@ diff --git a/options.c b/options.c
    rprintf(F," -a, --archive               archive mode; equals -rlptgoD (no -H,-A,-X)\n");
    rprintf(F,"     --no-OPTION             turn off an implied OPTION (e.g. --no-D)\n");
    rprintf(F," -r, --recursive             recurse into directories\n");
-@@ -445,7 +447,7 @@ enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
+@@ -446,7 +448,7 @@ enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
        OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST, OPT_HELP,
        OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW, OPT_MIN_SIZE, OPT_CHMOD,
        OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE,
@@ -638,7 +642,7 @@ diff --git a/options.c b/options.c
        OPT_SERVER, OPT_REFUSED_BASE = 9000};
  
  static struct poptOption long_options[] = {
-@@ -566,6 +568,7 @@ static struct poptOption long_options[] = {
+@@ -574,6 +576,7 @@ static struct poptOption long_options[] = {
    {"checksum",        'c', POPT_ARG_VAL,    &always_checksum, 1, 0, 0 },
    {"no-checksum",      0,  POPT_ARG_VAL,    &always_checksum, 0, 0, 0 },
    {"no-c",             0,  POPT_ARG_VAL,    &always_checksum, 0, 0, 0 },
@@ -646,7 +650,7 @@ diff --git a/options.c b/options.c
    {"block-size",      'B', POPT_ARG_LONG,   &block_size, 0, 0, 0 },
    {"compare-dest",     0,  POPT_ARG_STRING, 0, OPT_COMPARE_DEST, 0, 0 },
    {"copy-dest",        0,  POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 },
-@@ -1212,6 +1215,23 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1228,6 +1231,23 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                        }
                        break;
  
@@ -670,11 +674,11 @@ diff --git a/options.c b/options.c
                case OPT_HELP:
                        usage(FINFO);
                        exit_cleanup(0);
-@@ -1311,6 +1331,9 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1332,6 +1352,9 @@ int parse_arguments(int *argc_p, const char ***argv_p)
        }
  #endif
  
-+      if (checksum_files && !always_checksum)
++      if (!always_checksum)
 +              checksum_files = CSF_IGNORE_FILES;
 +
        if (write_batch && read_batch) {
@@ -683,7 +687,7 @@ diff --git a/options.c b/options.c
 diff --git a/rsync.h b/rsync.h
 --- a/rsync.h
 +++ b/rsync.h
-@@ -680,6 +680,10 @@ extern int xattrs_ndx;
+@@ -682,6 +682,10 @@ extern int xattrs_ndx;
  #define F_SUM(f) ((char*)OPT_EXTRA(f, LEN64_BUMP(f) + HLINK_BUMP(f) \
                                    + SUM_EXTRA_CNT - 1))
  
@@ -694,7 +698,7 @@ diff --git a/rsync.h b/rsync.h
  /* Some utility defines: */
  #define F_IS_ACTIVE(f) (f)->basename[0]
  #define F_IS_HLINKED(f) ((f)->flags & FLAG_HLINKED)
-@@ -858,6 +862,13 @@ typedef struct {
+@@ -860,6 +864,13 @@ typedef struct {
        char fname[1]; /* has variable size */
  } relnamecache;
  
index 8a7a5ca..8666a12 100644 (file)
@@ -28,7 +28,7 @@ diff --git a/flist.c b/flist.c
  extern int am_root;
  extern int am_server;
  extern int am_daemon;
-@@ -93,6 +94,9 @@ extern iconv_t ic_send, ic_recv;
+@@ -94,6 +95,9 @@ extern iconv_t ic_send, ic_recv;
  
  #define PTR_SIZE (sizeof (struct file_struct *))
  
@@ -38,7 +38,7 @@ diff --git a/flist.c b/flist.c
  int io_error;
  int checksum_len;
  dev_t filesystem_dev; /* used to implement -x */
-@@ -132,8 +136,13 @@ static char empty_sum[MAX_DIGEST_LEN];
+@@ -133,8 +137,13 @@ static char empty_sum[MAX_DIGEST_LEN];
  static int flist_count_offset; /* for --delete --progress */
  static int dir_count = 0;
  
@@ -52,7 +52,7 @@ diff --git a/flist.c b/flist.c
  } *csum_cache = NULL;
  
  static void flist_sort_and_clean(struct file_list *flist, int flags);
-@@ -327,7 +336,79 @@ static void flist_done_allocating(struct file_list *flist)
+@@ -363,7 +372,79 @@ static void flist_done_allocating(struct file_list *flist)
                flist->pool_boundary = ptr;
  }
  
@@ -133,7 +133,7 @@ diff --git a/flist.c b/flist.c
  {
        int slot, slots = am_sender ? 1 : basis_dir_cnt + 1;
  
-@@ -341,6 +422,9 @@ void reset_checksum_cache()
+@@ -377,6 +458,9 @@ void reset_checksum_cache()
                struct file_list *flist = csum_cache[slot].flist;
  
                if (flist) {
@@ -143,7 +143,7 @@ diff --git a/flist.c b/flist.c
                        /* Reset the pool memory and empty the file-list array. */
                        pool_free_old(flist->file_pool,
                                      pool_boundary(flist->file_pool, 0));
-@@ -351,6 +435,10 @@ void reset_checksum_cache()
+@@ -387,6 +471,10 @@ void reset_checksum_cache()
                flist->low = 0;
                flist->high = -1;
                flist->next = NULL;
@@ -154,7 +154,7 @@ diff --git a/flist.c b/flist.c
        }
  }
  
-@@ -359,7 +447,7 @@ void reset_checksum_cache()
+@@ -394,7 +482,7 @@ void reset_checksum_cache()
  static int add_checksum(struct file_list *flist, const char *dirname,
                        const char *basename, int basename_len, OFF_T file_length,
                        time_t mtime, uint32 ctime, uint32 inode,
@@ -163,7 +163,7 @@ diff --git a/flist.c b/flist.c
  {
        struct file_struct *file;
        int alloc_len, extra_len;
-@@ -375,7 +463,7 @@ static int add_checksum(struct file_list *flist, const char *dirname,
+@@ -411,7 +499,7 @@ static int add_checksum(struct file_list *flist, const char *dirname,
        if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN))
                extra_len = (extra_len | (EXTRA_ROUNDING * EXTRA_LEN)) + EXTRA_LEN;
  #endif
@@ -172,7 +172,7 @@ diff --git a/flist.c b/flist.c
        bp = pool_alloc(flist->file_pool, alloc_len, "add_checksum");
  
        memset(bp, 0, extra_len + FILE_STRUCT_LEN);
-@@ -384,7 +472,14 @@ static int add_checksum(struct file_list *flist, const char *dirname,
+@@ -420,7 +508,14 @@ static int add_checksum(struct file_list *flist, const char *dirname,
        bp += FILE_STRUCT_LEN;
  
        memcpy(bp, basename, basename_len);
@@ -187,7 +187,7 @@ diff --git a/flist.c b/flist.c
        file->mode = S_IFREG;
        file->modtime = mtime;
        file->len32 = (uint32)file_length;
-@@ -413,10 +508,11 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
+@@ -449,10 +544,11 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
        char line[MAXPATHLEN+1024], fbuf[MAXPATHLEN], sum[MAX_DIGEST_LEN];
        FILE *fp;
        char *cp;
@@ -199,8 +199,8 @@ diff --git a/flist.c b/flist.c
 +      const char *alt_sum = NULL;
        int dlen = dirname ? strlcpy(fbuf, dirname, sizeof fbuf) : 0;
  
-       if (dlen >= (int)(sizeof fbuf - sizeof RSYNCSUMS_FILE))
-@@ -437,7 +533,7 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
+       if (dlen >= (int)(sizeof fbuf - 1 - RSYNCSUMS_LEN))
+@@ -473,7 +569,7 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
        while (fgets(line, sizeof line, fp)) {
                cp = line;
                if (protocol_version >= 30) {
@@ -209,7 +209,7 @@ diff --git a/flist.c b/flist.c
                        if (*cp == '=')
                                while (*++cp == '=') {}
                        else
-@@ -448,7 +544,14 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
+@@ -484,7 +580,14 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
                }
  
                if (*cp == '=') {
@@ -225,7 +225,7 @@ diff --git a/flist.c b/flist.c
                } else {
                        for (i = 0; i < checksum_len*2; i++, cp++) {
                                int x;
-@@ -466,13 +569,14 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
+@@ -502,13 +605,14 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
                                else
                                        sum[i/2] = x << 4;
                        }
@@ -241,7 +241,7 @@ diff --git a/flist.c b/flist.c
                        if (*cp == '=')
                                while (*++cp == '=') {}
                        else
-@@ -522,24 +626,112 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
+@@ -558,24 +662,112 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
                        continue;
  
                strlcpy(fbuf+dlen, cp, sizeof fbuf - dlen);
@@ -356,7 +356,7 @@ diff --git a/flist.c b/flist.c
                read_checksums(slot, flist, file->dirname);
        }
  
-@@ -551,12 +743,31 @@ void get_cached_checksum(int slot, const char *fname, struct file_struct *file,
+@@ -587,12 +779,31 @@ void get_cached_checksum(int slot, const char *fname, struct file_struct *file,
                 && (checksum_files & CSF_LAX
                  || (F_CTIME(fp) == (uint32)stp->st_ctime
                   && F_INODE(fp) == (uint32)stp->st_ino))) {
@@ -389,7 +389,7 @@ diff --git a/flist.c b/flist.c
  }
  
  int push_pathname(const char *dir, int len)
-@@ -1343,6 +1554,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1378,6 +1589,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
        if (is_excluded(thisname, S_ISDIR(st.st_mode) != 0, filter_level)) {
                if (ignore_perishable)
                        non_perishable_cnt++;
@@ -398,7 +398,7 @@ diff --git a/flist.c b/flist.c
                return NULL;
        }
  
-@@ -1383,13 +1596,13 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1424,13 +1637,13 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
                        lastdir[len] = '\0';
                        lastdir_len = len;
                        if (checksum_files && am_sender && flist)
@@ -414,7 +414,7 @@ diff --git a/flist.c b/flist.c
                }
        }
        basename_len = strlen(basename) + 1; /* count the '\0' */
-@@ -1471,7 +1684,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1512,7 +1725,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
  
        if (always_checksum && am_sender && S_ISREG(st.st_mode)) {
                if (flist && checksum_files)
@@ -423,7 +423,7 @@ diff --git a/flist.c b/flist.c
                else
                        file_checksum(thisname, st.st_size, tmp_sum);
        }
-@@ -1768,6 +1981,9 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len,
+@@ -1804,6 +2017,9 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len,
  
        closedir(d);
  
@@ -433,7 +433,7 @@ diff --git a/flist.c b/flist.c
        if (f >= 0 && recurse && !divert_dirs) {
                int i, end = flist->used - 1;
                /* send_if_directory() bumps flist->used, so use "end". */
-@@ -2333,6 +2549,9 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
+@@ -2389,6 +2605,9 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
                }
        } else
                flist_eof = 1;
@@ -446,15 +446,15 @@ diff --git a/flist.c b/flist.c
 diff --git a/generator.c b/generator.c
 --- a/generator.c
 +++ b/generator.c
-@@ -114,6 +114,7 @@ static int lull_mod;
- static int dir_tweaking;
+@@ -114,6 +114,7 @@ static int dir_tweaking;
+ static int symlink_timeset_failed_flags;
  static int need_retouch_dir_times;
  static int need_retouch_dir_perms;
 +static int started_whole_dir, upcoming_whole_dir;
  static const char *solo_file = NULL;
  
  /* For calling delete_item() and delete_dir_contents(). */
-@@ -705,7 +706,7 @@ int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st, int slot
+@@ -717,7 +718,7 @@ int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st, int slot
        if (always_checksum > 0 && S_ISREG(st->st_mode)) {
                char sum[MAX_DIGEST_LEN];
                if (checksum_files && slot >= 0)
@@ -463,7 +463,7 @@ diff --git a/generator.c b/generator.c
                else
                        file_checksum(fn, st->st_size, sum);
                return memcmp(sum, F_SUM(file), checksum_len) == 0;
-@@ -1328,7 +1329,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1350,7 +1351,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                                fuzzy_dirlist = get_dirlist(fnamecmpbuf, -1, 1);
                        }
                        if (checksum_files) {
@@ -473,15 +473,15 @@ diff --git a/generator.c b/generator.c
                        }
                        need_new_dirscan = 0;
                }
-@@ -1457,9 +1459,12 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1488,9 +1490,12 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                                DEV_MINOR(devp) = minor(real_sx.st.st_dev);
                        }
                }
--              else if (delete_during && f_out != -1 && !phase && dry_run < 2
--                  && (file->flags & FLAG_CONTENT_DIR))
+-              else if (delete_during && f_out != -1 && !phase
+-                  && BITS_SETnUNSET(file->flags, FLAG_CONTENT_DIR, FLAG_MISSING_DIR))
 -                      delete_in_dir(fname, file, &real_sx.st.st_dev);
 +              else if (file->flags & FLAG_CONTENT_DIR && f_out != -1) {
-+                      if (delete_during && !phase && dry_run < 2)
++                      if (delete_during && !phase && !(file->flags & FLAG_MISSING_DIR))
 +                              delete_in_dir(fname, file, &real_sx.st.st_dev);
 +                      upcoming_whole_dir = 1;
 +              } else
@@ -489,7 +489,7 @@ diff --git a/generator.c b/generator.c
                goto cleanup;
        }
  
-@@ -1757,6 +1762,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1783,6 +1788,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                        handle_partial_dir(partialptr, PDIR_DELETE);
                }
                set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT);
@@ -498,7 +498,7 @@ diff --git a/generator.c b/generator.c
                if (itemizing)
                        itemize(fnamecmp, file, ndx, statret, &sx, 0, 0, NULL);
  #ifdef SUPPORT_HARD_LINKS
-@@ -2132,6 +2139,7 @@ void generate_files(int f_out, const char *local_name)
+@@ -2195,6 +2202,7 @@ void generate_files(int f_out, const char *local_name)
                                        delete_in_dir(f_name(fp, fbuf), fp, &dirdev);
                                }
                        }
@@ -506,7 +506,7 @@ diff --git a/generator.c b/generator.c
                }
                for (i = cur_flist->low; i <= cur_flist->high; i++) {
                        struct file_struct *file = cur_flist->sorted[i];
-@@ -2212,6 +2220,9 @@ void generate_files(int f_out, const char *local_name)
+@@ -2275,6 +2283,9 @@ void generate_files(int f_out, const char *local_name)
                        wait_for_receiver();
        }
  
@@ -519,7 +519,7 @@ diff --git a/generator.c b/generator.c
 diff --git a/io.c b/io.c
 --- a/io.c
 +++ b/io.c
-@@ -49,6 +49,7 @@ extern int read_batch;
+@@ -50,6 +50,7 @@ extern int read_batch;
  extern int csum_length;
  extern int protect_args;
  extern int checksum_seed;
@@ -527,7 +527,7 @@ diff --git a/io.c b/io.c
  extern int protocol_version;
  extern int remove_source_files;
  extern int preserve_hard_links;
-@@ -200,6 +201,9 @@ static void got_flist_entry_status(enum festatus status, const char *buf)
+@@ -205,6 +206,9 @@ static void got_flist_entry_status(enum festatus status, const char *buf)
                                flist_ndx_push(&hlink_list, ndx);
                                flist->in_progress++;
                        }
@@ -554,7 +554,7 @@ diff --git a/loadparm.c b/loadparm.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -1217,7 +1217,15 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1233,7 +1233,15 @@ int parse_arguments(int *argc_p, const char ***argv_p)
  
                case OPT_SUMFILES:
                        arg = poptGetOptArg(pc);
@@ -603,7 +603,7 @@ diff --git a/receiver.c b/receiver.c
 diff --git a/rsync.h b/rsync.h
 --- a/rsync.h
 +++ b/rsync.h
-@@ -864,6 +864,8 @@ typedef struct {
+@@ -866,6 +866,8 @@ typedef struct {
  
  #define CSF_ENABLE (1<<1)
  #define CSF_LAX (1<<2)
index b5020e6..d4eb3f8 100644 (file)
@@ -11,8 +11,8 @@ To use this patch, run these commands for a successful build:
 diff --git a/flist.c b/flist.c
 --- a/flist.c
 +++ b/flist.c
-@@ -1216,7 +1216,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
-       }
+@@ -1253,7 +1253,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+               memcpy(bp + basename_len, linkname, linkname_len);
  #endif
  
 -      if (always_checksum && am_sender && S_ISREG(st.st_mode))
@@ -20,11 +20,11 @@ diff --git a/flist.c b/flist.c
 +       && !get_sum_xattr(thisname, &st, tmp_sum))
                file_checksum(thisname, tmp_sum, st.st_size);
  
-       F_PATHNAME(file) = pathname;
+       if (am_sender)
 diff --git a/generator.c b/generator.c
 --- a/generator.c
 +++ b/generator.c
-@@ -703,7 +703,8 @@ int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st)
+@@ -715,7 +715,8 @@ int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st)
           of the file time to determine whether to sync */
        if (always_checksum > 0 && S_ISREG(st->st_mode)) {
                char sum[MAX_DIGEST_LEN];
@@ -169,16 +169,29 @@ diff --git a/xattrs.c b/xattrs.c
  
  #define RSYNC_XAL_INITIAL 5
  #define RSYNC_XAL_LIST_INITIAL 100
-@@ -65,6 +67,8 @@ extern int checksum_seed;
- #define XSTAT_ATTR RSYNC_PREFIX "%stat"
- #define XACC_ACL_ATTR RSYNC_PREFIX "%aacl"
- #define XDEF_ACL_ATTR RSYNC_PREFIX "%dacl"
-+#define MD4_ATTR RSYNC_PREFIX "%md4"
-+#define MD5_ATTR RSYNC_PREFIX "%md5"
+@@ -68,6 +70,10 @@ extern int checksum_seed;
+ #define XACC_ACL_ATTR RSYNC_PREFIX "%" XACC_ACL_SUFFIX
+ #define XDEF_ACL_SUFFIX "dacl"
+ #define XDEF_ACL_ATTR RSYNC_PREFIX "%" XDEF_ACL_SUFFIX
++#define MD4_SUFFIX "md4"
++#define MD4_ATTR RSYNC_PREFIX "%" MD4_SUFFIX
++#define MD5_SUFFIX "md5"
++#define MD5_ATTR RSYNC_PREFIX "%" MD5_SUFFIX
  
  typedef struct {
        char *datum, *name;
-@@ -829,6 +833,39 @@ int del_def_xattr_acl(const char *fname)
+@@ -237,7 +243,9 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
+                        || (am_root < 0
+                         && (strcmp(name+RPRE_LEN+1, XSTAT_SUFFIX) == 0
+                          || strcmp(name+RPRE_LEN+1, XACC_ACL_SUFFIX) == 0
+-                         || strcmp(name+RPRE_LEN+1, XDEF_ACL_SUFFIX) == 0)))
++                         || strcmp(name+RPRE_LEN+1, XDEF_ACL_SUFFIX) == 0
++                         || strcmp(name+RPRE_LEN+1, MD4_SUFFIX) == 0
++                         || strcmp(name+RPRE_LEN+1, MD5_SUFFIX) == 0)))
+                               continue;
+               }
+@@ -844,6 +852,39 @@ int del_def_xattr_acl(const char *fname)
  }
  #endif
  
index cd87197..f629701 100644 (file)
@@ -11,7 +11,7 @@ To use this patch, run these commands for a successful build:
 diff --git a/generator.c b/generator.c
 --- a/generator.c
 +++ b/generator.c
-@@ -40,6 +40,7 @@ extern int preserve_acls;
+@@ -39,6 +39,7 @@ extern int preserve_acls;
  extern int preserve_xattrs;
  extern int preserve_links;
  extern int preserve_devices;
@@ -19,7 +19,7 @@ diff --git a/generator.c b/generator.c
  extern int preserve_specials;
  extern int preserve_hard_links;
  extern int preserve_executability;
-@@ -1632,7 +1633,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1663,7 +1664,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                goto cleanup;
        }
  
@@ -31,7 +31,7 @@ diff --git a/generator.c b/generator.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -47,6 +47,7 @@ int append_mode = 0;
+@@ -48,6 +48,7 @@ int append_mode = 0;
  int keep_dirlinks = 0;
  int copy_dirlinks = 0;
  int copy_links = 0;
@@ -39,7 +39,7 @@ diff --git a/options.c b/options.c
  int preserve_links = 0;
  int preserve_hard_links = 0;
  int preserve_acls = 0;
-@@ -348,6 +349,7 @@ void usage(enum logcode F)
+@@ -349,6 +350,7 @@ void usage(enum logcode F)
    rprintf(F," -o, --owner                 preserve owner (super-user only)\n");
    rprintf(F," -g, --group                 preserve group\n");
    rprintf(F,"     --devices               preserve device files (super-user only)\n");
@@ -47,7 +47,7 @@ diff --git a/options.c b/options.c
    rprintf(F,"     --specials              preserve special files\n");
    rprintf(F," -D                          same as --devices --specials\n");
    rprintf(F," -t, --times                 preserve modification times\n");
-@@ -504,6 +506,7 @@ static struct poptOption long_options[] = {
+@@ -507,6 +509,7 @@ static struct poptOption long_options[] = {
    {"no-D",             0,  POPT_ARG_NONE,   0, OPT_NO_D, 0, 0 },
    {"devices",          0,  POPT_ARG_VAL,    &preserve_devices, 1, 0, 0 },
    {"no-devices",       0,  POPT_ARG_VAL,    &preserve_devices, 0, 0, 0 },
@@ -55,7 +55,7 @@ diff --git a/options.c b/options.c
    {"specials",         0,  POPT_ARG_VAL,    &preserve_specials, 1, 0, 0 },
    {"no-specials",      0,  POPT_ARG_VAL,    &preserve_specials, 0, 0, 0 },
    {"links",           'l', POPT_ARG_VAL,    &preserve_links, 1, 0, 0 },
-@@ -2022,6 +2025,9 @@ void server_options(char **args, int *argc_p)
+@@ -2048,6 +2051,9 @@ void server_options(char **args, int *argc_p)
        else if (remove_source_files)
                args[ac++] = "--remove-sent-files";
  
@@ -76,7 +76,7 @@ diff --git a/rsync.c b/rsync.c
  extern int am_root;
  extern int am_server;
  extern int am_sender;
-@@ -291,7 +292,8 @@ int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
+@@ -326,7 +327,8 @@ int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
  
        if (iflags & ITEM_TRANSFER) {
                int i = ndx - cur_flist->ndx_start;
index 5a989c8..06f6f58 100644 (file)
@@ -48,7 +48,7 @@ diff --git a/flist.c b/flist.c
  extern int relative_paths;
  extern int implied_dirs;
  extern int file_extra_cnt;
-@@ -345,7 +346,7 @@ int push_pathname(const char *dir, int len)
+@@ -380,7 +381,7 @@ int push_pathname(const char *dir, int len)
  
  static void send_file_entry(int f, struct file_struct *file, int ndx, int first_ndx)
  {
@@ -57,7 +57,7 @@ diff --git a/flist.c b/flist.c
        static mode_t mode;
  #ifdef SUPPORT_FILEFLAGS
        static uint32 fileflags;
-@@ -464,6 +465,13 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
+@@ -499,6 +500,13 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
                xflags |= XMIT_SAME_TIME;
        else
                modtime = file->modtime;
@@ -71,7 +71,7 @@ diff --git a/flist.c b/flist.c
  
  #ifdef SUPPORT_HARD_LINKS
        if (tmp_dev != 0) {
-@@ -534,6 +542,8 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
+@@ -569,6 +577,8 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
                else
                        write_int(f, modtime);
        }
@@ -80,7 +80,7 @@ diff --git a/flist.c b/flist.c
        if (!(xflags & XMIT_SAME_MODE))
                write_int(f, to_wire_mode(mode));
  #ifdef SUPPORT_FILEFLAGS
-@@ -626,7 +636,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
+@@ -661,7 +671,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
  static struct file_struct *recv_file_entry(struct file_list *flist,
                                           int xflags, int f)
  {
@@ -89,7 +89,7 @@ diff --git a/flist.c b/flist.c
        static mode_t mode;
  #ifdef SUPPORT_FILEFLAGS
        static uint32 fileflags;
-@@ -760,6 +770,19 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+@@ -795,6 +805,19 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                } else
                        modtime = read_int(f);
        }
@@ -109,7 +109,7 @@ diff --git a/flist.c b/flist.c
        if (!(xflags & XMIT_SAME_MODE))
                mode = from_wire_mode(read_int(f));
  
-@@ -900,6 +923,8 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+@@ -934,6 +957,8 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                F_GROUP(file) = gid;
                file->flags |= gid_flags;
        }
@@ -118,7 +118,7 @@ diff --git a/flist.c b/flist.c
        if (unsort_ndx)
                F_NDX(file) = flist->used + flist->ndx_start;
  
-@@ -1236,6 +1261,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1275,6 +1300,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
                F_OWNER(file) = st.st_uid;
        if (gid_ndx) /* Check gid_ndx instead of preserve_gid for del support */
                F_GROUP(file) = st.st_gid;
@@ -138,7 +138,7 @@ diff --git a/generator.c b/generator.c
  
  extern int verbose;
  extern int dry_run;
-@@ -41,6 +42,7 @@ extern int preserve_xattrs;
+@@ -40,6 +41,7 @@ extern int preserve_xattrs;
  extern int preserve_links;
  extern int preserve_devices;
  extern int preserve_specials;
@@ -146,7 +146,7 @@ diff --git a/generator.c b/generator.c
  extern int preserve_hard_links;
  extern int preserve_executability;
  extern int preserve_fileflags;
-@@ -612,6 +614,13 @@ int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
+@@ -617,6 +619,13 @@ int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
        if (gid_ndx && !(file->flags & FLAG_SKIP_GROUP) && sxp->st.st_gid != (gid_t)F_GROUP(file))
                return 0;
  
@@ -160,9 +160,9 @@ diff --git a/generator.c b/generator.c
  #ifdef SUPPORT_ACLS
        if (preserve_acls && !S_ISLNK(file->mode)) {
                if (!ACL_READY(*sxp))
-@@ -651,6 +660,12 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+@@ -660,6 +669,12 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+                : iflags & (ITEM_TRANSFER|ITEM_LOCAL_CHANGE) && !(iflags & ITEM_MATCHED)
                  && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
-                || (keep_time && cmp_time(file->modtime, sxp->st.st_mtime) != 0))
                        iflags |= ITEM_REPORT_TIME;
 +              if (crtimes_ndx) {
 +                      if (sxp->crtime == 0)
@@ -173,7 +173,7 @@ diff --git a/generator.c b/generator.c
  #if !defined HAVE_LCHMOD && !defined HAVE_SETATTRLIST
                if (S_ISLNK(file->mode)) {
                        ;
-@@ -1196,6 +1211,7 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx,
+@@ -1207,6 +1222,7 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx,
  static void list_file_entry(struct file_struct *f)
  {
        char permbuf[PERMSTRING_SIZE];
@@ -181,7 +181,7 @@ diff --git a/generator.c b/generator.c
        double len;
  
        if (!F_IS_ACTIVE(f)) {
-@@ -1210,14 +1226,16 @@ static void list_file_entry(struct file_struct *f)
+@@ -1221,14 +1237,16 @@ static void list_file_entry(struct file_struct *f)
  
  #ifdef SUPPORT_LINKS
        if (preserve_links && S_ISLNK(f->mode)) {
@@ -200,19 +200,19 @@ diff --git a/generator.c b/generator.c
                        f_name(f, NULL));
        }
  }
-@@ -1304,6 +1322,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1320,6 +1338,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                        return;
                }
        }
 +      sx.crtime = 0;
  #ifdef SUPPORT_ACLS
        sx.acc_acl = sx.def_acl = NULL;
- #endif
 diff --git a/ifuncs.h b/ifuncs.h
 --- a/ifuncs.h
 +++ b/ifuncs.h
-@@ -57,6 +57,28 @@ from_wire_mode(int mode)
-       return mode;
+@@ -67,6 +67,28 @@ d_name(struct dirent *di)
+ #endif
  }
  
 +static inline time_t
@@ -243,7 +243,7 @@ diff --git a/ifuncs.h b/ifuncs.h
 diff --git a/log.c b/log.c
 --- a/log.c
 +++ b/log.c
-@@ -647,7 +647,8 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
+@@ -653,7 +653,8 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
                        c[8] = !(iflags & ITEM_REPORT_FFLAGS) ? '.' : 'f';
                        c[9] = !(iflags & ITEM_REPORT_ACL) ? '.' : 'a';
                        c[10] = !(iflags & ITEM_REPORT_XATTR) ? '.' : 'x';
@@ -256,7 +256,7 @@ diff --git a/log.c b/log.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -59,6 +59,7 @@ int preserve_specials = 0;
+@@ -60,6 +60,7 @@ int preserve_specials = 0;
  int preserve_uid = 0;
  int preserve_gid = 0;
  int preserve_times = 0;
@@ -264,7 +264,7 @@ diff --git a/options.c b/options.c
  int update_only = 0;
  int cvs_exclude = 0;
  int dry_run = 0;
-@@ -361,6 +362,7 @@ void usage(enum logcode F)
+@@ -362,6 +363,7 @@ void usage(enum logcode F)
    rprintf(F," -D                          same as --devices --specials\n");
    rprintf(F," -t, --times                 preserve modification times\n");
    rprintf(F," -O, --omit-dir-times        omit directories from --times\n");
@@ -272,7 +272,7 @@ diff --git a/options.c b/options.c
    rprintf(F,"     --super                 receiver attempts super-user activities\n");
  #ifdef SUPPORT_XATTRS
    rprintf(F,"     --fake-super            store/recover privileged attrs using xattrs\n");
-@@ -505,6 +507,9 @@ static struct poptOption long_options[] = {
+@@ -508,6 +510,9 @@ static struct poptOption long_options[] = {
    {"times",           't', POPT_ARG_VAL,    &preserve_times, 2, 0, 0 },
    {"no-times",         0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
    {"no-t",             0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
@@ -282,7 +282,7 @@ diff --git a/options.c b/options.c
    {"omit-dir-times",  'O', POPT_ARG_VAL,    &omit_dir_times, 1, 0, 0 },
    {"no-omit-dir-times",0,  POPT_ARG_VAL,    &omit_dir_times, 0, 0, 0 },
    {"no-O",             0,  POPT_ARG_VAL,    &omit_dir_times, 0, 0, 0 },
-@@ -1772,6 +1777,8 @@ void server_options(char **args, int *argc_p)
+@@ -1799,6 +1804,8 @@ void server_options(char **args, int *argc_p)
                argstr[x++] = 'D';
        if (preserve_times)
                argstr[x++] = 't';
@@ -294,8 +294,8 @@ diff --git a/options.c b/options.c
 diff --git a/rsync.c b/rsync.c
 --- a/rsync.c
 +++ b/rsync.c
-@@ -437,6 +437,14 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
-               else if (receiver_symlink_times)
+@@ -472,6 +472,14 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
+               else
                        file->flags |= FLAG_TIME_FAILED;
        }
 +      if (crtimes_ndx && !(flags & ATTRS_SKIP_CRTIME)) {
@@ -309,7 +309,7 @@ diff --git a/rsync.c b/rsync.c
  
        change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
        change_gid = gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
-@@ -580,7 +588,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
+@@ -615,7 +623,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
        /* Change permissions before putting the file into place. */
        set_file_attrs(fnametmp, file, NULL, fnamecmp,
                       ATTRS_DELAY_IMMUTABLE
@@ -318,7 +318,7 @@ diff --git a/rsync.c b/rsync.c
  
        /* move tmp file over real file */
        if (verbose > 2)
-@@ -611,7 +619,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
+@@ -646,7 +654,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
  
    do_set_file_attrs:
        set_file_attrs(fnametmp, file, NULL, fnamecmp,
@@ -338,7 +338,7 @@ diff --git a/rsync.h b/rsync.h
  #define XMIT_SAME_FLAGS (1<<14)               /* protocols ?? - now */
  
  /* These flags are used in the live flist data. */
-@@ -151,6 +152,7 @@
+@@ -153,6 +154,7 @@
  #define ATTRS_REPORT          (1<<0)
  #define ATTRS_SKIP_MTIME      (1<<1)
  #define ATTRS_DELAY_IMMUTABLE (1<<2)
@@ -346,16 +346,16 @@ diff --git a/rsync.h b/rsync.h
  
  #define FULL_FLUSH    1
  #define NORMAL_FLUSH  0
-@@ -167,7 +169,7 @@
+@@ -169,7 +171,7 @@
  #define FNAMECMP_FUZZY                0x83
  
  /* For use by the itemize_changes code */
 -#define ITEM_REPORT_ATIME (1<<0)
 +#define ITEM_REPORT_CRTIME (1<<0)
- #define ITEM_REPORT_CHECKSUM (1<<1)
- #define ITEM_REPORT_SIZE (1<<2)
- #define ITEM_REPORT_TIME (1<<3)
-@@ -645,6 +647,7 @@ extern int file_extra_cnt;
+ #define ITEM_REPORT_CHANGE (1<<1)
+ #define ITEM_REPORT_SIZE (1<<2)     /* regular files only */
+ #define ITEM_REPORT_TIMEFAIL (1<<2) /* symlinks only */
+@@ -647,6 +649,7 @@ extern int file_extra_cnt;
  extern int inc_recurse;
  extern int uid_ndx;
  extern int gid_ndx;
@@ -363,7 +363,7 @@ diff --git a/rsync.h b/rsync.h
  extern int fileflags_ndx;
  extern int acls_ndx;
  extern int xattrs_ndx;
-@@ -652,6 +655,7 @@ extern int xattrs_ndx;
+@@ -654,6 +657,7 @@ extern int xattrs_ndx;
  #define FILE_STRUCT_LEN (offsetof(struct file_struct, basename))
  #define EXTRA_LEN (sizeof (union file_extras))
  #define PTR_EXTRA_CNT ((sizeof (char *) + EXTRA_LEN - 1) / EXTRA_LEN)
@@ -371,7 +371,7 @@ diff --git a/rsync.h b/rsync.h
  #define DEV_EXTRA_CNT 2
  #define DIRNODE_EXTRA_CNT 3
  #define SUM_EXTRA_CNT ((MAX_DIGEST_LEN + EXTRA_LEN - 1) / EXTRA_LEN)
-@@ -910,6 +914,7 @@ typedef struct {
+@@ -912,6 +916,7 @@ typedef struct {
  
  typedef struct {
      STRUCT_STAT st;
@@ -390,7 +390,7 @@ diff --git a/rsync.yo b/rsync.yo
       --super                 receiver attempts super-user activities
       --fake-super            store/recover privileged attrs using xattrs
   -S, --sparse                handle sparse files efficiently
-@@ -1015,6 +1016,9 @@ it is preserving modification times (see bf(--times)).  If NFS is sharing
+@@ -1022,6 +1023,9 @@ it is preserving modification times (see bf(--times)).  If NFS is sharing
  the directories on the receiving side, it is a good idea to use bf(-O).
  This option is inferred if you use bf(--backup) without bf(--backup-dir).
  
@@ -400,7 +400,7 @@ diff --git a/rsync.yo b/rsync.yo
  dit(bf(--super)) This tells the receiving side to attempt super-user
  activities even if the receiving rsync wasn't run by the super-user.  These
  activities include: preserving users via the bf(--owner) option, preserving
-@@ -1667,7 +1671,7 @@ with older versions of rsync, but that also turns on the output of other
+@@ -1674,7 +1678,7 @@ with older versions of rsync, but that also turns on the output of other
  verbose messages).
  
  The "%i" escape has a cryptic output that is 11 letters long.  The general
@@ -409,7 +409,7 @@ diff --git a/rsync.yo b/rsync.yo
  type of update being done, bf(X) is replaced by the file-type, and the
  other letters represent attributes that may be output if they are being
  modified.
-@@ -1721,6 +1725,8 @@ quote(itemization(
+@@ -1733,6 +1737,8 @@ quote(itemization(
    it() The bf(f) means that the fileflags information changed.
    it() The bf(a) means that the ACL information changed.
    it() The bf(x) means that the extended attribute information changed.
@@ -433,8 +433,8 @@ diff --git a/syscall.c b/syscall.c
  #define RETURN_ERROR_IF(x,e) \
        do { \
                if (x) { \
-@@ -403,3 +408,33 @@ char *d_name(struct dirent *di)
-       return di->d_name;
+@@ -394,3 +399,33 @@ OFF_T do_lseek(int fd, OFF_T offset, int whence)
+       return lseek(fd, offset, whence);
  #endif
  }
 +
index b022296..6791054 100644 (file)
@@ -11,7 +11,7 @@ To use this patch, run these commands for a successful build:
 diff --git a/exclude.c b/exclude.c
 --- a/exclude.c
 +++ b/exclude.c
-@@ -213,6 +213,8 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
+@@ -239,6 +239,8 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
                if (!(lp = new_array(struct filter_list_struct, 1)))
                        out_of_memory("add_rule");
                lp->head = lp->tail = NULL;
@@ -20,7 +20,7 @@ diff --git a/exclude.c b/exclude.c
                if (asprintf(&lp->debug_type, " [per-dir %s]", cp) < 0)
                        out_of_memory("add_rule");
                ret->u.mergelist = lp;
-@@ -445,6 +447,14 @@ void *push_local_filters(const char *dir, unsigned int dirlen)
+@@ -469,6 +471,14 @@ void *push_local_filters(const char *dir, unsigned int dirlen)
                                set_filter_dir(dir, dirlen);
                }
  
@@ -35,7 +35,7 @@ diff --git a/exclude.c b/exclude.c
                if (strlcpy(dirbuf + dirbuf_len, ex->pattern,
                    MAXPATHLEN - dirbuf_len) < MAXPATHLEN - dirbuf_len) {
                        parse_filter_file(lp, dirbuf, ex->match_flags,
-@@ -1004,6 +1014,7 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
+@@ -1029,6 +1039,7 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
        char line[BIGPATHBUFLEN];
        char *eob = line + sizeof line - 1;
        int word_split = mflags & MATCHFLG_WORD_SPLIT;
@@ -43,7 +43,7 @@ diff --git a/exclude.c b/exclude.c
  
        if (!fname || !*fname)
                return;
-@@ -1050,6 +1061,24 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
+@@ -1075,6 +1086,24 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
                                }
                                break;
                        }
@@ -68,7 +68,7 @@ diff --git a/exclude.c b/exclude.c
                        if (word_split && isspace(ch))
                                break;
                        if (eol_nulls? !ch : (ch == '\n' || ch == '\r'))
-@@ -1059,13 +1088,15 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
+@@ -1084,13 +1113,15 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
                        else
                                overflow = 1;
                }
@@ -88,11 +88,11 @@ diff --git a/exclude.c b/exclude.c
 diff --git a/rsync.h b/rsync.h
 --- a/rsync.h
 +++ b/rsync.h
-@@ -146,6 +146,7 @@
- #define XFLG_OLD_PREFIXES     (1<<1)
- #define XFLG_ANCHORED2ABS     (1<<2)
- #define XFLG_ABS_IF_SLASH     (1<<3)
-+#define XFLG_CVS_ENTRIES      (1<<4)
+@@ -148,6 +148,7 @@
+ #define XFLG_ANCHORED2ABS     (1<<2) /* leading slash indicates absolute */
+ #define XFLG_ABS_IF_SLASH     (1<<3) /* leading or interior slash is absolute */
+ #define XFLG_DIR2WILD3                (1<<4) /* dir/ match gets trailing *** added */
++#define XFLG_CVS_ENTRIES      (1<<5)
  
  #define ATTRS_REPORT          (1<<0)
  #define ATTRS_SKIP_MTIME      (1<<1)
index f9dcb98..a63f60d 100644 (file)
@@ -17,7 +17,7 @@ To use this patch, run these commands for a successful build:
 diff --git a/generator.c b/generator.c
 --- a/generator.c
 +++ b/generator.c
-@@ -63,6 +63,7 @@ extern int append_mode;
+@@ -62,6 +62,7 @@ extern int append_mode;
  extern int make_backups;
  extern int csum_length;
  extern int ignore_times;
@@ -25,7 +25,7 @@ diff --git a/generator.c b/generator.c
  extern int size_only;
  extern OFF_T max_size;
  extern OFF_T min_size;
-@@ -696,6 +697,9 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+@@ -708,6 +709,9 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
  /* Perform our quick-check heuristic for determining if a file is unchanged. */
  int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st)
  {
@@ -38,7 +38,7 @@ diff --git a/generator.c b/generator.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -105,6 +105,7 @@ int keep_partial = 0;
+@@ -106,6 +106,7 @@ int keep_partial = 0;
  int safe_symlinks = 0;
  int copy_unsafe_links = 0;
  int size_only = 0;
@@ -46,7 +46,7 @@ diff --git a/options.c b/options.c
  int daemon_bwlimit = 0;
  int bwlimit = 0;
  int fuzzy_basis = 0;
-@@ -387,6 +388,7 @@ void usage(enum logcode F)
+@@ -388,6 +389,7 @@ void usage(enum logcode F)
    rprintf(F,"     --contimeout=SECONDS    set daemon connection timeout in seconds\n");
    rprintf(F," -I, --ignore-times          don't skip files that match in size and mod-time\n");
    rprintf(F,"     --size-only             skip files that match in size\n");
@@ -54,7 +54,7 @@ diff --git a/options.c b/options.c
    rprintf(F,"     --modify-window=NUM     compare mod-times with reduced accuracy\n");
    rprintf(F," -T, --temp-dir=DIR          create temporary files in directory DIR\n");
    rprintf(F," -y, --fuzzy                 find similar file for basis if no dest file\n");
-@@ -527,6 +529,7 @@ static struct poptOption long_options[] = {
+@@ -530,6 +532,7 @@ static struct poptOption long_options[] = {
    {"chmod",            0,  POPT_ARG_STRING, 0, OPT_CHMOD, 0, 0 },
    {"ignore-times",    'I', POPT_ARG_NONE,   &ignore_times, 0, 0, 0 },
    {"size-only",        0,  POPT_ARG_NONE,   &size_only, 0, 0, 0 },
@@ -62,7 +62,7 @@ diff --git a/options.c b/options.c
    {"one-file-system", 'x', POPT_ARG_NONE,   0, 'x', 0, 0 },
    {"no-one-file-system",'x',POPT_ARG_VAL,   &one_file_system, 0, 0, 0 },
    {"no-x",            'x', POPT_ARG_VAL,    &one_file_system, 0, 0, 0 },
-@@ -1927,6 +1930,9 @@ void server_options(char **args, int *argc_p)
+@@ -1953,6 +1956,9 @@ void server_options(char **args, int *argc_p)
                }
        }
  
index 7be49e2..6eab0df 100644 (file)
@@ -23,7 +23,7 @@ switches to --detect-moved blindly accepts the staged file.
 diff --git a/generator.c b/generator.c
 --- a/generator.c
 +++ b/generator.c
-@@ -196,7 +196,9 @@ static int fattr_find(struct file_struct *f, char *fname)
+@@ -200,7 +200,9 @@ static int fattr_find(struct file_struct *f, char *fname)
                                continue;
                        }
                }
@@ -34,7 +34,7 @@ diff --git a/generator.c b/generator.c
                diff = u_strcmp(fmid->basename, f->basename);
                if (diff == 0) {
                        good_match = mid;
-@@ -1927,6 +1929,21 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1961,6 +1963,21 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                fnamecmp = partialptr;
                fnamecmp_type = FNAMECMP_PARTIAL_DIR;
                statret = 0;
@@ -59,7 +59,7 @@ diff --git a/generator.c b/generator.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -392,6 +392,8 @@ void usage(enum logcode F)
+@@ -393,6 +393,8 @@ void usage(enum logcode F)
    rprintf(F," -T, --temp-dir=DIR          create temporary files in directory DIR\n");
    rprintf(F," -y, --fuzzy                 find similar file for basis if no dest file\n");
    rprintf(F,"     --detect-renamed        try to find renamed files to speed up the transfer\n");
@@ -68,7 +68,7 @@ diff --git a/options.c b/options.c
    rprintf(F,"     --compare-dest=DIR      also compare destination files relative to DIR\n");
    rprintf(F,"     --copy-dest=DIR         ... and include copies of unchanged files\n");
    rprintf(F,"     --link-dest=DIR         hardlink to files in DIR when unchanged\n");
-@@ -572,7 +574,9 @@ static struct poptOption long_options[] = {
+@@ -580,7 +582,9 @@ static struct poptOption long_options[] = {
    {"compare-dest",     0,  POPT_ARG_STRING, 0, OPT_COMPARE_DEST, 0, 0 },
    {"copy-dest",        0,  POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 },
    {"link-dest",        0,  POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 },
@@ -76,10 +76,10 @@ diff --git a/options.c b/options.c
 +  {"detect-renamed",   0,  POPT_ARG_VAL,    &detect_renamed, 1, 0, 0 },
 +  {"detect-renamed-lax",0, POPT_ARG_VAL,    &detect_renamed, 2, 0, 0 },
 +  {"detect-moved",     0,  POPT_ARG_VAL,    &detect_renamed, 3, 0, 0 },
-   {"fuzzy",           'y', POPT_ARG_NONE,   &fuzzy_basis, 0, 0, 0 },
-   {"compress",        'z', POPT_ARG_NONE,   0, 'z', 0, 0 },
-   {"no-compress",      0,  POPT_ARG_VAL,    &do_compression, 0, 0, 0 },
-@@ -1923,8 +1927,14 @@ void server_options(char **args, int *argc_p)
+   {"fuzzy",           'y', POPT_ARG_VAL,    &fuzzy_basis, 1, 0, 0 },
+   {"no-fuzzy",         0,  POPT_ARG_VAL,    &fuzzy_basis, 0, 0, 0 },
+   {"no-y",             0,  POPT_ARG_VAL,    &fuzzy_basis, 0, 0, 0 },
+@@ -1949,8 +1953,14 @@ void server_options(char **args, int *argc_p)
                        args[ac++] = "--super";
                if (size_only)
                        args[ac++] = "--size-only";
@@ -108,7 +108,7 @@ diff --git a/rsync.yo b/rsync.yo
       --compare-dest=DIR      also compare received files relative to DIR
       --copy-dest=DIR         ... and include copies of unchanged files
       --link-dest=DIR         hardlink to files in DIR when unchanged
-@@ -1483,6 +1485,17 @@ the bf(--partial-dir) option, that directory will be used instead.  These
+@@ -1490,6 +1492,17 @@ the bf(--partial-dir) option, that directory will be used instead.  These
  potential alternate-basis files will be removed as the transfer progresses.
  This option conflicts with bf(--inplace) and bf(--append).
  
index 1243447..4a47233 100644 (file)
@@ -71,7 +71,7 @@ diff --git a/flist.c b/flist.c
  static char empty_sum[MAX_DIGEST_LEN];
  static int flist_count_offset; /* for --delete --progress */
  static int dir_count = 0;
-@@ -263,6 +266,45 @@ static int is_excluded(char *fname, int is_dir, int filter_level)
+@@ -298,6 +301,45 @@ static int is_excluded(const char *fname, int is_dir, int filter_level)
        return 0;
  }
  
@@ -117,7 +117,7 @@ diff --git a/flist.c b/flist.c
  static void send_directory(int f, struct file_list *flist,
                           char *fbuf, int len, int flags);
  
-@@ -2180,6 +2222,25 @@ struct file_list *recv_file_list(int f)
+@@ -2235,6 +2277,25 @@ struct file_list *recv_file_list(int f)
  
        flist_sort_and_clean(flist, relative_paths);
  
@@ -146,7 +146,7 @@ diff --git a/flist.c b/flist.c
 diff --git a/generator.c b/generator.c
 --- a/generator.c
 +++ b/generator.c
-@@ -81,6 +81,7 @@ extern char *basis_dir[];
+@@ -80,6 +80,7 @@ extern char *basis_dir[];
  extern int compare_dest;
  extern int copy_dest;
  extern int link_dest;
@@ -154,15 +154,15 @@ diff --git a/generator.c b/generator.c
  extern int whole_file;
  extern int list_only;
  extern int read_batch;
-@@ -99,6 +100,7 @@ extern char *backup_suffix;
+@@ -98,6 +99,7 @@ extern char *backup_suffix;
  extern int backup_suffix_len;
  extern struct file_list *cur_flist, *first_flist, *dir_flist;
- extern struct filter_list_struct server_filter_list;
+ extern struct filter_list_struct daemon_filter_list;
 +extern struct file_list the_fattr_list;
  
  int ignore_perishable = 0;
  int non_perishable_cnt = 0;
-@@ -106,6 +108,7 @@ int maybe_ATTRS_REPORT = 0;
+@@ -105,6 +107,7 @@ int maybe_ATTRS_REPORT = 0;
  
  static dev_t dev_zero;
  static int deletion_count = 0; /* used to implement --max-delete */
@@ -187,7 +187,7 @@ diff --git a/generator.c b/generator.c
  
  #define DEL_MAKE_ROOM (DEL_FOR_FILE|DEL_FOR_DIR|DEL_FOR_SYMLINK|DEL_FOR_DEVICE|DEL_FOR_SPECIAL)
  
-@@ -144,11 +148,121 @@ static int is_backup_file(char *fn)
+@@ -148,11 +152,121 @@ static int is_backup_file(char *fn)
        return k > 0 && strcmp(fn+k, backup_suffix) == 0;
  }
  
@@ -309,7 +309,7 @@ diff --git a/generator.c b/generator.c
   */
  static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
  {
-@@ -182,6 +296,8 @@ static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
+@@ -186,6 +300,8 @@ static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
                        goto check_ret;
                /* OK: try to delete the directory. */
        }
@@ -318,7 +318,7 @@ diff --git a/generator.c b/generator.c
  
        if (!(flags & DEL_MAKE_ROOM) && max_delete >= 0 && ++deletion_count > max_delete)
                return DR_AT_LIMIT;
-@@ -237,6 +353,8 @@ static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
+@@ -241,6 +357,8 @@ static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
   * 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.)
@@ -327,7 +327,7 @@ diff --git a/generator.c b/generator.c
   */
  static enum delret delete_dir_contents(char *fname, uint16 flags)
  {
-@@ -256,7 +374,9 @@ static enum delret delete_dir_contents(char *fname, uint16 flags)
+@@ -260,7 +378,9 @@ static enum delret delete_dir_contents(char *fname, uint16 flags)
        save_filters = push_local_filters(fname, dlen);
  
        non_perishable_cnt = 0;
@@ -337,7 +337,7 @@ diff --git a/generator.c b/generator.c
        ret = non_perishable_cnt ? DR_NOT_EMPTY : DR_SUCCESS;
  
        if (!dirlist->used)
-@@ -296,7 +416,8 @@ static enum delret delete_dir_contents(char *fname, uint16 flags)
+@@ -300,7 +420,8 @@ static enum delret delete_dir_contents(char *fname, uint16 flags)
                if (S_ISDIR(fp->mode)) {
                        if (delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS)
                                ret = DR_NOT_EMPTY;
@@ -347,7 +347,7 @@ diff --git a/generator.c b/generator.c
                if (delete_item(fname, fp->mode, flags) != DR_SUCCESS)
                        ret = DR_NOT_EMPTY;
        }
-@@ -461,13 +582,18 @@ static void do_delayed_deletions(char *delbuf)
+@@ -465,13 +586,18 @@ static void do_delayed_deletions(char *delbuf)
   * all the --delete-WHEN options.  Note that the fbuf pointer must point to a
   * MAXPATHLEN buffer with the name of the directory in it (the functions we
   * call will append names onto the end, but the old dir value will be restored
@@ -370,7 +370,7 @@ diff --git a/generator.c b/generator.c
        int save_uid_ndx = uid_ndx;
  
        if (!fbuf) {
-@@ -482,17 +608,22 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
+@@ -486,17 +612,22 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
                maybe_send_keepalive();
  
        if (io_error && !ignore_errors) {
@@ -398,7 +398,7 @@ diff --git a/generator.c b/generator.c
        if (one_file_system) {
                if (file->flags & FLAG_TOP_DIR)
                        filesystem_dev = *fs_dev;
-@@ -505,6 +636,14 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
+@@ -509,6 +640,14 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
  
        dirlist = get_dirlist(fbuf, dlen, 0);
  
@@ -413,7 +413,7 @@ diff --git a/generator.c b/generator.c
        /* If an item in dirlist is not found in flist, delete it
         * from the filesystem. */
        for (i = dirlist->used; i--; ) {
-@@ -517,19 +656,28 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
+@@ -521,19 +660,28 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
                                        f_name(fp, NULL));
                        continue;
                }
@@ -446,7 +446,7 @@ diff --git a/generator.c b/generator.c
        flist_free(dirlist);
  
        if (!save_uid_ndx) {
-@@ -564,9 +712,9 @@ static void do_delete_pass(void)
+@@ -568,9 +716,9 @@ static void do_delete_pass(void)
                 || !S_ISDIR(st.st_mode))
                        continue;
  
@@ -458,7 +458,7 @@ diff --git a/generator.c b/generator.c
  
        if (do_progress && !am_server)
                rprintf(FINFO, "                    \r");
-@@ -1199,6 +1347,7 @@ static void list_file_entry(struct file_struct *f)
+@@ -1210,6 +1358,7 @@ static void list_file_entry(struct file_struct *f)
        }
  }
  
@@ -466,13 +466,13 @@ diff --git a/generator.c b/generator.c
  static int phase = 0;
  static int dflt_perms;
  
-@@ -1449,8 +1598,12 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1480,8 +1629,12 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                        }
                }
-               else if (delete_during && f_out != -1 && !phase && dry_run < 2
--                  && (file->flags & FLAG_CONTENT_DIR))
+               else if (delete_during && f_out != -1 && !phase
+-                  && BITS_SETnUNSET(file->flags, FLAG_CONTENT_DIR, FLAG_MISSING_DIR))
 -                      delete_in_dir(fname, file, &real_sx.st.st_dev);
-+                  && (file->flags & FLAG_CONTENT_DIR)) {
++                  && BITS_SETnUNSET(file->flags, FLAG_CONTENT_DIR, FLAG_MISSING_DIR)) {
 +                      if (detect_renamed && real_ret != 0)
 +                              unexplored_dirs++;
 +                      delete_in_dir(fname, file, &real_sx.st.st_dev,
@@ -481,7 +481,7 @@ diff --git a/generator.c b/generator.c
                goto cleanup;
        }
  
-@@ -1728,8 +1881,14 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1757,8 +1910,14 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                        goto cleanup;
                }
  #endif
@@ -497,7 +497,7 @@ diff --git a/generator.c b/generator.c
                rsyserr(FERROR_XFER, stat_errno, "recv_generator: failed to stat %s",
                        full_fname(fname));
                goto cleanup;
-@@ -2072,6 +2231,12 @@ void generate_files(int f_out, const char *local_name)
+@@ -2135,6 +2294,12 @@ void generate_files(int f_out, const char *local_name)
        if (verbose > 2)
                rprintf(FINFO, "generator starting pid=%ld\n", (long)getpid());
  
@@ -510,7 +510,7 @@ diff --git a/generator.c b/generator.c
        if (delete_before && !solo_file && cur_flist->used > 0)
                do_delete_pass();
        if (delete_during == 2) {
-@@ -2082,7 +2247,7 @@ void generate_files(int f_out, const char *local_name)
+@@ -2145,7 +2310,7 @@ void generate_files(int f_out, const char *local_name)
        }
        do_progress = 0;
  
@@ -519,7 +519,7 @@ diff --git a/generator.c b/generator.c
                whole_file = 0;
        if (verbose >= 2) {
                rprintf(FINFO, "delta-transmission %s\n",
-@@ -2120,7 +2285,7 @@ void generate_files(int f_out, const char *local_name)
+@@ -2183,7 +2348,7 @@ void generate_files(int f_out, const char *local_name)
                                                dirdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
                                        } else
                                                dirdev = MAKEDEV(0, 0);
@@ -528,7 +528,7 @@ diff --git a/generator.c b/generator.c
                                }
                        }
                }
-@@ -2163,7 +2328,21 @@ void generate_files(int f_out, const char *local_name)
+@@ -2226,7 +2391,21 @@ void generate_files(int f_out, const char *local_name)
        } while ((cur_flist = cur_flist->next) != NULL);
  
        if (delete_during)
@@ -554,7 +554,7 @@ diff --git a/generator.c b/generator.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -81,6 +81,7 @@ int am_generator = 0;
+@@ -82,6 +82,7 @@ int am_generator = 0;
  int am_starting_up = 1;
  int relative_paths = -1;
  int implied_dirs = 1;
@@ -562,7 +562,7 @@ diff --git a/options.c b/options.c
  int numeric_ids = 0;
  int allow_8bit_chars = 0;
  int force_delete = 0;
-@@ -390,6 +391,7 @@ void usage(enum logcode F)
+@@ -391,6 +392,7 @@ void usage(enum logcode F)
    rprintf(F,"     --modify-window=NUM     compare mod-times with reduced accuracy\n");
    rprintf(F," -T, --temp-dir=DIR          create temporary files in directory DIR\n");
    rprintf(F," -y, --fuzzy                 find similar file for basis if no dest file\n");
@@ -570,15 +570,15 @@ diff --git a/options.c b/options.c
    rprintf(F,"     --compare-dest=DIR      also compare destination files relative to DIR\n");
    rprintf(F,"     --copy-dest=DIR         ... and include copies of unchanged files\n");
    rprintf(F,"     --link-dest=DIR         hardlink to files in DIR when unchanged\n");
-@@ -570,6 +572,7 @@ static struct poptOption long_options[] = {
+@@ -578,6 +580,7 @@ static struct poptOption long_options[] = {
    {"compare-dest",     0,  POPT_ARG_STRING, 0, OPT_COMPARE_DEST, 0, 0 },
    {"copy-dest",        0,  POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 },
    {"link-dest",        0,  POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 },
 +  {"detect-renamed",   0,  POPT_ARG_NONE,   &detect_renamed, 0, 0, 0 },
-   {"fuzzy",           'y', POPT_ARG_NONE,   &fuzzy_basis, 0, 0, 0 },
-   {"compress",        'z', POPT_ARG_NONE,   0, 'z', 0, 0 },
-   {"no-compress",      0,  POPT_ARG_VAL,    &do_compression, 0, 0, 0 },
-@@ -1564,7 +1567,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+   {"fuzzy",           'y', POPT_ARG_VAL,    &fuzzy_basis, 1, 0, 0 },
+   {"no-fuzzy",         0,  POPT_ARG_VAL,    &fuzzy_basis, 0, 0, 0 },
+   {"no-y",             0,  POPT_ARG_VAL,    &fuzzy_basis, 0, 0, 0 },
+@@ -1590,7 +1593,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                inplace = 1;
        }
  
@@ -587,7 +587,7 @@ diff --git a/options.c b/options.c
                partial_dir = tmp_partialdir;
  
        if (inplace) {
-@@ -1573,6 +1576,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1599,6 +1602,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                        snprintf(err_buf, sizeof err_buf,
                                 "--%s cannot be used with --%s\n",
                                 append_mode ? "append" : "inplace",
@@ -595,7 +595,7 @@ diff --git a/options.c b/options.c
                                 delay_updates ? "delay-updates" : "partial-dir");
                        return 0;
                }
-@@ -1919,6 +1923,8 @@ void server_options(char **args, int *argc_p)
+@@ -1945,6 +1949,8 @@ void server_options(char **args, int *argc_p)
                        args[ac++] = "--super";
                if (size_only)
                        args[ac++] = "--size-only";
@@ -615,7 +615,7 @@ diff --git a/rsync.yo b/rsync.yo
       --compare-dest=DIR      also compare received files relative to DIR
       --copy-dest=DIR         ... and include copies of unchanged files
       --link-dest=DIR         hardlink to files in DIR when unchanged
-@@ -1467,6 +1468,21 @@ Note that the use of the bf(--delete) option might get rid of any potential
+@@ -1474,6 +1475,21 @@ Note that the use of the bf(--delete) option might get rid of any potential
  fuzzy-match files, so either use bf(--delete-after) or specify some
  filename exclusions if you need to prevent this.
  
@@ -640,7 +640,7 @@ diff --git a/rsync.yo b/rsync.yo
 diff --git a/util.c b/util.c
 --- a/util.c
 +++ b/util.c
-@@ -1022,6 +1022,32 @@ int handle_partial_dir(const char *fname, int create)
+@@ -1112,6 +1112,32 @@ int handle_partial_dir(const char *fname, int create)
        return 1;
  }
  
index 36683c0..e40213b 100644 (file)
@@ -10,7 +10,7 @@ To use this patch, run these commands for a successful build:
 diff --git a/generator.c b/generator.c
 --- a/generator.c
 +++ b/generator.c
-@@ -56,6 +56,7 @@ extern int ignore_errors;
+@@ -55,6 +55,7 @@ extern int ignore_errors;
  extern int remove_source_files;
  extern int delay_updates;
  extern int update_only;
@@ -18,7 +18,7 @@ diff --git a/generator.c b/generator.c
  extern int ignore_existing;
  extern int ignore_non_existing;
  extern int inplace;
-@@ -1669,6 +1670,13 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1698,6 +1699,13 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                goto cleanup;
        }
  
@@ -32,7 +32,7 @@ diff --git a/generator.c b/generator.c
        fnamecmp = fname;
        fnamecmp_type = FNAMECMP_FNAME;
  
-@@ -1985,6 +1993,7 @@ void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
+@@ -2045,6 +2053,7 @@ void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
                        ignore_existing = -ignore_existing;
                        ignore_non_existing = -ignore_non_existing;
                        update_only = -update_only;
@@ -40,7 +40,7 @@ diff --git a/generator.c b/generator.c
                        always_checksum = -always_checksum;
                        size_only = -size_only;
                        append_mode = -append_mode;
-@@ -2010,6 +2019,7 @@ void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
+@@ -2070,6 +2079,7 @@ void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
                        ignore_existing = -ignore_existing;
                        ignore_non_existing = -ignore_non_existing;
                        update_only = -update_only;
@@ -51,7 +51,7 @@ diff --git a/generator.c b/generator.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -59,6 +59,7 @@ int preserve_uid = 0;
+@@ -60,6 +60,7 @@ int preserve_uid = 0;
  int preserve_gid = 0;
  int preserve_times = 0;
  int update_only = 0;
@@ -59,7 +59,7 @@ diff --git a/options.c b/options.c
  int cvs_exclude = 0;
  int dry_run = 0;
  int do_xfers = 1;
-@@ -325,6 +326,7 @@ void usage(enum logcode F)
+@@ -326,6 +327,7 @@ void usage(enum logcode F)
    rprintf(F,"     --backup-dir=DIR        make backups into hierarchy based in DIR\n");
    rprintf(F,"     --suffix=SUFFIX         set backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX);
    rprintf(F," -u, --update                skip files that are newer on the receiver\n");
@@ -67,7 +67,7 @@ diff --git a/options.c b/options.c
    rprintf(F,"     --inplace               update destination files in-place (SEE MAN PAGE)\n");
    rprintf(F,"     --append                append data onto shorter files\n");
    rprintf(F,"     --append-verify         like --append, but with old data in file checksum\n");
-@@ -531,6 +533,7 @@ static struct poptOption long_options[] = {
+@@ -534,6 +536,7 @@ static struct poptOption long_options[] = {
    {"no-one-file-system",'x',POPT_ARG_VAL,   &one_file_system, 0, 0, 0 },
    {"no-x",            'x', POPT_ARG_VAL,    &one_file_system, 0, 0, 0 },
    {"update",          'u', POPT_ARG_NONE,   &update_only, 0, 0, 0 },
index aca5d63..79177e7 100644 (file)
@@ -97,7 +97,7 @@ diff --git a/cleanup.c b/cleanup.c
 diff --git a/configure.in b/configure.in
 --- a/configure.in
 +++ b/configure.in
-@@ -552,7 +552,7 @@ AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
+@@ -554,7 +554,7 @@ AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
      strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
      setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \
      strerror putenv iconv_open locale_charset nl_langinfo getxattr \
@@ -139,7 +139,7 @@ diff --git a/generator.c b/generator.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -59,6 +59,7 @@ int preserve_uid = 0;
+@@ -60,6 +60,7 @@ int preserve_uid = 0;
  int preserve_gid = 0;
  int preserve_times = 0;
  int update_only = 0;
@@ -147,7 +147,7 @@ diff --git a/options.c b/options.c
  int cvs_exclude = 0;
  int dry_run = 0;
  int do_xfers = 1;
-@@ -325,6 +326,9 @@ void usage(enum logcode F)
+@@ -326,6 +327,9 @@ void usage(enum logcode F)
    rprintf(F,"     --backup-dir=DIR        make backups into hierarchy based in DIR\n");
    rprintf(F,"     --suffix=SUFFIX         set backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX);
    rprintf(F," -u, --update                skip files that are newer on the receiver\n");
@@ -157,7 +157,7 @@ diff --git a/options.c b/options.c
    rprintf(F,"     --inplace               update destination files in-place (SEE MAN PAGE)\n");
    rprintf(F,"     --append                append data onto shorter files\n");
    rprintf(F,"     --append-verify         like --append, but with old data in file checksum\n");
-@@ -531,6 +535,9 @@ static struct poptOption long_options[] = {
+@@ -534,6 +538,9 @@ static struct poptOption long_options[] = {
    {"no-one-file-system",'x',POPT_ARG_VAL,   &one_file_system, 0, 0, 0 },
    {"no-x",            'x', POPT_ARG_VAL,    &one_file_system, 0, 0, 0 },
    {"update",          'u', POPT_ARG_NONE,   &update_only, 0, 0, 0 },
@@ -167,7 +167,7 @@ diff --git a/options.c b/options.c
    {"existing",         0,  POPT_ARG_NONE,   &ignore_non_existing, 0, 0, 0 },
    {"ignore-non-existing",0,POPT_ARG_NONE,   &ignore_non_existing, 0, 0, 0 },
    {"ignore-existing",  0,  POPT_ARG_NONE,   &ignore_existing, 0, 0, 0 },
-@@ -1693,6 +1700,11 @@ void server_options(char **args, int *argc_p)
+@@ -1719,6 +1726,11 @@ void server_options(char **args, int *argc_p)
        if (!am_sender)
                args[ac++] = "--sender";
  
@@ -204,7 +204,7 @@ diff --git a/rsync.yo b/rsync.yo
   -n, --dry-run               perform a trial run with no changes made
   -W, --whole-file            copy files whole (w/o delta-xfer algorithm)
   -x, --one-file-system       don't cross filesystem boundaries
-@@ -1036,6 +1037,10 @@ NOTE: Don't use this option when the destination is a Solaris "tmpfs"
+@@ -1043,6 +1044,10 @@ NOTE: Don't use this option when the destination is a Solaris "tmpfs"
  filesystem. It doesn't seem to handle seeks over null regions
  correctly and ends up corrupting the files.
  
index eead498..1617794 100644 (file)
@@ -20,7 +20,7 @@ diff --git a/Makefile.in b/Makefile.in
  
  # Programs we must have to run the test cases
  CHECK_PROGS = rsync$(EXEEXT) tls$(EXEEXT) getgroups$(EXEEXT) getfsdev$(EXEEXT) \
-@@ -105,7 +105,7 @@ getgroups$(EXEEXT): getgroups.o
+@@ -107,7 +107,7 @@ getgroups$(EXEEXT): getgroups.o
  getfsdev$(EXEEXT): getfsdev.o
        $(CC) $(CFLAGS) $(LDFLAGS) -o $@ getfsdev.o $(LIBS)
  
@@ -65,8 +65,8 @@ diff --git a/compat.c b/compat.c
 diff --git a/configure.in b/configure.in
 --- a/configure.in
 +++ b/configure.in
-@@ -551,7 +551,7 @@ AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
-     memmove lchown vsnprintf snprintf vasprintf asprintf setsid glob strpbrk \
+@@ -553,7 +553,7 @@ AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
+     memmove lchown vsnprintf snprintf vasprintf asprintf setsid strpbrk \
      strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
      setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \
 -    strerror putenv iconv_open locale_charset nl_langinfo getxattr \
@@ -85,7 +85,7 @@ diff --git a/flist.c b/flist.c
  extern int uid_ndx;
  extern int gid_ndx;
  extern int eol_nulls;
-@@ -346,6 +347,9 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
+@@ -381,6 +382,9 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
  {
        static time_t modtime;
        static mode_t mode;
@@ -95,7 +95,7 @@ diff --git a/flist.c b/flist.c
  #ifdef SUPPORT_HARD_LINKS
        static int64 dev;
  #endif
-@@ -405,6 +409,14 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
+@@ -440,6 +444,14 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
                xflags |= XMIT_SAME_MODE;
        else
                mode = file->mode;
@@ -110,7 +110,7 @@ diff --git a/flist.c b/flist.c
  
        if ((preserve_devices && IS_DEVICE(mode))
         || (preserve_specials && IS_SPECIAL(mode))) {
-@@ -524,6 +536,10 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
+@@ -559,6 +571,10 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
        }
        if (!(xflags & XMIT_SAME_MODE))
                write_int(f, to_wire_mode(mode));
@@ -121,7 +121,7 @@ diff --git a/flist.c b/flist.c
        if (preserve_uid && !(xflags & XMIT_SAME_UID)) {
                if (protocol_version < 30)
                        write_int(f, uid);
-@@ -612,6 +628,9 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+@@ -647,6 +663,9 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
  {
        static int64 modtime;
        static mode_t mode;
@@ -131,7 +131,7 @@ diff --git a/flist.c b/flist.c
  #ifdef SUPPORT_HARD_LINKS
        static int64 dev;
  #endif
-@@ -746,6 +765,10 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+@@ -781,6 +800,10 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
  
        if (chmod_modes && !S_ISLNK(mode))
                mode = tweak_mode(mode, chmod_modes);
@@ -142,7 +142,7 @@ diff --git a/flist.c b/flist.c
  
        if (preserve_uid && !(xflags & XMIT_SAME_UID)) {
                if (protocol_version < 30)
-@@ -867,6 +890,10 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+@@ -901,6 +924,10 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                OPT_EXTRA(file, 0)->unum = (uint32)(file_length >> 32);
        }
        file->mode = mode;
@@ -153,7 +153,7 @@ diff --git a/flist.c b/flist.c
        if (preserve_uid)
                F_OWNER(file) = uid;
        if (preserve_gid) {
-@@ -1201,6 +1228,10 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1240,6 +1267,10 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
                OPT_EXTRA(file, 0)->unum = (uint32)(st.st_size >> 32);
        }
        file->mode = st.st_mode;
@@ -167,7 +167,7 @@ diff --git a/flist.c b/flist.c
 diff --git a/generator.c b/generator.c
 --- a/generator.c
 +++ b/generator.c
-@@ -43,8 +43,10 @@ extern int preserve_devices;
+@@ -42,8 +42,10 @@ extern int preserve_devices;
  extern int preserve_specials;
  extern int preserve_hard_links;
  extern int preserve_executability;
@@ -178,7 +178,7 @@ diff --git a/generator.c b/generator.c
  extern int uid_ndx;
  extern int gid_ndx;
  extern int delete_mode;
-@@ -162,7 +164,7 @@ static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
+@@ -166,7 +168,7 @@ static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
        }
  
        if (flags & DEL_NO_UID_WRITE)
@@ -187,7 +187,7 @@ diff --git a/generator.c b/generator.c
  
        if (S_ISDIR(mode) && !(flags & DEL_DIR_IS_EMPTY)) {
                int save_uid_ndx = uid_ndx;
-@@ -170,6 +172,13 @@ static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
+@@ -174,6 +176,13 @@ static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
                 * delete_dir_contents() always calls us w/DEL_DIR_IS_EMPTY. */
                if (!uid_ndx)
                        uid_ndx = ++file_extra_cnt;
@@ -201,7 +201,7 @@ diff --git a/generator.c b/generator.c
                ignore_perishable = 1;
                /* If DEL_RECURSE is not set, this just reports emptiness. */
                ret = delete_dir_contents(fbuf, flags);
-@@ -290,8 +299,12 @@ static enum delret delete_dir_contents(char *fname, uint16 flags)
+@@ -294,8 +303,12 @@ static enum delret delete_dir_contents(char *fname, uint16 flags)
                }
  
                strlcpy(p, fp->basename, remainder);
@@ -215,8 +215,8 @@ diff --git a/generator.c b/generator.c
                /* Save stack by recursing to ourself directly. */
                if (S_ISDIR(fp->mode)) {
                        if (delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS)
-@@ -585,6 +598,11 @@ int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
-       if (preserve_perms && !BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
+@@ -593,6 +606,11 @@ int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
+        && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0)))
                return 0;
  
 +#ifdef SUPPORT_FILEFLAGS
@@ -224,10 +224,10 @@ diff --git a/generator.c b/generator.c
 +              return 0;
 +#endif
 +
-       if (preserve_executability && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0)))
+       if (am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file))
                return 0;
  
-@@ -646,6 +664,11 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+@@ -658,6 +676,11 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
                if (gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
                    && sxp->st.st_gid != (gid_t)F_GROUP(file))
                        iflags |= ITEM_REPORT_GROUP;
@@ -239,7 +239,7 @@ diff --git a/generator.c b/generator.c
  #ifdef SUPPORT_ACLS
                if (preserve_acls && !S_ISLNK(file->mode)) {
                        if (!ACL_READY(*sxp))
-@@ -1391,6 +1414,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1423,6 +1446,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                        file->mode = dest_mode(file->mode, sx.st.st_mode,
                                               dflt_perms, statret == 0);
                }
@@ -250,7 +250,7 @@ diff --git a/generator.c b/generator.c
                if (statret != 0 && basis_dir[0] != NULL) {
                        int j = try_dests_non(file, fname, ndx, fnamecmpbuf, &sx,
                                              itemizing, code);
-@@ -1427,10 +1454,15 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1458,10 +1485,15 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                /* We need to ensure that the dirs in the transfer have writable
                 * permissions during the time we are putting files within them.
                 * This is then fixed after the transfer is done. */
@@ -267,7 +267,7 @@ diff --git a/generator.c b/generator.c
                                rsyserr(FERROR_XFER, errno,
                                        "failed to modify permissions on %s",
                                        full_fname(fname));
-@@ -1461,6 +1493,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1492,6 +1524,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                file->mode = dest_mode(file->mode, sx.st.st_mode, dflt_perms,
                                       exists);
        }
@@ -278,15 +278,19 @@ diff --git a/generator.c b/generator.c
  
  #ifdef SUPPORT_HARD_LINKS
        if (preserve_hard_links && F_HLINK_NOT_FIRST(file)
-@@ -1948,9 +1984,13 @@ static void touch_up_dirs(struct file_list *flist, int ndx)
+@@ -2004,13 +2040,17 @@ static void touch_up_dirs(struct file_list *flist, int ndx)
                        continue;
                fname = f_name(file, NULL);
                if (!(file->mode & S_IWUSR))
 -                      do_chmod(fname, file->mode);
 +                      do_chmod(fname, file->mode, 0);
-               if (need_retouch_dir_times)
--                      set_modtime(fname, file->modtime, file->mode);
-+                      set_modtime(fname, file->modtime, file->mode, 0);
+               if (need_retouch_dir_times) {
+                       STRUCT_STAT st;
+                       if (link_stat(fname, &st, 0) == 0
+                        && cmp_time(st.st_mtime, file->modtime) != 0)
+-                              set_modtime(fname, file->modtime, file->mode);
++                              set_modtime(fname, file->modtime, file->mode, 0);
+               }
 +#ifdef SUPPORT_FORCE_CHANGE
 +              if (force_change && F_FFLAGS(file) & force_change)
 +                      undo_make_mutable(fname, F_FFLAGS(file));
@@ -297,7 +301,7 @@ diff --git a/generator.c b/generator.c
 diff --git a/log.c b/log.c
 --- a/log.c
 +++ b/log.c
-@@ -644,7 +644,7 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
+@@ -650,7 +650,7 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
                        c[5] = !(iflags & ITEM_REPORT_PERMS) ? '.' : 'p';
                        c[6] = !(iflags & ITEM_REPORT_OWNER) ? '.' : 'o';
                        c[7] = !(iflags & ITEM_REPORT_GROUP) ? '.' : 'g';
@@ -309,7 +313,7 @@ diff --git a/log.c b/log.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -52,6 +52,7 @@ int preserve_hard_links = 0;
+@@ -53,6 +53,7 @@ int preserve_hard_links = 0;
  int preserve_acls = 0;
  int preserve_xattrs = 0;
  int preserve_perms = 0;
@@ -317,7 +321,7 @@ diff --git a/options.c b/options.c
  int preserve_executability = 0;
  int preserve_devices = 0;
  int preserve_specials = 0;
-@@ -84,6 +85,7 @@ int implied_dirs = 1;
+@@ -85,6 +86,7 @@ int implied_dirs = 1;
  int numeric_ids = 0;
  int allow_8bit_chars = 0;
  int force_delete = 0;
@@ -325,7 +329,7 @@ diff --git a/options.c b/options.c
  int io_timeout = 0;
  int allowed_lull = 0;
  int prune_empty_dirs = 0;
-@@ -224,6 +226,7 @@ static void print_rsync_version(enum logcode f)
+@@ -225,6 +227,7 @@ static void print_rsync_version(enum logcode f)
        char const *links = "no ";
        char const *iconv = "no ";
        char const *ipv6 = "no ";
@@ -333,7 +337,7 @@ diff --git a/options.c b/options.c
        STRUCT_STAT *dumstat;
  
  #if SUBPROTOCOL_VERSION != 0
-@@ -256,6 +259,9 @@ static void print_rsync_version(enum logcode f)
+@@ -257,6 +260,9 @@ static void print_rsync_version(enum logcode f)
  #if defined HAVE_LUTIMES && defined HAVE_UTIMES
        symtimes = "";
  #endif
@@ -343,7 +347,7 @@ diff --git a/options.c b/options.c
  
        rprintf(f, "%s  version %s  protocol version %d%s\n",
                RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
-@@ -269,8 +275,8 @@ static void print_rsync_version(enum logcode f)
+@@ -270,8 +276,8 @@ static void print_rsync_version(enum logcode f)
                (int)(sizeof (int64) * 8));
        rprintf(f, "    %ssocketpairs, %shardlinks, %ssymlinks, %sIPv6, batchfiles, %sinplace,\n",
                got_socketpair, hardlinks, links, ipv6, have_inplace);
@@ -354,7 +358,7 @@ diff --git a/options.c b/options.c
  
  #ifdef MAINTAINER_MODE
        rprintf(f, "Panic Action: \"%s\"\n", get_panic_action());
-@@ -337,6 +343,9 @@ void usage(enum logcode F)
+@@ -338,6 +344,9 @@ void usage(enum logcode F)
    rprintf(F," -K, --keep-dirlinks         treat symlinked dir on receiver as dir\n");
    rprintf(F," -H, --hard-links            preserve hard links\n");
    rprintf(F," -p, --perms                 preserve permissions\n");
@@ -364,7 +368,7 @@ diff --git a/options.c b/options.c
    rprintf(F," -E, --executability         preserve the file's executability\n");
    rprintf(F,"     --chmod=CHMOD           affect file and/or directory permissions\n");
  #ifdef SUPPORT_ACLS
-@@ -374,7 +383,12 @@ void usage(enum logcode F)
+@@ -375,7 +384,12 @@ void usage(enum logcode F)
    rprintf(F,"     --delete-after          receiver deletes after transfer, not during\n");
    rprintf(F,"     --delete-excluded       also delete excluded files from destination dirs\n");
    rprintf(F,"     --ignore-errors         delete even if there are I/O errors\n");
@@ -378,7 +382,7 @@ diff --git a/options.c b/options.c
    rprintf(F,"     --max-delete=NUM        don't delete more than NUM files\n");
    rprintf(F,"     --max-size=SIZE         don't transfer any file larger than SIZE\n");
    rprintf(F,"     --min-size=SIZE         don't transfer any file smaller than SIZE\n");
-@@ -477,6 +491,10 @@ static struct poptOption long_options[] = {
+@@ -480,6 +494,10 @@ static struct poptOption long_options[] = {
    {"perms",           'p', POPT_ARG_VAL,    &preserve_perms, 1, 0, 0 },
    {"no-perms",         0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
    {"no-p",             0,  POPT_ARG_VAL,    &preserve_perms, 0, 0, 0 },
@@ -389,21 +393,22 @@ diff --git a/options.c b/options.c
    {"executability",   'E', POPT_ARG_NONE,   &preserve_executability, 0, 0, 0 },
    {"acls",            'A', POPT_ARG_NONE,   0, 'A', 0, 0 },
    {"no-acls",          0,  POPT_ARG_VAL,    &preserve_acls, 0, 0, 0 },
-@@ -551,6 +569,13 @@ static struct poptOption long_options[] = {
-   {"remove-sent-files",0,  POPT_ARG_VAL,    &remove_source_files, 2, 0, 0 }, /* deprecated */
+@@ -558,6 +576,14 @@ static struct poptOption long_options[] = {
    {"remove-source-files",0,POPT_ARG_VAL,    &remove_source_files, 1, 0, 0 },
-   {"force",            0,  POPT_ARG_NONE,   &force_delete, 0, 0, 0 },
-+  {"force-delete",     0,  POPT_ARG_NONE,   &force_delete, 0, 0, 0 },
+   {"force",            0,  POPT_ARG_VAL,    &force_delete, 1, 0, 0 },
+   {"no-force",         0,  POPT_ARG_VAL,    &force_delete, 0, 0, 0 },
++  {"force-delete",     0,  POPT_ARG_VAL,    &force_delete, 1, 0, 0 },
++  {"no-force-delete",  0,  POPT_ARG_VAL,    &force_delete, 0, 0, 0 },
 +#ifdef SUPPORT_FORCE_CHANGE
 +  {"force-change",     0,  POPT_ARG_VAL,    &force_change, ALL_IMMUTABLE, 0, 0 },
 +  {"no-force-change",  0,  POPT_ARG_VAL,    &force_change, 0, 0, 0 },
 +  {"force-uchange",    0,  POPT_ARG_VAL,    &force_change, USR_IMMUTABLE, 0, 0 },
 +  {"force-schange",    0,  POPT_ARG_VAL,    &force_change, SYS_IMMUTABLE, 0, 0 },
 +#endif
-   {"ignore-errors",    0,  POPT_ARG_NONE,   &ignore_errors, 0, 0, 0 },
+   {"ignore-errors",    0,  POPT_ARG_VAL,    &ignore_errors, 1, 0, 0 },
+   {"no-ignore-errors", 0,  POPT_ARG_VAL,    &ignore_errors, 0, 0, 0 },
    {"max-delete",       0,  POPT_ARG_INT,    &max_delete, 0, 0, 0 },
-   {0,                 'F', POPT_ARG_NONE,   0, 'F', 0, 0 },
-@@ -1826,6 +1851,9 @@ void server_options(char **args, int *argc_p)
+@@ -1852,6 +1878,9 @@ void server_options(char **args, int *argc_p)
        if (xfer_dirs && !recurse && delete_mode && am_sender)
                args[ac++] = "--no-r";
  
@@ -413,7 +418,7 @@ diff --git a/options.c b/options.c
        if (do_compression && def_compress_level != Z_DEFAULT_COMPRESSION) {
                if (asprintf(&arg, "--compress-level=%d", def_compress_level) < 0)
                        goto oom;
-@@ -1913,6 +1941,16 @@ void server_options(char **args, int *argc_p)
+@@ -1939,6 +1968,16 @@ void server_options(char **args, int *argc_p)
                        args[ac++] = "--delete-excluded";
                if (force_delete)
                        args[ac++] = "--force";
@@ -441,7 +446,7 @@ diff --git a/rsync.c b/rsync.c
  extern int preserve_executability;
  extern int preserve_times;
  extern int am_root;
-@@ -339,6 +340,39 @@ mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int dflt_perms,
+@@ -374,6 +375,39 @@ mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int dflt_perms,
        return new_mode;
  }
  
@@ -481,7 +486,7 @@ diff --git a/rsync.c b/rsync.c
  int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
                   const char *fnamecmp, int flags)
  {
-@@ -392,7 +426,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
+@@ -427,7 +461,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
                flags |= ATTRS_SKIP_MTIME;
        if (!(flags & ATTRS_SKIP_MTIME)
            && cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
@@ -490,7 +495,7 @@ diff --git a/rsync.c b/rsync.c
                if (ret < 0) {
                        rsyserr(FERROR_XFER, errno, "failed to set times on %s",
                                full_fname(fname));
-@@ -428,7 +462,8 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
+@@ -463,7 +497,8 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
                if (am_root >= 0) {
                        if (do_lchown(fname,
                            change_uid ? (uid_t)F_OWNER(file) : sxp->st.st_uid,
@@ -500,7 +505,7 @@ diff --git a/rsync.c b/rsync.c
                                /* We shouldn't have attempted to change uid
                                 * or gid unless have the privilege. */
                                rsyserr(FERROR_XFER, errno, "%s %s failed",
-@@ -460,7 +495,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
+@@ -495,7 +530,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
  
  #ifdef HAVE_CHMOD
        if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) {
@@ -509,7 +514,7 @@ diff --git a/rsync.c b/rsync.c
                if (ret < 0) {
                        rsyserr(FERROR_XFER, errno,
                                "failed to set permissions on %s",
-@@ -472,6 +507,19 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
+@@ -507,6 +542,19 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
        }
  #endif
  
@@ -529,7 +534,7 @@ diff --git a/rsync.c b/rsync.c
        if (verbose > 1 && flags & ATTRS_REPORT) {
                if (updated)
                        rprintf(FCLIENT, "%s\n", fname);
-@@ -531,7 +579,8 @@ int finish_transfer(const char *fname, const char *fnametmp,
+@@ -566,7 +614,8 @@ int finish_transfer(const char *fname, const char *fnametmp,
  
        /* Change permissions before putting the file into place. */
        set_file_attrs(fnametmp, file, NULL, fnamecmp,
@@ -539,7 +544,7 @@ diff --git a/rsync.c b/rsync.c
  
        /* move tmp file over real file */
        if (verbose > 2)
-@@ -550,6 +599,10 @@ int finish_transfer(const char *fname, const char *fnametmp,
+@@ -585,6 +634,10 @@ int finish_transfer(const char *fname, const char *fnametmp,
        }
        if (ret == 0) {
                /* The file was moved into place (not copied), so it's done. */
@@ -561,7 +566,7 @@ diff --git a/rsync.h b/rsync.h
  
  /* These flags are used in the live flist data. */
  
-@@ -149,6 +150,7 @@
+@@ -151,6 +152,7 @@
  
  #define ATTRS_REPORT          (1<<0)
  #define ATTRS_SKIP_MTIME      (1<<1)
@@ -569,7 +574,7 @@ diff --git a/rsync.h b/rsync.h
  
  #define FULL_FLUSH    1
  #define NORMAL_FLUSH  0
-@@ -174,6 +176,7 @@
+@@ -177,6 +179,7 @@
  #define ITEM_REPORT_GROUP (1<<6)
  #define ITEM_REPORT_ACL (1<<7)
  #define ITEM_REPORT_XATTR (1<<8)
@@ -577,7 +582,7 @@ diff --git a/rsync.h b/rsync.h
  #define ITEM_BASIS_TYPE_FOLLOWS (1<<11)
  #define ITEM_XNAME_FOLLOWS (1<<12)
  #define ITEM_IS_NEW (1<<13)
-@@ -452,6 +455,28 @@ typedef unsigned int size_t;
+@@ -454,6 +457,28 @@ typedef unsigned int size_t;
  #endif
  #endif
  
@@ -595,8 +600,8 @@ diff --git a/rsync.h b/rsync.h
 +#ifndef SF_NOUNLINK
 +#define SF_NOUNLINK 0
 +#endif
-+#define USR_IMMUTABLE (UF_IMMUTABLE|UF_NOUNLINK)
-+#define SYS_IMMUTABLE (SF_IMMUTABLE|SF_NOUNLINK)
++#define USR_IMMUTABLE (UF_IMMUTABLE|UF_NOUNLINK|UF_APPEND)
++#define SYS_IMMUTABLE (SF_IMMUTABLE|SF_NOUNLINK|SF_APPEND)
 +#define ALL_IMMUTABLE (USR_IMMUTABLE|SYS_IMMUTABLE)
 +#define ST_FLAGS(st) (st.st_flags)
 +#else
@@ -606,7 +611,7 @@ diff --git a/rsync.h b/rsync.h
  /* Find a variable that is either exactly 32-bits or longer.
   * If some code depends on 32-bit truncation, it will need to
   * take special action in a "#if SIZEOF_INT32 > 4" section. */
-@@ -620,6 +645,7 @@ extern int file_extra_cnt;
+@@ -622,6 +647,7 @@ extern int file_extra_cnt;
  extern int inc_recurse;
  extern int uid_ndx;
  extern int gid_ndx;
@@ -614,7 +619,7 @@ diff --git a/rsync.h b/rsync.h
  extern int acls_ndx;
  extern int xattrs_ndx;
  
-@@ -657,6 +683,11 @@ extern int xattrs_ndx;
+@@ -659,6 +685,11 @@ extern int xattrs_ndx;
  /* When the associated option is on, all entries will have these present: */
  #define F_OWNER(f) REQ_EXTRA(f, uid_ndx)->unum
  #define F_GROUP(f) REQ_EXTRA(f, gid_ndx)->unum
@@ -659,7 +664,7 @@ diff --git a/rsync.yo b/rsync.yo
  
  dit(--no-OPTION) You may turn off one or more implied options by prefixing
  the option name with "no-".  Not all options may be prefixed with a "no-":
-@@ -785,7 +790,7 @@ they would be using bf(--copy-links).
+@@ -792,7 +797,7 @@ they would be using bf(--copy-links).
  Without this option, if the sending side has replaced a directory with a
  symlink to a directory, the receiving side will delete anything that is in
  the way of the new symlink, including a directory hierarchy (as long as
@@ -668,7 +673,7 @@ diff --git a/rsync.yo b/rsync.yo
  
  See also bf(--keep-dirlinks) for an analogous option for the receiving
  side.
-@@ -922,6 +927,29 @@ super-user copies all namespaces except system.*.  A normal user only copies
+@@ -929,6 +934,29 @@ super-user copies all namespaces except system.*.  A normal user only copies
  the user.* namespace.  To be able to backup and restore non-user namespaces as
  a normal user, see the bf(--fake-super) option.
  
@@ -698,7 +703,7 @@ diff --git a/rsync.yo b/rsync.yo
  dit(bf(--chmod)) This option tells rsync to apply one or more
  comma-separated "chmod" strings to the permission of the files in the
  transfer.  The resulting value is treated as though it was the permissions
-@@ -1177,12 +1205,13 @@ See bf(--delete) (which is implied) for more details on file-deletion.
+@@ -1184,12 +1212,13 @@ See bf(--delete) (which is implied) for more details on file-deletion.
  dit(bf(--ignore-errors)) Tells bf(--delete) to go ahead and delete files
  even when there are I/O errors.
  
@@ -715,7 +720,7 @@ diff --git a/rsync.yo b/rsync.yo
  bf(--recursive) option was also enabled.
  
  dit(bf(--max-delete=NUM)) This tells rsync not to delete more than NUM
-@@ -1638,7 +1667,7 @@ with older versions of rsync, but that also turns on the output of other
+@@ -1645,7 +1674,7 @@ with older versions of rsync, but that also turns on the output of other
  verbose messages).
  
  The "%i" escape has a cryptic output that is 11 letters long.  The general
@@ -724,7 +729,7 @@ diff --git a/rsync.yo b/rsync.yo
  type of update being done, bf(X) is replaced by the file-type, and the
  other letters represent attributes that may be output if they are being
  modified.
-@@ -1689,7 +1718,7 @@ quote(itemization(
+@@ -1701,7 +1730,7 @@ quote(itemization(
    sender's value (requires bf(--owner) and super-user privileges).
    it() A bf(g) means the group is different and is being updated to the
    sender's value (requires bf(--group) and the authority to set the group).
@@ -854,7 +859,7 @@ diff --git a/syscall.c b/syscall.c
 @@ -168,17 +223,74 @@ int do_chmod(const char *path, mode_t mode)
  #endif
        } else
-               code = chmod(path, mode & CHMOD_BITS);
+               code = chmod(path, mode & CHMOD_BITS); /* DISCOURAGED FUNCTION */
 +#ifdef SUPPORT_FORCE_CHANGE
 +      if (code < 0 && force_change && errno == EPERM && !S_ISLNK(mode)) {
 +              if (fileflags == NO_FFLAGS) {
@@ -875,7 +880,7 @@ diff --git a/syscall.c b/syscall.c
 +      fileflags = 0; /* avoid compiler warning */
 +#endif
        if (code != 0 && (preserve_perms || preserve_executability))
-           return code;
+               return code;
        return 0;
  }
  #endif
@@ -938,7 +943,7 @@ diff --git a/t_stub.c b/t_stub.c
  mode_t orig_umask = 002;
  char *partial_dir;
  char *module_dir;
-@@ -83,3 +84,23 @@ struct filter_list_struct server_filter_list;
+@@ -83,3 +84,23 @@ struct filter_list_struct daemon_filter_list;
  {
        return "tester";
  }
@@ -1036,7 +1041,30 @@ diff --git a/util.c b/util.c
 diff --git a/xattrs.c b/xattrs.c
 --- a/xattrs.c
 +++ b/xattrs.c
-@@ -915,7 +915,7 @@ int set_stat_xattr(const char *fname, struct file_struct *file, mode_t new_mode)
+@@ -280,6 +280,10 @@ int get_xattr(const char *fname, stat_x *sxp)
+ {
+       sxp->xattr = new(item_list);
+       *sxp->xattr = empty_xattr;
++
++      if (IS_SPECIAL(sxp->st.st_mode) || IS_DEVICE(sxp->st.st_mode))
++              return 0;
++
+       if (rsync_xal_get(fname, sxp->xattr) < 0) {
+               free_xattr(sxp);
+               return -1;
+@@ -814,6 +818,11 @@ int set_xattr(const char *fname, const struct file_struct *file,
+               return -1;
+       }
++      if (IS_SPECIAL(sxp->st.st_mode) || IS_DEVICE(sxp->st.st_mode)) {
++              errno = ENOTSUP;
++              return -1;
++      }
++
+       ndx = F_XATTR(file);
+       return rsync_xal_set(fname, lst + ndx, fnamecmp, sxp);
+ }
+@@ -930,7 +939,7 @@ int set_stat_xattr(const char *fname, struct file_struct *file, mode_t new_mode)
        mode = (fst.st_mode & _S_IFMT) | (fmode & ACCESSPERMS)
             | (S_ISDIR(fst.st_mode) ? 0700 : 0600);
        if (fst.st_mode != mode)
index af3b80c..e0cdbbf 100644 (file)
@@ -10,7 +10,7 @@ To use this patch, run these commands for a successful build:
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -47,6 +47,7 @@ int append_mode = 0;
+@@ -48,6 +48,7 @@ int append_mode = 0;
  int keep_dirlinks = 0;
  int copy_dirlinks = 0;
  int copy_links = 0;
@@ -18,7 +18,7 @@ diff --git a/options.c b/options.c
  int preserve_links = 0;
  int preserve_hard_links = 0;
  int preserve_acls = 0;
-@@ -382,6 +383,7 @@ void usage(enum logcode F)
+@@ -383,6 +384,7 @@ void usage(enum logcode F)
    rprintf(F,"     --partial-dir=DIR       put a partially transferred file into DIR\n");
    rprintf(F,"     --delay-updates         put all updated files into place at transfer's end\n");
    rprintf(F," -m, --prune-empty-dirs      prune empty directory chains from the file-list\n");
@@ -26,15 +26,15 @@ diff --git a/options.c b/options.c
    rprintf(F,"     --numeric-ids           don't map uid/gid values by user/group name\n");
    rprintf(F,"     --timeout=SECONDS       set I/O timeout in seconds\n");
    rprintf(F,"     --contimeout=SECONDS    set daemon connection timeout in seconds\n");
-@@ -613,6 +615,7 @@ static struct poptOption long_options[] = {
-   {"timeout",          0,  POPT_ARG_INT,    &io_timeout, 0, 0, 0 },
+@@ -626,6 +628,7 @@ static struct poptOption long_options[] = {
    {"no-timeout",       0,  POPT_ARG_VAL,    &io_timeout, 0, 0, 0 },
    {"contimeout",       0,  POPT_ARG_INT,    &connect_timeout, 0, 0, 0 },
+   {"no-contimeout",    0,  POPT_ARG_VAL,    &connect_timeout, 0, 0, 0 },
 +  {"fsync",            0,  POPT_ARG_NONE,   &do_fsync, 0, 0, 0 },
    {"rsh",             'e', POPT_ARG_STRING, &shell_cmd, 0, 0, 0 },
    {"rsync-path",       0,  POPT_ARG_STRING, &rsync_path, 0, 0, 0 },
    {"temp-dir",        'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
-@@ -1977,6 +1980,9 @@ void server_options(char **args, int *argc_p)
+@@ -2003,6 +2006,9 @@ void server_options(char **args, int *argc_p)
                        args[ac++] = tmpdir;
                }
  
index 7fbcbc6..710abb3 100644 (file)
@@ -23,7 +23,7 @@ diff --git a/exclude.c b/exclude.c
  
  extern int verbose;
  extern int am_server;
-@@ -580,16 +581,15 @@ static int rule_matches(char *fname, struct filter_struct *ex, int name_is_dir)
+@@ -604,16 +605,15 @@ static int rule_matches(const char *fname, struct filter_struct *ex, int name_is
                if (litmatch_array(pattern, strings, slash_handling))
                        return ret_match;
        } else if (anchored_match) {
@@ -55,7 +55,7 @@ diff --git a/flist.c b/flist.c
  extern int ignore_errors;
  extern int numeric_ids;
  extern int recurse;
-@@ -2617,6 +2618,7 @@ int f_name_cmp(const struct file_struct *f1, const struct file_struct *f2)
+@@ -2672,6 +2673,7 @@ int f_name_cmp(const struct file_struct *f1, const struct file_struct *f2)
  {
        int dif;
        const uchar *c1, *c2;
@@ -63,7 +63,7 @@ diff --git a/flist.c b/flist.c
        enum fnc_state state1, state2;
        enum fnc_type type1, type2;
        enum fnc_type t_path = protocol_version >= 29 ? t_PATH : t_ITEM;
-@@ -2727,7 +2729,15 @@ int f_name_cmp(const struct file_struct *f1, const struct file_struct *f2)
+@@ -2782,7 +2784,15 @@ int f_name_cmp(const struct file_struct *f1, const struct file_struct *f2)
                        if (type1 != type2)
                                return type1 == t_PATH ? 1 : -1;
                }
@@ -83,7 +83,7 @@ diff --git a/flist.c b/flist.c
 diff --git a/ifuncs.h b/ifuncs.h
 --- a/ifuncs.h
 +++ b/ifuncs.h
-@@ -98,3 +98,38 @@ toUpper(const char *ptr)
+@@ -108,3 +108,38 @@ toUpper(const char *ptr)
  {
        return toupper(*(unsigned char *)ptr);
  }
@@ -211,7 +211,7 @@ diff --git a/lib/wildmatch.c b/lib/wildmatch.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -117,6 +117,7 @@ OFF_T max_size = 0;
+@@ -118,6 +118,7 @@ OFF_T max_size = 0;
  OFF_T min_size = 0;
  int ignore_errors = 0;
  int modify_window = 0;
@@ -219,7 +219,7 @@ diff --git a/options.c b/options.c
  int blocking_io = -1;
  int checksum_seed = 0;
  int inplace = 0;
-@@ -407,6 +408,7 @@ void usage(enum logcode F)
+@@ -408,6 +409,7 @@ void usage(enum logcode F)
    rprintf(F,"     --files-from=FILE       read list of source-file names from FILE\n");
    rprintf(F," -0, --from0                 all *-from/filter files are delimited by 0s\n");
    rprintf(F," -s, --protect-args          no space-splitting; only wildcard special-chars\n");
@@ -227,7 +227,7 @@ diff --git a/options.c b/options.c
    rprintf(F,"     --address=ADDRESS       bind address for outgoing socket to daemon\n");
    rprintf(F,"     --port=PORT             specify double-colon alternate port number\n");
    rprintf(F,"     --sockopts=OPTIONS      specify custom TCP options\n");
-@@ -602,6 +604,8 @@ static struct poptOption long_options[] = {
+@@ -614,6 +616,8 @@ static struct poptOption long_options[] = {
    {"read-batch",       0,  POPT_ARG_STRING, &batch_name, OPT_READ_BATCH, 0, 0 },
    {"write-batch",      0,  POPT_ARG_STRING, &batch_name, OPT_WRITE_BATCH, 0, 0 },
    {"only-write-batch", 0,  POPT_ARG_STRING, &batch_name, OPT_ONLY_WRITE_BATCH, 0, 0 },
@@ -236,7 +236,7 @@ diff --git a/options.c b/options.c
    {"files-from",       0,  POPT_ARG_STRING, &files_from, 0, 0, 0 },
    {"from0",           '0', POPT_ARG_VAL,    &eol_nulls, 1, 0, 0},
    {"no-from0",         0,  POPT_ARG_VAL,    &eol_nulls, 0, 0, 0},
-@@ -1939,6 +1943,9 @@ void server_options(char **args, int *argc_p)
+@@ -1965,6 +1969,9 @@ void server_options(char **args, int *argc_p)
                args[ac++] = arg;
        }
  
@@ -257,7 +257,7 @@ diff --git a/rsync.yo b/rsync.yo
       --address=ADDRESS       bind address for outgoing socket to daemon
       --port=PORT             specify double-colon alternate port number
       --sockopts=OPTIONS      specify custom TCP options
-@@ -1425,6 +1426,10 @@ If you use this option with bf(--iconv), the args will also be translated
+@@ -1432,6 +1433,10 @@ If you use this option with bf(--iconv), the args will also be translated
  from the local to the remote character-set.  The translation happens before
  wild-cards are expanded.  See also the bf(--files-from) option.
  
index 8a934ba..b4e0848 100644 (file)
@@ -35,8 +35,8 @@ diff --git a/flist.c b/flist.c
  
  extern char curr_dir[MAXPATHLEN];
  
-@@ -824,7 +825,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
-               extra_len += (S_ISDIR(mode) ? 2 : 1) * EXTRA_LEN;
+@@ -859,7 +860,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+               extra_len += EXTRA_LEN;
  #endif
  
 -      if (always_checksum && S_ISREG(mode))
@@ -388,7 +388,7 @@ new file mode 100644
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -156,6 +156,7 @@ char *backup_suffix = NULL;
+@@ -157,6 +157,7 @@ char *backup_suffix = NULL;
  char *tmpdir = NULL;
  char *partial_dir = NULL;
  char *basis_dir[MAX_BASIS_DIRS+1];
@@ -396,7 +396,7 @@ diff --git a/options.c b/options.c
  char *config_file = NULL;
  char *shell_cmd = NULL;
  char *logfile_name = NULL;
-@@ -393,6 +394,7 @@ void usage(enum logcode F)
+@@ -394,6 +395,7 @@ void usage(enum logcode F)
    rprintf(F,"     --compare-dest=DIR      also compare destination files relative to DIR\n");
    rprintf(F,"     --copy-dest=DIR         ... and include copies of unchanged files\n");
    rprintf(F,"     --link-dest=DIR         hardlink to files in DIR when unchanged\n");
@@ -404,7 +404,7 @@ diff --git a/options.c b/options.c
    rprintf(F," -z, --compress              compress file data during the transfer\n");
    rprintf(F,"     --compress-level=NUM    explicitly set compression level\n");
    rprintf(F,"     --skip-compress=LIST    skip compressing files with a suffix in LIST\n");
-@@ -445,7 +447,7 @@ enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
+@@ -446,7 +448,7 @@ enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
        OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST, OPT_HELP,
        OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW, OPT_MIN_SIZE, OPT_CHMOD,
        OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE,
@@ -413,15 +413,15 @@ diff --git a/options.c b/options.c
        OPT_SERVER, OPT_REFUSED_BASE = 9000};
  
  static struct poptOption long_options[] = {
-@@ -570,6 +572,7 @@ static struct poptOption long_options[] = {
+@@ -578,6 +580,7 @@ static struct poptOption long_options[] = {
    {"compare-dest",     0,  POPT_ARG_STRING, 0, OPT_COMPARE_DEST, 0, 0 },
    {"copy-dest",        0,  POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 },
    {"link-dest",        0,  POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 },
 +  {"link-by-hash",     0,  POPT_ARG_STRING, 0, OPT_LINK_BY_HASH, 0, 0},
-   {"fuzzy",           'y', POPT_ARG_NONE,   &fuzzy_basis, 0, 0, 0 },
-   {"compress",        'z', POPT_ARG_NONE,   0, 'z', 0, 0 },
-   {"no-compress",      0,  POPT_ARG_VAL,    &do_compression, 0, 0, 0 },
-@@ -1244,6 +1247,21 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+   {"fuzzy",           'y', POPT_ARG_VAL,    &fuzzy_basis, 1, 0, 0 },
+   {"no-fuzzy",         0,  POPT_ARG_VAL,    &fuzzy_basis, 0, 0, 0 },
+   {"no-y",             0,  POPT_ARG_VAL,    &fuzzy_basis, 0, 0, 0 },
+@@ -1260,6 +1263,21 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                        return 0;
  #endif
  
@@ -429,7 +429,7 @@ diff --git a/options.c b/options.c
 +#ifdef HAVE_LINK
 +                      arg = poptGetOptArg(pc);
 +                      if (sanitize_paths)
-+                              arg = sanitize_path(NULL, arg, NULL, 0);
++                              arg = sanitize_path(NULL, arg, NULL, 0, SP_DEFAULT);
 +                      link_by_hash_dir = (char *)arg;
 +                      break;
 +#else
@@ -443,7 +443,7 @@ diff --git a/options.c b/options.c
                default:
                        /* A large opt value means that set_refuse_options()
                         * turned this option off. */
-@@ -1997,6 +2015,11 @@ void server_options(char **args, int *argc_p)
+@@ -2023,6 +2041,11 @@ void server_options(char **args, int *argc_p)
        } else if (inplace)
                args[ac++] = "--inplace";
  
@@ -532,7 +532,7 @@ diff --git a/receiver.c b/receiver.c
 diff --git a/rsync.c b/rsync.c
 --- a/rsync.c
 +++ b/rsync.c
-@@ -49,6 +49,7 @@ extern int inplace;
+@@ -48,6 +48,7 @@ extern int inplace;
  extern int flist_eof;
  extern int keep_dirlinks;
  extern int make_backups;
@@ -540,7 +540,7 @@ diff --git a/rsync.c b/rsync.c
  extern struct file_list *cur_flist, *first_flist, *dir_flist;
  extern struct chmod_mode_struct *daemon_chmod_modes;
  #ifdef ICONV_OPTION
-@@ -536,8 +537,15 @@ int finish_transfer(const char *fname, const char *fnametmp,
+@@ -571,8 +572,15 @@ int finish_transfer(const char *fname, const char *fnametmp,
        /* move tmp file over real file */
        if (verbose > 2)
                rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname);
@@ -561,7 +561,7 @@ diff --git a/rsync.c b/rsync.c
 diff --git a/rsync.h b/rsync.h
 --- a/rsync.h
 +++ b/rsync.h
-@@ -818,6 +818,14 @@ struct stats {
+@@ -820,6 +820,14 @@ struct stats {
        int num_transferred_files;
  };
  
index f06824b..78f28f7 100644 (file)
@@ -98,7 +98,7 @@ diff --git a/match.c b/match.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -1498,7 +1498,8 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1524,7 +1524,8 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                else if (log_format_has(stdout_format, 'i'))
                        stdout_format_has_i = itemize_changes | 1;
                if (!log_format_has(stdout_format, 'b')
@@ -155,7 +155,7 @@ diff --git a/receiver.c b/receiver.c
 diff --git a/rsync.yo b/rsync.yo
 --- a/rsync.yo
 +++ b/rsync.yo
-@@ -2075,7 +2075,7 @@ by the server and defaults to the current code(time()).  This option
+@@ -2087,7 +2087,7 @@ by the server and defaults to the current code(time()).  This option
  is used to set a specific checksum seed, which is useful for
  applications that want repeatable block and file checksums, or
  in the case where the user wants a more random checksum seed.
@@ -167,7 +167,7 @@ diff --git a/rsync.yo b/rsync.yo
 diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo
 --- a/rsyncd.conf.yo
 +++ b/rsyncd.conf.yo
-@@ -511,7 +511,8 @@ quote(itemization(
+@@ -509,7 +509,8 @@ quote(itemization(
    it() %a the remote IP address
    it() %b the number of bytes actually transferred
    it() %B the permission bits of the file (e.g. rwxrwxrwt)
index 33a990c..bc3f941 100644 (file)
@@ -23,7 +23,7 @@ To use this patch, run these commands for a successful build:
 diff --git a/clientserver.c b/clientserver.c
 --- a/clientserver.c
 +++ b/clientserver.c
-@@ -64,6 +64,7 @@ char *auth_user;
+@@ -67,6 +67,7 @@ char *auth_user;
  int read_only = 0;
  int module_id = -1;
  int munge_symlinks = 0;
@@ -31,7 +31,7 @@ diff --git a/clientserver.c b/clientserver.c
  struct chmod_mode_struct *daemon_chmod_modes;
  
  /* module_dirlen is the length of the module_dir string when in daemon
-@@ -73,6 +74,7 @@ char *module_dir = NULL;
+@@ -76,6 +77,7 @@ char *module_dir = NULL;
  unsigned int module_dirlen = 0;
  
  static int rl_nulls = 0;
@@ -39,7 +39,7 @@ diff --git a/clientserver.c b/clientserver.c
  
  #ifdef HAVE_SIGACTION
  static struct sigaction sigact;
-@@ -539,7 +541,7 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
+@@ -555,7 +557,7 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
        log_init(1);
  
  #ifdef HAVE_PUTENV
@@ -48,7 +48,7 @@ diff --git a/clientserver.c b/clientserver.c
                char *modname, *modpath, *hostaddr, *hostname, *username;
                int status;
  
-@@ -635,6 +637,44 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
+@@ -651,6 +653,44 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
                        set_blocking(fds[1]);
                        pre_exec_fd = fds[1];
                }
@@ -93,7 +93,7 @@ diff --git a/clientserver.c b/clientserver.c
                umask(0);
        }
  #endif
-@@ -848,6 +888,44 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
+@@ -880,6 +920,44 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
        return 0;
  }
  
@@ -273,10 +273,10 @@ diff --git a/t_stub.c b/t_stub.c
  char *partial_dir;
  char *module_dir;
 +pid_t namecvt_pid;
- struct filter_list_struct server_filter_list;
+ struct filter_list_struct daemon_filter_list;
  
   void rprintf(UNUSED(enum logcode code), const char *format, ...)
-@@ -69,6 +70,11 @@ struct filter_list_struct server_filter_list;
+@@ -69,6 +70,11 @@ struct filter_list_struct daemon_filter_list;
        return -1;
  }
  
@@ -341,7 +341,7 @@ diff --git a/util.c b/util.c
  extern char *partial_dir;
 +extern pid_t namecvt_pid;
 +extern unsigned int module_dirlen;
- extern struct filter_list_struct server_filter_list;
+ extern struct filter_list_struct daemon_filter_list;
  
  int sanitize_paths = 0;
 @@ -468,24 +469,44 @@ void kill_all(int sig)
index b750253..b07ac10 100644 (file)
@@ -10,7 +10,7 @@ To use this patch, run these commands for a successful build:
 diff --git a/generator.c b/generator.c
 --- a/generator.c
 +++ b/generator.c
-@@ -45,6 +45,7 @@ extern int preserve_hard_links;
+@@ -44,6 +44,7 @@ extern int preserve_hard_links;
  extern int preserve_executability;
  extern int preserve_perms;
  extern int preserve_times;
@@ -18,17 +18,17 @@ diff --git a/generator.c b/generator.c
  extern int uid_ndx;
  extern int gid_ndx;
  extern int delete_mode;
-@@ -625,6 +626,7 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
-                   (receiver_symlink_times && !(file->flags & FLAG_TIME_FAILED)) ||
- #endif
-                   !S_ISLNK(file->mode);
+@@ -624,6 +625,7 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+            const char *xname)
+ {
+       if (statret >= 0) { /* A from-dest-dir statret can == 1! */
 +              int omit_changes = omit_dir_changes && S_ISDIR(sxp->st.st_mode);
-               if (S_ISREG(file->mode) && F_LENGTH(file) != sxp->st.st_size)
-                       iflags |= ITEM_REPORT_SIZE;
-@@ -641,10 +643,11 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
-               if ((preserve_perms || preserve_executability)
-                && !BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
+               int keep_time = !preserve_times ? 0
+                   : S_ISDIR(file->mode) ? preserve_times > 1 :
+ #if defined HAVE_LUTIMES && defined HAVE_UTIMES
+@@ -653,10 +655,11 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+               } else if (preserve_executability
+                && ((sxp->st.st_mode & 0111 ? 1 : 0) ^ (file->mode & 0111 ? 1 : 0)))
                        iflags |= ITEM_REPORT_PERMS;
 -              if (uid_ndx && am_root && (uid_t)F_OWNER(file) != sxp->st.st_uid)
 +              if (uid_ndx && am_root && !omit_changes
@@ -41,7 +41,7 @@ diff --git a/generator.c b/generator.c
                        iflags |= ITEM_REPORT_GROUP;
  #ifdef SUPPORT_ACLS
                if (preserve_acls && !S_ISLNK(file->mode)) {
-@@ -1387,7 +1390,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1419,7 +1422,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                real_sx = sx;
                if (file->flags & FLAG_DIR_CREATED)
                        statret = -1;
@@ -53,7 +53,7 @@ diff --git a/generator.c b/generator.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -58,6 +58,7 @@ int preserve_specials = 0;
+@@ -59,6 +59,7 @@ int preserve_specials = 0;
  int preserve_uid = 0;
  int preserve_gid = 0;
  int preserve_times = 0;
@@ -61,7 +61,7 @@ diff --git a/options.c b/options.c
  int update_only = 0;
  int cvs_exclude = 0;
  int dry_run = 0;
-@@ -352,6 +353,7 @@ void usage(enum logcode F)
+@@ -353,6 +354,7 @@ void usage(enum logcode F)
    rprintf(F," -D                          same as --devices --specials\n");
    rprintf(F," -t, --times                 preserve modification times\n");
    rprintf(F," -O, --omit-dir-times        omit directories from --times\n");
@@ -69,7 +69,7 @@ diff --git a/options.c b/options.c
    rprintf(F,"     --super                 receiver attempts super-user activities\n");
  #ifdef SUPPORT_XATTRS
    rprintf(F,"     --fake-super            store/recover privileged attrs using xattrs\n");
-@@ -490,6 +492,7 @@ static struct poptOption long_options[] = {
+@@ -493,6 +495,7 @@ static struct poptOption long_options[] = {
    {"omit-dir-times",  'O', POPT_ARG_VAL,    &omit_dir_times, 1, 0, 0 },
    {"no-omit-dir-times",0,  POPT_ARG_VAL,    &omit_dir_times, 0, 0, 0 },
    {"no-O",             0,  POPT_ARG_VAL,    &omit_dir_times, 0, 0, 0 },
@@ -77,7 +77,7 @@ diff --git a/options.c b/options.c
    {"modify-window",    0,  POPT_ARG_INT,    &modify_window, OPT_MODIFY_WINDOW, 0, 0 },
    {"super",            0,  POPT_ARG_VAL,    &am_root, 2, 0, 0 },
    {"no-super",         0,  POPT_ARG_VAL,    &am_root, 0, 0, 0 },
-@@ -1483,6 +1486,8 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1509,6 +1512,8 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                parse_rule(&filter_list, backup_dir_buf, 0, 0);
        }
  
@@ -86,7 +86,7 @@ diff --git a/options.c b/options.c
        if (make_backups && !backup_dir) {
                omit_dir_times = 0; /* Implied, so avoid -O to sender. */
                if (preserve_times > 1)
-@@ -1721,6 +1726,8 @@ void server_options(char **args, int *argc_p)
+@@ -1747,6 +1752,8 @@ void server_options(char **args, int *argc_p)
                        argstr[x++] = 'm';
                if (omit_dir_times)
                        argstr[x++] = 'O';
@@ -106,7 +106,7 @@ diff --git a/rsync.c b/rsync.c
  extern int am_root;
  extern int am_server;
  extern int am_sender;
-@@ -404,9 +405,11 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
+@@ -439,9 +440,11 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
                        file->flags |= FLAG_TIME_FAILED;
        }
  
@@ -131,7 +131,7 @@ diff --git a/rsync.yo b/rsync.yo
       --super                 receiver attempts super-user activities
       --fake-super            store/recover privileged attrs using xattrs
   -S, --sparse                handle sparse files efficiently
-@@ -987,6 +988,10 @@ it is preserving modification times (see bf(--times)).  If NFS is sharing
+@@ -994,6 +995,10 @@ it is preserving modification times (see bf(--times)).  If NFS is sharing
  the directories on the receiving side, it is a good idea to use bf(-O).
  This option is inferred if you use bf(--backup) without bf(--backup-dir).
  
index 2974811..c1ad7f6 100644 (file)
@@ -78,7 +78,7 @@ diff --git a/cleanup.c b/cleanup.c
 diff --git a/clientserver.c b/clientserver.c
 --- a/clientserver.c
 +++ b/clientserver.c
-@@ -30,6 +30,9 @@ extern int am_sender;
+@@ -31,6 +31,9 @@ extern int am_sender;
  extern int am_server;
  extern int am_daemon;
  extern int am_root;
@@ -86,9 +86,9 @@ diff --git a/clientserver.c b/clientserver.c
 +extern int use_ssl;
 +#endif
  extern int rsync_port;
+ extern int protect_args;
  extern int ignore_errors;
- extern int kluge_around_eof;
-@@ -125,8 +128,18 @@ int start_socket_client(char *host, int remote_argc, char *remote_argv[],
+@@ -128,8 +131,18 @@ int start_socket_client(char *host, int remote_argc, char *remote_argv[],
  #endif
  
        ret = start_inband_exchange(fd, fd, user, remote_argc, remote_argv);
@@ -108,7 +108,7 @@ diff --git a/clientserver.c b/clientserver.c
  }
  
  static int exchange_protocols(int f_in, int f_out, char *buf, size_t bufsiz, int am_client)
-@@ -269,6 +282,32 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
+@@ -272,6 +285,32 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
        if (verbose > 1)
                print_child_argv("sending daemon args:", sargs);
  
@@ -141,7 +141,7 @@ diff --git a/clientserver.c b/clientserver.c
        io_printf(f_out, "%.*s\n", modlen, modname);
  
        /* Old servers may just drop the connection here,
-@@ -294,6 +333,10 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
+@@ -297,6 +336,10 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
                         * server to terminate the listing of modules.
                         * We don't want to go on and transfer
                         * anything; just exit. */
@@ -152,7 +152,7 @@ diff --git a/clientserver.c b/clientserver.c
                        exit(0);
                }
  
-@@ -301,6 +344,10 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
+@@ -304,6 +347,10 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
                        rprintf(FERROR, "%s\n", line);
                        /* This is always fatal; the server will now
                         * close the socket. */
@@ -163,7 +163,7 @@ diff --git a/clientserver.c b/clientserver.c
                        return -1;
                }
  
-@@ -898,6 +945,9 @@ int start_daemon(int f_in, int f_out)
+@@ -941,6 +988,9 @@ int start_daemon(int f_in, int f_out)
        if (exchange_protocols(f_in, f_out, line, sizeof line, 0) < 0)
                return -1;
  
@@ -173,7 +173,7 @@ diff --git a/clientserver.c b/clientserver.c
        line[0] = 0;
        if (!read_line_old(f_in, line, sizeof line))
                return -1;
-@@ -909,6 +959,20 @@ int start_daemon(int f_in, int f_out)
+@@ -952,6 +1002,20 @@ int start_daemon(int f_in, int f_out)
                return -1;
        }
  
@@ -222,7 +222,7 @@ diff --git a/configure.in b/configure.in
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -184,6 +184,14 @@ int logfile_format_has_o_or_i = 0;
+@@ -185,6 +185,14 @@ int logfile_format_has_o_or_i = 0;
  int always_checksum = 0;
  int list_only = 0;
  
@@ -237,7 +237,7 @@ diff --git a/options.c b/options.c
  #define MAX_BATCH_NAME_LEN 256        /* Must be less than MAXPATHLEN-13 */
  char *batch_name = NULL;
  
-@@ -224,6 +232,7 @@ static void print_rsync_version(enum logcode f)
+@@ -225,6 +233,7 @@ static void print_rsync_version(enum logcode f)
        char const *links = "no ";
        char const *iconv = "no ";
        char const *ipv6 = "no ";
@@ -245,7 +245,7 @@ diff --git a/options.c b/options.c
        STRUCT_STAT *dumstat;
  
  #if SUBPROTOCOL_VERSION != 0
-@@ -256,6 +265,9 @@ static void print_rsync_version(enum logcode f)
+@@ -257,6 +266,9 @@ static void print_rsync_version(enum logcode f)
  #if defined HAVE_LUTIMES && defined HAVE_UTIMES
        symtimes = "";
  #endif
@@ -255,7 +255,7 @@ diff --git a/options.c b/options.c
  
        rprintf(f, "%s  version %s  protocol version %d%s\n",
                RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
-@@ -269,8 +281,8 @@ static void print_rsync_version(enum logcode f)
+@@ -270,8 +282,8 @@ static void print_rsync_version(enum logcode f)
                (int)(sizeof (int64) * 8));
        rprintf(f, "    %ssocketpairs, %shardlinks, %ssymlinks, %sIPv6, batchfiles, %sinplace,\n",
                got_socketpair, hardlinks, links, ipv6, have_inplace);
@@ -266,7 +266,7 @@ diff --git a/options.c b/options.c
  
  #ifdef MAINTAINER_MODE
        rprintf(f, "Panic Action: \"%s\"\n", get_panic_action());
-@@ -432,6 +444,13 @@ void usage(enum logcode F)
+@@ -433,6 +445,13 @@ void usage(enum logcode F)
  #endif
    rprintf(F," -4, --ipv4                  prefer IPv4\n");
    rprintf(F," -6, --ipv6                  prefer IPv6\n");
@@ -280,7 +280,7 @@ diff --git a/options.c b/options.c
    rprintf(F,"     --version               print version number\n");
    rprintf(F,"(-h) --help                  show this help (-h works with no other options)\n");
  
-@@ -445,7 +464,7 @@ enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
+@@ -446,7 +465,7 @@ enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
        OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST, OPT_HELP,
        OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW, OPT_MIN_SIZE, OPT_CHMOD,
        OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE,
@@ -289,7 +289,7 @@ diff --git a/options.c b/options.c
        OPT_SERVER, OPT_REFUSED_BASE = 9000};
  
  static struct poptOption long_options[] = {
-@@ -634,6 +653,13 @@ static struct poptOption long_options[] = {
+@@ -649,6 +668,13 @@ static struct poptOption long_options[] = {
    {"checksum-seed",    0,  POPT_ARG_INT,    &checksum_seed, 0, 0, 0 },
    {"server",           0,  POPT_ARG_NONE,   0, OPT_SERVER, 0, 0 },
    {"sender",           0,  POPT_ARG_NONE,   0, OPT_SENDER, 0, 0 },
@@ -303,7 +303,7 @@ diff --git a/options.c b/options.c
    /* All the following options switch us into daemon-mode option-parsing. */
    {"config",           0,  POPT_ARG_STRING, 0, OPT_DAEMON, 0, 0 },
    {"daemon",           0,  POPT_ARG_NONE,   0, OPT_DAEMON, 0, 0 },
-@@ -659,6 +685,13 @@ static void daemon_usage(enum logcode F)
+@@ -674,6 +700,13 @@ static void daemon_usage(enum logcode F)
    rprintf(F," -v, --verbose               increase verbosity\n");
    rprintf(F," -4, --ipv4                  prefer IPv4\n");
    rprintf(F," -6, --ipv6                  prefer IPv6\n");
@@ -317,7 +317,7 @@ diff --git a/options.c b/options.c
    rprintf(F,"     --help                  show this help screen\n");
  
    rprintf(F,"\n");
-@@ -683,6 +716,13 @@ static struct poptOption long_daemon_options[] = {
+@@ -698,6 +731,13 @@ static struct poptOption long_daemon_options[] = {
    {"protocol",         0,  POPT_ARG_INT,    &protocol_version, 0, 0, 0 },
    {"server",           0,  POPT_ARG_NONE,   &am_server, 0, 0, 0 },
    {"temp-dir",        'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
@@ -331,7 +331,7 @@ diff --git a/options.c b/options.c
    {"verbose",         'v', POPT_ARG_NONE,   0, 'v', 0, 0 },
    {"no-verbose",       0,  POPT_ARG_VAL,    &verbose, 0, 0, 0 },
    {"no-v",             0,  POPT_ARG_VAL,    &verbose, 0, 0, 0 },
-@@ -962,6 +1002,12 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -979,6 +1019,12 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                                        verbose++;
                                        break;
  
@@ -344,7 +344,7 @@ diff --git a/options.c b/options.c
                                default:
                                        rprintf(FERROR,
                                            "rsync: %s: %s (in daemon mode)\n",
-@@ -985,6 +1031,17 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1002,6 +1048,17 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                                exit_cleanup(RERR_SYNTAX);
                        }
  
@@ -362,7 +362,7 @@ diff --git a/options.c b/options.c
                        *argv_p = argv = poptGetArgs(pc);
                        *argc_p = argc = count_args(argv);
                        am_starting_up = 0;
-@@ -1244,6 +1301,12 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1260,6 +1317,12 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                        return 0;
  #endif
  
@@ -375,7 +375,7 @@ diff --git a/options.c b/options.c
                default:
                        /* A large opt value means that set_refuse_options()
                         * turned this option off. */
-@@ -1567,6 +1630,17 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1593,6 +1656,17 @@ int parse_arguments(int *argc_p, const char ***argv_p)
        if (delay_updates && !partial_dir)
                partial_dir = tmp_partialdir;
  
@@ -393,7 +393,7 @@ diff --git a/options.c b/options.c
        if (inplace) {
  #ifdef HAVE_FTRUNCATE
                if (partial_dir) {
-@@ -2041,10 +2115,27 @@ char *check_for_hostspec(char *s, char **host_ptr, int *port_ptr)
+@@ -2067,10 +2141,27 @@ char *check_for_hostspec(char *s, char **host_ptr, int *port_ptr)
        char *p;
        int not_host;
        int hostlen;
@@ -435,7 +435,7 @@ diff --git a/rsync.h b/rsync.h
  
  #define SYMLINK_PREFIX "/rsyncd-munged/"
  #define SYMLINK_PREFIX_LEN ((int)sizeof SYMLINK_PREFIX - 1)
-@@ -537,6 +538,11 @@ typedef unsigned int size_t;
+@@ -539,6 +540,11 @@ typedef unsigned int size_t;
  # define SIZEOF_INT64 SIZEOF_OFF_T
  #endif
  
diff --git a/osx-create-time.diff b/osx-create-time.diff
deleted file mode 100644 (file)
index d868a7c..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-This patch handles the creation time on OS X by putting it into an
-extended attribute.  This is a modified version of a patch that was
-provided by Wesley W. Terpstra.
-
-To use this patch, run these commands for a successful build:
-
-    patch -p1 <patches/osx-create-time.diff
-    ./configure                                 (optional if already run)
-    make
-
-diff --git a/lib/sysxattrs.c b/lib/sysxattrs.c
---- a/lib/sysxattrs.c
-+++ b/lib/sysxattrs.c
-@@ -53,29 +53,118 @@ ssize_t sys_llistxattr(const char *path, char *list, size_t size)
- #elif HAVE_OSX_XATTRS
-+#include <sys/attr.h>
-+
-+#define CRTIME_XATTR "com.apple.crtime96"
-+#define IS_CRTIME(name) (*(name) == *CRTIME_XATTR && strcmp(name, CRTIME_XATTR) == 0)
-+#define CRTIME_XATTR_LEN (8+4)
-+
-+struct CreationTime {
-+      unsigned long length;
-+      struct timespec crtime;
-+};
-+
-+static struct timespec *getCreationTime(const char *path)
-+{
-+      static struct CreationTime attrBuf;
-+      struct attrlist attrList;
-+
-+      memset(&attrList, 0, sizeof attrList);
-+      attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
-+      attrList.commonattr = ATTR_CMN_CRTIME;
-+      if (getattrlist(path, &attrList, &attrBuf, sizeof attrBuf, FSOPT_NOFOLLOW) < 0)
-+              return NULL;
-+      return &attrBuf.crtime;
-+}
-+
-+static ssize_t get_crtime_xattr(const char *path, char *buf, size_t size)
-+{
-+      struct timespec *crtime_p;
-+
-+      if (buf == NULL)
-+              return CRTIME_XATTR_LEN;
-+      if (size < CRTIME_XATTR_LEN)
-+              return -1; /* Doesn't happen with rsync code... */
-+
-+      if ((crtime_p = getCreationTime(path)) == NULL)
-+              return -1;
-+
-+      SIVAL(buf, 0, crtime_p->tv_sec);
-+#if SIZEOF_TIME_T > 4
-+      SIVAL(buf, 4, crtime_p->tv_sec >> 32);
-+#else
-+      SIVAL(buf, 4, 0);
-+#endif
-+      SIVAL(buf, 8, crtime_p->tv_nsec);
-+
-+      return CRTIME_XATTR_LEN;
-+}
-+
-+static int set_crtime_xattr(const char *path, const char *buf, size_t size)
-+{
-+      struct attrlist attrList;
-+      struct timespec crtime;
-+
-+      if (size != CRTIME_XATTR_LEN)
-+              return -1;
-+
-+      crtime.tv_sec = IVAL(buf, 0);
-+#if SIZEOF_TIME_T > 4
-+      crtime.tv_sec += (time_t)IVAL(buf, 4) << 32;
-+#endif
-+      crtime.tv_nsec = IVAL(buf, 8);
-+
-+      memset(&attrList, 0, sizeof attrList);
-+      attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
-+      attrList.commonattr = ATTR_CMN_CRTIME;
-+      return setattrlist(path, &attrList, &crtime, sizeof crtime, FSOPT_NOFOLLOW);
-+}
-+
- ssize_t sys_lgetxattr(const char *path, const char *name, void *value, size_t size)
- {
-+      if (IS_CRTIME(name))
-+              return get_crtime_xattr(path, value, size);
-       return getxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
- }
- ssize_t sys_fgetxattr(int filedes, const char *name, void *value, size_t size)
- {
-+      /* XXX Figure out how to get creation time from an open filedes? */
-       return fgetxattr(filedes, name, value, size, 0, 0);
- }
- int sys_lsetxattr(const char *path, const char *name, const void *value, size_t size)
- {
-+      if (IS_CRTIME(name))
-+              return set_crtime_xattr(path, value, size);
-       return setxattr(path, name, value, size, 0, XATTR_NOFOLLOW);
- }
- int sys_lremovexattr(const char *path, const char *name)
- {
-+      /* Every file on hfs+ has this; you can't remove it... */
-+      if (IS_CRTIME(name))
-+              return 0;
-       return removexattr(path, name, XATTR_NOFOLLOW);
- }
- ssize_t sys_llistxattr(const char *path, char *list, size_t size)
- {
--      return listxattr(path, list, size, XATTR_NOFOLLOW);
-+      ssize_t ret = listxattr(path, list, size, XATTR_NOFOLLOW);
-+      if (ret < 0)
-+              return ret;
-+      if (getCreationTime(path) != NULL) {
-+              ret += sizeof CRTIME_XATTR;
-+              if (list) {
-+                      if ((size_t)ret > size) {
-+                              errno = ERANGE;
-+                              return -1;
-+                      }
-+                      memcpy(list + ret - sizeof CRTIME_XATTR,
-+                             CRTIME_XATTR, sizeof CRTIME_XATTR);
-+              }
-+      }
-+      return ret;
- }
- #elif HAVE_FREEBSD_XATTRS
index 97c0b96..d910772 100644 (file)
@@ -39,7 +39,7 @@ diff --git a/compat.c b/compat.c
 diff --git a/configure.in b/configure.in
 --- a/configure.in
 +++ b/configure.in
-@@ -552,13 +552,40 @@ AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
+@@ -554,13 +554,40 @@ AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
      strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
      setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \
      strerror putenv iconv_open locale_charset nl_langinfo getxattr \
@@ -84,7 +84,7 @@ diff --git a/configure.in b/configure.in
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -72,6 +72,7 @@ int remove_source_files = 0;
+@@ -73,6 +73,7 @@ int remove_source_files = 0;
  int one_file_system = 0;
  int protocol_version = PROTOCOL_VERSION;
  int sparse_files = 0;
@@ -92,7 +92,7 @@ diff --git a/options.c b/options.c
  int do_compression = 0;
  int def_compress_level = Z_DEFAULT_COMPRESSION;
  int am_root = 0; /* 0 = normal, 1 = root, 2 = --super, -1 = --fake-super */
-@@ -224,6 +225,7 @@ static void print_rsync_version(enum logcode f)
+@@ -225,6 +226,7 @@ static void print_rsync_version(enum logcode f)
        char const *links = "no ";
        char const *iconv = "no ";
        char const *ipv6 = "no ";
@@ -100,7 +100,7 @@ diff --git a/options.c b/options.c
        STRUCT_STAT *dumstat;
  
  #if SUBPROTOCOL_VERSION != 0
-@@ -256,6 +258,9 @@ static void print_rsync_version(enum logcode f)
+@@ -257,6 +259,9 @@ static void print_rsync_version(enum logcode f)
  #if defined HAVE_LUTIMES && defined HAVE_UTIMES
        symtimes = "";
  #endif
@@ -110,7 +110,7 @@ diff --git a/options.c b/options.c
  
        rprintf(f, "%s  version %s  protocol version %d%s\n",
                RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
-@@ -269,8 +274,8 @@ static void print_rsync_version(enum logcode f)
+@@ -270,8 +275,8 @@ static void print_rsync_version(enum logcode f)
                (int)(sizeof (int64) * 8));
        rprintf(f, "    %ssocketpairs, %shardlinks, %ssymlinks, %sIPv6, batchfiles, %sinplace,\n",
                got_socketpair, hardlinks, links, ipv6, have_inplace);
@@ -121,7 +121,7 @@ diff --git a/options.c b/options.c
  
  #ifdef MAINTAINER_MODE
        rprintf(f, "Panic Action: \"%s\"\n", get_panic_action());
-@@ -357,6 +362,9 @@ void usage(enum logcode F)
+@@ -358,6 +363,9 @@ void usage(enum logcode F)
    rprintf(F,"     --fake-super            store/recover privileged attrs using xattrs\n");
  #endif
    rprintf(F," -S, --sparse                handle sparse files efficiently\n");
@@ -131,15 +131,15 @@ diff --git a/options.c b/options.c
    rprintf(F," -n, --dry-run               perform a trial run with no changes made\n");
    rprintf(F," -W, --whole-file            copy files whole (without delta-xfer algorithm)\n");
    rprintf(F," -x, --one-file-system       don't cross filesystem boundaries\n");
-@@ -537,6 +545,7 @@ static struct poptOption long_options[] = {
-   {"max-size",         0,  POPT_ARG_STRING, &max_size_arg, OPT_MAX_SIZE, 0, 0 },
-   {"min-size",         0,  POPT_ARG_STRING, &min_size_arg, OPT_MIN_SIZE, 0, 0 },
-   {"sparse",          'S', POPT_ARG_NONE,   &sparse_files, 0, 0, 0 },
+@@ -542,6 +550,7 @@ static struct poptOption long_options[] = {
+   {"sparse",          'S', POPT_ARG_VAL,    &sparse_files, 1, 0, 0 },
+   {"no-sparse",        0,  POPT_ARG_VAL,    &sparse_files, 0, 0, 0 },
+   {"no-S",             0,  POPT_ARG_VAL,    &sparse_files, 0, 0, 0 },
 +  {"preallocate",      0,  POPT_ARG_NONE,   &preallocate_files, 0, 0, 0},
-   {"inplace",          0,  POPT_ARG_NONE,   &inplace, 0, 0, 0 },
+   {"inplace",          0,  POPT_ARG_VAL,    &inplace, 1, 0, 0 },
+   {"no-inplace",       0,  POPT_ARG_VAL,    &inplace, 0, 0, 0 },
    {"append",           0,  POPT_ARG_NONE,   0, OPT_APPEND, 0, 0 },
-   {"append-verify",    0,  POPT_ARG_VAL,    &append_mode, 2, 0, 0 },
-@@ -2022,6 +2031,9 @@ void server_options(char **args, int *argc_p)
+@@ -2048,6 +2057,9 @@ void server_options(char **args, int *argc_p)
        else if (remove_source_files)
                args[ac++] = "--remove-sent-files";
  
@@ -203,7 +203,7 @@ diff --git a/receiver.c b/receiver.c
 diff --git a/rsync.h b/rsync.h
 --- a/rsync.h
 +++ b/rsync.h
-@@ -602,6 +602,13 @@ struct ht_int64_node {
+@@ -604,6 +604,13 @@ struct ht_int64_node {
  #define ACLS_NEED_MASK 1
  #endif
  
@@ -228,7 +228,7 @@ diff --git a/rsync.yo b/rsync.yo
   -n, --dry-run               perform a trial run with no changes made
   -W, --whole-file            copy files whole (w/o delta-xfer algorithm)
   -x, --one-file-system       don't cross filesystem boundaries
-@@ -1036,6 +1037,18 @@ NOTE: Don't use this option when the destination is a Solaris "tmpfs"
+@@ -1043,6 +1044,18 @@ NOTE: Don't use this option when the destination is a Solaris "tmpfs"
  filesystem. It doesn't seem to handle seeks over null regions
  correctly and ends up corrupting the files.
  
@@ -261,8 +261,8 @@ diff --git a/syscall.c b/syscall.c
  extern int dry_run;
  extern int am_root;
  extern int read_only;
-@@ -291,3 +295,21 @@ char *d_name(struct dirent *di)
-       return di->d_name;
+@@ -282,3 +286,21 @@ OFF_T do_lseek(int fd, OFF_T offset, int whence)
+       return lseek(fd, offset, whence);
  #endif
  }
 +
diff --git a/remote-option.diff b/remote-option.diff
new file mode 100644 (file)
index 0000000..16975c0
--- /dev/null
@@ -0,0 +1,239 @@
+This patch implements a new --remote-option (-M) option that allows the
+user to override certain settings on the remote system.  For instance, it
+is now easier to pass -M--fake-super or "-M --log-file=/tmp/foo" instead of
+kluging up an --rsync-path setting.  This also solves the case where we
+want local --one-file-system (-x) but not remote ("-x -M--no-x"), or visa
+versa ("-M-x").
+
+To use this patch, run these commands for a successful build:
+
+    patch -p1 <patches/remote-option.diff
+    ./configure                      (optional if already run)
+    make
+
+diff --git a/options.c b/options.c
+--- a/options.c
++++ b/options.c
+@@ -174,6 +174,10 @@ int link_dest = 0;
+ int basis_dir_cnt = 0;
+ char *dest_option = NULL;
++#define MAX_REMOTE_ARGS (MAX_SERVER_ARGS/2)
++int remote_option_cnt = 0;
++const char *remote_options[MAX_SERVER_ARGS+1] = { "ARG0" };
++
+ int verbose = 0;
+ int quiet = 0;
+ int output_motd = 1;
+@@ -387,6 +391,7 @@ void usage(enum logcode F)
+   rprintf(F,"     --timeout=SECONDS       set I/O timeout in seconds\n");
+   rprintf(F,"     --contimeout=SECONDS    set daemon connection timeout in seconds\n");
+   rprintf(F," -I, --ignore-times          don't skip files that match in size and mod-time\n");
++  rprintf(F," -M, --remote-option=OPTION  send OPTION to the remote side only\n");
+   rprintf(F,"     --size-only             skip files that match in size\n");
+   rprintf(F,"     --modify-window=NUM     compare mod-times with reduced accuracy\n");
+   rprintf(F," -T, --temp-dir=DIR          create temporary files in directory DIR\n");
+@@ -645,6 +650,7 @@ static struct poptOption long_options[] = {
+   {"password-file",    0,  POPT_ARG_STRING, &password_file, 0, 0, 0 },
+   {"blocking-io",      0,  POPT_ARG_VAL,    &blocking_io, 1, 0, 0 },
+   {"no-blocking-io",   0,  POPT_ARG_VAL,    &blocking_io, 0, 0, 0 },
++  {"remote-option",   'M', POPT_ARG_STRING, 0, 'M', 0, 0 },
+   {"protocol",         0,  POPT_ARG_INT,    &protocol_version, 0, 0, 0 },
+   {"checksum-seed",    0,  POPT_ARG_INT,    &checksum_seed, 0, 0, 0 },
+   {"server",           0,  POPT_ARG_NONE,   0, OPT_SERVER, 0, 0 },
+@@ -1140,6 +1146,20 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+                       }
+                       break;
++              case 'M':
++                      arg = poptGetOptArg(pc);
++                      if (*arg != '-') {
++                              snprintf(err_buf, sizeof err_buf,
++                                      "Remote option must start with a dash: %s\n", arg);
++                              return 0;
++                      }
++                      if (remote_option_cnt >= MAX_REMOTE_ARGS) {
++                              rprintf(FERROR, "too many remote options specified.\n");
++                              exit_cleanup(RERR_SYNTAX);
++                      }
++                      remote_options[++remote_option_cnt] = arg;
++                      break;
++
+               case OPT_WRITE_BATCH:
+                       /* batch_name is already set */
+                       write_batch = 1;
+@@ -1826,6 +1846,11 @@ void server_options(char **args, int *argc_p)
+ #endif
+       argstr[x] = '\0';
++      if (x > (int)sizeof argstr) { /* Not possible... */
++              rprintf(FERROR, "argstr overflow in server_options().\n");
++              exit_cleanup(RERR_MALLOC);
++      }
++
+       args[ac++] = argstr;
+ #ifdef ICONV_OPTION
+@@ -2048,6 +2073,21 @@ void server_options(char **args, int *argc_p)
+       else if (remove_source_files)
+               args[ac++] = "--remove-sent-files";
++      if (ac > MAX_SERVER_ARGS) { /* Not possible... */
++              rprintf(FERROR, "argc overflow in server_options().\n");
++              exit_cleanup(RERR_MALLOC);
++      }
++
++      if (remote_option_cnt) {
++              int j;
++              if (ac + remote_option_cnt > MAX_SERVER_ARGS) {
++                      rprintf(FERROR, "too many remote options specified.\n");
++                      exit_cleanup(RERR_SYNTAX);
++              }
++              for (j = 1; j <= remote_option_cnt; j++)
++                      args[ac++] = (char*)remote_options[j];
++      }
++
+       *argc_p = ac;
+       return;
+diff --git a/pipe.c b/pipe.c
+--- a/pipe.c
++++ b/pipe.c
+@@ -22,12 +22,15 @@
+ #include "rsync.h"
++extern int am_root;
+ extern int am_sender;
+ extern int am_server;
+ extern int blocking_io;
+ extern int filesfrom_fd;
+ extern mode_t orig_umask;
+ extern char *logfile_name;
++extern int remote_option_cnt;
++extern const char *remote_options[];
+ extern struct chmod_mode_struct *chmod_modes;
+ /**
+@@ -139,6 +142,18 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
+                       logfile_close();
+               }
++              if (am_root < 0)
++                      am_root = 0;
++
++              if (remote_option_cnt) {
++                      int rc = remote_option_cnt + 1;
++                      const char **rv = remote_options;
++                      if (!parse_arguments(&rc, &rv)) {
++                              option_error();
++                              exit_cleanup(RERR_SYNTAX);
++                      }
++              }
++
+               if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
+                   close(to_child_pipe[1]) < 0 ||
+                   close(from_child_pipe[0]) < 0 ||
+diff --git a/rsync.yo b/rsync.yo
+--- a/rsync.yo
++++ b/rsync.yo
+@@ -412,6 +412,7 @@ to the detailed description below for a complete description.  verb(
+      --progress              show progress during transfer
+  -P                          same as --partial --progress
+  -i, --itemize-changes       output a change-summary for all updates
++ -M, --remote-option=OPTION  send OPTION to the remote side only
+      --out-format=FORMAT     output updates using the specified FORMAT
+      --log-file=FILE         log what we're doing to the specified FILE
+      --log-file-format=FMT   log updates using the specified FMT
+@@ -1020,16 +1021,13 @@ This is a good way to backup data without using a super-user, and to store
+ ACLs from incompatible systems.
+ The bf(--fake-super) option only affects the side where the option is used.
+-To affect the remote side of a remote-shell connection, specify an rsync
+-path:
++To affect the remote side of a remote-shell connection, use the
++bf(--remote-option) (bf(-M)) option:
+-quote(tt(  rsync -av --rsync-path="rsync --fake-super" /src/ host:/dest/))
++quote(tt(  rsync -av -M--fake-super /src/ host:/dest/))
+-Since there is only one "side" in a local copy, this option affects both
+-the sending and receiving of files.  You'll need to specify a copy using
+-"localhost" if you need to avoid this, possibly using the "lsh" shell
+-script (from the support directory) as a substitute for an actual remote
+-shell (see bf(--rsh)).
++For a local copy, this option affects only the source.  Specify a
++bf(--remote-option) to affect the destination.
+ This option is overridden by both bf(--super) and bf(--no-super).
+@@ -1275,6 +1273,36 @@ machine for use with the bf(--relative) option.  For instance:
+ quote(tt(    rsync -avR --rsync-path="cd /a/b && rsync" host:c/d /e/))
++dit(bf(-M, --remote-option=OPTION)) This option is used for more advanced
++situations where you want certain effects to be limited to one side of the
++transfer only.  For instance, if you want to pass bf(--log-file=FILE) and
++bf(--fake-super) to the remote system, specify it like this:
++
++quote(tt(    rsync -av -M --log-file=foo -M--fake-super src/ dest/))
++
++If you want to have an option affect only the local side of a transfer when
++it normally affects both sides, send its negation to the remote side.  Like
++this:
++
++quote(tt(    rsync -av -x -M--no-x src/ dest/))
++
++Be cautious using this, as it is possible to toggle an option that will cause
++rsync to have a different idea about what data to expect next over the socket,
++and that will make it fail in a cryptic fashion.
++
++Note that it is best to use a separate bf(--remote-option) for each option you
++want to pass.  This makes your useage compatible with the bf(--preserve-spaces)
++option.  If that option is off, any spaces in your remote options will be split
++by the remote shell unless you take steps to protect them.
++
++When performing a local transfer, the "local" side is the sender and the
++"remote" side is the receiver.
++
++Note some versions of the popt option-parsing library have a bug in them that
++prevents you from using an adjacent arg with an equal in it next to a short
++option letter (e.g. tt(-M--log-file=/tmp/foo).  If this bug affects your
++version of popt, you can use the version of popt that is included with rsync.
++
+ dit(bf(-C, --cvs-exclude)) This is a useful shorthand for excluding a
+ broad range of files that you often don't want to transfer between
+ systems. It uses a similar algorithm to CVS to determine if
+@@ -1746,7 +1774,7 @@ option if you wish to override this.
+ Here's a example command that requests the remote side to log what is
+ happening:
+-verb(  rsync -av --rsync-path="rsync --log-file=/tmp/rlog" src/ dest/)
++verb(  rsync -av --remote-option=--log-file=/tmp/rlog src/ dest/)
+ This is very useful if you need to debug why a connection is closing
+ unexpectedly.
+diff --git a/testsuite/chown.test b/testsuite/chown.test
+--- a/testsuite/chown.test
++++ b/testsuite/chown.test
+@@ -16,7 +16,7 @@
+ case $0 in
+ *fake*)
+     $RSYNC --version | grep ", xattrs" >/dev/null || test_skipped "Rsync needs xattrs for fake device tests"
+-    RSYNC="$RSYNC --fake-super"
++    RSYNC="$RSYNC --fake-super -M--fake-super"
+     TLS_ARGS=--fake-super
+     case "`xattr 2>&1`" in
+     *--list:*)
+diff --git a/testsuite/devices.test b/testsuite/devices.test
+--- a/testsuite/devices.test
++++ b/testsuite/devices.test
+@@ -17,7 +17,7 @@ outfile="$scratchdir/rsync.out"
+ case $0 in
+ *fake*)
+     $RSYNC --version | grep ", xattrs" >/dev/null || test_skipped "Rsync needs xattrs for fake device tests"
+-    RSYNC="$RSYNC --fake-super"
++    RSYNC="$RSYNC --fake-super -M--fake-super"
+     TLS_ARGS=--fake-super
+     case "`xattr 2>&1`" in
+     *--list:*)
index a889f7d..5855d5b 100644 (file)
@@ -25,7 +25,7 @@ diff --git a/flist.c b/flist.c
  extern struct stats stats;
  extern char *filesfrom_host;
  
-@@ -1502,6 +1503,9 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len,
+@@ -1537,6 +1538,9 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len,
                }
  
                send_file_name(f, flist, fbuf, NULL, flags, filter_level);
@@ -38,7 +38,7 @@ diff --git a/flist.c b/flist.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -108,6 +108,7 @@ int size_only = 0;
+@@ -109,6 +109,7 @@ int size_only = 0;
  int daemon_bwlimit = 0;
  int bwlimit = 0;
  int fuzzy_basis = 0;
@@ -46,7 +46,7 @@ diff --git a/options.c b/options.c
  size_t bwlimit_writemax = 0;
  int ignore_existing = 0;
  int ignore_non_existing = 0;
-@@ -423,6 +424,7 @@ void usage(enum logcode F)
+@@ -424,6 +425,7 @@ void usage(enum logcode F)
    rprintf(F,"     --password-file=FILE    read daemon-access password from FILE\n");
    rprintf(F,"     --list-only             list the files instead of copying them\n");
    rprintf(F,"     --bwlimit=KBPS          limit I/O bandwidth; KBytes per second\n");
@@ -54,7 +54,7 @@ diff --git a/options.c b/options.c
    rprintf(F,"     --write-batch=FILE      write a batched update to FILE\n");
    rprintf(F,"     --only-write-batch=FILE like --write-batch but w/o updating destination\n");
    rprintf(F,"     --read-batch=FILE       read a batched update from FILE\n");
-@@ -592,6 +594,7 @@ static struct poptOption long_options[] = {
+@@ -604,6 +606,7 @@ static struct poptOption long_options[] = {
    {"itemize-changes", 'i', POPT_ARG_NONE,   0, 'i', 0, 0 },
    {"no-itemize-changes",0, POPT_ARG_VAL,    &itemize_changes, 0, 0, 0 },
    {"no-i",             0,  POPT_ARG_VAL,    &itemize_changes, 0, 0, 0 },
index f509693..9832370 100644 (file)
--- a/slp.diff
+++ b/slp.diff
@@ -43,7 +43,7 @@ diff --git a/Makefile.in b/Makefile.in
 diff --git a/clientserver.c b/clientserver.c
 --- a/clientserver.c
 +++ b/clientserver.c
-@@ -1032,6 +1032,13 @@ int daemon_main(void)
+@@ -1068,6 +1068,13 @@ int daemon_main(void)
         * address too.  In fact, why not just do inet_ntop on the
         * local address??? */
  
@@ -60,7 +60,7 @@ diff --git a/clientserver.c b/clientserver.c
 diff --git a/configure.in b/configure.in
 --- a/configure.in
 +++ b/configure.in
-@@ -637,6 +637,29 @@ if test $rsync_cv_can_hardlink_special = yes; then
+@@ -639,6 +639,29 @@ if test $rsync_cv_can_hardlink_special = yes; then
      AC_DEFINE(CAN_HARDLINK_SPECIAL, 1, [Define to 1 if link() can hard-link special files.])
  fi
  
@@ -126,7 +126,7 @@ diff --git a/loadparm.c b/loadparm.c
 diff --git a/main.c b/main.c
 --- a/main.c
 +++ b/main.c
-@@ -1146,6 +1146,18 @@ static int start_client(int argc, char *argv[])
+@@ -1112,6 +1112,18 @@ static int start_client(int argc, char *argv[])
  
        if (!read_batch) { /* for read_batch, NO source is specified */
                char *path = check_for_hostspec(argv[0], &shell_machine, &rsync_port);
@@ -148,7 +148,7 @@ diff --git a/main.c b/main.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -224,6 +224,7 @@ static void print_rsync_version(enum logcode f)
+@@ -225,6 +225,7 @@ static void print_rsync_version(enum logcode f)
        char const *links = "no ";
        char const *iconv = "no ";
        char const *ipv6 = "no ";
@@ -156,7 +156,7 @@ diff --git a/options.c b/options.c
        STRUCT_STAT *dumstat;
  
  #if SUBPROTOCOL_VERSION != 0
-@@ -256,6 +257,9 @@ static void print_rsync_version(enum logcode f)
+@@ -257,6 +258,9 @@ static void print_rsync_version(enum logcode f)
  #if defined HAVE_LUTIMES && defined HAVE_UTIMES
        symtimes = "";
  #endif
@@ -166,7 +166,7 @@ diff --git a/options.c b/options.c
  
        rprintf(f, "%s  version %s  protocol version %d%s\n",
                RSYNC_NAME, RSYNC_VERSION, PROTOCOL_VERSION, subprotocol);
-@@ -269,8 +273,8 @@ static void print_rsync_version(enum logcode f)
+@@ -270,8 +274,8 @@ static void print_rsync_version(enum logcode f)
                (int)(sizeof (int64) * 8));
        rprintf(f, "    %ssocketpairs, %shardlinks, %ssymlinks, %sIPv6, batchfiles, %sinplace,\n",
                got_socketpair, hardlinks, links, ipv6, have_inplace);
@@ -180,7 +180,7 @@ diff --git a/options.c b/options.c
 diff --git a/rsync.h b/rsync.h
 --- a/rsync.h
 +++ b/rsync.h
-@@ -187,6 +187,10 @@
+@@ -190,6 +190,10 @@
  #define SIGNIFICANT_ITEM_FLAGS (~(\
        ITEM_BASIS_TYPE_FOLLOWS | ITEM_XNAME_FOLLOWS | ITEM_LOCAL_CHANGE))
  
@@ -188,7 +188,7 @@ diff --git a/rsync.h b/rsync.h
 +/* definately don't set to less than about 30 seconds */
 +#define SLP_MIN_TIMEOUT 120
 +
- #define CFN_KEEP_LEADING_DOT_DIR (1<<0)
+ #define CFN_KEEP_DOT_DIRS (1<<0)
  #define CFN_KEEP_TRAILING_SLASH (1<<1)
  #define CFN_DROP_TRAILING_DOT_DIR (1<<2)
 diff --git a/rsync.yo b/rsync.yo
@@ -235,7 +235,7 @@ diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo
  enddit()
  
  
-@@ -654,6 +663,7 @@ use chroot = yes
+@@ -652,6 +661,7 @@ use chroot = yes
  max connections = 4
  syslog facility = local5
  pid file = /var/run/rsyncd.pid
index 6356351..367a816 100644 (file)
@@ -12,15 +12,15 @@ To use this patch, run these commands for a successful build:
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -32,6 +32,7 @@ extern struct filter_list_struct filter_list;
- extern struct filter_list_struct server_filter_list;
+@@ -33,6 +33,7 @@ extern struct filter_list_struct filter_list;
+ extern struct filter_list_struct daemon_filter_list;
  
  int make_backups = 0;
 +int make_source_backups = 0;
  
  /**
   * If 1, send the whole file as literal data rather than trying to
-@@ -366,6 +367,7 @@ void usage(enum logcode F)
+@@ -367,6 +368,7 @@ void usage(enum logcode F)
    rprintf(F,"     --existing              skip creating new files on receiver\n");
    rprintf(F,"     --ignore-existing       skip updating files that already exist on receiver\n");
    rprintf(F,"     --remove-source-files   sender removes synchronized files (non-dirs)\n");
@@ -28,7 +28,7 @@ diff --git a/options.c b/options.c
    rprintf(F,"     --del                   an alias for --delete-during\n");
    rprintf(F,"     --delete                delete extraneous files from destination dirs\n");
    rprintf(F,"     --delete-before         receiver deletes before transfer, not during\n");
-@@ -595,6 +597,7 @@ static struct poptOption long_options[] = {
+@@ -607,6 +609,7 @@ static struct poptOption long_options[] = {
    {"bwlimit",          0,  POPT_ARG_INT,    &bwlimit, 0, 0, 0 },
    {"no-bwlimit",       0,  POPT_ARG_VAL,    &bwlimit, 0, 0, 0 },
    {"backup",          'b', POPT_ARG_VAL,    &make_backups, 1, 0, 0 },
@@ -36,7 +36,7 @@ diff --git a/options.c b/options.c
    {"no-backup",        0,  POPT_ARG_VAL,    &make_backups, 0, 0, 0 },
    {"backup-dir",       0,  POPT_ARG_STRING, &backup_dir, 0, 0, 0 },
    {"suffix",           0,  POPT_ARG_STRING, &backup_suffix, 0, 0, 0 },
-@@ -1925,6 +1928,8 @@ void server_options(char **args, int *argc_p)
+@@ -1951,6 +1954,8 @@ void server_options(char **args, int *argc_p)
                                goto oom;
                        args[ac++] = arg;
                }
@@ -56,7 +56,7 @@ diff --git a/rsync.yo b/rsync.yo
       --del                   an alias for --delete-during
       --delete                delete extraneous files from dest dirs
       --delete-before         receiver deletes before transfer (default)
-@@ -1098,6 +1099,14 @@ dit(bf(--remove-source-files)) This tells rsync to remove from the sending
+@@ -1105,6 +1106,14 @@ dit(bf(--remove-source-files)) This tells rsync to remove from the sending
  side the files (meaning non-directories) that are a part of the transfer
  and have been successfully duplicated on the receiving side.
  
index cd6d0c7..45c51f1 100644 (file)
@@ -33,7 +33,7 @@ To use this patch, run these commands for a successful build:
 diff --git a/generator.c b/generator.c
 --- a/generator.c
 +++ b/generator.c
-@@ -63,6 +63,7 @@ extern int append_mode;
+@@ -62,6 +62,7 @@ extern int append_mode;
  extern int make_backups;
  extern int csum_length;
  extern int ignore_times;
@@ -41,7 +41,7 @@ diff --git a/generator.c b/generator.c
  extern int size_only;
  extern OFF_T max_size;
  extern OFF_T min_size;
-@@ -696,7 +697,7 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+@@ -708,7 +709,7 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
  /* Perform our quick-check heuristic for determining if a file is unchanged. */
  int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st)
  {
@@ -53,7 +53,7 @@ diff --git a/generator.c b/generator.c
 diff --git a/main.c b/main.c
 --- a/main.c
 +++ b/main.c
-@@ -139,7 +139,7 @@ pid_t wait_process(pid_t pid, int *status_ptr, int flags)
+@@ -136,7 +136,7 @@ pid_t wait_process(pid_t pid, int *status_ptr, int flags)
  }
  
  /* Wait for a process to exit, calling io_flush while waiting. */
@@ -65,7 +65,7 @@ diff --git a/main.c b/main.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -105,6 +105,7 @@ int keep_partial = 0;
+@@ -106,6 +106,7 @@ int keep_partial = 0;
  int safe_symlinks = 0;
  int copy_unsafe_links = 0;
  int size_only = 0;
@@ -73,7 +73,7 @@ diff --git a/options.c b/options.c
  int daemon_bwlimit = 0;
  int bwlimit = 0;
  int fuzzy_basis = 0;
-@@ -162,6 +163,8 @@ char *logfile_name = NULL;
+@@ -163,6 +164,8 @@ char *logfile_name = NULL;
  char *logfile_format = NULL;
  char *stdout_format = NULL;
  char *password_file = NULL;
@@ -82,7 +82,7 @@ diff --git a/options.c b/options.c
  char *rsync_path = RSYNC_PATH;
  char *backup_dir = NULL;
  char backup_dir_buf[MAXPATHLEN];
-@@ -387,6 +390,7 @@ void usage(enum logcode F)
+@@ -388,6 +391,7 @@ void usage(enum logcode F)
    rprintf(F,"     --contimeout=SECONDS    set daemon connection timeout in seconds\n");
    rprintf(F," -I, --ignore-times          don't skip files that match in size and mod-time\n");
    rprintf(F,"     --size-only             skip files that match in size\n");
@@ -90,7 +90,7 @@ diff --git a/options.c b/options.c
    rprintf(F,"     --modify-window=NUM     compare mod-times with reduced accuracy\n");
    rprintf(F," -T, --temp-dir=DIR          create temporary files in directory DIR\n");
    rprintf(F," -y, --fuzzy                 find similar file for basis if no dest file\n");
-@@ -426,6 +430,8 @@ void usage(enum logcode F)
+@@ -427,6 +431,8 @@ void usage(enum logcode F)
    rprintf(F,"     --write-batch=FILE      write a batched update to FILE\n");
    rprintf(F,"     --only-write-batch=FILE like --write-batch but w/o updating destination\n");
    rprintf(F,"     --read-batch=FILE       read a batched update from FILE\n");
@@ -99,7 +99,7 @@ diff --git a/options.c b/options.c
    rprintf(F,"     --protocol=NUM          force an older protocol version to be used\n");
  #ifdef ICONV_OPTION
    rprintf(F,"     --iconv=CONVERT_SPEC    request charset conversion of filenames\n");
-@@ -527,6 +533,7 @@ static struct poptOption long_options[] = {
+@@ -530,6 +536,7 @@ static struct poptOption long_options[] = {
    {"chmod",            0,  POPT_ARG_STRING, 0, OPT_CHMOD, 0, 0 },
    {"ignore-times",    'I', POPT_ARG_NONE,   &ignore_times, 0, 0, 0 },
    {"size-only",        0,  POPT_ARG_NONE,   &size_only, 0, 0, 0 },
@@ -107,7 +107,7 @@ diff --git a/options.c b/options.c
    {"one-file-system", 'x', POPT_ARG_NONE,   0, 'x', 0, 0 },
    {"no-one-file-system",'x',POPT_ARG_VAL,   &one_file_system, 0, 0, 0 },
    {"no-x",            'x', POPT_ARG_VAL,    &one_file_system, 0, 0, 0 },
-@@ -630,6 +637,8 @@ static struct poptOption long_options[] = {
+@@ -645,6 +652,8 @@ static struct poptOption long_options[] = {
    {"password-file",    0,  POPT_ARG_STRING, &password_file, 0, 0, 0 },
    {"blocking-io",      0,  POPT_ARG_VAL,    &blocking_io, 1, 0, 0 },
    {"no-blocking-io",   0,  POPT_ARG_VAL,    &blocking_io, 0, 0, 0 },
@@ -116,7 +116,7 @@ diff --git a/options.c b/options.c
    {"protocol",         0,  POPT_ARG_INT,    &protocol_version, 0, 0, 0 },
    {"checksum-seed",    0,  POPT_ARG_INT,    &checksum_seed, 0, 0, 0 },
    {"server",           0,  POPT_ARG_NONE,   0, OPT_SERVER, 0, 0 },
-@@ -1608,6 +1617,16 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1634,6 +1643,16 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                }
        }
  
@@ -133,7 +133,7 @@ diff --git a/options.c b/options.c
        if (files_from) {
                char *h, *p;
                int q;
-@@ -1927,6 +1946,25 @@ void server_options(char **args, int *argc_p)
+@@ -1953,6 +1972,25 @@ void server_options(char **args, int *argc_p)
                }
        }
  
@@ -314,7 +314,7 @@ diff --git a/receiver.c b/receiver.c
 diff --git a/rsync.h b/rsync.h
 --- a/rsync.h
 +++ b/rsync.h
-@@ -133,6 +133,7 @@
+@@ -134,6 +134,7 @@
  #define IOERR_DEL_LIMIT (1<<2)
  
  #define MAX_ARGS 1000
@@ -342,7 +342,7 @@ diff --git a/rsync.yo b/rsync.yo
       --protocol=NUM          force an older protocol version to be used
       --iconv=CONVERT_SPEC    request charset conversion of filenames
       --checksum-seed=NUM     set block/file checksum seed (advanced)
-@@ -2021,6 +2024,33 @@ file previously generated by bf(--write-batch).
+@@ -2033,6 +2036,33 @@ file previously generated by bf(--write-batch).
  If em(FILE) is bf(-), the batch data will be read from standard input.
  See the "BATCH MODE" section for details.
  
diff --git a/sparse-block.diff b/sparse-block.diff
new file mode 100644 (file)
index 0000000..ba5da97
--- /dev/null
@@ -0,0 +1,107 @@
+This patch adds the --sparse-block option.  Andrea Righi writes:
+
+  In some filesystems, typically optimized for large I/O throughputs (like
+  IBM GPFS, IBM SAN FS, or distributed filesystems in general) a lot of
+  lseek() operations can strongly impact on performances. In this cases it
+  can be helpful to enlarge the block size used to handle sparse files
+  directly from a command line parameter.
+
+  For example, using a sparse write size of 32KB, I've been able to
+  increase the transfer rate of an order of magnitude copying the output
+  files of scientific applications from GPFS to GPFS or GPFS to SAN FS.
+
+  -Andrea
+
+To use this patch, run these commands for a successful build:
+
+    patch -p1 <patches/sparse-block.diff
+    ./configure                               (optional if already run)
+    make
+
+diff --git a/fileio.c b/fileio.c
+--- a/fileio.c
++++ b/fileio.c
+@@ -26,6 +26,7 @@
+ #endif
+ extern int sparse_files;
++extern long sparse_files_block_size;
+ static char last_byte;
+ static size_t sparse_seek = 0;
+@@ -115,7 +116,7 @@ int write_file(int f,char *buf,size_t len)
+       while (len > 0) {
+               int r1;
+               if (sparse_files > 0) {
+-                      int len1 = MIN(len, SPARSE_WRITE_SIZE);
++                      int len1 = MIN(len, (size_t)sparse_files_block_size);
+                       r1 = write_sparse(f, buf, len1);
+               } else {
+                       if (!wf_writeBuf) {
+diff --git a/options.c b/options.c
+--- a/options.c
++++ b/options.c
+@@ -73,6 +73,7 @@ int remove_source_files = 0;
+ int one_file_system = 0;
+ int protocol_version = PROTOCOL_VERSION;
+ int sparse_files = 0;
++long sparse_files_block_size = SPARSE_WRITE_SIZE;
+ int do_compression = 0;
+ int def_compress_level = Z_DEFAULT_COMPRESSION;
+ int am_root = 0; /* 0 = normal, 1 = root, 2 = --super, -1 = --fake-super */
+@@ -358,6 +359,7 @@ void usage(enum logcode F)
+   rprintf(F,"     --fake-super            store/recover privileged attrs using xattrs\n");
+ #endif
+   rprintf(F," -S, --sparse                handle sparse files efficiently\n");
++  rprintf(F,"     --sparse-block=SIZE     set the block size used to handle sparse files\n");
+   rprintf(F," -n, --dry-run               perform a trial run with no changes made\n");
+   rprintf(F," -W, --whole-file            copy files whole (without delta-xfer algorithm)\n");
+   rprintf(F," -x, --one-file-system       don't cross filesystem boundaries\n");
+@@ -542,6 +544,7 @@ static struct poptOption long_options[] = {
+   {"sparse",          'S', POPT_ARG_VAL,    &sparse_files, 1, 0, 0 },
+   {"no-sparse",        0,  POPT_ARG_VAL,    &sparse_files, 0, 0, 0 },
+   {"no-S",             0,  POPT_ARG_VAL,    &sparse_files, 0, 0, 0 },
++  {"sparse-block",     0,  POPT_ARG_LONG,   &sparse_files_block_size, 0, 0, 0 },
+   {"inplace",          0,  POPT_ARG_VAL,    &inplace, 1, 0, 0 },
+   {"no-inplace",       0,  POPT_ARG_VAL,    &inplace, 0, 0, 0 },
+   {"append",           0,  POPT_ARG_NONE,   0, OPT_APPEND, 0, 0 },
+@@ -1885,6 +1888,12 @@ void server_options(char **args, int *argc_p)
+               args[ac++] = arg;
+       }
++      if (sparse_files_block_size) {
++              if (asprintf(&arg, "--sparse-block=%lu", sparse_files_block_size) < 0)
++                      goto oom;
++              args[ac++] = arg;
++      }
++
+       if (io_timeout) {
+               if (asprintf(&arg, "--timeout=%d", io_timeout) < 0)
+                       goto oom;
+diff --git a/rsync.yo b/rsync.yo
+--- a/rsync.yo
++++ b/rsync.yo
+@@ -352,6 +352,7 @@ to the detailed description below for a complete description.  verb(
+      --super                 receiver attempts super-user activities
+      --fake-super            store/recover privileged attrs using xattrs
+  -S, --sparse                handle sparse files efficiently
++     --sparse-block=SIZE     set block size used to handle sparse files
+  -n, --dry-run               perform a trial run with no changes made
+  -W, --whole-file            copy files whole (w/o delta-xfer algorithm)
+  -x, --one-file-system       don't cross filesystem boundaries
+@@ -1043,6 +1044,15 @@ NOTE: Don't use this option when the destination is a Solaris "tmpfs"
+ filesystem. It doesn't seem to handle seeks over null regions
+ correctly and ends up corrupting the files.
++dit(bf(--sparse-block=SIZE)) Change the block size used to handle sparse files
++to SIZE bytes.  This option only has an effect if the bf(--sparse) (bf(-S))
++option was also specified.  The default block size used by rsync to detect a
++file hole is 1024 bytes; when the receiver writes data to the destination file
++and option bf(--sparse) is used, rsync checks every 1024-bytes chunk to detect
++if they are actually filled with data or not.  With certain filesystems,
++optimized to receive data streams for example, enlarging this block size can
++strongly increase performance.  The option can be used to tune this block size.
++
+ dit(bf(-n, --dry-run)) This makes rsync perform a trial run that doesn't
+ make any changes (and produces mostly the same output as a real run).  It
+ is most commonly used in combination with the bf(-v, --verbose) and/or
index 9a7280c..1ce8ab9 100644 (file)
@@ -10,7 +10,7 @@ To use this patch, run these commands for a successful build:
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -203,6 +203,7 @@ static int refused_delete, refused_archive_part, refused_compress;
+@@ -204,6 +204,7 @@ static int refused_delete, refused_archive_part, refused_compress;
  static int refused_partial, refused_progress, refused_delete_before;
  static int refused_delete_during;
  static int refused_inplace, refused_no_iconv;
@@ -18,7 +18,7 @@ diff --git a/options.c b/options.c
  static char *max_size_arg, *min_size_arg;
  static char tmp_partialdir[] = ".~tmp~";
  
-@@ -423,6 +424,7 @@ void usage(enum logcode F)
+@@ -424,6 +425,7 @@ void usage(enum logcode F)
    rprintf(F,"     --password-file=FILE    read daemon-access password from FILE\n");
    rprintf(F,"     --list-only             list the files instead of copying them\n");
    rprintf(F,"     --bwlimit=KBPS          limit I/O bandwidth; KBytes per second\n");
@@ -26,7 +26,7 @@ diff --git a/options.c b/options.c
    rprintf(F,"     --write-batch=FILE      write a batched update to FILE\n");
    rprintf(F,"     --only-write-batch=FILE like --write-batch but w/o updating destination\n");
    rprintf(F,"     --read-batch=FILE       read a batched update from FILE\n");
-@@ -630,6 +632,7 @@ static struct poptOption long_options[] = {
+@@ -645,6 +647,7 @@ static struct poptOption long_options[] = {
    {"password-file",    0,  POPT_ARG_STRING, &password_file, 0, 0, 0 },
    {"blocking-io",      0,  POPT_ARG_VAL,    &blocking_io, 1, 0, 0 },
    {"no-blocking-io",   0,  POPT_ARG_VAL,    &blocking_io, 0, 0, 0 },
@@ -34,7 +34,7 @@ diff --git a/options.c b/options.c
    {"protocol",         0,  POPT_ARG_INT,    &protocol_version, 0, 0, 0 },
    {"checksum-seed",    0,  POPT_ARG_INT,    &checksum_seed, 0, 0, 0 },
    {"server",           0,  POPT_ARG_NONE,   0, OPT_SERVER, 0, 0 },
-@@ -1259,6 +1262,13 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1275,6 +1278,13 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                }
        }
  
index fb6c36c..0c76ec2 100644 (file)
@@ -12,7 +12,7 @@ To use this patch, run these commands for a successful build:
 diff --git a/io.c b/io.c
 --- a/io.c
 +++ b/io.c
-@@ -53,6 +53,7 @@ extern int protocol_version;
+@@ -54,6 +54,7 @@ extern int protocol_version;
  extern int remove_source_files;
  extern int preserve_hard_links;
  extern struct stats stats;
@@ -20,7 +20,7 @@ diff --git a/io.c b/io.c
  extern struct file_list *cur_flist;
  #ifdef ICONV_OPTION
  extern int filesfrom_convert;
-@@ -216,16 +217,24 @@ static void check_timeout(void)
+@@ -221,16 +222,24 @@ static void check_timeout(void)
  {
        time_t t;
  
@@ -51,7 +51,7 @@ diff --git a/io.c b/io.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -112,6 +112,7 @@ size_t bwlimit_writemax = 0;
+@@ -113,6 +113,7 @@ size_t bwlimit_writemax = 0;
  int ignore_existing = 0;
  int ignore_non_existing = 0;
  int need_messages_from_generator = 0;
@@ -59,7 +59,7 @@ diff --git a/options.c b/options.c
  int max_delete = INT_MIN;
  OFF_T max_size = 0;
  OFF_T min_size = 0;
-@@ -423,6 +424,8 @@ void usage(enum logcode F)
+@@ -424,6 +425,8 @@ void usage(enum logcode F)
    rprintf(F,"     --password-file=FILE    read daemon-access password from FILE\n");
    rprintf(F,"     --list-only             list the files instead of copying them\n");
    rprintf(F,"     --bwlimit=KBPS          limit I/O bandwidth; KBytes per second\n");
@@ -68,7 +68,7 @@ diff --git a/options.c b/options.c
    rprintf(F,"     --write-batch=FILE      write a batched update to FILE\n");
    rprintf(F,"     --only-write-batch=FILE like --write-batch but w/o updating destination\n");
    rprintf(F,"     --read-batch=FILE       read a batched update from FILE\n");
-@@ -445,7 +448,7 @@ enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
+@@ -446,7 +449,7 @@ enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
        OPT_FILTER, OPT_COMPARE_DEST, OPT_COPY_DEST, OPT_LINK_DEST, OPT_HELP,
        OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW, OPT_MIN_SIZE, OPT_CHMOD,
        OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_ONLY_WRITE_BATCH, OPT_MAX_SIZE,
@@ -77,16 +77,16 @@ diff --git a/options.c b/options.c
        OPT_SERVER, OPT_REFUSED_BASE = 9000};
  
  static struct poptOption long_options[] = {
-@@ -613,6 +616,8 @@ static struct poptOption long_options[] = {
-   {"timeout",          0,  POPT_ARG_INT,    &io_timeout, 0, 0, 0 },
+@@ -626,6 +629,8 @@ static struct poptOption long_options[] = {
    {"no-timeout",       0,  POPT_ARG_VAL,    &io_timeout, 0, 0, 0 },
    {"contimeout",       0,  POPT_ARG_INT,    &connect_timeout, 0, 0, 0 },
+   {"no-contimeout",    0,  POPT_ARG_VAL,    &connect_timeout, 0, 0, 0 },
 +  {"stop-at",          0,  POPT_ARG_STRING, 0, OPT_STOP_AT, 0, 0 },
 +  {"time-limit",       0,  POPT_ARG_STRING, 0, OPT_TIME_LIMIT, 0, 0 },
    {"rsh",             'e', POPT_ARG_STRING, &shell_cmd, 0, 0, 0 },
    {"rsync-path",       0,  POPT_ARG_STRING, &rsync_path, 0, 0, 0 },
    {"temp-dir",        'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
-@@ -1244,6 +1249,36 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1260,6 +1265,36 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                        return 0;
  #endif
  
@@ -123,7 +123,7 @@ diff --git a/options.c b/options.c
                default:
                        /* A large opt value means that set_refuse_options()
                         * turned this option off. */
-@@ -1871,6 +1906,15 @@ void server_options(char **args, int *argc_p)
+@@ -1897,6 +1932,15 @@ void server_options(char **args, int *argc_p)
                args[ac++] = arg;
        }
  
@@ -151,7 +151,7 @@ diff --git a/rsync.yo b/rsync.yo
       --write-batch=FILE      write a batched update to FILE
       --only-write-batch=FILE like --write-batch but w/o updating dest
       --read-batch=FILE       read a batched update from FILE
-@@ -1995,6 +1997,19 @@ transfer was too fast, it will wait before sending the next data block. The
+@@ -2007,6 +2009,19 @@ transfer was too fast, it will wait before sending the next data block. The
  result is an average transfer rate equaling the specified limit. A value
  of zero specifies no limit.
  
index 47f5f00..eeb12cc 100644 (file)
@@ -26,7 +26,7 @@ diff --git a/flist.c b/flist.c
  #define PTR_SIZE (sizeof (struct file_struct *))
  
  int io_error;
-@@ -607,6 +610,24 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
+@@ -642,6 +645,24 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
                stats.total_size += F_LENGTH(file);
  }
  
@@ -51,7 +51,7 @@ diff --git a/flist.c b/flist.c
  static struct file_struct *recv_file_entry(struct file_list *flist,
                                           int xflags, int f)
  {
-@@ -675,6 +696,9 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+@@ -710,6 +731,9 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
        }
  #endif
  
@@ -64,7 +64,7 @@ diff --git a/flist.c b/flist.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -183,6 +183,8 @@ int logfile_format_has_i = 0;
+@@ -184,6 +184,8 @@ int logfile_format_has_i = 0;
  int logfile_format_has_o_or_i = 0;
  int always_checksum = 0;
  int list_only = 0;
@@ -73,7 +73,7 @@ diff --git a/options.c b/options.c
  
  #define MAX_BATCH_NAME_LEN 256        /* Must be less than MAXPATHLEN-13 */
  char *batch_name = NULL;
-@@ -430,6 +432,7 @@ void usage(enum logcode F)
+@@ -431,6 +433,7 @@ void usage(enum logcode F)
  #ifdef ICONV_OPTION
    rprintf(F,"     --iconv=CONVERT_SPEC    request charset conversion of filenames\n");
  #endif
@@ -81,15 +81,15 @@ diff --git a/options.c b/options.c
    rprintf(F," -4, --ipv4                  prefer IPv4\n");
    rprintf(F," -6, --ipv6                  prefer IPv6\n");
    rprintf(F,"     --version               print version number\n");
-@@ -620,6 +623,7 @@ static struct poptOption long_options[] = {
+@@ -633,6 +636,7 @@ static struct poptOption long_options[] = {
    {"iconv",            0,  POPT_ARG_STRING, &iconv_opt, 0, 0, 0 },
    {"no-iconv",         0,  POPT_ARG_NONE,   0, OPT_NO_ICONV, 0, 0 },
  #endif
 +  {"tr",               0,  POPT_ARG_STRING, &tr_opt, 0, 0, 0 },
    {"ipv4",            '4', POPT_ARG_VAL,    &default_af_hint, AF_INET, 0, 0 },
    {"ipv6",            '6', POPT_ARG_VAL,    &default_af_hint, AF_INET6, 0, 0 },
-   {"8-bit-output",    '8', POPT_ARG_NONE,   &allow_8bit_chars, 0, 0, 0 },
-@@ -1654,6 +1658,31 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+   {"8-bit-output",    '8', POPT_ARG_VAL,    &allow_8bit_chars, 1, 0, 0 },
+@@ -1680,6 +1684,31 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                }
        }
  
@@ -121,7 +121,7 @@ diff --git a/options.c b/options.c
        am_starting_up = 0;
  
        return 1;
-@@ -2022,6 +2051,12 @@ void server_options(char **args, int *argc_p)
+@@ -2048,6 +2077,12 @@ void server_options(char **args, int *argc_p)
        else if (remove_source_files)
                args[ac++] = "--remove-sent-files";
  
@@ -145,7 +145,7 @@ diff --git a/rsync.yo b/rsync.yo
       --checksum-seed=NUM     set block/file checksum seed (advanced)
   -4, --ipv4                  prefer IPv4
   -6, --ipv6                  prefer IPv6
-@@ -2059,6 +2060,22 @@ daemon uses the charset specified in its "charset" configuration parameter
+@@ -2071,6 +2072,22 @@ daemon uses the charset specified in its "charset" configuration parameter
  regardless of the remote charset you actually pass.  Thus, you may feel free to
  specify just the local charset for a daemon transfer (e.g. bf(--iconv=utf8)).
  
index a6128a0..f5d2b1c 100644 (file)
@@ -18,7 +18,7 @@ diff --git a/flist.c b/flist.c
  
  extern char curr_dir[MAXPATHLEN];
  
-@@ -754,7 +755,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+@@ -789,7 +790,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                        uid = (uid_t)read_varint(f);
                        if (xflags & XMIT_USER_NAME_FOLLOWS)
                                uid = recv_user_name(f, uid);
@@ -27,7 +27,7 @@ diff --git a/flist.c b/flist.c
                                uid = match_uid(uid);
                }
        }
-@@ -766,7 +767,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+@@ -801,7 +802,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                        gid_flags = 0;
                        if (xflags & XMIT_GROUP_NAME_FOLLOWS)
                                gid = recv_group_name(f, gid, &gid_flags);
@@ -36,7 +36,7 @@ diff --git a/flist.c b/flist.c
                                gid = match_gid(gid, &gid_flags);
                }
        }
-@@ -2087,8 +2088,13 @@ struct file_list *recv_file_list(int f)
+@@ -2142,8 +2143,13 @@ struct file_list *recv_file_list(int f)
        int dstart, flags;
        int64 start_read;
  
@@ -54,7 +54,7 @@ diff --git a/flist.c b/flist.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -166,6 +166,8 @@ char *rsync_path = RSYNC_PATH;
+@@ -167,6 +167,8 @@ char *rsync_path = RSYNC_PATH;
  char *backup_dir = NULL;
  char backup_dir_buf[MAXPATHLEN];
  char *sockopts = NULL;
@@ -63,7 +63,7 @@ diff --git a/options.c b/options.c
  int rsync_port = 0;
  int compare_dest = 0;
  int copy_dest = 0;
-@@ -383,6 +385,8 @@ void usage(enum logcode F)
+@@ -384,6 +386,8 @@ void usage(enum logcode F)
    rprintf(F,"     --delay-updates         put all updated files into place at transfer's end\n");
    rprintf(F," -m, --prune-empty-dirs      prune empty directory chains from the file-list\n");
    rprintf(F,"     --numeric-ids           don't map uid/gid values by user/group name\n");
@@ -72,7 +72,7 @@ diff --git a/options.c b/options.c
    rprintf(F,"     --timeout=SECONDS       set I/O timeout in seconds\n");
    rprintf(F,"     --contimeout=SECONDS    set daemon connection timeout in seconds\n");
    rprintf(F," -I, --ignore-times          don't skip files that match in size and mod-time\n");
-@@ -610,6 +614,8 @@ static struct poptOption long_options[] = {
+@@ -622,6 +626,8 @@ static struct poptOption long_options[] = {
    {"no-s",             0,  POPT_ARG_VAL,    &protect_args, 0, 0, 0},
    {"numeric-ids",      0,  POPT_ARG_VAL,    &numeric_ids, 1, 0, 0 },
    {"no-numeric-ids",   0,  POPT_ARG_VAL,    &numeric_ids, 0, 0, 0 },
@@ -81,7 +81,7 @@ diff --git a/options.c b/options.c
    {"timeout",          0,  POPT_ARG_INT,    &io_timeout, 0, 0, 0 },
    {"no-timeout",       0,  POPT_ARG_VAL,    &io_timeout, 0, 0, 0 },
    {"contimeout",       0,  POPT_ARG_INT,    &connect_timeout, 0, 0, 0 },
-@@ -1965,6 +1971,18 @@ void server_options(char **args, int *argc_p)
+@@ -1991,6 +1997,18 @@ void server_options(char **args, int *argc_p)
                args[ac++] = "--use-qsort";
  
        if (am_sender) {
@@ -112,7 +112,7 @@ diff --git a/rsync.yo b/rsync.yo
       --timeout=SECONDS       set I/O timeout in seconds
       --contimeout=SECONDS    set daemon connection timeout in seconds
   -I, --ignore-times          don't skip files that match size and time
-@@ -1595,6 +1597,46 @@ from the source system is used instead.  See also the comments on the
+@@ -1602,6 +1604,46 @@ from the source system is used instead.  See also the comments on the
  the chroot setting affects rsync's ability to look up the names of the
  users and groups and what you can do about it.
  
index c9465e7..1fd2934 100644 (file)
@@ -46,7 +46,7 @@ diff --git a/xattrs.c b/xattrs.c
  
  #define RSYNC_XAL_INITIAL 5
  #define RSYNC_XAL_LIST_INITIAL 100
-@@ -239,7 +241,7 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
+@@ -245,7 +247,7 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
                if (!(ptr = get_xattr_data(fname, name, &datum_len, 0)))
                        return -1;
  
@@ -55,7 +55,7 @@ diff --git a/xattrs.c b/xattrs.c
                        /* For large datums, we store a flag and a checksum. */
                        name_offset = 1 + MAX_DIGEST_LEN;
                        sum_init(checksum_seed);
-@@ -307,7 +309,7 @@ static int find_matching_xattr(item_list *xalp)
+@@ -305,7 +307,7 @@ static int find_matching_xattr(item_list *xalp)
                         || rxas1[j].datum_len != rxas2[j].datum_len
                         || strcmp(rxas1[j].name, rxas2[j].name))
                                break;
@@ -64,7 +64,7 @@ diff --git a/xattrs.c b/xattrs.c
                                if (memcmp(rxas1[j].datum + 1,
                                           rxas2[j].datum + 1,
                                           MAX_DIGEST_LEN) != 0)
-@@ -344,34 +346,43 @@ int send_xattr(stat_x *sxp, int f)
+@@ -342,13 +344,22 @@ int send_xattr(stat_x *sxp, int f)
  {
        int ndx = find_matching_xattr(sxp->xattr);
  
@@ -88,37 +88,29 @@ diff --git a/xattrs.c b/xattrs.c
 -              write_varint(f, count);
 +              write_varint30(f, count);
                for (rxa = sxp->xattr->items; count--; rxa++) {
- #ifdef HAVE_LINUX_XATTRS
--                      write_varint(f, rxa->name_len);
+                       size_t name_len = rxa->name_len;
+                       const char *name = rxa->name;
+@@ -367,8 +378,8 @@ int send_xattr(stat_x *sxp, int f)
+                               name_len += UPRE_LEN;
+                       }
+ #endif
+-                      write_varint(f, name_len);
 -                      write_varint(f, rxa->datum_len);
-+                      write_varint30(f, rxa->name_len);
++                      write_varint30(f, name_len);
 +                      write_varint30(f, rxa->datum_len);
-                       write_buf(f, rxa->name, rxa->name_len);
- #else
-                       /* We strip the rsync prefix from disguised namespaces
-                        * and put everything else in the user namespace. */
-                       if (HAS_PREFIX(rxa->name, RSYNC_PREFIX)
-                        && rxa->name[RPRE_LEN] != '%') {
--                              write_varint(f, rxa->name_len - RPRE_LEN);
--                              write_varint(f, rxa->datum_len);
-+                              write_varint30(f, rxa->name_len - RPRE_LEN);
-+                              write_varint30(f, rxa->datum_len);
-                               write_buf(f, rxa->name + RPRE_LEN, rxa->name_len - RPRE_LEN);
-                       } else {
--                              write_varint(f, rxa->name_len + UPRE_LEN);
--                              write_varint(f, rxa->datum_len);
-+                              write_varint30(f, rxa->name_len + UPRE_LEN);
-+                              write_varint30(f, rxa->datum_len);
+ #ifndef HAVE_LINUX_XATTRS
+                       if (name_len > rxa->name_len) {
                                write_buf(f, USER_PREFIX, UPRE_LEN);
-                               write_buf(f, rxa->name, rxa->name_len);
+@@ -376,7 +387,7 @@ int send_xattr(stat_x *sxp, int f)
                        }
  #endif
+                       write_buf(f, name, name_len);
 -                      if (rxa->datum_len > MAX_FULL_DATUM)
 +                      if (rxa->datum_len > MAX_FULL_DATUM && protocol_version >= 30)
                                write_buf(f, rxa->datum + 1, MAX_DIGEST_LEN);
                        else
                                write_buf(f, rxa->datum, rxa->datum_len);
-@@ -421,7 +432,7 @@ int xattr_diff(struct file_struct *file, stat_x *sxp, int find_all)
+@@ -426,7 +437,7 @@ int xattr_diff(struct file_struct *file, stat_x *sxp, int find_all)
                cmp = rec_cnt ? strcmp(snd_rxa->name, rec_rxa->name) : -1;
                if (cmp > 0)
                        same = 0;
@@ -127,7 +119,7 @@ diff --git a/xattrs.c b/xattrs.c
                        same = cmp == 0 && snd_rxa->datum_len == rec_rxa->datum_len
                            && memcmp(snd_rxa->datum + 1, rec_rxa->datum + 1,
                                      MAX_DIGEST_LEN) == 0;
-@@ -464,6 +475,9 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
+@@ -469,6 +480,9 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
        int cnt, prior_req = 0;
        rsync_xa *rxa;
  
@@ -137,7 +129,7 @@ diff --git a/xattrs.c b/xattrs.c
        lst += F_XATTR(file);
        for (rxa = lst->items, cnt = lst->count; cnt--; rxa++) {
                if (rxa->datum_len <= MAX_FULL_DATUM)
-@@ -518,6 +532,9 @@ int recv_xattr_request(struct file_struct *file, int f_in)
+@@ -523,6 +537,9 @@ int recv_xattr_request(struct file_struct *file, int f_in)
        rsync_xa *rxa;
        int rel_pos, cnt, num, got_xattr_data = 0;
  
@@ -147,10 +139,10 @@ diff --git a/xattrs.c b/xattrs.c
        if (F_XATTR(file) < 0) {
                rprintf(FERROR, "recv_xattr_request: internal data error!\n");
                exit_cleanup(RERR_STREAMIO);
-@@ -574,7 +591,22 @@ void receive_xattr(struct file_struct *file, int f)
- {
-       static item_list temp_xattr = EMPTY_ITEM_LIST;
-       int count, num;
+@@ -584,7 +601,22 @@ void receive_xattr(struct file_struct *file, int f)
+ #else
+       int need_sort = 1;
+ #endif
 -      int ndx = read_varint(f);
 +      int ndx;
 +
@@ -171,7 +163,7 @@ diff --git a/xattrs.c b/xattrs.c
  
        if (ndx < 0 || (size_t)ndx > rsync_xal_l.count) {
                rprintf(FERROR, "receive_xattr: xa index %d out of"
-@@ -587,7 +619,7 @@ void receive_xattr(struct file_struct *file, int f)
+@@ -597,7 +629,7 @@ void receive_xattr(struct file_struct *file, int f)
                return;
        }
        
@@ -180,7 +172,7 @@ diff --git a/xattrs.c b/xattrs.c
                (void)EXPAND_ITEM_LIST(&temp_xattr, rsync_xa, count);
                temp_xattr.count = 0;
        }
-@@ -595,9 +627,10 @@ void receive_xattr(struct file_struct *file, int f)
+@@ -605,9 +637,10 @@ void receive_xattr(struct file_struct *file, int f)
        for (num = 1; num <= count; num++) {
                char *ptr, *name;
                rsync_xa *rxa;