Preserve the right errno value when trying adjunct functions during
authorWayne Davison <wayned@samba.org>
Sat, 17 May 2008 14:44:20 +0000 (07:44 -0700)
committerWayne Davison <wayned@samba.org>
Sat, 17 May 2008 15:25:22 +0000 (08:25 -0700)
robust backup, copy, and renaming activities.

backup.c
generator.c
util.c

index 39a6e5ae5fd97202b741d0c1679898999eec1aad..22cfc71260b2cb72115115da3cd39e0f356d9a61 100644 (file)
--- 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;
index ed3db578370c4a7cfde69a8c3fdec29e861707f1..16f167e51eeac9ac983399bbd8e5f4b459e53faf 100644 (file)
@@ -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 2afb63ec8fed36f4ac81bee395e579e123eb385e..c4375175af076ebcacca55fe3cd356e6fc8298b4 100644 (file)
--- 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: