summaryrefslogtreecommitdiff
path: root/tls.c
diff options
context:
space:
mode:
authorWayne Davison <wayned@samba.org>2007-04-24 07:32:44 +0000
committerWayne Davison <wayned@samba.org>2007-04-24 07:32:44 +0000
commit9439c0cb5a4b020b9bfcfe0351e33c17b9c53b54 (patch)
tree17ce2427a5fbcaf3968c2d94635cda239b4f5712 /tls.c
parent2ed790f3541cd5803b285bb46b2cba02103cc88b (diff)
downloadrsync-9439c0cb5a4b020b9bfcfe0351e33c17b9c53b54.tar.gz
rsync-9439c0cb5a4b020b9bfcfe0351e33c17b9c53b54.tar.bz2
rsync-9439c0cb5a4b020b9bfcfe0351e33c17b9c53b54.zip
Adding the --fake-super option.
Diffstat (limited to 'tls.c')
-rw-r--r--tls.c58
1 files changed, 56 insertions, 2 deletions
diff --git a/tls.c b/tls.c
index cd4e26de..8a388199 100644
--- a/tls.c
+++ b/tls.c
@@ -34,15 +34,65 @@
* change. */
#include "rsync.h"
+#include "lib/sysxattrs.h"
#define PROGRAM "tls"
/* These are to make syscall.o shut up. */
int dry_run = 0;
+int am_root = 0;
int read_only = 1;
int list_only = 0;
int preserve_perms = 0;
+#ifdef HAVE_LINUX_XATTRS
+#define XSTAT_ATTR "user.rsync.%stat"
+#else
+#define XSTAT_ATTR "rsync.%stat"
+#endif
+
+static int stat_xattr(const char *fname, STRUCT_STAT *fst)
+{
+ int mode, rdev_major, rdev_minor, uid, gid, len;
+ char buf[256];
+
+ if (am_root >= 0 || IS_DEVICE(fst->st_mode) || IS_SPECIAL(fst->st_mode))
+ return -1;
+
+ len = sys_lgetxattr(fname, XSTAT_ATTR, buf, sizeof buf - 1);
+ if (len >= (int)sizeof buf) {
+ len = -1;
+ errno = ERANGE;
+ }
+ if (len < 0) {
+ if (errno == ENOTSUP || errno == ENOATTR)
+ return -1;
+ if (errno == EPERM && S_ISLNK(fst->st_mode)) {
+ fst->st_uid = 0;
+ fst->st_gid = 0;
+ return 0;
+ }
+ fprintf(stderr, "failed to read xattr %s for %s: %s\n",
+ XSTAT_ATTR, fname, strerror(errno));
+ return -1;
+ }
+ buf[len] = '\0';
+
+ if (sscanf(buf, "%o %d,%d %d:%d",
+ &mode, &rdev_major, &rdev_minor, &uid, &gid) != 5) {
+ fprintf(stderr, "Corrupt %s xattr attached to %s: \"%s\"\n",
+ XSTAT_ATTR, fname, buf);
+ exit(1);
+ }
+
+ fst->st_mode = from_wire_mode(mode);
+ fst->st_rdev = MAKEDEV(rdev_major, rdev_minor);
+ fst->st_uid = uid;
+ fst->st_gid = gid;
+
+ return 0;
+}
+
static void failed(char const *what, char const *where)
{
fprintf(stderr, PROGRAM ": %s %s: %s\n",
@@ -60,6 +110,8 @@ static void list_file(const char *fname)
if (do_lstat(fname, &buf) < 0)
failed("stat", fname);
+ if (am_root < 0)
+ stat_xattr(fname, &buf);
/* The size of anything but a regular file is probably not
* worth thinking about. */
@@ -125,9 +177,11 @@ main(int argc, char *argv[])
return 1;
}
- for (argv++; *argv; argv++) {
+ if (getenv("RSYNC_FAKE_SUPER"))
+ am_root = -1;
+
+ for (argv++; *argv; argv++)
list_file(*argv);
- }
return 0;
}