X-Git-Url: https://mattmccutchen.net/rsync/rsync.git/blobdiff_plain/52d3e10613fe75f02bebf30d66a768c815a40aae..06c28400fa4ce46406d4a0bbf417b9b07df0a29a:/receiver.c diff --git a/receiver.c b/receiver.c index 3fa154a7..18b0795a 100644 --- a/receiver.c +++ b/receiver.c @@ -23,7 +23,7 @@ extern int verbose; extern int recurse; extern int delete_mode; -extern int remote_version; +extern int protocol_version; extern int csum_length; extern struct stats stats; extern int dry_run; @@ -35,7 +35,10 @@ extern int io_error; extern char *tmpdir; extern char *compare_dest; extern int make_backups; +extern int do_progress; +extern char *backup_dir; extern char *backup_suffix; +extern int backup_suffix_len; static struct delete_list { DEV64_T dev; @@ -56,7 +59,7 @@ static int delete_already_done(struct file_list *flist,int j) for (i=0;imode)) { - if (robust_unlink(f_name(f)) != 0) { - rprintf(FERROR,"delete_one: unlink %s: %s\n",f_name(f),strerror(errno)); + if (!is_dir) { + if (robust_unlink(fn) != 0) { + rprintf(FERROR, "delete_one: unlink %s failed: %s\n", + full_fname(fn), strerror(errno)); } else if (verbose) { - rprintf(FINFO,"deleting %s\n",f_name(f)); + rprintf(FINFO, "deleting %s\n", fn); } } else { - if (do_rmdir(f_name(f)) != 0) { - if (errno != ENOTEMPTY && errno != EEXIST) - rprintf(FERROR,"delete_one: rmdir %s: %s\n", - f_name(f), strerror(errno)); + if (do_rmdir(fn) != 0) { + if (errno != ENOTEMPTY && errno != EEXIST) { + rprintf(FERROR, "delete_one: rmdir %s failed: %s\n", + full_fname(fn), strerror(errno)); + } } else if (verbose) { - rprintf(FINFO,"deleting directory %s\n",f_name(f)); + rprintf(FINFO, "deleting directory %s\n", fn); } } } +static int is_backup_file(char *fn) +{ + int k = strlen(fn) - backup_suffix_len; + return k > 0 && strcmp(fn+k, backup_suffix) == 0; +} /* this deletes any files on the receiving side that are not present @@ -126,7 +137,7 @@ void delete_files(struct file_list *flist) if (!S_ISDIR(flist->files[j]->mode) || !(flist->files[j]->flags & FLAG_DELETE)) continue; - if (remote_version < 19 && + if (protocol_version < 19 && delete_already_done(flist, j)) continue; name = strdup(f_name(flist->files[j])); @@ -142,20 +153,20 @@ void delete_files(struct file_list *flist) for (i=local_file_list->count-1;i>=0;i--) { if (max_delete && deletion_count > max_delete) break; if (!local_file_list->files[i]->basename) continue; - if (remote_version < 19 && + if (protocol_version < 19 && 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])) { char *f = f_name(local_file_list->files[i]); - int k = strlen(f) - strlen(backup_suffix); -/* Hi Andrew, do we really need to play with backup_suffix here? */ - if (make_backups && ((k <= 0) || - (strcmp(f+k,backup_suffix) != 0))) { + if (make_backups && (backup_dir || !is_backup_file(f))) { (void) make_backup(f); + if (verbose) + rprintf(FINFO, "deleting %s\n", f); } else { - deletion_count++; - delete_one(local_file_list->files[i]); + int mode = local_file_list->files[i]->mode; + delete_one(f, S_ISDIR(mode) != 0); } + deletion_count++; } } flist_free(local_file_list); @@ -196,14 +207,15 @@ static int get_tmpname(char *fnametmp, char *fname) length = strlen(fnametmp); fnametmp[length++] = '/'; fnametmp[length] = '\0'; /* always NULL terminated */ - } + } - if ((f = strrchr(fname, '/'))) { /* extra () for gcc */ + if ((f = strrchr(fname, '/')) != NULL) { ++f; if (!tmpdir) { length = f - fname; + /* copy up to and including the slash */ strlcpy(fnametmp, fname, length + 1); - } /* copy up to and including the slash */ + } } else { f = fname; } @@ -212,8 +224,7 @@ static int get_tmpname(char *fnametmp, char *fname) maxname = MIN(MAXPATHLEN - 7 - length, NAME_MAX - 8); - if (maxname < 1) - { + if (maxname < 1) { rprintf(FERROR, "temporary filename too long: %s\n", fname); fnametmp[0] = '\0'; return 0; @@ -230,7 +241,8 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname, OFF_T total_size) { int i; - unsigned int n,remainder,len,count; + struct sum_struct sum; + unsigned int len; OFF_T offset = 0; OFF_T offset2; char *data; @@ -238,15 +250,13 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname, static char file_sum2[MD4_SUM_LENGTH]; char *map=NULL; - count = read_int(f_in); - n = read_int(f_in); - remainder = read_int(f_in); + read_sum_head(f_in, &sum); sum_init(); for (i=recv_token(f_in,&data); i != 0; i=recv_token(f_in,&data)) { - - show_progress(offset, total_size); + if (do_progress) + show_progress(offset, total_size); if (i > 0) { extern int cleanup_got_literal; @@ -262,7 +272,8 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname, sum_update(data,i); if (fd != -1 && write_file(fd,data,i) != i) { - rprintf(FERROR,"write failed on %s : %s\n",fname,strerror(errno)); + rprintf(FERROR, "write failed on %s: %s\n", + full_fname(fname), strerror(errno)); exit_cleanup(RERR_FILEIO); } offset += i; @@ -270,10 +281,10 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname, } i = -(i+1); - offset2 = i*(OFF_T)n; - len = n; - if (i == (int) count-1 && remainder != 0) - len = remainder; + offset2 = i*(OFF_T)sum.blength; + len = sum.blength; + if (i == (int) sum.count-1 && sum.remainder != 0) + len = sum.remainder; stats.matched_data += len; @@ -289,32 +300,31 @@ static int receive_data(int f_in,struct map_struct *buf,int fd,char *fname, } if (fd != -1 && write_file(fd,map,len) != (int) len) { - rprintf(FERROR,"write failed on %s : %s\n", - fname,strerror(errno)); + rprintf(FERROR, "write failed on %s: %s\n", + full_fname(fname), strerror(errno)); exit_cleanup(RERR_FILEIO); } offset += len; } - end_progress(total_size); + if (do_progress) + end_progress(total_size); if (fd != -1 && offset > 0 && sparse_end(fd) != 0) { - rprintf(FERROR,"write failed on %s : %s\n", - fname,strerror(errno)); + rprintf(FERROR, "write failed on %s: %s\n", + full_fname(fname), strerror(errno)); exit_cleanup(RERR_FILEIO); } sum_end(file_sum1); - if (remote_version >= 14) { - read_buf(f_in,file_sum2,MD4_SUM_LENGTH); - if (verbose > 2) { - rprintf(FINFO,"got file_sum\n"); - } - if (fd != -1 && - memcmp(file_sum1,file_sum2,MD4_SUM_LENGTH) != 0) { - return 0; - } + read_buf(f_in,file_sum2,MD4_SUM_LENGTH); + if (verbose > 2) { + rprintf(FINFO,"got file_sum\n"); + } + if (fd != -1 + && memcmp(file_sum1,file_sum2,MD4_SUM_LENGTH) != 0) { + return 0; } return 1; } @@ -353,7 +363,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen) i = read_int(f_in); if (i == -1) { - if (phase==0 && remote_version >= 13) { + if (phase==0) { phase++; csum_length = SUM_LENGTH; if (verbose > 2) @@ -405,19 +415,32 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen) } if (fd1 != -1 && do_fstat(fd1,&st) != 0) { - rprintf(FERROR,"fstat %s : %s\n",fnamecmp,strerror(errno)); + rprintf(FERROR, "fstat %s failed: %s\n", + full_fname(fnamecmp), strerror(errno)); receive_data(f_in,NULL,-1,NULL,file->length); close(fd1); continue; } - if (fd1 != -1 && !S_ISREG(st.st_mode)) { - rprintf(FERROR,"%s : not a regular file (recv_files)\n",fnamecmp); - receive_data(f_in,NULL,-1,NULL,file->length); + if (fd1 != -1 && S_ISDIR(st.st_mode) && fnamecmp == fname) { + /* this special handling for directories + * wouldn't be necessary if robust_rename() + * and the underlying robust_unlink could cope + * with directories + */ + rprintf(FERROR,"recv_files: %s is a directory\n", + full_fname(fnamecmp)); + receive_data(f_in, NULL, -1, NULL, file->length); close(fd1); continue; } + if (fd1 != -1 && !S_ISREG(st.st_mode)) { + close(fd1); + fd1 = -1; + buf = NULL; + } + if (fd1 != -1 && !preserve_perms) { /* if the file exists already and we aren't preserving permissions then act as though the remote end sent @@ -458,7 +481,8 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen) fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS); } if (fd2 == -1) { - rprintf(FERROR,"mkstemp %s failed: %s\n",fnametmp,strerror(errno)); + rprintf(FERROR, "mkstemp %s failed: %s\n", + full_fname(fnametmp), strerror(errno)); receive_data(f_in,buf,-1,NULL,file->length); if (buf) unmap_file(buf); if (fd1 != -1) close(fd1); @@ -492,7 +516,7 @@ int recv_files(int f_in,struct file_list *flist,char *local_name,int f_gen) if (!recv_ok) { if (csum_length == SUM_LENGTH) { rprintf(FERROR,"ERROR: file corruption in %s. File changed during transfer?\n", - fname); + full_fname(fname)); } else { if (verbose > 1) rprintf(FINFO,"redoing %s(%d)\n",fname,i);