From 3ae9c1eeea23ba57d325e10c6926b2361a343ed4 Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Fri, 27 Oct 2006 15:21:22 +0000 Subject: [PATCH] - Fixed a problem with the sscanf() count (now 5, not 4). - 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 | 89 +++++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 32 deletions(-) diff --git a/fake-super.diff b/fake-super.diff index 9511970..cb5598d 100644 --- a/fake-super.diff +++ b/fake-super.diff @@ -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) -- 2.34.1