Go to the source code of this file.
Functions | |
int | skip_file (char *fname, struct file_struct *file, STRUCT_STAT *st) |
int | adapt_block_size (struct file_struct *file, int bsize) |
void | send_sums (struct sum_struct *s, int f_out) |
BOOL | disable_deltas_p (void) |
Perhaps we want to just send an empty checksum set for this file, which will force the whole thing to be literally transferred. More... | |
sum_struct * | generate_sums (struct map_struct *buf, OFF_T len, int n) |
Generate a stream of signatures/checksums that describe a buffer. More... | |
void | recv_generator (char *fname, struct file_list *flist, int i, int f_out) |
Acts on file number i from flist , whose name is fname . More... | |
void | generate_files (int f, struct file_list *flist, char *local_name, int f_recv) |
Variables | |
int | verbose |
int | dry_run |
int | relative_paths |
int | preserve_links |
int | am_root |
int | preserve_devices |
int | preserve_hard_links |
int | update_only |
int | opt_ignore_existing |
int | block_size |
int | csum_length |
int | ignore_times |
int | size_only |
int | io_timeout |
int | remote_version |
int | always_checksum |
int | modify_window = 0 |
char * | compare_dest |
|
Definition at line 47 of file generator.c. References always_checksum, cmp_modtime(), compare_dest, file_checksum(), file_struct::length, file_struct::modtime, remote_version, snprintf(), and file_struct::sum. Referenced by recv_generator().
00049 { 00050 if (st->st_size != file->length) { 00051 return 0; 00052 } 00053 00054 /* if always checksum is set then we use the checksum instead 00055 of the file time to determine whether to sync */ 00056 if (always_checksum && S_ISREG(st->st_mode)) { 00057 char sum[MD4_SUM_LENGTH]; 00058 char fnamecmpdest[MAXPATHLEN]; 00059 00060 if (compare_dest != NULL) { 00061 if (access(fname, 0) != 0) { 00062 snprintf(fnamecmpdest,MAXPATHLEN,"%s/%s", 00063 compare_dest,fname); 00064 fname = fnamecmpdest; 00065 } 00066 } 00067 file_checksum(fname,sum,st->st_size); 00068 if (remote_version < 21) { 00069 return (memcmp(sum,file->sum,2) == 0); 00070 } else { 00071 return (memcmp(sum,file->sum,MD4_SUM_LENGTH) == 0); 00072 } 00073 } 00074 00075 if (size_only) { 00076 return 1; 00077 } 00078 00079 if (ignore_times) { 00080 return 0; 00081 } 00082 00083 return (cmp_modtime(st->st_mtime,file->modtime) == 0); 00084 } |
|
Definition at line 88 of file generator.c. References file_struct::length. Referenced by recv_generator().
00089 { 00090 int ret; 00091 00092 if (bsize != BLOCK_SIZE) return bsize; 00093 00094 ret = file->length / (10000); /* rough heuristic */ 00095 ret = ret & ~15; /* multiple of 16 */ 00096 if (ret < bsize) ret = bsize; 00097 if (ret > CHUNK_SIZE/2) ret = CHUNK_SIZE/2; 00098 return ret; 00099 } |
|
Definition at line 105 of file generator.c. References block_size, sum_struct::count, csum_length, sum_struct::n, sum_struct::remainder, sum_buf::sum1, sum_buf::sum2, sum_struct::sums, write_buf(), and write_int(). Referenced by recv_generator().
00106 { 00107 if (s) { 00108 size_t i; 00109 00110 /* tell the other guy how many we are going to be 00111 doing and how many bytes there are in the last 00112 chunk */ 00113 write_int(f_out, s->count); 00114 write_int(f_out, s->n); 00115 write_int(f_out, s->remainder); 00116 00117 for (i = 0; i < s->count; i++) { 00118 write_int(f_out, s->sums[i].sum1); 00119 write_buf(f_out, s->sums[i].sum2, csum_length); 00120 } 00121 } else { 00122 /* we don't have checksums */ 00123 write_int(f_out, 0); 00124 write_int(f_out, block_size); 00125 write_int(f_out, 0); 00126 } 00127 } |
|
Perhaps we want to just send an empty checksum set for this file, which will force the whole thing to be literally transferred. When do we do this? If the user's explicitly said they want the whole thing, or if { they haven't explicitly requested a delta, and it's local but not batch mode.} Whew. Definition at line 139 of file generator.c. References local_server, no_whole_file, and whole_file. Referenced by generate_files(), and recv_generator().
00140 { 00141 extern int whole_file, no_whole_file; 00142 extern int local_server; 00143 extern int write_batch; 00144 00145 assert(whole_file == 0 || whole_file == 1); 00146 00147 /* whole_file and no_whole_file are never both on at the same time */ 00148 00149 if (whole_file) 00150 return True; 00151 else if (no_whole_file) 00152 return False; 00153 else if (write_batch) 00154 return False; 00155 else 00156 return local_server; 00157 } |
|
Generate a stream of signatures/checksums that describe a buffer.
Generate approximately one checksum every
Definition at line 167 of file generator.c. References sum_struct::count, FINFO, sum_struct::flength, get_checksum1(), get_checksum2(), sum_buf::i, sum_buf::len, map_ptr(), sum_struct::n, sum_buf::offset, out_of_memory(), sum_struct::remainder, rprintf(), sum_buf::sum1, sum_buf::sum2, sum_struct::sums, and verbose. Referenced by recv_generator().
00169 { 00170 int i; 00171 struct sum_struct *s; 00172 int count; 00173 int block_len = n; 00174 int remainder = (len % block_len); 00175 OFF_T offset = 0; 00176 00177 count = (len + (block_len - 1)) / block_len; 00178 00179 s = (struct sum_struct *) malloc(sizeof(*s)); 00180 if (!s) 00181 out_of_memory("generate_sums"); 00182 00183 s->count = count; 00184 s->remainder = remainder; 00185 s->n = n; 00186 s->flength = len; 00187 00188 if (count == 0) { 00189 s->sums = NULL; 00190 return s; 00191 } 00192 00193 if (verbose > 3) { 00194 rprintf(FINFO, "count=%ld rem=%ld n=%ld flength=%.0f\n", 00195 (long) s->count, (long) s->remainder, 00196 (long) s->n, (double) s->flength); 00197 } 00198 00199 s->sums = (struct sum_buf *) malloc(sizeof(s->sums[0]) * s->count); 00200 if (!s->sums) 00201 out_of_memory("generate_sums"); 00202 00203 for (i = 0; i < count; i++) { 00204 int n1 = MIN(len, n); 00205 char *map = map_ptr(buf, offset, n1); 00206 00207 s->sums[i].sum1 = get_checksum1(map, n1); 00208 get_checksum2(map, n1, s->sums[i].sum2); 00209 00210 s->sums[i].offset = offset; 00211 s->sums[i].len = n1; 00212 s->sums[i].i = i; 00213 00214 if (verbose > 3) 00215 rprintf(FINFO, 00216 "chunk[%d] offset=%.0f len=%d sum1=%08x\n", 00217 i, (double) s->sums[i].offset, 00218 s->sums[i].len, s->sums[i].sum1); 00219 00220 len -= n1; 00221 offset += n1; 00222 } 00223 00224 return s; 00225 } |
|
Acts on file number First fixes up permissions, then generates checksums for the file.
Definition at line 237 of file generator.c. References adapt_block_size(), am_root, block_size, check_hard_link(), cmp_modtime(), compare_dest, create_directory_path(), delete_file(), disable_deltas_p(), do_mkdir(), do_mknod(), do_open(), do_symlink(), dry_run, f_name(), FERROR, file_list::files, FINFO, free_sums(), generate_sums(), file_struct::link, link_stat(), map_file(), file_struct::mode, file_struct::modtime, only_existing, opt_ignore_existing, orig_umask, preserve_devices, preserve_hard_links, preserve_links, file_struct::rdev, relative_paths, robust_unlink(), rprintf(), safe_symlinks, send_sums(), set_perms(), skip_file(), snprintf(), unmap_file(), unsafe_symlink(), update_only, verbose, and write_int(). Referenced by generate_files(), and recv_files().
00238 { 00239 int fd; 00240 STRUCT_STAT st; 00241 struct map_struct *buf; 00242 struct sum_struct *s; 00243 int statret; 00244 struct file_struct *file = flist->files[i]; 00245 char *fnamecmp; 00246 char fnamecmpbuf[MAXPATHLEN]; 00247 extern char *compare_dest; 00248 extern int list_only; 00249 extern int preserve_perms; 00250 extern int only_existing; 00251 extern int orig_umask; 00252 00253 if (list_only) return; 00254 00255 if (verbose > 2) 00256 rprintf(FINFO,"recv_generator(%s,%d)\n",fname,i); 00257 00258 statret = link_stat(fname,&st); 00259 00260 if (only_existing && statret == -1 && errno == ENOENT) { 00261 /* we only want to update existing files */ 00262 if (verbose > 1) rprintf(FINFO, "not creating new file \"%s\"\n",fname); 00263 return; 00264 } 00265 00266 if (statret == 0 && 00267 !preserve_perms && 00268 (S_ISDIR(st.st_mode) == S_ISDIR(file->mode))) { 00269 /* if the file exists already and we aren't perserving 00270 presmissions then act as though the remote end sent 00271 us the file permissions we already have */ 00272 file->mode = (file->mode & _S_IFMT) | (st.st_mode & ~_S_IFMT); 00273 } 00274 00275 if (S_ISDIR(file->mode)) { 00276 /* The file to be received is a directory, so we need 00277 * to prepare appropriately. If there is already a 00278 * file of that name and it is *not* a directory, then 00279 * we need to delete it. If it doesn't exist, then 00280 * recursively create it. */ 00281 00282 if (dry_run) return; /* XXXX -- might cause inaccuracies?? -- mbp */ 00283 if (statret == 0 && !S_ISDIR(st.st_mode)) { 00284 if (robust_unlink(fname) != 0) { 00285 rprintf(FERROR, RSYNC_NAME 00286 ": recv_generator: unlink \"%s\" to make room for directory: %s\n", 00287 fname,strerror(errno)); 00288 return; 00289 } 00290 statret = -1; 00291 } 00292 if (statret != 0 && do_mkdir(fname,file->mode) != 0 && errno != EEXIST) { 00293 if (!(relative_paths && errno==ENOENT && 00294 create_directory_path(fname, orig_umask)==0 && 00295 do_mkdir(fname,file->mode)==0)) { 00296 rprintf(FERROR, RSYNC_NAME ": recv_generator: mkdir \"%s\": %s (2)\n", 00297 fname,strerror(errno)); 00298 } 00299 } 00300 /* f_out is set to -1 when doing final directory 00301 permission and modification time repair */ 00302 if (set_perms(fname,file,NULL,0) && verbose && (f_out != -1)) 00303 rprintf(FINFO,"%s/\n",fname); 00304 return; 00305 } 00306 00307 if (preserve_links && S_ISLNK(file->mode)) { 00308 #if SUPPORT_LINKS 00309 char lnk[MAXPATHLEN]; 00310 int l; 00311 extern int safe_symlinks; 00312 00313 if (safe_symlinks && unsafe_symlink(file->link, fname)) { 00314 if (verbose) { 00315 rprintf(FINFO,"ignoring unsafe symlink \"%s\" -> \"%s\"\n", 00316 fname,file->link); 00317 } 00318 return; 00319 } 00320 if (statret == 0) { 00321 l = readlink(fname,lnk,MAXPATHLEN-1); 00322 if (l > 0) { 00323 lnk[l] = 0; 00324 /* A link already pointing to the 00325 * right place -- no further action 00326 * required. */ 00327 if (strcmp(lnk,file->link) == 0) { 00328 set_perms(fname,file,&st,1); 00329 return; 00330 } 00331 } 00332 /* Not a symlink, so delete whatever's 00333 * already there and put a new symlink 00334 * in place. */ 00335 delete_file(fname); 00336 } 00337 if (do_symlink(file->link,fname) != 0) { 00338 rprintf(FERROR,RSYNC_NAME": symlink \"%s\" -> \"%s\": %s\n", 00339 fname,file->link,strerror(errno)); 00340 } else { 00341 set_perms(fname,file,NULL,0); 00342 if (verbose) { 00343 rprintf(FINFO,"%s -> %s\n", fname,file->link); 00344 } 00345 } 00346 #endif 00347 return; 00348 } 00349 00350 #ifdef HAVE_MKNOD 00351 if (am_root && preserve_devices && IS_DEVICE(file->mode)) { 00352 if (statret != 0 || 00353 st.st_mode != file->mode || 00354 st.st_rdev != file->rdev) { 00355 delete_file(fname); 00356 if (verbose > 2) 00357 rprintf(FINFO,"mknod(%s,0%o,0x%x)\n", 00358 fname,(int)file->mode,(int)file->rdev); 00359 if (do_mknod(fname,file->mode,file->rdev) != 0) { 00360 rprintf(FERROR,"mknod %s : %s\n",fname,strerror(errno)); 00361 } else { 00362 set_perms(fname,file,NULL,0); 00363 if (verbose) 00364 rprintf(FINFO,"%s\n",fname); 00365 } 00366 } else { 00367 set_perms(fname,file,&st,1); 00368 } 00369 return; 00370 } 00371 #endif 00372 00373 if (preserve_hard_links && check_hard_link(file)) { 00374 if (verbose > 1) 00375 rprintf(FINFO, "recv_generator: \"%s\" is a hard link\n",f_name(file)); 00376 return; 00377 } 00378 00379 if (!S_ISREG(file->mode)) { 00380 rprintf(FINFO, "skipping non-regular file \"%s\"\n",fname); 00381 return; 00382 } 00383 00384 fnamecmp = fname; 00385 00386 if ((statret == -1) && (compare_dest != NULL)) { 00387 /* try the file at compare_dest instead */ 00388 int saveerrno = errno; 00389 snprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",compare_dest,fname); 00390 statret = link_stat(fnamecmpbuf,&st); 00391 if (!S_ISREG(st.st_mode)) 00392 statret = -1; 00393 if (statret == -1) 00394 errno = saveerrno; 00395 else 00396 fnamecmp = fnamecmpbuf; 00397 } 00398 00399 if (statret == -1) { 00400 if (errno == ENOENT) { 00401 write_int(f_out,i); 00402 if (!dry_run) send_sums(NULL,f_out); 00403 } else { 00404 if (verbose > 1) 00405 rprintf(FERROR, RSYNC_NAME 00406 ": recv_generator failed to open \"%s\": %s\n", 00407 fname, strerror(errno)); 00408 } 00409 return; 00410 } 00411 00412 if (!S_ISREG(st.st_mode)) { 00413 if (delete_file(fname) != 0) { 00414 return; 00415 } 00416 00417 /* now pretend the file didn't exist */ 00418 write_int(f_out,i); 00419 if (!dry_run) send_sums(NULL,f_out); 00420 return; 00421 } 00422 00423 if (opt_ignore_existing && fnamecmp == fname) { 00424 if (verbose > 1) 00425 rprintf(FINFO,"%s exists\n",fname); 00426 return; 00427 } 00428 00429 if (update_only && cmp_modtime(st.st_mtime,file->modtime)>0 && fnamecmp == fname) { 00430 if (verbose > 1) 00431 rprintf(FINFO,"%s is newer\n",fname); 00432 return; 00433 } 00434 00435 if (skip_file(fname, file, &st)) { 00436 if (fnamecmp == fname) 00437 set_perms(fname,file,&st,1); 00438 return; 00439 } 00440 00441 if (dry_run) { 00442 write_int(f_out,i); 00443 return; 00444 } 00445 00446 if (disable_deltas_p()) { 00447 write_int(f_out,i); 00448 send_sums(NULL,f_out); 00449 return; 00450 } 00451 00452 /* open the file */ 00453 fd = do_open(fnamecmp, O_RDONLY, 0); 00454 00455 if (fd == -1) { 00456 rprintf(FERROR,RSYNC_NAME": failed to open \"%s\", continuing : %s\n",fnamecmp,strerror(errno)); 00457 /* pretend the file didn't exist */ 00458 write_int(f_out,i); 00459 send_sums(NULL,f_out); 00460 return; 00461 } 00462 00463 if (st.st_size > 0) { 00464 buf = map_file(fd,st.st_size); 00465 } else { 00466 buf = NULL; 00467 } 00468 00469 if (verbose > 3) 00470 rprintf(FINFO,"gen mapped %s of size %.0f\n",fnamecmp,(double)st.st_size); 00471 00472 s = generate_sums(buf,st.st_size,adapt_block_size(file, block_size)); 00473 00474 if (verbose > 2) 00475 rprintf(FINFO,"sending sums for %d\n",i); 00476 00477 write_int(f_out,i); 00478 send_sums(s,f_out); 00479 00480 close(fd); 00481 if (buf) unmap_file(buf); 00482 00483 free_sums(s); 00484 } |
|
Definition at line 488 of file generator.c. References am_root, file_struct::basename, file_list::count, csum_length, disable_deltas_p(), file_list::files, FINFO, ignore_times, io_timeout, file_struct::mode, read_int(), recv_generator(), remote_version, rprintf(), verbose, and write_int(). Referenced by do_recv().
00489 { 00490 int i; 00491 int phase=0; 00492 00493 if (verbose > 2) 00494 rprintf(FINFO,"generator starting pid=%d count=%d\n", 00495 (int)getpid(),flist->count); 00496 00497 if (verbose >= 2) { 00498 rprintf(FINFO, 00499 disable_deltas_p() 00500 ? "delta-transmission disabled for local transfer or --whole-file\n" 00501 : "delta transmission enabled\n"); 00502 } 00503 00504 /* we expect to just sit around now, so don't exit on a 00505 timeout. If we really get a timeout then the other process should 00506 exit */ 00507 io_timeout = 0; 00508 00509 for (i = 0; i < flist->count; i++) { 00510 struct file_struct *file = flist->files[i]; 00511 mode_t saved_mode = file->mode; 00512 if (!file->basename) continue; 00513 00514 /* we need to ensure that any directories we create have writeable 00515 permissions initially so that we can create the files within 00516 them. This is then fixed after the files are transferred */ 00517 if (!am_root && S_ISDIR(file->mode)) { 00518 file->mode |= S_IWUSR; /* user write */ 00519 /* XXX: Could this be causing a problem on SCO? Perhaps their 00520 * handling of permissions is strange? */ 00521 } 00522 00523 recv_generator(local_name?local_name:f_name(file), 00524 flist,i,f); 00525 00526 file->mode = saved_mode; 00527 } 00528 00529 phase++; 00530 csum_length = SUM_LENGTH; 00531 ignore_times=1; 00532 00533 if (verbose > 2) 00534 rprintf(FINFO,"generate_files phase=%d\n",phase); 00535 00536 write_int(f,-1); 00537 00538 if (remote_version >= 13) { 00539 /* in newer versions of the protocol the files can cycle through 00540 the system more than once to catch initial checksum errors */ 00541 for (i=read_int(f_recv); i != -1; i=read_int(f_recv)) { 00542 struct file_struct *file = flist->files[i]; 00543 recv_generator(local_name?local_name:f_name(file), 00544 flist,i,f); 00545 } 00546 00547 phase++; 00548 if (verbose > 2) 00549 rprintf(FINFO,"generate_files phase=%d\n",phase); 00550 00551 write_int(f,-1); 00552 } 00553 } |
|
Definition at line 26 of file generator.c. Referenced by generate_files(), generate_sums(), and recv_generator(). |
|
Definition at line 27 of file generator.c. Referenced by recv_generator(). |
|
Definition at line 28 of file generator.c. Referenced by recv_generator(). |
|
Definition at line 29 of file generator.c. Referenced by parse_arguments(), and recv_generator(). |
|
Definition at line 30 of file generator.c. Referenced by generate_files(), and recv_generator(). |
|
Definition at line 31 of file generator.c. Referenced by parse_arguments(), and recv_generator(). |
|
Definition at line 32 of file generator.c. Referenced by recv_generator(). |
|
Definition at line 33 of file generator.c. Referenced by recv_generator(). |
|
Definition at line 34 of file generator.c. Referenced by recv_generator(), and server_options(). |
|
Definition at line 35 of file generator.c. Referenced by recv_generator(), send_sums(), and server_options(). |
|
Definition at line 36 of file generator.c. Referenced by generate_files(), and send_sums(). |
|
Definition at line 37 of file generator.c. Referenced by generate_files(). |
|
Definition at line 38 of file generator.c. |
|
Definition at line 39 of file generator.c. Referenced by generate_files(). |
|
Definition at line 40 of file generator.c. Referenced by generate_files(), and skip_file(). |
|
Definition at line 41 of file generator.c. Referenced by skip_file(). |
|
Definition at line 86 of file options.c. Referenced by server_options(), and usage(). |
|
Definition at line 43 of file generator.c. Referenced by recv_generator(), and skip_file(). |