Added check to ensure that a read-only daemon doesn't honor
[rsync/rsync-patches.git] / links-depth.diff
CommitLineData
0143ad24
WD
1The attached patch gives the user ability to define how many symbolic
2links rsync should follow before actually adding it to the file list.
3
4The patch has been heavily modified from its original form to work
5with the latest codebase, but even in its original form it didn't
6handle relative symlinks properly, and that has not yet been fixed
7in this modified version.
8
be73a66e 9--- orig/flist.c 2005-01-24 00:18:21
1189721b 10+++ flist.c 2004-07-16 16:58:04
a6587818 11@@ -50,6 +50,7 @@ extern int filesfrom_fd;
0143ad24
WD
12 extern int one_file_system;
13 extern int keep_dirlinks;
14 extern int preserve_links;
15+extern int follow_links_depth;
16 extern int preserve_hard_links;
17 extern int preserve_perms;
18 extern int preserve_devices;
a6587818 19@@ -726,6 +727,30 @@ void receive_file_entry(struct file_stru
0143ad24
WD
20 }
21
22
23+#if SUPPORT_LINKS
1189721b 24+static int links_depth(char *linkname, STRUCT_STAT *st_ptr)
0143ad24
WD
25+{
26+ char buf[MAXPATHLEN];
27+ STRUCT_STAT st;
28+ int i;
29+
30+ for (i = 0; i < follow_links_depth; i++) {
31+ /* XXX This doesn't handle relative symlinks! */
32+ if (readlink_stat(linkname, &st, buf) != 0)
33+ break;
34+ *st_ptr = st;
35+ if (!S_ISLNK(st.st_mode))
36+ return 1;
37+ strlcpy(linkname, buf, MAXPATHLEN);
38+#if 0
39+ fprintf(stderr, "\n%s:%i [#%i] %s -> %s\n", __FILE__, __LINE__, i, file->u.link, linkname);
40+#endif
41+ }
42+
43+ return 0;
44+}
45+#endif
46+
47 /**
48 * Create a file_struct for a named file by reading its stat()
49 * information and performing extensive checks against global
0b2fb126 50@@ -850,7 +875,13 @@ skip_excludes:
0143ad24
WD
51 basename_len = strlen(basename) + 1; /* count the '\0' */
52
53 #if SUPPORT_LINKS
54- linkname_len = S_ISLNK(st.st_mode) ? strlen(linkname) + 1 : 0;
55+ if (S_ISLNK(st.st_mode)) {
56+ if (follow_links_depth && links_depth(linkname, &st))
57+ linkname_len = 0;
58+ else
59+ linkname_len = strlen(linkname) + 1;
60+ } else
61+ linkname_len = 0;
62 #else
63 linkname_len = 0;
64 #endif
be73a66e 65--- orig/options.c 2005-01-24 00:18:21
0143ad24
WD
66+++ options.c 2004-07-16 16:12:29
67@@ -42,6 +42,7 @@ int archive_mode = 0;
68 int keep_dirlinks = 0;
69 int copy_links = 0;
70 int preserve_links = 0;
71+int follow_links_depth = 0;
72 int preserve_hard_links = 0;
73 int preserve_perms = 0;
74 int preserve_devices = 0;
be73a66e 75@@ -253,6 +254,7 @@ void usage(enum logcode F)
0b2fb126 76 rprintf(F," --inplace update destination files in-place (SEE MAN PAGE)\n");
be73a66e 77 rprintf(F," -d, --dirs transfer directories without recursing\n");
0143ad24
WD
78 rprintf(F," -l, --links copy symlinks as symlinks\n");
79+ rprintf(F," --links-depth=NUM follow symlinks up to NUM depth\n");
80 rprintf(F," -L, --copy-links copy the referent of all symlinks\n");
81 rprintf(F," --copy-unsafe-links copy the referent of \"unsafe\" symlinks\n");
82 rprintf(F," --safe-links ignore \"unsafe\" symlinks\n");
be73a66e 83@@ -360,6 +362,7 @@ static struct poptOption long_options[]
f6c3b300 84 {"inplace", 0, POPT_ARG_NONE, &inplace, 0, 0, 0 },
be73a66e 85 {"dirs", 'd', POPT_ARG_VAL, &xfer_dirs, 2, 0, 0 },
0143ad24
WD
86 {"links", 'l', POPT_ARG_NONE, &preserve_links, 0, 0, 0 },
87+ {"links-depth", 0, POPT_ARG_INT, &follow_links_depth , 0, 0, 0 },
88 {"copy-links", 'L', POPT_ARG_NONE, &copy_links, 0, 0, 0 },
be73a66e 89 {"keep-dirlinks", 'K', POPT_ARG_NONE, &keep_dirlinks, 0, 0, 0 },
0143ad24 90 {"whole-file", 'W', POPT_ARG_VAL, &whole_file, 1, 0, 0 },