The patches for 3.0.0pre9.
authorWayne Davison <wayned@samba.org>
Mon, 11 Feb 2008 04:20:31 +0000 (04:20 +0000)
committerWayne Davison <wayned@samba.org>
Mon, 11 Feb 2008 04:20:31 +0000 (04:20 +0000)
32 files changed:
acls.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 [new file with mode: 0644]
date-only.diff
detect-renamed-lax.diff
detect-renamed.diff
downdate.diff
drop-cache.diff
flags.diff
fsync.diff
ignore-case.diff
link-by-hash.diff
log-checksum.diff
nameconverter.diff
omit-dir-changes.diff
openssl-support.diff
preallocate.diff
slow-down.diff
slp.diff
soften-links.diff
source-backup.diff
source-filter_dest-filter.diff
time-limit.diff
transliterate.diff
usermap.diff
xattrs.diff

index d1f8cd3..a18be5a 100644 (file)
--- a/acls.diff
+++ b/acls.diff
@@ -324,7 +324,7 @@ diff --git a/acls.c b/acls.c
 diff --git a/compat.c b/compat.c
 --- a/compat.c
 +++ b/compat.c
-@@ -175,13 +175,6 @@ void setup_protocol(int f_out,int f_in)
+@@ -177,13 +177,6 @@ void setup_protocol(int f_out,int f_in)
        if (protocol_version < 30) {
                if (append_mode == 1)
                        append_mode = 2;
index d897f8a..a27692b 100644 (file)
@@ -1,12 +1,9 @@
 To use this patch, run these commands for a successful build:
 
     patch -p1 <patches/atimes.diff
-    ./prepare-source
     ./configure                      (optional if already run)
     make
 
-TODO:  need to fix this to handle 64-bit time_t values!
-
 diff --git a/compat.c b/compat.c
 --- a/compat.c
 +++ b/compat.c
@@ -32,7 +29,7 @@ diff --git a/compat.c b/compat.c
        if (preserve_gid)
                gid_ndx = ++file_extra_cnt;
 +      if (preserve_atimes)
-+              atimes_ndx = ++file_extra_cnt;
++              atimes_ndx = (file_extra_cnt += TIME_EXTRA_CNT);
        if (preserve_acls && !am_sender)
                acls_ndx = ++file_extra_cnt;
        if (preserve_xattrs)
@@ -47,20 +44,21 @@ diff --git a/flist.c b/flist.c
  extern int relative_paths;
  extern int implied_dirs;
  extern int file_extra_cnt;
-@@ -343,6 +344,7 @@ int push_pathname(const char *dir, int len)
+@@ -342,7 +343,7 @@ int push_pathname(const char *dir, int len)
  static void send_file_entry(int f, struct file_struct *file, int ndx, int first_ndx)
  {
-       static time_t modtime;
-+      static time_t atime;
+-      static time_t modtime;
++      static time_t modtime, atime;
        static mode_t mode;
  #ifdef SUPPORT_HARD_LINKS
        static int64 dev;
-@@ -450,6 +452,13 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
+@@ -450,6 +451,13 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
                xflags |= XMIT_SAME_TIME;
        else
                modtime = file->modtime;
 +      if (atimes_ndx && !S_ISDIR(mode)) {
-+              time_t file_atime = F_ATIME(file);
++              time_t file_atime = f_atime(file);
 +              if (file_atime == atime)
 +                      xflags |= XMIT_SAME_ATIME;
 +              else
@@ -69,7 +67,7 @@ diff --git a/flist.c b/flist.c
  
  #ifdef SUPPORT_HARD_LINKS
        if (tmp_dev != 0) {
-@@ -522,6 +531,8 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
+@@ -522,6 +530,8 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
        }
        if (!(xflags & XMIT_SAME_MODE))
                write_int(f, to_wire_mode(mode));
@@ -78,7 +76,7 @@ diff --git a/flist.c b/flist.c
        if (uid_ndx && !(xflags & XMIT_SAME_UID)) {
                if (protocol_version < 30)
                        write_int(f, uid);
-@@ -608,7 +619,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
+@@ -608,7 +618,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
  static struct file_struct *recv_file_entry(struct file_list *flist,
                                           int xflags, int f)
  {
@@ -87,14 +85,14 @@ diff --git a/flist.c b/flist.c
        static mode_t mode;
  #ifdef SUPPORT_HARD_LINKS
        static int64 dev;
-@@ -741,6 +752,16 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+@@ -741,6 +751,16 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
        }
        if (!(xflags & XMIT_SAME_MODE))
                mode = from_wire_mode(read_int(f));
 +      if (atimes_ndx && !S_ISDIR(mode) && !(xflags & XMIT_SAME_ATIME)) {
 +              atime = read_varlong(f, 4);
 +#if SIZEOF_TIME_T < SIZEOF_INT64
-+              if ((atime > INT_MAX || atime < INT_MIN) && !am_generator) {
++              if (!am_generator && (int64)(time_t)atime != atime) {
 +                      rprintf(FERROR_XFER,
 +                              "Access time value of %s truncated on receiver.\n",
 +                              lastname);
@@ -104,63 +102,63 @@ diff --git a/flist.c b/flist.c
  
        if (chmod_modes && !S_ISLNK(mode))
                mode = tweak_mode(mode, chmod_modes);
-@@ -871,6 +892,8 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+@@ -871,6 +891,8 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                F_GROUP(file) = gid;
                file->flags |= gid_flags;
        }
 +      if (atimes_ndx)
-+              F_ATIME(file) = (uint32)atime;
++              f_atime_set(file, (time_t)atime);
        if (unsort_ndx)
                F_NDX(file) = flist->used + flist->ndx_start;
  
-@@ -1197,6 +1220,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1203,6 +1225,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
                F_OWNER(file) = st.st_uid;
        if (gid_ndx)
                F_GROUP(file) = st.st_gid;
 +      if (atimes_ndx)
-+              F_ATIME(file) = (uint32)st.st_atime;
++              f_atime_set(file, st.st_atime);
  
        if (basename != thisname)
                file->dirname = lastdir;
 diff --git a/generator.c b/generator.c
 --- a/generator.c
 +++ b/generator.c
-@@ -43,6 +43,7 @@ extern int preserve_specials;
- extern int preserve_hard_links;
- extern int preserve_perms;
- extern int preserve_times;
-+extern int preserve_atimes;
- extern int uid_ndx;
- extern int gid_ndx;
- extern int delete_mode;
-@@ -568,6 +569,9 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+@@ -21,6 +21,7 @@
+  */
+ #include "rsync.h"
++#include "ifuncs.h"
+ extern int verbose;
+ extern int dry_run;
+@@ -605,6 +606,9 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
                  && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
                 || (keep_time && cmp_time(file->modtime, sxp->st.st_mtime) != 0))
                        iflags |= ITEM_REPORT_TIME;
-+              if (preserve_atimes && !S_ISDIR(file->mode) && !S_ISLNK(file->mode)
-+               && cmp_time(F_ATIME(file), sxp->st.st_atime) != 0)
++              if (atimes_ndx && !S_ISDIR(file->mode) && !S_ISLNK(file->mode)
++               && cmp_time(f_atime(file), sxp->st.st_atime) != 0)
 +                      iflags |= ITEM_REPORT_ATIME;
  #if !defined HAVE_LCHMOD && !defined HAVE_SETATTRLIST
                if (S_ISLNK(file->mode)) {
                        ;
-@@ -921,6 +925,8 @@ static int try_dests_reg(struct file_struct *file, char *fname, int ndx,
+@@ -958,6 +962,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;
-+                      if (preserve_atimes)
++                      if (atimes_ndx)
 +                              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 (itemizing && (verbose > 1 || stdout_format_has_i > 1)) {
-@@ -1111,6 +1117,7 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx,
+@@ -1144,6 +1150,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;
++      time_t atime = atimes_ndx ? f_atime(f) : 0;
        double len;
  
        if (!F_IS_ACTIVE(f)) {
-@@ -1125,14 +1132,16 @@ static void list_file_entry(struct file_struct *f)
+@@ -1158,14 +1165,16 @@ static void list_file_entry(struct file_struct *f)
  
  #ifdef SUPPORT_LINKS
        if (preserve_links && S_ISLNK(f->mode)) {
@@ -179,7 +177,7 @@ diff --git a/generator.c b/generator.c
                        f_name(f, NULL));
        }
  }
-@@ -1882,7 +1891,7 @@ static void touch_up_dirs(struct file_list *flist, int ndx)
+@@ -1916,7 +1925,7 @@ static void touch_up_dirs(struct file_list *flist, int ndx)
                if (!(file->mode & S_IWUSR))
                        do_chmod(fname, file->mode);
                if (need_retouch_dir_times)
@@ -188,6 +186,38 @@ diff --git a/generator.c b/generator.c
                if (allowed_lull && !(counter % lull_mod))
                        maybe_send_keepalive();
                else if (!(counter & 0xFF))
+diff --git a/ifuncs.h b/ifuncs.h
+--- a/ifuncs.h
++++ b/ifuncs.h
+@@ -57,6 +57,28 @@ from_wire_mode(int mode)
+       return mode;
+ }
++static inline time_t
++f_atime(struct file_struct *fp)
++{
++#if SIZEOF_TIME_T > 4
++      time_t atime;
++      memcpy(&atime, &REQ_EXTRA(fp, atimes_ndx)->unum, SIZEOF_TIME_T);
++      return atime;
++#else
++      return REQ_EXTRA(fp, atimes_ndx)->unum;
++#endif
++}
++
++static inline void
++f_atime_set(struct file_struct *fp, time_t atime)
++{
++#if SIZEOF_TIME_T > 4
++      memcpy(&REQ_EXTRA(fp, atimes_ndx)->unum, &atime, SIZEOF_TIME_T);
++#else
++      REQ_EXTRA(fp, atimes_ndx)->unum = (uint32)atime;
++#endif
++}
++
+ static inline int
+ isDigit(const char *ptr)
+ {
 diff --git a/log.c b/log.c
 --- a/log.c
 +++ b/log.c
@@ -230,7 +260,7 @@ diff --git a/options.c b/options.c
    {"omit-dir-times",  'O', POPT_ARG_VAL,    &omit_dir_times, 1, 0, 0 },
    {"no-omit-dir-times",0,  POPT_ARG_VAL,    &omit_dir_times, 0, 0, 0 },
    {"no-O",             0,  POPT_ARG_VAL,    &omit_dir_times, 0, 0, 0 },
-@@ -1724,6 +1729,8 @@ void server_options(char **args, int *argc_p)
+@@ -1725,6 +1730,8 @@ void server_options(char **args, int *argc_p)
                argstr[x++] = 'D';
        if (preserve_times)
                argstr[x++] = 't';
@@ -242,15 +272,7 @@ diff --git a/options.c b/options.c
 diff --git a/rsync.c b/rsync.c
 --- a/rsync.c
 +++ b/rsync.c
-@@ -33,6 +33,7 @@ extern int preserve_acls;
- extern int preserve_xattrs;
- extern int preserve_perms;
- extern int preserve_executability;
-+extern int preserve_atimes;
- extern int preserve_times;
- extern int am_root;
- extern int am_server;
-@@ -344,6 +345,7 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
+@@ -344,6 +344,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;
@@ -258,7 +280,7 @@ diff --git a/rsync.c b/rsync.c
        mode_t new_mode = file->mode;
        int inherit;
  
-@@ -387,18 +389,36 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
+@@ -387,18 +388,36 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
                set_xattr(fname, file, fnamecmp, sxp);
  #endif
  
@@ -266,7 +288,7 @@ diff --git a/rsync.c b/rsync.c
 +       * how it uses the "updated" variable. */
        if (!preserve_times || (S_ISDIR(sxp->st.st_mode) && preserve_times == 1))
                flags |= ATTRS_SKIP_MTIME;
-+      if (!preserve_atimes || S_ISDIR(sxp->st.st_mode))
++      if (!atimes_ndx || S_ISDIR(sxp->st.st_mode))
 +              flags |= ATTRS_SKIP_ATIME;
        if (!(flags & ATTRS_SKIP_MTIME)
            && cmp_time(sxp->st.st_mtime, file->modtime) != 0) {
@@ -276,7 +298,7 @@ diff --git a/rsync.c b/rsync.c
 +      } else
 +              mtime = sxp->st.st_mtime;
 +      if (!(flags & ATTRS_SKIP_ATIME)) {
-+              time_t file_atime = F_ATIME(file);
++              time_t file_atime = f_atime(file);
 +              if (cmp_time(sxp->st.st_atime, file_atime) != 0) {
 +                      atime = file_atime;
 +                      updated = 1;
@@ -298,6 +320,24 @@ diff --git a/rsync.c b/rsync.c
        }
  
        change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
+@@ -528,7 +547,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,
+-                     ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
++                     ok_to_set_time ? 0 : ATTRS_SKIP_MTIME | ATTRS_SKIP_ATIME);
+       /* move tmp file over real file */
+       if (verbose > 2)
+@@ -555,7 +574,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
+   do_set_file_attrs:
+       set_file_attrs(fnametmp, file, NULL, fnamecmp,
+-                     ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
++                     ok_to_set_time ? 0 : ATTRS_SKIP_MTIME | ATTRS_SKIP_ATIME);
+       if (temp_copy_name) {
+               if (do_rename(fnametmp, fname) < 0) {
 diff --git a/rsync.h b/rsync.h
 --- a/rsync.h
 +++ b/rsync.h
@@ -317,7 +357,7 @@ diff --git a/rsync.h b/rsync.h
  
  #define FULL_FLUSH    1
  #define NORMAL_FLUSH  0
-@@ -618,6 +620,7 @@ extern int file_extra_cnt;
+@@ -619,12 +621,14 @@ extern int file_extra_cnt;
  extern int inc_recurse;
  extern int uid_ndx;
  extern int gid_ndx;
@@ -325,14 +365,13 @@ diff --git a/rsync.h b/rsync.h
  extern int acls_ndx;
  extern int xattrs_ndx;
  
-@@ -655,6 +658,7 @@ 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
-+#define F_ATIME(f) REQ_EXTRA(f, atimes_ndx)->unum
- #define F_ACL(f) REQ_EXTRA(f, acls_ndx)->num
- #define F_XATTR(f) REQ_EXTRA(f, xattrs_ndx)->num
- #define F_NDX(f) REQ_EXTRA(f, unsort_ndx)->num
+ #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)
++#define TIME_EXTRA_CNT ((SIZEOF_TIME_T + EXTRA_LEN - 1) / EXTRA_LEN)
+ #define DEV_EXTRA_CNT 2
+ #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
 --- a/rsync.yo
 +++ b/rsync.yo
@@ -344,7 +383,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
-@@ -974,6 +975,12 @@ it is preserving modification times (see bf(--times)).  If NFS is sharing
+@@ -987,6 +988,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).
  
@@ -357,7 +396,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
-@@ -1671,8 +1678,10 @@ quote(itemization(
+@@ -1687,8 +1694,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).
@@ -370,36 +409,23 @@ diff --git a/rsync.yo b/rsync.yo
    it() The bf(a) means that the ACL information changed.
    it() The bf(x) slot is reserved for reporting extended attribute changes
    (a feature that is not yet released).
-diff --git a/sender.c b/sender.c
---- a/sender.c
-+++ b/sender.c
-@@ -43,6 +43,7 @@ extern int do_progress;
- extern int inplace;
- extern int batch_fd;
- extern int write_batch;
-+extern unsigned int file_struct_len;
- extern struct stats stats;
- extern struct file_list *cur_flist, *first_flist, *dir_flist;
 diff --git a/testsuite/atimes.test b/testsuite/atimes.test
 new file mode 100644
 --- /dev/null
 +++ b/testsuite/atimes.test
-@@ -0,0 +1,19 @@
+@@ -0,0 +1,17 @@
 +#! /bin/sh
 +
 +# Test rsync copying atimes
 +
 +. "$suitedir/rsync.fns"
 +
-+set -x
-+
 +mkdir "$fromdir"
 +
 +touch "$fromdir/foo"
 +touch -a -t 200102031717.42 "$fromdir/foo"
 +
-+TLS_ARGS=--atime
++TLS_ARGS=--atimes
 +
 +checkit "$RSYNC -rtUgvvv \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
 +
@@ -412,7 +438,7 @@ diff --git a/testsuite/rsync.fns b/testsuite/rsync.fns
      # We can just write everything to stdout/stderr, because the
      # wrapper hides it unless there is a problem.
  
-+    if test x$TLS_ARGS = x--atime; then
++    if test x$TLS_ARGS = x--atimes; then
 +      ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
 +    fi
 +
@@ -423,7 +449,7 @@ diff --git a/testsuite/rsync.fns b/testsuite/rsync.fns
        failed="YES";
      fi
  
-+    if test x$TLS_ARGS != x--atime; then
++    if test x$TLS_ARGS != x--atimes; then
 +      ( cd "$2" && rsync_ls_lR . ) > "$tmpdir/ls-from"
 +    fi
 +
@@ -437,16 +463,16 @@ diff --git a/testsuite/rsync.fns b/testsuite/rsync.fns
 diff --git a/tls.c b/tls.c
 --- a/tls.c
 +++ b/tls.c
-@@ -104,6 +104,8 @@ static int stat_xattr(const char *fname, STRUCT_STAT *fst)
+@@ -105,6 +105,8 @@ static int stat_xattr(const char *fname, STRUCT_STAT *fst)
  
  #endif
  
-+static int display_atime = 0;
++static int display_atimes = 0;
 + 
  static void failed(char const *what, char const *where)
  {
        fprintf(stderr, PROGRAM ": %s %s: %s\n",
-@@ -111,12 +113,29 @@ static void failed(char const *what, char const *where)
+@@ -112,12 +114,29 @@ static void failed(char const *what, char const *where)
        exit(1);
  }
  
@@ -478,7 +504,7 @@ diff --git a/tls.c b/tls.c
        char linkbuf[4096];
  
        if (do_lstat(fname, &buf) < 0)
-@@ -153,19 +172,8 @@ static void list_file(const char *fname)
+@@ -154,19 +173,11 @@ static void list_file(const char *fname)
  
        permstring(permbuf, buf.st_mode);
  
@@ -496,11 +522,14 @@ diff --git a/tls.c b/tls.c
 -      } else
 -              strlcpy(datebuf, "                   ", sizeof datebuf);
 +      storetime(mtimebuf, buf.st_mtime, sizeof mtimebuf);
-+      storetime(atimebuf, buf.st_atime, sizeof atimebuf);
++      if (display_atimes)
++              storetime(atimebuf, S_ISDIR(buf.st_mode) ? 0 : buf.st_atime, sizeof atimebuf);
++      else
++              atimebuf[0] = '\0';
  
        /* TODO: Perhaps escape special characters in fname? */
  
-@@ -176,13 +184,15 @@ static void list_file(const char *fname)
+@@ -177,13 +188,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);
@@ -508,21 +537,20 @@ diff --git a/tls.c b/tls.c
 +      printf(" %6ld.%-6ld %6ld %s%s%s%s\n",
               (long)buf.st_uid, (long)buf.st_gid, (long)buf.st_nlink,
 -             datebuf, fname, linkbuf);
-+             mtimebuf, display_atime && !S_ISDIR(buf.st_mode) ? atimebuf : "",
-+             fname, linkbuf);
++             mtimebuf, atimebuf, fname, linkbuf);
  }
  
  static struct poptOption long_options[] = {
    /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
-+  {"atime",           'u', POPT_ARG_NONE,   &display_atime, 0, 0, 0},
++  {"atimes",          'U', POPT_ARG_NONE,   &display_atimes, 0, 0, 0},
  #ifdef SUPPORT_XATTRS
    {"fake-super",      'f', POPT_ARG_VAL,    &am_root, -1, 0, 0 },
  #endif
-@@ -196,6 +206,7 @@ static void tls_usage(int ret)
+@@ -197,6 +209,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");
-+  rprintf(F," -U, --atimes                display access (last-used) times\n");
++  fprintf(F," -U, --atimes                display access (last-used) times\n");
  #ifdef SUPPORT_XATTRS
    fprintf(F," -f, --fake-super            display attributes including fake-super xattrs\n");
  #endif
index 014c325..7198018 100644 (file)
@@ -106,7 +106,7 @@ diff --git a/backup.c b/backup.c
 diff --git a/generator.c b/generator.c
 --- a/generator.c
 +++ b/generator.c
-@@ -94,6 +94,9 @@ extern mode_t orig_umask;
+@@ -95,6 +95,9 @@ extern uid_t our_uid;
  extern char *backup_dir;
  extern char *backup_suffix;
  extern int backup_suffix_len;
@@ -116,10 +116,11 @@ diff --git a/generator.c b/generator.c
  extern struct file_list *cur_flist, *first_flist, *dir_flist;
  extern struct filter_list_struct server_filter_list;
  
-@@ -128,10 +131,14 @@ enum delret {
+@@ -136,10 +139,15 @@ enum delret {
+ /* Forward declaration for delete_item(). */
  static enum delret delete_dir_contents(char *fname, int flags);
  
++
 +/* Function now compares both backup_suffix and backup_suffix_dels. */
  static int is_backup_file(char *fn)
  {
@@ -132,7 +133,7 @@ diff --git a/generator.c b/generator.c
  }
  
  /* Delete a file or directory.  If DEL_RECURSE is set in the flags, this will
-@@ -167,9 +174,9 @@ static enum delret delete_item(char *fbuf, int mode, char *replace, int flags)
+@@ -178,9 +186,9 @@ static enum delret delete_item(char *fbuf, int mode, int flags)
        if (S_ISDIR(mode)) {
                what = "rmdir";
                ok = do_rmdir(fbuf) == 0;
@@ -191,7 +192,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 },
-@@ -1404,6 +1414,8 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1405,6 +1415,8 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
                        tmpdir = sanitize_path(NULL, tmpdir, NULL, 0);
                if (backup_dir)
                        backup_dir = sanitize_path(NULL, backup_dir, NULL, 0);
@@ -200,7 +201,7 @@ diff --git a/options.c b/options.c
        }
        if (server_filter_list.head && !am_sender) {
                struct filter_list_struct *elp = &server_filter_list;
-@@ -1425,6 +1437,14 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1426,6 +1438,14 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
                        if (check_filter(elp, dir, 1) < 0)
                                goto options_rejected;
                }
@@ -215,13 +216,12 @@ diff --git a/options.c b/options.c
        }
  
        if (!backup_suffix)
-@@ -1436,6 +1456,16 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1437,6 +1457,15 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
                        backup_suffix);
                return 0;
        }
-+      /* if backup_suffix_dels not supplied, default to backup_suffix */
 +      if (!backup_suffix_dels)
-+              backup_suffix_dels = backup_dir_dels ? "" : backup_suffix;
++              backup_suffix_dels = backup_dir_dels && !am_server ? "" : backup_suffix;
 +      backup_suffix_dels_len = strlen(backup_suffix_dels);
 +      if (strchr(backup_suffix_dels, '/') != NULL) {
 +              snprintf(err_buf, sizeof err_buf,
@@ -232,17 +232,11 @@ 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;
-@@ -1459,6 +1489,31 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1460,6 +1489,30 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
                        "P *%s", backup_suffix);
                parse_rule(&filter_list, backup_dir_buf, 0, 0);
        }
-+      /* If backup_dir_dels not supplied default to backup_dir if it has been supplied */
-+      if (backup_dir && !backup_dir_dels) {
-+              backup_dir_dels = backup_dir;
-+              backup_dir_dels_len = backup_dir_len;
-+              backup_dir_dels_remainder = backup_dir_remainder;
-+              strlcpy(backup_dir_dels_buf, backup_dir_buf, sizeof backup_dir_buf);
-+      } else if (backup_dir_dels) {
++      if (backup_dir_dels) {
 +              backup_dir_dels_len = strlcpy(backup_dir_dels_buf, backup_dir_dels, sizeof backup_dir_dels_buf);
 +              backup_dir_dels_remainder = sizeof backup_dir_dels_buf - backup_dir_dels_len;
 +              if (backup_dir_dels_remainder < 32) {
@@ -256,6 +250,11 @@ diff --git a/options.c b/options.c
 +              }
 +              if (verbose > 1 && !am_sender)
 +                      rprintf(FINFO, "backup_dir_dels is %s\n", backup_dir_dels_buf);
++      } else if (backup_dir) {
++              backup_dir_dels = backup_dir;
++              backup_dir_dels_len = backup_dir_len;
++              backup_dir_dels_remainder = backup_dir_remainder;
++              strlcpy(backup_dir_dels_buf, backup_dir_buf, sizeof backup_dir_buf);
 +      } else if (!backup_suffix_dels_len && (!am_server || !am_sender)) {
 +              snprintf(err_buf, sizeof err_buf,
 +                      "--suffix-dels cannot be a null string without --backup-dir-dels\n");
@@ -264,7 +263,7 @@ diff --git a/options.c b/options.c
  
        if (make_backups && !backup_dir) {
                omit_dir_times = 0; /* Implied, so avoid -O to sender. */
-@@ -1852,6 +1907,10 @@ void server_options(char **args, int *argc_p)
+@@ -1853,6 +1906,10 @@ void server_options(char **args, int *argc_p)
                args[ac++] = "--backup-dir";
                args[ac++] = backup_dir;
        }
@@ -275,13 +274,14 @@ 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) {
-@@ -1860,7 +1919,13 @@ void server_options(char **args, int *argc_p)
+@@ -1861,7 +1918,14 @@ void server_options(char **args, int *argc_p)
                        goto oom;
                args[ac++] = arg;
        }
 -
-+      /* Only send --suffix-dels if it specifies a non-default value. */
-+      if (strcmp(backup_suffix_dels, backup_dir_dels ? "" : BACKUP_SUFFIX) != 0) {
++      /* Only send --suffix-dels if it specifies a value different from the
++       * --suffix value, which would normally be used for deletions too. */
++      if (strcmp(backup_suffix_dels, backup_suffix) != 0) {
 +              /* We use the following syntax to avoid weirdness with '~'. */
 +              if (asprintf(&arg, "--suffix-dels=%s", backup_suffix_dels) < 0)
 +                      goto oom;
index 5cfea99..d968589 100644 (file)
@@ -51,7 +51,7 @@ diff --git a/log.c b/log.c
 diff --git a/main.c b/main.c
 --- a/main.c
 +++ b/main.c
-@@ -164,8 +164,11 @@ static void wait_process_with_flush(pid_t pid, int *exit_code_ptr)
+@@ -166,8 +166,11 @@ static void wait_process_with_flush(pid_t pid, int *exit_code_ptr)
                        *exit_code_ptr = RERR_TERMINATED;
                else
                        *exit_code_ptr = RERR_WAITCHILD;
@@ -64,7 +64,7 @@ diff --git a/main.c b/main.c
  }
  
  /* This function gets called from all 3 processes.  We want the client side
-@@ -1344,6 +1347,14 @@ RETSIGTYPE remember_children(UNUSED(int val))
+@@ -1346,6 +1349,14 @@ RETSIGTYPE remember_children(UNUSED(int val))
                                break;
                        }
                }
@@ -79,7 +79,7 @@ diff --git a/main.c b/main.c
        }
  #endif
  #ifndef HAVE_SIGACTION
-@@ -1402,6 +1413,12 @@ static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
+@@ -1404,6 +1415,12 @@ static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig))
  }
  #endif
  
@@ -92,7 +92,7 @@ diff --git a/main.c b/main.c
  
  int main(int argc,char *argv[])
  {
-@@ -1424,6 +1441,11 @@ int main(int argc,char *argv[])
+@@ -1426,6 +1443,11 @@ int main(int argc,char *argv[])
        SIGACTMASK(SIGFPE, rsync_panic_handler);
        SIGACTMASK(SIGABRT, rsync_panic_handler);
        SIGACTMASK(SIGBUS, rsync_panic_handler);
index 0a23786..d2a60b5 100644 (file)
@@ -223,7 +223,7 @@ diff --git a/flist.c b/flist.c
        struct file_struct *file;
        char thisname[MAXPATHLEN];
        char linkname[MAXPATHLEN];
-@@ -1130,9 +1311,16 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1136,9 +1317,16 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
                        memcpy(lastdir, thisname, len);
                        lastdir[len] = '\0';
                        lastdir_len = len;
@@ -241,7 +241,7 @@ diff --git a/flist.c b/flist.c
        basename_len = strlen(basename) + 1; /* count the '\0' */
  
  #ifdef SUPPORT_LINKS
-@@ -1208,11 +1396,21 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1214,11 +1402,21 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
        }
  #endif
  
@@ -266,7 +266,7 @@ diff --git a/flist.c b/flist.c
        /* This code is only used by the receiver when it is building
         * a list of files for a delete pass. */
        if (keep_dirlinks && linkname_len && flist) {
-@@ -2063,7 +2261,11 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
+@@ -2074,7 +2272,11 @@ 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);
                }
index 653d58a..06e2a3b 100644 (file)
@@ -20,7 +20,7 @@ diff --git a/clientserver.c b/clientserver.c
  extern int io_timeout;
  extern int no_detach;
  extern int write_batch;
-@@ -708,6 +709,8 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
+@@ -712,6 +713,8 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
        else if (am_root < 0) /* Treat --fake-super from client as --super. */
                am_root = 2;
  
@@ -312,7 +312,7 @@ diff --git a/flist.c b/flist.c
        }
        fclose(fp);
  
-@@ -1272,6 +1394,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1278,6 +1400,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++;
@@ -321,7 +321,7 @@ diff --git a/flist.c b/flist.c
                return NULL;
        }
  
-@@ -1402,13 +1526,36 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1408,13 +1532,36 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
                int j;
                if (flist && (j = flist_find(checksum_flist, file)) >= 0) {
                        struct file_struct *fp = checksum_flist->sorted[j];
@@ -363,7 +363,7 @@ diff --git a/flist.c b/flist.c
        }
  
        /* This code is only used by the receiver when it is building
-@@ -1703,6 +1850,9 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len,
+@@ -1709,6 +1856,9 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len,
  
        closedir(d);
  
@@ -373,7 +373,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". */
-@@ -2265,7 +2415,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
+@@ -2276,7 +2426,7 @@ struct file_list *send_file_list(int f, int argc, char *argv[])
                flist_eof = 1;
        
        if (checksum_updating && always_checksum && flist_eof)
@@ -444,7 +444,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 },
-@@ -1965,7 +1968,9 @@ void server_options(char **args, int *argc_p)
+@@ -1966,7 +1969,9 @@ void server_options(char **args, int *argc_p)
                                args[ac++] = basis_dir[i];
                        }
                }
@@ -458,7 +458,7 @@ diff --git a/options.c b/options.c
 diff --git a/rsync.h b/rsync.h
 --- a/rsync.h
 +++ b/rsync.h
-@@ -678,6 +678,10 @@ extern int xattrs_ndx;
+@@ -679,6 +679,10 @@ extern int xattrs_ndx;
  #define F_SUM(f) ((char*)OPT_EXTRA(f, LEN64_BUMP(f) + HLINK_BUMP(f) \
                                    + SUM_EXTRA_CNT - 1))
  
index 94953bb..8ff383d 100644 (file)
@@ -11,7 +11,7 @@ To use this patch, run these commands for a successful build:
 diff --git a/flist.c b/flist.c
 --- a/flist.c
 +++ b/flist.c
-@@ -1208,7 +1208,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1214,7 +1214,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
        }
  #endif
  
