diff --git a/lrzip.c b/lrzip.c index f388aee..8d336d7 100644 --- a/lrzip.c +++ b/lrzip.c @@ -262,10 +262,28 @@ static void fwrite_stdout(void *buf, i64 len) fflush(stdout); } -void flush_stdout(rzip_control *control) +void write_fdout(rzip_control *control, void *buf, i64 len) +{ + uchar *offset_buf = buf; + ssize_t ret; + + while (len > 0) { + ret = MIN(len, one_g); + ret = write(control->fd_out, offset_buf, (size_t)ret); + if (unlikely(ret <= 0)) + fatal("Failed to write to fd_out in write_fdout\n"); + len -= ret; + offset_buf += ret; + } +} + +void flush_tmpoutbuf(rzip_control *control) { print_verbose("Dumping buffer to stdout.\n"); - fwrite_stdout(control->tmp_outbuf, control->out_len); + if (STDOUT && !TEST_ONLY) + fwrite_stdout(control->tmp_outbuf, control->out_len); + else if (!STDOUT && !TEST_ONLY) + write_fdout(control, control->tmp_outbuf, control->out_len); control->rel_ofs += control->out_len; control->out_ofs = control->out_len = 0; } @@ -358,6 +376,12 @@ static void open_tmpoutbuf(rzip_control *control) control->out_ofs = control->out_len = MAGIC_LEN; } +void close_tmpoutbuf(rzip_control *control) +{ + control->flags &= ~FLAG_TMP_OUTBUF; + free(control->tmp_outbuf); +} + /* decompress one file from the command line */ @@ -446,11 +470,6 @@ void decompress_file(rzip_control *control) preserve_perms(control, fd_in, fd_out); } else { - /* When using a temporary output buffer we still generate - * temporary output files in case we use them should we run - * out of space. */ - if (!TEST_ONLY) - open_tmpoutbuf(control); fd_out = open_tmpoutfile(control); if (unlikely(fd_out == -1)) fatal("Failed to create %s\n", control->outfile); @@ -462,6 +481,8 @@ void decompress_file(rzip_control *control) fatal("Failed to unlink tmpfile: %s\n", control->outfile); } + open_tmpoutbuf(control); + read_magic(control, fd_in, &expected_size); if (!STDOUT) { @@ -847,7 +868,7 @@ void compress_file(rzip_control *control) if (unlikely(!STDOUT && close(fd_out))) fatal("Failed to close fd_out\n"); if (TMP_OUTBUF) - free(control->tmp_outbuf); + close_tmpoutbuf(control); if (!KEEP_FILES) { if (unlikely(unlink(control->infile))) diff --git a/lrzip.h b/lrzip.h index 17395f1..aa6c43b 100644 --- a/lrzip.h +++ b/lrzip.h @@ -33,5 +33,7 @@ void get_header_info(rzip_control *control, int fd_in, uchar *ctype, i64 *c_len, void get_fileinfo(rzip_control *control); void compress_file(rzip_control *control); void write_stdout_header(rzip_control *control); -void flush_stdout(rzip_control *control); +void write_fdout(rzip_control *control, void *buf, i64 len); +void flush_tmpoutbuf(rzip_control *control); +void close_tmpoutbuf(rzip_control *control); #endif diff --git a/main.c b/main.c index 92ba8f2..1cce5e8 100644 --- a/main.c +++ b/main.c @@ -698,8 +698,9 @@ int main(int argc, char *argv[]) } } - /* Use less ram when using STDOUT to store the temporary output file */ - if (STDOUT) + /* Use less ram when using STDOUT to store the temporary output + * file. */ + if (STDOUT && !(DECOMPRESS || TEST_ONLY)) control.maxram = control.ramsize * 2 / 9; else control.maxram = control.ramsize / 3; diff --git a/runzip.c b/runzip.c index 5a2c238..6124197 100644 --- a/runzip.c +++ b/runzip.c @@ -88,7 +88,9 @@ static i64 seekto_fdout(rzip_control *control, i64 pos) if (control->out_ofs > control->out_len) control->out_len = control->out_ofs; if (unlikely(control->out_ofs < 0 || control->out_ofs > control->out_maxlen)) { - print_err("Trying to seek outside tmpoutbuf in seekto_fdout\n"); + print_err("out_ofs %lld out_len %lld hist_ofs %lld rel_ofs %lld\n", + control->out_ofs, control->out_len, control->hist_ofs, control->rel_ofs); + print_err("Trying to seek outside tmpoutbuf to %lld in seekto_fdout\n", control->out_ofs); return -1; } return pos; @@ -102,7 +104,9 @@ static i64 seekto_fdhist(rzip_control *control, i64 pos) if (control->hist_ofs > control->out_len) control->out_len = control->hist_ofs; if (unlikely(control->hist_ofs < 0 || control->hist_ofs > control->out_maxlen)) { - print_err("Trying to seek outside tmpoutbuf in seekto_fdhist\n"); + print_err("out_ofs %lld out_len %lld hist_ofs %lld rel_ofs %lld\n", + control->out_ofs, control->out_len, control->hist_ofs, control->rel_ofs); + print_err("Trying to seek outside tmpoutbuf to %lld in seekto_fdhist\n", control->hist_ofs); return -1; } return pos; @@ -314,12 +318,10 @@ i64 runzip_fd(rzip_control *control, int fd_in, int fd_out, int fd_hist, i64 exp do { total += runzip_chunk(control, fd_in, fd_out, fd_hist, expected_size, total); - if (STDOUT) { - if (TMP_OUTBUF) - flush_stdout(control); - else - dump_tmpoutfile(control, fd_out); - } + if (TMP_OUTBUF) + flush_tmpoutbuf(control); + else if (STDOUT) + dump_tmpoutfile(control, fd_out); } while (total < expected_size || (!expected_size && !control->eof)); gettimeofday(&end,NULL); @@ -358,6 +360,8 @@ i64 runzip_fd(rzip_control *control, int fd_in, int fd_out, int fd_hist, i64 exp FILE *md5_fstream; int i, j; + if (TMP_OUTBUF) + close_tmpoutbuf(control); memcpy(md5_stored, md5_resblock, MD5_DIGEST_SIZE); if (unlikely(seekto_fdhist(control, 0) == -1)) fatal("Failed to seekto_fdhist in runzip_fd\n"); diff --git a/rzip.c b/rzip.c index 9725d5d..ae17097 100644 --- a/rzip.c +++ b/rzip.c @@ -979,7 +979,7 @@ retry: fatal("Failed to write md5 in rzip_fd\n"); if (TMP_OUTBUF) - flush_stdout(control); + flush_tmpoutbuf(control); gettimeofday(¤t, NULL); if (STDIN) diff --git a/stream.c b/stream.c index 1a028ad..723f947 100644 --- a/stream.c +++ b/stream.c @@ -635,21 +635,6 @@ out: const i64 one_g = 1000 * 1024 * 1024; -static void write_fdout(rzip_control *control, void *buf, i64 len) -{ - uchar *offset_buf = buf; - ssize_t ret; - - while (len > 0) { - ret = MIN(len, one_g); - ret = write(control->fd_out, offset_buf, (size_t)ret); - if (unlikely(ret <= 0)) - fatal("Failed to write to fd_out in write_fdout\n"); - len -= ret; - offset_buf += ret; - } -} - /* Look at whether we're writing to a ram location or physical files and write * the data accordingly. */ ssize_t put_fdout(rzip_control *control, void *offset_buf, ssize_t ret) @@ -661,9 +646,8 @@ ssize_t put_fdout(rzip_control *control, void *offset_buf, ssize_t ret) /* The data won't fit in a temporary output buffer so we have * to fall back to temporary files. */ print_verbose("Unable to decompress entirely in ram, will use physical files\n"); - control->flags &= ~FLAG_TMP_OUTBUF; write_fdout(control, control->tmp_outbuf, control->out_len); - free(control->tmp_outbuf); + close_tmpoutbuf(control); write_fdout(control, offset_buf, ret); return ret; } @@ -1139,7 +1123,7 @@ retry: if (TMP_OUTBUF) { if (!control->magic_written) write_stdout_header(control); - flush_stdout(control); + flush_tmpoutbuf(control); } /* Write chunk bytes of this block */