Avoid directory permission issues with --fake-super.
authorWayne Davison <wayned@samba.org>
Sun, 2 Jan 2011 00:39:55 +0000 (16:39 -0800)
committerWayne Davison <wayned@samba.org>
Sun, 2 Jan 2011 00:57:08 +0000 (16:57 -0800)
Fixes bug 7070.

generator.c
receiver.c
testsuite/xattrs.test

index c2fbc065057c01aa1ae3a91c980dc879d89603f4..e14b72eb9f02453abc2f64e70e507e41a0e0b1e9 100644 (file)
@@ -1411,8 +1411,15 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
        fnamecmp = fname;
 
        if (is_dir) {
+               mode_t added_perms;
                if (!implied_dirs && file->flags & FLAG_IMPLIED_DIR)
                        goto cleanup;
+               if (am_root < 0) {
+                       /* For --fake-super, the dir must be useable by the copying
+                        * user, just like it would be for root. */
+                       added_perms = S_IRUSR|S_IWUSR|S_IXUSR;
+               } else
+                       added_perms = 0;
                if (is_dir < 0) {
                        /* In inc_recurse mode we want to make sure any missing
                         * directories get created while we're still processing
@@ -1423,7 +1430,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                         && (S_ISDIR(sx.st.st_mode)
                          || delete_item(fname, sx.st.st_mode, del_opts | DEL_FOR_DIR) != 0))
                                goto cleanup; /* Any errors get reported later. */
-                       if (do_mkdir(fname, file->mode & 0700) == 0)
+                       if (do_mkdir(fname, (file->mode|added_perms) & 0700) == 0)
                                file->flags |= FLAG_DIR_CREATED;
                        goto cleanup;
                }
@@ -1466,10 +1473,10 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
                        itemize(fnamecmp, file, ndx, statret, &sx,
                                statret ? ITEM_LOCAL_CHANGE : 0, 0, NULL);
                }
-               if (real_ret != 0 && do_mkdir(fname,file->mode) < 0 && errno != EEXIST) {
+               if (real_ret != 0 && do_mkdir(fname,file->mode|added_perms) < 0 && errno != EEXIST) {
                        if (!relative_paths || errno != ENOENT
-                           || create_directory_path(fname) < 0
-                           || (do_mkdir(fname, file->mode) < 0 && errno != EEXIST)) {
+                        || create_directory_path(fname) < 0
+                        || (do_mkdir(fname, file->mode|added_perms) < 0 && errno != EEXIST)) {
                                rsyserr(FERROR_XFER, errno,
                                        "recv_generator: mkdir %s failed",
                                        full_fname(fname));
index 467db5ed4f92998ee904c0fda15fb11c6cd910b4..878ed00418ae273023fc2936477f6e19fefa51a4 100644 (file)
@@ -24,6 +24,7 @@
 extern int verbose;
 extern int dry_run;
 extern int do_xfers;
+extern int am_root;
 extern int am_server;
 extern int do_progress;
 extern int inc_recurse;
@@ -131,15 +132,25 @@ int get_tmpname(char *fnametmp, const char *fname)
 int open_tmpfile(char *fnametmp, const char *fname, struct file_struct *file)
 {
        int fd;
+       mode_t added_perms;
 
        if (!get_tmpname(fnametmp, fname))
                return -1;
 
+       if (am_root < 0) {
+               /* For --fake-super, the file must be useable by the copying
+                * user, just like it would be for root. */
+               added_perms = S_IRUSR|S_IWUSR;
+       } else {
+               /* For a normal copy, we need to be able to tweak things like xattrs. */
+               added_perms = S_IWUSR;
+       }
+
        /* We initially set the perms without the setuid/setgid bits or group
         * access to ensure that there is no race condition.  They will be
         * correctly updated after the right owner and group info is set.
         * (Thanks to snabb@epipe.fi for pointing this out.) */
-       fd = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
+       fd = do_mkstemp(fnametmp, (file->mode|added_perms) & INITACCESSPERMS);
 
 #if 0
        /* In most cases parent directories will already exist because their
@@ -149,7 +160,7 @@ int open_tmpfile(char *fnametmp, const char *fname, struct file_struct *file)
            && create_directory_path(fnametmp) == 0) {
                /* Get back to name with XXXXXX in it. */
                get_tmpname(fnametmp, fname);
-               fd = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
+               fd = do_mkstemp(fnametmp, (file->mode|added_perms) & INITACCESSPERMS);
        }
 #endif
 
index 2975b4a323680a4cab78bcd3820b0a0f8ea00310..616b6286dde1c52b71a2ef94a36c77a7b87d28bb 100644 (file)
@@ -48,7 +48,8 @@ makepath "$chkdir/foo"
 echo wow >"$chkdir/file1"
 cp_touch "$fromdir/foo/file3" "$chkdir/foo"
 
-files='foo file0 file1 file2 foo/file3 file4 foo/bar/file5'
+files='foo file0 file1 file2 foo/file3 file4 foo/bar foo/bar/file5'
+uid_gid=`"$TOOLDIR/tls" "$fromdir/foo" | sed 's/^.* \([0-9][0-9]*\)\.\([0-9][0-9]*\) .*/\1:\2/'`
 
 cd "$fromdir"
 
@@ -117,6 +118,23 @@ if [ -s "$scratchdir/ls-diff" ]; then
     exit 1
 fi
 
+cd "$chkdir"
+chmod go-rwx . $files
+
+xset user.rsync.%stat "100000 0,0 $uid_gid" $files
+xset user.rsync.%stat "40000 0,0 $uid_gid" foo foo/bar
+
+xls $files >"$scratchdir/xattrs.txt"
+
+cd "$fromdir"
+rm -rf "$todir"
+
+# When run by a non-root tester, this checks if no-user-perm files/dirs can be copied.
+checkit "$RSYNC -aiX --fake-super --chmod=a= . ../to" "$chkdir" "$todir" # 2>"$scratchdir/errors.txt"
+
+cd "$todir"
+xls $files | diff $diffopt "$scratchdir/xattrs.txt" -
+
 cd "$fromdir"
 rm -rf "$todir" "$chkdir"