aboutsummaryrefslogtreecommitdiff
path: root/src/lzma
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lzma/args.c35
-rw-r--r--src/lzma/args.h4
-rw-r--r--src/lzma/options.c14
-rw-r--r--src/lzma/process.c88
-rw-r--r--src/lzmadec/lzmadec.c157
5 files changed, 112 insertions, 186 deletions
diff --git a/src/lzma/args.c b/src/lzma/args.c
index a4764032..30df4522 100644
--- a/src/lzma/args.c
+++ b/src/lzma/args.c
@@ -39,8 +39,8 @@ bool opt_force = false;
bool opt_keep_original = false;
bool opt_preserve_name = false;
-lzma_check_type opt_check = LZMA_CHECK_CRC64;
-lzma_options_filter opt_filters[8];
+lzma_check opt_check = LZMA_CHECK_CRC64;
+lzma_filter opt_filters[8];
// We don't modify or free() this, but we need to assign it in some
// non-const pointers.
@@ -61,6 +61,7 @@ enum {
OPT_SPARC,
OPT_DELTA,
OPT_LZMA,
+ OPT_LZMA2,
OPT_FILES,
OPT_FILES0,
@@ -108,6 +109,7 @@ static const struct option long_opts[] = {
{ "sparc", no_argument, NULL, OPT_SPARC },
{ "delta", optional_argument, NULL, OPT_DELTA },
{ "lzma", optional_argument, NULL, OPT_LZMA },
+ { "lzma2", optional_argument, NULL, OPT_LZMA2 },
// Other
{ "format", required_argument, NULL, 'F' },
@@ -141,6 +143,7 @@ add_filter(lzma_vli id, const char *opt_str)
break;
case LZMA_FILTER_LZMA:
+ case LZMA_FILTER_LZMA2:
opt_filters[filter_count].options
= parse_options_lzma(opt_str);
break;
@@ -301,6 +304,10 @@ parse_real(int argc, char **argv)
add_filter(LZMA_FILTER_LZMA, optarg);
break;
+ case OPT_LZMA2:
+ add_filter(LZMA_FILTER_LZMA2, optarg);
+ break;
+
// Other
// --format
@@ -445,7 +452,8 @@ static void
set_compression_settings(void)
{
if (filter_count == 0) {
- opt_filters[0].id = LZMA_FILTER_LZMA;
+ opt_filters[0].id = opt_header == HEADER_ALONE
+ ? LZMA_FILTER_LZMA : LZMA_FILTER_LZMA2;
opt_filters[0].options = (lzma_options_lzma *)(
lzma_preset_lzma + preset_number);
filter_count = 1;
@@ -463,13 +471,15 @@ set_compression_settings(void)
my_exit(ERROR);
}
- const uint32_t memory_limit = opt_memory / (1024 * 1024) + 1;
- uint32_t memory_usage = lzma_memory_usage(opt_filters, true);
+ uint64_t memory_usage = lzma_memusage_encoder(opt_filters);
+ /* opt_mode == MODE_COMPRESS
+ ? lzma_memusage_encoder(opt_filters)
+ : lzma_memusage_decoder(opt_filters); */
// Don't go over the memory limits when the default
// setting is used.
if (preset_default) {
- while (memory_usage > memory_limit) {
+ while (memory_usage > opt_memory) {
if (preset_number == 0) {
errmsg(V_ERROR, _("Memory usage limit is too "
"small for any internal "
@@ -481,11 +491,10 @@ set_compression_settings(void)
opt_filters[0].options = (lzma_options_lzma *)(
lzma_preset_lzma
+ preset_number);
- memory_usage = lzma_memory_usage(opt_filters,
- true);
+ memory_usage = lzma_memusage_encoder(opt_filters);
}
} else {
- if (memory_usage > memory_limit) {
+ if (memory_usage > opt_memory) {
errmsg(V_ERROR, _("Memory usage limit is too small "
"for the given filter setup"));
my_exit(ERROR);
@@ -494,12 +503,8 @@ set_compression_settings(void)
// Limit the number of worked threads so that memory usage
// limit isn't exceeded.
- // FIXME: Probably should use bytes instead of mebibytes for
- // memory_usage and memory_limit.
- if (memory_usage == 0)
- memory_usage = 1;
-
- size_t thread_limit = memory_limit / memory_usage;
+ assert(memory_usage > 0);
+ size_t thread_limit = opt_memory / memory_usage;
if (thread_limit == 0)
thread_limit = 1;
diff --git a/src/lzma/args.h b/src/lzma/args.h
index c6098558..b60e7545 100644
--- a/src/lzma/args.h
+++ b/src/lzma/args.h
@@ -52,8 +52,8 @@ extern bool opt_preserve_name;
extern enum tool_mode opt_mode;
extern enum header_type opt_header;
-extern lzma_check_type opt_check;
-extern lzma_options_filter opt_filters[8];
+extern lzma_check opt_check;
+extern lzma_filter opt_filters[8];
extern const char *stdin_filename;
diff --git a/src/lzma/options.c b/src/lzma/options.c
index c82cb1a0..b2ec200e 100644
--- a/src/lzma/options.c
+++ b/src/lzma/options.c
@@ -299,9 +299,9 @@ extern lzma_options_lzma *
parse_options_lzma(const char *str)
{
static const name_id_map modes[] = {
- { "fast", LZMA_MODE_FAST },
- { "best", LZMA_MODE_BEST },
- { NULL, 0 }
+ { "fast", LZMA_MODE_FAST },
+ { "normal", LZMA_MODE_NORMAL },
+ { NULL, 0 }
};
static const name_id_map mfs[] = {
@@ -317,9 +317,9 @@ parse_options_lzma(const char *str)
{ "dict", NULL, LZMA_DICTIONARY_SIZE_MIN,
LZMA_DICTIONARY_SIZE_MAX },
{ "lc", NULL, LZMA_LITERAL_CONTEXT_BITS_MIN,
- LZMA_LITERAL_CONTEXT_BITS_MAX },
+ LZMA_LITERAL_CONTEXT_BITS_MAX },
{ "lp", NULL, LZMA_LITERAL_POS_BITS_MIN,
- LZMA_LITERAL_POS_BITS_MAX },
+ LZMA_LITERAL_POS_BITS_MAX },
{ "pb", NULL, LZMA_POS_BITS_MIN, LZMA_POS_BITS_MAX },
{ "mode", modes, 0, 0 },
{ "fb", NULL, LZMA_FAST_BYTES_MIN, LZMA_FAST_BYTES_MAX },
@@ -334,7 +334,9 @@ parse_options_lzma(const char *str)
.literal_context_bits = LZMA_LITERAL_CONTEXT_BITS_DEFAULT,
.literal_pos_bits = LZMA_LITERAL_POS_BITS_DEFAULT,
.pos_bits = LZMA_POS_BITS_DEFAULT,
- .mode = LZMA_MODE_BEST,
+ .preset_dictionary = NULL,
+ .persistent = false,
+ .mode = LZMA_MODE_NORMAL,
.fast_bytes = LZMA_FAST_BYTES_DEFAULT,
.match_finder = LZMA_MF_BT4,
.match_finder_cycles = 0,
diff --git a/src/lzma/process.c b/src/lzma/process.c
index c180caf7..b4387709 100644
--- a/src/lzma/process.c
+++ b/src/lzma/process.c
@@ -63,12 +63,7 @@ process_init(void)
}
for (size_t i = 0; i < opt_threads; ++i)
- threads[i] = (thread_data){
- .strm = LZMA_STREAM_INIT_VAR,
- .options = NULL,
- .pair = NULL,
- .in_use = false,
- };
+ memzero(&threads[i], sizeof(threads[0]));
if (pthread_attr_init(&thread_attr)
|| pthread_attr_setdetachstate(
@@ -169,7 +164,9 @@ single_init(thread_data *t)
}
} else {
// TODO Restrict file format if requested on the command line.
- ret = lzma_auto_decoder(&t->strm);
+ ret = lzma_auto_decoder(&t->strm, opt_memory,
+ LZMA_WARN_UNSUPPORTED_CHECK
+ | LZMA_CONCATENATED);
}
if (ret != LZMA_OK) {
@@ -185,36 +182,6 @@ single_init(thread_data *t)
}
-static lzma_ret
-single_skip_padding(thread_data *t, uint8_t *in_buf)
-{
- // Handle decoding of concatenated Streams. There can be arbitrary
- // number of nul-byte padding between the Streams, which must be
- // ignored.
- //
- // NOTE: Concatenating LZMA_Alone files works only if at least
- // one of lc, lp, and pb is non-zero. Using the concatenation
- // on LZMA_Alone files is strongly discouraged.
- while (true) {
- while (t->strm.avail_in > 0) {
- if (*t->strm.next_in != '\0')
- return LZMA_OK;
-
- ++t->strm.next_in;
- --t->strm.avail_in;
- }
-
- if (t->pair->src_eof)
- return LZMA_STREAM_END;
-
- t->strm.next_in = in_buf;
- t->strm.avail_in = io_read(t->pair, in_buf, BUFSIZ);
- if (t->strm.avail_in == SIZE_MAX)
- return LZMA_DATA_ERROR;
- }
-}
-
-
static void *
single(thread_data *t)
{
@@ -227,10 +194,11 @@ single(thread_data *t)
uint8_t in_buf[BUFSIZ];
uint8_t out_buf[BUFSIZ];
lzma_action action = LZMA_RUN;
- lzma_ret ret;
bool success = false;
t->strm.avail_in = 0;
+ t->strm.next_out = out_buf;
+ t->strm.avail_out = BUFSIZ;
while (!user_abort) {
if (t->strm.avail_in == 0 && !t->pair->src_eof) {
@@ -239,48 +207,36 @@ single(thread_data *t)
if (t->strm.avail_in == SIZE_MAX)
break;
- else if (t->pair->src_eof
- && opt_mode == MODE_COMPRESS)
+
+ if (t->pair->src_eof)
action = LZMA_FINISH;
}
- t->strm.next_out = out_buf;
- t->strm.avail_out = BUFSIZ;
-
- ret = lzma_code(&t->strm, action);
+ const lzma_ret ret = lzma_code(&t->strm, action);
- if (opt_mode != MODE_TEST)
+ if ((t->strm.avail_out == 0 || ret != LZMA_OK)
+ && opt_mode != MODE_TEST) {
if (io_write(t->pair, out_buf,
BUFSIZ - t->strm.avail_out))
break;
+ t->strm.next_out = out_buf;
+ t->strm.avail_out = BUFSIZ;
+ }
+
if (ret != LZMA_OK) {
if (ret == LZMA_STREAM_END) {
- if (opt_mode == MODE_COMPRESS) {
- assert(t->pair->src_eof);
- success = true;
- break;
- }
-
- // Support decoding concatenated .lzma files.
- ret = single_skip_padding(t, in_buf);
-
- if (ret == LZMA_STREAM_END) {
- assert(t->pair->src_eof);
- success = true;
- break;
- }
-
- if (ret == LZMA_OK && !single_init(t))
- continue;
-
- break;
-
+ // FIXME !!! This doesn't work when decoding
+ // LZMA_Alone files, because LZMA_Alone decoder
+ // doesn't wait for LZMA_FINISH.
+ assert(t->pair->src_eof);
+ success = true;
} else {
errmsg(V_ERROR, "%s: %s", t->pair->src_name,
str_strm_error(ret));
- break;
}
+
+ break;
}
}
diff --git a/src/lzmadec/lzmadec.c b/src/lzmadec/lzmadec.c
index 1fc561b7..ed5947ad 100644
--- a/src/lzmadec/lzmadec.c
+++ b/src/lzmadec/lzmadec.c
@@ -65,14 +65,7 @@ static uint8_t out_buf[BUFSIZ];
static lzma_stream strm = LZMA_STREAM_INIT;
/// Number of bytes to use memory at maximum
-static size_t mem_limit;
-
-/// Memory allocation hooks
-static lzma_allocator allocator = {
- .alloc = (void *(*)(void *, size_t, size_t))(&lzma_memlimit_alloc),
- .free = (void (*)(void *, void *))(&lzma_memlimit_free),
- .opaque = NULL,
-};
+static size_t memlimit;
/// Program name to be shown in error messages
static const char *argv0;
@@ -116,7 +109,7 @@ help(void)
" MiB of memory at maximum.\n"
"\n"
"Report bugs to <" PACKAGE_BUGREPORT "> (in English or Finnish).\n",
- argv0, ((uint64_t)(mem_limit) + 512 * 1024) / (1024 * 1024));
+ argv0, ((uint64_t)(memlimit) + 512 * 1024) / (1024 * 1024));
// Using PRIu64 above instead of %zu to support pre-C99 libc.
exit(0);
}
@@ -148,7 +141,7 @@ version(void)
/// Finds out the amount of physical memory in the system, and sets
/// a default memory usage limit.
static void
-set_default_mem_limit(void)
+set_default_memlimit(void)
{
uint64_t mem = physmem();
if (mem != 0) {
@@ -159,10 +152,10 @@ set_default_mem_limit(void)
mem = SIZE_MAX;
#endif
- mem_limit = mem / 3;
+ memlimit = mem / 3;
} else {
// Cannot autodetect, use 10 MiB as the default limit.
- mem_limit = (1U << 23) + (1U << 21);
+ memlimit = (1U << 23) + (1U << 21);
}
return;
@@ -272,7 +265,7 @@ parse_options(int argc, char **argv)
break;
case 'M':
- mem_limit = str_to_size(optarg);
+ memlimit = str_to_size(optarg);
break;
case 'h':
@@ -309,19 +302,20 @@ parse_options(int argc, char **argv)
static void
init(void)
{
+ const uint32_t flags = LZMA_WARN_UNSUPPORTED_CHECK | LZMA_CONCATENATED;
lzma_ret ret;
switch (format_type) {
case FORMAT_AUTO:
- ret = lzma_auto_decoder(&strm);
+ ret = lzma_auto_decoder(&strm, memlimit, flags);
break;
case FORMAT_NATIVE:
- ret = lzma_stream_decoder(&strm);
+ ret = lzma_stream_decoder(&strm, memlimit, flags);
break;
case FORMAT_ALONE:
- ret = lzma_alone_decoder(&strm);
+ ret = lzma_alone_decoder(&strm, memlimit);
break;
default:
@@ -345,50 +339,6 @@ init(void)
static void
-read_input(void)
-{
- strm.next_in = in_buf;
- strm.avail_in = fread(in_buf, 1, BUFSIZ, file);
-
- if (ferror(file)) {
- // POSIX says that fread() sets errno if an error occurred.
- // ferror() doesn't touch errno.
- fprintf(stderr, "%s: %s: Error reading input file: %s\n",
- argv0, filename, strerror(errno));
- exit(ERROR);
- }
-
- return;
-}
-
-
-static bool
-skip_padding(void)
-{
- // Handle concatenated Streams. There can be arbitrary number of
- // nul-byte padding between the Streams, which must be ignored.
- //
- // NOTE: Concatenating LZMA_Alone files works only if at least
- // one of lc, lp, and pb is non-zero. Using the concatenation
- // on LZMA_Alone files is strongly discouraged.
- while (true) {
- while (strm.avail_in > 0) {
- if (*strm.next_in != '\0')
- return true;
-
- ++strm.next_in;
- --strm.avail_in;
- }
-
- if (feof(file))
- return false;
-
- read_input();
- }
-}
-
-
-static void
uncompress(void)
{
if (file == stdin && !force && isatty(STDIN_FILENO)) {
@@ -400,44 +350,65 @@ uncompress(void)
}
init();
+
strm.avail_in = 0;
+ strm.next_out = out_buf;
+ strm.avail_out = BUFSIZ;
+
+ lzma_action action = LZMA_RUN;
while (true) {
- if (strm.avail_in == 0)
- read_input();
+ if (strm.avail_in == 0) {
+ strm.next_in = in_buf;
+ strm.avail_in = fread(in_buf, 1, BUFSIZ, file);
+
+ if (ferror(file)) {
+ // POSIX says that fread() sets errno if
+ // an error occurred. ferror() doesn't
+ // touch errno.
+ fprintf(stderr, "%s: %s: Error reading "
+ "input file: %s\n",
+ argv0, filename,
+ strerror(errno));
+ exit(ERROR);
+ }
- strm.next_out = out_buf;
- strm.avail_out = BUFSIZ;
+ if (feof(file))
+ action = LZMA_FINISH;
+ }
- const lzma_ret ret = lzma_code(&strm, LZMA_RUN);
+ const lzma_ret ret = lzma_code(&strm, action);
// Write and check write error before checking decoder error.
// This way as much data as possible gets written to output
- // even if decoder detected an error. Checking write error
- // needs to be done before checking decoder error due to
- // how concatenated Streams are handled a few lines later.
- const size_t write_size = BUFSIZ - strm.avail_out;
- if (fwrite(out_buf, 1, write_size, stdout) != write_size) {
- // Wouldn't be a surprise if writing to stderr would
- // fail too but at least try to show an error message.
- fprintf(stderr, "%s: Cannot write to "
- "standard output: %s\n", argv0,
- strerror(errno));
- exit(ERROR);
+ // even if decoder detected an error.
+ if (strm.avail_out == 0 || ret != LZMA_OK) {
+ const size_t write_size = BUFSIZ - strm.avail_out;
+
+ if (fwrite(out_buf, 1, write_size, stdout)
+ != write_size) {
+ // Wouldn't be a surprise if writing to stderr
+ // would fail too but at least try to show an
+ // error message.
+ fprintf(stderr, "%s: Cannot write to "
+ "standard output: %s\n", argv0,
+ strerror(errno));
+ exit(ERROR);
+ }
+
+ strm.next_out = out_buf;
+ strm.avail_out = BUFSIZ;
}
if (ret != LZMA_OK) {
- if (ret == LZMA_STREAM_END) {
- if (skip_padding()) {
- init();
- continue;
- }
-
+ // FIXME !!! Doesn't work with LZMA_Alone for the
+ // same reason as in process.c.
+ if (ret == LZMA_STREAM_END)
return;
- }
fprintf(stderr, "%s: %s: ", argv0, filename);
+ // FIXME Add LZMA_*_CHECK and LZMA_FORMAT_ERROR.
switch (ret) {
case LZMA_DATA_ERROR:
fprintf(stderr, "File is corrupt\n");
@@ -452,6 +423,11 @@ uncompress(void)
fprintf(stderr, "%s\n", strerror(ENOMEM));
exit(ERROR);
+ case LZMA_MEMLIMIT_ERROR:
+ fprintf(stderr, "Memory usage limit "
+ "reached\n");
+ exit(ERROR);
+
case LZMA_BUF_ERROR:
fprintf(stderr, "Unexpected end of input\n");
exit(ERROR);
@@ -479,23 +455,12 @@ main(int argc, char **argv)
{
argv0 = argv[0];
- set_default_mem_limit();
+ set_default_memlimit();
parse_options(argc, argv);
lzma_init_decoder();
- lzma_memlimit *mem_limiter = lzma_memlimit_create(mem_limit);
- if (mem_limiter == NULL) {
- fprintf(stderr, "%s: %s\n", argv0, strerror(ENOMEM));
- exit(ERROR);
- }
-
- assert(lzma_memlimit_count(mem_limiter) == 0);
-
- allocator.opaque = mem_limiter;
- strm.allocator = &allocator;
-
#ifdef WIN32
setmode(fileno(stdin), O_BINARY);
setmode(fileno(stdout), O_BINARY);
@@ -531,8 +496,6 @@ main(int argc, char **argv)
// Free the memory only when debugging. Freeing wastes some time,
// but allows detecting possible memory leaks with Valgrind.
lzma_end(&strm);
- assert(lzma_memlimit_count(mem_limiter) == 0);
- lzma_memlimit_end(mem_limiter, false);
#endif
return exit_status;