- Fixed a problem with the sscanf() count (now 5, not 4).
authorWayne Davison <wayned@samba.org>
Fri, 27 Oct 2006 15:21:22 +0000 (15:21 +0000)
committerWayne Davison <wayned@samba.org>
Fri, 27 Oct 2006 15:21:22 +0000 (15:21 +0000)
- Make sure we only create an xattr stat value when we need it
  and we delete it when it's not needed.

fake-super.diff

index 9511970..cb5598d 100644 (file)
@@ -165,20 +165,18 @@ After applying this patch, run these commands for a successful build:
    {"no-o",             0,  POPT_ARG_VAL,    &preserve_uid, 0, 0, 0 },
 --- old/rsync.c
 +++ new/rsync.c
-@@ -197,6 +197,12 @@ int set_file_attrs(char *fname, struct f
+@@ -197,7 +197,9 @@ int set_file_attrs(char *fname, struct f
                                        (long)sxp->st.st_gid, (long)file->gid);
                        }
                }
-+              if (am_root < 0) {
-+                      if (change_uid)
-+                              sxp->st.st_uid = file->uid;
-+                      if (change_gid)
-+                              sxp->st.st_gid = file->gid;
-+              } else
-               if (do_lchown(fname,
+-              if (do_lchown(fname,
++              if (am_root < 0)
++                      ;
++              else if (do_lchown(fname,
                    change_uid ? file->uid : sxp->st.st_uid,
                    change_gid ? file->gid : sxp->st.st_gid) != 0) {
-@@ -206,7 +212,7 @@ int set_file_attrs(char *fname, struct f
+                       /* shouldn't have attempted to change uid or gid
+@@ -206,7 +208,7 @@ int set_file_attrs(char *fname, struct f
                            change_uid ? "chown" : "chgrp",
                            full_fname(fname));
                        goto cleanup;
@@ -187,7 +185,7 @@ After applying this patch, run these commands for a successful build:
                /* a lchown had been done - we have to re-stat if the
                 * destination had the setuid or setgid bits set due
                 * to the side effect of the chown call */
-@@ -237,7 +243,16 @@ int set_file_attrs(char *fname, struct f
+@@ -237,7 +239,15 @@ int set_file_attrs(char *fname, struct f
  
  #ifdef HAVE_CHMOD
        if ((sxp->st.st_mode & CHMOD_BITS) != (new_mode & CHMOD_BITS)) {
@@ -199,29 +197,29 @@ After applying this patch, run these commands for a successful build:
 +                              ret = do_chmod(fname, mode);
 +                      else
 +                              ret = 0;
-+                      sxp->st.st_mode = new_mode;
 +              } else
 +                      ret = do_chmod(fname, new_mode);
                if (ret < 0) {
                        rsyserr(FERROR, errno,
                                "failed to set permissions on %s",
-@@ -249,6 +264,22 @@ int set_file_attrs(char *fname, struct f
+@@ -249,6 +259,23 @@ int set_file_attrs(char *fname, struct f
        }
  #endif
  
 +      if (am_root < 0) {
-+              int write_it = updated;
-+              if (IS_DEVICE(file->mode) || IS_SPECIAL(file->mode)) {
-+                      if (file->u.rdev != sxp->st.st_rdev) {
-+                              sxp->st.st_rdev = file->u.rdev;
-+                              write_it = 1;
-+                      }
-+              } else
-+                      sxp->st.st_rdev = 0;
-+              if (write_it && set_stat_xattr(fname, &sxp->st) < 0) {
++              switch (set_stat_xattr(fname, file)) {
++              case 0:
++                      break;
++              case -1:
 +                      rsyserr(FERROR, errno,
 +                              "write of stat xattr failed for %s",
 +                              full_fname(fname));
++                      break;
++              case -2:
++                      rsyserr(FERROR, errno,
++                              "delete of stat xattr failed for %s",
++                              full_fname(fname));
++                      break;
 +              }
 +      }
 +
@@ -272,7 +270,7 @@ After applying this patch, run these commands for a successful build:
  #if !defined MKNOD_CREATES_FIFOS && defined HAVE_MKFIFO
        if (S_ISFIFO(mode))
                return mkfifo(pathname, mode);
-@@ -215,23 +226,71 @@ int do_mkstemp(char *template, mode_t pe
+@@ -215,23 +226,98 @@ int do_mkstemp(char *template, mode_t pe
  #endif
  }
  
@@ -284,13 +282,13 @@ After applying this patch, run these commands for a successful build:
 +      len = sys_lgetxattr(fname, FAKE_XATTR, buf, sizeof buf - 1);
 +      if (len < 0 || len >= (int)sizeof buf) {
 +              if (errno == ENOTSUP || errno == ENOATTR)
-+                      return 0;
++                      return -1;
 +              return -1;
 +      }
 +      buf[len] = '\0';
 +
 +      if (sscanf(buf, "%o %d,%d %d:%d",
-+                 &mode, &rdev_major, &rdev_minor, &uid, &gid) != 4) {
++                 &mode, &rdev_major, &rdev_minor, &uid, &gid) != 5) {
 +              errno = EINVAL;
 +              return -1;
 +      }
@@ -303,17 +301,44 @@ After applying this patch, run these commands for a successful build:
 +      return 0;
 +}
 +
-+int set_stat_xattr(const char *fname, STRUCT_STAT *st)
++int set_stat_xattr(const char *fname, struct file_struct *file)
 +{
-+      char buf[256];
-+      int len;
++      STRUCT_STAT fst, xst;
++      int have_xattr;
++      dev_t rdev;
 +      if (dry_run) return 0;
 +      RETURN_ERROR_IF_RO_OR_LO;
-+      len = snprintf(buf, sizeof buf, "%o %u,%u %u:%u",
-+                     (int)st->st_mode,
-+                     (int)major(st->st_rdev), (int)minor(st->st_rdev),
-+                     (int)st->st_uid, (int)st->st_gid);
-+      return sys_lsetxattr(fname, FAKE_XATTR, buf, len, 0);
++
++      am_root = 2; /* get real stat() w/o xattr overlay */
++      do_stat(fname, &fst);
++      am_root = -1;
++      have_xattr = get_stat_xattr(fname, &xst) == 0;
++
++      if (IS_DEVICE(file->mode) || IS_SPECIAL(file->mode))
++              rdev = file->u.rdev;
++      else
++              rdev = 0;
++      if (!IS_DEVICE(fst.st_mode) && !IS_SPECIAL(fst.st_mode))
++              fst.st_rdev = 0; /* just in case */
++
++      if (fst.st_mode == file->mode && fst.st_rdev == rdev
++       && fst.st_uid == file->uid && fst.st_gid == file->gid) {
++              if (have_xattr && sys_lremovexattr(fname, FAKE_XATTR) < 0)
++                      return -2;
++              return 0;
++      }
++
++      if (!have_xattr
++       || xst.st_mode != file->mode || xst.st_rdev != rdev
++       || xst.st_uid != file->uid || xst.st_gid != file->gid) {
++              char buf[256];
++              int len = snprintf(buf, sizeof buf, "%o %u,%u %u:%u",
++                      (int)file->mode,
++                      (int)major(rdev), (int)minor(rdev),
++                      (int)file->uid, (int)file->gid);
++              return sys_lsetxattr(fname, FAKE_XATTR, buf, len, 0);
++      }
++      return 0;
 +}
 +
  int do_stat(const char *fname, STRUCT_STAT *st)