This patch will make rsync 3.0.x able to exchange ACLs with an older
[rsync/rsync-patches.git] / xattrs.diff
index 39239b0..d2b4533 100644 (file)
@@ -18,9 +18,6 @@ TODO:
  - This patch needs to more efficiently handle large xattrs, especially when
    they're unchanged.
 
  - This patch needs to more efficiently handle large xattrs, especially when
    they're unchanged.
 
- - Extraneous xattr values need to be removed from files that are not being
-   recreated.
-
  - We need to affect the itemized output to know when xattrs are being updated.
 
  - We need to affect the --link-dest option to avoid hard-linking two files
  - We need to affect the itemized output to know when xattrs are being updated.
 
  - We need to affect the --link-dest option to avoid hard-linking two files
@@ -46,7 +43,7 @@ TODO:
  popt_OBJS=popt/findme.o  popt/popt.o  popt/poptconfig.o \
 --- old/backup.c
 +++ new/backup.c
  popt_OBJS=popt/findme.o  popt/popt.o  popt/poptconfig.o \
 --- old/backup.c
 +++ new/backup.c
-@@ -24,6 +24,7 @@
+@@ -23,6 +23,7 @@
  extern int verbose;
  extern int am_root;
  extern int preserve_acls;
  extern int verbose;
  extern int am_root;
  extern int preserve_acls;
@@ -54,7 +51,7 @@ TODO:
  extern int preserve_devices;
  extern int preserve_specials;
  extern int preserve_links;
  extern int preserve_devices;
  extern int preserve_specials;
  extern int preserve_links;
-@@ -135,6 +136,9 @@ static int make_bak_dir(char *fullpath)
+@@ -134,6 +135,9 @@ static int make_bak_dir(char *fullpath)
  #ifdef SUPPORT_ACLS
                                sx.acc_acl = sx.def_acl = NULL;
  #endif
  #ifdef SUPPORT_ACLS
                                sx.acc_acl = sx.def_acl = NULL;
  #endif
@@ -64,7 +61,7 @@ TODO:
                                if (!(file = make_file(rel, NULL, NULL, 0, NO_FILTERS)))
                                        continue;
  #ifdef SUPPORT_ACLS
                                if (!(file = make_file(rel, NULL, NULL, 0, NO_FILTERS)))
                                        continue;
  #ifdef SUPPORT_ACLS
-@@ -143,6 +147,12 @@ static int make_bak_dir(char *fullpath)
+@@ -142,6 +146,12 @@ static int make_bak_dir(char *fullpath)
                                        cache_acl(file, &sx);
                                }
  #endif
                                        cache_acl(file, &sx);
                                }
  #endif
@@ -77,7 +74,7 @@ TODO:
                                set_file_attrs(fullpath, file, NULL, 0);
                                free(file);
                        }
                                set_file_attrs(fullpath, file, NULL, 0);
                                free(file);
                        }
