Fixes from Matt.
[rsync/rsync-patches.git] / links-depth.diff
... / ...
CommitLineData
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
9To use this patch, run these commands for a successful build:
10
11 patch -p1 <patches/links-depth.diff
12 ./configure (optional if already run)
13 make
14
15--- old/flist.c
16+++ new/flist.c
17@@ -47,6 +47,7 @@ extern int keep_dirlinks;
18 extern int preserve_acls;
19 extern int preserve_xattrs;
20 extern int preserve_links;
21+extern int follow_links_depth;
22 extern int preserve_hard_links;
23 extern int preserve_devices;
24 extern int preserve_specials;
25@@ -980,6 +981,30 @@ static struct file_struct *recv_file_ent
26 return file;
27 }
28
29+#if SUPPORT_LINKS
30+static int links_depth(char *linkname, STRUCT_STAT *st_ptr)
31+{
32+ char buf[MAXPATHLEN];
33+ STRUCT_STAT st;
34+ int i;
35+
36+ for (i = 0; i < follow_links_depth; i++) {
37+ /* XXX This doesn't handle relative symlinks! */
38+ if (readlink_stat(linkname, &st, buf) != 0)
39+ break;
40+ *st_ptr = st;
41+ if (!S_ISLNK(st.st_mode))
42+ return 1;
43+ strlcpy(linkname, buf, MAXPATHLEN);
44+#if 0
45+ fprintf(stderr, "\n%s:%i [#%i] %s -> %s\n", __FILE__, __LINE__, i, file->u.link, linkname);
46+#endif
47+ }
48+
49+ return 0;
50+}
51+#endif
52+
53 /* Create a file_struct for a named file by reading its stat() information
54 * and performing extensive checks against global options.
55 *
56@@ -1120,7 +1145,13 @@ struct file_struct *make_file(const char
57 basename_len = strlen(basename) + 1; /* count the '\0' */
58
59 #ifdef SUPPORT_LINKS
60- linkname_len = S_ISLNK(st.st_mode) ? strlen(linkname) + 1 : 0;
61+ if (S_ISLNK(st.st_mode)) {
62+ if (follow_links_depth && links_depth(linkname, &st))
63+ linkname_len = 0;
64+ else
65+ linkname_len = strlen(linkname) + 1;
66+ } else
67+ linkname_len = 0;
68 #else
69 linkname_len = 0;
70 #endif
71--- old/options.c
72+++ new/options.c
73@@ -46,6 +46,7 @@ int keep_dirlinks = 0;
74 int copy_dirlinks = 0;
75 int copy_links = 0;
76 int preserve_links = 0;
77+int follow_links_depth = 0;
78 int preserve_hard_links = 0;
79 int preserve_acls = 0;
80 int preserve_xattrs = 0;
81@@ -321,6 +322,7 @@ void usage(enum logcode F)
82 rprintf(F," --append append data onto shorter files\n");
83 rprintf(F," -d, --dirs transfer directories without recursing\n");
84 rprintf(F," -l, --links copy symlinks as symlinks\n");
85+ rprintf(F," --links-depth=NUM follow symlinks up to NUM depth\n");
86 rprintf(F," -L, --copy-links transform symlink into referent file/dir\n");
87 rprintf(F," --copy-unsafe-links only \"unsafe\" symlinks are transformed\n");
88 rprintf(F," --safe-links ignore symlinks that point outside the source tree\n");
89@@ -496,6 +498,7 @@ static struct poptOption long_options[]
90 {"links", 'l', POPT_ARG_VAL, &preserve_links, 1, 0, 0 },
91 {"no-links", 0, POPT_ARG_VAL, &preserve_links, 0, 0, 0 },
92 {"no-l", 0, POPT_ARG_VAL, &preserve_links, 0, 0, 0 },
93+ {"links-depth", 0, POPT_ARG_INT, &follow_links_depth , 0, 0, 0 },
94 {"copy-links", 'L', POPT_ARG_NONE, &copy_links, 0, 0, 0 },
95 {"copy-unsafe-links",0, POPT_ARG_NONE, &copy_unsafe_links, 0, 0, 0 },
96 {"safe-links", 0, POPT_ARG_NONE, &safe_symlinks, 0, 0, 0 },
97--- old/rsync.yo
98+++ new/rsync.yo
99@@ -335,6 +335,7 @@ to the detailed description below for a
100 --append append data onto shorter files
101 -d, --dirs transfer directories without recursing
102 -l, --links copy symlinks as symlinks
103+ --links-depth=NUM follow symlinks up to NUM depth
104 -L, --copy-links transform symlink into referent file/dir
105 --copy-unsafe-links only "unsafe" symlinks are transformed
106 --safe-links ignore symlinks that point outside the tree