Commit f1ca7c44 authored by Wayne Davison's avatar Wayne Davison

Preserve the right errno value when trying adjunct functions during

robust backup, copy, and renaming activities.
parent adc4ebdd
...@@ -180,10 +180,19 @@ int make_bak_dir(const char *fullpath) ...@@ -180,10 +180,19 @@ int make_bak_dir(const char *fullpath)
/* robustly move a file, creating new directory structures if necessary */ /* robustly move a file, creating new directory structures if necessary */
static int robust_move(const char *src, char *dst) static int robust_move(const char *src, char *dst)
{ {
if (robust_rename(src, dst, NULL, 0755) < 0 if (robust_rename(src, dst, NULL, 0755) < 0) {
&& (errno != ENOENT || make_bak_dir(dst) < 0 int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
|| robust_rename(src, dst, NULL, 0755) < 0)) if (errno == ENOENT && make_bak_dir(dst) == 0) {
return -1; if (robust_rename(src, dst, NULL, 0755) < 0)
save_errno = errno ? errno : save_errno;
else
save_errno = 0;
}
if (save_errno) {
errno = save_errno;
return -1;
}
}
return 0; return 0;
} }
...@@ -237,11 +246,18 @@ static int keep_backup(const char *fname) ...@@ -237,11 +246,18 @@ static int keep_backup(const char *fname)
uint32 *devp = F_RDEV_P(file); uint32 *devp = F_RDEV_P(file);
dev_t rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)); dev_t rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp));
do_unlink(buf); do_unlink(buf);
if (do_mknod(buf, file->mode, rdev) < 0 if (do_mknod(buf, file->mode, rdev) < 0) {
&& (errno != ENOENT || make_bak_dir(buf) < 0 int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
|| do_mknod(buf, file->mode, rdev) < 0)) { if (errno == ENOENT && make_bak_dir(buf) == 0) {
rsyserr(FERROR, errno, "mknod %s failed", if (do_mknod(buf, file->mode, rdev) < 0)
full_fname(buf)); save_errno = errno ? errno : save_errno;
else
save_errno = 0;
}
if (save_errno) {
rsyserr(FERROR, save_errno, "mknod %s failed",
full_fname(buf));
}
} else if (verbose > 2) { } else if (verbose > 2) {
rprintf(FINFO, "make_backup: DEVICE %s successful.\n", rprintf(FINFO, "make_backup: DEVICE %s successful.\n",
fname); fname);
...@@ -252,11 +268,18 @@ static int keep_backup(const char *fname) ...@@ -252,11 +268,18 @@ static int keep_backup(const char *fname)
if (!kept && S_ISDIR(file->mode)) { if (!kept && S_ISDIR(file->mode)) {
/* make an empty directory */ /* make an empty directory */
if (do_mkdir(buf, file->mode) < 0 if (do_mkdir(buf, file->mode) < 0) {
&& (errno != ENOENT || make_bak_dir(buf) < 0 int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
|| do_mkdir(buf, file->mode) < 0)) { if (errno == ENOENT && make_bak_dir(buf) == 0) {
rsyserr(FINFO, errno, "mkdir %s failed", if (do_mkdir(buf, file->mode) < 0)
full_fname(buf)); save_errno = errno ? errno : save_errno;
else
save_errno = 0;
}
if (save_errno) {
rsyserr(FINFO, save_errno, "mkdir %s failed",
full_fname(buf));
}
} }
ret_code = do_rmdir(fname); ret_code = do_rmdir(fname);
...@@ -278,11 +301,18 @@ static int keep_backup(const char *fname) ...@@ -278,11 +301,18 @@ static int keep_backup(const char *fname)
kept = 1; kept = 1;
} else { } else {
do_unlink(buf); do_unlink(buf);
if (do_symlink(sl, buf) < 0 if (do_symlink(sl, buf) < 0) {
&& (errno != ENOENT || make_bak_dir(buf) < 0 int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
|| do_symlink(sl, buf) < 0)) { if (errno == ENOENT && make_bak_dir(buf) == 0) {
rsyserr(FERROR, errno, "link %s -> \"%s\"", if (do_symlink(sl, buf) < 0)
full_fname(buf), sl); save_errno = errno ? errno : save_errno;
else
save_errno = 0;
}
if (save_errno) {
rsyserr(FERROR, save_errno, "link %s -> \"%s\"",
full_fname(buf), sl);
}
} }
do_unlink(fname); do_unlink(fname);
kept = 1; kept = 1;
......
...@@ -1868,15 +1868,21 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, ...@@ -1868,15 +1868,21 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx,
close(fd); close(fd);
goto cleanup; goto cleanup;
} }
if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0 if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0) {
&& (errno != ENOENT || make_bak_dir(backupptr) < 0 int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
|| (f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0)) { if (errno == ENOENT && make_bak_dir(backupptr) == 0) {
rsyserr(FERROR_XFER, errno, "open %s", if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0)
full_fname(backupptr)); save_errno = errno ? errno : save_errno;
unmake_file(back_file); else
back_file = NULL; save_errno = 0;
close(fd); }
goto cleanup; if (save_errno) {
rsyserr(FERROR_XFER, save_errno, "open %s", full_fname(backupptr));
unmake_file(back_file);
back_file = NULL;
close(fd);
goto cleanup;
}
} }
fnamecmp_type = FNAMECMP_BACKUP; fnamecmp_type = FNAMECMP_BACKUP;
} }
......
...@@ -275,38 +275,54 @@ int copy_file(const char *source, const char *dest, int ofd, ...@@ -275,38 +275,54 @@ int copy_file(const char *source, const char *dest, int ofd,
int len; /* Number of bytes read into `buf'. */ int len; /* Number of bytes read into `buf'. */
if ((ifd = do_open(source, O_RDONLY, 0)) < 0) { if ((ifd = do_open(source, O_RDONLY, 0)) < 0) {
int save_errno = errno;
rsyserr(FERROR_XFER, errno, "open %s", full_fname(source)); rsyserr(FERROR_XFER, errno, "open %s", full_fname(source));
errno = save_errno;
return -1; return -1;
} }
if (ofd < 0) { if (ofd < 0) {
if (robust_unlink(dest) && errno != ENOENT) { if (robust_unlink(dest) && errno != ENOENT) {
int save_errno = errno;
rsyserr(FERROR_XFER, errno, "unlink %s", full_fname(dest)); rsyserr(FERROR_XFER, errno, "unlink %s", full_fname(dest));
errno = save_errno;
return -1; return -1;
} }
if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0 if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0) {
&& (!create_bak_dir || errno != ENOENT || make_bak_dir(dest) < 0 int save_errno = errno ? errno : EINVAL; /* 0 paranoia */
|| (ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0)) { if (create_bak_dir && errno == ENOENT && make_bak_dir(dest) == 0) {
rsyserr(FERROR_XFER, errno, "open %s", full_fname(dest)); if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0)
close(ifd); save_errno = errno ? errno : save_errno;
return -1; else
save_errno = 0;
}
if (save_errno) {
rsyserr(FERROR_XFER, save_errno, "open %s", full_fname(dest));
close(ifd);
errno = save_errno;
return -1;
}
} }
} }
while ((len = safe_read(ifd, buf, sizeof buf)) > 0) { while ((len = safe_read(ifd, buf, sizeof buf)) > 0) {
if (full_write(ofd, buf, len) < 0) { if (full_write(ofd, buf, len) < 0) {
int save_errno = errno;
rsyserr(FERROR_XFER, errno, "write %s", full_fname(dest)); rsyserr(FERROR_XFER, errno, "write %s", full_fname(dest));
close(ifd); close(ifd);
close(ofd); close(ofd);
errno = save_errno;
return -1; return -1;
} }
} }
if (len < 0) { if (len < 0) {
int save_errno = errno;
rsyserr(FERROR_XFER, errno, "read %s", full_fname(source)); rsyserr(FERROR_XFER, errno, "read %s", full_fname(source));
close(ifd); close(ifd);
close(ofd); close(ofd);
errno = save_errno;
return -1; return -1;
} }
...@@ -316,8 +332,10 @@ int copy_file(const char *source, const char *dest, int ofd, ...@@ -316,8 +332,10 @@ int copy_file(const char *source, const char *dest, int ofd,
} }
if (close(ofd) < 0) { if (close(ofd) < 0) {
int save_errno = errno;
rsyserr(FERROR_XFER, errno, "close failed on %s", rsyserr(FERROR_XFER, errno, "close failed on %s",
full_fname(dest)); full_fname(dest));
errno = save_errno;
return -1; return -1;
} }
...@@ -401,8 +419,11 @@ int robust_rename(const char *from, const char *to, const char *partialptr, ...@@ -401,8 +419,11 @@ int robust_rename(const char *from, const char *to, const char *partialptr,
switch (errno) { switch (errno) {
#ifdef ETXTBSY #ifdef ETXTBSY
case ETXTBSY: case ETXTBSY:
if (robust_unlink(to) != 0) if (robust_unlink(to) != 0) {
errno = ETXTBSY;
return -1; return -1;
}
errno = ETXTBSY;
break; break;
#endif #endif
case EXDEV: case EXDEV:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment