Multiple compare-dest args

Vidar Madsen vidar at prosalg.no
Thu Apr 15 10:04:09 GMT 2004


Hi all.

I have just finished a small patch that adds support for multiple
--compare-dest or --link-dest args. Its primary usage is to do incremental
backups on top of eachother. (My current backup system stores each
incremental as a single diff of the latest full.) 

Example:

  First full backup:
  rsync -a somedir full-20040415/

  First incremental:
  rsync -a --compare-dest=../full-20040415 \
        somedir incr-20040416/

  Second incremental, on top of first:
  rsync -a --compare-dest=../incr-20040416 --compare-dest=../full-20040415
        somedir incr-20040417/

The args must be given in the correct order; Latest incremental first,
last resort last.

It scratches my itch, at least. Perhaps it can be of use to others as
well. :)

Vidar

-------------- next part --------------
diff -ru rsync-2.6.1pre-1/generator.c rsync-2.6.1pre-1-vidar/generator.c
--- rsync-2.6.1pre-1/generator.c	2004-03-07 21:29:59.000000000 +0100
+++ rsync-2.6.1pre-1-vidar/generator.c	2004-04-15 11:23:17.000000000 +0200
@@ -41,7 +41,7 @@
 extern int io_timeout;
 extern int protocol_version;
 extern int always_checksum;
-extern char *compare_dest;
+extern char *compare_dest[];
 extern int link_dest;
 
 
