From: Wayne Davison Date: Fri, 16 Jul 2004 16:43:30 +0000 (+0000) Subject: A proposed --links-depth option. X-Git-Url: https://mattmccutchen.net/rsync/rsync-patches.git/commitdiff_plain/0143ad24b85b7fef602bb952b9a03a9390801701 A proposed --links-depth option. --- diff --git a/links-depth.diff b/links-depth.diff new file mode 100644 index 0000000..f665bcf --- /dev/null +++ b/links-depth.diff @@ -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, ©_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 },