aboutsummaryrefslogtreecommitdiff
path: root/src/xz/file_io.c
diff options
context:
space:
mode:
authorLasse Collin <lasse.collin@tukaani.org>2010-01-31 12:01:54 +0200
committerLasse Collin <lasse.collin@tukaani.org>2010-01-31 12:01:54 +0200
commit231c3c7098f1099a56abb8afece76fc9b8699f05 (patch)
tree5887a319a46895b20f87075ba4f3b467a84bd85b /src/xz/file_io.c
parentAdd list.h to src/xz/Makefile.am. (diff)
downloadxz-231c3c7098f1099a56abb8afece76fc9b8699f05.tar.xz
Delay opening the destionation file and other fixes.
The opening of the destination file is now delayed a little. The coder is initialized, and if decompressing, the memory usage of the first Block compared against the memory usage limit before the destination file is opened. This means that if --force was used, the old "target" file won't be deleted so easily when something goes wrong very early. Thanks to Mark K for the bug report. The above fix required some changes to progress message handling. Now there is a separate function for setting and printing the filename. It is used also in list.c. list_file() now handles stdin correctly (gives an error). A useless check for user_abort was removed from file_io.c.
Diffstat (limited to 'src/xz/file_io.c')
-rw-r--r--src/xz/file_io.c107
1 files changed, 52 insertions, 55 deletions
diff --git a/src/xz/file_io.c b/src/xz/file_io.c
index 71461e7e..c1bca196 100644
--- a/src/xz/file_io.c
+++ b/src/xz/file_io.c
@@ -274,7 +274,7 @@ io_copy_attrs(const file_pair *pair)
/// Opens the source file. Returns false on success, true on error.
static bool
-io_open_src(file_pair *pair)
+io_open_src_real(file_pair *pair)
{
// There's nothing to open when reading from stdin.
if (pair->src_name == stdin_filename) {
@@ -495,6 +495,36 @@ error:
}
+extern file_pair *
+io_open_src(const char *src_name)
+{
+ if (is_empty_filename(src_name))
+ return NULL;
+
+ // Since we have only one file open at a time, we can use
+ // a statically allocated structure.
+ static file_pair pair;
+
+ pair = (file_pair){
+ .src_name = src_name,
+ .dest_name = NULL,
+ .src_fd = -1,
+ .dest_fd = -1,
+ .src_eof = false,
+ .dest_try_sparse = false,
+ .dest_pending_sparse = 0,
+ };
+
+ // Block the signals, for which we have a custom signal handler, so
+ // that we don't need to worry about EINTR.
+ signals_block();
+ const bool error = io_open_src_real(&pair);
+ signals_unblock();
+
+ return error ? NULL : &pair;
+}
+
+
/// \brief Closes source file of the file_pair structure
///
/// \param pair File whose src_fd should be closed
@@ -528,7 +558,7 @@ io_close_src(file_pair *pair, bool success)
static bool
-io_open_dest(file_pair *pair)
+io_open_dest_real(file_pair *pair)
{
if (opt_stdout || pair->src_fd == STDIN_FILENO) {
// We don't modify or free() this.
@@ -557,12 +587,8 @@ io_open_dest(file_pair *pair)
pair->dest_fd = open(pair->dest_name, flags, mode);
if (pair->dest_fd == -1) {
- // Don't bother with error message if user requested
- // us to exit anyway.
- if (!user_abort)
- message_error("%s: %s", pair->dest_name,
- strerror(errno));
-
+ message_error("%s: %s", pair->dest_name,
+ strerror(errno));
free(pair->dest_name);
return true;
}
@@ -643,6 +669,16 @@ io_open_dest(file_pair *pair)
}
+extern bool
+io_open_dest(file_pair *pair)
+{
+ signals_block();
+ const bool ret = io_open_dest_real(pair);
+ signals_unblock();
+ return ret;
+}
+
+
/// \brief Closes destination file of the file_pair structure
///
/// \param pair File whose dest_fd should be closed
@@ -650,7 +686,7 @@ io_open_dest(file_pair *pair)
///
/// \return Zero if closing succeeds. On error, -1 is returned and
/// error message printed.
-static int
+static bool
io_close_dest(file_pair *pair, bool success)
{
#ifndef TUKLIB_DOSLIKE
@@ -665,13 +701,13 @@ io_close_dest(file_pair *pair, bool success)
message_error(_("Error restoring the O_APPEND flag "
"to standard output: %s"),
strerror(errno));
- return -1;
+ return true;
}
}
#endif
if (pair->dest_fd == -1 || pair->dest_fd == STDOUT_FILENO)
- return 0;
+ return false;
if (close(pair->dest_fd)) {
message_error(_("%s: Closing the file failed: %s"),
@@ -681,7 +717,7 @@ io_close_dest(file_pair *pair, bool success)
// contents. Get rid of junk:
io_unlink(pair->dest_name, &pair->dest_st);
free(pair->dest_name);
- return -1;
+ return true;
}
// If the operation using this file wasn't successful, we git rid
@@ -691,48 +727,7 @@ io_close_dest(file_pair *pair, bool success)
free(pair->dest_name);
- return 0;
-}
-
-
-extern file_pair *
-io_open(const char *src_name)
-{
- if (is_empty_filename(src_name))
- return NULL;
-
- // Since we have only one file open at a time, we can use
- // a statically allocated structure.
- static file_pair pair;
-
- pair = (file_pair){
- .src_name = src_name,
- .dest_name = NULL,
- .src_fd = -1,
- .dest_fd = -1,
- .src_eof = false,
- .dest_try_sparse = false,
- .dest_pending_sparse = 0,
- };
-
- // Block the signals, for which we have a custom signal handler, so
- // that we don't need to worry about EINTR.
- signals_block();
-
- file_pair *ret = NULL;
- if (!io_open_src(&pair)) {
- // io_open_src() may have unblocked the signals temporarily,
- // and thus user_abort may have got set even if open()
- // succeeded.
- if (user_abort || io_open_dest(&pair))
- io_close_src(&pair, false);
- else
- ret = &pair;
- }
-
- signals_unblock();
-
- return ret;
+ return false;
}
@@ -764,7 +759,9 @@ io_close(file_pair *pair, bool success)
signals_block();
- if (success && pair->dest_fd != STDOUT_FILENO)
+ // Copy the file attributes. We need to skip this if destination
+ // file isn't open or it is standard output.
+ if (success && pair->dest_fd != -1 && pair->dest_fd != STDOUT_FILENO)
io_copy_attrs(pair);
// Close the destination first. If it fails, we must not remove