The code can now omit requesting that the sender supply an abbreviated
authorWayne Davison <wayned@samba.org>
Sat, 31 Mar 2007 06:02:32 +0000 (06:02 +0000)
committerWayne Davison <wayned@samba.org>
Sat, 31 Mar 2007 06:02:32 +0000 (06:02 +0000)
value that is already present on the receiving side.

xattrs.diff

index 8294c5b..f4c4401 100644 (file)
@@ -9,12 +9,6 @@ To use this patch, run these commands for a successful build:
 
 CAUTION:  this patch has been recently reworked, and needs more testing!
 
-TODO:
-
- - When an xattr value is long enough to be checksummed and is not changed,
-   we need to have the receiver get the unchanged value from the receiving
-   side instead of requesting that it be sent from the sender.
-
 --- old/Makefile.in
 +++ new/Makefile.in
 @@ -28,13 +28,13 @@ VERSION=@VERSION@
@@ -53,10 +47,11 @@ TODO:
                                if (!(file = make_file(rel, NULL, NULL, 0, NO_FILTERS)))
                                        continue;
  #ifdef SUPPORT_ACLS
-@@ -143,6 +147,13 @@ static int make_bak_dir(char *fullpath)
+@@ -143,7 +147,14 @@ static int make_bak_dir(char *fullpath)
                                        free_acl(&sx);
                                }
  #endif
+-                              set_file_attrs(fullpath, file, NULL, 0);
 +#ifdef SUPPORT_XATTRS
 +                              if (preserve_xattrs) {
 +                                      get_xattr(rel, &sx);
@@ -64,9 +59,10 @@ TODO:
 +                                      free_xattr(&sx);
 +                              }
 +#endif
-                               set_file_attrs(fullpath, file, NULL, 0);
++                              set_file_attrs(fullpath, file, NULL, NULL, 0);
                                free(file);
                        }
