A proposed --links-depth option.
authorWayne Davison <wayned@samba.org>
Fri, 16 Jul 2004 16:43:30 +0000 (16:43 +0000)
committerWayne Davison <wayned@samba.org>
Fri, 16 Jul 2004 16:43:30 +0000 (16:43 +0000)
links-depth.diff [new file with mode: 0644]

diff --git a/links-depth.diff b/links-depth.diff
new file mode 100644 (file)
index 0000000..f665bcf
--- /dev/null
@@ -0,0 +1,90 @@
+The attached patch gives the user ability to define how many symbolic
+links rsync should follow before actually adding it to the file list.
+
+The patch has been heavily modified from its original form to work
+with the latest codebase, but even in its original form it didn't
+handle relative symlinks properly, and that has not yet been fixed
+in this modified version.
+
+--- orig/flist.c       2004-07-15 02:21:10
++++ flist.c    2004-07-16 16:38:35
+@@ -49,6 +49,7 @@ extern int filesfrom_fd;
+ extern int one_file_system;
+ extern int keep_dirlinks;
+ extern int preserve_links;
++extern int follow_links_depth;
+ extern int preserve_hard_links;
+ extern int preserve_perms;
+ extern int preserve_devices;
+@@ -722,6 +723,30 @@ void receive_file_entry(struct file_stru
+ }
++#if SUPPORT_LINKS
++void links_depth(char *linkname, STRUCT_STAT *st_ptr)
++{
++      char buf[MAXPATHLEN];
++      STRUCT_STAT st;
++      int i;
++
++      for (i = 0; i < follow_links_depth; i++) {
++              /* XXX This doesn't handle relative symlinks! */
++              if (readlink_stat(linkname, &st, buf) != 0)
++                      break;
++              *st_ptr = st;
++              if (!S_ISLNK(st.st_mode))
++                      return 1;
++              strlcpy(linkname, buf, MAXPATHLEN);
++#if 0
++              fprintf(stderr, "\n%s:%i [#%i] %s -> %s\n", __FILE__, __LINE__, i, file->u.link, linkname);
++#endif
++      }
++
++      return 0;
++}
++#endif
++
+ /**
+  * Create a file_struct for a named file by reading its stat()
+  * information and performing extensive checks against global
+@@ -841,7 +866,13 @@ skip_excludes:
+       basename_len = strlen(basename) + 1; /* count the '\0' */
+ #if SUPPORT_LINKS
+-      linkname_len = S_ISLNK(st.st_mode) ? strlen(linkname) + 1 : 0;
++      if (S_ISLNK(st.st_mode)) {
++              if (follow_links_depth && links_depth(linkname, &st))
++                      linkname_len = 0;
++              else
++                      linkname_len = strlen(linkname) + 1;
++      } else
++              linkname_len = 0;
+ #else
+       linkname_len = 0;
+ #endif
+--- orig/options.c     2004-07-15 19:11:33
++++ options.c  2004-07-16 16:12:29
+@@ -42,6 +42,7 @@ int archive_mode = 0;
+ int keep_dirlinks = 0;
+ int copy_links = 0;
+ int preserve_links = 0;
++int follow_links_depth = 0;
+ int preserve_hard_links = 0;
+ int preserve_perms = 0;
+ int preserve_devices = 0;
+@@ -235,6 +236,7 @@ void usage(enum logcode F)
+   rprintf(F," -u, --update                update only (don't overwrite newer files)\n");
+   rprintf(F," -K, --keep-dirlinks         treat symlinked dir on receiver as dir\n");
+   rprintf(F," -l, --links                 copy symlinks as symlinks\n");
++  rprintf(F,"     --links-depth=NUM       follow symlinks up to NUM depth\n");
+   rprintf(F," -L, --copy-links            copy the referent of all symlinks\n");
+   rprintf(F,"     --copy-unsafe-links     copy the referent of \"unsafe\" symlinks\n");
+   rprintf(F,"     --safe-links            ignore \"unsafe\" symlinks\n");
+@@ -342,6 +344,7 @@ static struct poptOption long_options[] 
+   {"update",          'u', POPT_ARG_NONE,   &update_only, 0, 0, 0 },
+   {"keep-dirlinks",   'K', POPT_ARG_NONE,   &keep_dirlinks, 0, 0, 0 },
+   {"links",           'l', POPT_ARG_NONE,   &preserve_links, 0, 0, 0 },
++  {"links-depth",      0,  POPT_ARG_INT,    &follow_links_depth , 0, 0, 0 },
+   {"copy-links",      'L', POPT_ARG_NONE,   &copy_links, 0, 0, 0 },
+   {"whole-file",      'W', POPT_ARG_VAL,    &whole_file, 1, 0, 0 },
+   {"no-whole-file",    0,  POPT_ARG_VAL,    &whole_file, 0, 0, 0 },