rsync preserving symlinks on mirror

Wayne Davison wayned at samba.org
Thu Jun 3 20:24:30 GMT 2004


On Thu, Jun 03, 2004 at 08:54:24PM +0200, Keld J?rn Simonsen wrote:
> Hmm, I want to keep the symlinks in the original tree. So I think there
> is no way to have both: keeping the original symlinks and having my own
> symlinks are mutually exclusive options. 

Yes, and I apparently got your transfer need backwards in my reply -- the
-L option only works if you have symlinks to dirs on the sender side you
want to have as real dirs on the receiver side, and your need was the
opposite of that.  Sorry for getting off track there.

> I had hoped there was an option to do it, or I could have a new option
> implemented, but I think that is not logically possible.

There is one possible option I thought of.  A special-case that would
allow a symlink to a dir to remain untouched if the sending side was
sending us a dir.  The appended patch implements this as the option -U
(--use-dirlinks).  It only requires the receiving side to support the
option, so you can use it with an older sending rsync.  You may want to
give this a try.

..wayne..
-------------- next part --------------
--- generator.c	18 May 2004 08:50:17 -0000	1.85
+++ generator.c	3 Jun 2004 20:20:49 -0000
@@ -26,6 +26,7 @@
 extern int verbose;
 extern int dry_run;
 extern int relative_paths;
+extern int use_dirlinks;
 extern int preserve_links;
 extern int am_root;
 extern int preserve_devices;
@@ -320,6 +321,11 @@ void recv_generator(char *fname, struct 
 		 * recursively create it. */
 
 		if (dry_run) return; /* XXXX -- might cause inaccuracies?? -- mbp */
+		if (statret == 0 && use_dirlinks && S_ISLNK(st.st_mode)) {
+			STRUCT_STAT st2;
+			if (do_stat(fname, &st2) == 0 && S_ISDIR(st2.st_mode))
+			    st = st2;
+		}
 		if (statret == 0 && !S_ISDIR(st.st_mode)) {
 			if (robust_unlink(fname) != 0) {
 				rsyserr(FERROR, errno,
--- options.c	27 May 2004 21:51:53 -0000	1.153
+++ options.c	3 Jun 2004 20:20:49 -0000
@@ -39,6 +39,7 @@ int whole_file = -1;
 
 int archive_mode = 0;
 int copy_links = 0;
+int use_dirlinks = 0;
 int preserve_links = 0;
 int preserve_hard_links = 0;
 int preserve_perms = 0;
@@ -340,6 +341,7 @@ static struct poptOption long_options[] 
   {"update",          'u', POPT_ARG_NONE,   &update_only, 0, 0, 0 },
   {"links",           'l', POPT_ARG_NONE,   &preserve_links, 0, 0, 0 },
   {"copy-links",      'L', POPT_ARG_NONE,   &copy_links, 0, 0, 0 },
+  {"use-dirlinks",    'U', POPT_ARG_NONE,   &use_dirlinks, 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 },
   {"copy-unsafe-links", 0, POPT_ARG_NONE,   &copy_unsafe_links, 0, 0, 0 },
@@ -818,6 +820,8 @@ void server_options(char **args,int *arg
 		argstr[x++] = 'l';
 	if (copy_links)
 		argstr[x++] = 'L';
+	if (use_dirlinks && am_sender)
+		argstr[x++] = 'U';
 
 	if (whole_file > 0)
 		argstr[x++] = 'W';


More information about the rsync mailing list