@@ -69,13 +69,13 @@
 	if (always_checksum && S_ISREG(st->st_mode)) {
 		char sum[MD4_SUM_LENGTH];
 		char fnamecmpdest[MAXPATHLEN];
+		int i = 0;
 
-		if (compare_dest != NULL) {
-			if (access(fname, 0) != 0) {
-				pathjoin(fnamecmpdest, sizeof fnamecmpdest,
-					 compare_dest, fname);
-				fname = fnamecmpdest;
-			}
+		while ((access(fname, 0) != 0) && compare_dest[i] != NULL) {
+			pathjoin(fnamecmpdest, sizeof fnamecmpdest,
+					compare_dest[i], fname);
+			fname = fnamecmpdest;
+			i++;
 		}
 		file_checksum(fname,sum,st->st_size);
 		return memcmp(sum, file->u.sum, protocol_version < 21 ? 2
@@ -270,7 +270,7 @@
 	int statret;
 	char *fnamecmp;
 	char fnamecmpbuf[MAXPATHLEN];
-	extern char *compare_dest;
+	extern char *compare_dest[];
 	extern int list_only;
 	extern int only_existing;
 	extern int orig_umask;
@@ -408,11 +408,15 @@
 
 	fnamecmp = fname;
 
-	if (statret == -1 && compare_dest != NULL) {
+	if (statret == -1 && compare_dest[0] != NULL) {
 		/* try the file at compare_dest instead */
 		int saveerrno = errno;
-		pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, compare_dest, fname);
-		statret = link_stat(fnamecmpbuf,&st);
+		int i = 0;
+		while (statret == -1 && compare_dest[i] != NULL) {
+			pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, compare_dest[i], fname);
+			statret = link_stat(fnamecmpbuf,&st);
+			i++;
+		}
 		if (!S_ISREG(st.st_mode))
 			statret = -1;
 		if (statret == -1)
Only in rsync-2.6.1pre-1-vidar/lib: dummy
diff -ru rsync-2.6.1pre-1/options.c rsync-2.6.1pre-1-vidar/options.c
--- rsync-2.6.1pre-1/options.c	2004-02-22 09:56:43.000000000 +0100
+++ rsync-2.6.1pre-1-vidar/options.c	2004-04-15 11:29:35.000000000 +0200
@@ -112,7 +112,8 @@
 
 char *backup_suffix = NULL;
 char *tmpdir = NULL;
-char *compare_dest = NULL;
+char *compare_dest[MAX_COMP_DEST+1];
+int num_comp_dest = 0;
 char *config_file = NULL;
 char *shell_cmd = NULL;
 char *log_format = NULL;
@@ -301,7 +302,7 @@
 }
 
 enum {OPT_VERSION = 1000, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
-      OPT_DELETE_AFTER, OPT_DELETE_EXCLUDED, OPT_LINK_DEST,
+      OPT_DELETE_AFTER, OPT_DELETE_EXCLUDED, OPT_COMPARE_DEST, OPT_LINK_DEST,
       OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW,
       OPT_READ_BATCH, OPT_WRITE_BATCH,
       OPT_REFUSED_BASE = 9000};
@@ -358,7 +359,7 @@
   {"max-delete",       0,  POPT_ARG_INT,    &max_delete, 0, 0, 0 },
   {"timeout",          0,  POPT_ARG_INT,    &io_timeout, 0, 0, 0 },
   {"temp-dir",        'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
-  {"compare-dest",     0,  POPT_ARG_STRING, &compare_dest, 0, 0, 0 },
+  {"compare-dest",     0,  POPT_ARG_STRING, 0,				OPT_COMPARE_DEST, 0, 0 },
   {"link-dest",        0,  POPT_ARG_STRING, 0,              OPT_LINK_DEST, 0, 0 },
   /* TODO: Should this take an optional int giving the compression level? */
   {"compress",        'z', POPT_ARG_NONE,   &do_compression, 0, 0, 0 },
@@ -564,9 +565,31 @@
 			checksum_seed = FIXED_CHECKSUM_SEED;
 			break;
 
+		case OPT_COMPARE_DEST:
+#if HAVE_LINK
+			if (num_comp_dest >= MAX_COMP_DEST-1) {
+				rprintf(FERROR, "ERROR: %s\n", "too many --compare-dest args given");
+				return 0;
+			}
+			compare_dest[num_comp_dest] = (char *)poptGetOptArg(pc);
+			num_comp_dest++;
+			break;
+#else
+			snprintf(err_buf, sizeof err_buf,
+				 "hard links are not supported on this %s\n",
+				 am_server ? "server" : "client");
+			rprintf(FERROR, "ERROR: %s", err_buf);
+			return 0;
+#endif
+
 		case OPT_LINK_DEST:
 #if HAVE_LINK
-			compare_dest = (char *)poptGetOptArg(pc);
+			if (num_comp_dest >= MAX_COMP_DEST-1) {
+				rprintf(FERROR, "ERROR: %s\n", "too many --compare-dest args given");
+				return 0;
+			}
+			compare_dest[num_comp_dest] = (char *)poptGetOptArg(pc);
+			num_comp_dest++;
 			link_dest = 1;
 			break;
 #else
@@ -925,13 +948,16 @@
 		args[ac++] = tmpdir;
 	}
 
-	if (compare_dest && am_sender) {
+	if (compare_dest[0] && am_sender) {
 		/* the server only needs this option if it is not the sender,
 		 *   and it may be an older version that doesn't know this
 		 *   option, so don't send it if client is the sender.
 		 */
-		args[ac++] = link_dest ? "--link-dest" : "--compare-dest";
-		args[ac++] = compare_dest;
+		int i;
+		for (i = 0; i < num_comp_dest; i++) {
+			args[ac++] = link_dest ? "--link-dest" : "--compare-dest";
+			args[ac++] = compare_dest[i];
+		}
 	}
 
 	if (files_from && (!am_sender || remote_filesfrom_file)) {
Only in rsync-2.6.1pre-1-vidar: options.c~
Only in rsync-2.6.1pre-1-vidar/popt: dummy
diff -ru rsync-2.6.1pre-1/receiver.c rsync-2.6.1pre-1-vidar/receiver.c
--- rsync-2.6.1pre-1/receiver.c	2004-03-23 17:50:40.000000000 +0100
+++ rsync-2.6.1pre-1-vidar/receiver.c	2004-04-15 11:07:43.000000000 +0200
@@ -35,7 +35,7 @@
 extern int cvs_exclude;
 extern int io_error;
 extern char *tmpdir;
-extern char *compare_dest;
+extern char *compare_dest[];
 extern int make_backups;
 extern int do_progress;
 extern char *backup_dir;
@@ -295,7 +295,7 @@
 	char *fnamecmp;
 	char fnamecmpbuf[MAXPATHLEN];
 	struct map_struct *mapbuf;
-	int i;
+	int i, j;
 	struct file_struct *file;
 	int phase=0;
 	int recv_ok;
@@ -361,12 +361,14 @@
 		/* open the file */
 		fd1 = do_open(fnamecmp, O_RDONLY, 0);
 
-		if (fd1 == -1 && compare_dest != NULL) {
+		j = 0;
+		while (fd1 == -1 && compare_dest[j] != NULL) {
 			/* try the file at compare_dest instead */
 			pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
-				 compare_dest, fname);
+				 compare_dest[j], fname);
 			fnamecmp = fnamecmpbuf;
 			fd1 = do_open(fnamecmp, O_RDONLY, 0);
+			j++;
 		}
 
 		if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
diff -ru rsync-2.6.1pre-1/rsync.h rsync-2.6.1pre-1-vidar/rsync.h
--- rsync-2.6.1pre-1/rsync.h	2004-03-06 08:43:55.000000000 +0100
+++ rsync-2.6.1pre-1-vidar/rsync.h	2004-04-15 11:42:33.000000000 +0200
@@ -97,6 +97,8 @@
 
 #define MAX_ARGS 1000
 
+#define MAX_COMP_DEST 20
+
 #define MPLEX_BASE 7
 
 #define NO_EXCLUDES	0
Only in rsync-2.6.1pre-1-vidar: rsync.h~
Only in rsync-2.6.1pre-1-vidar/zlib: dummy


More information about the rsync mailing list