Have --fake-super turn a symlink into a file when
NO_SYMLINK_XATTRS is defined.
diff --git a/flist.c b/flist.c
index 6eb02c7..8b08ff6 100644
--- a/flist.c
+++ b/flist.c
@@ -196,7 +196,7 @@
 	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 2aa07cd..5f6afd6 100644
--- a/generator.c
+++ b/generator.c
@@ -946,7 +946,7 @@
 			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 @@
 			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 c8115fc..4d4a764 100644
--- a/rsync.h
+++ b/rsync.h
@@ -981,6 +981,9 @@
 
 #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 2d704a8..945a11d 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 @@
 {
 	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 9ba0aaa..550bc4b 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 8cc5748..1c5953d 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 @@
 			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 40f2eb9..448064a 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;