Updated to apply cleanly.
[rsync/rsync-patches.git] / append.diff
CommitLineData
2c0d3742
WD
1This patch adds the --append option, which works like a "resume" mode in
2an ftp client, appending new data onto the end of the files it updates.
3
f26fcad4 4--- orig/generator.c 2005-02-27 18:24:42
569f3cc7
WD
5+++ generator.c 2005-02-27 07:51:38
6@@ -51,6 +51,7 @@ extern int remove_sent_files;
2c0d3742
WD
7 extern int update_only;
8 extern int opt_ignore_existing;
9 extern int inplace;
10+extern int append_mode;
11 extern int make_backups;
12 extern int csum_length;
13 extern int ignore_times;
569f3cc7 14@@ -457,35 +458,42 @@ static void generate_and_send_sums(int f
2c0d3742
WD
15 OFF_T offset = 0;
16
17 sum_sizes_sqroot(&sum, len);
18+ write_sum_head(f_out, &sum);
19+
20+ if (append_mode > 0 && f_copy < 0)
21+ return;
22
23 if (len > 0)
24 mapbuf = map_file(fd, len, MAX_MAP_SIZE, sum.blength);
25 else
26 mapbuf = NULL;
27
28- write_sum_head(f_out, &sum);
29-
30 for (i = 0; i < sum.count; i++) {
31 int32 n1 = (int32)MIN(len, (OFF_T)sum.blength);
32 char *map = map_ptr(mapbuf, offset, n1);
33- uint32 sum1 = get_checksum1(map, n1);
34 char sum2[SUM_LENGTH];
35+ uint32 sum1;
36+
37+ len -= n1;
38+ offset += n1;
39
40- if (f_copy >= 0)
41+ if (f_copy >= 0) {
42 full_write(f_copy, map, n1);
43+ if (append_mode > 0)
44+ continue;
45+ }
46
47+ sum1 = get_checksum1(map, n1);
48 get_checksum2(map, n1, sum2);
49
50 if (verbose > 3) {
51 rprintf(FINFO,
52 "chunk[%.0f] offset=%.0f len=%ld sum1=%08lx\n",
53- (double)i, (double)offset, (long)n1,
54+ (double)i, (double)offset - n1, (long)n1,
55 (unsigned long)sum1);
56 }
57 write_int(f_out, sum1);
58 write_buf(f_out, sum2, sum.s2length);
59- len -= n1;
60- offset += n1;
61 }
62
63 if (mapbuf)
569f3cc7 64@@ -925,6 +933,9 @@ static void recv_generator(char *fname,
2c0d3742
WD
65 return;
66 }
67
68+ if (append_mode && st.st_size > file->length)
69+ return;
70+
71 if (!compare_dest && fnamecmp_type <= FNAMECMP_BASIS_DIR_HIGH)
72 ;
45f1b149 73 else if (fnamecmp_type == FNAMECMP_FUZZY)
569f3cc7 74@@ -951,7 +962,7 @@ prepare_to_open:
2c0d3742
WD
75
76 if (dry_run || read_batch)
77 goto notify_others;
78- if (whole_file > 0) {
79+ if (whole_file > 0 && !append_mode) {
45f1b149
WD
80 if (statret == 0)
81 statret = 1;
2c0d3742 82 goto notify_others;
f26fcad4 83@@ -1147,6 +1158,8 @@ void generate_files(int f_out, struct fi
2c0d3742
WD
84 only_existing = max_size = opt_ignore_existing = 0;
85 update_only = always_checksum = size_only = 0;
569f3cc7 86 ignore_times = 1;
2c0d3742
WD
87+ if (append_mode) /* resend w/o append mode */
88+ append_mode = -1; /* ... but only longer files */
569f3cc7 89 make_backups = 0; /* avoid a duplicate backup for inplace processing */
2c0d3742 90
569f3cc7 91 /* We expect to just sit around now, so don't exit on a timeout.
45f1b149 92--- orig/match.c 2005-02-15 19:27:04
2c0d3742
WD
93+++ match.c 2005-02-11 20:26:31
94@@ -23,6 +23,7 @@ extern int verbose;
95 extern int am_server;
96 extern int do_progress;
97 extern int checksum_seed;
98+extern int append_mode;
99
100 int updating_basis_file;
101
45f1b149 102@@ -334,6 +335,21 @@ void match_sums(int f, struct sum_struct
2c0d3742
WD
103
104 sum_init(checksum_seed);
105
106+ if (append_mode) {
107+ OFF_T j = 0;
108+ for (j = CHUNK_SIZE; j < s->flength; j += CHUNK_SIZE) {
109+ sum_update(map_ptr(buf, last_match, CHUNK_SIZE),
110+ CHUNK_SIZE);
111+ last_match = j;
112+ }
113+ if (last_match < s->flength) {
114+ int32 len = s->flength - last_match;
115+ sum_update(map_ptr(buf, last_match, len), len);
116+ last_match = s->flength;
117+ }
118+ s->count = 0;
119+ }
120+
121 if (len > 0 && s->count > 0) {
122 build_hash_table(s);
123
45f1b149 124@@ -347,7 +363,7 @@ void match_sums(int f, struct sum_struct
2c0d3742
WD
125 } else {
126 OFF_T j;
127 /* by doing this in pieces we avoid too many seeks */
128- for (j = CHUNK_SIZE; j < len; j += CHUNK_SIZE)
129+ for (j = last_match + CHUNK_SIZE; j < len; j += CHUNK_SIZE)
130 matched(f, s, buf, j, -2);
131 matched(f, s, buf, len, -1);
132 }
a2f30171 133--- orig/options.c 2005-03-01 05:49:24
4e75164f 134+++ options.c 2005-02-16 15:36:40
2c0d3742
WD
135@@ -39,6 +39,7 @@ int make_backups = 0;
136 **/
137 int whole_file = -1;
138
139+int append_mode = 0;
140 int archive_mode = 0;
141 int keep_dirlinks = 0;
142 int copy_links = 0;
569f3cc7 143@@ -163,6 +164,7 @@ static int F_option_cnt = 0;
2c0d3742 144 static int modify_window_set;
efd0f7d1 145 static int refused_delete, refused_archive_part;
4e75164f
WD
146 static int refused_partial, refused_progress, refused_delete_before;
147+static int refused_inplace;
2c0d3742
WD
148 static char *dest_option = NULL;
149 static char *max_size_arg;
150 static char partialdir_for_delayupdate[] = ".~tmp~";
569f3cc7 151@@ -272,6 +274,7 @@ void usage(enum logcode F)
2c0d3742
WD
152 rprintf(F," --suffix=SUFFIX set backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX);
153 rprintf(F," -u, --update skip files that are newer on the receiver\n");
154 rprintf(F," --inplace update destination files in-place (SEE MAN PAGE)\n");
155+ rprintf(F," --append append data onto shorter files\n");
156 rprintf(F," -d, --dirs transfer directories without recursing\n");
157 rprintf(F," -l, --links copy symlinks as symlinks\n");
158 rprintf(F," -L, --copy-links transform symlink into referent file/dir\n");
569f3cc7 159@@ -398,6 +401,7 @@ static struct poptOption long_options[]
2c0d3742
WD
160 {"links", 'l', POPT_ARG_NONE, &preserve_links, 0, 0, 0 },
161 {"copy-links", 'L', POPT_ARG_NONE, &copy_links, 0, 0, 0 },
162 {"keep-dirlinks", 'K', POPT_ARG_NONE, &keep_dirlinks, 0, 0, 0 },
163+ {"append", 0, POPT_ARG_VAL, &append_mode, 1, 0, 0 },
164 {"whole-file", 'W', POPT_ARG_VAL, &whole_file, 1, 0, 0 },
165 {"no-whole-file", 0, POPT_ARG_VAL, &whole_file, 0, 0, 0 },
45f1b149 166 {"copy-unsafe-links",0, POPT_ARG_NONE, &copy_unsafe_links, 0, 0, 0 },
569f3cc7 167@@ -571,6 +575,8 @@ static void set_refuse_options(char *bp)
2c0d3742
WD
168 refused_partial = op->val;
169 else if (wildmatch("progress", op->longName))
170 refused_progress = op->val;
171+ else if (wildmatch("inplace", op->longName))
172+ refused_inplace = op->val;
173 break;
174 }
175 if (!is_wild)
a2f30171 176@@ -1105,6 +1111,14 @@ int parse_arguments(int *argc, const cha
2c0d3742
WD
177 bwlimit_writemax = 512;
178 }
179
180+ if (append_mode) {
181+ if (refused_inplace) {
182+ create_refuse_error(refused_inplace);
183+ return 0;
184+ }
185+ inplace = 1;
186+ }
187+
188 if (delay_updates && !partial_dir)
189 partial_dir = partialdir_for_delayupdate;
190
a2f30171 191@@ -1415,7 +1429,9 @@ void server_options(char **args,int *arg
2c0d3742
WD
192 if (opt_ignore_existing && am_sender)
193 args[ac++] = "--ignore-existing";
194
195- if (inplace)
196+ if (append_mode)
197+ args[ac++] = "--append";
198+ else if (inplace)
199 args[ac++] = "--inplace";
200
201 if (tmpdir) {
569f3cc7 202--- orig/receiver.c 2005-02-26 19:27:54
2c0d3742 203+++ receiver.c 2005-02-11 20:26:32
569f3cc7 204@@ -44,6 +44,7 @@ extern int remove_sent_files;
2c0d3742
WD
205 extern int module_id;
206 extern int ignore_errors;
207 extern int orig_umask;
208+extern int append_mode;
209 extern int keep_partial;
210 extern int checksum_seed;
211 extern int inplace;
569f3cc7 212@@ -210,6 +211,28 @@ static int receive_data(int f_in, char *
2c0d3742
WD
213
214 sum_init(checksum_seed);
215
216+ if (append_mode) {
217+ OFF_T j;
218+ sum.flength = (OFF_T)sum.count * sum.blength;
219+ if (sum.remainder)
220+ sum.flength -= sum.blength - sum.remainder;
221+ for (j = CHUNK_SIZE; j < sum.flength; j += CHUNK_SIZE) {
222+ sum_update(map_ptr(mapbuf, offset, CHUNK_SIZE),
223+ CHUNK_SIZE);
224+ offset = j;
225+ }
226+ if (offset < sum.flength) {
227+ int32 len = sum.flength - offset;
228+ sum_update(map_ptr(mapbuf, offset, len), len);
229+ offset = sum.flength;
230+ }
231+ if (fd != -1 && do_lseek(fd, offset, SEEK_SET) != offset) {
232+ rsyserr(FERROR, errno, "lseek failed on %s",
233+ full_fname(fname));
234+ exit_cleanup(RERR_FILEIO);
235+ }
236+ }
237+
238 while ((i = recv_token(f_in, &data)) != 0) {
239 if (do_progress)
240 show_progress(offset, total_size);
569f3cc7 241@@ -399,6 +422,7 @@ int recv_files(int f_in, struct file_lis
2c0d3742
WD
242 send_msg(MSG_DONE, "", 0);
243 if (keep_partial && !partial_dir)
244 make_backups = 0; /* prevents double backup */
245+ append_mode = 0;
246 continue;
247 }
248
a2f30171 249--- orig/rsync.yo 2005-03-01 01:22:59
2c0d3742
WD
250+++ rsync.yo 2005-02-11 20:36:38
251@@ -309,6 +309,7 @@ to the detailed description below for a
252 --suffix=SUFFIX backup suffix (default ~ w/o --backup-dir)
253 -u, --update skip files that are newer on the receiver
254 --inplace update destination files in-place
255+ --append append data onto shorter files
256 -d, --dirs transfer directories without recursing
257 -l, --links copy symlinks as symlinks
258 -L, --copy-links transform symlink into referent file/dir
dc8e4919 259@@ -564,6 +565,14 @@ should not use this option to update fil
2c0d3742
WD
260 rsync will be unable to update a file in-place that is not writable by the
261 receiving user.
262
263+dit(bf(--append)) This causes rsync to update a file by appending data onto
264+the end of the file, which presumes that the data that already exists on
265+the receiving side is identical with the start of the file on the sending
266+side. If that is not true, the file will fail the checksum check, and a
267+normal bf(--inplace) update will correct the mismatch. Any file on the
268+receiving side that is longer than a file on the sending side is skipped.
269+Implies bf(--inplace).
270+
271 dit(bf(-d, --dirs)) Tell the sending side to include any directories that
272 are encountered. Unlike bf(--recursive), a directory's contents are not copied
273 unless the directory was specified on the command-line as either "." or a
569f3cc7 274--- orig/sender.c 2005-02-26 03:22:59
1d15f8d9
WD
275+++ sender.c 2005-02-20 00:17:01
276@@ -28,6 +28,7 @@ extern int log_format_has_i;
277 extern int daemon_log_format_has_i;
278 extern int csum_length;
279 extern int io_error;
2c0d3742 280+extern int append_mode;
1d15f8d9 281 extern int protocol_version;
699c8be0 282 extern int remove_sent_files;
1d15f8d9 283 extern int updating_basis_file;
699c8be0 284@@ -67,6 +68,13 @@ static struct sum_struct *receive_sums(i
2c0d3742
WD
285 (double)s->count, (long)s->blength, (long)s->remainder);
286 }
287
288+ if (append_mode) {
289+ s->flength = (OFF_T)s->count * s->blength;
290+ if (s->remainder)
291+ s->flength -= s->blength - s->remainder;
292+ return s;
293+ }
294+
295 if (s->count == 0)
296 return(s);
297
699c8be0 298@@ -161,6 +169,7 @@ void send_files(struct file_list *flist,
2c0d3742
WD
299 /* For inplace: redo phase turns off the backup
300 * flag so that we do a regular inplace send. */
301 make_backups = 0;
302+ append_mode = 0;
303 continue;
304 }
305 break;