@@ -24,7 +24,7 @@ diff --git a/flist.c b/flist.c
 diff --git a/generator.c b/generator.c
 --- a/generator.c
 +++ b/generator.c
-@@ -637,7 +637,8 @@ int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st)
+@@ -674,7 +674,8 @@ int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st)
           of the file time to determine whether to sync */
        if (always_checksum > 0 && S_ISREG(st->st_mode)) {
                char sum[MAX_DIGEST_LEN];
@@ -169,7 +169,7 @@ diff --git a/xattrs.c b/xattrs.c
  
  #define RSYNC_XAL_INITIAL 5
  #define RSYNC_XAL_LIST_INITIAL 100
-@@ -66,6 +68,8 @@ extern int checksum_seed;
+@@ -65,6 +67,8 @@ extern int checksum_seed;
  #define XSTAT_ATTR RSYNC_PREFIX "%stat"
  #define XACC_ACL_ATTR RSYNC_PREFIX "%aacl"
  #define XDEF_ACL_ATTR RSYNC_PREFIX "%dacl"
@@ -178,7 +178,7 @@ diff --git a/xattrs.c b/xattrs.c
  
  typedef struct {
        char *datum, *name;
-@@ -853,6 +857,39 @@ int del_def_xattr_acl(const char *fname)
+@@ -829,6 +833,39 @@ int del_def_xattr_acl(const char *fname)
  }
  #endif
  
index 7cb23b0..955b30d 100644 (file)
@@ -19,7 +19,7 @@ diff --git a/generator.c b/generator.c
  extern int preserve_specials;
  extern int preserve_hard_links;
  extern int preserve_perms;
-@@ -1564,7 +1565,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1598,7 +1599,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                goto cleanup;
        }
  
