diff options
author | Lasse Collin <lasse.collin@tukaani.org> | 2010-01-31 12:01:54 +0200 |
---|---|---|
committer | Lasse Collin <lasse.collin@tukaani.org> | 2010-01-31 12:01:54 +0200 |
commit | 231c3c7098f1099a56abb8afece76fc9b8699f05 (patch) | |
tree | 5887a319a46895b20f87075ba4f3b467a84bd85b /src/xz/coder.c | |
parent | Add list.h to src/xz/Makefile.am. (diff) | |
download | xz-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 '')
-rw-r--r-- | src/xz/coder.c | 64 |
1 files changed, 44 insertions, 20 deletions
diff --git a/src/xz/coder.c b/src/xz/coder.c index 48dfd4a6..4786e375 100644 --- a/src/xz/coder.c +++ b/src/xz/coder.c @@ -417,10 +417,23 @@ coder_init(file_pair *pair) ret = lzma_raw_decoder(&strm, filters); break; } + + // Try to decode the headers. This will catch too low + // memory usage limit in case it happens in the first + // Block of the first Stream, which is where it very + // probably will happen if it is going to happen. + if (ret == LZMA_OK && init_format != FORMAT_RAW) { + strm.next_out = NULL; + strm.avail_out = 0; + ret = lzma_code(&strm, LZMA_RUN); + } } if (ret != LZMA_OK) { message_error("%s: %s", pair->src_name, message_strm(ret)); + if (ret == LZMA_MEMLIMIT_ERROR) + message_mem_needed(V_ERROR, lzma_memusage(&strm)); + return CODER_INIT_ERROR; } @@ -585,16 +598,14 @@ coder_passthru(file_pair *pair) extern void coder_run(const char *filename) { - // Try to open the input and output files. - file_pair *pair = io_open(filename); + // Set and possibly print the filename for the progress message. + message_filename(filename); + + // Try to open the input file. + file_pair *pair = io_open_src(filename); if (pair == NULL) return; - // Initialize the progress indicator. - const uint64_t in_size = pair->src_st.st_size <= (off_t)(0) - ? 0 : (uint64_t)(pair->src_st.st_size); - message_progress_start(&strm, pair->src_name, in_size); - // Assume that something goes wrong. bool success = false; @@ -604,22 +615,35 @@ coder_run(const char *filename) strm.avail_in = io_read(pair, &in_buf, IO_BUFFER_SIZE); if (strm.avail_in != SIZE_MAX) { - switch (coder_init(pair)) { - case CODER_INIT_NORMAL: - success = coder_normal(pair); - break; - - case CODER_INIT_PASSTHRU: - success = coder_passthru(pair); - break; - - case CODER_INIT_ERROR: - break; + // Initialize the coder. This will detect the file format + // and, in decompression or testing mode, check the memory + // usage of the first Block too. This way we don't try to + // open the destination file if we see that coding wouldn't + // work at all anyway. This also avoids deleting the old + // "target" file if --force was used. + const enum coder_init_ret init_ret = coder_init(pair); + + if (init_ret != CODER_INIT_ERROR && !user_abort) { + // Don't open the destination file when --test + // is used. + if (opt_mode == MODE_TEST || !io_open_dest(pair)) { + // Initialize the progress indicator. + const uint64_t in_size + = pair->src_st.st_size <= 0 + ? 0 : pair->src_st.st_size; + message_progress_start(&strm, in_size); + + // Do the actual coding or passthru. + if (init_ret == CODER_INIT_NORMAL) + success = coder_normal(pair); + else + success = coder_passthru(pair); + + message_progress_end(success); + } } } - message_progress_end(success); - // Close the file pair. It needs to know if coding was successful to // know if the source or target file should be unlinked. io_close(pair, success); |