Sending --no-whole-file is no good because it will not work with old
[rsync/rsync.git] / generator.c
CommitLineData
ef1aa910 1/* -*- c-file-style: "linux" -*-
91262d5d
MP
2
3 rsync -- fast file replication program
ef1aa910
MP
4
5 Copyright (C) 1996-2000 by Andrew Tridgell
2f03f956 6 Copyright (C) Paul Mackerras 1996
91262d5d 7 Copyright (C) 2002 by Martin Pool <mbp@samba.org>
2f03f956
AT
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22*/
23
24#include "rsync.h"
25
26extern int verbose;
27extern int dry_run;
28extern int relative_paths;
29extern int preserve_links;
30extern int am_root;
31extern int preserve_devices;
32extern int preserve_hard_links;
33extern int update_only;
3d6feada 34extern int opt_ignore_existing;
2f03f956
AT
35extern int whole_file;
36extern int block_size;
37extern int csum_length;
38extern int ignore_times;
f83f0548 39extern int size_only;
2f03f956
AT
40extern int io_timeout;
41extern int remote_version;
42extern int always_checksum;
5b56cc19 43extern int modify_window;
60c8d7bc 44extern char *compare_dest;
2f03f956
AT
45
46
47/* choose whether to skip a particular file */
48static int skip_file(char *fname,
49 struct file_struct *file, STRUCT_STAT *st)
50{
51 if (st->st_size != file->length) {
52 return 0;
53 }
54
55 /* if always checksum is set then we use the checksum instead
56 of the file time to determine whether to sync */
57 if (always_checksum && S_ISREG(st->st_mode)) {
58 char sum[MD4_SUM_LENGTH];
60c8d7bc
DD
59 char fnamecmpdest[MAXPATHLEN];
60
61 if (compare_dest != NULL) {
62 if (access(fname, 0) != 0) {
8950ac03 63 snprintf(fnamecmpdest,MAXPATHLEN,"%s/%s",
60c8d7bc
DD
64 compare_dest,fname);
65 fname = fnamecmpdest;
66 }
67 }
2f03f956 68 file_checksum(fname,sum,st->st_size);
f855a7d0
AT
69 if (remote_version < 21) {
70 return (memcmp(sum,file->sum,2) == 0);
71 } else {
72 return (memcmp(sum,file->sum,MD4_SUM_LENGTH) == 0);
73 }
2f03f956
AT
74 }
75
f83f0548
AT
76 if (size_only) {
77 return 1;
78 }
79
2f03f956
AT
80 if (ignore_times) {
81 return 0;
82 }
83
5b56cc19 84 return (cmp_modtime(st->st_mtime,file->modtime) == 0);
2f03f956
AT
85}
86
87
88/* use a larger block size for really big files */
89static int adapt_block_size(struct file_struct *file, int bsize)
90{
91 int ret;
92
93 if (bsize != BLOCK_SIZE) return bsize;
94
95 ret = file->length / (10000); /* rough heuristic */
96 ret = ret & ~15; /* multiple of 16 */
97 if (ret < bsize) ret = bsize;
98 if (ret > CHUNK_SIZE/2) ret = CHUNK_SIZE/2;
99 return ret;
100}
101
102
103/*
104 send a sums struct down a fd
105 */
1707e0f9 106static void send_sums(struct sum_struct *s, int f_out)
2f03f956 107{
91262d5d
MP
108 if (s) {
109 size_t i;
110
111 /* tell the other guy how many we are going to be
112 doing and how many bytes there are in the last
113 chunk */
114 write_int(f_out, s->count);
115 write_int(f_out, s->n);
116 write_int(f_out, s->remainder);
117
118 for (i = 0; i < s->count; i++) {
119 write_int(f_out, s->sums[i].sum1);
120 write_buf(f_out, s->sums[i].sum2, csum_length);
121 }
122 } else {
123 /* we don't have checksums */
124 write_int(f_out, 0);
125 write_int(f_out, block_size);
126 write_int(f_out, 0);
f855a7d0 127 }
2f03f956
AT
128}
129
2f03f956
AT
130/*
131 generate a stream of signatures/checksums that describe a buffer
132
133 generate approximately one checksum every n bytes
134 */
135static struct sum_struct *generate_sums(struct map_struct *buf,OFF_T len,int n)
136{
137 int i;
138 struct sum_struct *s;
139 int count;
140 int block_len = n;
141 int remainder = (len%block_len);
142 OFF_T offset = 0;
143
144 count = (len+(block_len-1))/block_len;
145
146 s = (struct sum_struct *)malloc(sizeof(*s));
147 if (!s) out_of_memory("generate_sums");
148
149 s->count = count;
150 s->remainder = remainder;
151 s->n = n;
152 s->flength = len;
153
154 if (count==0) {
155 s->sums = NULL;
156 return s;
157 }
158
159 if (verbose > 3)
5f808dfb
AT
160 rprintf(FINFO,"count=%d rem=%d n=%d flength=%.0f\n",
161 s->count,s->remainder,s->n,(double)s->flength);
2f03f956
AT
162
163 s->sums = (struct sum_buf *)malloc(sizeof(s->sums[0])*s->count);
164 if (!s->sums) out_of_memory("generate_sums");
165
166 for (i=0;i<count;i++) {
167 int n1 = MIN(len,n);
168 char *map = map_ptr(buf,offset,n1);
169
170 s->sums[i].sum1 = get_checksum1(map,n1);
171 get_checksum2(map,n1,s->sums[i].sum2);
172
173 s->sums[i].offset = offset;
174 s->sums[i].len = n1;
175 s->sums[i].i = i;
176
177 if (verbose > 3)
5f808dfb
AT
178 rprintf(FINFO,"chunk[%d] offset=%.0f len=%d sum1=%08x\n",
179 i,(double)s->sums[i].offset,s->sums[i].len,s->sums[i].sum1);
2f03f956
AT
180
181 len -= n1;
182 offset += n1;
183 }
184
185 return s;
186}
187
188
ef1aa910
MP
189
190/*
191 * Acts on file number I from FLIST, whose name is fname.
192 *
193 * First fixes up permissions, then generates checksums for the file.
194 *
195 * (This comment was added later by mbp who was trying to work it out;
196 * it might be wrong.)
197 */
2f03f956
AT
198void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
199{
200 int fd;
201 STRUCT_STAT st;
202 struct map_struct *buf;
203 struct sum_struct *s;
204 int statret;
205 struct file_struct *file = flist->files[i];
375a4556
DD
206 char *fnamecmp;
207 char fnamecmpbuf[MAXPATHLEN];
208 extern char *compare_dest;
f7632fc6 209 extern int list_only;
4df9f368 210 extern int preserve_perms;
1347d512 211 extern int only_existing;
f7632fc6
AT
212
213 if (list_only) return;
2f03f956
AT
214
215 if (verbose > 2)
216 rprintf(FINFO,"recv_generator(%s,%d)\n",fname,i);
217
218 statret = link_stat(fname,&st);
63787382 219
1347d512
AT
220 if (only_existing && statret == -1 && errno == ENOENT) {
221 /* we only want to update existing files */
1bbd10fe 222 if (verbose > 1) rprintf(FINFO, "not creating new file \"%s\"\n",fname);
1347d512
AT
223 return;
224 }
225
4df9f368
AT
226 if (statret == 0 &&
227 !preserve_perms &&
228 (S_ISDIR(st.st_mode) == S_ISDIR(file->mode))) {
229 /* if the file exists already and we aren't perserving
230 presmissions then act as though the remote end sent
231 us the file permissions we already have */
7e0ca8e2 232 file->mode = (file->mode & _S_IFMT) | (st.st_mode & ~_S_IFMT);
4df9f368
AT
233 }
234
2f03f956 235 if (S_ISDIR(file->mode)) {
a1b1b1da
MP
236 /* The file to be received is a directory, so we need
237 * to prepare appropriately. If there is already a
238 * file of that name and it is *not* a directory, then
239 * we need to delete it. If it doesn't exist, then
240 * recursively create it. */
241
85d4d142 242 if (dry_run) return; /* XXXX -- might cause inaccuracies?? -- mbp */
2f03f956 243 if (statret == 0 && !S_ISDIR(st.st_mode)) {
c7c11a0d 244 if (robust_unlink(fname) != 0) {
85d4d142
MP
245 rprintf(FERROR, RSYNC_NAME
246 ": recv_generator: unlink \"%s\" to make room for directory: %s\n",
a1b1b1da 247 fname,strerror(errno));
2f03f956
AT
248 return;
249 }
250 statret = -1;
251 }
252 if (statret != 0 && do_mkdir(fname,file->mode) != 0 && errno != EEXIST) {
253 if (!(relative_paths && errno==ENOENT &&
254 create_directory_path(fname)==0 &&
255 do_mkdir(fname,file->mode)==0)) {
85d4d142 256 rprintf(FERROR, RSYNC_NAME ": recv_generator: mkdir \"%s\": %s (2)\n",
2f03f956
AT
257 fname,strerror(errno));
258 }
259 }
de343e3c
DD
260 /* f_out is set to -1 when doing final directory
261 permission and modification time repair */
262 if (set_perms(fname,file,NULL,0) && verbose && (f_out != -1))
2f03f956
AT
263 rprintf(FINFO,"%s/\n",fname);
264 return;
265 }
266
267 if (preserve_links && S_ISLNK(file->mode)) {
268#if SUPPORT_LINKS
269 char lnk[MAXPATHLEN];
270 int l;
271 extern int safe_symlinks;
272
273 if (safe_symlinks && unsafe_symlink(file->link, fname)) {
274 if (verbose) {
1bbd10fe 275 rprintf(FINFO,"ignoring unsafe symlink \"%s\" -> \"%s\"\n",
2f03f956
AT
276 fname,file->link);
277 }
278 return;
279 }
280 if (statret == 0) {
281 l = readlink(fname,lnk,MAXPATHLEN-1);
282 if (l > 0) {
283 lnk[l] = 0;
85d4d142
MP
284 /* A link already pointing to the
285 * right place -- no further action
286 * required. */
7e0ca8e2 287 if (strcmp(lnk,file->link) == 0) {
2f03f956
AT
288 set_perms(fname,file,&st,1);
289 return;
290 }
85d4d142
MP
291 }
292 /* Not a symlink, so delete whatever's
293 * already there and put a new symlink
294 * in place. */
4b3977bf 295 delete_file(fname);
2f03f956 296 }
2f03f956 297 if (do_symlink(file->link,fname) != 0) {
85d4d142 298 rprintf(FERROR,RSYNC_NAME": symlink \"%s\" -> \"%s\": %s\n",
2f03f956
AT
299 fname,file->link,strerror(errno));
300 } else {
301 set_perms(fname,file,NULL,0);
302 if (verbose) {
1bbd10fe 303 rprintf(FINFO,"%s -> %s\n", fname,file->link);
2f03f956
AT
304 }
305 }
306#endif
307 return;
308 }
309
310#ifdef HAVE_MKNOD
311 if (am_root && preserve_devices && IS_DEVICE(file->mode)) {
312 if (statret != 0 ||
313 st.st_mode != file->mode ||
314 st.st_rdev != file->rdev) {
315 delete_file(fname);
316 if (verbose > 2)
317 rprintf(FINFO,"mknod(%s,0%o,0x%x)\n",
318 fname,(int)file->mode,(int)file->rdev);
319 if (do_mknod(fname,file->mode,file->rdev) != 0) {
320 rprintf(FERROR,"mknod %s : %s\n",fname,strerror(errno));
321 } else {
322 set_perms(fname,file,NULL,0);
323 if (verbose)
324 rprintf(FINFO,"%s\n",fname);
325 }
326 } else {
327 set_perms(fname,file,&st,1);
328 }
329 return;
330 }
331#endif
332
333 if (preserve_hard_links && check_hard_link(file)) {
334 if (verbose > 1)
1bbd10fe 335 rprintf(FINFO, "\"%s\" is a hard link\n",f_name(file));
2f03f956
AT
336 return;
337 }
338
339 if (!S_ISREG(file->mode)) {
1bbd10fe 340 rprintf(FINFO, "skipping non-regular file \"%s\"\n",fname);
2f03f956
AT
341 return;
342 }
343
375a4556
DD
344 fnamecmp = fname;
345
346 if ((statret == -1) && (compare_dest != NULL)) {
347 /* try the file at compare_dest instead */
348 int saveerrno = errno;
8950ac03 349 snprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",compare_dest,fname);
375a4556
DD
350 statret = link_stat(fnamecmpbuf,&st);
351 if (!S_ISREG(st.st_mode))
352 statret = -1;
353 if (statret == -1)
354 errno = saveerrno;
355 else
356 fnamecmp = fnamecmpbuf;
357 }
358
2f03f956
AT
359 if (statret == -1) {
360 if (errno == ENOENT) {
361 write_int(f_out,i);
362 if (!dry_run) send_sums(NULL,f_out);
363 } else {
364 if (verbose > 1)
fb47591d
MP
365 rprintf(FERROR, RSYNC_NAME
366 ": recv_generator failed to open \"%s\": %s\n",
367 fname, strerror(errno));
2f03f956
AT
368 }
369 return;
370 }
371
372 if (!S_ISREG(st.st_mode)) {
373 if (delete_file(fname) != 0) {
374 return;
375 }
376
377 /* now pretend the file didn't exist */
378 write_int(f_out,i);
379 if (!dry_run) send_sums(NULL,f_out);
380 return;
381 }
382
3d6feada
MP
383 if (opt_ignore_existing && fnamecmp == fname) {
384 if (verbose > 1)
385 rprintf(FINFO,"%s exists\n",fname);
386 return;
387 }
388
5b56cc19 389 if (update_only && cmp_modtime(st.st_mtime,file->modtime)>0 && fnamecmp == fname) {
2f03f956
AT
390 if (verbose > 1)
391 rprintf(FINFO,"%s is newer\n",fname);
392 return;
393 }
394
395 if (skip_file(fname, file, &st)) {
bd4ed7f7
DD
396 if (fnamecmp == fname)
397 set_perms(fname,file,&st,1);
2f03f956
AT
398 return;
399 }
400
401 if (dry_run) {
402 write_int(f_out,i);
403 return;
404 }
405
1bfbf40b 406 assert(whole_file == 0 || whole_file == 1);
d157de20 407 /* We should have decided by now. */
2f03f956
AT
408 if (whole_file) {
409 write_int(f_out,i);
410 send_sums(NULL,f_out);
411 return;
412 }
413
414 /* open the file */
8c9fd200 415 fd = do_open(fnamecmp, O_RDONLY, 0);
2f03f956
AT
416
417 if (fd == -1) {
85d4d142 418 rprintf(FERROR,RSYNC_NAME": failed to open \"%s\", continuing : %s\n",fnamecmp,strerror(errno));
60be6acf
DD
419 /* pretend the file didn't exist */
420 write_int(f_out,i);
421 send_sums(NULL,f_out);
2f03f956
AT
422 return;
423 }
424
425 if (st.st_size > 0) {
426 buf = map_file(fd,st.st_size);
427 } else {
428 buf = NULL;
429 }
430
431 if (verbose > 3)
5f808dfb 432 rprintf(FINFO,"gen mapped %s of size %.0f\n",fnamecmp,(double)st.st_size);
2f03f956
AT
433
434 s = generate_sums(buf,st.st_size,adapt_block_size(file, block_size));
435
436 if (verbose > 2)
437 rprintf(FINFO,"sending sums for %d\n",i);
438
439 write_int(f_out,i);
440 send_sums(s,f_out);
441
442 close(fd);
443 if (buf) unmap_file(buf);
444
445 free_sums(s);
446}
447
448
449
450void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
451{
452 int i;
453 int phase=0;
454
455 if (verbose > 2)
456 rprintf(FINFO,"generator starting pid=%d count=%d\n",
457 (int)getpid(),flist->count);
458
a57873b7
AT
459 /* we expect to just sit around now, so don't exit on a
460 timeout. If we really get a timeout then the other process should
461 exit */
462 io_timeout = 0;
463
2f03f956
AT
464 for (i = 0; i < flist->count; i++) {
465 struct file_struct *file = flist->files[i];
466 mode_t saved_mode = file->mode;
467 if (!file->basename) continue;
468
469 /* we need to ensure that any directories we create have writeable
470 permissions initially so that we can create the files within
471 them. This is then fixed after the files are transferred */
472 if (!am_root && S_ISDIR(file->mode)) {
473 file->mode |= S_IWUSR; /* user write */
a1b1b1da
MP
474 /* XXX: Could this be causing a problem on SCO? Perhaps their
475 * handling of permissions is strange? */
2f03f956
AT
476 }
477
478 recv_generator(local_name?local_name:f_name(file),
479 flist,i,f);
480
481 file->mode = saved_mode;
482 }
483
484 phase++;
485 csum_length = SUM_LENGTH;
486 ignore_times=1;
487
488 if (verbose > 2)
489 rprintf(FINFO,"generate_files phase=%d\n",phase);
490
491 write_int(f,-1);
492
2f03f956
AT
493 if (remote_version >= 13) {
494 /* in newer versions of the protocol the files can cycle through
495 the system more than once to catch initial checksum errors */
496 for (i=read_int(f_recv); i != -1; i=read_int(f_recv)) {
497 struct file_struct *file = flist->files[i];
498 recv_generator(local_name?local_name:f_name(file),
499 flist,i,f);
500 }
501
502 phase++;
503 if (verbose > 2)
504 rprintf(FINFO,"generate_files phase=%d\n",phase);
505
506 write_int(f,-1);
507 }
508}