@@ -55,7 +55,7 @@ diff --git a/options.c b/options.c
    {"specials",         0,  POPT_ARG_VAL,    &preserve_specials, 1, 0, 0 },
    {"no-specials",      0,  POPT_ARG_VAL,    &preserve_specials, 0, 0, 0 },
    {"links",           'l', POPT_ARG_VAL,    &preserve_links, 1, 0, 0 },
-@@ -1999,6 +2002,9 @@ void server_options(char **args, int *argc_p)
+@@ -2000,6 +2003,9 @@ void server_options(char **args, int *argc_p)
        else if (remove_source_files)
                args[ac++] = "--remove-sent-files";
  
diff --git a/crtimes.diff b/crtimes.diff
new file mode 100644 (file)
index 0000000..e4c1831
--- /dev/null
@@ -0,0 +1,608 @@
+This patch adds a --crtimes (-N) option that will preserve
+create times on OS X.
+
+To use this patch, run these commands for a successful build:
+
+    patch -p1 <patches/flags.diff
+    patch -p1 <patches/crtimes.diff
+    ./configure                      (optional if already run)
+    make
+
+diff --git a/compat.c b/compat.c
+--- a/compat.c
++++ b/compat.c
+@@ -44,6 +44,7 @@ extern int protocol_version;
+ extern int protect_args;
+ extern int preserve_uid;
+ extern int preserve_gid;
++extern int preserve_crtimes;
+ extern int preserve_fileflags;
+ extern int preserve_acls;
+ extern int preserve_xattrs;
+@@ -61,7 +62,7 @@ extern iconv_t ic_send, ic_recv;
+ #endif
+ /* These index values are for the file-list's extra-attribute array. */
+-int uid_ndx, gid_ndx, fileflags_ndx, acls_ndx, xattrs_ndx, unsort_ndx;
++int uid_ndx, gid_ndx, crtimes_ndx, fileflags_ndx, acls_ndx, xattrs_ndx, unsort_ndx;
+ #ifdef ICONV_OPTION
+ int filesfrom_convert = 0;
+@@ -125,6 +126,8 @@ void setup_protocol(int f_out,int f_in)
+               uid_ndx = ++file_extra_cnt;
+       if (preserve_gid)
+               gid_ndx = ++file_extra_cnt;
++      if (preserve_crtimes)
++              crtimes_ndx = (file_extra_cnt += TIME_EXTRA_CNT);
+       if (preserve_fileflags)
+               fileflags_ndx = ++file_extra_cnt;
+       if (preserve_acls && !am_sender)
+diff --git a/flist.c b/flist.c
+--- a/flist.c
++++ b/flist.c
+@@ -54,6 +54,7 @@ extern int fileflags_ndx;
+ extern int uid_ndx;
+ extern int gid_ndx;
+ extern int eol_nulls;
++extern int crtimes_ndx;
+ extern int relative_paths;
+ extern int implied_dirs;
+ extern int file_extra_cnt;
+@@ -343,7 +344,7 @@ int push_pathname(const char *dir, int len)
+ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_ndx)
+ {
+-      static time_t modtime;
++      static time_t modtime, crtime;
+       static mode_t mode;
+ #ifdef SUPPORT_FLAGS
+       static uint32 fileflags;
+@@ -462,6 +463,13 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
+               xflags |= XMIT_SAME_TIME;
+       else
+               modtime = file->modtime;
++      if (crtimes_ndx) {
++              time_t file_crtime = f_crtime(file);
++              if (file_crtime == modtime)
++                      xflags |= XMIT_CRTIME_EQ_MTIME;
++              else
++                      crtime = file_crtime;
++      }
+ #ifdef SUPPORT_HARD_LINKS
+       if (tmp_dev != 0) {
+@@ -532,6 +540,8 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
+               else
+                       write_int(f, modtime);
+       }
++      if (crtimes_ndx && !(xflags & XMIT_CRTIME_EQ_MTIME))
++              write_varlong(f, crtime, 4);
+       if (!(xflags & XMIT_SAME_MODE))
+               write_int(f, to_wire_mode(mode));
+ #ifdef SUPPORT_FLAGS
+@@ -624,7 +634,7 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
+ static struct file_struct *recv_file_entry(struct file_list *flist,
+                                          int xflags, int f)
+ {
+-      static int64 modtime;
++      static int64 modtime, crtime;
+       static mode_t mode;
+ #ifdef SUPPORT_FLAGS
+       static uint32 fileflags;
+@@ -758,6 +768,19 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+               } else
+                       modtime = read_int(f);
+       }
++      if (crtimes_ndx) {
++              if (!(xflags & XMIT_CRTIME_EQ_MTIME)) {
++                      crtime = read_varlong(f, 4);
++#if SIZEOF_TIME_T < SIZEOF_INT64
++                      if (!am_generator && (int64)(time_t)crtime != crtime) {
++                              rprintf(FERROR_XFER,
++                                  "Create time value of %s truncated on receiver.\n",
++                                  lastname);
++                      }
++#endif
++              } else
++                      crtime = modtime;
++      }
+       if (!(xflags & XMIT_SAME_MODE))
+               mode = from_wire_mode(read_int(f));
+@@ -898,6 +921,8 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+               F_GROUP(file) = gid;
+               file->flags |= gid_flags;
+       }
++      if (crtimes_ndx)
++              f_crtime_set(file, (time_t)crtime);
+       if (unsort_ndx)
+               F_NDX(file) = flist->used + flist->ndx_start;
+@@ -1234,6 +1259,8 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+               F_OWNER(file) = st.st_uid;
+       if (gid_ndx)
+               F_GROUP(file) = st.st_gid;
++      if (crtimes_ndx)
++              f_crtime_set(file, get_create_time(fname));
+       if (basename != thisname)
+               file->dirname = lastdir;
+diff --git a/generator.c b/generator.c
+--- a/generator.c
++++ b/generator.c
+@@ -21,6 +21,7 @@
+  */
+ #include "rsync.h"
++#include "ifuncs.h"
+ extern int verbose;
+ extern int dry_run;
+@@ -41,6 +42,7 @@ extern int preserve_links;
+ extern int preserve_devices;
+ extern int preserve_specials;
+ extern int preserve_hard_links;
++extern int preserve_fileflags;
+ extern int preserve_perms;
+ extern int preserve_times;
+ extern int uid_ndx;
+@@ -137,6 +139,7 @@ enum delret {
+ /* Forward declaration for delete_item(). */
+ static enum delret delete_dir_contents(char *fname, int flags);
++
+ static int is_backup_file(char *fn)
+ {
+       int k = strlen(fn) - backup_suffix_len;
+@@ -598,6 +601,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;
++      if (crtimes_ndx) {
++              if (sxp->crtime == 0)
++                      sxp->crtime = get_create_time(fname);
++              if (cmp_time(sxp->crtime, f_crtime(file)) != 0)
++                      return 0;
++      }
++
+ #ifdef SUPPORT_ACLS
+       if (preserve_acls && !S_ISLNK(file->mode)) {
+               if (!ACL_READY(*sxp))
+@@ -634,6 +644,12 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+                 && (!(iflags & ITEM_XNAME_FOLLOWS) || *xname))
+                || (keep_time && cmp_time(file->modtime, sxp->st.st_mtime) != 0))
+                       iflags |= ITEM_REPORT_TIME;
++              if (crtimes_ndx) {
++                      if (sxp->crtime == 0)
++                              sxp->crtime = get_create_time(fnamecmp);
++                      if (cmp_time(sxp->crtime, f_crtime(file)) != 0)
++                              iflags |= ITEM_REPORT_CRTIME;
++              }
+ #if !defined HAVE_LCHMOD && !defined HAVE_SETATTRLIST
+               if (S_ISLNK(file->mode)) {
+                       ;
+@@ -1173,6 +1189,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;
+       if (!F_IS_ACTIVE(f)) {
+@@ -1187,14 +1204,16 @@ 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),
++                      crtimes_ndx ? timestring(crtime) : "",
+                       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) : "",
+                       f_name(f, NULL));
+       }
+ }
+@@ -1277,6 +1296,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+                       return;
+               }
+       }
++      sx.crtime = 0;
+ #ifdef SUPPORT_ACLS
+       sx.acc_acl = sx.def_acl = NULL;
+ #endif
+diff --git a/ifuncs.h b/ifuncs.h
+--- a/ifuncs.h
++++ b/ifuncs.h
+@@ -57,6 +57,28 @@ from_wire_mode(int mode)
+       return mode;
+ }
++static inline time_t
++f_crtime(struct file_struct *fp)
++{
++#if SIZEOF_TIME_T > 4
++      time_t crtime;
++      memcpy(&crtime, &REQ_EXTRA(fp, crtimes_ndx)->unum, SIZEOF_TIME_T);
++      return crtime;
++#else
++      return REQ_EXTRA(fp, crtimes_ndx)->unum;
++#endif
++}
++
++static inline void
++f_crtime_set(struct file_struct *fp, time_t crtime)
++{
++#if SIZEOF_TIME_T > 4
++      memcpy(&REQ_EXTRA(fp, crtimes_ndx)->unum, &crtime, SIZEOF_TIME_T);
++#else
++      REQ_EXTRA(fp, crtimes_ndx)->unum = (uint32)crtime;
++#endif
++}
++
+ static inline int
+ isDigit(const char *ptr)
+ {
+diff --git a/log.c b/log.c
+--- a/log.c
++++ b/log.c
+@@ -642,7 +642,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';
+-                      c[8] = !(iflags & ITEM_REPORT_ATIME) ? '.' : 'u';
++                      c[8] = !(iflags & ITEM_REPORT_CRTIME) ? '.' : 'n';
+                       c[9] = !(iflags & ITEM_REPORT_ACL) ? '.' : 'a';
+                       c[10] = !(iflags & ITEM_REPORT_XATTR) ? '.' : 'x';
+                       c[11] = '\0';
+diff --git a/options.c b/options.c
+--- a/options.c
++++ b/options.c
+@@ -59,6 +59,7 @@ int preserve_specials = 0;
+ int preserve_uid = 0;
+ int preserve_gid = 0;
+ int preserve_times = 0;
++int preserve_crtimes = 0;
+ int update_only = 0;
+ int cvs_exclude = 0;
+ int dry_run = 0;
+@@ -354,6 +355,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");
++  rprintf(F," -N, --crtimes               preserve create (newness) times\n");
+   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[] = {
+   {"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 },
++  {"crtimes",         'N', POPT_ARG_VAL,    &preserve_crtimes, 1, 0, 0 },
++  {"no-crtimes",       0,  POPT_ARG_VAL,    &preserve_crtimes, 0, 0, 0 },
++  {"no-N",             0,  POPT_ARG_VAL,    &preserve_crtimes, 0, 0, 0 },
+   {"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 },
+@@ -1742,6 +1747,8 @@ void server_options(char **args, int *argc_p)
+               argstr[x++] = 'D';
+       if (preserve_times)
+               argstr[x++] = 't';
++      if (preserve_crtimes)
++              argstr[x++] = 'N';
+       if (preserve_perms)
+               argstr[x++] = 'p';
+       else if (preserve_executability && am_sender)
+diff --git a/rsync.c b/rsync.c
+--- a/rsync.c
++++ b/rsync.c
+@@ -436,6 +436,14 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
+               if (ret == 0) /* ret == 1 if symlink could not be set */
+                       updated = 1;
+       }
++      if (crtimes_ndx && !(flags & ATTRS_SKIP_CRTIME)) {
++              time_t file_crtime = f_crtime(file);
++              if (sxp->crtime == 0)
++                      sxp->crtime = get_create_time(fname);
++              if (cmp_time(sxp->crtime, file_crtime) != 0
++               && set_create_time(fname, file_crtime) == 0)
++                      updated = 1;
++      }
+       change_uid = am_root && uid_ndx && sxp->st.st_uid != (uid_t)F_OWNER(file);
+       change_gid = gid_ndx && !(file->flags & FLAG_SKIP_GROUP)
+@@ -573,7 +581,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,
+-                     ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
++                     ok_to_set_time ? 0 : ATTRS_SKIP_MTIME | ATTRS_SKIP_CRTIME);
+ #ifdef SUPPORT_FLAGS
+       if (preserve_fileflags)
+@@ -608,7 +616,7 @@ int finish_transfer(const char *fname, const char *fnametmp,
+   do_set_file_attrs:
+       set_file_attrs(fnametmp, file, NULL, fnamecmp,
+-                     ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
++                     ok_to_set_time ? 0 : ATTRS_SKIP_MTIME | ATTRS_SKIP_CRTIME);
+       if (temp_copy_name) {
+               if (do_rename(fnametmp, fname) < 0) {
+diff --git a/rsync.h b/rsync.h
+--- a/rsync.h
++++ b/rsync.h
+@@ -60,6 +60,7 @@
+ #define XMIT_RDEV_MINOR_8_pre30 (1<<11)       /* protocols 28 - 29  */
+ #define XMIT_GROUP_NAME_FOLLOWS (1<<11) /* protocols 30 - now */
+ #define XMIT_HLINK_FIRST (1<<12)      /* protocols 30 - now (HLINKED files only) */
++#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. */
+@@ -149,6 +150,7 @@
+ #define ATTRS_REPORT          (1<<0)
+ #define ATTRS_SKIP_MTIME      (1<<1)
++#define ATTRS_SKIP_CRTIME     (1<<2)
+ #define FULL_FLUSH    1
+ #define NORMAL_FLUSH  0
+@@ -165,7 +167,7 @@
+ #define FNAMECMP_FUZZY                0x83
+ /* For use by the itemize_changes code */
+-#define ITEM_REPORT_ATIME (1<<0)
++#define ITEM_REPORT_CRTIME (1<<0)
+ #define ITEM_REPORT_CHECKSUM (1<<1)
+ #define ITEM_REPORT_SIZE (1<<2)
+ #define ITEM_REPORT_TIME (1<<3)
+@@ -635,6 +637,7 @@ extern int file_extra_cnt;
+ extern int inc_recurse;
+ extern int uid_ndx;
+ extern int gid_ndx;
++extern int crtimes_ndx;
+ extern int fileflags_ndx;
+ extern int acls_ndx;
+ extern int xattrs_ndx;
+@@ -642,6 +645,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)
++#define TIME_EXTRA_CNT ((SIZEOF_TIME_T + EXTRA_LEN - 1) / EXTRA_LEN)
+ #define DEV_EXTRA_CNT 2
+ #define DIRNODE_EXTRA_CNT 3
+ #define SUM_EXTRA_CNT ((MAX_DIGEST_LEN + EXTRA_LEN - 1) / EXTRA_LEN)
+@@ -896,6 +900,7 @@ typedef struct {
+ typedef struct {
+     STRUCT_STAT st;
++    time_t crtime;
+ #ifdef SUPPORT_ACLS
+     struct rsync_acl *acc_acl; /* access ACL */
+     struct rsync_acl *def_acl; /* default ACL */
+diff --git a/rsync.yo b/rsync.yo
+--- a/rsync.yo
++++ b/rsync.yo
+@@ -350,6 +350,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
++ -N, --crtimes               preserve create (newness) times
+      --super                 receiver attempts super-user activities
+      --fake-super            store/recover privileged attrs using xattrs
+  -S, --sparse                handle sparse files efficiently
+@@ -996,6 +997,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).
++dit(bf(-N, --crtimes)) This tells rsync to set the create (newness) times of
++the destination files to the same value as the source files.
++
+ 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
+@@ -1647,7 +1651,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
+-format is like the string bf(YXcstpoguax), where bf(Y) is replaced by the
++format is like the string bf(YXcstpognax), where bf(Y) is replaced by the
+ 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.
+@@ -1696,8 +1700,8 @@ 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).
+-  it() The bf(u) slot is reserved for reporting update (access) time changes
+-  (a feature that is not yet released).
++  it() A bf(n) means the create (newness) time is different and is being
++  updated to the sender's value (requires bf(--crtimes)).
+   it() The bf(a) means that the ACL information changed.
+   it() The bf(x) slot is reserved for reporting extended attribute changes
+   (a feature that is not yet released).
+diff --git a/syscall.c b/syscall.c
+--- a/syscall.c
++++ b/syscall.c
+@@ -36,6 +36,11 @@ extern int list_only;
+ extern int preserve_perms;
+ extern int preserve_executability;
++struct create_time {
++      unsigned long length;
++      struct timespec crtime;
++};
++
+ #define RETURN_ERROR_IF(x,e) \
+       do { \
+               if (x) { \
+@@ -300,3 +305,33 @@ char *d_name(struct dirent *di)
+       return di->d_name;
+ #endif
+ }
++
++time_t get_create_time(const char *path)
++{
++      static struct create_time attrBuf;
++      struct attrlist attrList;
++
++      memset(&attrList, 0, sizeof attrList);
++      attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
++      attrList.commonattr = ATTR_CMN_CRTIME;
++      if (getattrlist(path, &attrList, &attrBuf, sizeof attrBuf, FSOPT_NOFOLLOW) < 0)
++              return 0;
++      return attrBuf.crtime.tv_sec;
++}
++
++int set_create_time(const char *path, time_t crtime)
++{
++      struct attrlist attrList;
++      struct timespec ts;
++
++      if (dry_run) return 0;
++      RETURN_ERROR_IF_RO_OR_LO;
++
++      ts.tv_sec = crtime;
++      ts.tv_nsec = 0;
++
++      memset(&attrList, 0, sizeof attrList);
++      attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
++      attrList.commonattr = ATTR_CMN_CRTIME;
++      return setattrlist(path, &attrList, &ts, sizeof ts, FSOPT_NOFOLLOW);
++}
+diff --git a/testsuite/crtimes.test b/testsuite/crtimes.test
+new file mode 100644
+--- /dev/null
++++ b/testsuite/crtimes.test
+@@ -0,0 +1,24 @@
++#! /bin/sh
++
++# Test rsync copying create times
++
++. "$suitedir/rsync.fns"
++
++# Setting an older time via touch sets the create time to the mtime.
++# Setting it to a newer time affects just the mtime.
++
++mkdir "$fromdir"
++echo hiho "$fromdir/foo"
++
++touch -t 200101011111.11 "$fromdir"
++touch -t 200202022222.22 "$fromdir"
++
++touch -t 200111111111.11 "$fromdir/foo"
++touch -t 200212122222.22 "$fromdir/foo"
++
++TLS_ARGS=--crtimes
++
++checkit "$RSYNC -rtgvvv --crtimes \"$fromdir/\" \"$todir/\"" "$fromdir" "$todir"
++
++# The script would have aborted on error, so getting here means we've won.
++exit 0
+diff --git a/tls.c b/tls.c
+--- a/tls.c
++++ b/tls.c
+@@ -105,6 +105,8 @@ static int stat_xattr(const char *fname, STRUCT_STAT *fst)
+ #endif
++static int display_crtimes = 0;
++ 
+ static void failed(char const *what, char const *where)
+ {
+       fprintf(stderr, PROGRAM ": %s %s: %s\n",
+@@ -112,16 +114,36 @@ static void failed(char const *what, char const *where)
+       exit(1);
+ }
++static void storetime(char *dest, time_t t, size_t destsize)
++{
++      if (t) {
++              struct tm *mt = gmtime(&t);
++
++              snprintf(dest, destsize,
++                      "%04d-%02d-%02d %02d:%02d:%02d ",
++                      (int)mt->tm_year + 1900,
++                      (int)mt->tm_mon + 1,
++                      (int)mt->tm_mday,
++                      (int)mt->tm_hour,
++                      (int)mt->tm_min,
++                      (int)mt->tm_sec);
++      } else
++              strlcpy(dest, "                    ", destsize);
++}
++
+ static void list_file(const char *fname)
+ {
+       STRUCT_STAT buf;
++      time_t crtime = 0;
+       char permbuf[PERMSTRING_SIZE];
+-      struct tm *mt;
+-      char datebuf[50];
++      char mtimebuf[50];
++      char crtimebuf[50];
+       char linkbuf[4096];
+       if (do_lstat(fname, &buf) < 0)
+               failed("stat", fname);
++      if (display_crtimes && (crtime = get_create_time(fname)) == 0)
++              failed("get_create_time", fname);
+ #ifdef SUPPORT_XATTRS
+       if (am_root < 0)
+               stat_xattr(fname, &buf);
+@@ -154,19 +176,11 @@ static void list_file(const char *fname)
+       permstring(permbuf, buf.st_mode);
+-      if (buf.st_mtime) {
+-              mt = gmtime(&buf.st_mtime);
+-
+-              snprintf(datebuf, sizeof datebuf,
+-                      "%04d-%02d-%02d %02d:%02d:%02d",
+-                      (int)mt->tm_year + 1900,
+-                      (int)mt->tm_mon + 1,
+-                      (int)mt->tm_mday,
+-                      (int)mt->tm_hour,
+-                      (int)mt->tm_min,
+-                      (int)mt->tm_sec);
+-      } else
+-              strlcpy(datebuf, "                   ", sizeof datebuf);
++      storetime(mtimebuf, buf.st_mtime, sizeof mtimebuf);
++      if (display_crtimes)
++              storetime(crtimebuf, crtime, sizeof crtimebuf);
++      else
++              crtimebuf[0] = '\0';
+       /* TODO: Perhaps escape special characters in fname? */
+@@ -177,13 +191,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);
+-      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,
+-             datebuf, fname, linkbuf);
++             mtimebuf, crtimebuf, fname, linkbuf);
+ }
+ static struct poptOption long_options[] = {
+   /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
++  {"crtimes",         'N', POPT_ARG_NONE,   &display_crtimes, 0, 0, 0},
+ #ifdef SUPPORT_XATTRS
+   {"fake-super",      'f', POPT_ARG_VAL,    &am_root, -1, 0, 0 },
+ #endif
+@@ -197,6 +212,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");
++  fprintf(F," -N, --crtimes               display create (newness) times\n");
+ #ifdef SUPPORT_XATTRS
+   fprintf(F," -f, --fake-super            display attributes including fake-super xattrs\n");
+ #endif
index 00eb2cb..61c6d44 100644 (file)
@@ -25,7 +25,7 @@ diff --git a/generator.c b/generator.c
  extern int size_only;
  extern OFF_T max_size;
  extern OFF_T min_size;
-@@ -630,6 +631,9 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+@@ -667,6 +668,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)
  {
@@ -62,7 +62,7 @@ diff --git a/options.c b/options.c
    {"one-file-system", 'x', POPT_ARG_NONE,   0, 'x', 0, 0 },
    {"update",          'u', POPT_ARG_NONE,   &update_only, 0, 0, 0 },
    {"existing",         0,  POPT_ARG_NONE,   &ignore_non_existing, 0, 0, 0 },
-@@ -1904,6 +1907,9 @@ void server_options(char **args, int *argc_p)
+@@ -1905,6 +1908,9 @@ void server_options(char **args, int *argc_p)
                }
        }
  
index b1007ae..10cfcfd 100644 (file)
@@ -23,7 +23,7 @@ switches to --detect-moved blindly accepts the staged file.
 diff --git a/generator.c b/generator.c
 --- a/generator.c
 +++ b/generator.c
-@@ -186,7 +186,9 @@ static int fattr_find(struct file_struct *f, char *fname)
+@@ -194,7 +194,9 @@ static int fattr_find(struct file_struct *f, char *fname)
                                continue;
                        }
                }
