--- backup.c 26 Jan 2006 10:38:58 -0000 1.50 +++ backup.c 29 Jan 2006 08:47:12 -0000 @@ -160,8 +160,9 @@ static int make_bak_dir(char *fullpath) /* robustly move a file, creating new directory structures if necessary */ static int robust_move(char *src, char *dst) { - if (robust_rename(src, dst, 0755) < 0 && (errno != ENOENT - || make_bak_dir(dst) < 0 || robust_rename(src, dst, 0755) < 0)) + if (robust_rename(src, dst, NULL, 0755) < 0 + && (errno != ENOENT || make_bak_dir(dst) < 0 + || robust_rename(src, dst, NULL, 0755) < 0)) return -1; return 0; } --- cleanup.c 13 Jan 2006 21:17:09 -0000 1.32 +++ cleanup.c 29 Jan 2006 08:47:12 -0000 @@ -121,8 +121,8 @@ void _exit_cleanup(int code, const char flush_write_file(cleanup_fd_w); close(cleanup_fd_w); } - finish_transfer(cleanup_new_fname, fname, cleanup_file, 0, - !partial_dir); + finish_transfer(cleanup_new_fname, fname, NULL, + cleanup_file, 0, !partial_dir); } io_flush(FULL_FLUSH); if (cleanup_fname) --- receiver.c 14 Jan 2006 20:26:24 -0000 1.168 +++ receiver.c 29 Jan 2006 08:47:12 -0000 @@ -681,15 +681,18 @@ int recv_files(int f_in, struct file_lis } if ((recv_ok && (!delay_updates || !partialptr)) || inplace) { - finish_transfer(fname, fnametmp, file, recv_ok, 1); - if (partialptr != fname && fnamecmp == partialptr) { + if (partialptr == fname) + partialptr = NULL; + finish_transfer(fname, fnametmp, partialptr, + file, recv_ok, 1); + 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, file, recv_ok, - !partial_dir); + finish_transfer(partialptr, fnametmp, NULL, + file, recv_ok, !partial_dir); if (delay_updates && recv_ok) { set_delayed_bit(i); recv_ok = -1; --- rsync.c 25 Jan 2006 17:10:29 -0000 1.171 +++ rsync.c 29 Jan 2006 08:47:12 -0000 @@ -168,14 +168,17 @@ void sig_int(void) /* finish off a file transfer, renaming the file and setting the permissions and ownership */ -void finish_transfer(char *fname, char *fnametmp, struct file_struct *file, - int ok_to_set_time, int overwriting_basis) +void finish_transfer(char *fname, char *fnametmp, char *partialptr, + struct file_struct *file, int ok_to_set_time, + int overwriting_basis) { int ret; if (inplace) { if (verbose > 2) rprintf(FINFO, "finishing %s\n", fname); + fnametmp = fname; + assert(partialptr == NULL); goto do_set_perms; } @@ -188,7 +191,8 @@ void finish_transfer(char *fname, char * /* move tmp file over real file */ if (verbose > 2) rprintf(FINFO, "renaming %s to %s\n", fnametmp, fname); - ret = robust_rename(fnametmp, fname, file->mode & INITACCESSPERMS); + ret = robust_rename(fnametmp, fname, partialptr, + file->mode & INITACCESSPERMS); if (ret < 0) { rsyserr(FERROR, errno, "%s %s -> \"%s\"", ret == -2 ? "copy" : "rename", @@ -200,8 +204,20 @@ void finish_transfer(char *fname, char * /* The file was moved into place (not copied), so it's done. */ return; } + /* 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; + do_set_perms: - set_perms(fname, file, NULL, ok_to_set_time ? 0 : PERMS_SKIP_MTIME); + set_perms(fnametmp, file, NULL, ok_to_set_time ? 0 : PERMS_SKIP_MTIME); + + if (partialptr) { + if (do_rename(fnametmp, fname) < 0) { + rsyserr(FERROR, errno, "rename %s -> \"%s\"", + full_fname(fnametmp), fname); + } else + handle_partial_dir(partialptr, PDIR_DELETE); + } } const char *who_am_i(void) --- util.c 20 Jan 2006 00:14:04 -0000 1.191 +++ util.c 29 Jan 2006 08:47:13 -0000 @@ -377,8 +377,11 @@ int robust_unlink(char *fname) } /* Returns 0 on successful rename, 1 if we successfully copied the file - * across filesystems, -2 if copy_file() failed, and -1 on other errors. */ -int robust_rename(char *from, char *to, int mode) + * across filesystems, -2 if copy_file() failed, and -1 on other errors. + * If partialptr is not NULL and we need to do a copy, copy the file into + * the active partial-dir instead of over the destination file. */ +int robust_rename(char *from, char *to, char *partialptr, + int mode) { int tries = 4; @@ -394,6 +397,11 @@ int robust_rename(char *from, char *to, break; #endif case EXDEV: + if (partialptr) { + if (!handle_partial_dir(partialptr,PDIR_CREATE)) + return -1; + to = partialptr; + } if (copy_file(from, to, mode) != 0) return -2; do_unlink(from);