Fixed the sending of new files with long xattrs.
authorWayne Davison <wayned@samba.org>
Sat, 7 Apr 2007 08:15:24 +0000 (08:15 +0000)
committerWayne Davison <wayned@samba.org>
Sat, 7 Apr 2007 08:15:24 +0000 (08:15 +0000)
xattrs.diff

index feda8b5..d17ea9a 100644 (file)
@@ -277,7 +277,7 @@ CAUTION:  this patch has been recently reworked, and needs more testing!
             statx *sxp, int32 iflags, uchar fnamecmp_type,
             const char *xname)
  {
-@@ -562,16 +571,24 @@ void itemize(const char *fname, struct f
+@@ -562,16 +571,29 @@ void itemize(const char *fname, struct f
  #ifdef SUPPORT_ACLS
                if (preserve_acls && !S_ISLNK(file->mode)) {
                        if (!ACL_READY(*sxp))
@@ -287,6 +287,7 @@ CAUTION:  this patch has been recently reworked, and needs more testing!
                                iflags |= ITEM_REPORT_ACL;
                }
  #endif
+-      } else
 +#ifdef SUPPORT_XATTRS
 +              if (preserve_xattrs) {
 +                      if (!XATTR_READY(*sxp))
@@ -295,8 +296,13 @@ CAUTION:  this patch has been recently reworked, and needs more testing!
 +                              iflags |= ITEM_REPORT_XATTR;
 +              }
 +#endif
-       } else
++      } else {
++#ifdef SUPPORT_XATTRS
++              if (preserve_xattrs && xattr_diff(file, NULL, 1))
++                      iflags |= ITEM_REPORT_XATTR;
++#endif
                iflags |= ITEM_IS_NEW;
++      }
  
        iflags &= 0xffff;
 -      if ((iflags & SIGNIFICANT_ITEM_FLAGS || verbose > 1
@@ -304,7 +310,7 @@ CAUTION:  this patch has been recently reworked, and needs more testing!
          || stdout_format_has_i > 1 || (xname && *xname)) && !read_batch) {
                if (protocol_version >= 29) {
                        if (ndx >= 0)
-@@ -581,6 +598,10 @@ void itemize(const char *fname, struct f
+@@ -581,6 +603,10 @@ void itemize(const char *fname, struct f
                                write_byte(sock_f_out, fnamecmp_type);
                        if (iflags & ITEM_XNAME_FOLLOWS)
                                write_vstring(sock_f_out, xname, strlen(xname));
@@ -315,7 +321,7 @@ CAUTION:  this patch has been recently reworked, and needs more testing!
                } else if (ndx >= 0) {
                        enum logcode code = logfile_format_has_i ? FINFO : FCLIENT;
                        log_item(code, file, &stats, iflags, xname);
-@@ -855,14 +876,14 @@ static int try_dests_reg(struct file_str
+@@ -855,14 +881,14 @@ static int try_dests_reg(struct file_str
                        if (preserve_hard_links && F_IS_HLINKED(file))
                                finish_hard_link(file, fname, &sxp->st, itemizing, code, j);
                        if (itemizing && (verbose > 1 || stdout_format_has_i > 1)) {
@@ -332,7 +338,7 @@ CAUTION:  this patch has been recently reworked, and needs more testing!
                if (verbose > 1 && maybe_ATTRS_REPORT)
                        rprintf(FCLIENT, "%s is uptodate\n", fname);
                return -2;
-@@ -879,9 +900,13 @@ static int try_dests_reg(struct file_str
+@@ -879,9 +905,13 @@ static int try_dests_reg(struct file_str
                        }
                        return -1;
                }
@@ -348,7 +354,7 @@ CAUTION:  this patch has been recently reworked, and needs more testing!
                if (maybe_ATTRS_REPORT
                 && ((!itemizing && verbose && match_level == 2)
                  || (verbose > 1 && match_level == 3))) {
-@@ -1029,7 +1054,7 @@ static int try_dests_non(struct file_str
+@@ -1029,7 +1059,7 @@ static int try_dests_non(struct file_str
                            : ITEM_LOCAL_CHANGE
                             + (match_level == 3 ? ITEM_XNAME_FOLLOWS : 0);
                        char *lp = match_level == 3 ? "" : NULL;
@@ -357,7 +363,7 @@ CAUTION:  this patch has been recently reworked, and needs more testing!
                }
                if (verbose > 1 && maybe_ATTRS_REPORT) {
                        rprintf(FCLIENT, "%s%s is uptodate\n",
-@@ -1112,6 +1137,9 @@ static void recv_generator(char *fname, 
+@@ -1112,6 +1142,9 @@ static void recv_generator(char *fname, 
  #ifdef SUPPORT_ACLS
        sx.acc_acl = sx.def_acl = NULL;
  #endif
@@ -367,7 +373,7 @@ CAUTION:  this patch has been recently reworked, and needs more testing!
        if (dry_run > 1) {
                if (fuzzy_dirlist) {
                        flist_free(fuzzy_dirlist);
-@@ -1224,7 +1252,7 @@ static void recv_generator(char *fname, 
+@@ -1224,7 +1257,7 @@ static void recv_generator(char *fname, 
                                goto cleanup;
                        }
                }
@@ -376,7 +382,7 @@ CAUTION:  this patch has been recently reworked, and needs more testing!
                    && verbose && code != FNONE && f_out != -1)
                        rprintf(code, "%s/\n", fname);
                if (real_ret != 0 && one_file_system)
-@@ -1278,9 +1306,9 @@ static void recv_generator(char *fname, 
+@@ -1278,9 +1311,9 @@ static void recv_generator(char *fname, 
                        else if ((len = readlink(fname, lnk, MAXPATHLEN-1)) > 0
                              && strncmp(lnk, sl, len) == 0 && sl[len] == '\0') {
                                /* The link is pointing to the right place. */
@@ -387,7 +393,7 @@ CAUTION:  this patch has been recently reworked, and needs more testing!
  #ifdef SUPPORT_HARD_LINKS
                                if (preserve_hard_links && F_IS_HLINKED(file))
                                        finish_hard_link(file, fname, &sx.st, itemizing, code, -1);
-@@ -1317,7 +1345,7 @@ static void recv_generator(char *fname, 
+@@ -1317,7 +1350,7 @@ static void recv_generator(char *fname, 
                        rsyserr(FERROR, errno, "symlink %s -> \"%s\" failed",
                                full_fname(fname), sl);
                } else {
@@ -396,7 +402,7 @@ CAUTION:  this patch has been recently reworked, and needs more testing!
                        if (itemizing) {
                                itemize(fname, file, ndx, statret, &sx,
                                        ITEM_LOCAL_CHANGE, 0, NULL);
-@@ -1357,9 +1385,9 @@ static void recv_generator(char *fname, 
+@@ -1357,9 +1390,9 @@ static void recv_generator(char *fname, 
                         && BITS_EQUAL(sx.st.st_mode, file->mode, _S_IFMT)
                         && sx.st.st_rdev == rdev) {
                                /* The device or special file is identical. */
@@ -407,7 +413,7 @@ CAUTION:  this patch has been recently reworked, and needs more testing!
  #ifdef SUPPORT_HARD_LINKS
                                if (preserve_hard_links && F_IS_HLINKED(file))
                                        finish_hard_link(file, fname, &sx.st, itemizing, code, -1);
-@@ -1399,7 +1427,7 @@ static void recv_generator(char *fname, 
+@@ -1399,7 +1432,7 @@ static void recv_generator(char *fname, 
                        rsyserr(FERROR, errno, "mknod %s failed",
                                full_fname(fname));
                } else {
@@ -416,7 +422,7 @@ CAUTION:  this patch has been recently reworked, and needs more testing!
                        if (itemizing) {
                                itemize(fname, file, ndx, statret, &sx,
                                        ITEM_LOCAL_CHANGE, 0, NULL);
-@@ -1529,9 +1557,9 @@ static void recv_generator(char *fname, 
+@@ -1529,9 +1562,9 @@ static void recv_generator(char *fname, 
                        do_unlink(partialptr);
                        handle_partial_dir(partialptr, PDIR_DELETE);
                }
@@ -427,7 +433,7 @@ CAUTION:  this patch has been recently reworked, and needs more testing!
  #ifdef SUPPORT_HARD_LINKS
                if (preserve_hard_links && F_IS_HLINKED(file))
                        finish_hard_link(file, fname, &sx.st, itemizing, code, -1);
-@@ -1636,6 +1664,10 @@ static void recv_generator(char *fname, 
+@@ -1636,6 +1669,10 @@ static void recv_generator(char *fname, 
                if (preserve_acls)
                        free_acl(&real_sx);
  #endif
@@ -438,7 +444,7 @@ CAUTION:  this patch has been recently reworked, and needs more testing!
        }
  
        if (!do_xfers) {
-@@ -1657,7 +1689,7 @@ static void recv_generator(char *fname, 
+@@ -1657,7 +1694,7 @@ static void recv_generator(char *fname, 
  
        if (f_copy >= 0) {
                close(f_copy);
@@ -447,7 +453,7 @@ CAUTION:  this patch has been recently reworked, and needs more testing!
                if (verbose > 1) {
                        rprintf(FINFO, "backed up %s to %s\n",
                                fname, backupptr);
-@@ -1672,6 +1704,10 @@ static void recv_generator(char *fname, 
+@@ -1672,6 +1709,10 @@ static void recv_generator(char *fname, 
        if (preserve_acls)
                free_acl(&sx);
  #endif
@@ -1120,7 +1126,7 @@ CAUTION:  this patch has been recently reworked, and needs more testing!
                if (verbose > 2)
 --- old/testsuite/xattrs.test
 +++ new/testsuite/xattrs.test
-@@ -0,0 +1,76 @@
+@@ -0,0 +1,90 @@
 +#! /bin/sh
 +
 +# This program is distributable under the terms of the GNU GPL (see
@@ -1136,6 +1142,19 @@ CAUTION:  this patch has been recently reworked, and needs more testing!
 +*protocol=29*) test_skipped "xattr support requires protocol 30" ;;
 +esac
 +
++xset() {
++    xnam="$1"
++    xval="$2"
++    shift 2
++    setfattr -n "$xnam" -v "$xval" "${@}"
++    #xattr -s "$xnam" "$xval" "${@}"
++}
++
++xls() {
++    getfattr -d "${@}"
++    #xattr -l "${@}"
++}
++
 +makepath "$fromdir/foo"
 +echo something >"$fromdir/file1"
 +echo else >"$fromdir/file2"
@@ -1149,57 +1168,58 @@ CAUTION:  this patch has been recently reworked, and needs more testing!
 +
 +cd "$fromdir"
 +
-+setfattr -n user.short -v 'this is short' file1 2>/dev/null || test_skipped "Unable to set an xattr"
-+setfattr -n user.long -v 'this is a long attribute that will be truncated in the initial data send' file1
-+setfattr -n user.good -v 'this is good' file1
-+setfattr -n user.nice -v 'this is nice' file1
++xset user.short 'this is short' file1 2>/dev/null || test_skipped "Unable to set an xattr"
++xset user.long 'this is a long attribute that will be truncated in the initial data send' file1
++xset user.good 'this is good' file1
++xset user.nice 'this is nice' file1
 +
-+setfattr -n user.foo -v foo file2
-+setfattr -n user.bar -v bar file2
++xset user.foo foo file2
++xset user.bar bar file2
++xset user.long 'a long attribute for our new file that tests to ensure that this works' file2
 +
-+setfattr -n user.foo -v 'new foo' foo/file3
-+setfattr -n user.bar -v 'new bar' foo/file3
-+setfattr -n user.long -v 'this is also a long attribute that will be truncated in the initial data send' foo/file3
-+setfattr -n user.equal -v 'this long attribute should remain the same and not need to be transferred' foo/file3
++xset user.foo 'new foo' foo/file3
++xset user.bar 'new bar' foo/file3
++xset user.long 'this is also a long attribute that will be truncated in the initial data send' foo/file3
++xset user.equal 'this long attribute should remain the same and not need to be transferred' foo/file3
 +
-+setfattr -n user.short -v 'old short' "$chkdir/file1"
-+setfattr -n user.extra -v 'remove me' "$chkdir/file1"
++xset user.short 'old short' "$chkdir/file1"
++xset user.extra 'remove me' "$chkdir/file1"
 +
-+setfattr -n user.foo -v 'old foo' "$chkdir/foo/file3"
-+setfattr -n user.equal -v 'this long attribute should remain the same and not need to be transferred' "$chkdir/foo/file3"
++xset user.foo 'old foo' "$chkdir/foo/file3"
++xset user.equal 'this long attribute should remain the same and not need to be transferred' "$chkdir/foo/file3"
 +
-+getfattr -d $files >"$scratchdir/xattrs.txt"
++xls $files >"$scratchdir/xattrs.txt"
 +
 +# OK, let's try a simple xattr copy.
 +checkit "$RSYNC -avX . \"$chkdir/\"" "$fromdir" "$chkdir"
 +
 +cd "$chkdir"
-+getfattr -d $files | diff $diffopt "$scratchdir/xattrs.txt" -
++xls $files | diff $diffopt "$scratchdir/xattrs.txt" -
 +
 +cd "$fromdir"
 +
 +checkit "$RSYNC -aiX --copy-dest=../chk . ../to" "$fromdir" "$todir"
 +
 +cd "$todir"
-+getfattr -d $files | diff $diffopt "$scratchdir/xattrs.txt" -
++xls $files | diff $diffopt "$scratchdir/xattrs.txt" -
 +
 +cd "$fromdir"
-+setfattr -n user.nice -v 'this is nice, but different' file1
++xset user.nice 'this is nice, but different' file1
 +
-+getfattr -d $files >"$scratchdir/xattrs.txt"
++xls $files >"$scratchdir/xattrs.txt"
 +
 +rm -rf "$todir"
 +
 +checkit "$RSYNC -aiX --link-dest=../chk . ../to" "$chkdir" "$todir"
 +
 +cd "$todir"
-+getfattr -d $files | diff $diffopt "$scratchdir/xattrs.txt" -
++xls $files | diff $diffopt "$scratchdir/xattrs.txt" -
 +
 +# The script would have aborted on error, so getting here means we've won.
 +exit 0
 --- old/xattrs.c
 +++ new/xattrs.c
-@@ -0,0 +1,775 @@
+@@ -0,0 +1,771 @@
 +/*
 + * Extended Attribute support for rsync.
 + * Written by Jay Fenlason, vaguely based on the ACLs patch.
@@ -1319,39 +1339,33 @@ CAUTION:  this patch has been recently reworked, and needs more testing!
 +              list_len = -1;
 +              errno = ERANGE;
 +      }
-+      if (list_len < 0) {
-+              if (errno == ENOTSUP)
-+                      return 0;
-+              if (errno == ERANGE) {
-+                      list_len = sys_llistxattr(fname, NULL, 0);
-+                      if (list_len < 0) {
-+                              rsyserr(FERROR, errno,
-+                                      "get_xattr_names: llistxattr(\"%s\",0) failed",
-+                                      fname);
-+                              return -1;
-+                      }
-+                      if (namebuf_len)
-+                              free(namebuf);
-+                      namebuf_len = list_len + 1024;
-+                      namebuf = new_array(char, namebuf_len);
-+                      if (!namebuf)
-+                              out_of_memory("get_xattr_names");
-+                      list_len = sys_llistxattr(fname, namebuf, namebuf_len);
-+                      if (list_len < 0) {
-+                              rsyserr(FERROR, errno,
-+                                      "get_xattr_names: llistxattr(\"%s\",%ld) failed",
-+                                      fname, (long)namebuf_len);
-+                              return -1;
-+                      }
-+              } else {
++      if (list_len >= 0)
++              return list_len;
++      if (errno == ENOTSUP)
++              return 0;
++      if (errno == ERANGE) {
++              list_len = sys_llistxattr(fname, NULL, 0);
++              if (list_len < 0) {
 +                      rsyserr(FERROR, errno,
-+                              "get_xattr_names: llistxattr(\"%s\",%ld) failed",
-+                              fname, (long)namebuf_len);
++                              "get_xattr_names: llistxattr(\"%s\",0) failed",
++                              fname);
 +                      return -1;
 +              }
++              if (namebuf_len)
++                      free(namebuf);
++              namebuf_len = list_len + 1024;
++              namebuf = new_array(char, namebuf_len);
++              if (!namebuf)
++                      out_of_memory("get_xattr_names");
++              list_len = sys_llistxattr(fname, namebuf, namebuf_len);
++              if (list_len >= 0)
++                      return list_len;
 +      }
 +
-+      return list_len;
++      rsyserr(FERROR, errno,
++              "get_xattr_names: llistxattr(\"%s\",%ld) failed",
++              fname, (long)namebuf_len);
++      return -1;
 +}
 +
 +/* On entry, the *len_ptr parameter contains the size of the extra space we
@@ -1404,7 +1418,9 @@ CAUTION:  this patch has been recently reworked, and needs more testing!
 +      ssize_t list_len, name_len;
 +      size_t datum_len, name_offset;
 +      char *name, *ptr;
++#ifdef HAVE_LINUX_XATTRS
 +      int user_only = am_sender ? 0 : !am_root;
++#endif
 +
 +      /* This puts the name list into the "namebuf" buffer. */
 +      if ((list_len = get_xattr_names(fname)) < 0)
@@ -1570,12 +1586,12 @@ CAUTION:  this patch has been recently reworked, and needs more testing!
 +      int snd_cnt, rec_cnt;
 +      int cmp, same, xattrs_equal = 1;
 +
-+      if (!XATTR_READY(*sxp)) {
-+              rec_rxa = NULL;
-+              rec_cnt = 0;
-+      } else {
++      if (sxp && XATTR_READY(*sxp)) {
 +              rec_rxa = sxp->xattr->items;
 +              rec_cnt = sxp->xattr->count;
++      } else {
++              rec_rxa = NULL;
++              rec_cnt = 0;
 +      }
 +
 +      if (F_XATTR(file) >= 0)