From 83235dbc546d74ee325bb09b602bd62313fea793 Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Mon, 31 Dec 2007 10:18:22 -0800 Subject: [PATCH] Fixed a case where the receiver indicates a successful update when the transfer succeeded, but the final rename failed. --- generator.c | 8 +++----- receiver.c | 35 ++++++++++++++++++++--------------- rsync.c | 39 +++++++++++++++++++++++---------------- 3 files changed, 46 insertions(+), 36 deletions(-) diff --git a/generator.c b/generator.c index 046ad95d..35cbb572 100644 --- a/generator.c +++ b/generator.c @@ -841,7 +841,7 @@ static int copy_altdest_file(const char *src, const char *dest, struct file_stru { char buf[MAXPATHLEN]; const char *copy_to, *partialptr; - int fd_w; + int ok, fd_w; if (inplace) { /* Let copy_file open the destination in place. */ @@ -865,11 +865,9 @@ static int copy_altdest_file(const char *src, const char *dest, struct file_stru return -1; } partialptr = partial_dir ? partial_dir_fname(dest) : NULL; - if (partialptr && *partialptr == '/') - partialptr = NULL; - finish_transfer(dest, copy_to, src, partialptr, file, 1, 0); + ok = finish_transfer(dest, copy_to, src, partialptr, file, 1, 0); cleanup_disable(); - return 0; + return ok ? 0 : -1; } /* This is only called for regular files. We return -2 if we've finished diff --git a/receiver.c b/receiver.c index 3834ce26..38eaa840 100644 --- a/receiver.c +++ b/receiver.c @@ -688,26 +688,23 @@ int recv_files(int f_in, char *local_name) } if ((recv_ok && (!delay_updates || !partialptr)) || inplace) { - char *temp_copy_name; if (partialptr == fname) - partialptr = temp_copy_name = NULL; - else if (*partial_dir == '/') - temp_copy_name = NULL; - else - temp_copy_name = partialptr; - finish_transfer(fname, fnametmp, fnamecmp, - temp_copy_name, file, recv_ok, 1); - if (fnamecmp == partialptr) { + partialptr = NULL; + if (!finish_transfer(fname, fnametmp, fnamecmp, + partialptr, file, recv_ok, 1)) + recv_ok = -1; + else if (fnamecmp == partialptr) { do_unlink(partialptr); handle_partial_dir(partialptr, PDIR_DELETE); } } else if (keep_partial && partialptr && handle_partial_dir(partialptr, PDIR_CREATE)) { - finish_transfer(partialptr, fnametmp, fnamecmp, NULL, - file, recv_ok, !partial_dir); - if (delay_updates && recv_ok) { - bitbag_set_bit(delayed_bits, ndx); + if (!finish_transfer(partialptr, fnametmp, fnamecmp, NULL, + file, recv_ok, !partial_dir)) recv_ok = -1; + else if (delay_updates && recv_ok) { + bitbag_set_bit(delayed_bits, ndx); + recv_ok = 2; } } else { partialptr = NULL; @@ -716,11 +713,13 @@ int recv_files(int f_in, char *local_name) cleanup_disable(); - if (recv_ok > 0) { + switch (recv_ok) { + case 1: if (remove_source_files || inc_recurse || (preserve_hard_links && F_IS_HLINKED(file))) send_msg_int(MSG_SUCCESS, ndx); - } else if (!recv_ok) { + break; + case 0: { enum logcode msgtype = redoing || read_batch ? FERROR : FWARNING; if (msgtype == FERROR || verbose) { char *errstr, *redostr, *keptstr; @@ -746,6 +745,12 @@ int recv_files(int f_in, char *local_name) file->flags |= FLAG_FILE_SENT; } else if (inc_recurse) send_msg_int(MSG_NO_SEND, ndx); + break; + } + case -1: + if (inc_recurse) + send_msg_int(MSG_NO_SEND, ndx); + break; } } if (make_backups < 0) diff --git a/rsync.c b/rsync.c index 1654c30a..7505c634 100644 --- a/rsync.c +++ b/rsync.c @@ -504,15 +504,17 @@ RETSIGTYPE sig_int(UNUSED(int val)) } /* Finish off a file transfer: renaming the file and setting the file's - * attributes (e.g. permissions, ownership, etc.). If partialptr is not - * NULL and the robust_rename() call is forced to copy the temp file, we - * stage the file into the partial-dir and then rename it into place. */ -void finish_transfer(const char *fname, const char *fnametmp, - const char *fnamecmp, const char *partialptr, - struct file_struct *file, int ok_to_set_time, - int overwriting_basis) + * attributes (e.g. permissions, ownership, etc.). If the robust_rename() + * call is forced to copy the temp file and partialptr is both non-NULL and + * not an absolute path, we stage the file into the partial-dir and then + * rename it into place. This returns 1 on succcess or 0 on failure. */ +int finish_transfer(const char *fname, const char *fnametmp, + const char *fnamecmp, const char *partialptr, + struct file_struct *file, int ok_to_set_time, + int overwriting_basis) { int ret; + const char *temp_copy_name = partialptr && *partialptr != '/' ? partialptr : NULL; if (inplace) { if (verbose > 2) @@ -522,7 +524,7 @@ void finish_transfer(const char *fname, const char *fnametmp, } if (make_backups > 0 && overwriting_basis && !make_backup(fname)) - return; + return 1; /* Change permissions before putting the file into place. */ set_file_attrs(fnametmp, file, NULL, fnamecmp, @@ -531,34 +533,39 @@ void finish_transfer(const char *fname, const char *fnametmp, /* move tmp file over real file */ if (verbose > 2) rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname); - ret = robust_rename(fnametmp, fname, partialptr, + ret = robust_rename(fnametmp, fname, temp_copy_name, file->mode & INITACCESSPERMS); if (ret < 0) { rsyserr(FERROR_XFER, errno, "%s %s -> \"%s\"", ret == -2 ? "copy" : "rename", full_fname(fnametmp), fname); - do_unlink(fnametmp); - return; + if (!partialptr || (ret == -2 && temp_copy_name) + || robust_rename(fnametmp, partialptr, NULL, + file->mode & INITACCESSPERMS) < 0) + do_unlink(fnametmp); + return 0; } if (ret == 0) { /* The file was moved into place (not copied), so it's done. */ - return; + return 1; } /* The file was copied, so tweak the perms of the copied file. If it * was copied to partialptr, move it into its final destination. */ - fnametmp = partialptr ? partialptr : fname; + fnametmp = temp_copy_name ? temp_copy_name : fname; do_set_file_attrs: set_file_attrs(fnametmp, file, NULL, fnamecmp, ok_to_set_time ? 0 : ATTRS_SKIP_MTIME); - if (partialptr) { + if (temp_copy_name) { if (do_rename(fnametmp, fname) < 0) { rsyserr(FERROR_XFER, errno, "rename %s -> \"%s\"", full_fname(fnametmp), fname); - } else - handle_partial_dir(partialptr, PDIR_DELETE); + return 0; + } + handle_partial_dir(temp_copy_name, PDIR_DELETE); } + return 1; } struct file_list *flist_for_ndx(int ndx) -- 2.34.1