00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "rsync.h"
00022
00023 extern int verbose;
00024 extern int recurse;
00025 extern int delete_mode;
00026 extern int remote_version;
00027 extern int csum_length;
00028 extern struct stats stats;
00029 extern int dry_run;
00030 extern int am_server;
00031 extern int relative_paths;
00032 extern int preserve_hard_links;
00033 extern int cvs_exclude;
00034 extern int io_error;
00035 extern char *tmpdir;
00036 extern char *compare_dest;
00037 extern int make_backups;
00038 extern char *backup_suffix;
00039
00040 static struct delete_list {
00041 DEV64_T dev;
00042 INO64_T inode;
00043 } *delete_list;
00044 static int dlist_len, dlist_alloc_len;
00045
00046
00047
00048
00049
00050 static int delete_already_done(struct file_list *flist,int j)
00051 {
00052 int i;
00053 STRUCT_STAT st;
00054
00055 if (link_stat(f_name(flist->files[j]), &st)) return 1;
00056
00057 for (i=0;i<dlist_len;i++) {
00058 if (st.st_ino == delete_list[i].inode &&
00059 st.st_dev == delete_list[i].dev)
00060 return 1;
00061 }
00062
00063 return 0;
00064 }
00065
00066 static void add_delete_entry(struct file_struct *file)
00067 {
00068 if (dlist_len == dlist_alloc_len) {
00069 dlist_alloc_len += 1024;
00070 delete_list = (struct delete_list *)Realloc(delete_list, sizeof(delete_list[0])*dlist_alloc_len);
00071 if (!delete_list) out_of_memory("add_delete_entry");
00072 }
00073
00074 delete_list[dlist_len].dev = file->dev;
00075 delete_list[dlist_len].inode = file->inode;
00076 dlist_len++;
00077
00078 if (verbose > 3)
00079 rprintf(FINFO,"added %s to delete list\n", f_name(file));
00080 }
00081
00082 static void delete_one(struct file_struct *f)
00083 {
00084 if (!S_ISDIR(f->mode)) {
00085 if (robust_unlink(f_name(f)) != 0) {
00086 rprintf(FERROR,"delete_one: unlink %s: %s\n",f_name(f),strerror(errno));
00087 } else if (verbose) {
00088 rprintf(FINFO,"deleting %s\n",f_name(f));
00089 }
00090 } else {
00091 if (do_rmdir(f_name(f)) != 0) {
00092 if (errno != ENOTEMPTY && errno != EEXIST)
00093 rprintf(FERROR,"delete_one: rmdir %s: %s\n",
00094 f_name(f), strerror(errno));
00095 } else if (verbose) {
00096 rprintf(FINFO,"deleting directory %s\n",f_name(f));
00097 }
00098 }
00099 }
00100
00101
00102
00103
00104
00105
00106
00107 void delete_files(struct file_list *flist)
00108 {
00109 struct file_list *local_file_list;
00110 int i, j;
00111 char *name;
00112 extern int module_id;
00113 extern int ignore_errors;
00114 extern int max_delete;
00115 static int deletion_count;
00116
00117 if (cvs_exclude)
00118 add_cvs_excludes();
00119
00120 if (io_error && !(lp_ignore_errors(module_id) || ignore_errors)) {
00121 rprintf(FINFO,"IO error encountered - skipping file deletion\n");
00122 return;
00123 }
00124
00125 for (j=0;j<flist->count;j++) {
00126 if (!S_ISDIR(flist->files[j]->mode) ||
00127 !(flist->files[j]->flags & FLAG_DELETE)) continue;
00128
00129 if (remote_version < 19 &&
00130 delete_already_done(flist, j)) continue;
00131
00132 name = strdup(f_name(flist->files[j]));
00133
00134 if (!(local_file_list = send_file_list(-1,1,&name))) {
00135 free(name);
00136 continue;
00137 }
00138
00139 if (verbose > 1)
00140 rprintf(FINFO,"deleting in %s\n", name);
00141
00142 for (i=local_file_list->count-1;i>=0;i--) {
00143 if (max_delete && deletion_count > max_delete) break;
00144 if (!local_file_list->files[i]->basename) continue;
00145 if (remote_version < 19 &&
00146 S_ISDIR(local_file_list->files[i]->mode))
00147 add_delete_entry(local_file_list->files[i]);
00148 if (-1 == flist_find(flist,local_file_list->files[i])) {
00149 char *f = f_name(local_file_list->files[i]);
00150 int k = strlen(f) - strlen(backup_suffix);
00151
00152 if (make_backups && ((k <= 0) ||
00153 (strcmp(f+k,backup_suffix) != 0))) {
00154 (void) make_backup(f);
00155 } else {
00156 deletion_count++;
00157 delete_one(local_file_list->files[i]);
00158 }
00159 }
00160 }
00161 flist_free(local_file_list);
00162 free(name);
00163 }
00164 }
00165
00166
00167 static int get_tmpname(char *fnametmp, char *fname)
00168 {
00169 char *f;
00170
00171
00172 if (tmpdir) {
00173 f = strrchr(fname,'/');
00174 if (f == NULL)
00175 f = fname;
00176 else
00177 f++;
00178 if (strlen(tmpdir)+strlen(f)+10 > MAXPATHLEN) {
00179 rprintf(FERROR,"filename too long\n");
00180 return 0;
00181 }
00182 snprintf(fnametmp,MAXPATHLEN, "%s/.%s.XXXXXX",tmpdir,f);
00183 return 1;
00184 }
00185
00186 f = strrchr(fname,'/');
00187
00188 if (strlen(fname)+9 > MAXPATHLEN) {
00189 rprintf(FERROR,"filename too long\n");
00190 return 0;
00191 }
00192
00193 if (f) {
00194 *f = 0;
00195 snprintf(fnametmp,MAXPATHLEN,"%s/.%s.XXXXXX",
00196 fname,f+1);
00197 *f = '/';
00198 } else {
00199 snprintf(fnametmp,MAXPATHLEN,".%s.XXXXXX",fname);
00200 }
00201
00202 return 1;
00203 }
00204
00205
00206 static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname,
00207 OFF_T total_size)
00208 {
00209 int i;
00210 unsigned int n,remainder,len,count;
00211 OFF_T offset = 0;
00212 OFF_T offset2;
00213 char *data;
00214 static char file_sum1[MD4_SUM_LENGTH];
00215 static char file_sum2[MD4_SUM_LENGTH];
00216 char *map=NULL;
00217
00218 count = read_int(f_in);
00219 n = read_int(f_in);
00220 remainder = read_int(f_in);
00221
00222 sum_init();
00223
00224 for (i=recv_token(f_in,&data); i != 0; i=recv_token(f_in,&data)) {
00225
00226 show_progress(offset, total_size);
00227
00228 if (i > 0) {
00229 extern int cleanup_got_literal;
00230
00231 if (verbose > 3) {
00232 rprintf(FINFO,"data recv %d at %.0f\n",
00233 i,(double)offset);
00234 }
00235
00236 stats.literal_data += i;
00237 cleanup_got_literal = 1;
00238
00239 sum_update(data,i);
00240
00241 if (fd != -1 && write_file(fd,data,i) != i) {
00242 rprintf(FERROR,"write failed on %s : %s\n",fname,strerror(errno));
00243 exit_cleanup(RERR_FILEIO);
00244 }
00245 offset += i;
00246 continue;
00247 }
00248
00249 i = -(i+1);
00250 offset2 = i*(OFF_T)n;
00251 len = n;
00252 if (i == (int) count-1 && remainder != 0)
00253 len = remainder;
00254
00255 stats.matched_data += len;
00256
00257 if (verbose > 3)
00258 rprintf(FINFO,"chunk[%d] of size %d at %.0f offset=%.0f\n",
00259 i,len,(double)offset2,(double)offset);
00260
00261 if (buf) {
00262 map = map_ptr(buf,offset2,len);
00263
00264 see_token(map, len);
00265 sum_update(map,len);
00266 }
00267
00268 if (fd != -1 && write_file(fd,map,len) != (int) len) {
00269 rprintf(FERROR,"write failed on %s : %s\n",
00270 fname,strerror(errno));
00271 exit_cleanup(RERR_FILEIO);
00272 }
00273 offset += len;
00274 }
00275
00276 end_progress(total_size);
00277
00278 if (fd != -1 && offset > 0 && sparse_end(fd) != 0) {
00279 rprintf(FERROR,"write failed on %s : %s\n",
00280 fname,strerror(errno));
00281 exit_cleanup(RERR_FILEIO);
00282 }
00283
00284 sum_end(file_sum1);
00285
00286 if (remote_version >= 14) {
00287 read_buf(f_in,file_sum2,MD4_SUM_LENGTH);
00288 if (verbose > 2) {
00289 rprintf(FINFO,"got file_sum\n");
00290 }
00291 if (fd != -1 &&
00292 memcmp(file_sum1,file_sum2,MD4_SUM_LENGTH) != 0) {
00293 return 0;
00294 }
00295 }
00296 return 1;
00297 }
00298
00299
00300
00301
00302
00303
00304 int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen)
00305 {
00306 int fd1,fd2;
00307 STRUCT_STAT st;
00308 char *fname;
00309 char template[MAXPATHLEN];
00310 char fnametmp[MAXPATHLEN];
00311 char *fnamecmp;
00312 char fnamecmpbuf[MAXPATHLEN];
00313 struct map_struct *buf;
00314 int i;
00315 struct file_struct *file;
00316 int phase=0;
00317 int recv_ok;
00318 extern struct stats stats;
00319 extern int preserve_perms;
00320 extern int delete_after;
00321 extern int orig_umask;
00322 struct stats initial_stats;
00323
00324 if (verbose > 2) {
00325 rprintf(FINFO,"recv_files(%d) starting\n",flist->count);
00326 }
00327
00328 while (1) {
00329 cleanup_disable();
00330
00331 i = read_int(f_in);
00332 if (i == -1) {
00333 if (phase==0 && remote_version >= 13) {
00334 phase++;
00335 csum_length = SUM_LENGTH;
00336 if (verbose > 2)
00337 rprintf(FINFO,"recv_files phase=%d\n",phase);
00338 write_int(f_gen,-1);
00339 continue;
00340 }
00341 break;
00342 }
00343
00344 if (i < 0 || i >= flist->count) {
00345 rprintf(FERROR,"Invalid file index %d in recv_files (count=%d)\n",
00346 i, flist->count);
00347 exit_cleanup(RERR_PROTOCOL);
00348 }
00349
00350 file = flist->files[i];
00351 fname = f_name(file);
00352
00353 stats.num_transferred_files++;
00354 stats.total_transferred_size += file->length;
00355
00356 if (local_name)
00357 fname = local_name;
00358
00359 if (dry_run) {
00360 if (!am_server) {
00361 log_transfer(file, fname);
00362 }
00363 continue;
00364 }
00365
00366 initial_stats = stats;
00367
00368 if (verbose > 2)
00369 rprintf(FINFO,"recv_files(%s)\n",fname);
00370
00371 fnamecmp = fname;
00372
00373
00374 fd1 = do_open(fnamecmp, O_RDONLY, 0);
00375
00376 if ((fd1 == -1) && (compare_dest != NULL)) {
00377
00378 snprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s",
00379 compare_dest,fname);
00380 fnamecmp = fnamecmpbuf;
00381 fd1 = do_open(fnamecmp, O_RDONLY, 0);
00382 }
00383
00384 if (fd1 != -1 && do_fstat(fd1,&st) != 0) {
00385 rprintf(FERROR,"fstat %s : %s\n",fnamecmp,strerror(errno));
00386 receive_data(f_in,NULL,-1,NULL,file->length);
00387 close(fd1);
00388 continue;
00389 }
00390
00391 if (fd1 != -1 && !S_ISREG(st.st_mode)) {
00392 rprintf(FERROR,"%s : not a regular file (recv_files)\n",fnamecmp);
00393 receive_data(f_in,NULL,-1,NULL,file->length);
00394 close(fd1);
00395 continue;
00396 }
00397
00398 if (fd1 != -1 && !preserve_perms) {
00399
00400
00401
00402 file->mode = st.st_mode;
00403 }
00404
00405 if (fd1 != -1 && st.st_size > 0) {
00406 buf = map_file(fd1,st.st_size);
00407 if (verbose > 2)
00408 rprintf(FINFO,"recv mapped %s of size %.0f\n",fnamecmp,(double)st.st_size);
00409 } else {
00410 buf = NULL;
00411 }
00412
00413 if (!get_tmpname(fnametmp,fname)) {
00414 if (buf) unmap_file(buf);
00415 if (fd1 != -1) close(fd1);
00416 continue;
00417 }
00418
00419 strlcpy(template, fnametmp, sizeof(template));
00420
00421
00422
00423
00424
00425
00426
00427 fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
00428 if (fd2 == -1) {
00429 rprintf(FERROR,"mkstemp %s failed: %s\n",fnametmp,strerror(errno));
00430 receive_data(f_in,buf,-1,NULL,file->length);
00431 if (buf) unmap_file(buf);
00432 continue;
00433 }
00434
00435
00436
00437
00438 if (fd2 == -1 && relative_paths && errno == ENOENT &&
00439 create_directory_path(fnametmp, orig_umask) == 0) {
00440 strlcpy(fnametmp, template, sizeof(fnametmp));
00441 fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS);
00442 }
00443 if (fd2 == -1) {
00444 rprintf(FERROR,"cannot create %s : %s\n",fnametmp,strerror(errno));
00445 receive_data(f_in,buf,-1,NULL,file->length);
00446 if (buf) unmap_file(buf);
00447 if (fd1 != -1) close(fd1);
00448 continue;
00449 }
00450
00451 cleanup_set(fnametmp, fname, file, buf, fd1, fd2);
00452
00453 if (!am_server) {
00454 log_transfer(file, fname);
00455 }
00456
00457
00458 recv_ok = receive_data(f_in,buf,fd2,fname,file->length);
00459
00460 log_recv(file, &initial_stats);
00461
00462 if (buf) unmap_file(buf);
00463 if (fd1 != -1) {
00464 close(fd1);
00465 }
00466 close(fd2);
00467
00468 if (verbose > 2)
00469 rprintf(FINFO,"renaming %s to %s\n",fnametmp,fname);
00470
00471 finish_transfer(fname, fnametmp, file);
00472
00473 cleanup_disable();
00474
00475 if (!recv_ok) {
00476 if (csum_length == SUM_LENGTH) {
00477 rprintf(FERROR,"ERROR: file corruption in %s. File changed during transfer?\n",
00478 fname);
00479 } else {
00480 if (verbose > 1)
00481 rprintf(FINFO,"redoing %s(%d)\n",fname,i);
00482 write_int(f_gen,i);
00483 }
00484 }
00485 }
00486
00487 if (delete_after) {
00488 if (recurse && delete_mode && !local_name && flist->count>0) {
00489 delete_files(flist);
00490 }
00491 }
00492
00493 if (preserve_hard_links)
00494 do_hard_links();
00495
00496
00497
00498 for (i = 0; i < flist->count; i++) {
00499 file = flist->files[i];
00500 if (!file->basename || !S_ISDIR(file->mode)) continue;
00501 recv_generator(local_name?local_name:f_name(file),flist,i,-1);
00502 }
00503
00504 if (verbose > 2)
00505 rprintf(FINFO,"recv_files finished\n");
00506
00507 return 0;
00508 }
00509