Updated to apply cleanly.
[rsync-patches.git] / links-depth.diff
1 The attached patch gives the user ability to define how many symbolic
2 links rsync should follow before actually adding it to the file list.
3
4 The patch has been heavily modified from its original form to work
5 with the latest codebase, but even in its original form it didn't
6 handle relative symlinks properly, and that has not yet been fixed
7 in this modified version.
8
9 --- orig/flist.c        2005-04-28 15:56:50
10 +++ flist.c     2004-07-16 16:58:04
11 @@ -45,6 +45,7 @@ extern int filesfrom_fd;
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;
19 @@ -734,6 +735,30 @@ static struct file_struct *receive_file_
20  }
21  
22  
23 +#if SUPPORT_LINKS
24 +static int links_depth(char *linkname, STRUCT_STAT *st_ptr)
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
50 @@ -859,7 +884,13 @@ skip_filters:
51         basename_len = strlen(basename) + 1; /* count the '\0' */
52  
53  #ifdef 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
65 --- orig/options.c      2005-05-03 16:47:32
66 +++ options.c   2005-01-28 19:33:24
67 @@ -43,6 +43,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;
75 @@ -276,6 +277,7 @@ void usage(enum logcode F)
76    rprintf(F,"     --inplace               update destination files in-place (SEE MAN PAGE)\n");
77    rprintf(F," -d, --dirs                  transfer directories without recursing\n");
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            transform symlink into referent file/dir\n");
81    rprintf(F,"     --copy-unsafe-links     only \"unsafe\" symlinks are transformed\n");
82    rprintf(F,"     --safe-links            ignore symlinks that point outside the source tree\n");
83 @@ -403,6 +405,7 @@ static struct poptOption long_options[] 
84    {"inplace",          0,  POPT_ARG_NONE,   &inplace, 0, 0, 0 },
85    {"dirs",            'd', POPT_ARG_VAL,    &xfer_dirs, 2, 0, 0 },
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 },
89    {"keep-dirlinks",   'K', POPT_ARG_NONE,   &keep_dirlinks, 0, 0, 0 },
90    {"whole-file",      'W', POPT_ARG_VAL,    &whole_file, 1, 0, 0 },
91 --- orig/rsync.yo       2005-05-03 16:47:33
92 +++ rsync.yo    2005-01-28 19:33:40
93 @@ -319,6 +319,7 @@ to the detailed description below for a 
94       --inplace               update destination files in-place
95   -d, --dirs                  transfer directories without recursing
96   -l, --links                 copy symlinks as symlinks
97 +     --links-depth=NUM       follow symlinks up to NUM depth
98   -L, --copy-links            transform symlink into referent file/dir
99       --copy-unsafe-links     only "unsafe" symlinks are transformed
100       --safe-links            ignore symlinks that point outside the tree