mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-03-11 10:56:31 -04:00
Fixed a case where the receiver indicates a successful update when the
transfer succeeded, but the final rename failed.
This commit is contained in:
@@ -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
|
||||
|
||||
35
receiver.c
35
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)
|
||||
|
||||
39
rsync.c
39
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)
|
||||
|
||||
Reference in New Issue
Block a user