+               }
 @@ -194,6 +205,9 @@ static int keep_backup(const char *fname
  #ifdef SUPPORT_ACLS
        sx.acc_acl = sx.def_acl = NULL;
@@ -91,6 +87,26 @@ TODO:
  
        /* Check to see if this is a device file, or link */
        if ((am_root && preserve_devices && IS_DEVICE(file->mode))
+@@ -288,7 +309,7 @@ static int keep_backup(const char *fname
+                       robust_unlink(fname); /* Just in case... */
+               }
+       }
+-      set_file_attrs(buf, file, NULL, 0);
++      set_file_attrs(buf, file, NULL, fname, 0);
+       unmake_file(file);
+       if (verbose > 1) {
+--- old/cleanup.c
++++ new/cleanup.c
+@@ -142,7 +142,7 @@ NORETURN void _exit_cleanup(int code, co
+                               flush_write_file(cleanup_fd_w);
+                               close(cleanup_fd_w);
+                       }
+-                      finish_transfer(cleanup_new_fname, fname, NULL,
++                      finish_transfer(cleanup_new_fname, fname, NULL, NULL,
+                                       cleanup_file, 0, !partial_dir);
+               }
 --- old/compat.c
 +++ new/compat.c
 @@ -43,6 +43,7 @@ extern int protocol_version;
@@ -287,6 +303,15 @@ TODO:
                } else if (ndx >= 0) {
                        enum logcode code = logfile_format_has_i ? FINFO : FCLIENT;
                        log_item(code, file, &stats, iflags, xname);
+@@ -881,7 +902,7 @@ static int try_dests_reg(struct file_str
+               }
+               if (itemizing)
+                       itemize(fname, file, ndx, 0, sxp, ITEM_LOCAL_CHANGE, 0, NULL);
+-              set_file_attrs(fname, file, NULL, 0);
++              set_file_attrs(fname, file, NULL, NULL, 0);
+               if (maybe_ATTRS_REPORT
+                && ((!itemizing && verbose && match_level == 2)
+                 || (verbose > 1 && match_level == 3))) {
 @@ -1112,6 +1133,9 @@ static void recv_generator(char *fname, 
  #ifdef SUPPORT_ACLS
        sx.acc_acl = sx.def_acl = NULL;
@@ -297,6 +322,60 @@ TODO:
        if (dry_run > 1) {
                if (fuzzy_dirlist) {
                        flist_free(fuzzy_dirlist);
+@@ -1224,7 +1248,7 @@ static void recv_generator(char *fname, 
+                               goto cleanup;
+                       }
+               }
+-              if (set_file_attrs(fname, file, real_ret ? NULL : &real_sx, 0)
++              if (set_file_attrs(fname, file, real_ret ? NULL : &real_sx, NULL, 0)
+                   && verbose && code != FNONE && f_out != -1)
+                       rprintf(code, "%s/\n", fname);
+               if (real_ret != 0 && one_file_system)
+@@ -1280,7 +1304,7 @@ static void recv_generator(char *fname, 
+                               /* The link is pointing to the right place. */
+                               if (itemizing)
+                                       itemize(fname, file, ndx, 0, &sx, 0, 0, NULL);
+-                              set_file_attrs(fname, file, &sx, maybe_ATTRS_REPORT);
++                              set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT);
+ #ifdef SUPPORT_HARD_LINKS
+                               if (preserve_hard_links && F_IS_HLINKED(file))
+                                       finish_hard_link(file, fname, &sx.st, itemizing, code, -1);
+@@ -1317,7 +1341,7 @@ static void recv_generator(char *fname, 
+                       rsyserr(FERROR, errno, "symlink %s -> \"%s\" failed",
+                               full_fname(fname), sl);
+               } else {
+-                      set_file_attrs(fname, file, NULL, 0);
++                      set_file_attrs(fname, file, NULL, NULL, 0);
+                       if (itemizing) {
+                               itemize(fname, file, ndx, statret, &sx,
+                                       ITEM_LOCAL_CHANGE, 0, NULL);
+@@ -1359,7 +1383,7 @@ static void recv_generator(char *fname, 
+                               /* The device or special file is identical. */
+                               if (itemizing)
+                                       itemize(fname, file, ndx, 0, &sx, 0, 0, NULL);
+-                              set_file_attrs(fname, file, &sx, maybe_ATTRS_REPORT);
++                              set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT);
+ #ifdef SUPPORT_HARD_LINKS
+                               if (preserve_hard_links && F_IS_HLINKED(file))
+                                       finish_hard_link(file, fname, &sx.st, itemizing, code, -1);
+@@ -1399,7 +1423,7 @@ static void recv_generator(char *fname, 
+                       rsyserr(FERROR, errno, "mknod %s failed",
+                               full_fname(fname));
+               } else {
+-                      set_file_attrs(fname, file, NULL, 0);
++                      set_file_attrs(fname, file, NULL, NULL, 0);
+                       if (itemizing) {
+                               itemize(fname, file, ndx, statret, &sx,
+                                       ITEM_LOCAL_CHANGE, 0, NULL);
+@@ -1531,7 +1555,7 @@ static void recv_generator(char *fname, 
+               }
+               if (itemizing)
+                       itemize(fnamecmp, file, ndx, statret, &sx, 0, 0, NULL);
+-              set_file_attrs(fname, file, &sx, maybe_ATTRS_REPORT);
++              set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT);
+ #ifdef SUPPORT_HARD_LINKS
+               if (preserve_hard_links && F_IS_HLINKED(file))
+                       finish_hard_link(file, fname, &sx.st, itemizing, code, -1);
 @@ -1636,6 +1660,10 @@ static void recv_generator(char *fname, 
                if (preserve_acls)
                        free_acl(&real_sx);
@@ -308,6 +387,15 @@ TODO:
        }
  
        if (!do_xfers) {
+@@ -1657,7 +1685,7 @@ static void recv_generator(char *fname, 
+       if (f_copy >= 0) {
+               close(f_copy);
+-              set_file_attrs(backupptr, back_file, NULL, 0);
++              set_file_attrs(backupptr, back_file, NULL, NULL, 0);
+               if (verbose > 1) {
+                       rprintf(FINFO, "backed up %s to %s\n",
+                               fname, backupptr);
 @@ -1672,6 +1700,10 @@ static void recv_generator(char *fname, 
        if (preserve_acls)
                free_acl(&sx);
@@ -667,11 +755,30 @@ TODO:
                        maybe_log_item(file, iflags, itemizing, xname);
 +#ifdef SUPPORT_XATTRS
 +                      if (iflags & ITEM_REPORT_XATTR && !dry_run)
-+                              set_file_attrs(fname, file, NULL, 0);
++                              set_file_attrs(fname, file, NULL, fname, 0);
 +#endif
                        continue;
                }
                if (phase == 2) {
+@@ -655,15 +665,15 @@ int recv_files(int f_in, char *local_nam
+                               temp_copy_name = NULL;
+                       else
+                               temp_copy_name = partialptr;
+-                      finish_transfer(fname, fnametmp, temp_copy_name,
+-                                      file, recv_ok, 1);
++                      finish_transfer(fname, fnametmp, fnamecmp,
++                                      temp_copy_name, file, recv_ok, 1);
+                       if (fnamecmp == partialptr) {
+                               do_unlink(partialptr);
+                               handle_partial_dir(partialptr, PDIR_DELETE);
+                       }
+               } else if (keep_partial && partialptr
+                   && handle_partial_dir(partialptr, PDIR_CREATE)) {
+-                      finish_transfer(partialptr, fnametmp, NULL,
++                      finish_transfer(partialptr, fnametmp, fnamecmp, NULL,
+                                       file, recv_ok, !partial_dir);
+                       if (delay_updates && recv_ok) {
+                               bitbag_set_bit(delayed_bits, ndx);
 --- old/rsync.c
 +++ new/rsync.c
 @@ -32,6 +32,7 @@
@@ -707,6 +814,17 @@ TODO:
        }
  
        *iflag_ptr = iflags;
+@@ -228,8 +222,8 @@ mode_t dest_mode(mode_t flist_mode, mode
+       return new_mode;
+ }
+-int set_file_attrs(char *fname, struct file_struct *file, statx *sxp,
+-                 int flags)
++int set_file_attrs(const char *fname, struct file_struct *file, statx *sxp,
++                 const char *fnamecmp, int flags)
+ {
+       int updated = 0;
+       statx sx2;
 @@ -247,6 +241,9 @@ int set_file_attrs(char *fname, struct f
  #ifdef SUPPORT_ACLS
                sx2.acc_acl = sx2.def_acl = NULL;
@@ -722,8 +840,8 @@ TODO:
                new_mode = tweak_mode(new_mode, daemon_chmod_modes);
  
 +#ifdef SUPPORT_XATTRS
-+      if (preserve_xattrs && !am_generator)
-+              set_xattr(fname, file, sxp);
++      if (preserve_xattrs && fnamecmp)
++              set_xattr(fname, file, fnamecmp);
 +#endif
  #ifdef SUPPORT_ACLS
        /* It's OK to call set_acl() now, even for a dir, as the generator
@@ -738,15 +856,43 @@ TODO:
 -              free_acl(&sx2);
 +              if (preserve_acls)
 +                      free_acl(&sx2);
- #endif
++#endif
 +#ifdef SUPPORT_XATTRS
 +              if (preserve_xattrs)
 +                      free_xattr(&sx2);
-+#endif
+ #endif
 +      }
        return updated;
  }
  
+@@ -378,7 +385,8 @@ RETSIGTYPE sig_int(UNUSED(int val))
+  * attributes (e.g. permissions, ownership, etc.).  If partialptr is not
+  * NULL and the robust_rename() call is forced to copy the temp file, we
+  * stage the file into the partial-dir and then rename it into place. */
+-void finish_transfer(char *fname, char *fnametmp, char *partialptr,
++void finish_transfer(const char *fname, const char *fnametmp,
++                   const char *fnamecmp, const char *partialptr,
+                    struct file_struct *file, int ok_to_set_time,
+                    int overwriting_basis)
+ {
+@@ -395,7 +403,7 @@ void finish_transfer(char *fname, char *
+               return;
+       /* Change permissions before putting the file into place. */
+-      set_file_attrs(fnametmp, file, NULL,
++      set_file_attrs(fnametmp, file, NULL, fnamecmp,
+                      ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
+       /* move tmp file over real file */
+@@ -419,7 +427,7 @@ void finish_transfer(char *fname, char *
+       fnametmp = partialptr ? partialptr : fname;
+   do_set_file_attrs:
+-      set_file_attrs(fnametmp, file, NULL,
++      set_file_attrs(fnametmp, file, NULL, fnamecmp,
+                      ok_to_set_time ? 0 : ATTRS_SKIP_MTIME);
+       if (partialptr) {
 --- old/rsync.h
 +++ new/rsync.h
 @@ -569,6 +569,7 @@ extern int file_extra_cnt;
@@ -963,7 +1109,7 @@ TODO:
 +exit 0
 --- old/xattrs.c
 +++ new/xattrs.c
-@@ -0,0 +1,688 @@
+@@ -0,0 +1,713 @@
 +/*
 + * Extended Attribute support for rsync.
 + * Written by Jay Fenlason, vaguely based on the ACLs patch.
@@ -1358,7 +1504,7 @@ TODO:
 +                          && memcmp(snd_rxa->datum + 1, rec_rxa->datum + 1,
 +                                    MAX_DIGEST_LEN) == 0;
 +                      /* Flag unrequested items that we need. */
-+                      if (/*!same &&*/ find_all && snd_rxa->datum[0] == 0)
++                      if (!same && find_all && snd_rxa->datum[0] == 0)
 +                              snd_rxa->datum[0] = 1;
 +              } else {
 +                      same = cmp == 0 && snd_rxa->datum_len == rec_rxa->datum_len
@@ -1575,7 +1721,7 @@ TODO:
 +      F_XATTR(file) = ndx;
 +}
 +
-+static int rsync_xal_set(const char *fname, item_list *xalp)
++static int rsync_xal_set(const char *fname, item_list *xalp, const char *fnamecmp)
 +{
 +      rsync_xa *rxas = xalp->items;
 +      ssize_t list_len;
@@ -1589,9 +1735,34 @@ TODO:
 +
 +      for (i = 0; i < xalp->count; i++) {
 +              if ((size_t)(rxas[i].name - rxas[i].datum) < rxas[i].datum_len) {
-+                      rprintf(FERROR, "Abbreviated xattr value, %s, not received for %s\n",
-+                              rxas[i].name, full_fname(fname));
-+                      exit_cleanup(RERR_STREAMIO);
++                      size_t len = rxas[i].name_len;
++                      char *ptr;
++
++                      /* See if fnamecmp version is identical. */
++                      if ((ptr = get_xattr_data(fnamecmp, rxas[i].name, &len)) != NULL
++                       && len == rxas[i].datum_len) {
++                              char sum[MAX_DIGEST_LEN];
++                              sum_init(checksum_seed);
++                              sum_update(ptr, len);
++                              sum_end(sum);
++                              if (memcmp(sum, rxas[i].datum + 1, MAX_DIGEST_LEN) == 0) {
++                                      char *name = ptr + len;
++                                      memcpy(name, rxas[i].name, rxas[i].name_len);
++                                      rxas[i].name = name;
++                                      free(rxas[i].datum);
++                                      rxas[i].datum = ptr;
++                              } else
++                                      len = 0;
++                      } else
++                              len = 0;
++                      if (!len) {
++                              rprintf(FERROR, "Missing abbreviated xattr value, %s, for %s\n",
++                                      rxas[i].name, full_fname(fname));
++                              ret = -1;
++                              continue;
++                      }
++                      if (fname == fnamecmp) /* value is already set */
++                              continue;
 +              }
 +              status = sys_lsetxattr(fname, rxas[i].name, rxas[i].datum, rxas[i].datum_len);
 +              if (status < 0) {
@@ -1634,7 +1805,7 @@ TODO:
 +}
 +
 +/* Set extended attributes on indicated filename. */
-+int set_xattr(const char *fname, const struct file_struct *file, UNUSED(statx *sxp))
++int set_xattr(const char *fname, const struct file_struct *file, const char *fnamecmp)
 +{
 +      int ndx;
 +      item_list *lst = rsync_xal_l.items;
@@ -1648,7 +1819,7 @@ TODO:
 +      }
 +
 +      ndx = F_XATTR(file);
-+      return rsync_xal_set(fname, lst + ndx);
++      return rsync_xal_set(fname, lst + ndx, fnamecmp);
 +}
 +
 +#endif /* SUPPORT_XATTRS */