X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/8de330a38717f8f808e8aa88a5f4391c310e7fd6..d1be231290b3867648ee417fad341fdf1caaa94b:/receiver.c diff --git a/receiver.c b/receiver.c index bf843e7c..e7a164b9 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 { @@ -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); @@ -163,7 +172,7 @@ static int get_tmpname(char *fnametmp, char *fname) rprintf(FERROR,"filename too long\n"); return 0; } - slprintf(fnametmp,MAXPATHLEN-1, "%s/.%s.XXXXXX",tmpdir,f); + slprintf(fnametmp,MAXPATHLEN, "%s/.%s.XXXXXX",tmpdir,f); return 1; } @@ -176,11 +185,11 @@ static int get_tmpname(char *fnametmp, char *fname) if (f) { *f = 0; - slprintf(fnametmp,MAXPATHLEN-1,"%s/.%s.XXXXXX", + slprintf(fnametmp,MAXPATHLEN,"%s/.%s.XXXXXX", fname,f+1); *f = '/'; } else { - slprintf(fnametmp,MAXPATHLEN-1,".%s.XXXXXX",fname); + slprintf(fnametmp,MAXPATHLEN,".%s.XXXXXX",fname); } return 1; @@ -223,7 +232,7 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname, if (fd != -1 && write_file(fd,data,i) != i) { rprintf(FERROR,"write failed on %s : %s\n",fname,strerror(errno)); - exit_cleanup(1); + exit_cleanup(RERR_FILEIO); } offset += i; continue; @@ -249,7 +258,7 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname, if (fd != -1 && write_file(fd,map,len) != len) { rprintf(FERROR,"write failed on %s : %s\n", fname,strerror(errno)); - exit_cleanup(1); + exit_cleanup(RERR_FILEIO); } offset += len; } @@ -259,7 +268,7 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname, if (fd != -1 && offset > 0 && sparse_end(fd) != 0) { rprintf(FERROR,"write failed on %s : %s\n", fname,strerror(errno)); - exit_cleanup(1); + exit_cleanup(RERR_FILEIO); } sum_end(file_sum1); @@ -292,6 +301,8 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen) struct file_struct *file; int phase=0; int recv_ok; + extern struct stats stats; + struct stats initial_stats; if (verbose > 2) { rprintf(FINFO,"recv_files(%d) starting\n",flist->count); @@ -320,7 +331,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen) if (i < 0 || i >= flist->count) { rprintf(FERROR,"Invalid file index %d in recv_files (count=%d)\n", i, flist->count); - exit_cleanup(1); + exit_cleanup(RERR_PROTOCOL); } file = flist->files[i]; @@ -339,6 +350,8 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen) continue; } + initial_stats = stats; + if (verbose > 2) rprintf(FINFO,"recv_files(%s)\n",fname); @@ -349,7 +362,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen) if ((fd1 == -1) && (compare_dest != NULL)) { /* try the file at compare_dest instead */ - slprintf(fnamecmpbuf,MAXPATHLEN-1,"%s/%s", + slprintf(fnamecmpbuf,MAXPATHLEN,"%s/%s", compare_dest,fname); fnamecmp = fnamecmpbuf; fd1 = open(fnamecmp,O_RDONLY); @@ -383,6 +396,10 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen) continue; } + /* mktemp is deliberately used here instead of mkstemp. + because O_EXCL is used on the open, the race condition + is not a problem or a security hole, and we want to + control the access permissions on the created file. */ if (NULL == do_mktemp(fnametmp)) { rprintf(FERROR,"mktemp %s failed\n",fnametmp); receive_data(f_in,buf,-1,NULL,file->length); @@ -418,10 +435,10 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen) log_transfer(file, fname); } - log_recv(file); - /* recv file data */ recv_ok = receive_data(f_in,buf,fd2,fname,file->length); + + log_recv(file, &initial_stats); if (buf) unmap_file(buf); if (fd1 != -1) {