00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "rsync.h"
00025
00026 extern int verbose;
00027 extern int dry_run;
00028 extern int relative_paths;
00029 extern int preserve_links;
00030 extern int am_root;
00031 extern int preserve_devices;
00032 extern int preserve_hard_links;
00033 extern int update_only;
00034 extern int opt_ignore_existing;
00035 extern int block_size;
00036 extern int csum_length;
00037 extern int ignore_times;
00038 extern int size_only;
00039 extern int io_timeout;
00040 extern int remote_version;
00041 extern int always_checksum;
00042 extern int modify_window;
00043 extern char *compare_dest;
00044
00045
00046
00047 static int skip_file(char *fname,
00048 struct file_struct *file, STRUCT_STAT *st)
00049 {
00050 if (st->st_size != file->length) {
00051 return 0;
00052 }
00053
00054
00055
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 }
00085
00086
00087
00088 static int adapt_block_size(struct file_struct *file, int bsize)
00089 {
00090 int ret;
00091
00092 if (bsize != BLOCK_SIZE) return bsize;
00093
00094 ret = file->length / (10000);
00095 ret = ret & ~15;
00096 if (ret < bsize) ret = bsize;
00097 if (ret > CHUNK_SIZE/2) ret = CHUNK_SIZE/2;
00098 return ret;
00099 }
00100
00101
00102
00103
00104
00105 static void send_sums(struct sum_struct *s, int f_out)
00106 {
00107 if (s) {
00108 size_t i;
00109
00110
00111
00112
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
00123 write_int(f_out, 0);
00124 write_int(f_out, block_size);
00125 write_int(f_out, 0);
00126 }
00127 }
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 static BOOL disable_deltas_p(void)
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
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 }
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 static struct sum_struct *generate_sums(struct map_struct *buf, OFF_T len,
00168 int n)
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 }
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 void recv_generator(char *fname, struct file_list *flist, int i, int f_out)
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
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
00270
00271
00272 file->mode = (file->mode & _S_IFMT) | (st.st_mode & ~_S_IFMT);
00273 }
00274
00275 if (S_ISDIR(file->mode)) {
00276
00277
00278
00279
00280
00281
00282 if (dry_run) return;
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
00301
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
00325
00326
00327 if (strcmp(lnk,file->link) == 0) {
00328 set_perms(fname,file,&st,1);
00329 return;
00330 }
00331 }
00332
00333
00334
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
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
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
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
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 }
00485
00486
00487
00488 void generate_files(int f,struct file_list *flist,char *local_name,int f_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
00505
00506
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
00515
00516
00517 if (!am_root && S_ISDIR(file->mode)) {
00518 file->mode |= S_IWUSR;
00519
00520
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
00540
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 }