Moved one fsync() call.
[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 To 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 @@ -43,6 +43,7 @@ extern int one_file_system;
18  extern int copy_dirlinks;
19  extern int keep_dirlinks;
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 @@ -852,6 +853,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  /**
54   * Create a file_struct for a named file by reading its stat()
55   * information and performing extensive checks against global
56 @@ -994,7 +1019,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_perms = 0;
80  int preserve_executability = 0;
81 @@ -293,6 +294,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 @@ -444,6 +446,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 @@ -314,6 +314,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