Updated patches to work with the current trunk.
authorWayne Davison <wayne@opencoder.net>
Fri, 13 Mar 2009 17:32:54 +0000 (10:32 -0700)
committerWayne Davison <wayne@opencoder.net>
Fri, 13 Mar 2009 21:03:57 +0000 (14:03 -0700)
44 files changed:
acls.diff
adaptec_acl_mods.diff
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
daemon-forward-lookup.diff
date-only.diff
db.diff
detect-renamed-lax.diff
detect-renamed.diff
downdate.diff
dparam.diff [deleted file]
drop-cache.diff
fileflags.diff
fsync.diff
ignore-case.diff
link-by-hash.diff
log-checksum.diff [deleted file]
munge-links.diff [deleted file]
nameconverter.diff
netgroup-auth.diff
omit-dir-changes.diff
openssl-support.diff
osx-xattr-nodev.diff
preallocate.diff
remote-option.diff [deleted file]
slow-down.diff
slp.diff
soften-links.diff
source-backup.diff
source-filter_dest-filter.diff
sparse-block.diff
stdout.diff
time-limit.diff
transliterate.diff
tru64.diff
usermap.diff [deleted file]
xattrs.diff

index 3cc4cb4..6c5ffa7 100644 (file)
--- a/acls.diff
+++ b/acls.diff
@@ -10,6 +10,7 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/acls.c b/acls.c
+index 6e0f601..3a613c5 100644
 --- a/acls.c
 +++ b/acls.c
 @@ -31,6 +31,7 @@ extern int list_only;
@@ -322,9 +323,10 @@ diff --git a/acls.c b/acls.c
  
        if (S_ISDIR(file->mode))
 diff --git a/compat.c b/compat.c
+index 6e00072..1b66069 100644
 --- a/compat.c
 +++ b/compat.c
-@@ -190,13 +190,6 @@ void setup_protocol(int f_out,int f_in)
+@@ -189,13 +189,6 @@ void setup_protocol(int f_out,int f_in)
        if (protocol_version < 30) {
                if (append_mode == 1)
                        append_mode = 2;
index c7e33c3..8303079 100644 (file)
@@ -25,6 +25,7 @@ Fix a bug that could lose some bits when stripping some (supposedly)
 superfluous ACL info.
 
 diff --git a/lib/sysacls.c b/lib/sysacls.c
+index 7334fd4..1bacc75 100644
 --- a/lib/sysacls.c
 +++ b/lib/sysacls.c
 @@ -31,6 +31,18 @@
@@ -70,6 +71,7 @@ diff --git a/lib/sysacls.c b/lib/sysacls.c
                acl_add_perm(permset, ACL_READ);
        if (bits & 2)
 diff --git a/lib/sysacls.h b/lib/sysacls.h
+index fd75bb6..5bd64de 100644
 --- a/lib/sysacls.h
 +++ b/lib/sysacls.h
 @@ -59,8 +59,8 @@
index 8eea52f..effc37d 100644 (file)
@@ -5,9 +5,10 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/compat.c b/compat.c
+index 6e00072..795e6bd 100644
 --- a/compat.c
 +++ b/compat.c
-@@ -44,6 +44,7 @@ extern int protocol_version;
+@@ -43,6 +43,7 @@ extern int protocol_version;
  extern int protect_args;
  extern int preserve_uid;
  extern int preserve_gid;
@@ -15,7 +16,7 @@ diff --git a/compat.c b/compat.c
  extern int preserve_acls;
  extern int preserve_xattrs;
  extern int need_messages_from_generator;
-@@ -61,7 +62,7 @@ extern char *iconv_opt;
+@@ -60,7 +61,7 @@ extern char *iconv_opt;
  #endif
  
  /* These index values are for the file-list's extra-attribute array. */
@@ -24,7 +25,7 @@ diff --git a/compat.c b/compat.c
  
  int receiver_symlink_times = 0; /* receiver can set the time on a symlink */
  int sender_symlink_iconv = 0; /* sender should convert symlink content */
-@@ -137,6 +138,8 @@ void setup_protocol(int f_out,int f_in)
+@@ -136,6 +137,8 @@ void setup_protocol(int f_out,int f_in)
                uid_ndx = ++file_extra_cnt;
        if (preserve_gid)
                gid_ndx = ++file_extra_cnt;
@@ -34,9 +35,10 @@ diff --git a/compat.c b/compat.c
                acls_ndx = ++file_extra_cnt;
        if (preserve_xattrs)
 diff --git a/flist.c b/flist.c
+index 09b4fc5..169e918 100644
 --- a/flist.c
 +++ b/flist.c
-@@ -55,6 +55,7 @@ extern int preserve_specials;
+@@ -55,6 +55,7 @@ extern int missing_args;
  extern int uid_ndx;
  extern int gid_ndx;
  extern int eol_nulls;
@@ -44,7 +46,7 @@ diff --git a/flist.c b/flist.c
  extern int relative_paths;
  extern int implied_dirs;
  extern int file_extra_cnt;
-@@ -393,7 +394,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
+@@ -396,7 +397,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
  #endif
                            int ndx, int first_ndx)
  {
@@ -53,7 +55,7 @@ diff --git a/flist.c b/flist.c
        static mode_t mode;
  #ifdef SUPPORT_HARD_LINKS
        static int64 dev;
-@@ -467,6 +468,13 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
+@@ -484,6 +485,13 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
                xflags |= XMIT_SAME_TIME;
        else
                modtime = file->modtime;
@@ -67,7 +69,7 @@ diff --git a/flist.c b/flist.c
  
  #ifdef SUPPORT_HARD_LINKS
        if (tmp_dev != 0) {
-@@ -538,6 +546,8 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
+@@ -568,6 +576,8 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
        }
        if (!(xflags & XMIT_SAME_MODE))
                write_int(f, to_wire_mode(mode));
@@ -76,7 +78,7 @@ diff --git a/flist.c b/flist.c
        if (preserve_uid && !(xflags & XMIT_SAME_UID)) {
                if (protocol_version < 30)
                        write_int(f, uid);
-@@ -622,7 +632,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
+@@ -654,7 +664,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
  static struct file_struct *recv_file_entry(struct file_list *flist,
                                           int xflags, int f)
  {
@@ -85,7 +87,7 @@ diff --git a/flist.c b/flist.c
        static mode_t mode;
  #ifdef SUPPORT_HARD_LINKS
        static int64 dev;
-@@ -756,6 +766,16 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+@@ -793,6 +803,16 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
        }
        if (!(xflags & XMIT_SAME_MODE))
                mode = from_wire_mode(read_int(f));
@@ -100,9 +102,9 @@ diff --git a/flist.c b/flist.c
 +#endif
 +      }
  
-       if (chmod_modes && !S_ISLNK(mode))
+       if (chmod_modes && !S_ISLNK(mode) && mode)
                mode = tweak_mode(mode, chmod_modes);
-@@ -905,6 +925,8 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+@@ -942,6 +962,8 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                F_GROUP(file) = gid;
                file->flags |= gid_flags;
        }
@@ -111,7 +113,7 @@ diff --git a/flist.c b/flist.c
        if (unsort_ndx)
                F_NDX(file) = flist->used + flist->ndx_start;
  
-@@ -1277,6 +1299,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1327,6 +1349,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;
@@ -121,17 +123,10 @@ diff --git a/flist.c b/flist.c
        if (basename != thisname)
                file->dirname = lastdir;
 diff --git a/generator.c b/generator.c
+index 12007a1..7d15744 100644
 --- a/generator.c
 +++ b/generator.c
-@@ -21,6 +21,7 @@
-  */
- #include "rsync.h"
-+#include "ifuncs.h"
- extern int verbose;
- extern int dry_run;
-@@ -648,6 +649,9 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+@@ -455,6 +455,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))
                        iflags |= ITEM_REPORT_TIME;
@@ -141,7 +136,7 @@ diff --git a/generator.c b/generator.c
  #if !defined HAVE_LCHMOD && !defined HAVE_SETATTRLIST
                if (S_ISLNK(file->mode)) {
                        ;
-@@ -1018,6 +1022,8 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
+@@ -825,6 +828,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;
@@ -149,35 +144,45 @@ diff --git a/generator.c b/generator.c
 +                              set_file_attrs(fname, file, sxp, NULL, 0);
                        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)) {
-@@ -1203,6 +1209,7 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx,
+                       if (!maybe_ATTRS_REPORT && (INFO_GTE(NAME, 2) || stdout_format_has_i > 1)) {
+@@ -1010,6 +1015,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];
 +      time_t atime = atimes_ndx ? f_atime(f) : 0;
-       double len;
+       int64 len;
+       int colwidth = human_readable ? 14 : 11;
  
-       if (!F_IS_ACTIVE(f)) {
-@@ -1217,14 +1224,16 @@ static void list_file_entry(struct file_struct *f)
+@@ -1025,10 +1031,11 @@ static void list_file_entry(struct file_struct *f)
  
  #ifdef SUPPORT_LINKS
        if (preserve_links && S_ISLNK(f->mode)) {
--              rprintf(FINFO, "%s %11.0f %s %s -> %s\n",
-+              rprintf(FINFO, "%s %11.0f %s %s %s -> %s\n",
-                       permbuf, len, timestring(f->modtime),
+-              rprintf(FINFO, "%s %*s %s %s -> %s\n",
++              rprintf(FINFO, "%s %*s %s %s %s -> %s\n",
+                       permbuf, colwidth, comma_num(len),
+-                      timestring(f->modtime), f_name(f, NULL),
+-                      F_SYMLINK(f));
++                      timestring(f->modtime),
 +                      atimes_ndx ? timestring(atime) : "",
-                       f_name(f, NULL), F_SYMLINK(f));
++                      f_name(f, NULL), F_SYMLINK(f));
        } else
  #endif
-       {
--              rprintf(FINFO, "%s %11.0f %s %s\n",
-+              rprintf(FINFO, "%s %11.0f %s %s %s\n",
-                       permbuf, len, timestring(f->modtime),
-+                      atimes_ndx ? timestring(atime) : "",
+       if (missing_args == 2 && f->mode == 0) {
+@@ -1036,9 +1043,11 @@ static void list_file_entry(struct file_struct *f)
+                       colwidth + 31, "*missing",
                        f_name(f, NULL));
+       } else {
+-              rprintf(FINFO, "%s %*s %s %s\n",
++              rprintf(FINFO, "%s %*s %s %s %s\n",
+                       permbuf, colwidth, comma_num(len),
+-                      timestring(f->modtime), f_name(f, NULL));
++                      timestring(f->modtime),
++                      atimes_ndx ? timestring(atime) : "",
++                      f_name(f, NULL));
        }
  }
-@@ -2059,7 +2068,7 @@ static void touch_up_dirs(struct file_list *flist, int ndx)
+@@ -1875,7 +1884,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)
@@ -187,10 +192,11 @@ diff --git a/generator.c b/generator.c
                if (counter >= loopchk_limit) {
                        if (allowed_lull)
 diff --git a/ifuncs.h b/ifuncs.h
+index 8c128d5..7834d3a 100644
 --- a/ifuncs.h
 +++ b/ifuncs.h
-@@ -67,6 +67,28 @@ d_name(struct dirent *di)
- #endif
+@@ -35,6 +35,28 @@ realloc_xbuf(xbuf *xb, size_t sz)
+       xb->size = sz;
  }
  
 +static inline time_t
@@ -216,12 +222,13 @@ diff --git a/ifuncs.h b/ifuncs.h
 +}
 +
  static inline int
isDigit(const char *ptr)
to_wire_mode(mode_t mode)
  {
 diff --git a/log.c b/log.c
+index a687375..0f714ad 100644
 --- a/log.c
 +++ b/log.c
-@@ -660,7 +660,8 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
+@@ -715,7 +715,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';
@@ -232,6 +239,7 @@ diff --git a/log.c b/log.c
                        c[10] = !(iflags & ITEM_REPORT_XATTR) ? '.' : 'x';
                        c[11] = '\0';
 diff --git a/options.c b/options.c
+index e7c6c61..01ccf5a 100644
 --- a/options.c
 +++ b/options.c
 @@ -59,6 +59,7 @@ int preserve_specials = 0;
@@ -242,7 +250,7 @@ diff --git a/options.c b/options.c
  int update_only = 0;
  int cvs_exclude = 0;
  int dry_run = 0;
-@@ -354,6 +355,7 @@ void usage(enum logcode F)
+@@ -698,6 +699,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 +258,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");
-@@ -491,6 +493,9 @@ static struct poptOption long_options[] = {
+@@ -845,6 +847,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 +268,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 },
-@@ -1774,6 +1779,8 @@ void server_options(char **args, int *argc_p)
+@@ -2289,6 +2294,8 @@ void server_options(char **args, int *argc_p)
                argstr[x++] = 'D';
        if (preserve_times)
                argstr[x++] = 't';
@@ -270,9 +278,10 @@ diff --git a/options.c b/options.c
                argstr[x++] = 'p';
        else if (preserve_executability && am_sender)
 diff --git a/rsync.c b/rsync.c
+index 2c026a2..95a6ebe 100644
 --- a/rsync.c
 +++ b/rsync.c
-@@ -383,6 +383,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
+@@ -384,6 +384,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 +289,7 @@ diff --git a/rsync.c b/rsync.c
        mode_t new_mode = file->mode;
        int inherit;
  
-@@ -426,20 +427,38 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
+@@ -422,20 +423,38 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
                set_xattr(fname, file, fnamecmp, sxp);
  #endif
  
@@ -323,7 +332,7 @@ diff --git a/rsync.c b/rsync.c
        }
  
        change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
-@@ -573,7 +592,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
+@@ -570,7 +589,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,
@@ -331,8 +340,8 @@ diff --git a/rsync.c b/rsync.c
 +                     ok_to_set_time ? 0 : ATTRS_SKIP_MTIME | ATTRS_SKIP_ATIME);
  
        /* move tmp file over real file */
-       if (verbose > 2)
-@@ -600,7 +619,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
+       if (DEBUG_GTE(RECV, 1))
+@@ -597,7 +616,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
  
    do_set_file_attrs:
        set_file_attrs(fnametmp, file, NULL, fnamecmp,
@@ -342,17 +351,18 @@ diff --git a/rsync.c b/rsync.c
        if (temp_copy_name) {
                if (do_rename(fnametmp, fname) < 0) {
 diff --git a/rsync.h b/rsync.h
+index be7cf8a..2f85dee 100644
 --- a/rsync.h
 +++ b/rsync.h
-@@ -60,6 +60,7 @@
- #define XMIT_RDEV_MINOR_8_pre30 (1<<11)       /* protocols 28 - 29  */
+@@ -61,6 +61,7 @@
  #define XMIT_GROUP_NAME_FOLLOWS (1<<11) /* protocols 30 - now */
  #define XMIT_HLINK_FIRST (1<<12)      /* protocols 30 - now (HLINKED files only) */
+ #define XMIT_IO_ERROR_ENDLIST (1<<12) /* protocols 31 - now (w/XMIT_EXTENDED_FLAGS) */
 +#define XMIT_SAME_ATIME (1<<13)               /* protocols ?? - now */
  
  /* These flags are used in the live flist data. */
  
-@@ -154,6 +155,7 @@
+@@ -155,6 +156,7 @@
  
  #define ATTRS_REPORT          (1<<0)
  #define ATTRS_SKIP_MTIME      (1<<1)
@@ -360,7 +370,7 @@ diff --git a/rsync.h b/rsync.h
  
  #define FULL_FLUSH    1
  #define NORMAL_FLUSH  0
-@@ -632,12 +634,14 @@ extern int file_extra_cnt;
+@@ -652,12 +654,14 @@ extern int file_extra_cnt;
  extern int inc_recurse;
  extern int uid_ndx;
  extern int gid_ndx;
@@ -376,9 +386,10 @@ diff --git a/rsync.h b/rsync.h
  #define DIRNODE_EXTRA_CNT 3
  #define SUM_EXTRA_CNT ((MAX_DIGEST_LEN + EXTRA_LEN - 1) / EXTRA_LEN)
 diff --git a/rsync.yo b/rsync.yo
+index 941f7a5..ec98c6e 100644
 --- a/rsync.yo
 +++ b/rsync.yo
-@@ -353,6 +353,7 @@ to the detailed description below for a complete description.  verb(
+@@ -356,6 +356,7 @@ to the detailed description below for a complete description.  verb(
   -D                          same as --devices --specials
   -t, --times                 preserve modification times
   -O, --omit-dir-times        omit directories from --times
@@ -386,7 +397,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
-@@ -1004,6 +1005,12 @@ it is preserving modification times (see bf(--times)).  If NFS is sharing
+@@ -1071,6 +1072,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).
  
@@ -399,7 +410,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
-@@ -1723,7 +1730,10 @@ quote(itemization(
+@@ -1888,7 +1895,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).
@@ -413,6 +424,7 @@ diff --git a/rsync.yo b/rsync.yo
  ))
 diff --git a/testsuite/atimes.test b/testsuite/atimes.test
 new file mode 100644
+index 0000000..bd3f292
 --- /dev/null
 +++ b/testsuite/atimes.test
 @@ -0,0 +1,17 @@
@@ -434,6 +446,7 @@ new file mode 100644
 +# The script would have aborted on error, so getting here means we've won.
 +exit 0
 diff --git a/testsuite/rsync.fns b/testsuite/rsync.fns
+index b26aee3..0c1c7d8 100644
 --- a/testsuite/rsync.fns
 +++ b/testsuite/rsync.fns
 @@ -215,6 +215,10 @@ checkit() {
@@ -463,9 +476,10 @@ diff --git a/testsuite/rsync.fns b/testsuite/rsync.fns
      diff $diffopt "$tmpdir/ls-from" "$tmpdir/ls-to" || failed=YES
  
 diff --git a/tls.c b/tls.c
+index 8cc5748..c27c97f 100644
 --- a/tls.c
 +++ b/tls.c
-@@ -107,6 +107,8 @@ static int stat_xattr(const char *fname, STRUCT_STAT *fst)
+@@ -108,6 +108,8 @@ static int stat_xattr(const char *fname, STRUCT_STAT *fst)
  
  #endif
  
@@ -474,7 +488,7 @@ diff --git a/tls.c b/tls.c
  static void failed(char const *what, char const *where)
  {
        fprintf(stderr, PROGRAM ": %s %s: %s\n",
-@@ -114,12 +116,29 @@ static void failed(char const *what, char const *where)
+@@ -115,12 +117,29 @@ static void failed(char const *what, char const *where)
        exit(1);
  }
  
@@ -506,7 +520,7 @@ diff --git a/tls.c b/tls.c
        char linkbuf[4096];
  
        if (do_lstat(fname, &buf) < 0)
-@@ -158,19 +177,11 @@ static void list_file(const char *fname)
+@@ -159,19 +178,11 @@ static void list_file(const char *fname)
  
        permstring(permbuf, buf.st_mode);
  
@@ -531,10 +545,10 @@ diff --git a/tls.c b/tls.c
  
        /* TODO: Perhaps escape special characters in fname? */
  
-@@ -181,13 +192,14 @@ static void list_file(const char *fname)
+@@ -182,13 +193,14 @@ static void list_file(const char *fname)
                    (long)minor(buf.st_rdev));
-       } else /* NB: use double for size since it might not fit in a long. */
-               printf("%12.0f", (double)buf.st_size);
+       } else
+               printf("%15s", do_big_num(buf.st_size, 1, NULL));
 -      printf(" %6ld.%-6ld %6ld %s %s%s\n",
 +      printf(" %6ld.%-6ld %6ld %s%s%s%s\n",
               (long)buf.st_uid, (long)buf.st_gid, (long)buf.st_nlink,
@@ -548,7 +562,7 @@ diff --git a/tls.c b/tls.c
    {"link-times",      'l', POPT_ARG_NONE,   &link_times, 0, 0, 0 },
    {"link-owner",      'L', POPT_ARG_NONE,   &link_owner, 0, 0, 0 },
  #ifdef SUPPORT_XATTRS
-@@ -203,6 +215,7 @@ static void tls_usage(int ret)
+@@ -204,6 +216,7 @@ static void tls_usage(int ret)
    fprintf(F,"usage: " PROGRAM " [OPTIONS] FILE ...\n");
    fprintf(F,"Trivial file listing program for portably checking rsync\n");
    fprintf(F,"\nOptions:\n");
@@ -557,6 +571,7 @@ diff --git a/tls.c b/tls.c
    fprintf(F," -L, --link-owner            display the owner+group on a symlink\n");
  #ifdef SUPPORT_XATTRS
 diff --git a/util.c b/util.c
+index 0cafed6..05f6d72 100644
 --- a/util.c
 +++ b/util.c
 @@ -123,7 +123,7 @@ NORETURN void overflow_exit(const char *str)
@@ -571,7 +586,7 @@ diff --git a/util.c b/util.c
 @@ -131,9 +131,13 @@ int set_modtime(const char *fname, time_t modtime, mode_t mode)
  #endif
  
-       if (verbose > 2) {
+       if (DEBUG_GTE(TIME, 1)) {
 -              rprintf(FINFO, "set modtime of %s to (%ld) %s",
 +              char mtimebuf[200];
 +
index 3919e07..96a2f41 100644 (file)
@@ -20,6 +20,7 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/backup.c b/backup.c
+index 0da6b33..ff77078 100644
 --- a/backup.c
 +++ b/backup.c
 @@ -29,10 +29,17 @@ extern int preserve_specials;
@@ -36,11 +37,11 @@ diff --git a/backup.c b/backup.c
  extern char *backup_dir;
 +extern char *backup_dir_dels;
 +
-+static int deleting;
++static BOOL deleting;
  
  /* make a complete pathname for backup file */
  char *get_backup_name(const char *fname)
-@@ -51,11 +58,28 @@ char *get_backup_name(const char *fname)
+@@ -51,6 +58,22 @@ char *get_backup_name(const char *fname)
        return NULL;
  }
  
@@ -60,17 +61,10 @@ diff --git a/backup.c b/backup.c
 +      return NULL;
 +}
 +
- /* simple backup creates a backup with a suffix in the same directory */
- static int make_simple_backup(const char *fname)
- {
-       int rename_errno;
--      const char *fnamebak = get_backup_name(fname);
-+      const char *fnamebak = deleting ? get_delete_name(fname)
-+                                      : get_backup_name(fname);
-       if (!fnamebak)
-               return 0;
-@@ -96,7 +120,7 @@ int make_bak_dir(const char *fullpath)
+ /****************************************************************************
+ Create a directory given an absolute path, perms based upon another directory
+ path
+@@ -59,7 +82,7 @@ int make_bak_dir(const char *fullpath)
  {
        char fbuf[MAXPATHLEN], *rel, *end, *p;
        struct file_struct *file;
@@ -79,55 +73,49 @@ diff --git a/backup.c b/backup.c
        stat_x sx;
  
        while (*fullpath == '.' && fullpath[1] == '/') {
-@@ -221,7 +245,8 @@ static int keep_backup(const char *fname)
-       if (!(file = make_file(fname, NULL, NULL, 0, NO_FILTERS)))
-               return 1; /* the file could have disappeared */
+@@ -179,7 +202,7 @@ int make_backup(const char *fname, BOOL prefer_rename)
+       stat_x sx;
+       struct file_struct *file;
+       int save_preserve_xattrs;
+-      char *buf = get_backup_name(fname);
++      char *buf = deleting ? get_delete_name(fname) : get_backup_name(fname);
+       int ret = 0;
  
--      if (!(buf = get_backup_name(fname))) {
-+      buf = deleting ? get_delete_name(fname) : get_backup_name(fname);
-+      if (!buf) {
-               unmake_file(file);
-               return 0;
+       if (!buf)
+@@ -341,3 +364,13 @@ int make_backup(const char *fname, BOOL prefer_rename)
        }
-@@ -356,7 +381,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);
+       return ret;
  }
 +
 +/* backup switch routine called only when backing-up removed file */
-+int safe_delete(char *fname)
++int safe_delete(const char *fname)
 +{
 +      int ret;
 +      deleting = 1;
-+      ret = make_backup(fname);
++      ret = make_backup(fname, True);
 +      deleting = 0;
 +      return ret;
 +}
-diff --git a/generator.c b/generator.c
---- a/generator.c
-+++ b/generator.c
-@@ -96,6 +96,9 @@ extern uid_t our_uid;
+diff --git a/delete.c b/delete.c
+index 33fdd0e..31228d0 100644
+--- a/delete.c
++++ b/delete.c
+@@ -28,6 +28,9 @@ extern int max_delete;
  extern char *backup_dir;
  extern char *backup_suffix;
  extern int backup_suffix_len;
 +extern char *backup_dir_dels;
 +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 daemon_filter_list;
+ extern uid_t our_uid;
+ extern struct stats stats;
  
-@@ -142,10 +145,15 @@ static void handle_skipped_hlink(struct file_struct *file, int itemizing,
                               enum logcode code, int f_out);
- #endif
+@@ -35,10 +38,14 @@ int ignore_perishable = 0;
int non_perishable_cnt = 0;
+ int skipped_deletes = 0;
  
-+
 +/* Function now compares both backup_suffix and backup_suffix_dels. */
- static int is_backup_file(char *fn)
+ static inline int is_backup_file(char *fn)
  {
        int k = strlen(fn) - backup_suffix_len;
 -      return k > 0 && strcmp(fn+k, backup_suffix) == 0;
@@ -137,23 +125,24 @@ diff --git a/generator.c b/generator.c
 +      return k > 0 && strcmp(fn+k, backup_suffix_dels) == 0;
  }
  
- /* Delete a file or directory.  If DEL_RECURSE is set in the flags, this will
-@@ -193,9 +201,9 @@ static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
-       if (S_ISDIR(mode)) {
+ /* The directory is about to be deleted: if DEL_RECURSE is given, delete all
+@@ -170,9 +177,9 @@ enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
                what = "rmdir";
                ok = do_rmdir(fbuf) == 0;
--      } else if (make_backups > 0 && (backup_dir || !is_backup_file(fbuf))) {
-+      } else if (make_backups > 0 && (backup_dir_dels || !is_backup_file(fbuf))) {
-               what = "make_backup";
--              ok = make_backup(fbuf);
-+              ok = safe_delete(fbuf);
        } else {
-               what = "unlink";
-               ok = robust_unlink(fbuf) == 0;
+-              if (make_backups > 0 && (backup_dir || !is_backup_file(fbuf))) {
++              if (make_backups > 0 && (backup_dir_dels || !is_backup_file(fbuf))) {
+                       what = "make_backup";
+-                      ok = make_backup(fbuf, True);
++                      ok = safe_delete(fbuf);
+                       if (ok == 2) {
+                               what = "unlink";
+                               ok = robust_unlink(fbuf) == 0;
 diff --git a/options.c b/options.c
+index e7c6c61..37e4086 100644
 --- a/options.c
 +++ b/options.c
-@@ -150,10 +150,14 @@ int no_detach
+@@ -151,10 +151,14 @@ int no_detach
  int write_batch = 0;
  int read_batch = 0;
  int backup_dir_len = 0;
@@ -168,7 +157,7 @@ diff --git a/options.c b/options.c
  char *tmpdir = NULL;
  char *partial_dir = NULL;
  char *basis_dir[MAX_BASIS_DIRS+1];
-@@ -165,7 +169,9 @@ char *stdout_format = NULL;
+@@ -166,7 +170,9 @@ char *stdout_format = NULL;
  char *password_file = NULL;
  char *rsync_path = RSYNC_PATH;
  char *backup_dir = NULL;
@@ -176,9 +165,9 @@ diff --git a/options.c b/options.c
  char backup_dir_buf[MAXPATHLEN];
 +char backup_dir_dels_buf[MAXPATHLEN];
  char *sockopts = NULL;
int rsync_port = 0;
int compare_dest = 0;
-@@ -326,6 +332,8 @@ void usage(enum logcode F)
char *usermap = NULL;
char *groupmap = NULL;
+@@ -669,6 +675,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);
@@ -187,7 +176,7 @@ diff --git a/options.c b/options.c
    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");
-@@ -610,7 +618,9 @@ static struct poptOption long_options[] = {
+@@ -968,7 +976,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 },
@@ -197,7 +186,7 @@ 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 },
-@@ -1454,6 +1464,8 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+@@ -1964,6 +1974,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, SP_DEFAULT);
@@ -206,7 +195,7 @@ diff --git a/options.c b/options.c
        }
        if (daemon_filter_list.head && !am_sender) {
                struct filter_list_struct *elp = &daemon_filter_list;
-@@ -1475,6 +1487,14 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+@@ -1985,6 +1997,14 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                        if (check_filter(elp, FLOG, dir, 1) < 0)
                                goto options_rejected;
                }
@@ -221,7 +210,7 @@ diff --git a/options.c b/options.c
        }
  
        if (!backup_suffix)
-@@ -1486,6 +1506,20 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+@@ -1996,6 +2016,20 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                        backup_suffix);
                return 0;
        }
@@ -242,7 +231,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;
-@@ -1509,6 +1543,34 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+@@ -2019,6 +2053,34 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                        "P *%s", backup_suffix);
                parse_rule(&filter_list, backup_dir_buf, 0, 0);
        }
@@ -258,7 +247,7 @@ diff --git a/options.c b/options.c
 +                      backup_dir_dels_buf[backup_dir_dels_len++] = '/';
 +                      backup_dir_dels_buf[backup_dir_dels_len] = '\0';
 +              }
-+              if (verbose > 1 && !am_sender)
++              if (INFO_GTE(BACKUP, 1) && !am_sender)
 +                      rprintf(FINFO, "backup_dir_dels is %s\n", backup_dir_dels_buf);
 +      } else if (backup_dir) {
 +              backup_dir_dels = backup_dir;
@@ -277,7 +266,7 @@ diff --git a/options.c b/options.c
  
        if (make_backups && !backup_dir) {
                omit_dir_times = 0; /* Implied, so avoid -O to sender. */
-@@ -1917,6 +1979,10 @@ void server_options(char **args, int *argc_p)
+@@ -2432,6 +2494,10 @@ void server_options(char **args, int *argc_p)
                args[ac++] = "--backup-dir";
                args[ac++] = backup_dir;
        }
@@ -288,7 +277,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) {
-@@ -1925,7 +1991,14 @@ void server_options(char **args, int *argc_p)
+@@ -2440,7 +2506,14 @@ void server_options(char **args, int *argc_p)
                        goto oom;
                args[ac++] = arg;
        }
index cceeaa8..01a867b 100644 (file)
@@ -26,6 +26,7 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/errcode.h b/errcode.h
+index 41c5543..e9c5a28 100644
 --- a/errcode.h
 +++ b/errcode.h
 @@ -47,6 +47,8 @@
@@ -38,9 +39,10 @@ diff --git a/errcode.h b/errcode.h
   * ssh and the shell seem to return these values:
   *
 diff --git a/log.c b/log.c
+index a687375..8e46712 100644
 --- a/log.c
 +++ b/log.c
-@@ -83,6 +83,7 @@ struct {
+@@ -88,6 +88,7 @@ struct {
        { RERR_TERMINATED , "sibling process terminated abnormally" },
        { RERR_SIGNAL1    , "received SIGUSR1" },
        { RERR_SIGNAL     , "received SIGINT, SIGTERM, or SIGHUP" },
@@ -49,9 +51,10 @@ diff --git a/log.c b/log.c
        { RERR_MALLOC     , "error allocating core memory buffers" },
        { RERR_PARTIAL    , "some files/attrs were not transferred (see previous errors)" },
 diff --git a/main.c b/main.c
+index 2ef2f47..45159d3 100644
 --- a/main.c
 +++ b/main.c
-@@ -163,8 +163,11 @@ static void wait_process_with_flush(pid_t pid, int *exit_code_ptr)
+@@ -167,8 +167,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;
@@ -63,8 +66,8 @@ diff --git a/main.c b/main.c
 +      }
  }
  
- /* This function gets called from all 3 processes.  We want the client side
-@@ -1315,6 +1318,14 @@ RETSIGTYPE remember_children(UNUSED(int val))
+ void write_del_stats(int f)
+@@ -1389,6 +1392,14 @@ RETSIGTYPE remember_children(UNUSED(int val))
                                break;
                        }
                }
@@ -79,7 +82,7 @@ diff --git a/main.c b/main.c
        }
  #endif
  #ifndef HAVE_SIGACTION
-@@ -1373,6 +1384,12 @@ static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
+@@ -1447,6 +1458,12 @@ static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
  }
  #endif
  
@@ -92,7 +95,7 @@ diff --git a/main.c b/main.c
  
  int main(int argc,char *argv[])
  {
-@@ -1395,6 +1412,11 @@ int main(int argc,char *argv[])
+@@ -1469,6 +1486,11 @@ int main(int argc,char *argv[])
        SIGACTMASK(SIGFPE, rsync_panic_handler);
        SIGACTMASK(SIGABRT, rsync_panic_handler);
        SIGACTMASK(SIGBUS, rsync_panic_handler);
@@ -105,6 +108,7 @@ diff --git a/main.c b/main.c
  
        starttime = time(NULL);
 diff --git a/socket.c b/socket.c
+index 5df3a50..3423e18 100644
 --- a/socket.c
 +++ b/socket.c
 @@ -518,7 +518,17 @@ int is_a_socket(int fd)
index 03fed2c..aab3c1d 100644 (file)
@@ -17,9 +17,10 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/checksum.c b/checksum.c
+index 811b5b6..f418dc2 100644
 --- a/checksum.c
 +++ b/checksum.c
-@@ -100,7 +100,7 @@ void get_checksum2(char *buf, int32 len, char *sum)
+@@ -98,7 +98,7 @@ void get_checksum2(char *buf, int32 len, char *sum)
        }
  }
  
@@ -29,6 +30,7 @@ diff --git a/checksum.c b/checksum.c
        struct map_struct *buf;
        OFF_T i, len = size;
 diff --git a/clientserver.c b/clientserver.c
+index b6afe00..2681f33 100644
 --- a/clientserver.c
 +++ b/clientserver.c
 @@ -42,6 +42,8 @@ extern int numeric_ids;
@@ -40,7 +42,7 @@ diff --git a/clientserver.c b/clientserver.c
  extern int io_timeout;
  extern int no_detach;
  extern int write_batch;
-@@ -779,6 +781,9 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
+@@ -868,6 +870,9 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
        } else if (am_root < 0) /* Treat --fake-super from client as --super. */
                am_root = 2;
  
@@ -51,17 +53,26 @@ diff --git a/clientserver.c b/clientserver.c
                filesfrom_fd = f_in;
  
 diff --git a/flist.c b/flist.c
+index 09b4fc5..8a42d80 100644
 --- a/flist.c
 +++ b/flist.c
-@@ -34,6 +34,7 @@ extern int am_generator;
+@@ -22,6 +22,7 @@
+ #include "rsync.h"
+ #include "ifuncs.h"
++#include "itypes.h"
+ #include "rounding.h"
+ #include "inums.h"
+ #include "io.h"
+@@ -33,6 +34,7 @@ extern int am_sender;
+ extern int am_generator;
  extern int inc_recurse;
- extern int do_progress;
  extern int always_checksum;
 +extern int basis_dir_cnt;
  extern int module_id;
  extern int ignore_errors;
  extern int numeric_ids;
-@@ -61,6 +62,7 @@ extern int file_extra_cnt;
+@@ -61,6 +63,7 @@ extern int file_extra_cnt;
  extern int ignore_perishable;
  extern int non_perishable_cnt;
  extern int prune_empty_dirs;
@@ -69,15 +80,15 @@ diff --git a/flist.c b/flist.c
  extern int copy_links;
  extern int copy_unsafe_links;
  extern int protocol_version;
-@@ -69,6 +71,7 @@ extern int munge_symlinks;
- extern int need_unsorted_flist;
- extern int sender_symlink_iconv;
+@@ -71,6 +74,7 @@ extern int sender_symlink_iconv;
+ extern int output_needs_newline;
+ extern int sender_keeps_checksum;
  extern int unsort_ndx;
 +extern char *basis_dir[];
  extern struct stats stats;
  extern char *filesfrom_host;
-@@ -84,6 +87,12 @@ extern int filesfrom_convert;
+ extern char *usermap, *groupmap;
+@@ -87,6 +91,12 @@ extern int filesfrom_convert;
  extern iconv_t ic_send, ic_recv;
  #endif
  
@@ -90,9 +101,9 @@ diff --git a/flist.c b/flist.c
  #define PTR_SIZE (sizeof (struct file_struct *))
  
  int io_error;
-@@ -125,7 +134,11 @@ static char empty_sum[MAX_DIGEST_LEN];
+@@ -127,7 +137,11 @@ static char tmp_sum[MAX_DIGEST_LEN];
+ static char empty_sum[MAX_DIGEST_LEN];
  static int flist_count_offset; /* for --delete --progress */
- static int dir_count = 0;
  
 -static void flist_sort_and_clean(struct file_list *flist, int strip_root);
 +static struct csum_cache {
@@ -103,7 +114,7 @@ diff --git a/flist.c b/flist.c
  static void output_flist(struct file_list *flist);
  
  void init_flist(void)
-@@ -339,6 +352,238 @@ static void flist_done_allocating(struct file_list *flist)
+@@ -342,6 +356,238 @@ static void flist_done_allocating(struct file_list *flist)
                flist->pool_boundary = ptr;
  }
  
@@ -342,7 +353,7 @@ diff --git a/flist.c b/flist.c
  /* Call this with EITHER (1) "file, NULL, 0" to chdir() to the file's
   * F_PATHNAME(), or (2) "NULL, dir, dirlen" to chdir() to the supplied dir,
   * with dir == NULL taken to be the starting directory, and dirlen < 0
-@@ -1068,7 +1313,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1105,7 +1351,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
                              STRUCT_STAT *stp, int flags, int filter_level)
  {
        static char *lastdir;
@@ -351,7 +362,7 @@ diff --git a/flist.c b/flist.c
        struct file_struct *file;
        char thisname[MAXPATHLEN];
        char linkname[MAXPATHLEN];
-@@ -1207,9 +1452,16 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1251,9 +1497,16 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
                        memcpy(lastdir, thisname, len);
                        lastdir[len] = '\0';
                        lastdir_len = len;
@@ -369,48 +380,47 @@ diff --git a/flist.c b/flist.c
        basename_len = strlen(basename) + 1; /* count the '\0' */
  
  #ifdef SUPPORT_LINKS
-@@ -1286,14 +1538,18 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
-               memcpy(bp + basename_len, linkname, linkname_len);
+@@ -1267,11 +1520,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+               extra_len += EXTRA_LEN;
  #endif
  
--      if (always_checksum && am_sender && S_ISREG(st.st_mode))
+-      if (always_checksum && am_sender && S_ISREG(st.st_mode)) {
 -              file_checksum(thisname, tmp_sum, st.st_size);
--
-       if (am_sender)
-               F_PATHNAME(file) = pathname;
-       else if (!pool)
-               F_DEPTH(file) = extra_len / EXTRA_LEN;
+-              if (sender_keeps_checksum)
+-                      extra_len += SUM_EXTRA_CNT * EXTRA_LEN;
+-      }
++      if (sender_keeps_checksum && S_ISREG(st.st_mode))
++              extra_len += SUM_EXTRA_CNT * EXTRA_LEN;
+ #if EXTRA_ROUNDING > 0
+       if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN))
+@@ -1347,8 +1597,14 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+               return NULL;
+       }
  
+-      if (sender_keeps_checksum && S_ISREG(st.st_mode))
+-              memcpy(F_SUM(file), tmp_sum, checksum_len);
 +      if (always_checksum && am_sender && S_ISREG(st.st_mode)) {
 +              if (flist && checksum_files)
 +                      get_cached_checksum(0, thisname, file, &st, tmp_sum);
 +              else
 +                      file_checksum(thisname, st.st_size, tmp_sum);
++              if (sender_keeps_checksum)
++                      memcpy(F_SUM(file), tmp_sum, checksum_len);
 +      }
-+
-       if (basename_len == 0+1) {
-               if (!pool)
-                       unmake_file(file);
-@@ -2236,7 +2492,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);
-               }
--      }
-+      } else
-+              flist_eof = 1;
  
-       return flist;
- }
-@@ -2342,7 +2599,7 @@ struct file_list *recv_file_list(int f)
-       else if (f >= 0)
-               recv_id_list(f, flist);
+       if (unsort_ndx)
+               F_NDX(file) = stats.num_dirs;
+@@ -2462,7 +2718,7 @@ struct file_list *recv_file_list(int f)
+               flist_eof = 1;
+       }
  
 -      flist_sort_and_clean(flist, relative_paths);
 +      flist_sort_and_clean(flist, relative_paths ? CLEAN_STRIP_ROOT : 0);
  
        if (protocol_version < 30) {
                /* Recv the io_error flag */
-@@ -2562,7 +2819,7 @@ void flist_free(struct file_list *flist)
+@@ -2683,7 +2939,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. */
@@ -419,7 +429,7 @@ diff --git a/flist.c b/flist.c
  {
        char fbuf[MAXPATHLEN];
        int i, prev_i;
-@@ -2613,7 +2870,7 @@ static void flist_sort_and_clean(struct file_list *flist, int strip_root)
+@@ -2734,7 +2990,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. */
@@ -428,18 +438,18 @@ diff --git a/flist.c b/flist.c
                                struct file_struct *fp = flist->sorted[j];
                                if (!S_ISDIR(fp->mode))
                                        keep = i, drop = j;
-@@ -2629,8 +2886,8 @@ static void flist_sort_and_clean(struct file_list *flist, int strip_root)
+@@ -2750,8 +3006,8 @@ static void flist_sort_and_clean(struct file_list *flist, int strip_root)
                        } else
                                keep = j, drop = i;
  
 -                      if (!am_sender) {
--                              if (verbose > 1) {
+-                              if (DEBUG_GTE(DUP, 1)) {
 +                      if (!am_sender || flags & CLEAN_KEEP_LAST) {
-+                              if (verbose > 1 && !(flags & CLEAN_KEEP_LAST)) {
++                              if (DEBUG_GTE(DUP, 1) && !(flags & CLEAN_KEEP_LAST)) {
                                        rprintf(FINFO,
                                            "removing duplicate name %s from file list (%d)\n",
                                            f_name(file, fbuf), drop + flist->ndx_start);
-@@ -2652,7 +2909,7 @@ static void flist_sort_and_clean(struct file_list *flist, int strip_root)
+@@ -2773,7 +3029,7 @@ static void flist_sort_and_clean(struct file_list *flist, int strip_root)
        }
        flist->high = prev_i;
  
@@ -449,17 +459,18 @@ diff --git a/flist.c b/flist.c
                 * paths, but this must be done _after_ the sorting phase. */
                for (i = flist->low; i <= flist->high; i++) {
 diff --git a/generator.c b/generator.c
+index 12007a1..48a5062 100644
 --- a/generator.c
 +++ b/generator.c
-@@ -52,6 +52,7 @@ extern int delete_during;
- extern int delete_after;
+@@ -53,6 +53,7 @@ extern int delete_after;
+ extern int missing_args;
  extern int msgdone_cnt;
  extern int ignore_errors;
 +extern int checksum_files;
  extern int remove_source_files;
  extern int delay_updates;
  extern int update_only;
-@@ -715,7 +716,7 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+@@ -522,7 +523,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. */
@@ -468,7 +479,7 @@ diff --git a/generator.c b/generator.c
  {
        if (st->st_size != F_LENGTH(file))
                return 0;
-@@ -724,7 +725,10 @@ int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st)
+@@ -531,7 +532,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];
@@ -480,7 +491,7 @@ diff --git a/generator.c b/generator.c
                return memcmp(sum, F_SUM(file), checksum_len) == 0;
        }
  
-@@ -988,7 +992,7 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
+@@ -795,7 +799,7 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
                        match_level = 1;
                        /* FALL THROUGH */
                case 1:
@@ -489,7 +500,7 @@ diff --git a/generator.c b/generator.c
                                continue;
                        best_match = j;
                        match_level = 2;
-@@ -1261,7 +1265,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1074,7 +1078,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;
@@ -498,7 +509,7 @@ diff --git a/generator.c b/generator.c
        struct file_struct *fuzzy_file = NULL;
        int fd = -1, f_copy = -1;
        stat_x sx, real_sx;
-@@ -1350,8 +1354,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1158,8 +1162,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                                flist_free(fuzzy_dirlist);
                                fuzzy_dirlist = NULL;
                        }
@@ -509,7 +520,7 @@ diff --git a/generator.c b/generator.c
  #ifdef SUPPORT_ACLS
                        if (!preserve_perms)
                                dflt_perms = default_perms_for_dir(dn);
-@@ -1359,10 +1363,15 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1167,10 +1171,15 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                }
                parent_dirname = dn;
  
@@ -529,7 +540,7 @@ diff --git a/generator.c b/generator.c
                }
  
                statret = link_stat(fname, &sx.st, keep_dirlinks && is_dir);
-@@ -1796,7 +1805,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1612,7 +1621,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                ;
        else if (fnamecmp_type == FNAMECMP_FUZZY)
                ;
@@ -539,9 +550,10 @@ diff --git a/generator.c b/generator.c
                        do_unlink(partialptr);
                        handle_partial_dir(partialptr, PDIR_DELETE);
 diff --git a/hlink.c b/hlink.c
+index c9eb33a..6109266 100644
 --- a/hlink.c
 +++ b/hlink.c
-@@ -390,7 +390,7 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
+@@ -413,7 +413,7 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
                                }
                                break;
                        }
@@ -550,10 +562,11 @@ diff --git a/hlink.c b/hlink.c
                                continue;
                        statret = 1;
                        if (unchanged_attrs(cmpbuf, file, &alt_sx))
-diff --git a/ifuncs.h b/ifuncs.h
---- a/ifuncs.h
-+++ b/ifuncs.h
-@@ -74,6 +74,12 @@ isDigit(const char *ptr)
+diff --git a/itypes.h b/itypes.h
+index df34140..1bdf506 100644
+--- a/itypes.h
++++ b/itypes.h
+@@ -23,6 +23,12 @@ isDigit(const char *ptr)
  }
  
  static inline int
@@ -567,27 +580,28 @@ diff --git a/ifuncs.h b/ifuncs.h
  {
        return isprint(*(unsigned char *)ptr);
 diff --git a/loadparm.c b/loadparm.c
+index 8e48e6d..899d2b5 100644
 --- a/loadparm.c
 +++ b/loadparm.c
-@@ -149,6 +149,7 @@ typedef struct
-       char *temp_dir;
-       char *uid;
+@@ -132,6 +132,7 @@ typedef struct {
+ /* NOTE: update this macro if the last char* variable changes! */
+ #define LOCAL_STRING_COUNT() (offsetof(local_vars, uid) / sizeof (char*) + 1)
  
 +      int checksum_files;
        int max_connections;
        int max_verbosity;
        int syslog_facility;
-@@ -200,6 +201,7 @@ static service sDefault =
+@@ -204,6 +205,7 @@ static const all_vars Defaults = {
   /* temp_dir; */              NULL,
-  /* uid; */                   NOBODY_USER,
+  /* uid; */                   NULL,
  
 + /* checksum_files; */                CSF_IGNORE_FILES,
   /* max_connections; */               0,
   /* max_verbosity; */         1,
   /* syslog_facility; */               LOG_DAEMON,
-@@ -294,6 +296,12 @@ static struct enum_list enum_facilities[] = {
- #endif
      { -1, NULL }};
+@@ -305,6 +307,13 @@ static struct enum_list enum_facilities[] = {
+       { -1, NULL }
+ };
  
 +static struct enum_list enum_csum_modes[] = {
 +      { CSF_IGNORE_FILES, "none" },
@@ -595,18 +609,19 @@ diff --git a/loadparm.c b/loadparm.c
 +      { CSF_STRICT_MODE, "strict" },
 +      { -1, NULL }
 +};
- /* note that we do not initialise the defaults union - it is not allowed in ANSI C */
++
  static struct parm_struct parm_table[] =
-@@ -306,6 +314,7 @@ static struct parm_struct parm_table[] =
-  {"auth users",        P_STRING, P_LOCAL, &sDefault.auth_users,        NULL,0},
-  {"charset",           P_STRING, P_LOCAL, &sDefault.charset,           NULL,0},
-+ {"checksum files",    P_ENUM,   P_LOCAL, &sDefault.checksum_files,    enum_csum_modes,0},
-  {"comment",           P_STRING, P_LOCAL, &sDefault.comment,           NULL,0},
-  {"dont compress",     P_STRING, P_LOCAL, &sDefault.dont_compress,     NULL,0},
-  {"exclude from",      P_STRING, P_LOCAL, &sDefault.exclude_from,      NULL,0},
-@@ -423,6 +432,7 @@ FN_LOCAL_STRING(lp_secrets_file, secrets_file)
+ {
+  {"address",           P_STRING, P_GLOBAL,&Vars.g.bind_address,        NULL,0},
+@@ -315,6 +324,7 @@ static struct parm_struct parm_table[] =
+  {"auth users",        P_STRING, P_LOCAL, &Vars.l.auth_users,          NULL,0},
+  {"charset",           P_STRING, P_LOCAL, &Vars.l.charset,             NULL,0},
++ {"checksum files",    P_ENUM,   P_LOCAL, &Vars.l.checksum_files,      enum_csum_modes,0},
+  {"comment",           P_STRING, P_LOCAL, &Vars.l.comment,             NULL,0},
+  {"dont compress",     P_STRING, P_LOCAL, &Vars.l.dont_compress,       NULL,0},
+  {"exclude from",      P_STRING, P_LOCAL, &Vars.l.exclude_from,        NULL,0},
+@@ -419,6 +429,7 @@ FN_LOCAL_STRING(lp_secrets_file, secrets_file)
  FN_LOCAL_STRING(lp_temp_dir, temp_dir)
  FN_LOCAL_STRING(lp_uid, uid)
  
@@ -615,9 +630,10 @@ diff --git a/loadparm.c b/loadparm.c
  FN_LOCAL_INTEGER(lp_max_verbosity, max_verbosity)
  FN_LOCAL_INTEGER(lp_syslog_facility, syslog_facility)
 diff --git a/options.c b/options.c
+index e7c6c61..2e110f3 100644
 --- a/options.c
 +++ b/options.c
-@@ -113,6 +113,7 @@ size_t bwlimit_writemax = 0;
+@@ -112,6 +112,7 @@ size_t bwlimit_writemax = 0;
  int ignore_existing = 0;
  int ignore_non_existing = 0;
  int need_messages_from_generator = 0;
@@ -625,7 +641,7 @@ diff --git a/options.c b/options.c
  int max_delete = INT_MIN;
  OFF_T max_size = 0;
  OFF_T min_size = 0;
-@@ -318,6 +319,7 @@ void usage(enum logcode F)
+@@ -661,6 +662,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");
@@ -633,16 +649,16 @@ 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");
-@@ -447,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,
+@@ -798,7 +800,7 @@ enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
        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,
--      OPT_NO_D, OPT_APPEND, OPT_NO_ICONV,
-+      OPT_NO_D, OPT_APPEND, OPT_NO_ICONV, OPT_SUMFILES,
+       OPT_NO_D, OPT_APPEND, OPT_NO_ICONV, OPT_INFO, OPT_DEBUG,
+-      OPT_USERMAP, OPT_GROUPMAP, OPT_CHOWN,
++      OPT_USERMAP, OPT_GROUPMAP, OPT_CHOWN, OPT_SUMFILES,
        OPT_SERVER, OPT_REFUSED_BASE = 9000};
  
  static struct poptOption long_options[] = {
-@@ -575,6 +577,7 @@ static struct poptOption long_options[] = {
+@@ -933,6 +935,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 },
@@ -650,7 +666,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 },
-@@ -1229,6 +1232,23 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+@@ -1630,6 +1633,23 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                        }
                        break;
  
@@ -671,10 +687,10 @@ diff --git a/options.c b/options.c
 +                      }
 +                      break;
 +
-               case OPT_HELP:
-                       usage(FINFO);
-                       exit_cleanup(0);
-@@ -1333,6 +1353,9 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+               case OPT_INFO:
+                       arg = poptGetOptArg(pc);
+                       parse_output_words(info_words, info_levels, arg, USER_PRIORITY);
+@@ -1830,6 +1850,9 @@ int parse_arguments(int *argc_p, const char ***argv_p)
        }
  #endif
  
@@ -685,9 +701,10 @@ diff --git a/options.c b/options.c
                snprintf(err_buf, sizeof err_buf,
                        "--write-batch and --read-batch can not be used together\n");
 diff --git a/rsync.h b/rsync.h
+index be7cf8a..ba8f3db 100644
 --- a/rsync.h
 +++ b/rsync.h
-@@ -692,6 +692,10 @@ extern int xattrs_ndx;
+@@ -712,6 +712,10 @@ extern int xattrs_ndx;
  #define F_SUM(f) ((char*)OPT_EXTRA(f, LEN64_BUMP(f) + HLINK_BUMP(f) \
                                    + SUM_EXTRA_CNT - 1))
  
@@ -698,7 +715,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)
-@@ -879,6 +883,13 @@ typedef struct {
+@@ -902,6 +906,13 @@ typedef struct {
        char fname[1]; /* has variable size */
  } relnamecache;
  
@@ -713,9 +730,10 @@ diff --git a/rsync.h b/rsync.h
  #include "lib/mdigest.h"
  #include "lib/wildmatch.h"
 diff --git a/rsync.yo b/rsync.yo
+index 941f7a5..7aa62cf 100644
 --- a/rsync.yo
 +++ b/rsync.yo
-@@ -321,6 +321,7 @@ to the detailed description below for a complete description.  verb(
+@@ -323,6 +323,7 @@ to the detailed description below for a complete description.  verb(
   -q, --quiet                 suppress non-error messages
       --no-motd               suppress daemon-mode MOTD (see caveat)
   -c, --checksum              skip based on checksum, not mod-time & size
@@ -723,7 +741,7 @@ diff --git a/rsync.yo b/rsync.yo
   -a, --archive               archive mode; equals -rlptgoD (no -H,-A,-X)
       --no-OPTION             turn off an implied OPTION (e.g. --no-D)
   -r, --recursive             recurse into directories
-@@ -520,9 +521,9 @@ uses a "quick check" that (by default) checks if each file's size and time
+@@ -568,9 +569,9 @@ uses a "quick check" that (by default) checks if each file's size and time
  of last modification match between the sender and receiver.  This option
  changes this to compare a 128-bit MD4 checksum for each file that has a
  matching size.  Generating the checksums means that both sides will expend
@@ -736,7 +754,7 @@ diff --git a/rsync.yo b/rsync.yo
  
  The sending side generates its checksums while it is doing the file-system
  scan that builds the list of the available files.  The receiver generates
-@@ -530,12 +531,44 @@ its checksums when it is scanning for changed files, and will checksum any
+@@ -578,12 +579,44 @@ its checksums when it is scanning for changed files, and will checksum any
  file that has the same size as the corresponding sender's file:  files with
  either a changed size or a changed checksum are selected for transfer.
  
@@ -782,9 +800,10 @@ diff --git a/rsync.yo b/rsync.yo
  way of saying you want recursion and want to preserve almost
  everything (with -H being a notable omission).
 diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo
+index d4978cd..0fc98fd 100644
 --- a/rsyncd.conf.yo
 +++ b/rsyncd.conf.yo
-@@ -281,6 +281,17 @@ locking on this file to ensure that the max connections limit is not
+@@ -292,6 +292,17 @@ locking on this file to ensure that the max connections limit is not
  exceeded for the modules sharing the lock file.
  The default is tt(/var/run/rsyncd.lock).
  
@@ -804,12 +823,12 @@ diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo
  attempted uploads will fail. If "read only" is false then uploads will
 diff --git a/support/rsyncsums b/support/rsyncsums
 new file mode 100755
+index 0000000..ce03c80
 --- /dev/null
 +++ b/support/rsyncsums
-@@ -0,0 +1,202 @@
-+#!/usr/bin/perl
+@@ -0,0 +1,201 @@
++#!/usr/bin/perl -w
 +use strict;
-+use warnings;
 +
 +use Getopt::Long;
 +use Cwd qw(abs_path cwd);
index 195cdf6..621118b 100644 (file)
@@ -18,17 +18,18 @@ TODO:
  - Fix the code that removes .rsyncsums files when a dir becomes empty.
 
 diff --git a/flist.c b/flist.c
+index 8a42d80..d65c475 100644
 --- a/flist.c
 +++ b/flist.c
-@@ -26,6 +26,7 @@
+@@ -27,6 +27,7 @@
+ #include "inums.h"
  #include "io.h"
  
- extern int verbose;
 +extern int dry_run;
  extern int am_root;
  extern int am_server;
  extern int am_daemon;
-@@ -95,6 +96,9 @@ extern iconv_t ic_send, ic_recv;
+@@ -99,6 +100,9 @@ extern iconv_t ic_send, ic_recv;
  
  #define PTR_SIZE (sizeof (struct file_struct *))
  
@@ -38,9 +39,9 @@ diff --git a/flist.c b/flist.c
  int io_error;
  int checksum_len;
  dev_t filesystem_dev; /* used to implement -x */
-@@ -134,8 +138,13 @@ static char empty_sum[MAX_DIGEST_LEN];
+@@ -137,8 +141,13 @@ static char tmp_sum[MAX_DIGEST_LEN];
+ static char empty_sum[MAX_DIGEST_LEN];
  static int flist_count_offset; /* for --delete --progress */
- static int dir_count = 0;
  
 +#define REGULAR_SKIPPED(flist) ((flist)->to_redo)
 +
@@ -52,7 +53,7 @@ diff --git a/flist.c b/flist.c
  } *csum_cache = NULL;
  
  static void flist_sort_and_clean(struct file_list *flist, int flags);
-@@ -352,7 +361,79 @@ static void flist_done_allocating(struct file_list *flist)
+@@ -356,7 +365,79 @@ static void flist_done_allocating(struct file_list *flist)
                flist->pool_boundary = ptr;
  }
  
@@ -133,7 +134,7 @@ diff --git a/flist.c b/flist.c
  {
        int slot, slots = am_sender ? 1 : basis_dir_cnt + 1;
  
-@@ -366,6 +447,9 @@ void reset_checksum_cache()
+@@ -370,6 +451,9 @@ void reset_checksum_cache()
                struct file_list *flist = csum_cache[slot].flist;
  
                if (flist) {
@@ -143,7 +144,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));
-@@ -376,6 +460,10 @@ void reset_checksum_cache()
+@@ -380,6 +464,10 @@ void reset_checksum_cache()
                flist->low = 0;
                flist->high = -1;
                flist->next = NULL;
@@ -154,7 +155,7 @@ diff --git a/flist.c b/flist.c
        }
  }
  
-@@ -383,7 +471,7 @@ void reset_checksum_cache()
+@@ -387,7 +475,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 +164,7 @@ diff --git a/flist.c b/flist.c
  {
        struct file_struct *file;
        int alloc_len, extra_len;
-@@ -400,7 +488,7 @@ static int add_checksum(struct file_list *flist, const char *dirname,
+@@ -404,7 +492,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 +173,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);
-@@ -409,7 +497,14 @@ static int add_checksum(struct file_list *flist, const char *dirname,
+@@ -413,7 +501,14 @@ static int add_checksum(struct file_list *flist, const char *dirname,
        bp += FILE_STRUCT_LEN;
  
        memcpy(bp, basename, basename_len);
@@ -187,7 +188,7 @@ diff --git a/flist.c b/flist.c
        file->mode = S_IFREG;
        file->modtime = mtime;
        file->len32 = (uint32)file_length;
-@@ -438,10 +533,11 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
+@@ -442,10 +537,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;
@@ -200,7 +201,7 @@ diff --git a/flist.c b/flist.c
        int dlen = dirname ? strlcpy(fbuf, dirname, sizeof fbuf) : 0;
  
        if (dlen >= (int)(sizeof fbuf - 1 - RSYNCSUMS_LEN))
-@@ -462,7 +558,7 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
+@@ -466,7 +562,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 +210,7 @@ diff --git a/flist.c b/flist.c
                        if (*cp == '=')
                                while (*++cp == '=') {}
                        else
-@@ -473,7 +569,14 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
+@@ -477,7 +573,14 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
                }
  
                if (*cp == '=') {
@@ -225,7 +226,7 @@ diff --git a/flist.c b/flist.c
                } else {
                        for (i = 0; i < checksum_len*2; i++, cp++) {
                                int x;
-@@ -491,13 +594,14 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
+@@ -495,13 +598,14 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
                                else
                                        sum[i/2] = x << 4;
                        }
@@ -241,7 +242,7 @@ diff --git a/flist.c b/flist.c
                        if (*cp == '=')
                                while (*++cp == '=') {}
                        else
-@@ -547,24 +651,112 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
+@@ -551,24 +655,112 @@ static void read_checksums(int slot, struct file_list *flist, const char *dirnam
                        continue;
  
                strlcpy(fbuf+dlen, cp, sizeof fbuf - dlen);
@@ -356,7 +357,7 @@ diff --git a/flist.c b/flist.c
                read_checksums(slot, flist, file->dirname);
        }
  
-@@ -576,12 +768,31 @@ void get_cached_checksum(int slot, const char *fname, struct file_struct *file,
+@@ -580,12 +772,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 +390,7 @@ diff --git a/flist.c b/flist.c
  }
  
  /* Call this with EITHER (1) "file, NULL, 0" to chdir() to the file's
-@@ -1407,6 +1618,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1452,6 +1663,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 +399,7 @@ diff --git a/flist.c b/flist.c
                return NULL;
        }
  
-@@ -1453,13 +1666,13 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1498,13 +1711,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 +415,7 @@ diff --git a/flist.c b/flist.c
                }
        }
        basename_len = strlen(basename) + 1; /* count the '\0' */
-@@ -1545,7 +1758,7 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1599,7 +1812,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)
@@ -422,8 +423,8 @@ diff --git a/flist.c b/flist.c
 +                      get_cached_checksum(0, thisname, file, basename_len, &st, tmp_sum);
                else
                        file_checksum(thisname, st.st_size, tmp_sum);
-       }
-@@ -1898,6 +2111,9 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len,
+               if (sender_keeps_checksum)
+@@ -1971,6 +2184,9 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len,
  
        closedir(d);
  
@@ -433,7 +434,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". */
-@@ -2495,6 +2711,9 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
+@@ -2589,6 +2805,9 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
        } else
                flist_eof = 1;
  
@@ -444,17 +445,18 @@ diff --git a/flist.c b/flist.c
  }
  
 diff --git a/generator.c b/generator.c
+index 48a5062..8717ab7 100644
 --- a/generator.c
 +++ b/generator.c
-@@ -114,6 +114,7 @@ static int dir_tweaking;
+@@ -111,6 +111,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(). */
-@@ -726,7 +727,7 @@ int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st, int slot
+ enum nonregtype {
+@@ -533,7 +534,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 +465,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;
-@@ -1369,7 +1370,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1177,7 +1178,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                                fuzzy_dirlist = get_dirlist(fnamecmpbuf, -1, 1);
                        }
                        if (checksum_files) {
@@ -473,7 +475,7 @@ diff --git a/generator.c b/generator.c
                        }
                        need_new_dirscan = 0;
                }
-@@ -1519,6 +1521,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1335,6 +1337,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                        else
                                change_local_filter_dir(fname, strlen(fname), F_DEPTH(file));
                }
@@ -481,7 +483,7 @@ diff --git a/generator.c b/generator.c
                goto cleanup;
        }
  
-@@ -1811,6 +1814,8 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1627,6 +1630,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);
@@ -490,7 +492,7 @@ diff --git a/generator.c b/generator.c
                if (itemizing)
                        itemize(fnamecmp, file, ndx, statret, &sx, 0, 0, NULL);
  #ifdef SUPPORT_HARD_LINKS
-@@ -2252,6 +2257,7 @@ void generate_files(int f_out, const char *local_name)
+@@ -2068,6 +2073,7 @@ void generate_files(int f_out, const char *local_name)
                                } else
                                        change_local_filter_dir(fbuf, strlen(fbuf), F_DEPTH(fp));
                        }
@@ -498,21 +500,22 @@ 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];
-@@ -2338,6 +2344,9 @@ void generate_files(int f_out, const char *local_name)
+@@ -2162,6 +2168,9 @@ void generate_files(int f_out, const char *local_name)
                        wait_for_receiver();
        }
  
 +      if (checksum_files)
 +              reset_checksum_cache(started_whole_dir);
 +
-       do_progress = save_do_progress;
-       if (delete_during == 2)
-               do_delayed_deletions(fbuf);
+       info_levels[INFO_FLIST] = save_info_flist;
+       info_levels[INFO_PROGRESS] = save_info_progress;
 diff --git a/io.c b/io.c
+index 6a89c8f..50e73b1 100644
 --- a/io.c
 +++ b/io.c
-@@ -50,6 +50,7 @@ extern int read_batch;
- extern int csum_length;
+@@ -49,6 +49,7 @@ extern int list_only;
+ extern int read_batch;
  extern int protect_args;
  extern int checksum_seed;
 +extern int checksum_files;
@@ -530,9 +533,10 @@ diff --git a/io.c b/io.c
                break;
        case FES_REDO:
 diff --git a/loadparm.c b/loadparm.c
+index 899d2b5..3123c93 100644
 --- a/loadparm.c
 +++ b/loadparm.c
-@@ -300,6 +300,10 @@ static struct enum_list enum_csum_modes[] = {
+@@ -311,6 +311,10 @@ static struct enum_list enum_csum_modes[] = {
        { CSF_IGNORE_FILES, "none" },
        { CSF_LAX_MODE, "lax" },
        { CSF_STRICT_MODE, "strict" },
@@ -544,9 +548,10 @@ diff --git a/loadparm.c b/loadparm.c
  };
  
 diff --git a/options.c b/options.c
+index 2e110f3..26d5561 100644
 --- a/options.c
 +++ b/options.c
-@@ -1234,7 +1234,15 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+@@ -1635,7 +1635,15 @@ int parse_arguments(int *argc_p, const char ***argv_p)
  
                case OPT_SUMFILES:
                        arg = poptGetOptArg(pc);
@@ -564,17 +569,18 @@ diff --git a/options.c b/options.c
                                checksum_files |= CSF_LAX_MODE;
                        else if (strcmp(arg, "strict") == 0)
 diff --git a/receiver.c b/receiver.c
+index 4325e30..2cea8fe 100644
 --- a/receiver.c
 +++ b/receiver.c
-@@ -47,6 +47,7 @@ extern int append_mode;
- extern int sparse_files;
+@@ -47,6 +47,7 @@ extern int sparse_files;
  extern int keep_partial;
+ extern int checksum_len;
  extern int checksum_seed;
 +extern int checksum_files;
  extern int inplace;
  extern int delay_updates;
  extern mode_t orig_umask;
-@@ -343,7 +344,7 @@ static void handle_delayed_updates(char *local_name)
+@@ -344,7 +345,7 @@ static void handle_delayed_updates(char *local_name)
                                        "rename failed for %s (from %s)",
                                        full_fname(fname), partialptr);
                        } else {
@@ -583,7 +589,7 @@ diff --git a/receiver.c b/receiver.c
                                 || (preserve_hard_links && F_IS_HLINKED(file)))
                                        send_msg_int(MSG_SUCCESS, ndx);
                                handle_partial_dir(partialptr, PDIR_DELETE);
-@@ -758,7 +759,7 @@ int recv_files(int f_in, char *local_name)
+@@ -794,7 +795,7 @@ int recv_files(int f_in, char *local_name)
                case 2:
                        break;
                case 1:
@@ -593,9 +599,10 @@ diff --git a/receiver.c b/receiver.c
                                send_msg_int(MSG_SUCCESS, ndx);
                        break;
 diff --git a/rsync.h b/rsync.h
+index ba8f3db..89c47bd 100644
 --- a/rsync.h
 +++ b/rsync.h
-@@ -885,6 +885,8 @@ typedef struct {
+@@ -908,6 +908,8 @@ typedef struct {
  
  #define CSF_ENABLE (1<<1)
  #define CSF_LAX (1<<2)
@@ -605,9 +612,10 @@ diff --git a/rsync.h b/rsync.h
  #define CSF_IGNORE_FILES 0
  #define CSF_LAX_MODE (CSF_ENABLE|CSF_LAX)
 diff --git a/rsync.yo b/rsync.yo
+index 7aa62cf..a119ed7 100644
 --- a/rsync.yo
 +++ b/rsync.yo
-@@ -548,9 +548,13 @@ computed just as it would be if bf(--sumfiles) was not specified.
+@@ -596,9 +596,13 @@ computed just as it would be if bf(--sumfiles) was not specified.
  
  The MODE value is either "lax", for relaxed checking (which compares size
  and mtime), "strict" (which also compares ctime and inode), or "none" to
@@ -625,9 +633,10 @@ diff --git a/rsync.yo b/rsync.yo
  This option has no effect unless bf(--checksum, -c) was also specified.  It
  also only affects the current side of the transfer, so if you want the
 diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo
+index 0fc98fd..3024842 100644
 --- a/rsyncd.conf.yo
 +++ b/rsyncd.conf.yo
-@@ -284,13 +284,15 @@ The default is tt(/var/run/rsyncd.lock).
+@@ -295,13 +295,15 @@ The default is tt(/var/run/rsyncd.lock).
  dit(bf(checksum files)) This parameter tells rsync to make use of any cached
  checksum information it finds in per-directory .rsyncsums files when the
  current transfer is using the bf(--checksum) option.  The value can be set
index bd6d3de..9b5d729 100644 (file)
@@ -9,22 +9,24 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/flist.c b/flist.c
+index 09b4fc5..3295724 100644
 --- a/flist.c
 +++ b/flist.c
-@@ -1286,7 +1286,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
-               memcpy(bp + basename_len, linkname, linkname_len);
+@@ -1268,7 +1268,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
  #endif
  
--      if (always_checksum && am_sender && S_ISREG(st.st_mode))
-+      if (always_checksum && am_sender && S_ISREG(st.st_mode)
-+       && !get_sum_xattr(thisname, &st, tmp_sum))
-               file_checksum(thisname, tmp_sum, st.st_size);
-       if (am_sender)
+       if (always_checksum && am_sender && S_ISREG(st.st_mode)) {
+-              file_checksum(thisname, tmp_sum, st.st_size);
++              if (!get_sum_xattr(thisname, &st, tmp_sum))
++                      file_checksum(thisname, tmp_sum, st.st_size);
+               if (sender_keeps_checksum)
+                       extra_len += SUM_EXTRA_CNT * EXTRA_LEN;
+       }
 diff --git a/generator.c b/generator.c
+index 12007a1..2587bc9 100644
 --- a/generator.c
 +++ b/generator.c
-@@ -724,7 +724,8 @@ int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st)
+@@ -531,7 +531,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];
@@ -36,12 +38,12 @@ diff --git a/generator.c b/generator.c
  
 diff --git a/support/xsums b/support/xsums
 new file mode 100644
+index 0000000..31d2537
 --- /dev/null
 +++ b/support/xsums
-@@ -0,0 +1,119 @@
-+#!/usr/bin/perl
+@@ -0,0 +1,118 @@
++#!/usr/bin/perl -w
 +use strict;
-+use warnings;
 +
 +use Getopt::Long;
 +use Cwd qw(abs_path cwd);
@@ -159,9 +161,10 @@ new file mode 100644
 +EOT
 +}
 diff --git a/xattrs.c b/xattrs.c
+index 2d0e050..f364a2a 100644
 --- a/xattrs.c
 +++ b/xattrs.c
-@@ -33,6 +33,8 @@ extern int read_only;
+@@ -34,6 +34,8 @@ extern int read_only;
  extern int list_only;
  extern int preserve_xattrs;
  extern int checksum_seed;
@@ -170,7 +173,7 @@ diff --git a/xattrs.c b/xattrs.c
  
  #define RSYNC_XAL_INITIAL 5
  #define RSYNC_XAL_LIST_INITIAL 100
-@@ -68,6 +70,10 @@ extern int checksum_seed;
+@@ -69,6 +71,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
@@ -181,7 +184,7 @@ diff --git a/xattrs.c b/xattrs.c
  
  typedef struct {
        char *datum, *name;
-@@ -238,7 +244,9 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
+@@ -239,7 +245,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
@@ -192,7 +195,7 @@ diff --git a/xattrs.c b/xattrs.c
                                continue;
                }
  
-@@ -894,6 +902,39 @@ int del_def_xattr_acl(const char *fname)
+@@ -895,6 +903,39 @@ int del_def_xattr_acl(const char *fname)
  }
  #endif
  
index a900172..3f143cc 100644 (file)
@@ -9,6 +9,7 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/generator.c b/generator.c
+index 12007a1..a2875fd 100644
 --- a/generator.c
 +++ b/generator.c
 @@ -39,6 +39,7 @@ extern int preserve_acls;
@@ -19,7 +20,7 @@ diff --git a/generator.c b/generator.c
  extern int preserve_specials;
  extern int preserve_hard_links;
  extern int preserve_executability;
-@@ -1691,7 +1692,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1507,7 +1508,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                goto cleanup;
        }
  
@@ -29,6 +30,7 @@ diff --git a/generator.c b/generator.c
                        fname = f_name(file, NULL);
                rprintf(FINFO, "skipping non-regular file \"%s\"\n", fname);
 diff --git a/options.c b/options.c
+index e7c6c61..b0806e8 100644
 --- a/options.c
 +++ b/options.c
 @@ -48,6 +48,7 @@ int append_mode = 0;
@@ -39,7 +41,7 @@ diff --git a/options.c b/options.c
  int preserve_links = 0;
  int preserve_hard_links = 0;
  int preserve_acls = 0;
-@@ -350,6 +351,7 @@ void usage(enum logcode F)
+@@ -694,6 +695,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 +49,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");
-@@ -508,6 +510,7 @@ static struct poptOption long_options[] = {
+@@ -862,6 +864,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 +57,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 },
-@@ -2063,6 +2066,9 @@ void server_options(char **args, int *argc_p)
+@@ -2609,6 +2612,9 @@ void server_options(char **args, int *argc_p)
        else if (remove_source_files)
                args[ac++] = "--remove-sent-files";
  
@@ -66,9 +68,10 @@ diff --git a/options.c b/options.c
                rprintf(FERROR, "argc overflow in server_options().\n");
                exit_cleanup(RERR_MALLOC);
 diff --git a/rsync.c b/rsync.c
+index 2c026a2..cfc6ffa 100644
 --- a/rsync.c
 +++ b/rsync.c
-@@ -34,6 +34,7 @@ extern int preserve_xattrs;
+@@ -33,6 +33,7 @@ extern int preserve_xattrs;
  extern int preserve_perms;
  extern int preserve_executability;
  extern int preserve_times;
@@ -76,7 +79,7 @@ diff --git a/rsync.c b/rsync.c
  extern int am_root;
  extern int am_server;
  extern int am_sender;
-@@ -329,7 +330,8 @@ int read_ndx_and_attrs(int f_in, int *iflag_ptr, uchar *type_ptr,
+@@ -330,7 +331,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;
@@ -87,14 +90,15 @@ diff --git a/rsync.c b/rsync.c
                                "received request to transfer non-regular file: %d [%s]\n",
                                ndx, who_am_i());
 diff --git a/sender.c b/sender.c
+index bf8221d..f115457 100644
 --- a/sender.c
 +++ b/sender.c
-@@ -309,6 +309,20 @@ void send_files(int f_in, int f_out)
+@@ -329,6 +329,20 @@ void send_files(int f_in, int f_out)
                        exit_cleanup(RERR_PROTOCOL);
                }
  
-+              /* On Linux systems (at least), st_size is typically 0 for devices.
-+               * If so, try to determine the actual device size. */
++              /* On Matt's computer, st_size is falsely 0 for most devices.
++               * If this happens, try harder to determine the actual device size. */
 +              if (IS_DEVICE(st.st_mode) && st.st_size == 0) {
 +                      OFF_T off = lseek(fd, 0, SEEK_END);
 +                      if (off == (OFF_T) -1)
index d83bd9a..6c5148b 100644 (file)
@@ -9,9 +9,10 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/compat.c b/compat.c
+index ef1882d..132ff90 100644
 --- a/compat.c
 +++ b/compat.c
-@@ -45,6 +45,7 @@ extern int force_change;
+@@ -44,6 +44,7 @@ extern int force_change;
  extern int protect_args;
  extern int preserve_uid;
  extern int preserve_gid;
@@ -19,7 +20,7 @@ diff --git a/compat.c b/compat.c
  extern int preserve_fileflags;
  extern int preserve_acls;
  extern int preserve_xattrs;
-@@ -63,7 +64,7 @@ extern char *iconv_opt;
+@@ -62,7 +63,7 @@ extern char *iconv_opt;
  #endif
  
  /* These index values are for the file-list's extra-attribute array. */
@@ -28,7 +29,7 @@ diff --git a/compat.c b/compat.c
  
  int receiver_symlink_times = 0; /* receiver can set the time on a symlink */
  int sender_symlink_iconv = 0; /* sender should convert symlink content */
-@@ -139,6 +140,8 @@ void setup_protocol(int f_out,int f_in)
+@@ -138,6 +139,8 @@ void setup_protocol(int f_out,int f_in)
                uid_ndx = ++file_extra_cnt;
        if (preserve_gid)
                gid_ndx = ++file_extra_cnt;
@@ -38,9 +39,10 @@ diff --git a/compat.c b/compat.c
                fileflags_ndx = ++file_extra_cnt;
        if (preserve_acls && !am_sender)
 diff --git a/flist.c b/flist.c
+index e1d01be..3287447 100644
 --- a/flist.c
 +++ b/flist.c
-@@ -56,6 +56,7 @@ extern int preserve_fileflags;
+@@ -56,6 +56,7 @@ extern int missing_args;
  extern int uid_ndx;
  extern int gid_ndx;
  extern int eol_nulls;
@@ -48,7 +50,7 @@ diff --git a/flist.c b/flist.c
  extern int relative_paths;
  extern int implied_dirs;
  extern int file_extra_cnt;
-@@ -394,7 +395,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
+@@ -397,7 +398,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
  #endif
                            int ndx, int first_ndx)
  {
@@ -57,7 +59,7 @@ diff --git a/flist.c b/flist.c
        static mode_t mode;
  #ifdef SUPPORT_FILEFLAGS
        static uint32 fileflags;
-@@ -479,6 +480,13 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
+@@ -496,6 +497,13 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
                xflags |= XMIT_SAME_TIME;
        else
                modtime = file->modtime;
@@ -71,7 +73,7 @@ diff --git a/flist.c b/flist.c
  
  #ifdef SUPPORT_HARD_LINKS
        if (tmp_dev != 0) {
-@@ -548,6 +556,8 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
+@@ -578,6 +586,8 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
                else
                        write_int(f, modtime);
        }
@@ -80,7 +82,7 @@ diff --git a/flist.c b/flist.c
        if (!(xflags & XMIT_SAME_MODE))
                write_int(f, to_wire_mode(mode));
  #ifdef SUPPORT_FILEFLAGS
-@@ -638,7 +648,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
+@@ -670,7 +680,7 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
  static struct file_struct *recv_file_entry(struct file_list *flist,
                                           int xflags, int f)
  {
@@ -89,16 +91,7 @@ diff --git a/flist.c b/flist.c
        static mode_t mode;
  #ifdef SUPPORT_FILEFLAGS
        static uint32 fileflags;
-@@ -744,6 +754,8 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
-                               uid = F_OWNER(first);
-                       if (preserve_gid)
-                               gid = F_GROUP(first);
-+                      if (crtimes_ndx)
-+                              crtime = f_crtime(first);
-                       if ((preserve_devices && IS_DEVICE(mode))
-                        || (preserve_specials && IS_SPECIAL(mode))) {
-                               uint32 *devp = F_RDEV_P(first);
-@@ -773,6 +785,19 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+@@ -810,6 +820,19 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                } else
                        modtime = read_int(f);
        }
@@ -118,7 +111,7 @@ diff --git a/flist.c b/flist.c
        if (!(xflags & XMIT_SAME_MODE))
                mode = from_wire_mode(read_int(f));
  
-@@ -932,6 +957,8 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+@@ -969,6 +992,8 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                F_GROUP(file) = gid;
                file->flags |= gid_flags;
        }
@@ -127,7 +120,7 @@ diff --git a/flist.c b/flist.c
        if (unsort_ndx)
                F_NDX(file) = flist->used + flist->ndx_start;
  
-@@ -1308,6 +1335,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1358,6 +1383,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;
@@ -137,17 +130,10 @@ diff --git a/flist.c b/flist.c
        if (basename != thisname)
                file->dirname = lastdir;
 diff --git a/generator.c b/generator.c
+index eee42e8..932f81c 100644
 --- a/generator.c
 +++ b/generator.c
-@@ -21,6 +21,7 @@
-  */
- #include "rsync.h"
-+#include "ifuncs.h"
- extern int verbose;
- extern int dry_run;
-@@ -40,6 +41,7 @@ extern int preserve_xattrs;
+@@ -40,6 +40,7 @@ extern int preserve_xattrs;
  extern int preserve_links;
  extern int preserve_devices;
  extern int preserve_specials;
@@ -155,7 +141,7 @@ diff --git a/generator.c b/generator.c
  extern int preserve_hard_links;
  extern int preserve_executability;
  extern int preserve_fileflags;
-@@ -623,6 +625,13 @@ int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
+@@ -419,6 +420,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;
  
@@ -169,7 +155,7 @@ diff --git a/generator.c b/generator.c
  #ifdef SUPPORT_ACLS
        if (preserve_acls && !S_ISLNK(file->mode)) {
                if (!ACL_READY(*sxp))
-@@ -666,6 +675,12 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+@@ -462,6 +470,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))
                        iflags |= ITEM_REPORT_TIME;
@@ -182,65 +168,57 @@ diff --git a/generator.c b/generator.c
  #if !defined HAVE_LCHMOD && !defined HAVE_SETATTRLIST
                if (S_ISLNK(file->mode)) {
                        ;
-@@ -1226,6 +1241,7 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx,
+@@ -1022,6 +1036,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];
 +      time_t crtime = crtimes_ndx ? f_crtime(f) : 0;
-       double len;
+       int64 len;
+       int colwidth = human_readable ? 14 : 11;
  
-       if (!F_IS_ACTIVE(f)) {
-@@ -1240,14 +1256,16 @@ static void list_file_entry(struct file_struct *f)
+@@ -1037,10 +1052,11 @@ static void list_file_entry(struct file_struct *f)
  
  #ifdef SUPPORT_LINKS
        if (preserve_links && S_ISLNK(f->mode)) {
--              rprintf(FINFO, "%s %11.0f %s %s -> %s\n",
-+              rprintf(FINFO, "%s %11.0f %s %s %s -> %s\n",
-                       permbuf, len, timestring(f->modtime),
+-              rprintf(FINFO, "%s %*s %s %s -> %s\n",
++              rprintf(FINFO, "%s %*s %s %s %s -> %s\n",
+                       permbuf, colwidth, comma_num(len),
+-                      timestring(f->modtime), f_name(f, NULL),
+-                      F_SYMLINK(f));
++                      timestring(f->modtime),
 +                      crtimes_ndx ? timestring(crtime) : "",
-                       f_name(f, NULL), F_SYMLINK(f));
++                      f_name(f, NULL), F_SYMLINK(f));
        } else
  #endif
-       {
--              rprintf(FINFO, "%s %11.0f %s %s\n",
-+              rprintf(FINFO, "%s %11.0f %s %s %s\n",
-                       permbuf, len, timestring(f->modtime),
-+                      crtimes_ndx ? timestring(crtime) : "",
+       if (missing_args == 2 && f->mode == 0) {
+@@ -1048,9 +1064,11 @@ static void list_file_entry(struct file_struct *f)
+                       colwidth + 31, "*missing",
                        f_name(f, NULL));
+       } else {
+-              rprintf(FINFO, "%s %*s %s %s\n",
++              rprintf(FINFO, "%s %*s %s %s %s\n",
+                       permbuf, colwidth, comma_num(len),
+-                      timestring(f->modtime), f_name(f, NULL));
++                      timestring(f->modtime),
++                      crtimes_ndx ? timestring(crtime) : "",
++                      f_name(f, NULL));
        }
  }
-@@ -1339,6 +1357,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1141,6 +1159,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;
-diff --git a/hlink.c b/hlink.c
---- a/hlink.c
-+++ b/hlink.c
-@@ -366,6 +366,7 @@ int hard_link_check(struct file_struct *file, int ndx, const char *fname,
-               char cmpbuf[MAXPATHLEN];
-               stat_x alt_sx;
-               int j = 0;
-+              alt_sx.crtime = 0;
- #ifdef SUPPORT_ACLS
-               alt_sx.acc_acl = alt_sx.def_acl = NULL;
- #endif
-@@ -494,6 +495,7 @@ void finish_hard_link(struct file_struct *file, const char *fname, int fin_ndx,
-       } else
-               our_name = fname;
-+      prev_sx.crtime = 0;
- #ifdef SUPPORT_ACLS
-       prev_sx.acc_acl = prev_sx.def_acl = NULL;
- #endif
+       init_stat_x(&sx);
+       if (dry_run > 1 || (dry_missing_dir && is_below(file, dry_missing_dir))) {
 diff --git a/ifuncs.h b/ifuncs.h
+index 8c128d5..4254dfb 100644
 --- a/ifuncs.h
 +++ b/ifuncs.h
-@@ -67,6 +67,28 @@ d_name(struct dirent *di)
- #endif
+@@ -35,6 +35,28 @@ realloc_xbuf(xbuf *xb, size_t sz)
+       xb->size = sz;
  }
  
 +static inline time_t
@@ -266,12 +244,13 @@ diff --git a/ifuncs.h b/ifuncs.h
 +}
 +
  static inline int
isDigit(const char *ptr)
to_wire_mode(mode_t mode)
  {
 diff --git a/log.c b/log.c
+index 83948b1..7a1d9ce 100644
 --- a/log.c
 +++ b/log.c
-@@ -663,7 +663,8 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
+@@ -718,7 +718,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';
@@ -282,6 +261,7 @@ diff --git a/log.c b/log.c
                        if (iflags & (ITEM_IS_NEW|ITEM_MISSING_DATA)) {
                                char ch = iflags & ITEM_IS_NEW ? '+' : '?';
 diff --git a/options.c b/options.c
+index ae3d2d0..bb3bad3 100644
 --- a/options.c
 +++ b/options.c
 @@ -60,6 +60,7 @@ int preserve_specials = 0;
@@ -292,7 +272,7 @@ diff --git a/options.c b/options.c
  int update_only = 0;
  int cvs_exclude = 0;
  int dry_run = 0;
-@@ -363,6 +364,7 @@ void usage(enum logcode F)
+@@ -707,6 +708,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");
@@ -300,7 +280,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");
-@@ -509,6 +511,9 @@ static struct poptOption long_options[] = {
+@@ -863,6 +865,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 },
@@ -310,7 +290,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 },
-@@ -1800,6 +1805,8 @@ void server_options(char **args, int *argc_p)
+@@ -2315,6 +2320,8 @@ void server_options(char **args, int *argc_p)
                argstr[x++] = 'D';
        if (preserve_times)
                argstr[x++] = 't';
@@ -320,17 +300,10 @@ diff --git a/options.c b/options.c
                argstr[x++] = 'p';
        else if (preserve_executability && am_sender)
 diff --git a/rsync.c b/rsync.c
+index 3188535..ab4f8e4 100644
 --- a/rsync.c
 +++ b/rsync.c
-@@ -428,6 +428,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
-                               full_fname(fname));
-                       return 0;
-               }
-+              sx2.crtime = 0;
- #ifdef SUPPORT_ACLS
-               sx2.acc_acl = sx2.def_acl = NULL;
- #endif
-@@ -475,6 +476,14 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
+@@ -471,6 +471,14 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
                else
                        file->flags |= FLAG_TIME_FAILED;
        }
@@ -345,7 +318,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)
-@@ -622,7 +631,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
+@@ -619,7 +627,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
@@ -353,8 +326,8 @@ diff --git a/rsync.c b/rsync.c
 +                     | (ok_to_set_time ? 0 : ATTRS_SKIP_MTIME | ATTRS_SKIP_CRTIME));
  
        /* move tmp file over real file */
-       if (verbose > 2)
-@@ -653,7 +662,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
+       if (DEBUG_GTE(RECV, 1))
+@@ -650,7 +658,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
  
    do_set_file_attrs:
        set_file_attrs(fnametmp, file, NULL, fnamecmp,
@@ -364,17 +337,18 @@ diff --git a/rsync.c b/rsync.c
        if (temp_copy_name) {
                if (do_rename(fnametmp, fname) < 0) {
 diff --git a/rsync.h b/rsync.h
+index 16820fd..b3973c8 100644
 --- a/rsync.h
 +++ b/rsync.h
-@@ -60,6 +60,7 @@
- #define XMIT_RDEV_MINOR_8_pre30 (1<<11)       /* protocols 28 - 29  */
+@@ -61,6 +61,7 @@
  #define XMIT_GROUP_NAME_FOLLOWS (1<<11) /* protocols 30 - now */
  #define XMIT_HLINK_FIRST (1<<12)      /* protocols 30 - now (HLINKED files only) */
+ #define XMIT_IO_ERROR_ENDLIST (1<<12) /* protocols 31 - now (w/XMIT_EXTENDED_FLAGS) */
 +#define XMIT_CRTIME_EQ_MTIME (1<<13)  /* protocols ?? - now */
  #define XMIT_SAME_FLAGS (1<<14)               /* protocols ?? - now */
  
  /* These flags are used in the live flist data. */
-@@ -156,6 +157,7 @@
+@@ -157,6 +158,7 @@
  #define ATTRS_REPORT          (1<<0)
  #define ATTRS_SKIP_MTIME      (1<<1)
  #define ATTRS_DELAY_IMMUTABLE (1<<2)
@@ -382,7 +356,7 @@ diff --git a/rsync.h b/rsync.h
  
  #define FULL_FLUSH    1
  #define NORMAL_FLUSH  0
-@@ -172,7 +174,7 @@
+@@ -173,7 +175,7 @@
  #define FNAMECMP_FUZZY                0x83
  
  /* For use by the itemize_changes code */
@@ -391,7 +365,7 @@ diff --git a/rsync.h b/rsync.h
  #define ITEM_REPORT_CHANGE (1<<1)
  #define ITEM_REPORT_SIZE (1<<2)     /* regular files only */
  #define ITEM_REPORT_TIMEFAIL (1<<2) /* symlinks only */
-@@ -657,6 +659,7 @@ extern int file_extra_cnt;
+@@ -677,6 +679,7 @@ extern int file_extra_cnt;
  extern int inc_recurse;
  extern int uid_ndx;
  extern int gid_ndx;
@@ -399,7 +373,7 @@ diff --git a/rsync.h b/rsync.h
  extern int fileflags_ndx;
  extern int acls_ndx;
  extern int xattrs_ndx;
-@@ -664,6 +667,7 @@ extern int xattrs_ndx;
+@@ -684,6 +687,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)
@@ -407,7 +381,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)
-@@ -931,6 +935,7 @@ typedef struct {
+@@ -954,6 +958,7 @@ typedef struct {
  
  typedef struct {
      STRUCT_STAT st;
@@ -416,9 +390,10 @@ diff --git a/rsync.h b/rsync.h
      struct rsync_acl *acc_acl; /* access ACL */
      struct rsync_acl *def_acl; /* default ACL */
 diff --git a/rsync.yo b/rsync.yo
+index 7b41d5f..5670c46 100644
 --- a/rsync.yo
 +++ b/rsync.yo
-@@ -354,6 +354,7 @@ to the detailed description below for a complete description.  verb(
+@@ -357,6 +357,7 @@ to the detailed description below for a complete description.  verb(
   -D                          same as --devices --specials
   -t, --times                 preserve modification times
   -O, --omit-dir-times        omit directories from --times
@@ -426,7 +401,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
-@@ -1032,6 +1033,9 @@ it is preserving modification times (see bf(--times)).  If NFS is sharing
+@@ -1099,6 +1100,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).
  
@@ -436,7 +411,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
-@@ -1696,7 +1700,7 @@ with older versions of rsync, but that also turns on the output of other
+@@ -1861,7 +1865,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
@@ -445,7 +420,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.
-@@ -1755,6 +1759,8 @@ quote(itemization(
+@@ -1920,6 +1924,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.
@@ -455,6 +430,7 @@ diff --git a/rsync.yo b/rsync.yo
  
  One other output is possible:  when deleting files, the "%i" will output
 diff --git a/syscall.c b/syscall.c
+index 45604b1..c463997 100644
 --- a/syscall.c
 +++ b/syscall.c
 @@ -37,6 +37,11 @@ extern int force_change;
@@ -505,6 +481,7 @@ diff --git a/syscall.c b/syscall.c
 +}
 diff --git a/testsuite/crtimes.test b/testsuite/crtimes.test
 new file mode 100644
+index 0000000..b904e16
 --- /dev/null
 +++ b/testsuite/crtimes.test
 @@ -0,0 +1,24 @@
@@ -533,6 +510,7 @@ new file mode 100644
 +# The script would have aborted on error, so getting here means we've won.
 +exit 0
 diff --git a/testsuite/rsync.fns b/testsuite/rsync.fns
+index b26aee3..4faaf93 100644
 --- a/testsuite/rsync.fns
 +++ b/testsuite/rsync.fns
 @@ -24,9 +24,9 @@ todir="$tmpdir/to"
@@ -549,9 +527,10 @@ diff --git a/testsuite/rsync.fns b/testsuite/rsync.fns
  # Berkley's nice.
  PATH="$PATH:/usr/ucb"
 diff --git a/tls.c b/tls.c
+index 8cc5748..6da4df9 100644
 --- a/tls.c
 +++ b/tls.c
-@@ -107,6 +107,8 @@ static int stat_xattr(const char *fname, STRUCT_STAT *fst)
+@@ -108,6 +108,8 @@ static int stat_xattr(const char *fname, STRUCT_STAT *fst)
  
  #endif
  
@@ -560,7 +539,7 @@ diff --git a/tls.c b/tls.c
  static void failed(char const *what, char const *where)
  {
        fprintf(stderr, PROGRAM ": %s %s: %s\n",
-@@ -114,16 +116,36 @@ static void failed(char const *what, char const *where)
+@@ -115,16 +117,36 @@ static void failed(char const *what, char const *where)
        exit(1);
  }
  
@@ -599,7 +578,7 @@ diff --git a/tls.c b/tls.c
  #ifdef SUPPORT_XATTRS
        if (am_root < 0)
                stat_xattr(fname, &buf);
-@@ -158,19 +180,11 @@ static void list_file(const char *fname)
+@@ -159,19 +181,11 @@ static void list_file(const char *fname)
  
        permstring(permbuf, buf.st_mode);
  
@@ -624,10 +603,10 @@ diff --git a/tls.c b/tls.c
  
        /* TODO: Perhaps escape special characters in fname? */
  
-@@ -181,13 +195,14 @@ static void list_file(const char *fname)
+@@ -182,13 +196,14 @@ static void list_file(const char *fname)
                    (long)minor(buf.st_rdev));
-       } else /* NB: use double for size since it might not fit in a long. */
-               printf("%12.0f", (double)buf.st_size);
+       } else
+               printf("%15s", do_big_num(buf.st_size, 1, NULL));
 -      printf(" %6ld.%-6ld %6ld %s %s%s\n",
 +      printf(" %6ld.%-6ld %6ld %s%s%s%s\n",
               (long)buf.st_uid, (long)buf.st_gid, (long)buf.st_nlink,
@@ -641,7 +620,7 @@ diff --git a/tls.c b/tls.c
    {"link-times",      'l', POPT_ARG_NONE,   &link_times, 0, 0, 0 },
    {"link-owner",      'L', POPT_ARG_NONE,   &link_owner, 0, 0, 0 },
  #ifdef SUPPORT_XATTRS
-@@ -203,6 +218,7 @@ static void tls_usage(int ret)
+@@ -204,6 +219,7 @@ static void tls_usage(int ret)
    fprintf(F,"usage: " PROGRAM " [OPTIONS] FILE ...\n");
    fprintf(F,"Trivial file listing program for portably checking rsync\n");
    fprintf(F,"\nOptions:\n");
index be52c61..436ede8 100644 (file)
@@ -9,18 +9,19 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/exclude.c b/exclude.c
+index 5fa6e00..60e557d 100644
 --- a/exclude.c
 +++ b/exclude.c
-@@ -239,6 +239,8 @@ static void add_rule(struct filter_list_struct *listp, const char *pat,
+@@ -275,6 +275,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;
+               lp->head = lp->tail = lp->parent_dirscan_head = NULL;
 +              if (mflags & MATCHFLG_CVS_IGNORE)
 +                      cp = "CVS";
                if (asprintf(&lp->debug_type, " [per-dir %s]", cp) < 0)
                        out_of_memory("add_rule");
                ret->u.mergelist = lp;
-@@ -470,6 +472,14 @@ void *push_local_filters(const char *dir, unsigned int dirlen)
+@@ -536,6 +538,14 @@ void *push_local_filters(const char *dir, unsigned int dirlen)
                                set_filter_dir(dir, dirlen);
                }
  
@@ -35,7 +36,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,
-@@ -1030,6 +1040,7 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
+@@ -1122,6 +1132,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 +44,7 @@ diff --git a/exclude.c b/exclude.c
  
        if (!fname || !*fname)
                return;
-@@ -1076,6 +1087,24 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
+@@ -1168,6 +1179,24 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
                                }
                                break;
                        }
@@ -68,7 +69,7 @@ diff --git a/exclude.c b/exclude.c
                        if (word_split && isspace(ch))
                                break;
                        if (eol_nulls? !ch : (ch == '\n' || ch == '\r'))
-@@ -1085,13 +1114,15 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
+@@ -1177,13 +1206,15 @@ void parse_filter_file(struct filter_list_struct *listp, const char *fname,
                        else
                                overflow = 1;
                }
@@ -86,9 +87,10 @@ diff --git a/exclude.c b/exclude.c
                if (ch == EOF)
                        break;
 diff --git a/rsync.h b/rsync.h
+index be7cf8a..6605092 100644
 --- a/rsync.h
 +++ b/rsync.h
-@@ -151,6 +151,7 @@
+@@ -152,6 +152,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 */
@@ -97,6 +99,7 @@ diff --git a/rsync.h b/rsync.h
  #define ATTRS_REPORT          (1<<0)
  #define ATTRS_SKIP_MTIME      (1<<1)
 diff --git a/testsuite/exclude.test b/testsuite/exclude.test
+index 099344f..993edcc 100644
 --- a/testsuite/exclude.test
 +++ b/testsuite/exclude.test
 @@ -19,6 +19,7 @@ export CVSIGNORE
index 8339da5..1e8f62f 100644 (file)
@@ -9,36 +9,33 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/access.c b/access.c
+index 9a023de..ad1cdb1 100644
 --- a/access.c
 +++ b/access.c
-@@ -210,6 +210,42 @@ static int match_address(char *addr, char *tok)
+@@ -210,6 +210,38 @@ static int match_address(const char *addr, const char *tok)
        return ret;
  }
  
-+static int match_hostlookup(char *addr, char *tok)
++static int match_hostlookup(const char *addr, const char *tok)
 +{
 +      struct hostent *hp = NULL;
 +      unsigned int i, len;
-+      char *p;
++      const char *p;
 +
-+      if ((p = strchr(tok,'/')) != NULL) {
-+              *p = '\0';
++      if ((p = strchr(tok,'/')) != NULL)
 +              len = p - tok;
-+      else
++      else
 +              len = strlen(tok);
 +
 +      /* Fail quietly (hp left NULL) if tok is an address, not a hostname. */
 +#ifdef INET6
-+      if (strchr(tok, ':') != NULL) {
++      if (strcspn(tok, ":/") != len) {
 +              ;
 +      } else
 +#endif
 +      if (strspn(tok, ".0123456789") != len)
 +              hp = gethostbyname(tok);
 +
-+      if (p)
-+              *p = '/';
-+
 +      if (!hp)
 +              return 0;
 +
@@ -51,11 +48,11 @@ diff --git a/access.c b/access.c
 +      return 0;
 +}
 +
- static int access_match(char *list, char *addr, char *host)
+ static int access_match(const char *list, const char *addr, const char *host)
  {
        char *tok;
-@@ -223,7 +259,7 @@ static int access_match(char *list, char *addr, char *host)
-               strlower(host);
+@@ -221,7 +253,7 @@ static int access_match(const char *list, const char *addr, const char *host)
+       strlower(list2);
  
        for (tok = strtok(list2, " ,\t"); tok; tok = strtok(NULL, " ,\t")) {
 -              if (match_hostname(host, tok) || match_address(addr, tok)) {
index 693e017..0349f87 100644 (file)
@@ -15,9 +15,10 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/generator.c b/generator.c
+index 12007a1..a2519e6 100644
 --- a/generator.c
 +++ b/generator.c
-@@ -62,6 +62,7 @@ extern int append_mode;
+@@ -64,6 +64,7 @@ extern int append_mode;
  extern int make_backups;
  extern int csum_length;
  extern int ignore_times;
@@ -25,7 +26,7 @@ diff --git a/generator.c b/generator.c
  extern int size_only;
  extern OFF_T max_size;
  extern OFF_T min_size;
-@@ -717,6 +718,9 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+@@ -524,6 +525,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)
  {
@@ -36,25 +37,26 @@ diff --git a/generator.c b/generator.c
                return 0;
  
 diff --git a/options.c b/options.c
+index e7c6c61..b317903 100644
 --- a/options.c
 +++ b/options.c
-@@ -106,6 +106,7 @@ int keep_partial = 0;
- int safe_symlinks = 0;
+@@ -105,6 +105,7 @@ int safe_symlinks = 0;
  int copy_unsafe_links = 0;
+ int munge_symlinks = 0;
  int size_only = 0;
 +int date_only = 0;
  int daemon_bwlimit = 0;
  int bwlimit = 0;
  int fuzzy_basis = 0;
-@@ -389,6 +390,7 @@ void usage(enum logcode F)
-   rprintf(F,"     --contimeout=SECONDS    set daemon connection timeout in seconds\n");
+@@ -739,6 +740,7 @@ void usage(enum logcode F)
    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,"     --date-only             skip files that match in mod-time\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");
    rprintf(F," -y, --fuzzy                 find similar file for basis if no dest file\n");
-@@ -531,6 +533,7 @@ static struct poptOption long_options[] = {
+@@ -887,6 +889,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,9 +64,9 @@ 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 },
-@@ -1969,6 +1972,9 @@ void server_options(char **args, int *argc_p)
-               }
-       }
+@@ -2493,6 +2496,9 @@ void server_options(char **args, int *argc_p)
+       else if (missing_args == 1 && !am_sender)
+               args[ac++] = "--ignore-missing-args";
  
 +      if (date_only)
 +              args[ac++] = "--date-only";
@@ -73,9 +75,10 @@ diff --git a/options.c b/options.c
                if (asprintf(&arg, "--modify-window=%d", modify_window) < 0)
                        goto oom;
 diff --git a/rsync.yo b/rsync.yo
+index 941f7a5..710b32d 100644
 --- a/rsync.yo
 +++ b/rsync.yo
-@@ -386,6 +386,7 @@ to the detailed description below for a complete description.  verb(
+@@ -394,6 +394,7 @@ to the detailed description below for a complete description.  verb(
       --contimeout=SECONDS    set daemon connection timeout in seconds
   -I, --ignore-times          don't skip files that match size and time
       --size-only             skip files that match in size
@@ -83,7 +86,7 @@ diff --git a/rsync.yo b/rsync.yo
       --modify-window=NUM     compare mod-times with reduced accuracy
   -T, --temp-dir=DIR          create temporary files in directory DIR
   -y, --fuzzy                 find similar file for basis if no dest file
-@@ -506,6 +507,12 @@ time to just looking for files that have changed in size.  This is useful
+@@ -554,6 +555,12 @@ time to just looking for files that have changed in size.  This is useful
  when starting to use rsync after using another mirroring system which may
  not preserve timestamps exactly.
  
diff --git a/db.diff b/db.diff
index 479fd6b..65ba736 100644 (file)
--- a/db.diff
+++ b/db.diff
@@ -19,17 +19,17 @@ is used.  Future improvements may include:
 
 To use this patch, run these commands for a successful build:
 
-    patch -p1 <patches/remote-option.diff
     patch -p1 <patches/db.diff
     ./configure                               (optional if already run)
     make
 
 diff --git a/Makefile.in b/Makefile.in
+index feacb90..f9da8eb 100644
 --- a/Makefile.in
 +++ b/Makefile.in
-@@ -35,7 +35,7 @@ ZLIBOBJ=zlib/deflate.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o \
+@@ -36,7 +36,7 @@ ZLIBOBJ=zlib/deflate.o zlib/inffast.o zlib/inflate.o zlib/inftrees.o \
  OBJS1=flist.o rsync.o generator.o receiver.o cleanup.o sender.o exclude.o \
-       util.o main.o checksum.o match.o syscall.o log.o backup.o
+       util.o main.o checksum.o match.o syscall.o log.o backup.o delete.o
  OBJS2=options.o io.o compat.o hlink.o token.o uidlist.o socket.o hashtable.o \
 -      fileio.o batch.o clientname.o chmod.o acls.o xattrs.o
 +      fileio.o batch.o clientname.o chmod.o db.o acls.o xattrs.o
@@ -37,6 +37,7 @@ diff --git a/Makefile.in b/Makefile.in
  DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
  popt_OBJS=popt/findme.o  popt/popt.o  popt/poptconfig.o \
 diff --git a/checksum.c b/checksum.c
+index 811b5b6..a7617af 100644
 --- a/checksum.c
 +++ b/checksum.c
 @@ -23,6 +23,7 @@
@@ -45,9 +46,9 @@ diff --git a/checksum.c b/checksum.c
  extern int protocol_version;
 +extern int use_db;
  
- int csum_length = SHORT_SUM_LENGTH; /* initial value */
-@@ -100,10 +101,10 @@ void get_checksum2(char *buf, int32 len, char *sum)
+ /*
+   a simple 32 bit checksum that can be upadted from either end
+@@ -98,10 +99,10 @@ void get_checksum2(char *buf, int32 len, char *sum)
        }
  }
  
@@ -60,7 +61,7 @@ diff --git a/checksum.c b/checksum.c
        md_context m;
        int32 remainder;
        int fd;
-@@ -114,7 +115,7 @@ void file_checksum(char *fname, char *sum, OFF_T size)
+@@ -112,7 +113,7 @@ void file_checksum(char *fname, char *sum, OFF_T size)
        if (fd == -1)
                return;
  
@@ -69,7 +70,7 @@ diff --git a/checksum.c b/checksum.c
  
        if (protocol_version >= 30) {
                md5_begin(&m);
-@@ -148,6 +149,9 @@ void file_checksum(char *fname, char *sum, OFF_T size)
+@@ -146,6 +147,9 @@ void file_checksum(char *fname, char *sum, OFF_T size)
                mdfour_result(&m, (uchar *)sum);
        }
  
@@ -80,17 +81,18 @@ diff --git a/checksum.c b/checksum.c
        unmap_file(buf);
  }
 diff --git a/cleanup.c b/cleanup.c
+index 19ef072..ca46868 100644
 --- a/cleanup.c
 +++ b/cleanup.c
-@@ -27,6 +27,7 @@ extern int am_daemon;
+@@ -25,6 +25,7 @@
+ extern int am_server;
+ extern int am_daemon;
  extern int io_error;
++extern int use_db;
  extern int keep_partial;
  extern int got_xfer_error;
-+extern int use_db;
- extern char *partial_dir;
- extern char *logfile_name;
-@@ -124,6 +125,12 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
+ extern int output_needs_newline;
+@@ -130,6 +131,12 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
                /* FALLTHROUGH */
  #include "case_N.h"
  
@@ -104,6 +106,7 @@ diff --git a/cleanup.c b/cleanup.c
                        int status;
                        int pid = wait_process(cleanup_child_pid, &status, WNOHANG);
 diff --git a/clientserver.c b/clientserver.c
+index b6afe00..37cad54 100644
 --- a/clientserver.c
 +++ b/clientserver.c
 @@ -42,13 +42,16 @@ extern int numeric_ids;
@@ -121,9 +124,9 @@ diff --git a/clientserver.c b/clientserver.c
  extern mode_t orig_umask;
 +extern char *db_config;
  extern char *bind_address;
- extern char *sockopts;
  extern char *config_file;
-@@ -564,6 +567,9 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
+ extern char *logfile_format;
+@@ -648,6 +651,9 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
  
        log_init(1);
  
@@ -133,7 +136,7 @@ diff --git a/clientserver.c b/clientserver.c
  #ifdef HAVE_PUTENV
        if (*lp_prexfer_exec(i) || *lp_postxfer_exec(i)) {
                char *modname, *modpath, *hostaddr, *hostname, *username;
-@@ -767,6 +773,10 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
+@@ -856,6 +862,10 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
  
        am_server = 1; /* Don't let someone try to be tricky. */
        quiet = 0;
@@ -145,9 +148,10 @@ diff --git a/clientserver.c b/clientserver.c
                ignore_errors = 1;
        if (write_batch < 0)
 diff --git a/configure.in b/configure.in
+index bc7d4a7..43d51ff 100644
 --- a/configure.in
 +++ b/configure.in
-@@ -314,7 +314,7 @@ AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h \
+@@ -312,7 +312,7 @@ AC_CHECK_HEADERS(sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h \
      sys/un.h sys/attr.h mcheck.h arpa/inet.h arpa/nameser.h locale.h \
      netdb.h malloc.h float.h limits.h iconv.h libcharset.h langinfo.h \
      sys/acl.h acl/libacl.h attr/xattr.h sys/xattr.h sys/extattr.h \
@@ -156,7 +160,7 @@ diff --git a/configure.in b/configure.in
  AC_HEADER_MAJOR
  
  AC_CACHE_CHECK([if makedev takes 3 args],rsync_cv_MAKEDEV_TAKES_3_ARGS,[
-@@ -969,6 +969,29 @@ if test x"$enable_acl_support" = x"no" -o x"$enable_xattr_support" = x"no" -o x"
+@@ -977,6 +977,29 @@ if test x"$enable_acl_support" = x"no" -o x"$enable_xattr_support" = x"no" -o x"
      fi
  fi
  
@@ -188,6 +192,7 @@ diff --git a/configure.in b/configure.in
      AC_DEFINE(FORCE_FD_ZERO_MEMSET, 1, [Used to make "checker" understand that FD_ZERO() clears memory.])
 diff --git a/db.c b/db.c
 new file mode 100644
+index 0000000..6855488
 --- /dev/null
 +++ b/db.c
 @@ -0,0 +1,566 @@
@@ -758,37 +763,47 @@ new file mode 100644
 +      return 0;
 +}
 diff --git a/flist.c b/flist.c
+index 09b4fc5..8d280e9 100644
 --- a/flist.c
 +++ b/flist.c
-@@ -54,6 +54,7 @@ extern int preserve_devices;
- extern int preserve_specials;
+@@ -54,6 +54,7 @@ extern int preserve_specials;
+ extern int missing_args;
  extern int uid_ndx;
  extern int gid_ndx;
 +extern int use_db;
  extern int eol_nulls;
  extern int relative_paths;
  extern int implied_dirs;
-@@ -1286,14 +1287,16 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
-               memcpy(bp + basename_len, linkname, linkname_len);
+@@ -1267,11 +1268,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+               extra_len += EXTRA_LEN;
  #endif
  
--      if (always_checksum && am_sender && S_ISREG(st.st_mode))
+-      if (always_checksum && am_sender && S_ISREG(st.st_mode)) {
 -              file_checksum(thisname, tmp_sum, st.st_size);
--
-       if (am_sender)
-               F_PATHNAME(file) = pathname;
-       else if (!pool)
-               F_DEPTH(file) = extra_len / EXTRA_LEN;
+-              if (sender_keeps_checksum)
+-                      extra_len += SUM_EXTRA_CNT * EXTRA_LEN;
+-      }
++      if (sender_keeps_checksum && S_ISREG(st.st_mode))
++              extra_len += SUM_EXTRA_CNT * EXTRA_LEN;
  
+ #if EXTRA_ROUNDING > 0
+       if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN))
+@@ -1347,8 +1345,12 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+               return NULL;
+       }
+-      if (sender_keeps_checksum && S_ISREG(st.st_mode))
+-              memcpy(F_SUM(file), tmp_sum, checksum_len);
 +      if (always_checksum && am_sender && S_ISREG(st.st_mode)) {
 +              if (!use_db || !db_get_checksum(thisname, &st, tmp_sum))
 +                      file_checksum(thisname, &st, tmp_sum);
++              if (sender_keeps_checksum)
++                      memcpy(F_SUM(file), tmp_sum, checksum_len);
 +      }
-+
-       if (basename_len == 0+1) {
-               if (!pool)
-                       unmake_file(file);
-@@ -1936,6 +1939,9 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
+       if (unsort_ndx)
+               F_NDX(file) = stats.num_dirs;
+@@ -2010,6 +2012,9 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
                     | (eol_nulls || reading_remotely ? RL_EOL_NULLS : 0);
        int implied_dot_dir = 0;
  
@@ -799,9 +814,10 @@ diff --git a/flist.c b/flist.c
        if (show_filelist_p())
                start_filelist_progress("building file list");
 diff --git a/generator.c b/generator.c
+index 12007a1..315463f 100644
 --- a/generator.c
 +++ b/generator.c
-@@ -58,6 +58,7 @@ extern int update_only;
+@@ -60,6 +60,7 @@ extern int human_readable;
  extern int ignore_existing;
  extern int ignore_non_existing;
  extern int inplace;
@@ -809,7 +825,7 @@ diff --git a/generator.c b/generator.c
  extern int append_mode;
  extern int make_backups;
  extern int csum_length;
-@@ -724,7 +725,8 @@ int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st)
+@@ -531,7 +532,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];
@@ -819,7 +835,7 @@ diff --git a/generator.c b/generator.c
                return memcmp(sum, F_SUM(file), checksum_len) == 0;
        }
  
-@@ -2206,6 +2208,9 @@ void generate_files(int f_out, const char *local_name)
+@@ -2022,6 +2024,9 @@ void generate_files(int f_out, const char *local_name)
                        : "enabled");
        }
  
@@ -830,9 +846,10 @@ diff --git a/generator.c b/generator.c
         * waiting for the other 2 processes to do their thing, we don't want
         * to exit on a timeout.  If the data stops flowing, the receiver will
 diff --git a/loadparm.c b/loadparm.c
+index 8e48e6d..e6eaec8 100644
 --- a/loadparm.c
 +++ b/loadparm.c
-@@ -126,6 +126,7 @@ typedef struct
+@@ -107,6 +107,7 @@ typedef struct {
        char *auth_users;
        char *charset;
        char *comment;
@@ -840,7 +857,7 @@ diff --git a/loadparm.c b/loadparm.c
        char *dont_compress;
        char *exclude;
        char *exclude_from;
-@@ -177,6 +178,7 @@ static service sDefault =
+@@ -181,6 +182,7 @@ static const all_vars Defaults = {
   /* auth_users; */            NULL,
   /* charset; */               NULL,
   /* comment; */               NULL,
@@ -848,15 +865,15 @@ diff --git a/loadparm.c b/loadparm.c
   /* dont_compress; */         DEFAULT_DONT_COMPRESS,
   /* exclude; */                       NULL,
   /* exclude_from; */          NULL,
-@@ -307,6 +309,7 @@ static struct parm_struct parm_table[] =
-  {"auth users",        P_STRING, P_LOCAL, &sDefault.auth_users,        NULL,0},
-  {"charset",           P_STRING, P_LOCAL, &sDefault.charset,           NULL,0},
-  {"comment",           P_STRING, P_LOCAL, &sDefault.comment,           NULL,0},
-+ {"db config",         P_STRING, P_LOCAL, &sDefault.db_config,         NULL,0},
-  {"dont compress",     P_STRING, P_LOCAL, &sDefault.dont_compress,     NULL,0},
-  {"exclude from",      P_STRING, P_LOCAL, &sDefault.exclude_from,      NULL,0},
-  {"exclude",           P_STRING, P_LOCAL, &sDefault.exclude,           NULL,0},
-@@ -400,6 +403,7 @@ FN_GLOBAL_INTEGER(lp_rsync_port, &Globals.rsync_port)
+@@ -316,6 +318,7 @@ static struct parm_struct parm_table[] =
+  {"auth users",        P_STRING, P_LOCAL, &Vars.l.auth_users,          NULL,0},
+  {"charset",           P_STRING, P_LOCAL, &Vars.l.charset,             NULL,0},
+  {"comment",           P_STRING, P_LOCAL, &Vars.l.comment,             NULL,0},
++ {"db config",         P_STRING, P_LOCAL, &Vars.l.db_config,           NULL,0},
+  {"dont compress",     P_STRING, P_LOCAL, &Vars.l.dont_compress,       NULL,0},
+  {"exclude from",      P_STRING, P_LOCAL, &Vars.l.exclude_from,        NULL,0},
+  {"exclude",           P_STRING, P_LOCAL, &Vars.l.exclude,             NULL,0},
+@@ -396,6 +399,7 @@ FN_GLOBAL_INTEGER(lp_rsync_port, &Vars.g.rsync_port)
  FN_LOCAL_STRING(lp_auth_users, auth_users)
  FN_LOCAL_STRING(lp_charset, charset)
  FN_LOCAL_STRING(lp_comment, comment)
@@ -865,6 +882,7 @@ diff --git a/loadparm.c b/loadparm.c
  FN_LOCAL_STRING(lp_exclude, exclude)
  FN_LOCAL_STRING(lp_exclude_from, exclude_from)
 diff --git a/main.c b/main.c
+index 2ef2f47..ac88e12 100644
 --- a/main.c
 +++ b/main.c
 @@ -49,6 +49,7 @@ extern int copy_unsafe_links;
@@ -875,15 +893,15 @@ diff --git a/main.c b/main.c
  extern int file_total;
  extern int recurse;
  extern int xfer_dirs;
-@@ -73,6 +74,7 @@ extern char *partial_dir;
+@@ -74,6 +75,7 @@ extern char *filesfrom_host;
+ extern char *partial_dir;
  extern char *dest_option;
- extern char *basis_dir[];
  extern char *rsync_path;
 +extern char *db_config;
  extern char *shell_cmd;
  extern char *batch_name;
  extern char *password_file;
-@@ -1491,6 +1493,9 @@ int main(int argc,char *argv[])
+@@ -1565,6 +1567,9 @@ int main(int argc,char *argv[])
                exit_cleanup(RERR_SYNTAX);
        }
  
@@ -894,6 +912,7 @@ diff --git a/main.c b/main.c
                set_nonblocking(STDIN_FILENO);
                set_nonblocking(STDOUT_FILENO);
 diff --git a/options.c b/options.c
+index e7c6c61..d47cb7c 100644
 --- a/options.c
 +++ b/options.c
 @@ -92,6 +92,7 @@ int use_qsort = 0;
@@ -903,8 +922,8 @@ diff --git a/options.c b/options.c
 +char *db_config = NULL;
  int eol_nulls = 0;
  int protect_args = 0;
- int human_readable = 0;
-@@ -229,6 +230,7 @@ static void print_rsync_version(enum logcode f)
+ int human_readable = 1;
+@@ -566,6 +567,7 @@ static void print_rsync_version(enum logcode f)
        char const *links = "no ";
        char const *iconv = "no ";
        char const *ipv6 = "no ";
@@ -912,7 +931,7 @@ diff --git a/options.c b/options.c
        STRUCT_STAT *dumstat;
  
  #if SUBPROTOCOL_VERSION != 0
-@@ -262,6 +264,11 @@ static void print_rsync_version(enum logcode f)
+@@ -599,6 +601,11 @@ static void print_rsync_version(enum logcode f)
  #if defined HAVE_LUTIMES && defined HAVE_UTIMES
        symtimes = "";
  #endif
@@ -924,7 +943,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);
-@@ -275,8 +282,8 @@ static void print_rsync_version(enum logcode f)
+@@ -612,8 +619,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);
@@ -935,7 +954,7 @@ diff --git a/options.c b/options.c
  
  #ifdef MAINTAINER_MODE
        rprintf(f, "Panic Action: \"%s\"\n", get_panic_action());
-@@ -322,6 +329,7 @@ void usage(enum logcode F)
+@@ -661,6 +668,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");
@@ -943,7 +962,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");
-@@ -580,6 +588,7 @@ static struct poptOption long_options[] = {
+@@ -933,6 +941,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 },
@@ -952,19 +971,20 @@ diff --git a/options.c b/options.c
    {"compare-dest",     0,  POPT_ARG_STRING, 0, OPT_COMPARE_DEST, 0, 0 },
    {"copy-dest",        0,  POPT_ARG_STRING, 0, OPT_COPY_DEST, 0, 0 },
 diff --git a/pipe.c b/pipe.c
+index a33117c..2f6aa21 100644
 --- a/pipe.c
 +++ b/pipe.c
-@@ -26,6 +26,9 @@ extern int am_sender;
- extern int am_server;
+@@ -27,6 +27,9 @@ extern int am_server;
  extern int blocking_io;
  extern int filesfrom_fd;
+ extern int munge_symlinks;
 +extern int always_checksum;
 +extern int use_db;
 +extern char *db_config;
  extern mode_t orig_umask;
  extern char *logfile_name;
  extern int remote_option_cnt;
-@@ -141,6 +144,9 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
+@@ -143,6 +146,9 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
                        logfile_close();
                }
  
@@ -974,7 +994,7 @@ diff --git a/pipe.c b/pipe.c
                if (remote_option_cnt) {
                        int rc = remote_option_cnt + 1;
                        const char **rv = remote_options;
-@@ -148,6 +154,8 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
+@@ -150,6 +156,8 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
                                option_error();
                                exit_cleanup(RERR_SYNTAX);
                        }
@@ -984,9 +1004,10 @@ diff --git a/pipe.c b/pipe.c
  
                if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
 diff --git a/rsync.yo b/rsync.yo
+index 941f7a5..1b81189 100644
 --- a/rsync.yo
 +++ b/rsync.yo
-@@ -321,6 +321,7 @@ to the detailed description below for a complete description.  verb(
+@@ -323,6 +323,7 @@ to the detailed description below for a complete description.  verb(
   -q, --quiet                 suppress non-error messages
       --no-motd               suppress daemon-mode MOTD (see caveat)
   -c, --checksum              skip based on checksum, not mod-time & size
@@ -994,7 +1015,7 @@ diff --git a/rsync.yo b/rsync.yo
   -a, --archive               archive mode; equals -rlptgoD (no -H,-A,-X)
       --no-OPTION             turn off an implied OPTION (e.g. --no-D)
   -r, --recursive             recurse into directories
-@@ -537,6 +538,47 @@ checksum that is generated as the file is transferred, but that
+@@ -584,6 +585,47 @@ checksum that is generated as the file is transferred, but that
  automatic after-the-transfer verification has nothing to do with this
  option's before-the-transfer "Does this file need to be updated?" check.
  
@@ -1043,9 +1064,10 @@ diff --git a/rsync.yo b/rsync.yo
  way of saying you want recursion and want to preserve almost
  everything (with -H being a notable omission).
 diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo
+index d4978cd..68c588c 100644
 --- a/rsyncd.conf.yo
 +++ b/rsyncd.conf.yo
-@@ -270,6 +270,18 @@ is daemon.  This setting has no effect if the "log file" setting is a
+@@ -281,6 +281,18 @@ is daemon.  This setting has no effect if the "log file" setting is a
  non-empty string (either set in the per-modules settings, or inherited
  from the global settings).
  
@@ -1066,12 +1088,12 @@ diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo
  generate (since the information goes into the log file). The default is 1,
 diff --git a/support/rsyncdb b/support/rsyncdb
 new file mode 100755
+index 0000000..801068c
 --- /dev/null
 +++ b/support/rsyncdb
-@@ -0,0 +1,332 @@
-+#!/usr/bin/perl
+@@ -0,0 +1,331 @@
++#!/usr/bin/perl -w
 +use strict;
-+use warnings;
 +
 +use DBI;
 +use Getopt::Long;
index 2c84ed2..b90b7b5 100644 (file)
@@ -21,9 +21,10 @@ switches to --detect-moved blindly accepts the staged file.
 -- Matt McCutchen <hashproduct+rsync@gmail.com>
 
 diff --git a/generator.c b/generator.c
+index 35ba203..ac844ac 100644
 --- a/generator.c
 +++ b/generator.c
-@@ -200,7 +200,9 @@ static int fattr_find(struct file_struct *f, char *fname)
+@@ -469,7 +469,9 @@ static int fattr_find(struct file_struct *f, char *fname)
                                continue;
                        }
                }
@@ -34,7 +35,7 @@ diff --git a/generator.c b/generator.c
                diff = u_strcmp(fmid->basename, f->basename);
                if (diff == 0) {
                        good_match = mid;
-@@ -1988,6 +1990,21 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1796,6 +1798,21 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                fnamecmp = partialptr;
                fnamecmp_type = FNAMECMP_PARTIAL_DIR;
                statret = 0;
@@ -57,9 +58,10 @@ diff --git a/generator.c b/generator.c
  
        if (!do_xfers)
 diff --git a/options.c b/options.c
+index 7e454b3..1da38cb 100644
 --- a/options.c
 +++ b/options.c
-@@ -394,6 +394,8 @@ void usage(enum logcode F)
+@@ -744,6 +744,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 +70,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");
-@@ -581,7 +583,9 @@ static struct poptOption long_options[] = {
+@@ -939,7 +941,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 },
@@ -79,7 +81,7 @@ diff --git a/options.c b/options.c
    {"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 },
-@@ -1965,8 +1969,14 @@ void server_options(char **args, int *argc_p)
+@@ -2480,8 +2484,14 @@ void server_options(char **args, int *argc_p)
                        args[ac++] = "--super";
                if (size_only)
                        args[ac++] = "--size-only";
@@ -93,13 +95,14 @@ diff --git a/options.c b/options.c
 +                      else
 +                              args[ac++] = "--detect-moved";
 +              }
+               if (do_stats)
+                       args[ac++] = "--stats";
        } else {
-               if (skip_compress) {
-                       if (asprintf(&arg, "--skip-compress=%s", skip_compress) < 0)
 diff --git a/rsync.yo b/rsync.yo
+index 4df39b0..e254152 100644
 --- a/rsync.yo
 +++ b/rsync.yo
-@@ -390,6 +390,8 @@ to the detailed description below for a complete description.  verb(
+@@ -398,6 +398,8 @@ to the detailed description below for a complete description.  verb(
   -T, --temp-dir=DIR          create temporary files in directory DIR
   -y, --fuzzy                 find similar file for basis if no dest file
       --detect-renamed        try to find renamed files to speed the xfer
@@ -108,7 +111,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
-@@ -1507,6 +1509,17 @@ the bf(--partial-dir) option, that directory will be used instead.  These
+@@ -1621,6 +1623,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 b40b8fa..f85c1b6 100644 (file)
@@ -33,9 +33,10 @@ TODO:
   that could use it.
 
 diff --git a/compat.c b/compat.c
+index 6e00072..5fc9e37 100644
 --- a/compat.c
 +++ b/compat.c
-@@ -41,6 +41,7 @@ extern int checksum_seed;
+@@ -40,6 +40,7 @@ extern int checksum_seed;
  extern int basis_dir_cnt;
  extern int prune_empty_dirs;
  extern int protocol_version;
@@ -43,7 +44,7 @@ diff --git a/compat.c b/compat.c
  extern int protect_args;
  extern int preserve_uid;
  extern int preserve_gid;
-@@ -120,6 +121,7 @@ void set_allow_inc_recurse(void)
+@@ -119,6 +120,7 @@ void set_allow_inc_recurse(void)
                allow_inc_recurse = 0;
        else if (!am_sender
         && (delete_before || delete_after
@@ -51,7 +52,58 @@ diff --git a/compat.c b/compat.c
          || delay_updates || prune_empty_dirs))
                allow_inc_recurse = 0;
        else if (am_server && !local_server
+diff --git a/delete.c b/delete.c
+index 33fdd0e..6130a4c 100644
+--- a/delete.c
++++ b/delete.c
+@@ -25,6 +25,7 @@
+ extern int am_root;
+ extern int make_backups;
+ extern int max_delete;
++extern int detect_renamed;
+ extern char *backup_dir;
+ extern char *backup_suffix;
+ extern int backup_suffix_len;
+@@ -45,6 +46,8 @@ static inline int is_backup_file(char *fn)
+  * 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.)
++ *
++ * Note: --detect-rename may use this routine with DEL_NO_DELETIONS set!
+  */
+ static enum delret delete_dir_contents(char *fname, uint16 flags)
+ {
+@@ -64,7 +67,9 @@ static enum delret delete_dir_contents(char *fname, uint16 flags)
+       save_filters = push_local_filters(fname, dlen);
+       non_perishable_cnt = 0;
++      file_extra_cnt += SUM_EXTRA_CNT;
+       dirlist = get_dirlist(fname, dlen, 0);
++      file_extra_cnt -= SUM_EXTRA_CNT;
+       ret = non_perishable_cnt ? DR_NOT_EMPTY : DR_SUCCESS;
+       if (!dirlist->used)
+@@ -104,7 +109,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;
+-              }
++              } else if (detect_renamed && S_ISREG(fp->mode))
++                      look_for_rename(fp, fname);
+               if (delete_item(fname, fp->mode, flags) != DR_SUCCESS)
+                       ret = DR_NOT_EMPTY;
+       }
+@@ -127,6 +133,8 @@ static enum delret delete_dir_contents(char *fname, uint16 flags)
+  *
+  * Note that fbuf must point to a MAXPATHLEN buffer if the mode indicates it's
+  * a directory! (The buffer is used for recursion, but returned unchanged.)
++ *
++ * Also note: --detect-rename may use this routine with DEL_NO_DELETIONS set!
+  */
+ enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
+ {
 diff --git a/flist.c b/flist.c
+index 09b4fc5..929aa85 100644
 --- a/flist.c
 +++ b/flist.c
 @@ -63,6 +63,7 @@ extern int non_perishable_cnt;
@@ -62,7 +114,7 @@ diff --git a/flist.c b/flist.c
  extern int protocol_version;
  extern int sanitize_paths;
  extern int munge_symlinks;
-@@ -121,6 +122,8 @@ static int64 tmp_dev, tmp_ino;
+@@ -124,6 +125,8 @@ static int64 tmp_dev, tmp_ino;
  #endif
  static char tmp_sum[MAX_DIGEST_LEN];
  
@@ -70,8 +122,8 @@ 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;
-@@ -288,6 +291,45 @@ static int is_excluded(const char *fname, int is_dir, int filter_level)
+@@ -291,6 +294,45 @@ static int is_excluded(const char *fname, int is_dir, int filter_level)
        return 0;
  }
  
@@ -117,7 +169,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);
  
-@@ -2344,6 +2386,25 @@ struct file_list *recv_file_list(int f)
+@@ -2464,6 +2506,25 @@ struct file_list *recv_file_list(int f)
  
        flist_sort_and_clean(flist, relative_paths);
  
@@ -142,11 +194,12 @@ diff --git a/flist.c b/flist.c
 +
        if (protocol_version < 30) {
                /* Recv the io_error flag */
-               if (ignore_errors)
+               int err = read_int(f);
 diff --git a/generator.c b/generator.c
+index 12007a1..35ba203 100644
 --- a/generator.c
 +++ b/generator.c
-@@ -80,6 +80,7 @@ extern char *basis_dir[];
+@@ -81,6 +81,7 @@ extern char *partial_dir;
  extern int compare_dest;
  extern int copy_dest;
  extern int link_dest;
@@ -154,41 +207,141 @@ diff --git a/generator.c b/generator.c
  extern int whole_file;
  extern int list_only;
  extern int read_batch;
-@@ -98,6 +99,7 @@ extern char *backup_suffix;
- extern int backup_suffix_len;
+@@ -98,10 +99,12 @@ extern uid_t our_uid;
+ extern char *basis_dir[MAX_BASIS_DIRS+1];
  extern struct file_list *cur_flist, *first_flist, *dir_flist;
- extern struct filter_list_struct daemon_filter_list;
+ extern struct filter_list_struct filter_list, daemon_filter_list;
 +extern struct file_list the_fattr_list;
  
- int ignore_perishable = 0;
- int non_perishable_cnt = 0;
-@@ -105,6 +107,7 @@ int maybe_ATTRS_REPORT = 0;
+ int maybe_ATTRS_REPORT = 0;
  
  static dev_t dev_zero;
- static int deletion_count = 0; /* used to implement --max-delete */
 +static int unexplored_dirs = 1;
  static int deldelay_size = 0, deldelay_cnt = 0;
  static char *deldelay_buf = NULL;
  static int deldelay_fd = -1;
-@@ -115,7 +118,7 @@ static int need_retouch_dir_times;
- static int need_retouch_dir_perms;
- static const char *solo_file = NULL;
+@@ -181,6 +184,8 @@ static int remember_delete(struct file_struct *file, const char *fname, int flag
+               if (!flush_delete_delay())
+                       return 0;
+       }
++      if (flags & DEL_NO_DELETIONS)
++              return DR_SUCCESS;
  
--/* For calling delete_item() and delete_dir_contents(). */
-+/* For calling delete_item(), delete_dir_contents(), and delete_in_dir(). */
- #define DEL_NO_UID_WRITE      (1<<0) /* file/dir has our uid w/o write perm */
- #define DEL_RECURSE           (1<<1) /* if dir, delete all contents */
- #define DEL_DIR_IS_EMPTY      (1<<2) /* internal delete_FUNCTIONS use only */
-@@ -124,6 +127,7 @@ static const char *solo_file = NULL;
- #define DEL_FOR_SYMLINK       (1<<5) /* making room for a replacement symlink */
- #define DEL_FOR_DEVICE                (1<<6) /* making room for a replacement device */
- #define DEL_FOR_SPECIAL       (1<<7) /* making room for a replacement special */
-+#define DEL_NO_DELETIONS      (1<<9) /* just check for renames w/o deleting */
+       return 1;
+ }
+@@ -272,13 +277,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
+- * on exit). */
+-static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
++ * on exit).
++ *
++ * Note:  --detect-rename may use this routine with DEL_NO_DELETIONS set!
++ */
++static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev,
++                        int del_flags)
+ {
+       static int already_warned = 0;
+       struct file_list *dirlist;
+-      char delbuf[MAXPATHLEN];
+-      int dlen, i;
++      char *p, delbuf[MAXPATHLEN];
++      unsigned remainder;
++      int dlen, i, restore_dot = 0;
+       int save_uid_ndx = uid_ndx;
  
- #define DEL_MAKE_ROOM (DEL_FOR_FILE|DEL_FOR_DIR|DEL_FOR_SYMLINK|DEL_FOR_DEVICE|DEL_FOR_SPECIAL)
+       if (!fbuf) {
+@@ -293,17 +303,22 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
+               maybe_send_keepalive();
  
-@@ -148,11 +152,121 @@ static int is_backup_file(char *fn)
-       return k > 0 && strcmp(fn+k, backup_suffix) == 0;
+       if (io_error && !ignore_errors) {
+-              if (already_warned)
++              if (!already_warned) {
++                      rprintf(FINFO,
++                          "IO error encountered -- skipping file deletion\n");
++                      already_warned = 1;
++              }
++              if (!detect_renamed)
+                       return;
+-              rprintf(FINFO,
+-                      "IO error encountered -- skipping file deletion\n");
+-              already_warned = 1;
+-              return;
++              del_flags |= DEL_NO_DELETIONS;
+       }
+       dlen = strlen(fbuf);
+       change_local_filter_dir(fbuf, dlen, F_DEPTH(file));
++      if (detect_renamed)
++              unexplored_dirs--;
++
+       if (one_file_system) {
+               if (file->flags & FLAG_TOP_DIR)
+                       filesystem_dev = *fs_dev;
+@@ -316,6 +331,14 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
+       dirlist = get_dirlist(fbuf, dlen, 0);
++      p = fbuf + dlen;
++      if (dlen == 1 && *fbuf == '.') {
++              restore_dot = 1;
++              p = fbuf;
++      } else if (dlen != 1 || *fbuf != '/')
++              *p++ = '/';
++      remainder = MAXPATHLEN - (p - fbuf);
++
+       /* If an item in dirlist is not found in flist, delete it
+        * from the filesystem. */
+       for (i = dirlist->used; i--; ) {
+@@ -328,6 +351,10 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
+                                       f_name(fp, NULL));
+                       continue;
+               }
++              if (detect_renamed && S_ISREG(fp->mode)) {
++                      strlcpy(p, fp->basename, remainder);
++                      look_for_rename(fp, fbuf);
++              }
+               /* Here we want to match regardless of file type.  Replacement
+                * of a file with one of another type is handled separately by
+                * a delete_item call with a DEL_MAKE_ROOM flag. */
+@@ -336,14 +363,19 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
+                       if (!(fp->mode & S_IWUSR) && !am_root && (uid_t)F_OWNER(fp) == our_uid)
+                               flags |= DEL_NO_UID_WRITE;
+                       f_name(fp, delbuf);
+-                      if (delete_during == 2) {
+-                              if (!remember_delete(fp, delbuf, flags))
++                      if (delete_during == 2 && !(del_flags & DEL_NO_DELETIONS)) {
++                              if (!remember_delete(fp, delbuf, del_flags | flags))
+                                       break;
+                       } else
+-                              delete_item(delbuf, fp->mode, flags);
+-              }
++                              delete_item(delbuf, fp->mode, del_flags | flags);
++              } else if (detect_renamed && S_ISDIR(fp->mode))
++                      unexplored_dirs++;
+       }
++      if (restore_dot)
++              fbuf[0] = '.';
++      fbuf[dlen] = '\0';
++
+       flist_free(dirlist);
+       if (!save_uid_ndx) {
+@@ -381,14 +413,122 @@ static void do_delete_pass(void)
+                || !S_ISDIR(st.st_mode))
+                       continue;
+-              delete_in_dir(fbuf, file, &st.st_dev);
++              delete_in_dir(fbuf, file, &st.st_dev, 0);
+       }
+-      delete_in_dir(NULL, NULL, &dev_zero);
++      delete_in_dir(NULL, NULL, &dev_zero, 0);
+       if (INFO_GTE(FLIST, 2) && !am_server)
+               rprintf(FINFO, "                    \r");
  }
  
 +/* Search for a regular file that matches either (1) the size & modified
@@ -266,7 +419,7 @@ diff --git a/generator.c b/generator.c
 +      return good_match >= 0 ? good_match : ok_match;
 +}
 +
-+static void look_for_rename(struct file_struct *file, char *fname)
++void look_for_rename(struct file_struct *file, char *fname)
 +{
 +      struct file_struct *fp;
 +      char *partialptr, *fn;
@@ -295,172 +448,14 @@ diff --git a/generator.c b/generator.c
 +      }
 +
 +      /* I think this falls into the -vv category with "%s is uptodate", etc. */
-+      if (verbose > 1)
++      if (INFO_GTE(MISC, 2))
 +              rprintf(FINFO, "found renamed: %s => %s\n", fname, fn);
 +}
 +
- /* Delete a file or directory.  If DEL_RECURSE is set in the flags, this will
-  * delete recursively.
-  *
-  * Note that fbuf must point to a MAXPATHLEN buffer if the mode indicates it's
-  * a directory! (The buffer is used for recursion, but returned unchanged.)
-+ *
-+ * Also note: --detect-rename may use this routine with DEL_NO_DELETIONS set!
-  */
- 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. */
-       }
-+      if (flags & DEL_NO_DELETIONS)
-+              return DR_SUCCESS;
-       if (!(flags & DEL_MAKE_ROOM) && max_delete >= 0 && ++deletion_count > max_delete)
-               return DR_AT_LIMIT;
-@@ -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.)
-+ *
-+ * Note: --detect-rename may use this routine with DEL_NO_DELETIONS set!
-  */
- 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;
-+      file_extra_cnt += SUM_EXTRA_CNT;
-       dirlist = get_dirlist(fname, dlen, 0);
-+      file_extra_cnt -= SUM_EXTRA_CNT;
-       ret = non_perishable_cnt ? DR_NOT_EMPTY : DR_SUCCESS;
-       if (!dirlist->used)
-@@ -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;
--              }
-+              } else if (detect_renamed && S_ISREG(fp->mode))
-+                      look_for_rename(fp, fname);
-               if (delete_item(fname, fp->mode, flags) != DR_SUCCESS)
-                       ret = DR_NOT_EMPTY;
-       }
-@@ -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
-- * on exit). */
--static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
-+ * on exit).
-+ *
-+ * Note:  --detect-rename may use this routine with DEL_NO_DELETIONS set!
-+ */
-+static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev,
-+                        int del_flags)
+ int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
  {
-       static int already_warned = 0;
-       struct file_list *dirlist;
--      char delbuf[MAXPATHLEN];
--      int dlen, i;
-+      char *p, delbuf[MAXPATHLEN];
-+      unsigned remainder;
-+      int dlen, i, restore_dot = 0;
-       int save_uid_ndx = uid_ndx;
-       if (!fbuf) {
-@@ -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) {
--              if (already_warned)
-+              if (!already_warned) {
-+                      rprintf(FINFO,
-+                          "IO error encountered -- skipping file deletion\n");
-+                      already_warned = 1;
-+              }
-+              if (!detect_renamed)
-                       return;
--              rprintf(FINFO,
--                      "IO error encountered -- skipping file deletion\n");
--              already_warned = 1;
--              return;
-+              del_flags |= DEL_NO_DELETIONS;
-       }
-       dlen = strlen(fbuf);
-       change_local_filter_dir(fbuf, dlen, F_DEPTH(file));
-+      if (detect_renamed)
-+              unexplored_dirs--;
-+
-       if (one_file_system) {
-               if (file->flags & FLAG_TOP_DIR)
-                       filesystem_dev = *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);
-+      p = fbuf + dlen;
-+      if (dlen == 1 && *fbuf == '.') {
-+              restore_dot = 1;
-+              p = fbuf;
-+      } else if (dlen != 1 || *fbuf != '/')
-+              *p++ = '/';
-+      remainder = MAXPATHLEN - (p - fbuf);
-+
-       /* If an item in dirlist is not found in flist, delete it
-        * from the filesystem. */
-       for (i = dirlist->used; i--; ) {
-@@ -521,6 +660,10 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
-                                       f_name(fp, NULL));
-                       continue;
-               }
-+              if (detect_renamed && S_ISREG(fp->mode)) {
-+                      strlcpy(p, fp->basename, remainder);
-+                      look_for_rename(fp, fbuf);
-+              }
-               /* Here we want to match regardless of file type.  Replacement
-                * of a file with one of another type is handled separately by
-                * a delete_item call with a DEL_MAKE_ROOM flag. */
-@@ -529,14 +672,19 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
-                       if (!(fp->mode & S_IWUSR) && !am_root && (uid_t)F_OWNER(fp) == our_uid)
-                               flags |= DEL_NO_UID_WRITE;
-                       f_name(fp, delbuf);
--                      if (delete_during == 2) {
--                              if (!remember_delete(fp, delbuf, flags))
-+                      if (delete_during == 2 && !(del_flags & DEL_NO_DELETIONS)) {
-+                              if (!remember_delete(fp, delbuf, del_flags | flags))
-                                       break;
-                       } else
--                              delete_item(delbuf, fp->mode, flags);
--              }
-+                              delete_item(delbuf, fp->mode, del_flags | flags);
-+              } else if (detect_renamed && S_ISDIR(fp->mode))
-+                      unexplored_dirs++;
-       }
-+      if (restore_dot)
-+              fbuf[0] = '.';
-+      fbuf[dlen] = '\0';
-+
-       flist_free(dirlist);
-       if (!save_uid_ndx) {
-@@ -574,9 +722,9 @@ static void do_delete_pass(void)
-                || !S_ISDIR(st.st_mode))
-                       continue;
--              delete_in_dir(fbuf, file, &st.st_dev);
-+              delete_in_dir(fbuf, file, &st.st_dev, 0);
-       }
--      delete_in_dir(NULL, NULL, &dev_zero);
-+      delete_in_dir(NULL, NULL, &dev_zero, 0);
-       if (do_progress && !am_server)
-               rprintf(FINFO, "                    \r");
-@@ -1229,6 +1377,7 @@ static void list_file_entry(struct file_struct *f)
+ #if !defined HAVE_LUTIMES || !defined HAVE_UTIMES
+@@ -1042,6 +1182,7 @@ static void list_file_entry(struct file_struct *f)
        }
  }
  
@@ -468,7 +463,7 @@ diff --git a/generator.c b/generator.c
  static int phase = 0;
  static int dflt_perms;
  
-@@ -1505,9 +1654,12 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1321,9 +1462,12 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                }
                else if (delete_during && f_out != -1 && !phase
                    && !(file->flags & FLAG_MISSING_DIR)) {
@@ -484,7 +479,7 @@ diff --git a/generator.c b/generator.c
                                change_local_filter_dir(fname, strlen(fname), F_DEPTH(file));
                }
                goto cleanup;
-@@ -1785,8 +1937,14 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1601,8 +1745,14 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                        goto cleanup;
                }
  #endif
@@ -500,8 +495,8 @@ diff --git a/generator.c b/generator.c
                rsyserr(FERROR_XFER, stat_errno, "recv_generator: failed to stat %s",
                        full_fname(fname));
                goto cleanup;
-@@ -2187,6 +2345,12 @@ void generate_files(int f_out, const char *local_name)
-       if (verbose > 2)
+@@ -2003,6 +2153,12 @@ void generate_files(int f_out, const char *local_name)
+       if (DEBUG_GTE(GENR, 1))
                rprintf(FINFO, "generator starting pid=%ld\n", (long)getpid());
  
 +      if (detect_renamed) {
@@ -513,16 +508,16 @@ diff --git a/generator.c b/generator.c
        if (delete_before && !solo_file && cur_flist->used > 0)
                do_delete_pass();
        if (delete_during == 2) {
-@@ -2197,7 +2361,7 @@ void generate_files(int f_out, const char *local_name)
+@@ -2013,7 +2169,7 @@ void generate_files(int f_out, const char *local_name)
        }
-       do_progress = 0;
+       info_levels[INFO_FLIST] = info_levels[INFO_PROGRESS] = 0;
  
 -      if (append_mode > 0 || whole_file < 0)
 +      if (append_mode > 0 || detect_renamed || whole_file < 0)
                whole_file = 0;
-       if (verbose >= 2) {
+       if (DEBUG_GTE(FLIST, 1)) {
                rprintf(FINFO, "delta-transmission %s\n",
-@@ -2239,7 +2403,7 @@ void generate_files(int f_out, const char *local_name)
+@@ -2055,7 +2211,7 @@ void generate_files(int f_out, const char *local_name)
                                                dirdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
                                        } else
                                                dirdev = MAKEDEV(0, 0);
@@ -531,8 +526,8 @@ diff --git a/generator.c b/generator.c
                                } else
                                        change_local_filter_dir(fbuf, strlen(fbuf), F_DEPTH(fp));
                        }
-@@ -2289,7 +2453,21 @@ void generate_files(int f_out, const char *local_name)
-               write_ndx(f_out, NDX_DONE);
+@@ -2102,7 +2258,21 @@ void generate_files(int f_out, const char *local_name)
+       } while ((cur_flist = cur_flist->next) != NULL);
  
        if (delete_during)
 -              delete_in_dir(NULL, NULL, &dev_zero);
@@ -552,20 +547,21 @@ diff --git a/generator.c b/generator.c
 +              }
 +      }
        phase++;
-       if (verbose > 2)
+       if (DEBUG_GTE(GENR, 1))
                rprintf(FINFO, "generate_files phase=%d\n", phase);
 diff --git a/options.c b/options.c
+index e7c6c61..7e454b3 100644
 --- a/options.c
 +++ b/options.c
-@@ -82,6 +82,7 @@ int am_generator = 0;
+@@ -80,6 +80,7 @@ int am_server = 0;
+ int am_sender = 0;
  int am_starting_up = 1;
  int relative_paths = -1;
- int implied_dirs = 1;
 +int detect_renamed = 0;
+ int implied_dirs = 1;
+ int missing_args = 0; /* 0 = FERROR_XFER, 1 = ignore, 2 = delete */
  int numeric_ids = 0;
- int allow_8bit_chars = 0;
- int force_delete = 0;
-@@ -392,6 +393,7 @@ void usage(enum logcode F)
+@@ -742,6 +743,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");
@@ -573,7 +569,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");
-@@ -579,6 +581,7 @@ static struct poptOption long_options[] = {
+@@ -937,6 +939,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 },
@@ -581,7 +577,7 @@ diff --git a/options.c b/options.c
    {"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 },
-@@ -1591,7 +1594,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+@@ -2105,7 +2108,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                inplace = 1;
        }
  
@@ -590,7 +586,7 @@ diff --git a/options.c b/options.c
                partial_dir = tmp_partialdir;
  
        if (inplace) {
-@@ -1600,6 +1603,7 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+@@ -2114,6 +2117,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",
@@ -598,19 +594,41 @@ diff --git a/options.c b/options.c
                                 delay_updates ? "delay-updates" : "partial-dir");
                        return 0;
                }
-@@ -1961,6 +1965,8 @@ void server_options(char **args, int *argc_p)
+@@ -2476,6 +2480,8 @@ void server_options(char **args, int *argc_p)
                        args[ac++] = "--super";
                if (size_only)
                        args[ac++] = "--size-only";
 +              if (detect_renamed)
 +                      args[ac++] = "--detect-renamed";
+               if (do_stats)
+                       args[ac++] = "--stats";
        } else {
-               if (skip_compress) {
-                       if (asprintf(&arg, "--skip-compress=%s", skip_compress) < 0)
+diff --git a/rsync.h b/rsync.h
+index be7cf8a..278e282 100644
+--- a/rsync.h
++++ b/rsync.h
+@@ -242,7 +242,7 @@ enum msgcode {
+ #define NDX_DEL_STATS -2
+ #define NDX_FLIST_OFFSET -101
+-/* For calling delete_item() and delete_dir_contents(). */
++/* For calling delete_item(), delete_dir_contents(), and delete_in_dir(). */
+ #define DEL_NO_UID_WRITE      (1<<0) /* file/dir has our uid w/o write perm */
+ #define DEL_RECURSE           (1<<1) /* if dir, delete all contents */
+ #define DEL_DIR_IS_EMPTY      (1<<2) /* internal delete_FUNCTIONS use only */
+@@ -252,6 +252,7 @@ enum msgcode {
+ #define DEL_FOR_DEVICE                (1<<6) /* making room for a replacement device */
+ #define DEL_FOR_SPECIAL       (1<<7) /* making room for a replacement special */
+ #define DEL_FOR_BACKUP                (1<<8) /* the delete is for a backup operation */
++#define DEL_NO_DELETIONS      (1<<9) /* just check for renames w/o deleting */
+ #define DEL_MAKE_ROOM (DEL_FOR_FILE|DEL_FOR_DIR|DEL_FOR_SYMLINK|DEL_FOR_DEVICE|DEL_FOR_SPECIAL)
 diff --git a/rsync.yo b/rsync.yo
+index 941f7a5..4df39b0 100644
 --- a/rsync.yo
 +++ b/rsync.yo
-@@ -389,6 +389,7 @@ to the detailed description below for a complete description.  verb(
+@@ -397,6 +397,7 @@ to the detailed description below for a complete description.  verb(
       --modify-window=NUM     compare mod-times with reduced accuracy
   -T, --temp-dir=DIR          create temporary files in directory DIR
   -y, --fuzzy                 find similar file for basis if no dest file
@@ -618,7 +636,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
-@@ -1491,6 +1492,21 @@ Note that the use of the bf(--delete) option might get rid of any potential
+@@ -1605,6 +1606,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.
  
@@ -641,10 +659,11 @@ diff --git a/rsync.yo b/rsync.yo
  the destination machine as an additional hierarchy to compare destination
  files against doing transfers (if the files are missing in the destination
 diff --git a/util.c b/util.c
+index 0cafed6..7e5c71f 100644
 --- a/util.c
 +++ b/util.c
-@@ -1168,6 +1168,32 @@ int handle_partial_dir(const char *fname, int create)
-       return 1;
+@@ -1064,6 +1064,32 @@ char *normalize_path(char *path, BOOL force_newbuf, unsigned int *len_ptr)
+       return path;
  }
  
 +/* We need to supply our own strcmp function for file list comparisons
@@ -674,5 +693,5 @@ diff --git a/util.c b/util.c
 +}
 +
  /**
-  * Determine if a symlink points outside the current directory tree.
-  * This is considered "unsafe" because e.g. when mirroring somebody
+  * Return a quoted string with the full pathname of the indicated filename.
+  * The string " (in MODNAME)" may also be appended.  The returned pointer
index 5e8ea06..fae61b1 100644 (file)
@@ -8,23 +8,24 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/generator.c b/generator.c
+index 12007a1..f326030 100644
 --- a/generator.c
 +++ b/generator.c
-@@ -55,6 +55,7 @@ extern int ignore_errors;
+@@ -56,6 +56,7 @@ extern int ignore_errors;
  extern int remove_source_files;
  extern int delay_updates;
  extern int update_only;
 +extern int downdate_only;
+ extern int human_readable;
  extern int ignore_existing;
  extern int ignore_non_existing;
- extern int inplace;
-@@ -1726,6 +1727,13 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1542,6 +1543,13 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                goto cleanup;
        }
  
 +      if (downdate_only && statret == 0
 +          && cmp_time(sx.st.st_mtime, file->modtime) < 0) {
-+              if (verbose > 1)
++              if (INFO_GTE(SKIP, 1))
 +                      rprintf(FINFO, "%s is older\n", fname);
 +              return;
 +      }
@@ -32,7 +33,7 @@ diff --git a/generator.c b/generator.c
        fnamecmp = fname;
        fnamecmp_type = FNAMECMP_FNAME;
  
-@@ -2097,6 +2105,7 @@ void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
+@@ -1913,6 +1921,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 +41,7 @@ diff --git a/generator.c b/generator.c
                        always_checksum = -always_checksum;
                        size_only = -size_only;
                        append_mode = -append_mode;
-@@ -2122,6 +2131,7 @@ void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
+@@ -1938,6 +1947,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;
@@ -49,6 +50,7 @@ diff --git a/generator.c b/generator.c
                        size_only = -size_only;
                        append_mode = -append_mode;
 diff --git a/options.c b/options.c
+index e7c6c61..371d72f 100644
 --- a/options.c
 +++ b/options.c
 @@ -60,6 +60,7 @@ int preserve_uid = 0;
@@ -59,7 +61,7 @@ diff --git a/options.c b/options.c
  int cvs_exclude = 0;
  int dry_run = 0;
  int do_xfers = 1;
-@@ -327,6 +328,7 @@ void usage(enum logcode F)
+@@ -670,6 +671,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 +69,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");
-@@ -535,6 +537,7 @@ static struct poptOption long_options[] = {
+@@ -891,6 +893,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 },
diff --git a/dparam.diff b/dparam.diff
deleted file mode 100644 (file)
index 95f920f..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-This patch adds a daemon option, --dparam (-M), that lets you override
-global/default items in the config file when starting the daemon up.
-
-To use this patch, run these commands for a successful build:
-
-    patch -p1 <patches/dparam.diff
-    ./configure                               (optional if already run)
-    make
-
-diff --git a/clientserver.c b/clientserver.c
---- a/clientserver.c
-+++ b/clientserver.c
-@@ -1045,6 +1045,7 @@ int daemon_main(void)
-               fprintf(stderr, "Failed to parse config file: %s\n", config_file);
-               exit_cleanup(RERR_SYNTAX);
-       }
-+      set_dparams(0);
-       if (no_detach)
-               create_pid_file();
-diff --git a/loadparm.c b/loadparm.c
---- a/loadparm.c
-+++ b/loadparm.c
-@@ -51,6 +51,9 @@
- #include "rsync.h"
- #include "ifuncs.h"
-+
-+extern item_list dparam_list;
-+
- #define PTR_DIFF(p1,p2) ((ptrdiff_t)(((char *)(p1)) - (char *)(p2)))
- #define strequal(a,b) (strcasecmp(a,b)==0)
- #define BOOLSTR(b) ((b) ? "Yes" : "No")
-@@ -780,8 +783,11 @@ static BOOL do_section(char *sectionname)
-    bRetval = False;
-    /* if we were in a global section then do the local inits */
--   if (bInGlobalSection && !isglobal)
-+   if (bInGlobalSection && !isglobal) {
-+     if (!iNumServices)
-+      set_dparams(0);
-      init_locals();
-+   }
-    /* if we've just struck a global section, note the fact. */
-    bInGlobalSection = isglobal;
-@@ -844,6 +850,29 @@ BOOL lp_load(char *pszFname, int globals_only)
-       return (bRetval);
- }
-+BOOL set_dparams(int syntax_check_only)
-+{
-+      char *equal, *val, **params = dparam_list.items;
-+      unsigned j;
-+
-+      for (j = 0; j < dparam_list.count; j++) {
-+              equal = strchr(params[j], '='); /* options.c verified this */
-+              *equal = '\0';
-+              if (syntax_check_only) {
-+                      if (map_parameter(params[j]) < 0) {
-+                              rprintf(FCLIENT, "Unknown parameter \"%s\"\n", params[j]);
-+                              *equal = '=';
-+                              return False;
-+                      }
-+              } else {
-+                      for (val = equal+1; isSpace(val); val++) {}
-+                      do_parameter(params[j], val);
-+              }
-+              *equal = '=';
-+      }
-+
-+      return True;
-+}
- /***************************************************************************
- * return the max number of services
-diff --git a/options.c b/options.c
---- a/options.c
-+++ b/options.c
-@@ -124,6 +124,7 @@ int inplace = 0;
- int delay_updates = 0;
- long block_size = 0; /* "long" because popt can't set an int32. */
- char *skip_compress = NULL;
-+item_list dparam_list = EMPTY_ITEM_LIST;
- /** Network address family. **/
- int default_af_hint
-@@ -653,6 +654,7 @@ static struct poptOption long_options[] = {
-   /* 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 },
-+  {"dparam",           0,  POPT_ARG_STRING, 0, OPT_DAEMON, 0, 0 },
-   {"detach",           0,  POPT_ARG_NONE,   0, OPT_DAEMON, 0, 0 },
-   {"no-detach",        0,  POPT_ARG_NONE,   0, OPT_DAEMON, 0, 0 },
-   {0,0,0,0, 0, 0, 0}
-@@ -667,6 +669,7 @@ static void daemon_usage(enum logcode F)
-   rprintf(F,"     --address=ADDRESS       bind to the specified address\n");
-   rprintf(F,"     --bwlimit=KBPS          limit I/O bandwidth; KBytes per second\n");
-   rprintf(F,"     --config=FILE           specify alternate rsyncd.conf file\n");
-+  rprintf(F," -M, --dparam=OVERRIDE       override global daemon config parameter\n");
-   rprintf(F,"     --no-detach             do not detach from the parent\n");
-   rprintf(F,"     --port=PORT             listen on alternate port number\n");
-   rprintf(F,"     --log-file=FILE         override the \"log file\" setting\n");
-@@ -688,6 +691,7 @@ static struct poptOption long_daemon_options[] = {
-   {"bwlimit",          0,  POPT_ARG_INT,    &daemon_bwlimit, 0, 0, 0 },
-   {"config",           0,  POPT_ARG_STRING, &config_file, 0, 0, 0 },
-   {"daemon",           0,  POPT_ARG_NONE,   &daemon_opt, 0, 0, 0 },
-+  {"dparam",          'M', POPT_ARG_STRING, 0, 'M', 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 },
-   {"detach",           0,  POPT_ARG_VAL,    &no_detach, 0, 0, 0 },
-@@ -971,11 +975,24 @@ int parse_arguments(int *argc_p, const char ***argv_p)
-                       pc = poptGetContext(RSYNC_NAME, argc, argv,
-                                           long_daemon_options, 0);
-                       while ((opt = poptGetNextOpt(pc)) != -1) {
-+                              char **cpp;
-                               switch (opt) {
-                               case 'h':
-                                       daemon_usage(FINFO);
-                                       exit_cleanup(0);
-+                              case 'M':
-+                                      arg = poptGetOptArg(pc);
-+                                      if (!strchr(arg, '=')) {
-+                                              rprintf(FERROR,
-+                                                  "--dparam value is missing an '=': %s\n",
-+                                                  arg);
-+                                              goto daemon_error;
-+                                      }
-+                                      cpp = EXPAND_ITEM_LIST(&dparam_list, char *, 4);
-+                                      *cpp = strdup(arg);
-+                                      break;
-+
-                               case 'v':
-                                       verbose++;
-                                       break;
-@@ -989,6 +1006,9 @@ int parse_arguments(int *argc_p, const char ***argv_p)
-                               }
-                       }
-+                      if (dparam_list.count && !set_dparams(1))
-+                              exit_cleanup(RERR_SYNTAX);
-+
-                       if (tmpdir && strlen(tmpdir) >= MAXPATHLEN - 10) {
-                               snprintf(err_buf, sizeof err_buf,
-                                        "the --temp-dir path is WAY too long.\n");
-diff --git a/rsync.yo b/rsync.yo
---- a/rsync.yo
-+++ b/rsync.yo
-@@ -439,6 +439,7 @@ accepted: verb(
-      --address=ADDRESS       bind to the specified address
-      --bwlimit=KBPS          limit I/O bandwidth; KBytes per second
-      --config=FILE           specify alternate rsyncd.conf file
-+ -M, --dparam=OVERRIDE       override global daemon config parameter
-      --no-detach             do not detach from the parent
-      --port=PORT             listen on alternate port number
-      --log-file=FILE         override the "log file" setting
-@@ -2147,6 +2148,14 @@ The default is /etc/rsyncd.conf unless the daemon is running over
- a remote shell program and the remote user is not the super-user; in that case
- the default is rsyncd.conf in the current directory (typically $HOME).
-+dit(bf(-M, --dparam=OVERRIDE)) This option can be used to set a daemon-config
-+parameter when starting up rsync in daemon mode.  It is equivalent to adding
-+the parameter at the end of the global settings prior to the first module's
-+definition.  The parameter names can be specified without spaces, if you so
-+desire.  For instance:
-+
-+verb(    rsync --daemon -M pidfile=/path/rsync.pid )
-+
- dit(bf(--no-detach)) When running as a daemon, this option instructs
- rsync to not detach itself and become a background process.  This
- option is required when running as a service on Cygwin, and may also
-diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo
---- a/rsyncd.conf.yo
-+++ b/rsyncd.conf.yo
-@@ -83,10 +83,14 @@ dit(bf(motd file)) This parameter allows you to specify a
- "message of the day" to display to clients on each connect. This
- usually contains site information and any legal notices. The default
- is no motd file.
-+This can be overridden by the bf(--dparam=motdfile=FILE)
-+command-line option when starting the daemon.
- dit(bf(pid file)) This parameter tells the rsync daemon to write
- its process ID to that file.  If the file already exists, the rsync
- daemon will abort rather than overwrite the file.
-+This can be overridden by the bf(--dparam=pidfile=FILE)
-+command-line option when starting the daemon.
- dit(bf(port)) You can override the default port the daemon will listen on
- by specifying this value (defaults to 873).  This is ignored if the daemon
-@@ -260,6 +264,12 @@ If the daemon fails to open the specified file, it will fall back to
- using syslog and output an error about the failure.  (Note that the
- failure to open the specified log file used to be a fatal error.)
-+This setting can be overridden by using the bf(--log-file=FILE) or
-+bf(--dparam=logfile=FILE) command-line options.  The former overrides
-+all the log-file parameters of the daemon and all module settings.
-+The latter sets the daemon's log file and the default for all the
-+modules, which still allows modules to override the default setting.
-+
- dit(bf(syslog facility)) This parameter allows you to
- specify the syslog facility name to use when logging messages from the
- rsync daemon. You may use any standard syslog facility name which is
index fcb15a9..be0f9eb 100644 (file)
@@ -63,12 +63,19 @@ Changes:
 * pass --drop-cache on to the remote server
 * make test works now
 
+To use this patch, run these commands for a successful build:
+
+    patch -p1 <patches/drop-cache.diff
+    ./configure                         (optional if already run)
+    make
+
 diff --git a/checksum.c b/checksum.c
+index 811b5b6..f1f51cb 100644
 --- a/checksum.c
 +++ b/checksum.c
-@@ -26,6 +26,10 @@ extern int protocol_version;
- int csum_length = SHORT_SUM_LENGTH; /* initial value */
+@@ -24,6 +24,10 @@
+ extern int checksum_seed;
+ extern int protocol_version;
  
 +#ifdef HAVE_POSIX_FADVISE64
 +#define close(fd) fadv_close(fd)
@@ -78,9 +85,10 @@ diff --git a/checksum.c b/checksum.c
    a simple 32 bit checksum that can be upadted from either end
    (inspired by Mark Adler's Adler-32 checksum)
 diff --git a/cleanup.c b/cleanup.c
+index 19ef072..84a6cf3 100644
 --- a/cleanup.c
 +++ b/cleanup.c
-@@ -46,7 +46,13 @@ void close_all(void)
+@@ -47,7 +47,13 @@ void close_all(void)
        int fd;
        int ret;
        STRUCT_STAT st;
@@ -95,21 +103,23 @@ diff --git a/cleanup.c b/cleanup.c
        for (fd = max_fd; fd >= 0; fd--) {
                if ((ret = do_fstat(fd, &st)) == 0) {
 diff --git a/configure.in b/configure.in
+index bc7d4a7..e9ff45a 100644
 --- a/configure.in
 +++ b/configure.in
-@@ -554,7 +554,7 @@ AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
-     strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
+@@ -553,7 +553,7 @@ AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
      setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \
      strerror putenv iconv_open locale_charset nl_langinfo getxattr \
--    extattr_get_link sigaction sigprocmask setattrlist)
-+    extattr_get_link sigaction sigprocmask setattrlist posix_fadvise64)
+     extattr_get_link sigaction sigprocmask setattrlist getgrouplist \
+-    initgroups)
++    initgroups posix_fadvise64)
  
  dnl cygwin iconv.h defines iconv_open as libiconv_open
  if test x"$ac_cv_func_iconv_open" != x"yes"; then
 diff --git a/fileio.c b/fileio.c
+index 0faa619..0326fe8 100644
 --- a/fileio.c
 +++ b/fileio.c
-@@ -30,6 +30,12 @@ extern int sparse_files;
+@@ -31,6 +31,12 @@ extern int sparse_files;
  static char last_byte;
  static OFF_T sparse_seek = 0;
  
@@ -123,9 +133,10 @@ diff --git a/fileio.c b/fileio.c
  {
        int ret;
 diff --git a/generator.c b/generator.c
+index 12007a1..f0c7a91 100644
 --- a/generator.c
 +++ b/generator.c
-@@ -115,6 +115,10 @@ static int need_retouch_dir_times;
+@@ -112,6 +112,10 @@ static int need_retouch_dir_times;
  static int need_retouch_dir_perms;
  static const char *solo_file = NULL;
  
@@ -133,10 +144,11 @@ diff --git a/generator.c b/generator.c
 +#define close(fd) fadv_close(fd)
 +#endif
 +
- /* For calling delete_item() and delete_dir_contents(). */
- #define DEL_NO_UID_WRITE      (1<<0) /* file/dir has our uid w/o write perm */
- #define DEL_RECURSE           (1<<1) /* if dir, delete all contents */
+ enum nonregtype {
+     TYPE_DIR, TYPE_SPECIAL, TYPE_DEVICE, TYPE_SYMLINK
+ };
 diff --git a/options.c b/options.c
+index e7c6c61..ce55d8e 100644
 --- a/options.c
 +++ b/options.c
 @@ -60,6 +60,7 @@ int preserve_uid = 0;
@@ -147,7 +159,7 @@ diff --git a/options.c b/options.c
  int cvs_exclude = 0;
  int dry_run = 0;
  int do_xfers = 1;
-@@ -327,6 +328,9 @@ void usage(enum logcode F)
+@@ -670,6 +671,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 +169,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");
-@@ -535,6 +539,9 @@ static struct poptOption long_options[] = {
+@@ -891,6 +895,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 +179,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 },
-@@ -1720,6 +1727,11 @@ void server_options(char **args, int *argc_p)
+@@ -2235,6 +2242,11 @@ void server_options(char **args, int *argc_p)
        if (!am_sender)
                args[ac++] = "--sender";
  
@@ -180,9 +192,10 @@ diff --git a/options.c b/options.c
        argstr[0] = '-';
  
 diff --git a/receiver.c b/receiver.c
+index 4325e30..a3da64e 100644
 --- a/receiver.c
 +++ b/receiver.c
-@@ -63,6 +63,10 @@ static flist_ndx_list batch_redo_list;
+@@ -64,6 +64,10 @@ static flist_ndx_list batch_redo_list;
  /* We're either updating the basis file or an identical copy: */
  static int updating_basis_or_equiv;
  
@@ -194,9 +207,10 @@ diff --git a/receiver.c b/receiver.c
   * get_tmpname() - create a tmp filename for a given filename
   *
 diff --git a/rsync.yo b/rsync.yo
+index 941f7a5..512aa6b 100644
 --- a/rsync.yo
 +++ b/rsync.yo
-@@ -356,6 +356,7 @@ to the detailed description below for a complete description.  verb(
+@@ -359,6 +359,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
@@ -204,7 +218,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
-@@ -1053,6 +1054,10 @@ NOTE: Don't use this option when the destination is a Solaris "tmpfs"
+@@ -1120,6 +1121,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.
  
@@ -216,9 +230,10 @@ diff --git a/rsync.yo b/rsync.yo
  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
 diff --git a/sender.c b/sender.c
+index bf8221d..9e23dbb 100644
 --- a/sender.c
 +++ b/sender.c
-@@ -46,6 +46,10 @@ extern int write_batch;
+@@ -45,6 +45,10 @@ extern int write_batch;
  extern struct stats stats;
  extern struct file_list *cur_flist, *first_flist, *dir_flist;
  
@@ -230,27 +245,29 @@ diff --git a/sender.c b/sender.c
   * @file
   *
 diff --git a/t_unsafe.c b/t_unsafe.c
+index 9ba0aaa..3cb55e9 100644
 --- a/t_unsafe.c
 +++ b/t_unsafe.c
-@@ -28,6 +28,7 @@ int am_root = 0;
+@@ -27,6 +27,7 @@ int dry_run = 0;
+ int am_root = 0;
  int read_only = 0;
  int list_only = 0;
- int verbose = 0;
 +int drop_cache = 0;
+ int human_readable = 0;
  int preserve_perms = 0;
  int preserve_executability = 0;
 diff --git a/util.c b/util.c
+index 0cafed6..06d8770 100644
 --- a/util.c
 +++ b/util.c
-@@ -26,6 +26,7 @@
- extern int verbose;
+@@ -27,6 +27,7 @@
  extern int dry_run;
  extern int module_id;
 +extern int drop_cache;
  extern int modify_window;
  extern int relative_paths;
- extern int human_readable;
+ extern int preserve_xattrs;
 @@ -42,6 +43,131 @@ char curr_dir[MAXPATHLEN];
  unsigned int curr_dir_len;
  int curr_dir_depth; /* This is only set for a sanitizing daemon. */
index 97f30e3..39a3895 100644 (file)
@@ -9,9 +9,10 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/Makefile.in b/Makefile.in
+index feacb90..cd4cf2d 100644
 --- a/Makefile.in
 +++ b/Makefile.in
-@@ -42,7 +42,7 @@ popt_OBJS=popt/findme.o  popt/popt.o  popt/poptconfig.o \
+@@ -43,7 +43,7 @@ popt_OBJS=popt/findme.o  popt/popt.o  popt/poptconfig.o \
        popt/popthelp.o popt/poptparse.o
  OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@
  
@@ -20,7 +21,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) \
-@@ -107,7 +107,7 @@ getgroups$(EXEEXT): getgroups.o
+@@ -108,7 +108,7 @@ getgroups$(EXEEXT): getgroups.o
  getfsdev$(EXEEXT): getfsdev.o
        $(CC) $(CFLAGS) $(LDFLAGS) -o $@ getfsdev.o $(LIBS)
  
@@ -30,9 +31,10 @@ diff --git a/Makefile.in b/Makefile.in
        $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(TRIMSLASH_OBJ) $(LIBS)
  
 diff --git a/compat.c b/compat.c
+index 6e00072..ef1882d 100644
 --- a/compat.c
 +++ b/compat.c
-@@ -41,9 +41,11 @@ extern int checksum_seed;
+@@ -40,9 +40,11 @@ extern int checksum_seed;
  extern int basis_dir_cnt;
  extern int prune_empty_dirs;
  extern int protocol_version;
@@ -44,7 +46,7 @@ diff --git a/compat.c b/compat.c
  extern int preserve_acls;
  extern int preserve_xattrs;
  extern int need_messages_from_generator;
-@@ -61,7 +63,7 @@ extern char *iconv_opt;
+@@ -60,7 +62,7 @@ extern char *iconv_opt;
  #endif
  
  /* These index values are for the file-list's extra-attribute array. */
@@ -53,7 +55,7 @@ diff --git a/compat.c b/compat.c
  
  int receiver_symlink_times = 0; /* receiver can set the time on a symlink */
  int sender_symlink_iconv = 0; /* sender should convert symlink content */
-@@ -137,6 +139,8 @@ void setup_protocol(int f_out,int f_in)
+@@ -136,6 +138,8 @@ void setup_protocol(int f_out,int f_in)
                uid_ndx = ++file_extra_cnt;
        if (preserve_gid)
                gid_ndx = ++file_extra_cnt;
@@ -63,29 +65,80 @@ diff --git a/compat.c b/compat.c
                acls_ndx = ++file_extra_cnt;
        if (preserve_xattrs)
 diff --git a/configure.in b/configure.in
+index bc7d4a7..8709fa4 100644
 --- a/configure.in
 +++ b/configure.in
 @@ -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 \
-+    chflags strerror putenv iconv_open locale_charset nl_langinfo getxattr \
-     extattr_get_link sigaction sigprocmask setattrlist)
+     strerror putenv iconv_open locale_charset nl_langinfo getxattr \
+     extattr_get_link sigaction sigprocmask setattrlist getgrouplist \
+-    initgroups)
++    initgroups chflags)
  
  dnl cygwin iconv.h defines iconv_open as libiconv_open
+ if test x"$ac_cv_func_iconv_open" != x"yes"; then
+diff --git a/delete.c b/delete.c
+index 33fdd0e..1c0df57 100644
+--- a/delete.c
++++ b/delete.c
+@@ -25,6 +25,7 @@
+ extern int am_root;
+ extern int make_backups;
+ extern int max_delete;
++extern int force_change;
+ extern char *backup_dir;
+ extern char *backup_suffix;
+ extern int backup_suffix_len;
+@@ -98,8 +99,12 @@ static enum delret delete_dir_contents(char *fname, uint16 flags)
+               }
+               strlcpy(p, fp->basename, remainder);
++#ifdef SUPPORT_FORCE_CHANGE
++              if (force_change)
++                      make_mutable(fname, fp->mode, F_FFLAGS(fp), force_change);
++#endif
+               if (!(fp->mode & S_IWUSR) && !am_root && (uid_t)F_OWNER(fp) == our_uid)
+-                      do_chmod(fname, fp->mode | S_IWUSR);
++                      do_chmod(fname, fp->mode | S_IWUSR, NO_FFLAGS);
+               /* Save stack by recursing to ourself directly. */
+               if (S_ISDIR(fp->mode)) {
+                       if (delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS)
+@@ -140,7 +145,7 @@ enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
+       }
+       if (flags & DEL_NO_UID_WRITE)
+-              do_chmod(fbuf, mode | S_IWUSR);
++              do_chmod(fbuf, mode | S_IWUSR, NO_FFLAGS);
+       if (S_ISDIR(mode) && !(flags & DEL_DIR_IS_EMPTY)) {
+               int save_uid_ndx = uid_ndx;
+@@ -148,6 +153,13 @@ 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;
++#ifdef SUPPORT_FORCE_CHANGE
++              if (force_change) {
++                      STRUCT_STAT st;
++                      if (x_lstat(fbuf, &st, NULL) == 0)
++                              make_mutable(fbuf, st.st_mode, st.st_flags, force_change);
++              }
++#endif
+               ignore_perishable = 1;
+               /* If DEL_RECURSE is not set, this just reports emptiness. */
+               ret = delete_dir_contents(fbuf, flags);
 diff --git a/flist.c b/flist.c
+index 09b4fc5..e1d01be 100644
 --- a/flist.c
 +++ b/flist.c
-@@ -52,6 +52,7 @@ extern int preserve_links;
+@@ -51,6 +51,7 @@ extern int preserve_links;
  extern int preserve_hard_links;
  extern int preserve_devices;
  extern int preserve_specials;
 +extern int preserve_fileflags;
+ extern int missing_args;
  extern int uid_ndx;
  extern int gid_ndx;
- extern int eol_nulls;
-@@ -395,6 +396,9 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
+@@ -398,6 +399,9 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
  {
        static time_t modtime;
        static mode_t mode;
@@ -95,7 +148,7 @@ diff --git a/flist.c b/flist.c
  #ifdef SUPPORT_HARD_LINKS
        static int64 dev;
  #endif
-@@ -424,6 +428,14 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
+@@ -441,6 +445,14 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
                xflags |= XMIT_SAME_MODE;
        else
                mode = file->mode;
@@ -110,7 +163,7 @@ diff --git a/flist.c b/flist.c
  
        if ((preserve_devices && IS_DEVICE(mode))
         || (preserve_specials && IS_SPECIAL(mode))) {
-@@ -538,6 +550,10 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
+@@ -568,6 +580,10 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
        }
        if (!(xflags & XMIT_SAME_MODE))
                write_int(f, to_wire_mode(mode));
@@ -121,7 +174,7 @@ diff --git a/flist.c b/flist.c
        if (preserve_uid && !(xflags & XMIT_SAME_UID)) {
                if (protocol_version < 30)
                        write_int(f, uid);
-@@ -624,6 +640,9 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+@@ -656,6 +672,9 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
  {
        static int64 modtime;
        static mode_t mode;
@@ -131,9 +184,9 @@ diff --git a/flist.c b/flist.c
  #ifdef SUPPORT_HARD_LINKS
        static int64 dev;
  #endif
-@@ -759,6 +778,10 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+@@ -796,6 +815,10 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
  
-       if (chmod_modes && !S_ISLNK(mode))
+       if (chmod_modes && !S_ISLNK(mode) && mode)
                mode = tweak_mode(mode, chmod_modes);
 +#ifdef SUPPORT_FILEFLAGS
 +      if (preserve_fileflags && !(xflags & XMIT_SAME_FLAGS))
@@ -142,7 +195,7 @@ diff --git a/flist.c b/flist.c
  
        if (preserve_uid && !(xflags & XMIT_SAME_UID)) {
                if (protocol_version < 30)
-@@ -899,6 +922,10 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+@@ -936,6 +959,10 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
        }
  #endif
        file->mode = mode;
@@ -153,7 +206,7 @@ diff --git a/flist.c b/flist.c
        if (preserve_uid)
                F_OWNER(file) = uid;
        if (preserve_gid) {
-@@ -1273,6 +1300,10 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1323,6 +1350,10 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
        }
  #endif
        file->mode = st.st_mode;
@@ -164,15 +217,16 @@ diff --git a/flist.c b/flist.c
        if (uid_ndx) /* Check uid_ndx instead of preserve_uid for del support */
                F_OWNER(file) = st.st_uid;
        if (gid_ndx) /* Check gid_ndx instead of preserve_gid for del support */
-@@ -1408,6 +1439,7 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
+@@ -1466,6 +1497,7 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
  #endif
  #ifdef SUPPORT_XATTRS
                if (preserve_xattrs) {
 +                      sx.st.st_mode = file->mode;
-                       sx.xattr = NULL;
                        if (get_xattr(fname, &sx) < 0) {
                                io_error |= IOERR_GENERAL;
+                               return NULL;
 diff --git a/generator.c b/generator.c
+index 12007a1..eee42e8 100644
 --- a/generator.c
 +++ b/generator.c
 @@ -42,8 +42,10 @@ extern int preserve_devices;
@@ -186,44 +240,7 @@ diff --git a/generator.c b/generator.c
  extern int uid_ndx;
  extern int gid_ndx;
  extern int delete_mode;
-@@ -166,7 +168,7 @@ static enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
-       }
-       if (flags & DEL_NO_UID_WRITE)
--              do_chmod(fbuf, mode | S_IWUSR);
-+              do_chmod(fbuf, mode | S_IWUSR, NO_FFLAGS);
-       if (S_ISDIR(mode) && !(flags & DEL_DIR_IS_EMPTY)) {
-               int save_uid_ndx = uid_ndx;
-@@ -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;
-+#ifdef SUPPORT_FORCE_CHANGE
-+              if (force_change) {
-+                      STRUCT_STAT st;
-+                      if (x_lstat(fbuf, &st, NULL) == 0)
-+                              make_mutable(fbuf, st.st_mode, st.st_flags, force_change);
-+              }
-+#endif
-               ignore_perishable = 1;
-               /* If DEL_RECURSE is not set, this just reports emptiness. */
-               ret = delete_dir_contents(fbuf, flags);
-@@ -294,8 +303,12 @@ static enum delret delete_dir_contents(char *fname, uint16 flags)
-               }
-               strlcpy(p, fp->basename, remainder);
-+#ifdef SUPPORT_FORCE_CHANGE
-+              if (force_change)
-+                      make_mutable(fname, fp->mode, F_FFLAGS(fp), force_change);
-+#endif
-               if (!(fp->mode & S_IWUSR) && !am_root && (uid_t)F_OWNER(fp) == our_uid)
--                      do_chmod(fname, fp->mode | S_IWUSR);
-+                      do_chmod(fname, fp->mode | S_IWUSR, NO_FFLAGS);
-               /* Save stack by recursing to ourself directly. */
-               if (S_ISDIR(fp->mode)) {
-                       if (delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS)
-@@ -599,6 +612,11 @@ int unchanged_attrs(const char *fname, struct file_struct *file, stat_x *sxp)
+@@ -406,6 +408,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;
  
@@ -235,7 +252,7 @@ diff --git a/generator.c b/generator.c
        if (am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file))
                return 0;
  
-@@ -664,6 +682,11 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+@@ -471,6 +478,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;
@@ -247,7 +264,7 @@ diff --git a/generator.c b/generator.c
  #ifdef SUPPORT_ACLS
                if (preserve_acls && !S_ISLNK(file->mode)) {
                        if (!ACL_READY(*sxp))
-@@ -1442,6 +1465,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1258,6 +1270,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);
                }
@@ -258,7 +275,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);
-@@ -1482,10 +1509,15 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1298,10 +1314,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. */
@@ -275,7 +292,7 @@ diff --git a/generator.c b/generator.c
                                rsyserr(FERROR_XFER, errno,
                                        "failed to modify permissions on %s",
                                        full_fname(fname));
-@@ -1520,6 +1552,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1336,6 +1357,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);
        }
@@ -286,7 +303,7 @@ diff --git a/generator.c b/generator.c
  
  #ifdef SUPPORT_HARD_LINKS
        if (preserve_hard_links && F_HLINK_NOT_FIRST(file)
-@@ -2054,13 +2090,17 @@ static void touch_up_dirs(struct file_list *flist, int ndx)
+@@ -1870,13 +1895,17 @@ static void touch_up_dirs(struct file_list *flist, int ndx)
                        continue;
                fname = f_name(file, NULL);
                if (!(file->mode & S_IWUSR))
@@ -307,9 +324,10 @@ diff --git a/generator.c b/generator.c
                        if (allowed_lull)
                                maybe_send_keepalive();
 diff --git a/log.c b/log.c
+index a687375..83948b1 100644
 --- a/log.c
 +++ b/log.c
-@@ -660,7 +660,7 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
+@@ -715,7 +715,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';
@@ -319,6 +337,7 @@ diff --git a/log.c b/log.c
                        c[10] = !(iflags & ITEM_REPORT_XATTR) ? '.' : 'x';
                        c[11] = '\0';
 diff --git a/options.c b/options.c
+index e7c6c61..ae3d2d0 100644
 --- a/options.c
 +++ b/options.c
 @@ -53,6 +53,7 @@ int preserve_hard_links = 0;
@@ -329,15 +348,15 @@ diff --git a/options.c b/options.c
  int preserve_executability = 0;
  int preserve_devices = 0;
  int preserve_specials = 0;
-@@ -85,6 +86,7 @@ int implied_dirs = 1;
- int numeric_ids = 0;
+@@ -86,6 +87,7 @@ int numeric_ids = 0;
+ int msgs2stderr = 0;
  int allow_8bit_chars = 0;
  int force_delete = 0;
 +int force_change = 0;
  int io_timeout = 0;
- int allowed_lull = 0;
  int prune_empty_dirs = 0;
-@@ -225,6 +227,7 @@ static void print_rsync_version(enum logcode f)
+ int use_qsort = 0;
+@@ -566,6 +568,7 @@ static void print_rsync_version(enum logcode f)
        char const *links = "no ";
        char const *iconv = "no ";
        char const *ipv6 = "no ";
@@ -345,7 +364,7 @@ diff --git a/options.c b/options.c
        STRUCT_STAT *dumstat;
  
  #if SUBPROTOCOL_VERSION != 0
-@@ -258,6 +261,9 @@ static void print_rsync_version(enum logcode f)
+@@ -599,6 +602,9 @@ static void print_rsync_version(enum logcode f)
  #if defined HAVE_LUTIMES && defined HAVE_UTIMES
        symtimes = "";
  #endif
@@ -355,7 +374,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);
-@@ -271,8 +277,8 @@ static void print_rsync_version(enum logcode f)
+@@ -612,8 +618,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);
@@ -366,7 +385,7 @@ diff --git a/options.c b/options.c
  
  #ifdef MAINTAINER_MODE
        rprintf(f, "Panic Action: \"%s\"\n", get_panic_action());
-@@ -339,6 +345,9 @@ void usage(enum logcode F)
+@@ -683,6 +689,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");
@@ -376,9 +395,9 @@ 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
-@@ -376,7 +385,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");
+@@ -722,7 +731,12 @@ void usage(enum logcode F)
+   rprintf(F,"     --ignore-missing-args   ignore missing source args without error\n");
+   rprintf(F,"     --delete-missing-args   delete missing source args from destination\n");
    rprintf(F,"     --ignore-errors         delete even if there are I/O errors\n");
 -  rprintf(F,"     --force                 force deletion of directories even if not empty\n");
 +  rprintf(F,"     --force-delete          force deletion of directories even if not empty\n");
@@ -390,7 +409,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");
-@@ -481,6 +495,10 @@ static struct poptOption long_options[] = {
+@@ -835,6 +849,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 },
@@ -401,7 +420,7 @@ 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 },
-@@ -559,6 +577,14 @@ static struct poptOption long_options[] = {
+@@ -917,6 +935,14 @@ static struct poptOption long_options[] = {
    {"remove-source-files",0,POPT_ARG_VAL,    &remove_source_files, 1, 0, 0 },
    {"force",            0,  POPT_ARG_VAL,    &force_delete, 1, 0, 0 },
    {"no-force",         0,  POPT_ARG_VAL,    &force_delete, 0, 0, 0 },
@@ -416,7 +435,7 @@ diff --git a/options.c b/options.c
    {"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 },
-@@ -1868,6 +1894,9 @@ void server_options(char **args, int *argc_p)
+@@ -2383,6 +2409,9 @@ void server_options(char **args, int *argc_p)
        if (xfer_dirs && !recurse && delete_mode && am_sender)
                args[ac++] = "--no-r";
  
@@ -426,7 +445,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;
-@@ -1955,6 +1984,16 @@ void server_options(char **args, int *argc_p)
+@@ -2470,6 +2499,16 @@ void server_options(char **args, int *argc_p)
                        args[ac++] = "--delete-excluded";
                if (force_delete)
                        args[ac++] = "--force";
@@ -444,9 +463,10 @@ diff --git a/options.c b/options.c
                        args[ac++] = "--only-write-batch=X";
                if (am_root > 1)
 diff --git a/rsync.c b/rsync.c
+index 2c026a2..3188535 100644
 --- a/rsync.c
 +++ b/rsync.c
-@@ -32,6 +32,7 @@ extern int dry_run;
+@@ -31,6 +31,7 @@ extern int dry_run;
  extern int preserve_acls;
  extern int preserve_xattrs;
  extern int preserve_perms;
@@ -454,7 +474,7 @@ diff --git a/rsync.c b/rsync.c
  extern int preserve_executability;
  extern int preserve_times;
  extern int am_root;
-@@ -377,6 +378,39 @@ mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int dflt_perms,
+@@ -378,6 +379,39 @@ mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int dflt_perms,
        return new_mode;
  }
  
@@ -494,7 +514,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)
  {
-@@ -430,7 +464,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
+@@ -426,7 +460,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) {
@@ -503,7 +523,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));
-@@ -466,7 +500,8 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
+@@ -462,7 +496,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,
@@ -513,7 +533,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",
-@@ -498,7 +533,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
+@@ -494,7 +529,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)) {
@@ -522,7 +542,7 @@ diff --git a/rsync.c b/rsync.c
                if (ret < 0) {
                        rsyserr(FERROR_XFER, errno,
                                "failed to set permissions on %s",
-@@ -510,6 +545,19 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
+@@ -506,6 +541,19 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
        }
  #endif
  
@@ -539,10 +559,10 @@ diff --git a/rsync.c b/rsync.c
 +      }
 +#endif
 +
-       if (verbose > 1 && flags & ATTRS_REPORT) {
+       if (INFO_GTE(NAME, 2) && flags & ATTRS_REPORT) {
                if (updated)
                        rprintf(FCLIENT, "%s\n", fname);
-@@ -573,7 +621,8 @@ int finish_transfer(const char *fname, const char *fnametmp,
+@@ -570,7 +618,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,
@@ -551,8 +571,8 @@ diff --git a/rsync.c b/rsync.c
 +                     | (ok_to_set_time ? 0 : ATTRS_SKIP_MTIME));
  
        /* move tmp file over real file */
-       if (verbose > 2)
-@@ -592,6 +641,10 @@ int finish_transfer(const char *fname, const char *fnametmp,
+       if (DEBUG_GTE(RECV, 1))
+@@ -589,6 +638,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. */
@@ -564,17 +584,18 @@ diff --git a/rsync.c b/rsync.c
        }
        /* The file was copied, so tweak the perms of the copied file.  If it
 diff --git a/rsync.h b/rsync.h
+index be7cf8a..16820fd 100644
 --- a/rsync.h
 +++ b/rsync.h
-@@ -60,6 +60,7 @@
- #define XMIT_RDEV_MINOR_8_pre30 (1<<11)       /* protocols 28 - 29  */
+@@ -61,6 +61,7 @@
  #define XMIT_GROUP_NAME_FOLLOWS (1<<11) /* protocols 30 - now */
  #define XMIT_HLINK_FIRST (1<<12)      /* protocols 30 - now (HLINKED files only) */
+ #define XMIT_IO_ERROR_ENDLIST (1<<12) /* protocols 31 - now (w/XMIT_EXTENDED_FLAGS) */
 +#define XMIT_SAME_FLAGS (1<<14)               /* protocols ?? - now */
  
  /* These flags are used in the live flist data. */
  
-@@ -154,6 +155,7 @@
+@@ -155,6 +156,7 @@
  
  #define ATTRS_REPORT          (1<<0)
  #define ATTRS_SKIP_MTIME      (1<<1)
@@ -582,7 +603,7 @@ diff --git a/rsync.h b/rsync.h
  
  #define FULL_FLUSH    1
  #define NORMAL_FLUSH  0
-@@ -180,6 +182,7 @@
+@@ -181,6 +183,7 @@
  #define ITEM_REPORT_GROUP (1<<6)
  #define ITEM_REPORT_ACL (1<<7)
  #define ITEM_REPORT_XATTR (1<<8)
@@ -590,7 +611,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)
-@@ -462,6 +465,28 @@ typedef unsigned int size_t;
+@@ -482,6 +485,28 @@ typedef unsigned int size_t;
  #endif
  #endif
  
@@ -619,7 +640,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. */
-@@ -632,6 +657,7 @@ extern int file_extra_cnt;
+@@ -652,6 +677,7 @@ extern int file_extra_cnt;
  extern int inc_recurse;
  extern int uid_ndx;
  extern int gid_ndx;
@@ -627,7 +648,7 @@ diff --git a/rsync.h b/rsync.h
  extern int acls_ndx;
  extern int xattrs_ndx;
  
-@@ -669,6 +695,11 @@ extern int xattrs_ndx;
+@@ -689,6 +715,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
@@ -640,9 +661,10 @@ diff --git a/rsync.h b/rsync.h
  #define F_XATTR(f) REQ_EXTRA(f, xattrs_ndx)->num
  #define F_NDX(f) REQ_EXTRA(f, unsort_ndx)->num
 diff --git a/rsync.yo b/rsync.yo
+index 941f7a5..7b41d5f 100644
 --- a/rsync.yo
 +++ b/rsync.yo
-@@ -342,6 +342,7 @@ to the detailed description below for a complete description.  verb(
+@@ -345,6 +345,7 @@ to the detailed description below for a complete description.  verb(
   -K, --keep-dirlinks         treat symlinked dir on receiver as dir
   -H, --hard-links            preserve hard links
   -p, --perms                 preserve permissions
@@ -650,9 +672,9 @@ diff --git a/rsync.yo b/rsync.yo
   -E, --executability         preserve executability
       --chmod=CHMOD           affect file and/or directory permissions
   -A, --acls                  preserve ACLs (implies -p)
-@@ -373,7 +374,10 @@ to the detailed description below for a complete description.  verb(
-      --delete-after          receiver deletes after transfer, not before
-      --delete-excluded       also delete excluded files from dest dirs
+@@ -378,7 +379,10 @@ to the detailed description below for a complete description.  verb(
+      --ignore-missing-args   ignore missing source args without error
+      --delete-missing-args   delete missing source args from destination
       --ignore-errors         delete even if there are I/O errors
 -     --force                 force deletion of dirs even if not empty
 +     --force-delete          force deletion of dirs even if not empty
@@ -662,7 +684,7 @@ diff --git a/rsync.yo b/rsync.yo
       --max-delete=NUM        don't delete more than NUM files
       --max-size=SIZE         don't transfer any file larger than SIZE
       --min-size=SIZE         don't transfer any file smaller than SIZE
-@@ -544,7 +548,8 @@ specified, in which case bf(-r) is not implied.
+@@ -592,7 +596,8 @@ specified, in which case bf(-r) is not implied.
  
  Note that bf(-a) bf(does not preserve hardlinks), because
  finding multiply-linked files is expensive.  You must separately
@@ -672,7 +694,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-":
-@@ -802,7 +807,7 @@ they would be using bf(--copy-links).
+@@ -869,7 +874,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
@@ -681,7 +703,7 @@ diff --git a/rsync.yo b/rsync.yo
  
  See also bf(--keep-dirlinks) for an analogous option for the receiving
  side.
-@@ -939,6 +944,29 @@ super-user copies all namespaces except system.*.  A normal user only copies
+@@ -1006,6 +1011,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.
  
@@ -711,7 +733,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
-@@ -1201,12 +1229,13 @@ See bf(--delete) (which is implied) for more details on file-deletion.
+@@ -1285,12 +1313,13 @@ display as a "*missing" entry in the bf(--list-only) output.
  dit(bf(--ignore-errors)) Tells bf(--delete) to go ahead and delete files
  even when there are I/O errors.
  
@@ -728,7 +750,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
-@@ -1667,7 +1696,7 @@ with older versions of rsync, but that also turns on the output of other
+@@ -1832,7 +1861,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
@@ -737,7 +759,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.
-@@ -1723,7 +1752,7 @@ quote(itemization(
+@@ -1888,7 +1917,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).
@@ -747,6 +769,7 @@ diff --git a/rsync.yo b/rsync.yo
    it() The bf(x) means that the extended attribute information changed.
  ))
 diff --git a/syscall.c b/syscall.c
+index cfabc3e..45604b1 100644
 --- a/syscall.c
 +++ b/syscall.c
 @@ -33,6 +33,7 @@ extern int dry_run;
@@ -941,16 +964,17 @@ diff --git a/syscall.c b/syscall.c
  
  void trim_trailing_slashes(char *name)
 diff --git a/t_stub.c b/t_stub.c
+index 02cfa69..9228d0c 100644
 --- a/t_stub.c
 +++ b/t_stub.c
-@@ -26,6 +26,7 @@ int module_id = -1;
+@@ -25,6 +25,7 @@ int modify_window = 0;
+ int module_id = -1;
  int relative_paths = 0;
- int human_readable = 0;
  int module_dirlen = 0;
 +int force_change = 0;
  int preserve_xattrs = 0;
  mode_t orig_umask = 002;
- char *partial_dir;
+ char number_separator = ',';
 @@ -89,3 +90,23 @@ struct filter_list_struct daemon_filter_list;
  {
        return "tester";
@@ -976,16 +1000,17 @@ diff --git a/t_stub.c b/t_stub.c
 +}
 +#endif
 diff --git a/util.c b/util.c
+index 0cafed6..ed26a05 100644
 --- a/util.c
 +++ b/util.c
-@@ -29,6 +29,7 @@ extern int module_id;
+@@ -30,6 +30,7 @@ extern int module_id;
  extern int modify_window;
  extern int relative_paths;
- extern int human_readable;
-+extern int force_change;
  extern int preserve_xattrs;
++extern int force_change;
  extern char *module_dir;
  extern unsigned int module_dirlen;
+ extern mode_t orig_umask;
 @@ -123,7 +124,7 @@ NORETURN void overflow_exit(const char *str)
        exit_cleanup(RERR_MALLOC);
  }
@@ -1047,9 +1072,10 @@ diff --git a/util.c b/util.c
  }
  
 diff --git a/xattrs.c b/xattrs.c
+index 2d0e050..5d04599 100644
 --- a/xattrs.c
 +++ b/xattrs.c
-@@ -281,6 +281,10 @@ int get_xattr(const char *fname, stat_x *sxp)
+@@ -282,6 +282,10 @@ int get_xattr(const char *fname, stat_x *sxp)
  {
        sxp->xattr = new(item_list);
        *sxp->xattr = empty_xattr;
@@ -1060,7 +1086,7 @@ diff --git a/xattrs.c b/xattrs.c
        if (rsync_xal_get(fname, sxp->xattr) < 0) {
                free_xattr(sxp);
                return -1;
-@@ -864,6 +868,11 @@ int set_xattr(const char *fname, const struct file_struct *file,
+@@ -865,6 +869,11 @@ int set_xattr(const char *fname, const struct file_struct *file,
                return -1;
        }
  
@@ -1072,7 +1098,7 @@ diff --git a/xattrs.c b/xattrs.c
        ndx = F_XATTR(file);
        return rsync_xal_set(fname, lst + ndx, fnamecmp, sxp);
  }
-@@ -980,7 +989,7 @@ int set_stat_xattr(const char *fname, struct file_struct *file, mode_t new_mode)
+@@ -981,7 +990,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 1cfee20..98bfafa 100644 (file)
@@ -8,6 +8,7 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/options.c b/options.c
+index e7c6c61..44ad60e 100644
 --- a/options.c
 +++ b/options.c
 @@ -48,6 +48,7 @@ int append_mode = 0;
@@ -18,15 +19,15 @@ diff --git a/options.c b/options.c
  int preserve_links = 0;
  int preserve_hard_links = 0;
  int preserve_acls = 0;
-@@ -384,6 +385,7 @@ void usage(enum logcode F)
+@@ -730,6 +731,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");
 +  rprintf(F,"     --fsync                 fsync every written file\n");
    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");
-@@ -627,6 +629,7 @@ static struct poptOption long_options[] = {
+   rprintf(F,"     --usermap=STRING        custom username mapping\n");
+   rprintf(F,"     --groupmap=STRING       custom groupname mapping\n");
+@@ -988,6 +990,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 },
@@ -34,7 +35,7 @@ diff --git a/options.c b/options.c
    {"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 },
-@@ -2019,6 +2022,9 @@ void server_options(char **args, int *argc_p)
+@@ -2555,6 +2558,9 @@ void server_options(char **args, int *argc_p)
                        args[ac++] = tmpdir;
                }
  
@@ -45,9 +46,10 @@ diff --git a/options.c b/options.c
                        /* the server only needs this option if it is not the sender,
                         *   and it may be an older version that doesn't know this
 diff --git a/receiver.c b/receiver.c
+index 4325e30..1523977 100644
 --- a/receiver.c
 +++ b/receiver.c
-@@ -39,6 +39,7 @@ extern int relative_paths;
+@@ -38,6 +38,7 @@ extern int relative_paths;
  extern int preserve_hard_links;
  extern int preserve_perms;
  extern int preserve_xattrs;
@@ -55,9 +57,9 @@ diff --git a/receiver.c b/receiver.c
  extern int basis_dir_cnt;
  extern int make_backups;
  extern int cleanup_got_literal;
-@@ -302,6 +303,12 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
-               exit_cleanup(RERR_FILEIO);
-       }
+@@ -305,6 +306,12 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
+       if (sum_end(file_sum1) != checksum_len)
+               overflow_exit("checksum_len"); /* Impossible... */
  
 +      if (do_fsync && fd != -1 && fsync(fd) != 0) {
 +              rsyserr(FERROR, errno, "fsync failed on %s",
@@ -65,10 +67,11 @@ diff --git a/receiver.c b/receiver.c
 +              exit_cleanup(RERR_FILEIO);
 +      }
 +
-       sum_len = sum_end(file_sum1);
        if (mapbuf)
+               unmap_file(mapbuf);
 diff --git a/t_stub.c b/t_stub.c
+index 02cfa69..fb61480 100644
 --- a/t_stub.c
 +++ b/t_stub.c
 @@ -21,6 +21,7 @@
@@ -80,16 +83,17 @@ diff --git a/t_stub.c b/t_stub.c
  int module_id = -1;
  int relative_paths = 0;
 diff --git a/util.c b/util.c
+index 0cafed6..88b3521 100644
 --- a/util.c
 +++ b/util.c
-@@ -26,6 +26,7 @@
- extern int verbose;
+@@ -27,6 +27,7 @@
  extern int dry_run;
  extern int module_id;
 +extern int do_fsync;
  extern int modify_window;
  extern int relative_paths;
- extern int human_readable;
+ extern int preserve_xattrs;
 @@ -334,6 +335,13 @@ int copy_file(const char *source, const char *dest, int ofd,
                        full_fname(source));
        }
index 332a44a..65ee9c1 100644 (file)
@@ -13,6 +13,7 @@ TODO:
    --iconv setting when converting case.
 
 diff --git a/exclude.c b/exclude.c
+index 5fa6e00..5b3b135 100644
 --- a/exclude.c
 +++ b/exclude.c
 @@ -21,6 +21,7 @@
@@ -21,9 +22,9 @@ diff --git a/exclude.c b/exclude.c
  #include "rsync.h"
 +#include "ifuncs.h"
  
- extern int verbose;
  extern int am_server;
-@@ -605,16 +606,15 @@ static int rule_matches(const char *fname, struct filter_struct *ex, int name_is
+ extern int am_sender;
+@@ -697,16 +698,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) {
@@ -45,17 +46,18 @@ diff --git a/exclude.c b/exclude.c
  
        return !ret_match;
 diff --git a/flist.c b/flist.c
+index 09b4fc5..ae70300 100644
 --- a/flist.c
 +++ b/flist.c
-@@ -35,6 +35,7 @@ extern int inc_recurse;
- extern int do_progress;
+@@ -34,6 +34,7 @@ extern int am_generator;
+ extern int inc_recurse;
  extern int always_checksum;
  extern int module_id;
 +extern int ignore_case;
  extern int ignore_errors;
  extern int numeric_ids;
  extern int recurse;
-@@ -2803,6 +2804,7 @@ int f_name_cmp(const struct file_struct *f1, const struct file_struct *f2)
+@@ -2924,6 +2925,7 @@ int f_name_cmp(const struct file_struct *f1, const struct file_struct *f2)
  {
        int dif;
        const uchar *c1, *c2;
@@ -63,7 +65,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;
-@@ -2913,7 +2915,15 @@ int f_name_cmp(const struct file_struct *f1, const struct file_struct *f2)
+@@ -3034,7 +3036,15 @@ int f_name_cmp(const struct file_struct *f1, const struct file_struct *f2)
                        if (type1 != type2)
                                return type1 == t_PATH ? 1 : -1;
                }
@@ -81,11 +83,12 @@ diff --git a/flist.c b/flist.c
        return dif;
  }
 diff --git a/ifuncs.h b/ifuncs.h
+index 8c128d5..a4cfd3d 100644
 --- a/ifuncs.h
 +++ b/ifuncs.h
-@@ -108,3 +108,38 @@ toUpper(const char *ptr)
- {
-       return toupper(*(unsigned char *)ptr);
+@@ -77,3 +77,38 @@ init_stat_x(stat_x *sx_p)
+       sx_p->xattr = NULL;
+ #endif
  }
 +
 +static inline int
@@ -123,6 +126,7 @@ diff --git a/ifuncs.h b/ifuncs.h
 +#define ic_strNE(s1,s2) (!ic_strEQ(s1,s2))
 +#define ic_strnNE(s1,s2) (!ic_strnEQ(s1,s2,n))
 diff --git a/lib/wildmatch.c b/lib/wildmatch.c
+index f3a1731..72660ca 100644
 --- a/lib/wildmatch.c
 +++ b/lib/wildmatch.c
 @@ -53,6 +53,8 @@
@@ -209,9 +213,10 @@ diff --git a/lib/wildmatch.c b/lib/wildmatch.c
  }
  
 diff --git a/options.c b/options.c
+index e7c6c61..6e73e9c 100644
 --- a/options.c
 +++ b/options.c
-@@ -118,6 +118,7 @@ OFF_T max_size = 0;
+@@ -117,6 +117,7 @@ OFF_T max_size = 0;
  OFF_T min_size = 0;
  int ignore_errors = 0;
  int modify_window = 0;
@@ -219,7 +224,7 @@ diff --git a/options.c b/options.c
  int blocking_io = -1;
  int checksum_seed = 0;
  int inplace = 0;
-@@ -409,6 +410,7 @@ void usage(enum logcode F)
+@@ -759,6 +760,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 +232,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");
-@@ -615,6 +617,8 @@ static struct poptOption long_options[] = {
+@@ -973,6 +975,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 +241,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},
-@@ -1981,6 +1985,9 @@ void server_options(char **args, int *argc_p)
+@@ -2505,6 +2509,9 @@ void server_options(char **args, int *argc_p)
                args[ac++] = arg;
        }
  
@@ -247,9 +252,10 @@ diff --git a/options.c b/options.c
                if (partial_dir != tmp_partialdir) {
                        args[ac++] = "--partial-dir";
 diff --git a/rsync.yo b/rsync.yo
+index 941f7a5..339aca8 100644
 --- a/rsync.yo
 +++ b/rsync.yo
-@@ -406,6 +406,7 @@ to the detailed description below for a complete description.  verb(
+@@ -414,6 +414,7 @@ to the detailed description below for a complete description.  verb(
       --files-from=FILE       read list of source-file names from FILE
   -0, --from0                 all *from/filter files are delimited by 0s
   -s, --protect-args          no space-splitting; wildcard chars only
@@ -257,7 +263,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
-@@ -1449,6 +1450,10 @@ If you use this option with bf(--iconv), the args will also be translated
+@@ -1563,6 +1564,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.
  
@@ -269,13 +275,14 @@ diff --git a/rsync.yo b/rsync.yo
  scratch directory when creating temporary copies of the files transferred
  on the receiving side.  The default behavior is to create each temporary
 diff --git a/wildtest.c b/wildtest.c
+index 07351a1..c899eb8 100644
 --- a/wildtest.c
 +++ b/wildtest.c
-@@ -31,6 +31,7 @@ int fnmatch_errors = 0;
+@@ -30,6 +30,7 @@
+ int fnmatch_errors = 0;
  #endif
  
- int wildmatch_errors = 0;
 +int ignore_case = 0;
typedef char bool;
+ int wildmatch_errors = 0;
char number_separator = ',';
  
index ca447b4..32d0521 100644 (file)
@@ -13,10 +13,11 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/Makefile.in b/Makefile.in
+index feacb90..b27b1e7 100644
 --- a/Makefile.in
 +++ b/Makefile.in
-@@ -36,7 +36,7 @@ OBJS1=flist.o rsync.o generator.o receiver.o cleanup.o sender.o exclude.o \
-       util.o main.o checksum.o match.o syscall.o log.o backup.o
+@@ -37,7 +37,7 @@ OBJS1=flist.o rsync.o generator.o receiver.o cleanup.o sender.o exclude.o \
+       util.o main.o checksum.o match.o syscall.o log.o backup.o delete.o
  OBJS2=options.o io.o compat.o hlink.o token.o uidlist.o socket.o hashtable.o \
        fileio.o batch.o clientname.o chmod.o acls.o xattrs.o
 -OBJS3=progress.o pipe.o
@@ -25,17 +26,18 @@ diff --git a/Makefile.in b/Makefile.in
  popt_OBJS=popt/findme.o  popt/popt.o  popt/poptconfig.o \
        popt/popthelp.o popt/poptparse.o
 diff --git a/flist.c b/flist.c
+index 09b4fc5..570bcee 100644
 --- a/flist.c
 +++ b/flist.c
-@@ -71,6 +71,7 @@ extern int sender_symlink_iconv;
+@@ -73,6 +73,7 @@ extern int sender_keeps_checksum;
  extern int unsort_ndx;
  extern struct stats stats;
  extern char *filesfrom_host;
 +extern char *link_by_hash_dir;
+ extern char *usermap, *groupmap;
  
  extern char curr_dir[MAXPATHLEN];
-@@ -844,7 +845,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+@@ -881,7 +882,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                extra_len += EXTRA_LEN;
  #endif
  
@@ -46,9 +48,10 @@ diff --git a/flist.c b/flist.c
  #if SIZEOF_INT64 >= 8
 diff --git a/hashlink.c b/hashlink.c
 new file mode 100644
+index 0000000..15e2a73
 --- /dev/null
 +++ b/hashlink.c
-@@ -0,0 +1,336 @@
+@@ -0,0 +1,339 @@
 +/*
 +   Copyright (C) Cronosys, LLC 2004
 +
@@ -96,7 +99,8 @@ new file mode 100644
 +      }
 +      *dst = 0;
 +
-+      asprintf(&dst,"%s/%s",link_by_hash_dir,hash);
++      if (asprintf(&dst,"%s/%s",link_by_hash_dir,hash) < 0)
++              out_of_memory("make_hash_name");
 +      return dst;
 +}
 +
@@ -153,8 +157,8 @@ new file mode 100644
 +                      *fnbr = this_fnbr;
 +
 +              hashfile = new_array(struct hashfile_struct, 1);
-+              asprintf(&hashfile->name,"%s/%s",hashname,
-+                       di->d_name);
++              if (asprintf(&hashfile->name,"%s/%s",hashname, di->d_name) < 0)
++                      out_of_memory("find_hashfiles");
 +              if (do_stat(hashfile->name,&st) == -1) {
 +                      rsyserr(FERROR, errno, "stat failed: %s", hashfile->name);
 +                      kill_hashfile(hashfile);
@@ -300,7 +304,8 @@ new file mode 100644
 +              }
 +
 +              first = 1;
-+              asprintf(&linkname,"%s/0",hashname);
++              if (asprintf(&linkname,"%s/0",hashname) < 0)
++                      out_of_memory("link_by_hash");
 +              rprintf(FINFO, "(1) linkname = %s\n", linkname);
 +      } else {
 +              struct hashfile_struct *hashfiles, *hashfile;
@@ -313,7 +318,8 @@ new file mode 100644
 +
 +              if (hashfiles == NULL) {
 +                      first = 1;
-+                      asprintf(&linkname,"%s/0",hashname);
++                      if (asprintf(&linkname,"%s/0",hashname) < 0)
++                              out_of_memory("link_by_hash");
 +                      rprintf(FINFO, "(2) linkname = %s\n", linkname);
 +              } else {
 +                      int fd;
@@ -334,8 +340,8 @@ new file mode 100644
 +                              kill_hashfile(hashfile);
 +                      } else {
 +                              first = 1;
-+                              asprintf(&linkname, "%s/%ld", hashname,
-+                                       last_fnbr + 1);
++                              if (asprintf(&linkname, "%s/%ld", hashname, last_fnbr + 1) < 0)
++                                      out_of_memory("link_by_hash");
 +                              rprintf(FINFO, "(4) linkname = %s\n", linkname);
 +                      }
 +              }
@@ -350,8 +356,8 @@ new file mode 100644
 +                      if (errno == EMLINK) {
 +                              first = 1;
 +                              free(linkname);
-+                              asprintf(&linkname,"%s/%ld",hashname,
-+                                       last_fnbr + 1);
++                              if (asprintf(&linkname,"%s/%ld",hashname, last_fnbr + 1) < 0)
++                                      out_of_memory("link_by_hash");
 +                              rprintf(FINFO, "(5) linkname = %s\n", linkname);
 +                              rprintf(FINFO,"link-by-hash: max link count exceeded, starting new file \"%s\".\n", linkname);
 +                      } else {
@@ -386,9 +392,10 @@ new file mode 100644
 +}
 +#endif
 diff --git a/options.c b/options.c
+index e7c6c61..73b1aa4 100644
 --- a/options.c
 +++ b/options.c
-@@ -157,6 +157,7 @@ char *backup_suffix = NULL;
+@@ -158,6 +158,7 @@ char *backup_suffix = NULL;
  char *tmpdir = NULL;
  char *partial_dir = NULL;
  char *basis_dir[MAX_BASIS_DIRS+1];
@@ -396,7 +403,7 @@ diff --git a/options.c b/options.c
  char *config_file = NULL;
  char *shell_cmd = NULL;
  char *logfile_name = NULL;
-@@ -395,6 +396,7 @@ void usage(enum logcode F)
+@@ -745,6 +746,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,16 +411,16 @@ 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");
-@@ -447,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,
+@@ -798,7 +800,7 @@ enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
        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,
--      OPT_NO_D, OPT_APPEND, OPT_NO_ICONV,
-+      OPT_NO_D, OPT_APPEND, OPT_NO_ICONV, OPT_LINK_BY_HASH,
+       OPT_NO_D, OPT_APPEND, OPT_NO_ICONV, OPT_INFO, OPT_DEBUG,
+-      OPT_USERMAP, OPT_GROUPMAP, OPT_CHOWN,
++      OPT_USERMAP, OPT_GROUPMAP, OPT_CHOWN, OPT_LINK_BY_HASH,
        OPT_SERVER, OPT_REFUSED_BASE = 9000};
  
  static struct poptOption long_options[] = {
-@@ -579,6 +581,7 @@ static struct poptOption long_options[] = {
+@@ -937,6 +939,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 },
@@ -421,7 +428,7 @@ diff --git a/options.c b/options.c
    {"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 },
-@@ -1261,6 +1264,21 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+@@ -1742,6 +1745,21 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                        return 0;
  #endif
  
@@ -443,7 +450,7 @@ diff --git a/options.c b/options.c
                default:
                        /* A large opt value means that set_refuse_options()
                         * turned this option off. */
-@@ -2038,6 +2056,11 @@ void server_options(char **args, int *argc_p)
+@@ -2584,6 +2602,11 @@ void server_options(char **args, int *argc_p)
        } else if (inplace)
                args[ac++] = "--inplace";
  
@@ -456,9 +463,10 @@ diff --git a/options.c b/options.c
                if (filesfrom_host) {
                        args[ac++] = "--files-from";
 diff --git a/receiver.c b/receiver.c
+index 4325e30..2709d5e 100644
 --- a/receiver.c
 +++ b/receiver.c
-@@ -163,12 +163,14 @@ int open_tmpfile(char *fnametmp, const char *fname, struct file_struct *file)
+@@ -164,11 +164,13 @@ int open_tmpfile(char *fnametmp, const char *fname, struct file_struct *file)
  }
  
  static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
@@ -467,11 +475,10 @@ diff --git a/receiver.c b/receiver.c
 +                      const char *md4)
  {
        static char file_sum1[MAX_DIGEST_LEN];
-       static char file_sum2[MAX_DIGEST_LEN];
        struct map_struct *mapbuf;
        struct sum_struct sum;
 +      md_context mdfour_data;
-       int32 len, sum_len;
+       int32 len;
        OFF_T offset = 0;
        OFF_T offset2;
 @@ -188,6 +190,9 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
@@ -502,16 +509,17 @@ diff --git a/receiver.c b/receiver.c
                }
  
                if (updating_basis_or_equiv) {
-@@ -303,6 +312,8 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
-       }
+@@ -305,6 +314,9 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
+       if (sum_end(file_sum1) != checksum_len)
+               overflow_exit("checksum_len"); /* Impossible... */
  
-       sum_len = sum_end(file_sum1);
 +      if (md4)
 +              mdfour_result(&mdfour_data, (uchar*)md4);
++
        if (mapbuf)
                unmap_file(mapbuf);
-@@ -318,7 +329,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
+@@ -319,7 +331,7 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
  
  static void discard_receive_data(int f_in, OFF_T length)
  {
@@ -520,7 +528,7 @@ diff --git a/receiver.c b/receiver.c
  }
  
  static void handle_delayed_updates(char *local_name)
-@@ -708,7 +719,7 @@ int recv_files(int f_in, char *local_name)
+@@ -744,7 +756,7 @@ int recv_files(int f_in, char *local_name)
  
                /* recv file data */
                recv_ok = receive_data(f_in, fnamecmp, fd1, st.st_size,
@@ -530,19 +538,20 @@ diff --git a/receiver.c b/receiver.c
                log_item(log_code, file, &initial_stats, iflags, NULL);
  
 diff --git a/rsync.c b/rsync.c
+index 2c026a2..87f6d54 100644
 --- a/rsync.c
 +++ b/rsync.c
-@@ -48,6 +48,7 @@ extern int inplace;
- extern int flist_eof;
+@@ -48,6 +48,7 @@ extern int flist_eof;
+ extern int msgs2stderr;
  extern int keep_dirlinks;
  extern int make_backups;
 +extern char *link_by_hash_dir;
  extern struct file_list *cur_flist, *first_flist, *dir_flist;
  extern struct chmod_mode_struct *daemon_chmod_modes;
  #ifdef ICONV_OPTION
-@@ -578,8 +579,15 @@ int finish_transfer(const char *fname, const char *fnametmp,
+@@ -575,8 +576,15 @@ int finish_transfer(const char *fname, const char *fnametmp,
        /* move tmp file over real file */
-       if (verbose > 2)
+       if (DEBUG_GTE(RECV, 1))
                rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname);
 -      ret = robust_rename(fnametmp, fname, temp_copy_name,
 -                          file->mode & INITACCESSPERMS);
@@ -559,10 +568,11 @@ diff --git a/rsync.c b/rsync.c
                rsyserr(FERROR_XFER, errno, "%s %s -> \"%s\"",
                        ret == -2 ? "copy" : "rename",
 diff --git a/rsync.h b/rsync.h
+index be7cf8a..d4e2aca 100644
 --- a/rsync.h
 +++ b/rsync.h
-@@ -830,6 +830,14 @@ struct stats {
-       int num_transferred_files;
+@@ -853,6 +853,14 @@ struct stats {
+       int xferred_files;
  };
  
 +struct hashfile_struct {
@@ -577,9 +587,10 @@ diff --git a/rsync.h b/rsync.h
  
  struct flist_ndx_item {
 diff --git a/rsync.yo b/rsync.yo
+index 941f7a5..568b481 100644
 --- a/rsync.yo
 +++ b/rsync.yo
-@@ -392,6 +392,7 @@ to the detailed description below for a complete description.  verb(
+@@ -400,6 +400,7 @@ to the detailed description below for a complete description.  verb(
       --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
diff --git a/log-checksum.diff b/log-checksum.diff
deleted file mode 100644 (file)
index 627d13d..0000000
+++ /dev/null
@@ -1,284 +0,0 @@
-This patch to rsync adds a %C log escape that expands to the sender's
-post-transfer checksum of a file for protocol 30 or above.  This way, if
-you need the MD5 checksums of transferred files, you can have rsync log
-them instead of spending extra processor time on a separate command to
-compute them.
-
--- Matt McCutchen <hashproduct@gmail.com>
-
-To use this patch, run these commands for a successful build:
-
-    patch -p1 <patches/log-checksum.diff
-    ./configure                                 (optional if already run)
-    make
-
-diff --git a/flist.c b/flist.c
---- a/flist.c
-+++ b/flist.c
-@@ -68,6 +68,7 @@ extern int sanitize_paths;
- extern int munge_symlinks;
- extern int need_unsorted_flist;
- extern int sender_symlink_iconv;
-+extern int sender_keeps_checksum;
- extern int unsort_ndx;
- extern struct stats stats;
- extern char *filesfrom_host;
-@@ -1223,6 +1224,12 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
-               extra_len += EXTRA_LEN;
- #endif
-+      if (always_checksum && am_sender && S_ISREG(st.st_mode)) {
-+              file_checksum(thisname, tmp_sum, st.st_size);
-+              if (sender_keeps_checksum)
-+                      extra_len += SUM_EXTRA_CNT * EXTRA_LEN;
-+      }
-+
- #if EXTRA_ROUNDING > 0
-       if (extra_len & (EXTRA_ROUNDING * EXTRA_LEN))
-               extra_len = (extra_len | (EXTRA_ROUNDING * EXTRA_LEN)) + EXTRA_LEN;
-@@ -1286,9 +1293,6 @@ 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);
--
-       if (am_sender)
-               F_PATHNAME(file) = pathname;
-       else if (!pool)
-@@ -1300,6 +1304,9 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
-               return NULL;
-       }
-+      if (sender_keeps_checksum && S_ISREG(st.st_mode))
-+              memcpy(F_SUM(file), tmp_sum, checksum_len);
-+
-       if (unsort_ndx)
-               F_NDX(file) = dir_count;
-diff --git a/log.c b/log.c
---- a/log.c
-+++ b/log.c
-@@ -32,8 +32,10 @@ extern int local_server;
- extern int quiet;
- extern int module_id;
- extern int msg_fd_out;
-+extern int checksum_len;
- extern int allow_8bit_chars;
- extern int protocol_version;
-+extern int always_checksum;
- extern int preserve_times;
- extern int uid_ndx;
- extern int gid_ndx;
-@@ -57,6 +59,7 @@ extern iconv_t ic_send, ic_recv;
- extern char curr_dir[];
- extern char *full_module_path;
- extern unsigned int module_dirlen;
-+extern char sender_file_sum[MAX_DIGEST_LEN];
- static int log_initialised;
- static int logfile_was_closed;
-@@ -632,6 +635,28 @@ static void log_formatted(enum logcode code, const char *format, const char *op,
-                       snprintf(buf2, sizeof buf2, fmt, (double)b);
-                       n = buf2;
-                       break;
-+              case 'C':
-+                      if (protocol_version >= 30
-+                       && (iflags & ITEM_TRANSFER
-+                        || (always_checksum && S_ISREG(file->mode)))) {
-+                              int i, x1, x2;
-+                              const char *sum = iflags & ITEM_TRANSFER
-+                                              ? sender_file_sum : F_SUM(file);
-+                              c = buf2 + checksum_len*2;
-+                              *c = '\0';
-+                              for (i = checksum_len; --i >= 0; ) {
-+                                      x1 = CVAL(sum, i);
-+                                      x2 = x1 >> 4;
-+                                      x1 &= 0xF;
-+                                      *--c = x1 <= 9 ? x1 + '0' : x1 + 'a' - 10;
-+                                      *--c = x2 <= 9 ? x2 + '0' : x2 + 'a' - 10;
-+                              }
-+                      } else {
-+                              memset(buf2, ' ', checksum_len*2);
-+                              buf2[checksum_len*2] = '\0';
-+                      }
-+                      n = buf2;
-+                      break;
-               case 'i':
-                       if (iflags & ITEM_DELETED) {
-                               n = "*deleting  ";
-diff --git a/main.c b/main.c
---- a/main.c
-+++ b/main.c
-@@ -37,6 +37,7 @@ extern int am_generator;
- extern int am_daemon;
- extern int inc_recurse;
- extern int blocking_io;
-+extern int always_checksum;
- extern int remove_source_files;
- extern int need_messages_from_generator;
- extern int kluge_around_eof;
-@@ -68,6 +69,8 @@ extern int connect_timeout;
- extern pid_t cleanup_child_pid;
- extern unsigned int module_dirlen;
- extern struct stats stats;
-+extern char *stdout_format;
-+extern char *logfile_format;
- extern char *filesfrom_host;
- extern char *partial_dir;
- extern char *dest_option;
-@@ -85,6 +88,7 @@ int local_server = 0;
- int daemon_over_rsh = 0;
- mode_t orig_umask = 0;
- int batch_gen_fd = -1;
-+int sender_keeps_checksum = 0;
- /* There's probably never more than at most 2 outstanding child processes,
-  * but set it higher, just in case. */
-@@ -1003,6 +1007,12 @@ int client_run(int f_in, int f_out, pid_t pid, int argc, char *argv[])
-       if (am_sender) {
-               keep_dirlinks = 0; /* Must be disabled on the sender. */
-+
-+              if (always_checksum
-+               && (log_format_has(stdout_format, 'C')
-+                || log_format_has(logfile_format, 'C')))
-+                      sender_keeps_checksum = 1;
-+
-               if (protocol_version >= 30)
-                       io_start_multiplex_out();
-               else
-diff --git a/match.c b/match.c
---- a/match.c
-+++ b/match.c
-@@ -25,8 +25,10 @@ extern int verbose;
- extern int do_progress;
- extern int checksum_seed;
- extern int append_mode;
-+extern int checksum_len;
- int updating_basis_file;
-+char sender_file_sum[MAX_DIGEST_LEN];
- static int false_alarms;
- static int hash_hits;
-@@ -329,9 +331,6 @@ static void hash_search(int f,struct sum_struct *s,
-  **/
- void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
- {
--      char file_sum[MAX_DIGEST_LEN];
--      int sum_len;
--
-       last_match = 0;
-       false_alarms = 0;
-       hash_hits = 0;
-@@ -379,18 +378,28 @@ void match_sums(int f, struct sum_struct *s, struct map_struct *buf, OFF_T len)
-               matched(f, s, buf, len, -1);
-       }
--      sum_len = sum_end(file_sum);
--      /* If we had a read error, send a bad checksum. */
--      if (buf && buf->status != 0)
--              file_sum[0]++;
-+      if (sum_end(sender_file_sum) != checksum_len)
-+              overflow_exit("checksum_len"); /* Impossible... */
-+
-+      /* If we had a read error, send a bad checksum.  We use all bits
-+       * off as long as the checksum doesn't happen to be that, in
-+       * which case we turn the last 0 bit into a 1. */
-+      if (buf && buf->status != 0) {
-+              int i;
-+              for (i = 0; i < checksum_len && sender_file_sum[i] == 0; i++) {}
-+              memset(sender_file_sum, 0, checksum_len);
-+              if (i == checksum_len)
-+                      sender_file_sum[i-1]++;
-+      }
-       if (verbose > 2)
-               rprintf(FINFO,"sending file_sum\n");
--      write_buf(f, file_sum, sum_len);
-+      write_buf(f, sender_file_sum, checksum_len);
--      if (verbose > 2)
-+      if (verbose > 2) {
-               rprintf(FINFO, "false_alarms=%d hash_hits=%d matches=%d\n",
-                       false_alarms, hash_hits, matches);
-+      }
-       total_hash_hits += hash_hits;
-       total_false_alarms += false_alarms;
-diff --git a/options.c b/options.c
---- a/options.c
-+++ b/options.c
-@@ -1525,7 +1525,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')
--               && !log_format_has(stdout_format, 'c'))
-+               && !log_format_has(stdout_format, 'c')
-+               && !log_format_has(stdout_format, 'C'))
-                       log_before_transfer = !am_server;
-       } else if (itemize_changes) {
-               stdout_format = "%i %n%L";
-diff --git a/receiver.c b/receiver.c
---- a/receiver.c
-+++ b/receiver.c
-@@ -46,6 +46,7 @@ extern int remove_source_files;
- extern int append_mode;
- extern int sparse_files;
- extern int keep_partial;
-+extern int checksum_len;
- extern int checksum_seed;
- extern int inplace;
- extern int delay_updates;
-@@ -54,6 +55,7 @@ extern struct stats stats;
- extern char *tmpdir;
- extern char *partial_dir;
- extern char *basis_dir[];
-+extern char sender_file_sum[MAX_DIGEST_LEN];
- extern struct file_list *cur_flist, *first_flist, *dir_flist;
- extern struct filter_list_struct daemon_filter_list;
-@@ -166,10 +168,9 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
-                       const char *fname, int fd, OFF_T total_size)
- {
-       static char file_sum1[MAX_DIGEST_LEN];
--      static char file_sum2[MAX_DIGEST_LEN];
-       struct map_struct *mapbuf;
-       struct sum_struct sum;
--      int32 len, sum_len;
-+      int32 len;
-       OFF_T offset = 0;
-       OFF_T offset2;
-       char *data;
-@@ -302,15 +303,16 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
-               exit_cleanup(RERR_FILEIO);
-       }
--      sum_len = sum_end(file_sum1);
-+      if (sum_end(file_sum1) != checksum_len)
-+              overflow_exit("checksum_len"); /* Impossible... */
-       if (mapbuf)
-               unmap_file(mapbuf);
--      read_buf(f_in, file_sum2, sum_len);
-+      read_buf(f_in, sender_file_sum, checksum_len);
-       if (verbose > 2)
-               rprintf(FINFO,"got file_sum\n");
--      if (fd != -1 && memcmp(file_sum1, file_sum2, sum_len) != 0)
-+      if (fd != -1 && memcmp(file_sum1, sender_file_sum, checksum_len) != 0)
-               return 0;
-       return 1;
- }
-diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo
---- a/rsyncd.conf.yo
-+++ b/rsyncd.conf.yo
-@@ -510,6 +510,7 @@ quote(itemization(
-   it() %b the number of bytes actually transferred
-   it() %B the permission bits of the file (e.g. rwxrwxrwt)
-   it() %c the total size of the block checksums received for the basis file (only when sending)
-+  it() %C the full-file MD5 checksum if bf(--checksum) is enabled or a file was transferred (only for protocol 30 or above).
-   it() %f the filename (long form on sender; no trailing "/")
-   it() %G the gid of the file (decimal) or "DEFAULT"
-   it() %h the remote host name
diff --git a/munge-links.diff b/munge-links.diff
deleted file mode 100644 (file)
index e163888..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-This patch adds the --munge-links option, which works like the daemon's
-"munge symlinks" parameter.
-
-To use this patch, run these commands for a successful build:
-
-    patch -p1 <patches/remote-option.diff
-    patch -p1 <patches/munge-links.diff
-    ./configure                               (optional if already run)
-    make
-
-diff --git a/clientserver.c b/clientserver.c
---- a/clientserver.c
-+++ b/clientserver.c
-@@ -37,6 +37,7 @@ extern int ignore_errors;
- extern int preserve_xattrs;
- extern int kluge_around_eof;
- extern int daemon_over_rsh;
-+extern int munge_symlinks;
- extern int sanitize_paths;
- extern int numeric_ids;
- extern int filesfrom_fd;
-@@ -66,7 +67,6 @@ extern iconv_t ic_send, ic_recv;
- char *auth_user;
- int read_only = 0;
- int module_id = -1;
--int munge_symlinks = 0;
- struct chmod_mode_struct *daemon_chmod_modes;
- /* module_dirlen is the length of the module_dir string when in daemon
-@@ -418,6 +418,7 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
-       char *name = lp_name(i);
-       int use_chroot = lp_use_chroot(i);
-       int ret, pre_exec_fd = -1;
-+      int save_munge_symlinks;
-       pid_t pre_exec_pid = 0;
-       char *request = NULL;
-@@ -688,9 +689,11 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
-               munge_symlinks = !use_chroot || module_dirlen;
-       if (munge_symlinks) {
-               STRUCT_STAT st;
--              if (do_stat(SYMLINK_PREFIX, &st) == 0 && S_ISDIR(st.st_mode)) {
--                      rprintf(FLOG, "Symlink munging is unsupported when a %s directory exists.\n",
--                              SYMLINK_PREFIX);
-+              char prefix[SYMLINK_PREFIX_LEN]; /* NOT +1 ! */
-+              strlcpy(prefix, SYMLINK_PREFIX, sizeof prefix); /* trim the trailing slash */
-+              if (do_stat(prefix, &st) == 0 && S_ISDIR(st.st_mode)) {
-+                      rprintf(FLOG, "Symlink munging is unsafe when a %s directory exists.\n",
-+                              prefix);
-                       io_printf(f_out, "@ERROR: daemon security issue -- contact admin\n", name);
-                       exit_cleanup(RERR_UNSUPPORTED);
-               }
-@@ -746,6 +749,8 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
-       read_args(f_in, name, line, sizeof line, rl_nulls, &argv, &argc, &request);
-       orig_argv = argv;
-+      save_munge_symlinks = munge_symlinks;
-+
-       verbose = 0; /* future verbosity is controlled by client options */
-       ret = parse_arguments(&argc, (const char ***) &argv);
-       if (protect_args && ret) {
-@@ -757,6 +762,8 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
-       } else
-               orig_early_argv = NULL;
-+      munge_symlinks = save_munge_symlinks; /* The client mustn't control this. */
-+
-       if (pre_exec_pid) {
-               err_msg = finish_pre_exec(pre_exec_pid, pre_exec_fd, request,
-                                         orig_early_argv, orig_argv);
-diff --git a/options.c b/options.c
---- a/options.c
-+++ b/options.c
-@@ -105,6 +105,7 @@ int connect_timeout = 0;
- int keep_partial = 0;
- int safe_symlinks = 0;
- int copy_unsafe_links = 0;
-+int munge_symlinks = 0;
- int size_only = 0;
- int daemon_bwlimit = 0;
- int bwlimit = 0;
-@@ -339,6 +340,7 @@ void usage(enum logcode F)
-   rprintf(F," -L, --copy-links            transform symlink into referent file/dir\n");
-   rprintf(F,"     --copy-unsafe-links     only \"unsafe\" symlinks are transformed\n");
-   rprintf(F,"     --safe-links            ignore symlinks that point outside the source tree\n");
-+  rprintf(F,"     --munge-links           munge symlinks to make them safer (but unusable)\n");
-   rprintf(F," -k, --copy-dirlinks         transform symlink to a dir into referent dir\n");
-   rprintf(F," -K, --keep-dirlinks         treat symlinked dir on receiver as dir\n");
-   rprintf(F," -H, --hard-links            preserve hard links\n");
-@@ -521,6 +523,8 @@ static struct poptOption long_options[] = {
-   {"copy-links",      'L', POPT_ARG_NONE,   &copy_links, 0, 0, 0 },
-   {"copy-unsafe-links",0,  POPT_ARG_NONE,   &copy_unsafe_links, 0, 0, 0 },
-   {"safe-links",       0,  POPT_ARG_NONE,   &safe_symlinks, 0, 0, 0 },
-+  {"munge-links",      0,  POPT_ARG_VAL,    &munge_symlinks, 1, 0, 0 },
-+  {"no-munge-links",   0,  POPT_ARG_VAL,    &munge_symlinks, 0, 0, 0 },
-   {"copy-dirlinks",   'k', POPT_ARG_NONE,   &copy_dirlinks, 0, 0, 0 },
-   {"keep-dirlinks",   'K', POPT_ARG_NONE,   &keep_dirlinks, 0, 0, 0 },
-   {"hard-links",      'H', POPT_ARG_NONE,   0, 'H', 0, 0 },
-@@ -1472,6 +1476,17 @@ int parse_arguments(int *argc_p, const char ***argv_p)
-               need_messages_from_generator = 1;
-       }
-+      if (munge_symlinks && !am_daemon) {
-+              STRUCT_STAT st;
-+              char prefix[SYMLINK_PREFIX_LEN]; /* NOT +1 ! */
-+              strlcpy(prefix, SYMLINK_PREFIX, sizeof prefix); /* trim the trailing slash */
-+              if (do_stat(prefix, &st) == 0 && S_ISDIR(st.st_mode)) {
-+                      rprintf(FERROR, "Symlink munging is unsafe when a %s directory exists.\n",
-+                              prefix);
-+                      exit_cleanup(RERR_UNSUPPORTED);
-+              }
-+      }
-+
-       if (sanitize_paths) {
-               int i;
-               for (i = argc; i-- > 0; )
-diff --git a/pipe.c b/pipe.c
---- a/pipe.c
-+++ b/pipe.c
-@@ -26,6 +26,7 @@ extern int am_sender;
- extern int am_server;
- extern int blocking_io;
- extern int filesfrom_fd;
-+extern int munge_symlinks;
- extern mode_t orig_umask;
- extern char *logfile_name;
- extern int remote_option_cnt;
-@@ -133,6 +134,7 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
-               am_sender = 0;
-               am_server = 1;
-               filesfrom_fd = -1;
-+              munge_symlinks = 0; /* Each side needs its own option. */
-               chmod_modes = NULL; /* Let the sending side handle this. */
-               /* Let the client side handle this. */
-diff --git a/rsync.h b/rsync.h
---- a/rsync.h
-+++ b/rsync.h
-@@ -32,7 +32,7 @@
- #define DEFAULT_LOCK_FILE "/var/run/rsyncd.lock"
- #define URL_PREFIX "rsync://"
--#define SYMLINK_PREFIX "/rsyncd-munged/"
-+#define SYMLINK_PREFIX "/rsyncd-munged/"  /* This MUST have a trailing slash! */
- #define SYMLINK_PREFIX_LEN ((int)sizeof SYMLINK_PREFIX - 1)
- #define BACKUP_SUFFIX "~"
-diff --git a/rsync.yo b/rsync.yo
---- a/rsync.yo
-+++ b/rsync.yo
-@@ -338,6 +338,7 @@ to the detailed description below for a complete description.  verb(
-  -L, --copy-links            transform symlink into referent file/dir
-      --copy-unsafe-links     only "unsafe" symlinks are transformed
-      --safe-links            ignore symlinks that point outside the tree
-+     --munge-links           munge symlinks to make them safer
-  -k, --copy-dirlinks         transform symlink to dir into referent dir
-  -K, --keep-dirlinks         treat symlinked dir on receiver as dir
-  -H, --hard-links            preserve hard links
-@@ -795,6 +796,25 @@ which point outside the copied tree. All absolute symlinks are
- also ignored. Using this option in conjunction with bf(--relative) may
- give unexpected results.
-+dit(bf(--munge-links)) This option tells rsync to (1) modify all symlinks on
-+the receiving side in a way that makes them unusable but recoverable (see
-+below), or (2) to unmunge symlinks on the sending side that had been stored in
-+a munged state.  This is useful if you don't quite trust the source of the data
-+to not try to slip in a symlink to a unexpected place.
-+
-+The way rsync disables the use of symlinks is to prefix each one with the
-+string "/rsyncd-munged/".  This prevents the links from being used as long as
-+that directory does not exist.  When this option is enabled, rsync will refuse
-+to run if that path is a directory or a symlink to a directory.
-+
-+The option only affects the client side of the transfer, so if you need it to
-+affect the server, specify it via bf(--remote-option).  (Note that in a local
-+transfer, the client side is the sender.)
-+
-+This option has no affect on a daemon, since the daemon configures whether it
-+wants munged symlinks via its "munge symlinks" parameter.  See also the
-+"munge-symlinks" perl script in the support directory of the source code.
-+
- dit(bf(-k, --copy-dirlinks)) This option causes the sending side to treat
- a symlink to a directory as though it were a real directory.  This is
- useful if you don't want symlinks to non-directories to be affected, as
-diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo
---- a/rsyncd.conf.yo
-+++ b/rsyncd.conf.yo
-@@ -191,8 +191,9 @@ to translate names, and that it is not possible for a user to change those
- resources.
- dit(bf(munge symlinks)) This parameter tells rsync to modify
--all incoming symlinks in a way that makes them unusable but recoverable
--(see below).  This should help protect your files from user trickery when
-+all symlinks in the same way as the (non-daemon-affecting)
-+bf(--munge-links) command-line option (using a method described below).
-+This should help protect your files from user trickery when
- your daemon module is writable.  The default is disabled when "use chroot"
- is on and the inside-chroot path is "/", otherwise it is enabled.
index 1d65549..9ee9720 100644 (file)
@@ -21,12 +21,13 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/clientserver.c b/clientserver.c
+index b6afe00..568a121 100644
 --- a/clientserver.c
 +++ b/clientserver.c
-@@ -67,6 +67,7 @@ char *auth_user;
+@@ -67,6 +67,7 @@ extern iconv_t ic_send, ic_recv;
+ char *auth_user;
  int read_only = 0;
  int module_id = -1;
- int munge_symlinks = 0;
 +pid_t namecvt_pid = 0;
  struct chmod_mode_struct *daemon_chmod_modes;
  
@@ -39,7 +40,7 @@ diff --git a/clientserver.c b/clientserver.c
  
  #ifdef HAVE_SIGACTION
  static struct sigaction sigact;
-@@ -565,7 +567,7 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
+@@ -649,7 +651,7 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
        log_init(1);
  
  #ifdef HAVE_PUTENV
@@ -48,7 +49,7 @@ diff --git a/clientserver.c b/clientserver.c
                char *modname, *modpath, *hostaddr, *hostname, *username;
                int status;
  
-@@ -654,6 +656,44 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
+@@ -738,6 +740,44 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
                        set_blocking(fds[1]);
                        pre_exec_fd = fds[1];
                }
@@ -93,7 +94,7 @@ diff --git a/clientserver.c b/clientserver.c
                umask(0);
        }
  #endif
-@@ -877,6 +917,44 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
+@@ -965,6 +1005,44 @@ static int rsync_module(int f_in, int f_out, int i, const char *addr, const char
        return 0;
  }
  
@@ -139,9 +140,10 @@ diff --git a/clientserver.c b/clientserver.c
     with "list = False". */
  static void send_listing(int fd)
 diff --git a/loadparm.c b/loadparm.c
+index 8e48e6d..c623689 100644
 --- a/loadparm.c
 +++ b/loadparm.c
-@@ -140,6 +140,7 @@ typedef struct
+@@ -121,6 +121,7 @@ typedef struct {
        char *log_file;
        char *log_format;
        char *name;
@@ -149,7 +151,7 @@ diff --git a/loadparm.c b/loadparm.c
        char *outgoing_chmod;
        char *path;
        char *postxfer_exec;
-@@ -191,6 +192,7 @@ static service sDefault =
+@@ -195,6 +196,7 @@ static const all_vars Defaults = {
   /* log_file; */              NULL,
   /* log_format; */            "%o %h [%a] %m (%u) %f %l",
   /* name; */                  NULL,
@@ -157,15 +159,15 @@ diff --git a/loadparm.c b/loadparm.c
   /* outgoing_chmod; */                NULL,
   /* path; */                  NULL,
   /* postxfer_exec; */         NULL,
-@@ -328,6 +330,7 @@ static struct parm_struct parm_table[] =
-  {"max verbosity",     P_INTEGER,P_LOCAL, &sDefault.max_verbosity,     NULL,0},
-  {"munge symlinks",    P_BOOL,   P_LOCAL, &sDefault.munge_symlinks,    NULL,0},
-  {"name",              P_STRING, P_LOCAL, &sDefault.name,              NULL,0},
-+ {"name converter",    P_STRING, P_LOCAL, &sDefault.name_converter,    NULL,0},
-  {"numeric ids",       P_BOOL,   P_LOCAL, &sDefault.numeric_ids,       NULL,0},
-  {"outgoing chmod",    P_STRING, P_LOCAL, &sDefault.outgoing_chmod,    NULL,0},
-  {"path",              P_PATH,   P_LOCAL, &sDefault.path,              NULL,0},
-@@ -418,6 +421,7 @@ FN_LOCAL_STRING(lp_outgoing_chmod, outgoing_chmod)
+@@ -337,6 +339,7 @@ static struct parm_struct parm_table[] =
+  {"max verbosity",     P_INTEGER,P_LOCAL, &Vars.l.max_verbosity,       NULL,0},
+  {"munge symlinks",    P_BOOL,   P_LOCAL, &Vars.l.munge_symlinks,      NULL,0},
+  {"name",              P_STRING, P_LOCAL, &Vars.l.name,                NULL,0},
++ {"name converter",    P_STRING, P_LOCAL, &Vars.l.name_converter,      NULL,0},
+  {"numeric ids",       P_BOOL,   P_LOCAL, &Vars.l.numeric_ids,         NULL,0},
+  {"outgoing chmod",    P_STRING, P_LOCAL, &Vars.l.outgoing_chmod,      NULL,0},
+  {"path",              P_PATH,   P_LOCAL, &Vars.l.path,                NULL,0},
+@@ -414,6 +417,7 @@ FN_LOCAL_STRING(lp_outgoing_chmod, outgoing_chmod)
  FN_LOCAL_STRING(lp_path, path)
  FN_LOCAL_STRING(lp_postxfer_exec, postxfer_exec)
  FN_LOCAL_STRING(lp_prexfer_exec, prexfer_exec)
@@ -174,9 +176,10 @@ diff --git a/loadparm.c b/loadparm.c
  FN_LOCAL_STRING(lp_secrets_file, secrets_file)
  FN_LOCAL_STRING(lp_temp_dir, temp_dir)
 diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo
+index d4978cd..fd0f7d9 100644
 --- a/rsyncd.conf.yo
 +++ b/rsyncd.conf.yo
-@@ -159,10 +159,11 @@ if the module is not read-only).
+@@ -163,10 +163,11 @@ if the module is not read-only).
  
  When this parameter is enabled, rsync will not attempt to map users and groups
  by name (by default), but instead copy IDs as though bf(--numeric-ids) had
@@ -190,7 +193,7 @@ diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo
  process in the chroot hierarchy will need to have access to the resources
  used by these library functions (traditionally /etc/passwd and
  /etc/group, but perhaps additional dynamic libraries as well).
-@@ -227,6 +228,27 @@ path elements that rsync believes will allow a symlink to escape the module's
+@@ -232,6 +233,27 @@ path elements that rsync believes will allow a symlink to escape the module's
  hierarchy.  There are tricky ways to work around this, though, so you had
  better trust your users if you choose this combination of parameters.
  
@@ -220,10 +223,11 @@ diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo
  the daemon will use the value of the "charset" parameter regardless of the
 diff --git a/support/nameconvert b/support/nameconvert
 new file mode 100755
+index 0000000..d01f593
 --- /dev/null
 +++ b/support/nameconvert
-@@ -0,0 +1,43 @@
-+#!/usr/bin/perl
+@@ -0,0 +1,42 @@
++#!/usr/bin/perl -w
 +# This implements a simple protocol to do {user,group}-{name,id}
 +# conversions.  All input and output consists of simple strings
 +# with a terminating null char (or newline for debugging).  If
@@ -242,7 +246,6 @@ new file mode 100755
 +# "name converter" setting.
 +
 +use strict;
-+use warnings;
 +
 +my $eol = grep(/^--debug$/, @ARGV) ? "\n" : "\0";
 +$/ = $eol;
@@ -267,10 +270,11 @@ new file mode 100755
 +    print $ans, $eol;
 +}
 diff --git a/t_stub.c b/t_stub.c
+index 02cfa69..eaaf8a9 100644
 --- a/t_stub.c
 +++ b/t_stub.c
-@@ -30,6 +30,7 @@ int preserve_xattrs = 0;
mode_t orig_umask = 002;
+@@ -30,6 +30,7 @@ mode_t orig_umask = 002;
char number_separator = ',';
  char *partial_dir;
  char *module_dir;
 +pid_t namecvt_pid;
@@ -290,17 +294,18 @@ diff --git a/t_stub.c b/t_stub.c
  {
        return NULL;
 diff --git a/uidlist.c b/uidlist.c
+index 7e8cbd7..472aeb9 100644
 --- a/uidlist.c
 +++ b/uidlist.c
-@@ -32,6 +32,7 @@ extern int preserve_uid;
+@@ -33,6 +33,7 @@ extern int preserve_uid;
  extern int preserve_gid;
  extern int preserve_acls;
  extern int numeric_ids;
 +extern pid_t namecvt_pid;
+ extern char *usermap;
+ extern char *groupmap;
  
- #ifdef HAVE_GETGROUPS
- # ifndef GETGROUPS_T
-@@ -69,8 +70,12 @@ static struct idlist *add_to_list(struct idlist **root, id_t id, const char *nam
+@@ -75,8 +76,12 @@ static struct idlist *add_to_list(struct idlist **root, id_t id, const char *nam
  /* turn a uid into a user name */
  static const char *uid_to_name(uid_t uid)
  {
@@ -315,7 +320,7 @@ diff --git a/uidlist.c b/uidlist.c
                return strdup(pass->pw_name);
        return NULL;
  }
-@@ -78,8 +83,12 @@ static const char *uid_to_name(uid_t uid)
+@@ -84,8 +89,12 @@ static const char *uid_to_name(uid_t uid)
  /* turn a gid into a group name */
  static const char *gid_to_name(gid_t gid)
  {
@@ -331,10 +336,11 @@ diff --git a/uidlist.c b/uidlist.c
        return NULL;
  }
 diff --git a/util.c b/util.c
+index 0cafed6..dc1647b 100644
 --- a/util.c
 +++ b/util.c
-@@ -31,9 +31,10 @@ extern int relative_paths;
- extern int human_readable;
+@@ -31,9 +31,10 @@ extern int modify_window;
+ extern int relative_paths;
  extern int preserve_xattrs;
  extern char *module_dir;
 -extern unsigned int module_dirlen;
index 5c3bdef..bd54f84 100644 (file)
@@ -10,6 +10,7 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/access.c b/access.c
+index 9a023de..c6d9f3c 100644
 --- a/access.c
 +++ b/access.c
 @@ -19,11 +19,14 @@
@@ -18,12 +19,12 @@ diff --git a/access.c b/access.c
  #include "rsync.h"
 +#include <netdb.h>
  
- static int match_hostname(char *host, char *tok)
+ static int match_hostname(const char *host, const char *tok)
  {
        if (!host || !*host)
                return 0;
 +      if (*tok == '@' && tok[1])
 +              return innetgr(tok + 1, host, NULL, NULL);
-       return wildmatch(tok, host);
+       return iwildmatch(tok, host);
  }
  
index 18530c8..a7db145 100644 (file)
@@ -8,6 +8,7 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/generator.c b/generator.c
+index 12007a1..29c9297 100644
 --- a/generator.c
 +++ b/generator.c
 @@ -44,6 +44,7 @@ extern int preserve_hard_links;
@@ -18,7 +19,7 @@ diff --git a/generator.c b/generator.c
  extern int uid_ndx;
  extern int gid_ndx;
  extern int delete_mode;
-@@ -630,6 +631,7 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+@@ -437,6 +438,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! */
@@ -26,7 +27,7 @@ diff --git a/generator.c b/generator.c
                int keep_time = !preserve_times ? 0
                    : S_ISDIR(file->mode) ? preserve_times > 1 :
  #if defined HAVE_LUTIMES && defined HAVE_UTIMES
-@@ -659,10 +661,11 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+@@ -466,10 +468,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;
@@ -41,7 +42,7 @@ diff --git a/generator.c b/generator.c
                        iflags |= ITEM_REPORT_GROUP;
  #ifdef SUPPORT_ACLS
                if (preserve_acls && !S_ISLNK(file->mode)) {
-@@ -1438,7 +1441,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1254,7 +1257,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                real_sx = sx;
                if (file->flags & FLAG_DIR_CREATED)
                        statret = -1;
@@ -51,6 +52,7 @@ diff --git a/generator.c b/generator.c
                                               dflt_perms, statret == 0);
                }
 diff --git a/options.c b/options.c
+index e7c6c61..03588fd 100644
 --- a/options.c
 +++ b/options.c
 @@ -59,6 +59,7 @@ int preserve_specials = 0;
@@ -61,7 +63,7 @@ diff --git a/options.c b/options.c
  int update_only = 0;
  int cvs_exclude = 0;
  int dry_run = 0;
-@@ -354,6 +355,7 @@ void usage(enum logcode F)
+@@ -698,6 +699,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 +71,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");
-@@ -494,6 +496,7 @@ static struct poptOption long_options[] = {
+@@ -848,6 +850,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 +79,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 },
-@@ -1510,6 +1513,8 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+@@ -2020,6 +2023,8 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                parse_rule(&filter_list, backup_dir_buf, 0, 0);
        }
  
@@ -86,7 +88,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)
-@@ -1748,6 +1753,8 @@ void server_options(char **args, int *argc_p)
+@@ -2263,6 +2268,8 @@ void server_options(char **args, int *argc_p)
                        argstr[x++] = 'm';
                if (omit_dir_times)
                        argstr[x++] = 'O';
@@ -96,9 +98,10 @@ diff --git a/options.c b/options.c
                if (copy_links)
                        argstr[x++] = 'L';
 diff --git a/rsync.c b/rsync.c
+index 2c026a2..caf3204 100644
 --- a/rsync.c
 +++ b/rsync.c
-@@ -34,6 +34,7 @@ extern int preserve_xattrs;
+@@ -33,6 +33,7 @@ extern int preserve_xattrs;
  extern int preserve_perms;
  extern int preserve_executability;
  extern int preserve_times;
@@ -106,7 +109,7 @@ diff --git a/rsync.c b/rsync.c
  extern int am_root;
  extern int am_server;
  extern int am_sender;
-@@ -442,9 +443,11 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
+@@ -438,9 +439,11 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
                        file->flags |= FLAG_TIME_FAILED;
        }
  
@@ -121,9 +124,10 @@ diff --git a/rsync.c b/rsync.c
        if (S_ISLNK(sxp->st.st_mode)) {
                ;
 diff --git a/rsync.yo b/rsync.yo
+index 941f7a5..9aef20a 100644
 --- a/rsync.yo
 +++ b/rsync.yo
-@@ -353,6 +353,7 @@ to the detailed description below for a complete description.  verb(
+@@ -356,6 +356,7 @@ to the detailed description below for a complete description.  verb(
   -D                          same as --devices --specials
   -t, --times                 preserve modification times
   -O, --omit-dir-times        omit directories from --times
@@ -131,7 +135,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
-@@ -1004,6 +1005,10 @@ it is preserving modification times (see bf(--times)).  If NFS is sharing
+@@ -1071,6 +1072,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 888800c..8015bd6 100644 (file)
@@ -36,9 +36,10 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/Makefile.in b/Makefile.in
+index feacb90..3016643 100644
 --- a/Makefile.in
 +++ b/Makefile.in
-@@ -40,7 +40,7 @@ OBJS3=progress.o pipe.o
+@@ -41,7 +41,7 @@ OBJS3=progress.o pipe.o
  DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o
  popt_OBJS=popt/findme.o  popt/popt.o  popt/poptconfig.o \
        popt/popthelp.o popt/poptparse.o
@@ -48,6 +49,7 @@ diff --git a/Makefile.in b/Makefile.in
  TLS_OBJ = tls.o syscall.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@
  
 diff --git a/cleanup.c b/cleanup.c
+index 19ef072..506f575 100644
 --- a/cleanup.c
 +++ b/cleanup.c
 @@ -25,6 +25,9 @@
@@ -59,8 +61,8 @@ diff --git a/cleanup.c b/cleanup.c
 +#endif
  extern int keep_partial;
  extern int got_xfer_error;
- extern char *partial_dir;
-@@ -121,6 +124,14 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
+ extern int output_needs_newline;
+@@ -127,6 +130,14 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
                                code, file, line);
                }
  
@@ -76,9 +78,10 @@ diff --git a/cleanup.c b/cleanup.c
  #include "case_N.h"
  
 diff --git a/clientserver.c b/clientserver.c
+index b6afe00..5467c72 100644
 --- a/clientserver.c
 +++ b/clientserver.c
-@@ -31,6 +31,9 @@ extern int am_sender;
+@@ -30,6 +30,9 @@ extern int am_sender;
  extern int am_server;
  extern int am_daemon;
  extern int am_root;
@@ -88,7 +91,7 @@ diff --git a/clientserver.c b/clientserver.c
  extern int rsync_port;
  extern int protect_args;
  extern int ignore_errors;
-@@ -128,8 +131,18 @@ int start_socket_client(char *host, int remote_argc, char *remote_argv[],
+@@ -134,8 +137,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,8 +111,8 @@ 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)
-@@ -272,6 +285,32 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
-       if (verbose > 1)
+@@ -278,6 +291,32 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
+       if (DEBUG_GTE(CMD, 1))
                print_child_argv("sending daemon args:", sargs);
  
 +#ifdef HAVE_OPENSSL
@@ -141,7 +144,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,
-@@ -297,6 +336,10 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
+@@ -303,6 +342,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 +155,7 @@ diff --git a/clientserver.c b/clientserver.c
                        exit(0);
                }
  
-@@ -304,6 +347,10 @@ int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char
+@@ -310,6 +353,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 +166,7 @@ diff --git a/clientserver.c b/clientserver.c
                        return -1;
                }
  
-@@ -934,6 +981,9 @@ int start_daemon(int f_in, int f_out)
+@@ -1022,6 +1069,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 +176,7 @@ diff --git a/clientserver.c b/clientserver.c
        line[0] = 0;
        if (!read_line_old(f_in, line, sizeof line))
                return -1;
-@@ -945,6 +995,20 @@ int start_daemon(int f_in, int f_out)
+@@ -1033,6 +1083,20 @@ int start_daemon(int f_in, int f_out)
                return -1;
        }
  
@@ -195,9 +198,10 @@ diff --git a/clientserver.c b/clientserver.c
                /* it's some sort of command that I don't understand */
                io_printf(f_out, "@ERROR: Unknown command '%s'\n", line);
 diff --git a/configure.in b/configure.in
+index bc7d4a7..73ca6c5 100644
 --- a/configure.in
 +++ b/configure.in
-@@ -295,6 +295,21 @@ if test x"$enable_locale" != x"no"; then
+@@ -293,6 +293,21 @@ if test x"$enable_locale" != x"no"; then
        AC_DEFINE(CONFIG_LOCALE)
  fi
  
@@ -220,9 +224,10 @@ diff --git a/configure.in b/configure.in
  case $host_os in
        *cygwin* ) AC_MSG_RESULT(yes)
 diff --git a/options.c b/options.c
+index e7c6c61..634b89e 100644
 --- a/options.c
 +++ b/options.c
-@@ -185,6 +185,14 @@ int logfile_format_has_o_or_i = 0;
+@@ -191,6 +191,14 @@ int logfile_format_has_o_or_i = 0;
  int always_checksum = 0;
  int list_only = 0;
  
@@ -237,7 +242,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;
  
-@@ -225,6 +233,7 @@ static void print_rsync_version(enum logcode f)
+@@ -566,6 +574,7 @@ static void print_rsync_version(enum logcode f)
        char const *links = "no ";
        char const *iconv = "no ";
        char const *ipv6 = "no ";
@@ -245,7 +250,7 @@ diff --git a/options.c b/options.c
        STRUCT_STAT *dumstat;
  
  #if SUBPROTOCOL_VERSION != 0
-@@ -258,6 +267,9 @@ static void print_rsync_version(enum logcode f)
+@@ -599,6 +608,9 @@ static void print_rsync_version(enum logcode f)
  #if defined HAVE_LUTIMES && defined HAVE_UTIMES
        symtimes = "";
  #endif
@@ -255,7 +260,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);
-@@ -271,8 +283,8 @@ static void print_rsync_version(enum logcode f)
+@@ -612,8 +624,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 +271,7 @@ diff --git a/options.c b/options.c
  
  #ifdef MAINTAINER_MODE
        rprintf(f, "Panic Action: \"%s\"\n", get_panic_action());
-@@ -434,6 +446,13 @@ void usage(enum logcode F)
+@@ -784,6 +796,13 @@ void usage(enum logcode F)
  #endif
    rprintf(F," -4, --ipv4                  prefer IPv4\n");
    rprintf(F," -6, --ipv6                  prefer IPv6\n");
@@ -280,16 +285,16 @@ 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");
  
-@@ -447,7 +466,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,
+@@ -798,7 +817,7 @@ enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
        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,
--      OPT_NO_D, OPT_APPEND, OPT_NO_ICONV,
-+      OPT_NO_D, OPT_APPEND, OPT_NO_ICONV, OPT_USE_SSL,
+       OPT_NO_D, OPT_APPEND, OPT_NO_ICONV, OPT_INFO, OPT_DEBUG,
+-      OPT_USERMAP, OPT_GROUPMAP, OPT_CHOWN,
++      OPT_USERMAP, OPT_GROUPMAP, OPT_CHOWN, OPT_USE_SSL,
        OPT_SERVER, OPT_REFUSED_BASE = 9000};
  
  static struct poptOption long_options[] = {
-@@ -650,6 +669,13 @@ static struct poptOption long_options[] = {
+@@ -1012,6 +1031,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 +308,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 },
-@@ -675,6 +701,13 @@ static void daemon_usage(enum logcode F)
+@@ -1039,6 +1065,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 +322,7 @@ diff --git a/options.c b/options.c
    rprintf(F,"     --help                  show this help screen\n");
  
    rprintf(F,"\n");
-@@ -699,6 +732,13 @@ static struct poptOption long_daemon_options[] = {
+@@ -1064,6 +1097,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 +336,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 },
-@@ -980,6 +1020,12 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+@@ -1358,6 +1398,12 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                                        verbose++;
                                        break;
  
@@ -344,7 +349,7 @@ diff --git a/options.c b/options.c
                                default:
                                        rprintf(FERROR,
                                            "rsync: %s: %s (in daemon mode)\n",
-@@ -1003,6 +1049,17 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+@@ -1384,6 +1430,17 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                                exit_cleanup(RERR_SYNTAX);
                        }
  
@@ -362,7 +367,7 @@ diff --git a/options.c b/options.c
                        *argv_p = argv = poptGetArgs(pc);
                        *argc_p = argc = count_args(argv);
                        am_starting_up = 0;
-@@ -1261,6 +1318,12 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+@@ -1742,6 +1799,12 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                        return 0;
  #endif
  
@@ -375,7 +380,7 @@ diff --git a/options.c b/options.c
                default:
                        /* A large opt value means that set_refuse_options()
                         * turned this option off. */
-@@ -1594,6 +1657,17 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+@@ -2108,6 +2171,17 @@ int parse_arguments(int *argc_p, const char ***argv_p)
        if (delay_updates && !partial_dir)
                partial_dir = tmp_partialdir;
  
@@ -393,38 +398,30 @@ diff --git a/options.c b/options.c
        if (inplace) {
  #ifdef HAVE_FTRUNCATE
                if (partial_dir) {
-@@ -2087,10 +2161,27 @@ char *check_for_hostspec(char *s, char **host_ptr, int *port_ptr)
-       char *p;
-       int not_host;
-       int hostlen;
--
+@@ -2698,9 +2772,18 @@ char *check_for_hostspec(char *s, char **host_ptr, int *port_ptr)
+ {
+       char *path;
 -      if (port_ptr && strncasecmp(URL_PREFIX, s, strlen(URL_PREFIX)) == 0) {
-+      int url_prefix_len = sizeof URL_PREFIX - 1;
-+
-+      if (!port_ptr)
-+              url_prefix_len = 0;
-+      else if (strncasecmp(URL_PREFIX, s, url_prefix_len) != 0) {
-+#ifdef HAVE_OPENSSL
-+              url_prefix_len = sizeof SSL_URL_PREFIX - 1;
-+              if (strncasecmp(SSL_URL_PREFIX, s, url_prefix_len) != 0)
-+                      url_prefix_len = 0;
-+              else {
+-              *host_ptr = parse_hostspec(s + strlen(URL_PREFIX), &path, port_ptr);
+-              if (*host_ptr) {
++      if (port_ptr) {
++              int url_prefix_len;
++              if (strncasecmp(URL_PREFIX, s, sizeof URL_PREFIX - 1) == 0)
++                      url_prefix_len = sizeof URL_PREFIX - 1;
++              else if (strncasecmp(SSL_URL_PREFIX, s, sizeof SSL_URL_PREFIX - 1) == 0) {
 +                      if (!use_ssl)
 +                              init_tls();
 +                      use_ssl = 1;
-+              }
-+#else
-+              url_prefix_len = 0;
-+#endif
-+      }
-+      if (url_prefix_len) {
-               char *path;
--              s += strlen(URL_PREFIX);
-+              s += url_prefix_len;
-               if ((p = strchr(s, '/')) != NULL) {
-                       hostlen = p - s;
-                       path = p + 1;
++                      url_prefix_len = sizeof SSL_URL_PREFIX - 1;
++              } else
++                      url_prefix_len = 0;
++              if (url_prefix_len && (*host_ptr = parse_hostspec(s + url_prefix_len, &path, port_ptr))) {
+                       if (!*port_ptr)
+                               *port_ptr = RSYNC_PORT;
+                       return path;
 diff --git a/rsync.h b/rsync.h
+index be7cf8a..7b7cc88 100644
 --- a/rsync.h
 +++ b/rsync.h
 @@ -31,6 +31,7 @@
@@ -433,9 +430,9 @@ diff --git a/rsync.h b/rsync.h
  #define URL_PREFIX "rsync://"
 +#define SSL_URL_PREFIX "rsyncs://"
  
- #define SYMLINK_PREFIX "/rsyncd-munged/"
+ #define SYMLINK_PREFIX "/rsyncd-munged/"  /* This MUST have a trailing slash! */
  #define SYMLINK_PREFIX_LEN ((int)sizeof SYMLINK_PREFIX - 1)
-@@ -549,6 +550,11 @@ typedef unsigned int size_t;
+@@ -569,6 +570,11 @@ typedef unsigned int size_t;
  # define SIZEOF_INT64 SIZEOF_OFF_T
  #endif
  
@@ -449,9 +446,10 @@ diff --git a/rsync.h b/rsync.h
        int32 size, entries;
 diff --git a/ssl.c b/ssl.c
 new file mode 100644
+index 0000000..f0d4d9f
 --- /dev/null
 +++ b/ssl.c
-@@ -0,0 +1,370 @@
+@@ -0,0 +1,369 @@
 +/* -*- c-file-style: "linux" -*-
 + * ssl.c: operations for negotiating SSL rsync connections.
 + *
@@ -485,7 +483,6 @@ new file mode 100644
 +
 +#define BUF_SIZE 1024
 +
-+extern int verbose;
 +extern int am_daemon;
 +extern int am_server;
 +
@@ -571,7 +568,7 @@ new file mode 100644
 +              cbs = buf;
 +              break;
 +      }
-+      if (verbose > 2) {
++      if (DEBUG_GTE(CONNECT, 1)) {
 +              rprintf(FLOG, "SSL: info_callback(%p,%s,%d)\n", ssl, cbs, val);
 +              if (cb == SSL_CB_HANDSHAKE_DONE) {
 +                      SSL_CIPHER_description(SSL_get_current_cipher((SSL*)ssl),
index 452181b..a0950d6 100644 (file)
@@ -9,20 +9,22 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/flist.c b/flist.c
+index 09b4fc5..a948194 100644
 --- a/flist.c
 +++ b/flist.c
-@@ -1408,6 +1408,7 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
+@@ -1466,6 +1466,7 @@ static struct file_struct *send_file_name(int f, struct file_list *flist,
  #endif
  #ifdef SUPPORT_XATTRS
                if (preserve_xattrs) {
 +                      sx.st.st_mode = file->mode;
-                       sx.xattr = NULL;
                        if (get_xattr(fname, &sx) < 0) {
                                io_error |= IOERR_GENERAL;
+                               return NULL;
 diff --git a/xattrs.c b/xattrs.c
+index 2d0e050..3c70d8a 100644
 --- a/xattrs.c
 +++ b/xattrs.c
-@@ -281,6 +281,10 @@ int get_xattr(const char *fname, stat_x *sxp)
+@@ -282,6 +282,10 @@ int get_xattr(const char *fname, stat_x *sxp)
  {
        sxp->xattr = new(item_list);
        *sxp->xattr = empty_xattr;
@@ -33,7 +35,7 @@ diff --git a/xattrs.c b/xattrs.c
        if (rsync_xal_get(fname, sxp->xattr) < 0) {
                free_xattr(sxp);
                return -1;
-@@ -864,6 +868,11 @@ int set_xattr(const char *fname, const struct file_struct *file,
+@@ -865,6 +869,11 @@ int set_xattr(const char *fname, const struct file_struct *file,
                return -1;
        }
  
index e9cd77c..5f0980b 100644 (file)
@@ -10,9 +10,10 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/compat.c b/compat.c
+index 6e00072..c9590cc 100644
 --- a/compat.c
 +++ b/compat.c
-@@ -33,6 +33,7 @@ extern int inplace;
+@@ -32,6 +32,7 @@ extern int inplace;
  extern int recurse;
  extern int use_qsort;
  extern int allow_inc_recurse;
@@ -20,7 +21,7 @@ diff --git a/compat.c b/compat.c
  extern int append_mode;
  extern int fuzzy_basis;
  extern int read_batch;
-@@ -187,6 +188,15 @@ void setup_protocol(int f_out,int f_in)
+@@ -186,6 +187,15 @@ void setup_protocol(int f_out,int f_in)
        if (read_batch)
                check_batch_flags();
  
@@ -37,14 +38,15 @@ diff --git a/compat.c b/compat.c
                if (append_mode == 1)
                        append_mode = 2;
 diff --git a/configure.in b/configure.in
+index bc7d4a7..61f9b05 100644
 --- a/configure.in
 +++ b/configure.in
-@@ -554,13 +554,40 @@ AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
-     strlcat strlcpy strtol mallinfo getgroups setgroups geteuid getegid \
+@@ -553,13 +553,40 @@ AC_CHECK_FUNCS(waitpid wait4 getcwd strdup chown chmod lchmod mknod mkfifo \
      setlocale setmode open64 lseek64 mkstemp64 mtrace va_copy __va_copy \
      strerror putenv iconv_open locale_charset nl_langinfo getxattr \
--    extattr_get_link sigaction sigprocmask setattrlist)
-+    extattr_get_link sigaction sigprocmask setattrlist fallocate posix_fallocate)
+     extattr_get_link sigaction sigprocmask setattrlist getgrouplist \
+-    initgroups)
++    initgroups fallocate posix_fallocate)
  
  dnl cygwin iconv.h defines iconv_open as libiconv_open
  if test x"$ac_cv_func_iconv_open" != x"yes"; then
@@ -82,6 +84,7 @@ diff --git a/configure.in b/configure.in
  if test $ac_cv_func_getpgrp = yes; then
      AC_FUNC_GETPGRP
 diff --git a/options.c b/options.c
+index e7c6c61..6f848f1 100644
 --- a/options.c
 +++ b/options.c
 @@ -73,6 +73,7 @@ int remove_source_files = 0;
@@ -92,7 +95,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 */
-@@ -225,6 +226,7 @@ static void print_rsync_version(enum logcode f)
+@@ -566,6 +567,7 @@ static void print_rsync_version(enum logcode f)
        char const *links = "no ";
        char const *iconv = "no ";
        char const *ipv6 = "no ";
@@ -100,7 +103,7 @@ diff --git a/options.c b/options.c
        STRUCT_STAT *dumstat;
  
  #if SUBPROTOCOL_VERSION != 0
-@@ -258,6 +260,9 @@ static void print_rsync_version(enum logcode f)
+@@ -599,6 +601,9 @@ static void print_rsync_version(enum logcode f)
  #if defined HAVE_LUTIMES && defined HAVE_UTIMES
        symtimes = "";
  #endif
@@ -110,7 +113,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);
-@@ -271,8 +276,8 @@ static void print_rsync_version(enum logcode f)
+@@ -612,8 +617,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 +124,7 @@ diff --git a/options.c b/options.c
  
  #ifdef MAINTAINER_MODE
        rprintf(f, "Panic Action: \"%s\"\n", get_panic_action());
-@@ -359,6 +364,9 @@ void usage(enum logcode F)
+@@ -703,6 +708,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,7 +134,7 @@ 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");
-@@ -543,6 +551,7 @@ static struct poptOption long_options[] = {
+@@ -899,6 +907,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 },
@@ -139,7 +142,7 @@ diff --git a/options.c b/options.c
    {"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 },
-@@ -2063,6 +2072,9 @@ void server_options(char **args, int *argc_p)
+@@ -2609,6 +2618,9 @@ void server_options(char **args, int *argc_p)
        else if (remove_source_files)
                args[ac++] = "--remove-sent-files";
  
@@ -150,16 +153,17 @@ diff --git a/options.c b/options.c
                rprintf(FERROR, "argc overflow in server_options().\n");
                exit_cleanup(RERR_MALLOC);
 diff --git a/receiver.c b/receiver.c
+index 4325e30..739a0ba 100644
 --- a/receiver.c
 +++ b/receiver.c
-@@ -45,6 +45,7 @@ extern int cleanup_got_literal;
+@@ -44,6 +44,7 @@ extern int cleanup_got_literal;
  extern int remove_source_files;
  extern int append_mode;
  extern int sparse_files;
 +extern int preallocate_files;
  extern int keep_partial;
+ extern int checksum_len;
  extern int checksum_seed;
- extern int inplace;
 @@ -175,6 +176,18 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
        char *data;
        int32 i;
@@ -179,27 +183,28 @@ diff --git a/receiver.c b/receiver.c
  
        read_sum_head(f_in, &sum);
  
-@@ -285,7 +298,15 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
+@@ -285,8 +298,14 @@ static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r,
                goto report_write_error;
  
  #ifdef HAVE_FTRUNCATE
 -      if (inplace && fd != -1
+-       && ftruncate(fd, offset) < 0) {
 +      /* inplace: New data could be shorter than old data.
 +       * preallocate_files: total_size could have been an overestimate.
 +       *     Cut off any extra preallocated zeros from dest file. */
-+      if (fd != -1
++      if ((inplace
 +#ifdef SUPPORT_PREALLOCATION
-+       && (inplace || preallocated_len > offset)
-+#else
-+       && inplace
++        || preallocated_len > offset
 +#endif
-        && ftruncate(fd, offset) < 0) {
++        ) && fd != -1 && ftruncate(fd, offset) < 0) {
                rsyserr(FERROR_XFER, errno, "ftruncate failed on %s",
                        full_fname(fname));
+       }
 diff --git a/rsync.h b/rsync.h
+index be7cf8a..0ad3075 100644
 --- a/rsync.h
 +++ b/rsync.h
-@@ -614,6 +614,13 @@ struct ht_int64_node {
+@@ -634,6 +634,13 @@ struct ht_int64_node {
  #define ACLS_NEED_MASK 1
  #endif
  
@@ -214,9 +219,10 @@ diff --git a/rsync.h b/rsync.h
        int32 num;
        uint32 unum;
 diff --git a/rsync.yo b/rsync.yo
+index 941f7a5..36a2077 100644
 --- a/rsync.yo
 +++ b/rsync.yo
-@@ -356,6 +356,7 @@ to the detailed description below for a complete description.  verb(
+@@ -359,6 +359,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
@@ -224,7 +230,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
-@@ -1053,6 +1054,18 @@ NOTE: Don't use this option when the destination is a Solaris "tmpfs"
+@@ -1120,6 +1121,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.
  
@@ -244,6 +250,7 @@ diff --git a/rsync.yo b/rsync.yo
  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
 diff --git a/syscall.c b/syscall.c
+index cfabc3e..81fb957 100644
 --- a/syscall.c
 +++ b/syscall.c
 @@ -29,6 +29,10 @@
@@ -280,6 +287,7 @@ diff --git a/syscall.c b/syscall.c
 +}
 +#endif
 diff --git a/t_stub.c b/t_stub.c
+index 02cfa69..52a7f02 100644
 --- a/t_stub.c
 +++ b/t_stub.c
 @@ -22,6 +22,7 @@
@@ -289,13 +297,14 @@ diff --git a/t_stub.c b/t_stub.c
 +int preallocate_files = 0;
  int module_id = -1;
  int relative_paths = 0;
- int human_readable = 0;
+ int module_dirlen = 0;
 diff --git a/util.c b/util.c
+index 0cafed6..20dd0d3 100644
 --- a/util.c
 +++ b/util.c
-@@ -25,6 +25,7 @@
+@@ -26,6 +26,7 @@
+ #include "inums.h"
  
- extern int verbose;
  extern int dry_run;
 +extern int preallocate_files;
  extern int module_id;
diff --git a/remote-option.diff b/remote-option.diff
deleted file mode 100644 (file)
index 481390d..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-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;
-+static int remote_option_alloc = 0;
-+int remote_option_cnt = 0;
-+const char **remote_options = NULL;
-+
- int verbose = 0;
- int quiet = 0;
- int output_motd = 1;
-@@ -388,6 +392,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");
-@@ -646,6 +651,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 },
-@@ -1141,6 +1147,26 @@ 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+2 >= remote_option_alloc) {
-+                              remote_option_alloc += 16;
-+                              remote_options = realloc_array(remote_options,
-+                                                      const char *, remote_option_alloc);
-+                              if (!remote_options)
-+                                      out_of_memory("parse_arguments");
-+                              if (!remote_option_cnt)
-+                                      remote_options[0] = "ARG0";
-+                      }
-+                      remote_options[++remote_option_cnt] = arg;
-+                      remote_options[remote_option_cnt+1] = NULL;
-+                      break;
-+
-               case OPT_WRITE_BATCH:
-                       /* batch_name is already set */
-                       write_batch = 1;
-@@ -2063,6 +2089,16 @@ void server_options(char **args, int *argc_p)
-       else if (remove_source_files)
-               args[ac++] = "--remove-sent-files";
-+      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];
-+      }
-+
-       if (ac > MAX_SERVER_ARGS) { /* Not possible... */
-               rprintf(FERROR, "argc overflow in server_options().\n");
-               exit_cleanup(RERR_MALLOC);
-diff --git a/pipe.c b/pipe.c
---- a/pipe.c
-+++ b/pipe.c
-@@ -28,6 +28,8 @@ 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 +141,15 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
-                       logfile_close();
-               }
-+              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
-@@ -416,6 +416,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
-@@ -1030,16 +1031,16 @@ 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 both the source and the destination.
-+If you wish a local copy to enable this option just for the destination
-+files, specify bf(-M--fake-super).  If you wish a local copy to enable
-+this option just for the source files, combine bf(--fake-super) with
-+bf(-M--super).
- This option is overridden by both bf(--super) and bf(--no-super).
-@@ -1292,6 +1293,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(--protect-args)
-+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
-@@ -1768,7 +1799,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.
index 39ec240..fa29d74 100644 (file)
@@ -15,17 +15,18 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/flist.c b/flist.c
+index 09b4fc5..a8847a2 100644
 --- a/flist.c
 +++ b/flist.c
-@@ -69,6 +69,7 @@ extern int munge_symlinks;
- extern int need_unsorted_flist;
- extern int sender_symlink_iconv;
+@@ -71,6 +71,7 @@ extern int sender_symlink_iconv;
+ extern int output_needs_newline;
+ extern int sender_keeps_checksum;
  extern int unsort_ndx;
 +extern unsigned long sleep_asec;
  extern struct stats stats;
  extern char *filesfrom_host;
-@@ -1631,6 +1632,9 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len,
+ extern char *usermap, *groupmap;
+@@ -1704,6 +1705,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);
@@ -36,9 +37,10 @@ diff --git a/flist.c b/flist.c
  
        fbuf[len] = '\0';
 diff --git a/options.c b/options.c
+index e7c6c61..762a167 100644
 --- a/options.c
 +++ b/options.c
-@@ -109,6 +109,7 @@ int size_only = 0;
+@@ -108,6 +108,7 @@ int size_only = 0;
  int daemon_bwlimit = 0;
  int bwlimit = 0;
  int fuzzy_basis = 0;
@@ -46,7 +48,7 @@ diff --git a/options.c b/options.c
  size_t bwlimit_writemax = 0;
  int ignore_existing = 0;
  int ignore_non_existing = 0;
-@@ -425,6 +426,7 @@ void usage(enum logcode F)
+@@ -775,6 +776,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 +56,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");
-@@ -605,6 +607,7 @@ static struct poptOption long_options[] = {
+@@ -963,6 +965,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 6c6bc4e..4284227 100644 (file)
--- a/slp.diff
+++ b/slp.diff
@@ -11,6 +11,7 @@ TODO: the configure changes should abort if the user requests --enable-slp
 and we can't honor that request.
 
 diff --git a/Makefile.in b/Makefile.in
+index feacb90..09e1547 100644
 --- a/Makefile.in
 +++ b/Makefile.in
 @@ -13,6 +13,8 @@ CFLAGS=@CFLAGS@
@@ -22,7 +23,7 @@ diff --git a/Makefile.in b/Makefile.in
  
  INSTALLCMD=@INSTALL@
  INSTALLMAN=@INSTALL@
-@@ -37,7 +39,7 @@ OBJS1=flist.o rsync.o generator.o receiver.o cleanup.o sender.o exclude.o \
+@@ -38,7 +40,7 @@ OBJS1=flist.o rsync.o generator.o receiver.o cleanup.o sender.o exclude.o \
  OBJS2=options.o io.o compat.o hlink.o token.o uidlist.o socket.o hashtable.o \
        fileio.o batch.o clientname.o chmod.o acls.o xattrs.o
  OBJS3=progress.o pipe.o
@@ -31,7 +32,7 @@ diff --git a/Makefile.in b/Makefile.in
  popt_OBJS=popt/findme.o  popt/popt.o  popt/poptconfig.o \
        popt/popthelp.o popt/poptparse.o
  OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) $(ZLIBOBJ) @BUILD_POPT@
-@@ -73,7 +75,7 @@ install-strip:
+@@ -74,7 +76,7 @@ install-strip:
        $(MAKE) INSTALL_STRIP='-s' install
  
  rsync$(EXEEXT): $(OBJS)
@@ -41,9 +42,10 @@ diff --git a/Makefile.in b/Makefile.in
  $(OBJS): $(HEADERS)
  $(CHECK_OBJS): $(HEADERS)
 diff --git a/clientserver.c b/clientserver.c
+index b6afe00..a242809 100644
 --- a/clientserver.c
 +++ b/clientserver.c
-@@ -1064,6 +1064,13 @@ int daemon_main(void)
+@@ -1153,6 +1153,13 @@ int daemon_main(void)
         * address too.  In fact, why not just do inet_ntop on the
         * local address??? */
  
@@ -58,9 +60,10 @@ diff --git a/clientserver.c b/clientserver.c
        return -1;
  }
 diff --git a/configure.in b/configure.in
+index bc7d4a7..f8dc177 100644
 --- a/configure.in
 +++ b/configure.in
-@@ -639,6 +639,29 @@ if test $rsync_cv_can_hardlink_special = yes; then
+@@ -647,6 +647,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
  
@@ -91,42 +94,44 @@ diff --git a/configure.in b/configure.in
  AC_TRY_RUN([
  #include <sys/types.h>
 diff --git a/loadparm.c b/loadparm.c
+index 8e48e6d..a833006 100644
 --- a/loadparm.c
 +++ b/loadparm.c
-@@ -111,6 +111,9 @@ typedef struct
+@@ -97,6 +97,9 @@ typedef struct {
        char *socket_options;
  
        int rsync_port;
 +#ifdef HAVE_LIBSLP
 +      int slp_refresh;
 +#endif
- } global;
+ } global_vars;
  
- static global Globals;
-@@ -302,6 +305,9 @@ static struct parm_struct parm_table[] =
-  {"motd file",         P_STRING, P_GLOBAL,&Globals.motd_file,          NULL,0},
-  {"pid file",          P_STRING, P_GLOBAL,&Globals.pid_file,           NULL,0},
-  {"port",              P_INTEGER,P_GLOBAL,&Globals.rsync_port,         NULL,0},
+ /* This structure describes a single section.  Their order must match the
+@@ -311,6 +314,9 @@ static struct parm_struct parm_table[] =
+  {"motd file",         P_STRING, P_GLOBAL,&Vars.g.motd_file,           NULL,0},
+  {"pid file",          P_STRING, P_GLOBAL,&Vars.g.pid_file,            NULL,0},
+  {"port",              P_INTEGER,P_GLOBAL,&Vars.g.rsync_port,          NULL,0},
 +#ifdef HAVE_LIBSLP
-+ {"slp refresh",       P_INTEGER,P_GLOBAL,&Globals.slp_refresh,        NULL,0},
++ {"slp refresh",       P_INTEGER,P_GLOBAL,&Vars.g.slp_refresh,         NULL,0},
 +#endif
-  {"socket options",    P_STRING, P_GLOBAL,&Globals.socket_options,     NULL,0},
+  {"socket options",    P_STRING, P_GLOBAL,&Vars.g.socket_options,      NULL,0},
  
-  {"auth users",        P_STRING, P_LOCAL, &sDefault.auth_users,        NULL,0},
-@@ -396,6 +402,9 @@ FN_GLOBAL_STRING(lp_pid_file, &Globals.pid_file)
- FN_GLOBAL_STRING(lp_socket_options, &Globals.socket_options)
+  {"auth users",        P_STRING, P_LOCAL, &Vars.l.auth_users,          NULL,0},
+@@ -392,6 +398,9 @@ FN_GLOBAL_STRING(lp_pid_file, &Vars.g.pid_file)
+ FN_GLOBAL_STRING(lp_socket_options, &Vars.g.socket_options)
  
- FN_GLOBAL_INTEGER(lp_rsync_port, &Globals.rsync_port)
+ FN_GLOBAL_INTEGER(lp_rsync_port, &Vars.g.rsync_port)
 +#ifdef HAVE_LIBSLP
-+FN_GLOBAL_INTEGER(lp_slp_refresh, &Globals.slp_refresh)
++FN_GLOBAL_INTEGER(lp_slp_refresh, &Vars.g.slp_refresh)
 +#endif
  
  FN_LOCAL_STRING(lp_auth_users, auth_users)
  FN_LOCAL_STRING(lp_charset, charset)
 diff --git a/main.c b/main.c
+index 2ef2f47..3535264 100644
 --- a/main.c
 +++ b/main.c
-@@ -1121,6 +1121,18 @@ static int start_client(int argc, char *argv[])
+@@ -1195,6 +1195,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);
@@ -146,9 +151,10 @@ diff --git a/main.c b/main.c
                        char *dummy_host;
                        int dummy_port = 0;
 diff --git a/options.c b/options.c
+index e7c6c61..dae5716 100644
 --- a/options.c
 +++ b/options.c
-@@ -225,6 +225,7 @@ static void print_rsync_version(enum logcode f)
+@@ -566,6 +566,7 @@ static void print_rsync_version(enum logcode f)
        char const *links = "no ";
        char const *iconv = "no ";
        char const *ipv6 = "no ";
@@ -156,7 +162,7 @@ diff --git a/options.c b/options.c
        STRUCT_STAT *dumstat;
  
  #if SUBPROTOCOL_VERSION != 0
-@@ -258,6 +259,9 @@ static void print_rsync_version(enum logcode f)
+@@ -599,6 +600,9 @@ static void print_rsync_version(enum logcode f)
  #if defined HAVE_LUTIMES && defined HAVE_UTIMES
        symtimes = "";
  #endif
@@ -166,7 +172,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);
-@@ -271,8 +275,8 @@ static void print_rsync_version(enum logcode f)
+@@ -612,8 +616,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);
@@ -178,9 +184,10 @@ diff --git a/options.c b/options.c
  #ifdef MAINTAINER_MODE
        rprintf(f, "Panic Action: \"%s\"\n", get_panic_action());
 diff --git a/rsync.h b/rsync.h
+index be7cf8a..8353124 100644
 --- a/rsync.h
 +++ b/rsync.h
-@@ -193,6 +193,10 @@
+@@ -194,6 +194,10 @@
  #define SIGNIFICANT_ITEM_FLAGS (~(\
        ITEM_BASIS_TYPE_FOLLOWS | ITEM_XNAME_FOLLOWS | ITEM_LOCAL_CHANGE))
  
@@ -192,6 +199,7 @@ diff --git a/rsync.h b/rsync.h
  #define CFN_KEEP_TRAILING_SLASH (1<<1)
  #define CFN_DROP_TRAILING_DOT_DIR (1<<2)
 diff --git a/rsync.yo b/rsync.yo
+index 941f7a5..1518b3f 100644
 --- a/rsync.yo
 +++ b/rsync.yo
 @@ -148,7 +148,12 @@ particular rsync daemon by leaving off the module name:
@@ -210,6 +218,7 @@ diff --git a/rsync.yo b/rsync.yo
  
 diff --git a/rsyncd.conf b/rsyncd.conf
 new file mode 100644
+index 0000000..971723f
 --- /dev/null
 +++ b/rsyncd.conf
 @@ -0,0 +1,3 @@
@@ -217,9 +226,10 @@ new file mode 100644
 +slp refresh = 300
 +
 diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo
+index d4978cd..318f0ec 100644
 --- a/rsyncd.conf.yo
 +++ b/rsyncd.conf.yo
-@@ -104,6 +104,15 @@ details on some of the options you may be able to set. By default no
+@@ -108,6 +108,15 @@ details on some of the options you may be able to set. By default no
  special socket options are set.  These settings can also be specified
  via the bf(--sockopts) command-line option.
  
@@ -235,7 +245,7 @@ diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo
  enddit()
  
  manpagesection(MODULE PARAMETERS)
-@@ -652,6 +661,7 @@ use chroot = yes
+@@ -739,6 +748,7 @@ use chroot = yes
  max connections = 4
  syslog facility = local5
  pid file = /var/run/rsyncd.pid
@@ -244,6 +254,7 @@ diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo
  [ftp]
          path = /var/ftp/./pub
 diff --git a/socket.c b/socket.c
+index 5df3a50..a4a2b0a 100644
 --- a/socket.c
 +++ b/socket.c
 @@ -530,6 +530,16 @@ void start_accept_loop(int port, int (*fn)(int, int))
@@ -289,29 +300,29 @@ diff --git a/socket.c b/socket.c
  
                /* close log file before the potentially very long select so
                 * file can be trimmed by another process instead of growing
-@@ -577,8 +598,18 @@ void start_accept_loop(int port, int (*fn)(int, int))
- #else
+@@ -578,7 +599,18 @@ void start_accept_loop(int port, int (*fn)(int, int))
                fds = deffds;
  #endif
--
--              if (select(maxfd + 1, &fds, NULL, NULL, NULL) != 1)
+-              if (select(maxfd + 1, &fds, NULL, NULL, NULL) < 1)
 +#ifdef HAVE_LIBSLP
 +              sel_ret = select(maxfd + 1, &fds, NULL, NULL,
 +                               slp_timeout ? &slp_tv : NULL);
 +              if (sel_ret == 0 && slp_timeout && time(NULL) > next_slp_refresh) {
-+                  rprintf(FINFO, "Service registration expired, refreshing it\n");
-+                  register_services();
-+                  next_slp_refresh = time(NULL) + slp_timeout;
++                      rprintf(FINFO, "Service registration expired, refreshing it\n");
++                      register_services();
++                      next_slp_refresh = time(NULL) + slp_timeout;
 +              }
 +#else
 +              sel_ret = select(maxfd + 1, &fds, NULL, NULL, NULL);
 +#endif
-+              if (sel_ret != 1)
++              if (sel_ret < 1)
                        continue;
  
                for (i = 0, fd = -1; sp[i] >= 0; i++) {
 diff --git a/srvloc.c b/srvloc.c
 new file mode 100644
+index 0000000..99eea16
 --- /dev/null
 +++ b/srvloc.c
 @@ -0,0 +1,103 @@
@@ -420,6 +431,7 @@ new file mode 100644
 +}
 diff --git a/srvreg.c b/srvreg.c
 new file mode 100644
+index 0000000..04afe60
 --- /dev/null
 +++ b/srvreg.c
 @@ -0,0 +1,128 @@
index c4ccd43..7892689 100644 (file)
@@ -11,6 +11,7 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/syscall.c b/syscall.c
+index cfabc3e..fbbd79e 100644
 --- a/syscall.c
 +++ b/syscall.c
 @@ -63,9 +63,14 @@ int do_symlink(const char *fname1, const char *fname2)
index 38386fb..e5e802a 100644 (file)
@@ -10,6 +10,7 @@ To use this patch, run these commands for a successful build:
 -- Matt McCutchen <hashproduct@gmail.com>
 
 diff --git a/options.c b/options.c
+index e7c6c61..77fb180 100644
 --- a/options.c
 +++ b/options.c
 @@ -33,6 +33,7 @@ extern struct filter_list_struct filter_list;
@@ -20,7 +21,7 @@ diff --git a/options.c b/options.c
  
  /**
   * If 1, send the whole file as literal data rather than trying to
-@@ -368,6 +369,7 @@ void usage(enum logcode F)
+@@ -712,6 +713,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 +29,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");
-@@ -608,6 +610,7 @@ static struct poptOption long_options[] = {
+@@ -966,6 +968,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 +37,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 },
-@@ -1967,6 +1970,8 @@ void server_options(char **args, int *argc_p)
+@@ -2484,6 +2487,8 @@ void server_options(char **args, int *argc_p)
                                goto oom;
                        args[ac++] = arg;
                }
@@ -44,19 +45,20 @@ diff --git a/options.c b/options.c
 +                      args[ac++] = "--source-backup";
        }
  
-       if (modify_window_set) {
+       /* --delete-missing-args needs the cooperation of both sides, but
 diff --git a/rsync.yo b/rsync.yo
+index 941f7a5..4080af2 100644
 --- a/rsync.yo
 +++ b/rsync.yo
-@@ -365,6 +365,7 @@ to the detailed description below for a complete description.  verb(
+@@ -368,6 +368,7 @@ to the detailed description below for a complete description.  verb(
       --existing              skip creating new files on receiver
       --ignore-existing       skip updating files that exist on receiver
       --remove-source-files   sender removes synchronized files (non-dir)
 +     --source-backup         ... and backs up those files
       --del                   an alias for --delete-during
       --delete                delete extraneous files from dest dirs
-      --delete-before         receiver deletes before transfer (default)
-@@ -1115,6 +1116,14 @@ dit(bf(--remove-source-files)) This tells rsync to remove from the sending
+      --delete-before         receiver deletes before xfer, not during
+@@ -1182,6 +1183,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.
  
@@ -72,6 +74,7 @@ diff --git a/rsync.yo b/rsync.yo
  receiving side (ones that aren't on the sending side), but only for the
  directories that are being synchronized.  You must have asked rsync to
 diff --git a/sender.c b/sender.c
+index bf8221d..102540c 100644
 --- a/sender.c
 +++ b/sender.c
 @@ -39,6 +39,7 @@ extern int protocol_version;
@@ -79,10 +82,10 @@ diff --git a/sender.c b/sender.c
  extern int updating_basis_file;
  extern int make_backups;
 +extern int make_source_backups;
- extern int do_progress;
  extern int inplace;
  extern int batch_fd;
-@@ -123,6 +124,7 @@ void successful_send(int ndx)
+ extern int write_batch;
+@@ -122,6 +123,7 @@ void successful_send(int ndx)
        char fname[MAXPATHLEN];
        struct file_struct *file;
        struct file_list *flist;
@@ -90,16 +93,16 @@ diff --git a/sender.c b/sender.c
  
        if (!remove_source_files)
                return;
-@@ -133,7 +135,11 @@ void successful_send(int ndx)
+@@ -132,7 +134,11 @@ void successful_send(int ndx)
                return;
        f_name(file, fname);
  
 -      if (do_unlink(fname) == 0) {
 +      if (make_source_backups)
-+              result = !make_backup(fname);
++              result = !make_backup(fname, True);
 +      else
 +              result = do_unlink(fname);
 +      if (result == 0) {
-               if (verbose > 1)
+               if (INFO_GTE(REMOVE, 1))
                        rprintf(FINFO, "sender removed %s\n", fname);
        } else
index 684186e..62a19aa 100644 (file)
@@ -31,9 +31,10 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/generator.c b/generator.c
+index 12007a1..88bd5e7 100644
 --- a/generator.c
 +++ b/generator.c
-@@ -62,6 +62,7 @@ extern int append_mode;
+@@ -64,6 +64,7 @@ extern int append_mode;
  extern int make_backups;
  extern int csum_length;
  extern int ignore_times;
@@ -41,7 +42,7 @@ diff --git a/generator.c b/generator.c
  extern int size_only;
  extern OFF_T max_size;
  extern OFF_T min_size;
-@@ -717,7 +718,7 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+@@ -524,7 +525,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)
  {
@@ -51,9 +52,10 @@ diff --git a/generator.c b/generator.c
  
        /* if always checksum is set then we use the checksum instead
 diff --git a/main.c b/main.c
+index 2ef2f47..e7b4a05 100644
 --- a/main.c
 +++ b/main.c
-@@ -136,7 +136,7 @@ pid_t wait_process(pid_t pid, int *status_ptr, int flags)
+@@ -140,7 +140,7 @@ pid_t wait_process(pid_t pid, int *status_ptr, int flags)
  }
  
  /* Wait for a process to exit, calling io_flush while waiting. */
@@ -63,17 +65,18 @@ diff --git a/main.c b/main.c
        pid_t waited_pid;
        int status;
 diff --git a/options.c b/options.c
+index e7c6c61..059bcbf 100644
 --- a/options.c
 +++ b/options.c
-@@ -106,6 +106,7 @@ int keep_partial = 0;
- int safe_symlinks = 0;
+@@ -105,6 +105,7 @@ int safe_symlinks = 0;
  int copy_unsafe_links = 0;
+ int munge_symlinks = 0;
  int size_only = 0;
 +int times_only = 0;
  int daemon_bwlimit = 0;
  int bwlimit = 0;
  int fuzzy_basis = 0;
-@@ -163,6 +164,8 @@ char *logfile_name = NULL;
+@@ -164,6 +165,8 @@ char *logfile_name = NULL;
  char *logfile_format = NULL;
  char *stdout_format = NULL;
  char *password_file = NULL;
@@ -82,15 +85,15 @@ diff --git a/options.c b/options.c
  char *rsync_path = RSYNC_PATH;
  char *backup_dir = NULL;
  char backup_dir_buf[MAXPATHLEN];
-@@ -389,6 +392,7 @@ void usage(enum logcode F)
-   rprintf(F,"     --contimeout=SECONDS    set daemon connection timeout in seconds\n");
+@@ -739,6 +742,7 @@ void usage(enum logcode F)
    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,"     --times-only            skip files that match in mod-time\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");
    rprintf(F," -y, --fuzzy                 find similar file for basis if no dest file\n");
-@@ -428,6 +432,8 @@ void usage(enum logcode F)
+@@ -778,6 +782,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 +102,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");
-@@ -531,6 +537,7 @@ static struct poptOption long_options[] = {
+@@ -887,6 +893,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,16 +110,16 @@ 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 },
-@@ -646,6 +653,8 @@ static struct poptOption long_options[] = {
+@@ -1007,6 +1014,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 },
 +  {"source-filter",    0,  POPT_ARG_STRING, &source_filter, 0, 0, 0 },
 +  {"dest-filter",      0,  POPT_ARG_STRING, &dest_filter, 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 },
-@@ -1635,6 +1644,16 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+@@ -2149,6 +2158,16 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                }
        }
  
@@ -133,9 +136,9 @@ diff --git a/options.c b/options.c
        if (files_from) {
                char *h, *p;
                int q;
-@@ -1969,6 +1988,25 @@ void server_options(char **args, int *argc_p)
-               }
-       }
+@@ -2493,6 +2512,25 @@ void server_options(char **args, int *argc_p)
+       else if (missing_args == 1 && !am_sender)
+               args[ac++] = "--ignore-missing-args";
  
 +      if (times_only && am_sender)
 +              args[ac++] = "--times-only";
@@ -160,9 +163,10 @@ diff --git a/options.c b/options.c
                if (asprintf(&arg, "--modify-window=%d", modify_window) < 0)
                        goto oom;
 diff --git a/pipe.c b/pipe.c
+index a33117c..43eea31 100644
 --- a/pipe.c
 +++ b/pipe.c
-@@ -167,3 +167,77 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
+@@ -180,3 +180,77 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
  
        return pid;
  }
@@ -172,7 +176,7 @@ diff --git a/pipe.c b/pipe.c
 +      pid_t pid;
 +      int pipefds[2];
 +
-+      if (verbose >= 2)
++      if (DEBUG_GTE(CMD, 1))
 +              print_child_argv("opening connection using:", command);
 +
 +      if (pipe(pipefds) < 0) {
@@ -216,7 +220,7 @@ diff --git a/pipe.c b/pipe.c
 +{
 +      pid_t pid;
 +
-+      if (verbose >= 2)
++      if (DEBUG_GTE(CMD, 1))
 +              print_child_argv("opening connection using:", command);
 +
 +      pid = do_fork();
@@ -241,6 +245,7 @@ diff --git a/pipe.c b/pipe.c
 +      return pid;
 +}
 diff --git a/receiver.c b/receiver.c
+index 4325e30..e5ede73 100644
 --- a/receiver.c
 +++ b/receiver.c
 @@ -52,6 +52,7 @@ extern int delay_updates;
@@ -249,18 +254,18 @@ diff --git a/receiver.c b/receiver.c
  extern char *tmpdir;
 +extern char *dest_filter;
  extern char *partial_dir;
- extern char *basis_dir[];
- extern struct file_list *cur_flist, *first_flist, *dir_flist;
-@@ -433,6 +434,8 @@ int recv_files(int f_in, char *local_name)
+ extern char *basis_dir[MAX_BASIS_DIRS+1];
+ extern char sender_file_sum[MAX_DIGEST_LEN];
+@@ -441,6 +442,8 @@ int recv_files(int f_in, char *local_name)
        const char *parent_dirname = "";
  #endif
        int ndx, recv_ok;
 +      pid_t pid = 0;
 +      char *filter_argv[MAX_FILTER_ARGS + 1];
  
-       if (verbose > 2)
+       if (DEBUG_GTE(RECV, 1))
                rprintf(FINFO, "recv_files(%d) starting\n", cur_flist->used);
-@@ -440,6 +443,23 @@ int recv_files(int f_in, char *local_name)
+@@ -448,6 +451,23 @@ int recv_files(int f_in, char *local_name)
        if (delay_updates)
                delayed_bits = bitbag_create(cur_flist->used + 1);
  
@@ -284,8 +289,8 @@ diff --git a/receiver.c b/receiver.c
        while (1) {
                cleanup_disable();
  
-@@ -706,6 +726,9 @@ int recv_files(int f_in, char *local_name)
-               else if (!am_server && verbose && do_progress)
+@@ -742,6 +762,9 @@ int recv_files(int f_in, char *local_name)
+               else if (!am_server && INFO_GTE(NAME, 1) && INFO_EQ(PROGRESS, 1))
                        rprintf(FINFO, "%s\n", fname);
  
 +              if (dest_filter)
@@ -294,7 +299,7 @@ diff --git a/receiver.c b/receiver.c
                /* recv file data */
                recv_ok = receive_data(f_in, fnamecmp, fd1, st.st_size,
                                       fname, fd2, F_LENGTH(file));
-@@ -720,6 +743,16 @@ int recv_files(int f_in, char *local_name)
+@@ -756,6 +779,16 @@ int recv_files(int f_in, char *local_name)
                        exit_cleanup(RERR_FILEIO);
                }
  
@@ -312,9 +317,10 @@ diff --git a/receiver.c b/receiver.c
                        if (partialptr == fname)
                                partialptr = NULL;
 diff --git a/rsync.h b/rsync.h
+index be7cf8a..8d78818 100644
 --- a/rsync.h
 +++ b/rsync.h
-@@ -137,6 +137,7 @@
+@@ -138,6 +138,7 @@
  #define IOERR_DEL_LIMIT (1<<2)
  
  #define MAX_ARGS 1000
@@ -323,9 +329,10 @@ diff --git a/rsync.h b/rsync.h
  #define MAX_SERVER_ARGS (MAX_BASIS_DIRS*2 + 100)
  
 diff --git a/rsync.yo b/rsync.yo
+index 941f7a5..edfad5e 100644
 --- a/rsync.yo
 +++ b/rsync.yo
-@@ -386,6 +386,7 @@ to the detailed description below for a complete description.  verb(
+@@ -394,6 +394,7 @@ to the detailed description below for a complete description.  verb(
       --contimeout=SECONDS    set daemon connection timeout in seconds
   -I, --ignore-times          don't skip files that match size and time
       --size-only             skip files that match in size
@@ -333,7 +340,7 @@ diff --git a/rsync.yo b/rsync.yo
       --modify-window=NUM     compare mod-times with reduced accuracy
   -T, --temp-dir=DIR          create temporary files in directory DIR
   -y, --fuzzy                 find similar file for basis if no dest file
-@@ -425,6 +426,8 @@ to the detailed description below for a complete description.  verb(
+@@ -434,6 +435,8 @@ to the detailed description below for a complete description.  verb(
       --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
@@ -342,7 +349,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)
-@@ -2055,6 +2058,33 @@ file previously generated by bf(--write-batch).
+@@ -2256,6 +2259,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.
  
@@ -377,9 +384,10 @@ diff --git a/rsync.yo b/rsync.yo
  is useful for creating a batch file that is compatible with an older
  version of rsync.  For instance, if rsync 2.6.4 is being used with the
 diff --git a/sender.c b/sender.c
+index bf8221d..f315f80 100644
 --- a/sender.c
 +++ b/sender.c
-@@ -43,6 +43,7 @@ extern int do_progress;
+@@ -42,6 +42,7 @@ extern int make_backups;
  extern int inplace;
  extern int batch_fd;
  extern int write_batch;
@@ -387,7 +395,7 @@ diff --git a/sender.c b/sender.c
  extern struct stats stats;
  extern struct file_list *cur_flist, *first_flist, *dir_flist;
  
-@@ -175,6 +176,26 @@ void send_files(int f_in, int f_out)
+@@ -174,6 +175,26 @@ void send_files(int f_in, int f_out)
        enum logcode log_code = log_before_transfer ? FLOG : FINFO;
        int f_xfer = write_batch < 0 ? batch_fd : f_out;
        int ndx, j;
@@ -412,9 +420,9 @@ diff --git a/sender.c b/sender.c
 +              }
 +      }
  
-       if (verbose > 2)
+       if (DEBUG_GTE(SEND, 1))
                rprintf(FINFO, "send_files starting\n");
-@@ -279,6 +300,7 @@ void send_files(int f_in, int f_out)
+@@ -299,6 +320,7 @@ void send_files(int f_in, int f_out)
                        exit_cleanup(RERR_PROTOCOL);
                }
  
@@ -422,7 +430,7 @@ diff --git a/sender.c b/sender.c
                fd = do_open(fname, O_RDONLY, 0);
                if (fd == -1) {
                        if (errno == ENOENT) {
-@@ -300,6 +322,33 @@ void send_files(int f_in, int f_out)
+@@ -320,6 +342,33 @@ void send_files(int f_in, int f_out)
                        continue;
                }
  
@@ -456,7 +464,7 @@ diff --git a/sender.c b/sender.c
                /* map the local file */
                if (do_fstat(fd, &st) != 0) {
                        io_error |= IOERR_GENERAL;
-@@ -350,6 +399,8 @@ void send_files(int f_in, int f_out)
+@@ -370,6 +419,8 @@ void send_files(int f_in, int f_out)
                        }
                }
                close(fd);
index 88f6110..bb8d199 100644 (file)
@@ -19,26 +19,28 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/fileio.c b/fileio.c
+index 0faa619..b76dc02 100644
 --- a/fileio.c
 +++ b/fileio.c
-@@ -26,6 +26,7 @@
+@@ -27,6 +27,7 @@
  #endif
  
  extern int sparse_files;
-+extern long sparse_files_block_size;
++extern int sparse_files_block_size;
  
  static char last_byte;
  static OFF_T sparse_seek = 0;
-@@ -115,7 +116,7 @@ int write_file(int f, char *buf, int len)
+@@ -116,7 +117,7 @@ int write_file(int f, char *buf, int 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);
++                      int len1 = MIN(len, sparse_files_block_size);
                        r1 = write_sparse(f, buf, len1);
                } else {
                        if (!wf_writeBuf) {
 diff --git a/options.c b/options.c
+index e7c6c61..a0fb2e7 100644
 --- a/options.c
 +++ b/options.c
 @@ -73,6 +73,7 @@ int remove_source_files = 0;
@@ -49,7 +51,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 */
-@@ -359,6 +360,7 @@ void usage(enum logcode F)
+@@ -703,6 +704,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");
@@ -57,7 +59,7 @@ 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");
-@@ -543,6 +545,7 @@ static struct poptOption long_options[] = {
+@@ -899,6 +901,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 },
@@ -65,7 +67,7 @@ diff --git a/options.c b/options.c
    {"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 },
-@@ -1901,6 +1904,12 @@ void server_options(char **args, int *argc_p)
+@@ -2416,6 +2419,12 @@ void server_options(char **args, int *argc_p)
                args[ac++] = arg;
        }
  
@@ -79,9 +81,10 @@ diff --git a/options.c b/options.c
                if (asprintf(&arg, "--timeout=%d", io_timeout) < 0)
                        goto oom;
 diff --git a/rsync.yo b/rsync.yo
+index 941f7a5..5fa8396 100644
 --- a/rsync.yo
 +++ b/rsync.yo
-@@ -356,6 +356,7 @@ to the detailed description below for a complete description.  verb(
+@@ -359,6 +359,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
@@ -89,7 +92,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
-@@ -1053,6 +1054,15 @@ NOTE: Don't use this option when the destination is a Solaris "tmpfs"
+@@ -1120,6 +1121,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.
  
index 143c34f..50e42a2 100644 (file)
@@ -8,17 +8,18 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/options.c b/options.c
+index e7c6c61..e0e0cda 100644
 --- a/options.c
 +++ b/options.c
-@@ -204,6 +204,7 @@ static int refused_delete, refused_archive_part, refused_compress;
- static int refused_partial, refused_progress, refused_delete_before;
+@@ -300,6 +300,7 @@ static int refused_partial, refused_progress, refused_delete_before;
  static int refused_delete_during;
  static int refused_inplace, refused_no_iconv;
+ static BOOL usermap_via_chown, groupmap_via_chown;
 +static char *stdout_buffering;
  static char *max_size_arg, *min_size_arg;
  static char tmp_partialdir[] = ".~tmp~";
  
-@@ -425,6 +426,7 @@ void usage(enum logcode F)
+@@ -775,6 +776,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,15 +27,15 @@ 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");
-@@ -646,6 +648,7 @@ static struct poptOption long_options[] = {
+@@ -1007,6 +1009,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 },
 +  {"stdout",           0,  POPT_ARG_STRING, &stdout_buffering, 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 },
-@@ -1276,6 +1279,13 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+@@ -1757,6 +1760,13 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                }
        }
  
@@ -45,6 +46,6 @@ diff --git a/options.c b/options.c
 +                      setvbuf(stdout, NULL, _IOLBF, 0);
 +      }
 +
-       if (human_readable && argc == 2 && !am_server) {
+       if (human_readable > 1 && argc == 2 && !am_server) {
                /* Allow the old meaning of 'h' (--help) on its own. */
                usage(FINFO);
index e0b0ce9..7e1fd66 100644 (file)
@@ -10,9 +10,10 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/io.c b/io.c
+index 6a89c8f..d248f0f 100644
 --- a/io.c
 +++ b/io.c
-@@ -54,6 +54,7 @@ extern int protocol_version;
+@@ -53,6 +53,7 @@ extern int protocol_version;
  extern int remove_source_files;
  extern int preserve_hard_links;
  extern struct stats stats;
@@ -49,9 +50,10 @@ diff --git a/io.c b/io.c
                if (!am_server && !am_daemon) {
                        rprintf(FERROR, "io timeout after %d seconds -- exiting\n",
 diff --git a/options.c b/options.c
+index e7c6c61..6e72c02 100644
 --- a/options.c
 +++ b/options.c
-@@ -113,6 +113,7 @@ size_t bwlimit_writemax = 0;
+@@ -112,6 +112,7 @@ size_t bwlimit_writemax = 0;
  int ignore_existing = 0;
  int ignore_non_existing = 0;
  int need_messages_from_generator = 0;
@@ -59,7 +61,7 @@ diff --git a/options.c b/options.c
  int max_delete = INT_MIN;
  OFF_T max_size = 0;
  OFF_T min_size = 0;
-@@ -425,6 +426,8 @@ void usage(enum logcode F)
+@@ -775,6 +776,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,16 +70,16 @@ 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");
-@@ -447,7 +450,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,
+@@ -798,7 +801,7 @@ enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
        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,
--      OPT_NO_D, OPT_APPEND, OPT_NO_ICONV,
-+      OPT_NO_D, OPT_APPEND, OPT_NO_ICONV, OPT_STOP_AT, OPT_TIME_LIMIT,
+       OPT_NO_D, OPT_APPEND, OPT_NO_ICONV, OPT_INFO, OPT_DEBUG,
+-      OPT_USERMAP, OPT_GROUPMAP, OPT_CHOWN,
++      OPT_USERMAP, OPT_GROUPMAP, OPT_CHOWN, OPT_STOP_AT, OPT_TIME_LIMIT,
        OPT_SERVER, OPT_REFUSED_BASE = 9000};
  
  static struct poptOption long_options[] = {
-@@ -627,6 +630,8 @@ static struct poptOption long_options[] = {
+@@ -988,6 +991,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 },
@@ -86,7 +88,7 @@ diff --git a/options.c b/options.c
    {"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 },
-@@ -1261,6 +1266,36 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+@@ -1742,6 +1747,36 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                        return 0;
  #endif
  
@@ -123,7 +125,7 @@ diff --git a/options.c b/options.c
                default:
                        /* A large opt value means that set_refuse_options()
                         * turned this option off. */
-@@ -1913,6 +1948,15 @@ void server_options(char **args, int *argc_p)
+@@ -2428,6 +2463,15 @@ void server_options(char **args, int *argc_p)
                args[ac++] = arg;
        }
  
@@ -140,9 +142,10 @@ diff --git a/options.c b/options.c
                args[ac++] = "--backup-dir";
                args[ac++] = backup_dir;
 diff --git a/rsync.yo b/rsync.yo
+index 941f7a5..6945d06 100644
 --- a/rsync.yo
 +++ b/rsync.yo
-@@ -422,6 +422,8 @@ to the detailed description below for a complete description.  verb(
+@@ -431,6 +431,8 @@ to the detailed description below for a complete description.  verb(
       --password-file=FILE    read daemon-access password from FILE
       --list-only             list the files instead of copying them
       --bwlimit=KBPS          limit I/O bandwidth; KBytes per second
@@ -151,7 +154,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
-@@ -2029,6 +2031,19 @@ transfer was too fast, it will wait before sending the next data block. The
+@@ -2230,6 +2232,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.
  
@@ -172,6 +175,7 @@ diff --git a/rsync.yo b/rsync.yo
  another identical destination with bf(--read-batch). See the "BATCH MODE"
  section for details, and also the bf(--only-write-batch) option.
 diff --git a/util.c b/util.c
+index 0cafed6..f3e2669 100644
 --- a/util.c
 +++ b/util.c
 @@ -123,6 +123,133 @@ NORETURN void overflow_exit(const char *str)
index 68bc269..c2fcc6b 100644 (file)
@@ -14,9 +14,10 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/flist.c b/flist.c
+index 09b4fc5..f69167e 100644
 --- a/flist.c
 +++ b/flist.c
-@@ -84,6 +84,9 @@ extern int filesfrom_convert;
+@@ -87,6 +87,9 @@ extern int filesfrom_convert;
  extern iconv_t ic_send, ic_recv;
  #endif
  
@@ -26,7 +27,7 @@ diff --git a/flist.c b/flist.c
  #define PTR_SIZE (sizeof (struct file_struct *))
  
  int io_error;
-@@ -619,6 +622,24 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
+@@ -651,6 +654,24 @@ static void send_file_entry(int f, const char *fname, struct file_struct *file,
                stats.total_size += F_LENGTH(file);
  }
  
@@ -51,7 +52,7 @@ diff --git a/flist.c b/flist.c
  static struct file_struct *recv_file_entry(struct file_list *flist,
                                           int xflags, int f)
  {
-@@ -687,6 +708,9 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+@@ -719,6 +740,9 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
        }
  #endif
  
@@ -62,9 +63,10 @@ diff --git a/flist.c b/flist.c
                clean_fname(thisname, 0);
  
 diff --git a/options.c b/options.c
+index e7c6c61..cd0891c 100644
 --- a/options.c
 +++ b/options.c
-@@ -184,6 +184,8 @@ int logfile_format_has_i = 0;
+@@ -190,6 +190,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 +75,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;
-@@ -432,6 +434,7 @@ void usage(enum logcode F)
+@@ -782,6 +784,7 @@ void usage(enum logcode F)
  #ifdef ICONV_OPTION
    rprintf(F,"     --iconv=CONVERT_SPEC    request charset conversion of filenames\n");
  #endif
@@ -81,7 +83,7 @@ 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");
-@@ -634,6 +637,7 @@ static struct poptOption long_options[] = {
+@@ -995,6 +998,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
@@ -89,7 +91,7 @@ diff --git a/options.c b/options.c
    {"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_VAL,    &allow_8bit_chars, 1, 0, 0 },
-@@ -1681,6 +1685,31 @@ int parse_arguments(int *argc_p, const char ***argv_p)
+@@ -2195,6 +2199,31 @@ int parse_arguments(int *argc_p, const char ***argv_p)
                }
        }
  
@@ -121,7 +123,7 @@ diff --git a/options.c b/options.c
        am_starting_up = 0;
  
        return 1;
-@@ -2063,6 +2092,12 @@ void server_options(char **args, int *argc_p)
+@@ -2609,6 +2638,12 @@ void server_options(char **args, int *argc_p)
        else if (remove_source_files)
                args[ac++] = "--remove-sent-files";
  
@@ -135,9 +137,10 @@ diff --git a/options.c b/options.c
                rprintf(FERROR, "argc overflow in server_options().\n");
                exit_cleanup(RERR_MALLOC);
 diff --git a/rsync.yo b/rsync.yo
+index 941f7a5..dda8608 100644
 --- a/rsync.yo
 +++ b/rsync.yo
-@@ -427,6 +427,7 @@ to the detailed description below for a complete description.  verb(
+@@ -436,6 +436,7 @@ to the detailed description below for a complete description.  verb(
       --read-batch=FILE       read a batched update from FILE
       --protocol=NUM          force an older protocol version to be used
       --iconv=CONVERT_SPEC    request charset conversion of filenames
@@ -145,7 +148,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
-@@ -2093,6 +2094,22 @@ daemon uses the charset specified in its "charset" configuration parameter
+@@ -2294,6 +2295,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 431cc6f..43852ce 100644 (file)
@@ -7,6 +7,7 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/syscall.c b/syscall.c
+index cfabc3e..c6deb7e 100644
 --- a/syscall.c
 +++ b/syscall.c
 @@ -23,6 +23,7 @@
diff --git a/usermap.diff b/usermap.diff
deleted file mode 100644 (file)
index a17bac8..0000000
+++ /dev/null
@@ -1,550 +0,0 @@
-This adds a --usermap and a --groupmap option.  See the man page for
-more details.
-
-To use this patch, run these commands for a successful build:
-
-    patch -p1 <patches/usermap.diff
-    ./configure                         (optional if already run)
-    make
-
-diff --git a/flist.c b/flist.c
---- a/flist.c
-+++ b/flist.c
-@@ -71,6 +71,7 @@ extern int sender_symlink_iconv;
- extern int unsort_ndx;
- extern struct stats stats;
- extern char *filesfrom_host;
-+extern char *usermap, *groupmap;
- extern char curr_dir[MAXPATHLEN];
-@@ -767,7 +768,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);
--                      else if (inc_recurse && am_root && !numeric_ids)
-+                      else if (inc_recurse && am_root && (!numeric_ids || usermap))
-                               uid = match_uid(uid);
-               }
-       }
-@@ -779,7 +780,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);
--                      else if (inc_recurse && (!am_root || !numeric_ids))
-+                      else if (inc_recurse && (!am_root || !numeric_ids || groupmap))
-                               gid = match_gid(gid, &gid_flags);
-               }
-       }
-@@ -2248,8 +2249,13 @@ struct file_list *recv_file_list(int f)
-       int64 start_read;
-       int save_verbose = verbose;
--      if (!first_flist)
-+      if (!first_flist) {
-               rprintf(FLOG, "receiving file list\n");
-+              if (usermap)
-+                      parse_name_map(usermap, 1);
-+              if (groupmap)
-+                      parse_name_map(groupmap, 0);
-+      }
-       if (show_filelist_p())
-               start_filelist_progress("receiving file list");
-       else if (inc_recurse && verbose && !am_server && !first_flist)
-diff --git a/options.c b/options.c
---- a/options.c
-+++ b/options.c
-@@ -167,6 +167,8 @@ char *rsync_path = RSYNC_PATH;
- char *backup_dir = NULL;
- char backup_dir_buf[MAXPATHLEN];
- char *sockopts = NULL;
-+char *usermap = NULL;
-+char *groupmap = NULL;
- int rsync_port = 0;
- int compare_dest = 0;
- int copy_dest = 0;
-@@ -385,6 +387,9 @@ 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");
-+  rprintf(F,"     --usermap=STRING        custom username mapping\n");
-+  rprintf(F,"     --groupmap=STRING       custom groupname mapping\n");
-+  rprintf(F,"     --chown=USER:GROUP      simple username/groupname mapping\n");
-   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");
-@@ -447,7 +452,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,
--      OPT_NO_D, OPT_APPEND, OPT_NO_ICONV,
-+      OPT_NO_D, OPT_APPEND, OPT_NO_ICONV, OPT_USERMAP, OPT_GROUPMAP, OPT_CHOWN,
-       OPT_SERVER, OPT_REFUSED_BASE = 9000};
- static struct poptOption long_options[] = {
-@@ -623,6 +628,9 @@ 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 },
-+  {"usermap",          0,  POPT_ARG_STRING, 0, OPT_USERMAP, 0, 0 },
-+  {"groupmap",         0,  POPT_ARG_STRING, 0, OPT_GROUPMAP, 0, 0 },
-+  {"chown",            0,  POPT_ARG_STRING, 0, OPT_CHOWN, 0, 0 },
-   {"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 },
-@@ -1229,6 +1237,43 @@ int parse_arguments(int *argc_p, const char ***argv_p)
-                       }
-                       break;
-+              case OPT_USERMAP:
-+                      if (usermap) {
-+                              snprintf(err_buf, sizeof err_buf,
-+                                  "You can only specify --usermap once.\n");
-+                              return 0;
-+                      }
-+                      usermap = (char *)poptGetOptArg(pc);
-+                      break;
-+
-+              case OPT_GROUPMAP:
-+                      if (groupmap) {
-+                              snprintf(err_buf, sizeof err_buf,
-+                                  "You can only specify --groupmap once.\n");
-+                              return 0;
-+                      }
-+                      groupmap = (char *)poptGetOptArg(pc);
-+                      break;
-+
-+              case OPT_CHOWN:
-+                      if (usermap || groupmap) {
-+                              snprintf(err_buf, sizeof err_buf,
-+                                  "You can only specify --chown once.\n");
-+                              return 0;
-+                      } else {
-+                              const char *chown = poptGetOptArg(pc);
-+                              int len;
-+                              if ((arg = strchr(chown, ':')) != NULL) {
-+                                      if (arg[1] && asprintf(&groupmap, "*:%s", arg+1) < 0)
-+                                              out_of_memory("parse_arguments");
-+                                      len = arg - chown;
-+                              } else
-+                                      len = strlen(chown);
-+                              if (len && asprintf(&usermap, "*:%.*s", len, chown) < 0)
-+                                      out_of_memory("parse_arguments");
-+                      }
-+                      break;
-+
-               case OPT_HELP:
-                       usage(FINFO);
-                       exit_cleanup(0);
-@@ -2007,6 +2052,18 @@ void server_options(char **args, int *argc_p)
-               args[ac++] = "--use-qsort";
-       if (am_sender) {
-+              if (usermap) {
-+                      if (asprintf(&arg, "--usermap=%s", usermap) < 0)
-+                              goto oom;
-+                      args[ac++] = arg;
-+              }
-+
-+              if (groupmap) {
-+                      if (asprintf(&arg, "--groupmap=%s", groupmap) < 0)
-+                              goto oom;
-+                      args[ac++] = arg;
-+              }
-+
-               if (ignore_existing)
-                       args[ac++] = "--ignore-existing";
-diff --git a/rsync.yo b/rsync.yo
---- a/rsync.yo
-+++ b/rsync.yo
-@@ -382,6 +382,9 @@ to the detailed description below for a complete description.  verb(
-      --delay-updates         put all updated files into place at end
-  -m, --prune-empty-dirs      prune empty directory chains from file-list
-      --numeric-ids           don't map uid/gid values by user/group name
-+     --usermap=STRING        custom username mapping
-+     --groupmap=STRING       custom groupname mapping
-+     --chown=USER:GROUP      simple username/groupname mapping
-      --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
-@@ -1624,6 +1627,57 @@ 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.
-+dit(bf(--usermap=STRING, --groupmap=STRING)) These options allow you to
-+specify users and groups that should be mapped to other values by the
-+receiving side.  The bf(STRING) is one or more bf(FROM):bf(TO) pairs of
-+values separated by commas.  Any matching bf(FROM) value from the sender is
-+replaced with a bf(TO) value from the receiver.  You may specify usernames
-+or user IDs for the bf(FROM) and bf(TO) values, and the bf(FROM) value may
-+also be a wild-card string, which will be matched against the sender's
-+names (wild-cards do NOT match against ID numbers, though see below for
-+why a '*' matches everything).  You may instead specify a range of ID
-+numbers via an inclusive range: LOW-HIGH.  For example:
-+
-+verb(  --usermap=0-99:nobody,wayne:admin,*:normal --groupmap=usr:1,1:usr)
-+
-+The first match in the list is the one that is used.  You should specify
-+all your user mappings using a single bf(--usermap) option, and/or all
-+your group mappings using a single bf(--groupmap) option.
-+
-+Note that the sender's name for the 0 user and group are not transmitted
-+to the receiver, so you should either match these values using a 0, or use
-+the names in effect on the receiving side (typically "root").  All other
-+bf(FROM) names match those in use on the sending side.  All bf(TO) names
-+match those in use on the receiving side.
-+
-+Any IDs that do not have a name on the sending side are treated as having an
-+empty name for the purpose of matching.  This allows them to be matched via
-+a "*" or using an empty name.  For instance:
-+
-+verb(  --usermap=:nobody --groupmap=*:nobody)
-+
-+When the bf(--numeric-ids) option is used,the sender does not send any
-+names, so all the IDs are treated as having an empty name.  This means that
-+you will need to specify numeric bf(FROM) values if you want to map these
-+nameless IDs to different values.
-+
-+For the bf(--usermap) option to have any effect, the bf(-o) (bf(--owner))
-+option must be used (or implied), and the receiver will need to be running
-+as a super-user (see also the bf(--fake-super) option).  For the bf(--groupmap)
-+option to have any effect, the bf(-g) (bf(--groups)) option must be used
-+(or implied), and the receiver will need to have permissions to set that
-+group.
-+
-+dit(bf(--chown=USER:GROUP)) This option forces all files to be owned by USER
-+with group GROUP.  This is a simpler interface than using bf(--usermap) and
-+bf(--groupmap) directly, but it is implemented using those options internally,
-+so you cannot mix them.  If either the USER or GROUP is empty, no mapping for
-+the omitted user/group will occur.  If GROUP is empty, the trailing colon may
-+be omitted, but if USER is empty, a leading colon must be supplied.
-+
-+If you specify "--chown=foo:bar, this is exactly the same as specifying
-+"--usermap=*:foo --groupmap=*:bar", only easier.
-+
- dit(bf(--timeout=TIMEOUT)) This option allows you to set a maximum I/O
- timeout in seconds. If no data is transferred for the specified time
- then rsync will exit. The default is 0, which means no timeout.
-diff --git a/support/mapfrom b/support/mapfrom
-new file mode 100755
---- /dev/null
-+++ b/support/mapfrom
-@@ -0,0 +1,5 @@
-+#!/usr/bin/perl
-+while (<>) {
-+    push @_, "$2:$1" if /^(\w+):[^:]+:(\d+)/;
-+}
-+print join(',', @_), "\n";
-diff --git a/support/mapto b/support/mapto
-new file mode 100755
---- /dev/null
-+++ b/support/mapto
-@@ -0,0 +1,5 @@
-+#!/usr/bin/perl
-+while (<>) {
-+    push @_, "$1:$2" if /^(\w+):[^:]+:(\d+)/;
-+}
-+print join(',', @_), "\n";
-diff --git a/uidlist.c b/uidlist.c
---- a/uidlist.c
-+++ b/uidlist.c
-@@ -24,6 +24,7 @@
-  * are special. */
- #include "rsync.h"
-+#include "ifuncs.h"
- #include "io.h"
- extern int verbose;
-@@ -32,6 +33,8 @@ extern int preserve_uid;
- extern int preserve_gid;
- extern int preserve_acls;
- extern int numeric_ids;
-+extern char *usermap;
-+extern char *groupmap;
- #ifdef HAVE_GETGROUPS
- # ifndef GETGROUPS_T
-@@ -41,6 +44,9 @@ extern int numeric_ids;
- #define GID_NONE ((gid_t)-1)
-+#define NFLAGS_WILD_NAME_MATCH (1<<0)
-+#define NFLAGS_NAME_MATCH (1<<1)
-+
- struct idlist {
-       struct idlist *next;
-       const char *name;
-@@ -48,8 +54,8 @@ struct idlist {
-       uint16 flags;
- };
--static struct idlist *uidlist;
--static struct idlist *gidlist;
-+static struct idlist *uidlist, *uidmap;
-+static struct idlist *gidlist, *gidmap;
- static struct idlist *add_to_list(struct idlist **root, id_t id, const char *name,
-                                 id_t id2, uint16 flags)
-@@ -84,22 +90,6 @@ static const char *gid_to_name(gid_t gid)
-       return NULL;
- }
--static uid_t map_uid(uid_t id, const char *name)
--{
--      uid_t uid;
--      if (id != 0 && name_to_uid(name, &uid))
--              return uid;
--      return id;
--}
--
--static gid_t map_gid(gid_t id, const char *name)
--{
--      gid_t gid;
--      if (id != 0 && name_to_gid(name, &gid))
--              return gid;
--      return id;
--}
--
- static int is_in_group(gid_t gid)
- {
- #ifdef HAVE_GETGROUPS
-@@ -159,34 +149,53 @@ static int is_in_group(gid_t gid)
- #endif
- }
--/* Add a uid to the list of uids.  Only called on receiving side. */
--static struct idlist *recv_add_uid(uid_t id, const char *name)
-+/* Add a uid/gid to its list of ids.  Only called on receiving side. */
-+static struct idlist *recv_add_id(struct idlist **idlist_ptr, struct idlist *idmap,
-+                                id_t id, const char *name)
- {
--      uid_t id2 = name ? map_uid(id, name) : id;
-       struct idlist *node;
-+      int flag;
-+      id_t id2;
--      node = add_to_list(&uidlist, id, name, id2, 0);
-+      if (!name)
-+              name = "";
--      if (verbose > 3) {
--              rprintf(FINFO, "uid %u(%s) maps to %u\n",
--                      (unsigned)id, name ? name : "", (unsigned)id2);
-+      for (node = idmap; node; node = node->next) {
-+              if (node->flags & NFLAGS_WILD_NAME_MATCH) {
-+                      if (!wildmatch(node->name, name))
-+                              continue;
-+              } else if (node->flags & NFLAGS_NAME_MATCH) {
-+                      if (strcmp(node->name, name) != 0)
-+                              continue;
-+              } else if (node->name) {
-+                      if (id < node->id || id > (unsigned long)node->name)
-+                              continue;
-+              } else {
-+                      if (node->id != id)
-+                              continue;
-+              }
-+              break;
-       }
-+      if (node)
-+              id2 = node->id2;
-+      else if (*name && id) {
-+              if (idlist_ptr == &uidlist) {
-+                      uid_t uid;
-+                      id2 = name_to_uid(name, &uid) ? uid : id;
-+              } else {
-+                      gid_t gid;
-+                      id2 = name_to_gid(name, &gid) ? gid : id;
-+              }
-+      } else
-+              id2 = id;
--      return node;
--}
--
--/* Add a gid to the list of gids.  Only called on receiving side. */
--static struct idlist *recv_add_gid(gid_t id, const char *name)
--{
--      gid_t id2 = name ? map_gid(id, name) : id;
--      struct idlist *node;
--
--      node = add_to_list(&gidlist, id, name, id2,
--              !am_root && !is_in_group(id2) ? FLAG_SKIP_GROUP : 0);
-+      flag = idlist_ptr == &gidlist && !am_root && !is_in_group(id2) ? FLAG_SKIP_GROUP : 0;
-+      node = add_to_list(idlist_ptr, id, *name ? name : NULL, id2, flag);
-       if (verbose > 3) {
--              rprintf(FINFO, "gid %u(%s) maps to %u\n",
--                      (unsigned)id, name ? name : "", (unsigned)id2);
-+              rprintf(FINFO, "%sid %u(%s) maps to %u\n",
-+                      idlist_ptr == &uidlist ? "u" : "g",
-+                      (unsigned)id, name, (unsigned)id2);
-       }
-       return node;
-@@ -195,12 +204,9 @@ static struct idlist *recv_add_gid(gid_t id, const char *name)
- /* this function is a definate candidate for a faster algorithm */
- uid_t match_uid(uid_t uid)
- {
--      static uid_t last_in, last_out;
-+      static uid_t last_in = -1, last_out = -1;
-       struct idlist *list;
--      if (uid == 0)
--              return 0;
--
-       if (uid == last_in)
-               return last_out;
-@@ -208,10 +214,13 @@ uid_t match_uid(uid_t uid)
-       for (list = uidlist; list; list = list->next) {
-               if (list->id == uid)
--                      return last_out = list->id2;
-+                      break;
-       }
--      return last_out = uid;
-+      if (!list)
-+              list = recv_add_id(&uidlist, uidmap, uid, NULL);
-+
-+      return last_out = list->id2;
- }
- gid_t match_gid(gid_t gid, uint16 *flags_ptr)
-@@ -227,7 +236,7 @@ gid_t match_gid(gid_t gid, uint16 *flags_ptr)
-                               break;
-               }
-               if (!list)
--                      list = recv_add_gid(gid, NULL);
-+                      list = recv_add_id(&gidlist, gidmap, gid, NULL);
-               last = list;
-       }
-@@ -320,7 +329,7 @@ uid_t recv_user_name(int f, uid_t uid)
-               free(name);
-               name = NULL;
-       }
--      node = recv_add_uid(uid, name); /* node keeps name's memory */
-+      node = recv_add_id(&uidlist, uidmap, uid, name); /* node keeps name's memory */
-       return node->id2;
- }
-@@ -336,7 +345,7 @@ gid_t recv_group_name(int f, gid_t gid, uint16 *flags_ptr)
-               free(name);
-               name = NULL;
-       }
--      node = recv_add_gid(gid, name); /* node keeps name's memory */
-+      node = recv_add_id(&gidlist, gidmap, gid, name); /* node keeps name's memory */
-       if (flags_ptr && node->flags & FLAG_SKIP_GROUP)
-               *flags_ptr |= FLAG_SKIP_GROUP;
-       return node->id2;
-@@ -363,17 +372,103 @@ void recv_id_list(int f, struct file_list *flist)
-       /* Now convert all the uids/gids from sender values to our values. */
- #ifdef SUPPORT_ACLS
--      if (preserve_acls && !numeric_ids)
-+      if (preserve_acls && (!numeric_ids || usermap || groupmap))
-               match_acl_ids();
- #endif
--      if (am_root && preserve_uid && !numeric_ids) {
-+      if (am_root && preserve_uid && (!numeric_ids || usermap)) {
-               for (i = 0; i < flist->used; i++)
-                       F_OWNER(flist->files[i]) = match_uid(F_OWNER(flist->files[i]));
-       }
--      if (preserve_gid && (!am_root || !numeric_ids)) {
-+      if (preserve_gid && (!am_root || !numeric_ids || groupmap)) {
-               for (i = 0; i < flist->used; i++) {
-                       F_GROUP(flist->files[i]) = match_gid(F_GROUP(flist->files[i]),
-                                                            &flist->files[i]->flags);
-               }
-       }
- }
-+
-+void parse_name_map(char *map, int usernames)
-+{
-+      struct idlist **idmap_ptr = usernames ? &uidmap : &gidmap;
-+      struct idlist **idlist_ptr = usernames ? &uidlist : &gidlist;
-+      char *colon, *end, *name, *cp = map + strlen(map);
-+      id_t id1;
-+      uint16 flags;
-+
-+      /* Parse the list in reverse, so the order in the struct is right. */
-+      while (1) {
-+              end = cp;
-+              while (cp > map && cp[-1] != ',') cp--;
-+              if (!(colon = strchr(cp, ':'))) {
-+                      rprintf(FERROR, "No colon found in --%smap: %s\n",
-+                              usernames ? "user" : "group", cp);
-+                      exit_cleanup(RERR_SYNTAX);
-+              }
-+              if (!colon[1]) {
-+                      rprintf(FERROR, "No name found after colon --%smap: %s\n",
-+                              usernames ? "user" : "group", cp);
-+                      exit_cleanup(RERR_SYNTAX);
-+              }
-+              *colon = '\0';
-+
-+              if (isDigit(cp)) {
-+                      char *dash = strchr(cp, '-');
-+                      if (strspn(cp, "0123456789-") != (size_t)(colon - cp)
-+                       || (dash && (!dash[1] || strchr(dash+1, '-')))) {
-+                        bad_number:
-+                              rprintf(FERROR, "Invalid number in --%smap: %s\n",
-+                                      usernames ? "user" : "group", cp);
-+                              exit_cleanup(RERR_SYNTAX);
-+                      }
-+                      if (dash)
-+                              name = (char *)atol(dash+1);
-+                      else
-+                              name = (char *)0;
-+                      flags = 0;
-+                      id1 = atol(cp);
-+              } else if (strpbrk(cp, "*[?")) {
-+                      flags = NFLAGS_WILD_NAME_MATCH;
-+                      name = cp;
-+                      id1 = 0;
-+              } else {
-+                      flags = NFLAGS_NAME_MATCH;
-+                      name = cp;
-+                      id1 = 0;
-+              }
-+
-+              if (isDigit(colon+1)) {
-+                      if (strspn(colon+1, "0123456789") != (size_t)(end - colon - 1)) {
-+                              cp = colon+1;
-+                              goto bad_number;
-+                      }
-+                      add_to_list(idmap_ptr, id1, name, atol(colon+1), flags);
-+              } else if (usernames) {
-+                      uid_t uid;
-+                      if (name_to_uid(colon+1, &uid))
-+                              add_to_list(idmap_ptr, id1, name, uid, flags);
-+                      else {
-+                              rprintf(FERROR,
-+                                  "Unknown --usermap name on receiver: %s\n",
-+                                  colon+1);
-+                      }
-+              } else {
-+                      gid_t gid;
-+                      if (name_to_gid(colon+1, &gid))
-+                              add_to_list(idmap_ptr, id1, name, gid, flags);
-+                      else {
-+                              rprintf(FERROR,
-+                                  "Unknown --groupmap name on receiver: %s\n",
-+                                  colon+1);
-+                      }
-+              }
-+
-+              if (cp == map)
-+                      break;
-+
-+              *--cp = '\0'; /* replace comma */
-+      }
-+
-+      /* The 0 user/group doesn't get its name sent, so add it explicitly. */
-+      recv_add_id(idlist_ptr, *idmap_ptr, 0,
-+                  numeric_ids ? NULL : usernames ? uid_to_name(0) : gid_to_name(0));
-+}
index 4446c7c..6ec2f0c 100644 (file)
@@ -11,9 +11,10 @@ To use this patch, run these commands for a successful build:
     make
 
 diff --git a/compat.c b/compat.c
+index 1b66069..fb46fa5 100644
 --- a/compat.c
 +++ b/compat.c
-@@ -190,13 +190,6 @@ void setup_protocol(int f_out,int f_in)
+@@ -189,13 +189,6 @@ void setup_protocol(int f_out,int f_in)
        if (protocol_version < 30) {
                if (append_mode == 1)
                        append_mode = 2;
@@ -28,17 +29,18 @@ diff --git a/compat.c b/compat.c
  
        if (delete_mode && !(delete_before+delete_during+delete_after)) {
 diff --git a/xattrs.c b/xattrs.c
+index 2d0e050..b2017ed 100644
 --- a/xattrs.c
 +++ b/xattrs.c
-@@ -21,6 +21,7 @@
+@@ -22,6 +22,7 @@
  #include "rsync.h"
  #include "ifuncs.h"
+ #include "inums.h"
 +#include "io.h"
  #include "lib/sysxattrs.h"
  
  #ifdef SUPPORT_XATTRS
-@@ -33,6 +34,7 @@ extern int read_only;
+@@ -34,6 +35,7 @@ extern int read_only;
  extern int list_only;
  extern int preserve_xattrs;
  extern int checksum_seed;
@@ -46,7 +48,7 @@ diff --git a/xattrs.c b/xattrs.c
  
  #define RSYNC_XAL_INITIAL 5
  #define RSYNC_XAL_LIST_INITIAL 100
-@@ -246,7 +248,7 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
+@@ -247,7 +249,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 +57,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);
-@@ -348,7 +350,7 @@ static int find_matching_xattr(item_list *xalp)
+@@ -349,7 +351,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 +66,7 @@ diff --git a/xattrs.c b/xattrs.c
                                if (memcmp(rxas1[j].datum + 1,
                                           rxas2[j].datum + 1,
                                           MAX_DIGEST_LEN) != 0)
-@@ -385,13 +387,22 @@ int send_xattr(stat_x *sxp, int f)
+@@ -386,13 +388,22 @@ int send_xattr(stat_x *sxp, int f)
  {
        int ndx = find_matching_xattr(sxp->xattr);
  
@@ -90,7 +92,7 @@ diff --git a/xattrs.c b/xattrs.c
                for (rxa = sxp->xattr->items; count--; rxa++) {
                        size_t name_len = rxa->name_len;
                        const char *name = rxa->name;
-@@ -410,8 +421,8 @@ int send_xattr(stat_x *sxp, int f)
+@@ -411,8 +422,8 @@ int send_xattr(stat_x *sxp, int f)
                                name_len += UPRE_LEN;
                        }
  #endif
@@ -101,7 +103,7 @@ diff --git a/xattrs.c b/xattrs.c
  #ifndef HAVE_LINUX_XATTRS
                        if (name_len > rxa->name_len) {
                                write_buf(f, USER_PREFIX, UPRE_LEN);
-@@ -419,7 +430,7 @@ int send_xattr(stat_x *sxp, int f)
+@@ -420,7 +431,7 @@ int send_xattr(stat_x *sxp, int f)
                        }
  #endif
                        write_buf(f, name, name_len);
@@ -110,7 +112,7 @@ diff --git a/xattrs.c b/xattrs.c
                                write_buf(f, rxa->datum + 1, MAX_DIGEST_LEN);
                        else
                                write_buf(f, rxa->datum, rxa->datum_len);
-@@ -469,7 +480,7 @@ int xattr_diff(struct file_struct *file, stat_x *sxp, int find_all)
+@@ -470,7 +481,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;
@@ -119,7 +121,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;
-@@ -514,6 +525,9 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
+@@ -515,6 +526,9 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
        int cnt, prior_req = 0;
        rsync_xa *rxa;
  
@@ -129,7 +131,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)
-@@ -570,6 +584,9 @@ int recv_xattr_request(struct file_struct *file, int f_in)
+@@ -571,6 +585,9 @@ int recv_xattr_request(struct file_struct *file, int f_in)
        rsync_xa *rxa;
        int rel_pos, cnt, num, got_xattr_data = 0;
  
@@ -139,7 +141,7 @@ 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);
-@@ -632,7 +649,22 @@ void receive_xattr(struct file_struct *file, int f)
+@@ -633,7 +650,22 @@ void receive_xattr(struct file_struct *file, int f)
  #else
        int need_sort = 1;
  #endif
@@ -163,7 +165,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"
-@@ -645,7 +677,7 @@ void receive_xattr(struct file_struct *file, int f)
+@@ -646,7 +678,7 @@ void receive_xattr(struct file_struct *file, int f)
                return;
        }
        
@@ -172,7 +174,7 @@ diff --git a/xattrs.c b/xattrs.c
                (void)EXPAND_ITEM_LIST(&temp_xattr, rsync_xa, count);
                temp_xattr.count = 0;
        }
-@@ -653,9 +685,10 @@ void receive_xattr(struct file_struct *file, int f)
+@@ -654,9 +686,10 @@ void receive_xattr(struct file_struct *file, int f)
        for (num = 1; num <= count; num++) {
                char *ptr, *name;
                rsync_xa *rxa;