@@ -34,7 +34,7 @@ diff --git a/generator.c b/generator.c
                diff = u_strcmp(fmid->basename, f->basename);
                if (diff == 0) {
                        good_match = mid;
-@@ -1862,6 +1864,21 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1894,6 +1896,21 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                fnamecmp = partialptr;
                fnamecmp_type = FNAMECMP_PARTIAL_DIR;
                statret = 0;
@@ -79,7 +79,7 @@ diff --git a/options.c b/options.c
    {"fuzzy",           'y', POPT_ARG_NONE,   &fuzzy_basis, 0, 0, 0 },
    {"compress",        'z', POPT_ARG_NONE,   0, 'z', 0, 0 },
    {"no-compress",      0,  POPT_ARG_VAL,    &do_compression, 0, 0, 0 },
-@@ -1900,8 +1904,14 @@ void server_options(char **args, int *argc_p)
+@@ -1901,8 +1905,14 @@ void server_options(char **args, int *argc_p)
                        args[ac++] = "--super";
                if (size_only)
                        args[ac++] = "--size-only";
@@ -108,7 +108,7 @@ diff --git a/rsync.yo b/rsync.yo
       --compare-dest=DIR      also compare received files relative to DIR
       --copy-dest=DIR         ... and include copies of unchanged files
       --link-dest=DIR         hardlink to files in DIR when unchanged
-@@ -1467,6 +1469,17 @@ the bf(--partial-dir) option, that directory will be used instead.  These
+@@ -1483,6 +1485,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 90f3803..d063ece 100644 (file)
@@ -117,7 +117,7 @@ diff --git a/flist.c b/flist.c
  static void send_directory(int f, struct file_list *flist,
                           char *fbuf, int len, int flags);
  
-@@ -2167,6 +2209,25 @@ struct file_list *recv_file_list(int f)
+@@ -2178,6 +2220,25 @@ struct file_list *recv_file_list(int f)
  
        flist_sort_and_clean(flist, relative_paths);
  
@@ -154,7 +154,7 @@ diff --git a/generator.c b/generator.c
  extern int whole_file;
  extern int list_only;
  extern int read_batch;
-@@ -96,6 +97,7 @@ extern char *backup_suffix;
+@@ -97,6 +98,7 @@ extern char *backup_suffix;
  extern int backup_suffix_len;
  extern struct file_list *cur_flist, *first_flist, *dir_flist;
  extern struct filter_list_struct server_filter_list;
@@ -162,7 +162,7 @@ diff --git a/generator.c b/generator.c
  
  int ignore_perishable = 0;
  int non_perishable_cnt = 0;
-@@ -103,6 +105,7 @@ int maybe_ATTRS_REPORT = 0;
+@@ -104,6 +106,7 @@ int maybe_ATTRS_REPORT = 0;
  
  static dev_t dev_zero;
  static int deletion_count = 0; /* used to implement --max-delete */
@@ -170,17 +170,24 @@ diff --git a/generator.c b/generator.c
  static int deldelay_size = 0, deldelay_cnt = 0;
  static char *deldelay_buf = NULL;
  static int deldelay_fd = -1;
-@@ -112,7 +115,8 @@ static int need_retouch_dir_times;
+@@ -113,7 +116,7 @@ static int need_retouch_dir_times;
  static int need_retouch_dir_perms;
  static const char *solo_file = NULL;
  
 -/* For calling delete_item() and delete_dir_contents(). */
 +/* For calling delete_item(), delete_dir_contents(), and delete_in_dir(). */
-+#define DEL_NO_DELETIONS      (1<<0)
- #define DEL_RECURSE           (1<<1) /* recurse */
+ #define DEL_OWNED_BY_US       (1<<0) /* file/dir has our uid */
+ #define DEL_RECURSE           (1<<1) /* if dir, delete all contents */
  #define DEL_DIR_IS_EMPTY      (1<<2) /* internal delete_FUNCTIONS use only */
+@@ -122,6 +125,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 */
  
-@@ -134,11 +138,121 @@ static int is_backup_file(char *fn)
+ #define DEL_MAKE_ROOM (DEL_FOR_FILE|DEL_FOR_DIR|DEL_FOR_SYMLINK|DEL_FOR_DEVICE|DEL_FOR_SPECIAL)
+@@ -142,11 +146,121 @@ static int is_backup_file(char *fn)
        return k > 0 && strcmp(fn+k, backup_suffix) == 0;
  }
  
@@ -300,18 +307,18 @@ diff --git a/generator.c b/generator.c
 + *
 + * Also note: --detect-rename may use this routine with DEL_NO_DELETIONS set!
   */
- static enum delret delete_item(char *fbuf, int mode, char *replace, int flags)
+ static enum delret delete_item(char *fbuf, int mode, int flags)
  {
-@@ -160,6 +274,8 @@ static enum delret delete_item(char *fbuf, int mode, char *replace, int flags)
+@@ -171,6 +285,8 @@ static enum delret delete_item(char *fbuf, int mode, int flags)
                        goto check_ret;
                /* OK: try to delete the directory. */
        }
 +      if (flags & DEL_NO_DELETIONS)
 +              return DR_SUCCESS;
  
