On 24 July 2011 21:05, Reuben Thomas <r...@sc3d.org> wrote: > I just came across the copy-file module, which does exactly what I > want (it is even geared to making backup files), but (unfortunately > for use in an interactive program) exits on error.
Just to move this along a bit, I attach a patch which changes copy_file_preserving to return error codes instead of calling error. Obviously, I don't expect this to be applied to gnulib, but as per my original message, I'd like to know if a version of copy_file_preserving along these lines is thought to be a good idea for interactive use (I need it for creating backup files in GNU Zile), and how I might produce a patch that provides an error-returning variant without duplicating all the code. diff --git a/lib/copy-file.h b/lib/copy-file.h index cb8b1f7..b0c29e0 100644 --- a/lib/copy-file.h +++ b/lib/copy-file.h @@ -26,7 +26,7 @@ extern "C" { Modification times, owner, group and access permissions are preserved as far as possible. Exit upon failure. */ -extern void copy_file_preserving (const char *src_filename, const char *dest_filename); +extern int copy_file_preserving (const char *src_filename, const char *dest_filename); #ifdef __cplusplus diff --git a/lib/copy-file.c b/lib/copy-file.c index f9cd9c0..b5b8447 100644 --- a/lib/copy-file.c +++ b/lib/copy-file.c @@ -53,7 +53,7 @@ enum { IO_SIZE = 32 * 1024 }; -void +int copy_file_preserving (const char *src_filename, const char *dest_filename) { int src_fd; @@ -63,37 +63,37 @@ copy_file_preserving (const char *src_filename, const char *dest_filename) char *buf = xmalloc (IO_SIZE); src_fd = open (src_filename, O_RDONLY | O_BINARY); - if (src_fd < 0 || fstat (src_fd, &statbuf) < 0) - error (EXIT_FAILURE, errno, _("error while opening \"%s\" for reading"), - src_filename); + if (src_fd < 0) + return -1; + if (fstat (src_fd, &statbuf) < 0) + goto error_exit_2; mode = statbuf.st_mode & 07777; dest_fd = open (dest_filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0600); if (dest_fd < 0) - error (EXIT_FAILURE, errno, _("cannot open backup file \"%s\" for writing"), - dest_filename); + return -1; /* Copy the file contents. */ for (;;) { size_t n_read = safe_read (src_fd, buf, IO_SIZE); if (n_read == SAFE_READ_ERROR) - error (EXIT_FAILURE, errno, _("error reading \"%s\""), src_filename); + goto error_exit; if (n_read == 0) break; if (full_write (dest_fd, buf, n_read) < n_read) - error (EXIT_FAILURE, errno, _("error writing \"%s\""), dest_filename); + goto error_exit; } free (buf); #if !USE_ACL if (close (dest_fd) < 0) - error (EXIT_FAILURE, errno, _("error writing \"%s\""), dest_filename); + goto error_exit_2; if (close (src_fd) < 0) - error (EXIT_FAILURE, errno, _("error after reading \"%s\""), src_filename); + return -1; #endif /* Preserve the access and modification times. */ @@ -123,15 +123,23 @@ copy_file_preserving (const char *src_filename, const char *dest_filename) /* Preserve the access permissions. */ #if USE_ACL if (copy_acl (src_filename, src_fd, dest_filename, dest_fd, mode)) - exit (EXIT_FAILURE); + goto error_exit; #else chmod (dest_filename, mode); #endif #if USE_ACL if (close (dest_fd) < 0) - error (EXIT_FAILURE, errno, _("error writing \"%s\""), dest_filename); + goto error_exit_2; if (close (src_fd) < 0) - error (EXIT_FAILURE, errno, _("error after reading \"%s\""), src_filename); + return -1; #endif + + return 0; + + error_exit: + close (dest_fd); + error_exit_2: + close (src_fd); + return -1; }