From f1ca7c4429f2a8e9de72f91d95218bb324df6a9e Mon Sep 17 00:00:00 2001 From: Wayne Davison Date: Sat, 17 May 2008 07:44:20 -0700 Subject: [PATCH] Preserve the right errno value when trying adjunct functions during robust backup, copy, and renaming activities. --- backup.c | 68 ++++++++++++++++++++++++++++++++++++++--------------- generator.c | 24 ++++++++++++------- util.c | 35 +++++++++++++++++++++------ 3 files changed, 92 insertions(+), 35 deletions(-) diff --git a/backup.c b/backup.c index 39a6e5ae..22cfc712 100644 --- a/backup.c +++ b/backup.c @@ -180,10 +180,19 @@ int make_bak_dir(const char *fullpath) /* robustly move a file, creating new directory structures if necessary */ static int robust_move(const char *src, char *dst) { - if (robust_rename(src, dst, NULL, 0755) < 0 - && (errno != ENOENT || make_bak_dir(dst) < 0 - || robust_rename(src, dst, NULL, 0755) < 0)) - return -1; + if (robust_rename(src, dst, NULL, 0755) < 0) { + int save_errno = errno ? errno : EINVAL; /* 0 paranoia */ + if (errno == ENOENT && make_bak_dir(dst) == 0) { + 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; } @@ -237,11 +246,18 @@ static int keep_backup(const char *fname) uint32 *devp = F_RDEV_P(file); dev_t rdev = MAKEDEV(DEV_MAJOR(devp), DEV_MINOR(devp)); do_unlink(buf); - if (do_mknod(buf, file->mode, rdev) < 0 - && (errno != ENOENT || make_bak_dir(buf) < 0 - || do_mknod(buf, file->mode, rdev) < 0)) { - rsyserr(FERROR, errno, "mknod %s failed", - full_fname(buf)); + if (do_mknod(buf, file->mode, rdev) < 0) { + int save_errno = errno ? errno : EINVAL; /* 0 paranoia */ + if (errno == ENOENT && make_bak_dir(buf) == 0) { + if (do_mknod(buf, file->mode, rdev) < 0) + 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) { rprintf(FINFO, "make_backup: DEVICE %s successful.\n", fname); @@ -252,11 +268,18 @@ static int keep_backup(const char *fname) if (!kept && S_ISDIR(file->mode)) { /* make an empty directory */ - if (do_mkdir(buf, file->mode) < 0 - && (errno != ENOENT || make_bak_dir(buf) < 0 - || do_mkdir(buf, file->mode) < 0)) { - rsyserr(FINFO, errno, "mkdir %s failed", - full_fname(buf)); + if (do_mkdir(buf, file->mode) < 0) { + int save_errno = errno ? errno : EINVAL; /* 0 paranoia */ + if (errno == ENOENT && make_bak_dir(buf) == 0) { + if (do_mkdir(buf, file->mode) < 0) + 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); @@ -278,11 +301,18 @@ static int keep_backup(const char *fname) kept = 1; } else { do_unlink(buf); - if (do_symlink(sl, buf) < 0 - && (errno != ENOENT || make_bak_dir(buf) < 0 - || do_symlink(sl, buf) < 0)) { - rsyserr(FERROR, errno, "link %s -> \"%s\"", - full_fname(buf), sl); + if (do_symlink(sl, buf) < 0) { + int save_errno = errno ? errno : EINVAL; /* 0 paranoia */ + if (errno == ENOENT && make_bak_dir(buf) == 0) { + if (do_symlink(sl, buf) < 0) + 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); kept = 1; diff --git a/generator.c b/generator.c index ed3db578..16f167e5 100644 --- a/generator.c +++ b/generator.c @@ -1868,15 +1868,21 @@ static void recv_generator(char *fname, struct file_struct *file, int ndx, close(fd); goto cleanup; } - if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0 - && (errno != ENOENT || make_bak_dir(backupptr) < 0 - || (f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0)) { - rsyserr(FERROR_XFER, errno, "open %s", - full_fname(backupptr)); - unmake_file(back_file); - back_file = NULL; - close(fd); - goto cleanup; + if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0) { + int save_errno = errno ? errno : EINVAL; /* 0 paranoia */ + if (errno == ENOENT && make_bak_dir(backupptr) == 0) { + if ((f_copy = do_open(backupptr, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600)) < 0) + save_errno = errno ? errno : save_errno; + else + save_errno = 0; + } + 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; } diff --git a/util.c b/util.c index 2afb63ec..c4375175 100644 --- a/util.c +++ b/util.c @@ -275,38 +275,54 @@ int copy_file(const char *source, const char *dest, int ofd, int len; /* Number of bytes read into `buf'. */ if ((ifd = do_open(source, O_RDONLY, 0)) < 0) { + int save_errno = errno; rsyserr(FERROR_XFER, errno, "open %s", full_fname(source)); + errno = save_errno; return -1; } if (ofd < 0) { if (robust_unlink(dest) && errno != ENOENT) { + int save_errno = errno; rsyserr(FERROR_XFER, errno, "unlink %s", full_fname(dest)); + errno = save_errno; return -1; } - 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 - || (ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0)) { - rsyserr(FERROR_XFER, errno, "open %s", full_fname(dest)); - close(ifd); - return -1; + if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0) { + int save_errno = errno ? errno : EINVAL; /* 0 paranoia */ + if (create_bak_dir && errno == ENOENT && make_bak_dir(dest) == 0) { + if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0) + save_errno = errno ? errno : save_errno; + 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) { if (full_write(ofd, buf, len) < 0) { + int save_errno = errno; rsyserr(FERROR_XFER, errno, "write %s", full_fname(dest)); close(ifd); close(ofd); + errno = save_errno; return -1; } } if (len < 0) { + int save_errno = errno; rsyserr(FERROR_XFER, errno, "read %s", full_fname(source)); close(ifd); close(ofd); + errno = save_errno; return -1; } @@ -316,8 +332,10 @@ int copy_file(const char *source, const char *dest, int ofd, } if (close(ofd) < 0) { + int save_errno = errno; rsyserr(FERROR_XFER, errno, "close failed on %s", full_fname(dest)); + errno = save_errno; return -1; } @@ -401,8 +419,11 @@ int robust_rename(const char *from, const char *to, const char *partialptr, switch (errno) { #ifdef ETXTBSY case ETXTBSY: - if (robust_unlink(to) != 0) + if (robust_unlink(to) != 0) { + errno = ETXTBSY; return -1; + } + errno = ETXTBSY; break; #endif case EXDEV: -- 2.34.1