-       if (!replace && max_delete >= 0 && ++deletion_count > max_delete)
+       if (!(flags & DEL_MAKE_ROOM) && max_delete >= 0 && ++deletion_count > max_delete)
                return DR_AT_LIMIT;
-@@ -206,6 +322,8 @@ static enum delret delete_item(char *fbuf, int mode, char *replace, int flags)
+@@ -226,6 +342,8 @@ static enum delret delete_item(char *fbuf, int mode, int 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.)
@@ -320,7 +327,7 @@ diff --git a/generator.c b/generator.c
   */
  static enum delret delete_dir_contents(char *fname, int flags)
  {
-@@ -225,7 +343,9 @@ static enum delret delete_dir_contents(char *fname, int flags)
+@@ -245,7 +363,9 @@ static enum delret delete_dir_contents(char *fname, int flags)
        save_filters = push_local_filters(fname, dlen);
  
        non_perishable_cnt = 0;
@@ -330,16 +337,17 @@ diff --git a/generator.c b/generator.c
        ret = non_perishable_cnt ? DR_NOT_EMPTY : DR_SUCCESS;
  
        if (!dirlist->used)
-@@ -262,6 +382,8 @@ static enum delret delete_dir_contents(char *fname, int flags)
-               if (S_ISDIR(fp->mode)
-                && delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS)
-                       ret = DR_NOT_EMPTY;
-+              if (detect_renamed && S_ISREG(fp->mode))
+@@ -288,7 +408,8 @@ static enum delret delete_dir_contents(char *fname, int flags)
+                               do_chmod(fname, fp->mode |= S_IWUSR);
+                       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, NULL, flags) != DR_SUCCESS)
+               if (delete_item(fname, fp->mode, flags) != DR_SUCCESS)
                        ret = DR_NOT_EMPTY;
        }
-@@ -414,13 +536,18 @@ static void do_delayed_deletions(char *delbuf)
+@@ -449,13 +570,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
@@ -362,7 +370,7 @@ diff --git a/generator.c b/generator.c
  
        if (!fbuf) {
                change_local_filter_dir(NULL, 0, 0);
-@@ -430,21 +557,28 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
+@@ -465,21 +591,28 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
        if (verbose > 2)
                rprintf(FINFO, "delete_in_dir(%s)\n", fbuf);
  
@@ -396,7 +404,7 @@ diff --git a/generator.c b/generator.c
        if (one_file_system) {
                if (file->flags & FLAG_TOP_DIR)
                        filesystem_dev = *fs_dev;
-@@ -454,6 +588,14 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
+@@ -489,6 +622,14 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
  
        dirlist = get_dirlist(fbuf, dlen, 0);
  
@@ -411,7 +419,7 @@ diff --git a/generator.c b/generator.c
        /* If an item in dirlist is not found in flist, delete it
         * from the filesystem. */
        for (i = dirlist->used; i--; ) {
-@@ -466,16 +608,25 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
+@@ -501,18 +642,26 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
                                        f_name(fp, NULL));
                        continue;
                }
@@ -420,15 +428,19 @@ diff --git a/generator.c b/generator.c
 +                      look_for_rename(fp, fbuf);
 +              }
                if (flist_find(cur_flist, fp) < 0) {
+-                      int flags = DEL_RECURSE
+-                                | (!uid_ndx || (uid_t)F_OWNER(fp) == our_uid ? DEL_OWNED_BY_US : 0);
++                      int own_flag = (!uid_ndx || (uid_t)F_OWNER(fp) == our_uid ? DEL_OWNED_BY_US : 0);
                        f_name(fp, delbuf);
 -                      if (delete_during == 2) {
+-                              if (!remember_delete(fp, delbuf, flags))
 +                      if (delete_during == 2 && !(flags & DEL_NO_DELETIONS)) {
-                               if (!remember_delete(fp, delbuf))
++                              if (!remember_delete(fp, delbuf, own_flag | flags))
                                        break;
                        } else
--                              delete_item(delbuf, fp->mode, NULL, DEL_RECURSE);
+-                              delete_item(delbuf, fp->mode, flags);
 -              }
-+                              delete_item(delbuf, fp->mode, NULL, flags);
++                              delete_item(delbuf, fp->mode, own_flag | flags);
 +              } else if (detect_renamed && S_ISDIR(fp->mode))
 +                      unexplored_dirs++;
        }
@@ -440,7 +452,7 @@ diff --git a/generator.c b/generator.c
        flist_free(dirlist);
  }
  
-@@ -505,9 +656,9 @@ static void do_delete_pass(void)
+@@ -542,9 +691,9 @@ static void do_delete_pass(void)
                 || !S_ISDIR(st.st_mode))
                        continue;
  
@@ -452,7 +464,7 @@ diff --git a/generator.c b/generator.c
  
        if (do_progress && !am_server)
                rprintf(FINFO, "                    \r");
-@@ -1137,6 +1288,7 @@ static void list_file_entry(struct file_struct *f)
+@@ -1170,6 +1319,7 @@ static void list_file_entry(struct file_struct *f)
        }
  }
  
@@ -460,7 +472,7 @@ diff --git a/generator.c b/generator.c
  static int phase = 0;
  static int dflt_perms;
  
-@@ -1381,8 +1533,12 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1415,8 +1565,12 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                        }
                }
                else if (delete_during && f_out != -1 && !phase && dry_run < 2
@@ -475,7 +487,7 @@ diff --git a/generator.c b/generator.c
                goto cleanup;
        }
  
-@@ -1660,8 +1816,14 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1694,8 +1848,14 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                        goto cleanup;
                }
  #endif
@@ -491,7 +503,7 @@ diff --git a/generator.c b/generator.c
                rsyserr(FERROR_XFER, stat_errno, "recv_generator: failed to stat %s",
                        full_fname(fname));
                goto cleanup;
-@@ -2004,6 +2166,12 @@ void generate_files(int f_out, const char *local_name)
+@@ -2038,6 +2198,12 @@ void generate_files(int f_out, const char *local_name)
        if (verbose > 2)
                rprintf(FINFO, "generator starting pid=%ld\n", (long)getpid());
  
@@ -504,7 +516,7 @@ diff --git a/generator.c b/generator.c
        if (delete_before && !solo_file && cur_flist->used > 0)
                do_delete_pass();
        if (delete_during == 2) {
-@@ -2014,7 +2182,7 @@ void generate_files(int f_out, const char *local_name)
+@@ -2048,7 +2214,7 @@ void generate_files(int f_out, const char *local_name)
        }
        do_progress = 0;
  
@@ -513,7 +525,7 @@ diff --git a/generator.c b/generator.c
                whole_file = 0;
        if (verbose >= 2) {
                rprintf(FINFO, "delta-transmission %s\n",
-@@ -2052,7 +2220,7 @@ void generate_files(int f_out, const char *local_name)
+@@ -2086,7 +2252,7 @@ void generate_files(int f_out, const char *local_name)
                                                dirdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
                                        } else
                                                dirdev = MAKEDEV(0, 0);
@@ -522,7 +534,7 @@ diff --git a/generator.c b/generator.c
                                }
                        }
                }
-@@ -2095,7 +2263,21 @@ void generate_files(int f_out, const char *local_name)
+@@ -2129,7 +2295,21 @@ void generate_files(int f_out, const char *local_name)
        } while ((cur_flist = cur_flist->next) != NULL);
  
        if (delete_during)
@@ -572,7 +584,7 @@ diff --git a/options.c b/options.c
    {"fuzzy",           'y', POPT_ARG_NONE,   &fuzzy_basis, 0, 0, 0 },
    {"compress",        'z', POPT_ARG_NONE,   0, 'z', 0, 0 },
    {"no-compress",      0,  POPT_ARG_VAL,    &do_compression, 0, 0, 0 },
-@@ -1541,7 +1544,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1542,7 +1545,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
                inplace = 1;
        }
  
@@ -581,7 +593,7 @@ diff --git a/options.c b/options.c
                partial_dir = tmp_partialdir;
  
        if (inplace) {
-@@ -1550,6 +1553,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1551,6 +1554,7 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
                        snprintf(err_buf, sizeof err_buf,
                                 "--%s cannot be used with --%s\n",
                                 append_mode ? "append" : "inplace",
@@ -589,7 +601,7 @@ diff --git a/options.c b/options.c
                                 delay_updates ? "delay-updates" : "partial-dir");
                        return 0;
                }
-@@ -1896,6 +1900,8 @@ void server_options(char **args, int *argc_p)
+@@ -1897,6 +1901,8 @@ void server_options(char **args, int *argc_p)
                        args[ac++] = "--super";
                if (size_only)
                        args[ac++] = "--size-only";
@@ -609,7 +621,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
-@@ -1451,6 +1452,21 @@ Note that the use of the bf(--delete) option might get rid of any potential
+@@ -1467,6 +1468,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.
  
index 6fe7bed..701841b 100644 (file)
@@ -18,7 +18,7 @@ diff --git a/generator.c b/generator.c
  extern int ignore_existing;
  extern int ignore_non_existing;
  extern int inplace;
-@@ -1601,6 +1602,13 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1635,6 +1636,13 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                goto cleanup;
        }
  
@@ -32,7 +32,7 @@ diff --git a/generator.c b/generator.c
        fnamecmp = fname;
        fnamecmp_type = FNAMECMP_FNAME;
  
-@@ -1917,6 +1925,7 @@ void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
+@@ -1951,6 +1959,7 @@ void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
                        ignore_existing = -ignore_existing;
                        ignore_non_existing = -ignore_non_existing;
                        update_only = -update_only;
@@ -40,7 +40,7 @@ diff --git a/generator.c b/generator.c
                        always_checksum = -always_checksum;
                        size_only = -size_only;
                        append_mode = -append_mode;
-@@ -1942,6 +1951,7 @@ void check_for_finished_files(int itemizing, enum logcode code, int check_redo)
+@@ -1976,6 +1985,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;
index 8c282e0..6803125 100644 (file)
@@ -125,7 +125,7 @@ diff --git a/fileio.c b/fileio.c
 diff --git a/generator.c b/generator.c
 --- a/generator.c
 +++ b/generator.c
-@@ -112,6 +112,10 @@ static int need_retouch_dir_times;
+@@ -113,6 +113,10 @@ static int need_retouch_dir_times;
  static int need_retouch_dir_perms;
  static const char *solo_file = NULL;
  
@@ -134,8 +134,8 @@ diff --git a/generator.c b/generator.c
 +#endif
 +
  /* For calling delete_item() and delete_dir_contents(). */
- #define DEL_RECURSE           (1<<1) /* recurse */
- #define DEL_DIR_IS_EMPTY      (1<<2) /* internal delete_FUNCTIONS use only */
+ #define DEL_OWNED_BY_US       (1<<0) /* file/dir has our uid */
+ #define DEL_RECURSE           (1<<1) /* if dir, delete all contents */
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
@@ -167,7 +167,7 @@ diff --git a/options.c b/options.c
    {"existing",         0,  POPT_ARG_NONE,   &ignore_non_existing, 0, 0, 0 },
    {"ignore-non-existing",0,POPT_ARG_NONE,   &ignore_non_existing, 0, 0, 0 },
    {"ignore-existing",  0,  POPT_ARG_NONE,   &ignore_existing, 0, 0, 0 },
-@@ -1670,6 +1677,11 @@ void server_options(char **args, int *argc_p)
+@@ -1671,6 +1678,11 @@ void server_options(char **args, int *argc_p)
        if (!am_sender)
                args[ac++] = "--sender";
  
@@ -204,7 +204,7 @@ diff --git a/rsync.yo b/rsync.yo
   -n, --dry-run               perform a trial run with no changes made
   -W, --whole-file            copy files whole (w/o delta-xfer algorithm)
   -x, --one-file-system       don't cross filesystem boundaries
-@@ -1023,6 +1024,10 @@ NOTE: Don't use this option when the destination is a Solaris "tmpfs"
+@@ -1036,6 +1037,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.
  
@@ -238,8 +238,8 @@ diff --git a/t_unsafe.c b/t_unsafe.c
  int verbose = 0;
 +int drop_cache = 0;
  int preserve_perms = 0;
+ int preserve_executability = 0;
  
- int
 diff --git a/util.c b/util.c
 --- a/util.c
 +++ b/util.c
index 2673e91..ea30598 100644 (file)
@@ -1,4 +1,4 @@
-This patch provides --flags, which preserves the st_flags field.
+This patch provides --fileflags, which preserves the st_flags stat() field.
 Modified from a patch that was written by Rolf Grossmann.
 
 To use this patch, run these commands for a successful build:
@@ -70,20 +70,22 @@ diff --git a/flist.c b/flist.c
  #ifdef SUPPORT_HARD_LINKS
        static int64 dev;
  #endif
-@@ -403,6 +407,12 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
+@@ -403,6 +407,14 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
                xflags |= XMIT_SAME_MODE;
        else
                mode = file->mode;
 +#ifdef SUPPORT_FLAGS
