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