1 /* -*- c-file-style: "linux" -*-
3 rsync -- fast file replication program
5 Copyright (C) 1996-2000 by Andrew Tridgell
6 Copyright (C) Paul Mackerras 1996
7 Copyright (C) 2002 by Martin Pool <mbp@samba.org>
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.
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.
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.
28 extern int relative_paths
;
29 extern int preserve_links
;
31 extern int preserve_devices
;
32 extern int preserve_hard_links
;
33 extern int update_only
;
34 extern int opt_ignore_existing
;
35 extern int block_size
;
36 extern int csum_length
;
37 extern int ignore_times
;
39 extern int io_timeout
;
40 extern int remote_version
;
41 extern int always_checksum
;
42 extern int modify_window
;
43 extern char *compare_dest
;
46 /* choose whether to skip a particular file */
47 static int skip_file(char *fname
,
48 struct file_struct
*file
, STRUCT_STAT
*st
)
50 if (st
->st_size
!= file
->length
) {
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
];
60 if (compare_dest
!= NULL
) {
61 if (access(fname
, 0) != 0) {
62 snprintf(fnamecmpdest
,MAXPATHLEN
,"%s/%s",
67 file_checksum(fname
,sum
,st
->st_size
);
68 if (remote_version
< 21) {
69 return (memcmp(sum
,file
->sum
,2) == 0);
71 return (memcmp(sum
,file
->sum
,MD4_SUM_LENGTH
) == 0);
83 return (cmp_modtime(st
->st_mtime
,file
->modtime
) == 0);
87 /* use a larger block size for really big files */
88 static int adapt_block_size(struct file_struct
*file
, int bsize
)
92 if (bsize
!= BLOCK_SIZE
) return bsize
;
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;
103 send a header that says "we have no checksums" down the f_out fd
105 static void send_null_sums(int f_out
)
108 write_int(f_out
, block_size
);
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.
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.}
123 static BOOL
disable_deltas_p(void)
125 extern int whole_file
, no_whole_file
;
126 extern int local_server
;
127 extern int write_batch
;
129 assert(whole_file
== 0 || whole_file
== 1);
131 /* whole_file and no_whole_file are never both on at the same time */
135 else if (no_whole_file
)
137 else if (write_batch
)
145 * Generate and send a stream of signatures/checksums that describe a buffer
147 * Generate approximately one checksum every block_len bytes.
149 static void generate_and_send_sums(struct map_struct
*buf
, OFF_T len
,
150 int block_len
, int f_out
)
153 struct sum_struct sum
;
156 sum
.count
= (len
+ (block_len
- 1)) / block_len
;
157 sum
.remainder
= (len
% block_len
);
160 /* not needed here sum.sums = NULL; */
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
);
168 write_int(f_out
, sum
.count
);
169 write_int(f_out
, sum
.n
);
170 write_int(f_out
, sum
.remainder
);
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
];
178 get_checksum2(map
, n1
, sum2
);
182 "chunk[%d] offset=%.0f len=%d sum1=%08lx\n",
183 i
, (double) offset
, n1
, (unsigned long) sum1
);
185 write_int(f_out
, sum1
);
186 write_buf(f_out
, sum2
, csum_length
);
195 * Acts on file number @p i from @p flist, whose name is @p fname.
197 * First fixes up permissions, then generates checksums for the file.
199 * @note This comment was added later by mbp who was trying to work it
200 * out. It might be wrong.
202 void recv_generator(char *fname
, struct file_list
*flist
, int i
, int f_out
)
206 struct map_struct
*buf
;
208 struct file_struct
*file
= flist
->files
[i
];
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
;
217 if (list_only
) return;
220 rprintf(FINFO
,"recv_generator(%s,%d)\n",fname
,i
);
222 statret
= link_stat(fname
,&st
);
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
);
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
);
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. */
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
));
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
));
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
);
271 if (preserve_links
&& S_ISLNK(file
->mode
)) {
273 char lnk
[MAXPATHLEN
];
275 extern int safe_symlinks
;
277 if (safe_symlinks
&& unsafe_symlink(file
->link
, fname
)) {
279 rprintf(FINFO
,"ignoring unsafe symlink \"%s\" -> \"%s\"\n",
285 l
= readlink(fname
,lnk
,MAXPATHLEN
-1);
288 /* A link already pointing to the
289 * right place -- no further action
291 if (strcmp(lnk
,file
->link
) == 0) {
292 set_perms(fname
,file
,&st
,1);
296 /* Not a symlink, so delete whatever's
297 * already there and put a new symlink
301 if (do_symlink(file
->link
,fname
) != 0) {
302 rprintf(FERROR
,RSYNC_NAME
": symlink \"%s\" -> \"%s\": %s\n",
303 fname
,file
->link
,strerror(errno
));
305 set_perms(fname
,file
,NULL
,0);
307 rprintf(FINFO
,"%s -> %s\n", fname
,file
->link
);
315 if (am_root
&& preserve_devices
&& IS_DEVICE(file
->mode
)) {
317 st
.st_mode
!= file
->mode
||
318 st
.st_rdev
!= file
->rdev
) {
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
));
326 set_perms(fname
,file
,NULL
,0);
328 rprintf(FINFO
,"%s\n",fname
);
331 set_perms(fname
,file
,&st
,1);
337 if (preserve_hard_links
&& check_hard_link(file
)) {
339 rprintf(FINFO
, "recv_generator: \"%s\" is a hard link\n",f_name(file
));
343 if (!S_ISREG(file
->mode
)) {
344 rprintf(FINFO
, "skipping non-regular file \"%s\"\n",fname
);
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
))
360 fnamecmp
= fnamecmpbuf
;
364 if (errno
== ENOENT
) {
366 if (!dry_run
) send_null_sums(f_out
);
369 rprintf(FERROR
, RSYNC_NAME
370 ": recv_generator failed to open \"%s\": %s\n",
371 fname
, strerror(errno
));
376 if (!S_ISREG(st
.st_mode
)) {
377 if (delete_file(fname
) != 0) {
381 /* now pretend the file didn't exist */
383 if (!dry_run
) send_null_sums(f_out
);
387 if (opt_ignore_existing
&& fnamecmp
== fname
) {
389 rprintf(FINFO
,"%s exists\n",fname
);
393 if (update_only
&& cmp_modtime(st
.st_mtime
,file
->modtime
)>0 && fnamecmp
== fname
) {
395 rprintf(FINFO
,"%s is newer\n",fname
);
399 if (skip_file(fname
, file
, &st
)) {
400 if (fnamecmp
== fname
)
401 set_perms(fname
,file
,&st
,1);
410 if (disable_deltas_p()) {
412 send_null_sums(f_out
);
417 fd
= do_open(fnamecmp
, O_RDONLY
, 0);
420 rprintf(FERROR
,RSYNC_NAME
": failed to open \"%s\", continuing : %s\n",fnamecmp
,strerror(errno
));
421 /* pretend the file didn't exist */
423 send_null_sums(f_out
);
427 if (st
.st_size
> 0) {
428 buf
= map_file(fd
,st
.st_size
);
434 rprintf(FINFO
,"gen mapped %s of size %.0f\n",fnamecmp
,(double)st
.st_size
);
437 rprintf(FINFO
, "generating and sending sums for %d\n", i
);
440 generate_and_send_sums(buf
, st
.st_size
,
441 adapt_block_size(file
, block_size
), f_out
);
444 if (buf
) unmap_file(buf
);
449 void generate_files(int f
,struct file_list
*flist
,char *local_name
,int f_recv
)
455 rprintf(FINFO
,"generator starting pid=%d count=%d\n",
456 (int)getpid(),flist
->count
);
461 ? "delta-transmission disabled for local transfer or --whole-file\n"
462 : "delta transmission enabled\n");
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
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;
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? */
484 recv_generator(local_name
?local_name
:f_name(file
),
487 file
->mode
= saved_mode
;
491 csum_length
= SUM_LENGTH
;
495 rprintf(FINFO
,"generate_files phase=%d\n",phase
);
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
),
510 rprintf(FINFO
,"generate_files phase=%d\n",phase
);