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 whole_file;
36 extern int block_size;
37 extern int csum_length;
38 extern int ignore_times;
40 extern int io_timeout;
41 extern int remote_version;
42 extern int always_checksum;
43 extern int modify_window;
44 extern char *compare_dest;
47 /* choose whether to skip a particular file */
48 static int skip_file(char *fname,
49 struct file_struct *file, STRUCT_STAT *st)
51 if (st->st_size != file->length) {
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];
59 char fnamecmpdest[MAXPATHLEN];
61 if (compare_dest != NULL) {
62 if (access(fname, 0) != 0) {
63 snprintf(fnamecmpdest,MAXPATHLEN,"%s/%s",
68 file_checksum(fname,sum,st->st_size);
69 if (remote_version < 21) {
70 return (memcmp(sum,file->sum,2) == 0);
72 return (memcmp(sum,file->sum,MD4_SUM_LENGTH) == 0);
84 return (cmp_modtime(st->st_mtime,file->modtime) == 0);
88 /* use a larger block size for really big files */
89 static int adapt_block_size(struct file_struct *file, int bsize)
93 if (bsize != BLOCK_SIZE) return bsize;
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;
104 send a sums struct down a fd
106 static void send_sums(struct sum_struct *s, int f_out)
111 /* tell the other guy how many we are going to be
112 doing and how many bytes there are in the last
114 write_int(f_out, s->count);
115 write_int(f_out, s->n);
116 write_int(f_out, s->remainder);
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);
123 /* we don't have checksums */
125 write_int(f_out, block_size);
131 generate a stream of signatures/checksums that describe a buffer
133 generate approximately one checksum every n bytes
135 static struct sum_struct *generate_sums(struct map_struct *buf,OFF_T len,int n)
138 struct sum_struct *s;
141 int remainder = (len%block_len);
144 count = (len+(block_len-1))/block_len;
146 s = (struct sum_struct *)malloc(sizeof(*s));
147 if (!s) out_of_memory("generate_sums");
150 s->remainder = remainder;
160 rprintf(FINFO,"count=%d rem=%d n=%d flength=%.0f\n",
161 s->count,s->remainder,s->n,(double)s->flength);
163 s->sums = (struct sum_buf *)malloc(sizeof(s->sums[0])*s->count);
164 if (!s->sums) out_of_memory("generate_sums");
166 for (i=0;i<count;i++) {
168 char *map = map_ptr(buf,offset,n1);
170 s->sums[i].sum1 = get_checksum1(map,n1);
171 get_checksum2(map,n1,s->sums[i].sum2);
173 s->sums[i].offset = offset;
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);
191 * Acts on file number I from FLIST, whose name is fname.
193 * First fixes up permissions, then generates checksums for the file.
195 * (This comment was added later by mbp who was trying to work it out;
196 * it might be wrong.)
198 void recv_generator(char *fname,struct file_list *flist,int i,int f_out)
202 struct map_struct *buf;
203 struct sum_struct *s;
205 struct file_struct *file = flist->files[i];
207 char fnamecmpbuf[MAXPATHLEN];
208 extern char *compare_dest;
209 extern int list_only;
210 extern int preserve_perms;
211 extern int only_existing;
213 if (list_only) return;
216 rprintf(FINFO,"recv_generator(%s,%d)\n",fname,i);
218 statret = link_stat(fname,&st);
220 if (only_existing && statret == -1 && errno == ENOENT) {
221 /* we only want to update existing files */
222 if (verbose > 1) rprintf(FINFO, "not creating new file \"%s\"\n",fname);
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 */
232 file->mode = (file->mode & _S_IFMT) | (st.st_mode & ~_S_IFMT);
235 if (S_ISDIR(file->mode)) {
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. */
242 if (dry_run) return; /* XXXX -- might cause inaccuracies?? -- mbp */
243 if (statret == 0 && !S_ISDIR(st.st_mode)) {
244 if (robust_unlink(fname) != 0) {
245 rprintf(FERROR, RSYNC_NAME
246 ": recv_generator: unlink \"%s\" to make room for directory: %s\n",
247 fname,strerror(errno));
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)) {
256 rprintf(FERROR, RSYNC_NAME ": recv_generator: mkdir \"%s\": %s (2)\n",
257 fname,strerror(errno));
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))
263 rprintf(FINFO,"%s/\n",fname);
267 if (preserve_links && S_ISLNK(file->mode)) {
269 char lnk[MAXPATHLEN];
271 extern int safe_symlinks;
273 if (safe_symlinks && unsafe_symlink(file->link, fname)) {
275 rprintf(FINFO,"ignoring unsafe symlink \"%s\" -> \"%s\"\n",
281 l = readlink(fname,lnk,MAXPATHLEN-1);
284 /* A link already pointing to the
285 * right place -- no further action
287 if (strcmp(lnk,file->link) == 0) {
288 set_perms(fname,file,&st,1);
292 /* Not a symlink, so delete whatever's
293 * already there and put a new symlink
297 if (do_symlink(file->link,fname) != 0) {
298 rprintf(FERROR,RSYNC_NAME": symlink \"%s\" -> \"%s\": %s\n",
299 fname,file->link,strerror(errno));
301 set_perms(fname,file,NULL,0);
303 rprintf(FINFO,"%s -> %s\n", fname,file->link);
311 if (am_root && preserve_devices && IS_DEVICE(file->mode)) {
313 st.st_mode != file->mode ||
314 st.st_rdev != file->rdev) {
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));
322 set_perms(fname,file,NULL,0);
324 rprintf(FINFO,"%s\n",fname);
327 set_perms(fname,file,&st,1);
333 if (preserve_hard_links && check_hard_link(file)) {
335 rprintf(FINFO, "\"%s\" is a hard link\n",f_name(file));
339 if (!S_ISREG(file->mode)) {
340 rprintf(FINFO, "skipping non-regular file \"%s\"\n",fname);
346 if ((statret == -1) && (compare_dest != NULL)) {
347 /* try the file at compare_dest instead */
348 int saveerrno = errno;
349 snprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",compare_dest,fname);
350 statret = link_stat(fnamecmpbuf,&st);
351 if (!S_ISREG(st.st_mode))
356 fnamecmp = fnamecmpbuf;
360 if (errno == ENOENT) {
362 if (!dry_run) send_sums(NULL,f_out);
365 rprintf(FERROR, RSYNC_NAME
366 ": recv_generator failed to open \"%s\": %s\n",
367 fname, strerror(errno));
372 if (!S_ISREG(st.st_mode)) {
373 if (delete_file(fname) != 0) {
377 /* now pretend the file didn't exist */
379 if (!dry_run) send_sums(NULL,f_out);
383 if (opt_ignore_existing && fnamecmp == fname) {
385 rprintf(FINFO,"%s exists\n",fname);
389 if (update_only && cmp_modtime(st.st_mtime,file->modtime)>0 && fnamecmp == fname) {
391 rprintf(FINFO,"%s is newer\n",fname);
395 if (skip_file(fname, file, &st)) {
396 if (fnamecmp == fname)
397 set_perms(fname,file,&st,1);
408 send_sums(NULL,f_out);
413 fd = do_open(fnamecmp, O_RDONLY, 0);
416 rprintf(FERROR,RSYNC_NAME": failed to open \"%s\", continuing : %s\n",fnamecmp,strerror(errno));
417 /* pretend the file didn't exist */
419 send_sums(NULL,f_out);
423 if (st.st_size > 0) {
424 buf = map_file(fd,st.st_size);
430 rprintf(FINFO,"gen mapped %s of size %.0f\n",fnamecmp,(double)st.st_size);
432 s = generate_sums(buf,st.st_size,adapt_block_size(file, block_size));
435 rprintf(FINFO,"sending sums for %d\n",i);
441 if (buf) unmap_file(buf);
448 void generate_files(int f,struct file_list *flist,char *local_name,int f_recv)
454 rprintf(FINFO,"generator starting pid=%d count=%d\n",
455 (int)getpid(),flist->count);
457 /* we expect to just sit around now, so don't exit on a
458 timeout. If we really get a timeout then the other process should
462 for (i = 0; i < flist->count; i++) {
463 struct file_struct *file = flist->files[i];
464 mode_t saved_mode = file->mode;
465 if (!file->basename) continue;
467 /* we need to ensure that any directories we create have writeable
468 permissions initially so that we can create the files within
469 them. This is then fixed after the files are transferred */
470 if (!am_root && S_ISDIR(file->mode)) {
471 file->mode |= S_IWUSR; /* user write */
472 /* XXX: Could this be causing a problem on SCO? Perhaps their
473 * handling of permissions is strange? */
476 recv_generator(local_name?local_name:f_name(file),
479 file->mode = saved_mode;
483 csum_length = SUM_LENGTH;
487 rprintf(FINFO,"generate_files phase=%d\n",phase);
491 if (remote_version >= 13) {
492 /* in newer versions of the protocol the files can cycle through
493 the system more than once to catch initial checksum errors */
494 for (i=read_int(f_recv); i != -1; i=read_int(f_recv)) {
495 struct file_struct *file = flist->files[i];
496 recv_generator(local_name?local_name:f_name(file),
502 rprintf(FINFO,"generate_files phase=%d\n",phase);