-@@ -194,6 +204,9 @@ static int keep_backup(const char *fname
+@@ -193,6 +203,9 @@ static int keep_backup(const char *fname
  #ifdef SUPPORT_ACLS
        sx.acc_acl = sx.def_acl = NULL;
  #endif
  #ifdef SUPPORT_ACLS
        sx.acc_acl = sx.def_acl = NULL;
  #endif
@@ -87,7 +84,7 @@ TODO:
  
        if (!(file = make_file(fname, NULL, NULL, 0, NO_FILTERS)))
                return 1; /* the file could have disappeared */
  
        if (!(file = make_file(fname, NULL, NULL, 0, NO_FILTERS)))
                return 1; /* the file could have disappeared */
-@@ -209,6 +222,12 @@ static int keep_backup(const char *fname
+@@ -208,6 +221,12 @@ static int keep_backup(const char *fname
                cache_acl(file, &sx);
        }
  #endif
                cache_acl(file, &sx);
        }
  #endif
@@ -102,18 +99,18 @@ TODO:
        if ((am_root && preserve_devices && IS_DEVICE(file->mode))
 --- old/compat.c
 +++ new/compat.c
        if ((am_root && preserve_devices && IS_DEVICE(file->mode))
 --- old/compat.c
 +++ new/compat.c
-@@ -50,6 +50,8 @@ void setup_protocol(int f_out,int f_in)
-               preserve_gid = ++flist_extra_cnt;
+@@ -64,6 +64,8 @@ void setup_protocol(int f_out,int f_in)
+               preserve_gid = ++file_extra_cnt;
        if (preserve_acls && !am_sender)
        if (preserve_acls && !am_sender)
-               preserve_acls = ++flist_extra_cnt;
+               preserve_acls = ++file_extra_cnt;
 +      if (preserve_xattrs && !am_sender)
 +      if (preserve_xattrs && !am_sender)
-+              preserve_xattrs = ++flist_extra_cnt;
++              preserve_xattrs = ++file_extra_cnt;
  
        if (remote_protocol == 0) {
                if (!read_batch)
 --- old/configure.in
 +++ new/configure.in
  
        if (remote_protocol == 0) {
                if (!read_batch)
 --- old/configure.in
 +++ new/configure.in
-@@ -878,6 +878,40 @@ samba_cv_HAVE_ACL_GET_PERM_NP=yes,samba_
+@@ -883,6 +883,40 @@ samba_cv_HAVE_ACL_GET_PERM_NP=yes,samba_
    AC_MSG_RESULT(no)
  )
  
    AC_MSG_RESULT(no)
  )
  
@@ -164,7 +161,7 @@ TODO:
  extern int preserve_links;
  extern int preserve_hard_links;
  extern int preserve_devices;
  extern int preserve_links;
  extern int preserve_hard_links;
  extern int preserve_devices;
-@@ -812,6 +813,10 @@ static struct file_struct *recv_file_ent
+@@ -864,6 +865,10 @@ static struct file_struct *recv_file_ent
        if (preserve_acls)
                receive_acl(file, f);
  #endif
        if (preserve_acls)
                receive_acl(file, f);
  #endif
@@ -173,10 +170,10 @@ TODO:
 +              receive_xattr(file, f );
 +#endif
  
 +              receive_xattr(file, f );
 +#endif
  
-       return file;
- }
-@@ -1082,7 +1087,7 @@ static struct file_struct *send_file_nam
-                                         unsigned short flags)
+       if (S_ISREG(mode) || S_ISLNK(mode))
+               stats.total_size += file_length;
+@@ -1136,7 +1141,7 @@ static struct file_struct *send_file_nam
+                                         int flags, int filter_flags)
  {
        struct file_struct *file;
 -#ifdef SUPPORT_ACLS
  {
        struct file_struct *file;
 -#ifdef SUPPORT_ACLS
@@ -184,7 +181,7 @@ TODO:
        statx sx;
  #endif
  
        statx sx;
  #endif
  
-@@ -1102,6 +1107,13 @@ static struct file_struct *send_file_nam
+@@ -1155,6 +1160,13 @@ static struct file_struct *send_file_nam
                        return NULL;
        }
  #endif
                        return NULL;
        }
  #endif
@@ -198,7 +195,7 @@ TODO:
  
        maybe_emit_filelist_progress(flist->count + flist_count_offset);
  
  
        maybe_emit_filelist_progress(flist->count + flist_count_offset);
  
-@@ -1113,6 +1125,10 @@ static struct file_struct *send_file_nam
+@@ -1166,6 +1178,10 @@ static struct file_struct *send_file_nam
                if (preserve_acls)
                        send_acl(&sx, f);
  #endif
                if (preserve_acls)
                        send_acl(&sx, f);
  #endif
@@ -378,7 +375,7 @@ TODO:
 +#endif
 --- old/options.c
 +++ new/options.c
 +#endif
 --- old/options.c
 +++ new/options.c
-@@ -48,6 +48,7 @@ int copy_links = 0;
+@@ -47,6 +47,7 @@ int copy_links = 0;
  int preserve_links = 0;
  int preserve_hard_links = 0;
  int preserve_acls = 0;
  int preserve_links = 0;
  int preserve_hard_links = 0;
  int preserve_acls = 0;
@@ -445,7 +442,7 @@ TODO:
    {"times",           't', POPT_ARG_VAL,    &preserve_times, 1, 0, 0 },
    {"no-times",         0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
    {"no-t",             0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
    {"times",           't', POPT_ARG_VAL,    &preserve_times, 1, 0, 0 },
    {"no-times",         0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
    {"no-t",             0,  POPT_ARG_VAL,    &preserve_times, 0, 0, 0 },
-@@ -1115,6 +1125,17 @@ int parse_arguments(int *argc, const cha
+@@ -1121,6 +1131,17 @@ int parse_arguments(int *argc, const cha
                        return 0;
  #endif
  
                        return 0;
  #endif
  
@@ -463,7 +460,7 @@ TODO:
  
                default:
                        /* A large opt value means that set_refuse_options()
  
                default:
                        /* A large opt value means that set_refuse_options()
-@@ -1562,6 +1583,10 @@ void server_options(char **args,int *arg
+@@ -1585,6 +1606,10 @@ void server_options(char **args,int *arg
        if (preserve_acls)
                argstr[x++] = 'A';
  #endif
        if (preserve_acls)
                argstr[x++] = 'A';
  #endif
@@ -471,12 +468,12 @@ TODO:
 +      if (preserve_xattrs)
 +              argstr[x++] = 'X';
 +#endif
 +      if (preserve_xattrs)
 +              argstr[x++] = 'X';
 +#endif
-       if (preserve_uid)
-               argstr[x++] = 'o';
-       if (preserve_gid)
+       if (recurse)
+               argstr[x++] = 'r';
+       if (always_checksum)
 --- old/rsync.c
 +++ new/rsync.c
 --- old/rsync.c
 +++ new/rsync.c
-@@ -33,6 +33,7 @@
+@@ -32,6 +32,7 @@
  extern int verbose;
  extern int dry_run;
  extern int preserve_acls;
  extern int verbose;
  extern int dry_run;
  extern int preserve_acls;
@@ -484,7 +481,7 @@ TODO:
  extern int preserve_perms;
  extern int preserve_executability;
  extern int preserve_times;
  extern int preserve_perms;
  extern int preserve_executability;
  extern int preserve_times;
-@@ -271,6 +272,10 @@ int set_file_attrs(char *fname, struct f
+@@ -321,6 +322,10 @@ int set_file_attrs(char *fname, struct f
        if (daemon_chmod_modes && !S_ISLNK(new_mode))
                new_mode = tweak_mode(new_mode, daemon_chmod_modes);
  
        if (daemon_chmod_modes && !S_ISLNK(new_mode))
                new_mode = tweak_mode(new_mode, daemon_chmod_modes);
  
@@ -497,7 +494,7 @@ TODO:
         * will enable owner-writability using chmod, if necessary.
 --- old/rsync.h
 +++ new/rsync.h
         * will enable owner-writability using chmod, if necessary.
 --- old/rsync.h
 +++ new/rsync.h
-@@ -511,6 +511,10 @@ struct idev_node {
+@@ -555,6 +555,10 @@ struct idev_node {
  #define ACLS_NEED_MASK 1
  #endif
  
  #define ACLS_NEED_MASK 1
  #endif
  
@@ -508,15 +505,23 @@ TODO:
  #define GID_NONE ((gid_t)-1)
  
  union file_extras {
  #define GID_NONE ((gid_t)-1)
  
  union file_extras {
-@@ -563,6 +567,7 @@ extern int preserve_gid;
- #define F_UID(f) REQ_EXTRA(f, preserve_uid)->unum
- #define F_GID(f) REQ_EXTRA(f, preserve_gid)->unum
+@@ -575,6 +579,7 @@ extern int file_extra_cnt;
+ extern int preserve_uid;
+ extern int preserve_gid;
+ extern int preserve_acls;
++extern int preserve_xattrs;
+ #define FILE_STRUCT_LEN (offsetof(struct file_struct, basename))
+ #define EXTRA_LEN (sizeof (union file_extras))
+@@ -608,6 +613,7 @@ extern int preserve_acls;
+ #define F_OWNER(f) REQ_EXTRA(f, preserve_uid)->unum
+ #define F_GROUP(f) REQ_EXTRA(f, preserve_gid)->unum
  #define F_ACL(f) REQ_EXTRA(f, preserve_acls)->unum
 +#define F_XATTR(f) REQ_EXTRA(f, preserve_xattrs)->unum
  
  /* These items are per-entry optional and mutally exclusive: */
  #define F_HL_GNUM(f) OPT_EXTRA(f, LEN64_BUMP(f))->num
  #define F_ACL(f) REQ_EXTRA(f, preserve_acls)->unum
 +#define F_XATTR(f) REQ_EXTRA(f, preserve_xattrs)->unum
  
  /* These items are per-entry optional and mutally exclusive: */
  #define F_HL_GNUM(f) OPT_EXTRA(f, LEN64_BUMP(f))->num
-@@ -738,6 +743,9 @@ typedef struct {
+@@ -799,6 +805,9 @@ typedef struct {
      struct rsync_acl *acc_acl; /* access ACL */
      struct rsync_acl *def_acl; /* default ACL */
  #endif
      struct rsync_acl *acc_acl; /* access ACL */
      struct rsync_acl *def_acl; /* default ACL */
  #endif
@@ -545,7 +550,7 @@ TODO:
   -o, --owner                 preserve owner (super-user only)
   -g, --group                 preserve group
       --devices               preserve device files (super-user only)
   -o, --owner                 preserve owner (super-user only)
   -g, --group                 preserve group
       --devices               preserve device files (super-user only)
-@@ -818,6 +819,11 @@ The ACL-sending protocol used by this ve
+@@ -835,6 +836,11 @@ The ACL-sending protocol used by this ve
  the patch that was shipped with 2.6.8.  Sending ACLs to an older version
  of the ACL patch is not supported.
  
  the patch that was shipped with 2.6.8.  Sending ACLs to an older version
  of the ACL patch is not supported.
  
@@ -559,7 +564,7 @@ TODO:
  transfer.  The resulting value is treated as though it was the permissions
 --- old/xattr.c
 +++ new/xattr.c
  transfer.  The resulting value is treated as though it was the permissions
 --- old/xattr.c
 +++ new/xattr.c
-@@ -0,0 +1,415 @@
+@@ -0,0 +1,459 @@
 +/*
 + * Extended Attribute support for rsync.
 + * Written by Jay Fenlason, vaguely based on the ACLs patch.
 +/*
 + * Extended Attribute support for rsync.
 + * Written by Jay Fenlason, vaguely based on the ACLs patch.
@@ -591,8 +596,6 @@ TODO:
 +extern int am_root;
 +extern int read_only;
 +extern int list_only;
 +extern int am_root;
 +extern int read_only;
 +extern int list_only;
-+extern int preserve_xattrs;
-+extern unsigned int file_struct_len;
 +
 +#define RSYNC_XAL_INITIAL 5
 +#define RSYNC_XAL_LIST_INITIAL 100
 +
 +#define RSYNC_XAL_INITIAL 5
 +#define RSYNC_XAL_LIST_INITIAL 100
@@ -651,16 +654,15 @@ TODO:
 +      return strcmp(xa1->name, xa2->name);
 +}
 +
 +      return strcmp(xa1->name, xa2->name);
 +}
 +
-+static int rsync_xal_get(const char *fname, item_list *xalp)
++static ssize_t rsync_xal_list(const char *fname)
 +{
 +{
-+      ssize_t list_len, name_len, datum_len;
-+      char *name, *ptr;
++      ssize_t list_len;
 +
 +      if (!namebuf) {
 +              namebuf_len = 1024;
 +              namebuf = new_array(char, namebuf_len);
 +              if (!namebuf)
 +
 +      if (!namebuf) {
 +              namebuf_len = 1024;
 +              namebuf = new_array(char, namebuf_len);
 +              if (!namebuf)
-+                      out_of_memory("rsync_xal_get");
++                      out_of_memory("rsync_xal_list");
 +      }
 +
 +      /* The length returned includes all the '\0' terminators. */
 +      }
 +
 +      /* The length returned includes all the '\0' terminators. */
@@ -676,29 +678,41 @@ TODO:
 +                      list_len = sys_llistxattr(fname, NULL, 0);
 +                      if (list_len < 0) {
 +                              rsyserr(FERROR, errno,
 +                      list_len = sys_llistxattr(fname, NULL, 0);
 +                      if (list_len < 0) {
 +                              rsyserr(FERROR, errno,
-+                                      "rsync_xal_get: llistxattr(\"%s\",0) failed",
++                                      "rsync_xal_list: llistxattr(\"%s\",0) failed",
 +                                      fname);
 +                              return -1;
 +                      }
 +                      namebuf = realloc_array(namebuf, char, list_len + 1024);
 +                      if (!namebuf)
 +                                      fname);
 +                              return -1;
 +                      }
 +                      namebuf = realloc_array(namebuf, char, list_len + 1024);
 +                      if (!namebuf)
-+                              out_of_memory("rsync_xal_get");
++                              out_of_memory("rsync_xal_list");
 +                      namebuf_len = list_len + 1024;
 +                      list_len = sys_llistxattr(fname, namebuf, namebuf_len);
 +                      if (list_len < 0) {
 +                              rsyserr(FERROR, errno,
 +                      namebuf_len = list_len + 1024;
 +                      list_len = sys_llistxattr(fname, namebuf, namebuf_len);
 +                      if (list_len < 0) {
 +                              rsyserr(FERROR, errno,
-+                                      "rsync_xal_get: llistxattr(\"%s\",%ld) failed",
++                                      "rsync_xal_list: llistxattr(\"%s\",%ld) failed",
 +                                      fname, (long)namebuf_len);
 +                              return -1;
 +                      }
 +              } else {
 +                      rsyserr(FERROR, errno,
 +                                      fname, (long)namebuf_len);
 +                              return -1;
 +                      }
 +              } else {
 +                      rsyserr(FERROR, errno,
-+                              "rsync_xal_get: llistxattr(\"%s\",%ld) failed",
++                              "rsync_xal_list: llistxattr(\"%s\",%ld) failed",
 +                              fname, (long)namebuf_len);
 +                      return -1;
 +              }
 +      }
 +
 +                              fname, (long)namebuf_len);
 +                      return -1;
 +              }
 +      }
 +
++      return list_len;
++}
++
++static int rsync_xal_get(const char *fname, item_list *xalp)
++{
++      ssize_t list_len, name_len, datum_len;
++      char *name, *ptr;
++
++      /* This puts the name list into the "namebuf" buffer. */
++      if ((list_len = rsync_xal_list(fname)) < 0)
++              return -1;
++
 +      for (name = namebuf; list_len > 0; name += name_len) {
 +              rsync_xa *rxas;
 +
 +      for (name = namebuf; list_len > 0; name += name_len) {
 +              rsync_xa *rxas;
 +
@@ -941,8 +955,14 @@ TODO:
 +static int rsync_xal_set(const char *fname, item_list *xalp)
 +{
 +      rsync_xa *rxas = xalp->items;
 +static int rsync_xal_set(const char *fname, item_list *xalp)
 +{
 +      rsync_xa *rxas = xalp->items;
++      ssize_t list_len;
 +      size_t i;
 +      size_t i;
-+      int ret = 0;
++      char *name;
++      int name_len, ret = 0;
++
++      /* This puts the current name list into the "namebuf" buffer. */
++      if ((list_len = rsync_xal_list(fname)) < 0)
++              return -1;
 +
 +      for (i = 0; i < xalp->count; i++) {
 +              int status = sys_lsetxattr(fname, rxas[i].name, rxas[i].datum, rxas[i].datum_len);
 +
 +      for (i = 0; i < xalp->count; i++) {
 +              int status = sys_lsetxattr(fname, rxas[i].name, rxas[i].datum, rxas[i].datum_len);
@@ -953,6 +973,35 @@ TODO:
 +                      ret = -1;
 +              }
 +      }
 +                      ret = -1;
 +              }
 +      }
++
++      /* Remove any extraneous names. */
++      for (name = namebuf; list_len > 0; name += name_len) {
++              name_len = strlen(name) + 1;
++              list_len -= name_len;
++
++#ifdef HAVE_LINUX_XATTRS
++              /* We always ignore the system namespace, and non-root
++               * ignores everything but the user namespace. */
++              if (am_root ? HAS_PREFIX(name, SYSTEM_PREFIX)
++                          : !HAS_PREFIX(name, USER_PREFIX))
++                      continue;
++#endif
++
++              for (i = 0; i < xalp->count; i++) {
++                      if (strcmp(name, rxas[i].name) == 0)
++                              break;
++              }
++              if (i == xalp->count) {
++                      int status = sys_lremovexattr(fname, name);
++                      if (status < 0) {
++                              rsyserr(FERROR, errno,
++                                      "rsync_xal_clear: lremovexattr(\"%s\",\"%s\") failed",
++                                      fname, name);
++                              ret = -1;
++                      }
++              }
++      }
++
 +      return ret;
 +}
 +
 +      return ret;
 +}
 +