X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/37f9805dabba76b7a00bd2a0227762f6f239b598..8c9fd200f9061cbb68b00fd3d58cacdbb46e2d23:/receiver.c diff --git a/receiver.c b/receiver.c index 9701303b..6eb9acab 100644 --- a/receiver.c +++ b/receiver.c @@ -33,6 +33,8 @@ extern int cvs_exclude; extern int io_error; extern char *tmpdir; extern char *compare_dest; +extern int make_backups; +extern char *backup_suffix; static struct delete_list { @@ -81,7 +83,7 @@ static void add_delete_entry(struct file_struct *file) static void delete_one(struct file_struct *f) { if (!S_ISDIR(f->mode)) { - if (do_unlink(f_name(f)) != 0) { + if (robust_unlink(f_name(f)) != 0) { rprintf(FERROR,"unlink %s : %s\n",f_name(f),strerror(errno)); } else if (verbose) { rprintf(FINFO,"deleting %s\n",f_name(f)); @@ -139,8 +141,15 @@ static void delete_files(struct file_list *flist) S_ISDIR(local_file_list->files[i]->mode)) add_delete_entry(local_file_list->files[i]); if (-1 == flist_find(flist,local_file_list->files[i])) { - delete_one(local_file_list->files[i]); - } + char *f = f_name(local_file_list->files[i]); + int k = strlen(f) - strlen(backup_suffix); + if (make_backups && ((k <= 0) || + (strcmp(f+k,backup_suffix) != 0))) { + (void) make_backup(f); + } else { + delete_one(local_file_list->files[i]); + } + } } flist_free(local_file_list); free(name); @@ -349,14 +358,14 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen) fnamecmp = fname; /* open the file */ - fd1 = open(fnamecmp,O_RDONLY); + fd1 = do_open(fnamecmp, O_RDONLY, 0); if ((fd1 == -1) && (compare_dest != NULL)) { /* try the file at compare_dest instead */ slprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s", compare_dest,fname); fnamecmp = fnamecmpbuf; - fd1 = open(fnamecmp,O_RDONLY); + fd1 = do_open(fnamecmp, O_RDONLY, 0); } if (fd1 != -1 && do_fstat(fd1,&st) != 0) { @@ -403,17 +412,21 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen) setuid/setgid bits to ensure that there is no race condition. They are then correctly updated after the lchown. Thanks to snabb@epipe.fi for pointing - this out */ + this out. We also set it initially without group + access because of a similar race condition. */ fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL, - file->mode & ACCESSPERMS); + file->mode & INITACCESSPERMS); + /* in most cases parent directories will already exist + because their information should have been previously + transferred, but that may not be the case with -R */ if (fd2 == -1 && relative_paths && errno == ENOENT && create_directory_path(fnametmp) == 0) { fd2 = do_open(fnametmp,O_WRONLY|O_CREAT|O_EXCL, - file->mode & ACCESSPERMS); + file->mode & INITACCESSPERMS); } if (fd2 == -1) { - rprintf(FERROR,"open %s : %s\n",fnametmp,strerror(errno)); + rprintf(FERROR,"cannot create %s : %s\n",fnametmp,strerror(errno)); receive_data(f_in,buf,-1,NULL,file->length); if (buf) unmap_file(buf); if (fd1 != -1) close(fd1); @@ -464,7 +477,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen) for (i = 0; i < flist->count; i++) { file = flist->files[i]; if (!file->basename || !S_ISDIR(file->mode)) continue; - recv_generator(f_name(file),flist,i,-1); + recv_generator(local_name?local_name:f_name(file),flist,i,-1); } if (verbose > 2)