* Trivial ls for comparing two directories after running an rsync.
*
* Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
- * Copyright (C) 2003, 2004, 2005 Wayne Davison
+ * Copyright (C) 2003-2007 Wayne Davison
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License version
- * 2 as published by the Free Software Foundation.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* 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",
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. */
return 1;
}
- for (argv++; *argv; argv++) {
+ if (getenv("RSYNC_FAKE_SUPER"))
+ am_root = -1;
+
+ for (argv++; *argv; argv++)
list_file(*argv);
- }
return 0;
}