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