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

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
-- 
To unsubscribe or change options: http://lists.samba.org/mailman/listinfo/rsync
Before posting, read: http://www.catb.org/~esr/faqs/smart-questions.html

Reply via email to