X-Git-Url: https://mattmccutchen.net/rsync/rsync-patches.git/blobdiff_plain/c8e414748a6682ca35ec3c3fb389c6adae9479db..64e98de1da91464b3f444242af02b74294486431:/fake-super.diff diff --git a/fake-super.diff b/fake-super.diff index e8a078a..05a3bf1 100644 --- a/fake-super.diff +++ b/fake-super.diff @@ -19,7 +19,7 @@ above: --- old/backup.c +++ new/backup.c -@@ -129,7 +129,7 @@ static int make_bak_dir(char *fullpath) +@@ -128,7 +128,7 @@ static int make_bak_dir(char *fullpath) if (p >= rel) { /* Try to transfer the directory settings of the * actual dir that the files are coming from. */ @@ -28,7 +28,7 @@ above: rsyserr(FERROR, errno, "make_bak_dir stat %s failed", full_fname(rel)); -@@ -200,7 +200,7 @@ static int keep_backup(char *fname) +@@ -199,7 +199,7 @@ static int keep_backup(const char *fname int ret_code; /* return if no file to keep */ @@ -39,9 +39,9 @@ above: sx.acc_acl = sx.def_acl = NULL; --- old/clientserver.c +++ new/clientserver.c -@@ -625,6 +625,11 @@ static int rsync_module(int f_in, int f_ - ret = parse_arguments(&argc, (const char ***) &argv, 0); - quiet = 0; /* Don't let someone try to be tricky. */ +@@ -630,6 +630,11 @@ static int rsync_module(int f_in, int f_ + if (lp_ignore_errors(module_id)) + ignore_errors = 1; + if (lp_fake_super(i)) + am_root = -1; @@ -53,7 +53,13 @@ above: --- old/flist.c +++ new/flist.c -@@ -181,7 +181,7 @@ static int readlink_stat(const char *pat +@@ -194,12 +194,12 @@ static int readlink_stat(const char *pat + rprintf(FINFO,"copying unsafe symlink \"%s\" -> \"%s\"\n", + path, linkbuf); + } +- return do_stat(path, stp); ++ return x_stat(path, stp, NULL); + } } return 0; #else @@ -62,7 +68,7 @@ above: #endif } -@@ -189,17 +189,17 @@ int link_stat(const char *path, STRUCT_S +@@ -207,17 +207,17 @@ int link_stat(const char *path, STRUCT_S { #ifdef SUPPORT_LINKS if (copy_links) @@ -84,7 +90,7 @@ above: #endif } -@@ -234,26 +234,6 @@ static int is_excluded(char *fname, int +@@ -252,26 +252,6 @@ static int is_excluded(char *fname, int return 0; } @@ -108,10 +114,10 @@ above: - return mode; -} - - static void send_directory(int f, struct file_list *flist, - char *fbuf, int len); + static void send_directory(int f, struct file_list *flist, int ndx, + char *fbuf, int len, int flags); -@@ -793,7 +773,7 @@ struct file_struct *make_file(char *fnam +@@ -925,7 +905,7 @@ struct file_struct *make_file(const char if (save_errno == ENOENT) { #ifdef SUPPORT_LINKS /* Avoid "vanished" error if symlink points nowhere. */ @@ -120,14 +126,14 @@ above: && S_ISLNK(st.st_mode)) { io_error |= IOERR_GENERAL; rprintf(FERROR, "symlink has no referent: %s\n", -@@ -963,7 +943,7 @@ struct file_struct *make_file(char *fnam +@@ -1097,7 +1077,7 @@ struct file_struct *make_file(const char int save_mode = file->mode; file->mode = S_IFDIR; /* Find a directory with our name. */ - if (flist_find(the_file_list, file) >= 0 + if (flist_find(dir_flist, file) >= 0 - && do_stat(thisname, &st2) == 0 && S_ISDIR(st2.st_mode)) { + && x_stat(thisname, &st2, NULL) == 0 && S_ISDIR(st2.st_mode)) { file->modtime = st2.st_mtime; - file->length = st2.st_size; + file->len32 = 0; file->mode = st2.st_mode; --- old/loadparm.c +++ new/loadparm.c @@ -163,7 +169,7 @@ above: FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors) FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable) FN_LOCAL_BOOL(lp_list, list) -@@ -816,7 +820,7 @@ BOOL lp_load(char *pszFname, int globals +@@ -815,7 +819,7 @@ BOOL lp_load(char *pszFname, int globals if (pszFname) pstrcpy(n2,pszFname); @@ -183,7 +189,7 @@ above: int am_server = 0; int am_sender = 0; int am_generator = 0; -@@ -329,6 +329,9 @@ void usage(enum logcode F) +@@ -326,6 +326,9 @@ void usage(enum logcode F) rprintf(F," -t, --times preserve times\n"); rprintf(F," -O, --omit-dir-times omit directories when preserving times\n"); rprintf(F," --super receiver attempts super-user activities\n"); @@ -193,7 +199,7 @@ above: rprintf(F," -S, --sparse handle sparse files efficiently\n"); rprintf(F," -n, --dry-run show what would have been transferred\n"); rprintf(F," -W, --whole-file copy files whole (without rsync algorithm)\n"); -@@ -453,6 +456,7 @@ static struct poptOption long_options[] +@@ -451,6 +454,7 @@ static struct poptOption long_options[] {"modify-window", 0, POPT_ARG_INT, &modify_window, OPT_MODIFY_WINDOW, 0, 0 }, {"super", 0, POPT_ARG_VAL, &am_root, 2, 0, 0 }, {"no-super", 0, POPT_ARG_VAL, &am_root, 0, 0, 0 }, @@ -201,7 +207,7 @@ above: {"owner", 'o', POPT_ARG_VAL, &preserve_uid, 1, 0, 0 }, {"no-owner", 0, POPT_ARG_VAL, &preserve_uid, 0, 0, 0 }, {"no-o", 0, POPT_ARG_VAL, &preserve_uid, 0, 0, 0 }, -@@ -1178,6 +1182,14 @@ int parse_arguments(int *argc, const cha +@@ -1183,6 +1187,14 @@ int parse_arguments(int *argc, const cha } #endif @@ -218,18 +224,18 @@ above: "--write-batch and --read-batch can not be used together\n"); --- old/rsync.c +++ new/rsync.c -@@ -196,7 +196,9 @@ int set_file_attrs(char *fname, struct f - (long)sxp->st.st_gid, (long)file->gid); +@@ -299,7 +299,9 @@ int set_file_attrs(char *fname, struct f + (long)sxp->st.st_gid, (long)F_GID(file)); } } - 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) { + change_uid ? F_UID(file) : sxp->st.st_uid, + change_gid ? F_GID(file) : sxp->st.st_gid) != 0) { /* shouldn't have attempted to change uid or gid -@@ -205,7 +207,7 @@ int set_file_attrs(char *fname, struct f +@@ -308,7 +310,7 @@ int set_file_attrs(char *fname, struct f change_uid ? "chown" : "chgrp", full_fname(fname)); goto cleanup; @@ -238,7 +244,7 @@ above: /* 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 */ -@@ -222,6 +224,8 @@ int set_file_attrs(char *fname, struct f +@@ -325,6 +327,8 @@ int set_file_attrs(char *fname, struct f #ifdef SUPPORT_XATTRS if (preserve_xattrs && set_xattr(fname, file, sxp) == 0) updated = 1; @@ -247,10 +253,10 @@ above: #endif #ifdef SUPPORT_ACLS /* It's OK to call set_acl() now, even for a dir, as the generator -@@ -236,7 +240,7 @@ int set_file_attrs(char *fname, struct f +@@ -339,7 +343,7 @@ int set_file_attrs(char *fname, struct f #ifdef HAVE_CHMOD - if ((sxp->st.st_mode & CHMOD_BITS) != (new_mode & CHMOD_BITS)) { + if (!BITS_EQUAL(sxp->st.st_mode, new_mode, CHMOD_BITS)) { - int ret = do_chmod(fname, new_mode); + int ret = am_root < 0 ? 0 : do_chmod(fname, new_mode); if (ret < 0) { @@ -258,7 +264,7 @@ above: "failed to set permissions on %s", --- old/rsync.h +++ new/rsync.h -@@ -707,6 +707,12 @@ typedef struct { +@@ -813,6 +813,12 @@ typedef struct { #include "proto.h" @@ -271,11 +277,10 @@ above: /* We have replacement versions of these if they're missing. */ #ifndef HAVE_ASPRINTF int asprintf(char **ptr, const char *format, ...); -@@ -924,3 +930,23 @@ int inet_pton(int af, const char *src, v - #ifdef MAINTAINER_MODE +@@ -1031,6 +1037,26 @@ int inet_pton(int af, const char *src, v const char *get_panic_action(void); #endif -+ + +static inline int to_wire_mode(mode_t mode) +{ +#ifdef SUPPORT_LINKS @@ -295,6 +300,10 @@ above: +#endif + return mode; +} ++ + static inline int + isDigit(const char *ptr) + { --- old/rsync.yo +++ new/rsync.yo @@ -333,6 +333,7 @@ to the detailed description below for a @@ -381,7 +390,7 @@ above: extern int read_only; extern int list_only; extern int preserve_perms; -@@ -79,6 +80,15 @@ int do_mknod(char *pathname, mode_t mode +@@ -79,6 +80,15 @@ int do_mknod(const char *pathname, mode_ { if (dry_run) return 0; RETURN_ERROR_IF_RO_OR_LO; @@ -418,7 +427,7 @@ above: /* These are to make syscall.o shut up. */ int dry_run = 0; -+int am_root = 0; /* TODO: add option to set this to -1. */ ++int am_root = 0; int read_only = 1; int list_only = 0; int preserve_perms = 0; @@ -434,54 +443,97 @@ above: int preserve_perms = 0; --- old/xattr.c +++ new/xattr.c -@@ -28,11 +28,14 @@ - extern int dry_run; - extern int read_only; - extern int list_only; -+extern int am_root; - extern unsigned int file_struct_len; - - #define RSYNC_XAL_INITIAL 5 - #define RSYNC_XAL_LIST_INITIAL 100 +@@ -42,11 +42,16 @@ extern int list_only; + #define SPRE_LEN ((int)sizeof SYSTEM_PREFIX - 1) -+#define FAKE_XATTR "user.rsync%stat" + #ifdef HAVE_LINUX_XATTRS +-#define RPRE_LEN 0 ++#define MIGHT_NEED_RPRE (am_root < 0) ++#define RSYNC_PREFIX USER_PREFIX "rsync." + #else ++#define MIGHT_NEED_RPRE am_root + #define RSYNC_PREFIX "rsync." +-#define RPRE_LEN ((int)sizeof RSYNC_PREFIX - 1) + #endif ++#define RPRE_LEN ((int)sizeof RSYNC_PREFIX - 1) + ++#define XSTAT_ATTR RSYNC_PREFIX "%stat" ++#define XSTAT_LEN ((int)sizeof XSTAT_ATTR - 1) + typedef struct { - char *name; - char *datum; -@@ -134,9 +137,15 @@ static int rsync_xal_get(const char *fna - if (name_size == 0) - return 0; - for (left = name_size, name = namebuf; left > 0 ; left -= len, name += len) { -- rsync_xa *rxas = EXPAND_ITEM_LIST(xalp, rsync_xa, RSYNC_XAL_INITIAL); -+ rsync_xa *rxas; + char *datum, *name; +@@ -147,6 +152,10 @@ static int rsync_xal_get(const char *fna + continue; + #endif - len = strlen(name) + 1; -+ if (am_root < 0 && len == sizeof FAKE_XATTR -+ && name[10] == '%' && strcmp(name, FAKE_XATTR) == 0) ++ if (am_root < 0 && name_len == XSTAT_LEN + 1 ++ && name[RPRE_LEN] == '%' && strcmp(name, XSTAT_ATTR) == 0) + continue; + -+ rxas = EXPAND_ITEM_LIST(xalp, rsync_xa, RSYNC_XAL_INITIAL); -+ - datum_size = sys_lgetxattr(fname, name, NULL, 0); - if (datum_size < 0) { + datum_len = sys_lgetxattr(fname, name, NULL, 0); + if (datum_len < 0) { if (errno == ENOTSUP) -@@ -288,6 +297,14 @@ void receive_xattr(struct file_struct *f - out_of_memory("receive_xattr"); - read_buf(f, ptr, name_len); - read_buf(f, ptr + name_len, datum_len); -+ -+ if (am_root < 0 && name_len == sizeof FAKE_XATTR -+ && ptr[10] == '%' && strcmp(ptr, FAKE_XATTR) == 0) { +@@ -176,6 +185,13 @@ static int rsync_xal_get(const char *fna + return -1; + } + } ++#ifdef HAVE_LINUX_XATTRS ++ if (am_root < 0 && name_len > RPRE_LEN ++ && HAS_PREFIX(name, RSYNC_PREFIX)) { ++ name += RPRE_LEN; ++ name_len -= RPRE_LEN; ++ } ++#endif + rxas = EXPAND_ITEM_LIST(xalp, rsync_xa, RSYNC_XAL_INITIAL); + rxas->name = ptr + datum_len; + rxas->datum = ptr; +@@ -296,13 +312,9 @@ void receive_xattr(struct file_struct *f + rsync_xa *rxa; + size_t name_len = read_int(f); + size_t datum_len = read_int(f); +-#ifdef HAVE_LINUX_XATTRS +- size_t extra_len = 0; +-#else +- size_t extra_len = am_root ? RPRE_LEN : 0; ++ size_t extra_len = MIGHT_NEED_RPRE ? RPRE_LEN : 0; + if (datum_len + extra_len < datum_len) + out_of_memory("receive_xattr"); /* overflow */ +-#endif + if (name_len + datum_len + extra_len < name_len) + out_of_memory("receive_xattr"); /* overflow */ + ptr = new_array(char, name_len + datum_len + extra_len); +@@ -313,9 +325,14 @@ void receive_xattr(struct file_struct *f + read_buf(f, ptr, datum_len); + #ifdef HAVE_LINUX_XATTRS + /* Non-root can only save the user namespace. */ +- if (!am_root && !HAS_PREFIX(name, USER_PREFIX)) { +- free(ptr); +- continue; ++ if (am_root <= 0 && !HAS_PREFIX(name, USER_PREFIX)) { ++ if (!am_root) { ++ free(ptr); ++ continue; ++ } ++ name -= RPRE_LEN; ++ name_len += RPRE_LEN; ++ memcpy(name, RSYNC_PREFIX, RPRE_LEN); + } + #else + /* This OS only has a user namespace, so we either +@@ -333,6 +350,12 @@ void receive_xattr(struct file_struct *f + continue; + } + #endif ++ if (am_root < 0 && name_len == XSTAT_LEN + 1 ++ && name[RPRE_LEN] == '%' ++ && strcmp(name, XSTAT_ATTR) == 0) { + free(ptr); -+ temp_xattr.count--; + continue; + } -+ - rxa->name_len = name_len; - rxa->datum_len = datum_len; - rxa->name = ptr; -@@ -373,4 +390,146 @@ int set_xattr(const char *fname, const s + rxa = EXPAND_ITEM_LIST(&temp_xattr, rsync_xa, count); + rxa->name = name; + rxa->datum = ptr; +@@ -410,4 +433,150 @@ int set_xattr(const char *fname, const s return rsync_xal_set(fname, lst + ndx); /* TODO: This needs to return 1 if no xattrs changed! */ } @@ -499,10 +551,10 @@ above: + xst = fst; + if (fname) { + fd = -1; -+ len = sys_lgetxattr(fname, FAKE_XATTR, buf, sizeof buf - 1); ++ len = sys_lgetxattr(fname, XSTAT_ATTR, buf, sizeof buf - 1); + } else { + fname = "fd"; -+ len = sys_fgetxattr(fd, FAKE_XATTR, buf, sizeof buf - 1); ++ len = sys_fgetxattr(fd, XSTAT_ATTR, buf, sizeof buf - 1); + } + if (len >= (int)sizeof buf) { + len = -1; @@ -517,7 +569,7 @@ above: + return 0; + } + rsyserr(FERROR, errno, "failed to read xattr %s for %s", -+ FAKE_XATTR, full_fname(fname)); ++ XSTAT_ATTR, full_fname(fname)); + return -1; + } + buf[len] = '\0'; @@ -525,7 +577,7 @@ above: + if (sscanf(buf, "%o %d,%d %d:%d", + &mode, &rdev_major, &rdev_minor, &uid, &gid) != 5) { + rprintf(FERROR, "Corrupt %s xattr attached to %s: \"%s\"\n", -+ FAKE_XATTR, full_fname(fname), buf); ++ XSTAT_ATTR, full_fname(fname), buf); + exit_cleanup(RERR_FILEIO); + } + @@ -541,14 +593,14 @@ above: +{ + STRUCT_STAT fst, xst; + dev_t rdev; -+ mode_t mode; ++ mode_t mode, fmode; + + if (dry_run) + return 0; + + if (read_only || list_only) { + rsyserr(FERROR, EROFS, "failed to write xattr %s for %s", -+ FAKE_XATTR, full_fname(fname)); ++ XSTAT_ATTR, full_fname(fname)); + return -1; + } + @@ -558,23 +610,27 @@ above: + return -1; + } + -+ if (IS_DEVICE(file->mode) || IS_SPECIAL(file->mode)) -+ rdev = file->u.rdev; -+ else ++ fst.st_mode &= (_S_IFMT | CHMOD_BITS); ++ fmode = file->mode & (_S_IFMT | CHMOD_BITS); ++ ++ if (IS_DEVICE(fmode) || IS_SPECIAL(fmode)) { ++ uint32 *devp = F_RDEV_P(file); ++ rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)); ++ } else + rdev = 0; + + /* Dump the special permissions and enable full owner access. */ -+ mode = (fst.st_mode & ~CHMOD_BITS) | (file->mode & ACCESSPERMS) ++ mode = (fst.st_mode & _S_IFMT) | (fmode & ACCESSPERMS) + | (S_ISDIR(fst.st_mode) ? 0700 : 0600); + if (fst.st_mode != mode) + do_chmod(fname, mode); + if (!IS_DEVICE(fst.st_mode) && !IS_SPECIAL(fst.st_mode)) + fst.st_rdev = 0; /* just in case */ + -+ if (mode == file->mode && fst.st_rdev == rdev -+ && fst.st_uid == file->uid && fst.st_gid == file->gid) { ++ if (mode == fmode && fst.st_rdev == rdev ++ && fst.st_uid == F_UID(file) && fst.st_gid == F_GID(file)) { + /* xst.st_mode will be 0 if there's no current stat xattr */ -+ if (xst.st_mode && sys_lremovexattr(fname, FAKE_XATTR) < 0) { ++ if (xst.st_mode && sys_lremovexattr(fname, XSTAT_ATTR) < 0) { + rsyserr(FERROR, errno, + "delete of stat xattr failed for %s", + full_fname(fname)); @@ -583,19 +639,19 @@ above: + return 0; + } + -+ if (xst.st_mode != file->mode || xst.st_rdev != rdev -+ || xst.st_uid != file->uid || xst.st_gid != file->gid) { ++ if (xst.st_mode != fmode || xst.st_rdev != rdev ++ || xst.st_uid != F_UID(file) || xst.st_gid != F_GID(file)) { + char buf[256]; + int len = snprintf(buf, sizeof buf, "%o %u,%u %u:%u", -+ to_wire_mode(file->mode) & (_S_IFMT|CHMOD_BITS), ++ to_wire_mode(fmode), + (int)major(rdev), (int)minor(rdev), -+ (int)file->uid, (int)file->gid); -+ if (sys_lsetxattr(fname, FAKE_XATTR, buf, len) < 0) { ++ (int)F_UID(file), (int)F_GID(file)); ++ if (sys_lsetxattr(fname, XSTAT_ATTR, buf, len) < 0) { + if (errno == EPERM && S_ISLNK(fst.st_mode)) + return 0; + rsyserr(FERROR, errno, + "failed to write xattr %s for %s", -+ FAKE_XATTR, full_fname(fname)); ++ XSTAT_ATTR, full_fname(fname)); + return -1; + } + }