-+      if (F_FFLAGS(file) == fileflags)
-+              xflags |= XMIT_SAME_FLAGS;
-+      else
-+              fileflags = F_FFLAGS(file);
++      if (fileflags_ndx) {
++              if (F_FFLAGS(file) == fileflags)
++                      xflags |= XMIT_SAME_FLAGS;
++              else
++                      fileflags = F_FFLAGS(file);
++      }
 +#endif
  
        if ((preserve_devices && IS_DEVICE(mode))
         || (preserve_specials && IS_SPECIAL(mode))) {
-@@ -522,6 +532,10 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
+@@ -522,6 +534,10 @@ static void send_file_entry(int f, struct file_struct *file, int ndx, int first_
        }
        if (!(xflags & XMIT_SAME_MODE))
                write_int(f, to_wire_mode(mode));
@@ -94,7 +96,7 @@ diff --git a/flist.c b/flist.c
        if (uid_ndx && !(xflags & XMIT_SAME_UID)) {
                if (protocol_version < 30)
                        write_int(f, uid);
-@@ -610,6 +624,9 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+@@ -610,6 +626,9 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
  {
        static int64 modtime;
        static mode_t mode;
@@ -104,11 +106,8 @@ diff --git a/flist.c b/flist.c
  #ifdef SUPPORT_HARD_LINKS
        static int64 dev;
  #endif
-@@ -741,9 +758,12 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
-       }
-       if (!(xflags & XMIT_SAME_MODE))
-               mode = from_wire_mode(read_int(f));
--
+@@ -744,6 +763,10 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
        if (chmod_modes && !S_ISLNK(mode))
                mode = tweak_mode(mode, chmod_modes);
 +#ifdef SUPPORT_FLAGS
@@ -118,7 +117,7 @@ diff --git a/flist.c b/flist.c
  
        if (uid_ndx && !(xflags & XMIT_SAME_UID)) {
                if (protocol_version < 30)
-@@ -865,6 +885,10 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
+@@ -865,6 +888,10 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
                OPT_EXTRA(file, 0)->unum = (uint32)(file_length >> 32);
        }
        file->mode = mode;
@@ -129,7 +128,7 @@ diff --git a/flist.c b/flist.c
        if (uid_ndx)
                F_OWNER(file) = uid;
        if (gid_ndx) {
-@@ -1193,6 +1217,10 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
+@@ -1199,6 +1226,10 @@ struct file_struct *make_file(const char *fname, struct file_list *flist,
                OPT_EXTRA(file, 0)->unum = (uint32)(st.st_size >> 32);
        }
        file->mode = st.st_mode;
@@ -143,171 +142,138 @@ diff --git a/flist.c b/flist.c
 diff --git a/generator.c b/generator.c
 --- a/generator.c
 +++ b/generator.c
-@@ -112,6 +112,14 @@ static int need_retouch_dir_times;
- static int need_retouch_dir_perms;
- static const char *solo_file = NULL;
+@@ -122,6 +122,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_AN_IMMUTABLE      (1<<8) /* item has an immutable flag set */
  
-+#ifdef SUPPORT_FLAGS
-+#define FF_PTR(p) F_FFLAGS(p)
-+#define FF_STAT(s) s.st_flags
-+#else
-+#define FF_PTR(p) 0
-+#define FF_STAT(s) 0
-+#endif
-+
- /* For calling delete_item() and delete_dir_contents(). */
- #define DEL_RECURSE           (1<<1) /* recurse */
- #define DEL_DIR_IS_EMPTY      (1<<2) /* internal delete_FUNCTIONS use only */
-@@ -127,7 +135,6 @@ enum delret {
- /* Forward declaration for delete_item(). */
- static enum delret delete_dir_contents(char *fname, int flags);
--
- static int is_backup_file(char *fn)
- {
-       int k = strlen(fn) - backup_suffix_len;
-@@ -140,17 +147,20 @@ static int is_backup_file(char *fn)
-  * Note that fbuf must point to a MAXPATHLEN buffer if the mode indicates it's
-  * a directory! (The buffer is used for recursion, but returned unchanged.)
-  */
--static enum delret delete_item(char *fbuf, int mode, char *replace, int flags)
-+static enum delret delete_item(char *fbuf, int mode, uint32 fileflags, char *replace, int flags)
- {
-       enum delret ret;
-       char *what;
-       int ok;
-       if (verbose > 2) {
--              rprintf(FINFO, "delete_item(%s) mode=%o flags=%d\n",
--                      fbuf, mode, flags);
-+              rprintf(FINFO, "delete_item(%s) mode=%o fileflags=%o flags=%d\n",
-+                      fbuf, mode, fileflags, flags);
-       }
+ #define DEL_MAKE_ROOM (DEL_FOR_FILE|DEL_FOR_DIR|DEL_FOR_SYMLINK|DEL_FOR_DEVICE|DEL_FOR_SPECIAL)
+@@ -161,6 +162,10 @@ static enum delret delete_item(char *fbuf, int mode, int flags)
  
+       if (!am_root && !(mode & S_IWUSR) && flags & DEL_OWNED_BY_US)
+               do_chmod(fbuf, mode |= S_IWUSR);
 +#ifdef SUPPORT_FLAGS
-+      make_mutable(fbuf, mode, fileflags);
++      if (fileflags_ndx && flags & DEL_AN_IMMUTABLE)
++              make_mutable(fbuf, mode, NODELETE_FLAGS);
 +#endif
        if (S_ISDIR(mode) && !(flags & DEL_DIR_IS_EMPTY)) {
                ignore_perishable = 1;
-               /* If DEL_RECURSE is not set, this just reports emptiness. */
-@@ -262,7 +272,7 @@ static enum delret delete_dir_contents(char *fname, int flags)
-               if (S_ISDIR(fp->mode)
-                && delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS)
-                       ret = DR_NOT_EMPTY;
--              if (delete_item(fname, fp->mode, NULL, flags) != DR_SUCCESS)
-+              if (delete_item(fname, fp->mode, FF_PTR(fp), NULL, flags) != DR_SUCCESS)
-                       ret = DR_NOT_EMPTY;
-       }
-@@ -318,8 +328,9 @@ static int remember_delete(struct file_struct *file, const char *fname)
+@@ -282,6 +287,14 @@ static enum delret delete_dir_contents(char *fname, int flags)
+                       flags |= DEL_OWNED_BY_US;
+               else
+                       flags &= ~DEL_OWNED_BY_US;
++#ifdef SUPPORT_FLAGS
++              if (fileflags_ndx) {
++                      if (F_FFLAGS(fp) & NODELETE_FLAGS)
++                              flags |= DEL_AN_IMMUTABLE;
++                      else
++                              flags &= ~DEL_AN_IMMUTABLE;
++              }
++#endif 
+               /* Save stack by recursing to ourself directly. */
+               if (S_ISDIR(fp->mode)) {
+                       if (!am_root && !(fp->mode & S_IWUSR) && flags & DEL_OWNED_BY_US)
+@@ -341,15 +354,22 @@ static int flush_delete_delay(void)
+ static int remember_delete(struct file_struct *file, const char *fname, int flags)
+ {
+-      const char *plus = (!am_root && !(file->mode & S_IWUSR) && flags & DEL_OWNED_BY_US)
+-                       ? "+" : "";
++      char buf[16], *bp = buf;
+       int len;
  
++      if (!am_root && !(file->mode & S_IWUSR) && flags & DEL_OWNED_BY_US)
++              *bp++ = '+';
++#ifdef SUPPORT_FLAGS
++      if (flags & DEL_AN_IMMUTABLE)
++              *bp++ = '-';
++#endif
++      *bp = '\0';
++
        while (1) {
                len = snprintf(deldelay_buf + deldelay_cnt,
--                             deldelay_size - deldelay_cnt,
--                             "%x %s%c", (int)file->mode, fname, '\0');
-+                             deldelay_size - deldelay_cnt, "%x %x %s%c",
-+                             (int)file->mode, (int)FF_PTR(file),
-+                             fname, '\0');
+                              deldelay_size - deldelay_cnt,
+                              "%s%x %s%c",
+-                             plus, (int)file->mode, fname, '\0');
++                             buf, (int)file->mode, fname, '\0');
                if ((deldelay_cnt += len) <= deldelay_size)
                        break;
                if (deldelay_fd < 0 && !start_delete_delay_temp())
-@@ -332,7 +343,7 @@ static int remember_delete(struct file_struct *file, const char *fname)
+@@ -362,10 +382,10 @@ static int remember_delete(struct file_struct *file, const char *fname, int flag
        return 1;
  }
  
--static int read_delay_line(char *buf)
-+static int read_delay_line(char *buf, int *fileflags_p)
+-static int read_delay_line(char *buf, int *own_flag_p)
++static int read_delay_line(char *buf, int *flags_p)
  {
        static int read_pos = 0;
-       int j, len, mode;
-@@ -374,12 +385,12 @@ static int read_delay_line(char *buf)
+-      int j, len, mode;
++      int j, len, mode, flags = 0;
+       char *bp, *past_space;
  
+       while (1) {
+@@ -405,9 +425,15 @@ static int read_delay_line(char *buf, int *own_flag_p)
        bp = deldelay_buf + read_pos;
+       if (*bp == '+') {
+               bp++;
+-              *own_flag_p = DEL_OWNED_BY_US;
+-      } else
+-              *own_flag_p = 0;
++              flags |= DEL_OWNED_BY_US;
++      }
++#ifdef SUPPORT_FLAGS
++      if (*bp == '-') {
++              bp++;
++              flags |= DEL_AN_IMMUTABLE;
++      }
++#endif
++      *flags_p = flags;
  
--      if (sscanf(bp, "%x ", &mode) != 1) {
-+      if (sscanf(bp, "%x %x ", &mode, fileflags_p) != 2) {
+       if (sscanf(bp, "%x ", &mode) != 1) {
          invalid_data:
-               rprintf(FERROR, "ERROR: invalid data in delete-delay file.\n");
-               return -1;
-       }
--      past_space = strchr(bp, ' ') + 1;
-+      past_space = strchr(strchr(bp, ' ') + 1, ' ') + 1;
-       len = j - read_pos - (past_space - bp) + 1; /* count the '\0' */
-       read_pos = j + 1;
-@@ -397,15 +408,15 @@ static int read_delay_line(char *buf)
+@@ -432,15 +458,15 @@ static int read_delay_line(char *buf, int *own_flag_p)
  
  static void do_delayed_deletions(char *delbuf)
  {
--      int mode;
-+      int mode, fileflags;
+-      int mode, own_flag;
++      int mode, flags;
  
        if (deldelay_fd >= 0) {
                if (deldelay_cnt && !flush_delete_delay())
                        return;
                lseek(deldelay_fd, 0, 0);
        }
--      while ((mode = read_delay_line(delbuf)) >= 0)
--              delete_item(delbuf, mode, NULL, DEL_RECURSE);
-+      while ((mode = read_delay_line(delbuf, &fileflags)) >= 0)
-+              delete_item(delbuf, mode, fileflags, NULL, DEL_RECURSE);
+-      while ((mode = read_delay_line(delbuf, &own_flag)) >= 0)
+-              delete_item(delbuf, mode, own_flag | DEL_RECURSE);
++      while ((mode = read_delay_line(delbuf, &flags)) >= 0)
++              delete_item(delbuf, mode, DEL_RECURSE | flags);
        if (deldelay_fd >= 0)
                close(deldelay_fd);
  }
-@@ -472,7 +483,7 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
-                               if (!remember_delete(fp, delbuf))
-                                       break;
-                       } else
--                              delete_item(delbuf, fp->mode, NULL, DEL_RECURSE);
-+                              delete_item(delbuf, fp->mode, FF_PTR(fp), NULL, DEL_RECURSE);
+@@ -503,6 +529,9 @@ static void delete_in_dir(char *fbuf, struct file_struct *file, dev_t *fs_dev)
                }
-       }
+               if (flist_find(cur_flist, fp) < 0) {
+                       int flags = DEL_RECURSE
++#ifdef SUPPORT_FLAGS
++                                | (fileflags_ndx && F_FFLAGS(fp) & NODELETE_FLAGS ? DEL_AN_IMMUTABLE : 0)
++#endif
+                                 | (!uid_ndx || (uid_t)F_OWNER(fp) == our_uid ? DEL_OWNED_BY_US : 0);
+                       f_name(fp, delbuf);
+                       if (delete_during == 2) {
+@@ -1316,6 +1345,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
  
-@@ -1294,7 +1305,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
-                        * full later (right before we handle its contents). */
-                       if (statret == 0
-                        && (S_ISDIR(sx.st.st_mode)
--                        || delete_item(fname, sx.st.st_mode, "directory", del_opts) != 0))
-+                        || delete_item(fname, sx.st.st_mode, FF_STAT(sx.st), "directory", del_opts) != 0))
-                               goto cleanup; /* Any errors get reported later. */
-                       if (do_mkdir(fname, file->mode & 0700) == 0)
-                               file->flags |= FLAG_DIR_CREATED;
-@@ -1306,7 +1317,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
-                * we need to delete it.  If it doesn't exist, then
-                * (perhaps recursively) create it. */
-               if (statret == 0 && !S_ISDIR(sx.st.st_mode)) {
--                      if (delete_item(fname, sx.st.st_mode, "directory", del_opts) != 0)
-+                      if (delete_item(fname, sx.st.st_mode, FF_STAT(sx.st), "directory", del_opts) != 0)
-                               goto skipping_dir_contents;
-                       statret = -1;
-               }
-@@ -1435,7 +1446,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
-                       }
-                       /* Not the right symlink (or not a symlink), so
-                        * delete it. */
--                      if (delete_item(fname, sx.st.st_mode, "symlink", del_opts) != 0)
-+                      if (delete_item(fname, sx.st.st_mode, FF_STAT(sx.st), "symlink", del_opts) != 0)
-                               goto cleanup;
-               } else if (basis_dir[0] != NULL) {
-                       int j = try_dests_non(file, fname, ndx, fnamecmpbuf, &sx,
-@@ -1514,7 +1525,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
-                                       goto return_with_success;
-                               goto cleanup;
-                       }
--                      if (delete_item(fname, sx.st.st_mode, t, del_opts) != 0)
-+                      if (delete_item(fname, sx.st.st_mode, FF_STAT(sx.st), t, del_opts) != 0)
-                               goto cleanup;
-               } else if (basis_dir[0] != NULL) {
-                       int j = try_dests_non(file, fname, ndx, fnamecmpbuf, &sx,
-@@ -1605,7 +1616,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
-       fnamecmp_type = FNAMECMP_FNAME;
-       if (statret == 0 && !S_ISREG(sx.st.st_mode)) {
--              if (delete_item(fname, sx.st.st_mode, "regular file", del_opts) != 0)
-+              if (delete_item(fname, sx.st.st_mode, FF_STAT(sx.st), "regular file", del_opts) != 0)
-                       goto cleanup;
-               statret = -1;
-               stat_errno = ENOENT;
+       if (statret == 0 && sx.st.st_uid == our_uid)
+               del_opts |= DEL_OWNED_BY_US;
++#ifdef SUPPORT_FLAGS
++      if (statret == 0 && fileflags_ndx && sx.st.st_flags & NODELETE_FLAGS)
++              del_opts |= DEL_AN_IMMUTABLE;
++#endif
+       if (S_ISDIR(file->mode)) {
+               if (!implied_dirs && file->flags & FLAG_IMPLIED_DIR)
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
@@ -372,7 +338,7 @@ diff --git a/options.c b/options.c
 +#ifndef SUPPORT_FLAGS
 +      if (preserve_fileflags) {
 +              snprintf(err_buf, sizeof err_buf,
-+                       "file flags are not supported on this %s\n",
++                       "the --fileflags option is not supported on this %s\n",
 +                       am_server ? "server" : "client");
 +              return 0;
 +      }
@@ -381,12 +347,12 @@ diff --git a/options.c b/options.c
        if (write_batch && read_batch) {
                snprintf(err_buf, sizeof err_buf,
                        "--write-batch and --read-batch can not be used together\n");
-@@ -1803,6 +1820,9 @@ void server_options(char **args, int *argc_p)
+@@ -1804,6 +1821,9 @@ void server_options(char **args, int *argc_p)
        if (xfer_dirs && !recurse && delete_mode && am_sender)
                args[ac++] = "--no-r";
  
 +      if (preserve_fileflags)
-+              args[ac++] = "--flags";
++              args[ac++] = "--fileflags";
 +
        if (do_compression && def_compress_level != Z_DEFAULT_COMPRESSION) {
                if (asprintf(&arg, "--compress-level=%d", def_compress_level) < 0)
@@ -402,24 +368,7 @@ diff --git a/rsync.c b/rsync.c
  extern int preserve_executability;
  extern int preserve_times;
  extern int am_root;
-@@ -60,6 +61,16 @@ iconv_t ic_chck = (iconv_t)-1;
- iconv_t ic_send = (iconv_t)-1, ic_recv = (iconv_t)-1;
- # endif
-+#ifdef SUPPORT_FLAGS
-+#ifndef UF_NOUNLINK
-+#define UF_NOUNLINK 0
-+#endif
-+#ifndef SF_NOUNLINK
-+#define SF_NOUNLINK 0
-+#endif
-+#define NOCHANGE_FLAGS (UF_IMMUTABLE|UF_APPEND|UF_NOUNLINK|SF_IMMUTABLE|SF_APPEND|SF_NOUNLINK)
-+#endif
-+
- static const char *default_charset(void)
- {
- # if defined HAVE_LIBCHARSET_H && defined HAVE_LOCALE_CHARSET
-@@ -338,6 +349,41 @@ mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int dflt_perms,
+@@ -338,6 +339,41 @@ mode_t dest_mode(mode_t flist_mode, mode_t stat_mode, int dflt_perms,
        return new_mode;
  }
  
@@ -440,7 +389,7 @@ diff --git a/rsync.c b/rsync.c
 +/* Remove immutable flags from an object, so it can be altered/removed. */
 +void make_mutable(const char *fname, mode_t mode, uint32 fileflags)
 +{
-+      if (!preserve_fileflags && S_ISLNK(mode))
++      if (S_ISLNK(mode))
 +              return;
 +
 +      if (fileflags & NOCHANGE_FLAGS)
@@ -450,7 +399,7 @@ diff --git a/rsync.c b/rsync.c
 +/* Undo a prior make_mutable() call. */
 +void undo_make_mutable(const char *fname, mode_t mode, uint32 fileflags)
 +{
-+      if (!preserve_fileflags && S_ISLNK(mode))
++      if (S_ISLNK(mode))
 +              return;
 +
 +      if (fileflags & NOCHANGE_FLAGS)
@@ -461,7 +410,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)
  {
-@@ -469,6 +515,15 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
+@@ -469,6 +505,15 @@ int set_file_attrs(const char *fname, struct file_struct *file, stat_x *sxp,
        }
  #endif
  
@@ -477,22 +426,24 @@ diff --git a/rsync.c b/rsync.c
        if (verbose > 1 && flags & ATTRS_REPORT) {
                if (updated)
                        rprintf(FCLIENT, "%s\n", fname);
-@@ -530,6 +585,9 @@ int finish_transfer(const char *fname, const char *fnametmp,
+@@ -530,6 +575,10 @@ int finish_transfer(const char *fname, const char *fnametmp,
        set_file_attrs(fnametmp, file, NULL, fnamecmp,
                       ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
  
 +#ifdef SUPPORT_FLAGS
-+      make_mutable(fnametmp, file->mode, F_FFLAGS(file));
++      if (preserve_fileflags)
++              make_mutable(fnametmp, file->mode, F_FFLAGS(file));
 +#endif
        /* move tmp file over real file */
        if (verbose > 2)
                rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname);
-@@ -547,6 +605,9 @@ int finish_transfer(const char *fname, const char *fnametmp,
+@@ -547,6 +596,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. */
 +#ifdef SUPPORT_FLAGS
-+              undo_make_mutable(fname, file->mode, F_FFLAGS(file));
++              if (preserve_fileflags)
++                      undo_make_mutable(fname, file->mode, F_FFLAGS(file));
 +#endif
                return 1;
        }
@@ -508,18 +459,29 @@ diff --git a/rsync.h b/rsync.h
  
  /* These flags are used in the live flist data. */
  
-@@ -451,6 +452,10 @@ typedef unsigned int size_t;
+@@ -451,6 +452,21 @@ typedef unsigned int size_t;
  #endif
  #endif
  
 +#ifdef HAVE_CHFLAGS
 +#define SUPPORT_FLAGS 1
 +#endif
++
++#ifdef SUPPORT_FLAGS
++#ifndef UF_NOUNLINK
++#define UF_NOUNLINK 0
++#endif
++#ifndef SF_NOUNLINK
++#define SF_NOUNLINK 0
++#endif
++#define NODELETE_FLAGS (UF_IMMUTABLE|UF_NOUNLINK|SF_IMMUTABLE|SF_NOUNLINK)
++#define NOCHANGE_FLAGS (NODELETE_FLAGS|UF_APPEND|SF_APPEND)
++#endif
 +
  /* 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. */
-@@ -618,6 +623,7 @@ extern int file_extra_cnt;
+@@ -619,6 +635,7 @@ extern int file_extra_cnt;
  extern int inc_recurse;
  extern int uid_ndx;
  extern int gid_ndx;
@@ -527,7 +489,7 @@ diff --git a/rsync.h b/rsync.h
  extern int acls_ndx;
  extern int xattrs_ndx;
  
-@@ -655,6 +661,7 @@ extern int xattrs_ndx;
+@@ -656,6 +673,7 @@ 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
@@ -542,26 +504,25 @@ diff --git a/rsync.yo b/rsync.yo
   -K, --keep-dirlinks         treat symlinked dir on receiver as dir
   -H, --hard-links            preserve hard links
   -p, --perms                 preserve permissions
-+     --flags                 preserve file flags
++     --fileflags             preserve file-flags
   -E, --executability         preserve executability
       --chmod=CHMOD           affect file and/or directory permissions
   -A, --acls                  preserve ACLs (implies -p)
-@@ -540,7 +541,9 @@ specified, in which case bf(-r) is not implied.
+@@ -540,7 +541,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
 -specify bf(-H).
-+specify bf(-H).  Note also that for compatibility, bf(-a)
-+currently bf(does not include --flags) (see there) to include preserving
-+change file flags (if supported by the OS).
++specify bf(-H).  Note also that for backward compatibility, bf(-a)
++currently does bf(not) imply the bf(--fileflags) option.
  
  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-":
-@@ -909,6 +912,13 @@ super-user copies all namespaces except system.*.  A normal user only copies
+@@ -922,6 +924,13 @@ 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.
  
-+dit(bf(--flags)) This option causes rsync to update the change file flags
++dit(bf(--fileflags)) This option causes rsync to update the file-flags
 +to be the same as the source file, if your OS supports the bf(chflags)(2)
 +system call.  In any case, an attempt is made to remove flags that would
 +prevent a file to be altered.  Some flags can only be altered by the
@@ -574,7 +535,7 @@ diff --git a/rsync.yo b/rsync.yo
 diff --git a/syscall.c b/syscall.c
 --- a/syscall.c
 +++ b/syscall.c
-@@ -173,6 +173,15 @@ int do_chmod(const char *path, mode_t mode)
+@@ -174,6 +174,15 @@ int do_chmod(const char *path, mode_t mode)
  }
  #endif
  
index fb8f076..f782f24 100644 (file)
@@ -34,7 +34,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 },
-@@ -1954,6 +1957,9 @@ void server_options(char **args, int *argc_p)
+@@ -1955,6 +1958,9 @@ void server_options(char **args, int *argc_p)
                        args[ac++] = tmpdir;
                }
  
index 6faa4a6..eb5623d 100644 (file)
@@ -55,7 +55,7 @@ diff --git a/flist.c b/flist.c
  extern int ignore_errors;
  extern int numeric_ids;
  extern int recurse;
-@@ -2604,6 +2605,7 @@ int f_name_cmp(const struct file_struct *f1, const struct file_struct *f2)
+@@ -2615,6 +2616,7 @@ int f_name_cmp(const struct file_struct *f1, const struct file_struct *f2)
  {
        int dif;
        const uchar *c1, *c2;
@@ -63,7 +63,7 @@ diff --git a/flist.c b/flist.c
        enum fnc_state state1, state2;
        enum fnc_type type1, type2;
        enum fnc_type t_path = protocol_version >= 29 ? t_PATH : t_ITEM;
-@@ -2714,7 +2716,15 @@ int f_name_cmp(const struct file_struct *f1, const struct file_struct *f2)
+@@ -2725,7 +2727,15 @@ int f_name_cmp(const struct file_struct *f1, const struct file_struct *f2)
                        if (type1 != type2)
                                return type1 == t_PATH ? 1 : -1;
                }
@@ -236,7 +236,7 @@ diff --git a/options.c b/options.c
    {"files-from",       0,  POPT_ARG_STRING, &files_from, 0, 0, 0 },
    {"from0",           '0', POPT_ARG_VAL,    &eol_nulls, 1, 0, 0},
    {"no-from0",         0,  POPT_ARG_VAL,    &eol_nulls, 0, 0, 0},
-@@ -1916,6 +1920,9 @@ void server_options(char **args, int *argc_p)
+@@ -1917,6 +1921,9 @@ void server_options(char **args, int *argc_p)
                args[ac++] = arg;
        }
  
@@ -257,7 +257,7 @@ diff --git a/rsync.yo b/rsync.yo
       --address=ADDRESS       bind address for outgoing socket to daemon
       --port=PORT             specify double-colon alternate port number
       --sockopts=OPTIONS      specify custom TCP options
-@@ -1409,6 +1410,10 @@ If you use this option with bf(--iconv), the args will also be translated
+@@ -1425,6 +1426,10 @@ If you use this option with bf(--iconv), the args will also be translated
  from the local to the remote character set.  The translation happens before
  wild-cards are expanded.  See also the bf(--files-from) option.
  
index 423c9a2..454edce 100644 (file)
@@ -443,7 +443,7 @@ diff --git a/options.c b/options.c
                default:
                        /* A large opt value means that set_refuse_options()
                         * turned this option off. */
-@@ -1974,6 +1992,11 @@ void server_options(char **args, int *argc_p)
+@@ -1975,6 +1993,11 @@ void server_options(char **args, int *argc_p)
        } else if (inplace)
                args[ac++] = "--inplace";
  
@@ -520,7 +520,7 @@ diff --git a/receiver.c b/receiver.c
  }
  
  static void handle_delayed_updates(char *local_name)
-@@ -675,7 +686,7 @@ int recv_files(int f_in, char *local_name)
+@@ -676,7 +687,7 @@ int recv_files(int f_in, char *local_name)
  
                /* recv file data */
                recv_ok = receive_data(f_in, fnamecmp, fd1, st.st_size,
@@ -561,7 +561,7 @@ diff --git a/rsync.c b/rsync.c
 diff --git a/rsync.h b/rsync.h
 --- a/rsync.h
 +++ b/rsync.h
-@@ -816,6 +816,14 @@ struct stats {
+@@ -817,6 +817,14 @@ struct stats {
        int num_transferred_files;
  };
  
index 7dd5f48..18ca205 100644 (file)
@@ -98,7 +98,7 @@ diff --git a/match.c b/match.c
 diff --git a/options.c b/options.c
 --- a/options.c
 +++ b/options.c
-@@ -1475,7 +1475,8 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1476,7 +1476,8 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
                else if (log_format_has(stdout_format, 'i'))
                        stdout_format_has_i = itemize_changes | 1;
                if (!log_format_has(stdout_format, 'b')
@@ -155,7 +155,7 @@ diff --git a/receiver.c b/receiver.c
 diff --git a/rsync.yo b/rsync.yo
 --- a/rsync.yo
 +++ b/rsync.yo
-@@ -2046,7 +2046,7 @@ by the server and defaults to the current code(time()).  This option
+@@ -2065,7 +2065,7 @@ by the server and defaults to the current code(time()).  This option
  is used to set a specific checksum seed, which is useful for
  applications that want repeatable block and file checksums, or
  in the case where the user wants a more random checksum seed.
index 2f428c8..b599678 100644 (file)
@@ -93,7 +93,7 @@ diff --git a/clientserver.c b/clientserver.c
                umask(0);
        }
  #endif
-@@ -789,6 +829,44 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
+@@ -793,6 +833,44 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
        return 0;
  }
  
index 9be94e3..ca148e1 100644 (file)
@@ -18,7 +18,7 @@ diff --git a/generator.c b/generator.c
  extern int uid_ndx;
  extern int gid_ndx;
  extern int delete_mode;
-@@ -560,6 +561,7 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+@@ -597,6 +598,7 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
                int keep_time = !preserve_times ? 0
                    : S_ISDIR(file->mode) ? preserve_times > 1
                    : !S_ISLNK(file->mode);
@@ -26,7 +26,7 @@ diff --git a/generator.c b/generator.c
  
                if (S_ISREG(file->mode) && F_LENGTH(file) != sxp->st.st_size)
                        iflags |= ITEM_REPORT_SIZE;
-@@ -575,10 +577,11 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+@@ -612,10 +614,11 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
  #endif
                if (!BITS_EQUAL(sxp->st.st_mode, file->mode, CHMOD_BITS))
                        iflags |= ITEM_REPORT_PERMS;
@@ -41,7 +41,7 @@ diff --git a/generator.c b/generator.c
                        iflags |= ITEM_REPORT_GROUP;
  #ifdef SUPPORT_ACLS
                if (preserve_acls && !S_ISLNK(file->mode)) {
-@@ -1319,7 +1322,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
+@@ -1353,7 +1356,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                real_sx = sx;
                if (file->flags & FLAG_DIR_CREATED)
                        statret = -1;
@@ -77,7 +77,7 @@ diff --git a/options.c b/options.c
    {"modify-window",    0,  POPT_ARG_INT,    &modify_window, OPT_MODIFY_WINDOW, 0, 0 },
    {"super",            0,  POPT_ARG_VAL,    &am_root, 2, 0, 0 },
    {"no-super",         0,  POPT_ARG_VAL,    &am_root, 0, 0, 0 },
-@@ -1460,6 +1463,8 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1461,6 +1464,8 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
                parse_rule(&filter_list, backup_dir_buf, 0, 0);
        }
  
@@ -86,7 +86,7 @@ diff --git a/options.c b/options.c
        if (make_backups && !backup_dir) {
                omit_dir_times = 0; /* Implied, so avoid -O to sender. */
                if (preserve_times > 1)
-@@ -1698,6 +1703,8 @@ void server_options(char **args, int *argc_p)
+@@ -1699,6 +1704,8 @@ void server_options(char **args, int *argc_p)
                        argstr[x++] = 'm';
                if (omit_dir_times)
                        argstr[x++] = 'O';
@@ -131,7 +131,7 @@ diff --git a/rsync.yo b/rsync.yo
       --super                 receiver attempts super-user activities
       --fake-super            store/recover privileged attrs using xattrs
   -S, --sparse                handle sparse files efficiently
-@@ -974,6 +975,10 @@ it is preserving modification times (see bf(--times)).  If NFS is sharing
+@@ -987,6 +988,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 8dc8924..6faebdc 100644 (file)
@@ -163,7 +163,7 @@ diff --git a/clientserver.c b/clientserver.c
                        return -1;
                }
  
-@@ -839,6 +886,9 @@ int start_daemon(int f_in, int f_out)
+@@ -843,6 +890,9 @@ int start_daemon(int f_in, int f_out)
        if (exchange_protocols(f_in, f_out, line, sizeof line, 0) < 0)
                return -1;
  
@@ -173,7 +173,7 @@ diff --git a/clientserver.c b/clientserver.c
        line[0] = 0;
        if (!read_line_old(f_in, line, sizeof line))
                return -1;
-@@ -850,6 +900,20 @@ int start_daemon(int f_in, int f_out)
+@@ -854,6 +904,20 @@ int start_daemon(int f_in, int f_out)
                return -1;
        }
  
@@ -375,7 +375,7 @@ diff --git a/options.c b/options.c
                default:
                        /* A large opt value means that set_refuse_options()
                         * turned this option off. */
-@@ -1544,6 +1607,17 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1545,6 +1608,17 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
        if (delay_updates && !partial_dir)
                partial_dir = tmp_partialdir;
  
@@ -393,7 +393,7 @@ diff --git a/options.c b/options.c
        if (inplace) {
  #ifdef HAVE_FTRUNCATE
                if (partial_dir) {
-@@ -2018,10 +2092,27 @@ char *check_for_hostspec(char *s, char **host_ptr, int *port_ptr)
+@@ -2019,10 +2093,27 @@ char *check_for_hostspec(char *s, char **host_ptr, int *port_ptr)
        char *p;
        int not_host;
        int hostlen;
index f5f21a4..fb8354c 100644 (file)
@@ -95,7 +95,7 @@ diff --git a/options.c b/options.c
        if (write_batch && read_batch) {
                snprintf(err_buf, sizeof err_buf,
                        "--write-batch and --read-batch can not be used together\n");
-@@ -1999,6 +2017,9 @@ void server_options(char **args, int *argc_p)
+@@ -2000,6 +2018,9 @@ void server_options(char **args, int *argc_p)
        else if (remove_source_files)
                args[ac++] = "--remove-sent-files";
  
@@ -160,7 +160,7 @@ diff --git a/receiver.c b/receiver.c
 diff --git a/rsync.h b/rsync.h
 --- a/rsync.h
 +++ b/rsync.h
-@@ -600,6 +600,10 @@ struct ht_int64_node {
+@@ -601,6 +601,10 @@ struct ht_int64_node {
  #define ACLS_NEED_MASK 1
  #endif
  
@@ -182,7 +182,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
-@@ -1023,6 +1024,19 @@ NOTE: Don't use this option when the destination is a Solaris "tmpfs"
+@@ -1036,6 +1037,19 @@ 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 49376ad..df1090a 100644 (file)
@@ -25,7 +25,7 @@ diff --git a/flist.c b/flist.c
  extern struct stats stats;
  extern char *filesfrom_host;
  
-@@ -1494,6 +1495,9 @@ static void send_directory(int f, struct file_list *flist, char *fbuf, int len,
+@@ -1500,6 +1501,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);
index 12dd4b6..6fd3c2e 100644 (file)
--- a/slp.diff
+++ b/slp.diff
@@ -43,7 +43,7 @@ diff --git a/Makefile.in b/Makefile.in
 diff --git a/clientserver.c b/clientserver.c
 --- a/clientserver.c
 +++ b/clientserver.c
-@@ -973,6 +973,13 @@ int daemon_main(void)
+@@ -977,6 +977,13 @@ int daemon_main(void)
         * address too.  In fact, why not just do inet_ntop on the
         * local address??? */
  
@@ -126,7 +126,7 @@ diff --git a/loadparm.c b/loadparm.c
 diff --git a/main.c b/main.c
 --- a/main.c
 +++ b/main.c
-@@ -1144,6 +1144,18 @@ static int start_client(int argc, char *argv[])
+@@ -1146,6 +1146,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);
index afc62d9..c4ccd43 100644 (file)
@@ -13,7 +13,7 @@ To use this patch, run these commands for a successful build:
 diff --git a/syscall.c b/syscall.c
 --- a/syscall.c
 +++ b/syscall.c
-@@ -62,9 +62,14 @@ int do_symlink(const char *fname1, const char *fname2)
+@@ -63,9 +63,14 @@ int do_symlink(const char *fname1, const char *fname2)
  #ifdef HAVE_LINK
  int do_link(const char *fname1, const char *fname2)
  {
index 8dc21d5..f65cd8f 100644 (file)
@@ -36,7 +36,7 @@ diff --git a/options.c b/options.c
    {"no-backup",        0,  POPT_ARG_VAL,    &make_backups, 0, 0, 0 },
    {"backup-dir",       0,  POPT_ARG_STRING, &backup_dir, 0, 0, 0 },
    {"suffix",           0,  POPT_ARG_STRING, &backup_suffix, 0, 0, 0 },
-@@ -1902,6 +1905,8 @@ void server_options(char **args, int *argc_p)
+@@ -1903,6 +1906,8 @@ void server_options(char **args, int *argc_p)
                                goto oom;
                        args[ac++] = arg;
                }
@@ -56,7 +56,7 @@ diff --git a/rsync.yo b/rsync.yo
       --del                   an alias for --delete-during
       --delete                delete extraneous files from dest dirs
       --delete-before         receiver deletes before transfer (default)
-@@ -1085,6 +1086,14 @@ dit(bf(--remove-source-files)) This tells rsync to remove from the sending
+@@ -1098,6 +1099,14 @@ dit(bf(--remove-source-files)) This tells rsync to remove from the sending
  side the files (meaning non-directories) that are a part of the transfer
  and have been successfully duplicated on the receiving side.
  
index 5a5bf15..b1605f3 100644 (file)
@@ -41,7 +41,7 @@ diff --git a/generator.c b/generator.c
  extern int size_only;
  extern OFF_T max_size;
  extern OFF_T min_size;
-@@ -630,7 +631,7 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
+@@ -667,7 +668,7 @@ void itemize(const char *fnamecmp, struct file_struct *file, int ndx, int statre
  /* Perform our quick-check heuristic for determining if a file is unchanged. */
  int unchanged_file(char *fn, struct file_struct *file, STRUCT_STAT *st)
  {
@@ -53,7 +53,7 @@ diff --git a/generator.c b/generator.c
 diff --git a/main.c b/main.c
 --- a/main.c
 +++ b/main.c
-@@ -137,7 +137,7 @@ pid_t wait_process(pid_t pid, int *status_ptr, int flags)
+@@ -139,7 +139,7 @@ pid_t wait_process(pid_t pid, int *status_ptr, int flags)
  }
  
  /* Wait for a process to exit, calling io_flush while waiting. */
@@ -116,7 +116,7 @@ diff --git a/options.c b/options.c
    {"protocol",         0,  POPT_ARG_INT,    &protocol_version, 0, 0, 0 },
    {"checksum-seed",    0,  POPT_ARG_INT,    &checksum_seed, 0, 0, 0 },
    {"server",           0,  POPT_ARG_NONE,   0, OPT_SERVER, 0, 0 },
-@@ -1585,6 +1594,16 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1586,6 +1595,16 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
                }
        }
  
@@ -133,7 +133,7 @@ diff --git a/options.c b/options.c
        if (files_from) {
                char *h, *p;
                int q;
-@@ -1904,6 +1923,25 @@ void server_options(char **args, int *argc_p)
+@@ -1905,6 +1924,25 @@ void server_options(char **args, int *argc_p)
                }
        }
  
@@ -251,7 +251,7 @@ diff --git a/receiver.c b/receiver.c
  extern char *partial_dir;
  extern char *basis_dir[];
  extern struct file_list *cur_flist, *first_flist, *dir_flist;
-@@ -394,6 +395,8 @@ int recv_files(int f_in, char *local_name)
+@@ -395,6 +396,8 @@ int recv_files(int f_in, char *local_name)
        const char *parent_dirname = "";
  #endif
        int ndx, recv_ok;
@@ -260,7 +260,7 @@ diff --git a/receiver.c b/receiver.c
  
        if (verbose > 2)
                rprintf(FINFO, "recv_files(%d) starting\n", cur_flist->used);
-@@ -401,6 +404,23 @@ int recv_files(int f_in, char *local_name)
+@@ -402,6 +405,23 @@ int recv_files(int f_in, char *local_name)
        if (delay_updates)
                delayed_bits = bitbag_create(cur_flist->used + 1);
  
@@ -284,7 +284,7 @@ diff --git a/receiver.c b/receiver.c
        while (1) {
                cleanup_disable();
  
-@@ -673,6 +693,9 @@ int recv_files(int f_in, char *local_name)
+@@ -674,6 +694,9 @@ int recv_files(int f_in, char *local_name)
                else if (!am_server && verbose && do_progress)
                        rprintf(FINFO, "%s\n", fname);
  
@@ -294,7 +294,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));
-@@ -687,6 +710,16 @@ int recv_files(int f_in, char *local_name)
+@@ -688,6 +711,16 @@ int recv_files(int f_in, char *local_name)
                        exit_cleanup(RERR_FILEIO);
                }
  
@@ -342,7 +342,7 @@ diff --git a/rsync.yo b/rsync.yo
       --protocol=NUM          force an older protocol version to be used
       --iconv=CONVERT_SPEC    request charset conversion of filenames
       --checksum-seed=NUM     set block/file checksum seed (advanced)
-@@ -2003,6 +2006,33 @@ file previously generated by bf(--write-batch).
+@@ -2021,6 +2024,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.
  
index 118ce58..e6a6876 100644 (file)
@@ -123,7 +123,7 @@ diff --git a/options.c b/options.c
                default:
                        /* A large opt value means that set_refuse_options()
                         * turned this option off. */
-@@ -1848,6 +1883,15 @@ void server_options(char **args, int *argc_p)
+@@ -1849,6 +1884,15 @@ void server_options(char **args, int *argc_p)
                args[ac++] = arg;
        }
  
@@ -151,7 +151,7 @@ diff --git a/rsync.yo b/rsync.yo
       --write-batch=FILE      write a batched update to FILE
       --only-write-batch=FILE like --write-batch but w/o updating dest
       --read-batch=FILE       read a batched update from FILE
-@@ -1977,6 +1979,19 @@ transfer was too fast, it will wait before sending the next data block. The
+@@ -1995,6 +1997,19 @@ transfer was too fast, it will wait before sending the next data block. The
  result is an average transfer rate equaling the specified limit. A value
  of zero specifies no limit.
  
index 7f3a6bd..92d61a7 100644 (file)
@@ -89,7 +89,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_NONE,   &allow_8bit_chars, 0, 0, 0 },
-@@ -1631,6 +1635,31 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
+@@ -1632,6 +1636,31 @@ int parse_arguments(int *argc_p, const char ***argv_p, int frommain)
                }
        }
  
@@ -121,7 +121,7 @@ diff --git a/options.c b/options.c
        am_starting_up = 0;
  
        return 1;
-@@ -1999,6 +2028,12 @@ void server_options(char **args, int *argc_p)
+@@ -2000,6 +2029,12 @@ void server_options(char **args, int *argc_p)
        else if (remove_source_files)
                args[ac++] = "--remove-sent-files";
  
@@ -145,7 +145,7 @@ diff --git a/rsync.yo b/rsync.yo
       --checksum-seed=NUM     set block/file checksum seed (advanced)
   -4, --ipv4                  prefer IPv4
   -6, --ipv6                  prefer IPv6
-@@ -2030,6 +2031,22 @@ specifying matching rules that can match on both sides of the transfer.
+@@ -2049,6 +2050,22 @@ specifying matching rules that can match on both sides of the transfer.
  For instance, you can specify extra include/exclude rules if there are
  filename differences on the two sides that need to be accounted for.
  
index 2b89567..14774a2 100644 (file)
@@ -36,7 +36,7 @@ diff --git a/flist.c b/flist.c
                                gid = match_gid(gid, &gid_flags);
                }
        }
-@@ -2074,8 +2075,13 @@ struct file_list *recv_file_list(int f)
+@@ -2085,8 +2086,13 @@ struct file_list *recv_file_list(int f)
        int dstart, flags;
        int64 start_read;
  
@@ -81,7 +81,7 @@ diff --git a/options.c b/options.c
    {"timeout",          0,  POPT_ARG_INT,    &io_timeout, 0, 0, 0 },
    {"no-timeout",       0,  POPT_ARG_VAL,    &io_timeout, 0, 0, 0 },
    {"contimeout",       0,  POPT_ARG_INT,    &connect_timeout, 0, 0, 0 },
-@@ -1942,6 +1948,18 @@ void server_options(char **args, int *argc_p)
+@@ -1943,6 +1949,18 @@ void server_options(char **args, int *argc_p)
                args[ac++] = "--use-qsort";
  
        if (am_sender) {
@@ -112,7 +112,7 @@ diff --git a/rsync.yo b/rsync.yo
       --timeout=SECONDS       set I/O timeout in seconds
       --contimeout=SECONDS    set daemon connection timeout in seconds
   -I, --ignore-times          don't skip files that match size and time
-@@ -1579,6 +1581,46 @@ from the source system is used instead.  See also the comments on the
+@@ -1595,6 +1597,46 @@ from the source system is used instead.  See also the comments on the
  the chroot setting affects rsync's ability to look up the names of the
  users and groups and what you can do about it.
  
index 0768dae..cf9cc7e 100644 (file)
@@ -13,7 +13,7 @@ To use this patch, run these commands for a successful build:
 diff --git a/compat.c b/compat.c
 --- a/compat.c
 +++ b/compat.c
-@@ -175,13 +175,6 @@ void setup_protocol(int f_out,int f_in)
+@@ -177,13 +177,6 @@ void setup_protocol(int f_out,int f_in)
        if (protocol_version < 30) {
                if (append_mode == 1)
                        append_mode = 2;
@@ -46,7 +46,7 @@ diff --git a/xattrs.c b/xattrs.c
  
  #define RSYNC_XAL_INITIAL 5
  #define RSYNC_XAL_LIST_INITIAL 100
-@@ -242,7 +244,7 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
+@@ -239,7 +241,7 @@ static int rsync_xal_get(const char *fname, item_list *xalp)
                if (!(ptr = get_xattr_data(fname, name, &datum_len, 0)))
                        return -1;
  
@@ -55,7 +55,7 @@ diff --git a/xattrs.c b/xattrs.c
                        /* For large datums, we store a flag and a checksum. */
                        name_offset = 1 + MAX_DIGEST_LEN;
                        sum_init(checksum_seed);
-@@ -310,7 +312,7 @@ static int find_matching_xattr(item_list *xalp)
+@@ -307,7 +309,7 @@ static int find_matching_xattr(item_list *xalp)
                         || rxas1[j].datum_len != rxas2[j].datum_len
                         || strcmp(rxas1[j].name, rxas2[j].name))
                                break;
@@ -64,7 +64,7 @@ diff --git a/xattrs.c b/xattrs.c
                                if (memcmp(rxas1[j].datum + 1,
                                           rxas2[j].datum + 1,
                                           MAX_DIGEST_LEN) != 0)
-@@ -347,34 +349,43 @@ int send_xattr(stat_x *sxp, int f)
+@@ -344,34 +346,43 @@ int send_xattr(stat_x *sxp, int f)
  {
        int ndx = find_matching_xattr(sxp->xattr);
  
@@ -118,7 +118,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);
-@@ -424,7 +435,7 @@ int xattr_diff(struct file_struct *file, stat_x *sxp, int find_all)
+@@ -421,7 +432,7 @@ int xattr_diff(struct file_struct *file, stat_x *sxp, int find_all)
                cmp = rec_cnt ? strcmp(snd_rxa->name, rec_rxa->name) : -1;
                if (cmp > 0)
                        same = 0;
@@ -127,7 +127,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;
-@@ -467,6 +478,9 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
+@@ -464,6 +475,9 @@ void send_xattr_request(const char *fname, struct file_struct *file, int f_out)
        int cnt, prior_req = 0;
        rsync_xa *rxa;
  
@@ -137,7 +137,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)
-@@ -540,6 +554,9 @@ int recv_xattr_request(struct file_struct *file, int f_in)
+@@ -518,6 +532,9 @@ int recv_xattr_request(struct file_struct *file, int f_in)
        rsync_xa *rxa;
        int rel_pos, cnt, num, got_xattr_data = 0;
  
@@ -147,7 +147,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);
-@@ -596,7 +613,22 @@ void receive_xattr(struct file_struct *file, int f)
+@@ -574,7 +591,22 @@ void receive_xattr(struct file_struct *file, int f)
  {
        static item_list temp_xattr = EMPTY_ITEM_LIST;
        int count, num;
@@ -171,7 +171,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"
-@@ -609,7 +641,7 @@ void receive_xattr(struct file_struct *file, int f)
+@@ -587,7 +619,7 @@ void receive_xattr(struct file_struct *file, int f)
                return;
        }
        
@@ -180,7 +180,7 @@ diff --git a/xattrs.c b/xattrs.c
                (void)EXPAND_ITEM_LIST(&temp_xattr, rsync_xa, count);
                temp_xattr.count = 0;
        }
-@@ -617,9 +649,10 @@ void receive_xattr(struct file_struct *file, int f)
+@@ -595,9 +627,10 @@ void receive_xattr(struct file_struct *file, int f)
        for (num = 1; num <= count; num++) {
                char *ptr, *name;
                rsync_xa *rxa;