aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWayne Davison <wayned@samba.org>2009-09-02 09:06:29 -0700
committerWayne Davison <wayned@samba.org>2009-09-02 09:06:29 -0700
commit6e310d38fcdeacb8055bb7e83d4e64c37fd54a38 (patch)
tree4a6676f79d57605fd67701953950c059c3af985e
parent3b83a22057b71e7df2b960d3997fb4474910f30e (diff)
downloadandroid_external_rsync-6e310d38fcdeacb8055bb7e83d4e64c37fd54a38.tar.gz
android_external_rsync-6e310d38fcdeacb8055bb7e83d4e64c37fd54a38.tar.bz2
android_external_rsync-6e310d38fcdeacb8055bb7e83d4e64c37fd54a38.zip
Have --fake-super turn a symlink into a file when
NO_SYMLINK_XATTRS is defined.
-rw-r--r--flist.c2
-rw-r--r--generator.c4
-rw-r--r--rsync.h3
-rw-r--r--syscall.c41
-rw-r--r--t_unsafe.c1
-rw-r--r--tls.c5
-rw-r--r--trimslash.c1
7 files changed, 52 insertions, 5 deletions
diff --git a/flist.c b/flist.c
index 6eb02c7b..8b08ff6f 100644
--- a/flist.c
+++ b/flist.c
@@ -196,7 +196,7 @@ static int readlink_stat(const char *path, STRUCT_STAT *stp, char *linkbuf)
if (link_stat(path, stp, copy_dirlinks) < 0)
return -1;
if (S_ISLNK(stp->st_mode)) {
- int llen = readlink(path, linkbuf, MAXPATHLEN - 1);
+ int llen = do_readlink(path, linkbuf, MAXPATHLEN - 1);
if (llen < 0)
return -1;
linkbuf[llen] = '\0';
diff --git a/generator.c b/generator.c
index 2aa07cd0..5f6afd6f 100644
--- a/generator.c
+++ b/generator.c
@@ -946,7 +946,7 @@ static int try_dests_non(struct file_struct *file, char *fname, int ndx,
break;
case TYPE_SYMLINK:
#ifdef SUPPORT_LINKS
- if ((len = readlink(cmpbuf, lnk, MAXPATHLEN-1)) <= 0)
+ if ((len = do_readlink(cmpbuf, lnk, MAXPATHLEN-1)) <= 0)
continue;
lnk[len] = '\0';
if (strcmp(lnk, F_SYMLINK(file)) != 0)
@@ -1369,7 +1369,7 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
int len;
if (S_ISLNK(sx.st.st_mode)
- && (len = readlink(fname, lnk, MAXPATHLEN-1)) > 0
+ && (len = do_readlink(fname, lnk, MAXPATHLEN-1)) > 0
&& strncmp(lnk, sl, len) == 0 && sl[len] == '\0') {
/* The link is pointing to the right place. */
set_file_attrs(fname, file, &sx, NULL, maybe_ATTRS_REPORT);
diff --git a/rsync.h b/rsync.h
index c8115fce..4d4a7642 100644
--- a/rsync.h
+++ b/rsync.h
@@ -981,6 +981,9 @@ extern int errno;
#ifdef HAVE_READLINK
#define SUPPORT_LINKS 1
+#ifndef NO_SYMLINK_XATTRS
+#define do_readlink(path, buf, bufsiz) readlink(path, buf, bufsiz)
+#endif
#endif
#ifdef HAVE_LINK
#define SUPPORT_HARD_LINKS 1
diff --git a/syscall.c b/syscall.c
index 2d704a89..945a11d4 100644
--- a/syscall.c
+++ b/syscall.c
@@ -31,6 +31,7 @@
extern int dry_run;
extern int am_root;
+extern int am_sender;
extern int read_only;
extern int list_only;
extern int preserve_perms;
@@ -58,8 +59,48 @@ int do_symlink(const char *lnk, const char *fname)
{
if (dry_run) return 0;
RETURN_ERROR_IF_RO_OR_LO;
+
+#ifdef NO_SYMLINK_XATTRS
+ /* For --fake-super, we create a normal file with mode 0600
+ * and write the lnk into it. */
+ if (am_root < 0) {
+ int ok, len = strlen(lnk);
+ int fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, S_IWUSR|S_IRUSR);
+ if (fd < 0)
+ return -1;
+ ok = write(fd, lnk, len) == len;
+ if (close(fd) < 0)
+ ok = 0;
+ return ok ? 0 : -1;
+ }
+#endif
+
return symlink(lnk, fname);
}
+
+#ifdef NO_SYMLINK_XATTRS
+ssize_t do_readlink(const char *path, char *buf, size_t bufsiz)
+{
+ /* For --fake-super, we read the link from the file. */
+ if (am_root < 0) {
+ int fd = open(path, O_RDONLY|O_NOFOLLOW);
+ if (fd >= 0) {
+ int len = read(fd, buf, bufsiz);
+ close(fd);
+ return len;
+ }
+ if (errno != ELOOP)
+ return -1;
+ /* A real symlink needs to be turned into a fake one on the receiving
+ * side, so tell the generator that the link has no length. */
+ if (!am_sender)
+ return 0;
+ /* Otherwise fall through and let the sender report the real length. */
+ }
+
+ return readlink(path, buf, bufsiz);
+}
+#endif
#endif
#ifdef HAVE_LINK
diff --git a/t_unsafe.c b/t_unsafe.c
index 9ba0aaa5..550bc4b3 100644
--- a/t_unsafe.c
+++ b/t_unsafe.c
@@ -25,6 +25,7 @@
int dry_run = 0;
int am_root = 0;
+int am_sender = 1;
int read_only = 0;
int list_only = 0;
int human_readable = 0;
diff --git a/tls.c b/tls.c
index 8cc57482..1c5953d7 100644
--- a/tls.c
+++ b/tls.c
@@ -43,6 +43,7 @@
/* These are to make syscall.o shut up. */
int dry_run = 0;
int am_root = 0;
+int am_sender = 1;
int read_only = 1;
int list_only = 0;
int link_times = 0;
@@ -147,9 +148,9 @@ static void list_file(const char *fname)
buf.st_uid = buf.st_gid = 0;
strlcpy(linkbuf, " -> ", sizeof linkbuf);
/* const-cast required for silly UNICOS headers */
- len = readlink((char *) fname, linkbuf+4, sizeof(linkbuf) - 4);
+ len = do_readlink((char *) fname, linkbuf+4, sizeof(linkbuf) - 4);
if (len == -1)
- failed("readlink", fname);
+ failed("do_readlink", fname);
else
/* it's not nul-terminated */
linkbuf[4+len] = 0;
diff --git a/trimslash.c b/trimslash.c
index 40f2eb9b..448064ab 100644
--- a/trimslash.c
+++ b/trimslash.c
@@ -23,6 +23,7 @@
/* These are to make syscall.o shut up. */
int dry_run = 0;
int am_root = 0;
+int am_sender = 1;
int read_only = 1;
int list_only = 0;
int preserve_perms = 0;