Skip to content

Commit

Permalink
Preserve the right errno value when trying adjunct functions during
Browse files Browse the repository at this point in the history
robust backup, copy, and renaming activities.
  • Loading branch information
Wayne Davison committed May 17, 2008
1 parent adc4ebd commit f1ca7c4
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 35 deletions.
68 changes: 49 additions & 19 deletions backup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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;
Expand Down
24 changes: 15 additions & 9 deletions generator.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
35 changes: 28 additions & 7 deletions util.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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;
}

Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit f1ca7c4

Please sign in to comment.