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