/* robustly move a file, creating new directory structures if necessary */
static int robust_move(char *src, char *dst)
{
- int keep_trying = 4;
- int keep_path_extfs = 0;
- int failed;
-
- while (keep_trying) {
- if (keep_path_extfs) {
- failed = copy_file(src, dst, 0755);
- if (!failed)
- do_unlink(src);
- } else
- failed = robust_rename(src, dst);
-
- if (failed) {
- if (verbose > 2) {
- rprintf(FERROR, "robust_move failed: %s(%d)\n",
- strerror(errno), errno);
- }
- switch (errno) {
- case EXDEV: /* external filesystem */
- keep_path_extfs = 1;
- keep_trying--;
- break;
- case ENOENT: /* no directory to write to */
- if (make_bak_dir(dst) < 0)
- keep_trying = 0;
- else
- keep_trying--;
- break;
- default:
- keep_trying = 0;
- break;
- }
- } else
- keep_trying = 0;
- }
- return !failed;
+ if (robust_rename(src, dst, 0755) != 0 || errno != ENOENT
+ || make_bak_dir(dst) < 0 || robust_rename(src, dst, 0755) != 0)
+ return -1;
+ return 0;
}
change_gid = preserve_gid && file->gid != GID_NONE
&& st->st_gid != file->gid;
if (change_uid || change_gid) {
- if (verbose > 2 && !dry_run) {
+ if (verbose > 2) {
if (change_uid) {
rprintf(FINFO,
"set uid of %s from %ld to %ld\n",
and ownership */
void finish_transfer(char *fname, char *fnametmp, struct file_struct *file)
{
+ int ret;
+
if (make_backups && !make_backup(fname))
return;
/* move tmp file over real file */
- if (robust_rename(fnametmp,fname) != 0) {
- if (errno == EXDEV) {
- /* rename failed on cross-filesystem link.
- Copy the file instead. */
- if (copy_file(fnametmp,fname, file->mode & INITACCESSPERMS)) {
- rprintf(FERROR, "copy %s -> \"%s\": %s\n",
- full_fname(fnametmp), fname,
- strerror(errno));
- } else {
- set_perms(fname,file,NULL,0);
- }
- } else {
- rprintf(FERROR,"rename %s -> \"%s\": %s\n",
- full_fname(fnametmp), fname, strerror(errno));
- }
+ ret = robust_rename(fnametmp, fname, file->mode & INITACCESSPERMS);
+ if (ret != 0) {
+ rprintf(FERROR, "%s %s -> \"%s\": %s\n",
+ ret == -2 ? "copy" : "rename",
+ full_fname(fnametmp), fname, strerror(errno));
do_unlink(fnametmp);
} else {
set_perms(fname,file,NULL,0);
#endif
}
-int robust_rename(char *from, char *to)
+/* Returns 0 on success, -1 on most errors, and -2 if we got an error
+ * trying to copy the file across file systems. */
+int robust_rename(char *from, char *to, int mode)
{
-#ifndef ETXTBSY
- return do_rename(from, to);
-#else
- int rc = do_rename(from, to);
- if (rc == 0 || errno != ETXTBSY)
- return rc;
- if (robust_unlink(to) != 0)
- return -1;
- return do_rename(from, to);
+ int tries = 4;
+
+ while (tries--) {
+ if (do_rename(from, to) == 0)
+ return 0;
+
+ switch (errno) {
+#ifdef ETXTBSY
+ case ETXTBSY:
+ if (robust_unlink(to) != 0)
+ return -1;
+ break;
#endif
+ case EXDEV:
+ if (copy_file(from, to, mode) != 0)
+ return -2;
+ do_unlink(from);
+ return 0;
+ default:
+ return -1;
+ }
+ }
+ return -1;
}