From 231c3c7098f1099a56abb8afece76fc9b8699f05 Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Sun, 31 Jan 2010 12:01:54 +0200 Subject: 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. --- src/xz/file_io.c | 107 +++++++++++++++++++++++++++---------------------------- 1 file changed, 52 insertions(+), 55 deletions(-) (limited to 'src/xz/file_io.c') 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 -- cgit v1.2.3