aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Matuska <mm@FreeBSD.org>2010-10-11 12:43:51 +0000
committerMartin Matuska <mm@FreeBSD.org>2010-10-11 12:43:51 +0000
commit42ec4a8d7015d9854b3992e7f6dfa94a99a60fd6 (patch)
tree5712a6766741c007b4f2fc14a8870788048bec60
parentc19dc90688c2dacd857449ee2edceb09c3811e20 (diff)
downloadsrc-42ec4a8d7015d9854b3992e7f6dfa94a99a60fd6.tar.gz
src-42ec4a8d7015d9854b3992e7f6dfa94a99a60fd6.zip
Vendor import of xz (stripped)vendor/xz/20101010
Git revision: d52b411716a614c202e89ba732492efb9916cd3f Approved by: delphij (mentor)
Notes
Notes: svn path=/vendor/xz/dist/; revision=213688 svn path=/vendor/xz/20101010/; revision=213689; tag=vendor/xz/20101010
-rw-r--r--ChangeLog814
-rw-r--r--FREEBSD-Xlist37
-rw-r--r--FREEBSD-upgrade28
-rw-r--r--README98
-rw-r--r--THANKS6
-rw-r--r--po/LINGUAS2
-rw-r--r--po/POTFILES.in3
-rw-r--r--po/cs.po717
-rw-r--r--po/de.po903
-rw-r--r--po/it.po902
-rw-r--r--src/common/sysdefs.h16
-rw-r--r--src/common/tuklib_cpucores.c14
-rw-r--r--src/common/tuklib_gettext.h4
-rw-r--r--src/common/tuklib_mbstr.h66
-rw-r--r--src/common/tuklib_mbstr_fw.c31
-rw-r--r--src/common/tuklib_mbstr_width.c64
-rw-r--r--src/common/tuklib_physmem.c33
-rw-r--r--src/liblzma/api/lzma.h13
-rw-r--r--src/liblzma/api/lzma/index.h7
-rw-r--r--src/liblzma/api/lzma/lzma.h10
-rw-r--r--src/liblzma/api/lzma/subblock.h200
-rw-r--r--src/liblzma/api/lzma/vli.h11
-rw-r--r--src/liblzma/common/block_buffer_encoder.c2
-rw-r--r--src/liblzma/common/block_util.c6
-rw-r--r--src/liblzma/common/chunk_size.c67
-rw-r--r--src/liblzma/common/common.c2
-rw-r--r--src/liblzma/common/common.h6
-rw-r--r--src/liblzma/common/filter_common.c9
-rw-r--r--src/liblzma/common/filter_decoder.c16
-rw-r--r--src/liblzma/common/filter_encoder.c12
-rw-r--r--src/liblzma/common/stream_buffer_encoder.c2
-rw-r--r--src/liblzma/delta/delta_encoder.c2
-rw-r--r--src/liblzma/lz/lz_decoder.c7
-rw-r--r--src/liblzma/lz/lz_decoder.h2
-rw-r--r--src/liblzma/lz/lz_encoder.c15
-rw-r--r--src/liblzma/lz/lz_encoder.h2
-rw-r--r--src/liblzma/lz/lz_encoder_mf.c4
-rw-r--r--src/liblzma/lzma/lzma2_encoder.c2
-rw-r--r--src/liblzma/lzma/lzma_encoder_optimum_fast.c2
-rw-r--r--src/liblzma/lzma/lzma_encoder_optimum_normal.c14
-rw-r--r--src/liblzma/lzma/lzma_encoder_presets.c31
-rw-r--r--src/liblzma/subblock/subblock_decoder.c630
-rw-r--r--src/liblzma/subblock/subblock_decoder.h22
-rw-r--r--src/liblzma/subblock/subblock_decoder_helper.c70
-rw-r--r--src/liblzma/subblock/subblock_decoder_helper.h29
-rw-r--r--src/liblzma/subblock/subblock_encoder.c984
-rw-r--r--src/liblzma/subblock/subblock_encoder.h21
-rw-r--r--src/lzmainfo/lzmainfo.127
-rw-r--r--src/lzmainfo/lzmainfo.c13
-rw-r--r--src/xz/args.c107
-rw-r--r--src/xz/args.h2
-rw-r--r--src/xz/coder.c62
-rw-r--r--src/xz/coder.h4
-rw-r--r--src/xz/file_io.c15
-rw-r--r--src/xz/hardware.c98
-rw-r--r--src/xz/hardware.h23
-rw-r--r--src/xz/list.c794
-rw-r--r--src/xz/main.c40
-rw-r--r--src/xz/message.c336
-rw-r--r--src/xz/message.h22
-rw-r--r--src/xz/options.c78
-rw-r--r--src/xz/options.h7
-rw-r--r--src/xz/private.h6
-rw-r--r--src/xz/signals.c25
-rw-r--r--src/xz/signals.h4
-rw-r--r--src/xz/util.c146
-rw-r--r--src/xz/util.h7
-rw-r--r--src/xz/xz.12354
-rw-r--r--src/xzdec/xzdec.182
-rw-r--r--src/xzdec/xzdec.c167
70 files changed, 6535 insertions, 3822 deletions
diff --git a/ChangeLog b/ChangeLog
index a3cb84ad49bd..c42458decf3c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,817 @@
+commit d52b411716a614c202e89ba732492efb9916cd3f
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sun Oct 10 17:58:58 2010 +0300
+
+ xz: Use "%"PRIu32 instead of "%d" in a format string.
+
+commit ae74d1bdeb075c3beefe76e1136c5741804e7e91
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sun Oct 10 17:43:26 2010 +0300
+
+ test_files.sh: Fix the first line.
+
+ For some reason this prevented running the test only
+ on OS/2 and even on that it broke only recently.
+
+ Thanks to Elbert Pol.
+
+commit d492b80ddd6f9a13419de6d102df7374d8f448e8
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sun Oct 10 16:49:01 2010 +0300
+
+ lzmainfo: Use "%"PRIu32 instead of "%u" for uint32_t.
+
+commit 825e859a9054bd91202e5723c41a17e72f63040a
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sun Oct 10 16:47:01 2010 +0300
+
+ lzmainfo: Use fileno(stdin) instead of STDIN_FILENO.
+
+commit acbc4cdecbeec2a4dfaac04f185ece49b2ff17c8
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sat Oct 9 23:20:51 2010 +0300
+
+ lzmainfo: Use setmode() on DOS-like systems.
+
+commit ef364d3abc5647111c5424ea0d83a567e184a23b
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sat Oct 9 21:51:03 2010 +0300
+
+ OS/2 and DOS: Be less verbose on signals.
+
+ Calling raise() to kill xz when user has pressed C-c
+ is a bit verbose on OS/2 and DOS/DJGPP. Instead of
+ calling raise(), set only the exit status to 1.
+
+commit 5629c4be07b6c67e79842b2569da1cedc9c0d69a
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sat Oct 9 19:28:49 2010 +0300
+
+ DOS: Update the Makefile, config.h and README.
+
+ This is now simpler and builds only xz.exe.
+
+commit f25a77e6b9bc48a243ddfbbd755b7960eec7e0ac
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sat Oct 9 18:57:55 2010 +0300
+
+ Windows: Put some license info into README-Windows.txt.
+
+commit e75100f549f85d231df25c07aa94d63e78e2d668
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sat Oct 9 18:57:04 2010 +0300
+
+ Windows: Fix a diagnostics bug in build.bash.
+
+commit efeb998a2b1025df1c1d202cc7d21d866cd1c336
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sat Oct 9 13:02:15 2010 +0300
+
+ lzmainfo: Add Windows resource file.
+
+commit 389d418445f1623593dfdbba55d52fbb6d1205f5
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sat Oct 9 12:57:25 2010 +0300
+
+ Add missing public domain notice to lzmadec_w32res.rc.
+
+commit 6389c773a4912dd9f111256d74ba1605230a7957
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sat Oct 9 12:52:12 2010 +0300
+
+ Windows: Update common_w32res.rc.
+
+commit 71275457ca24c9b01721f5cfc3638cf094daf454
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sat Oct 9 12:27:08 2010 +0300
+
+ Windows: Make build.bash prefer MinGW-w32 over MinGW.
+
+ This is simply for licensing reasons. The 64-bit version
+ will be built with MinGW-w64 anyway (at least for now),
+ so using it also for 32-bit build allows using the same
+ copyright notice about the MinGW-w64/w32 runtime.
+
+ Note that using MinGW would require a copyright notice too,
+ because its runtime is not in the public domain either even
+ though MinGW's home page claims that it is public domain.
+ See <http://marc.info/?l=mingw-users&m=126489506214078>.
+
+commit 3ac35719d8433af937af6491383d4a50e343099b
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sat Oct 9 11:33:21 2010 +0300
+
+ Windows: Copy COPYING-Windows.txt (if it exists) to the package.
+
+ Also, put README-Windows.txt to the doc directory like
+ the other documentation files.
+
+commit 7b5db576fd7a4a67813b8437a9ccd4dbc94bbaae
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Fri Oct 8 21:42:37 2010 +0300
+
+ Windows: Fix build.bash again.
+
+ 630a8beda34af0ac153c8051b1bf01230558e422 wasn't good.
+
+commit d3cd7abe85ec7c2f46cf198b15c00d5d119df3dd
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Fri Oct 8 16:53:20 2010 +0300
+
+ Use LZMA_VERSION_STRING instead of PACKAGE_VERSION.
+
+ Those are the same thing, and the former makes it a bit
+ easier to build the code with other build systems, because
+ one doesn't need to update the version number into custom
+ config.h.
+
+ This change affects only lzmainfo. Other tools were already
+ using LZMA_VERSION_STRING.
+
+commit 084c60d318f2dbaef4078d9b100b4a373d0c3a7f
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Fri Oct 8 15:59:25 2010 +0300
+
+ configure.ac: Remove two unused defines.
+
+commit 11f51b6714357cb67ec7e56ed9575c199b5581fe
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Fri Oct 8 15:32:29 2010 +0300
+
+ Make tests accommodate missing xz or xzdec.
+
+commit b1c7368f95e93ccdefdd0748e04398c26766f47f
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Fri Oct 8 15:25:45 2010 +0300
+
+ Build: Add options to disable individual command line tools.
+
+commit 630a8beda34af0ac153c8051b1bf01230558e422
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Thu Oct 7 00:44:53 2010 +0300
+
+ Windows: Make build.bash work without --enable-dynamic=no.
+
+commit f9907503f882a745dce9d84c2968f6c175ba966a
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Tue Oct 5 14:13:16 2010 +0300
+
+ Build: Remove the static/dynamic tricks.
+
+ Most distros want xz linked against shared liblzma, so
+ it doesn't help much to require --enable-dynamic for that.
+ Those who want to avoid PIC on x86-32 to get better
+ performance, can still do it e.g. by using --disable-shared
+ to compile xz and then another pass to compile shared liblzma.
+
+ Part of these static/dynamic tricks were needed for Windows
+ in the past. Nowadays we rely on GCC and binutils to do the
+ right thing with auto-import. If the Autotooled build system
+ needs to support some other toolchain on Windows in the future,
+ this may need some rethinking.
+
+commit fda4724d8114fccfa31c1839c15479f350c2fb4c
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Tue Oct 5 12:18:58 2010 +0300
+
+ configure.ac: Silence a warning from Autoconf 2.68.
+
+commit 80b5675fa62c87426fe86f8fcd20feeabc4361b9
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Mon Oct 4 19:43:01 2010 +0300
+
+ A few more languages files to the xz man page.
+
+ Thanks to Jonathan Nieder.
+
+commit f9722dbeca4dc4c43cfd15d122dafaac50b0a0bb
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sat Oct 2 12:07:33 2010 +0300
+
+ Update the FAQ.
+
+commit 61ae593661e8dc402394e84d567ca2044a51572b
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sat Oct 2 11:38:20 2010 +0300
+
+ liblzma: Small fixes to comments in the API headers.
+
+commit 9166682dc601fd42c1b9510572e3f917d18de504
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Tue Sep 28 11:40:12 2010 +0300
+
+ Create the PDF versions of the man pages better.
+
+commit 17d3c61edd35de8fa884944fc70d1db86daa5dd8
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Tue Sep 28 10:59:53 2010 +0300
+
+ Move version.sh to build-aux.
+
+commit 84af9d8770451339a692e9b70f96cf56156a6069
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Tue Sep 28 10:53:02 2010 +0300
+
+ Update .gitignore.
+
+commit 31575a449ac64c523da3bab8d0c0b522cdc7c780
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Tue Sep 28 01:17:14 2010 +0300
+
+ Fix accomodate -> accommodate on the xz man page.
+
+commit cec0ddc8ec4ce81685a51998b978e22167e461f9
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Mon Sep 27 23:29:34 2010 +0300
+
+ Major man page updates.
+
+ Lots of content was updated on the xz man page.
+
+ Technical improvements:
+ - Start a new sentence on a new line.
+ - Use fairly short lines.
+ - Use constant-width font for examples (where supported).
+ - Some minor cleanups.
+
+ Thanks to Jonathan Nieder for some language fixes.
+
+commit 075257ab0416a0603be930082e31a5703e4ba345
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sun Sep 26 18:10:31 2010 +0300
+
+ Fix the preset -3e.
+
+ depth=0 was missing.
+
+commit 2577da9ebdba13fbe99ae5ee8bde35f7ed60f6d1
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Thu Sep 23 14:03:10 2010 +0300
+
+ Add translations.bash and translation notes to README.
+
+ translations.bash prints some messages from xz, which
+ hopefully makes it a bit easier to test translations.
+
+commit a3c5997c57e5b1a20aae6d1071b584b4f17d0b23
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Fri Sep 17 22:14:30 2010 +0300
+
+ xz: Update the Czech translation.
+
+ Thanks to Marek Černocký.
+
+commit a1766af582dc23fddd9da1eeb4b9d61e3eb4c2e6
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Thu Sep 16 23:40:41 2010 +0300
+
+ xz: Add Italian translation.
+
+ Thanks to Milo Casagrande and Lorenzo De Liso.
+
+commit 21088018554e2b0e02914205377ceb6e34a090bd
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Wed Sep 15 00:34:13 2010 +0300
+
+ xz: Edit a translators comment.
+
+commit be16e28ece1b492b8f93382b7fa1cc4da23c6ff6
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Tue Sep 14 22:47:14 2010 +0300
+
+ xz: Add German translation.
+
+ Thanks to Andre Noll.
+
+commit e23ea74f3240e6b69683f9e69d1716e0f9e9092b
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Fri Sep 10 14:30:25 2010 +0300
+
+ Updated README.
+
+commit 8dad2fd69336985adb9f774fa96dc9c0efcb5a71
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Fri Sep 10 14:30:07 2010 +0300
+
+ Updated INSTALL.
+
+commit 0b5f07fe3728c27cce416ddc40f7e4803ae96ac2
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Fri Sep 10 14:26:20 2010 +0300
+
+ Updated the git repository address in ChangeLog.
+
+commit a8760203f93a69bc39fd14520a6e9e7b7d70be06
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Fri Sep 10 14:09:33 2010 +0300
+
+ xz: Add a comment to translators about "literal context bits".
+
+commit bb0b1004f83cdc4d309e1471c2ecaf9f95ce60c5
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Fri Sep 10 10:30:33 2010 +0300
+
+ xz: Multiple fixes.
+
+ The code assumed that printing numbers with thousand separators
+ and decimal points would always produce only US-ASCII characters.
+ This was used for buffer sizes (with snprintf(), no overflows)
+ and aligning columns of the progress indicator and --list. That
+ assumption was wrong (e.g. LC_ALL=fi_FI.UTF-8 with glibc), so
+ multibyte character support was added in this commit. The old
+ way is used if the operating system doesn't have enough multibyte
+ support (e.g. lacks wcwidth()).
+
+ The sizes of buffers were increased to accomodate multibyte
+ characters. I don't know how big they should be exactly, but
+ they aren't used for anything critical, so it's not too bad.
+ If they still aren't big enough, I hopefully get a bug report.
+ snprintf() takes care of avoiding buffer overflows.
+
+ Some static buffers were replaced with buffers allocated on
+ stack. double_to_str() was removed. uint64_to_str() and
+ uint64_to_nicestr() now share the static buffer and test
+ for thousand separator support.
+
+ Integrity check names "None" and "Unknown-N" (2 <= N <= 15)
+ were marked to be translated. I had forgot these, plus they
+ wouldn't have worked correctly anyway before this commit,
+ because printing tables with multibyte strings didn't work.
+
+ Thanks to Marek Černocký for reporting the bug about
+ misaligned table columns in --list output.
+
+commit 639f8e2af33cf8a184d59ba56b6df7c098679d61
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Wed Sep 8 08:49:22 2010 +0300
+
+ Update the Czech translation.
+
+ Thanks to Marek Černocký.
+
+commit 41bc9956ebfd7c86777d33676acf34c45e7ca7c7
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Tue Sep 7 12:31:40 2010 +0300
+
+ xz: Add a note to translators.
+
+commit 77a7746616e555fc08028e883a56d06bf0088b81
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Tue Sep 7 10:42:13 2010 +0300
+
+ Fix use of N_() and ngettext().
+
+ I had somehow thought that N_() is usually used
+ as shorthand for ngettext().
+
+ This also fixes a missing \n from a call to ngettext().
+
+commit e6ad39335842343e622ab51207d1d3cb9caad801
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Mon Sep 6 19:43:12 2010 +0300
+
+ Add missing files to POTFILES.in.
+
+commit 58f55131820d2e08a1a6beb9ec0ee2378044eb30
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Mon Sep 6 10:16:24 2010 +0300
+
+ xz: Improve a comment.
+
+commit bcb1b898341f7073f51660d7052d7ed6c5461a66
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sun Sep 5 21:34:29 2010 +0300
+
+ xz: Update the comment about NetBSD in file_io.c.
+
+ Thanks to Joerg Sonnenberger.
+
+commit da014d55972f5addbf6b4360d3d8ed2ef4282170
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sun Sep 5 21:11:33 2010 +0300
+
+ xz: Use an array instead of pointer for stdin_filename.
+
+ Thanks Joerg Sonnenberger.
+
+commit 8c7d3d1a0781c296c6b6e2465becaffd2132f7ee
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sun Sep 5 12:16:17 2010 +0300
+
+ xz: Hopefully ease translating the messages in list.c.
+
+commit ef840950ad99cf2955c754875af0e01acf125079
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sat Sep 4 23:14:44 2010 +0300
+
+ xz: Fix grammar.
+
+commit c46afd6edc04ea140db6c59e8486f5707c810c13
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sat Sep 4 23:12:20 2010 +0300
+
+ xz: Use lzma_lzma_preset() to initialize the options structure.
+
+commit 8fd3ac046d0b1416a2094fecc456d9e0f4d5d065
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sat Sep 4 22:16:28 2010 +0300
+
+ Don't set lc=4 with --extreme.
+
+ This should reduce the cases where --extreme makes
+ compression worse. On the other hand, some other
+ files may now benefit slightly less from --extreme.
+
+commit 474bac0c33e94aeaca8ada17ab19972b1424bc2b
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sat Sep 4 22:10:32 2010 +0300
+
+ xz: Minor improvements to --help and --long-help.
+
+commit 373ee26f955617295c5c537b04a153a1969140d2
+Author: Jonathan Nieder <jrnieder@gmail.com>
+Date: Fri Sep 3 16:49:15 2010 -0500
+
+ Adjust memory limits in test_compress.sh
+
+ Testing compression at level -4 now requires 48 MiB of free store at
+ compression time and 5 MiB at decompression time.
+
+ Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
+
+commit 2fce9312f36727ea82f3430cc5d3a7d243c5f087
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Fri Sep 3 15:54:40 2010 +0300
+
+ xz: Make -vv show also decompressor memory usage.
+
+commit b4b1cbcb53624ab832f8b3189c74450dc7ea29b6
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Fri Sep 3 15:13:12 2010 +0300
+
+ Tweak the compression presets -0 .. -5.
+
+ "Extreme" mode might need some further tweaking still.
+ Docs were not updated yet.
+
+commit 77fe5954cd3d10fb1837372684cbc133b56b6a87
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Fri Sep 3 12:28:41 2010 +0300
+
+ liblzma: Adjust default depth calculation for HC3 and HC4.
+
+ It was 8 + nice_len / 4, now it is 4 + nice_len / 4.
+ This allows faster settings at lower nice_len values,
+ even though it seems that I won't use automatic depth
+ calcuation with HC3 and HC4 in the presets.
+
+commit fce69059cf901ce8075a78c7607d591f144a3b5a
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Fri Sep 3 11:11:25 2010 +0300
+
+ xz: Make --help two lines shorter.
+
+ At least for now, the --help option doesn't list any
+ options that take arguments, so "Mandatory arguments to..."
+ can be omitted.
+
+commit a848e47ced6e5e2a564b5c454b2f5a19c2f40298
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Thu Sep 2 19:22:35 2010 +0300
+
+ xz: Make setting a preset override a custom filter chain.
+
+ This is more logical behavior than ignoring preset level
+ options once a custom filter chain has been specified.
+
+commit b3ff7ba044eaeab3e424d7b51fe914daf681b1a3
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Thu Sep 2 19:09:57 2010 +0300
+
+ xz: Always warn if adjusting dictionary size due to memlimit.
+
+commit d5653ba8a1ea9c00de4fddc617aba3c51e18139d
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Tue Aug 10 11:04:30 2010 +0300
+
+ Fix test_compress.sh.
+
+ It broke when --memory option was removed from xzdec.
+
+ Thanks to Jonathan Nieder.
+
+commit 792331bdee706aa852a78b171040ebf814c6f3ae
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sat Aug 7 20:45:18 2010 +0300
+
+ Disable the memory usage limiter by default.
+
+ For several people, the limiter causes bigger problems that
+ it solves, so it is better to have it disabled by default.
+ Those who want to have a limiter by default need to enable
+ it via the environment variable XZ_DEFAULTS.
+
+ Support for environment variable XZ_DEFAULTS was added. It is
+ parsed before XZ_OPT and technically identical with it. The
+ intended uses differ quite a bit though; see the man page.
+
+ The memory usage limit can now be set separately for
+ compression and decompression using --memlimit-compress and
+ --memlimit-decompress. To set both at once, -M or --memlimit
+ can be used. --memory was retained as a legacy alias for
+ --memlimit for backwards compatibility.
+
+ The semantics of --info-memory were changed in backwards
+ incompatible way. Compatibility wasn't meaningful due to
+ changes in the memory usage limiter functionality.
+
+ The memory usage limiter info is no longer shown at the
+ bottom of xz --long -help.
+
+ The memory usage limiter support for removed completely from xzdec.
+
+ xz's man page was updated to match the above changes. Various
+ unrelated fixes were also made to the man page.
+
+commit 4a45dd4c39f75d25c7a37b6400cb24d4010ca801
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Fri Aug 6 20:22:16 2010 +0300
+
+ Add missing const to a global constant in xz.
+
+commit 01aa4869cb220b7fdad6d1acbabb2233045daa8f
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Wed Jul 28 11:44:55 2010 +0300
+
+ Language fixes for man pages.
+
+ Thanks to A. Costa and Jonathan Nieder.
+
+commit ce1f0deafe8504e1492bf1b1efb3e3ec950b1a2b
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Tue Jul 27 20:47:12 2010 +0300
+
+ Windows: Add a note about building a Git repository snapshot
+
+commit 507a4a4dea1e5462f12f7ed4b076c34e02054a38
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Tue Jul 27 20:45:03 2010 +0300
+
+ Windows: build.sh is a bash script so name it correctly.
+
+commit b1cbfd40f049a646a639eb78a3e41e9e3ef73339
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Tue Jul 27 20:27:32 2010 +0300
+
+ Windows: Don't strip liblzma.a too much.
+
+commit a540198ffb25fad36380c5e92ac20c2d28eec46a
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Tue Jul 13 20:07:26 2010 +0300
+
+ Updated THANKS.
+
+commit bab0f01ed931f606b4675aa9f9331a17cec09bad
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Tue Jul 13 19:55:50 2010 +0300
+
+ Add two simple example programs.
+
+ Hopefully these help a bit when learning the basics
+ of liblzma API. I plan to write detailed examples about
+ both basic and advanced features with lots of comments,
+ but these two examples are good have right now.
+
+ The examples were written by Daniel Mealha Cabrita. Thanks.
+
+commit c15c42abb3c8c6e77c778ef06c97a4a10b8b5d00
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Tue Jun 15 14:06:29 2010 +0300
+
+ Add --no-adjust.
+
+commit 2130926dd1c839280358172dfadd8d3054bde2b4
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Fri Jun 11 21:51:32 2010 +0300
+
+ Updated THANKS.
+
+commit bc612d0e0c9e4504c59d49168e87a7ae3e458443
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Fri Jun 11 21:48:32 2010 +0300
+
+ Clarify the description of the default memlimit in the man page.
+
+ Thanks to Denis Excoffier.
+
+commit e1b6935d60a00405e6b5b455a3426d2248cc926c
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Fri Jun 11 21:43:28 2010 +0300
+
+ Fix string to uint64_t conversion.
+
+ Thanks to Denis Excoffier for the bug report.
+
+commit 3e49c8acb0f5312948eddb2342dbb5802d4571d0
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Fri Jun 11 10:40:28 2010 +0300
+
+ Put the git commit to the filename in mydist rule.
+
+commit d8b41eedce486d400f701b757b7b5e4e32276618
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Wed Jun 2 23:13:55 2010 +0300
+
+ Fix compiling with -Werror.
+
+commit b5fbab6123a39c9a55cd5d7af410e9aae067d5f8
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Wed Jun 2 23:09:22 2010 +0300
+
+ Silence a bogus Valgrind warning.
+
+ When using -O2 with GCC, it liked to swap two comparisons
+ in one "if" statement. It's otherwise fine except that
+ the latter part, which is seemingly never executed, got
+ executed (nothing wrong with that) and then triggered
+ warning in Valgrind about conditional jump depending on
+ uninitialized variable. A few people find this annoying
+ so do things a bit differently to avoid the warning.
+
+commit 29a7b250e685852f2f97615493ec49acaf528623
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Wed Jun 2 21:32:12 2010 +0300
+
+ Fix a Windows-specific FIXME in signal handling code.
+
+commit e89d987056cee7d4e279be3ef3a6cc690bfc0e6d
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Wed Jun 2 17:46:58 2010 +0300
+
+ Adjust SA_RESTART workaround.
+
+ I want to get a bug report if something else than
+ DJGPP lacks SA_RESTART.
+
+commit e243145c84ab5c3be8259fd486ead0de5235b3f0
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Tue Jun 1 16:02:30 2010 +0300
+
+ xz man page updates.
+
+ - Concatenating .xz files and padding
+ - List mode
+ - Robot mode
+ - A few examples (but many more are needed)
+
+commit ce6dc3c0a891f23a862f80ec08d3b6f0beb2a562
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Tue Jun 1 15:51:44 2010 +0300
+
+ Major update to xz --list.
+
+commit 905e54804a899e4ad526d38fdba7e803ab9b71bd
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Tue Jun 1 14:13:03 2010 +0300
+
+ Rename message_filters_get() to message_filters_to_str().
+
+commit 4b346ae8af20045027ae5efb068c6d69da3324d2
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Tue Jun 1 14:09:12 2010 +0300
+
+ Fix a comment.
+
+commit 07dc34f6da45c9ab757dad7fd5eef522ad27d296
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Thu May 27 16:17:42 2010 +0300
+
+ Fix lzma_block_compressed_size().
+
+commit 44d70cb154225e47eebf15a3cfbdf3794cbb4593
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Thu May 27 14:32:51 2010 +0300
+
+ Take Cygwin into account in some #if lines.
+
+ This change is no-op, but good to have just in case
+ for the future.
+
+commit a334348dc02803241cf4e0a539eecdc0e7ad2cc7
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Thu May 27 13:42:44 2010 +0300
+
+ Remove references to the Subblock filter in xz and tests.
+
+ Thanks to Jonathan Nieder.
+
+commit 70e5e2f6a7084e6af909deee88ceac2f6efa7893
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Thu May 27 13:35:36 2010 +0300
+
+ Remove unused chunk_size.c.
+
+ Thanks to Jonathan Nieder for the reminder.
+
+commit 01a414eaf4be6352c06b48001b041b47e8202faa
+Author: Jonathan Nieder <jrnieder@gmail.com>
+Date: Thu May 27 02:31:33 2010 -0500
+
+ Use my_min() instead of MIN() in src/xz/list.c
+
+ This should have been done in
+ 920a69a8d8e4203c5edddd829d932130eac188ea.
+
+commit 920a69a8d8e4203c5edddd829d932130eac188ea
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Wed May 26 10:36:46 2010 +0300
+
+ Rename MIN() and MAX() to my_min() and my_max().
+
+ This should avoid some minor portability issues.
+
+commit 019ae27c24d0c694545a6a46f8b9fb552198b015
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Wed May 26 10:30:20 2010 +0300
+
+ Fix compilation of debug/known_sizes.c.
+
+commit 98a4856a6ea84f79c790057a6eb89a25bc45b074
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Wed May 26 10:28:54 2010 +0300
+
+ Remove references to Subblock filter in debug/sync_flush.c.
+
+commit 703d2c33c095c41ae0693ee8c27c45e3847e4535
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Wed May 26 10:16:57 2010 +0300
+
+ Better #error message.
+
+commit d8a55c48b39703dd83f11089ad01e1ff2ac102e0
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Wed May 26 09:55:47 2010 +0300
+
+ Remove the Subblock filter code for now.
+
+ The spec isn't finished and the code didn't compile anymore.
+ It won't be included in XZ Utils 5.0.0. It's easy to get it
+ back once the spec is done.
+
+commit b6377fc990f9b8651149cae0fecb8b9c5904e26d
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Sun May 16 18:42:22 2010 +0300
+
+ Split message_filters().
+
+ message_filters_to_str() converts the filter chain to
+ a string. message_filters_show() replaces the original
+ message_filters().
+
+ uint32_to_optstr() was also added to show the dictionary
+ size in nicer format when possible.
+
+commit d9986db782d6cf0f314342127280519339378fa0
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Fri May 14 23:17:20 2010 +0300
+
+ Omit lzma_restrict from the API headers.
+
+ It isn't really useful so omitting it makes things
+ shorter and slightly more readable.
+
+commit 0d3489efca0a723dca0394809fa3e6170843af4b
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Mon May 10 19:57:24 2010 +0300
+
+ Updated INSTALL.
+
+commit 3fb3d594a2b53886adee161b6261e92277f05f7c
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Mon May 10 19:54:52 2010 +0300
+
+ Updated THANKS.
+
+commit 6548e304657e77d3a972053db3c41c5daf591113
+Author: Lasse Collin <lasse.collin@tukaani.org>
+Date: Mon May 10 19:54:15 2010 +0300
+
+ Updates to tuklib_physmem and tuklib_cpucores.
+
+ Don't use #error to generate compile error, because some
+ compilers actually don't take it as an error. This fixes
+ tuklib_physmem on IRIX.
+
+ Fix incorrect error check for sysconf() return values.
+
+ Add AIX, HP-UX, and Tru64 specific code to detect the
+ amount RAM.
+
+ Add HP-UX specific code to detect the number of CPU cores.
+
+ Thanks a lot to Peter O'Gorman for initial patches,
+ testing, and debugging these fixes.
+
commit a290cfee3e23f046889c022aa96b4eca2016fdda
Author: Lasse Collin <lasse.collin@tukaani.org>
Date: Mon Apr 12 21:55:56 2010 +0300
diff --git a/FREEBSD-Xlist b/FREEBSD-Xlist
new file mode 100644
index 000000000000..c9c6bdba4c75
--- /dev/null
+++ b/FREEBSD-Xlist
@@ -0,0 +1,37 @@
+$FreeBSD$
+*/*/*/Makefile.*
+*/*/Makefile.*
+*/.gitignore
+*/Makefile.*
+.git
+.gitignore
+ABOUT-NLS
+COPYING.GPLv2
+COPYING.GPLv3
+COPYING.LGPLv2.1
+Doxyfile.in
+INSTALL
+INSTALL.generic
+Makefile
+Makefile.*
+NEWS
+PACKAGERS
+aclocal.m4
+autogen.sh
+build-aux/
+config.h.in
+configure
+configure.ac
+debug/
+doc/
+dos/
+extra/
+lib/
+m4/
+makefile.am
+src/*/*.rc
+src/liblzma/liblzma.pc.in
+src/scripts/
+tests/
+version.sh
+windows/
diff --git a/FREEBSD-upgrade b/FREEBSD-upgrade
new file mode 100644
index 000000000000..bfa186c21faa
--- /dev/null
+++ b/FREEBSD-upgrade
@@ -0,0 +1,28 @@
+$FreeBSD$
+
+xz
+
+The source code is pulled with git:
+
+ git clone git://ctrl.tukaani.org/xz.git xz
+
+ChangeLog is generated with:
+
+ git log > ChangeLog
+
+For the import files and directories were pruned by:
+
+sh -c 'for F in `cat FREEBSD-Xlist | grep -v FreeBSD`; do rm -rf ./$F ; done'
+
+You may check if there are any new files that we don't need.
+
+The instructions for importing new release and merging to HEAD can be found
+at FreeBSD wiki:
+
+ http://wiki.freebsd.org/SubversionPrimer/VendorImports
+
+To make local changes to xz, simply patch and commit to the trunk
+branch (aka HEAD). Never make local changes on the vendor branch.
+
+mm@FreeBSD.org
+10-May-2010
diff --git a/README b/README
index 6b695d5ccdb8..d6cfda78d3db 100644
--- a/README
+++ b/README
@@ -9,8 +9,9 @@ XZ Utils
1.3. Documentation for liblzma
2. Version numbering
3. Reporting bugs
- 4. Other implementations of the .xz format
- 5. Contact information
+ 4. Translating the xz tool
+ 5. Other implementations of the .xz format
+ 6. Contact information
0. Overview
@@ -187,7 +188,94 @@ XZ Utils
system.
-4. Other implementations of the .xz format
+4. Translating the xz tool
+--------------------------
+
+ The messages from the xz tool have been translated into a few
+ languages. Before starting to translate into a new language, ask
+ the author that someone else hasn't already started working on it.
+
+ Test your translation. Testing includes comparing the translated
+ output to the original English version by running the same commands
+ in both your target locale and with LC_ALL=C. Ask someone to
+ proof-read and test the translation.
+
+ Testing can be done e.g. by installing xz into a temporary directory:
+
+ ./configure --disable-shared --prefix=/tmp/xz-test
+ # <Edit the .po file in the po directory.>
+ make -C po update-po
+ make install
+ bash debug/translations.bash | less
+ bash debug/translations.bash | less -S # For --list outputs
+
+ Repeat the above as needed (no need to re-run configure though).
+
+ Note especially the following:
+
+ - The output of --help and --long-help must look nice on
+ a 80-column terminal. It's OK to add extra lines if needed.
+
+ - In contrast, don't add extra lines to error messages and such.
+ They are often preceded with e.g. a filename on the same line,
+ so you have no way to predict where to put a \n. Let the terminal
+ do the wrapping even if it looks ugly. Adding new lines will be
+ even uglier in the generic case even if it looks nice in a few
+ limited examples.
+
+ - Be careful with column alignment in tables and table-like output
+ (--list, --list --verbose --verbose, --info-memory, --help, and
+ --long-help):
+
+ * All descriptions of options in --help should start in the
+ same column (but it doesn't need to be the same column as
+ in the English messages; just be consistent if you change it).
+ Check that both --help and --long-help look OK, since they
+ share several strings.
+
+ * --list --verbose and --info-memory print lines that have
+ the format "Description: %s". If you need a longer
+ description, you can put extra space between the colon
+ and %s. Then you may need to add extra space to other
+ strings too so that the result as a whole looks good (all
+ values start at the same column).
+
+ * The columns of the actual tables in --list --verbose --verbose
+ should be aligned properly. Abbreviate if necessary. It might
+ be good to keep at least 2 or 3 spaces between column headings
+ and avoid spaces in the headings so that the columns stand out
+ better, but this is a matter of opinion. Do what you think
+ looks best.
+
+ - Be careful to put a period at the end of a sentence when the
+ original version has it, and don't put it when the original
+ doesn't have it. Similarly, be careful with \n characters
+ at the beginning and end of the strings.
+
+ - Read the TRANSLATORS comments that have been extracted from the
+ source code and included in xz.pot. If they suggest testing the
+ translation with some type of command, do it. If testing needs
+ input files, use e.g. tests/files/good-*.xz.
+
+ - When updating the translation, read the fuzzy (modified) strings
+ carefully, and don't mark them as updated before you actually
+ have updated them. Reading through the unchanged messages can be
+ good too; sometimes you may find a better wording for them.
+
+ - If you find language problems in the original English strings,
+ feel free to suggest improvements. Ask if something is unclear.
+
+ - The translated messages should be understandable (sometimes this
+ may be a problem with the original English messages too). Don't
+ make a direct word-by-word translation from English especially if
+ the result doesn't sound good in your language.
+
+ In short, take your time and pay attention to the details. Making
+ a good translation is not a quick and trivial thing to do. The
+ translated xz should look as polished as the English version.
+
+
+5. Other implementations of the .xz format
------------------------------------------
7-Zip and the p7zip port of 7-Zip support the .xz format starting
@@ -202,13 +290,11 @@ XZ Utils
http://tukaani.org/xz/embedded.html
-5. Contact information
+6. Contact information
----------------------
If you have questions, bug reports, patches etc. related to XZ Utils,
contact Lasse Collin <lasse.collin@tukaani.org> (in Finnish or English).
- tukaani.org uses greylisting to reduce spam, thus when you send your
- first email, it may get delayed by a few hours. In addition to that,
I'm sometimes slow at replying. If you haven't got a reply within two
weeks, assume that your email has got lost and resend it or use IRC.
diff --git a/THANKS b/THANKS
index 2ffbb1e0f5f8..635a29ac0dfa 100644
--- a/THANKS
+++ b/THANKS
@@ -12,12 +12,15 @@ has been important. :-) In alphabetical order:
- Emmanuel Blot
- Trent W. Buck
- David Burklund
+ - Daniel Mealha Cabrita
+ - Milo Casagrande
- Marek Černocký
- Andrew Dudman
- Markus Duft
- İsmail Dönmez
- Robert Elz
- Gilles Espinasse
+ - Denis Excoffier
- Mike Frysinger
- Joachim Henke
- Peter Ivanov
@@ -30,11 +33,14 @@ has been important. :-) In alphabetical order:
- Peter Lawler
- Hin-Tak Leung
- Andraž 'ruskie' Levstik
+ - Lorenzo De Liso
- Jim Meyering
- Rafał Mużyło
- Adrien Nader
- Hongbo Ni
- Jonathan Nieder
+ - Andre Noll
+ - Peter O'Gorman
- Igor Pavlov
- Elbert Pol
- Mikko Pouru
diff --git a/po/LINGUAS b/po/LINGUAS
index 841618abade8..7bd249cd2bf5 100644
--- a/po/LINGUAS
+++ b/po/LINGUAS
@@ -1 +1,3 @@
cs
+de
+it
diff --git a/po/POTFILES.in b/po/POTFILES.in
index ee430c5c3abe..e1438e0ec1f2 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -3,8 +3,11 @@ src/xz/args.c
src/xz/coder.c
src/xz/file_io.c
src/xz/hardware.c
+src/xz/list.c
src/xz/main.c
src/xz/message.c
src/xz/options.c
+src/xz/signals.c
src/xz/suffix.c
src/xz/util.c
+src/common/tuklib_exit.c
diff --git a/po/cs.po b/po/cs.po
index a953fd382969..a60a96f3b34f 100644
--- a/po/cs.po
+++ b/po/cs.po
@@ -1,11 +1,16 @@
+# XZ Utils Czech translation
+# This file is put in the public domain.
+# Marek Černocký <marek@manet.cz>, 2010.
+#
msgid ""
msgstr ""
"Project-Id-Version: xz-utils\n"
"Report-Msgid-Bugs-To: lasse.collin@tukaani.org\n"
-"POT-Creation-Date: 2009-12-04 16:04+0100\n"
-"PO-Revision-Date: 2009-12-05 13:51+0100\n"
+"POT-Creation-Date: 2010-09-17 18:33+0200\n"
+"PO-Revision-Date: 2010-09-17 18:54+0200\n"
"Last-Translator: Marek Černocký <marek@manet.cz>\n"
"Language-Team: Czech <diskuze@lists.l10n.cz>\n"
+"Language: cs\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -13,158 +18,395 @@ msgstr ""
"X-Poedit-Language: Czech\n"
"X-Poedit-SourceCharset: utf-8\n"
-#: src/xz/args.c:306
+#: src/xz/args.c:333
#, c-format
msgid "%s: Unknown file format type"
msgstr "%s: Neznámý typ formátu souboru"
-#: src/xz/args.c:329 src/xz/args.c:337
+#: src/xz/args.c:356 src/xz/args.c:364
#, c-format
msgid "%s: Unsupported integrity check type"
msgstr "%s: Neznámý typ kontroly integrity"
-#: src/xz/args.c:355
-msgid "Only one file can be specified with `--files'or `--files0'."
+#: src/xz/args.c:382
+msgid "Only one file can be specified with `--files' or `--files0'."
msgstr ""
-"Můžete zadat pouze jeden soubor spolu s přepínači „--files“ nebo „--files0“"
+"Spolu s přepínači „--files“ nebo „--files0“ může být zadán pouze jeden soubor"
-#: src/xz/args.c:413
-msgid "The environment variable XZ_OPT contains too many arguments"
-msgstr "Proměnná prostředí XZ_OPT obsahuje příliš mnoho argumentů"
+#: src/xz/args.c:445
+#, c-format
+msgid "The environment variable %s contains too many arguments"
+msgstr "Proměnná prostředí %s obsahuje příliš mnoho argumentů"
#: src/xz/coder.c:95
msgid "Maximum number of filters is four"
msgstr "Maximální počet filtrů je čtyři"
#: src/xz/coder.c:108
-#, c-format
-msgid ""
-"Memory usage limit (%<PRIu64> MiB) is too small for the given filter setup (%"
-"<PRIu64> MiB)"
-msgstr ""
-"Omezení použitelné paměti (%<PRIu64> MiB) je příliš malé pro dané nastavení "
-"filtru (%<PRIu64> MiB)"
+msgid "Memory usage limit is too low for the given filter setup."
+msgstr "Omezení použitelné paměti je příliš malé pro dané nastavení filtru."
-#: src/xz/coder.c:128
+#: src/xz/coder.c:129
msgid "Using a preset in raw mode is discouraged."
msgstr "Použití přednastavení v režimu raw je nevhodné."
-#: src/xz/coder.c:130
+#: src/xz/coder.c:131
msgid "The exact options of the presets may vary between software versions."
msgstr ""
"Přesné volby u přednastavení se mohou lišit mezi různými verzemi softwaru."
-#: src/xz/coder.c:158
+#: src/xz/coder.c:157
msgid "The .lzma format supports only the LZMA1 filter"
msgstr "Formát .lzma podporuje pouze filtr LZMA1"
-#: src/xz/coder.c:166
+#: src/xz/coder.c:165
msgid "LZMA1 cannot be used with the .xz format"
msgstr "LZMA1 nelze použít s formátem .xz"
-#: src/xz/coder.c:186
+#: src/xz/coder.c:182
+msgid "Unsupported filter chain or filter options"
+msgstr "Nepodporovaný omezující filtr nebo volby filtru"
+
+#: src/xz/coder.c:190
#, c-format
-msgid "%s MiB (%s B) of memory is required per thread, limit is %s MiB (%s B)"
-msgstr ""
-"Je vyžadováno %s MiB (%s B) paměti pro každé vlákno, limit je %s MiB (%s B)"
+msgid "Decompression will need %s MiB of memory."
+msgstr "Dekomprimace bude vyžadovat %s MiB paměti."
-#: src/xz/coder.c:554
+#: src/xz/coder.c:247
#, c-format
-msgid "Limit was %s MiB, but %s MiB would have been needed"
-msgstr "Limit byl %s MiB, ale bylo by zapotřebí %s MiB"
+msgid ""
+"Adjusted LZMA%c dictionary size from %s MiB to %s MiB to not exceed the "
+"memory usage limit of %s MiB"
+msgstr ""
+"Přizpůsobit velikost slovníku LZMA%c z %s MiB na %s MiB, tak aby nebylo "
+"překročeno omezení použitelné paměti %s MiB"
-#: src/xz/file_io.c:113
+#. TRANSLATORS: When compression or decompression finishes,
+#. and xz is going to remove the source file, xz first checks
+#. if the source file still exists, and if it does, does its
+#. device and inode numbers match what xz saw when it opened
+#. the source file. If these checks fail, this message is
+#. shown, %s being the filename, and the file is not deleted.
+#. The check for device and inode numbers is there, because
+#. it is possible that the user has put a new file in place
+#. of the original file, and in that case it obviously
+#. shouldn't be removed.
+#: src/xz/file_io.c:137
#, c-format
-msgid "%s: File seems to be moved, not removing"
-msgstr "%s: Vypadá to, že soubor byl přesunut, neodstraní se"
+msgid "%s: File seems to have been moved, not removing"
+msgstr "%s: Vypadá to, že soubor byl přesunut, proto nebude odstraněn"
-#: src/xz/file_io.c:120 src/xz/file_io.c:527
+#: src/xz/file_io.c:144 src/xz/file_io.c:590
#, c-format
msgid "%s: Cannot remove: %s"
msgstr "%s: Nelze odstranit: %s"
-#: src/xz/file_io.c:145
+#: src/xz/file_io.c:169
#, c-format
msgid "%s: Cannot set the file owner: %s"
msgstr "%s: Nelze nastavit vlastníka souboru: %s"
-#: src/xz/file_io.c:151
+#: src/xz/file_io.c:175
#, c-format
msgid "%s: Cannot set the file group: %s"
msgstr "%s: Nelze nastavit skupinu souboru: %s"
-#: src/xz/file_io.c:170
+#: src/xz/file_io.c:194
#, c-format
msgid "%s: Cannot set the file permissions: %s"
msgstr "%s: Nelze nastavit oprávnění souboru: %s"
-#: src/xz/file_io.c:308 src/xz/file_io.c:387
+#: src/xz/file_io.c:337 src/xz/file_io.c:420
#, c-format
msgid "%s: Is a symbolic link, skipping"
msgstr "%s: Jedná se o symbolický odkaz, vynechává se"
-#: src/xz/file_io.c:422
+#: src/xz/file_io.c:455
#, c-format
msgid "%s: Is a directory, skipping"
msgstr "%s: Jedná se o složku, vynechává se"
-#: src/xz/file_io.c:429
+#: src/xz/file_io.c:462
#, c-format
msgid "%s: Not a regular file, skipping"
msgstr "%s: Nejedná se o běžný soubor, vynechává se"
-#: src/xz/file_io.c:446
+#: src/xz/file_io.c:479
#, c-format
msgid "%s: File has setuid or setgid bit set, skipping"
msgstr "%s: Soubor má nastavený bit setuid nebo setgid, vynechává se"
-#: src/xz/file_io.c:453
+#: src/xz/file_io.c:486
#, c-format
msgid "%s: File has sticky bit set, skipping"
msgstr "%s: Soubor má nastavený bit sticky, vynechává se"
-#: src/xz/file_io.c:460
+#: src/xz/file_io.c:493
#, c-format
msgid "%s: Input file has more than one hard link, skipping"
msgstr "%s: Vstupní soubor má více než jeden pevný odkaz, vynechává se"
-#: src/xz/file_io.c:644
+#: src/xz/file_io.c:714
#, c-format
msgid "Error restoring the O_APPEND flag to standard output: %s"
msgstr "Chyba při obnovení příznaku O_APPEND na standardní výstup: %s"
-#: src/xz/file_io.c:655
+#: src/xz/file_io.c:726
#, c-format
msgid "%s: Closing the file failed: %s"
msgstr "%s: Selhalo zavření souboru: %s"
-#: src/xz/file_io.c:732 src/xz/file_io.c:889
+#: src/xz/file_io.c:762 src/xz/file_io.c:946
#, c-format
msgid "%s: Seeking failed when trying to create a sparse file: %s"
msgstr ""
"%s: Selhalo nastavení pozice při pokusu o vytvoření záložního souboru: %s"
-#: src/xz/file_io.c:789
+#: src/xz/file_io.c:821
#, c-format
msgid "%s: Read error: %s"
msgstr "%s: Chyba čtení: %s"
-#: src/xz/file_io.c:847
+#: src/xz/file_io.c:844
+#, c-format
+msgid "%s: Error seeking the file: %s"
+msgstr "%s: Chyba při posunu v rámci souboru: %s"
+
+#: src/xz/file_io.c:854
+#, c-format
+msgid "%s: Unexpected end of file"
+msgstr "%s: Neočekávaný konec souboru"
+
+#: src/xz/file_io.c:904
#, c-format
msgid "%s: Write error: %s"
msgstr "%s: Chyba zápisu: %s"
-#: src/xz/main.c:76
+#: src/xz/hardware.c:100
+msgid "Disabled"
+msgstr "Vypnuto"
+
+#. TRANSLATORS: Test with "xz --info-memory" to see if
+#. the alignment looks nice.
+#: src/xz/hardware.c:119
+msgid "Total amount of physical memory (RAM): "
+msgstr "Celkové množství fyzické paměti (RAM): "
+
+#: src/xz/hardware.c:121
+msgid "Memory usage limit for compression: "
+msgstr "Omezení použitelné paměti pro komprimaci: "
+
+#: src/xz/hardware.c:123
+msgid "Memory usage limit for decompression: "
+msgstr "Omezení použitelné paměti pro dekomprimaci:"
+
+#. TRANSLATORS: Indicates that there is no integrity check.
+#. This string is used in tables, so the width must not
+#. exceed ten columns with a fixed-width font.
+#: src/xz/list.c:62
+msgid "None"
+msgstr "žádná"
+
+#. TRANSLATORS: Indicates that integrity check name is not known,
+#. but the Check ID is known (here 2). This and other "Unknown-N"
+#. strings are used in tables, so the width must not exceed ten
+#. columns with a fixed-width font. It's OK to omit the dash if
+#. you need space for one extra letter, but don't use spaces.
+#: src/xz/list.c:69
+msgid "Unknown-2"
+msgstr "neznámá-2"
+
+#: src/xz/list.c:70
+msgid "Unknown-3"
+msgstr "neznámá-3"
+
+#: src/xz/list.c:72
+msgid "Unknown-5"
+msgstr "neznámá-5"
+
+#: src/xz/list.c:73
+msgid "Unknown-6"
+msgstr "neznámá-6"
+
+#: src/xz/list.c:74
+msgid "Unknown-7"
+msgstr "neznámá-7"
+
+#: src/xz/list.c:75
+msgid "Unknown-8"
+msgstr "neznámá-8"
+
+#: src/xz/list.c:76
+msgid "Unknown-9"
+msgstr "neznámá-9"
+
+#: src/xz/list.c:78
+msgid "Unknown-11"
+msgstr "neznámá-11"
+
+#: src/xz/list.c:79
+msgid "Unknown-12"
+msgstr "neznámá-12"
+
+#: src/xz/list.c:80
+msgid "Unknown-13"
+msgstr "neznámá-13"
+
+#: src/xz/list.c:81
+msgid "Unknown-14"
+msgstr "neznámá-14"
+
+#: src/xz/list.c:82
+msgid "Unknown-15"
+msgstr "neznámá-15"
+
+#: src/xz/list.c:126
+#, c-format
+msgid "%s: File is empty"
+msgstr "%s: Soubor je prázdný"
+
+#: src/xz/list.c:131
+#, c-format
+msgid "%s: Too small to be a valid .xz file"
+msgstr "%s: Je příliš malý na to, aby to mohl být platný soubor .xz"
+
+#. TRANSLATORS: These are column headings. From Strms (Streams)
+#. to Ratio, the columns are right aligned. Check and Filename
+#. are left aligned. If you need longer words, it's OK to
+#. use two lines here. Test with "xz -l foo.xz".
+#: src/xz/list.c:612
+msgid "Strms Blocks Compressed Uncompressed Ratio Check Filename"
+msgstr "Proud Bloky Komprim Nekomprim Poměr Kontrl Název souboru"
+
+#: src/xz/list.c:652
+#, c-format
+msgid " Streams: %s\n"
+msgstr " Proudů: %s\n"
+
+#: src/xz/list.c:654
+#, c-format
+msgid " Blocks: %s\n"
+msgstr " Bloků: %s\n"
+
+#: src/xz/list.c:656
+#, c-format
+msgid " Compressed size: %s\n"
+msgstr " Komprimovaná velikost: %s\n"
+
+#: src/xz/list.c:659
+#, c-format
+msgid " Uncompressed size: %s\n"
+msgstr " Nekomprimovaná velikost: %s\n"
+
+#: src/xz/list.c:662
+#, c-format
+msgid " Ratio: %s\n"
+msgstr " Poměr komprimace: %s\n"
+
+#: src/xz/list.c:664
+#, c-format
+msgid " Check: %s\n"
+msgstr " Typ kontroly: %s\n"
+
+#: src/xz/list.c:665
+#, c-format
+msgid " Stream padding: %s\n"
+msgstr " Zarovnání proudu: %s\n"
+
+#. TRANSLATORS: The second line is column headings. All except
+#. Check are right aligned; Check is left aligned. Test with
+#. "xz -lv foo.xz".
+#: src/xz/list.c:693
+msgid ""
+" Streams:\n"
+" Stream Blocks CompOffset UncompOffset CompSize "
+"UncompSize Ratio Check Padding"
+msgstr ""
+" Proudy:\n"
+" Proud Bloky KomprPozice NekomprPozice KomprVelikost "
+"NekomprVelikost Poměr Kontrola Zarovnání"
+
+#. TRANSLATORS: The second line is column headings. All
+#. except Check are right aligned; Check is left aligned.
+#: src/xz/list.c:748
+#, c-format
+msgid ""
+" Blocks:\n"
+" Stream Block CompOffset UncompOffset TotalSize "
+"UncompSize Ratio Check"
+msgstr ""
+" Bloky:\n"
+" Proud Blok KomprPozice NekomprPozice CelkVelikost "
+"NekomprVelikost Poměr Kontrola"
+
+#. TRANSLATORS: These are additional column headings
+#. for the most verbose listing mode. CheckVal
+#. (Check value), Flags, and Filters are left aligned.
+#. Header (Block Header Size), CompSize, and MemUsage
+#. are right aligned. %*s is replaced with 0-120
+#. spaces to make the CheckVal column wide enough.
+#. Test with "xz -lvv foo.xz".
+#: src/xz/list.c:760
+#, c-format
+msgid " CheckVal %*s Header Flags CompSize MemUsage Filters"
+msgstr " KontrHod %*s Hlavič Příznaky KomprVel PoužiPam Filtry"
+
+#: src/xz/list.c:838 src/xz/list.c:1007
+#, c-format
+msgid " Memory needed: %s MiB\n"
+msgstr " Potřebná paměť: %s MiB\n"
+
+#: src/xz/list.c:840 src/xz/list.c:1009
+#, c-format
+msgid " Sizes in headers: %s\n"
+msgstr " Velikosti v hlavičkách: %s\n"
+
+#: src/xz/list.c:841 src/xz/list.c:1010
+msgid "Yes"
+msgstr "Ano"
+
+#: src/xz/list.c:841 src/xz/list.c:1010
+msgid "No"
+msgstr "Ne"
+
+#. TRANSLATORS: %s is an integer. Only the plural form of this
+#. message is used (e.g. "2 files"). Test with "xz -l foo.xz bar.xz".
+#: src/xz/list.c:986
+#, c-format
+msgid "%s file\n"
+msgid_plural "%s files\n"
+msgstr[0] "%s soubor\n"
+msgstr[1] "%s soubory\n"
+msgstr[2] "%s souborů\n"
+
+#: src/xz/list.c:999
+msgid "Totals:"
+msgstr "Celkem:"
+
+#: src/xz/list.c:1000
+#, c-format
+msgid " Number of files: %s\n"
+msgstr " Počet souborů: %s\n"
+
+#: src/xz/list.c:1072
+msgid "--list works only on .xz files (--format=xz or --format=auto)"
+msgstr "--list pracuje pouze se soubory .xz (--format=xz nebo --format=auto)"
+
+#: src/xz/list.c:1078
+msgid "--list does not support reading from standard input"
+msgstr "--list nepodporuje čtení ze standardního vstupu"
+
+#: src/xz/main.c:89
#, c-format
msgid "%s: Error reading filenames: %s"
msgstr "%s: Chyba při čtení názvů souborů: %s"
-#: src/xz/main.c:83
+#: src/xz/main.c:96
#, c-format
msgid "%s: Unexpected end of input when reading filenames"
msgstr "%s: Neočekávaný konec vstupu při čtení názvů souborů"
-#: src/xz/main.c:107
+#: src/xz/main.c:120
#, c-format
msgid ""
"%s: Null character found when reading filenames; maybe you meant to use `--"
@@ -173,11 +415,11 @@ msgstr ""
"%s: Byl nalezen nulový znak při čtení názvů souborů; nechtěli jste náhodou "
"použít „--files0“ místo „--files“?"
-#: src/xz/main.c:160
+#: src/xz/main.c:174
msgid "Compression and decompression with --robot are not supported yet."
msgstr "Komprimace a dekomprimace s přepínačem --robot není zatím podporovaná."
-#: src/xz/main.c:207
+#: src/xz/main.c:231
msgid ""
"Cannot read data from standard input when reading filenames from standard "
"input"
@@ -185,59 +427,59 @@ msgstr ""
"Ze standardního vstupu nelze číst data, když se ze standardního vstupu "
"načítají názvy souborů"
-#: src/xz/message.c:841 src/xz/message.c:885
+#: src/xz/message.c:800 src/xz/message.c:844
msgid "Internal error (bug)"
msgstr "Interní chyba"
-#: src/xz/message.c:848
+#: src/xz/message.c:807
msgid "Cannot establish signal handlers"
msgstr "Nelze ustanovit ovladač signálu"
-#: src/xz/message.c:857
+#: src/xz/message.c:816
msgid "No integrity check; not verifying file integrity"
msgstr "Žádná kontrola integrity; integrita souboru se nebude ověřovat"
-#: src/xz/message.c:860
+#: src/xz/message.c:819
msgid "Unsupported type of integrity check; not verifying file integrity"
msgstr ""
"Nepodporovaný typ kontroly integrity; integrita souboru se nebude ověřovat"
-#: src/xz/message.c:867
+#: src/xz/message.c:826
msgid "Memory usage limit reached"
msgstr "Dosaženo omezení použitelné paměti"
-#: src/xz/message.c:870
+#: src/xz/message.c:829
msgid "File format not recognized"
msgstr "Formát souboru nebyl rozpoznán"
-#: src/xz/message.c:873
+#: src/xz/message.c:832
msgid "Unsupported options"
msgstr "Nepodporovaná volba"
-#: src/xz/message.c:876
+#: src/xz/message.c:835
msgid "Compressed data is corrupt"
msgstr "Komprimovaná data jsou poškozená"
-#: src/xz/message.c:879
+#: src/xz/message.c:838
msgid "Unexpected end of input"
msgstr "Neočekávaný konec vstupu"
-#: src/xz/message.c:898
+#: src/xz/message.c:886
#, c-format
-msgid "%s: Filter chain:"
-msgstr "%s: Omezující filtr:"
+msgid "%s MiB of memory is required. The limit is %s."
+msgstr "Je vyžadováno %s MiB paměti. Limit je %s."
-#: src/xz/message.c:1009
+#: src/xz/message.c:1053
#, c-format
-msgid "Try `%s --help' for more information."
-msgstr "Zkuste „%s --help“ pro více informací"
+msgid "%s: Filter chain: %s\n"
+msgstr "%s: Omezující filtr: %s\n"
-#: src/xz/message.c:1021
+#: src/xz/message.c:1063
#, c-format
-msgid "%s MiB (%s bytes)\n"
-msgstr "%s MiB (%s bajtů)\n"
+msgid "Try `%s --help' for more information."
+msgstr "Zkuste „%s --help“ pro více informací"
-#: src/xz/message.c:1049
+#: src/xz/message.c:1089
#, c-format
msgid ""
"Usage: %s [OPTION]... [FILE]...\n"
@@ -248,30 +490,30 @@ msgstr ""
"Komprimuje nebo dekomprimuje SOUBORy ve formátu xz.\n"
"\n"
-#: src/xz/message.c:1053
+#: src/xz/message.c:1096
msgid ""
"Mandatory arguments to long options are mandatory for short options too.\n"
msgstr ""
"Povinné argumenty pro dlouhé přepínače jsou povinné rovněž pro krátké "
"přepínače.\n"
-#: src/xz/message.c:1057
+#: src/xz/message.c:1100
msgid " Operation mode:\n"
msgstr "Operační režim:\n"
-#: src/xz/message.c:1060
+#: src/xz/message.c:1103
msgid ""
" -z, --compress force compression\n"
" -d, --decompress force decompression\n"
" -t, --test test compressed file integrity\n"
-" -l, --list list information about files"
+" -l, --list list information about .xz files"
msgstr ""
" -z, --compress provést komprimaci\n"
" -d, --decompress provést dekomprimaci\n"
" -t, --test testovat integritu komprimovaného souboru\n"
-" -l, --list vypsat informace o souborech"
+" -l, --list vypsat informace o souborech .xz"
-#: src/xz/message.c:1066
+#: src/xz/message.c:1109
msgid ""
"\n"
" Operation modifiers:\n"
@@ -279,7 +521,7 @@ msgstr ""
"\n"
"Modifikátory operací:\n"
-#: src/xz/message.c:1069
+#: src/xz/message.c:1112
msgid ""
" -k, --keep keep (don't delete) input files\n"
" -f, --force force overwrite of output file and (de)compress links\n"
@@ -291,27 +533,27 @@ msgstr ""
" -c, --stdout zapisovat na standardní výstup a nemazat vstupní "
"soubory"
-#: src/xz/message.c:1075
+#: src/xz/message.c:1118
msgid ""
" --no-sparse do not create sparse files when decompressing\n"
" -S, --suffix=.SUF use the suffix `.SUF' on compressed files\n"
-" --files=[FILE] read filenames to process from FILE; if FILE is\n"
+" --files[=FILE] read filenames to process from FILE; if FILE is\n"
" omitted, filenames are read from the standard input;\n"
" filenames must be terminated with the newline "
"character\n"
-" --files0=[FILE] like --files but use the null character as terminator"
+" --files0[=FILE] like --files but use the null character as terminator"
msgstr ""
" --no-sparse nevytvářet při dekomprimaci záložní soubory\n"
-" -S, --suffix=.SUF použít u komprimovaných souborů příponu „.SUF“\n"
-" --files=[SOUBOR] číst názvy souborů, které se mají zpracovat, ze "
+" -S, --suffix=.PRIP použít u komprimovaných souborů příponu „.PRIP“\n"
+" --files[=SOUBOR] číst názvy souborů, které se mají zpracovat, ze "
"SOUBORu;\n"
" pokud není SOUBOR zadán, čte se ze standardního "
"vstupu;\n"
" názvy souborů musí být zakončeny znakem nového řádku\n"
-" --files0=[SOUBOR] stejné jako --files, ale použít k zakončování nulový "
+" --files0[=SOUBOR] stejné jako --files, ale použít k zakončování nulový "
"znak"
-#: src/xz/message.c:1083
+#: src/xz/message.c:1126
msgid ""
"\n"
" Basic file format and compression options:\n"
@@ -319,48 +561,70 @@ msgstr ""
"\n"
"Základní přepínače pro formát souboru a komprimaci:\n"
-#: src/xz/message.c:1085
+#: src/xz/message.c:1128
msgid ""
" -F, --format=FMT file format to encode or decode; possible values are\n"
" `auto' (default), `xz', `lzma', and `raw'\n"
-" -C, --check=CHECK integrity check type: `crc32', `crc64' (default),\n"
-" `sha256', or `none' (use with caution)"
+" -C, --check=CHECK integrity check type: `none' (use with caution),\n"
+" `crc32', `crc64' (default), or `sha256'"
msgstr ""
" -F, --format=FORMÁT formát souboru k zakódování nebo dekódování; možné\n"
" hodnoty jsou „auto“ (výchozí), „xz“, „lzma“ a „raw“\n"
-" -C, --check=KONTROLA typ kontroly integrity: „crc32“, „crc64“ (výchozí),\n"
-" „sha256“ nebo „none“ (používejte s rozmyslem)"
+" -C, --check=KONTROLA typ kontroly integrity: „none“ (používejte s "
+"rozmyslem),\n"
+" „crc32“, „crc64“ (výchozí) nebo „sha256“"
-#: src/xz/message.c:1092
+#: src/xz/message.c:1135
msgid ""
-" -0 .. -9 compression preset; 0-2 fast compression, 3-5 good\n"
-" compression, 6-9 excellent compression; default is 6"
-msgstr ""
-" -0 .. -9 přednastavení komprimace; 0-2 rychlá komprimace, 3-5\n"
-" dobrá komprimace, 6-9 skvělá komprimace; výchozí je 6"
+" -0 ... -9 compression preset; default is 6; take compressor "
+"*and*\n"
+" decompressor memory usage into account before using "
+"7-9!"
+msgstr ""
+" -0 .. -9 přednastavení komprimace; výchozí je 6; než "
+"použijete\n"
+" hodnoty 7 – 9, vezměte do úvahy množství použité "
+"paměti"
-#: src/xz/message.c:1096
+#: src/xz/message.c:1139
msgid ""
-" -e, --extreme use more CPU time when encoding to increase "
-"compression\n"
-" ratio without increasing memory usage of the decoder"
+" -e, --extreme try to improve compression ratio by using more CPU "
+"time;\n"
+" does not affect decompressor memory requirements"
msgstr ""
-" -e, --extreme využít více procesorového času pro kódování, čímž se\n"
-" zvýší kompresní poměr bez zvýšení paměti použité "
-"kodérem"
+" -e, --extreme zkusit zlepšit poměr komprimace využitím více času\n"
+" procesoru; nemá vliv na paměťové nároky dekomprimace"
-#: src/xz/message.c:1101
+#: src/xz/message.c:1144
+#, no-c-format
+msgid ""
+" --memlimit-compress=LIMIT\n"
+" --memlimit-decompress=LIMIT\n"
+" -M, --memlimit=LIMIT\n"
+" set memory usage limit for compression, "
+"decompression,\n"
+" or both; LIMIT is in bytes, % of RAM, or 0 for defaults"
+msgstr ""
+" --memlimit-compress=LIMIT\n"
+" --memlimit-decompress=LIMIT\n"
+" -M, --memlimit=LIMIT\n"
+" nastaví omezení použitelné paměti pro komprimaci,\n"
+" dekomprimaci nebo obojí; LIMIT je v bajtech, % z "
+"paměti\n"
+" RAM nebo 0 pro výchozí"
+
+#: src/xz/message.c:1151
msgid ""
-" -M, --memory=NUM use roughly NUM bytes of memory at maximum; 0 "
-"indicates\n"
-" the default setting, which is 40 % of total RAM"
+" --no-adjust if compression settings exceed the memory usage "
+"limit,\n"
+" give an error instead of adjusting the settings "
+"downwards"
msgstr ""
-" -M, --memory=POČ použít zhruba POČ bajtů paměti jako maximum; 0 "
-"znamená\n"
-" výchozí nastavení, což je 40% celkového množství "
-"paměti"
+" --no-adjust pokud nastavení komprimace přesáhne omezení "
+"použitelné\n"
+" paměti, předat chybu namísto snížení nastavení"
-#: src/xz/message.c:1106
+#: src/xz/message.c:1157
msgid ""
"\n"
" Custom filter chain for compression (alternative for using presets):"
@@ -369,14 +633,14 @@ msgstr ""
"Vlastní omezující filtr pro komprimaci (alternativa k použití "
"přednastavených):"
-#: src/xz/message.c:1111
+#: src/xz/message.c:1166
msgid ""
"\n"
" --lzma1[=OPTS] LZMA1 or LZMA2; OPTS is a comma-separated list of zero "
"or\n"
" --lzma2[=OPTS] more of the following options (valid values; "
"default):\n"
-" preset=NUM reset options to preset number NUM (0-9)\n"
+" preset=PRE reset options to a preset (0-9[e])\n"
" dict=NUM dictionary size (4KiB - 1536MiB; 8MiB)\n"
" lc=NUM number of literal context bits (0-4; 3)\n"
" lp=NUM number of literal position bits (0-4; 0)\n"
@@ -393,28 +657,28 @@ msgstr ""
"žádné\n"
" --lzma2[=VOLBY] nebo více následujících voleb (platné hodnoty; "
"výchozí):\n"
-" preset=POČ obnovení voleb na přednastavený POČet (0-"
-"9)\n"
-" dict=POČ velikost slovníku (4 KiB - 1536 MiB; 8 "
+" preset=PŘE změnit volby na PŘEdnastavené (0 – 9"
+"[e])\n"
+" dict=POČ velikost slovníku (4 KiB – 1536 MiB; 8 "
"MiB)\n"
-" lc=POČ počet kontextových bitů literálu (0-4; "
+" lc=POČ počet kontextových bitů literálu (0 – 4; "
"3)\n"
-" lp=POČ počet pozičních bitů literálu (0-4; 0)\n"
-" pb=POČ počet pozičních bitů (0-4; 2)\n"
+" lp=POČ počet pozičních bitů literálu (0 – 4; "
+"0)\n"
+" pb=POČ počet pozičních bitů (0 – 4; 2)\n"
" mode=REŽIM režim komprimace (fast, normal; normal)\n"
-" nice=POČ příznivá délka shody (2-273; 64)\n"
-" mf=NÁZEV vyhledávač shod (hc3, hc4, bt2, bt3, "
-"bt4;\n"
-" bt4)\n"
+" nice=NUM příznivá délka shody (2 – 273; 64)\n"
+" mf=NÁZEV hledání shod (hc3, hc4, bt2, bt3, bt4; "
+"bt4)\n"
" depth=POČ maximální hloubka prohledávání;\n"
-" 0=automaticky (výchozí)"
+" 0 = automaticky (výchozí)"
-#: src/xz/message.c:1126
+#: src/xz/message.c:1181
msgid ""
"\n"
-" --x86[=OPTS] x86 BCJ filter\n"
+" --x86[=OPTS] x86 BCJ filter (32-bit and 64-bit)\n"
" --powerpc[=OPTS] PowerPC BCJ filter (big endian only)\n"
-" --ia64[=OPTS] IA64 (Itanium) BCJ filter\n"
+" --ia64[=OPTS] IA-64 (Itanium) BCJ filter\n"
" --arm[=OPTS] ARM BCJ filter (little endian only)\n"
" --armthumb[=OPTS] ARM-Thumb BCJ filter (little endian only)\n"
" --sparc[=OPTS] SPARC BCJ filter\n"
@@ -422,7 +686,7 @@ msgid ""
" start=NUM start offset for conversions (default=0)"
msgstr ""
"\n"
-" --x86[=VOLBY] Filtr x86 BCJ\n"
+" --x86[=VOLBY] Filtr x86 BCJ (32bitový a 64bitový)\n"
" --powerpc[=VOLBY] Filtr PowerPC BCJ (pouze big endian)\n"
" --ia64[=VOLBY] Filtr IA64 (Itanium) BCJ\n"
" --arm[=VOLBY] Filtr ARM BCJ (pouze little endian)\n"
@@ -431,7 +695,7 @@ msgstr ""
" Platné volby pro všechny filtry BCJ:\n"
" start=POČ počáteční posun pro převody (výchozí=0)"
-#: src/xz/message.c:1138
+#: src/xz/message.c:1193
msgid ""
"\n"
" --delta[=OPTS] Delta filter; valid OPTS (valid values; default):\n"
@@ -442,25 +706,9 @@ msgstr ""
" --delta[=VOLBY] Filtr Delta; platné VOLBY (platné hodnoty; výchozí):\n"
" dist=POČ vzdálenost mezi bajty, které jsou "
"odečítány\n"
-" jeden od druhého (1-256; 1)"
-
-#: src/xz/message.c:1146
-msgid ""
-"\n"
-" --subblock[=OPTS] Subblock filter; valid OPTS (valid values; default):\n"
-" size=NUM number of bytes of data per subblock\n"
-" (1 - 256Mi; 4Ki)\n"
-" rle=NUM run-length encoder chunk size (0-256; 0)"
-msgstr ""
-"\n"
-" --subblock[=VOLBY] Subblokový filtr; platné VOLBY (platné hodnoty; "
-"výchozí):\n"
-" size=POČ počet bajtů dat na subblok\n"
-" (1 - 256 Mi; 4 Ki)\n"
-" rle=POČ velikost dávky pro kodér run-length (0-"
-"256; 0)"
+" jeden od druhého (1 – 256; 1)"
-#: src/xz/message.c:1155
+#: src/xz/message.c:1201
msgid ""
"\n"
" Other options:\n"
@@ -468,7 +716,7 @@ msgstr ""
"\n"
" Ostatní přepínače:\n"
-#: src/xz/message.c:1158
+#: src/xz/message.c:1204
msgid ""
" -q, --quiet suppress warnings; specify twice to suppress errors "
"too\n"
@@ -479,22 +727,28 @@ msgstr ""
" -v, --verbose podrobnější zprávy; zadáním dvakrát, budou ještě\n"
" podrobnější"
-#: src/xz/message.c:1163
+#: src/xz/message.c:1209
msgid " -Q, --no-warn make warnings not affect the exit status"
msgstr " -Q, --no-warn způsobí, že varování neovlivní stav ukončení"
-#: src/xz/message.c:1165
+#: src/xz/message.c:1211
msgid ""
" --robot use machine-parsable messages (useful for scripts)"
msgstr ""
-" --robot použít strojově analyzovatelné zprávy (užitečné pro "
-"skripty)"
+" --robot použít strojově analyzovatelné zprávy (užitečné pro\n"
+" skripty)"
-#: src/xz/message.c:1168
-msgid " --info-memory display the memory usage limit and exit"
-msgstr " --info-memory zobrazit omezení využití paměti a skončit"
+#: src/xz/message.c:1214
+msgid ""
+" --info-memory display the total amount of RAM and the currently "
+"active\n"
+" memory usage limits, and exit"
+msgstr ""
+" --info-memory zobrazit celkové množství paměti RAM a současné "
+"aktivní\n"
+" omezení použitelné paměti a skončit"
-#: src/xz/message.c:1170
+#: src/xz/message.c:1217
msgid ""
" -h, --help display the short help (lists only the basic options)\n"
" -H, --long-help display this long help and exit"
@@ -503,7 +757,7 @@ msgstr ""
"přepínače)\n"
" -H, --long-help zobrazit tuto úplnou nápovědu a skončit"
-#: src/xz/message.c:1174
+#: src/xz/message.c:1221
msgid ""
" -h, --help display this short help and exit\n"
" -H, --long-help display the long help (lists also the advanced options)"
@@ -512,11 +766,11 @@ msgstr ""
" -H, --long-help zobrazit úplnou nápovědu (vypíše i pokročilé "
"přepínače)"
-#: src/xz/message.c:1179
+#: src/xz/message.c:1226
msgid " -V, --version display the version number and exit"
msgstr " -V, --version zobrazit číslo verze a skončit"
-#: src/xz/message.c:1181
+#: src/xz/message.c:1228
msgid ""
"\n"
"With no FILE, or when FILE is -, read standard input.\n"
@@ -525,31 +779,16 @@ msgstr ""
"Pokud SOUBOR není zadán nebo pokud je -, bude se číst ze standardního "
"vstupu.\n"
-#: src/xz/message.c:1185
-#, c-format
-msgid ""
-"On this system and configuration, this program will use a maximum of "
-"roughly\n"
-"%s MiB RAM and "
-msgstr ""
-"Na tomto systému a s tímto nastavením použije tento program maximum ze "
-"zhruba\n"
-"%s MiB RAM a "
-
-#: src/xz/message.c:1187
-msgid ""
-"one thread.\n"
-"\n"
-msgstr ""
-"jedno vlákno.\n"
-"\n"
-
-#: src/xz/message.c:1192
+#. TRANSLATORS: This message indicates the bug reporting address
+#. for this package. Please add _another line_ saying
+#. "Report translation bugs to <...>\n" with the email or WWW
+#. address for translation bugs. Thanks.
+#: src/xz/message.c:1234
#, c-format
msgid "Report bugs to <%s> (in English or Finnish).\n"
msgstr "Chyby hlaste na <%s> (v angličtině nebo finštině).\n"
-#: src/xz/message.c:1194
+#: src/xz/message.c:1236
#, c-format
msgid "%s home page: <%s>\n"
msgstr "Domovská stránka %s: <%s>\n"
@@ -569,16 +808,16 @@ msgstr "%s: Neplatný název volby"
msgid "%s: Invalid option value"
msgstr "%s: Neplatná hodnota volby"
-#: src/xz/options.c:308
+#: src/xz/options.c:247
#, c-format
msgid "Unsupported LZMA1/LZMA2 preset: %s"
msgstr "Nepodporované přednastavení LZMA1/LZMA2: %s"
-#: src/xz/options.c:426
-msgid "The sum of lc and lp must be at maximum of 4"
-msgstr "Součet lc a lp musí být maximálně 4"
+#: src/xz/options.c:355
+msgid "The sum of lc and lp must not exceed 4"
+msgstr "Součet lc a lp nesmí překročit hodnotu 4"
-#: src/xz/options.c:431
+#: src/xz/options.c:359
#, c-format
msgid "The selected match finder requires at least nice=%<PRIu32>"
msgstr "Vybraný vyhledávač shod vyžaduje minimálně nice=%<PRIu32>"
@@ -588,8 +827,8 @@ msgstr "Vybraný vyhledávač shod vyžaduje minimálně nice=%<PRIu32>"
msgid ""
"%s: With --format=raw, --suffix=.SUF is required unless writing to stdout"
msgstr ""
-"%s: S --format=raw je vyžadováno --sufix=.SUF, vyjma zápisu do standardního "
-"výstupu"
+"%s: S přepínačem --format=raw je vyžadován --sufix=.PRIP, vyjma zápisu do "
+"standardního výstupu"
#: src/xz/suffix.c:99
#, c-format
@@ -606,31 +845,105 @@ msgstr "%s: Soubor již má příponu „%s“, vynechává se"
msgid "%s: Invalid filename suffix"
msgstr "%s: Neplatná přípona názvu souboru"
-#: src/xz/util.c:53
+#: src/xz/util.c:61
#, c-format
msgid "%s: Value is not a non-negative decimal integer"
msgstr "%s: Hodnota není nezáporné desítkové číslo"
-#: src/xz/util.c:95
+#: src/xz/util.c:103
#, c-format
-msgid "%s: Invalid multiplier suffix. Valid suffixes:"
-msgstr "%s: Neplatná přípona. Platné přípony jsou:"
+msgid "%s: Invalid multiplier suffix"
+msgstr "%s: Neplatná jednotka s předponou"
+
+#: src/xz/util.c:105
+msgid "Valid suffixes are `KiB' (2^10), `MiB' (2^20), and `GiB' (2^30)."
+msgstr ""
+"Platné jednotky s předponami jsou „KiB“ (2^10 B), „MiB“ (2^20 B) a "
+"„GiB“ (2^30 B)."
-#: src/xz/util.c:115
+#: src/xz/util.c:122
#, c-format
msgid "Value of the option `%s' must be in the range [%<PRIu64>, %<PRIu64>]"
msgstr "Hodnota volby „%s“ musí být v rozsahu [%<PRIu64>, %<PRIu64>]"
-#: src/xz/util.c:212
+#: src/xz/util.c:247
msgid "Empty filename, skipping"
msgstr "Prázdný název souboru, vynechává se"
-#: src/xz/util.c:226
-msgid "Compressed data not read from a terminal unless `--force' is used."
-msgstr ""
-"Komprimovaná data se nečtou z terminálu, vyjma použití volby „--force“."
-
-#: src/xz/util.c:239
-msgid "Compressed data not written to a terminal unless `--force' is used."
-msgstr ""
-"Komprimovaná data se nezapisují do terminálu, vyjma použití volby „--force“."
+#: src/xz/util.c:261
+msgid "Compressed data cannot be read from a terminal"
+msgstr "Z terminálu nelze číst komprimovaná data"
+
+#: src/xz/util.c:274
+msgid "Compressed data cannot be written to a terminal"
+msgstr "Do terminálu nelze zapisovat komprimovaná data"
+
+#: src/common/tuklib_exit.c:39
+msgid "Writing to standard output failed"
+msgstr "Zápis do standardního výstupu selhal"
+
+#: src/common/tuklib_exit.c:42
+msgid "Unknown error"
+msgstr "Neznámá chyba"
+
+#~ msgid "Limit was %s MiB, but %s MiB would have been needed"
+#~ msgstr "Limit byl %s MiB, ale bylo by zapotřebí %s MiB"
+
+#~ msgid "%s MiB (%s bytes)\n"
+#~ msgstr "%s MiB (%s bajtů)\n"
+
+#~ msgid ""
+#~ " -e, --extreme use more CPU time when encoding to increase "
+#~ "compression\n"
+#~ " ratio without increasing memory usage of the decoder"
+#~ msgstr ""
+#~ " -e, --extreme využít více procesorového času pro kódování, čímž "
+#~ "se\n"
+#~ " zvýší kompresní poměr bez zvýšení paměti použité "
+#~ "kodérem"
+
+#~ msgid ""
+#~ " -M, --memory=NUM use roughly NUM bytes of memory at maximum; 0 "
+#~ "indicates\n"
+#~ " the default setting, which is 40 % of total RAM"
+#~ msgstr ""
+#~ " -M, --memory=POČ použít zhruba POČ bajtů paměti jako maximum; 0 "
+#~ "znamená\n"
+#~ " výchozí nastavení, což je 40% celkového množství "
+#~ "paměti"
+
+#~ msgid ""
+#~ "\n"
+#~ " --subblock[=OPTS] Subblock filter; valid OPTS (valid values; "
+#~ "default):\n"
+#~ " size=NUM number of bytes of data per subblock\n"
+#~ " (1 - 256Mi; 4Ki)\n"
+#~ " rle=NUM run-length encoder chunk size (0-256; "
+#~ "0)"
+#~ msgstr ""
+#~ "\n"
+#~ " --subblock[=VOLBY] Subblokový filtr; platné VOLBY (platné hodnoty; "
+#~ "výchozí):\n"
+#~ " size=POČ počet bajtů dat na subblok\n"
+#~ " (1 - 256 Mi; 4 Ki)\n"
+#~ " rle=POČ velikost dávky pro kodér run-length "
+#~ "(0-256; 0)"
+
+#~ msgid ""
+#~ "On this system and configuration, this program will use a maximum of "
+#~ "roughly\n"
+#~ "%s MiB RAM and "
+#~ msgstr ""
+#~ "Na tomto systému a s tímto nastavením použije tento program maximum ze "
+#~ "zhruba\n"
+#~ "%s MiB RAM a "
+
+#~ msgid ""
+#~ "one thread.\n"
+#~ "\n"
+#~ msgstr ""
+#~ "jedno vlákno.\n"
+#~ "\n"
+
+#~ msgid "%s: Invalid multiplier suffix. Valid suffixes:"
+#~ msgstr "%s: Neplatná přípona. Platné přípony jsou:"
diff --git a/po/de.po b/po/de.po
new file mode 100644
index 000000000000..d88b8cd8a5ec
--- /dev/null
+++ b/po/de.po
@@ -0,0 +1,903 @@
+# XZ Utils German translation
+# This file is put in the public domain.
+# Andre Noll <maan@systemlinux.org>, 2010.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: XZ Utils 4.999.9beta\n"
+"Report-Msgid-Bugs-To: lasse.collin@tukaani.org\n"
+"POT-Creation-Date: 2010-09-11 17:07+0200\n"
+"PO-Revision-Date: 2010-09-07 20:27+0200\n"
+"Last-Translator: <maan@systemlinux.org>\n"
+"Language-Team: German\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/xz/args.c:333
+#, c-format
+msgid "%s: Unknown file format type"
+msgstr "%s: Unbekanntes file format"
+
+#: src/xz/args.c:356 src/xz/args.c:364
+#, c-format
+msgid "%s: Unsupported integrity check type"
+msgstr "%s: Integritäts-Check Typ nicht unterstützt"
+
+#: src/xz/args.c:382
+msgid "Only one file can be specified with `--files' or `--files0'."
+msgstr ""
+"Nur ein file kann als Argument für --files oder --files0 angegeben werden."
+
+#: src/xz/args.c:445
+#, c-format
+msgid "The environment variable %s contains too many arguments"
+msgstr "Die Umgebungsvariable %s enthält zu viele Argumente"
+
+#: src/xz/coder.c:95
+msgid "Maximum number of filters is four"
+msgstr "Maximal vier Filter möglich"
+
+#: src/xz/coder.c:108
+msgid "Memory usage limit is too low for the given filter setup."
+msgstr ""
+"Das Speicher Limit ist zu niedrig für die gegebene Filter Konfiguration."
+
+#: src/xz/coder.c:129
+msgid "Using a preset in raw mode is discouraged."
+msgstr "Verwendung der Voreinstellung im raw Modus wird nicht empfohlen."
+
+#: src/xz/coder.c:131
+msgid "The exact options of the presets may vary between software versions."
+msgstr ""
+"Die genauen Optionen der Voreinstellung können zwischen Software Versionen "
+"variieren."
+
+#: src/xz/coder.c:157
+msgid "The .lzma format supports only the LZMA1 filter"
+msgstr "Das .lzma Format unterstützt nur den LZMA1 Filter"
+
+#: src/xz/coder.c:165
+msgid "LZMA1 cannot be used with the .xz format"
+msgstr "LZMA1 kann nicht mit dem .xz Format verwendet werden"
+
+#: src/xz/coder.c:182
+msgid "Unsupported filter chain or filter options"
+msgstr "Optionen nicht unterstützt"
+
+#: src/xz/coder.c:190
+#, c-format
+msgid "Decompression will need %s MiB of memory."
+msgstr "Dekompression wird %s MiB Speicher brauchen."
+
+#: src/xz/coder.c:247
+#, c-format
+msgid ""
+"Adjusted LZMA%c dictionary size from %s MiB to %s MiB to not exceed the "
+"memory usage limit of %s MiB"
+msgstr ""
+"Passte LZMA%c Wörterbuch Größe von %s MiB to %s MiB an, um nicht das "
+"Speicher Nutzungslimit von %s MiB zu übersteigen"
+
+#. TRANSLATORS: When compression or decompression finishes,
+#. and xz is going to remove the source file, xz first checks
+#. if the source file still exists, and if it does, does its
+#. device and inode numbers match what xz saw when it opened
+#. the source file. If these checks fail, this message is
+#. shown, %s being the filename, and the file is not deleted.
+#. The check for device and inode numbers is there, because
+#. it is possible that the user has put a new file in place
+#. of the original file, and in that case it obviously
+#. shouldn't be removed.
+#: src/xz/file_io.c:137
+#, c-format
+msgid "%s: File seems to have been moved, not removing"
+msgstr ""
+"%s: Datei scheint umbenannt worden zu sein, daher wird sie nicht gelöscht"
+
+#: src/xz/file_io.c:144 src/xz/file_io.c:590
+#, c-format
+msgid "%s: Cannot remove: %s"
+msgstr "%s: Kann nicht löschen: %s"
+
+#: src/xz/file_io.c:169
+#, c-format
+msgid "%s: Cannot set the file owner: %s"
+msgstr "%s: Kann Datei Eigentümer nicht setzen: %s"
+
+#: src/xz/file_io.c:175
+#, c-format
+msgid "%s: Cannot set the file group: %s"
+msgstr "%s: Kann Datei Gruppe nicht setzen: %s"
+
+#: src/xz/file_io.c:194
+#, c-format
+msgid "%s: Cannot set the file permissions: %s"
+msgstr "%s: Kann Zugriffsrechte nicht setzen: %s"
+
+#: src/xz/file_io.c:337 src/xz/file_io.c:420
+#, c-format
+msgid "%s: Is a symbolic link, skipping"
+msgstr "%s: Überspringe symbolischen Verweis"
+
+#: src/xz/file_io.c:455
+#, c-format
+msgid "%s: Is a directory, skipping"
+msgstr "%s: Überspringe Verzeichnis"
+
+#: src/xz/file_io.c:462
+#, c-format
+msgid "%s: Not a regular file, skipping"
+msgstr "%s: Keine reguläre Datei, überspringe"
+
+#: src/xz/file_io.c:479
+#, c-format
+msgid "%s: File has setuid or setgid bit set, skipping"
+msgstr "%s: Datei hat das setuid oder setgid Bit gesetzt, überspringe"
+
+#: src/xz/file_io.c:486
+#, c-format
+msgid "%s: File has sticky bit set, skipping"
+msgstr "%s: Datei hat sticky Bit gesetzt, überspringe"
+
+#: src/xz/file_io.c:493
+#, c-format
+msgid "%s: Input file has more than one hard link, skipping"
+msgstr "%s: Eingabedatei hat mehr als einen hard link, überspringe"
+
+#: src/xz/file_io.c:714
+#, c-format
+msgid "Error restoring the O_APPEND flag to standard output: %s"
+msgstr ""
+"Fehler beim Wiederherstellen des O_APPEND flags bei Standard Output: %s"
+
+#: src/xz/file_io.c:726
+#, c-format
+msgid "%s: Closing the file failed: %s"
+msgstr "%s: Fehler beim Schießen der Datei: %s"
+
+#: src/xz/file_io.c:762 src/xz/file_io.c:946
+#, c-format
+msgid "%s: Seeking failed when trying to create a sparse file: %s"
+msgstr ""
+"%s: Positionierungsfehler beim Versuch eine sparse Datei zu erzeugen: %s"
+
+#: src/xz/file_io.c:821
+#, c-format
+msgid "%s: Read error: %s"
+msgstr "%s: Lesefehler: %s"
+
+#: src/xz/file_io.c:844
+#, c-format
+msgid "%s: Error seeking the file: %s"
+msgstr "%s: Fehler beim Lesen der Dateinamen: %s"
+
+#: src/xz/file_io.c:854
+#, c-format
+msgid "%s: Unexpected end of file"
+msgstr "%s: Unerwartetes Ende der Datei"
+
+#: src/xz/file_io.c:904
+#, c-format
+msgid "%s: Write error: %s"
+msgstr "%s: Schreibfehler: %s"
+
+#: src/xz/hardware.c:100
+msgid "Disabled"
+msgstr "Deaktiviert"
+
+#. TRANSLATORS: Test with "xz --info-memory" to see if
+#. the alignment looks nice.
+#: src/xz/hardware.c:119
+msgid "Total amount of physical memory (RAM): "
+msgstr "Gesamtmenge physikalischer Speicher (RAM): "
+
+#: src/xz/hardware.c:121
+msgid "Memory usage limit for compression: "
+msgstr "Speicher Nutzungslimit für Kompression: "
+
+#: src/xz/hardware.c:123
+msgid "Memory usage limit for decompression: "
+msgstr "Speicher Nutzungslimit für Dekompression: "
+
+#. TRANSLATORS: Indicates that there is no integrity check.
+#. This string is used in tables, so the width must not
+#. exceed ten columns with a fixed-width font.
+#: src/xz/list.c:62
+msgid "None"
+msgstr "Kein"
+
+#. TRANSLATORS: Indicates that integrity check name is not known,
+#. but the Check ID is known (here 2). This and other "Unknown-N"
+#. strings are used in tables, so the width must not exceed ten
+#. columns with a fixed-width font. It's OK to omit the dash if
+#. you need space for one extra letter.
+#: src/xz/list.c:69
+msgid "Unknown-2"
+msgstr "Unbek.2"
+
+#: src/xz/list.c:70
+msgid "Unknown-3"
+msgstr "Unbek.3"
+
+#: src/xz/list.c:72
+msgid "Unknown-5"
+msgstr "Unbek.5"
+
+#: src/xz/list.c:73
+msgid "Unknown-6"
+msgstr "Unbek.6"
+
+#: src/xz/list.c:74
+msgid "Unknown-7"
+msgstr "Unbek.7"
+
+#: src/xz/list.c:75
+msgid "Unknown-8"
+msgstr "Unbek.8"
+
+#: src/xz/list.c:76
+msgid "Unknown-9"
+msgstr "Unbek.9"
+
+#: src/xz/list.c:78
+msgid "Unknown-11"
+msgstr "Unbek.11"
+
+#: src/xz/list.c:79
+msgid "Unknown-12"
+msgstr "Unbek.12"
+
+#: src/xz/list.c:80
+msgid "Unknown-13"
+msgstr "Unbek.13"
+
+#: src/xz/list.c:81
+msgid "Unknown-14"
+msgstr "Unbek.14"
+
+#: src/xz/list.c:82
+msgid "Unknown-15"
+msgstr "Unbek.15"
+
+#: src/xz/list.c:126
+#, c-format
+msgid "%s: File is empty"
+msgstr "%s: Datei ist leer"
+
+#: src/xz/list.c:131
+#, c-format
+msgid "%s: Too small to be a valid .xz file"
+msgstr "%s: Zu klein um ein gültiges .xz file zu sein"
+
+#. TRANSLATORS: These are column headings. From Strms (Streams)
+#. to Ratio, the columns are right aligned. Check and Filename
+#. are left aligned. If you need longer words, it's OK to
+#. use two lines here. Test with "xz -l foo.xz".
+#: src/xz/list.c:612
+msgid "Strms Blocks Compressed Uncompressed Ratio Check Filename"
+msgstr " Str. Blöcke Kompr. Unkompr. Verh. Check Dateiname"
+
+#: src/xz/list.c:652
+#, c-format
+msgid " Streams: %s\n"
+msgstr " Ströme: %s\n"
+
+#: src/xz/list.c:654
+#, c-format
+msgid " Blocks: %s\n"
+msgstr " Blöcke: %s\n"
+
+#: src/xz/list.c:656
+#, c-format
+msgid " Compressed size: %s\n"
+msgstr " Größe komprimiert: %s\n"
+
+#: src/xz/list.c:659
+#, c-format
+msgid " Uncompressed size: %s\n"
+msgstr " Größe unkomprimiert: %s\n"
+
+#: src/xz/list.c:662
+#, c-format
+msgid " Ratio: %s\n"
+msgstr " Verhältnis: %s\n"
+
+#: src/xz/list.c:664
+#, c-format
+msgid " Check: %s\n"
+msgstr " Check: %s\n"
+
+#: src/xz/list.c:665
+#, c-format
+msgid " Stream padding: %s\n"
+msgstr " Strom Auffüllung: %s\n"
+
+#. TRANSLATORS: The second line is column headings. All except
+#. Check are right aligned; Check is left aligned. Test with
+#. "xz -lv foo.xz".
+#: src/xz/list.c:693
+msgid ""
+" Streams:\n"
+" Stream Blocks CompOffset UncompOffset CompSize "
+"UncompSize Ratio Check Padding"
+msgstr ""
+" Ströme:\n"
+" Strom Blöcke KompOffset UnkompOffset KompGröße "
+"UnkompGröße Verh. Check Auffüllung"
+
+#. TRANSLATORS: The second line is column headings. All
+#. except Check are right aligned; Check is left aligned.
+#: src/xz/list.c:748
+#, c-format
+msgid ""
+" Blocks:\n"
+" Stream Block CompOffset UncompOffset TotalSize "
+"UncompSize Ratio Check"
+msgstr ""
+" Blöcke:\n"
+" Strom Block KompOffset UnkompOffset TotalGröße "
+"UnkompGröße Verh. Check"
+
+#. TRANSLATORS: These are additional column headings
+#. for the most verbose listing mode. CheckVal
+#. (Check value), Flags, and Filters are left aligned.
+#. Header (Block Header Size), CompSize, and MemUsage
+#. are right aligned. %*s is replaced with 0-120
+#. spaces to make the CheckVal column wide enough.
+#. Test with "xz -lvv foo.xz".
+#: src/xz/list.c:760
+#, c-format
+msgid " CheckVal %*s Header Flags CompSize MemUsage Filters"
+msgstr " CheckWert %*s Kopf Schalter KompGröße Speicher Filter"
+
+#: src/xz/list.c:838 src/xz/list.c:1007
+#, c-format
+msgid " Memory needed: %s MiB\n"
+msgstr " Benötigter Speicher: %s MiB\n"
+
+#: src/xz/list.c:840 src/xz/list.c:1009
+#, c-format
+msgid " Sizes in headers: %s\n"
+msgstr " Größe in Köpfen: %s\n"
+
+#: src/xz/list.c:841 src/xz/list.c:1010
+msgid "Yes"
+msgstr "Ja"
+
+#: src/xz/list.c:841 src/xz/list.c:1010
+msgid "No"
+msgstr "Nein"
+
+#. TRANSLATORS: %s is an integer. Only the plural form of this
+#. message is used (e.g. "2 files"). Test with "xz -l foo.xz bar.xz".
+#: src/xz/list.c:986
+#, c-format
+msgid "%s file\n"
+msgid_plural "%s files\n"
+msgstr[0] "%s Datei\n"
+msgstr[1] "%s Dateien\n"
+
+#: src/xz/list.c:999
+msgid "Totals:"
+msgstr "Gesamt:"
+
+#: src/xz/list.c:1000
+#, c-format
+msgid " Number of files: %s\n"
+msgstr " Anzahl Dateien: %s\n"
+
+#: src/xz/list.c:1072
+msgid "--list works only on .xz files (--format=xz or --format=auto)"
+msgstr ""
+"--list funktioniert nur mit .xz Dateien (--format=xz oder --format=auto)"
+
+#: src/xz/list.c:1078
+msgid "--list does not support reading from standard input"
+msgstr "--list unterstützt kein Lesen der Standardeingabe"
+
+#: src/xz/main.c:89
+#, c-format
+msgid "%s: Error reading filenames: %s"
+msgstr "%s: Fehler beim Lesen der Dateinamen: %s"
+
+#: src/xz/main.c:96
+#, c-format
+msgid "%s: Unexpected end of input when reading filenames"
+msgstr "%s: Unerwartetes Ende beim Lesen der Dateinamen"
+
+#: src/xz/main.c:120
+#, c-format
+msgid ""
+"%s: Null character found when reading filenames; maybe you meant to use `--"
+"files0' instead of `--files'?"
+msgstr ""
+"%s: Null Charakter gefunden beim Lesen der Dateinamen; Meinten Sie `--"
+"files0' statt `--files'?"
+
+#: src/xz/main.c:174
+msgid "Compression and decompression with --robot are not supported yet."
+msgstr "Kompression und Dekompression mit --robot ist noch nicht unterstützt."
+
+#: src/xz/main.c:231
+msgid ""
+"Cannot read data from standard input when reading filenames from standard "
+"input"
+msgstr ""
+"Lesen der Standardeingabe ist nicht möglich, wenn die Dateinamen auch von "
+"der Standardeingabe gelesen werden"
+
+#: src/xz/message.c:800 src/xz/message.c:844
+msgid "Internal error (bug)"
+msgstr "Interner Fehler (Bug)"
+
+#: src/xz/message.c:807
+msgid "Cannot establish signal handlers"
+msgstr "Kann Signal Routine nicht setzen"
+
+#: src/xz/message.c:816
+msgid "No integrity check; not verifying file integrity"
+msgstr "Kein Integritäts-Check; werde Datei-Integrität nicht überprüfen"
+
+#: src/xz/message.c:819
+msgid "Unsupported type of integrity check; not verifying file integrity"
+msgstr ""
+"Typ des Integritäts-Checks nicht unterstützt; werde Datei-Integrität nicht "
+"überprüfen"
+
+#: src/xz/message.c:826
+msgid "Memory usage limit reached"
+msgstr "Speicher-Limit erreicht"
+
+#: src/xz/message.c:829
+msgid "File format not recognized"
+msgstr "Datei Format nicht erkannt"
+
+#: src/xz/message.c:832
+msgid "Unsupported options"
+msgstr "Optionen nicht unterstützt"
+
+#: src/xz/message.c:835
+msgid "Compressed data is corrupt"
+msgstr "Komprimierte Daten sind korrupt"
+
+#: src/xz/message.c:838
+msgid "Unexpected end of input"
+msgstr "Unerwartetes Eingabe Ende"
+
+#: src/xz/message.c:886
+#, c-format
+msgid "%s MiB of memory is required. The limit is %s."
+msgstr "%s MiB Speicher wird benötigt. Limit ist %s."
+
+#: src/xz/message.c:1053
+#, c-format
+msgid "%s: Filter chain: %s\n"
+msgstr "%s: Filter Kette: %s\n"
+
+#: src/xz/message.c:1063
+#, c-format
+msgid "Try `%s --help' for more information."
+msgstr "Versuchen Sie `%s --help' für mehr Informationen."
+
+#: src/xz/message.c:1089
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... [FILE]...\n"
+"Compress or decompress FILEs in the .xz format.\n"
+"\n"
+msgstr ""
+"Benutzung: %s [OPTION]... [DATEI]...\n"
+"Komprimiert oder dekomprimiert .xz DATEI(EN).\n"
+"\n"
+
+#: src/xz/message.c:1096
+msgid ""
+"Mandatory arguments to long options are mandatory for short options too.\n"
+msgstr ""
+"Obligatorische Argumente für lange Optionen sind auch für kurze Optionen\n"
+"zwingend.\n"
+
+#: src/xz/message.c:1100
+msgid " Operation mode:\n"
+msgstr " Operationsmodus:\n"
+
+#: src/xz/message.c:1103
+msgid ""
+" -z, --compress force compression\n"
+" -d, --decompress force decompression\n"
+" -t, --test test compressed file integrity\n"
+" -l, --list list information about .xz files"
+msgstr ""
+" -z, --compress erzwinge Komprimierung\n"
+" -d, --decompress erzwinge Dekomprimierung\n"
+" -t, --test überprüfe Datei Integrität\n"
+" -l, --list liste Datei Informationen"
+
+#: src/xz/message.c:1109
+msgid ""
+"\n"
+" Operation modifiers:\n"
+msgstr ""
+"\n"
+" Operationsmodifikatoren:\n"
+
+#: src/xz/message.c:1112
+msgid ""
+" -k, --keep keep (don't delete) input files\n"
+" -f, --force force overwrite of output file and (de)compress links\n"
+" -c, --stdout write to standard output and don't delete input files"
+msgstr ""
+" -k, --keep Eingabedateien beibehalten (nicht löschen)\n"
+" -f, --force erzwinge Überschreiben der Ausgabedatei und\n"
+" (de)komprimiere Verweise (Links)\n"
+" -c, --stdout schreibe nach Standard Output und lösche nicht die\n"
+" Eingabedateien"
+
+#: src/xz/message.c:1118
+msgid ""
+" --no-sparse do not create sparse files when decompressing\n"
+" -S, --suffix=.SUF use the suffix `.SUF' on compressed files\n"
+" --files[=FILE] read filenames to process from FILE; if FILE is\n"
+" omitted, filenames are read from the standard input;\n"
+" filenames must be terminated with the newline "
+"character\n"
+" --files0[=FILE] like --files but use the null character as terminator"
+msgstr ""
+" --no-sparse erzeuge keine sparse Datei beim Dekomprimieren\n"
+" -S, --suffix=.SUF benutze `.SUF' Endung für komprimierte Dateien\n"
+" --files=[DATEI] lese zu verarbeitende Dateinamen von DATEI; falls\n"
+" DATEI nicht angegeben wurde, werden Dateinamen\n"
+" von Standard Input gelesen. Dateinamen müssen mit\n"
+" einem Zeilenumbruch voneinander getrennt werden\n"
+" --files0=[DATEI] wie --files, aber benutze den Null Charakter als "
+"Trenner"
+
+#: src/xz/message.c:1126
+msgid ""
+"\n"
+" Basic file format and compression options:\n"
+msgstr ""
+"\n"
+" Grundlegende Optionen für Dateiformat und Kompression:\n"
+
+#: src/xz/message.c:1128
+msgid ""
+" -F, --format=FMT file format to encode or decode; possible values are\n"
+" `auto' (default), `xz', `lzma', and `raw'\n"
+" -C, --check=CHECK integrity check type: `none' (use with caution),\n"
+" `crc32', `crc64' (default), or `sha256'"
+msgstr ""
+" -F, --format=FMT Dateiformat zur Kodierung oder Dekodierung; "
+"mögliche\n"
+" Werte sind `auto' (Voreinstellung), `xz', `lzma' "
+"und\n"
+" `raw'\n"
+" -C, --check=CHECK Typ des Integritätschecks: `none' (Vorsicht), "
+"`crc32',\n"
+" `crc64' (Voreinstellung), oder `sha256'"
+
+#: src/xz/message.c:1135
+msgid ""
+" -0 ... -9 compression preset; default is 6; take compressor "
+"*and*\n"
+" decompressor memory usage into account before using 7-"
+"9!"
+msgstr ""
+" -0 .. -9 Kompressionseinstellung; Voreinstellung is 6. "
+"Beachten\n"
+" Sie den Speicherverbrauch des Komprimieres *und* "
+"des\n"
+" Dekomprimierers, wenn Sie 7-9 benutzen!"
+
+#: src/xz/message.c:1139
+msgid ""
+" -e, --extreme try to improve compression ratio by using more CPU "
+"time;\n"
+" does not affect decompressor memory requirements"
+msgstr ""
+" -e, --extreme Versuche durch stärkere CPU Nutzung das "
+"Kompressions-\n"
+" verhältnis zu verbessern. Das beeinflusst nicht den\n"
+" Speicherbedarf des Dekomprimierers."
+
+#: src/xz/message.c:1144
+#, no-c-format
+msgid ""
+" --memlimit-compress=LIMIT\n"
+" --memlimit-decompress=LIMIT\n"
+" -M, --memlimit=LIMIT\n"
+" set memory usage limit for compression, "
+"decompression,\n"
+" or both; LIMIT is in bytes, % of RAM, or 0 for defaults"
+msgstr ""
+" --memlimit-compress=LIMIT\n"
+" --memlimit-decompress=LIMIT\n"
+" -M, --memlimit=LIMIT Setze Speicher Nutzungslimit für Kompression,\n"
+" Dekompression, oder beides; LIMIT ist in bytes, % "
+"RAM,\n"
+" oder 0 für Grundeinstellungen."
+
+#: src/xz/message.c:1151
+msgid ""
+" --no-adjust if compression settings exceed the memory usage "
+"limit,\n"
+" give an error instead of adjusting the settings "
+"downwards"
+msgstr ""
+" --no-adjust Wenn die Kompressionseinstellungen das Speicher\n"
+" Nutzungslimit übersteigen, erzeuge einen Fehler "
+"statt\n"
+" die Einstellungen nach unten anzupassen."
+
+#: src/xz/message.c:1157
+msgid ""
+"\n"
+" Custom filter chain for compression (alternative for using presets):"
+msgstr ""
+"\n"
+" User-definierte Filter Kette für Kompression (alternativ zu Voreinstellung):"
+
+#: src/xz/message.c:1166
+msgid ""
+"\n"
+" --lzma1[=OPTS] LZMA1 or LZMA2; OPTS is a comma-separated list of zero "
+"or\n"
+" --lzma2[=OPTS] more of the following options (valid values; "
+"default):\n"
+" preset=PRE reset options to a preset (0-9[e])\n"
+" dict=NUM dictionary size (4KiB - 1536MiB; 8MiB)\n"
+" lc=NUM number of literal context bits (0-4; 3)\n"
+" lp=NUM number of literal position bits (0-4; 0)\n"
+" pb=NUM number of position bits (0-4; 2)\n"
+" mode=MODE compression mode (fast, normal; normal)\n"
+" nice=NUM nice length of a match (2-273; 64)\n"
+" mf=NAME match finder (hc3, hc4, bt2, bt3, bt4; "
+"bt4)\n"
+" depth=NUM maximum search depth; 0=automatic "
+"(default)"
+msgstr ""
+"\n"
+" --lzma1[=OPTIONEN] LZMA1 oder LZMA2; OPTIONEN ist eine durch Kommata\n"
+" --lzma2[=OPTIONEN] getrennte Liste bestehend aus den folgenden "
+"Optionen\n"
+" (zulässige Werte; Voreinstellung):\n"
+" preset=NUM Setze Optionen zurück zu "
+"Voreinstellung\n"
+" (0-9[e])\n"
+" dict=NUM Wörterbuch Größe (4 KiB - 1536 MiB; 8 "
+"MiB)\n"
+" lc=NUM Anzahl der Literal Kontext Bits (0-4; "
+"3)\n"
+" lp=NUM Anzahl der Literal Positionsbits (0-4; "
+"0)\n"
+" pb=NUM Anzahl der Positionsbits (0-4; 2)\n"
+" mode=MODUS Kompressionsmodus (fast, normal; "
+"normal)\n"
+" nice=NUM Nice-Länge eines Treffers (2-273; 64)\n"
+" mf=NAME Algorithmus zum Auffinden von\n"
+" Übereinstimmungen (hc3, hc4, bt2, bt3, "
+"bt4;\n"
+" bt4)\n"
+" depth=NUM Maximale Suchtiefe; 0=automatisch\n"
+" (Voreinstellung)"
+
+#: src/xz/message.c:1181
+msgid ""
+"\n"
+" --x86[=OPTS] x86 BCJ filter (32-bit and 64-bit)\n"
+" --powerpc[=OPTS] PowerPC BCJ filter (big endian only)\n"
+" --ia64[=OPTS] IA-64 (Itanium) BCJ filter\n"
+" --arm[=OPTS] ARM BCJ filter (little endian only)\n"
+" --armthumb[=OPTS] ARM-Thumb BCJ filter (little endian only)\n"
+" --sparc[=OPTS] SPARC BCJ filter\n"
+" Valid OPTS for all BCJ filters:\n"
+" start=NUM start offset for conversions (default=0)"
+msgstr ""
+"\n"
+" --x86[=OPTIONEN] x86 BCJ Filter (32-bit und 64-bit)\n"
+" --powerpc[=OPTIONEN] PowerPC BCJ Filter (nur big endian)\n"
+" --ia64[=OPTIONEN] IA64 (Itanium) BCJ Filter\n"
+" --arm[=OPTIONEN] ARM BCJ Filter (nur little endian)\n"
+" --armthumb[=OPTIONEN] ARM-Thumb BCJ Filter (nur little endian)\n"
+" --sparc[=OPTIONEN] SPARC BCJ Filter\n"
+" Zulässige Optionen für alle BCJ Filter:\n"
+" start=NUM Start-Offset für Konversion\n"
+" (Voreinstellung=0)"
+
+#: src/xz/message.c:1193
+msgid ""
+"\n"
+" --delta[=OPTS] Delta filter; valid OPTS (valid values; default):\n"
+" dist=NUM distance between bytes being subtracted\n"
+" from each other (1-256; 1)"
+msgstr ""
+"\n"
+" --delta[=OPTIONEN] Delta Filter; zulässige Optionen (gültige Werte;\n"
+" Voreinstellung):\n"
+" dist=NUM Abstand zwischen den Bytes, die "
+"voneinander\n"
+" subtrahiert werden (1-256; 1)"
+
+#: src/xz/message.c:1201
+msgid ""
+"\n"
+" Other options:\n"
+msgstr ""
+"\n"
+" Andere Optionen:\n"
+
+#: src/xz/message.c:1204
+msgid ""
+" -q, --quiet suppress warnings; specify twice to suppress errors "
+"too\n"
+" -v, --verbose be verbose; specify twice for even more verbose"
+msgstr ""
+" -q, --quiet unterdrücke Warnungen; benutze diese Option zweimal\n"
+" um auch Fehlermeldungen zu unterdrücken\n"
+" -v, --verbose sei gesprächig; benutze diese Option zweimal um "
+"noch\n"
+" gesprächiger zu sein"
+
+#: src/xz/message.c:1209
+msgid " -Q, --no-warn make warnings not affect the exit status"
+msgstr " -Q, --no-warn Warnungen verändern nicht den exit status"
+
+#: src/xz/message.c:1211
+msgid ""
+" --robot use machine-parsable messages (useful for scripts)"
+msgstr ""
+" --robot benutze Maschinen-lesbare Meldungen (nützlich für\n"
+" Skripte)"
+
+#: src/xz/message.c:1214
+msgid ""
+" --info-memory display the total amount of RAM and the currently "
+"active\n"
+" memory usage limits, and exit"
+msgstr " --info-memory zeige Speicherlimit an und terminiere"
+
+#: src/xz/message.c:1217
+msgid ""
+" -h, --help display the short help (lists only the basic options)\n"
+" -H, --long-help display this long help and exit"
+msgstr ""
+" -h, --help zeige kurze Hilfe and (zeigt nur die grundlegenden\n"
+" Optionen)\n"
+" -H, --long-help zeige diese lange Hilfe an und terminiere"
+
+#: src/xz/message.c:1221
+msgid ""
+" -h, --help display this short help and exit\n"
+" -H, --long-help display the long help (lists also the advanced options)"
+msgstr ""
+" -h, --help zeige diese kurze Hilfe an und terminiere\n"
+" -H, --long-help zeige die lange Hilfe an (zeigt auch "
+"fortgeschrittene\n"
+" Optionen an)"
+
+#: src/xz/message.c:1226
+msgid " -V, --version display the version number and exit"
+msgstr " -V, --version zeige Versionsnummer an und terminiere"
+
+#: src/xz/message.c:1228
+msgid ""
+"\n"
+"With no FILE, or when FILE is -, read standard input.\n"
+msgstr ""
+"\n"
+"Wenn DATEI nicht angegeben wurde, oder DATEI gleich - ist, dann wird von\n"
+"der Standardeingabe gelesen.\n"
+
+#. TRANSLATORS: This message indicates the bug reporting address
+#. for this package. Please add _another line_ saying
+#. "Report translation bugs to <...>\n" with the email or WWW
+#. address for translation bugs. Thanks.
+#: src/xz/message.c:1234
+#, c-format
+msgid "Report bugs to <%s> (in English or Finnish).\n"
+msgstr ""
+"Melde Bugs an <%s> (in englisch oder finnisch).\n"
+"Melde Übersetzungsfehler an <maan@systemlinux.org> (in englisch oder "
+"deutsch).\n"
+
+#: src/xz/message.c:1236
+#, c-format
+msgid "%s home page: <%s>\n"
+msgstr "%s Homepage: <%s>\n"
+
+#: src/xz/options.c:86
+#, c-format
+msgid "%s: Options must be `name=value' pairs separated with commas"
+msgstr ""
+"%s: Optionen müssen in der Form `Name=Wert` gegeben werden, getrennt durch "
+"Kommata"
+
+#: src/xz/options.c:93
+#, c-format
+msgid "%s: Invalid option name"
+msgstr "%s: Ungültige Option"
+
+#: src/xz/options.c:113
+#, c-format
+msgid "%s: Invalid option value"
+msgstr "%s: Ungültiger Wert für Option"
+
+#: src/xz/options.c:247
+#, c-format
+msgid "Unsupported LZMA1/LZMA2 preset: %s"
+msgstr "LZMA1/LZMA2 Voreinstellung ist ungültig: %s"
+
+#: src/xz/options.c:355
+msgid "The sum of lc and lp must not exceed 4"
+msgstr "Die Summe aus lc und lp darf höchstens 4 sein"
+
+#: src/xz/options.c:359
+#, c-format
+msgid "The selected match finder requires at least nice=%<PRIu32>"
+msgstr ""
+"Der ausgewählte Algorithmus zum Auffinden von Übereinstimmungen braucht "
+"mindestens nice=%<PRIu32>"
+
+#: src/xz/suffix.c:79 src/xz/suffix.c:164
+#, c-format
+msgid ""
+"%s: With --format=raw, --suffix=.SUF is required unless writing to stdout"
+msgstr ""
+"%s: Mit --format=raw ist --sufix=.SUF notwendig, falls nicht nach stdout "
+"geschrieben wird"
+
+#: src/xz/suffix.c:99
+#, c-format
+msgid "%s: Filename has an unknown suffix, skipping"
+msgstr "%s: Dateiname hat unbekannte Endung, überspringe"
+
+#: src/xz/suffix.c:154
+#, c-format
+msgid "%s: File already has `%s' suffix, skipping"
+msgstr "%s: Datei hat bereits `%s' Endung, überspringe"
+
+#: src/xz/suffix.c:205
+#, c-format
+msgid "%s: Invalid filename suffix"
+msgstr "%s: Ungültige Datei Endung"
+
+#: src/xz/util.c:61
+#, c-format
+msgid "%s: Value is not a non-negative decimal integer"
+msgstr "%s: Wert ist keine nicht-negative ganze Zahl"
+
+#: src/xz/util.c:103
+#, c-format
+msgid "%s: Invalid multiplier suffix"
+msgstr "%s: Ungültige Einheit"
+
+#: src/xz/util.c:105
+msgid "Valid suffixes are `KiB' (2^10), `MiB' (2^20), and `GiB' (2^30)."
+msgstr "Gültige Einheiten sind `KiB' (2^10), `MiB' (2^20), und `GiB' (2^30)."
+
+#: src/xz/util.c:122
+#, c-format
+msgid "Value of the option `%s' must be in the range [%<PRIu64>, %<PRIu64>]"
+msgstr "Wert der Option `%s' muss im Bereich [%<PRIu64>, %<PRIu64>] sein"
+
+#: src/xz/util.c:247
+msgid "Empty filename, skipping"
+msgstr "Leere Dateiname, überspringe"
+
+#: src/xz/util.c:261
+msgid "Compressed data cannot be read from a terminal"
+msgstr "Komprimierte Daten können nicht vom Terminal gelesen werden"
+
+#: src/xz/util.c:274
+msgid "Compressed data cannot be written to a terminal"
+msgstr "Komprimierte Daten können nicht auf das Terminal geschrieben werden"
+
+#: src/common/tuklib_exit.c:39
+msgid "Writing to standard output failed"
+msgstr "Schreiben auf die Standardausgabe fehlgeschlagen"
+
+#: src/common/tuklib_exit.c:42
+msgid "Unknown error"
+msgstr "Unbekannter Fehler"
diff --git a/po/it.po b/po/it.po
new file mode 100644
index 000000000000..8e096dd4eaef
--- /dev/null
+++ b/po/it.po
@@ -0,0 +1,902 @@
+# Italian translation for xz-utils
+# This file is in the public domain
+# Gruppo traduzione italiano di Ubuntu-it <gruppo-traduzione@ubuntu-it.org>, 2009, 2010
+# Lorenzo De Liso <blackz@ubuntu.com>, 2010.
+# Milo Casagrande <milo@ubuntu.com>, 2009, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: xz-utils\n"
+"Report-Msgid-Bugs-To: lasse.collin@tukaani.org\n"
+"POT-Creation-Date: 2010-09-10 14:50+0300\n"
+"PO-Revision-Date: 2010-09-16 21:32+0200\n"
+"Last-Translator: Milo Casagrande <milo@ubuntu.com>\n"
+"Language-Team: Italian <tp@lists.linux.it>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2010-08-16 19:16+0000\n"
+"X-Generator: Launchpad (build Unknown)\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/xz/args.c:333
+#, c-format
+msgid "%s: Unknown file format type"
+msgstr "%s: tipo di formato del file sconosciutoN"
+
+#: src/xz/args.c:356 src/xz/args.c:364
+#, c-format
+msgid "%s: Unsupported integrity check type"
+msgstr "%s: tipo di controllo integrità non supportato"
+
+#: src/xz/args.c:382
+msgid "Only one file can be specified with `--files' or `--files0'."
+msgstr "Solo un file può essere specificato con \"--files\" o \"--files0\"."
+
+#: src/xz/args.c:445
+#, c-format
+msgid "The environment variable %s contains too many arguments"
+msgstr "La variabile d'ambiente %s contiene troppi argomenti"
+
+#: src/xz/coder.c:95
+msgid "Maximum number of filters is four"
+msgstr "Il numero massimo di filtri è quattro"
+
+#: src/xz/coder.c:108
+msgid "Memory usage limit is too low for the given filter setup."
+msgstr ""
+"Il limite dell'uso della memoria è troppo basso per l'impostazione del "
+"filtro dato."
+
+#: src/xz/coder.c:129
+msgid "Using a preset in raw mode is discouraged."
+msgstr "Non è consigliato usare un preset nella modalità raw."
+
+#: src/xz/coder.c:131
+msgid "The exact options of the presets may vary between software versions."
+msgstr ""
+"Le opzioni esatte per i preset possono variare tra le versioni del software."
+
+#: src/xz/coder.c:157
+msgid "The .lzma format supports only the LZMA1 filter"
+msgstr "Il formato .lzma supporta solo il filtro LZMA1"
+
+#: src/xz/coder.c:165
+msgid "LZMA1 cannot be used with the .xz format"
+msgstr "LZMA1 non può essere usato con il formato .xz"
+
+#: src/xz/coder.c:182
+msgid "Unsupported filter chain or filter options"
+msgstr "Catena di filtri od opzioni del filtro non supportata"
+
+#: src/xz/coder.c:190
+#, c-format
+msgid "Decompression will need %s MiB of memory."
+msgstr "L'estrazione necessita di %s MiB di memoria."
+
+#: src/xz/coder.c:247
+#, c-format
+msgid ""
+"Adjusted LZMA%c dictionary size from %s MiB to %s MiB to not exceed the "
+"memory usage limit of %s MiB"
+msgstr ""
+"Regolata la dimensione del dizionario LZMA%c da %s MiB a %s MiB per non "
+"superare il limite dell'uso della memoria di %s MiB"
+
+#. TRANSLATORS: When compression or decompression finishes,
+#. and xz is going to remove the source file, xz first checks
+#. if the source file still exists, and if it does, does its
+#. device and inode numbers match what xz saw when it opened
+#. the source file. If these checks fail, this message is
+#. shown, %s being the filename, and the file is not deleted.
+#. The check for device and inode numbers is there, because
+#. it is possible that the user has put a new file in place
+#. of the original file, and in that case it obviously
+#. shouldn't be removed.
+#: src/xz/file_io.c:137
+#, c-format
+msgid "%s: File seems to have been moved, not removing"
+msgstr "%s: sembra che il file sia stato spostato, non viene rimosso"
+
+#: src/xz/file_io.c:144 src/xz/file_io.c:590
+#, c-format
+msgid "%s: Cannot remove: %s"
+msgstr "%s: impossibile rimuovere: %s"
+
+#: src/xz/file_io.c:169
+#, c-format
+msgid "%s: Cannot set the file owner: %s"
+msgstr "%s: impossibile impostare il proprietario del file: %s"
+
+#: src/xz/file_io.c:175
+#, c-format
+msgid "%s: Cannot set the file group: %s"
+msgstr "%s: impossibile impostare il gruppo del file: %s"
+
+#: src/xz/file_io.c:194
+#, c-format
+msgid "%s: Cannot set the file permissions: %s"
+msgstr "%s: impossibile impostare i permessi del file: %s"
+
+#: src/xz/file_io.c:337 src/xz/file_io.c:420
+#, c-format
+msgid "%s: Is a symbolic link, skipping"
+msgstr "%s: è un collegamento simbolico, viene saltato"
+
+#: src/xz/file_io.c:455
+#, c-format
+msgid "%s: Is a directory, skipping"
+msgstr "%s: è una directory, viene saltata"
+
+#: src/xz/file_io.c:462
+#, c-format
+msgid "%s: Not a regular file, skipping"
+msgstr "%s: non è un file regolare, viene saltato"
+
+#: src/xz/file_io.c:479
+#, c-format
+msgid "%s: File has setuid or setgid bit set, skipping"
+msgstr "%s: il file ha il bit setuid o setgid impostato, viene saltato"
+
+#: src/xz/file_io.c:486
+#, c-format
+msgid "%s: File has sticky bit set, skipping"
+msgstr "%s: il file ha lo sticky bit impostato, viene saltato"
+
+#: src/xz/file_io.c:493
+#, c-format
+msgid "%s: Input file has more than one hard link, skipping"
+msgstr "%s: il file di input ha più di un collegamento fisico, viene saltato"
+
+#: src/xz/file_io.c:714
+#, c-format
+msgid "Error restoring the O_APPEND flag to standard output: %s"
+msgstr "Errore nel ripristinare la flag O_APPEND sullo standard output: %s"
+
+#: src/xz/file_io.c:726
+#, c-format
+msgid "%s: Closing the file failed: %s"
+msgstr "%s: chiusura del file non riuscita: %s"
+
+#: src/xz/file_io.c:762 src/xz/file_io.c:946
+#, c-format
+msgid "%s: Seeking failed when trying to create a sparse file: %s"
+msgstr ""
+"%s: posizionamento non riuscito nel tentativo di creare un file sparso: %s"
+
+#: src/xz/file_io.c:821
+#, c-format
+msgid "%s: Read error: %s"
+msgstr "%s: errore di lettura: %s"
+
+#: src/xz/file_io.c:844
+#, c-format
+msgid "%s: Error seeking the file: %s"
+msgstr "%s: errore nel cercare il file: %s"
+
+#: src/xz/file_io.c:854
+#, c-format
+msgid "%s: Unexpected end of file"
+msgstr "%s: fine del file inaspettata"
+
+#: src/xz/file_io.c:904
+#, c-format
+msgid "%s: Write error: %s"
+msgstr "%s: errore di scrittura: %s"
+
+#: src/xz/hardware.c:100
+msgid "Disabled"
+msgstr "Disabilitato"
+
+#. TRANSLATORS: Test with "xz --info-memory" to see if
+#. the alignment looks nice.
+#: src/xz/hardware.c:119
+msgid "Total amount of physical memory (RAM): "
+msgstr "Quantità totale di memoria fisica (RAM): "
+
+#: src/xz/hardware.c:121
+msgid "Memory usage limit for compression: "
+msgstr "Limite utilizzo memoria per la compressione: "
+
+#: src/xz/hardware.c:123
+msgid "Memory usage limit for decompression: "
+msgstr "Limite utilizzo memoria per l'estrazione: "
+
+#. TRANSLATORS: Indicates that there is no integrity check.
+#. This string is used in tables, so the width must not
+#. exceed ten columns with a fixed-width font.
+#: src/xz/list.c:62
+msgid "None"
+msgstr "Nessuno"
+
+#. TRANSLATORS: Indicates that integrity check name is not known,
+#. but the Check ID is known (here 2). This and other "Unknown-N"
+#. strings are used in tables, so the width must not exceed ten
+#. columns with a fixed-width font. It's OK to omit the dash if
+#. you need space for one extra letter.
+#: src/xz/list.c:69
+msgid "Unknown-2"
+msgstr "Sconosc2"
+
+#: src/xz/list.c:70
+msgid "Unknown-3"
+msgstr "Sconosc3"
+
+#: src/xz/list.c:72
+msgid "Unknown-5"
+msgstr "Sconosc5"
+
+#: src/xz/list.c:73
+msgid "Unknown-6"
+msgstr "Sconosc6"
+
+#: src/xz/list.c:74
+msgid "Unknown-7"
+msgstr "Sconosc7"
+
+#: src/xz/list.c:75
+msgid "Unknown-8"
+msgstr "Sconosc8"
+
+#: src/xz/list.c:76
+msgid "Unknown-9"
+msgstr "Sconosc9"
+
+#: src/xz/list.c:78
+msgid "Unknown-11"
+msgstr "Sconosc11"
+
+#: src/xz/list.c:79
+msgid "Unknown-12"
+msgstr "Sconosc12"
+
+#: src/xz/list.c:80
+msgid "Unknown-13"
+msgstr "Sconosc13"
+
+#: src/xz/list.c:81
+msgid "Unknown-14"
+msgstr "Sconosc14"
+
+#: src/xz/list.c:82
+msgid "Unknown-15"
+msgstr "Sconosc15"
+
+#: src/xz/list.c:126
+#, c-format
+msgid "%s: File is empty"
+msgstr "%s: il file è vuoto"
+
+#: src/xz/list.c:131
+#, c-format
+msgid "%s: Too small to be a valid .xz file"
+msgstr "%s: troppo piccolo per essere un file .xz valido"
+
+#. TRANSLATORS: These are column headings. From Strms (Streams)
+#. to Ratio, the columns are right aligned. Check and Filename
+#. are left aligned. If you need longer words, it's OK to
+#. use two lines here. Test with "xz -l foo.xz".
+#: src/xz/list.c:612
+msgid "Strms Blocks Compressed Uncompressed Ratio Check Filename"
+msgstr " Strm Blocc. Compresso Estratto Rapp. Contr Nome file"
+
+#: src/xz/list.c:652
+#, c-format
+msgid " Streams: %s\n"
+msgstr " Stream: %s\n"
+
+#: src/xz/list.c:654
+#, c-format
+msgid " Blocks: %s\n"
+msgstr " Blocchi: %s\n"
+
+#: src/xz/list.c:656
+#, c-format
+msgid " Compressed size: %s\n"
+msgstr " Dim. compresso: %s\n"
+
+#: src/xz/list.c:659
+#, c-format
+msgid " Uncompressed size: %s\n"
+msgstr " Dim. estratto: %s\n"
+
+#: src/xz/list.c:662
+#, c-format
+msgid " Ratio: %s\n"
+msgstr " Rapporto: %s\n"
+
+#: src/xz/list.c:664
+#, c-format
+msgid " Check: %s\n"
+msgstr " Controllo: %s\n"
+
+#: src/xz/list.c:665
+#, c-format
+msgid " Stream padding: %s\n"
+msgstr " Padding dello stream: %s\n"
+
+#. TRANSLATORS: The second line is column headings. All except
+#. Check are right aligned; Check is left aligned. Test with
+#. "xz -lv foo.xz".
+#: src/xz/list.c:693
+msgid ""
+" Streams:\n"
+" Stream Blocks CompOffset UncompOffset CompSize "
+"UncompSize Ratio Check Padding"
+msgstr ""
+"Stream:\n"
+" Stream Blocc. Offset comp. Offset estr. Dim. comp. Dim. "
+"estratto Rapp. Contr Padding"
+
+#. TRANSLATORS: The second line is column headings. All
+#. except Check are right aligned; Check is left aligned.
+#: src/xz/list.c:748
+#, c-format
+msgid ""
+" Blocks:\n"
+" Stream Block CompOffset UncompOffset TotalSize "
+"UncompSize Ratio Check"
+msgstr ""
+" Blocchi:\n"
+" Stream Blocc. Offset comp. Offset estratto Dim. tot. Dim. "
+"estratto Rapp. Contr"
+
+#. TRANSLATORS: These are additional column headings
+#. for the most verbose listing mode. CheckVal
+#. (Check value), Flags, and Filters are left aligned.
+#. Header (Block Header Size), CompSize, and MemUsage
+#. are right aligned. %*s is replaced with 0-120
+#. spaces to make the CheckVal column wide enough.
+#. Test with "xz -lvv foo.xz".
+#: src/xz/list.c:760
+#, c-format
+msgid " CheckVal %*s Header Flags CompSize MemUsage Filters"
+msgstr " Val.cont %*s Header Flag Dim.compr. Uso mem. Filtri"
+
+#: src/xz/list.c:838 src/xz/list.c:1007
+#, c-format
+msgid " Memory needed: %s MiB\n"
+msgstr " Memoria necessaria: %s MiB\n"
+
+#: src/xz/list.c:840 src/xz/list.c:1009
+#, c-format
+msgid " Sizes in headers: %s\n"
+msgstr " Dim. negli header: %s\n"
+
+#: src/xz/list.c:841 src/xz/list.c:1010
+msgid "Yes"
+msgstr "Sì"
+
+#: src/xz/list.c:841 src/xz/list.c:1010
+msgid "No"
+msgstr "No"
+
+#. TRANSLATORS: %s is an integer. Only the plural form of this
+#. message is used (e.g. "2 files"). Test with "xz -l foo.xz bar.xz".
+#: src/xz/list.c:986
+#, c-format
+msgid "%s file\n"
+msgid_plural "%s files\n"
+msgstr[0] "%s file\n"
+msgstr[1] "%s file\n"
+
+#: src/xz/list.c:999
+msgid "Totals:"
+msgstr "Totali:"
+
+#: src/xz/list.c:1000
+#, c-format
+msgid " Number of files: %s\n"
+msgstr " Numero di file: %s\n"
+
+#: src/xz/list.c:1072
+msgid "--list works only on .xz files (--format=xz or --format=auto)"
+msgstr "--list funziona solamente con file .xz (--format=xz o --format=auto)"
+
+#: src/xz/list.c:1078
+msgid "--list does not support reading from standard input"
+msgstr "--list non è in grado di leggere dallo standard input"
+
+#: src/xz/main.c:89
+#, c-format
+msgid "%s: Error reading filenames: %s"
+msgstr "%s: errore nel leggere i nomi dei file: %s"
+
+#: src/xz/main.c:96
+#, c-format
+msgid "%s: Unexpected end of input when reading filenames"
+msgstr "%s: fine dell'input durante la lettura dei nomi dei file non attesa"
+
+#: src/xz/main.c:120
+#, c-format
+msgid ""
+"%s: Null character found when reading filenames; maybe you meant to use `--"
+"files0' instead of `--files'?"
+msgstr ""
+"%s: nessun carattere trovato durante la lettura dei nomi dei file; forse si "
+"intendeva usare \"--files0\" invece di \"--files\"?"
+
+#: src/xz/main.c:174
+msgid "Compression and decompression with --robot are not supported yet."
+msgstr "La compressione e l'estrazione con --robot non sono ancora supportate."
+
+#: src/xz/main.c:231
+msgid ""
+"Cannot read data from standard input when reading filenames from standard "
+"input"
+msgstr ""
+"Impossibile leggere i dati dallo standard input durante la lettura dei nomi "
+"dei file dallo standard input"
+
+#: src/xz/message.c:800 src/xz/message.c:844
+msgid "Internal error (bug)"
+msgstr "Errore interno (bug)"
+
+#: src/xz/message.c:807
+msgid "Cannot establish signal handlers"
+msgstr "Impossibile stabilire i gestori dei segnali"
+
+#: src/xz/message.c:816
+msgid "No integrity check; not verifying file integrity"
+msgstr ""
+"Nessun controllo d'integrità; l'integrità del file non viene verificata"
+
+#: src/xz/message.c:819
+msgid "Unsupported type of integrity check; not verifying file integrity"
+msgstr ""
+"Tipo di controllo di integrità non supportato; l'integrità del file non "
+"viene verificata"
+
+#: src/xz/message.c:826
+msgid "Memory usage limit reached"
+msgstr "Limite di utilizzo della memoria raggiunto"
+
+#: src/xz/message.c:829
+msgid "File format not recognized"
+msgstr "Formato di file non riconosciuto"
+
+#: src/xz/message.c:832
+msgid "Unsupported options"
+msgstr "Opzioni non supportate"
+
+#: src/xz/message.c:835
+msgid "Compressed data is corrupt"
+msgstr "I dati compressi sono danneggiati"
+
+#: src/xz/message.c:838
+msgid "Unexpected end of input"
+msgstr "Fine dell'input non attesa"
+
+#: src/xz/message.c:886
+#, c-format
+msgid "%s MiB of memory is required. The limit is %s."
+msgstr "%s MiB di memoria sono richiesti. Il limite è %s."
+
+#: src/xz/message.c:1053
+#, c-format
+msgid "%s: Filter chain: %s\n"
+msgstr "%s: catena di filtri: %s\n"
+
+#: src/xz/message.c:1063
+#, c-format
+msgid "Try `%s --help' for more information."
+msgstr "Provare \"%s --help\" per maggiori informazioni."
+
+#: src/xz/message.c:1089
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... [FILE]...\n"
+"Compress or decompress FILEs in the .xz format.\n"
+"\n"
+msgstr ""
+"Uso: %s [OPZIONI]... [FILE]...\n"
+"Comprime o estrae i FILE nel formato .xz.\n"
+"\n"
+
+#: src/xz/message.c:1096
+msgid ""
+"Mandatory arguments to long options are mandatory for short options too.\n"
+msgstr ""
+"Gli argomenti obbligatori per le opzioni lunghe lo sono anche per quelle "
+"brevi.\n"
+
+#: src/xz/message.c:1100
+msgid " Operation mode:\n"
+msgstr " Modalità di operazione:\n"
+
+#: src/xz/message.c:1103
+msgid ""
+" -z, --compress force compression\n"
+" -d, --decompress force decompression\n"
+" -t, --test test compressed file integrity\n"
+" -l, --list list information about .xz files"
+msgstr ""
+" -z, --compress Forza la compressione\n"
+" -d, --decompress Forza l'estrazione\n"
+" -t, --test Verifica l'integrità dei file compressi\n"
+" -l, --list Elenca informazioni sui file .xz"
+
+#: src/xz/message.c:1109
+msgid ""
+"\n"
+" Operation modifiers:\n"
+msgstr ""
+"\n"
+" Modificatori di operazioni:\n"
+
+#: src/xz/message.c:1112
+msgid ""
+" -k, --keep keep (don't delete) input files\n"
+" -f, --force force overwrite of output file and (de)compress links\n"
+" -c, --stdout write to standard output and don't delete input files"
+msgstr ""
+" -k, --keep Mantiene (non elimina) i file di input\n"
+" -f, --force Forza la sovrascrittura dell'output e comprime/estrae "
+"i\n"
+" collegamenti\n"
+" -c, --stdout Scrive sullo standard output e non elimina i file di "
+"input"
+
+#: src/xz/message.c:1118
+msgid ""
+" --no-sparse do not create sparse files when decompressing\n"
+" -S, --suffix=.SUF use the suffix `.SUF' on compressed files\n"
+" --files[=FILE] read filenames to process from FILE; if FILE is\n"
+" omitted, filenames are read from the standard input;\n"
+" filenames must be terminated with the newline "
+"character\n"
+" --files0[=FILE] like --files but use the null character as terminator"
+msgstr ""
+" --no-sparse Non crea file sparsi durante l'estrazione\n"
+" -S, --suffix=.SUF Usa il suffisso \".SUF\" sui file compressi\n"
+" --files=[FILE] Legge i nomi dei file da elaborare da FILE; se FILE è\n"
+" omesso, i nomi dei file sono letti dallo standard "
+"input;\n"
+" i nomi dei file devono essere terminati con un "
+"carattere\n"
+" di newline\n"
+" --files0=[FILE] Come --files ma usa il carattere null come terminatore"
+
+#: src/xz/message.c:1126
+msgid ""
+"\n"
+" Basic file format and compression options:\n"
+msgstr ""
+"\n"
+" Formato file di base e opzioni di compressione:\n"
+
+#: src/xz/message.c:1128
+msgid ""
+" -F, --format=FMT file format to encode or decode; possible values are\n"
+" `auto' (default), `xz', `lzma', and `raw'\n"
+" -C, --check=CHECK integrity check type: `none' (use with caution),\n"
+" `crc32', `crc64' (default), or `sha256'"
+msgstr ""
+" -F, --format=FMT Formato file per codificare o decodificare; i "
+"possibili\n"
+" valori sono \"auto\" (predefinito) \"xz\", \"lzma\" e "
+"\"raw\"\n"
+" -C, --check=CHECK Tipo di verifica integrità: \"none\" (usare con "
+"attenzione),\n"
+" \"crc32\", \"crc64\" (predefinito) o \"sha256\""
+
+#: src/xz/message.c:1135
+msgid ""
+" -0 ... -9 compression preset; default is 6; take compressor "
+"*and*\n"
+" decompressor memory usage into account before using 7-"
+"9!"
+msgstr ""
+" -0 ... -9 Preset di compressione; predefinito è 6; tenere a "
+"mente\n"
+" l'utilizzo di memoria per comprimere ed estrarre "
+"prima\n"
+" di usare 7-9"
+
+#: src/xz/message.c:1139
+msgid ""
+" -e, --extreme try to improve compression ratio by using more CPU "
+"time;\n"
+" does not affect decompressor memory requirements"
+msgstr ""
+" -e, --extreme Tenta di migliorare il rapporto di compressione\n"
+" utilizzando più tempo di CPU; non cambia i requisiti "
+"di\n"
+" memoria in fase di estrazione"
+
+#: src/xz/message.c:1144
+#, no-c-format
+msgid ""
+" --memlimit-compress=LIMIT\n"
+" --memlimit-decompress=LIMIT\n"
+" -M, --memlimit=LIMIT\n"
+" set memory usage limit for compression, "
+"decompression,\n"
+" or both; LIMIT is in bytes, % of RAM, or 0 for defaults"
+msgstr ""
+" --memlimit-compress=LIMIT\n"
+" --memlimit-decompress=LIMIT\n"
+" -M, --memlimit=LIMIT\n"
+" Imposta il limite di utilizzo della memoria per la\n"
+" compressione, l'estrazione o entrambe; LIMIT è in "
+"byte,\n"
+" % della memoria RAM oppure 0 per il valore predefinito"
+
+#: src/xz/message.c:1151
+msgid ""
+" --no-adjust if compression settings exceed the memory usage "
+"limit,\n"
+" give an error instead of adjusting the settings "
+"downwards"
+msgstr ""
+" --no-adjust Se le impostazioni di compressione eccedono il limite "
+"di\n"
+" utilizzo della memoria, lancia un errore invece di\n"
+" utilizzare valori più piccoli"
+
+#: src/xz/message.c:1157
+msgid ""
+"\n"
+" Custom filter chain for compression (alternative for using presets):"
+msgstr ""
+"\n"
+" Catena di filtri personalizzati per la compressione (alternative per\n"
+" l'utilizzo di preset):"
+
+#: src/xz/message.c:1166
+msgid ""
+"\n"
+" --lzma1[=OPTS] LZMA1 or LZMA2; OPTS is a comma-separated list of zero "
+"or\n"
+" --lzma2[=OPTS] more of the following options (valid values; "
+"default):\n"
+" preset=PRE reset options to a preset (0-9[e])\n"
+" dict=NUM dictionary size (4KiB - 1536MiB; 8MiB)\n"
+" lc=NUM number of literal context bits (0-4; 3)\n"
+" lp=NUM number of literal position bits (0-4; 0)\n"
+" pb=NUM number of position bits (0-4; 2)\n"
+" mode=MODE compression mode (fast, normal; normal)\n"
+" nice=NUM nice length of a match (2-273; 64)\n"
+" mf=NAME match finder (hc3, hc4, bt2, bt3, bt4; "
+"bt4)\n"
+" depth=NUM maximum search depth; 0=automatic "
+"(default)"
+msgstr ""
+"\n"
+" --lzma1[=OPZ] LZMA1 o LZMA2; OPZ è un elenco separato da virgole di "
+"zero\n"
+" --lzma2[=OPZ] o più delle seguenti opzioni (valori validi; "
+"predefinito):\n"
+" preset=NUM Reimposta le opzioni al preset NUM (0-9"
+"[e])\n"
+" dict=NUM Dimensione del dizionario\n"
+" (4KiB - 1536MiB; 8MiB)\n"
+" lc=NUM Numero di bit letterali di contesto (0-4; "
+"3)\n"
+" lp=NUM Numero di bit letterali di posizione (0-"
+"4; 0)\n"
+" pb=NUM Numero di bit di posizione (0-4; 2)\n"
+" mode=MODE Modalità di compressione\n"
+" (fast, normal; normal)\n"
+" nice=NUM Lunghezza valida per una corrispondenza\n"
+" (2-273; 64)\n"
+" mf=NAME Strumento per cercare corrispondenze\n"
+" (hc3, hc4, bt2, bt3, bt4; bt4)\n"
+" depth=NUM Profondità massima di ricerca; "
+"0=automatica\n"
+" (predefinito)"
+
+#: src/xz/message.c:1181
+msgid ""
+"\n"
+" --x86[=OPTS] x86 BCJ filter (32-bit and 64-bit)\n"
+" --powerpc[=OPTS] PowerPC BCJ filter (big endian only)\n"
+" --ia64[=OPTS] IA-64 (Itanium) BCJ filter\n"
+" --arm[=OPTS] ARM BCJ filter (little endian only)\n"
+" --armthumb[=OPTS] ARM-Thumb BCJ filter (little endian only)\n"
+" --sparc[=OPTS] SPARC BCJ filter\n"
+" Valid OPTS for all BCJ filters:\n"
+" start=NUM start offset for conversions (default=0)"
+msgstr ""
+"\n"
+" --x86[=OPZ] Filtro BCJ x86 (32 e 64 bit)\n"
+" --powerpc[=OPZ] Filtro BCJ PowerPC (solo big endian)\n"
+" --ia64[=OPZ] Filtro BCJ IA-64 (Itanium)\n"
+" --arm[=OPZ] Filtro BCJ ARM (solo little endian)\n"
+" --armthumb[=OPZ] Filtro BCJ ARM-Thumb (solo little endian)\n"
+" --sparc[=OPZ] Filtro BCJ SPARC\n"
+" OPZ valide per tutti i filtri BCJ:\n"
+" start=NUM Offset iniziale per le conversioni\n"
+" (predefinito=0)"
+
+#: src/xz/message.c:1193
+msgid ""
+"\n"
+" --delta[=OPTS] Delta filter; valid OPTS (valid values; default):\n"
+" dist=NUM distance between bytes being subtracted\n"
+" from each other (1-256; 1)"
+msgstr ""
+"\n"
+" --delta[=OPZ] Filtro Delta; OPZ valide (valori validi; predefinito):\n"
+" dist=NUM Distanza tra byte sottratti\n"
+" gli uni dagli altri (1-256; 1)"
+
+#: src/xz/message.c:1201
+msgid ""
+"\n"
+" Other options:\n"
+msgstr ""
+"\n"
+" Altre opzioni:\n"
+
+#: src/xz/message.c:1204
+msgid ""
+" -q, --quiet suppress warnings; specify twice to suppress errors "
+"too\n"
+" -v, --verbose be verbose; specify twice for even more verbose"
+msgstr ""
+" -q, --quiet Sopprime gli avvisi; specificare due volte per "
+"sopprimere\n"
+" anche gli errori\n"
+" -v, --verbose Output prolisso; specificare due volte per output "
+"ancora\n"
+" più prolisso"
+
+#: src/xz/message.c:1209
+msgid " -Q, --no-warn make warnings not affect the exit status"
+msgstr " -Q, --no-warn Gli avvisi non influenzano lo stato d'uscita"
+
+#: src/xz/message.c:1211
+msgid ""
+" --robot use machine-parsable messages (useful for scripts)"
+msgstr " --robot Usa messaggi analizzabili (utile per gli script)"
+
+#: src/xz/message.c:1214
+msgid ""
+" --info-memory display the total amount of RAM and the currently "
+"active\n"
+" memory usage limits, and exit"
+msgstr ""
+" --info-memory Visualizza la quantità totale di RAM, il limite "
+"attuale\n"
+" attivo di utilizzo della memore ed esce"
+
+#: src/xz/message.c:1217
+msgid ""
+" -h, --help display the short help (lists only the basic options)\n"
+" -H, --long-help display this long help and exit"
+msgstr ""
+" -h, --help Stampa l'aiuto breve (elenca solo le opzioni di base)\n"
+" -H, --long-help Stampa questo lungo aiuto ed esce"
+
+#: src/xz/message.c:1221
+msgid ""
+" -h, --help display this short help and exit\n"
+" -H, --long-help display the long help (lists also the advanced options)"
+msgstr ""
+" -h, --help Stampa questo breve aiuto ed esce\n"
+" -H, --long-help Stampa l'aiuto lungo (elenca anche le opzioni avanzate)"
+
+#: src/xz/message.c:1226
+msgid " -V, --version display the version number and exit"
+msgstr " -V, --version Stampa il numero della versione ed esce"
+
+#: src/xz/message.c:1228
+msgid ""
+"\n"
+"With no FILE, or when FILE is -, read standard input.\n"
+msgstr ""
+"\n"
+"Senza FILE, o quando FILE è -, legge lo standard input.\n"
+
+#. TRANSLATORS: This message indicates the bug reporting address
+#. for this package. Please add _another line_ saying
+#. "Report translation bugs to <...>\n" with the email or WWW
+#. address for translation bugs. Thanks.
+#: src/xz/message.c:1234
+#, c-format
+msgid "Report bugs to <%s> (in English or Finnish).\n"
+msgstr ""
+"Segnalare i bug a <%s> (in inglese o finlandese).\n"
+"Segnalare i bug di traduzione a <tp@lists.linux.it>.\n"
+
+#: src/xz/message.c:1236
+#, c-format
+msgid "%s home page: <%s>\n"
+msgstr "Sito web di %s: <%s>\n"
+
+#: src/xz/options.c:86
+#, c-format
+msgid "%s: Options must be `name=value' pairs separated with commas"
+msgstr ""
+"%s: le opzioni devono essere coppie \"nome=valore\" separate da virgole"
+
+#: src/xz/options.c:93
+#, c-format
+msgid "%s: Invalid option name"
+msgstr "%s: nome opzione non valido"
+
+#: src/xz/options.c:113
+#, c-format
+msgid "%s: Invalid option value"
+msgstr "%s: valore dell'opzione non valido"
+
+#: src/xz/options.c:247
+#, c-format
+msgid "Unsupported LZMA1/LZMA2 preset: %s"
+msgstr "Preset LZMA/LZMA2 non supportato: %s"
+
+#: src/xz/options.c:355
+msgid "The sum of lc and lp must not exceed 4"
+msgstr "La somma di lc e lp non deve superare 4"
+
+#: src/xz/options.c:359
+#, c-format
+msgid "The selected match finder requires at least nice=%<PRIu32>"
+msgstr ""
+"Lo strumento per cercare corrispondenze selezionato richiede almeno nice=%"
+"<PRIu32>"
+
+#: src/xz/suffix.c:79 src/xz/suffix.c:164
+#, c-format
+msgid ""
+"%s: With --format=raw, --suffix=.SUF is required unless writing to stdout"
+msgstr ""
+"%s: con --format=raw, --suffix=.SUF è richiesto a meno che non si scriva "
+"sullo stdout"
+
+#: src/xz/suffix.c:99
+#, c-format
+msgid "%s: Filename has an unknown suffix, skipping"
+msgstr "%s: il nome del file ha un suffisso sconosciuto, viene saltato"
+
+#: src/xz/suffix.c:154
+#, c-format
+msgid "%s: File already has `%s' suffix, skipping"
+msgstr "%s: il file ha già il suffisso \"%s\", viene saltato"
+
+#: src/xz/suffix.c:205
+#, c-format
+msgid "%s: Invalid filename suffix"
+msgstr "%s: suffisso del nome del file non valido"
+
+#: src/xz/util.c:61
+#, c-format
+msgid "%s: Value is not a non-negative decimal integer"
+msgstr "%s: il valore non è un numero intero decimale non-negativo"
+
+#: src/xz/util.c:103
+#, c-format
+msgid "%s: Invalid multiplier suffix"
+msgstr "%s: suffisso del moltiplicatore non valido"
+
+#: src/xz/util.c:105
+msgid "Valid suffixes are `KiB' (2^10), `MiB' (2^20), and `GiB' (2^30)."
+msgstr ""
+"I suffissi validi sono \"KiB\" (2^10), \"MiB\" (2^20), e \"GiB\" (2^30)."
+
+#: src/xz/util.c:122
+#, c-format
+msgid "Value of the option `%s' must be in the range [%<PRIu64>, %<PRIu64>]"
+msgstr ""
+"Il valore dell'opzione \"%s\" deve essere nell'intervallo [%<PRIu64>, %"
+"<PRIu64>]"
+
+#: src/xz/util.c:247
+msgid "Empty filename, skipping"
+msgstr "Nome file vuoto, viene saltato"
+
+#: src/xz/util.c:261
+msgid "Compressed data cannot be read from a terminal"
+msgstr "I dati compressi non possono essere letti da un terminale"
+
+#: src/xz/util.c:274
+msgid "Compressed data cannot be written to a terminal"
+msgstr "I dati compressi non possono essere scritti ad un terminale"
+
+#: src/common/tuklib_exit.c:39
+msgid "Writing to standard output failed"
+msgstr "Scrittura sullo standard ouput non riuscita"
+
+#: src/common/tuklib_exit.c:42
+msgid "Unknown error"
+msgstr "Errore sconosciuto"
diff --git a/src/common/sysdefs.h b/src/common/sysdefs.h
index 97a1c045cfb0..1e138b1c2e79 100644
--- a/src/common/sysdefs.h
+++ b/src/common/sysdefs.h
@@ -102,11 +102,11 @@
# elif SIZEOF_SIZE_T == 8
# define SIZE_MAX UINT64_MAX
# else
-# error sizeof(size_t) is not 32-bit or 64-bit
+# error size_t is not 32-bit or 64-bit
# endif
#endif
#if SIZE_MAX != UINT32_MAX && SIZE_MAX != UINT64_MAX
-# error sizeof(size_t) is not 32-bit or 64-bit
+# error size_t is not 32-bit or 64-bit
#endif
#include <stdlib.h>
@@ -156,13 +156,11 @@ typedef unsigned char _Bool;
#undef memzero
#define memzero(s, n) memset(s, 0, n)
-#ifndef MIN
-# define MIN(x, y) ((x) < (y) ? (x) : (y))
-#endif
-
-#ifndef MAX
-# define MAX(x, y) ((x) > (y) ? (x) : (y))
-#endif
+// NOTE: Avoid using MIN() and MAX(), because even conditionally defining
+// those macros can cause some portability trouble, since on some systems
+// the system headers insist defining their own versions.
+#define my_min(x, y) ((x) < (y) ? (x) : (y))
+#define my_max(x, y) ((x) > (y) ? (x) : (y))
#ifndef ARRAY_SIZE
# define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
diff --git a/src/common/tuklib_cpucores.c b/src/common/tuklib_cpucores.c
index e35d9bc74d9a..1da13df7f5f6 100644
--- a/src/common/tuklib_cpucores.c
+++ b/src/common/tuklib_cpucores.c
@@ -20,6 +20,11 @@
#elif defined(TUKLIB_CPUCORES_SYSCONF)
# include <unistd.h>
+
+// HP-UX
+#elif defined(TUKLIB_CPUCORES_PSTAT_GETDYNAMIC)
+# include <sys/param.h>
+# include <sys/pstat.h>
#endif
@@ -34,7 +39,7 @@ tuklib_cpucores(void)
size_t cpus_size = sizeof(cpus);
if (sysctl(name, 2, &cpus, &cpus_size, NULL, 0) != -1
&& cpus_size == sizeof(cpus) && cpus > 0)
- ret = (uint32_t)cpus;
+ ret = cpus;
#elif defined(TUKLIB_CPUCORES_SYSCONF)
# ifdef _SC_NPROCESSORS_ONLN
@@ -45,7 +50,12 @@ tuklib_cpucores(void)
const long cpus = sysconf(_SC_NPROC_ONLN);
# endif
if (cpus > 0)
- ret = (uint32_t)cpus;
+ ret = cpus;
+
+#elif defined(TUKLIB_CPUCORES_PSTAT_GETDYNAMIC)
+ struct pst_dynamic pst;
+ if (pstat_getdynamic(&pst, sizeof(pst), 1, 0) != -1)
+ ret = pst.psd_proc_cnt;
#endif
return ret;
diff --git a/src/common/tuklib_gettext.h b/src/common/tuklib_gettext.h
index 248521347ab0..ff1890407125 100644
--- a/src/common/tuklib_gettext.h
+++ b/src/common/tuklib_gettext.h
@@ -33,12 +33,12 @@
textdomain(package); \
} while (0)
# define _(msgid) gettext(msgid)
-# define N_(msgid1, msgid2, n) ngettext(msgid1, msgid2, n)
#else
# define tuklib_gettext_init(package, localedir) \
setlocale(LC_ALL, "")
# define _(msgid) (msgid)
-# define N_(msgid1, msgid2, n) ((n) == 1 ? (msgid1) : (msgid2))
+# define ngettext(msgid1, msgid2, n) ((n) == 1 ? (msgid1) : (msgid2))
#endif
+#define N_(msgid) msgid
#endif
diff --git a/src/common/tuklib_mbstr.h b/src/common/tuklib_mbstr.h
new file mode 100644
index 000000000000..9f3583551806
--- /dev/null
+++ b/src/common/tuklib_mbstr.h
@@ -0,0 +1,66 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file tuklib_mstr.h
+/// \brief Utility functions for handling multibyte strings
+///
+/// If not enough multibyte string support is available in the C library,
+/// these functions keep working with the assumption that all strings
+/// are in a single-byte character set without combining characters, e.g.
+/// US-ASCII or ISO-8859-*.
+//
+// Author: Lasse Collin
+//
+// This file has been put into the public domain.
+// You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef TUKLIB_MBSTR_H
+#define TUKLIB_MBSTR_H
+
+#include "tuklib_common.h"
+TUKLIB_DECLS_BEGIN
+
+#define tuklib_mbstr_width TUKLIB_SYMBOL(tuklib_mbstr_width)
+extern size_t tuklib_mbstr_width(const char *str, size_t *bytes);
+///<
+/// \brief Get the number of columns needed for the multibyte string
+///
+/// This is somewhat similar to wcswidth() but works on multibyte strings.
+///
+/// \param str String whose width is to be calculated. If the
+/// current locale uses a multibyte character set
+/// that has shift states, the string must begin
+/// and end in the initial shift state.
+/// \param bytes If this is not NULL, *bytes is set to the
+/// value returned by strlen(str) (even if an
+/// error occurs when calculating the width).
+///
+/// \return On success, the number of columns needed to display the
+/// string e.g. in a terminal emulator is returned. On error,
+/// (size_t)-1 is returned. Possible errors include invalid,
+/// partial, or non-printable multibyte character in str, or
+/// that str doesn't end in the initial shift state.
+
+#define tuklib_mbstr_fw TUKLIB_SYMBOL(tuklib_mbstr_fw)
+extern int tuklib_mbstr_fw(const char *str, int columns_min);
+///<
+/// \brief Get the field width for printf() e.g. to align table columns
+///
+/// Printing simple tables to a terminal can be done using the field field
+/// feature in the printf() format string, but it works only with single-byte
+/// character sets. To do the same with multibyte strings, tuklib_mbstr_fw()
+/// can be used to calculate appropriate field width.
+///
+/// The behavior of this function is undefined, if
+/// - str is NULL or not terminated with '\0';
+/// - columns_min <= 0; or
+/// - the calculated field width exceeds INT_MAX.
+///
+/// \return If tuklib_mbstr_width(str, NULL) fails, -1 is returned.
+/// If str needs more columns than columns_min, zero is returned.
+/// Otherwise a positive integer is returned, which can be
+/// used as the field width, e.g. printf("%*s", fw, str).
+
+TUKLIB_DECLS_END
+#endif
diff --git a/src/common/tuklib_mbstr_fw.c b/src/common/tuklib_mbstr_fw.c
new file mode 100644
index 000000000000..978a3fe10d93
--- /dev/null
+++ b/src/common/tuklib_mbstr_fw.c
@@ -0,0 +1,31 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file tuklib_mstr_fw.c
+/// \brief Get the field width for printf() e.g. to align table columns
+//
+// Author: Lasse Collin
+//
+// This file has been put into the public domain.
+// You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "tuklib_mbstr.h"
+
+
+extern int
+tuklib_mbstr_fw(const char *str, int columns_min)
+{
+ size_t len;
+ const size_t width = tuklib_mbstr_width(str, &len);
+ if (width == (size_t)-1)
+ return -1;
+
+ if (width > (size_t)columns_min)
+ return 0;
+
+ if (width < (size_t)columns_min)
+ len += (size_t)columns_min - width;
+
+ return len;
+}
diff --git a/src/common/tuklib_mbstr_width.c b/src/common/tuklib_mbstr_width.c
new file mode 100644
index 000000000000..3c38990f4608
--- /dev/null
+++ b/src/common/tuklib_mbstr_width.c
@@ -0,0 +1,64 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file tuklib_mstr_width.c
+/// \brief Calculate width of a multibyte string
+//
+// Author: Lasse Collin
+//
+// This file has been put into the public domain.
+// You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "tuklib_mbstr.h"
+
+#if defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH)
+# include <wchar.h>
+#endif
+
+
+extern size_t
+tuklib_mbstr_width(const char *str, size_t *bytes)
+{
+ const size_t len = strlen(str);
+ if (bytes != NULL)
+ *bytes = len;
+
+#if !(defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH))
+ // In single-byte mode, the width of the string is the same
+ // as its length.
+ return len;
+
+#else
+ mbstate_t state;
+ memset(&state, 0, sizeof(state));
+
+ size_t width = 0;
+ size_t i = 0;
+
+ // Convert one multibyte character at a time to wchar_t
+ // and get its width using wcwidth().
+ while (i < len) {
+ wchar_t wc;
+ const size_t ret = mbrtowc(&wc, str + i, len - i, &state);
+ if (ret < 1 || ret > len)
+ return (size_t)-1;
+
+ i += ret;
+
+ const int wc_width = wcwidth(wc);
+ if (wc_width < 0)
+ return (size_t)-1;
+
+ width += wc_width;
+ }
+
+ // Require that the string ends in the initial shift state.
+ // This way the caller can be combine the string with other
+ // strings without needing to worry about the shift states.
+ if (!mbsinit(&state))
+ return (size_t)-1;
+
+ return width;
+#endif
+}
diff --git a/src/common/tuklib_physmem.c b/src/common/tuklib_physmem.c
index 1536e6e5da1c..623b6e70b7f2 100644
--- a/src/common/tuklib_physmem.c
+++ b/src/common/tuklib_physmem.c
@@ -33,6 +33,10 @@
# include <syidef.h>
# include <ssdef.h>
+// AIX
+#elif defined(TUKLIB_PHYSMEM_AIX)
+# include <sys/systemcfg.h>
+
#elif defined(TUKLIB_PHYSMEM_SYSCONF)
# include <unistd.h>
@@ -42,6 +46,16 @@
# endif
# include <sys/sysctl.h>
+// Tru64
+#elif defined(TUKLIB_PHYSMEM_GETSYSINFO)
+# include <sys/sysinfo.h>
+# include <machine/hal_sysinfo.h>
+
+// HP-UX
+#elif defined(TUKLIB_PHYSMEM_PSTAT_GETSTATIC)
+# include <sys/param.h>
+# include <sys/pstat.h>
+
// IRIX
#elif defined(TUKLIB_PHYSMEM_GETINVENT_R)
# include <invent.h>
@@ -105,10 +119,13 @@ tuklib_physmem(void)
if (LIB$GETSYI(&val, &vms_mem, 0, 0, 0, 0) == SS$_NORMAL)
ret = (uint64_t)vms_mem * 8192;
+#elif defined(TUKLIB_PHYSMEM_AIX)
+ ret = _system_configuration.physmem;
+
#elif defined(TUKLIB_PHYSMEM_SYSCONF)
const long pagesize = sysconf(_SC_PAGESIZE);
const long pages = sysconf(_SC_PHYS_PAGES);
- if (pagesize != -1 || pages != -1)
+ if (pagesize != -1 && pages != -1)
// According to docs, pagesize * pages can overflow.
// Simple case is 32-bit box with 4 GiB or more RAM,
// which may report exactly 4 GiB of RAM, and "long"
@@ -140,6 +157,20 @@ tuklib_physmem(void)
ret = mem.u32;
}
+#elif defined(TUKLIB_PHYSMEM_GETSYSINFO)
+ // Docs are unclear if "start" is needed, but it doesn't hurt
+ // much to have it.
+ int memkb;
+ int start = 0;
+ if (getsysinfo(GSI_PHYSMEM, (caddr_t)&memkb, sizeof(memkb), &start)
+ != -1)
+ ret = (uint64_t)memkb * 1024;
+
+#elif defined(TUKLIB_PHYSMEM_PSTAT_GETSTATIC)
+ struct pst_static pst;
+ if (pstat_getstatic(&pst, sizeof(pst), 1, 0) != -1)
+ ret = (uint64_t)pst.physical_memory * (uint64_t)pst.page_size;
+
#elif defined(TUKLIB_PHYSMEM_GETINVENT_R)
inv_state_t *st = NULL;
if (setinvent_r(&st) != -1) {
diff --git a/src/liblzma/api/lzma.h b/src/liblzma/api/lzma.h
index 5be9b4e31558..fb593a35a07e 100644
--- a/src/liblzma/api/lzma.h
+++ b/src/liblzma/api/lzma.h
@@ -234,10 +234,6 @@
# define lzma_attribute(attr) __attribute__(attr)
# endif
-# ifndef lzma_restrict
-# define lzma_restrict __restrict__
-# endif
-
/* warn_unused_result was added in GCC 3.4. */
# ifndef lzma_attr_warn_unused_result
# if __GNUC__ == 3 && __GNUC_MINOR__ < 4
@@ -249,14 +245,6 @@
# ifndef lzma_attribute
# define lzma_attribute(attr)
# endif
-
-# ifndef lzma_restrict
-# if __STDC_VERSION__ >= 199901L
-# define lzma_restrict restrict
-# else
-# define lzma_restrict
-# endif
-# endif
#endif
@@ -296,7 +284,6 @@ extern "C" {
/* Filters */
#include "lzma/filter.h"
-#include "lzma/subblock.h"
#include "lzma/bcj.h"
#include "lzma/delta.h"
#include "lzma/lzma.h"
diff --git a/src/liblzma/api/lzma/index.h b/src/liblzma/api/lzma/index.h
index 8d7a799f4ab5..5ea12e359e5d 100644
--- a/src/liblzma/api/lzma/index.h
+++ b/src/liblzma/api/lzma/index.h
@@ -368,7 +368,7 @@ extern LZMA_API(lzma_ret) lzma_index_stream_flags(
/**
* \brief Get the types of integrity Checks
*
- * If lzma_index_stream_padding() is used to set the Stream Flags for
+ * If lzma_index_stream_flags() is used to set the Stream Flags for
* every Stream, lzma_index_checks() can be used to get a bitmask to
* indicate which Check types have been used. It can be useful e.g. if
* showing the Check types to the user.
@@ -562,9 +562,8 @@ extern LZMA_API(lzma_bool) lzma_index_iter_locate(
* - LZMA_MEM_ERROR
* - LZMA_PROG_ERROR
*/
-extern LZMA_API(lzma_ret) lzma_index_cat(lzma_index *lzma_restrict dest,
- lzma_index *lzma_restrict src,
- lzma_allocator *allocator)
+extern LZMA_API(lzma_ret) lzma_index_cat(
+ lzma_index *dest, lzma_index *src, lzma_allocator *allocator)
lzma_nothrow lzma_attr_warn_unused_result;
diff --git a/src/liblzma/api/lzma/lzma.h b/src/liblzma/api/lzma/lzma.h
index c17736d7eaac..9d31a5ce51bc 100644
--- a/src/liblzma/api/lzma/lzma.h
+++ b/src/liblzma/api/lzma/lzma.h
@@ -49,7 +49,7 @@
* The memory usage formulas are only rough estimates, which are closest to
* reality when dict_size is a power of two. The formulas are more complex
* in reality, and can also change a little between liblzma versions. Use
- * lzma_memusage_encoder() to get more accurate estimate of memory usage.
+ * lzma_raw_encoder_memusage() to get more accurate estimate of memory usage.
*/
typedef enum {
LZMA_MF_HC3 = 0x03,
@@ -69,7 +69,9 @@ typedef enum {
*
* Minimum nice_len: 4
*
- * Memory usage: dict_size * 7.5
+ * Memory usage:
+ * - dict_size <= 32 MiB: dict_size * 7.5
+ * - dict_size > 32 MiB: dict_size * 6.5
*/
LZMA_MF_BT2 = 0x12,
@@ -98,7 +100,9 @@ typedef enum {
*
* Minimum nice_len: 4
*
- * Memory usage: dict_size * 11.5
+ * Memory usage:
+ * - dict_size <= 32 MiB: dict_size * 11.5
+ * - dict_size > 32 MiB: dict_size * 10.5
*/
} lzma_match_finder;
diff --git a/src/liblzma/api/lzma/subblock.h b/src/liblzma/api/lzma/subblock.h
deleted file mode 100644
index 4ffb049824b7..000000000000
--- a/src/liblzma/api/lzma/subblock.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/**
- * \file lzma/subblock.h
- * \brief Subblock filter
- */
-
-/*
- * Author: Lasse Collin
- *
- * This file has been put into the public domain.
- * You can do whatever you want with this file.
- *
- * See ../lzma.h for information about liblzma as a whole.
- */
-
-#ifndef LZMA_H_INTERNAL
-# error Never include this file directly. Use <lzma.h> instead.
-#endif
-
-
-/**
- * \brief Filter ID
- *
- * Filter ID of the Subblock filter. This is used as lzma_filter.id.
- */
-#define LZMA_FILTER_SUBBLOCK LZMA_VLI_C(0x01)
-
-
-/**
- * \brief Subfilter mode
- *
- * See lzma_options_subblock.subfilter_mode for details.
- */
-typedef enum {
- LZMA_SUBFILTER_NONE,
- /**<
- * No Subfilter is in use.
- */
-
- LZMA_SUBFILTER_SET,
- /**<
- * New Subfilter has been requested to be initialized.
- */
-
- LZMA_SUBFILTER_RUN,
- /**<
- * Subfilter is active.
- */
-
- LZMA_SUBFILTER_FINISH
- /**<
- * Subfilter has been requested to be finished.
- */
-} lzma_subfilter_mode;
-
-
-/**
- * \brief Options for the Subblock filter
- *
- * Specifying options for the Subblock filter is optional: if the pointer
- * options is NULL, no subfilters are allowed and the default value is used
- * for subblock_data_size.
- */
-typedef struct {
- /* Options for encoder and decoder */
-
- /**
- * \brief Allowing subfilters
- *
- * If this true, subfilters are allowed.
- *
- * In the encoder, if this is set to false, subfilter_mode and
- * subfilter_options are completely ignored.
- */
- lzma_bool allow_subfilters;
-
- /* Options for encoder only */
-
- /**
- * \brief Alignment
- *
- * The Subblock filter encapsulates the input data into Subblocks.
- * Each Subblock has a header which takes a few bytes of space.
- * When the output of the Subblock encoder is fed to another filter
- * that takes advantage of the alignment of the input data (e.g. LZMA),
- * the Subblock filter can add padding to keep the actual data parts
- * in the Subblocks aligned correctly.
- *
- * The alignment should be a positive integer. Subblock filter will
- * add enough padding between Subblocks so that this is true for
- * every payload byte:
- * input_offset % alignment == output_offset % alignment
- *
- * The Subblock filter assumes that the first output byte will be
- * written to a position in the output stream that is properly
- * aligned. This requirement is automatically met when the start
- * offset of the Stream or Block is correctly told to Block or
- * Stream encoder.
- */
- uint32_t alignment;
-# define LZMA_SUBBLOCK_ALIGNMENT_MIN 1
-# define LZMA_SUBBLOCK_ALIGNMENT_MAX 32
-# define LZMA_SUBBLOCK_ALIGNMENT_DEFAULT 4
-
- /**
- * \brief Size of the Subblock Data part of each Subblock
- *
- * This value is re-read every time a new Subblock is started.
- *
- * Bigger values
- * - save a few bytes of space;
- * - increase latency in the encoder (but no effect for decoding);
- * - decrease memory locality (increased cache pollution) in the
- * encoder (no effect in decoding).
- */
- uint32_t subblock_data_size;
-# define LZMA_SUBBLOCK_DATA_SIZE_MIN 1
-# define LZMA_SUBBLOCK_DATA_SIZE_MAX (UINT32_C(1) << 28)
-# define LZMA_SUBBLOCK_DATA_SIZE_DEFAULT 4096
-
- /**
- * \brief Run-length encoder remote control
- *
- * The Subblock filter has an internal run-length encoder (RLE). It
- * can be useful when the data includes byte sequences that repeat
- * very many times. The RLE can be used also when a Subfilter is
- * in use; the RLE will be applied to the output of the Subfilter.
- *
- * Note that in contrast to traditional RLE, this RLE is intended to
- * be used only when there's a lot of data to be repeated. If the
- * input data has e.g. 500 bytes of NULs now and then, this RLE
- * is probably useless, because plain LZMA should provide better
- * results.
- *
- * Due to above reasons, it was decided to keep the implementation
- * of the RLE very simple. When the rle variable is non-zero, it
- * subblock_data_size must be a multiple of rle. Once the Subblock
- * encoder has got subblock_data_size bytes of input, it will check
- * if the whole buffer of the last subblock_data_size can be
- * represented with repeats of chunks having size of rle bytes.
- *
- * If there are consecutive identical buffers of subblock_data_size
- * bytes, they will be encoded using a single repeat entry if
- * possible.
- *
- * If need arises, more advanced RLE can be implemented later
- * without breaking API or ABI.
- */
- uint32_t rle;
-# define LZMA_SUBBLOCK_RLE_OFF 0
-# define LZMA_SUBBLOCK_RLE_MIN 1
-# define LZMA_SUBBLOCK_RLE_MAX 256
-
- /**
- * \brief Subfilter remote control
- *
- * When the Subblock filter is initialized, this variable must be
- * LZMA_SUBFILTER_NONE or LZMA_SUBFILTER_SET.
- *
- * When subfilter_mode is LZMA_SUBFILTER_NONE, the application may
- * put Subfilter options to subfilter_options structure, and then
- * set subfilter_mode to LZMA_SUBFILTER_SET. No new input data will
- * be read until the Subfilter has been enabled. Once the Subfilter
- * has been enabled, liblzma will set subfilter_mode to
- * LZMA_SUBFILTER_RUN.
- *
- * When subfilter_mode is LZMA_SUBFILTER_RUN, the application may
- * set subfilter_mode to LZMA_SUBFILTER_FINISH. All the input
- * currently available will be encoded before unsetting the
- * Subfilter. Application must not change the amount of available
- * input until the Subfilter has finished. Once the Subfilter has
- * finished, liblzma will set subfilter_mode to LZMA_SUBFILTER_NONE.
- *
- * If the intent is to have Subfilter enabled to the very end of
- * the data, it is not needed to separately disable Subfilter with
- * LZMA_SUBFILTER_FINISH. Using LZMA_FINISH as the second argument
- * of lzma_code() will make the Subblock encoder to disable the
- * Subfilter once all the data has been ran through the Subfilter.
- *
- * After the first call with LZMA_SYNC_FLUSH or LZMA_FINISH, the
- * application must not change subfilter_mode until LZMA_STREAM_END.
- * Setting LZMA_SUBFILTER_SET/LZMA_SUBFILTER_FINISH and
- * LZMA_SYNC_FLUSH/LZMA_FINISH _at the same time_ is fine.
- *
- * \note This variable is ignored if allow_subfilters is false.
- */
- lzma_subfilter_mode subfilter_mode;
-
- /**
- * \brief Subfilter and its options
- *
- * When no Subfilter is used, the data is copied as is into Subblocks.
- * Setting a Subfilter allows encoding some parts of the data with
- * an additional filter. It is possible to many different Subfilters
- * in the same Block, although only one can be used at once.
- *
- * \note This variable is ignored if allow_subfilters is false.
- */
- lzma_filter subfilter_options;
-
-} lzma_options_subblock;
diff --git a/src/liblzma/api/lzma/vli.h b/src/liblzma/api/lzma/vli.h
index 8d4277f71227..57e3d3882b5e 100644
--- a/src/liblzma/api/lzma/vli.h
+++ b/src/liblzma/api/lzma/vli.h
@@ -113,9 +113,8 @@ typedef uint64_t lzma_vli;
* - LZMA_BUF_ERROR: No output space was provided.
* - LZMA_PROG_ERROR: Arguments are not sane.
*/
-extern LZMA_API(lzma_ret) lzma_vli_encode(lzma_vli vli,
- size_t *vli_pos, uint8_t *lzma_restrict out,
- size_t *lzma_restrict out_pos, size_t out_size) lzma_nothrow;
+extern LZMA_API(lzma_ret) lzma_vli_encode(lzma_vli vli, size_t *vli_pos,
+ uint8_t *out, size_t *out_pos, size_t out_size) lzma_nothrow;
/**
@@ -153,9 +152,9 @@ extern LZMA_API(lzma_ret) lzma_vli_encode(lzma_vli vli,
* - LZMA_BUF_ERROR: No input was provided.
* - LZMA_PROG_ERROR: Arguments are not sane.
*/
-extern LZMA_API(lzma_ret) lzma_vli_decode(lzma_vli *lzma_restrict vli,
- size_t *vli_pos, const uint8_t *lzma_restrict in,
- size_t *lzma_restrict in_pos, size_t in_size) lzma_nothrow;
+extern LZMA_API(lzma_ret) lzma_vli_decode(lzma_vli *vli, size_t *vli_pos,
+ const uint8_t *in, size_t *in_pos, size_t in_size)
+ lzma_nothrow;
/**
diff --git a/src/liblzma/common/block_buffer_encoder.c b/src/liblzma/common/block_buffer_encoder.c
index 4d90feef50bd..a8f71c2140e0 100644
--- a/src/liblzma/common/block_buffer_encoder.c
+++ b/src/liblzma/common/block_buffer_encoder.c
@@ -139,7 +139,7 @@ block_encode_uncompressed(lzma_block *block, const uint8_t *in, size_t in_size,
// Size of the uncompressed chunk
const size_t copy_size
- = MIN(in_size - in_pos, LZMA2_CHUNK_MAX);
+ = my_min(in_size - in_pos, LZMA2_CHUNK_MAX);
out[(*out_pos)++] = (copy_size - 1) >> 8;
out[(*out_pos)++] = (copy_size - 1) & 0xFF;
diff --git a/src/liblzma/common/block_util.c b/src/liblzma/common/block_util.c
index cb9cde255e65..62c934547c9e 100644
--- a/src/liblzma/common/block_util.c
+++ b/src/liblzma/common/block_util.c
@@ -15,7 +15,7 @@
extern LZMA_API(lzma_ret)
-lzma_block_compressed_size(lzma_block *block, lzma_vli total_size)
+lzma_block_compressed_size(lzma_block *block, lzma_vli unpadded_size)
{
// Validate everything but Uncompressed Size and filters.
if (lzma_block_unpadded_size(block) == 0)
@@ -25,13 +25,13 @@ lzma_block_compressed_size(lzma_block *block, lzma_vli total_size)
+ lzma_check_size(block->check);
// Validate that Compressed Size will be greater than zero.
- if (container_size <= total_size)
+ if (unpadded_size <= container_size)
return LZMA_DATA_ERROR;
// Calculate what Compressed Size is supposed to be.
// If Compressed Size was present in Block Header,
// compare that the new value matches it.
- const lzma_vli compressed_size = total_size - container_size;
+ const lzma_vli compressed_size = unpadded_size - container_size;
if (block->compressed_size != LZMA_VLI_UNKNOWN
&& block->compressed_size != compressed_size)
return LZMA_DATA_ERROR;
diff --git a/src/liblzma/common/chunk_size.c b/src/liblzma/common/chunk_size.c
deleted file mode 100644
index 363f07ece8bb..000000000000
--- a/src/liblzma/common/chunk_size.c
+++ /dev/null
@@ -1,67 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file chunk_size.c
-/// \brief Finds out the minimal reasonable chunk size for a filter chain
-//
-// Author: Lasse Collin
-//
-// This file has been put into the public domain.
-// You can do whatever you want with this file.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "common.h"
-
-
-/**
- * \brief Finds out the minimal reasonable chunk size for a filter chain
- *
- * This function helps determining the Uncompressed Sizes of the Blocks when
- * doing multi-threaded encoding.
- *
- * When compressing a large file on a system having multiple CPUs or CPU
- * cores, the file can be split into smaller chunks, that are compressed
- * independently into separate Blocks in the same .lzma Stream.
- *
- * \return Minimum reasonable Uncompressed Size of a Block. The
- * recommended minimum Uncompressed Size is between this value
- * and the value times two.
-
- Zero if the Uncompressed Sizes of Blocks don't matter
- */
-extern LZMA_API(size_t)
-lzma_chunk_size(const lzma_options_filter *filters)
-{
- while (filters->id != LZMA_VLI_UNKNOWN) {
- switch (filters->id) {
- // TODO LZMA_FILTER_SPARSE
-
- case LZMA_FILTER_COPY:
- case LZMA_FILTER_SUBBLOCK:
- case LZMA_FILTER_X86:
- case LZMA_FILTER_POWERPC:
- case LZMA_FILTER_IA64:
- case LZMA_FILTER_ARM:
- case LZMA_FILTER_ARMTHUMB:
- case LZMA_FILTER_SPARC:
- // These are very fast, thus there is no point in
- // splitting the data into smaller blocks.
- break;
-
- case LZMA_FILTER_LZMA1:
- // The block sizes of the possible next filters in
- // the chain are irrelevant after the LZMA filter.
- return ((lzma_options_lzma *)(filters->options))
- ->dictionary_size;
-
- default:
- // Unknown filters
- return 0;
- }
-
- ++filters;
- }
-
- // Indicate that splitting would be useless.
- return SIZE_MAX;
-}
diff --git a/src/liblzma/common/common.c b/src/liblzma/common/common.c
index 2f185e490d48..07b1d4763f69 100644
--- a/src/liblzma/common/common.c
+++ b/src/liblzma/common/common.c
@@ -76,7 +76,7 @@ lzma_bufcpy(const uint8_t *restrict in, size_t *restrict in_pos,
{
const size_t in_avail = in_size - *in_pos;
const size_t out_avail = out_size - *out_pos;
- const size_t copy_size = MIN(in_avail, out_avail);
+ const size_t copy_size = my_min(in_avail, out_avail);
memcpy(out + *out_pos, in + *in_pos, copy_size);
diff --git a/src/liblzma/common/common.h b/src/liblzma/common/common.h
index 7b7fbb11c3d8..3a85168f13b9 100644
--- a/src/liblzma/common/common.h
+++ b/src/liblzma/common/common.h
@@ -60,12 +60,6 @@
#define LZMA_FILTER_RESERVED_START (LZMA_VLI_C(1) << 62)
-/// Internal helper filter used by Subblock decoder. It is mapped to an
-/// otherwise invalid Filter ID, which is impossible to get from any input
-/// file (even if malicious file).
-#define LZMA_FILTER_SUBBLOCK_HELPER LZMA_VLI_C(0x7000000000000001)
-
-
/// Supported flags that can be passed to lzma_stream_decoder()
/// or lzma_auto_decoder().
#define LZMA_SUPPORTED_FLAGS \
diff --git a/src/liblzma/common/filter_common.c b/src/liblzma/common/filter_common.c
index 2322d7deec9a..b157c6280f81 100644
--- a/src/liblzma/common/filter_common.c
+++ b/src/liblzma/common/filter_common.c
@@ -52,15 +52,6 @@ static const struct {
.changes_size = true,
},
#endif
-#if defined(HAVE_ENCODER_SUBBLOCK) || defined(HAVE_DECODER_SUBBLOCK)
- {
- .id = LZMA_FILTER_SUBBLOCK,
- .options_size = sizeof(lzma_options_subblock),
- .non_last_ok = true,
- .last_ok = true,
- .changes_size = true,
- },
-#endif
#ifdef HAVE_DECODER_X86
{
.id = LZMA_FILTER_X86,
diff --git a/src/liblzma/common/filter_decoder.c b/src/liblzma/common/filter_decoder.c
index 95f77b76cf7a..1ebbe2afef0c 100644
--- a/src/liblzma/common/filter_decoder.c
+++ b/src/liblzma/common/filter_decoder.c
@@ -14,8 +14,6 @@
#include "filter_common.h"
#include "lzma_decoder.h"
#include "lzma2_decoder.h"
-#include "subblock_decoder.h"
-#include "subblock_decoder_helper.h"
#include "simple_decoder.h"
#include "delta_decoder.h"
@@ -60,20 +58,6 @@ static const lzma_filter_decoder decoders[] = {
.props_decode = &lzma_lzma2_props_decode,
},
#endif
-#ifdef HAVE_DECODER_SUBBLOCK
- {
- .id = LZMA_FILTER_SUBBLOCK,
- .init = &lzma_subblock_decoder_init,
-// .memusage = &lzma_subblock_decoder_memusage,
- .props_decode = NULL,
- },
- {
- .id = LZMA_FILTER_SUBBLOCK_HELPER,
- .init = &lzma_subblock_decoder_helper_init,
- .memusage = NULL,
- .props_decode = NULL,
- },
-#endif
#ifdef HAVE_DECODER_X86
{
.id = LZMA_FILTER_X86,
diff --git a/src/liblzma/common/filter_encoder.c b/src/liblzma/common/filter_encoder.c
index ab3d3af15e23..436d2cc6e424 100644
--- a/src/liblzma/common/filter_encoder.c
+++ b/src/liblzma/common/filter_encoder.c
@@ -14,7 +14,6 @@
#include "filter_common.h"
#include "lzma_encoder.h"
#include "lzma2_encoder.h"
-#include "subblock_encoder.h"
#include "simple_encoder.h"
#include "delta_encoder.h"
@@ -77,17 +76,6 @@ static const lzma_filter_encoder encoders[] = {
.props_encode = &lzma_lzma2_props_encode,
},
#endif
-#ifdef HAVE_ENCODER_SUBBLOCK
- {
- .id = LZMA_FILTER_SUBBLOCK,
- .init = &lzma_subblock_encoder_init,
-// .memusage = &lzma_subblock_encoder_memusage,
- .chunk_size = NULL,
- .props_size_get = NULL,
- .props_size_fixed = 0,
- .props_encode = NULL,
- },
-#endif
#ifdef HAVE_ENCODER_X86
{
.id = LZMA_FILTER_X86,
diff --git a/src/liblzma/common/stream_buffer_encoder.c b/src/liblzma/common/stream_buffer_encoder.c
index bbafaa6d01d9..f727d8542b34 100644
--- a/src/liblzma/common/stream_buffer_encoder.c
+++ b/src/liblzma/common/stream_buffer_encoder.c
@@ -33,7 +33,7 @@ lzma_stream_buffer_bound(size_t uncompressed_size)
// Catch the possible integer overflow and also prevent the size of
// the Stream exceeding LZMA_VLI_MAX (theoretically possible on
// 64-bit systems).
- if (MIN(SIZE_MAX, LZMA_VLI_MAX) - block_bound < HEADERS_BOUND)
+ if (my_min(SIZE_MAX, LZMA_VLI_MAX) - block_bound < HEADERS_BOUND)
return 0;
return block_bound + HEADERS_BOUND;
diff --git a/src/liblzma/delta/delta_encoder.c b/src/liblzma/delta/delta_encoder.c
index 80d0d1764ddc..ea1cc2cb020c 100644
--- a/src/liblzma/delta/delta_encoder.c
+++ b/src/liblzma/delta/delta_encoder.c
@@ -59,7 +59,7 @@ delta_encode(lzma_coder *coder, lzma_allocator *allocator,
if (coder->next.code == NULL) {
const size_t in_avail = in_size - *in_pos;
const size_t out_avail = out_size - *out_pos;
- const size_t size = MIN(in_avail, out_avail);
+ const size_t size = my_min(in_avail, out_avail);
copy_and_encode(coder, in + *in_pos, out + *out_pos, size);
diff --git a/src/liblzma/lz/lz_decoder.c b/src/liblzma/lz/lz_decoder.c
index 350b1f898125..2c57355125f7 100644
--- a/src/liblzma/lz/lz_decoder.c
+++ b/src/liblzma/lz/lz_decoder.c
@@ -81,8 +81,9 @@ decode_buffer(lzma_coder *coder,
// It must not decode past the end of the dictionary
// buffer, and we don't want it to decode more than is
// actually needed to fill the out[] buffer.
- coder->dict.limit = coder->dict.pos + MIN(out_size - *out_pos,
- coder->dict.size - coder->dict.pos);
+ coder->dict.limit = coder->dict.pos
+ + my_min(out_size - *out_pos,
+ coder->dict.size - coder->dict.pos);
// Call the coder->lz.code() to do the actual decoding.
const lzma_ret ret = coder->lz.code(
@@ -264,7 +265,7 @@ lzma_lz_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
&& lz_options.preset_dict_size > 0) {
// If the preset dictionary is bigger than the actual
// dictionary, copy only the tail.
- const size_t copy_size = MIN(lz_options.preset_dict_size,
+ const size_t copy_size = my_min(lz_options.preset_dict_size,
lz_options.dict_size);
const size_t offset = lz_options.preset_dict_size - copy_size;
memcpy(next->coder->dict.buf, lz_options.preset_dict + offset,
diff --git a/src/liblzma/lz/lz_decoder.h b/src/liblzma/lz/lz_decoder.h
index bf1609dbedf9..7266e803165f 100644
--- a/src/liblzma/lz/lz_decoder.h
+++ b/src/liblzma/lz/lz_decoder.h
@@ -129,7 +129,7 @@ dict_repeat(lzma_dict *dict, uint32_t distance, uint32_t *len)
{
// Don't write past the end of the dictionary.
const size_t dict_avail = dict->limit - dict->pos;
- uint32_t left = MIN(dict_avail, *len);
+ uint32_t left = my_min(dict_avail, *len);
*len -= left;
// Repeat a block of data from the history. Because memcpy() is faster
diff --git a/src/liblzma/lz/lz_encoder.c b/src/liblzma/lz/lz_encoder.c
index 757e53749c4d..273f577b69b9 100644
--- a/src/liblzma/lz/lz_encoder.c
+++ b/src/liblzma/lz/lz_encoder.c
@@ -341,7 +341,7 @@ lz_encoder_prepare(lzma_mf *mf, lzma_allocator *allocator,
// Deallocate the old hash array if it exists and has different size
// than what is needed now.
- if (mf->hash != NULL && old_count != new_count) {
+ if (old_count != new_count) {
lzma_free(mf->hash, allocator);
mf->hash = NULL;
}
@@ -349,9 +349,10 @@ lz_encoder_prepare(lzma_mf *mf, lzma_allocator *allocator,
// Maximum number of match finder cycles
mf->depth = lz_options->depth;
if (mf->depth == 0) {
- mf->depth = 16 + (mf->nice_len / 2);
- if (!is_bt)
- mf->depth /= 2;
+ if (is_bt)
+ mf->depth = 16 + mf->nice_len / 2;
+ else
+ mf->depth = 4 + mf->nice_len / 4;
}
return false;
@@ -423,7 +424,7 @@ lz_encoder_init(lzma_mf *mf, lzma_allocator *allocator,
&& lz_options->preset_dict_size > 0) {
// If the preset dictionary is bigger than the actual
// dictionary, use only the tail.
- mf->write_pos = MIN(lz_options->preset_dict_size, mf->size);
+ mf->write_pos = my_min(lz_options->preset_dict_size, mf->size);
memcpy(mf->buffer, lz_options->preset_dict
+ lz_options->preset_dict_size - mf->write_pos,
mf->write_pos);
@@ -444,6 +445,8 @@ lzma_lz_encoder_memusage(const lzma_lz_options *lz_options)
lzma_mf mf = {
.buffer = NULL,
.hash = NULL,
+ .hash_size_sum = 0,
+ .sons_count = 0,
};
// Setup the size information into mf.
@@ -519,6 +522,8 @@ lzma_lz_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
next->coder->mf.buffer = NULL;
next->coder->mf.hash = NULL;
+ next->coder->mf.hash_size_sum = 0;
+ next->coder->mf.sons_count = 0;
next->coder->next = LZMA_NEXT_CODER_INIT;
}
diff --git a/src/liblzma/lz/lz_encoder.h b/src/liblzma/lz/lz_encoder.h
index f6352a47227e..741c4532280d 100644
--- a/src/liblzma/lz/lz_encoder.h
+++ b/src/liblzma/lz/lz_encoder.h
@@ -281,7 +281,7 @@ mf_read(lzma_mf *mf, uint8_t *out, size_t *out_pos, size_t out_size,
size_t *left)
{
const size_t out_avail = out_size - *out_pos;
- const size_t copy_size = MIN(out_avail, *left);
+ const size_t copy_size = my_min(out_avail, *left);
assert(mf->read_ahead == 0);
assert(mf->read_pos >= *left);
diff --git a/src/liblzma/lz/lz_encoder_mf.c b/src/liblzma/lz/lz_encoder_mf.c
index b31b08578d45..f82a1c1d2959 100644
--- a/src/liblzma/lz/lz_encoder_mf.c
+++ b/src/liblzma/lz/lz_encoder_mf.c
@@ -481,7 +481,7 @@ bt_find_func(
<< 1);
const uint8_t *const pb = cur - delta;
- uint32_t len = MIN(len0, len1);
+ uint32_t len = my_min(len0, len1);
if (pb[len] == cur[len]) {
while (++len != len_limit)
@@ -546,7 +546,7 @@ bt_skip_func(
+ (delta > cyclic_pos ? cyclic_size : 0))
<< 1);
const uint8_t *pb = cur - delta;
- uint32_t len = MIN(len0, len1);
+ uint32_t len = my_min(len0, len1);
if (pb[len] == cur[len]) {
while (++len != len_limit)
diff --git a/src/liblzma/lzma/lzma2_encoder.c b/src/liblzma/lzma/lzma2_encoder.c
index 1e0569a4a956..b48e0d6894f6 100644
--- a/src/liblzma/lzma/lzma2_encoder.c
+++ b/src/liblzma/lzma/lzma2_encoder.c
@@ -372,7 +372,7 @@ extern lzma_ret
lzma_lzma2_props_encode(const void *options, uint8_t *out)
{
const lzma_options_lzma *const opt = options;
- uint32_t d = MAX(opt->dict_size, LZMA_DICT_SIZE_MIN);
+ uint32_t d = my_max(opt->dict_size, LZMA_DICT_SIZE_MIN);
// Round up to to the next 2^n - 1 or 2^n + 2^(n - 1) - 1 depending
// on which one is the next:
diff --git a/src/liblzma/lzma/lzma_encoder_optimum_fast.c b/src/liblzma/lzma/lzma_encoder_optimum_fast.c
index 4ca55b60028f..f835f69356bd 100644
--- a/src/liblzma/lzma/lzma_encoder_optimum_fast.c
+++ b/src/liblzma/lzma/lzma_encoder_optimum_fast.c
@@ -33,7 +33,7 @@ lzma_lzma_optimum_fast(lzma_coder *restrict coder, lzma_mf *restrict mf,
}
const uint8_t *buf = mf_ptr(mf) - 1;
- const uint32_t buf_avail = MIN(mf_avail(mf) + 1, MATCH_LEN_MAX);
+ const uint32_t buf_avail = my_min(mf_avail(mf) + 1, MATCH_LEN_MAX);
if (buf_avail < 2) {
// There's not enough input left to encode a match.
diff --git a/src/liblzma/lzma/lzma_encoder_optimum_normal.c b/src/liblzma/lzma/lzma_encoder_optimum_normal.c
index 9284c8a2896f..7e856493c8cd 100644
--- a/src/liblzma/lzma/lzma_encoder_optimum_normal.c
+++ b/src/liblzma/lzma/lzma_encoder_optimum_normal.c
@@ -287,7 +287,7 @@ helper1(lzma_coder *restrict coder, lzma_mf *restrict mf,
matches_count = coder->matches_count;
}
- const uint32_t buf_avail = MIN(mf_avail(mf) + 1, MATCH_LEN_MAX);
+ const uint32_t buf_avail = my_min(mf_avail(mf) + 1, MATCH_LEN_MAX);
if (buf_avail < 2) {
*back_res = UINT32_MAX;
*len_res = 1;
@@ -371,7 +371,7 @@ helper1(lzma_coder *restrict coder, lzma_mf *restrict mf,
}
}
- const uint32_t len_end = MAX(len_main, rep_lens[rep_max_index]);
+ const uint32_t len_end = my_max(len_main, rep_lens[rep_max_index]);
if (len_end < 2) {
*back_res = coder->opts[1].back_prev;
@@ -565,12 +565,12 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
if (buf_avail_full < 2)
return len_end;
- const uint32_t buf_avail = MIN(buf_avail_full, nice_len);
+ const uint32_t buf_avail = my_min(buf_avail_full, nice_len);
if (!next_is_literal && match_byte != current_byte) { // speed optimization
// try literal + rep0
const uint8_t *const buf_back = buf - reps[0] - 1;
- const uint32_t limit = MIN(buf_avail_full, nice_len + 1);
+ const uint32_t limit = my_min(buf_avail_full, nice_len + 1);
uint32_t len_test = 1;
while (len_test < limit && buf[len_test] == buf_back[len_test])
@@ -648,7 +648,7 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
uint32_t len_test_2 = len_test + 1;
- const uint32_t limit = MIN(buf_avail_full,
+ const uint32_t limit = my_min(buf_avail_full,
len_test_2 + nice_len);
for (; len_test_2 < limit
&& buf[len_test_2] == buf_back[len_test_2];
@@ -743,7 +743,7 @@ helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
// Try Match + Literal + Rep0
const uint8_t *const buf_back = buf - cur_back - 1;
uint32_t len_test_2 = len_test + 1;
- const uint32_t limit = MIN(buf_avail_full,
+ const uint32_t limit = my_min(buf_avail_full,
len_test_2 + nice_len);
for (; len_test_2 < limit &&
@@ -860,7 +860,7 @@ lzma_lzma_optimum_normal(lzma_coder *restrict coder, lzma_mf *restrict mf,
len_end = helper2(coder, reps, mf_ptr(mf) - 1, len_end,
position + cur, cur, mf->nice_len,
- MIN(mf_avail(mf) + 1, OPTS - 1 - cur));
+ my_min(mf_avail(mf) + 1, OPTS - 1 - cur));
}
backward(coder, len_res, back_res, cur);
diff --git a/src/liblzma/lzma/lzma_encoder_presets.c b/src/liblzma/lzma/lzma_encoder_presets.c
index c4c9c146f559..21e427a8d027 100644
--- a/src/liblzma/lzma/lzma_encoder_presets.c
+++ b/src/liblzma/lzma/lzma_encoder_presets.c
@@ -23,9 +23,6 @@ lzma_lzma_preset(lzma_options_lzma *options, uint32_t preset)
if (level > 9 || (flags & ~supported_flags))
return true;
- const uint32_t dict_shift = level <= 1 ? 16 : level + 17;
- options->dict_size = UINT32_C(1) << dict_shift;
-
options->preset_dict = NULL;
options->preset_dict_size = 0;
@@ -33,19 +30,31 @@ lzma_lzma_preset(lzma_options_lzma *options, uint32_t preset)
options->lp = LZMA_LP_DEFAULT;
options->pb = LZMA_PB_DEFAULT;
- options->mode = level <= 2 ? LZMA_MODE_FAST : LZMA_MODE_NORMAL;
+ options->dict_size = UINT32_C(1) << (uint8_t []){
+ 18, 20, 21, 22, 22, 23, 23, 24, 25, 26 }[level];
- options->nice_len = level == 0 ? 8 : level <= 5 ? 32 : 64;
- options->mf = level <= 1 ? LZMA_MF_HC3 : level <= 2 ? LZMA_MF_HC4
- : LZMA_MF_BT4;
- options->depth = 0;
+ if (level <= 3) {
+ options->mode = LZMA_MODE_FAST;
+ options->mf = level == 0 ? LZMA_MF_HC3 : LZMA_MF_HC4;
+ options->nice_len = level <= 1 ? 128 : 273;
+ options->depth = (uint8_t []){ 4, 8, 24, 48 }[level];
+ } else {
+ options->mode = LZMA_MODE_NORMAL;
+ options->mf = LZMA_MF_BT4;
+ options->nice_len = level == 4 ? 16 : level == 5 ? 32 : 64;
+ options->depth = 0;
+ }
if (flags & LZMA_PRESET_EXTREME) {
- options->lc = 4; // FIXME?
options->mode = LZMA_MODE_NORMAL;
options->mf = LZMA_MF_BT4;
- options->nice_len = 273;
- options->depth = 512;
+ if (level == 3 || level == 5) {
+ options->nice_len = 192;
+ options->depth = 0;
+ } else {
+ options->nice_len = 273;
+ options->depth = 512;
+ }
}
return false;
diff --git a/src/liblzma/subblock/subblock_decoder.c b/src/liblzma/subblock/subblock_decoder.c
deleted file mode 100644
index e055cee3ea78..000000000000
--- a/src/liblzma/subblock/subblock_decoder.c
+++ /dev/null
@@ -1,630 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file subblock_decoder.c
-/// \brief Decoder of the Subblock filter
-//
-// Author: Lasse Collin
-//
-// This file has been put into the public domain.
-// You can do whatever you want with this file.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "subblock_decoder.h"
-#include "subblock_decoder_helper.h"
-#include "filter_decoder.h"
-
-
-/// Maximum number of consecutive Subblocks with Subblock Type Padding
-#define PADDING_MAX 31
-
-
-struct lzma_coder_s {
- lzma_next_coder next;
-
- enum {
- // These require that there is at least one input
- // byte available.
- SEQ_FLAGS,
- SEQ_FILTER_FLAGS,
- SEQ_FILTER_END,
- SEQ_REPEAT_COUNT_1,
- SEQ_REPEAT_COUNT_2,
- SEQ_REPEAT_COUNT_3,
- SEQ_REPEAT_SIZE,
- SEQ_REPEAT_READ_DATA,
- SEQ_SIZE_1,
- SEQ_SIZE_2,
- SEQ_SIZE_3, // This must be right before SEQ_DATA.
-
- // These don't require any input to be available.
- SEQ_DATA,
- SEQ_REPEAT_FAST,
- SEQ_REPEAT_NORMAL,
- } sequence;
-
- /// Number of bytes left in the current Subblock Data field.
- size_t size;
-
- /// Number of consecutive Subblocks with Subblock Type Padding
- uint32_t padding;
-
- /// True when .next.code() has returned LZMA_STREAM_END.
- bool next_finished;
-
- /// True when the Subblock decoder has detected End of Payload Marker.
- /// This may become true before next_finished becomes true.
- bool this_finished;
-
- /// True if Subfilters are allowed.
- bool allow_subfilters;
-
- /// Indicates if at least one byte of decoded output has been
- /// produced after enabling Subfilter.
- bool got_output_with_subfilter;
-
- /// Possible subfilter
- lzma_next_coder subfilter;
-
- /// Filter Flags decoder is needed to parse the ID and Properties
- /// of the subfilter.
- lzma_next_coder filter_flags_decoder;
-
- /// The filter_flags_decoder stores its results here.
- lzma_filter filter_flags;
-
- /// Options for the Subblock decoder helper. This is used to tell
- /// the helper when it should return LZMA_STREAM_END to the subfilter.
- lzma_options_subblock_helper helper;
-
- struct {
- /// How many times buffer should be repeated
- size_t count;
-
- /// Size of the buffer
- size_t size;
-
- /// Position in the buffer
- size_t pos;
-
- /// Buffer to hold the data to be repeated
- uint8_t buffer[LZMA_SUBBLOCK_RLE_MAX];
- } repeat;
-
- /// Temporary buffer needed when the Subblock filter is not the last
- /// filter in the chain. The output of the next filter is first
- /// decoded into buffer[], which is then used as input for the actual
- /// Subblock decoder.
- struct {
- size_t pos;
- size_t size;
- uint8_t buffer[LZMA_BUFFER_SIZE];
- } temp;
-};
-
-
-/// Values of valid Subblock Flags
-enum {
- FLAG_PADDING,
- FLAG_EOPM,
- FLAG_DATA,
- FLAG_REPEAT,
- FLAG_SET_SUBFILTER,
- FLAG_END_SUBFILTER,
-};
-
-
-/// Calls the subfilter and updates coder->uncompressed_size.
-static lzma_ret
-subfilter_decode(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *in, size_t *in_pos,
- size_t in_size, uint8_t *restrict out,
- size_t *restrict out_pos, size_t out_size, lzma_action action)
-{
- assert(coder->subfilter.code != NULL);
-
- // Call the subfilter.
- const lzma_ret ret = coder->subfilter.code(
- coder->subfilter.coder, allocator,
- in, in_pos, in_size, out, out_pos, out_size, action);
-
- return ret;
-}
-
-
-static lzma_ret
-decode_buffer(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *in, size_t *in_pos,
- size_t in_size, uint8_t *restrict out,
- size_t *restrict out_pos, size_t out_size, lzma_action action)
-{
- while (*out_pos < out_size && (*in_pos < in_size
- || coder->sequence >= SEQ_DATA))
- switch (coder->sequence) {
- case SEQ_FLAGS: {
- // Do the correct action depending on the Subblock Type.
- switch (in[*in_pos] >> 4) {
- case FLAG_PADDING:
- // Only check that reserved bits are zero.
- if (++coder->padding > PADDING_MAX
- || in[*in_pos] & 0x0F)
- return LZMA_DATA_ERROR;
- ++*in_pos;
- break;
-
- case FLAG_EOPM:
- // There must be no Padding before EOPM.
- if (coder->padding != 0)
- return LZMA_DATA_ERROR;
-
- // Check that reserved bits are zero.
- if (in[*in_pos] & 0x0F)
- return LZMA_DATA_ERROR;
-
- // There must be no Subfilter enabled.
- if (coder->subfilter.code != NULL)
- return LZMA_DATA_ERROR;
-
- ++*in_pos;
- return LZMA_STREAM_END;
-
- case FLAG_DATA:
- // First four bits of the Subblock Data size.
- coder->size = in[*in_pos] & 0x0F;
- ++*in_pos;
- coder->got_output_with_subfilter = true;
- coder->sequence = SEQ_SIZE_1;
- break;
-
- case FLAG_REPEAT:
- // First four bits of the Repeat Count. We use
- // coder->size as a temporary place for it.
- coder->size = in[*in_pos] & 0x0F;
- ++*in_pos;
- coder->got_output_with_subfilter = true;
- coder->sequence = SEQ_REPEAT_COUNT_1;
- break;
-
- case FLAG_SET_SUBFILTER: {
- if (coder->padding != 0 || (in[*in_pos] & 0x0F)
- || coder->subfilter.code != NULL
- || !coder->allow_subfilters)
- return LZMA_DATA_ERROR;
-
- assert(coder->filter_flags.options == NULL);
- abort();
-// return_if_error(lzma_filter_flags_decoder_init(
-// &coder->filter_flags_decoder,
-// allocator, &coder->filter_flags));
-
- coder->got_output_with_subfilter = false;
-
- ++*in_pos;
- coder->sequence = SEQ_FILTER_FLAGS;
- break;
- }
-
- case FLAG_END_SUBFILTER: {
- if (coder->padding != 0 || (in[*in_pos] & 0x0F)
- || coder->subfilter.code == NULL
- || !coder->got_output_with_subfilter)
- return LZMA_DATA_ERROR;
-
- // Tell the helper filter to indicate End of Input
- // to our subfilter.
- coder->helper.end_was_reached = true;
-
- size_t dummy = 0;
- const lzma_ret ret = subfilter_decode(coder, allocator,
- NULL, &dummy, 0, out, out_pos,out_size,
- action);
-
- // If we didn't reach the end of the subfilter's output
- // yet, return to the application. On the next call we
- // will get to this same switch-case again, because we
- // haven't updated *in_pos yet.
- if (ret != LZMA_STREAM_END)
- return ret;
-
- // Free Subfilter's memory. This is a bit debatable,
- // since we could avoid some malloc()/free() calls
- // if the same Subfilter gets used soon again. But
- // if Subfilter isn't used again, we could leave
- // a memory-hogging filter dangling until someone
- // frees Subblock filter itself.
- lzma_next_end(&coder->subfilter, allocator);
-
- // Free memory used for subfilter options. This is
- // safe, because we don't support any Subfilter that
- // would allow pointers in the options structure.
- lzma_free(coder->filter_flags.options, allocator);
- coder->filter_flags.options = NULL;
-
- ++*in_pos;
-
- break;
- }
-
- default:
- return LZMA_DATA_ERROR;
- }
-
- break;
- }
-
- case SEQ_FILTER_FLAGS: {
- const lzma_ret ret = coder->filter_flags_decoder.code(
- coder->filter_flags_decoder.coder, allocator,
- in, in_pos, in_size, NULL, NULL, 0, LZMA_RUN);
- if (ret != LZMA_STREAM_END)
- return ret == LZMA_OPTIONS_ERROR
- ? LZMA_DATA_ERROR : ret;
-
- // Don't free the filter_flags_decoder. It doesn't take much
- // memory and we may need it again.
-
- // Initialize the Subfilter. Subblock and Copy filters are
- // not allowed.
- if (coder->filter_flags.id == LZMA_FILTER_SUBBLOCK)
- return LZMA_DATA_ERROR;
-
- coder->helper.end_was_reached = false;
-
- lzma_filter filters[3] = {
- {
- .id = coder->filter_flags.id,
- .options = coder->filter_flags.options,
- }, {
- .id = LZMA_FILTER_SUBBLOCK_HELPER,
- .options = &coder->helper,
- }, {
- .id = LZMA_VLI_UNKNOWN,
- .options = NULL,
- }
- };
-
- // Optimization: We know that LZMA uses End of Payload Marker
- // (not End of Input), so we can omit the helper filter.
- if (filters[0].id == LZMA_FILTER_LZMA1)
- filters[1].id = LZMA_VLI_UNKNOWN;
-
- return_if_error(lzma_raw_decoder_init(
- &coder->subfilter, allocator, filters));
-
- coder->sequence = SEQ_FLAGS;
- break;
- }
-
- case SEQ_FILTER_END:
- // We are in the beginning of a Subblock. The next Subblock
- // whose type is not Padding, must indicate end of Subfilter.
- if (in[*in_pos] == (FLAG_PADDING << 4)) {
- ++*in_pos;
- break;
- }
-
- if (in[*in_pos] != (FLAG_END_SUBFILTER << 4))
- return LZMA_DATA_ERROR;
-
- coder->sequence = SEQ_FLAGS;
- break;
-
- case SEQ_REPEAT_COUNT_1:
- case SEQ_SIZE_1:
- // We use the same code to parse
- // - the Size (28 bits) in Subblocks of type Data; and
- // - the Repeat count (28 bits) in Subblocks of type
- // Repeating Data.
- coder->size |= (size_t)(in[*in_pos]) << 4;
- ++*in_pos;
- ++coder->sequence;
- break;
-
- case SEQ_REPEAT_COUNT_2:
- case SEQ_SIZE_2:
- coder->size |= (size_t)(in[*in_pos]) << 12;
- ++*in_pos;
- ++coder->sequence;
- break;
-
- case SEQ_REPEAT_COUNT_3:
- case SEQ_SIZE_3:
- coder->size |= (size_t)(in[*in_pos]) << 20;
- ++*in_pos;
-
- // The real value is the stored value plus one.
- ++coder->size;
-
- // This moves to SEQ_REPEAT_SIZE or SEQ_DATA. That's why
- // SEQ_DATA must be right after SEQ_SIZE_3 in coder->sequence.
- ++coder->sequence;
- break;
-
- case SEQ_REPEAT_SIZE:
- // Move the Repeat Count to the correct variable and parse
- // the Size of the Data to be repeated.
- coder->repeat.count = coder->size;
- coder->repeat.size = (size_t)(in[*in_pos]) + 1;
- coder->repeat.pos = 0;
-
- // The size of the Data field must be bigger than the number
- // of Padding bytes before this Subblock.
- if (coder->repeat.size <= coder->padding)
- return LZMA_DATA_ERROR;
-
- ++*in_pos;
- coder->padding = 0;
- coder->sequence = SEQ_REPEAT_READ_DATA;
- break;
-
- case SEQ_REPEAT_READ_DATA: {
- // Fill coder->repeat.buffer[].
- const size_t in_avail = in_size - *in_pos;
- const size_t out_avail
- = coder->repeat.size - coder->repeat.pos;
- const size_t copy_size = MIN(in_avail, out_avail);
-
- memcpy(coder->repeat.buffer + coder->repeat.pos,
- in + *in_pos, copy_size);
- *in_pos += copy_size;
- coder->repeat.pos += copy_size;
-
- if (coder->repeat.pos == coder->repeat.size) {
- coder->repeat.pos = 0;
-
- if (coder->repeat.size == 1
- && coder->subfilter.code == NULL)
- coder->sequence = SEQ_REPEAT_FAST;
- else
- coder->sequence = SEQ_REPEAT_NORMAL;
- }
-
- break;
- }
-
- case SEQ_DATA: {
- // The size of the Data field must be bigger than the number
- // of Padding bytes before this Subblock.
- assert(coder->size > 0);
- if (coder->size <= coder->padding)
- return LZMA_DATA_ERROR;
-
- coder->padding = 0;
-
- // Limit the amount of input to match the available
- // Subblock Data size.
- size_t in_limit;
- if (in_size - *in_pos > coder->size)
- in_limit = *in_pos + coder->size;
- else
- in_limit = in_size;
-
- if (coder->subfilter.code == NULL) {
- const size_t copy_size = lzma_bufcpy(
- in, in_pos, in_limit,
- out, out_pos, out_size);
-
- coder->size -= copy_size;
- } else {
- const size_t in_start = *in_pos;
- const lzma_ret ret = subfilter_decode(
- coder, allocator,
- in, in_pos, in_limit,
- out, out_pos, out_size,
- action);
-
- // Update the number of unprocessed bytes left in
- // this Subblock. This assert() is true because
- // in_limit prevents *in_pos getting too big.
- assert(*in_pos - in_start <= coder->size);
- coder->size -= *in_pos - in_start;
-
- if (ret == LZMA_STREAM_END) {
- // End of Subfilter can occur only at
- // a Subblock boundary.
- if (coder->size != 0)
- return LZMA_DATA_ERROR;
-
- // We need a Subblock with Unset
- // Subfilter before more data.
- coder->sequence = SEQ_FILTER_END;
- break;
- }
-
- if (ret != LZMA_OK)
- return ret;
- }
-
- // If we couldn't process the whole Subblock Data yet, return.
- if (coder->size > 0)
- return LZMA_OK;
-
- coder->sequence = SEQ_FLAGS;
- break;
- }
-
- case SEQ_REPEAT_FAST: {
- // Optimization for cases when there is only one byte to
- // repeat and no Subfilter.
- const size_t out_avail = out_size - *out_pos;
- const size_t copy_size = MIN(coder->repeat.count, out_avail);
-
- memset(out + *out_pos, coder->repeat.buffer[0], copy_size);
-
- *out_pos += copy_size;
- coder->repeat.count -= copy_size;
-
- if (coder->repeat.count != 0)
- return LZMA_OK;
-
- coder->sequence = SEQ_FLAGS;
- break;
- }
-
- case SEQ_REPEAT_NORMAL:
- do {
- // Cycle the repeat buffer if needed.
- if (coder->repeat.pos == coder->repeat.size) {
- if (--coder->repeat.count == 0) {
- coder->sequence = SEQ_FLAGS;
- break;
- }
-
- coder->repeat.pos = 0;
- }
-
- if (coder->subfilter.code == NULL) {
- lzma_bufcpy(coder->repeat.buffer,
- &coder->repeat.pos,
- coder->repeat.size,
- out, out_pos, out_size);
- } else {
- const lzma_ret ret = subfilter_decode(
- coder, allocator,
- coder->repeat.buffer,
- &coder->repeat.pos,
- coder->repeat.size,
- out, out_pos, out_size,
- action);
-
- if (ret == LZMA_STREAM_END) {
- // End of Subfilter can occur only at
- // a Subblock boundary.
- if (coder->repeat.pos
- != coder->repeat.size
- || --coder->repeat
- .count != 0)
- return LZMA_DATA_ERROR;
-
- // We need a Subblock with Unset
- // Subfilter before more data.
- coder->sequence = SEQ_FILTER_END;
- break;
-
- } else if (ret != LZMA_OK) {
- return ret;
- }
- }
- } while (*out_pos < out_size);
-
- break;
-
- default:
- return LZMA_PROG_ERROR;
- }
-
- return LZMA_OK;
-}
-
-
-static lzma_ret
-subblock_decode(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *restrict in, size_t *restrict in_pos,
- size_t in_size, uint8_t *restrict out,
- size_t *restrict out_pos, size_t out_size, lzma_action action)
-{
- if (coder->next.code == NULL)
- return decode_buffer(coder, allocator, in, in_pos, in_size,
- out, out_pos, out_size, action);
-
- while (*out_pos < out_size) {
- if (!coder->next_finished
- && coder->temp.pos == coder->temp.size) {
- coder->temp.pos = 0;
- coder->temp.size = 0;
-
- const lzma_ret ret = coder->next.code(
- coder->next.coder,
- allocator, in, in_pos, in_size,
- coder->temp.buffer, &coder->temp.size,
- LZMA_BUFFER_SIZE, action);
-
- if (ret == LZMA_STREAM_END)
- coder->next_finished = true;
- else if (coder->temp.size == 0 || ret != LZMA_OK)
- return ret;
- }
-
- if (coder->this_finished) {
- if (coder->temp.pos != coder->temp.size)
- return LZMA_DATA_ERROR;
-
- if (coder->next_finished)
- return LZMA_STREAM_END;
-
- return LZMA_OK;
- }
-
- const lzma_ret ret = decode_buffer(coder, allocator,
- coder->temp.buffer, &coder->temp.pos,
- coder->temp.size,
- out, out_pos, out_size, action);
-
- if (ret == LZMA_STREAM_END)
- // The next coder in the chain hasn't finished
- // yet. If the input data is valid, there
- // must be no more output coming, but the
- // next coder may still need a litle more
- // input to detect End of Payload Marker.
- coder->this_finished = true;
- else if (ret != LZMA_OK)
- return ret;
- else if (coder->next_finished && *out_pos < out_size)
- return LZMA_DATA_ERROR;
- }
-
- return LZMA_OK;
-}
-
-
-static void
-subblock_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
-{
- lzma_next_end(&coder->next, allocator);
- lzma_next_end(&coder->subfilter, allocator);
- lzma_next_end(&coder->filter_flags_decoder, allocator);
- lzma_free(coder->filter_flags.options, allocator);
- lzma_free(coder, allocator);
- return;
-}
-
-
-extern lzma_ret
-lzma_subblock_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
- const lzma_filter_info *filters)
-{
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
- return LZMA_MEM_ERROR;
-
- next->code = &subblock_decode;
- next->end = &subblock_decoder_end;
-
- next->coder->next = LZMA_NEXT_CODER_INIT;
- next->coder->subfilter = LZMA_NEXT_CODER_INIT;
- next->coder->filter_flags_decoder = LZMA_NEXT_CODER_INIT;
-
- } else {
- lzma_next_end(&next->coder->subfilter, allocator);
- lzma_free(next->coder->filter_flags.options, allocator);
- }
-
- next->coder->filter_flags.options = NULL;
-
- next->coder->sequence = SEQ_FLAGS;
- next->coder->padding = 0;
- next->coder->next_finished = false;
- next->coder->this_finished = false;
- next->coder->temp.pos = 0;
- next->coder->temp.size = 0;
-
- if (filters[0].options != NULL)
- next->coder->allow_subfilters = ((lzma_options_subblock *)(
- filters[0].options))->allow_subfilters;
- else
- next->coder->allow_subfilters = false;
-
- return lzma_next_filter_init(
- &next->coder->next, allocator, filters + 1);
-}
diff --git a/src/liblzma/subblock/subblock_decoder.h b/src/liblzma/subblock/subblock_decoder.h
deleted file mode 100644
index d1030b2b94f5..000000000000
--- a/src/liblzma/subblock/subblock_decoder.h
+++ /dev/null
@@ -1,22 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file subblock_decoder.h
-/// \brief Decoder of the Subblock filter
-//
-// Author: Lasse Collin
-//
-// This file has been put into the public domain.
-// You can do whatever you want with this file.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef LZMA_SUBBLOCK_DECODER_H
-#define LZMA_SUBBLOCK_DECODER_H
-
-#include "common.h"
-
-
-extern lzma_ret lzma_subblock_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
-
-#endif
diff --git a/src/liblzma/subblock/subblock_decoder_helper.c b/src/liblzma/subblock/subblock_decoder_helper.c
deleted file mode 100644
index 2a864eddad9f..000000000000
--- a/src/liblzma/subblock/subblock_decoder_helper.c
+++ /dev/null
@@ -1,70 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file subblock_decoder_helper.c
-/// \brief Helper filter for the Subblock decoder
-///
-/// This filter is used to indicate End of Input for subfilters needing it.
-//
-// Author: Lasse Collin
-//
-// This file has been put into the public domain.
-// You can do whatever you want with this file.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "subblock_decoder_helper.h"
-
-
-struct lzma_coder_s {
- const lzma_options_subblock_helper *options;
-};
-
-
-static lzma_ret
-helper_decode(lzma_coder *coder,
- lzma_allocator *allocator lzma_attribute((unused)),
- const uint8_t *restrict in, size_t *restrict in_pos,
- size_t in_size, uint8_t *restrict out,
- size_t *restrict out_pos, size_t out_size,
- lzma_action action lzma_attribute((unused)))
-{
- // If end_was_reached is true, we cannot have any input.
- assert(!coder->options->end_was_reached || *in_pos == in_size);
-
- // We can safely copy as much as possible, because we are never
- // given more data than a single Subblock Data field.
- lzma_bufcpy(in, in_pos, in_size, out, out_pos, out_size);
-
- // Return LZMA_STREAM_END when instructed so by the Subblock decoder.
- return coder->options->end_was_reached ? LZMA_STREAM_END : LZMA_OK;
-}
-
-
-static void
-helper_end(lzma_coder *coder, lzma_allocator *allocator)
-{
- lzma_free(coder, allocator);
- return;
-}
-
-
-extern lzma_ret
-lzma_subblock_decoder_helper_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters)
-{
- // This is always the last filter in the chain.
- assert(filters[1].init == NULL);
-
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
- return LZMA_MEM_ERROR;
-
- next->code = &helper_decode;
- next->end = &helper_end;
- }
-
- next->coder->options = filters[0].options;
-
- return LZMA_OK;
-}
diff --git a/src/liblzma/subblock/subblock_decoder_helper.h b/src/liblzma/subblock/subblock_decoder_helper.h
deleted file mode 100644
index 18dcbb39a397..000000000000
--- a/src/liblzma/subblock/subblock_decoder_helper.h
+++ /dev/null
@@ -1,29 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file subblock_decoder_helper.h
-/// \brief Helper filter for the Subblock decoder
-///
-/// This filter is used to indicate End of Input for subfilters needing it.
-//
-// Author: Lasse Collin
-//
-// This file has been put into the public domain.
-// You can do whatever you want with this file.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef LZMA_SUBBLOCK_DECODER_HELPER_H
-#define LZMA_SUBBLOCK_DECODER_HELPER_H
-
-#include "common.h"
-
-
-typedef struct {
- bool end_was_reached;
-} lzma_options_subblock_helper;
-
-
-extern lzma_ret lzma_subblock_decoder_helper_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
-
-#endif
diff --git a/src/liblzma/subblock/subblock_encoder.c b/src/liblzma/subblock/subblock_encoder.c
deleted file mode 100644
index 4f71f99cc639..000000000000
--- a/src/liblzma/subblock/subblock_encoder.c
+++ /dev/null
@@ -1,984 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file subblock_encoder.c
-/// \brief Encoder of the Subblock filter
-//
-// Author: Lasse Collin
-//
-// This file has been put into the public domain.
-// You can do whatever you want with this file.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "subblock_encoder.h"
-#include "filter_encoder.h"
-
-
-/// Maximum number of repeats that a single Repeating Data can indicate.
-/// This is directly from the file format specification.
-#define REPEAT_COUNT_MAX (1U << 28)
-
-/// Number of bytes the data chunk (not including the header part) must be
-/// before we care about alignment. This is somewhat arbitrary. It just
-/// doesn't make sense to waste bytes for alignment when the data chunk
-/// is very small.
-#define MIN_CHUNK_SIZE_FOR_ALIGN 4
-
-/// Number of bytes of the header part of Subblock Type `Data'. This is
-/// used as the `skew' argument for subblock_align().
-#define ALIGN_SKEW_DATA 4
-
-/// Like above but for Repeating Data.
-#define ALIGN_SKEW_REPEATING_DATA 5
-
-/// Writes one byte to output buffer and updates the alignment counter.
-#define write_byte(b) \
-do { \
- assert(*out_pos < out_size); \
- out[*out_pos] = b; \
- ++*out_pos; \
- ++coder->alignment.out_pos; \
-} while (0)
-
-
-struct lzma_coder_s {
- lzma_next_coder next;
- bool next_finished;
-
- enum {
- SEQ_FILL,
- SEQ_FLUSH,
- SEQ_RLE_COUNT_0,
- SEQ_RLE_COUNT_1,
- SEQ_RLE_COUNT_2,
- SEQ_RLE_COUNT_3,
- SEQ_RLE_SIZE,
- SEQ_RLE_DATA,
- SEQ_DATA_SIZE_0,
- SEQ_DATA_SIZE_1,
- SEQ_DATA_SIZE_2,
- SEQ_DATA_SIZE_3,
- SEQ_DATA,
- SEQ_SUBFILTER_INIT,
- SEQ_SUBFILTER_FLAGS,
- } sequence;
-
- /// Pointer to the options given by the application. This is used
- /// for two-way communication with the application.
- lzma_options_subblock *options;
-
- /// Position in various arrays.
- size_t pos;
-
- /// Holds subblock.size - 1 or rle.size - 1 when encoding size
- /// of Data or Repeat Count.
- uint32_t tmp;
-
- struct {
- /// This is a copy of options->alignment, or
- /// LZMA_SUBBLOCK_ALIGNMENT_DEFAULT if options is NULL.
- uint32_t multiple;
-
- /// Number of input bytes which we have processed and started
- /// writing out. 32-bit integer is enough since we care only
- /// about the lowest bits when fixing alignment.
- uint32_t in_pos;
-
- /// Number of bytes written out.
- uint32_t out_pos;
- } alignment;
-
- struct {
- /// Pointer to allocated buffer holding the Data field
- /// of Subblock Type "Data".
- uint8_t *data;
-
- /// Number of bytes in the buffer.
- size_t size;
-
- /// Allocated size of the buffer.
- size_t limit;
-
- /// Number of input bytes that we have already read but
- /// not yet started writing out. This can be different
- /// to `size' when using Subfilter. That's why we track
- /// in_pending separately for RLE (see below).
- uint32_t in_pending;
- } subblock;
-
- struct {
- /// Buffer to hold the data that may be coded with
- /// Subblock Type `Repeating Data'.
- uint8_t buffer[LZMA_SUBBLOCK_RLE_MAX];
-
- /// Number of bytes in buffer[].
- size_t size;
-
- /// Number of times the first `size' bytes of buffer[]
- /// will be repeated.
- uint64_t count;
-
- /// Like subblock.in_pending above, but for RLE.
- uint32_t in_pending;
- } rle;
-
- struct {
- enum {
- SUB_NONE,
- SUB_SET,
- SUB_RUN,
- SUB_FLUSH,
- SUB_FINISH,
- SUB_END_MARKER,
- } mode;
-
- /// This is a copy of options->allow_subfilters. We use
- /// this to verify that the application doesn't change
- /// the value of allow_subfilters.
- bool allow;
-
- /// When this is true, application is not allowed to modify
- /// options->subblock_mode. We may still modify it here.
- bool mode_locked;
-
- /// True if we have encoded at least one byte of data with
- /// the Subfilter.
- bool got_input;
-
- /// Track the amount of input available once
- /// LZMA_SUBFILTER_FINISH has been enabled.
- /// This is needed for sanity checking (kind
- /// of duplicating what common/code.c does).
- size_t in_avail;
-
- /// Buffer for the Filter Flags field written after
- /// the `Set Subfilter' indicator.
- uint8_t *flags;
-
- /// Size of Filter Flags field.
- uint32_t flags_size;
-
- /// Pointers to Subfilter.
- lzma_next_coder subcoder;
-
- } subfilter;
-
- /// Temporary buffer used when we are not the last filter in the chain.
- struct {
- size_t pos;
- size_t size;
- uint8_t buffer[LZMA_BUFFER_SIZE];
- } temp;
-};
-
-
-/// \brief Aligns the output buffer
-///
-/// Aligns the output buffer so that after skew bytes the output position is
-/// a multiple of coder->alignment.multiple.
-static bool
-subblock_align(lzma_coder *coder, uint8_t *restrict out,
- size_t *restrict out_pos, size_t out_size,
- size_t chunk_size, uint32_t skew)
-{
- assert(*out_pos < out_size);
-
- // Fix the alignment only if it makes sense at least a little.
- if (chunk_size >= MIN_CHUNK_SIZE_FOR_ALIGN) {
- const uint32_t target = coder->alignment.in_pos
- % coder->alignment.multiple;
-
- while ((coder->alignment.out_pos + skew)
- % coder->alignment.multiple != target) {
- // Zero indicates padding.
- write_byte(0x00);
-
- // Check if output buffer got full and indicate it to
- // the caller.
- if (*out_pos == out_size)
- return true;
- }
- }
-
- // Output buffer is not full.
- return false;
-}
-
-
-/// \brief Checks if buffer contains repeated data
-///
-/// \param needle Buffer containing a single repeat chunk
-/// \param needle_size Size of needle in bytes
-/// \param buf Buffer to search for repeated needles
-/// \param buf_chunks Buffer size is buf_chunks * needle_size.
-///
-/// \return True if the whole buf is filled with repeated needles.
-///
-static bool
-is_repeating(const uint8_t *restrict needle, size_t needle_size,
- const uint8_t *restrict buf, size_t buf_chunks)
-{
- while (buf_chunks-- != 0) {
- if (memcmp(buf, needle, needle_size) != 0)
- return false;
-
- buf += needle_size;
- }
-
- return true;
-}
-
-
-/// \brief Optimizes the repeating style and updates coder->sequence
-static void
-subblock_rle_flush(lzma_coder *coder)
-{
- // The Subblock decoder can use memset() when the size of the data
- // being repeated is one byte, so we check if the RLE buffer is
- // filled with a single repeating byte.
- if (coder->rle.size > 1) {
- const uint8_t b = coder->rle.buffer[0];
- size_t i = 0;
- while (true) {
- if (coder->rle.buffer[i] != b)
- break;
-
- if (++i == coder->rle.size) {
- // TODO Integer overflow check maybe,
- // although this needs at least 2**63 bytes
- // of input until it gets triggered...
- coder->rle.count *= coder->rle.size;
- coder->rle.size = 1;
- break;
- }
- }
- }
-
- if (coder->rle.count == 1) {
- // The buffer should be repeated only once. It is
- // waste of space to use Repeating Data. Instead,
- // write a regular Data Subblock. See SEQ_RLE_COUNT_0
- // in subblock_buffer() for more info.
- coder->tmp = coder->rle.size - 1;
- } else if (coder->rle.count > REPEAT_COUNT_MAX) {
- // There's so much to repeat that it doesn't fit into
- // 28-bit integer. We will write two or more Subblocks
- // of type Repeating Data.
- coder->tmp = REPEAT_COUNT_MAX - 1;
- } else {
- coder->tmp = coder->rle.count - 1;
- }
-
- coder->sequence = SEQ_RLE_COUNT_0;
-
- return;
-}
-
-
-/// \brief Resizes coder->subblock.data for a new size limit
-static lzma_ret
-subblock_data_size(lzma_coder *coder, lzma_allocator *allocator,
- size_t new_limit)
-{
- // Verify that the new limit is valid.
- if (new_limit < LZMA_SUBBLOCK_DATA_SIZE_MIN
- || new_limit > LZMA_SUBBLOCK_DATA_SIZE_MAX)
- return LZMA_OPTIONS_ERROR;
-
- // Ff the new limit is different than the previous one, we need
- // to reallocate the data buffer.
- if (new_limit != coder->subblock.limit) {
- lzma_free(coder->subblock.data, allocator);
- coder->subblock.data = lzma_alloc(new_limit, allocator);
- if (coder->subblock.data == NULL)
- return LZMA_MEM_ERROR;
- }
-
- coder->subblock.limit = new_limit;
-
- return LZMA_OK;
-}
-
-
-static lzma_ret
-subblock_buffer(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *restrict in, size_t *restrict in_pos,
- size_t in_size, uint8_t *restrict out,
- size_t *restrict out_pos, size_t out_size, lzma_action action)
-{
- // Changing allow_subfilter is not allowed.
- if (coder->options != NULL && coder->subfilter.allow
- != coder->options->allow_subfilters)
- return LZMA_PROG_ERROR;
-
- // Check if we need to do something special with the Subfilter.
- if (coder->subfilter.allow) {
- assert(coder->options != NULL);
-
- // See if subfilter_mode has been changed.
- switch (coder->options->subfilter_mode) {
- case LZMA_SUBFILTER_NONE:
- if (coder->subfilter.mode != SUB_NONE)
- return LZMA_PROG_ERROR;
- break;
-
- case LZMA_SUBFILTER_SET:
- if (coder->subfilter.mode_locked
- || coder->subfilter.mode != SUB_NONE)
- return LZMA_PROG_ERROR;
-
- coder->subfilter.mode = SUB_SET;
- coder->subfilter.got_input = false;
-
- if (coder->sequence == SEQ_FILL)
- coder->sequence = SEQ_FLUSH;
-
- break;
-
- case LZMA_SUBFILTER_RUN:
- if (coder->subfilter.mode != SUB_RUN)
- return LZMA_PROG_ERROR;
-
- break;
-
- case LZMA_SUBFILTER_FINISH: {
- const size_t in_avail = in_size - *in_pos;
-
- if (coder->subfilter.mode == SUB_RUN) {
- if (coder->subfilter.mode_locked)
- return LZMA_PROG_ERROR;
-
- coder->subfilter.mode = SUB_FINISH;
- coder->subfilter.in_avail = in_avail;
-
- } else if (coder->subfilter.mode != SUB_FINISH
- || coder->subfilter.in_avail
- != in_avail) {
- return LZMA_PROG_ERROR;
- }
-
- break;
- }
-
- default:
- return LZMA_OPTIONS_ERROR;
- }
-
- // If we are sync-flushing or finishing, the application may
- // no longer change subfilter_mode. Note that this check is
- // done after checking the new subfilter_mode above; this
- // way the application may e.g. set LZMA_SUBFILTER_SET and
- // LZMA_SYNC_FLUSH at the same time, but it cannot modify
- // subfilter_mode on the later lzma_code() calls before
- // we have returned LZMA_STREAM_END.
- if (action != LZMA_RUN)
- coder->subfilter.mode_locked = true;
- }
-
- // Main loop
- while (*out_pos < out_size)
- switch (coder->sequence) {
- case SEQ_FILL:
- // Grab the new Subblock Data Size and reallocate the buffer.
- if (coder->subblock.size == 0 && coder->options != NULL
- && coder->options->subblock_data_size
- != coder->subblock.limit)
- return_if_error(subblock_data_size(coder,
- allocator, coder->options
- ->subblock_data_size));
-
- if (coder->subfilter.mode == SUB_NONE) {
- assert(coder->subfilter.subcoder.code == NULL);
-
- // No Subfilter is enabled, just copy the data as is.
- coder->subblock.in_pending += lzma_bufcpy(
- in, in_pos, in_size,
- coder->subblock.data,
- &coder->subblock.size,
- coder->subblock.limit);
-
- // If we ran out of input before the whole buffer
- // was filled, return to application.
- if (coder->subblock.size < coder->subblock.limit
- && action == LZMA_RUN)
- return LZMA_OK;
-
- } else {
- assert(coder->options->subfilter_mode
- != LZMA_SUBFILTER_SET);
-
- // Using LZMA_FINISH automatically toggles
- // LZMA_SUBFILTER_FINISH.
- //
- // NOTE: It is possible that application had set
- // LZMA_SUBFILTER_SET and LZMA_FINISH at the same
- // time. In that case it is possible that we will
- // cycle to LZMA_SUBFILTER_RUN, LZMA_SUBFILTER_FINISH,
- // and back to LZMA_SUBFILTER_NONE in a single
- // Subblock encoder function call.
- if (action == LZMA_FINISH) {
- coder->options->subfilter_mode
- = LZMA_SUBFILTER_FINISH;
- coder->subfilter.mode = SUB_FINISH;
- }
-
- const size_t in_start = *in_pos;
-
- const lzma_ret ret = coder->subfilter.subcoder.code(
- coder->subfilter.subcoder.coder,
- allocator, in, in_pos, in_size,
- coder->subblock.data,
- &coder->subblock.size,
- coder->subblock.limit,
- coder->subfilter.mode == SUB_FINISH
- ? LZMA_FINISH : action);
-
- const size_t in_used = *in_pos - in_start;
- coder->subblock.in_pending += in_used;
- if (in_used > 0)
- coder->subfilter.got_input = true;
-
- coder->subfilter.in_avail = in_size - *in_pos;
-
- if (ret == LZMA_STREAM_END) {
- // All currently available input must have
- // been processed.
- assert(*in_pos == in_size);
-
- // Flush now. Even if coder->subblock.size
- // happened to be zero, we still need to go
- // to SEQ_FLUSH to possibly finish RLE or
- // write the Subfilter Unset indicator.
- coder->sequence = SEQ_FLUSH;
-
- if (coder->subfilter.mode == SUB_RUN) {
- // Flushing with Subfilter enabled.
- assert(action == LZMA_SYNC_FLUSH);
- coder->subfilter.mode = SUB_FLUSH;
- break;
- }
-
- // Subfilter finished its job.
- assert(coder->subfilter.mode == SUB_FINISH
- || action == LZMA_FINISH);
-
- // At least one byte of input must have been
- // encoded with the Subfilter. This is
- // required by the file format specification.
- if (!coder->subfilter.got_input)
- return LZMA_PROG_ERROR;
-
- // We don't strictly need to do this, but
- // doing it sounds like a good idea, because
- // otherwise the Subfilter's memory could be
- // left allocated for long time, and would
- // just waste memory.
- lzma_next_end(&coder->subfilter.subcoder,
- allocator);
-
- // We need to flush the currently buffered
- // data and write Unset Subfilter marker.
- // Note that we cannot set
- // coder->options->subfilter_mode to
- // LZMA_SUBFILTER_NONE yet, because we
- // haven't written the Unset Subfilter
- // marker yet.
- coder->subfilter.mode = SUB_END_MARKER;
- coder->sequence = SEQ_FLUSH;
- break;
- }
-
- // Return if we couldn't fill the buffer or
- // if an error occurred.
- if (coder->subblock.size < coder->subblock.limit
- || ret != LZMA_OK)
- return ret;
- }
-
- coder->sequence = SEQ_FLUSH;
-
- // SEQ_FILL doesn't produce any output so falling through
- // to SEQ_FLUSH is safe.
- assert(*out_pos < out_size);
-
- // Fall through
-
- case SEQ_FLUSH:
- if (coder->options != NULL) {
- // Update the alignment variable.
- coder->alignment.multiple = coder->options->alignment;
- if (coder->alignment.multiple
- < LZMA_SUBBLOCK_ALIGNMENT_MIN
- || coder->alignment.multiple
- > LZMA_SUBBLOCK_ALIGNMENT_MAX)
- return LZMA_OPTIONS_ERROR;
-
- // Run-length encoder
- //
- // First check if there is some data pending and we
- // have an obvious need to flush it immediately.
- if (coder->rle.count > 0
- && (coder->rle.size
- != coder->options->rle
- || coder->subblock.size
- % coder->rle.size)) {
- subblock_rle_flush(coder);
- break;
- }
-
- // Grab the (possibly new) RLE chunk size and
- // validate it.
- coder->rle.size = coder->options->rle;
- if (coder->rle.size > LZMA_SUBBLOCK_RLE_MAX)
- return LZMA_OPTIONS_ERROR;
-
- if (coder->subblock.size != 0
- && coder->rle.size
- != LZMA_SUBBLOCK_RLE_OFF
- && coder->subblock.size
- % coder->rle.size == 0) {
-
- // Initialize coder->rle.buffer if we don't
- // have RLE already running.
- if (coder->rle.count == 0)
- memcpy(coder->rle.buffer,
- coder->subblock.data,
- coder->rle.size);
-
- // Test if coder->subblock.data is repeating.
- // If coder->rle.count would overflow, we
- // force flushing. Forced flushing shouldn't
- // really happen in real-world situations.
- const size_t count = coder->subblock.size
- / coder->rle.size;
- if (UINT64_MAX - count > coder->rle.count
- && is_repeating(
- coder->rle.buffer,
- coder->rle.size,
- coder->subblock.data,
- count)) {
- coder->rle.count += count;
- coder->rle.in_pending += coder
- ->subblock.in_pending;
- coder->subblock.in_pending = 0;
- coder->subblock.size = 0;
-
- } else if (coder->rle.count > 0) {
- // It's not repeating or at least not
- // with the same byte sequence as the
- // earlier Subblock Data buffers. We
- // have some data pending in the RLE
- // buffer already, so do a flush.
- // Once flushed, we will check again
- // if the Subblock Data happens to
- // contain a different repeating
- // sequence.
- subblock_rle_flush(coder);
- break;
- }
- }
- }
-
- // If we now have some data left in coder->subblock, the RLE
- // buffer is empty and we must write a regular Subblock Data.
- if (coder->subblock.size > 0) {
- assert(coder->rle.count == 0);
- coder->tmp = coder->subblock.size - 1;
- coder->sequence = SEQ_DATA_SIZE_0;
- break;
- }
-
- // Check if we should enable Subfilter.
- if (coder->subfilter.mode == SUB_SET) {
- if (coder->rle.count > 0)
- subblock_rle_flush(coder);
- else
- coder->sequence = SEQ_SUBFILTER_INIT;
- break;
- }
-
- // Check if we have just finished Subfiltering.
- if (coder->subfilter.mode == SUB_END_MARKER) {
- if (coder->rle.count > 0) {
- subblock_rle_flush(coder);
- break;
- }
-
- coder->options->subfilter_mode = LZMA_SUBFILTER_NONE;
- coder->subfilter.mode = SUB_NONE;
-
- write_byte(0x50);
- if (*out_pos == out_size)
- return LZMA_OK;
- }
-
- // Check if we have already written everything.
- if (action != LZMA_RUN && *in_pos == in_size
- && (coder->subfilter.mode == SUB_NONE
- || coder->subfilter.mode == SUB_FLUSH)) {
- if (coder->rle.count > 0) {
- subblock_rle_flush(coder);
- break;
- }
-
- if (action == LZMA_SYNC_FLUSH) {
- if (coder->subfilter.mode == SUB_FLUSH)
- coder->subfilter.mode = SUB_RUN;
-
- coder->subfilter.mode_locked = false;
- coder->sequence = SEQ_FILL;
-
- } else {
- assert(action == LZMA_FINISH);
-
- // Write EOPM.
- // NOTE: No need to use write_byte() here
- // since we are finishing.
- out[*out_pos] = 0x10;
- ++*out_pos;
- }
-
- return LZMA_STREAM_END;
- }
-
- // Otherwise we have more work to do.
- coder->sequence = SEQ_FILL;
- break;
-
- case SEQ_RLE_COUNT_0:
- assert(coder->rle.count > 0);
-
- if (coder->rle.count == 1) {
- // The buffer should be repeated only once. Fix
- // the alignment and write the first byte of
- // Subblock Type `Data'.
- if (subblock_align(coder, out, out_pos, out_size,
- coder->rle.size, ALIGN_SKEW_DATA))
- return LZMA_OK;
-
- write_byte(0x20 | (coder->tmp & 0x0F));
-
- } else {
- // We have something to actually repeat, which should
- // mean that it takes less space with run-length
- // encoding.
- if (subblock_align(coder, out, out_pos, out_size,
- coder->rle.size,
- ALIGN_SKEW_REPEATING_DATA))
- return LZMA_OK;
-
- write_byte(0x30 | (coder->tmp & 0x0F));
- }
-
- // NOTE: If we have to write more than one Repeating Data
- // due to rle.count > REPEAT_COUNT_MAX, the subsequent
- // Repeating Data Subblocks may get wrong alignment, because
- // we add rle.in_pending to alignment.in_pos at once instead
- // of adding only as much as this particular Repeating Data
- // consumed input data. Correct alignment is always restored
- // after all the required Repeating Data Subblocks have been
- // written. This problem occurs in such a weird cases that
- // it's not worth fixing.
- coder->alignment.out_pos += coder->rle.size;
- coder->alignment.in_pos += coder->rle.in_pending;
- coder->rle.in_pending = 0;
-
- coder->sequence = SEQ_RLE_COUNT_1;
- break;
-
- case SEQ_RLE_COUNT_1:
- write_byte(coder->tmp >> 4);
- coder->sequence = SEQ_RLE_COUNT_2;
- break;
-
- case SEQ_RLE_COUNT_2:
- write_byte(coder->tmp >> 12);
- coder->sequence = SEQ_RLE_COUNT_3;
- break;
-
- case SEQ_RLE_COUNT_3:
- write_byte(coder->tmp >> 20);
-
- // Again, see if we are writing regular Data or Repeating Data.
- // In the former case, we skip SEQ_RLE_SIZE.
- if (coder->rle.count == 1)
- coder->sequence = SEQ_RLE_DATA;
- else
- coder->sequence = SEQ_RLE_SIZE;
-
- if (coder->rle.count > REPEAT_COUNT_MAX)
- coder->rle.count -= REPEAT_COUNT_MAX;
- else
- coder->rle.count = 0;
-
- break;
-
- case SEQ_RLE_SIZE:
- assert(coder->rle.size >= LZMA_SUBBLOCK_RLE_MIN);
- assert(coder->rle.size <= LZMA_SUBBLOCK_RLE_MAX);
- write_byte(coder->rle.size - 1);
- coder->sequence = SEQ_RLE_DATA;
- break;
-
- case SEQ_RLE_DATA:
- lzma_bufcpy(coder->rle.buffer, &coder->pos, coder->rle.size,
- out, out_pos, out_size);
- if (coder->pos < coder->rle.size)
- return LZMA_OK;
-
- coder->pos = 0;
- coder->sequence = SEQ_FLUSH;
- break;
-
- case SEQ_DATA_SIZE_0:
- // We need four bytes for the Size field.
- if (subblock_align(coder, out, out_pos, out_size,
- coder->subblock.size, ALIGN_SKEW_DATA))
- return LZMA_OK;
-
- coder->alignment.out_pos += coder->subblock.size;
- coder->alignment.in_pos += coder->subblock.in_pending;
- coder->subblock.in_pending = 0;
-
- write_byte(0x20 | (coder->tmp & 0x0F));
- coder->sequence = SEQ_DATA_SIZE_1;
- break;
-
- case SEQ_DATA_SIZE_1:
- write_byte(coder->tmp >> 4);
- coder->sequence = SEQ_DATA_SIZE_2;
- break;
-
- case SEQ_DATA_SIZE_2:
- write_byte(coder->tmp >> 12);
- coder->sequence = SEQ_DATA_SIZE_3;
- break;
-
- case SEQ_DATA_SIZE_3:
- write_byte(coder->tmp >> 20);
- coder->sequence = SEQ_DATA;
- break;
-
- case SEQ_DATA:
- lzma_bufcpy(coder->subblock.data, &coder->pos,
- coder->subblock.size, out, out_pos, out_size);
- if (coder->pos < coder->subblock.size)
- return LZMA_OK;
-
- coder->subblock.size = 0;
- coder->pos = 0;
- coder->sequence = SEQ_FLUSH;
- break;
-
- case SEQ_SUBFILTER_INIT: {
- assert(coder->subblock.size == 0);
- assert(coder->subblock.in_pending == 0);
- assert(coder->rle.count == 0);
- assert(coder->rle.in_pending == 0);
- assert(coder->subfilter.mode == SUB_SET);
- assert(coder->options != NULL);
-
- // There must be a filter specified.
- if (coder->options->subfilter_options.id == LZMA_VLI_UNKNOWN)
- return LZMA_OPTIONS_ERROR;
-
- // Initialize a raw encoder to work as a Subfilter.
- lzma_filter options[2];
- options[0] = coder->options->subfilter_options;
- options[1].id = LZMA_VLI_UNKNOWN;
-
- return_if_error(lzma_raw_encoder_init(
- &coder->subfilter.subcoder, allocator,
- options));
-
- // Encode the Filter Flags field into a buffer. This should
- // never fail since we have already successfully initialized
- // the Subfilter itself. Check it still, and return
- // LZMA_PROG_ERROR instead of whatever the ret would say.
- lzma_ret ret = lzma_filter_flags_size(
- &coder->subfilter.flags_size, options);
- assert(ret == LZMA_OK);
- if (ret != LZMA_OK)
- return LZMA_PROG_ERROR;
-
- coder->subfilter.flags = lzma_alloc(
- coder->subfilter.flags_size, allocator);
- if (coder->subfilter.flags == NULL)
- return LZMA_MEM_ERROR;
-
- // Now we have a big-enough buffer. Encode the Filter Flags.
- // Like above, this should never fail.
- size_t dummy = 0;
- ret = lzma_filter_flags_encode(options, coder->subfilter.flags,
- &dummy, coder->subfilter.flags_size);
- assert(ret == LZMA_OK);
- assert(dummy == coder->subfilter.flags_size);
- if (ret != LZMA_OK || dummy != coder->subfilter.flags_size)
- return LZMA_PROG_ERROR;
-
- // Write a Subblock indicating a new Subfilter.
- write_byte(0x40);
-
- coder->options->subfilter_mode = LZMA_SUBFILTER_RUN;
- coder->subfilter.mode = SUB_RUN;
- coder->alignment.out_pos += coder->subfilter.flags_size;
- coder->sequence = SEQ_SUBFILTER_FLAGS;
-
- // It is safe to fall through because SEQ_SUBFILTER_FLAGS
- // uses lzma_bufcpy() which doesn't write unless there is
- // output space.
- }
-
- // Fall through
-
- case SEQ_SUBFILTER_FLAGS:
- // Copy the Filter Flags to the output stream.
- lzma_bufcpy(coder->subfilter.flags, &coder->pos,
- coder->subfilter.flags_size,
- out, out_pos, out_size);
- if (coder->pos < coder->subfilter.flags_size)
- return LZMA_OK;
-
- lzma_free(coder->subfilter.flags, allocator);
- coder->subfilter.flags = NULL;
-
- coder->pos = 0;
- coder->sequence = SEQ_FILL;
- break;
-
- default:
- return LZMA_PROG_ERROR;
- }
-
- return LZMA_OK;
-}
-
-
-static lzma_ret
-subblock_encode(lzma_coder *coder, lzma_allocator *allocator,
- const uint8_t *restrict in, size_t *restrict in_pos,
- size_t in_size, uint8_t *restrict out,
- size_t *restrict out_pos, size_t out_size, lzma_action action)
-{
- if (coder->next.code == NULL)
- return subblock_buffer(coder, allocator, in, in_pos, in_size,
- out, out_pos, out_size, action);
-
- while (*out_pos < out_size
- && (*in_pos < in_size || action != LZMA_RUN)) {
- if (!coder->next_finished
- && coder->temp.pos == coder->temp.size) {
- coder->temp.pos = 0;
- coder->temp.size = 0;
-
- const lzma_ret ret = coder->next.code(coder->next.coder,
- allocator, in, in_pos, in_size,
- coder->temp.buffer, &coder->temp.size,
- LZMA_BUFFER_SIZE, action);
- if (ret == LZMA_STREAM_END) {
- assert(action != LZMA_RUN);
- coder->next_finished = true;
- } else if (coder->temp.size == 0 || ret != LZMA_OK) {
- return ret;
- }
- }
-
- const lzma_ret ret = subblock_buffer(coder, allocator,
- coder->temp.buffer, &coder->temp.pos,
- coder->temp.size, out, out_pos, out_size,
- coder->next_finished ? LZMA_FINISH : LZMA_RUN);
- if (ret == LZMA_STREAM_END) {
- assert(action != LZMA_RUN);
- assert(coder->next_finished);
- return LZMA_STREAM_END;
- }
-
- if (ret != LZMA_OK)
- return ret;
- }
-
- return LZMA_OK;
-}
-
-
-static void
-subblock_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
-{
- lzma_next_end(&coder->next, allocator);
- lzma_next_end(&coder->subfilter.subcoder, allocator);
- lzma_free(coder->subblock.data, allocator);
- lzma_free(coder->subfilter.flags, allocator);
- lzma_free(coder, allocator);
- return;
-}
-
-
-extern lzma_ret
-lzma_subblock_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
- const lzma_filter_info *filters)
-{
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
- return LZMA_MEM_ERROR;
-
- next->code = &subblock_encode;
- next->end = &subblock_encoder_end;
-
- next->coder->next = LZMA_NEXT_CODER_INIT;
- next->coder->subblock.data = NULL;
- next->coder->subblock.limit = 0;
- next->coder->subfilter.subcoder = LZMA_NEXT_CODER_INIT;
- } else {
- lzma_next_end(&next->coder->subfilter.subcoder,
- allocator);
- lzma_free(next->coder->subfilter.flags, allocator);
- }
-
- next->coder->subfilter.flags = NULL;
-
- next->coder->next_finished = false;
- next->coder->sequence = SEQ_FILL;
- next->coder->options = filters[0].options;
- next->coder->pos = 0;
-
- next->coder->alignment.in_pos = 0;
- next->coder->alignment.out_pos = 0;
- next->coder->subblock.size = 0;
- next->coder->subblock.in_pending = 0;
- next->coder->rle.count = 0;
- next->coder->rle.in_pending = 0;
- next->coder->subfilter.mode = SUB_NONE;
- next->coder->subfilter.mode_locked = false;
-
- next->coder->temp.pos = 0;
- next->coder->temp.size = 0;
-
- // Grab some values from the options structure if it is available.
- size_t subblock_size_limit;
- if (next->coder->options != NULL) {
- if (next->coder->options->alignment
- < LZMA_SUBBLOCK_ALIGNMENT_MIN
- || next->coder->options->alignment
- > LZMA_SUBBLOCK_ALIGNMENT_MAX) {
- subblock_encoder_end(next->coder, allocator);
- return LZMA_OPTIONS_ERROR;
- }
- next->coder->alignment.multiple
- = next->coder->options->alignment;
- next->coder->subfilter.allow
- = next->coder->options->allow_subfilters;
- subblock_size_limit = next->coder->options->subblock_data_size;
- } else {
- next->coder->alignment.multiple
- = LZMA_SUBBLOCK_ALIGNMENT_DEFAULT;
- next->coder->subfilter.allow = false;
- subblock_size_limit = LZMA_SUBBLOCK_DATA_SIZE_DEFAULT;
- }
-
- return_if_error(subblock_data_size(next->coder, allocator,
- subblock_size_limit));
-
- return lzma_next_filter_init(
- &next->coder->next, allocator, filters + 1);
-}
diff --git a/src/liblzma/subblock/subblock_encoder.h b/src/liblzma/subblock/subblock_encoder.h
deleted file mode 100644
index ddbfe64bce87..000000000000
--- a/src/liblzma/subblock/subblock_encoder.h
+++ /dev/null
@@ -1,21 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-/// \file subblock_encoder.h
-/// \brief Encoder of the Subblock filter
-//
-// Author: Lasse Collin
-//
-// This file has been put into the public domain.
-// You can do whatever you want with this file.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef LZMA_SUBBLOCK_ENCODER_H
-#define LZMA_SUBBLOCK_ENCODER_H
-
-#include "common.h"
-
-extern lzma_ret lzma_subblock_encoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, const lzma_filter_info *filters);
-
-#endif
diff --git a/src/lzmainfo/lzmainfo.1 b/src/lzmainfo/lzmainfo.1
index ef736a6c6622..f2b93b4c643f 100644
--- a/src/lzmainfo/lzmainfo.1
+++ b/src/lzmainfo/lzmainfo.1
@@ -4,9 +4,9 @@
.\" This file has been put into the public domain.
.\" You can do whatever you want with this file.
.\"
-.TH LZMAINFO 1 "2009-08-13" "Tukaani" "XZ Utils"
+.TH LZMAINFO 1 "2010-09-27" "Tukaani" "XZ Utils"
.SH NAME
-lzmainfo \- show infomation stored in the .lzma file header
+lzmainfo \- show information stored in the .lzma file header
.SH SYNOPSIS
.B lzmainfo
.RB [ \-\-help ]
@@ -16,10 +16,12 @@ lzmainfo \- show infomation stored in the .lzma file header
.B lzmainfo
shows information stored in the
.B .lzma
-file header. It reads the first 13 bytes from the specified
+file header.
+It reads the first 13 bytes from the specified
.IR file ,
decodes the header, and prints it to standard output in human
-readable format. If no
+readable format.
+If no
.I files
are given or
.I file
@@ -27,16 +29,19 @@ is
.BR \- ,
standard input is read.
.PP
-Usually the most interesting information is the uncompressed size and
-the dictionary size. Uncompressed size can be shown only if the file is
-in the non-streamed
+Usually the most interesting information is
+the uncompressed size and the dictionary size.
+Uncompressed size can be shown only if
+the file is in the non-streamed
.B .lzma
-format variant. The amount of memory required to decompress the file is
+format variant.
+The amount of memory required to decompress the file is
a few dozen kilobytes plus the dictionary size.
.PP
.B lzmainfo
-is included in XZ Utils primarily for backward compatibility with LZMA Utils.
-.SH EXIT STATUS
+is included in XZ Utils primarily for
+backward compatibility with LZMA Utils.
+.SH "EXIT STATUS"
.TP
.B 0
All is good.
@@ -51,5 +56,5 @@ while the correct suffix would be
.B MiB
(2^20 bytes).
This is to keep the output compatible with LZMA Utils.
-.SH SEE ALSO
+.SH "SEE ALSO"
.BR xz (1)
diff --git a/src/lzmainfo/lzmainfo.c b/src/lzmainfo/lzmainfo.c
index af8e66cc8f99..3100dc631af2 100644
--- a/src/lzmainfo/lzmainfo.c
+++ b/src/lzmainfo/lzmainfo.c
@@ -20,6 +20,11 @@
#include "tuklib_progname.h"
#include "tuklib_exit.h"
+#ifdef TUKLIB_DOSLIKE
+# include <fcntl.h>
+# include <io.h>
+#endif
+
static void lzma_attribute((noreturn))
help(void)
@@ -43,7 +48,7 @@ _("Usage: %s [--help] [--version] [FILE]...\n"
static void lzma_attribute((noreturn))
version(void)
{
- puts("lzmainfo (" PACKAGE_NAME ") " PACKAGE_VERSION);
+ puts("lzmainfo (" PACKAGE_NAME ") " LZMA_VERSION_STRING);
tuklib_exit(EXIT_SUCCESS, EXIT_FAILURE, true);
}
@@ -150,7 +155,7 @@ lzmainfo(const char *name, FILE *f)
lzma_options_lzma *opt = filter.options;
printf("\nDictionary size: "
- "%u MB (2^%u bytes)\n"
+ "%" PRIu32 " MB (2^%" PRIu32 " bytes)\n"
"Literal context bits (lc): %" PRIu32 "\n"
"Literal pos bits (lp): %" PRIu32 "\n"
"Number of pos bits (pb): %" PRIu32 "\n",
@@ -171,6 +176,10 @@ main(int argc, char **argv)
parse_args(argc, argv);
+#ifdef TUKLIB_DOSLIKE
+ setmode(fileno(stdin), O_BINARY);
+#endif
+
int ret = EXIT_SUCCESS;
// We print empty lines around the output only when reading from
diff --git a/src/xz/args.c b/src/xz/args.c
index f37f80244b4e..4bd84a0c141c 100644
--- a/src/xz/args.c
+++ b/src/xz/args.c
@@ -25,15 +25,40 @@ bool opt_robot = false;
// We don't modify or free() this, but we need to assign it in some
// non-const pointers.
-const char *stdin_filename = "(stdin)";
+const char stdin_filename[] = "(stdin)";
+
+
+/// Parse and set the memory usage limit for compression and/or decompression.
+static void
+parse_memlimit(const char *name, const char *name_percentage, char *str,
+ bool set_compress, bool set_decompress)
+{
+ bool is_percentage = false;
+ uint64_t value;
+
+ const size_t len = strlen(str);
+ if (len > 0 && str[len - 1] == '%') {
+ str[len - 1] = '\0';
+ is_percentage = true;
+ value = str_to_uint64(name_percentage, str, 1, 100);
+ } else {
+ // On 32-bit systems, SIZE_MAX would make more sense than
+ // UINT64_MAX. But use UINT64_MAX still so that scripts
+ // that assume > 4 GiB values don't break.
+ value = str_to_uint64(name, str, 0, UINT64_MAX);
+ }
+
+ hardware_memlimit_set(
+ value, set_compress, set_decompress, is_percentage);
+ return;
+}
static void
parse_real(args_info *args, int argc, char **argv)
{
enum {
- OPT_SUBBLOCK = INT_MIN,
- OPT_X86,
+ OPT_X86 = INT_MIN,
OPT_POWERPC,
OPT_IA64,
OPT_ARM,
@@ -46,6 +71,9 @@ parse_real(args_info *args, int argc, char **argv)
OPT_NO_SPARSE,
OPT_FILES,
OPT_FILES0,
+ OPT_MEM_COMPRESS,
+ OPT_MEM_DECOMPRESS,
+ OPT_NO_ADJUST,
OPT_INFO_MEMORY,
OPT_ROBOT,
};
@@ -75,7 +103,11 @@ parse_real(args_info *args, int argc, char **argv)
// Basic compression settings
{ "format", required_argument, NULL, 'F' },
{ "check", required_argument, NULL, 'C' },
- { "memory", required_argument, NULL, 'M' },
+ { "memlimit-compress", required_argument, NULL, OPT_MEM_COMPRESS },
+ { "memlimit-decompress", required_argument, NULL, OPT_MEM_DECOMPRESS },
+ { "memlimit", required_argument, NULL, 'M' },
+ { "memory", required_argument, NULL, 'M' }, // Old alias
+ { "no-adjust", no_argument, NULL, OPT_NO_ADJUST },
{ "threads", required_argument, NULL, 'T' },
{ "extreme", no_argument, NULL, 'e' },
@@ -92,7 +124,6 @@ parse_real(args_info *args, int argc, char **argv)
{ "armthumb", optional_argument, NULL, OPT_ARMTHUMB },
{ "sparc", optional_argument, NULL, OPT_SPARC },
{ "delta", optional_argument, NULL, OPT_DELTA },
- { "subblock", optional_argument, NULL, OPT_SUBBLOCK },
// Other options
{ "quiet", no_argument, NULL, 'q' },
@@ -104,7 +135,7 @@ parse_real(args_info *args, int argc, char **argv)
{ "long-help", no_argument, NULL, 'H' },
{ "version", no_argument, NULL, 'V' },
- { NULL, 0, NULL, 0 }
+ { NULL, 0, NULL, 0 }
};
int c;
@@ -118,28 +149,25 @@ parse_real(args_info *args, int argc, char **argv)
coder_set_preset(c - '0');
break;
- // --memory
- case 'M': {
- // Support specifying the limit as a percentage of
- // installed physical RAM.
- size_t len = strlen(optarg);
- if (len > 0 && optarg[len - 1] == '%') {
- optarg[len - 1] = '\0';
- hardware_memlimit_set_percentage(
- str_to_uint64(
- "memory%", optarg, 1, 100));
- } else {
- // On 32-bit systems, SIZE_MAX would make more
- // sense than UINT64_MAX. But use UINT64_MAX
- // still so that scripts that assume > 4 GiB
- // values don't break.
- hardware_memlimit_set(str_to_uint64(
- "memory", optarg,
- 0, UINT64_MAX));
- }
+ // --memlimit-compress
+ case OPT_MEM_COMPRESS:
+ parse_memlimit("memlimit-compress",
+ "memlimit-compress%", optarg,
+ true, false);
+ break;
+ // --memlimit-decompress
+ case OPT_MEM_DECOMPRESS:
+ parse_memlimit("memlimit-decompress",
+ "memlimit-decompress%", optarg,
+ false, true);
+ break;
+
+ // --memlimit
+ case 'M':
+ parse_memlimit("memlimit", "memlimit%", optarg,
+ true, true);
break;
- }
// --suffix
case 'S':
@@ -179,7 +207,7 @@ parse_real(args_info *args, int argc, char **argv)
// --info-memory
case OPT_INFO_MEMORY:
// This doesn't return.
- message_memlimit();
+ hardware_memlimit_show();
// --help
case 'h':
@@ -234,11 +262,6 @@ parse_real(args_info *args, int argc, char **argv)
// Filter setup
- case OPT_SUBBLOCK:
- coder_add_filter(LZMA_FILTER_SUBBLOCK,
- options_subblock(optarg));
- break;
-
case OPT_X86:
coder_add_filter(LZMA_FILTER_X86,
options_bcj(optarg));
@@ -374,6 +397,10 @@ parse_real(args_info *args, int argc, char **argv)
break;
+ case OPT_NO_ADJUST:
+ opt_auto_adjust = false;
+ break;
+
default:
message_try_help();
tuklib_exit(E_ERROR, E_ERROR, false);
@@ -385,9 +412,9 @@ parse_real(args_info *args, int argc, char **argv)
static void
-parse_environment(args_info *args, char *argv0)
+parse_environment(args_info *args, char *argv0, const char *varname)
{
- char *env = getenv("XZ_OPT");
+ char *env = getenv(varname);
if (env == NULL)
return;
@@ -413,10 +440,11 @@ parse_environment(args_info *args, char *argv0)
// Keep argc small enough to fit into a singed int
// and to keep it usable for memory allocation.
- if (++argc == MIN(INT_MAX, SIZE_MAX / sizeof(char *)))
+ if (++argc == my_min(
+ INT_MAX, SIZE_MAX / sizeof(char *)))
message_fatal(_("The environment variable "
- "XZ_OPT contains too many "
- "arguments"));
+ "%s contains too many "
+ "arguments"), varname);
}
}
@@ -504,8 +532,9 @@ args_parse(args_info *args, int argc, char **argv)
}
}
- // First the flags from environment
- parse_environment(args, argv[0]);
+ // First the flags from the environment
+ parse_environment(args, argv[0], "XZ_DEFAULTS");
+ parse_environment(args, argv[0], "XZ_OPT");
// Then from the command line
parse_real(args, argc, argv);
diff --git a/src/xz/args.h b/src/xz/args.h
index ac5959b52bad..b23f4ef12c92 100644
--- a/src/xz/args.h
+++ b/src/xz/args.h
@@ -37,6 +37,6 @@ extern bool opt_keep_original;
// extern bool opt_recursive;
extern bool opt_robot;
-extern const char *stdin_filename;
+extern const char stdin_filename[];
extern void args_parse(args_info *args, int argc, char **argv);
diff --git a/src/xz/coder.c b/src/xz/coder.c
index 2ee0c704b2cf..5182dddc3ff2 100644
--- a/src/xz/coder.c
+++ b/src/xz/coder.c
@@ -22,8 +22,8 @@ enum coder_init_ret {
enum operation_mode opt_mode = MODE_COMPRESS;
-
enum format_type opt_format = FORMAT_AUTO;
+bool opt_auto_adjust = true;
/// Stream used to communicate with liblzma
@@ -42,14 +42,6 @@ static size_t filters_count = 0;
/// Number of the preset (0-9)
static size_t preset_number = 6;
-/// True if we should auto-adjust the compression settings to use less memory
-/// if memory usage limit is too low for the original settings.
-static bool auto_adjust = true;
-
-/// Indicate if no preset has been explicitly given. In that case, if we need
-/// to auto-adjust for lower memory usage, we won't print a warning.
-static bool preset_default = true;
-
/// If a preset is used (no custom filter chain) and preset_extreme is true,
/// a significantly slower compression is used to achieve slightly better
/// compression ratio.
@@ -75,7 +67,15 @@ extern void
coder_set_preset(size_t new_preset)
{
preset_number = new_preset;
- preset_default = false;
+
+ // Setting a preset makes us forget a possibly defined custom
+ // filter chain.
+ while (filters_count > 0) {
+ --filters_count;
+ free(filters[filters_count].options);
+ filters[filters_count].options = NULL;
+ }
+
return;
}
@@ -145,8 +145,6 @@ coder_set_compression_settings(void)
? LZMA_FILTER_LZMA1 : LZMA_FILTER_LZMA2;
filters[0].options = &opt_lzma;
filters_count = 1;
- } else {
- preset_default = false;
}
// Terminate the filter options array.
@@ -168,12 +166,12 @@ coder_set_compression_settings(void)
"with the .xz format"));
// Print the selected filter chain.
- message_filters(V_DEBUG, filters);
+ message_filters_show(V_DEBUG, filters);
// If using --format=raw, we can be decoding. The memusage function
// also validates the filter chain and the options used for the
// filters.
- const uint64_t memory_limit = hardware_memlimit_get();
+ const uint64_t memory_limit = hardware_memlimit_get(opt_mode);
uint64_t memory_usage;
if (opt_mode == MODE_COMPRESS)
memory_usage = lzma_raw_encoder_memusage(filters);
@@ -186,12 +184,19 @@ coder_set_compression_settings(void)
// Print memory usage info before possible dictionary
// size auto-adjusting.
message_mem_needed(V_DEBUG, memory_usage);
+ if (opt_mode == MODE_COMPRESS) {
+ const uint64_t decmem = lzma_raw_decoder_memusage(filters);
+ if (decmem != UINT64_MAX)
+ message(V_DEBUG, _("Decompression will need "
+ "%s MiB of memory."), uint64_to_str(
+ round_up_to_mib(decmem), 0));
+ }
if (memory_usage > memory_limit) {
// If --no-auto-adjust was used or we didn't find LZMA1 or
// LZMA2 as the last filter, give an error immediately.
// --format=raw implies --no-auto-adjust.
- if (!auto_adjust || opt_format == FORMAT_RAW)
+ if (!opt_auto_adjust || opt_format == FORMAT_RAW)
memlimit_too_small(memory_usage);
assert(opt_mode == MODE_COMPRESS);
@@ -239,18 +244,15 @@ coder_set_compression_settings(void)
}
// Tell the user that we decreased the dictionary size.
- // However, omit the message if no preset or custom chain
- // was given. FIXME: Always warn?
- if (!preset_default)
- message(V_WARNING, _("Adjusted LZMA%c dictionary size "
- "from %s MiB to %s MiB to not exceed "
- "the memory usage limit of %s MiB"),
- filters[i].id == LZMA_FILTER_LZMA2
- ? '2' : '1',
- uint64_to_str(orig_dict_size >> 20, 0),
- uint64_to_str(opt->dict_size >> 20, 1),
- uint64_to_str(round_up_to_mib(
- memory_limit), 2));
+ message(V_WARNING, _("Adjusted LZMA%c dictionary size "
+ "from %s MiB to %s MiB to not exceed "
+ "the memory usage limit of %s MiB"),
+ filters[i].id == LZMA_FILTER_LZMA2
+ ? '2' : '1',
+ uint64_to_str(orig_dict_size >> 20, 0),
+ uint64_to_str(opt->dict_size >> 20, 1),
+ uint64_to_str(round_up_to_mib(
+ memory_limit), 2));
}
/*
@@ -410,12 +412,14 @@ coder_init(file_pair *pair)
case FORMAT_XZ:
ret = lzma_stream_decoder(&strm,
- hardware_memlimit_get(), flags);
+ hardware_memlimit_get(
+ MODE_DECOMPRESS), flags);
break;
case FORMAT_LZMA:
ret = lzma_alone_decoder(&strm,
- hardware_memlimit_get());
+ hardware_memlimit_get(
+ MODE_DECOMPRESS));
break;
case FORMAT_RAW:
diff --git a/src/xz/coder.h b/src/xz/coder.h
index 0d3af6ad4494..4626466f39ce 100644
--- a/src/xz/coder.h
+++ b/src/xz/coder.h
@@ -37,6 +37,10 @@ extern enum operation_mode opt_mode;
/// This is set in args.c.
extern enum format_type opt_format;
+/// If true, the compression settings are automatically adjusted down if
+/// they exceed the memory usage limit.
+extern bool opt_auto_adjust;
+
/// Set the integrity check type used when compressing
extern void coder_set_check(lzma_check check);
diff --git a/src/xz/file_io.c b/src/xz/file_io.c
index a78002eba559..6e24c58a945c 100644
--- a/src/xz/file_io.c
+++ b/src/xz/file_io.c
@@ -370,15 +370,16 @@ io_open_src_real(file_pair *pair)
}
#ifdef O_NOFOLLOW
- // Give an understandable error message in if reason
+ // Give an understandable error message if the reason
// for failing was that the file was a symbolic link.
//
// Note that at least Linux, OpenBSD, Solaris, and Darwin
- // use ELOOP to indicate if O_NOFOLLOW was the reason
+ // use ELOOP to indicate that O_NOFOLLOW was the reason
// that open() failed. Because there may be
// directories in the pathname, ELOOP may occur also
// because of a symlink loop in the directory part.
- // So ELOOP doesn't tell us what actually went wrong.
+ // So ELOOP doesn't tell us what actually went wrong,
+ // and this stupidity went into POSIX-1.2008 too.
//
// FreeBSD associates EMLINK with O_NOFOLLOW and
// Tru64 uses ENOTSUP. We use these directly here
@@ -396,10 +397,10 @@ io_open_src_real(file_pair *pair)
was_symlink = true;
# elif defined(__NetBSD__)
- // FIXME? As of 2008-11-20, NetBSD doesn't document what
- // errno is used with O_NOFOLLOW. It seems to be EFTYPE,
- // but since it isn't documented, it may be wrong to rely
- // on it here.
+ // As of 2010-09-05, NetBSD doesn't document what errno is
+ // used with O_NOFOLLOW. It is EFTYPE though, and I
+ // understood that is very unlikely to change even though
+ // it is undocumented.
if (errno == EFTYPE)
was_symlink = true;
diff --git a/src/xz/hardware.c b/src/xz/hardware.c
index 74742fcec870..a4733c27e118 100644
--- a/src/xz/hardware.c
+++ b/src/xz/hardware.c
@@ -18,8 +18,11 @@
/// the --threads=NUM command line option.
static uint32_t threadlimit;
-/// Memory usage limit
-static uint64_t memlimit;
+/// Memory usage limit for compression
+static uint64_t memlimit_compress;
+
+/// Memory usage limit for decompression
+static uint64_t memlimit_decompress;
/// Total amount of physical RAM
static uint64_t total_ram;
@@ -49,50 +52,79 @@ hardware_threadlimit_get(void)
extern void
-hardware_memlimit_set(uint64_t new_memlimit)
+hardware_memlimit_set(uint64_t new_memlimit,
+ bool set_compress, bool set_decompress, bool is_percentage)
{
- if (new_memlimit != 0) {
- memlimit = new_memlimit;
- } else {
- // The default depends on the amount of RAM but so that
- // on "low-memory" systems the relative limit is higher
- // to make it more likely that files created with "xz -9"
- // will still decompress without overriding the limit
- // manually.
- //
- // If 40 % of RAM is 80 MiB or more, use 40 % of RAM as
- // the limit.
- memlimit = 40 * total_ram / 100;
- if (memlimit < UINT64_C(80) * 1024 * 1024) {
- // If 80 % of RAM is less than 80 MiB,
- // use 80 % of RAM as the limit.
- memlimit = 80 * total_ram / 100;
- if (memlimit > UINT64_C(80) * 1024 * 1024) {
- // Otherwise use 80 MiB as the limit.
- memlimit = UINT64_C(80) * 1024 * 1024;
- }
- }
+ if (is_percentage) {
+ assert(new_memlimit > 0);
+ assert(new_memlimit <= 100);
+ new_memlimit = (uint32_t)new_memlimit * total_ram / 100;
}
+ if (set_compress)
+ memlimit_compress = new_memlimit;
+
+ if (set_decompress)
+ memlimit_decompress = new_memlimit;
+
return;
}
-extern void
-hardware_memlimit_set_percentage(uint32_t percentage)
+extern uint64_t
+hardware_memlimit_get(enum operation_mode mode)
{
- assert(percentage > 0);
- assert(percentage <= 100);
+ // Zero is a special value that indicates the default. Currently
+ // the default simply disables the limit. Once there is threading
+ // support, this might be a little more complex, because there will
+ // probably be a special case where a user asks for "optimal" number
+ // of threads instead of a specific number (this might even become
+ // the default mode). Each thread may use a significant amount of
+ // memory. When there are no memory usage limits set, we need some
+ // default soft limit for calculating the "optimal" number of
+ // threads.
+ const uint64_t memlimit = mode == MODE_COMPRESS
+ ? memlimit_compress : memlimit_decompress;
+ return memlimit != 0 ? memlimit : UINT64_MAX;
+}
+
+
+/// Helper for hardware_memlimit_show() to print one human-readable info line.
+static void
+memlimit_show(const char *str, uint64_t value)
+{
+ // The memory usage limit is considered to be disabled if value
+ // is 0 or UINT64_MAX. This might get a bit more complex once there
+ // is threading support. See the comment in hardware_memlimit_get().
+ if (value == 0 || value == UINT64_MAX)
+ printf("%s %s\n", str, _("Disabled"));
+ else
+ printf("%s %s MiB (%s B)\n", str,
+ uint64_to_str(round_up_to_mib(value), 0),
+ uint64_to_str(value, 1));
- memlimit = percentage * total_ram / 100;
return;
}
-extern uint64_t
-hardware_memlimit_get(void)
+extern void
+hardware_memlimit_show(void)
{
- return memlimit;
+ if (opt_robot) {
+ printf("%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\n", total_ram,
+ memlimit_compress, memlimit_decompress);
+ } else {
+ // TRANSLATORS: Test with "xz --info-memory" to see if
+ // the alignment looks nice.
+ memlimit_show(_("Total amount of physical memory (RAM): "),
+ total_ram);
+ memlimit_show(_("Memory usage limit for compression: "),
+ memlimit_compress);
+ memlimit_show(_("Memory usage limit for decompression: "),
+ memlimit_decompress);
+ }
+
+ tuklib_exit(E_SUCCESS, E_ERROR, message_verbosity_get() != V_SILENT);
}
@@ -106,7 +138,7 @@ hardware_init(void)
total_ram = (uint64_t)(ASSUME_RAM) * 1024 * 1024;
// Set the defaults.
- hardware_memlimit_set(0);
+ hardware_memlimit_set(0, true, true, false);
hardware_threadlimit_set(0);
return;
}
diff --git a/src/xz/hardware.h b/src/xz/hardware.h
index b2cf34cbc8cd..bed952b07d23 100644
--- a/src/xz/hardware.h
+++ b/src/xz/hardware.h
@@ -23,13 +23,16 @@ extern void hardware_threadlimit_set(uint32_t threadlimit);
extern uint32_t hardware_threadlimit_get(void);
-/// Set custom memory usage limit. This is used for both encoding and
-/// decoding. Zero indicates resetting the limit back to defaults.
-extern void hardware_memlimit_set(uint64_t memlimit);
-
-/// Set custom memory usage limit as a percentage of installed RAM.
-/// The percentage must be in the range [1, 100].
-extern void hardware_memlimit_set_percentage(uint32_t percentage);
-
-/// Get the current memory usage limit.
-extern uint64_t hardware_memlimit_get(void);
+/// Set the memory usage limit. There are separate limits for compression
+/// and decompression (the latter includes also --list), one or both can
+/// be set with a single call to this function. Zero indicates resetting
+/// the limit back to the defaults. The limit can also be set as a percentage
+/// of installed RAM; the percentage must be in the range [1, 100].
+extern void hardware_memlimit_set(uint64_t new_memlimit,
+ bool set_compress, bool set_decompress, bool is_percentage);
+
+/// Get the current memory usage limit for compression or decompression.
+extern uint64_t hardware_memlimit_get(enum operation_mode mode);
+
+/// Display the amount of RAM and memory usage limits and exit.
+extern void hardware_memlimit_show(void) lzma_attribute((noreturn));
diff --git a/src/xz/list.c b/src/xz/list.c
index 91707b918b47..1c93718b1382 100644
--- a/src/xz/list.c
+++ b/src/xz/list.c
@@ -14,6 +14,84 @@
#include "tuklib_integer.h"
+/// Information about a .xz file
+typedef struct {
+ /// Combined Index of all Streams in the file
+ lzma_index *idx;
+
+ /// Total amount of Stream Padding
+ uint64_t stream_padding;
+
+ /// Highest memory usage so far
+ uint64_t memusage_max;
+
+ /// True if all Blocks so far have Compressed Size and
+ /// Uncompressed Size fields
+ bool all_have_sizes;
+
+} xz_file_info;
+
+#define XZ_FILE_INFO_INIT { NULL, 0, 0, true }
+
+
+/// Information about a .xz Block
+typedef struct {
+ /// Size of the Block Header
+ uint32_t header_size;
+
+ /// A few of the Block Flags as a string
+ char flags[3];
+
+ /// Size of the Compressed Data field in the Block
+ lzma_vli compressed_size;
+
+ /// Decoder memory usage for this Block
+ uint64_t memusage;
+
+ /// The filter chain of this Block in human-readable form
+ char filter_chain[FILTERS_STR_SIZE];
+
+} block_header_info;
+
+
+/// Check ID to string mapping
+static const char check_names[LZMA_CHECK_ID_MAX + 1][12] = {
+ // TRANSLATORS: Indicates that there is no integrity check.
+ // This string is used in tables, so the width must not
+ // exceed ten columns with a fixed-width font.
+ N_("None"),
+ "CRC32",
+ // TRANSLATORS: Indicates that integrity check name is not known,
+ // but the Check ID is known (here 2). This and other "Unknown-N"
+ // strings are used in tables, so the width must not exceed ten
+ // columns with a fixed-width font. It's OK to omit the dash if
+ // you need space for one extra letter, but don't use spaces.
+ N_("Unknown-2"),
+ N_("Unknown-3"),
+ "CRC64",
+ N_("Unknown-5"),
+ N_("Unknown-6"),
+ N_("Unknown-7"),
+ N_("Unknown-8"),
+ N_("Unknown-9"),
+ "SHA-256",
+ N_("Unknown-11"),
+ N_("Unknown-12"),
+ N_("Unknown-13"),
+ N_("Unknown-14"),
+ N_("Unknown-15"),
+};
+
+/// Buffer size for get_check_names(). This may be a bit ridiculous,
+/// but at least it's enough if some language needs many multibyte chars.
+#define CHECKS_STR_SIZE 1024
+
+
+/// Value of the Check field as hexadecimal string.
+/// This is set by parse_check_value().
+static char check_value[2 * LZMA_CHECK_SIZE_MAX + 1];
+
+
/// Totals that are displayed if there was more than one file.
/// The "files" counter is also used in print_info_adv() to show
/// the file number.
@@ -23,15 +101,17 @@ static struct {
uint64_t blocks;
uint64_t compressed_size;
uint64_t uncompressed_size;
+ uint64_t stream_padding;
+ uint64_t memusage_max;
uint32_t checks;
-} totals = { 0, 0, 0, 0, 0, 0 };
+ bool all_have_sizes;
+} totals = { 0, 0, 0, 0, 0, 0, 0, 0, true };
/// \brief Parse the Index(es) from the given .xz file
///
-/// \param idx If decoding is successful, *idx will be set to point
-/// to lzma_index containing the decoded information.
-/// On error, *idx is not modified.
+/// \param xfi Pointer to structure where the decoded information
+/// is stored.
/// \param pair Input file
///
/// \return On success, false is returned. On error, true is returned.
@@ -40,7 +120,7 @@ static struct {
// takes a callback function to parse the Index(es) from a .xz file to make
// it easy for applications.
static bool
-parse_indexes(lzma_index **idx, file_pair *pair)
+parse_indexes(xz_file_info *xfi, file_pair *pair)
{
if (pair->src_st.st_size <= 0) {
message_error(_("%s: File is empty"), pair->src_name);
@@ -135,7 +215,7 @@ parse_indexes(lzma_index **idx, file_pair *pair)
pos -= index_size;
// See how much memory we can use for decoding this Index.
- uint64_t memlimit = hardware_memlimit_get();
+ uint64_t memlimit = hardware_memlimit_get(MODE_LIST);
uint64_t memused = 0;
if (combined_index != NULL) {
memused = lzma_index_memused(combined_index);
@@ -156,7 +236,7 @@ parse_indexes(lzma_index **idx, file_pair *pair)
do {
// Don't give the decoder more input than the
// Index size.
- strm.avail_in = MIN(IO_BUFFER_SIZE, index_size);
+ strm.avail_in = my_min(IO_BUFFER_SIZE, index_size);
if (io_pread(pair, &buf, strm.avail_in, pos))
goto error;
@@ -257,12 +337,14 @@ parse_indexes(lzma_index **idx, file_pair *pair)
combined_index = this_index;
this_index = NULL;
+ xfi->stream_padding += stream_padding;
+
} while (pos > 0);
lzma_end(&strm);
// All OK. Make combined_index available to the caller.
- *idx = combined_index;
+ xfi->idx = combined_index;
return false;
error:
@@ -274,9 +356,196 @@ error:
}
+/// \brief Parse the Block Header
+///
+/// The result is stored into *bhi. The caller takes care of initializing it.
+///
+/// \return False on success, true on error.
+static bool
+parse_block_header(file_pair *pair, const lzma_index_iter *iter,
+ block_header_info *bhi, xz_file_info *xfi)
+{
+#if IO_BUFFER_SIZE < LZMA_BLOCK_HEADER_SIZE_MAX
+# error IO_BUFFER_SIZE < LZMA_BLOCK_HEADER_SIZE_MAX
+#endif
+
+ // Get the whole Block Header with one read, but don't read past
+ // the end of the Block (or even its Check field).
+ const uint32_t size = my_min(iter->block.total_size
+ - lzma_check_size(iter->stream.flags->check),
+ LZMA_BLOCK_HEADER_SIZE_MAX);
+ io_buf buf;
+ if (io_pread(pair, &buf, size, iter->block.compressed_file_offset))
+ return true;
+
+ // Zero would mean Index Indicator and thus not a valid Block.
+ if (buf.u8[0] == 0)
+ goto data_error;
+
+ lzma_block block;
+ lzma_filter filters[LZMA_FILTERS_MAX + 1];
+
+ // Initialize the pointers so that they can be passed to free().
+ for (size_t i = 0; i < ARRAY_SIZE(filters); ++i)
+ filters[i].options = NULL;
+
+ // Initialize the block structure and decode Block Header Size.
+ block.version = 0;
+ block.check = iter->stream.flags->check;
+ block.filters = filters;
+
+ block.header_size = lzma_block_header_size_decode(buf.u8[0]);
+ if (block.header_size > size)
+ goto data_error;
+
+ // Decode the Block Header.
+ switch (lzma_block_header_decode(&block, NULL, buf.u8)) {
+ case LZMA_OK:
+ break;
+
+ case LZMA_OPTIONS_ERROR:
+ message_error("%s: %s", pair->src_name,
+ message_strm(LZMA_OPTIONS_ERROR));
+ return true;
+
+ case LZMA_DATA_ERROR:
+ goto data_error;
+
+ default:
+ message_bug();
+ }
+
+ // Check the Block Flags. These must be done before calling
+ // lzma_block_compressed_size(), because it overwrites
+ // block.compressed_size.
+ bhi->flags[0] = block.compressed_size != LZMA_VLI_UNKNOWN
+ ? 'c' : '-';
+ bhi->flags[1] = block.uncompressed_size != LZMA_VLI_UNKNOWN
+ ? 'u' : '-';
+ bhi->flags[2] = '\0';
+
+ // Collect information if all Blocks have both Compressed Size
+ // and Uncompressed Size fields. They can be useful e.g. for
+ // multi-threaded decompression so it can be useful to know it.
+ xfi->all_have_sizes &= block.compressed_size != LZMA_VLI_UNKNOWN
+ && block.uncompressed_size != LZMA_VLI_UNKNOWN;
+
+ // Validate or set block.compressed_size.
+ switch (lzma_block_compressed_size(&block,
+ iter->block.unpadded_size)) {
+ case LZMA_OK:
+ break;
+
+ case LZMA_DATA_ERROR:
+ goto data_error;
+
+ default:
+ message_bug();
+ }
+
+ // Copy the known sizes.
+ bhi->header_size = block.header_size;
+ bhi->compressed_size = block.compressed_size;
+
+ // Calculate the decoder memory usage and update the maximum
+ // memory usage of this Block.
+ bhi->memusage = lzma_raw_decoder_memusage(filters);
+ if (xfi->memusage_max < bhi->memusage)
+ xfi->memusage_max = bhi->memusage;
+
+ // Convert the filter chain to human readable form.
+ message_filters_to_str(bhi->filter_chain, filters, false);
+
+ // Free the memory allocated by lzma_block_header_decode().
+ for (size_t i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i)
+ free(filters[i].options);
+
+ return false;
+
+data_error:
+ // Show the error message.
+ message_error("%s: %s", pair->src_name,
+ message_strm(LZMA_DATA_ERROR));
+
+ // Free the memory allocated by lzma_block_header_decode().
+ // This is truly needed only if we get here after a succcessful
+ // call to lzma_block_header_decode() but it doesn't hurt to
+ // always do it.
+ for (size_t i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i)
+ free(filters[i].options);
+
+ return true;
+}
+
+
+/// \brief Parse the Check field and put it into check_value[]
+///
+/// \return False on success, true on error.
+static bool
+parse_check_value(file_pair *pair, const lzma_index_iter *iter)
+{
+ // Don't read anything from the file if there is no integrity Check.
+ if (iter->stream.flags->check == LZMA_CHECK_NONE) {
+ snprintf(check_value, sizeof(check_value), "---");
+ return false;
+ }
+
+ // Locate and read the Check field.
+ const uint32_t size = lzma_check_size(iter->stream.flags->check);
+ const off_t offset = iter->block.compressed_file_offset
+ + iter->block.total_size - size;
+ io_buf buf;
+ if (io_pread(pair, &buf, size, offset))
+ return true;
+
+ // CRC32 and CRC64 are in little endian. Guess that all the future
+ // 32-bit and 64-bit Check values are little endian too. It shouldn't
+ // be a too big problem if this guess is wrong.
+ if (size == 4)
+ snprintf(check_value, sizeof(check_value),
+ "%08" PRIx32, conv32le(buf.u32[0]));
+ else if (size == 8)
+ snprintf(check_value, sizeof(check_value),
+ "%016" PRIx64, conv64le(buf.u64[0]));
+ else
+ for (size_t i = 0; i < size; ++i)
+ snprintf(check_value + i * 2, 3, "%02x", buf.u8[i]);
+
+ return false;
+}
+
+
+/// \brief Parse detailed information about a Block
+///
+/// Since this requires seek(s), listing information about all Blocks can
+/// be slow.
+///
+/// \param pair Input file
+/// \param iter Location of the Block whose Check value should
+/// be printed.
+/// \param bhi Pointer to structure where to store the information
+/// about the Block Header field.
+///
+/// \return False on success, true on error. If an error occurs,
+/// the error message is printed too so the caller doesn't
+/// need to worry about that.
+static bool
+parse_details(file_pair *pair, const lzma_index_iter *iter,
+ block_header_info *bhi, xz_file_info *xfi)
+{
+ if (parse_block_header(pair, iter, bhi, xfi))
+ return true;
+
+ if (parse_check_value(pair, iter))
+ return true;
+
+ return false;
+}
+
+
/// \brief Get the compression ratio
///
-/// This has slightly different format than that is used by in message.c.
+/// This has slightly different format than that is used in message.c.
static const char *
get_ratio(uint64_t compressed_size, uint64_t uncompressed_size)
{
@@ -288,47 +557,30 @@ get_ratio(uint64_t compressed_size, uint64_t uncompressed_size)
if (ratio > 9.999)
return "---";
- static char buf[6];
+ static char buf[16];
snprintf(buf, sizeof(buf), "%.3f", ratio);
return buf;
}
-static const char check_names[LZMA_CHECK_ID_MAX + 1][12] = {
- "None",
- "CRC32",
- "Unknown-2",
- "Unknown-3",
- "CRC64",
- "Unknown-5",
- "Unknown-6",
- "Unknown-7",
- "Unknown-8",
- "Unknown-9",
- "SHA-256",
- "Unknown-11",
- "Unknown-12",
- "Unknown-13",
- "Unknown-14",
- "Unknown-15",
-};
-
-
/// \brief Get a comma-separated list of Check names
///
+/// The check names are translated with gettext except when in robot mode.
+///
+/// \param buf Buffer to hold the resulting string
/// \param checks Bit mask of Checks to print
/// \param space_after_comma
/// It's better to not use spaces in table-like listings,
/// but in more verbose formats a space after a comma
/// is good for readability.
-static const char *
-get_check_names(uint32_t checks, bool space_after_comma)
+static void
+get_check_names(char buf[CHECKS_STR_SIZE],
+ uint32_t checks, bool space_after_comma)
{
assert(checks != 0);
- static char buf[sizeof(check_names)];
char *pos = buf;
- size_t left = sizeof(buf);
+ size_t left = CHECKS_STR_SIZE;
const char *sep = space_after_comma ? ", " : ",";
bool comma = false;
@@ -336,96 +588,70 @@ get_check_names(uint32_t checks, bool space_after_comma)
for (size_t i = 0; i <= LZMA_CHECK_ID_MAX; ++i) {
if (checks & (UINT32_C(1) << i)) {
my_snprintf(&pos, &left, "%s%s",
- comma ? sep : "", check_names[i]);
+ comma ? sep : "",
+ opt_robot ? check_names[i]
+ : _(check_names[i]));
comma = true;
}
}
- return buf;
+ return;
}
-/// \brief Read the Check value from the .xz file and print it
-///
-/// Since this requires a seek, listing all Check values for all Blocks can
-/// be slow.
-///
-/// \param pair Input file
-/// \param iter Location of the Block whose Check value should
-/// be printed.
-///
-/// \return False on success, true on I/O error.
static bool
-print_check_value(file_pair *pair, const lzma_index_iter *iter)
-{
- // Don't read anything from the file if there is no integrity Check.
- if (iter->stream.flags->check == LZMA_CHECK_NONE) {
- printf("---");
- return false;
- }
-
- // Locate and read the Check field.
- const uint32_t size = lzma_check_size(iter->stream.flags->check);
- const off_t offset = iter->block.compressed_file_offset
- + iter->block.total_size - size;
- io_buf buf;
- if (io_pread(pair, &buf, size, offset))
- return true;
-
- // CRC32 and CRC64 are in little endian. Guess that all the future
- // 32-bit and 64-bit Check values are little endian too. It shouldn't
- // be a too big problem if this guess is wrong.
- if (size == 4) {
- printf("%08" PRIx32, conv32le(buf.u32[0]));
- } else if (size == 8) {
- printf("%016" PRIx64, conv64le(buf.u64[0]));
- } else {
- for (size_t i = 0; i < size; ++i)
- printf("%02x", buf.u8[i]);
- }
-
- return false;
-}
-
-
-static void
-print_info_basic(const lzma_index *idx, file_pair *pair)
+print_info_basic(const xz_file_info *xfi, file_pair *pair)
{
static bool headings_displayed = false;
if (!headings_displayed) {
headings_displayed = true;
- // TRANSLATORS: These are column titles. From Strms (Streams)
+ // TRANSLATORS: These are column headings. From Strms (Streams)
// to Ratio, the columns are right aligned. Check and Filename
// are left aligned. If you need longer words, it's OK to
- // use two lines here. Test with xz --list.
+ // use two lines here. Test with "xz -l foo.xz".
puts(_("Strms Blocks Compressed Uncompressed Ratio "
"Check Filename"));
}
- printf("%5s %7s %11s %11s %5s %-7s %s\n",
- uint64_to_str(lzma_index_stream_count(idx), 0),
- uint64_to_str(lzma_index_block_count(idx), 1),
- uint64_to_nicestr(lzma_index_file_size(idx),
- NICESTR_B, NICESTR_TIB, false, 2),
- uint64_to_nicestr(lzma_index_uncompressed_size(idx),
- NICESTR_B, NICESTR_TIB, false, 3),
- get_ratio(lzma_index_file_size(idx),
- lzma_index_uncompressed_size(idx)),
- get_check_names(lzma_index_checks(idx), false),
- pair->src_name);
+ char checks[CHECKS_STR_SIZE];
+ get_check_names(checks, lzma_index_checks(xfi->idx), false);
+
+ const char *cols[7] = {
+ uint64_to_str(lzma_index_stream_count(xfi->idx), 0),
+ uint64_to_str(lzma_index_block_count(xfi->idx), 1),
+ uint64_to_nicestr(lzma_index_file_size(xfi->idx),
+ NICESTR_B, NICESTR_TIB, false, 2),
+ uint64_to_nicestr(lzma_index_uncompressed_size(xfi->idx),
+ NICESTR_B, NICESTR_TIB, false, 3),
+ get_ratio(lzma_index_file_size(xfi->idx),
+ lzma_index_uncompressed_size(xfi->idx)),
+ checks,
+ pair->src_name,
+ };
+ printf("%*s %*s %*s %*s %*s %-*s %s\n",
+ tuklib_mbstr_fw(cols[0], 5), cols[0],
+ tuklib_mbstr_fw(cols[1], 7), cols[1],
+ tuklib_mbstr_fw(cols[2], 11), cols[2],
+ tuklib_mbstr_fw(cols[3], 11), cols[3],
+ tuklib_mbstr_fw(cols[4], 5), cols[4],
+ tuklib_mbstr_fw(cols[5], 7), cols[5],
+ cols[6]);
- return;
+ return false;
}
static void
print_adv_helper(uint64_t stream_count, uint64_t block_count,
uint64_t compressed_size, uint64_t uncompressed_size,
- uint32_t checks)
+ uint32_t checks, uint64_t stream_padding)
{
- printf(_(" Stream count: %s\n"),
+ char checks_str[CHECKS_STR_SIZE];
+ get_check_names(checks_str, checks, true);
+
+ printf(_(" Streams: %s\n"),
uint64_to_str(stream_count, 0));
- printf(_(" Block count: %s\n"),
+ printf(_(" Blocks: %s\n"),
uint64_to_str(block_count, 0));
printf(_(" Compressed size: %s\n"),
uint64_to_nicestr(compressed_size,
@@ -435,129 +661,237 @@ print_adv_helper(uint64_t stream_count, uint64_t block_count,
NICESTR_B, NICESTR_TIB, true, 0));
printf(_(" Ratio: %s\n"),
get_ratio(compressed_size, uncompressed_size));
- printf(_(" Check: %s\n"),
- get_check_names(checks, true));
+ printf(_(" Check: %s\n"), checks_str);
+ printf(_(" Stream padding: %s\n"),
+ uint64_to_nicestr(stream_padding,
+ NICESTR_B, NICESTR_TIB, true, 0));
return;
}
-static void
-print_info_adv(const lzma_index *idx, file_pair *pair)
+static bool
+print_info_adv(xz_file_info *xfi, file_pair *pair)
{
// Print the overall information.
- print_adv_helper(lzma_index_stream_count(idx),
- lzma_index_block_count(idx),
- lzma_index_file_size(idx),
- lzma_index_uncompressed_size(idx),
- lzma_index_checks(idx));
-
- // TODO: The rest of this function needs some work. Currently
- // the offsets are not printed, which could be useful even when
- // printed in a less accurate format. On the other hand, maybe
- // this should print the information with exact byte values,
- // or maybe there should be at least an option to do that.
+ print_adv_helper(lzma_index_stream_count(xfi->idx),
+ lzma_index_block_count(xfi->idx),
+ lzma_index_file_size(xfi->idx),
+ lzma_index_uncompressed_size(xfi->idx),
+ lzma_index_checks(xfi->idx),
+ xfi->stream_padding);
+
+ // Size of the biggest Check. This is used to calculate the width
+ // of the CheckVal field. The table would get insanely wide if
+ // we always reserved space for 64-byte Check (128 chars as hex).
+ uint32_t check_max = 0;
+
+ // Print information about the Streams.
//
- // We could also display some other info. E.g. it could be useful
- // to quickly see how big is the biggest Block (uncompressed size)
- // and if all Blocks have Compressed Size and Uncompressed Size
- // fields present, which can be used e.g. for multithreaded
- // decompression.
-
- // Avoid printing Stream and Block lists when they wouldn't be useful.
- bool show_blocks = false;
- if (lzma_index_stream_count(idx) > 1) {
- puts(_(" Streams:"));
- puts(_(" Number Blocks Compressed "
- "Uncompressed Ratio Check"));
-
- lzma_index_iter iter;
- lzma_index_iter_init(&iter, idx);
- while (!lzma_index_iter_next(&iter, LZMA_INDEX_ITER_STREAM)) {
- if (iter.stream.block_count > 1)
- show_blocks = true;
+ // TRANSLATORS: The second line is column headings. All except
+ // Check are right aligned; Check is left aligned. Test with
+ // "xz -lv foo.xz".
+ puts(_(" Streams:\n Stream Blocks"
+ " CompOffset UncompOffset"
+ " CompSize UncompSize Ratio"
+ " Check Padding"));
+
+ lzma_index_iter iter;
+ lzma_index_iter_init(&iter, xfi->idx);
+
+ while (!lzma_index_iter_next(&iter, LZMA_INDEX_ITER_STREAM)) {
+ const char *cols1[4] = {
+ uint64_to_str(iter.stream.number, 0),
+ uint64_to_str(iter.stream.block_count, 1),
+ uint64_to_str(iter.stream.compressed_offset, 2),
+ uint64_to_str(iter.stream.uncompressed_offset, 3),
+ };
+ printf(" %*s %*s %*s %*s ",
+ tuklib_mbstr_fw(cols1[0], 6), cols1[0],
+ tuklib_mbstr_fw(cols1[1], 9), cols1[1],
+ tuklib_mbstr_fw(cols1[2], 15), cols1[2],
+ tuklib_mbstr_fw(cols1[3], 15), cols1[3]);
+
+ const char *cols2[5] = {
+ uint64_to_str(iter.stream.compressed_size, 0),
+ uint64_to_str(iter.stream.uncompressed_size, 1),
+ get_ratio(iter.stream.compressed_size,
+ iter.stream.uncompressed_size),
+ _(check_names[iter.stream.flags->check]),
+ uint64_to_str(iter.stream.padding, 2),
+ };
+ printf("%*s %*s %*s %-*s %*s\n",
+ tuklib_mbstr_fw(cols2[0], 15), cols2[0],
+ tuklib_mbstr_fw(cols2[1], 15), cols2[1],
+ tuklib_mbstr_fw(cols2[2], 5), cols2[2],
+ tuklib_mbstr_fw(cols2[3], 10), cols2[3],
+ tuklib_mbstr_fw(cols2[4], 7), cols2[4]);
+
+ // Update the maximum Check size.
+ if (lzma_check_size(iter.stream.flags->check) > check_max)
+ check_max = lzma_check_size(iter.stream.flags->check);
+ }
- printf(" %8s %10s %11s %11s %5s %s\n",
- uint64_to_str(iter.stream.number, 0),
- uint64_to_str(iter.stream.block_count, 1),
- uint64_to_nicestr(
- iter.stream.compressed_size,
- NICESTR_B, NICESTR_TIB, false, 2),
- uint64_to_nicestr(
- iter.stream.uncompressed_size,
- NICESTR_B, NICESTR_TIB, false, 3),
- get_ratio(iter.stream.compressed_size,
- iter.stream.uncompressed_size),
- check_names[iter.stream.flags->check]);
+ // Cache the verbosity level to a local variable.
+ const bool detailed = message_verbosity_get() >= V_DEBUG;
+
+ // Information collected from Block Headers
+ block_header_info bhi;
+
+ // Print information about the Blocks but only if there is
+ // at least one Block.
+ if (lzma_index_block_count(xfi->idx) > 0) {
+ // Calculate the width of the CheckVal field.
+ const int checkval_width = my_max(8, 2 * check_max);
+
+ // TRANSLATORS: The second line is column headings. All
+ // except Check are right aligned; Check is left aligned.
+ printf(_(" Blocks:\n Stream Block"
+ " CompOffset UncompOffset"
+ " TotalSize UncompSize Ratio Check"));
+
+ if (detailed) {
+ // TRANSLATORS: These are additional column headings
+ // for the most verbose listing mode. CheckVal
+ // (Check value), Flags, and Filters are left aligned.
+ // Header (Block Header Size), CompSize, and MemUsage
+ // are right aligned. %*s is replaced with 0-120
+ // spaces to make the CheckVal column wide enough.
+ // Test with "xz -lvv foo.xz".
+ printf(_(" CheckVal %*s Header Flags "
+ "CompSize MemUsage Filters"),
+ checkval_width - 8, "");
}
- }
- if (show_blocks || lzma_index_block_count(idx)
- > lzma_index_stream_count(idx)
- || message_verbosity_get() >= V_DEBUG) {
- puts(_(" Blocks:"));
- // FIXME: Number in Stream/file, which one is better?
- puts(_(" Stream Number Compressed "
- "Uncompressed Ratio Check"));
+ putchar('\n');
- lzma_index_iter iter;
- lzma_index_iter_init(&iter, idx);
+ lzma_index_iter_init(&iter, xfi->idx);
+
+ // Iterate over the Blocks.
while (!lzma_index_iter_next(&iter, LZMA_INDEX_ITER_BLOCK)) {
- printf(" %8s %10s %11s %11s %5s %-7s",
+ if (detailed && parse_details(pair, &iter, &bhi, xfi))
+ return true;
+
+ const char *cols1[4] = {
uint64_to_str(iter.stream.number, 0),
- uint64_to_str(iter.block.number_in_stream, 1),
- uint64_to_nicestr(iter.block.total_size,
- NICESTR_B, NICESTR_TIB, false, 2),
- uint64_to_nicestr(
- iter.block.uncompressed_size,
- NICESTR_B, NICESTR_TIB, false, 3),
+ uint64_to_str(
+ iter.block.number_in_stream, 1),
+ uint64_to_str(
+ iter.block.compressed_file_offset, 2),
+ uint64_to_str(
+ iter.block.uncompressed_file_offset, 3)
+ };
+ printf(" %*s %*s %*s %*s ",
+ tuklib_mbstr_fw(cols1[0], 6), cols1[0],
+ tuklib_mbstr_fw(cols1[1], 9), cols1[1],
+ tuklib_mbstr_fw(cols1[2], 15), cols1[2],
+ tuklib_mbstr_fw(cols1[3], 15), cols1[3]);
+
+ const char *cols2[4] = {
+ uint64_to_str(iter.block.total_size, 0),
+ uint64_to_str(iter.block.uncompressed_size,
+ 1),
get_ratio(iter.block.total_size,
iter.block.uncompressed_size),
- check_names[iter.stream.flags->check]);
-
- if (message_verbosity_get() >= V_DEBUG)
- if (print_check_value(pair, &iter))
- return;
+ _(check_names[iter.stream.flags->check])
+ };
+ printf("%*s %*s %*s %-*s",
+ tuklib_mbstr_fw(cols2[0], 15), cols2[0],
+ tuklib_mbstr_fw(cols2[1], 15), cols2[1],
+ tuklib_mbstr_fw(cols2[2], 5), cols2[2],
+ tuklib_mbstr_fw(cols2[3], detailed ? 11 : 1),
+ cols2[3]);
+
+ if (detailed) {
+ const lzma_vli compressed_size
+ = iter.block.unpadded_size
+ - bhi.header_size
+ - lzma_check_size(
+ iter.stream.flags->check);
+
+ const char *cols3[6] = {
+ check_value,
+ uint64_to_str(bhi.header_size, 0),
+ bhi.flags,
+ uint64_to_str(compressed_size, 1),
+ uint64_to_str(
+ round_up_to_mib(bhi.memusage),
+ 2),
+ bhi.filter_chain
+ };
+ // Show MiB for memory usage, because it
+ // is the only size which is not in bytes.
+ printf("%-*s %*s %-5s %*s %*s MiB %s",
+ checkval_width, cols3[0],
+ tuklib_mbstr_fw(cols3[1], 6), cols3[1],
+ cols3[2],
+ tuklib_mbstr_fw(cols3[3], 15),
+ cols3[3],
+ tuklib_mbstr_fw(cols3[4], 7), cols3[4],
+ cols3[5]);
+ }
putchar('\n');
}
}
+
+ if (detailed) {
+ printf(_(" Memory needed: %s MiB\n"), uint64_to_str(
+ round_up_to_mib(xfi->memusage_max), 0));
+ printf(_(" Sizes in headers: %s\n"),
+ xfi->all_have_sizes ? _("Yes") : _("No"));
+ }
+
+ return false;
}
-static void
-print_info_robot(const lzma_index *idx, file_pair *pair)
+static bool
+print_info_robot(xz_file_info *xfi, file_pair *pair)
{
+ char checks[CHECKS_STR_SIZE];
+ get_check_names(checks, lzma_index_checks(xfi->idx), false);
+
+ printf("name\t%s\n", pair->src_name);
+
printf("file\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64
- "\t%s\t%s\t%s\n",
- lzma_index_stream_count(idx),
- lzma_index_block_count(idx),
- lzma_index_file_size(idx),
- lzma_index_uncompressed_size(idx),
- get_ratio(lzma_index_file_size(idx),
- lzma_index_uncompressed_size(idx)),
- get_check_names(lzma_index_checks(idx), false),
- pair->src_name);
+ "\t%s\t%s\t%" PRIu64 "\n",
+ lzma_index_stream_count(xfi->idx),
+ lzma_index_block_count(xfi->idx),
+ lzma_index_file_size(xfi->idx),
+ lzma_index_uncompressed_size(xfi->idx),
+ get_ratio(lzma_index_file_size(xfi->idx),
+ lzma_index_uncompressed_size(xfi->idx)),
+ checks,
+ xfi->stream_padding);
if (message_verbosity_get() >= V_VERBOSE) {
lzma_index_iter iter;
- lzma_index_iter_init(&iter, idx);
+ lzma_index_iter_init(&iter, xfi->idx);
while (!lzma_index_iter_next(&iter, LZMA_INDEX_ITER_STREAM))
printf("stream\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64
- "\t%" PRIu64 "\t%" PRIu64
- "\t%s\t%" PRIu64 "\t%s\n",
+ "\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64
+ "\t%s\t%s\t%" PRIu64 "\n",
iter.stream.number,
+ iter.stream.block_count,
iter.stream.compressed_offset,
iter.stream.uncompressed_offset,
iter.stream.compressed_size,
iter.stream.uncompressed_size,
get_ratio(iter.stream.compressed_size,
iter.stream.uncompressed_size),
- iter.stream.padding,
- check_names[iter.stream.flags->check]);
+ check_names[iter.stream.flags->check],
+ iter.stream.padding);
lzma_index_iter_rewind(&iter);
+ block_header_info bhi;
+
while (!lzma_index_iter_next(&iter, LZMA_INDEX_ITER_BLOCK)) {
+ if (message_verbosity_get() >= V_DEBUG
+ && parse_details(
+ pair, &iter, &bhi, xfi))
+ return true;
+
printf("block\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64
"\t%" PRIu64 "\t%" PRIu64
"\t%" PRIu64 "\t%" PRIu64 "\t%s\t%s",
@@ -572,30 +906,46 @@ print_info_robot(const lzma_index *idx, file_pair *pair)
iter.block.uncompressed_size),
check_names[iter.stream.flags->check]);
- if (message_verbosity_get() >= V_DEBUG) {
- putchar('\t');
- if (print_check_value(pair, &iter))
- return;
- }
+ if (message_verbosity_get() >= V_DEBUG)
+ printf("\t%s\t%" PRIu32 "\t%s\t%" PRIu64
+ "\t%" PRIu64 "\t%s",
+ check_value,
+ bhi.header_size,
+ bhi.flags,
+ bhi.compressed_size,
+ bhi.memusage,
+ bhi.filter_chain);
putchar('\n');
}
}
- return;
+ if (message_verbosity_get() >= V_DEBUG)
+ printf("summary\t%" PRIu64 "\t%s\n",
+ xfi->memusage_max,
+ xfi->all_have_sizes ? "yes" : "no");
+
+ return false;
}
static void
-update_totals(const lzma_index *idx)
+update_totals(const xz_file_info *xfi)
{
// TODO: Integer overflow checks
++totals.files;
- totals.streams += lzma_index_stream_count(idx);
- totals.blocks += lzma_index_block_count(idx);
- totals.compressed_size += lzma_index_file_size(idx);
- totals.uncompressed_size += lzma_index_uncompressed_size(idx);
- totals.checks |= lzma_index_checks(idx);
+ totals.streams += lzma_index_stream_count(xfi->idx);
+ totals.blocks += lzma_index_block_count(xfi->idx);
+ totals.compressed_size += lzma_index_file_size(xfi->idx);
+ totals.uncompressed_size += lzma_index_uncompressed_size(xfi->idx);
+ totals.stream_padding += xfi->stream_padding;
+ totals.checks |= lzma_index_checks(xfi->idx);
+
+ if (totals.memusage_max < xfi->memusage_max)
+ totals.memusage_max = xfi->memusage_max;
+
+ totals.all_have_sizes &= xfi->all_have_sizes;
+
return;
}
@@ -609,6 +959,10 @@ print_totals_basic(void)
line[sizeof(line) - 1] = '\0';
puts(line);
+ // Get the check names.
+ char checks[CHECKS_STR_SIZE];
+ get_check_names(checks, totals.checks, false);
+
// Print the totals except the file count, which needs
// special handling.
printf("%5s %7s %11s %11s %5s %-7s ",
@@ -620,16 +974,16 @@ print_totals_basic(void)
NICESTR_B, NICESTR_TIB, false, 3),
get_ratio(totals.compressed_size,
totals.uncompressed_size),
- get_check_names(totals.checks, false));
+ checks);
// Since we print totals only when there are at least two files,
// the English message will always use "%s files". But some other
// languages need different forms for different plurals so we
- // have to translate this string still.
+ // have to translate this with ngettext().
//
- // TRANSLATORS: This simply indicates the number of files shown
- // by --list even though the format string uses %s.
- printf(N_("%s file", "%s files\n",
+ // TRANSLATORS: %s is an integer. Only the plural form of this
+ // message is used (e.g. "2 files"). Test with "xz -l foo.xz bar.xz".
+ printf(ngettext("%s file\n", "%s files\n",
totals.files <= ULONG_MAX ? totals.files
: (totals.files % 1000000) + 1000000),
uint64_to_str(totals.files, 0));
@@ -647,7 +1001,14 @@ print_totals_adv(void)
uint64_to_str(totals.files, 0));
print_adv_helper(totals.streams, totals.blocks,
totals.compressed_size, totals.uncompressed_size,
- totals.checks);
+ totals.checks, totals.stream_padding);
+
+ if (message_verbosity_get() >= V_DEBUG) {
+ printf(_(" Memory needed: %s MiB\n"), uint64_to_str(
+ round_up_to_mib(totals.memusage_max), 0));
+ printf(_(" Sizes in headers: %s\n"),
+ totals.all_have_sizes ? _("Yes") : _("No"));
+ }
return;
}
@@ -656,17 +1017,28 @@ print_totals_adv(void)
static void
print_totals_robot(void)
{
+ char checks[CHECKS_STR_SIZE];
+ get_check_names(checks, totals.checks, false);
+
printf("totals\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64
- "\t%s\t%s\t%" PRIu64 "\n",
+ "\t%s\t%s\t%" PRIu64 "\t%" PRIu64,
totals.streams,
totals.blocks,
totals.compressed_size,
totals.uncompressed_size,
get_ratio(totals.compressed_size,
totals.uncompressed_size),
- get_check_names(totals.checks, false),
+ checks,
+ totals.stream_padding,
totals.files);
+ if (message_verbosity_get() >= V_DEBUG)
+ printf("\t%" PRIu64 "\t%s",
+ totals.memusage_max,
+ totals.all_have_sizes ? "yes" : "no");
+
+ putchar('\n');
+
return;
}
@@ -716,11 +1088,9 @@ list_file(const char *filename)
if (pair == NULL)
return;
- lzma_index *idx;
- if (!parse_indexes(&idx, pair)) {
- // Update the totals that are displayed after all
- // the individual files have been listed.
- update_totals(idx);
+ xz_file_info xfi = XZ_FILE_INFO_INIT;
+ if (!parse_indexes(&xfi, pair)) {
+ bool fail;
// We have three main modes:
// - --robot, which has submodes if --verbose is specified
@@ -728,13 +1098,19 @@ list_file(const char *filename)
// - Normal --list without --verbose
// - --list with one or two --verbose
if (opt_robot)
- print_info_robot(idx, pair);
+ fail = print_info_robot(&xfi, pair);
else if (message_verbosity_get() <= V_WARNING)
- print_info_basic(idx, pair);
+ fail = print_info_basic(&xfi, pair);
else
- print_info_adv(idx, pair);
+ fail = print_info_adv(&xfi, pair);
+
+ // Update the totals that are displayed after all
+ // the individual files have been listed. Don't count
+ // broken files.
+ if (!fail)
+ update_totals(&xfi);
- lzma_index_end(idx, NULL);
+ lzma_index_end(xfi.idx, NULL);
}
io_close(pair, false);
diff --git a/src/xz/main.c b/src/xz/main.c
index e0905893c89d..8196c6e7e774 100644
--- a/src/xz/main.c
+++ b/src/xz/main.c
@@ -13,10 +13,15 @@
#include "private.h"
#include <ctype.h>
-
/// Exit status to use. This can be changed with set_exit_status().
static enum exit_status_type exit_status = E_SUCCESS;
+#if defined(_WIN32) && !defined(__CYGWIN__)
+/// exit_status has to be protected with a critical section due to
+/// how "signal handling" is done on Windows. See signals.c for details.
+static CRITICAL_SECTION exit_status_cs;
+#endif
+
/// True if --no-warn is specified. When this is true, we don't set
/// the exit status to E_WARNING when something worth a warning happens.
static bool no_warn = false;
@@ -27,9 +32,17 @@ set_exit_status(enum exit_status_type new_status)
{
assert(new_status == E_WARNING || new_status == E_ERROR);
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ EnterCriticalSection(&exit_status_cs);
+#endif
+
if (exit_status != E_ERROR)
exit_status = new_status;
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ LeaveCriticalSection(&exit_status_cs);
+#endif
+
return;
}
@@ -129,6 +142,10 @@ read_name(const args_info *args)
int
main(int argc, char **argv)
{
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ InitializeCriticalSection(&exit_status_cs);
+#endif
+
// Set up the progname variable.
tuklib_progname_init(argv);
@@ -262,11 +279,24 @@ main(int argc, char **argv)
// of calling tuklib_exit().
signals_exit();
+ // Make a local copy of exit_status to keep the Windows code
+ // thread safe. At this point it is fine if we miss the user
+ // pressing C-c and don't set the exit_status to E_ERROR on
+ // Windows.
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ EnterCriticalSection(&exit_status_cs);
+#endif
+
+ enum exit_status_type es = exit_status;
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ LeaveCriticalSection(&exit_status_cs);
+#endif
+
// Suppress the exit status indicating a warning if --no-warn
// was specified.
- if (exit_status == E_WARNING && no_warn)
- exit_status = E_SUCCESS;
+ if (es == E_WARNING && no_warn)
+ es = E_SUCCESS;
- tuklib_exit(exit_status, E_ERROR,
- message_verbosity_get() != V_SILENT);
+ tuklib_exit(es, E_ERROR, message_verbosity_get() != V_SILENT);
}
diff --git a/src/xz/message.c b/src/xz/message.c
index f24e98e97d92..3f2b813d7c7a 100644
--- a/src/xz/message.c
+++ b/src/xz/message.c
@@ -142,19 +142,19 @@ message_init(void)
*/
#ifdef SIGALRM
- // At least DJGPP lacks SA_RESTART. It's not essential for us (the
- // rest of the code can handle interrupted system calls), so just
- // define it zero.
-# ifndef SA_RESTART
+ // DJGPP lacks SA_RESTART, but it shouldn't give EINTR
+ // in most places either.
+# if defined(__DJGPP__) && !defined(SA_RESTART)
# define SA_RESTART 0
# endif
+
// Establish the signal handlers which set a flag to tell us that
// progress info should be updated. Since these signals don't
- // require any quick action, we set SA_RESTART.
+ // require any quick action, we set SA_RESTART. That way we don't
+ // need to block them either in signals_block() to keep stdio
+ // functions from getting EINTR.
static const int sigs[] = {
-#ifdef SIGALRM
SIGALRM,
-#endif
#ifdef SIGINFO
SIGINFO,
#endif
@@ -321,7 +321,8 @@ progress_percentage(uint64_t in_pos)
double percentage = (double)(in_pos) / (double)(expected_in_size)
* 99.9;
- static char buf[sizeof("99.9 %")];
+ // Use big enough buffer to hold e.g. a multibyte decimal point.
+ static char buf[16];
snprintf(buf, sizeof(buf), "%.1f %%", percentage);
return buf;
@@ -333,12 +334,8 @@ progress_percentage(uint64_t in_pos)
static const char *
progress_sizes(uint64_t compressed_pos, uint64_t uncompressed_pos, bool final)
{
- // This is enough to hold sizes up to about 99 TiB if thousand
- // separator is used, or about 1 PiB without thousand separator.
- // After that the progress indicator will look a bit silly, since
- // the compression ratio no longer fits with three decimal places.
- static char buf[36];
-
+ // Use big enough buffer to hold e.g. a multibyte thousand separators.
+ static char buf[128];
char *pos = buf;
size_t left = sizeof(buf);
@@ -402,7 +399,8 @@ progress_speed(uint64_t uncompressed_pos, uint64_t elapsed)
// - 9.9 KiB/s
// - 99 KiB/s
// - 999 KiB/s
- static char buf[sizeof("999 GiB/s")];
+ // Use big enough buffer to hold e.g. a multibyte decimal point.
+ static char buf[16];
snprintf(buf, sizeof(buf), "%.*f %s",
speed > 9.9 ? 0 : 1, speed, unit[unit_index]);
return buf;
@@ -588,12 +586,19 @@ message_progress_update(void)
// Print the actual progress message. The idea is that there is at
// least three spaces between the fields in typical situations, but
// even in rare situations there is at least one space.
- fprintf(stderr, "\r %6s %35s %9s %10s %10s\r",
+ const char *cols[5] = {
progress_percentage(in_pos),
progress_sizes(compressed_pos, uncompressed_pos, false),
progress_speed(uncompressed_pos, elapsed),
progress_time(elapsed),
- progress_remaining(in_pos, elapsed));
+ progress_remaining(in_pos, elapsed),
+ };
+ fprintf(stderr, "\r %*s %*s %*s %10s %10s\r",
+ tuklib_mbstr_fw(cols[0], 6), cols[0],
+ tuklib_mbstr_fw(cols[1], 35), cols[1],
+ tuklib_mbstr_fw(cols[2], 9), cols[2],
+ cols[3],
+ cols[4]);
#ifdef SIGALRM
// Updating the progress info was finished. Reset
@@ -663,12 +668,19 @@ progress_flush(bool finished)
// statistics are printed in the same format as the progress
// indicator itself.
if (progress_automatic) {
- fprintf(stderr, "\r %6s %35s %9s %10s %10s\n",
+ const char *cols[5] = {
finished ? "100 %" : progress_percentage(in_pos),
progress_sizes(compressed_pos, uncompressed_pos, true),
progress_speed(uncompressed_pos, elapsed),
progress_time(elapsed),
- finished ? "" : progress_remaining(in_pos, elapsed));
+ finished ? "" : progress_remaining(in_pos, elapsed),
+ };
+ fprintf(stderr, "\r %*s %*s %*s %10s %10s\n",
+ tuklib_mbstr_fw(cols[0], 6), cols[0],
+ tuklib_mbstr_fw(cols[1], 35), cols[1],
+ tuklib_mbstr_fw(cols[2], 9), cols[2],
+ cols[3],
+ cols[4]);
} else {
// The filename is always printed.
fprintf(stderr, "%s: ", filename);
@@ -848,13 +860,15 @@ message_mem_needed(enum message_verbosity v, uint64_t memusage)
// the user might need to +1 MiB to get high enough limit.)
memusage = round_up_to_mib(memusage);
+ // With US-ASCII:
// 2^64 with thousand separators + " MiB" suffix + '\0' = 26 + 4 + 1
- char memlimitstr[32];
+ // But there may be multibyte chars so reserve enough space.
+ char memlimitstr[128];
// Show the memory usage limit as MiB unless it is less than 1 MiB.
// This way it's easy to notice errors where one has typed
// --memory=123 instead of --memory=123MiB.
- uint64_t memlimit = hardware_memlimit_get();
+ uint64_t memlimit = hardware_memlimit_get(opt_mode);
if (memlimit < (UINT32_C(1) << 20)) {
snprintf(memlimitstr, sizeof(memlimitstr), "%s B",
uint64_to_str(memlimit, 1));
@@ -876,141 +890,179 @@ message_mem_needed(enum message_verbosity v, uint64_t memusage)
}
-extern void
-message_filters(enum message_verbosity v, const lzma_filter *filters)
+/// \brief Convert uint32_t to a nice string for --lzma[12]=dict=SIZE
+///
+/// The idea is to use KiB or MiB suffix when possible.
+static const char *
+uint32_to_optstr(uint32_t num)
{
- if (v > verbosity)
- return;
+ static char buf[16];
- fprintf(stderr, _("%s: Filter chain:"), progname);
+ if ((num & ((UINT32_C(1) << 20) - 1)) == 0)
+ snprintf(buf, sizeof(buf), "%" PRIu32 "MiB", num >> 20);
+ else if ((num & ((UINT32_C(1) << 10) - 1)) == 0)
+ snprintf(buf, sizeof(buf), "%" PRIu32 "KiB", num >> 10);
+ else
+ snprintf(buf, sizeof(buf), "%" PRIu32, num);
+
+ return buf;
+}
+
+
+extern void
+message_filters_to_str(char buf[FILTERS_STR_SIZE],
+ const lzma_filter *filters, bool all_known)
+{
+ char *pos = buf;
+ size_t left = FILTERS_STR_SIZE;
for (size_t i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i) {
- fprintf(stderr, " --");
+ // Add the dashes for the filter option. A space is
+ // needed after the first and later filters.
+ my_snprintf(&pos, &left, "%s", i == 0 ? "--" : " --");
switch (filters[i].id) {
case LZMA_FILTER_LZMA1:
case LZMA_FILTER_LZMA2: {
const lzma_options_lzma *opt = filters[i].options;
- const char *mode;
- const char *mf;
-
- switch (opt->mode) {
- case LZMA_MODE_FAST:
- mode = "fast";
- break;
-
- case LZMA_MODE_NORMAL:
- mode = "normal";
- break;
-
- default:
- mode = "UNKNOWN";
- break;
- }
-
- switch (opt->mf) {
- case LZMA_MF_HC3:
- mf = "hc3";
- break;
-
- case LZMA_MF_HC4:
- mf = "hc4";
- break;
-
- case LZMA_MF_BT2:
- mf = "bt2";
- break;
-
- case LZMA_MF_BT3:
- mf = "bt3";
- break;
-
- case LZMA_MF_BT4:
- mf = "bt4";
- break;
-
- default:
- mf = "UNKNOWN";
- break;
+ const char *mode = NULL;
+ const char *mf = NULL;
+
+ if (all_known) {
+ switch (opt->mode) {
+ case LZMA_MODE_FAST:
+ mode = "fast";
+ break;
+
+ case LZMA_MODE_NORMAL:
+ mode = "normal";
+ break;
+
+ default:
+ mode = "UNKNOWN";
+ break;
+ }
+
+ switch (opt->mf) {
+ case LZMA_MF_HC3:
+ mf = "hc3";
+ break;
+
+ case LZMA_MF_HC4:
+ mf = "hc4";
+ break;
+
+ case LZMA_MF_BT2:
+ mf = "bt2";
+ break;
+
+ case LZMA_MF_BT3:
+ mf = "bt3";
+ break;
+
+ case LZMA_MF_BT4:
+ mf = "bt4";
+ break;
+
+ default:
+ mf = "UNKNOWN";
+ break;
+ }
}
- fprintf(stderr, "lzma%c=dict=%" PRIu32
+ // Add the filter name and dictionary size, which
+ // is always known.
+ my_snprintf(&pos, &left, "lzma%c=dict=%s",
+ filters[i].id == LZMA_FILTER_LZMA2
+ ? '2' : '1',
+ uint32_to_optstr(opt->dict_size));
+
+ // With LZMA1 also lc/lp/pb are known when
+ // decompressing, but this function is never
+ // used to print information about .lzma headers.
+ assert(filters[i].id == LZMA_FILTER_LZMA2
+ || all_known);
+
+ // Print the rest of the options, which are known
+ // only when compressing.
+ if (all_known)
+ my_snprintf(&pos, &left,
",lc=%" PRIu32 ",lp=%" PRIu32
",pb=%" PRIu32
",mode=%s,nice=%" PRIu32 ",mf=%s"
",depth=%" PRIu32,
- filters[i].id == LZMA_FILTER_LZMA2
- ? '2' : '1',
- opt->dict_size,
opt->lc, opt->lp, opt->pb,
mode, opt->nice_len, mf, opt->depth);
break;
}
case LZMA_FILTER_X86:
- fprintf(stderr, "x86");
- break;
-
case LZMA_FILTER_POWERPC:
- fprintf(stderr, "powerpc");
- break;
-
case LZMA_FILTER_IA64:
- fprintf(stderr, "ia64");
- break;
-
case LZMA_FILTER_ARM:
- fprintf(stderr, "arm");
- break;
-
case LZMA_FILTER_ARMTHUMB:
- fprintf(stderr, "armthumb");
- break;
+ case LZMA_FILTER_SPARC: {
+ static const char bcj_names[][9] = {
+ "x86",
+ "powerpc",
+ "ia64",
+ "arm",
+ "armthumb",
+ "sparc",
+ };
+
+ const lzma_options_bcj *opt = filters[i].options;
+ my_snprintf(&pos, &left, "%s", bcj_names[filters[i].id
+ - LZMA_FILTER_X86]);
+
+ // Show the start offset only when really needed.
+ if (opt != NULL && opt->start_offset != 0)
+ my_snprintf(&pos, &left, "=start=%" PRIu32,
+ opt->start_offset);
- case LZMA_FILTER_SPARC:
- fprintf(stderr, "sparc");
break;
+ }
case LZMA_FILTER_DELTA: {
const lzma_options_delta *opt = filters[i].options;
- fprintf(stderr, "delta=dist=%" PRIu32, opt->dist);
+ my_snprintf(&pos, &left, "delta=dist=%" PRIu32,
+ opt->dist);
break;
}
default:
- fprintf(stderr, "UNKNOWN");
+ // This should be possible only if liblzma is
+ // newer than the xz tool.
+ my_snprintf(&pos, &left, "UNKNOWN");
break;
}
}
- fputc('\n', stderr);
return;
}
extern void
-message_try_help(void)
+message_filters_show(enum message_verbosity v, const lzma_filter *filters)
{
- // Print this with V_WARNING instead of V_ERROR to prevent it from
- // showing up when --quiet has been specified.
- message(V_WARNING, _("Try `%s --help' for more information."),
- progname);
+ if (v > verbosity)
+ return;
+
+ char buf[FILTERS_STR_SIZE];
+ message_filters_to_str(buf, filters, true);
+ fprintf(stderr, _("%s: Filter chain: %s\n"), progname, buf);
return;
}
extern void
-message_memlimit(void)
+message_try_help(void)
{
- if (opt_robot)
- printf("%" PRIu64 "\n", hardware_memlimit_get());
- else
- printf(_("%s MiB (%s bytes)\n"),
- uint64_to_str(
- round_up_to_mib(hardware_memlimit_get()), 0),
- uint64_to_str(hardware_memlimit_get(), 1));
-
- tuklib_exit(E_SUCCESS, E_ERROR, verbosity != V_SILENT);
+ // Print this with V_WARNING instead of V_ERROR to prevent it from
+ // showing up when --quiet has been specified.
+ message(V_WARNING, _("Try `%s --help' for more information."),
+ progname);
+ return;
}
@@ -1020,7 +1072,7 @@ message_version(void)
// It is possible that liblzma version is different than the command
// line tool version, so print both.
if (opt_robot) {
- printf("XZ_VERSION=%d\nLIBLZMA_VERSION=%d\n",
+ printf("XZ_VERSION=%" PRIu32 "\nLIBLZMA_VERSION=%" PRIu32 "\n",
LZMA_VERSION, lzma_version_number());
} else {
printf("xz (" PACKAGE_NAME ") " LZMA_VERSION_STRING "\n");
@@ -1038,8 +1090,11 @@ message_help(bool long_help)
"Compress or decompress FILEs in the .xz format.\n\n"),
progname);
- puts(_("Mandatory arguments to long options are mandatory for "
- "short options too.\n"));
+ // NOTE: The short help doesn't currently have options that
+ // take arguments.
+ if (long_help)
+ puts(_("Mandatory arguments to long options are mandatory "
+ "for short options too.\n"));
if (long_help)
puts(_(" Operation mode:\n"));
@@ -1048,7 +1103,7 @@ message_help(bool long_help)
" -z, --compress force compression\n"
" -d, --decompress force decompression\n"
" -t, --test test compressed file integrity\n"
-" -l, --list list information about files"));
+" -l, --list list information about .xz files"));
if (long_help)
puts(_("\n Operation modifiers:\n"));
@@ -1062,32 +1117,40 @@ message_help(bool long_help)
puts(_(
" --no-sparse do not create sparse files when decompressing\n"
" -S, --suffix=.SUF use the suffix `.SUF' on compressed files\n"
-" --files=[FILE] read filenames to process from FILE; if FILE is\n"
+" --files[=FILE] read filenames to process from FILE; if FILE is\n"
" omitted, filenames are read from the standard input;\n"
" filenames must be terminated with the newline character\n"
-" --files0=[FILE] like --files but use the null character as terminator"));
+" --files0[=FILE] like --files but use the null character as terminator"));
if (long_help) {
puts(_("\n Basic file format and compression options:\n"));
puts(_(
" -F, --format=FMT file format to encode or decode; possible values are\n"
" `auto' (default), `xz', `lzma', and `raw'\n"
-" -C, --check=CHECK integrity check type: `crc32', `crc64' (default),\n"
-" `sha256', or `none' (use with caution)"));
+" -C, --check=CHECK integrity check type: `none' (use with caution),\n"
+" `crc32', `crc64' (default), or `sha256'"));
}
puts(_(
-" -0 .. -9 compression preset; 0-2 fast compression, 3-5 good\n"
-" compression, 6-9 excellent compression; default is 6"));
+" -0 ... -9 compression preset; default is 6; take compressor *and*\n"
+" decompressor memory usage into account before using 7-9!"));
puts(_(
-" -e, --extreme use more CPU time when encoding to increase compression\n"
-" ratio without increasing memory usage of the decoder"));
+" -e, --extreme try to improve compression ratio by using more CPU time;\n"
+" does not affect decompressor memory requirements"));
- if (long_help)
+ if (long_help) {
puts(_( // xgettext:no-c-format
-" -M, --memory=NUM use roughly NUM bytes of memory at maximum; 0 indicates\n"
-" the default setting, which is 40 % of total RAM"));
+" --memlimit-compress=LIMIT\n"
+" --memlimit-decompress=LIMIT\n"
+" -M, --memlimit=LIMIT\n"
+" set memory usage limit for compression, decompression,\n"
+" or both; LIMIT is in bytes, % of RAM, or 0 for defaults"));
+
+ puts(_(
+" --no-adjust if compression settings exceed the memory usage limit,\n"
+" give an error instead of adjusting the settings downwards"));
+ }
if (long_help) {
puts(_(
@@ -1095,11 +1158,15 @@ message_help(bool long_help)
#if defined(HAVE_ENCODER_LZMA1) || defined(HAVE_DECODER_LZMA1) \
|| defined(HAVE_ENCODER_LZMA2) || defined(HAVE_DECODER_LZMA2)
+ // TRANSLATORS: The word "literal" in "literal context bits"
+ // means how many "context bits" to use when encoding
+ // literals. A literal is a single 8-bit byte. It doesn't
+ // mean "literally" here.
puts(_(
"\n"
" --lzma1[=OPTS] LZMA1 or LZMA2; OPTS is a comma-separated list of zero or\n"
" --lzma2[=OPTS] more of the following options (valid values; default):\n"
-" preset=NUM reset options to preset number NUM (0-9)\n"
+" preset=PRE reset options to a preset (0-9[e])\n"
" dict=NUM dictionary size (4KiB - 1536MiB; 8MiB)\n"
" lc=NUM number of literal context bits (0-4; 3)\n"
" lp=NUM number of literal position bits (0-4; 0)\n"
@@ -1112,9 +1179,9 @@ message_help(bool long_help)
puts(_(
"\n"
-" --x86[=OPTS] x86 BCJ filter\n"
+" --x86[=OPTS] x86 BCJ filter (32-bit and 64-bit)\n"
" --powerpc[=OPTS] PowerPC BCJ filter (big endian only)\n"
-" --ia64[=OPTS] IA64 (Itanium) BCJ filter\n"
+" --ia64[=OPTS] IA-64 (Itanium) BCJ filter\n"
" --arm[=OPTS] ARM BCJ filter (little endian only)\n"
" --armthumb[=OPTS] ARM-Thumb BCJ filter (little endian only)\n"
" --sparc[=OPTS] SPARC BCJ filter\n"
@@ -1128,15 +1195,6 @@ message_help(bool long_help)
" dist=NUM distance between bytes being subtracted\n"
" from each other (1-256; 1)"));
#endif
-
-#if defined(HAVE_ENCODER_SUBBLOCK) || defined(HAVE_DECODER_SUBBLOCK)
- puts(_(
-"\n"
-" --subblock[=OPTS] Subblock filter; valid OPTS (valid values; default):\n"
-" size=NUM number of bytes of data per subblock\n"
-" (1 - 256Mi; 4Ki)\n"
-" rle=NUM run-length encoder chunk size (0-256; 0)"));
-#endif
}
if (long_help)
@@ -1153,7 +1211,8 @@ message_help(bool long_help)
" --robot use machine-parsable messages (useful for scripts)"));
puts("");
puts(_(
-" --info-memory display the memory usage limit and exit"));
+" --info-memory display the total amount of RAM and the currently active\n"
+" memory usage limits, and exit"));
puts(_(
" -h, --help display the short help (lists only the basic options)\n"
" -H, --long-help display this long help and exit"));
@@ -1168,15 +1227,6 @@ message_help(bool long_help)
puts(_("\nWith no FILE, or when FILE is -, read standard input.\n"));
- if (long_help) {
- printf(_(
-"On this system and configuration, this program will use a maximum of roughly\n"
-"%s MiB RAM and "), uint64_to_str(round_up_to_mib(hardware_memlimit_get()), 0));
- printf(N_("one thread.\n\n", "%s threads.\n\n",
- hardware_threadlimit_get()),
- uint64_to_str(hardware_threadlimit_get(), 0));
- }
-
// TRANSLATORS: This message indicates the bug reporting address
// for this package. Please add _another line_ saying
// "Report translation bugs to <...>\n" with the email or WWW
diff --git a/src/xz/message.h b/src/xz/message.h
index 7d637dfe6b76..37e608216886 100644
--- a/src/xz/message.h
+++ b/src/xz/message.h
@@ -86,8 +86,24 @@ extern const char *message_strm(lzma_ret code);
extern void message_mem_needed(enum message_verbosity v, uint64_t memusage);
+/// Buffer size for message_filters_to_str()
+#define FILTERS_STR_SIZE 512
+
+
+/// \brief Get the filter chain as a string
+///
+/// \param buf Pointer to caller allocated buffer to hold
+/// the filter chain string
+/// \param filters Pointer to the filter chain
+/// \param all_known If true, all filter options are printed.
+/// If false, only the options that get stored
+/// into .xz headers are printed.
+extern void message_filters_to_str(char buf[FILTERS_STR_SIZE],
+ const lzma_filter *filters, bool all_known);
+
+
/// Print the filter chain.
-extern void message_filters(
+extern void message_filters_show(
enum message_verbosity v, const lzma_filter *filters);
@@ -95,10 +111,6 @@ extern void message_filters(
extern void message_try_help(void);
-/// Print the memory usage limit and exit.
-extern void message_memlimit(void) lzma_attribute((noreturn));
-
-
/// Prints the version number to stdout and exits with exit status SUCCESS.
extern void message_version(void) lzma_attribute((noreturn));
diff --git a/src/xz/options.c b/src/xz/options.c
index 00b34a83ae1b..379a2e46dc08 100644
--- a/src/xz/options.c
+++ b/src/xz/options.c
@@ -139,67 +139,6 @@ parse_options(const char *str, const option_map *opts,
}
-//////////////
-// Subblock //
-//////////////
-
-enum {
- OPT_SIZE,
- OPT_RLE,
- OPT_ALIGN,
-};
-
-
-static void
-set_subblock(void *options, uint32_t key, uint64_t value,
- const char *valuestr lzma_attribute((unused)))
-{
- lzma_options_subblock *opt = options;
-
- switch (key) {
- case OPT_SIZE:
- opt->subblock_data_size = value;
- break;
-
- case OPT_RLE:
- opt->rle = value;
- break;
-
- case OPT_ALIGN:
- opt->alignment = value;
- break;
- }
-}
-
-
-extern lzma_options_subblock *
-options_subblock(const char *str)
-{
- static const option_map opts[] = {
- { "size", NULL, LZMA_SUBBLOCK_DATA_SIZE_MIN,
- LZMA_SUBBLOCK_DATA_SIZE_MAX },
- { "rle", NULL, LZMA_SUBBLOCK_RLE_OFF,
- LZMA_SUBBLOCK_RLE_MAX },
- { "align",NULL, LZMA_SUBBLOCK_ALIGNMENT_MIN,
- LZMA_SUBBLOCK_ALIGNMENT_MAX },
- { NULL, NULL, 0, 0 }
- };
-
- lzma_options_subblock *options
- = xmalloc(sizeof(lzma_options_subblock));
- *options = (lzma_options_subblock){
- .allow_subfilters = false,
- .alignment = LZMA_SUBBLOCK_ALIGNMENT_DEFAULT,
- .subblock_data_size = LZMA_SUBBLOCK_DATA_SIZE_DEFAULT,
- .rle = LZMA_SUBBLOCK_RLE_OFF,
- };
-
- parse_options(str, opts, &set_subblock, options);
-
- return options;
-}
-
-
///////////
// Delta //
///////////
@@ -407,24 +346,13 @@ options_lzma(const char *str)
};
lzma_options_lzma *options = xmalloc(sizeof(lzma_options_lzma));
- *options = (lzma_options_lzma){
- .dict_size = LZMA_DICT_SIZE_DEFAULT,
- .preset_dict = NULL,
- .preset_dict_size = 0,
- .lc = LZMA_LC_DEFAULT,
- .lp = LZMA_LP_DEFAULT,
- .pb = LZMA_PB_DEFAULT,
- .mode = LZMA_MODE_NORMAL,
- .nice_len = 64,
- .mf = LZMA_MF_BT4,
- .depth = 0,
- };
+ if (lzma_lzma_preset(options, LZMA_PRESET_DEFAULT))
+ message_bug();
parse_options(str, opts, &set_lzma, options);
if (options->lc + options->lp > LZMA_LCLP_MAX)
- message_fatal(_("The sum of lc and lp must be at "
- "maximum of 4"));
+ message_fatal(_("The sum of lc and lp must not exceed 4"));
const uint32_t nice_len_min = options->mf & 0x0F;
if (options->nice_len < nice_len_min)
diff --git a/src/xz/options.h b/src/xz/options.h
index e7389c8e99cb..61ec8d58a145 100644
--- a/src/xz/options.h
+++ b/src/xz/options.h
@@ -10,13 +10,6 @@
//
///////////////////////////////////////////////////////////////////////////////
-/// \brief Parser for Subblock options
-///
-/// \return Pointer to allocated options structure.
-/// Doesn't return on error.
-extern lzma_options_subblock *options_subblock(const char *str);
-
-
/// \brief Parser for Delta options
///
/// \return Pointer to allocated options structure.
diff --git a/src/xz/private.h b/src/xz/private.h
index b543435750d8..6b01e51354e1 100644
--- a/src/xz/private.h
+++ b/src/xz/private.h
@@ -25,6 +25,12 @@
#include "tuklib_gettext.h"
#include "tuklib_progname.h"
#include "tuklib_exit.h"
+#include "tuklib_mbstr.h"
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
#ifndef STDIN_FILENO
# define STDIN_FILENO (fileno(stdin))
diff --git a/src/xz/signals.c b/src/xz/signals.c
index b27cd5b52cb1..7e65b2a38bf3 100644
--- a/src/xz/signals.c
+++ b/src/xz/signals.c
@@ -16,7 +16,7 @@
volatile sig_atomic_t user_abort = false;
-#ifndef _WIN32
+#if !(defined(_WIN32) && !defined(__CYGWIN__))
/// If we were interrupted by a signal, we store the signal number so that
/// we can raise that signal to kill the program when all cleanups have
@@ -142,12 +142,19 @@ signals_exit(void)
const int sig = exit_signal;
if (sig != 0) {
+#ifdef TUKLIB_DOSLIKE
+ // Don't raise(), set only exit status. This avoids
+ // printing unwanted message about SIGINT when the user
+ // presses C-c.
+ set_exit_status(E_ERROR);
+#else
struct sigaction sa;
sa.sa_handler = SIG_DFL;
sigfillset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(sig, &sa, NULL);
raise(exit_signal);
+#endif
}
return;
@@ -156,11 +163,14 @@ signals_exit(void)
#else
// While Windows has some very basic signal handling functions as required
-// by C89, they are not really used, or so I understood. Instead, we use
-// SetConsoleCtrlHandler() to catch user pressing C-c.
-
-#include <windows.h>
-
+// by C89, they are not really used, and e.g. SIGINT doesn't work exactly
+// the way it does on POSIX (Windows creates a new thread for the signal
+// handler). Instead, we use SetConsoleCtrlHandler() to catch user
+// pressing C-c, because that seems to be the recommended way to do it.
+//
+// NOTE: This doesn't work under MSYS. Trying with SIGINT doesn't work
+// either even if it appeared to work at first. So test using Windows
+// console window.
static BOOL WINAPI
signal_handler(DWORD type lzma_attribute((unused)))
@@ -168,9 +178,6 @@ signal_handler(DWORD type lzma_attribute((unused)))
// Since we don't get a signal number which we could raise() at
// signals_exit() like on POSIX, just set the exit status to
// indicate an error, so that we cannot return with zero exit status.
- //
- // FIXME: Since this function runs in its own thread,
- // set_exit_status() should have a mutex.
set_exit_status(E_ERROR);
user_abort = true;
return TRUE;
diff --git a/src/xz/signals.h b/src/xz/signals.h
index 7603d8033f71..5b125e0f0d7b 100644
--- a/src/xz/signals.h
+++ b/src/xz/signals.h
@@ -21,7 +21,7 @@ extern volatile sig_atomic_t user_abort;
extern void signals_init(void);
-#if defined(_WIN32) || defined(__VMS)
+#if (defined(_WIN32) && !defined(__CYGWIN__)) || defined(__VMS)
# define signals_block() do { } while (0)
# define signals_unblock() do { } while (0)
#else
@@ -34,7 +34,7 @@ extern void signals_block(void);
extern void signals_unblock(void);
#endif
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__CYGWIN__)
# define signals_exit() do { } while (0)
#else
/// If user has sent us a signal earlier to terminate the process,
diff --git a/src/xz/util.c b/src/xz/util.c
index deb5dcc2fd39..987b44302539 100644
--- a/src/xz/util.c
+++ b/src/xz/util.c
@@ -14,6 +14,13 @@
#include <stdarg.h>
+/// Buffers for uint64_to_str() and uint64_to_nicestr()
+static char bufs[4][128];
+
+/// Thousand separator support in uint64_to_str() and uint64_to_nicestr()
+static enum { UNKNOWN, WORKS, BROKEN } thousand = UNKNOWN;
+
+
extern void *
xrealloc(void *ptr, size_t size)
{
@@ -56,11 +63,17 @@ str_to_uint64(const char *name, const char *value, uint64_t min, uint64_t max)
do {
// Don't overflow.
- if (result > (UINT64_MAX - 9) / 10)
+ if (result > UINT64_MAX / 10)
goto error;
result *= 10;
- result += *value - '0';
+
+ // Another overflow check
+ const uint32_t add = *value - '0';
+ if (UINT64_MAX - add < result)
+ goto error;
+
+ result += add;
++value;
} while (*value >= '0' && *value <= '9');
@@ -119,22 +132,28 @@ round_up_to_mib(uint64_t n)
}
-extern const char *
-uint64_to_str(uint64_t value, uint32_t slot)
+/// Check if thousand separator is supported. Run-time checking is easiest,
+/// because it seems to be sometimes lacking even on POSIXish system.
+static void
+check_thousand_sep(uint32_t slot)
{
- // 2^64 with thousand separators is 26 bytes plus trailing '\0'.
- static char bufs[4][32];
-
- assert(slot < ARRAY_SIZE(bufs));
-
- static enum { UNKNOWN, WORKS, BROKEN } thousand = UNKNOWN;
if (thousand == UNKNOWN) {
bufs[slot][0] = '\0';
- snprintf(bufs[slot], sizeof(bufs[slot]), "%'" PRIu64,
- UINT64_C(1));
+ snprintf(bufs[slot], sizeof(bufs[slot]), "%'u", 1U);
thousand = bufs[slot][0] == '1' ? WORKS : BROKEN;
}
+ return;
+}
+
+
+extern const char *
+uint64_to_str(uint64_t value, uint32_t slot)
+{
+ assert(slot < ARRAY_SIZE(bufs));
+
+ check_thousand_sep(slot);
+
if (thousand == WORKS)
snprintf(bufs[slot], sizeof(bufs[slot]), "%'" PRIu64, value);
else
@@ -151,14 +170,21 @@ uint64_to_nicestr(uint64_t value, enum nicestr_unit unit_min,
{
assert(unit_min <= unit_max);
assert(unit_max <= NICESTR_TIB);
+ assert(slot < ARRAY_SIZE(bufs));
+
+ check_thousand_sep(slot);
enum nicestr_unit unit = NICESTR_B;
- const char *str;
+ char *pos = bufs[slot];
+ size_t left = sizeof(bufs[slot]);
if ((unit_min == NICESTR_B && value < 10000)
|| unit_max == NICESTR_B) {
// The value is shown as bytes.
- str = uint64_to_str(value, slot);
+ if (thousand == WORKS)
+ my_snprintf(&pos, &left, "%'u", (unsigned int)value);
+ else
+ my_snprintf(&pos, &left, "%u", (unsigned int)value);
} else {
// Scale the value to a nicer unit. Unless unit_min and
// unit_max limit us, we will show at most five significant
@@ -169,49 +195,23 @@ uint64_to_nicestr(uint64_t value, enum nicestr_unit unit_min,
++unit;
} while (unit < unit_min || (d > 9999.9 && unit < unit_max));
- str = double_to_str(d);
+ if (thousand == WORKS)
+ my_snprintf(&pos, &left, "%'.1f", d);
+ else
+ my_snprintf(&pos, &left, "%.1f", d);
}
static const char suffix[5][4] = { "B", "KiB", "MiB", "GiB", "TiB" };
+ my_snprintf(&pos, &left, " %s", suffix[unit]);
- // Minimum buffer size:
- // 26 2^64 with thousand separators
- // 4 " KiB"
- // 2 " ("
- // 26 2^64 with thousand separators
- // 3 " B)"
- // 1 '\0'
- // 62 Total
- static char buf[4][64];
- char *pos = buf[slot];
- size_t left = sizeof(buf[slot]);
- my_snprintf(&pos, &left, "%s %s", str, suffix[unit]);
-
- if (always_also_bytes && value >= 10000)
- snprintf(pos, left, " (%s B)", uint64_to_str(value, slot));
-
- return buf[slot];
-}
-
-
-extern const char *
-double_to_str(double value)
-{
- static char buf[64];
-
- static enum { UNKNOWN, WORKS, BROKEN } thousand = UNKNOWN;
- if (thousand == UNKNOWN) {
- buf[0] = '\0';
- snprintf(buf, sizeof(buf), "%'.1f", 2.0);
- thousand = buf[0] == '2' ? WORKS : BROKEN;
+ if (always_also_bytes && value >= 10000) {
+ if (thousand == WORKS)
+ snprintf(pos, left, " (%'" PRIu64 " B)", value);
+ else
+ snprintf(pos, left, " (%" PRIu64 " B)", value);
}
- if (thousand == WORKS)
- snprintf(buf, sizeof(buf), "%'.1f", value);
- else
- snprintf(buf, sizeof(buf), "%.1f", value);
-
- return buf;
+ return bufs[slot];
}
@@ -225,7 +225,10 @@ my_snprintf(char **pos, size_t *left, const char *fmt, ...)
// If an error occurred, we want the caller to think that the whole
// buffer was used. This way no more data will be written to the
- // buffer. We don't need better error handling here.
+ // buffer. We don't need better error handling here, although it
+ // is possible that the result looks garbage on the terminal if
+ // e.g. an UTF-8 character gets split. That shouldn't (easily)
+ // happen though, because the buffers used have some extra room.
if (len < 0 || (size_t)(len) >= *left) {
*left = 0;
} else {
@@ -237,45 +240,6 @@ my_snprintf(char **pos, size_t *left, const char *fmt, ...)
}
-/*
-/// \brief Simple quoting to get rid of ASCII control characters
-///
-/// This is not so cool and locale-dependent, but should be good enough
-/// At least we don't print any control characters on the terminal.
-///
-extern char *
-str_quote(const char *str)
-{
- size_t dest_len = 0;
- bool has_ctrl = false;
-
- while (str[dest_len] != '\0')
- if (*(unsigned char *)(str + dest_len++) < 0x20)
- has_ctrl = true;
-
- char *dest = malloc(dest_len + 1);
- if (dest != NULL) {
- if (has_ctrl) {
- for (size_t i = 0; i < dest_len; ++i)
- if (*(unsigned char *)(str + i) < 0x20)
- dest[i] = '?';
- else
- dest[i] = str[i];
-
- dest[dest_len] = '\0';
-
- } else {
- // Usually there are no control characters,
- // so we can optimize.
- memcpy(dest, str, dest_len + 1);
- }
- }
-
- return dest;
-}
-*/
-
-
extern bool
is_empty_filename(const char *filename)
{
diff --git a/src/xz/util.h b/src/xz/util.h
index 2e08b4a868ec..fea8cc6695dc 100644
--- a/src/xz/util.h
+++ b/src/xz/util.h
@@ -96,13 +96,6 @@ extern const char *uint64_to_nicestr(uint64_t value,
bool always_also_bytes, uint32_t slot);
-/// \brief Convert double to a string with one decimal place
-///
-/// This is like uint64_to_str() except that this converts a double and
-/// uses exactly one decimal place.
-extern const char *double_to_str(double value);
-
-
/// \brief Wrapper for snprintf() to help constructing a string in pieces
///
/// A maximum of *left bytes is written starting from *pos. *pos and *left
diff --git a/src/xz/xz.1 b/src/xz/xz.1
index b60353d0e927..cba1d077c2d1 100644
--- a/src/xz/xz.1
+++ b/src/xz/xz.1
@@ -5,9 +5,11 @@
.\" This file has been put into the public domain.
.\" You can do whatever you want with this file.
.\"
-.TH XZ 1 "2010-03-07" "Tukaani" "XZ Utils"
+.TH XZ 1 "2010-10-04" "Tukaani" "XZ Utils"
+.
.SH NAME
xz, unxz, xzcat, lzma, unlzma, lzcat \- Compress or decompress .xz and .lzma files
+.
.SH SYNOPSIS
.B xz
.RI [ option ]...
@@ -33,8 +35,8 @@ is equivalent to
is equivalent to
.BR "xz \-\-format=lzma \-\-decompress \-\-stdout" .
.PP
-When writing scripts that need to decompress files, it is recommended to
-always use the name
+When writing scripts that need to decompress files,
+it is recommended to always use the name
.B xz
with appropriate arguments
.RB ( "xz \-d"
@@ -43,19 +45,22 @@ or
instead of the names
.B unxz
and
-.BR xzcat.
+.BR xzcat .
+.
.SH DESCRIPTION
.B xz
-is a general-purpose data compression tool with command line syntax similar to
+is a general-purpose data compression tool with
+command line syntax similar to
.BR gzip (1)
and
.BR bzip2 (1).
The native file format is the
.B .xz
-format, but also the legacy
+format, but the legacy
.B .lzma
-format and raw compressed streams with no container format headers
-are supported.
+format used by LZMA Utils and
+raw compressed streams with no container format headers
+are also supported.
.PP
.B xz
compresses or decompresses each
@@ -68,13 +73,16 @@ are given or
is
.BR \- ,
.B xz
-reads from standard input and writes the processed data to standard output.
+reads from standard input and writes the processed data
+to standard output.
.B xz
will refuse (display an error and skip the
.IR file )
-to write compressed data to standard output if it is a terminal. Similarly,
+to write compressed data to standard output if it is a terminal.
+Similarly,
.B xz
-will refuse to read compressed data from standard input if it is a terminal.
+will refuse to read compressed data
+from standard input if it is a terminal.
.PP
Unless
.B \-\-stdout
@@ -117,8 +125,9 @@ will display a warning and skip the
if any of the following applies:
.IP \(bu 3
.I File
-is not a regular file. Symbolic links are not followed, thus they
-are not considered to be regular files.
+is not a regular file.
+Symbolic links are not followed,
+and thus they are not considered to be regular files.
.IP \(bu 3
.I File
has more than one hard link.
@@ -126,7 +135,7 @@ has more than one hard link.
.I File
has setuid, setgid, or sticky bit set.
.IP \(bu 3
-The operation mode is set to compress, and the
+The operation mode is set to compress and the
.I file
already has a suffix of the target file format
.RB ( .xz
@@ -142,7 +151,7 @@ when compressing to the
.B .lzma
format).
.IP \(bu 3
-The operation mode is set to decompress, and the
+The operation mode is set to decompress and the
.I file
doesn't have a suffix of any of the supported file formats
.RB ( .xz ,
@@ -154,12 +163,13 @@ or
After successfully compressing or decompressing the
.IR file ,
.B xz
-copies the owner, group, permissions, access time, and modification time
-from the source
+copies the owner, group, permissions, access time,
+and modification time from the source
.I file
-to the target file. If copying the group fails, the permissions are modified
-so that the target file doesn't become accessible to users who didn't have
-permission to access the source
+to the target file.
+If copying the group fails, the permissions are modified
+so that the target file doesn't become accessible to users
+who didn't have permission to access the source
.IR file .
.B xz
doesn't support copying other metadata like access control lists
@@ -169,7 +179,8 @@ Once the target file has been successfully closed, the source
.I file
is removed unless
.B \-\-keep
-was specified. The source
+was specified.
+The source
.I file
is never removed if the output is written to standard output.
.PP
@@ -180,66 +191,108 @@ or
to the
.B xz
process makes it print progress information to standard error.
-This has only limited use since when standard error is a terminal, using
+This has only limited use since when standard error
+is a terminal, using
.B \-\-verbose
will display an automatically updating progress indicator.
+.
.SS "Memory usage"
The memory usage of
.B xz
-varies from a few hundred kilobytes to several gigabytes depending on
-the compression settings. The settings used when compressing a file
-affect also the memory usage of the decompressor. Typically the decompressor
-needs only 5\ % to 20\ % of the amount of RAM that the compressor needed when
-creating the file. Still, the worst-case memory usage of the decompressor
-is several gigabytes.
-.PP
-To prevent uncomfortable surprises caused by huge memory usage,
+varies from a few hundred kilobytes to several gigabytes
+depending on the compression settings.
+The settings used when compressing a file determine
+the memory requirements of the decompressor.
+Typically the decompressor needs 5\ % to 20\ % of
+the amount of memory that the compressor needed when
+creating the file.
+For example, decompressing a file created with
+.B xz \-9
+currently requires 65\ MiB of memory.
+Still, it is possible to have
+.B .xz
+files that require several gigabytes of memory to decompress.
+.PP
+Especially users of older systems may find
+the possibility of very large memory usage annoying.
+To prevent uncomfortable surprises,
.B xz
-has a built-in memory usage limiter. While some operating systems provide
-ways to limit the memory usage of processes, relying on it wasn't deemed
-to be flexible enough. The default limit depends on the total amount of
-physical RAM:
-.IP \(bu 3
-If 40\ % of RAM is at least 80 MiB, 40\ % of RAM is used as the limit.
-.IP \(bu 3
-If 80\ % of RAM is over 80 MiB, 80 MiB is used as the limit.
-.IP \(bu 3
-Otherwise 80\ % of RAM is used as the limit.
-.PP
-When compressing, if the selected compression settings exceed the memory
-usage limit, the settings are automatically adjusted downwards and a notice
-about this is displayed. As an exception, if the memory usage limit is
-exceeded when compressing with
-.BR \-\-format=raw ,
-an error is displayed and
+has a built-in memory usage limiter, which is disabled by default.
+While some operating systems provide ways to limit
+the memory usage of processes, relying on it
+wasn't deemed to be flexible enough (e.g. using
+.BR ulimit (1)
+to limit virtual memory tends to cripple
+.BR mmap (2)).
+.PP
+The memory usage limiter can be enabled with
+the command line option \fB\-\-memlimit=\fIlimit\fR.
+Often it is more convenient to enable the limiter
+by default by setting the environment variable
+.BR XZ_DEFAULTS ,
+e.g.\&
+.BR XZ_DEFAULTS=\-\-memlimit=150MiB .
+It is possible to set the limits separately
+for compression and decompression
+by using \fB\-\-memlimit\-compress=\fIlimit\fR and
+\fB\-\-memlimit\-decompress=\fIlimit\fR.
+Using these two options outside
+.B XZ_DEFAULTS
+is rarely useful because a single run of
.B xz
-will exit with exit status
-.BR 1 .
+cannot do both compression and decompression and
+.BI \-\-memlimit= limit
+(or \fB\-M\fR \fIlimit\fR)
+is shorter to type on the command line.
.PP
-If source
-.I file
-cannot be decompressed without exceeding the memory usage limit, an error
-message is displayed and the file is skipped. Note that compressed files
-may contain many blocks, which may have been compressed with different
-settings. Typically all blocks will have roughly the same memory requirements,
-but it is possible that a block later in the file will exceed the memory usage
-limit, and an error about too low memory usage limit gets displayed after some
-data has already been decompressed.
-.PP
-The absolute value of the active memory usage limit can be seen with
-.B \-\-info-memory
-or near the bottom of the output of
-.BR \-\-long\-help .
-The default limit can be overridden with
-\fB\-\-memory=\fIlimit\fR.
+If the specified memory usage limit is exceeded when decompressing,
+.B xz
+will display an error and decompressing the file will fail.
+If the limit is exceeded when compressing,
+.B xz
+will try to scale the settings down so that the limit
+is no longer exceeded (except when using \fB\-\-format=raw\fR
+or \fB\-\-no\-adjust\fR).
+This way the operation won't fail unless the limit is very small.
+The scaling of the settings is done in steps that don't
+match the compression level presets, e.g. if the limit is
+only slightly less than the amount required for
+.BR "xz \-9" ,
+the settings will be scaled down only a little,
+not all the way down to
+.BR "xz \-8" .
+.
+.SS "Concatenation and padding with .xz files"
+It is possible to concatenate
+.B .xz
+files as is.
+.B xz
+will decompress such files as if they were a single
+.B .xz
+file.
+.PP
+It is possible to insert padding between the concatenated parts
+or after the last part.
+The padding must consist of null bytes and the size
+of the padding must be a multiple of four bytes.
+This can be useful e.g. if the
+.B .xz
+file is stored on a medium that measures file sizes
+in 512-byte blocks.
+.PP
+Concatenation and padding are not allowed with
+.B .lzma
+files or raw streams.
+.
.SH OPTIONS
+.
.SS "Integer suffixes and special values"
-In most places where an integer argument is expected, an optional suffix
-is supported to easily indicate large integers. There must be no space
-between the integer and the suffix.
+In most places where an integer argument is expected,
+an optional suffix is supported to easily indicate large integers.
+There must be no space between the integer and the suffix.
.TP
.B KiB
-The integer is multiplied by 1,024 (2^10). Also
+Multiply the integer by 1,024 (2^10).
.BR Ki ,
.BR k ,
.BR kB ,
@@ -250,7 +303,7 @@ are accepted as synonyms for
.BR KiB .
.TP
.B MiB
-The integer is multiplied by 1,048,576 (2^20). Also
+Multiply the integer by 1,048,576 (2^20).
.BR Mi ,
.BR m ,
.BR M ,
@@ -260,7 +313,7 @@ are accepted as synonyms for
.BR MiB .
.TP
.B GiB
-The integer is multiplied by 1,073,741,824 (2^30). Also
+Multiply the integer by 1,073,741,824 (2^30).
.BR Gi ,
.BR g ,
.BR G ,
@@ -269,16 +322,20 @@ and
are accepted as synonyms for
.BR GiB .
.PP
-A special value
+The special value
.B max
-can be used to indicate the maximum integer value supported by the option.
+can be used to indicate the maximum integer value
+supported by the option.
+.
.SS "Operation mode"
-If multiple operation mode options are given, the last one takes effect.
+If multiple operation mode options are given,
+the last one takes effect.
.TP
.BR \-z ", " \-\-compress
-Compress. This is the default operation mode when no operation mode option
-is specified, and no other operation mode is implied from the command name
-(for example,
+Compress.
+This is the default operation mode when no operation mode option
+is specified and no other operation mode is implied from
+the command name (for example,
.B unxz
implies
.BR \-\-decompress ).
@@ -289,45 +346,73 @@ Decompress.
.BR \-t ", " \-\-test
Test the integrity of compressed
.IR files .
-No files are created or removed. This option is equivalent to
+This option is equivalent to
.B "\-\-decompress \-\-stdout"
except that the decompressed data is discarded instead of being
written to standard output.
+No files are created or removed.
.TP
.BR \-l ", " \-\-list
-View information about the compressed files. No uncompressed output is
-produced, and no files are created or removed. In list mode, the program
-cannot read the compressed data from standard input or from other
-unseekable sources.
-.IP
-.B "This feature has not been implemented yet."
+Print information about compressed
+.IR files .
+No uncompressed output is produced,
+and no files are created or removed.
+In list mode, the program cannot read
+the compressed data from standard
+input or from other unseekable sources.
+.IP ""
+The default listing shows basic information about
+.IR files ,
+one file per line.
+To get more detailed information, use also the
+.B \-\-verbose
+option.
+For even more information, use
+.B \-\-verbose
+twice, but note that this may be slow, because getting all the extra
+information requires many seeks.
+The width of verbose output exceeds
+80 characters, so piping the output to e.g.\&
+.B "less\ \-S"
+may be convenient if the terminal isn't wide enough.
+.IP ""
+The exact output may vary between
+.B xz
+versions and different locales.
+For machine-readable output,
+.B \-\-robot \-\-list
+should be used.
+.
.SS "Operation modifiers"
.TP
.BR \-k ", " \-\-keep
-Keep (don't delete) the input files.
+Don't delete the input files.
.TP
.BR \-f ", " \-\-force
This option has several effects:
.RS
.IP \(bu 3
-If the target file already exists, delete it before compressing or
-decompressing.
+If the target file already exists,
+delete it before compressing or decompressing.
.IP \(bu 3
-Compress or decompress even if the input is a symbolic link to a regular file,
-has more than one hard link, or has setuid, setgid, or sticky bit set.
-The setuid, setgid, and sticky bits are not copied to the target file.
+Compress or decompress even if the input is
+a symbolic link to a regular file,
+has more than one hard link,
+or has the setuid, setgid, or sticky bit set.
+The setuid, setgid, and sticky bits are not copied
+to the target file.
.IP \(bu 3
-If combined with
+When used with
.B \-\-decompress
.BR \-\-stdout
and
.B xz
-doesn't recognize the type of the source file,
-.B xz
-will copy the source file as is to standard output. This allows using
+cannot recognize the type of the source file,
+copy the source file as is to standard output.
+This allows
.B xzcat
-.B \--force
-like
+.B \-\-force
+to be used like
.BR cat (1)
for files that have not been compressed with
.BR xz .
@@ -343,21 +428,23 @@ can be used to restrict
to decompress only a single file format.
.RE
.TP
-.BR \-c ", " \-\-stdout ", " \-\-to-stdout
-Write the compressed or decompressed data to standard output instead of
-a file. This implies
+.BR \-c ", " \-\-stdout ", " \-\-to\-stdout
+Write the compressed or decompressed data to
+standard output instead of a file.
+This implies
.BR \-\-keep .
.TP
.B \-\-no\-sparse
-Disable creation of sparse files. By default, if decompressing into
-a regular file,
+Disable creation of sparse files.
+By default, if decompressing into a regular file,
.B xz
-tries to make the file sparse if the decompressed data contains long
-sequences of binary zeros. It works also when writing to standard output
-as long as standard output is connected to a regular file, and certain
-additional conditions are met to make it safe. Creating sparse files may
-save disk space and speed up the decompression by reducing the amount of
-disk I/O.
+tries to make the file sparse if the decompressed data contains
+long sequences of binary zeros.
+It also works when writing to standard output
+as long as standard output is connected to a regular file
+and certain additional conditions are met to make it safe.
+Creating sparse files may save disk space and speed up
+the decompression by reducing the amount of disk I/O.
.TP
\fB\-S\fR \fI.suf\fR, \fB\-\-suffix=\fI.suf
When compressing, use
@@ -366,11 +453,12 @@ as the suffix for the target file instead of
.B .xz
or
.BR .lzma .
-If not writing to standard output and the source file already has the suffix
+If not writing to standard output and
+the source file already has the suffix
.IR .suf ,
a warning is displayed and the file is skipped.
-.IP
-When decompressing, recognize also files with the suffix
+.IP ""
+When decompressing, recognize files with the suffix
.I .suf
in addition to files with the
.BR .xz ,
@@ -378,13 +466,15 @@ in addition to files with the
.BR .lzma ,
or
.B .tlz
-suffix. If the source file has the suffix
+suffix.
+If the source file has the suffix
.IR .suf ,
the suffix is removed to get the target filename.
-.IP
+.IP ""
When compressing or decompressing raw streams
.RB ( \-\-format=raw ),
-the suffix must always be specified unless writing to standard output,
+the suffix must always be specified unless
+writing to standard output,
because there is no default suffix for raw streams.
.TP
\fB\-\-files\fR[\fB=\fIfile\fR]
@@ -392,8 +482,9 @@ Read the filenames to process from
.IR file ;
if
.I file
-is omitted, filenames are read from standard input. Filenames must be
-terminated with the newline character. A dash
+is omitted, filenames are read from standard input.
+Filenames must be terminated with the newline character.
+A dash
.RB ( \- )
is taken as a regular filename; it doesn't mean standard input.
If filenames are given also as command line arguments, they are
@@ -401,53 +492,62 @@ processed before the filenames read from
.IR file .
.TP
\fB\-\-files0\fR[\fB=\fIfile\fR]
-This is identical to \fB\-\-files\fR[\fB=\fIfile\fR] except that the
-filenames must be terminated with the null character.
+This is identical to \fB\-\-files\fR[\fB=\fIfile\fR] except
+that each filename must be terminated with the null character.
+.
.SS "Basic file format and compression options"
.TP
\fB\-F\fR \fIformat\fR, \fB\-\-format=\fIformat
-Specify the file format to compress or decompress:
+Specify the file
+.I format
+to compress or decompress:
.RS
-.IP \(bu 3
-.BR auto :
-This is the default. When compressing,
+.TP
+.B auto
+This is the default.
+When compressing,
.B auto
is equivalent to
.BR xz .
-When decompressing, the format of the input file is automatically detected.
+When decompressing,
+the format of the input file is automatically detected.
Note that raw streams (created with
.BR \-\-format=raw )
cannot be auto-detected.
-.IP \(bu 3
-.BR xz :
+.TP
+.B xz
Compress to the
.B .xz
file format, or accept only
.B .xz
files when decompressing.
-.IP \(bu 3
-.B lzma
-or
-.BR alone :
+.TP
+.BR lzma ", " alone
Compress to the legacy
.B .lzma
file format, or accept only
.B .lzma
-files when decompressing. The alternative name
+files when decompressing.
+The alternative name
.B alone
is provided for backwards compatibility with LZMA Utils.
-.IP \(bu 3
-.BR raw :
-Compress or uncompress a raw stream (no headers). This is meant for advanced
-users only. To decode raw streams, you need to set not only
+.TP
+.B raw
+Compress or uncompress a raw stream (no headers).
+This is meant for advanced users only.
+To decode raw streams, you need use
.B \-\-format=raw
-but also specify the filter chain, which would normally be stored in the
-container format headers.
+and explicitly specify the filter chain,
+which normally would have been stored in the container headers.
.RE
.TP
\fB\-C\fR \fIcheck\fR, \fB\-\-check=\fIcheck
-Specify the type of the integrity check, which is calculated from the
-uncompressed data. This option has an effect only when compressing into the
+Specify the type of the integrity check.
+The check is calculated from the uncompressed data and
+stored in the
+.B .xz
+file.
+This option has an effect only when compressing into the
.B .xz
format; the
.B .lzma
@@ -455,235 +555,406 @@ format doesn't support integrity checks.
The integrity check (if any) is verified when the
.B .xz
file is decompressed.
-.IP
+.IP ""
Supported
.I check
types:
.RS
-.IP \(bu 3
-.BR none :
-Don't calculate an integrity check at all. This is usually a bad idea. This
-can be useful when integrity of the data is verified by other means anyway.
-.IP \(bu 3
-.BR crc32 :
+.TP
+.B none
+Don't calculate an integrity check at all.
+This is usually a bad idea.
+This can be useful when integrity of the data is verified
+by other means anyway.
+.TP
+.B crc32
Calculate CRC32 using the polynomial from IEEE-802.3 (Ethernet).
-.IP \(bu 3
-.BR crc64 :
-Calculate CRC64 using the polynomial from ECMA-182. This is the default, since
-it is slightly better than CRC32 at detecting damaged files and the speed
-difference is negligible.
-.IP \(bu 3
-.BR sha256 :
-Calculate SHA-256. This is somewhat slower than CRC32 and CRC64.
+.TP
+.B crc64
+Calculate CRC64 using the polynomial from ECMA-182.
+This is the default, since it is slightly better than CRC32
+at detecting damaged files and the speed difference is negligible.
+.TP
+.B sha256
+Calculate SHA-256.
+This is somewhat slower than CRC32 and CRC64.
.RE
-.IP
+.IP ""
Integrity of the
.B .xz
-headers is always verified with CRC32. It is not possible to change or
-disable it.
+headers is always verified with CRC32.
+It is not possible to change or disable it.
.TP
.BR \-0 " ... " \-9
-Select compression preset. If a preset level is specified multiple times,
+Select a compression preset level.
+The default is
+.BR \-6 .
+If multiple preset levels are specified,
the last one takes effect.
-.IP
-The compression preset levels can be categorised roughly into three
-categories:
-.RS
-.IP "\fB\-0\fR ... \fB\-2"
-Fast presets with relatively low memory usage.
-.B \-1
+If a custom filter chain was already specified, setting
+a compression preset level clears the custom filter chain.
+.IP ""
+The differences between the presets are more significant than with
+.BR gzip (1)
and
-.B \-2
-should give compression speed and ratios comparable to
-.B "bzip2 \-1"
+.BR bzip2 (1).
+The selected compression settings determine
+the memory requirements of the decompressor,
+thus using a too high preset level might make it painful
+to decompress the file on an old system with little RAM.
+Specifically,
+.B "it's not a good idea to blindly use \-9 for everything"
+like it often is with
+.BR gzip (1)
and
-.BR "bzip2 \-9" ,
-respectively.
-Currently
-.B \-0
-is not very good (not much faster than
-.B \-1
-but much worse compression). In future,
+.BR bzip2 (1).
+.RS
+.TP
+.BR "\-0" " ... " "\-3"
+These are somewhat fast presets.
.B \-0
-may be indicate some fast algorithm instead of LZMA2.
-.IP "\fB\-3\fR ... \fB\-5"
-Good compression ratio with low to medium memory usage.
-These are significantly slower than levels 0\-2.
-.IP "\fB\-6\fR ... \fB\-9"
-Excellent compression with medium to high memory usage. These are also
-slower than the lower preset levels. The default is
-.BR \-6 .
-Unless you want to maximize the compression ratio, you probably don't want
-a higher preset level than
-.B \-7
-due to speed and memory usage.
+is sometimes faster than
+.B "gzip \-9"
+while compressing much better.
+The higher ones often have speed comparable to
+.BR bzip2 (1)
+with comparable or better compression ratio,
+although the results
+depend a lot on the type of data being compressed.
+.TP
+.BR "\-4" " ... " "\-6"
+Good to very good compression while keeping
+decompressor memory usage reasonable even for old systems.
+.B \-6
+is the default, which is usually a good choice
+e.g. for distributing files that need to be decompressible
+even on systems with only 16\ MiB RAM.
+.RB ( \-5e
+or
+.B \-6e
+may be worth considering too.
+See
+.BR \-\-extreme .)
+.TP
+.B "\-7 ... \-9"
+These are like
+.B \-6
+but with higher compressor and decompressor memory requirements.
+These are useful only when compressing files bigger than
+8\ MiB, 16\ MiB, and 32\ MiB, respectively.
.RE
-.IP
-The exact compression settings (filter chain) used by each preset may
-vary between
-.B xz
-versions. The settings may also vary between files being compressed, if
-.B xz
-determines that modified settings will probably give better compression
-ratio without significantly affecting compression time or memory usage.
-.IP
-Because the settings may vary, the memory usage may vary too. The following
-table lists the maximum memory usage of each preset level, which won't be
-exceeded even in future versions of
-.BR xz .
-.IP
-.B "FIXME: The table below is just a rough idea."
+.IP ""
+On the same hardware, the decompression speed is approximately
+a constant number of bytes of compressed data per second.
+In other words, the better the compression,
+the faster the decompression will usually be.
+This also means that the amount of uncompressed output
+produced per second can vary a lot.
+.IP ""
+The following table summarises the features of the presets:
.RS
.RS
+.PP
.TS
tab(;);
-c c c
-n n n.
-Preset;Compression;Decompression
-\-0;6 MiB;1 MiB
-\-1;6 MiB;1 MiB
-\-2;10 MiB;1 MiB
-\-3;20 MiB;2 MiB
-\-4;30 MiB;3 MiB
-\-5;60 MiB;6 MiB
-\-6;100 MiB;10 MiB
-\-7;200 MiB;20 MiB
-\-8;400 MiB;40 MiB
-\-9;800 MiB;80 MiB
+c c c c c
+n n n n n.
+Preset;DictSize;CompCPU;CompMem;DecMem
+\-0;256 KiB;0;3 MiB;1 MiB
+\-1;1 MiB;1;9 MiB;2 MiB
+\-2;2 MiB;2;17 MiB;3 MiB
+\-3;4 MiB;3;32 MiB;5 MiB
+\-4;4 MiB;4;48 MiB;5 MiB
+\-5;8 MiB;5;94 MiB;9 MiB
+\-6;8 MiB;6;94 MiB;9 MiB
+\-7;16 MiB;6;186 MiB;17 MiB
+\-8;32 MiB;6;370 MiB;33 MiB
+\-9;64 MiB;6;674 MiB;65 MiB
.TE
.RE
.RE
-.IP
-When compressing,
+.IP ""
+Column descriptions:
+.RS
+.IP \(bu 3
+DictSize is the LZMA2 dictionary size.
+It is waste of memory to use a dictionary bigger than
+the size of the uncompressed file.
+This is why it is good to avoid using the presets
+.BR \-7 " ... " \-9
+when there's no real need for them.
+At
+.B \-6
+and lower, the amount of memory wasted is
+usually low enough to not matter.
+.IP \(bu 3
+CompCPU is a simplified representation of the LZMA2 settings
+that affect compression speed.
+The dictionary size affects speed too,
+so while CompCPU is the same for levels
+.BR \-6 " ... " \-9 ,
+higher levels still tend to be a little slower.
+To get even slower and thus possibly better compression, see
+.BR \-\-extreme .
+.IP \(bu 3
+CompMem contains the compressor memory requirements
+in the single-threaded mode.
+It may vary slightly between
.B xz
-automatically adjusts the compression settings downwards if
-the memory usage limit would be exceeded, so it is safe to specify
-a high preset level even on systems that don't have lots of RAM.
+versions.
+Memory requirements of some of the future multithreaded modes may
+be dramatically higher than that of the single-threaded mode.
+.IP \(bu 3
+DecMem contains the decompressor memory requirements.
+That is, the compression settings determine
+the memory requirements of the decompressor.
+The exact decompressor memory usage is slighly more than
+the LZMA2 dictionary size, but the values in the table
+have been rounded up to the next full MiB.
+.RE
+.TP
+.BR \-e ", " \-\-extreme
+Use a slower variant of the selected compression preset level
+.RB ( \-0 " ... " \-9 )
+to hopefully get a little bit better compression ratio,
+but with bad luck this can also make it worse.
+Decompressor memory usage is not affected,
+but compressor memory usage increases a little at preset levels
+.BR \-0 " ... " \-3 .
+.IP ""
+Since there are two presets with dictionary sizes
+4\ MiB and 8\ MiB, the presets
+.B \-3e
+and
+.B \-5e
+use slightly faster settings (lower CompCPU) than
+.B \-4e
+and
+.BR \-6e ,
+respectively.
+That way no two presets are identical.
+.RS
+.RS
+.PP
+.TS
+tab(;);
+c c c c c
+n n n n n.
+Preset;DictSize;CompCPU;CompMem;DecMem
+\-0e;256 KiB;8;4 MiB;1 MiB
+\-1e;1 MiB;8;13 MiB;2 MiB
+\-2e;2 MiB;8;25 MiB;3 MiB
+\-3e;4 MiB;7;48 MiB;5 MiB
+\-4e;4 MiB;8;48 MiB;5 MiB
+\-5e;8 MiB;7;94 MiB;9 MiB
+\-6e;8 MiB;8;94 MiB;9 MiB
+\-7e;16 MiB;8;186 MiB;17 MiB
+\-8e;32 MiB;8;370 MiB;33 MiB
+\-9e;64 MiB;8;674 MiB;65 MiB
+.TE
+.RE
+.RE
+.IP ""
+For example, there are a total of four presets that use
+8\ MiB dictionary, whose order from the fastest to the slowest is
+.BR \-5 ,
+.BR \-6 ,
+.BR \-5e ,
+and
+.BR \-6e .
.TP
-.BR \-\-fast " and " \-\-best
+.B \-\-fast
+.PD 0
+.TP
+.B \-\-best
+.PD
These are somewhat misleading aliases for
.B \-0
and
.BR \-9 ,
respectively.
-These are provided only for backwards compatibility with LZMA Utils.
+These are provided only for backwards compatibility
+with LZMA Utils.
Avoid using these options.
-.IP
-Especially the name of
-.B \-\-best
-is misleading, because the definition of best depends on the input data,
-and that usually people don't want the very best compression ratio anyway,
-because it would be very slow.
.TP
-.BR \-e ", " \-\-extreme
-Modify the compression preset (\fB\-0\fR ... \fB\-9\fR) so that a little bit
-better compression ratio can be achieved without increasing memory usage
-of the compressor or decompressor (exception: compressor memory usage may
-increase a little with presets \fB\-0\fR ... \fB\-2\fR). The downside is that
-the compression time will increase dramatically (it can easily double).
-.TP
-\fB\-M\fR \fIlimit\fR, \fB\-\-memory=\fIlimit
-Set the memory usage limit. If this option is specified multiple times,
-the last one takes effect. The
+.BI \-\-memlimit\-compress= limit
+Set a memory usage limit for compression.
+If this option is specified multiple times,
+the last one takes effect.
+.IP ""
+If the compression settings exceed the
+.IR limit ,
+.B xz
+will adjust the settings downwards so that
+the limit is no longer exceeded and display a notice that
+automatic adjustment was done.
+Such adjustments are not made when compressing with
+.B \-\-format=raw
+or if
+.B \-\-no\-adjust
+has been specified.
+In those cases, an error is displayed and
+.B xz
+will exit with exit status 1.
+.IP ""
+The
.I limit
can be specified in multiple ways:
.RS
.IP \(bu 3
The
.I limit
-can be an absolute value in bytes. Using an integer suffix like
+can be an absolute value in bytes.
+Using an integer suffix like
.B MiB
-can be useful. Example:
-.B "\-\-memory=80MiB"
+can be useful.
+Example:
+.B "\-\-memlimit\-compress=80MiB"
.IP \(bu 3
The
.I limit
-can be specified as a percentage of physical RAM. Example:
-.B "\-\-memory=70%"
+can be specified as a percentage of total physical memory (RAM).
+This can be useful especially when setting the
+.B XZ_DEFAULTS
+environment variable in a shell initialization script
+that is shared between different computers.
+That way the limit is automatically bigger
+on systems with more memory.
+Example:
+.B "\-\-memlimit\-compress=70%"
.IP \(bu 3
The
.I limit
can be reset back to its default value by setting it to
.BR 0 .
-See the section
-.B "Memory usage"
-for how the default limit is defined.
-.IP \(bu 3
-The memory usage limiting can be effectively disabled by setting
+This is currently equivalent to setting the
.I limit
to
-.BR max .
-This isn't recommended. It's usually better to use, for example,
-.BR \-\-memory=90% .
+.B max
+(no memory usage limit).
+Once multithreading support has been implemented,
+there may be a difference between
+.B 0
+and
+.B max
+for the multithreaded case, so it is recommended to use
+.B 0
+instead of
+.B max
+until the details have been decided.
.RE
-.IP
-The current
-.I limit
-can be seen near the bottom of the output of the
-.B \-\-long-help
-option.
+.IP ""
+See also the section
+.BR "Memory usage" .
+.TP
+.BI \-\-memlimit\-decompress= limit
+Set a memory usage limit for decompression.
+This also affects the
+.B \-\-list
+mode.
+If the operation is not possible without exceeding the
+.IR limit ,
+.B xz
+will display an error and decompressing the file will fail.
+See
+.BI \-\-memlimit\-compress= limit
+for possible ways to specify the
+.IR limit .
+.TP
+\fB\-M\fR \fIlimit\fR, \fB\-\-memlimit=\fIlimit\fR, \fB\-\-memory=\fIlimit
+This is equivalent to specifying \fB\-\-memlimit\-compress=\fIlimit
+\fB\-\-memlimit\-decompress=\fIlimit\fR.
+.TP
+.B \-\-no\-adjust
+Display an error and exit if the compression settings exceed the
+the memory usage limit.
+The default is to adjust the settings downwards so
+that the memory usage limit is not exceeded.
+Automatic adjusting is always disabled when creating raw streams
+.RB ( \-\-format=raw ).
.TP
\fB\-T\fR \fIthreads\fR, \fB\-\-threads=\fIthreads
-Specify the maximum number of worker threads to use. The default is
-the number of available CPU cores. You can see the current value of
-.I threads
-near the end of the output of the
-.B \-\-long\-help
-option.
-.IP
-The actual number of worker threads can be less than
+Specify the number of worker threads to use.
+The actual number of threads can be less than
.I threads
if using more threads would exceed the memory usage limit.
-In addition to CPU-intensive worker threads,
-.B xz
-may use a few auxiliary threads, which don't use a lot of CPU time.
-.IP
-.B "Multithreaded compression and decompression are not implemented yet,"
-.B "so this option has no effect for now."
-.SS Custom compressor filter chains
-A custom filter chain allows specifying the compression settings in detail
-instead of relying on the settings associated to the preset levels.
-When a custom filter chain is specified, the compression preset level options
-(\fB\-0\fR ... \fB\-9\fR and \fB\-\-extreme\fR) are silently ignored.
-.PP
-A filter chain is comparable to piping on the UN*X command line.
-When compressing, the uncompressed input goes to the first filter, whose
-output goes to the next filter (if any). The output of the last filter
-gets written to the compressed file. The maximum number of filters in
-the chain is four, but typically a filter chain has only one or two filters.
-.PP
-Many filters have limitations where they can be in the filter chain:
-some filters can work only as the last filter in the chain, some only
-as a non-last filter, and some work in any position in the chain. Depending
-on the filter, this limitation is either inherent to the filter design or
-exists to prevent security issues.
-.PP
-A custom filter chain is specified by using one or more filter options in
-the order they are wanted in the filter chain. That is, the order of filter
-options is significant! When decoding raw streams
+.IP ""
+.B "Multithreaded compression and decompression are not"
+.B "implemented yet, so this option has no effect for now."
+.IP ""
+.B "As of writing (2010-09-27), it hasn't been decided"
+.B "if threads will be used by default on multicore systems"
+.B "once support for threading has been implemented."
+.B "Comments are welcome."
+The complicating factor is that using many threads
+will increase the memory usage dramatically.
+Note that if multithreading will be the default,
+it will probably be done so that single-threaded and
+multithreaded modes produce the same output,
+so compression ratio won't be significantly affected
+if threading will be enabled by default.
+.
+.SS "Custom compressor filter chains"
+A custom filter chain allows specifying
+the compression settings in detail instead of relying on
+the settings associated to the preset levels.
+When a custom filter chain is specified,
+the compression preset level options
+(\fB\-0\fR ... \fB\-9\fR and \fB\-\-extreme\fR) are
+silently ignored.
+.PP
+A filter chain is comparable to piping on the command line.
+When compressing, the uncompressed input goes to the first filter,
+whose output goes to the next filter (if any).
+The output of the last filter gets written to the compressed file.
+The maximum number of filters in the chain is four,
+but typically a filter chain has only one or two filters.
+.PP
+Many filters have limitations on where they can be
+in the filter chain:
+some filters can work only as the last filter in the chain,
+some only as a non-last filter, and some work in any position
+in the chain.
+Depending on the filter, this limitation is either inherent to
+the filter design or exists to prevent security issues.
+.PP
+A custom filter chain is specified by using one or more
+filter options in the order they are wanted in the filter chain.
+That is, the order of filter options is significant!
+When decoding raw streams
.RB ( \-\-format=raw ),
-the filter chain is specified in the same order as it was specified when
-compressing.
+the filter chain is specified in the same order as
+it was specified when compressing.
.PP
Filters take filter-specific
.I options
-as a comma-separated list. Extra commas in
+as a comma-separated list.
+Extra commas in
.I options
-are ignored. Every option has a default value, so you need to
+are ignored.
+Every option has a default value, so you need to
specify only those you want to change.
.TP
-\fB\-\-lzma1\fR[\fB=\fIoptions\fR], \fB\-\-lzma2\fR[\fB=\fIoptions\fR]
-Add LZMA1 or LZMA2 filter to the filter chain. These filter can be used
-only as the last filter in the chain.
-.IP
-LZMA1 is a legacy filter, which is supported almost solely due to the legacy
+\fB\-\-lzma1\fR[\fB=\fIoptions\fR]
+.PD 0
+.TP
+\fB\-\-lzma2\fR[\fB=\fIoptions\fR]
+.PD
+Add LZMA1 or LZMA2 filter to the filter chain.
+These filters can be used only as the last filter in the chain.
+.IP ""
+LZMA1 is a legacy filter,
+which is supported almost solely due to the legacy
.B .lzma
-file format, which supports only LZMA1. LZMA2 is an updated
-version of LZMA1 to fix some practical issues of LZMA1. The
+file format, which supports only LZMA1.
+LZMA2 is an updated
+version of LZMA1 to fix some practical issues of LZMA1.
+The
.B .xz
-format uses LZMA2, and doesn't support LZMA1 at all. Compression speed and
-ratios of LZMA1 and LZMA2 are practically the same.
-.IP
+format uses LZMA2 and doesn't support LZMA1 at all.
+Compression speed and ratios of LZMA1 and LZMA2
+are practically the same.
+.IP ""
LZMA1 and LZMA2 share the same set of
.IR options :
.RS
@@ -694,8 +965,9 @@ Reset all LZMA1 or LZMA2
to
.IR preset .
.I Preset
-consist of an integer, which may be followed by single-letter preset
-modifiers. The integer can be from
+consist of an integer, which may be followed by single-letter
+preset modifiers.
+The integer can be from
.B 0
to
.BR 9 ,
@@ -704,7 +976,6 @@ The only supported modifier is currently
.BR e ,
which matches
.BR \-\-extreme .
-.IP
The default
.I preset
is
@@ -714,84 +985,155 @@ from which the default values for the rest of the LZMA1 or LZMA2
are taken.
.TP
.BI dict= size
-Dictionary (history buffer) size indicates how many bytes of the recently
-processed uncompressed data is kept in memory. One method to reduce size of
-the uncompressed data is to store distance-length pairs, which
-indicate what data to repeat from the dictionary buffer. The bigger
-the dictionary, the better the compression ratio usually is,
-but dictionaries bigger than the uncompressed data are waste of RAM.
-.IP
-Typical dictionary size is from 64 KiB to 64 MiB. The minimum is 4 KiB.
-The maximum for compression is currently 1.5 GiB. The decompressor already
-supports dictionaries up to one byte less than 4 GiB, which is the
-maximum for LZMA1 and LZMA2 stream formats.
-.IP
-Dictionary size has the biggest effect on compression ratio.
-Dictionary size and match finder together determine the memory usage of
-the LZMA1 or LZMA2 encoder. The same dictionary size is required
-for decompressing that was used when compressing, thus the memory usage of
-the decoder is determined by the dictionary size used when compressing.
+Dictionary (history buffer)
+.I size
+indicates how many bytes of the recently processed
+uncompressed data is kept in memory.
+The algorithm tries to find repeating byte sequences (matches) in
+the uncompressed data, and replace them with references
+to the data currently in the dictionary.
+The bigger the dictionary, the higher is the chance
+to find a match.
+Thus, increasing dictionary
+.I size
+usually improves compression ratio, but
+a dictionary bigger than the uncompressed file is waste of memory.
+.IP ""
+Typical dictionary
+.I size
+is from 64\ KiB to 64\ MiB.
+The minimum is 4\ KiB.
+The maximum for compression is currently 1.5\ GiB (1536\ MiB).
+The decompressor already supports dictionaries up to
+one byte less than 4\ GiB, which is the maximum for
+the LZMA1 and LZMA2 stream formats.
+.IP ""
+Dictionary
+.I size
+and match finder
+.RI ( mf )
+together determine the memory usage of the LZMA1 or LZMA2 encoder.
+The same (or bigger) dictionary
+.I size
+is required for decompressing that was used when compressing,
+thus the memory usage of the decoder is determined
+by the dictionary size used when compressing.
+The
+.B .xz
+headers store the dictionary
+.I size
+either as
+.RI "2^" n
+or
+.RI "2^" n " + 2^(" n "\-1),"
+so these
+.I sizes
+are somewhat preferred for compression.
+Other
+.I sizes
+will get rounded up when stored in the
+.B .xz
+headers.
.TP
.BI lc= lc
-Specify the number of literal context bits. The minimum is
-.B 0
-and the maximum is
-.BR 4 ;
-the default is
-.BR 3 .
+Specify the number of literal context bits.
+The minimum is 0 and the maximum is 4; the default is 3.
In addition, the sum of
.I lc
and
.I lp
-must not exceed
-.BR 4 .
+must not exceed 4.
+.IP ""
+All bytes that cannot be encoded as matches
+are encoded as literals.
+That is, literals are simply 8-bit bytes
+that are encoded one at a time.
+.IP ""
+The literal coding makes an assumption that the highest
+.I lc
+bits of the previous uncompressed byte correlate
+with the next byte.
+E.g. in typical English text, an upper-case letter is
+often followed by a lower-case letter, and a lower-case
+letter is usually followed by another lower-case letter.
+In the US-ASCII character set, the highest three bits are 010
+for upper-case letters and 011 for lower-case letters.
+When
+.I lc
+is at least 3, the literal coding can take advantage of
+this property in the uncompressed data.
+.IP ""
+The default value (3) is usually good.
+If you want maximum compression, test
+.BR lc=4 .
+Sometimes it helps a little, and
+sometimes it makes compression worse.
+If it makes it worse, test e.g.\&
+.B lc=2
+too.
.TP
.BI lp= lp
-Specify the number of literal position bits. The minimum is
-.B 0
-and the maximum is
-.BR 4 ;
-the default is
-.BR 0 .
+Specify the number of literal position bits.
+The minimum is 0 and the maximum is 4; the default is 0.
+.IP ""
+.I Lp
+affects what kind of alignment in the uncompressed data is
+assumed when encoding literals.
+See
+.I pb
+below for more information about alignment.
.TP
.BI pb= pb
-Specify the number of position bits. The minimum is
-.B 0
-and the maximum is
-.BR 4 ;
-the default is
-.BR 2 .
-.TP
-.BI mode= mode
-Compression
-.I mode
-specifies the function used to analyze the data produced by the match finder.
-Supported
-.I modes
-are
-.B fast
-and
-.BR normal .
-The default is
-.B fast
-for
-.I presets
-.BR 0 \- 2
+Specify the number of position bits.
+The minimum is 0 and the maximum is 4; the default is 2.
+.IP ""
+.I Pb
+affects what kind of alignment in the uncompressed data is
+assumed in general.
+The default means four-byte alignment
+.RI (2^ pb =2^2=4),
+which is often a good choice when there's no better guess.
+.IP ""
+When the aligment is known, setting
+.I pb
+accordingly may reduce the file size a little.
+E.g. with text files having one-byte
+alignment (US-ASCII, ISO-8859-*, UTF-8), setting
+.B pb=0
+can improve compression slightly.
+For UTF-16 text,
+.B pb=1
+is a good choice.
+If the alignment is an odd number like 3 bytes,
+.B pb=0
+might be the best choice.
+.IP ""
+Even though the assumed alignment can be adjusted with
+.I pb
and
-.B normal
-for
-.I presets
-.BR 3 \- 9 .
+.IR lp ,
+LZMA1 and LZMA2 still slightly favor 16-byte alignment.
+It might be worth taking into account when designing file formats
+that are likely to be often compressed with LZMA1 or LZMA2.
.TP
.BI mf= mf
-Match finder has a major effect on encoder speed, memory usage, and
-compression ratio. Usually Hash Chain match finders are faster than
-Binary Tree match finders. Hash Chains are usually used together with
-.B mode=fast
-and Binary Trees with
-.BR mode=normal .
-The memory usage formulas are only rough estimates,
-which are closest to reality when
+Match finder has a major effect on encoder speed,
+memory usage, and compression ratio.
+Usually Hash Chain match finders are faster than Binary Tree
+match finders.
+The default depends on the
+.IR preset :
+0 uses
+.BR hc3 ,
+1\-3
+use
+.BR hc4 ,
+and the rest use
+.BR bt4 .
+.IP ""
+The following match finders are supported.
+The memory usage formulas below are rough approximations,
+which are closest to the reality when
.I dict
is a power of two.
.RS
@@ -804,6 +1146,7 @@ Minimum value for
3
.br
Memory usage:
+.br
.I dict
* 7.5 (if
.I dict
@@ -822,8 +1165,16 @@ Minimum value for
4
.br
Memory usage:
+.br
+.I dict
+* 7.5 (if
.I dict
-* 7.5
+<= 32 MiB);
+.br
+.I dict
+* 6.5 (if
+.I dict
+> 32 MiB)
.TP
.B bt2
Binary Tree with 2-byte hashing
@@ -844,6 +1195,7 @@ Minimum value for
3
.br
Memory usage:
+.br
.I dict
* 11.5 (if
.I dict
@@ -862,53 +1214,96 @@ Minimum value for
4
.br
Memory usage:
+.br
.I dict
-* 11.5
+* 11.5 (if
+.I dict
+<= 32 MiB);
+.br
+.I dict
+* 10.5 (if
+.I dict
+> 32 MiB)
.RE
.TP
+.BI mode= mode
+Compression
+.I mode
+specifies the method to analyze
+the data produced by the match finder.
+Supported
+.I modes
+are
+.B fast
+and
+.BR normal .
+The default is
+.B fast
+for
+.I presets
+0\-3 and
+.B normal
+for
+.I presets
+4\-9.
+.IP ""
+Usually
+.B fast
+is used with Hash Chain match finders and
+.B normal
+with Binary Tree match finders.
+This is also what the
+.I presets
+do.
+.TP
.BI nice= nice
-Specify what is considered to be a nice length for a match. Once a match
-of at least
-.I nice
-bytes is found, the algorithm stops looking for possibly better matches.
-.IP
+Specify what is considered to be a nice length for a match.
+Once a match of at least
.I nice
-can be 2\-273 bytes. Higher values tend to give better compression ratio
-at expense of speed. The default depends on the
-.I preset
-level.
+bytes is found, the algorithm stops
+looking for possibly better matches.
+.IP ""
+.I Nice
+can be 2\-273 bytes.
+Higher values tend to give better compression ratio
+at the expense of speed.
+The default depends on the
+.IR preset .
.TP
.BI depth= depth
-Specify the maximum search depth in the match finder. The default is the
-special value
-.BR 0 ,
+Specify the maximum search depth in the match finder.
+The default is the special value of 0,
which makes the compressor determine a reasonable
.I depth
from
.I mf
and
.IR nice .
-.IP
+.IP ""
+Reasonable
+.I depth
+for Hash Chains is 4\-100 and 16\-1000 for Binary Trees.
Using very high values for
.I depth
-can make the encoder extremely slow with carefully crafted files.
+can make the encoder extremely slow with some files.
Avoid setting the
.I depth
-over 1000 unless you are prepared to interrupt the compression in case it
-is taking too long.
+over 1000 unless you are prepared to interrupt
+the compression in case it is taking far too long.
.RE
-.IP
+.IP ""
When decoding raw streams
.RB ( \-\-format=raw ),
-LZMA2 needs only the value of
-.BR dict .
+LZMA2 needs only the dictionary
+.IR size .
LZMA1 needs also
-.BR lc ,
-.BR lp ,
+.IR lc ,
+.IR lp ,
and
-.BR pb.
+.IR pb .
.TP
\fB\-\-x86\fR[\fB=\fIoptions\fR]
+.PD 0
.TP
\fB\-\-powerpc\fR[\fB=\fIoptions\fR]
.TP
@@ -919,28 +1314,72 @@ and
\fB\-\-armthumb\fR[\fB=\fIoptions\fR]
.TP
\fB\-\-sparc\fR[\fB=\fIoptions\fR]
-Add a branch/call/jump (BCJ) filter to the filter chain. These filters
-can be used only as non-last filter in the filter chain.
-.IP
-A BCJ filter converts relative addresses in the machine code to their
-absolute counterparts. This doesn't change the size of the data, but
-it increases redundancy, which allows e.g. LZMA2 to get better
-compression ratio.
-.IP
-The BCJ filters are always reversible, so using a BCJ filter for wrong
-type of data doesn't cause any data loss. However, applying a BCJ filter
-for wrong type of data is a bad idea, because it tends to make the
-compression ratio worse.
-.IP
+.PD
+Add a branch/call/jump (BCJ) filter to the filter chain.
+These filters can be used only as a non-last filter
+in the filter chain.
+.IP ""
+A BCJ filter converts relative addresses in
+the machine code to their absolute counterparts.
+This doesn't change the size of the data,
+but it increases redundancy,
+which can help LZMA2 to produce 0\-15\ % smaller
+.B .xz
+file.
+The BCJ filters are always reversible,
+so using a BCJ filter for wrong type of data
+doesn't cause any data loss, although it may make
+the compression ratio slightly worse.
+.IP ""
+It is fine to apply a BCJ filter on a whole executable;
+there's no need to apply it only on the executable section.
+Applying a BCJ filter on an archive that contains both executable
+and non-executable files may or may not give good results,
+so it generally isn't good to blindly apply a BCJ filter when
+compressing binary packages for distribution.
+.IP ""
+These BCJ filters are very fast and
+use insignificant amount of memory.
+If a BCJ filter improves compression ratio of a file,
+it can improve decompression speed at the same time.
+This is because, on the same hardware,
+the decompression speed of LZMA2 is roughly
+a fixed number of bytes of compressed data per second.
+.IP ""
+These BCJ filters have known problems related to
+the compression ratio:
+.RS
+.IP \(bu 3
+Some types of files containing executable code
+(e.g. object files, static libraries, and Linux kernel modules)
+have the addresses in the instructions filled with filler values.
+These BCJ filters will still do the address conversion,
+which will make the compression worse with these files.
+.IP \(bu 3
+Applying a BCJ filter on an archive containing multiple similar
+executables can make the compression ratio worse than not using
+a BCJ filter.
+This is because the BCJ filter doesn't detect the boundaries
+of the executable files, and doesn't reset
+the address conversion counter for each executable.
+.RE
+.IP ""
+Both of the above problems will be fixed
+in the future in a new filter.
+The old BCJ filters will still be useful in embedded systems,
+because the decoder of the new filter will be bigger
+and use more memory.
+.IP ""
Different instruction sets have have different alignment:
.RS
.RS
+.PP
.TS
tab(;);
l n l
l n l.
Filter;Alignment;Notes
-x86;1;32-bit and 64-bit x86
+x86;1;32-bit or 64-bit x86
PowerPC;4;Big endian only
ARM;4;Little endian only
ARM-Thumb;2;Little endian only
@@ -949,15 +1388,18 @@ SPARC;4;Big or little endian
.TE
.RE
.RE
-.IP
-Since the BCJ-filtered data is usually compressed with LZMA2, the compression
-ratio may be improved slightly if the LZMA2 options are set to match the
-alignment of the selected BCJ filter. For example, with the IA-64 filter,
-it's good to set
+.IP ""
+Since the BCJ-filtered data is usually compressed with LZMA2,
+the compression ratio may be improved slightly if
+the LZMA2 options are set to match the
+alignment of the selected BCJ filter.
+For example, with the IA-64 filter, it's good to set
.B pb=4
-with LZMA2 (2^4=16). The x86 filter is an exception; it's usually good to
-stick to LZMA2's default four-byte alignment when compressing x86 executables.
-.IP
+with LZMA2 (2^4=16).
+The x86 filter is an exception;
+it's usually good to stick to LZMA2's default
+four-byte alignment when compressing x86 executables.
+.IP ""
All BCJ filters support the same
.IR options :
.RS
@@ -965,36 +1407,32 @@ All BCJ filters support the same
.BI start= offset
Specify the start
.I offset
-that is used when converting between relative and absolute addresses.
+that is used when converting between relative
+and absolute addresses.
The
.I offset
-must be a multiple of the alignment of the filter (see the table above).
-The default is zero. In practice, the default is good; specifying
-a custom
+must be a multiple of the alignment of the filter
+(see the table above).
+The default is zero.
+In practice, the default is good; specifying a custom
.I offset
is almost never useful.
-.IP
-Specifying a non-zero start
-.I offset
-is probably useful only if the executable has multiple sections, and there
-are many cross-section jumps or calls. Applying a BCJ filter separately for
-each section with proper start offset and then compressing the result as
-a single chunk may give some improvement in compression ratio compared
-to applying the BCJ filter with the default
-.I offset
-for the whole executable.
.RE
.TP
\fB\-\-delta\fR[\fB=\fIoptions\fR]
-Add Delta filter to the filter chain. The Delta filter
-can be used only as non-last filter in the filter chain.
-.IP
-Currently only simple byte-wise delta calculation is supported. It can
-be useful when compressing e.g. uncompressed bitmap images or uncompressed
-PCM audio. However, special purpose algorithms may give significantly better
-results than Delta + LZMA2. This is true especially with audio, which
-compresses faster and better e.g. with FLAC.
-.IP
+Add the Delta filter to the filter chain.
+The Delta filter can be only used as a non-last filter
+in the filter chain.
+.IP ""
+Currently only simple byte-wise delta calculation is supported.
+It can be useful when compressing e.g. uncompressed bitmap images
+or uncompressed PCM audio.
+However, special purpose algorithms may give significantly better
+results than Delta + LZMA2.
+This is true especially with audio,
+which compresses faster and better e.g. with
+.BR flac (1).
+.IP ""
Supported
.IR options :
.RS
@@ -1002,109 +1440,111 @@ Supported
.BI dist= distance
Specify the
.I distance
-of the delta calculation as bytes.
+of the delta calculation in bytes.
.I distance
-must be 1\-256. The default is 1.
-.IP
+must be 1\-256.
+The default is 1.
+.IP ""
For example, with
.B dist=2
and eight-byte input A1 B1 A2 B3 A3 B5 A4 B7, the output will be
A1 B1 01 02 01 02 01 02.
.RE
+.
.SS "Other options"
.TP
.BR \-q ", " \-\-quiet
-Suppress warnings and notices. Specify this twice to suppress errors too.
-This option has no effect on the exit status. That is, even if a warning
-was suppressed, the exit status to indicate a warning is still used.
+Suppress warnings and notices.
+Specify this twice to suppress errors too.
+This option has no effect on the exit status.
+That is, even if a warning was suppressed,
+the exit status to indicate a warning is still used.
.TP
.BR \-v ", " \-\-verbose
-Be verbose. If standard error is connected to a terminal,
+Be verbose.
+If standard error is connected to a terminal,
.B xz
will display a progress indicator.
Specifying
.B \-\-verbose
-twice will give even more verbose output (useful mostly for debugging).
-.IP
+twice will give even more verbose output.
+.IP ""
The progress indicator shows the following information:
.RS
.IP \(bu 3
-Completion percentage is shown if the size of the input file is known.
-That is, percentage cannot be shown in pipes.
+Completion percentage is shown
+if the size of the input file is known.
+That is, the percentage cannot be shown in pipes.
.IP \(bu 3
-Amount of compressed data produced (compressing) or consumed (decompressing).
+Amount of compressed data produced (compressing)
+or consumed (decompressing).
.IP \(bu 3
-Amount of uncompressed data consumed (compressing) or produced
-(decompressing).
+Amount of uncompressed data consumed (compressing)
+or produced (decompressing).
.IP \(bu 3
-Compression ratio, which is calculated by dividing the amount of
-compressed data processed so far by the amount of uncompressed data
-processed so far.
+Compression ratio, which is calculated by dividing
+the amount of compressed data processed so far by
+the amount of uncompressed data processed so far.
.IP \(bu 3
-Compression or decompression speed. This is measured as the amount of
-uncompressed data consumed (compression) or produced (decompression)
-per second. It is shown once a few seconds have passed since
+Compression or decompression speed.
+This is measured as the amount of uncompressed data consumed
+(compression) or produced (decompression) per second.
+It is shown after a few seconds have passed since
.B xz
started processing the file.
.IP \(bu 3
-Elapsed time or estimated time remaining.
-Elapsed time is displayed in the format M:SS or H:MM:SS.
-The estimated remaining time is displayed in a less precise format
-which never has colons, for example, 2 min 30 s. The estimate can
-be shown only when the size of the input file is known and a couple of
-seconds have already passed since
+Elapsed time in the format M:SS or H:MM:SS.
+.IP \(bu 3
+Estimated remaining time is shown
+only when the size of the input file is
+known and a couple of seconds have already passed since
.B xz
started processing the file.
+The time is shown in a less precise format which
+never has any colons, e.g. 2 min 30 s.
.RE
-.IP
+.IP ""
When standard error is not a terminal,
.B \-\-verbose
will make
.B xz
-print the filename, compressed size, uncompressed size, compression ratio,
-speed, and elapsed time on a single line to standard error after
-compressing or decompressing the file. If operating took at least a few
-seconds, also the speed and elapsed time are printed. If the operation
-didn't finish, for example due to user interruption, also the completion
-percentage is printed if the size of the input file is known.
+print the filename, compressed size, uncompressed size,
+compression ratio, and possibly also the speed and elapsed time
+on a single line to standard error after compressing or
+decompressing the file.
+The speed and elapsed time are included only when
+the operation took at least a few seconds.
+If the operation didn't finish, e.g. due to user interruption,
+also the completion percentage is printed
+if the size of the input file is known.
.TP
.BR \-Q ", " \-\-no\-warn
-Don't set the exit status to
-.B 2
-even if a condition worth a warning was detected. This option doesn't affect
-the verbosity level, thus both
+Don't set the exit status to 2
+even if a condition worth a warning was detected.
+This option doesn't affect the verbosity level, thus both
.B \-\-quiet
and
.B \-\-no\-warn
-have to be used to not display warnings and to not alter the exit status.
+have to be used to not display warnings and
+to not alter the exit status.
.TP
.B \-\-robot
-Print messages in a machine-parsable format. This is intended to ease
-writing frontends that want to use
+Print messages in a machine-parsable format.
+This is intended to ease writing frontends that want to use
.B xz
-instead of liblzma, which may be the case with various scripts. The output
-with this option enabled is meant to be stable across
+instead of liblzma, which may be the case with various scripts.
+The output with this option enabled is meant to be stable across
.B xz
-releases. Currently
-.B \-\-robot
-is implemented only for
-.B \-\-info\-memory
-and
-.BR \-\-version ,
-but the idea is to make it usable for actual compression
-and decompression too.
+releases.
+See the section
+.B "ROBOT MODE"
+for details.
.TP
-.BR \-\-info-memory
-Display the current memory usage limit in human-readable format on
-a single line, and exit successfully. To see how much RAM
+.BR \-\-info\-memory
+Display, in human-readable format, how much physical memory (RAM)
.B xz
-thinks your system has, use
-.BR "\-\-memory=100% \-\-info\-memory" .
-To get machine-parsable output
-(memory usage limit as bytes without thousand separators), specify
-.B \-\-robot
-before
-.BR \-\-info-memory .
+thinks the system has and the memory usage limits for compression
+and decompression, and exit successfully.
.TP
.BR \-h ", " \-\-help
Display a help message describing the most commonly used options,
@@ -1118,10 +1558,337 @@ and exit successfully
.BR \-V ", " \-\-version
Display the version number of
.B xz
-and liblzma in human readable format. To get machine-parsable output, specify
+and liblzma in human readable format.
+To get machine-parsable output, specify
.B \-\-robot
before
.BR \-\-version .
+.
+.SH "ROBOT MODE"
+The robot mode is activated with the
+.B \-\-robot
+option.
+It makes the output of
+.B xz
+easier to parse by other programs.
+Currently
+.B \-\-robot
+is supported only together with
+.BR \-\-version ,
+.BR \-\-info\-memory ,
+and
+.BR \-\-list .
+It will be supported for normal compression and
+decompression in the future.
+.
+.SS Version
+.B "xz \-\-robot \-\-version"
+will print the version number of
+.B xz
+and liblzma in the following format:
+.PP
+.BI XZ_VERSION= XYYYZZZS
+.br
+.BI LIBLZMA_VERSION= XYYYZZZS
+.TP
+.I X
+Major version.
+.TP
+.I YYY
+Minor version.
+Even numbers are stable.
+Odd numbers are alpha or beta versions.
+.TP
+.I ZZZ
+Patch level for stable releases or
+just a counter for development releases.
+.TP
+.I S
+Stability.
+0 is alpha, 1 is beta, and 2 is stable.
+.I S
+should be always 2 when
+.I YYY
+is even.
+.PP
+.I XYYYZZZS
+are the same on both lines if
+.B xz
+and liblzma are from the same XZ Utils release.
+.PP
+Examples: 4.999.9beta is
+.B 49990091
+and
+5.0.0 is
+.BR 50000002 .
+.
+.SS "Memory limit information"
+.B "xz \-\-robot \-\-info\-memory"
+prints a single line with three tab-separated columns:
+.IP 1. 4
+Total amount of physical memory (RAM) in bytes
+.IP 2. 4
+Memory usage limit for compression in bytes.
+A special value of zero indicates the default setting,
+which for single-threaded mode is the same as no limit.
+.IP 3. 4
+Memory usage limit for decompression in bytes.
+A special value of zero indicates the default setting,
+which for single-threaded mode is the same as no limit.
+.PP
+In the future, the output of
+.B "xz \-\-robot \-\-info\-memory"
+may have more columns, but never more than a single line.
+.
+.SS "List mode"
+.B "xz \-\-robot \-\-list"
+uses tab-separated output.
+The first column of every line has a string
+that indicates the type of the information found on that line:
+.TP
+.B name
+This is always the first line when starting to list a file.
+The second column on the line is the filename.
+.TP
+.B file
+This line contains overall information about the
+.B .xz
+file.
+This line is always printed after the
+.B name
+line.
+.TP
+.B stream
+This line type is used only when
+.B \-\-verbose
+was specified.
+There are as many
+.B stream
+lines as there are streams in the
+.B .xz
+file.
+.TP
+.B block
+This line type is used only when
+.B \-\-verbose
+was specified.
+There are as many
+.B block
+lines as there are blocks in the
+.B .xz
+file.
+The
+.B block
+lines are shown after all the
+.B stream
+lines; different line types are not interleaved.
+.TP
+.B summary
+This line type is used only when
+.B \-\-verbose
+was specified twice.
+This line is printed after all
+.B block
+lines.
+Like the
+.B file
+line, the
+.B summary
+line contains overall information about the
+.B .xz
+file.
+.TP
+.B totals
+This line is always the very last line of the list output.
+It shows the total counts and sizes.
+.PP
+The columns of the
+.B file
+lines:
+.PD 0
+.RS
+.IP 2. 4
+Number of streams in the file
+.IP 3. 4
+Total number of blocks in the stream(s)
+.IP 4. 4
+Compressed size of the file
+.IP 5. 4
+Uncompressed size of the file
+.IP 6. 4
+Compression ratio, for example
+.BR 0.123.
+If ratio is over 9.999, three dashes
+.RB ( \-\-\- )
+are displayed instead of the ratio.
+.IP 7. 4
+Comma-separated list of integrity check names.
+The following strings are used for the known check types:
+.BR None ,
+.BR CRC32 ,
+.BR CRC64 ,
+and
+.BR SHA\-256 .
+For unknown check types,
+.BI Unknown\- N
+is used, where
+.I N
+is the Check ID as a decimal number (one or two digits).
+.IP 8. 4
+Total size of stream padding in the file
+.RE
+.PD
+.PP
+The columns of the
+.B stream
+lines:
+.PD 0
+.RS
+.IP 2. 4
+Stream number (the first stream is 1)
+.IP 3. 4
+Number of blocks in the stream
+.IP 4. 4
+Compressed start offset
+.IP 5. 4
+Uncompressed start offset
+.IP 6. 4
+Compressed size (does not include stream padding)
+.IP 7. 4
+Uncompressed size
+.IP 8. 4
+Compression ratio
+.IP 9. 4
+Name of the integrity check
+.IP 10. 4
+Size of stream padding
+.RE
+.PD
+.PP
+The columns of the
+.B block
+lines:
+.PD 0
+.RS
+.IP 2. 4
+Number of the stream containing this block
+.IP 3. 4
+Block number relative to the beginning of the stream
+(the first block is 1)
+.IP 4. 4
+Block number relative to the beginning of the file
+.IP 5. 4
+Compressed start offset relative to the beginning of the file
+.IP 6. 4
+Uncompressed start offset relative to the beginning of the file
+.IP 7. 4
+Total compressed size of the block (includes headers)
+.IP 8. 4
+Uncompressed size
+.IP 9. 4
+Compression ratio
+.IP 10. 4
+Name of the integrity check
+.RE
+.PD
+.PP
+If
+.B \-\-verbose
+was specified twice, additional columns are included on the
+.B block
+lines.
+These are not displayed with a single
+.BR \-\-verbose ,
+because getting this information requires many seeks
+and can thus be slow:
+.PD 0
+.RS
+.IP 11. 4
+Value of the integrity check in hexadecimal
+.IP 12. 4
+Block header size
+.IP 13. 4
+Block flags:
+.B c
+indicates that compressed size is present, and
+.B u
+indicates that uncompressed size is present.
+If the flag is not set, a dash
+.RB ( \- )
+is shown instead to keep the string length fixed.
+New flags may be added to the end of the string in the future.
+.IP 14. 4
+Size of the actual compressed data in the block (this excludes
+the block header, block padding, and check fields)
+.IP 15. 4
+Amount of memory (in bytes) required to decompress
+this block with this
+.B xz
+version
+.IP 16. 4
+Filter chain.
+Note that most of the options used at compression time
+cannot be known, because only the options
+that are needed for decompression are stored in the
+.B .xz
+headers.
+.RE
+.PD
+.PP
+The columns of the
+.B totals
+line:
+.PD 0
+.RS
+.IP 2. 4
+Number of streams
+.IP 3. 4
+Number of blocks
+.IP 4. 4
+Compressed size
+.IP 5. 4
+Uncompressed size
+.IP 6. 4
+Average compression ratio
+.IP 7. 4
+Comma-separated list of integrity check names
+that were present in the files
+.IP 8. 4
+Stream padding size
+.IP 9. 4
+Number of files.
+This is here to
+keep the order of the earlier columns the same as on
+.B file
+lines.
+.PD
+.RE
+.PP
+If
+.B \-\-verbose
+was specified twice, additional columns are included on the
+.B totals
+line:
+.PD 0
+.RS
+.IP 10. 4
+Maximum amount of memory (in bytes) required to decompress
+the files with this
+.B xz
+version
+.IP 11. 4
+.B yes
+or
+.B no
+indicating if all block headers have both compressed size and
+uncompressed size stored in them
+.RE
+.PD
+.PP
+Future versions may add new line types and
+new columns can be added to the existing line types,
+but the existing columns won't be changed.
+.
.SH "EXIT STATUS"
.TP
.B 0
@@ -1131,21 +1898,76 @@ All is good.
An error occurred.
.TP
.B 2
-Something worth a warning occurred, but no actual errors occurred.
+Something worth a warning occurred,
+but no actual errors occurred.
.PP
-Notices (not warnings or errors) printed on standard error don't affect
-the exit status.
+Notices (not warnings or errors) printed on standard error
+don't affect the exit status.
+.
.SH ENVIRONMENT
+.B xz
+parses space-separated lists of options
+from the environment variables
+.B XZ_DEFAULTS
+and
+.BR XZ_OPT ,
+in this order, before parsing the options from the command line.
+Note that only options are parsed from the environment variables;
+all non-options are silently ignored.
+Parsing is done with
+.BR getopt_long (3)
+which is used also for the command line arguments.
+.TP
+.B XZ_DEFAULTS
+User-specific or system-wide default options.
+Typically this is set in a shell initialization script to enable
+.BR xz 's
+memory usage limiter by default.
+Excluding shell initialization scripts
+and similar special cases, scripts must never set or unset
+.BR XZ_DEFAULTS .
.TP
.B XZ_OPT
-A space-separated list of options is parsed from
+This is for passing options to
+.B xz
+when it is not possible to set the options directly on the
+.B xz
+command line.
+This is the case e.g. when
+.B xz
+is run by a script or tool, e.g. GNU
+.BR tar (1):
+.RS
+.RS
+.PP
+.nf
+.ft CW
+XZ_OPT=\-2v tar caf foo.tar.xz foo
+.ft R
+.fi
+.RE
+.RE
+.IP ""
+Scripts may use
.B XZ_OPT
-before parsing the options given on the command line. Note that only
-options are parsed from
-.BR XZ_OPT ;
-all non-options are silently ignored. Parsing is done with
-.BR getopt_long (3)
-which is used also for the command line arguments.
+e.g. to set script-specific default compression options.
+It is still recommended to allow users to override
+.B XZ_OPT
+if that is reasonable, e.g. in
+.BR sh (1)
+scripts one may use something like this:
+.RS
+.RS
+.PP
+.nf
+.ft CW
+XZ_OPT=${XZ_OPT\-"\-7e"}
+export XZ_OPT
+.ft R
+.fi
+.RE
+.RE
+.
.SH "LZMA UTILS COMPATIBILITY"
The command line syntax of
.B xz
@@ -1154,26 +1976,32 @@ is practically a superset of
.BR unlzma ,
and
.BR lzcat
-as found from LZMA Utils 4.32.x. In most cases, it is possible to replace
-LZMA Utils with XZ Utils without breaking existing scripts. There are some
-incompatibilities though, which may sometimes cause problems.
+as found from LZMA Utils 4.32.x.
+In most cases, it is possible to replace
+LZMA Utils with XZ Utils without breaking existing scripts.
+There are some incompatibilities though,
+which may sometimes cause problems.
+.
.SS "Compression preset levels"
The numbering of the compression level presets is not identical in
.B xz
and LZMA Utils.
-The most important difference is how dictionary sizes are mapped to different
-presets. Dictionary size is roughly equal to the decompressor memory usage.
+The most important difference is how dictionary sizes
+are mapped to different presets.
+Dictionary size is roughly equal to the decompressor memory usage.
.RS
+.PP
.TS
tab(;);
c c c
c n n.
Level;xz;LZMA Utils
-\-1;64 KiB;64 KiB
-\-2;512 KiB;1 MiB
-\-3;1 MiB;512 KiB
-\-4;2 MiB;1 MiB
-\-5;4 MiB;2 MiB
+\-0;256 KiB;N/A
+\-1;1 MiB;64 KiB
+\-2;2 MiB;1 MiB
+\-3;4 MiB;512 KiB
+\-4;4 MiB;1 MiB
+\-5;8 MiB;2 MiB
\-6;8 MiB;4 MiB
\-7;16 MiB;8 MiB
\-8;32 MiB;16 MiB
@@ -1181,20 +2009,24 @@ Level;xz;LZMA Utils
.TE
.RE
.PP
-The dictionary size differences affect the compressor memory usage too,
-but there are some other differences between LZMA Utils and XZ Utils, which
+The dictionary size differences affect
+the compressor memory usage too,
+but there are some other differences between
+LZMA Utils and XZ Utils, which
make the difference even bigger:
.RS
+.PP
.TS
tab(;);
c c c
c n n.
Level;xz;LZMA Utils 4.32.x
-\-1;2 MiB;2 MiB
-\-2;5 MiB;12 MiB
-\-3;13 MiB;12 MiB
-\-4;25 MiB;16 MiB
-\-5;48 MiB;26 MiB
+\-0;3 MiB;N/A
+\-1;9 MiB;2 MiB
+\-2;17 MiB;12 MiB
+\-3;32 MiB;12 MiB
+\-4;48 MiB;16 MiB
+\-5;94 MiB;26 MiB
\-6;94 MiB;45 MiB
\-7;186 MiB;83 MiB
\-8;370 MiB;159 MiB
@@ -1206,33 +2038,40 @@ The default preset level in LZMA Utils is
.B \-7
while in XZ Utils it is
.BR \-6 ,
-so both use 8 MiB dictionary by default.
+so both use an 8 MiB dictionary by default.
+.
.SS "Streamed vs. non-streamed .lzma files"
-Uncompressed size of the file can be stored in the
+The uncompressed size of the file can be stored in the
.B .lzma
-header. LZMA Utils does that when compressing regular files.
-The alternative is to mark that uncompressed size is unknown and
-use end of payload marker to indicate where the decompressor should stop.
-LZMA Utils uses this method when uncompressed size isn't known, which is
-the case for example in pipes.
+header.
+LZMA Utils does that when compressing regular files.
+The alternative is to mark that uncompressed size is unknown
+and use end-of-payload marker to indicate
+where the decompressor should stop.
+LZMA Utils uses this method when uncompressed size isn't known,
+which is the case for example in pipes.
.PP
.B xz
supports decompressing
.B .lzma
-files with or without end of payload marker, but all
+files with or without end-of-payload marker, but all
.B .lzma
files created by
.B xz
-will use end of payload marker and have uncompressed size marked as unknown
-in the
+will use end-of-payload marker and have uncompressed size
+marked as unknown in the
.B .lzma
-header. This may be a problem in some (uncommon) situations. For example, a
+header.
+This may be a problem in some uncommon situations.
+For example, a
.B .lzma
-decompressor in an embedded device might work only with files that have known
-uncompressed size. If you hit this problem, you need to use LZMA Utils or
-LZMA SDK to create
+decompressor in an embedded device might work
+only with files that have known uncompressed size.
+If you hit this problem, you need to use LZMA Utils
+or LZMA SDK to create
.B .lzma
files with known uncompressed size.
+.
.SS "Unsupported .lzma files"
The
.B .lzma
@@ -1240,7 +2079,8 @@ format allows
.I lc
values up to 8, and
.I lp
-values up to 4. LZMA Utils can decompress files with any
+values up to 4.
+LZMA Utils can decompress files with any
.I lc
and
.IR lp ,
@@ -1256,24 +2096,25 @@ is possible with
.B xz
and with LZMA SDK.
.PP
-The implementation of the LZMA1 filter in liblzma requires
-that the sum of
+The implementation of the LZMA1 filter in liblzma
+requires that the sum of
.I lc
and
.I lp
-must not exceed 4. Thus,
+must not exceed 4.
+Thus,
.B .lzma
-files which exceed this limitation, cannot be decompressed with
+files, which exceed this limitation, cannot be decompressed with
.BR xz .
.PP
LZMA Utils creates only
.B .lzma
-files which have dictionary size of
+files which have a dictionary size of
.RI "2^" n
-(a power of 2), but accepts files with any dictionary size.
+(a power of 2) but accepts files with any dictionary size.
liblzma accepts only
.B .lzma
-files which have dictionary size of
+files which have a dictionary size of
.RI "2^" n
or
.RI "2^" n " + 2^(" n "\-1)."
@@ -1281,13 +2122,18 @@ This is to decrease false positives when detecting
.B .lzma
files.
.PP
-These limitations shouldn't be a problem in practice, since practically all
+These limitations shouldn't be a problem in practice,
+since practically all
.B .lzma
files have been compressed with settings that liblzma will accept.
+.
.SS "Trailing garbage"
-When decompressing, LZMA Utils silently ignore everything after the first
+When decompressing,
+LZMA Utils silently ignore everything after the first
.B .lzma
-stream. In most situations, this is a bug. This also means that LZMA Utils
+stream.
+In most situations, this is a bug.
+This also means that LZMA Utils
don't support decompressing concatenated
.B .lzma
files.
@@ -1296,34 +2142,46 @@ If there is data left after the first
.B .lzma
stream,
.B xz
-considers the file to be corrupt. This may break obscure scripts which have
+considers the file to be corrupt.
+This may break obscure scripts which have
assumed that trailing garbage is ignored.
+.
.SH NOTES
-.SS Compressed output may vary
-The exact compressed output produced from the same uncompressed input file
-may vary between XZ Utils versions even if compression options are identical.
-This is because the encoder can be improved (faster or better compression)
-without affecting the file format. The output can vary even between different
-builds of the same XZ Utils version, if different build options are used.
+.
+.SS "Compressed output may vary"
+The exact compressed output produced from
+the same uncompressed input file
+may vary between XZ Utils versions even if
+compression options are identical.
+This is because the encoder can be improved
+(faster or better compression)
+without affecting the file format.
+The output can vary even between different
+builds of the same XZ Utils version,
+if different build options are used.
.PP
The above means that implementing
.B \-\-rsyncable
to create rsyncable
.B .xz
-files is not going to happen without freezing a part of the encoder
+files is not going to happen without
+freezing a part of the encoder
implementation, which can then be used with
.BR \-\-rsyncable .
-.SS Embedded .xz decompressors
+.
+.SS "Embedded .xz decompressors"
Embedded
.B .xz
-decompressor implementations like XZ Embedded don't necessarily support files
-created with
+decompressor implementations like XZ Embedded don't necessarily
+support files created with integrity
.I check
types other than
.B none
and
.BR crc32 .
-Since the default is \fB\-\-check=\fIcrc64\fR, you must use
+Since the default is
+.BR \-\-check=crc64 ,
+you must use
.B \-\-check=none
or
.B \-\-check=crc32
@@ -1333,16 +2191,374 @@ Outside embedded systems, all
.B .xz
format decompressors support all the
.I check
-types, or at least are able to decompress the file without verifying the
+types, or at least are able to decompress
+the file without verifying the
integrity check if the particular
.I check
is not supported.
.PP
-XZ Embedded supports BCJ filters, but only with the default start offset.
+XZ Embedded supports BCJ filters,
+but only with the default start offset.
+.
+.SH EXAMPLES
+.
+.SS Basics
+Compress the file
+.I foo
+into
+.I foo.xz
+using the default compression level
+.RB ( \-6 ),
+and remove
+.I foo
+if compression is successful:
+.RS
+.PP
+.nf
+.ft CW
+xz foo
+.ft R
+.fi
+.RE
+.PP
+Decompress
+.I bar.xz
+into
+.I bar
+and don't remove
+.I bar.xz
+even if decompression is successful:
+.RS
+.PP
+.nf
+.ft CW
+xz \-dk bar.xz
+.ft R
+.fi
+.RE
+.PP
+Create
+.I baz.tar.xz
+with the preset
+.B \-4e
+.RB ( "\-4 \-\-extreme" ),
+which is slower than e.g. the default
+.BR \-6 ,
+but needs less memory for compression and decompression (48\ MiB
+and 5\ MiB, respectively):
+.RS
+.PP
+.nf
+.ft CW
+tar cf \- baz | xz \-4e > baz.tar.xz
+.ft R
+.fi
+.RE
+.PP
+A mix of compressed and uncompressed files can be decompressed
+to standard output with a single command:
+.RS
+.PP
+.nf
+.ft CW
+xz \-dcf a.txt b.txt.xz c.txt d.txt.lzma > abcd.txt
+.ft R
+.fi
+.RE
+.
+.SS "Parallel compression of many files"
+On GNU and *BSD,
+.BR find (1)
+and
+.BR xargs (1)
+can be used to parallelize compression of many files:
+.RS
+.PP
+.nf
+.ft CW
+find . \-type f \e! \-name '*.xz' \-print0 \e
+ | xargs \-0r \-P4 \-n16 xz \-T1
+.ft R
+.fi
+.RE
+.PP
+The
+.B \-P
+option to
+.BR xargs (1)
+sets the number of parallel
+.B xz
+processes.
+The best value for the
+.B \-n
+option depends on how many files there are to be compressed.
+If there are only a couple of files,
+the value should probably be 1;
+with tens of thousands of files,
+100 or even more may be appropriate to reduce the number of
+.B xz
+processes that
+.BR xargs (1)
+will eventually create.
+.PP
+The option
+.B \-T1
+for
+.B xz
+is there to force it to single-threaded mode, because
+.BR xargs (1)
+is used to control the amount of parallelization.
+.
+.SS "Robot mode"
+Calculate how many bytes have been saved in total
+after compressing multiple files:
+.RS
+.PP
+.nf
+.ft CW
+xz \-\-robot \-\-list *.xz | awk '/^totals/{print $5\-$4}'
+.ft R
+.fi
+.RE
+.PP
+A script may want to know that it is using new enough
+.BR xz .
+The following
+.BR sh (1)
+script checks that the version number of the
+.B xz
+tool is at least 5.0.0.
+This method is compatible with old beta versions,
+which didn't support the
+.B \-\-robot
+option:
+.RS
+.PP
+.nf
+.ft CW
+if ! eval "$(xz \-\-robot \-\-version 2> /dev/null)" ||
+ [ "$XZ_VERSION" \-lt 50000002 ]; then
+ echo "Your xz is too old."
+fi
+unset XZ_VERSION LIBLZMA_VERSION
+.ft R
+.fi
+.RE
+.PP
+Set a memory usage limit for decompression using
+.BR XZ_OPT ,
+but if a limit has already been set, don't increase it:
+.RS
+.PP
+.nf
+.ft CW
+NEWLIM=$((123 << 20)) # 123 MiB
+OLDLIM=$(xz \-\-robot \-\-info\-memory | cut \-f3)
+if [ $OLDLIM \-eq 0 \-o $OLDLIM \-gt $NEWLIM ]; then
+ XZ_OPT="$XZ_OPT \-\-memlimit\-decompress=$NEWLIM"
+ export XZ_OPT
+fi
+.ft R
+.fi
+.RE
+.
+.SS "Custom compressor filter chains"
+The simplest use for custom filter chains is
+customizing a LZMA2 preset.
+This can be useful,
+because the presets cover only a subset of the
+potentially useful combinations of compression settings.
+.PP
+The CompCPU columns of the tables
+from the descriptions of the options
+.BR "\-0" " ... " "\-9"
+and
+.B \-\-extreme
+are useful when customizing LZMA2 presets.
+Here are the relevant parts collected from those two tables:
+.RS
+.PP
+.TS
+tab(;);
+c c
+n n.
+Preset;CompCPU
+\-0;0
+\-1;1
+\-2;2
+\-3;3
+\-4;4
+\-5;5
+\-6;6
+\-5e;7
+\-6e;8
+.TE
+.RE
+.PP
+If you know that a file requires
+somewhat big dictionary (e.g. 32 MiB) to compress well,
+but you want to compress it quicker than
+.B "xz \-8"
+would do, a preset with a low CompCPU value (e.g. 1)
+can be modified to use a bigger dictionary:
+.RS
+.PP
+.nf
+.ft CW
+xz \-\-lzma2=preset=1,dict=32MiB foo.tar
+.ft R
+.fi
+.RE
+.PP
+With certain files, the above command may be faster than
+.B "xz \-6"
+while compressing significantly better.
+However, it must be emphasized that only some files benefit from
+a big dictionary while keeping the CompCPU value low.
+The most obvious situation,
+where a big dictionary can help a lot,
+is an archive containing very similar files
+of at least a few megabytes each.
+The dictionary size has to be significantly bigger
+than any individual file to allow LZMA2 to take
+full advantage of the similarities between consecutive files.
+.PP
+If very high compressor and decompressor memory usage is fine,
+and the file being compressed is
+at least several hundred megabytes, it may be useful
+to use an even bigger dictionary than the 64 MiB that
+.B "xz \-9"
+would use:
+.RS
+.PP
+.nf
+.ft CW
+xz \-vv \-\-lzma2=dict=192MiB big_foo.tar
+.ft R
+.fi
+.RE
+.PP
+Using
+.B \-vv
+.RB ( "\-\-verbose \-\-verbose" )
+like in the above example can be useful
+to see the memory requirements
+of the compressor and decompressor.
+Remember that using a dictionary bigger than
+the size of the uncompressed file is waste of memory,
+so the above command isn't useful for small files.
+.PP
+Sometimes the compression time doesn't matter,
+but the decompressor memory usage has to be kept low
+e.g. to make it possible to decompress the file on
+an embedded system.
+The following command uses
+.B \-6e
+.RB ( "\-6 \-\-extreme" )
+as a base and sets the dictionary to only 64\ KiB.
+The resulting file can be decompressed with XZ Embedded
+(that's why there is
+.BR \-\-check=crc32 )
+using about 100\ KiB of memory.
+.RS
+.PP
+.nf
+.ft CW
+xz \-\-check=crc32 \-\-lzma2=preset=6e,dict=64KiB foo
+.ft R
+.fi
+.RE
+.PP
+If you want to squeeze out as many bytes as possible,
+adjusting the number of literal context bits
+.RI ( lc )
+and number of position bits
+.RI ( pb )
+can sometimes help.
+Adjusting the number of literal position bits
+.RI ( lp )
+might help too, but usually
+.I lc
+and
+.I pb
+are more important.
+E.g. a source code archive contains mostly US-ASCII text,
+so something like the following might give
+slightly (like 0.1\ %) smaller file than
+.B "xz \-6e"
+(try also without
+.BR lc=4 ):
+.RS
+.PP
+.nf
+.ft CW
+xz \-\-lzma2=preset=6e,pb=0,lc=4 source_code.tar
+.ft R
+.fi
+.RE
+.PP
+Using another filter together with LZMA2 can improve
+compression with certain file types.
+E.g. to compress a x86-32 or x86-64 shared library
+using the x86 BCJ filter:
+.RS
+.PP
+.nf
+.ft CW
+xz \-\-x86 \-\-lzma2 libfoo.so
+.ft R
+.fi
+.RE
+.PP
+Note that the order of the filter options is significant.
+If
+.B \-\-x86
+is specified after
+.BR \-\-lzma2 ,
+.B xz
+will give an error,
+because there cannot be any filter after LZMA2,
+and also because the x86 BCJ filter cannot be used
+as the last filter in the chain.
+.PP
+The Delta filter together with LZMA2
+can give good results with bitmap images.
+It should usually beat PNG,
+which has a few more advanced filters than simple
+delta but uses Deflate for the actual compression.
+.PP
+The image has to be saved in uncompressed format,
+e.g. as uncompressed TIFF.
+The distance parameter of the Delta filter is set
+to match the number of bytes per pixel in the image.
+E.g. 24-bit RGB bitmap needs
+.BR dist=3 ,
+and it is also good to pass
+.B pb=0
+to LZMA2 to accommodate the three-byte alignment:
+.RS
+.PP
+.nf
+.ft CW
+xz \-\-delta=dist=3 \-\-lzma2=pb=0 foo.tiff
+.ft R
+.fi
+.RE
+.PP
+If multiple images have been put into a single archive (e.g.\&
+.BR .tar ),
+the Delta filter will work on that too as long as all images
+have the same number of bytes per pixel.
+.
.SH "SEE ALSO"
.BR xzdec (1),
+.BR xzdiff (1),
+.BR xzgrep (1),
+.BR xzless (1),
+.BR xzmore (1),
.BR gzip (1),
-.BR bzip2 (1)
+.BR bzip2 (1),
+.BR 7z (1)
.PP
XZ Utils: <http://tukaani.org/xz/>
.br
diff --git a/src/xzdec/xzdec.1 b/src/xzdec/xzdec.1
index 3057c586d25f..7cc9be5de086 100644
--- a/src/xzdec/xzdec.1
+++ b/src/xzdec/xzdec.1
@@ -4,7 +4,7 @@
.\" This file has been put into the public domain.
.\" You can do whatever you want with this file.
.\"
-.TH XZDEC 1 "2010-03-07" "Tukaani" "XZ Utils"
+.TH XZDEC 1 "2010-09-27" "Tukaani" "XZ Utils"
.SH NAME
xzdec, lzmadec \- Small .xz and .lzma decompressors
.SH SYNOPSIS
@@ -25,7 +25,8 @@ files.
.B xzdec
is intended to work as a drop-in replacement for
.BR xz (1)
-in the most common situations where a script has been written to use
+in the most common situations where a script
+has been written to use
.B "xz \-\-decompress \-\-stdout"
(and possibly a few other commonly used options) to decompress
.B .xz
@@ -43,9 +44,12 @@ files.
.PP
To reduce the size of the executable,
.B xzdec
-doesn't support multithreading or localization, and doesn't read options from
+doesn't support multithreading or localization,
+and doesn't read options from
+.B XZ_DEFAULTS
+and
.B XZ_OPT
-environment variable.
+environment variables.
.B xzdec
doesn't support displaying intermediate progress information: sending
.B SIGINFO
@@ -77,45 +81,6 @@ compatibility.
.B xzdec
always writes the decompressed data to standard output.
.TP
-\fB\-M\fR \fIlimit\fR, \fB\-\-memory=\fIlimit
-Set the memory usage
-.IR limit .
-If this option is specified multiple times, the last one takes effect. The
-.I limit
-can be specified in multiple ways:
-.RS
-.IP \(bu 3
-The
-.I limit
-can be an absolute value in bytes. Using an integer suffix like
-.B MiB
-can be useful. Example:
-.B "\-\-memory=80MiB"
-.IP \(bu 3
-The
-.I limit
-can be specified as a percentage of physical RAM. Example:
-.B "\-\-memory=70%"
-.IP \(bu 3
-The
-.I limit
-can be reset back to its default value by setting it to
-.BR 0 .
-.IP \(bu 3
-The memory usage limiting can be effectively disabled by setting
-.I limit
-to
-.BR max .
-This isn't recommended. It's usually better to use, for example,
-.BR \-\-memory=90% .
-.RE
-.IP
-The current
-.I limit
-can be seen near the bottom of the output of the
-.B \-\-help
-option.
-.TP
.BR \-q ", " \-\-quiet
Specifying this once does nothing since
.B xzdec
@@ -127,8 +92,7 @@ Ignored for
.BR xz (1)
compatibility.
.B xzdec
-never uses the exit status
-.BR "2" .
+never uses the exit status 2.
.TP
.BR \-h ", " \-\-help
Display a help message and exit successfully.
@@ -148,18 +112,32 @@ An error occurred.
.B xzdec
doesn't have any warning messages like
.BR xz (1)
-has, thus the exit status
-.B 2
-is not used by
+has, thus the exit status 2 is not used by
.BR xzdec .
.SH NOTES
+Use
+.BR xz (1)
+instead of
+.B xzdec
+or
+.B lzmadec
+for normal everyday use.
+.B xzdec
+or
+.B lzmadec
+are meant only for situations where it is important to have
+a smaller decompressor than the full-featured
+.BR xz (1).
+.PP
.B xzdec
and
.B lzmadec
-are not really that small. The size can be reduced further by dropping
-features from liblzma at compile time, but that shouldn't usually be done
-for executables distributed in typical non-embedded operating system
-distributions. If you need a truly small
+are not really that small.
+The size can be reduced further by dropping
+features from liblzma at compile time,
+but that shouldn't usually be done for executables distributed
+in typical non-embedded operating system distributions.
+If you need a truly small
.B .xz
decompressor, consider using XZ Embedded.
.SH "SEE ALSO"
diff --git a/src/xzdec/xzdec.c b/src/xzdec/xzdec.c
index 8518d362a2dd..fd015076de97 100644
--- a/src/xzdec/xzdec.c
+++ b/src/xzdec/xzdec.c
@@ -35,12 +35,6 @@
#endif
-/// Number of bytes to use memory at maximum
-static uint64_t memlimit;
-
-/// Total amount of physical RAM
-static uint64_t total_ram;
-
/// Error messages are suppressed if this is zero, which is the case when
/// --quiet has been given at least twice.
static unsigned int display_errors = 2;
@@ -66,10 +60,6 @@ my_errorf(const char *fmt, ...)
static void lzma_attribute((noreturn))
help(void)
{
- // Round up to the next MiB and do it correctly also with UINT64_MAX.
- const uint64_t mem_mib = (memlimit >> 20)
- + ((memlimit & ((UINT32_C(1) << 20) - 1)) != 0);
-
printf(
"Usage: %s [OPTION]... [FILE]...\n"
"Uncompress files in the ." TOOL_FORMAT " format to the standard output.\n"
@@ -77,7 +67,6 @@ help(void)
" -c, --stdout (ignored)\n"
" -d, --decompress (ignored)\n"
" -k, --keep (ignored)\n"
-" -M, --memory=NUM use NUM bytes of memory at maximum (0 means default)\n"
" -q, --quiet specify *twice* to suppress errors\n"
" -Q, --no-warn (ignored)\n"
" -h, --help display this help and exit\n"
@@ -85,11 +74,9 @@ help(void)
"\n"
"With no FILE, or when FILE is -, read standard input.\n"
"\n"
-"On this system and configuration, this program will use a maximum of roughly\n"
-"%" PRIu64 " MiB RAM.\n"
-"\n"
"Report bugs to <" PACKAGE_BUGREPORT "> (in English or Finnish).\n"
-PACKAGE_NAME " home page: <" PACKAGE_URL ">\n", progname, mem_mib);
+PACKAGE_NAME " home page: <" PACKAGE_URL ">\n", progname);
+
tuklib_exit(EXIT_SUCCESS, EXIT_FAILURE, display_errors);
}
@@ -104,117 +91,6 @@ version(void)
}
-/// Find out the amount of physical memory (RAM) in the system, and set
-/// the memory usage limit to the given percentage of RAM.
-static void
-memlimit_set_percentage(uint32_t percentage)
-{
- memlimit = percentage * total_ram / 100;
- return;
-}
-
-
-/// Set the memory usage limit to give number of bytes. Zero is a special
-/// value to indicate the default limit.
-static void
-memlimit_set(uint64_t new_memlimit)
-{
- if (new_memlimit != 0) {
- memlimit = new_memlimit;
- } else {
- memlimit = 40 * total_ram / 100;
- if (memlimit < UINT64_C(80) * 1024 * 1024) {
- memlimit = 80 * total_ram / 100;
- if (memlimit > UINT64_C(80) * 1024 * 1024)
- memlimit = UINT64_C(80) * 1024 * 1024;
- }
- }
-
- return;
-}
-
-
-/// Get the total amount of physical RAM and set the memory usage limit
-/// to the default value.
-static void
-memlimit_init(void)
-{
- // If we cannot determine the amount of RAM, use the assumption
- // defined by the configure script.
- total_ram = lzma_physmem();
- if (total_ram == 0)
- total_ram = (uint64_t)(ASSUME_RAM) * 1024 * 1024;
-
- memlimit_set(0);
- return;
-}
-
-
-/// \brief Convert a string to uint64_t
-///
-/// This is rudely copied from src/xz/util.c and modified a little. :-(
-///
-/// \param max Return value when the string "max" was specified.
-///
-static uint64_t
-str_to_uint64(const char *value, uint64_t max)
-{
- uint64_t result = 0;
-
- // Accept special value "max".
- if (strcmp(value, "max") == 0)
- return max;
-
- if (*value < '0' || *value > '9') {
- my_errorf("%s: Value is not a non-negative decimal integer",
- value);
- exit(EXIT_FAILURE);
- }
-
- do {
- // Don't overflow.
- if (result > (UINT64_MAX - 9) / 10)
- return UINT64_MAX;
-
- result *= 10;
- result += *value - '0';
- ++value;
- } while (*value >= '0' && *value <= '9');
-
- if (*value != '\0') {
- // Look for suffix.
- uint64_t multiplier = 0;
- if (*value == 'k' || *value == 'K')
- multiplier = UINT64_C(1) << 10;
- else if (*value == 'm' || *value == 'M')
- multiplier = UINT64_C(1) << 20;
- else if (*value == 'g' || *value == 'G')
- multiplier = UINT64_C(1) << 30;
-
- ++value;
-
- // Allow also e.g. Ki, KiB, and KB.
- if (*value != '\0' && strcmp(value, "i") != 0
- && strcmp(value, "iB") != 0
- && strcmp(value, "B") != 0)
- multiplier = 0;
-
- if (multiplier == 0) {
- my_errorf("%s: Invalid suffix", value - 1);
- exit(EXIT_FAILURE);
- }
-
- // Don't overflow here either.
- if (result > UINT64_MAX / multiplier)
- result = UINT64_MAX;
- else
- result *= multiplier;
- }
-
- return result;
-}
-
-
/// Parses command line options.
static void
parse_options(int argc, char **argv)
@@ -226,7 +102,6 @@ parse_options(int argc, char **argv)
{ "decompress", no_argument, NULL, 'd' },
{ "uncompress", no_argument, NULL, 'd' },
{ "keep", no_argument, NULL, 'k' },
- { "memory", required_argument, NULL, 'M' },
{ "quiet", no_argument, NULL, 'q' },
{ "no-warn", no_argument, NULL, 'Q' },
{ "help", no_argument, NULL, 'h' },
@@ -245,31 +120,6 @@ parse_options(int argc, char **argv)
case 'Q':
break;
- case 'M': {
- // Support specifying the limit as a percentage of
- // installed physical RAM.
- const size_t len = strlen(optarg);
- if (len > 0 && optarg[len - 1] == '%') {
- // Memory limit is a percentage of total
- // installed RAM.
- optarg[len - 1] = '\0';
- const uint64_t percentage
- = str_to_uint64(optarg, 100);
- if (percentage < 1 || percentage > 100) {
- my_errorf("Percentage must be in "
- "the range [1, 100]");
- exit(EXIT_FAILURE);
- }
-
- memlimit_set_percentage(percentage);
- } else {
- memlimit_set(str_to_uint64(
- optarg, UINT64_MAX));
- }
-
- break;
- }
-
case 'q':
if (display_errors > 0)
--display_errors;
@@ -298,13 +148,12 @@ uncompress(lzma_stream *strm, FILE *file, const char *filename)
// Initialize the decoder
#ifdef LZMADEC
- ret = lzma_alone_decoder(strm, memlimit);
+ ret = lzma_alone_decoder(strm, UINT64_MAX);
#else
- ret = lzma_stream_decoder(strm, memlimit, LZMA_CONCATENATED);
+ ret = lzma_stream_decoder(strm, UINT64_MAX, LZMA_CONCATENATED);
#endif
// The only reasonable error here is LZMA_MEM_ERROR.
- // FIXME: Maybe also LZMA_MEMLIMIT_ERROR in future?
if (ret != LZMA_OK) {
my_errorf("%s", ret == LZMA_MEM_ERROR ? strerror(ENOMEM)
: "Internal error (bug)");
@@ -392,10 +241,6 @@ uncompress(lzma_stream *strm, FILE *file, const char *filename)
msg = strerror(ENOMEM);
break;
- case LZMA_MEMLIMIT_ERROR:
- msg = "Memory usage limit reached";
- break;
-
case LZMA_FORMAT_ERROR:
msg = "File format not recognized";
break;
@@ -431,10 +276,6 @@ main(int argc, char **argv)
// Initialize progname which we will be used in error messages.
tuklib_progname_init(argv);
- // Set the default memory usage limit. This is needed before parsing
- // the command line arguments.
- memlimit_init();
-
// Parse the command line options.
parse_options(argc, argv);