Updated to apply cleanly.
[rsync/rsync-patches.git] / compare-dest.diff
CommitLineData
824abc86
WD
1Depends-On-Patch: g2r-basis-filename.diff
2
09add1ae
WD
3This patch allows multiple --compare-dest or --link-dest options to be
4used, making the transfer of some files more optimal. Note that the
5algorithm does NOT search for the best match -- it stops at the first
6match and uses that as the basis file for the transfer, so be sure to
8dd60649
WD
7order your arguments appropriately (the args are searched in the order
8they are suppled).
09add1ae 9
8dd60649
WD
10Before compiling, be sure to run "make proto".
11
a6587818 12--- orig/generator.c 2004-09-20 19:57:58
d2fa0b30 13+++ generator.c 2004-07-30 07:28:13
a6587818 14@@ -45,7 +45,7 @@ extern int io_timeout;
09add1ae
WD
15 extern int protocol_version;
16 extern int always_checksum;
b952a177 17 extern char *partial_dir;
09add1ae
WD
18-extern char *compare_dest;
19+extern char *compare_dest[];
20 extern int link_dest;
21 extern int whole_file;
22 extern int local_server;
a6587818 23@@ -426,11 +426,19 @@ static void recv_generator(char *fname,
09add1ae 24 fnamecmp = fname;
d2fa0b30 25 fnamecmp_type = G2R_FNAME;
09add1ae
WD
26
27- if (statret == -1 && compare_dest != NULL) {
28+ if (statret == -1 && compare_dest[0] != NULL) {
29 /* try the file at compare_dest instead */
09add1ae 30- pathjoin(fnamecmpbuf, sizeof fnamecmpbuf, compare_dest, fname);
b952a177
WD
31- if (link_stat(fnamecmpbuf, &st, 0) == 0
32- && S_ISREG(st.st_mode)) {
b543b4de
WD
33+ int i = 0;
34+ do {
af96621e
WD
35+ pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
36+ compare_dest[i], fname);
b952a177
WD
37+ if (link_stat(fnamecmpbuf, &st, 0) == 0
38+ && S_ISREG(st.st_mode)) {
39+ statret = 0;
40+ break;
09add1ae 41+ }
b543b4de 42+ } while (compare_dest[++i] != NULL);
b952a177
WD
43+ if (statret == 0) {
44 #if HAVE_LINK
45 if (link_dest && !dry_run) {
46 if (do_link(fnamecmpbuf, fname) < 0) {
a6587818 47@@ -441,15 +449,14 @@ static void recv_generator(char *fname,
d2fa0b30
WD
48 safe_fname(fname));
49 }
50 fnamecmp = fnamecmpbuf;
51- fnamecmp_type = 0;
52+ fnamecmp_type = i;
53 }
b952a177
WD
54 } else
55 #endif
d2fa0b30 56 {
b952a177 57 fnamecmp = fnamecmpbuf;
d2fa0b30
WD
58- fnamecmp_type = 0;
59+ fnamecmp_type = i;
60 }
b952a177 61- statret = 0;
d2fa0b30
WD
62 }
63 }
64
2f5fa77e 65--- orig/main.c 2004-07-22 00:10:43
d2fa0b30 66+++ main.c 2004-07-30 07:23:54
d5753a22 67@@ -59,7 +59,7 @@ extern int filesfrom_fd;
495f1899
WD
68 extern pid_t cleanup_child_pid;
69 extern char *files_from;
70 extern char *remote_filesfrom_file;
71-extern char *compare_dest;
72+extern char *compare_dest[];
73 extern char *rsync_path;
74 extern char *shell_cmd;
75 extern char *batch_name;
7de7bd2a 76@@ -463,7 +463,7 @@ static int do_recv(int f_in,int f_out,st
495f1899
WD
77 int pid;
78 int status = 0;
79 int error_pipe[2], name_pipe[2];
c2530f70
WD
80- BOOL need_name_pipe = compare_dest && !dry_run;
81+ BOOL need_name_pipe = compare_dest[0] && !dry_run;
495f1899 82
d5753a22
WD
83 /* The receiving side mustn't obey this, or an existing symlink that
84 * points to an identical file won't be replaced by the referent. */
a6587818 85--- orig/options.c 2004-09-20 05:10:48
9619a6f0 86+++ options.c 2004-08-13 07:55:37
7de7bd2a 87@@ -114,12 +114,13 @@ int write_batch = 0;
b952a177
WD
88 int read_batch = 0;
89 int backup_dir_len = 0;
90 int backup_suffix_len;
91+int num_comp_dest = 0;
92 unsigned int backup_dir_remainder;
09add1ae
WD
93
94 char *backup_suffix = NULL;
95 char *tmpdir = NULL;
b952a177 96 char *partial_dir = NULL;
09add1ae
WD
97-char *compare_dest = NULL;
98+char *compare_dest[MAX_COMP_DEST+1];
09add1ae
WD
99 char *config_file = NULL;
100 char *shell_cmd = NULL;
101 char *log_format = NULL;
7de7bd2a 102@@ -140,6 +141,7 @@ char *batch_name = NULL;
09add1ae
WD
103
104 static int daemon_opt; /* sets am_daemon after option error-reporting */
105 static int modify_window_set;
106+static int saw_compare_dest = 0;
107
108 /** Local address to bind. As a character string because it's
109 * interpreted by the IPv6 layer: should be a numeric IP4 or IP6
7de7bd2a 110@@ -317,7 +319,7 @@ void usage(enum logcode F)
09add1ae
WD
111 }
112
113 enum {OPT_VERSION = 1000, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
114- OPT_DELETE_AFTER, OPT_DELETE_EXCLUDED, OPT_LINK_DEST,
115+ OPT_DELETE_AFTER, OPT_DELETE_EXCLUDED, OPT_COMPARE_DEST, OPT_LINK_DEST,
116 OPT_INCLUDE, OPT_INCLUDE_FROM, OPT_MODIFY_WINDOW,
117 OPT_READ_BATCH, OPT_WRITE_BATCH, OPT_TIMEOUT,
118 OPT_REFUSED_BASE = 9000};
7de7bd2a 119@@ -376,8 +378,8 @@ static struct poptOption long_options[]
09add1ae
WD
120 {"max-delete", 0, POPT_ARG_INT, &max_delete, 0, 0, 0 },
121 {"timeout", 0, POPT_ARG_INT, &io_timeout, OPT_TIMEOUT, 0, 0 },
122 {"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
123- {"compare-dest", 0, POPT_ARG_STRING, &compare_dest, 0, 0, 0 },
124- {"link-dest", 0, POPT_ARG_STRING, &compare_dest, OPT_LINK_DEST, 0, 0 },
125+ {"compare-dest", 0, POPT_ARG_STRING, 0, OPT_COMPARE_DEST, 0, 0 },
126+ {"link-dest", 0, POPT_ARG_STRING, 0, OPT_LINK_DEST, 0, 0 },
127 /* TODO: Should this take an optional int giving the compression level? */
128 {"compress", 'z', POPT_ARG_NONE, &do_compression, 0, 0, 0 },
129 {"daemon", 0, POPT_ARG_NONE, &daemon_opt, 0, 0, 0 },
a6587818 130@@ -605,8 +607,28 @@ int parse_arguments(int *argc, const cha
09add1ae
WD
131 select_timeout = io_timeout;
132 break;
133
134+ case OPT_COMPARE_DEST:
09add1ae
WD
135+ if (num_comp_dest >= MAX_COMP_DEST-1) {
136+ rprintf(FERROR, "ERROR: %s\n", "too many --compare-dest args given");
137+ return 0;
138+ }
139+ arg = poptGetOptArg(pc);
140+ if (sanitize_paths)
2f579ee5 141+ arg = sanitize_path(NULL, arg, NULL, 0);
09add1ae
WD
142+ compare_dest[num_comp_dest++] = (char *)arg;
143+ saw_compare_dest = 1;
144+ break;
09add1ae
WD
145+
146 case OPT_LINK_DEST:
147 #if HAVE_LINK
148+ if (num_comp_dest >= MAX_COMP_DEST-1) {
90bcf59b 149+ rprintf(FERROR, "ERROR: %s\n", "too many --link-dest args given");
09add1ae
WD
150+ return 0;
151+ }
152+ arg = poptGetOptArg(pc);
153+ if (sanitize_paths)
2f579ee5 154+ arg = sanitize_path(NULL, arg, NULL, 0);
09add1ae
WD
155+ compare_dest[num_comp_dest++] = (char *)arg;
156 link_dest = 1;
157 break;
158 #else
a6587818 159@@ -699,6 +721,11 @@ int parse_arguments(int *argc, const cha
d5753a22 160 return 0;
09add1ae
WD
161 }
162
163+ if (saw_compare_dest && link_dest) {
164+ rprintf(FINFO,
165+ "WARNING: promoting --compare-dest options to --link-dest.\n");
166+ }
167+
168 if (archive_mode) {
169 if (!files_from)
170 recurse = 1;
a6587818 171@@ -729,8 +756,6 @@ int parse_arguments(int *argc, const cha
2f579ee5 172 tmpdir = sanitize_path(NULL, tmpdir, NULL, 0);
b952a177 173 if (partial_dir)
2f579ee5 174 partial_dir = sanitize_path(NULL, partial_dir, NULL, 0);
09add1ae 175- if (compare_dest)
2f579ee5 176- compare_dest = sanitize_path(NULL, compare_dest, NULL, 0);
09add1ae 177 if (backup_dir)
2f579ee5 178 backup_dir = sanitize_path(NULL, backup_dir, NULL, 0);
09add1ae 179 if (files_from)
a6587818 180@@ -738,6 +763,7 @@ int parse_arguments(int *argc, const cha
9619a6f0
WD
181 }
182 if (server_exclude_list.head && !am_sender) {
183 struct exclude_list_struct *elp = &server_exclude_list;
184+ int i;
185 if (tmpdir) {
186 clean_fname(tmpdir, 1);
187 if (check_exclude(elp, tmpdir, 1) < 0)
a6587818 188@@ -748,9 +774,9 @@ int parse_arguments(int *argc, const cha
9619a6f0
WD
189 if (check_exclude(elp, partial_dir, 1) < 0)
190 goto options_rejected;
191 }
192- if (compare_dest) {
193- clean_fname(compare_dest, 1);
194- if (check_exclude(elp, compare_dest, 1) < 0)
195+ for (i = 0; i < num_comp_dest; i++) {
196+ clean_fname(compare_dest[i], 1);
197+ if (check_exclude(elp, compare_dest[i], 1) < 0)
198 goto options_rejected;
199 }
200 if (backup_dir) {
a6587818 201@@ -890,8 +916,8 @@ int parse_arguments(int *argc, const cha
09add1ae
WD
202 **/
203 void server_options(char **args,int *argc)
204 {
205+ static char argstr[50+MAX_COMP_DEST*2];
206 int ac = *argc;
207- static char argstr[50];
208 char *arg;
209
210 int i, x;
a6587818 211@@ -1074,13 +1100,16 @@ void server_options(char **args,int *arg
09add1ae
WD
212 args[ac++] = tmpdir;
213 }
214
215- if (compare_dest && am_sender) {
216+ if (compare_dest[0] && am_sender) {
217 /* the server only needs this option if it is not the sender,
218 * and it may be an older version that doesn't know this
219 * option, so don't send it if client is the sender.
220 */
221- args[ac++] = link_dest ? "--link-dest" : "--compare-dest";
222- args[ac++] = compare_dest;
223+ int i;
224+ for (i = 0; i < num_comp_dest; i++) {
225+ args[ac++] = link_dest ? "--link-dest" : "--compare-dest";
226+ args[ac++] = compare_dest[i];
227+ }
228 }
229
230 if (files_from && (!am_sender || remote_filesfrom_file)) {
a6587818 231--- orig/receiver.c 2004-09-07 21:57:20
d2fa0b30 232+++ receiver.c 2004-07-30 07:31:12
d5753a22 233@@ -38,7 +38,7 @@ extern int cvs_exclude;
09add1ae
WD
234 extern int io_error;
235 extern char *tmpdir;
b952a177 236 extern char *partial_dir;
09add1ae 237-extern char *compare_dest;
d2fa0b30 238+extern char *compare_dest[];
09add1ae
WD
239 extern int make_backups;
240 extern int do_progress;
241 extern char *backup_dir;
a6587818 242@@ -438,7 +438,8 @@ int recv_files(int f_in, struct file_lis
d2fa0b30
WD
243 partialptr = partial_dir ? partial_dir_fname(fname) : fname;
244
245 if (f_in_name >= 0) {
246- switch (read_byte(f_in_name)) {
247+ uchar j;
248+ switch (j = read_byte(f_in_name)) {
249 case G2R_FNAME:
250 fnamecmp = fname;
251 break;
a6587818 252@@ -450,7 +451,7 @@ int recv_files(int f_in, struct file_lis
d2fa0b30
WD
253 break;
254 default:
255 pathjoin(fnamecmpbuf, sizeof fnamecmpbuf,
256- compare_dest, fname);
257+ compare_dest[j], fname);
258 fnamecmp = fnamecmpbuf;
259 break;
260 }
a6587818 261--- orig/rsync.h 2004-09-07 21:52:22
d2fa0b30 262+++ rsync.h 2004-07-30 07:23:54
09add1ae
WD
263@@ -98,6 +98,8 @@
264
265 #define MAX_ARGS 1000
266
267+#define MAX_COMP_DEST 20
268+
269 #define MPLEX_BASE 7
270
271 #define NO_EXCLUDES 0