Add an unpatched version of xz, XZ Utils, to /trunk/deps/third_party.

README.chromium will be placed in the Chromium tree in the directory that
receives xz. Here are its contents, which provide information about xz:

--
Name: XZ Utils
URL: http://tukaani.org/xz/
Source URL: git://ctrl.tukaani.org/xz.git
Version: git commit c15c42abb3c8c6e77c778ef06c97a4a10b8b5d00
         (2010-06-15 14:06:29 +0300), newer than 4.999.9beta
License: Public domain/license grant, LGPL 2.1, GPL 2, GPL 3
License File: COPYING

Description:
XZ Utils is general-purpose data compression software implementing the
modified Lempel-Ziv-Markov chain algorithm (LZMA2).

Local Modifications:
 - None.
--

BUG=47199
TEST=none
Review URL: http://codereview.chromium.org/2869016

git-svn-id: http://src.chromium.org/svn/trunk/deps/third_party/xz@50504 4ff67af0-8c30-449e-8e8b-ad334ec8d88c
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0b5bb53
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,56 @@
+*~
+*.bak
+*.bak[0-9]
+
+.deps
+.libs
+*.la
+*.lo
+*.o
+Makefile.in
+
+/ABOUT-NLS
+/autom4te.cache
+/Doxyfile
+/aclocal.m4
+/build-aux
+/config.h
+/config.h.in
+/config.log
+/config.status
+/configure
+/libtool
+/stamp-h1
+
+/src/liblzma/liblzma.pc
+/src/lzmainfo/lzmainfo
+/src/xz/xz
+/src/xzdec/lzmadec
+/src/xzdec/xzdec
+
+/src/scripts/xzdiff
+/src/scripts/xzgrep
+/src/scripts/xzless
+/src/scripts/xzmore
+
+/tests/compress_generated_abc
+/tests/compress_generated_random
+/tests/compress_generated_text
+/tests/create_compress_files
+/tests/test_block_header
+/tests/test_check
+/tests/test_filter_flags
+/tests/test_index
+/tests/test_stream_flags
+
+/lib/Makefile
+/tests/Makefile
+/Makefile
+/debug/Makefile
+/src/scripts/Makefile
+/src/xz/Makefile
+/src/Makefile
+/src/liblzma/Makefile
+/src/liblzma/api/Makefile
+/src/lzmainfo/Makefile
+/src/xzdec/Makefile
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..63a9815
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,27 @@
+
+Authors of XZ Utils
+===================
+
+    XZ Utils is developed and maintained by Lasse Collin
+    <lasse.collin@tukaani.org>.
+
+    Major parts of liblzma are based on code written by Igor Pavlov,
+    specifically the LZMA SDK <http://7-zip.org/sdk.html>. Without
+    this code, XZ Utils wouldn't exist.
+
+    The SHA-256 implementation in liblzma is based on the code found from
+    7-Zip <http://7-zip.org/>, which has a modified version of the SHA-256
+    code found from Crypto++ <http://www.cryptopp.com/>. The SHA-256 code
+    in Crypto++ was written by Kevin Springle and Wei Dai.
+
+    Some scripts have been adapted from gzip. The original versions
+    were written by Jean-loup Gailly, Charles Levert, and Paul Eggert.
+    Andrew Dudman helped adapting the script and their man pages for
+    XZ Utils.
+
+    The GNU Autotools based build system contains files from many authors,
+    which I'm not trying list here.
+
+    Several people have contributed fixes or reported bugs. Most of them
+    are mentioned in the file THANKS.
+
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..43c90d0
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,65 @@
+
+XZ Utils Licensing
+==================
+
+    Different licenses apply to different files in this package. Here
+    is a rough summary of which licenses apply to which parts of this
+    package (but check the individual files to be sure!):
+
+      - liblzma is in the public domain.
+
+      - xz, xzdec, and lzmadec command line tools are in the public
+        domain unless GNU getopt_long had to be compiled and linked
+        in from the lib directory. The getopt_long code is under
+        GNU LGPLv2.1+.
+
+      - The scripts to grep, diff, and view compressed files have been
+        adapted from gzip. These scripts and their documentation are
+        under GNU GPLv2+.
+
+      - All the documentation in the doc directory and most of the
+        XZ Utils specific documentation files in other directories
+        are in the public domain.
+
+      - Translated messages are in the public domain.
+
+      - The build system contains public domain files, and files that
+        are under GNU GPLv2+ or GNU GPLv3+. None of these files end up
+        in the binaries being built.
+
+      - Test files and test code in the tests directory, and debugging
+        utilities in the debug directory are in the public domain.
+
+      - The extra directory may contain public domain files, and files
+        that are under various free software licenses.
+
+    You can do whatever you want with the files that have been put into
+    the public domain. If you find public domain legally problematic,
+    take the previous sentence as a license grant. If you still find
+    the lack of copyright legally problematic, you have too many
+    lawyers.
+
+    As usual, this software is provided "as is", without any warranty.
+
+    If you copy significant amounts of public domain code from XZ Utils
+    into your project, acknowledging this somewhere in your software is
+    polite (especially if it is proprietary, non-free software), but
+    naturally it is not legally required. Here is an example of a good
+    notice to put into "about box" or into documentation:
+
+        This software includes code from XZ Utils <http://tukaani.org/xz/>.
+
+    The following license texts are included in the following files:
+      - COPYING.LGPLv2.1: GNU Lesser General Public License version 2.1
+      - COPYING.GPLv2: GNU General Public License version 2
+      - COPYING.GPLv3: GNU General Public License version 3
+
+    Note that the toolchain (compiler, linker etc.) may add some code
+    pieces that are copyrighted. Thus, it is possible that e.g. liblzma
+    binary wouldn't actually be in the public domain in its entirety
+    even though it contains no copyrighted code from the XZ Utils source
+    package.
+
+    If you have questions, don't hesitate to ask the author(s) for more
+    information.
+
diff --git a/COPYING.GPLv2 b/COPYING.GPLv2
new file mode 100644
index 0000000..d511905
--- /dev/null
+++ b/COPYING.GPLv2
@@ -0,0 +1,339 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/COPYING.GPLv3 b/COPYING.GPLv3
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/COPYING.GPLv3
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/COPYING.LGPLv2.1 b/COPYING.LGPLv2.1
new file mode 100644
index 0000000..5ab7695
--- /dev/null
+++ b/COPYING.LGPLv2.1
@@ -0,0 +1,504 @@
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..ff22a97
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,7 @@
+See the commit log in the git repository:
+
+    git://ctrl.tukaani.org/xz.git
+
+Note that "make dist" doesn't put this tiny file into the package.
+Instead, the git commit log is used as ChangeLog. See dist-hook in
+Makefile.am for details.
diff --git a/Doxyfile.in b/Doxyfile.in
new file mode 100644
index 0000000..fa3c1e1
--- /dev/null
+++ b/Doxyfile.in
@@ -0,0 +1,1234 @@
+# Doxyfile 1.4.7
+
+# Copyright (C) 1997-2007 by Dimitri van Heesch
+# License: GNU GPLv2+
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = "@PACKAGE_NAME@"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER         = "@PACKAGE_VERSION@"
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = doc
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
+# Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# This tag can be used to specify the encoding used in the generated output.
+# The encoding is not always determined by the language that is chosen,
+# but also whether or not the output is meant for Windows or non-Windows users.
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
+# forces the Windows encoding (this is the default for the Windows binary),
+# whereas setting the tag to NO uses a Unix-style encoding (the default for
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING   = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC    = YES
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP         = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC         = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS       = NO
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT                  = @top_srcdir@/src
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
+
+FILE_PATTERNS          = *.h *.c
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS       = YES
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS       =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.  Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.  The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.  Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE               =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX         = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA             =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD                =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.  This is useful
+# if you want to understand what is going on.  On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = YES
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED             = LZMA_API(type)=type \
+                         LZMA_API_IMPORT \
+                         LZMA_API_CALL=
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#   TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#   TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a caller dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS           =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH    = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT   = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that a graph may be further truncated if the graph's
+# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH
+# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default),
+# the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..5f38085
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,369 @@
+
+XZ Utils Installation
+=====================
+
+    0. Preface
+    1. Supported platforms
+       1.1. Compilers
+       1.2. Platform-specific notes
+            1.2.1. IRIX
+            1.2.2. Tru64
+            1.2.3. Windows
+            1.2.4. DOS
+            1.2.5. OS/2
+            1.2.6. OpenVMS
+       1.3. Adding support for new platforms
+    2. configure options
+    3. xzgrep and other scripts
+       3.1. Dependencies
+       3.2. PATH
+    4. Troubleshooting
+       4.1. "No C99 compiler was found."
+       4.1. "No POSIX conforming shell (sh) was found."
+       4.2. configure works but build fails at crc32_x86.S
+
+
+0. Preface
+----------
+
+    If you aren't familiar with building packages that use GNU Autotools,
+    see the file INSTALL.generic for generic instructions before reading
+    further.
+
+    If you are going to build a package for distribution, see also the
+    file PACKAGERS. It contains information that should help making the
+    binary packages as good as possible, but the information isn't very
+    interesting to those making local builds for private use or for use
+    in special situations like embedded systems.
+
+
+1. Supported platforms
+----------------------
+
+    XZ Utils are developed on GNU/Linux, but they should work on many
+    POSIX-like operating systems like *BSDs and Solaris, and even on
+    a few non-POSIX operating systems.
+
+
+1.1. Compilers
+
+    A C99 compiler is required to compile XZ Utils. If you use GCC, you
+    need at least version 3.x.x. GCC version 2.xx.x doesn't support some
+    C99 features used in XZ Utils source code, thus GCC 2 won't compile
+    XZ Utils.
+
+    XZ Utils takes advantage of some GNU C extensions when building
+    with GCC. Because these extensions are used only when building
+    with GCC, it should be possible to use any C99 compiler.
+
+
+1.2. Platform-specific notes
+
+1.2.1. IRIX
+
+    MIPSpro 7.4.4m has been reported to produce broken code if using
+    the -O2 optimization flag ("make check" fails). Using -O1 should
+    work.
+
+
+1.2.2. Tru64
+
+    If you try to use the native C compiler on Tru64 (passing CC=cc to
+    configure), it is possible that the configure script will complain
+    that no C99 compiler was found even when the native compiler supports
+    C99. You can safely override the test for C99 compiler by passing
+    ac_cv_prog_cc_c99= as the argument to the configure script.
+
+
+1.2.3. Windows
+
+    Building XZ Utils on Windows is supported under MinGW + MSYS and
+    Cygwin. There is windows/build.sh to ease packaging XZ Utils with
+    MinGW + MSYS into a redistributable .zip or .7z file. See
+    windows/INSTALL-Windows.txt for more information.
+
+    It might be possible to build liblzma with a non-GNU toolchain too,
+    but that will probably require writing a separate makefile. Building
+    the command line tools with non-GNU toolchains will be harder than
+    building only liblzma.
+
+    Even if liblzma is built with MinGW, the resulting DLL or static
+    library can be used by other compilers and linkers, including MSVC.
+    Thus, it shouldn't be a problem to use MinGW to build liblzma even
+    if you cannot use MinGW to build the rest of your project. See
+    windows/README-Windows.txt for details.
+
+
+1.2.4. DOS
+
+    There is an experimental Makefile in the "dos" directory to build
+    XZ Utils on DOS using DJGPP. Support for long file names (LFN) is
+    needed. See dos/README for more information.
+
+    GNU Autotools based build hasn't been tried on DOS. If you try, I
+    would like to hear if it worked.
+
+
+1.2.5. OS/2
+
+    To omit large number of harmless warnings about visibility support,
+    pass gl_cv_cc_visibility=no as an argument to the configure script.
+    This isn't mandatory since it should have no effect on the resulting
+    binaries.
+
+
+1.2.6. OpenVMS
+
+    XZ Utils can be built for OpenVMS, but the build system files are
+    currently not included in the XZ Utils source package. The required
+    OpenVMS-specific files are maintained by Jouk Jansen and can be
+    downloaded here:
+
+        http://nchrem.tnw.tudelft.nl/openvms/software2.html#xzutils
+
+
+1.3. Adding support for new platforms
+
+    If you have written patches to make XZ Utils to work on previously
+    unsupported platform, please send the patches to me! I will consider
+    including them to the official version. It's nice to minimize the
+    need of third-party patching.
+
+    One exception: Don't request or send patches to change the whole
+    source package to C89. I find C99 substantially nicer to write and
+    maintain. However, the public library headers must be in C89 to
+    avoid frustrating those who maintain programs, which are strictly
+    in C89 or C++.
+
+
+2. configure options
+--------------------
+
+    In most cases, the defaults are what you want. Most of the options
+    below are useful only when building a size-optimized version of
+    liblzma or command line tools.
+
+    --enable-encoders=LIST
+    --disable-encoders
+                Specify a comma-separated LIST of filter encoders to
+                build. See "./configure --help" for exact list of
+                available filter encoders. The default is to build all
+                supported encoders.
+
+                If LIST is empty or --disable-encoders is used, no filter
+                encoders will be built and also the code shared between
+                encoders will be omitted.
+
+                Disabling encoders will remove some symbols from the
+                liblzma ABI, so this option should be used only when it
+                is known to not cause problems.
+
+    --enable-decoders=LIST
+    --disable-decoders
+                This is like --enable-encoders but for decoders. The
+                default is to build all supported decoders.
+
+    --enable-match-finders=LIST
+                liblzma includes two categories of match finders:
+                hash chains and binary trees. Hash chains (hc3 and hc4)
+                are quite fast but they don't provide the best compression
+                ratio. Binary trees (bt2, bt3 and bt4) give excellent
+                compression ratio, but they are slower and need more
+                memory than hash chains.
+
+                You need to enable at least one match finder to build the
+                LZMA1 or LZMA2 filter encoders. Usually hash chains are
+                used only in the fast mode, while binary trees are used to
+                when the best compression ratio is wanted.
+
+                The default is to build all the match finders if LZMA1
+                or LZMA2 filter encoders are being built.
+
+    --enable-checks=LIST
+                liblzma support multiple integrity checks. CRC32 is
+                mandatory, and cannot be omitted. See "./configure --help"
+                for exact list of available integrity check types.
+
+                liblzma and the command line tools can decompress files
+                which use unsupported integrity check type, but naturally
+                the file integrity cannot be verified in that case.
+
+                Disabling integrity checks may remove some symbols from
+                the liblzma ABI, so this option should be used only when
+                it is known to not cause problems.
+
+    --disable-assembler
+                liblzma includes some assembler optimizations. Currently
+                there is only assembler code for CRC32 and CRC64 for
+                32-bit x86.
+
+                All the assembler code in liblzma is position-independent
+                code, which is suitable for use in shared libraries and
+                position-independent executables. So far only i386
+                instructions are used, but the code is optimized for i686
+                class CPUs. If you are compiling liblzma exclusively for
+                pre-i686 systems, you may want to disable the assembler
+                code.
+
+    --enable-unaligned-access
+                Allow liblzma to use unaligned memory access for 16-bit
+                and 32-bit loads and stores. This should be enabled only
+                when the hardware supports this, i.e. when unaligned
+                access is fast. Some operating system kernels emulate
+                unaligned access, which is extremely slow. This option
+                shouldn't be used on systems that rely on such emulation.
+
+                Unaligned access is enabled by default on x86, x86-64,
+                and big endian PowerPC.
+
+    --enable-small
+                Reduce the size of liblzma by selecting smaller but
+                semantically equivalent version of some functions, and
+                omit precomputed lookup tables. This option tends to
+                make liblzma slightly slower.
+
+                Note that while omitting the precomputed tables makes
+                liblzma smaller on disk, the tables are still needed at
+                run time, and need to be computed at startup. This also
+                means that the RAM holding the tables won't be shared
+                between applications linked against shared liblzma.
+
+                This option doesn't modify CFLAGS to tell the compiler
+                to optimize for size. You need to add -Os or equivalent
+                flag(s) to CFLAGS manually.
+
+    --enable-assume-ram=SIZE
+                On the most common operating systems, XZ Utils is able to
+                detect the amount of physical memory on the system. This
+                information is used to set the default memory usage limit.
+
+                On some systems, there is no code to detect the amount of
+                RAM though. Using --enable-assume-ram one can set how much
+                memory to assume on these systems. SIZE is given as MiB.
+                The default is 128 MiB, which allows decompressing files
+                created with "xz -9".
+
+                Feel free to send patches to add support for detecting
+                the amount of RAM on the operating system you use. See
+                src/common/tuklib_physmem.c for details.
+
+    --disable-threads
+                Disable threading support. This makes some things
+                thread-unsafe, meaning that if multithreaded application
+                calls liblzma functions from more than one thread,
+                something bad may happen.
+
+                Use this option if threading support causes you trouble,
+                or if you know that you will use liblzma only from
+                single-threaded applications and want to avoid dependency
+                on libpthread.
+
+    --enable-dynamic=TYPE
+                Specify how command line tools should be linked against
+                liblzma. Possible TYPES:
+
+                    yes     All command line tools are linked against
+                            shared liblzma (if shared liblzma was built).
+                            This is equivalent to --enable-dynamic (i.e.
+                            no =TYPE).
+
+                    mixed   Some tools are linked against static liblzma
+                            and some against shared liblzma. This is the
+                            default and recommended way.
+
+                    no      All command line tools are linked against
+                            static liblzma (if static liblzma was built).
+                            This is equivalent to --disable-dynamic.
+
+                This option is mostly useful for packagers, if distro
+                policy requires linking against shared libaries. See the
+                file PACKAGERS for more information about pros and cons
+                of this option.
+
+    --enable-debug
+                This enables the assert() macro and possibly some other
+                run-time consistency checks. It makes the code slower, so
+                you normally don't want to have this enabled.
+
+    --enable-werror
+                If building with GCC, make all compiler warnings an error,
+                that abort the compilation. This may help catching bugs,
+                and should work on most systems. This has no effect on the
+                resulting binaries.
+
+
+3. xzgrep and other scripts
+---------------------------
+
+3.1. Dependencies
+
+    POSIX shell (sh) and bunch of other standard POSIX tools are required
+    to run the scripts. The configure script tries to find a POSIX
+    compliant sh, but if it fails, you can force the shell by passing
+    gl_cv_posix_shell=/path/to/posix-sh as an argument to the configure
+    script.
+
+    Some of the scripts require also mktemp. The original mktemp can be
+    found from <http://www.mktemp.org/>. On GNU, most will use the mktemp
+    program from GNU coreutils instead of the original implementation.
+    Both mktemp versions are fine for XZ Utils (and practically for
+    everything else too).
+
+
+3.2. PATH
+
+    The scripts assume that the required tools (standard POSIX utilities,
+    mktemp, and xz) are in PATH; the scripts don't set the PATH themselves.
+    Some people like this while some think this is a bug. Those in the
+    latter group can easily patch the scripts before running the configure
+    script by taking advantage of a placeholder line in the scripts.
+
+    For example, to make the scripts prefix /usr/bin:/bin to PATH:
+
+        perl -pi -e 's|^#SET_PATH.*$|PATH=/usr/bin:/bin:\$PATH|' \
+                src/scripts/xz*.in
+
+
+4. Troubleshooting
+------------------
+
+4.1. "No C99 compiler was found."
+
+    You need a C99 compiler to build XZ Utils. If the configure script
+    cannot find a C99 compiler and you think you have such a compiler
+    installed, set the compiler command by passing CC=/path/to/c99 as
+    an argument to the configure script.
+
+    If you get this error even when you think your compiler supports C99,
+    you can override the test by passing ac_cv_prog_cc_c99= as an argument
+    to the configure script. The test for C99 compiler is not perfect (and
+    it is not as easy to make it perfect as it sounds), so sometimes this
+    may be needed. You will get a compile error if your compiler doesn't
+    support enough C99.
+
+
+4.1. "No POSIX conforming shell (sh) was found."
+
+    xzgrep and other scripts need a shell that (roughly) conforms
+    to POSIX. The configure script tries to find such a shell. If
+    it fails, you can force the shell to be used by passing
+    gl_cv_posix_shell=/path/to/posix-sh as an argument to the configure
+    script.
+
+
+4.2. configure works but build fails at crc32_x86.S
+
+    The easy fix is to pass --disable-assembler to the configure script.
+
+    The configure script determines if assembler code can be used by
+    looking at the configure triplet; there is currently no check if
+    the assembler code can actually actually be built. The x86 assembler
+    code should work on x86 GNU/Linux, *BSDs, Solaris, Darwin, MinGW,
+    Cygwin, and DJGPP. On other x86 systems, there may be problems and
+    the assembler code may need to be disabled with the configure option.
+
+    If you get this error when building for x86-64, you have specified or
+    the configure script has misguessed your architecture. Pass the
+    correct configure triplet using the --build=CPU-COMPANY-SYSTEM option
+    (see INSTALL.generic).
+
diff --git a/INSTALL.generic b/INSTALL.generic
new file mode 100644
index 0000000..2550dab
--- /dev/null
+++ b/INSTALL.generic
@@ -0,0 +1,302 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
+2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+
+   This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+   Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package.  The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+   It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring.  Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+   The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'.  You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.
+
+     Running `configure' might take a while.  While running, it prints
+     some messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+  6. Often, you can also type `make uninstall' to remove the installed
+     files again.
+
+Compilers and Options
+=====================
+
+   Some systems require unusual options for compilation or linking that
+the `configure' script does not know about.  Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+   You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here
+is an example:
+
+     ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+   You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you can use GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory.  After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+   On MacOS X 10.5 and later systems, you can create libraries and
+executables that work on multiple system types--known as "fat" or
+"universal" binaries--by specifying multiple `-arch' options to the
+compiler but only a single `-arch' option to the preprocessor.  Like
+this:
+
+     ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+                 CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+                 CPP="gcc -E" CXXCPP="g++ -E"
+
+   This is not guaranteed to produce working output in all cases, you
+may have to build one architecture at a time and combine the results
+using the `lipo' tool if you have problems.
+
+Installation Names
+==================
+
+   By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc.  You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+   Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Particular systems
+==================
+
+   On HP-UX, the default C compiler is not ANSI C compatible.  If GNU
+CC is not installed, it is recommended to use the following options in
+order to use an ANSI C compiler:
+
+     ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
+
+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+
+   On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
+parse its `<wchar.h>' header file.  The option `-nodtk' can be used as
+a workaround.  If GNU CC is not installed, it is therefore recommended
+to try
+
+     ./configure CC="cc"
+
+and if that doesn't work, try
+
+     ./configure CC="cc -nodtk"
+
+   On Solaris, don't put `/usr/ucb' early in your `PATH'.  This
+directory contains several dysfunctional programs; working variants of
+these programs are available in `/usr/bin'.  So, if you need `/usr/ucb'
+in your `PATH', put it _after_ `/usr/bin'.
+
+   On Haiku, software installed for all users goes in `/boot/common',
+not `/usr/local'.  It is recommended to use the following options:
+
+     ./configure --prefix=/boot/common
+
+Specifying the System Type
+==========================
+
+   There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on.  Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS
+     KERNEL-OS
+
+   See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+   If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+   Variables not defined in a site shell script can be set in the
+environment passed to `configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug.  Until the bug is fixed you can use this workaround:
+
+     CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+   `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+     Print a summary of all of the options to `configure', and exit.
+
+`--help=short'
+`--help=recursive'
+     Print a summary of the options unique to this package's
+     `configure', and exit.  The `short' variant lists options used
+     only in the top level, while the `recursive' variant lists options
+     also present in any nested packages.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
+
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`--prefix=DIR'
+     Use DIR as the installation prefix.  *Note Installation Names::
+     for more details, including other options available for fine-tuning
+     the installation locations.
+
+`--no-create'
+`-n'
+     Run the configure checks, but stop before creating any output
+     files.
+
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..9d6cf1e
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,85 @@
+##
+## Author: Lasse Collin
+##
+## This file has been put into the public domain.
+## You can do whatever you want with this file.
+##
+
+DIST_SUBDIRS = lib src po tests debug
+SUBDIRS =
+
+if COND_GNULIB
+SUBDIRS += lib
+endif
+
+SUBDIRS += src po tests
+
+dist_doc_DATA = \
+	AUTHORS \
+	COPYING \
+	COPYING.GPLv2 \
+	NEWS \
+	README \
+	THANKS \
+	TODO \
+	doc/faq.txt \
+	doc/history.txt \
+	doc/xz-file-format.txt \
+	doc/lzma-file-format.txt
+
+EXTRA_DIST = \
+	extra \
+	dos \
+	windows \
+	autogen.sh \
+	version.sh \
+	Doxyfile.in \
+	COPYING.GPLv2 \
+	COPYING.GPLv3 \
+	COPYING.LGPLv2.1 \
+	INSTALL.generic \
+	PACKAGERS
+
+ACLOCAL_AMFLAGS = -I m4
+
+# List of man pages to conver to PDF and plain text in the dist-hook target.
+manfiles = \
+	src/xz/xz.1 \
+	src/xzdec/xzdec.1 \
+	src/lzmainfo/lzmainfo.1 \
+	src/scripts/xzdiff.1 \
+	src/scripts/xzgrep.1 \
+	src/scripts/xzless.1 \
+	src/scripts/xzmore.1
+
+# Create ChangeLog from output of "git log --date=iso --stat".
+# Convert the man pages to PDF and plain text (ASCII only) formats.
+dist-hook:
+	if test -d "$(srcdir)/.git" && type git > /dev/null 2>&1; then \
+		( cd "$(srcdir)" && git log --date=iso --stat ) \
+			> "$(distdir)/ChangeLog"; \
+	fi
+	if type groff > /dev/null 2>&1 && type ps2pdf > /dev/null 2>&1; then \
+		dest="$(distdir)/doc/man" && \
+		$(MKDIR_P) "$$dest/pdf-a4" "$$dest/pdf-letter" "$$dest/txt" && \
+		for FILE in $(manfiles); do \
+			BASE=`basename $$FILE .1` && \
+			groff -man -t -Tps -P-pa4 < "$(srcdir)/$$FILE" \
+				| ps2pdf - - \
+				> "$$dest/pdf-a4/$$BASE-a4.pdf" && \
+			groff -man -t -Tps -P-pletter < "$(srcdir)/$$FILE" \
+				| ps2pdf - - \
+				> "$$dest/pdf-letter/$$BASE-letter.pdf" && \
+			groff -man -t -Tascii < "$(srcdir)/$$FILE" \
+				| col -bx > "$$dest/txt/$$BASE.txt"; \
+		done; \
+	fi
+
+# This works with GNU tar and gives cleaner package than normal 'make dist'.
+mydist:
+	if test -d "$(srcdir)/.git" && type git > /dev/null 2>&1; then \
+		SNAPSHOT=`cd "$(srcdir)" && git describe --abbrev=4 | cut -b2-`; \
+		test -n "$$SNAPSHOT" && VERSION=$$SNAPSHOT; \
+	fi; \
+	TAR_OPTIONS='--owner=0 --group=0 --numeric-owner --mode=u+rw,go+r-w' \
+		$(MAKE) VERSION="$$VERSION" dist-gzip
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/NEWS
diff --git a/PACKAGERS b/PACKAGERS
new file mode 100644
index 0000000..c5d375a
--- /dev/null
+++ b/PACKAGERS
@@ -0,0 +1,279 @@
+
+Information to packagers of XZ Utils
+====================================
+
+    0. Preface
+    1. Package naming
+    2. Package description
+    3. License
+    4. configure options
+       4.1. Static vs. dynamic linking of liblzma
+       4.2. Optimizing xzdec and lzmadec
+    5. Additional documentation
+    6. Extra files
+    7. Installing XZ Utils and LZMA Utils in parallel
+    8. Example
+
+
+0. Preface
+----------
+
+    This document is meant for people who create and maintain XZ Utils
+    packages for operating system distributions. The focus is on GNU/Linux
+    systems, but most things apply to other systems too.
+
+    While the standard "configure && make DESTDIR=$PKG install" should
+    give a pretty good package, there are some details which packagers
+    may want to tweak.
+
+    Packagers should also read the INSTALL file.
+
+
+1. Package naming
+-----------------
+
+    The preferred name for the XZ Utils package is "xz", because that's
+    the name of the upstream tarball. Naturally you may have good reasons
+    to use some other name; I won't get angry about it. ;-) It's just nice
+    to be able to point people to the correct package name without asking
+    what distro they have.
+
+    If your distro policy is to split things into small pieces, here is
+    one suggestion:
+
+        xz              xz, xzdec, scripts (xzdiff, xzgrep, etc.), docs
+        xz-lzma         lzma, unlzma, lzcat, lzgrep etc. symlinks and
+                        lzmadec binary for compatibility with LZMA Utils
+        liblzma         liblzma.so.*
+        liblzma-devel   liblzma.so, liblzma.a, API headers
+
+
+2. Package description
+----------------------
+
+    Here is a suggestion which you may use as the package description.
+    If you can use only one-line description, pick only the first line.
+    Naturally, feel free to use some other description if you find it
+    better, and maybe send it to me too.
+
+        Library and command line tools for XZ and LZMA compressed files
+
+        XZ Utils provide a general purpose data compression library
+        and command line tools. The native file format is the .xz
+        format, but also the legacy .lzma format is supported. The .xz
+        format supports multiple compression algorithms, of which LZMA2
+        is currently the primary algorithm. With typical files, XZ Utils
+        create about 30 % smaller files than gzip.
+
+    If you are splitting XZ Utils into multiple packages, here are some
+    suggestions for package descriptions:
+
+    xz:
+
+        Command line tools for XZ and LZMA compressed files
+
+        This package includes the xz compression tool and other command
+        line tools from XZ Utils. xz has command line syntax similar to
+        that of gzip. The native file format is the .xz format, but also
+        the legacy .lzma format is supported. The .xz format supports
+        multiple compression algorithms, of which LZMA2 is currently the
+        primary algorithm. With typical files, XZ Utils create about 30 %
+        smaller files than gzip.
+
+        Note that this package doesn't include the files needed for
+        LZMA Utils 4.32.x compatibility. Install also the xz-lzma
+        package to make XZ Utils emulate LZMA Utils 4.32.x.
+
+    xz-lzma:
+
+        LZMA Utils emulation with XZ Utils
+
+        This package includes executables and symlinks to make
+        XZ Utils emulate lzma, unlzma, lzcat, and other command
+        line tools found from the legacy LZMA Utils 4.32.x package.
+
+    liblzma:
+
+        Library for XZ and LZMA compressed files
+
+        liblzma is a general purpose data compression library with
+        an API similar to that of zlib. liblzma supports multiple
+        algorithms, of which LZMA2 is currently the primary algorithm.
+        The native file format is .xz, but also the legacy .lzma
+        format and raw streams (no headers at all) are supported.
+
+        This package includes the shared library.
+
+    liblzma-devel:
+
+        Library for XZ and LZMA compressed files
+
+        This package includes the API headers, static library, and
+        other development files related to liblzma.
+
+
+3. License
+----------
+
+    If the package manager supports a license field, you probably should
+    put GPLv2+ there (GNU GPL v2 or later). The interesting parts of
+    XZ Utils are in the public domain, but some less important files
+    ending up into the binary package are under GPLv2+. So it is simplest
+    to just say GPLv2+ if you cannot specify "public domain and GPLv2+".
+
+    If you split XZ Utils into multiple packages as described earlier
+    in this file, liblzma and liblzma-dev packages will contain only
+    public domain code (from XZ Utils at least; compiler or linker may
+    add some third-party code, which may be copyrighted).
+
+
+4. configure options
+--------------------
+
+    Unless you are building a package for a distribution that is meant
+    only for embedded systems, don't use the following configure options:
+
+        --enable-debug
+        --enable-encoders (*)
+        --enable-decoders
+        --enable-match-finders
+        --enable-checks
+        --enable-small (*)
+        --disable-threads (*)
+
+    (*) These are OK when building xzdec and lzmadec as explained later.
+
+    You may use --enable-werror but be careful with it since it may break
+    the build due to some useless warning when the build environment
+    changes (like CPU architecture or compiler version).
+
+
+4.1. Static vs. dynamic linking of liblzma
+
+    The default is to link the most important command line tools against
+    static liblzma, and the less important tools against shared liblzma.
+    This can be changed by passing --enable-dynamic to configure, or by
+    not building static libraries at all by passing --disable-static
+    to configure. It is mildly recommended that you use the default, but
+    the configure options make it easy to do otherwise if the distro policy
+    so requires.
+
+    On 32-bit x86, linking against static liblzma can give a minor
+    speed improvement. Static libraries on x86 are usually compiled as
+    position-dependent code (non-PIC) and shared libraries are built as
+    position-independent code (PIC). PIC wastes one register, which can
+    make the code slightly slower compared to a non-PIC version. (Note
+    that this doesn't apply to x86-64.)
+
+    Linking against static liblzma avoids a dependency on liblzma shared
+    library, and makes it slightly easier to copy the command line tools
+    between systems (e.g. quick 'n' dirty emergency recovery of some
+    files). It also allows putting the command line tools to /bin while
+    leaving liblzma to /usr/lib (assuming that your distribution uses
+    such a file system hierarchy), if no other file in /bin would require
+    liblzma.
+
+    If you don't want to distribute static libraries but you still
+    want to link the command line tools against static liblzma, it is
+    probably easiest to build both static and shared liblzma, but after
+    "make DESTDIR=$PKG install" remove liblzma.a and modify liblzma.la
+    to not contain a reference to liblzma.a.
+
+
+4.2. Optimizing xzdec and lzmadec
+
+    xzdec and lzmadec are intended to be relatively small instead of
+    optimizing for the best speed. Thus, it is a good idea to build
+    xzdec and lzmadec separately:
+
+      - Only decoder code is needed, so you can speed up the build
+        slightly by passing --disable-encoders to configure. This
+        shouldn't affect the final size of the executables though,
+        because the linker is able to omit the encoder code anyway.
+
+      - xzdec and lzmadec will never use multithreading capabilities of
+        liblzma. You can avoid dependency on libpthread by passing
+        --disable-threads to configure.
+
+      - There are and will be no translated messages for xzdec and
+        lzmadec, so it is fine to pass also --disable-nls to configure.
+
+      - To select somewhat size-optimized variant of some things in
+        liblzma, pass --enable-small to configure.
+
+      - Tell the compiler to optimize for size instead of speed.
+        E.g. with GCC, put -Os into CFLAGS.
+
+
+5. Additional documentation
+---------------------------
+
+    "make install" copies some additional documentation to $docdir
+    (--docdir in configure). These a copy of the GNU GPL v2, which can
+    be replaced with a symlink if your distro ships with shared copies
+    of the common license texts.
+
+
+6. Extra files
+--------------
+
+    The "extra" directory contains some small extra tools or other files.
+    The exact set of extra files can vary between XZ Utils releases. The
+    extra files have only limited use or they are too dangerous to be
+    put directly to $bindir (7z2lzma.sh is a good example, since it can
+    silently create corrupt output if certain conditions are not met).
+
+    If you feel like it, you may copy the extra directory under the doc
+    directory (e.g. /usr/share/doc/xz/extra). Maybe some people will find
+    them useful. However, most people needing these tools probably are
+    able to find them from the source package too.
+
+    The "debug" directory contains some tools that are useful only when
+    hacking on XZ Utils. Don't package these tools.
+
+
+7. Installing XZ Utils and LZMA Utils in parallel
+-------------------------------------------------
+
+    XZ Utils and LZMA Utils 4.32.x can be installed in parallel by
+    omitting the compatibility symlinks (lzma, unlzma, lzcat, lzgrep etc.)
+    from the XZ Utils package. It's probably a good idea to still package
+    the symlinks into a separate package so that users may choose if they
+    want to use XZ Utils or LZMA Utils for handling .lzma files.
+
+
+8. Example
+----------
+
+    Here is an example for i686 GNU/Linux that
+      - links xz against static liblzma;
+      - includes only shared liblzma in the final package;
+      - links xzdec and lzmadec against static liblzma while
+        avoiding libpthread dependency.
+
+    PKG=/tmp/xz-pkg
+    tar xf xz-x.y.z.tar.gz
+    cd xz-x.y.z
+    ./configure \
+            --prefix=/usr \
+            --sysconfdir=/etc \
+            CFLAGS='-march=i686 -O2'
+    make
+    make DESTDIR=$PKG install-strip
+    rm -f $PKG/usr/lib/lib*.a
+    sed -i "s/^old_library=.*$/old_library=''/" $PKG/usr/lib/lib*.la
+    make clean
+    ./configure \
+            --prefix=/usr \
+            --sysconfdir=/etc \
+            --disable-shared \
+            --disable-nls \
+            --disable-encoders \
+            --enable-small \
+            --disable-threads \
+            CFLAGS='-march=i686 -Os'
+    make -C src/liblzma
+    make -C src/xzdec
+    make -C src/xzdec DESTDIR=$PKG install-strip
+    cp -a extra $PKG/usr/share/doc/xz
+
diff --git a/README b/README
new file mode 100644
index 0000000..6b695d5
--- /dev/null
+++ b/README
@@ -0,0 +1,218 @@
+
+XZ Utils
+========
+
+    0. Overview
+    1. Documentation
+       1.1. Overall documentation
+       1.2. Documentation for command line tools
+       1.3. Documentation for liblzma
+    2. Version numbering
+    3. Reporting bugs
+    4. Other implementations of the .xz format
+    5. Contact information
+
+
+0. Overview
+-----------
+
+    XZ Utils provide a general-purpose data compression library and
+    command line tools. The native file format is the .xz format, but
+    also the legacy .lzma format is supported. The .xz format supports
+    multiple compression algorithms, which are called "filters" in
+    context of XZ Utils. The primary filter is currently LZMA2. With
+    typical files, XZ Utils create about 30 % smaller files than gzip.
+
+    To ease adapting support for the .xz format into existing applications
+    and scripts, the API of liblzma is somewhat similar to the API of the
+    popular zlib library. For the same reason, the command line tool xz
+    has similar command line syntax than that of gzip.
+
+    When aiming for the highest compression ratio, LZMA2 encoder uses
+    a lot of CPU time and may use, depending on the settings, even
+    hundreds of megabytes of RAM. However, in fast modes, LZMA2 encoder
+    competes with bzip2 in compression speed, RAM usage, and compression
+    ratio.
+
+    LZMA2 is reasonably fast to decompress. It is a little slower than
+    gzip, but a lot faster than bzip2. Being fast to decompress means
+    that the .xz format is especially nice when the same file will be
+    decompressed very many times (usually on different computers), which
+    is the case e.g. when distributing software packages. In such
+    situations, it's not too bad if the compression takes some time,
+    since that needs to be done only once to benefit many people.
+
+    With some file types, combining (or "chaining") LZMA2 with an
+    additional filter can improve compression ratio. A filter chain may
+    contain up to four filters, although usually only one two is used.
+    For example, putting a BCJ (Branch/Call/Jump) filter before LZMA2
+    in the filter chain can improve compression ratio of executable files.
+
+    Since the .xz format allows adding new filter IDs, it is possible that
+    some day there will be a filter that is, for example, much faster to
+    compress than LZMA2 (but probably with worse compression ratio).
+    Similarly, it is possible that some day there is a filter that will
+    compress better than LZMA2.
+
+    XZ Utils doesn't support multithreaded compression or decompression
+    yet. It has been planned though and taken into account when designing
+    the .xz file format.
+
+
+1. Documentation
+----------------
+
+1.1. Overall documentation
+
+    README              This file
+
+    INSTALL.generic     Generic install instructions for those not familiar
+                        with packages using GNU Autotools
+    INSTALL             Installation instructions specific to XZ Utils
+    PACKAGERS           Information to packagers of XZ Utils
+
+    COPYING             XZ Utils copyright and license information
+    COPYING.GPLv2       GNU General Public License version 2
+    COPYING.GPLv3       GNU General Public License version 3
+    COPYING.LGPLv2.1    GNU Lesser General Public License version 2.1
+
+    AUTHORS             The main authors of XZ Utils
+    THANKS              Incomplete list of people who have helped making
+                        this software
+    NEWS                User-visible changes between XZ Utils releases
+    ChangeLog           Detailed list of changes (commit log)
+    TODO                Known bugs and some sort of to-do list
+
+    Note that only some of the above files are included in binary
+    packages.
+
+
+1.2. Documentation for command line tools
+
+    The command line tools are documented as man pages. In source code
+    releases (and possibly also in some binary packages), the man pages
+    are also provided in plain text (ASCII only) and PDF formats in the
+    directory "doc/man" to make the man pages more accessible to those
+    whose operating system doesn't provide an easy way to view man pages.
+
+
+1.3. Documentation for liblzma
+
+    The liblzma API headers include short docs about each function
+    and data type as Doxygen tags. These docs should be quite OK as
+    a quick reference.
+
+    I have planned to write a bunch of very well documented example
+    programs, which (due to comments) should work as a tutorial to
+    various features of liblzma. No such example programs have been
+    written yet.
+
+    For now, if you have never used liblzma, libbzip2, or zlib, I
+    recommend learning *basics* of zlib API. Once you know that, it
+    should be easier to learn liblzma.
+
+        http://zlib.net/manual.html
+        http://zlib.net/zlib_how.html
+
+
+2. Version numbering
+--------------------
+
+    The version number format of XZ Utils is X.Y.ZS:
+
+      - X is the major version. When this is incremented, the library
+        API and ABI break.
+
+      - Y is the minor version. It is incremented when new features are
+        added without breaking existing API or ABI. Even Y indicates
+        stable release and odd Y indicates unstable (alpha or beta
+        version).
+
+      - Z is the revision. This has different meaning for stable and
+        unstable releases:
+          * Stable: Z is incremented when bugs get fixed without adding
+            any new features.
+          * Unstable: Z is just a counter. API or ABI of features added
+            in earlier unstable releases having the same X.Y may break.
+
+      - S indicates stability of the release. It is missing from the
+        stable releases where Y is an even number. When Y is odd, S
+        is either "alpha" or "beta" to make it very clear that such
+        versions are not stable releases. The same X.Y.Z combination is
+        not used for more than one stability level i.e. after X.Y.Zalpha,
+        the next version can be X.Y.(Z+1)beta but not X.Y.Zbeta.
+
+
+3. Reporting bugs
+-----------------
+
+    Naturally it is easiest for me if you already know what causes the
+    unexpected behavior. Even better if you have a patch to propose.
+    However, quite often the reason for unexpected behavior is unknown,
+    so here are a few things to do before sending a bug report:
+
+      1. Try to create a small example how to reproduce the issue.
+
+      2. Compile XZ Utils with debugging code using configure switches
+         --enable-debug and, if possible, --disable-shared. If you are
+         using GCC, use CFLAGS='-O0 -ggdb3'. Don't strip the resulting
+         binaries.
+
+      3. Turn on core dumps. The exact command depends on your shell;
+         for example in GNU bash it is done with "ulimit -c unlimited",
+         and in tcsh with "limit coredumpsize unlimited".
+
+      4. Try to reproduce the suspected bug. If you get "assertion failed"
+         message, be sure to include the complete message in your bug
+         report. If the application leaves a coredump, get a backtrace
+         using gdb:
+           $ gdb /path/to/app-binary   # Load the app to the debugger.
+           (gdb) core core   # Open the coredump.
+           (gdb) bt   # Print the backtrace. Copy & paste to bug report.
+           (gdb) quit   # Quit gdb.
+
+    Report your bug via email or IRC (see Contact information below).
+    Don't send core dump files or any executables. If you have a small
+    example file(s) (total size less than 256 KiB), please include
+    it/them as an attachment. If you have bigger test files, put them
+    online somewhere and include an URL to the file(s) in the bug report.
+
+    Always include the exact version number of XZ Utils in the bug report.
+    If you are using a snapshot from the git repository, use "git describe"
+    to get the exact snapshot version. If you are using XZ Utils shipped
+    in an operating system distribution, mention the distribution name,
+    distribution version, and exact xz package version; if you cannot
+    repeat the bug with the code compiled from unpatched source code,
+    you probably need to report a bug to your distribution's bug tracking
+    system.
+
+
+4. Other implementations of the .xz format
+------------------------------------------
+
+    7-Zip and the p7zip port of 7-Zip support the .xz format starting
+    from the version 9.00alpha.
+
+        http://7-zip.org/
+        http://p7zip.sourceforge.net/
+
+    XZ Embedded is a limited implementation written for use in the Linux
+    kernel, but it is also suitable for other embedded use.
+
+        http://tukaani.org/xz/embedded.html
+
+
+5. 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.
+
+    You can find me also from #tukaani on Freenode; my nick is Larhzu.
+    The channel tends to be pretty quiet, so just ask your question and
+    someone may wake up.
+
diff --git a/THANKS b/THANKS
new file mode 100644
index 0000000..4f79e47
--- /dev/null
+++ b/THANKS
@@ -0,0 +1,69 @@
+
+Thanks
+======
+
+Some people have helped more, some less, but nevertheless everyone's help
+has been important. :-) In alphabetical order:
+  - Mark Adler
+  - H. Peter Anvin
+  - Nelson H. F. Beebe
+  - Karl Berry
+  - Anders F. Björklund
+  - Emmanuel Blot
+  - Trent W. Buck
+  - David Burklund
+  - Marek Černocký
+  - Andrew Dudman
+  - Markus Duft
+  - İsmail Dönmez
+  - Robert Elz
+  - Gilles Espinasse
+  - Denis Excoffier
+  - Mike Frysinger
+  - Joachim Henke
+  - Peter Ivanov
+  - Jouk Jansen
+  - Per Øyvind Karlsen
+  - Thomas Klausner
+  - Richard Koch
+  - Ville Koskinen
+  - Stephan Kulow
+  - Peter Lawler
+  - Hin-Tak Leung
+  - Andraž 'ruskie' Levstik
+  - Jim Meyering
+  - Rafał Mużyło
+  - Adrien Nader
+  - Hongbo Ni
+  - Jonathan Nieder
+  - Peter O'Gorman
+  - Igor Pavlov
+  - Elbert Pol
+  - Mikko Pouru
+  - Robert Readman
+  - Bernhard Reutner-Fischer
+  - Christian von Roques
+  - Jukka Salmi
+  - Alexandre Sauvé
+  - Andreas Schwab
+  - Dan Shechter
+  - Stuart Shelton
+  - Jonathan Stott
+  - Paul Townsend
+  - Mohammed Adnène Trojette
+  - Alexey Tourbin
+  - Patrick J. Volkerding
+  - Christian Weisgerber
+  - Bert Wesarg
+  - Ralf Wildenhues
+  - Charles Wilson
+  - Lars Wirzenius
+  - Pilorz Wojciech
+  - Ryan Young
+  - Andreas Zieringer
+
+Also thanks to all the people who have participated in the Tukaani project.
+
+I have probably forgot to add some names to the above list. Sorry about
+that and thanks for your help.
+
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..9fac1b3
--- /dev/null
+++ b/TODO
@@ -0,0 +1,60 @@
+
+XZ Utils To-Do List
+===================
+
+Known bugs
+----------
+
+    The test suite is too incomplete.
+
+    If the memory usage limit is less than about 13 MiB, xz is unable to
+    automatically scale down the compression settings enough even though
+    it would be  possible by switching from BT2/BT3/BT4 match finder to
+    HC3/HC4.
+
+    The code to detect number of CPU cores doesn't count hyperthreading
+    as multiple cores. In context of xz, it probably should.
+    Hyperthreading is good at least with p7zip.
+
+    XZ Utils compress some files significantly worse than LZMA Utils.
+    This is due to faster compression presets used by XZ Utils, and
+    can be worked around by using "xz --extreme". However, the presets
+    need some tweaking and maybe this issue can be minimized without
+    making the typical case too much slower.
+
+    xz doesn't quote unprintable characters when it displays file names
+    given on the command line.
+
+    tuklib_exit() doesn't block signals => EINTR is possible.
+
+
+Missing features
+----------------
+
+    xz doesn't support copying extended attributes, access control
+    lists etc. from source to target file.
+
+    Multithreaded compression
+
+    Multithreaded decompression
+
+    Buffer-to-buffer coding could use less RAM (especially when
+    decompressing LZMA1 or LZMA2).
+
+    I/O library is not implemented. It will possibly be named libzzf.
+
+    lzma_strerror() to convert lzma_ret to human readable form?
+    This is tricky, because the same error codes are used with
+    slightly different meanings.
+
+
+Documentation
+-------------
+
+    Some tutorial is needed for liblzma. I have planned to write some
+    extremely well commented example programs, which would work as
+    a tutorial. I suppose the Doxygen tags are quite OK as a quick
+    reference once one is familiar with the liblzma API.
+
+    Document the LZMA1 and LZMA2 algorithms.
+
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..f0195ec
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+###############################################################################
+#
+# Author: Lasse Collin
+#
+# This file has been put into the public domain.
+# You can do whatever you want with this file.
+#
+###############################################################################
+
+# The result of using "autoreconf -fi" should be identical to using this
+# script. I'm leaving this script here just in case someone finds it useful.
+
+set -e -x
+
+${AUTOPOINT:-autopoint} -f
+${LIBTOOLIZE:-libtoolize} -c -f || glibtoolize -c -f
+${ACLOCAL:-aclocal} -I m4
+${AUTOCONF:-autoconf}
+${AUTOHEADER:-autoheader}
+${AUTOMAKE:-automake} -acf --foreign
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..e93e806
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,693 @@
+#                                               -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+###############################################################################
+#
+# Author: Lasse Collin
+#
+# This file has been put into the public domain.
+# You can do whatever you want with this file.
+#
+###############################################################################
+
+# NOTE: Don't add useless checks. autoscan detects this and that, but don't
+# let it confuse you. For example, we don't care about checking for behavior
+# of malloc(), stat(), or lstat(), since we don't use those functions in
+# a way that would cause the problems the autoconf macros check.
+
+AC_PREREQ([2.64])
+
+AC_INIT([XZ Utils], m4_esyscmd([/bin/sh version.sh]),
+	[lasse.collin@tukaani.org], [xz], [http://tukaani.org/xz/])
+AC_CONFIG_SRCDIR([src/liblzma/common/common.h])
+AC_CONFIG_AUX_DIR([build-aux])
+AC_CONFIG_MACRO_DIR([m4])
+AC_CONFIG_HEADER([config.h])
+
+echo
+echo "$PACKAGE_STRING"
+
+echo
+echo "System type:"
+# This is needed to know if assembler optimizations can be used.
+AC_CANONICAL_HOST
+
+# We do some special things on Windows (32-bit or 64-bit) builds.
+case $host_os in
+	mingw* | cygwin*) is_w32=yes ;;
+	*)                is_w32=no ;;
+esac
+AM_CONDITIONAL([COND_W32], [test "$is_w32" = yes])
+
+# We need to use $EXEEXT with $(LN_S) when creating symlinks to
+# executables. Cygwin is an exception to this, since it is recommended
+# that symlinks don't have the .exe suffix. To make this work, we
+# define LN_EXEEXT.
+case $host_os in
+	cygwin)  LN_EXEEXT= ;;
+	*)       LN_EXEEXT='$(EXEEXT)' ;;
+esac
+AC_SUBST([LN_EXEEXT])
+
+echo
+echo "Configure options:"
+AM_CFLAGS=
+
+
+#############
+# Debugging #
+#############
+
+AC_MSG_CHECKING([if debugging code should be compiled])
+AC_ARG_ENABLE([debug], AC_HELP_STRING([--enable-debug], [Enable debugging code.]),
+	[], enable_debug=no)
+if test "x$enable_debug" = xyes; then
+	AC_MSG_RESULT([yes])
+else
+	AC_DEFINE([NDEBUG], [1], [Define to 1 to disable debugging code.])
+	AC_MSG_RESULT([no])
+fi
+
+
+###########
+# Filters #
+###########
+
+m4_define([SUPPORTED_FILTERS], [lzma1,lzma2,delta,x86,powerpc,ia64,arm,armthumb,sparc])dnl
+m4_define([SIMPLE_FILTERS], [x86,powerpc,ia64,arm,armthumb,sparc])
+m4_define([LZ_FILTERS], [lzma1,lzma2])
+
+m4_foreach([NAME], [SUPPORTED_FILTERS],
+[enable_filter_[]NAME=no
+enable_encoder_[]NAME=no
+enable_decoder_[]NAME=no
+])dnl
+
+AC_MSG_CHECKING([which encoders to build])
+AC_ARG_ENABLE([encoders], AC_HELP_STRING([--enable-encoders=LIST],
+		[Comma-separated list of encoders to build. Default=all.
+		Available encoders:]
+			m4_translit(m4_defn([SUPPORTED_FILTERS]), [,], [ ])),
+	[], [enable_encoders=SUPPORTED_FILTERS])
+enable_encoders=`echo "$enable_encoders" | sed 's/,/ /g'`
+if test "x$enable_encoders" = xno || test "x$enable_encoders" = x; then
+	AC_MSG_RESULT([(none)])
+else
+	AC_DEFINE([HAVE_ENCODER], [1],
+		[Define to 1 if encoder components are enabled.])
+	for arg in $enable_encoders
+	do
+		case $arg in m4_foreach([NAME], [SUPPORTED_FILTERS], [
+			NAME)
+				enable_filter_[]NAME=yes
+				enable_encoder_[]NAME=yes
+				AC_DEFINE(HAVE_ENCODER_[]m4_toupper(NAME), [1],
+				[Define to 1 if] NAME [encoder is enabled.])
+				;;])
+			*)
+				AC_MSG_RESULT([])
+				AC_MSG_ERROR([unknown filter: $arg])
+				;;
+		esac
+	done
+	AC_MSG_RESULT([$enable_encoders])
+fi
+
+AC_MSG_CHECKING([which decoders to build])
+AC_ARG_ENABLE([decoders], AC_HELP_STRING([--enable-decoders=LIST],
+		[Comma-separated list of decoders to build. Default=all.
+		Available decoders are the same as available encoders.]),
+	[], [enable_decoders=SUPPORTED_FILTERS])
+enable_decoders=`echo "$enable_decoders" | sed 's/,/ /g'`
+if test "x$enable_decoders" = xno || test "x$enable_decoders" = x; then
+	AC_MSG_RESULT([(none)])
+else
+	AC_DEFINE([HAVE_DECODER], [1],
+		[Define to 1 if decoder components are enabled.])
+	for arg in $enable_decoders
+	do
+		case $arg in m4_foreach([NAME], [SUPPORTED_FILTERS], [
+			NAME)
+				enable_filter_[]NAME=yes
+				enable_decoder_[]NAME=yes
+				AC_DEFINE(HAVE_DECODER_[]m4_toupper(NAME), [1],
+				[Define to 1 if] NAME [decoder is enabled.])
+				;;])
+			*)
+				AC_MSG_RESULT([])
+				AC_MSG_ERROR([unknown filter: $arg])
+				;;
+		esac
+	done
+
+	# LZMA2 requires that LZMA1 is enabled.
+	test "x$enable_encoder_lzma2" = xyes && enable_encoder_lzma1=yes
+	test "x$enable_decoder_lzma2" = xyes && enable_decoder_lzma1=yes
+
+	AC_MSG_RESULT([$enable_decoders])
+fi
+
+if test "x$enable_encoder_lzma2$enable_encoder_lzma1" = xyesno \
+		|| test "x$enable_decoder_lzma2$enable_decoder_lzma1" = xyesno; then
+	AC_MSG_ERROR([LZMA2 requires that LZMA1 is also enabled.])
+fi
+
+AM_CONDITIONAL(COND_MAIN_ENCODER, test "x$enable_encoders" != xno && test "x$enable_encoders" != x)
+AM_CONDITIONAL(COND_MAIN_DECODER, test "x$enable_decoders" != xno && test "x$enable_decoders" != x)
+
+m4_foreach([NAME], [SUPPORTED_FILTERS],
+[AM_CONDITIONAL(COND_FILTER_[]m4_toupper(NAME), test "x$enable_filter_[]NAME" = xyes)
+AM_CONDITIONAL(COND_ENCODER_[]m4_toupper(NAME), test "x$enable_encoder_[]NAME" = xyes)
+AM_CONDITIONAL(COND_DECODER_[]m4_toupper(NAME), test "x$enable_decoder_[]NAME" = xyes)
+])dnl
+
+# The so called "simple filters" share common code.
+enable_filter_simple=no
+enable_encoder_simple=no
+enable_decoder_simple=no
+m4_foreach([NAME], [SIMPLE_FILTERS],
+[test "x$enable_filter_[]NAME" = xyes && enable_filter_simple=yes
+test "x$enable_encoder_[]NAME" = xyes && enable_encoder_simple=yes
+test "x$enable_decoder_[]NAME" = xyes && enable_decoder_simple=yes
+])dnl
+AM_CONDITIONAL(COND_FILTER_SIMPLE, test "x$enable_filter_simple" = xyes)
+AM_CONDITIONAL(COND_ENCODER_SIMPLE, test "x$enable_encoder_simple" = xyes)
+AM_CONDITIONAL(COND_DECODER_SIMPLE, test "x$enable_decoder_simple" = xyes)
+
+# LZ-based filters share common code.
+enable_filter_lz=no
+enable_encoder_lz=no
+enable_decoder_lz=no
+m4_foreach([NAME], [LZ_FILTERS],
+[test "x$enable_filter_[]NAME" = xyes && enable_filter_lz=yes
+test "x$enable_encoder_[]NAME" = xyes && enable_encoder_lz=yes
+test "x$enable_decoder_[]NAME" = xyes && enable_decoder_lz=yes
+])dnl
+AM_CONDITIONAL(COND_FILTER_LZ, test "x$enable_filter_lz" = xyes)
+AM_CONDITIONAL(COND_ENCODER_LZ, test "x$enable_encoder_lz" = xyes)
+AM_CONDITIONAL(COND_DECODER_LZ, test "x$enable_decoder_lz" = xyes)
+
+
+#################
+# Match finders #
+#################
+
+m4_define([SUPPORTED_MATCH_FINDERS], [hc3,hc4,bt2,bt3,bt4])
+
+m4_foreach([NAME], [SUPPORTED_MATCH_FINDERS],
+[enable_match_finder_[]NAME=no
+])
+
+AC_MSG_CHECKING([which match finders to build])
+AC_ARG_ENABLE([match-finders], AC_HELP_STRING([--enable-match-finders=LIST],
+		[Comma-separated list of match finders to build. Default=all.
+		At least one match finder is required for encoding with
+		the LZMA1 and LZMA2 filters. Available match finders:]
+		m4_translit(m4_defn([SUPPORTED_MATCH_FINDERS]), [,], [ ])), [],
+	[enable_match_finders=SUPPORTED_MATCH_FINDERS])
+enable_match_finders=`echo "$enable_match_finders" | sed 's/,/ /g'`
+if test "x$enable_encoder_lz" = xyes ; then
+	for arg in $enable_match_finders
+		do
+		case $arg in m4_foreach([NAME], [SUPPORTED_MATCH_FINDERS], [
+			NAME)
+				enable_match_finder_[]NAME=yes
+				AC_DEFINE(HAVE_MF_[]m4_toupper(NAME), [1],
+				[Define to 1 to enable] NAME [match finder.])
+				;;])
+			*)
+				AC_MSG_RESULT([])
+				AC_MSG_ERROR([unknown match finder: $arg])
+				;;
+		esac
+	done
+	AC_MSG_RESULT([$enable_match_finders])
+else
+	AC_MSG_RESULT([(none because not building any LZ-based encoder)])
+fi
+
+
+####################
+# Integrity checks #
+####################
+
+m4_define([SUPPORTED_CHECKS], [crc32,crc64,sha256])
+
+m4_foreach([NAME], [SUPPORTED_FILTERS],
+[enable_check_[]NAME=no
+])dnl
+
+AC_MSG_CHECKING([which integrity checks to build])
+AC_ARG_ENABLE([checks], AC_HELP_STRING([--enable-checks=LIST],
+		[Comma-separated list of integrity checks to build.
+		Default=all. Available integrity checks:]
+		m4_translit(m4_defn([SUPPORTED_CHECKS]), [,], [ ])),
+	[], [enable_checks=SUPPORTED_CHECKS])
+enable_checks=`echo "$enable_checks" | sed 's/,/ /g'`
+if test "x$enable_checks" = xno || test "x$enable_checks" = x; then
+	AC_MSG_RESULT([(none)])
+else
+	for arg in $enable_checks
+	do
+		case $arg in m4_foreach([NAME], [SUPPORTED_CHECKS], [
+			NAME)
+				enable_check_[]NAME=yes
+				AC_DEFINE(HAVE_CHECK_[]m4_toupper(NAME), [1],
+				[Define to 1 if] NAME
+				[integrity check is enabled.])
+				;;])
+			*)
+				AC_MSG_RESULT([])
+				AC_MSG_ERROR([unknown integrity check: $arg])
+				;;
+		esac
+	done
+	AC_MSG_RESULT([$enable_checks])
+fi
+if test "x$enable_checks_crc32" = xno ; then
+	AC_MSG_ERROR([For now, the CRC32 check must always be enabled.])
+fi
+
+m4_foreach([NAME], [SUPPORTED_CHECKS],
+[AM_CONDITIONAL(COND_CHECK_[]m4_toupper(NAME), test "x$enable_check_[]NAME" = xyes)
+])dnl
+
+
+###########################
+# Assembler optimizations #
+###########################
+
+AC_MSG_CHECKING([if assembler optimizations should be used])
+AC_ARG_ENABLE([assembler], AC_HELP_STRING([--disable-assembler],
+		[Do not use assembler optimizations even if such exist
+		for the architecture.]),
+	[], [enable_assembler=yes])
+if test "x$enable_assembler" = xyes; then
+	enable_assembler=no
+	case $host_os in
+		# Darwin should work too but only if not creating universal
+		# binaries. Solaris x86 could work too but I cannot test.
+		linux* | *bsd* | mingw* | cygwin*)
+			case $host_cpu in
+				i?86)   enable_assembler=x86 ;;
+				x86_64) enable_assembler=x86_64 ;;
+			esac
+			;;
+	esac
+fi
+case $enable_assembler in
+	x86 | x86_64 | no)
+		AC_MSG_RESULT([$enable_assembler])
+		;;
+	*)
+		AC_MSG_RESULT([])
+		AC_MSG_ERROR([--enable-assembler accepts only \`yes', \`no', \`x86', or \`x86_64'.])
+		;;
+esac
+AM_CONDITIONAL(COND_ASM_X86, test "x$enable_assembler" = xx86)
+AM_CONDITIONAL(COND_ASM_X86_64, test "x$enable_assembler" = xx86_64)
+
+
+#####################
+# Size optimization #
+#####################
+
+AC_MSG_CHECKING([if small size is preferred over speed])
+AC_ARG_ENABLE([small], AC_HELP_STRING([--enable-small],
+		[Make liblzma smaller and a little slower.
+		This is disabled by default to optimize for speed.]),
+	[], [enable_small=no])
+if test "x$enable_small" = xyes; then
+	AC_DEFINE([HAVE_SMALL], [1], [Define to 1 if optimizing for size.])
+elif test "x$enable_small" != xno; then
+	AC_MSG_RESULT([])
+	AC_MSG_ERROR([--enable-small accepts only \`yes' or \`no'])
+fi
+AC_MSG_RESULT([$enable_small])
+AM_CONDITIONAL(COND_SMALL, test "x$enable_small" = xyes)
+
+
+#############
+# Threading #
+#############
+
+AC_MSG_CHECKING([if threading support is wanted])
+AC_ARG_ENABLE([threads], AC_HELP_STRING([--disable-threads],
+		[Disable threading support.
+		This makes some things thread-unsafe.]),
+	[], [enable_threads=yes])
+if test "x$enable_threads" != xyes && test "x$enable_threads" != xno; then
+	AC_MSG_RESULT([])
+	AC_MSG_ERROR([--enable-threads accepts only \`yes' or \`no'])
+fi
+AC_MSG_RESULT([$enable_threads])
+# We use the actual result a little later.
+
+
+#########################
+# Assumed amount of RAM #
+#########################
+
+# We use 128 MiB as default, because it will allow decompressing files
+# created with "xz -9". It would be slightly safer to guess a lower value,
+# but most systems, on which we don't have any way to determine the amount
+# of RAM, will probably have at least 128 MiB of RAM.
+AC_MSG_CHECKING([how much RAM to assume if the real amount is unknown])
+AC_ARG_ENABLE([assume-ram], AC_HELP_STRING([--enable-assume-ram=SIZE],
+		[If and only if the real amount of RAM cannot be determined,
+		assume SIZE MiB. The default is 128 MiB. This affects the
+		default memory usage limit.]),
+	[], [enable_assume_ram=128])
+assume_ram_check=`echo "$enable_assume_ram" | tr -d 0123456789`
+if test -z "$enable_assume_ram" || test -n "$assume_ram_check"; then
+	AC_MSG_RESULT([])
+	AC_MSG_ERROR([--enable-assume-ram accepts only an integer argument])
+fi
+AC_MSG_RESULT([$enable_assume_ram MiB])
+AC_DEFINE_UNQUOTED([ASSUME_RAM], [$enable_assume_ram],
+		[How many MiB of RAM to assume if the real amount cannot
+		be determined.])
+
+
+############################################
+# xz/xzdec/lzmadec linkage against liblzma #
+############################################
+
+# Link the xz, xzdec, and lzmadec command line tools against static liblzma
+# unless using --enable-dynamic. Using static liblzma gives a little bit
+# faster executable on x86, because no register is wasted for PIC. We also
+# have one dependency less, which allows users to more freely copy the xz
+# binary to other boxes. However, I wouldn't be surprised if distro
+# maintainers still prefer dynamic linking, so let's make it easy for them.
+
+AC_MSG_CHECKING([how programs should be linked against liblzma])
+AC_ARG_ENABLE([dynamic], [AC_HELP_STRING([--enable-dynamic=TYPE],
+			[Set how command line tools are linked against liblzma.
+			TYPE can be mixed, yes, or no. The default is mixed.])],
+		[], [enable_dynamic=mixed])
+case $enable_dynamic in
+	mixed)
+		AC_MSG_RESULT([mixed (some dynamically, some statically)])
+		;;
+	yes)
+		AC_MSG_RESULT([dynamically])
+		;;
+	no)
+		AC_MSG_RESULT([statically])
+		;;
+	*)
+		AC_MSG_RESULT([])
+		AC_MSG_ERROR([--enable-dynamic accepts only \`mixed', \`yes', or \`no'])
+		;;
+esac
+# We use the actual results later, because we don't know yet
+# if --disable-shared or --disable-static was used.
+
+
+###############################################################################
+# Checks for programs.
+###############################################################################
+
+echo
+gl_POSIX_SHELL
+if test -z "$POSIX_SHELL" ; then
+	AC_MSG_ERROR([No POSIX conforming shell (sh) was found.])
+fi
+
+echo
+echo "Initializing Automake:"
+
+AM_INIT_AUTOMAKE([1.10 foreign tar-v7 filename-length-max=99])
+AC_PROG_LN_S
+
+AC_PROG_CC_C99
+if test x$ac_cv_prog_cc_c99 = xno ; then
+	AC_MSG_ERROR([No C99 compiler was found.])
+fi
+
+AM_PROG_CC_C_O
+AM_PROG_AS
+AC_USE_SYSTEM_EXTENSIONS
+
+if test "x$enable_threads" = xyes; then
+	echo
+	echo "Threading support:"
+	ACX_PTHREAD
+	LIBS="$LIBS $PTHREAD_LIBS"
+	AM_CFLAGS="$AM_CFLAGS $PTHREAD_CFLAGS"
+	CC="$PTHREAD_CC"
+fi
+
+echo
+echo "Initializing Libtool:"
+LT_PREREQ([2.2])
+LT_INIT([win32-dll])
+LT_LANG([Windows Resource])
+
+# This is a bit wrong since it is possible to request that only some libs
+# are built as shared. Using that feature isn't so common though, and this
+# breaks only on Windows (at least for now) if the user enables only some
+# libs as shared.
+AM_CONDITIONAL([COND_SHARED], [test "x$enable_shared" != xno])
+
+
+###############################################################################
+# Checks for libraries.
+###############################################################################
+
+echo
+echo "Initializing gettext:"
+AM_GNU_GETTEXT_VERSION([0.16.1])
+AM_GNU_GETTEXT([external])
+
+###############################################################################
+# Checks for header files.
+###############################################################################
+
+echo
+echo "System headers and functions:"
+
+# There is currently no workarounds in this package if some of
+# these headers are missing.
+AC_CHECK_HEADERS([fcntl.h limits.h sys/time.h],
+	[],
+	[AC_MSG_ERROR([Required header file(s) are missing.])])
+
+
+###############################################################################
+# Checks for typedefs, structures, and compiler characteristics.
+###############################################################################
+
+dnl We don't need these as long as we need a C99 compiler anyway.
+dnl AC_C_INLINE
+dnl AC_C_RESTRICT
+
+AC_HEADER_STDBOOL
+
+AC_TYPE_UINT8_T
+AC_TYPE_UINT16_T
+AC_TYPE_INT32_T
+AC_TYPE_UINT32_T
+AC_TYPE_INT64_T
+AC_TYPE_UINT64_T
+AC_TYPE_UINTPTR_T
+
+AC_CHECK_SIZEOF([size_t])
+
+# The command line tool can copy high resolution timestamps if such
+# information is availabe in struct stat. Otherwise one second accuracy
+# is used.
+AC_CHECK_MEMBERS([
+	struct stat.st_atim.tv_nsec,
+	struct stat.st_atimespec.tv_nsec,
+	struct stat.st_atimensec,
+	struct stat.st_uatime,
+	struct stat.st_atim.st__tim.tv_nsec])
+
+AC_SYS_LARGEFILE
+AC_C_BIGENDIAN
+
+
+###############################################################################
+# Checks for library functions.
+###############################################################################
+
+# Gnulib replacements as needed
+gl_GETOPT
+
+# Find the best function to set timestamps.
+AC_CHECK_FUNCS([futimens futimes futimesat utimes utime], [break])
+
+TUKLIB_PROGNAME
+TUKLIB_INTEGER
+TUKLIB_PHYSMEM
+TUKLIB_CPUCORES
+
+
+###############################################################################
+# If using GCC, set some additional AM_CFLAGS:
+###############################################################################
+
+if test "$GCC" = yes ; then
+	echo
+	echo "GCC extensions:"
+fi
+
+# Always do the visibility check but don't set AM_CFLAGS on Windows.
+# This way things get set properly even on Windows.
+gl_VISIBILITY
+if test -n "$CFLAG_VISIBILITY" && test "$is_w32" = no; then
+	AM_CFLAGS="$AM_CFLAGS $CFLAG_VISIBILITY"
+fi
+
+if test "$GCC" = yes ; then
+	# Enable as much warnings as possible. These commented warnings won't
+	# work for this package though:
+	#   * -Wunreachable-code breaks several assert(0) cases, which are
+	#     backed up with "return LZMA_PROG_ERROR".
+	#   * -Wcast-qual would break various things where we need a non-const
+	#     pointer although we don't modify anything through it.
+	#   * -Wcast-align breaks optimized CRC32 and CRC64 implementation
+	#     on some architectures (not on x86), where this warning is bogus,
+	#     because we take care of correct alignment.
+	#   * -Winline, -Wdisabled-optimization, -Wunsafe-loop-optimizations
+	#     don't seem so useful here; at least the last one gives some
+	#     warnings which are not bugs.
+	for NEW_FLAG in \
+			-Wall \
+			-Wextra \
+			-Wformat=2 \
+			-Winit-self \
+			-Wmissing-include-dirs \
+			-Wstrict-aliasing \
+			-Wfloat-equal \
+			-Wundef \
+			-Wshadow \
+			-Wpointer-arith \
+			-Wbad-function-cast \
+			-Wwrite-strings \
+			-Wlogical-op \
+			-Waggregate-return \
+			-Wstrict-prototypes \
+			-Wold-style-definition \
+			-Wmissing-prototypes \
+			-Wmissing-declarations \
+			-Wmissing-noreturn \
+			-Wredundant-decls
+	do
+		AC_MSG_CHECKING([if $CC accepts $NEW_FLAG])
+		OLD_CFLAGS="$CFLAGS"
+		CFLAGS="$CFLAGS $NEW_FLAG"
+		AC_COMPILE_IFELSE([void foo(void) { }], [
+			AM_CFLAGS="$AM_CFLAGS $NEW_FLAG"
+			AC_MSG_RESULT([yes])
+		], [
+			AC_MSG_RESULT([no])
+		])
+		CFLAGS="$OLD_CFLAGS"
+	done
+
+	AC_ARG_ENABLE([werror],
+		AC_HELP_STRING([--enable-werror], [Enable -Werror to abort
+			compilation on all compiler warnings.]),
+		[], [enable_werror=no])
+	if test "x$enable_werror" = "xyes"; then
+		AM_CFLAGS="$AM_CFLAGS -Werror"
+	fi
+fi
+
+
+###############################################################################
+# Create the makefiles and config.h
+###############################################################################
+
+echo
+
+# Don't build the lib directory at all if we don't need any replacement
+# functions.
+AM_CONDITIONAL([COND_GNULIB], test -n "$LIBOBJS")
+
+# Add default AM_CFLAGS.
+AC_SUBST([AM_CFLAGS])
+
+# Set additional flags for static/dynamic linking. The idea is that every
+# program (not library) being built will use either STATIC_{CPPFLAGS,LDFLAGS}
+# or DYNAMIC_{CPPFLAGS,LDFLAGS} depending on which type of linkage is
+# preferred. These preferences get overridden by use of --disable-static,
+# --disable-shared, or --enable-dynamic.
+#
+# This is quite messy, because we want to use LZMA_API_STATIC when linking
+# against static liblzma. It's needed on Windows.
+if test "x$enable_static" = xno; then
+	enable_dynamic=yes
+fi
+if test "x$enable_shared" = xno; then
+	enable_dynamic=no
+fi
+case $enable_dynamic in
+	yes)
+		STATIC_CPPFLAGS=
+		STATIC_LDFLAGS=
+		DYNAMIC_CPPFLAGS=
+		DYNAMIC_LDFLAGS=
+		;;
+	mixed)
+		STATIC_CPPFLAGS="-DLZMA_API_STATIC"
+		STATIC_LDFLAGS="-static"
+		DYNAMIC_CPPFLAGS=
+		DYNAMIC_LDFLAGS=
+		;;
+	no)
+		STATIC_CPPFLAGS="-DLZMA_API_STATIC"
+		STATIC_LDFLAGS="-static"
+		DYNAMIC_CPPFLAGS="-DLZMA_API_STATIC"
+		DYNAMIC_LDFLAGS="-static"
+		;;
+esac
+AC_SUBST([STATIC_CPPFLAGS])
+AC_SUBST([STATIC_LDFLAGS])
+AC_SUBST([DYNAMIC_CPPFLAGS])
+AC_SUBST([DYNAMIC_LDFLAGS])
+
+# This is needed for src/scripts.
+xz=`echo xz | sed "$program_transform_name"`
+AC_SUBST([xz])
+
+AC_CONFIG_FILES([
+	Doxyfile
+	Makefile
+	po/Makefile.in
+	lib/Makefile
+	src/Makefile
+	src/liblzma/liblzma.pc
+	src/liblzma/Makefile
+	src/liblzma/api/Makefile
+	src/xz/Makefile
+	src/xzdec/Makefile
+	src/lzmainfo/Makefile
+	src/scripts/Makefile
+	src/scripts/xzdiff
+	src/scripts/xzgrep
+	src/scripts/xzmore
+	src/scripts/xzless
+	tests/Makefile
+	debug/Makefile
+])
+
+AC_OUTPUT
+
+# Some warnings
+if test x$tuklib_cv_physmem_method = xunknown; then
+	echo
+	echo "WARNING:"
+	echo "No supported method to detect the amount of RAM."
+	echo "Consider using --enable-assume-ram (if you didn't already)"
+	echo "or make a patch to add support for this operating system."
+fi
+
+# Not threading yet so don't warn.
+#if test x$tuklib_cv_cpucores_method = xunknown; then
+#	echo
+#	echo "WARNING:"
+#	echo "No supported method to detect the number of CPU cores."
+#fi
diff --git a/debug/Makefile.am b/debug/Makefile.am
new file mode 100644
index 0000000..23834f4
--- /dev/null
+++ b/debug/Makefile.am
@@ -0,0 +1,30 @@
+##
+## Author: Lasse Collin
+##
+## This file has been put into the public domain.
+## You can do whatever you want with this file.
+##
+
+noinst_PROGRAMS = \
+	repeat \
+	sync_flush \
+	full_flush \
+	memusage \
+	crc32 \
+	known_sizes \
+	hex2bin
+
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/src/common \
+	-I$(top_srcdir)/src/liblzma/api \
+	$(STATIC_CPPFLAGS)
+
+AM_LDFLAGS = $(STATIC_LDFLAGS)
+
+LDADD = $(top_builddir)/src/liblzma/liblzma.la
+
+if COND_GNULIB
+LDADD += $(top_builddir)/lib/libgnu.a
+endif
+
+LDADD += $(LTLIBINTL)
diff --git a/debug/README b/debug/README
new file mode 100644
index 0000000..749610d
--- /dev/null
+++ b/debug/README
@@ -0,0 +1,17 @@
+
+Debug tools
+-----------
+
+    This directory contains a few tiny programs that may be helpful when
+    debugging LZMA Utils.
+
+    These tools are not meant to be installed. Often one needs to edit
+    the source code a little to make the programs do the wanted things.
+    If you don't know how these programs could help you, it is likely
+    that they really are useless to you.
+
+    These aren't intended to be used as example programs. They take some
+    shortcuts here and there, which correct programs should not do. Many
+    possible errors (especially I/O errors) are ignored. Don't report
+    bugs or send patches to fix this kind of bugs.
+
diff --git a/debug/crc32.c b/debug/crc32.c
new file mode 100644
index 0000000..e545a3c
--- /dev/null
+++ b/debug/crc32.c
@@ -0,0 +1,39 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       crc32.c
+/// \brief      Primitive CRC32 calculation tool
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "sysdefs.h"
+#include "lzma.h"
+#include <stdio.h>
+
+
+int
+main(void)
+{
+	uint32_t crc = 0;
+
+	do {
+		uint8_t buf[BUFSIZ];
+		const size_t size = fread(buf, 1, sizeof(buf), stdin);
+		crc = lzma_crc32(buf, size, crc);
+	} while (!ferror(stdin) && !feof(stdin));
+
+	//printf("%08" PRIX32 "\n", crc);
+
+	// I want it little endian so it's easy to work with hex editor.
+	printf("%02" PRIX32 " ", crc & 0xFF);
+	printf("%02" PRIX32 " ", (crc >> 8) & 0xFF);
+	printf("%02" PRIX32 " ", (crc >> 16) & 0xFF);
+	printf("%02" PRIX32 " ", crc >> 24);
+	printf("\n");
+
+	return 0;
+}
diff --git a/debug/full_flush.c b/debug/full_flush.c
new file mode 100644
index 0000000..67442b1
--- /dev/null
+++ b/debug/full_flush.c
@@ -0,0 +1,102 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       full_flush.c
+/// \brief      Encode files using LZMA_FULL_FLUSH
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "sysdefs.h"
+#include "lzma.h"
+#include <stdio.h>
+
+
+static lzma_stream strm = LZMA_STREAM_INIT;
+static FILE *file_in;
+
+
+static void
+encode(size_t size, lzma_action action)
+{
+	static const size_t CHUNK = 64;
+	uint8_t in[CHUNK];
+	uint8_t out[CHUNK];
+	lzma_ret ret;
+
+	do {
+		if (strm.avail_in == 0 && size > 0) {
+			const size_t amount = my_min(size, CHUNK);
+			strm.avail_in = fread(in, 1, amount, file_in);
+			strm.next_in = in;
+			size -= amount; // Intentionally not using avail_in.
+		}
+
+		strm.next_out = out;
+		strm.avail_out = CHUNK;
+
+		ret = lzma_code(&strm, size == 0 ? action : LZMA_RUN);
+
+		if (ret != LZMA_OK && ret != LZMA_STREAM_END) {
+			fprintf(stderr, "%s:%u: %s: ret == %d\n",
+					__FILE__, __LINE__, __func__, ret);
+			exit(1);
+		}
+
+		fwrite(out, 1, CHUNK - strm.avail_out, stdout);
+
+	} while (size > 0 || strm.avail_out == 0);
+
+	if ((action == LZMA_RUN && ret != LZMA_OK)
+			|| (action != LZMA_RUN && ret != LZMA_STREAM_END)) {
+		fprintf(stderr, "%s:%u: %s: ret == %d\n",
+				__FILE__, __LINE__, __func__, ret);
+		exit(1);
+	}
+}
+
+
+int
+main(int argc, char **argv)
+{
+	file_in = argc > 1 ? fopen(argv[1], "rb") : stdin;
+
+
+	// Config
+	lzma_options_lzma opt_lzma;
+	if (lzma_lzma_preset(&opt_lzma, 1)) {
+		fprintf(stderr, "preset failed\n");
+		exit(1);
+	}
+	lzma_filter filters[LZMA_FILTERS_MAX + 1];
+	filters[0].id = LZMA_FILTER_LZMA2;
+	filters[0].options = &opt_lzma;
+	filters[1].id = LZMA_VLI_UNKNOWN;
+
+	// Init
+	if (lzma_stream_encoder(&strm, filters, LZMA_CHECK_CRC32) != LZMA_OK) {
+		fprintf(stderr, "init failed\n");
+		exit(1);
+	}
+
+// 	if (lzma_easy_encoder(&strm, 1)) {
+// 		fprintf(stderr, "init failed\n");
+// 		exit(1);
+// 	}
+
+	// Encoding
+	encode(0, LZMA_FULL_FLUSH);
+	encode(6, LZMA_FULL_FLUSH);
+	encode(0, LZMA_FULL_FLUSH);
+	encode(7, LZMA_FULL_FLUSH);
+	encode(0, LZMA_FULL_FLUSH);
+	encode(0, LZMA_FINISH);
+
+	// Clean up
+	lzma_end(&strm);
+
+	return 0;
+}
diff --git a/debug/hex2bin.c b/debug/hex2bin.c
new file mode 100644
index 0000000..7324624
--- /dev/null
+++ b/debug/hex2bin.c
@@ -0,0 +1,53 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       hex2bin.c
+/// \brief      Converts hexadecimal input strings to binary
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "sysdefs.h"
+#include <stdio.h>
+#include <ctype.h>
+
+
+static int
+getbin(int x)
+{
+	if (x >= '0' && x <= '9')
+		return x - '0';
+
+	if (x >= 'A' && x <= 'F')
+		return x - 'A' + 10;
+
+	return x - 'a' + 10;
+}
+
+
+int
+main(void)
+{
+	while (true) {
+		int byte = getchar();
+		if (byte == EOF)
+			return 0;
+		if (!isxdigit(byte))
+			continue;
+
+		const int digit = getchar();
+		if (digit == EOF || !isxdigit(digit)) {
+			fprintf(stderr, "Invalid input\n");
+			return 1;
+		}
+
+		byte = (getbin(byte) << 4) | getbin(digit);
+		if (putchar(byte) == EOF) {
+			perror(NULL);
+			return 1;
+		}
+	}
+}
diff --git a/debug/known_sizes.c b/debug/known_sizes.c
new file mode 100644
index 0000000..6c3641f
--- /dev/null
+++ b/debug/known_sizes.c
@@ -0,0 +1,129 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       known_sizes.c
+/// \brief      Encodes .lzma Stream with sizes known in Block Header
+///
+/// The input file is encoded in RAM, and the known Compressed Size
+/// and/or Uncompressed Size values are stored in the Block Header.
+/// As of writing there's no such Stream encoder in liblzma.
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "sysdefs.h"
+#include "lzma.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/unistd.h>
+#include <stdio.h>
+
+
+// Support file sizes up to 1 MiB. We use this for output space too, so files
+// close to 1 MiB had better compress at least a little or we have a buffer
+// overflow.
+#define BUFFER_SIZE (1U << 20)
+
+
+int
+main(void)
+{
+	// Allocate the buffers.
+	uint8_t *in = malloc(BUFFER_SIZE);
+	uint8_t *out = malloc(BUFFER_SIZE);
+	if (in == NULL || out == NULL)
+		return 1;
+
+	// Fill the input buffer.
+	const size_t in_size = fread(in, 1, BUFFER_SIZE, stdin);
+
+	// Filter setup
+	lzma_options_lzma opt_lzma;
+	if (lzma_lzma_preset(&opt_lzma, 1))
+		return 1;
+
+	lzma_filter filters[] = {
+		{
+			.id = LZMA_FILTER_LZMA2,
+			.options = &opt_lzma
+		},
+		{
+			.id = LZMA_VLI_UNKNOWN
+		}
+	};
+
+	lzma_block block = {
+		.check = LZMA_CHECK_CRC32,
+		.compressed_size = BUFFER_SIZE, // Worst case reserve
+		.uncompressed_size = in_size,
+		.filters = filters,
+	};
+
+	lzma_stream strm = LZMA_STREAM_INIT;
+	if (lzma_block_encoder(&strm, &block) != LZMA_OK)
+		return 1;
+
+	// Reserve space for Stream Header and Block Header. We need to
+	// calculate the size of the Block Header first.
+	if (lzma_block_header_size(&block) != LZMA_OK)
+		return 1;
+
+	size_t out_size = LZMA_STREAM_HEADER_SIZE + block.header_size;
+
+	strm.next_in = in;
+	strm.avail_in = in_size;
+	strm.next_out = out + out_size;
+	strm.avail_out = BUFFER_SIZE - out_size;
+
+	if (lzma_code(&strm, LZMA_FINISH) != LZMA_STREAM_END)
+		return 1;
+
+	out_size += strm.total_out;
+
+	if (lzma_block_header_encode(&block, out + LZMA_STREAM_HEADER_SIZE)
+			!= LZMA_OK)
+		return 1;
+
+	lzma_index *idx = lzma_index_init(NULL);
+	if (idx == NULL)
+		return 1;
+
+	if (lzma_index_append(idx, NULL, block.header_size + strm.total_out,
+			strm.total_in) != LZMA_OK)
+		return 1;
+
+	if (lzma_index_encoder(&strm, idx) != LZMA_OK)
+		return 1;
+
+	if (lzma_code(&strm, LZMA_RUN) != LZMA_STREAM_END)
+		return 1;
+
+	out_size += strm.total_out;
+
+	lzma_end(&strm);
+
+	lzma_index_end(idx, NULL);
+
+	// Encode the Stream Header and Stream Footer. backwards_size is
+	// needed only for the Stream Footer.
+	lzma_stream_flags sf = {
+		.backward_size = strm.total_out,
+		.check = block.check,
+	};
+
+	if (lzma_stream_header_encode(&sf, out) != LZMA_OK)
+		return 1;
+
+	if (lzma_stream_footer_encode(&sf, out + out_size) != LZMA_OK)
+		return 1;
+
+	out_size += LZMA_STREAM_HEADER_SIZE;
+
+	// Write out the file.
+	fwrite(out, 1, out_size, stdout);
+
+	return 0;
+}
diff --git a/debug/memusage.c b/debug/memusage.c
new file mode 100644
index 0000000..bd72b5a
--- /dev/null
+++ b/debug/memusage.c
@@ -0,0 +1,51 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       memusage.c
+/// \brief      Calculates memory usage using lzma_memory_usage()
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "sysdefs.h"
+#include "lzma.h"
+#include <stdio.h>
+
+int
+main(void)
+{
+	lzma_options_lzma lzma = {
+		.dict_size = (1U << 30) + (1U << 29),
+		.lc = 3,
+		.lp = 0,
+		.pb = 2,
+		.preset_dict = NULL,
+		.preset_dict_size = 0,
+		.mode = LZMA_MODE_NORMAL,
+		.nice_len = 48,
+		.mf = LZMA_MF_BT4,
+		.depth = 0,
+	};
+
+/*
+	lzma_options_filter filters[] = {
+		{ LZMA_FILTER_LZMA1,
+			(lzma_options_lzma *)&lzma_preset_lzma[6 - 1] },
+		{ UINT64_MAX, NULL }
+	};
+*/
+	lzma_filter filters[] = {
+		{ LZMA_FILTER_LZMA1, &lzma },
+		{ UINT64_MAX, NULL }
+	};
+
+	printf("Encoder: %10" PRIu64 " B\n",
+			lzma_raw_encoder_memusage(filters));
+	printf("Decoder: %10" PRIu64 " B\n",
+			lzma_raw_decoder_memusage(filters));
+
+	return 0;
+}
diff --git a/debug/repeat.c b/debug/repeat.c
new file mode 100644
index 0000000..a00bde2
--- /dev/null
+++ b/debug/repeat.c
@@ -0,0 +1,36 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       repeat.c
+/// \brief      Repeats given string given times
+///
+/// This program can be useful when debugging run-length encoder in
+/// the Subblock filter, especially the condition when repeat count
+/// doesn't fit into 28-bit integer.
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "sysdefs.h"
+#include <stdio.h>
+
+
+int
+main(int argc, char **argv)
+{
+	if (argc != 3) {
+		fprintf(stderr, "Usage: %s COUNT STRING\n", argv[0]);
+		exit(1);
+	}
+
+	unsigned long long count = strtoull(argv[1], NULL, 10);
+	const size_t size = strlen(argv[2]);
+
+	while (count-- != 0)
+		fwrite(argv[2], 1, size, stdout);
+
+	return !!(ferror(stdout) || fclose(stdout));
+}
diff --git a/debug/sync_flush.c b/debug/sync_flush.c
new file mode 100644
index 0000000..fc2ebcb
--- /dev/null
+++ b/debug/sync_flush.c
@@ -0,0 +1,124 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       sync_flush.c
+/// \brief      Encode files using LZMA_SYNC_FLUSH
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "sysdefs.h"
+#include "lzma.h"
+#include <stdio.h>
+
+
+static lzma_stream strm = LZMA_STREAM_INIT;
+static FILE *file_in;
+
+
+static void
+encode(size_t size, lzma_action action)
+{
+	static const size_t CHUNK = 64;
+	uint8_t in[CHUNK];
+	uint8_t out[CHUNK];
+	lzma_ret ret;
+
+	do {
+		if (strm.avail_in == 0 && size > 0) {
+			const size_t amount = my_min(size, CHUNK);
+			strm.avail_in = fread(in, 1, amount, file_in);
+			strm.next_in = in;
+			size -= amount; // Intentionally not using avail_in.
+		}
+
+		strm.next_out = out;
+		strm.avail_out = CHUNK;
+
+		ret = lzma_code(&strm, size == 0 ? action : LZMA_RUN);
+
+		if (ret != LZMA_OK && ret != LZMA_STREAM_END) {
+			fprintf(stderr, "%s:%u: %s: ret == %d\n",
+					__FILE__, __LINE__, __func__, ret);
+			exit(1);
+		}
+
+		fwrite(out, 1, CHUNK - strm.avail_out, stdout);
+
+	} while (size > 0 || strm.avail_out == 0);
+
+	if ((action == LZMA_RUN && ret != LZMA_OK)
+			|| (action != LZMA_RUN && ret != LZMA_STREAM_END)) {
+		fprintf(stderr, "%s:%u: %s: ret == %d\n",
+				__FILE__, __LINE__, __func__, ret);
+		exit(1);
+	}
+}
+
+
+int
+main(int argc, char **argv)
+{
+	file_in = argc > 1 ? fopen(argv[1], "rb") : stdin;
+
+	// Config
+	lzma_options_lzma opt_lzma = {
+		.dict_size = 1U << 16,
+		.lc = LZMA_LC_DEFAULT,
+		.lp = LZMA_LP_DEFAULT,
+		.pb = LZMA_PB_DEFAULT,
+		.preset_dict = NULL,
+		.mode = LZMA_MODE_NORMAL,
+		.nice_len = 32,
+		.mf = LZMA_MF_HC3,
+		.depth = 0,
+	};
+
+	lzma_options_delta opt_delta = {
+		.dist = 16
+	};
+
+	lzma_filter filters[LZMA_FILTERS_MAX + 1];
+	filters[0].id = LZMA_FILTER_LZMA2;
+	filters[0].options = &opt_lzma;
+	filters[1].id = LZMA_VLI_UNKNOWN;
+
+	// Init
+	if (lzma_stream_encoder(&strm, filters, LZMA_CHECK_CRC32) != LZMA_OK) {
+		fprintf(stderr, "init failed\n");
+		exit(1);
+	}
+
+	// Encoding
+	encode(0, LZMA_SYNC_FLUSH);
+	encode(6, LZMA_SYNC_FLUSH);
+	encode(0, LZMA_SYNC_FLUSH);
+	encode(7, LZMA_SYNC_FLUSH);
+	encode(0, LZMA_SYNC_FLUSH);
+	encode(0, LZMA_FINISH);
+
+/*
+	encode(53, LZMA_SYNC_FLUSH);
+	opt_lzma.lc = 2;
+	opt_lzma.lp = 1;
+	opt_lzma.pb = 0;
+	if (lzma_filters_update(&strm, filters) != LZMA_OK) {
+		fprintf(stderr, "update failed\n");
+		exit(1);
+	}
+	encode(404, LZMA_FINISH);
+*/
+
+	// Clean up
+	lzma_end(&strm);
+
+	return 0;
+
+	// Prevent useless warnings so we don't need to have special CFLAGS
+	// to disable -Werror.
+	(void)opt_lzma;
+	(void)opt_delta;
+}
diff --git a/doc/faq.txt b/doc/faq.txt
new file mode 100644
index 0000000..8e87457
--- /dev/null
+++ b/doc/faq.txt
@@ -0,0 +1,128 @@
+
+XZ Utils FAQ
+============
+
+Q:  What do the letters XZ mean?
+
+A:  Nothing. They are just two letters, which come from the file format
+    suffix .xz. The .xz suffix was selected, because it seemed to be
+    pretty much unused. It is no deeper meaning.
+
+
+Q:  What are LZMA and LZMA2?
+
+A:  LZMA stands for Lempel-Ziv-Markov chain-Algorithm. It is the name
+    of the compression algorithm designed by Igor Pavlov for 7-Zip.
+    LZMA is based on LZ77 and range encoding.
+
+    LZMA2 is an updated version of the original LZMA to fix a couple of
+    practical issues. In context of XZ Utils, LZMA is called LZMA1 to
+    emphasize that LZMA is not the same thing as LZMA2. LZMA2 is the
+    primary compression algorithm in the .xz file format.
+
+
+Q:  There are many LZMA related projects. How does XZ Utils relate to them?
+
+A:  7-Zip and LZMA SDK are the original projects. LZMA SDK is roughly
+    a subset of the 7-Zip source tree.
+
+    p7zip is 7-Zip's command line tools ported to POSIX-like systems.
+
+    LZMA Utils provide a gzip-like lzma tool for POSIX-like systems.
+    LZMA Utils are based on LZMA SDK. XZ Utils are the successor to
+    LZMA Utils.
+
+    There are several other projects using LZMA. Most are more or less
+    based on LZMA SDK.
+
+
+Q:  Do XZ Utils support the .7z format?
+
+A:  No. Use 7-Zip (Windows) or p7zip (POSIX-like systems) to handle .7z
+    files.
+
+
+Q:  I have many .tar.7z files. Can I convert them to .tar.xz without
+    spending hours recompressing the data?
+
+A:  In the "extra" directory, there is a script named 7z2lzma.bash which
+    is able to convert some .7z files to the .lzma format (not .xz). It
+    needs the 7za (or 7z) command from p7zip. The script may silently
+    produce corrupt output if certain assumptions are not met, so
+    decompress the resulting .lzma file and compare it against the
+    original before deleting the original file!
+
+
+Q:  I have many .lzma files. Can I quickly convert them to the .xz format?
+
+A:  For now, no. Since XZ Utils supports the .lzma format, it's usually
+    not too bad to keep the old files in the old format. If you want to
+    do the conversion anyway, you need to decompress the .lzma files and
+    then recompress to the .xz format.
+
+    Technically, there is a way to make the conversion relatively fast
+    (roughly twice the time that normal decompression takes). Writing
+    such a tool would take quite a bit time though, and would probably
+    be useful to only a few people. If you really want such a conversion
+    tool, contact Lasse Collin and offer some money.
+
+
+Q:  I have installed xz, but my tar doesn't recognize .tar.xz files.
+    How can I extract .tar.xz files?
+
+A:  xz -dc foo.tar.xz | tar xf -
+
+
+Q:  Can I recover parts of a broken .xz file (e.g. corrupted CD-R)?
+
+A:  It may be possible if the file consists of multiple blocks, which
+    typically is not the case if the file was created in single-threaded
+    mode. There is no recovery program yet.
+
+
+Q:  Is (some part of) XZ Utils patented?
+
+A:  Lasse Collin is not aware of any patents that could affect XZ Utils.
+    However, due to nature of software patents, it's not possible to
+    guarantee that XZ Utils isn't affected by any third party patent(s).
+
+
+Q:  Where can I find documentation about the file format and algorithms?
+
+A:  The .xz format is documented in xz-file-format.txt. It is a container
+    format only, and doesn't include descriptions of any non-trivial
+    filters.
+
+    Documenting LZMA and LZMA2 is planned, but for now, there is no other
+    documentation that the source code. Before you begin, you should know
+    the basics of LZ77 and range coding algorithms. LZMA is based on LZ77,
+    but LZMA is *a lot* more complex. Range coding is used to compress
+    the final bitstream like Huffman coding is used in Deflate.
+
+
+Q:  I cannot find BCJ and BCJ2 filters. Don't they exist in liblzma?
+
+A:  BCJ filter is called "x86" in liblzma. BCJ2 is not included,
+    because it requires using more than one encoded output stream.
+
+
+Q:  How do I build a program that needs liblzmadec (lzmadec.h)?
+
+A:  liblzmadec is part of LZMA Utils. XZ Utils has liblzma, but no
+    liblzmadec. The code using liblzmadec should be ported to use
+    liblzma instead. If you cannot or don't want to do that, download
+    LZMA Utils from <http://tukaani.org/lzma/>.
+
+
+Q:  The default build of liblzma is too big. How can I make it smaller?
+
+A:  Give --enable-small to the configure script. Use also appropriate
+    --enable or --disable options to include only those filter encoders
+    and decoders and integrity checks that you actually need. Use
+    CFLAGS=-Os (with GCC) or equivalent to tell your compiler to optimize
+    for size. See INSTALL for information about configure options.
+
+    If the result is still too big, take a look at XZ Embedded. It is
+    a separate project, which provides a limited but significantly
+    smaller XZ decoder implementation than XZ Utils.
+
diff --git a/doc/history.txt b/doc/history.txt
new file mode 100644
index 0000000..c97492e
--- /dev/null
+++ b/doc/history.txt
@@ -0,0 +1,149 @@
+
+History of LZMA Utils and XZ Utils
+==================================
+
+Tukaani distribution
+
+    In 2005, there was a small group working on Tukaani distribution, which
+    was a Slackware fork. One of the project goals was to fit the distro on
+    a single 700 MiB ISO-9660 image. Using LZMA instead of gzip helped a
+    lot. Roughly speaking, one could fit data that took 1000 MiB in gzipped
+    form into 700 MiB with LZMA. Naturally compression ratio varied across
+    packages, but this was what we got on average.
+
+    Slackware packages have traditionally had .tgz as the filename suffix,
+    which is an abbreviation of .tar.gz. A logical naming for LZMA
+    compressed packages was .tlz, being an abbreviation of .tar.lzma.
+
+    At the end of the year 2007, there was no distribution under the
+    Tukaani project anymore, but development of LZMA Utils was kept going.
+    Still, there were .tlz packages around, because at least Vector Linux
+    (a Slackware based distribution) used LZMA for its packages.
+
+    First versions of the modified pkgtools used the LZMA_Alone tool from
+    Igor Pavlov's LZMA SDK as is. It was fine, because users wouldn't need
+    to interact with LZMA_Alone directly. But people soon wanted to use
+    LZMA for other files too, and the interface of LZMA_Alone wasn't
+    comfortable for those used to gzip and bzip2.
+
+
+First steps of LZMA Utils
+
+    The first version of LZMA Utils (4.22.0) included a shell script called
+    lzmash. It was wrapper that had gzip-like command line interface. It
+    used the LZMA_Alone tool from LZMA SDK to do all the real work. zgrep,
+    zdiff, and related scripts from gzip were adapted work with LZMA and
+    were part of the first LZMA Utils release too.
+
+    LZMA Utils 4.22.0 included also lzmadec, which was a small (less than
+    10 KiB) decoder-only command line tool. It was written on top of the
+    decoder-only C code found from the LZMA SDK. lzmadec was convenient in
+    situations where LZMA_Alone (a few hundred KiB) would be too big.
+
+    lzmash and lzmadec were written by Lasse Collin.
+
+
+Second generation
+
+    The lzmash script was an ugly and not very secure hack. The last
+    version of LZMA Utils to use lzmash was 4.27.1.
+
+    LZMA Utils 4.32.0beta1 introduced a new lzma command line tool written
+    by Ville Koskinen. It was written in C++, and used the encoder and
+    decoder from C++ LZMA SDK with little modifications. This tool replaced
+    both the lzmash script and the LZMA_Alone command line tool in LZMA
+    Utils.
+
+    Introducing this new tool caused some temporary incompatibilities,
+    because LZMA_Alone executable was simply named lzma like the new
+    command line tool, but they had completely different command line
+    interface. The file format was still the same.
+
+    Lasse wrote liblzmadec, which was a small decoder-only library based
+    on the C code found from LZMA SDK. liblzmadec had API similar to zlib,
+    although there were some significant differences, which made it
+    non-trivial to use it in some applications designed for zlib and
+    libbzip2.
+
+    The lzmadec command line tool was converted to use liblzmadec.
+
+    Alexandre Sauvé helped converting build system to use GNU Autotools.
+    This made is easier to test for certain less portable features needed
+    by the new command line tool.
+
+    Since the new command line tool never got completely finished (for
+    example, it didn't support LZMA_OPT environment variable), the intent
+    was to not call 4.32.x stable. Similarly, liblzmadec wasn't polished,
+    but appeared to work well enough, so some people started using it too.
+
+    Because the development of the third generation of LZMA Utils was
+    delayed considerably (3-4 years), the 4.32.x branch had to be kept
+    maintained. It got some bug fixes now and then, and finally it was
+    decided to call it stable, although most of the missing features were
+    never added.
+
+
+File format problems
+
+    The file format used by LZMA_Alone was primitive. It was designed for
+    embedded systems in mind, and thus provided only minimal set of
+    features. The two biggest problems for non-embedded use were lack of
+    magic bytes and integrity check.
+
+    Igor and Lasse started developing a new file format with some help
+    from Ville Koskinen. Also Mark Adler, Mikko Pouru, H. Peter Anvin,
+    and Lars Wirzenius helped with some minor things at some point of the
+    development. Designing the new format took quite a long time (actually,
+    too long time would be more appropriate expression). It was mostly
+    because Lasse was quite slow at getting things done due to personal
+    reasons.
+
+    Originally the new format was supposed to use the same .lzma suffix
+    that was already used by the old file format. Switching to the new
+    format wouldn't have caused much trouble when the old format wasn't
+    used by many people. But since the development of the new format took
+    so long time, the old format got quite popular, and it was decided
+    that the new file format must use a different suffix.
+
+    It was decided to use .xz as the suffix of the new file format. The
+    first stable .xz file format specification was finally released in
+    December 2008. In addition to fixing the most obvious problems of
+    the old .lzma format, the .xz format added some new features like
+    support for multiple filters (compression algorithms), filter chaining
+    (like piping on the command line), and limited random-access reading.
+
+    Currently the primary compression algorithm used in .xz is LZMA2.
+    It is an extension on top of the original LZMA to fix some practical
+    problems: LZMA2 adds support for flushing the encoder, uncompressed
+    chunks, eases stateful decoder implementations, and improves support
+    for multithreading. Since LZMA2 is better than the original LZMA, the
+    original LZMA is not supported in .xz.
+
+
+Transition to XZ Utils
+
+    The early versions of XZ Utils were called LZMA Utils. The first
+    releases were 4.42.0alphas. They dropped the rest of the C++ LZMA SDK.
+    The code was still directly based on LZMA SDK but ported to C and
+    converted from callback API to stateful API. Later, Igor Pavlov made
+    C version of the LZMA encoder too; these ports from C++ to C were
+    independent in LZMA SDK and LZMA Utils.
+
+    The core of the new LZMA Utils was liblzma, a compression library with
+    zlib-like API. liblzma supported both the old and new file format. The
+    gzip-like lzma command line tool was rewritten to use liblzma.
+
+    The new LZMA Utils code base was renamed to XZ Utils when the name
+    of the new file format had been decided. The liblzma compression
+    library retained its name though, because changing it would have
+    caused unnecessary breakage in applications already using the early
+    liblzma snapshots.
+
+    The xz command line tool can emulate the gzip-like lzma tool by
+    creating appropriate symlinks (e.g. lzma -> xz). Thus, practically
+    all scripts using the lzma tool from LZMA Utils will work as is with
+    XZ Utils (and will keep using the old .lzma format). Still, the .lzma
+    format is more or less deprecated. XZ Utils will keep supporting it,
+    but new applications should use the .xz format, and migrating old
+    applications to .xz is often a good idea too.
+
diff --git a/doc/lzma-file-format.txt b/doc/lzma-file-format.txt
new file mode 100644
index 0000000..21fcb19
--- /dev/null
+++ b/doc/lzma-file-format.txt
@@ -0,0 +1,166 @@
+
+The .lzma File Format
+=====================
+
+        0. Preface
+           0.1. Notices and Acknowledgements
+           0.2. Changes
+        1. File Format
+           1.1. Header
+                1.1.1. Properties
+                1.1.2. Dictionary Size
+                1.1.3. Uncompressed Size
+           1.2. LZMA Compressed Data
+        2. References
+
+
+0. Preface
+
+        This document describes the .lzma file format, which is
+        sometimes also called LZMA_Alone format. It is a legacy file
+        format, which is being or has been replaced by the .xz format.
+        The MIME type of the .lzma format is `application/x-lzma'.
+
+        The most commonly used software to handle .lzma files are
+        LZMA SDK, LZMA Utils, 7-Zip, and XZ Utils. This document
+        describes some of the differences between these implementations
+        and gives hints what subset of the .lzma format is the most
+        portable.
+
+
+0.1. Notices and Acknowledgements
+
+        This file format was designed by Igor Pavlov for use in
+        LZMA SDK. This document was written by Lasse Collin
+        <lasse.collin@tukaani.org> using the documentation found
+        from the LZMA SDK.
+
+        This document has been put into the public domain.
+
+
+0.2. Changes
+
+        Last modified: 2009-05-01 11:15+0300
+
+
+1. File Format
+
+        +-+-+-+-+-+-+-+-+-+-+-+-+-+==========================+
+        |         Header          |   LZMA Compressed Data   |
+        +-+-+-+-+-+-+-+-+-+-+-+-+-+==========================+
+
+        The .lzma format file consist of 13-byte Header followed by
+        the LZMA Compressed Data.
+
+        Unlike the .gz, .bz2, and .xz formats, it is not possible to
+        concatenate multiple .lzma files as is and expect the
+        decompression tool to decode the resulting file as if it were
+        a single .lzma file.
+
+        For example, the command line tools from LZMA Utils and
+        LZMA SDK silently ignore all the data after the first .lzma
+        stream. In contrast, the command line tool from XZ Utils
+        considers the .lzma file to be corrupt if there is data after
+        the first .lzma stream.
+
+
+1.1. Header
+
+        +------------+----+----+----+----+--+--+--+--+--+--+--+--+
+        | Properties |  Dictionary Size  |   Uncompressed Size   |
+        +------------+----+----+----+----+--+--+--+--+--+--+--+--+
+
+
+1.1.1. Properties
+
+        The Properties field contains three properties. An abbreviation
+        is given in parentheses, followed by the value range of the
+        property. The field consists of
+
+            1) the number of literal context bits (lc, [0, 8]);
+            2) the number of literal position bits (lp, [0, 4]); and
+            3) the number of position bits (pb, [0, 4]).
+
+        The properties are encoded using the following formula:
+
+            Properties = (pb * 5 + lp) * 9 + lc
+
+        The following C code illustrates a straightforward way to
+        decode the Properties field:
+
+            uint8_t lc, lp, pb;
+            uint8_t prop = get_lzma_properties();
+            if (prop > (4 * 5 + 4) * 9 + 8)
+                return LZMA_PROPERTIES_ERROR;
+
+            pb = prop / (9 * 5);
+            prop -= pb * 9 * 5;
+            lp = prop / 9;
+            lc = prop - lp * 9;
+
+        XZ Utils has an additional requirement: lc + lp <= 4. Files
+        which don't follow this requirement cannot be decompressed
+        with XZ Utils. Usually this isn't a problem since the most
+        common lc/lp/pb values are 3/0/2. It is the only lc/lp/pb
+        combination that the files created by LZMA Utils can have,
+        but LZMA Utils can decompress files with any lc/lp/pb.
+
+
+1.1.2. Dictionary Size
+
+        Dictionary Size is stored as an unsigned 32-bit little endian
+        integer. Any 32-bit value is possible, but for maximum
+        portability, only sizes of 2^n and 2^n + 2^(n-1) should be
+        used.
+
+        LZMA Utils creates only files with dictionary size 2^n,
+        16 <= n <= 25. LZMA Utils can decompress files with any
+        dictionary size.
+
+        XZ Utils creates and decompresses .lzma files only with
+        dictionary sizes 2^n and 2^n + 2^(n-1). If some other
+        dictionary size is specified when compressing, the value
+        stored in the Dictionary Size field is a rounded up, but the
+        specified value is still used in the actual compression code.
+
+
+1.1.3. Uncompressed Size
+
+        Uncompressed Size is stored as unsigned 64-bit little endian
+        integer. A special value of 0xFFFF_FFFF_FFFF_FFFF indicates
+        that Uncompressed Size is unknown. End of Payload Marker (*)
+        is used if and only if Uncompressed Size is unknown.
+
+        XZ Utils rejects files whose Uncompressed Size field specifies
+        a known size that is 256 GiB or more. This is to reject false
+        positives when trying to guess if the input file is in the
+        .lzma format. When Uncompressed Size is unknown, there is no
+        limit for the uncompressed size of the file.
+
+        (*) Some tools use the term End of Stream (EOS) marker
+            instead of End of Payload Marker.
+
+
+1.2. LZMA Compressed Data
+
+        Detailed description of the format of this field is out of
+        scope of this document.
+
+
+2. References
+
+        LZMA SDK - The original LZMA implementation
+        http://7-zip.org/sdk.html
+
+        7-Zip
+        http://7-zip.org/
+
+        LZMA Utils - LZMA adapted to POSIX-like systems
+        http://tukaani.org/lzma/
+
+        XZ Utils - The next generation of LZMA Utils
+        http://tukaani.org/xz/
+
+        The .xz file format - The successor of the the .lzma format
+        http://tukaani.org/xz/xz-file-format.txt
+
diff --git a/doc/xz-file-format.txt b/doc/xz-file-format.txt
new file mode 100644
index 0000000..4ed6650
--- /dev/null
+++ b/doc/xz-file-format.txt
@@ -0,0 +1,1150 @@
+
+The .xz File Format
+===================
+
+Version 1.0.4 (2009-08-27)
+
+
+        0. Preface
+           0.1. Notices and Acknowledgements
+           0.2. Getting the Latest Version
+           0.3. Version History
+        1. Conventions
+           1.1. Byte and Its Representation
+           1.2. Multibyte Integers
+        2. Overall Structure of .xz File
+           2.1. Stream
+                2.1.1. Stream Header
+                       2.1.1.1. Header Magic Bytes
+                       2.1.1.2. Stream Flags
+                       2.1.1.3. CRC32
+                2.1.2. Stream Footer
+                       2.1.2.1. CRC32
+                       2.1.2.2. Backward Size
+                       2.1.2.3. Stream Flags
+                       2.1.2.4. Footer Magic Bytes
+           2.2. Stream Padding
+        3. Block
+           3.1. Block Header
+                3.1.1. Block Header Size
+                3.1.2. Block Flags
+                3.1.3. Compressed Size
+                3.1.4. Uncompressed Size
+                3.1.5. List of Filter Flags
+                3.1.6. Header Padding
+                3.1.7. CRC32
+           3.2. Compressed Data
+           3.3. Block Padding
+           3.4. Check
+        4. Index
+           4.1. Index Indicator
+           4.2. Number of Records
+           4.3. List of Records
+                4.3.1. Unpadded Size
+                4.3.2. Uncompressed Size
+           4.4. Index Padding
+           4.5. CRC32
+        5. Filter Chains
+           5.1. Alignment
+           5.2. Security
+           5.3. Filters
+                5.3.1. LZMA2
+                5.3.2. Branch/Call/Jump Filters for Executables
+                5.3.3. Delta
+                       5.3.3.1. Format of the Encoded Output
+           5.4. Custom Filter IDs
+                5.4.1. Reserved Custom Filter ID Ranges
+        6. Cyclic Redundancy Checks
+        7. References
+
+
+0. Preface
+
+        This document describes the .xz file format (filename suffix
+        ".xz", MIME type "application/x-xz"). It is intended that this
+        this format replace the old .lzma format used by LZMA SDK and
+        LZMA Utils.
+
+
+0.1. Notices and Acknowledgements
+
+        This file format was designed by Lasse Collin
+        <lasse.collin@tukaani.org> and Igor Pavlov.
+
+        Special thanks for helping with this document goes to
+        Ville Koskinen. Thanks for helping with this document goes to
+        Mark Adler, H. Peter Anvin, Mikko Pouru, and Lars Wirzenius.
+
+        This document has been put into the public domain.
+
+
+0.2. Getting the Latest Version
+
+        The latest official version of this document can be downloaded
+        from <http://tukaani.org/xz/xz-file-format.txt>.
+
+        Specific versions of this document have a filename
+        xz-file-format-X.Y.Z.txt where X.Y.Z is the version number.
+        For example, the version 1.0.0 of this document is available
+        at <http://tukaani.org/xz/xz-file-format-1.0.0.txt>.
+
+
+0.3. Version History
+
+        Version   Date          Description
+
+        1.0.4     2009-08-27    Language improvements in Sections 1.2,
+                                2.1.1.2, 3.1.1, 3.1.2, and 5.3.1
+
+        1.0.3     2009-06-05    Spelling fixes in Sections 5.1 and 5.4
+
+        1.0.2     2009-06-04    Typo fixes in Sections 4 and 5.3.1
+
+        1.0.1     2009-06-01    Typo fix in Section 0.3 and minor
+                                clarifications to Sections 2, 2.2,
+                                3.3, 4.4, and 5.3.2
+
+        1.0.0     2009-01-14    The first official version
+
+
+1. Conventions
+
+        The key words "MUST", "MUST NOT", "REQUIRED", "SHOULD",
+        "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+        document are to be interpreted as described in [RFC-2119].
+
+        Indicating a warning means displaying a message, returning
+        appropriate exit status, or doing something else to let the
+        user know that something worth warning occurred. The operation
+        SHOULD still finish if a warning is indicated.
+
+        Indicating an error means displaying a message, returning
+        appropriate exit status, or doing something else to let the
+        user know that something prevented successfully finishing the
+        operation. The operation MUST be aborted once an error has
+        been indicated.
+
+
+1.1. Byte and Its Representation
+
+        In this document, byte is always 8 bits.
+
+        A "null byte" has all bits unset. That is, the value of a null
+        byte is 0x00.
+
+        To represent byte blocks, this document uses notation that
+        is similar to the notation used in [RFC-1952]:
+
+            +-------+
+            |  Foo  |   One byte.
+            +-------+
+
+            +---+---+
+            |  Foo  |   Two bytes; that is, some of the vertical bars
+            +---+---+   can be missing.
+
+            +=======+
+            |  Foo  |   Zero or more bytes.
+            +=======+
+
+        In this document, a boxed byte or a byte sequence declared
+        using this notation is called "a field". The example field
+        above would be called "the Foo field" or plain "Foo".
+
+        If there are many fields, they may be split to multiple lines.
+        This is indicated with an arrow ("--->"):
+
+            +=====+
+            | Foo |
+            +=====+
+
+                 +=====+
+            ---> | Bar |
+                 +=====+
+
+        The above is equivalent to this:
+
+            +=====+=====+
+            | Foo | Bar |
+            +=====+=====+
+
+
+1.2. Multibyte Integers
+
+        Multibyte integers of static length, such as CRC values,
+        are stored in little endian byte order (least significant
+        byte first).
+
+        When smaller values are more likely than bigger values (for
+        example file sizes), multibyte integers are encoded in a
+        variable-length representation:
+          - Numbers in the range [0, 127] are copied as is, and take
+            one byte of space.
+          - Bigger numbers will occupy two or more bytes. All but the
+            last byte of the multibyte representation have the highest
+            (eighth) bit set.
+
+        For now, the value of the variable-length integers is limited
+        to 63 bits, which limits the encoded size of the integer to
+        nine bytes. These limits may be increased in the future if
+        needed.
+
+        The following C code illustrates encoding and decoding of
+        variable-length integers. The functions return the number of
+        bytes occupied by the integer (1-9), or zero on error.
+
+            #include <stddef.h>
+            #include <inttypes.h>
+
+            size_t
+            encode(uint8_t buf[static 9], uint64_t num)
+            {
+                if (num > UINT64_MAX / 2)
+                    return 0;
+
+                size_t i = 0;
+
+                while (num >= 0x80) {
+                    buf[i++] = (uint8_t)(num) | 0x80;
+                    num >>= 7;
+                }
+
+                buf[i++] = (uint8_t)(num);
+
+                return i;
+            }
+
+            size_t
+            decode(const uint8_t buf[], size_t size_max, uint64_t *num)
+            {
+                if (size_max == 0)
+                    return 0;
+
+                if (size_max > 9)
+                    size_max = 9;
+
+                *num = buf[0] & 0x7F;
+                size_t i = 0;
+
+                while (buf[i++] & 0x80) {
+                    if (i >= size_max || buf[i] == 0x00)
+                        return 0;
+
+                    *num |= (uint64_t)(buf[i] & 0x7F) << (i * 7);
+                }
+
+                return i;
+            }
+
+
+2. Overall Structure of .xz File
+
+        A standalone .xz files consist of one or more Streams which may
+        have Stream Padding between or after them:
+
+            +========+================+========+================+
+            | Stream | Stream Padding | Stream | Stream Padding | ...
+            +========+================+========+================+
+
+        The sizes of Stream and Stream Padding are always multiples
+        of four bytes, thus the size of every valid .xz file MUST be
+        a multiple of four bytes.
+
+        While a typical file contains only one Stream and no Stream
+        Padding, a decoder handling standalone .xz files SHOULD support
+        files that have more than one Stream or Stream Padding.
+
+        In contrast to standalone .xz files, when the .xz file format
+        is used as an internal part of some other file format or
+        communication protocol, it usually is expected that the decoder
+        stops after the first Stream, and doesn't look for Stream
+        Padding or possibly other Streams.
+
+
+2.1. Stream
+
+        +-+-+-+-+-+-+-+-+-+-+-+-+=======+=======+     +=======+
+        |     Stream Header     | Block | Block | ... | Block |
+        +-+-+-+-+-+-+-+-+-+-+-+-+=======+=======+     +=======+
+
+             +=======+-+-+-+-+-+-+-+-+-+-+-+-+
+        ---> | Index |     Stream Footer     |
+             +=======+-+-+-+-+-+-+-+-+-+-+-+-+
+
+        All the above fields have a size that is a multiple of four. If
+        Stream is used as an internal part of another file format, it
+        is RECOMMENDED to make the Stream start at an offset that is
+        a multiple of four bytes.
+
+        Stream Header, Index, and Stream Footer are always present in
+        a Stream. The maximum size of the Index field is 16 GiB (2^34).
+
+        There are zero or more Blocks. The maximum number of Blocks is
+        limited only by the maximum size of the Index field.
+
+        Total size of a Stream MUST be less than 8 EiB (2^63 bytes).
+        The same limit applies to the total amount of uncompressed
+        data stored in a Stream.
+
+        If an implementation supports handling .xz files with multiple
+        concatenated Streams, it MAY apply the above limits to the file
+        as a whole instead of limiting per Stream basis.
+
+
+2.1.1. Stream Header
+
+        +---+---+---+---+---+---+-------+------+--+--+--+--+
+        |  Header Magic Bytes   | Stream Flags |   CRC32   |
+        +---+---+---+---+---+---+-------+------+--+--+--+--+
+
+
+2.1.1.1. Header Magic Bytes
+
+        The first six (6) bytes of the Stream are so called Header
+        Magic Bytes. They can be used to identify the file type.
+
+            Using a C array and ASCII:
+            const uint8_t HEADER_MAGIC[6]
+                    = { 0xFD, '7', 'z', 'X', 'Z', 0x00 };
+
+            In plain hexadecimal:
+            FD 37 7A 58 5A 00
+
+        Notes:
+          - The first byte (0xFD) was chosen so that the files cannot
+            be erroneously detected as being in .lzma format, in which
+            the first byte is in the range [0x00, 0xE0].
+          - The sixth byte (0x00) was chosen to prevent applications
+            from misdetecting the file as a text file.
+
+        If the Header Magic Bytes don't match, the decoder MUST
+        indicate an error.
+
+
+2.1.1.2. Stream Flags
+
+        The first byte of Stream Flags is always a null byte. In the
+        future, this byte may be used to indicate a new Stream version
+        or other Stream properties.
+
+        The second byte of Stream Flags is a bit field:
+
+            Bit(s)  Mask  Description
+             0-3    0x0F  Type of Check (see Section 3.4):
+                              ID    Size      Check name
+                              0x00   0 bytes  None
+                              0x01   4 bytes  CRC32
+                              0x02   4 bytes  (Reserved)
+                              0x03   4 bytes  (Reserved)
+                              0x04   8 bytes  CRC64
+                              0x05   8 bytes  (Reserved)
+                              0x06   8 bytes  (Reserved)
+                              0x07  16 bytes  (Reserved)
+                              0x08  16 bytes  (Reserved)
+                              0x09  16 bytes  (Reserved)
+                              0x0A  32 bytes  SHA-256
+                              0x0B  32 bytes  (Reserved)
+                              0x0C  32 bytes  (Reserved)
+                              0x0D  64 bytes  (Reserved)
+                              0x0E  64 bytes  (Reserved)
+                              0x0F  64 bytes  (Reserved)
+             4-7    0xF0  Reserved for future use; MUST be zero for now.
+
+        Implementations SHOULD support at least the Check IDs 0x00
+        (None) and 0x01 (CRC32). Supporting other Check IDs is
+        OPTIONAL. If an unsupported Check is used, the decoder SHOULD
+        indicate a warning or error.
+
+        If any reserved bit is set, the decoder MUST indicate an error.
+        It is possible that there is a new field present which the
+        decoder is not aware of, and can thus parse the Stream Header
+        incorrectly.
+
+
+2.1.1.3. CRC32
+
+        The CRC32 is calculated from the Stream Flags field. It is
+        stored as an unsigned 32-bit little endian integer. If the
+        calculated value does not match the stored one, the decoder
+        MUST indicate an error.
+
+        The idea is that Stream Flags would always be two bytes, even
+        if new features are needed. This way old decoders will be able
+        to verify the CRC32 calculated from Stream Flags, and thus
+        distinguish between corrupt files (CRC32 doesn't match) and
+        files that the decoder doesn't support (CRC32 matches but
+        Stream Flags has reserved bits set).
+
+
+2.1.2. Stream Footer
+
+        +-+-+-+-+---+---+---+---+-------+------+----------+---------+
+        | CRC32 | Backward Size | Stream Flags | Footer Magic Bytes |
+        +-+-+-+-+---+---+---+---+-------+------+----------+---------+
+
+
+2.1.2.1. CRC32
+
+        The CRC32 is calculated from the Backward Size and Stream Flags
+        fields. It is stored as an unsigned 32-bit little endian
+        integer. If the calculated value does not match the stored one,
+        the decoder MUST indicate an error.
+
+        The reason to have the CRC32 field before the Backward Size and
+        Stream Flags fields is to keep the four-byte fields aligned to
+        a multiple of four bytes.
+
+
+2.1.2.2. Backward Size
+
+        Backward Size is stored as a 32-bit little endian integer,
+        which indicates the size of the Index field as multiple of
+        four bytes, minimum value being four bytes:
+
+            real_backward_size = (stored_backward_size + 1) * 4;
+
+        If the stored value does not match the real size of the Index
+        field, the decoder MUST indicate an error.
+
+        Using a fixed-size integer to store Backward Size makes
+        it slightly simpler to parse the Stream Footer when the
+        application needs to parse the Stream backwards.
+
+
+2.1.2.3. Stream Flags
+
+        This is a copy of the Stream Flags field from the Stream
+        Header. The information stored to Stream Flags is needed
+        when parsing the Stream backwards. The decoder MUST compare
+        the Stream Flags fields in both Stream Header and Stream
+        Footer, and indicate an error if they are not identical.
+
+
+2.1.2.4. Footer Magic Bytes
+
+        As the last step of the decoding process, the decoder MUST
+        verify the existence of Footer Magic Bytes. If they don't
+        match, an error MUST be indicated.
+
+            Using a C array and ASCII:
+            const uint8_t FOOTER_MAGIC[2] = { 'Y', 'Z' };
+
+            In hexadecimal:
+            59 5A
+
+        The primary reason to have Footer Magic Bytes is to make
+        it easier to detect incomplete files quickly, without
+        uncompressing. If the file does not end with Footer Magic Bytes
+        (excluding Stream Padding described in Section 2.2), it cannot
+        be undamaged, unless someone has intentionally appended garbage
+        after the end of the Stream.
+
+
+2.2. Stream Padding
+
+        Only the decoders that support decoding of concatenated Streams
+        MUST support Stream Padding.
+
+        Stream Padding MUST contain only null bytes. To preserve the
+        four-byte alignment of consecutive Streams, the size of Stream
+        Padding MUST be a multiple of four bytes. Empty Stream Padding
+        is allowed. If these requirements are not met, the decoder MUST
+        indicate an error.
+
+        Note that non-empty Stream Padding is allowed at the end of the
+        file; there doesn't need to be a new Stream after non-empty
+        Stream Padding. This can be convenient in certain situations
+        [GNU-tar].
+
+        The possibility of Stream Padding MUST be taken into account
+        when designing an application that parses Streams backwards,
+        and the application supports concatenated Streams.
+
+
+3. Block
+
+        +==============+=================+===============+=======+
+        | Block Header | Compressed Data | Block Padding | Check |
+        +==============+=================+===============+=======+
+
+
+3.1. Block Header
+
+        +-------------------+-------------+=================+
+        | Block Header Size | Block Flags | Compressed Size |
+        +-------------------+-------------+=================+
+
+             +===================+======================+
+        ---> | Uncompressed Size | List of Filter Flags |
+             +===================+======================+
+
+             +================+--+--+--+--+
+        ---> | Header Padding |   CRC32   |
+             +================+--+--+--+--+
+
+
+3.1.1. Block Header Size
+
+        This field overlaps with the Index Indicator field (see
+        Section 4.1).
+
+        This field contains the size of the Block Header field,
+        including the Block Header Size field itself. Valid values are
+        in the range [0x01, 0xFF], which indicate the size of the Block
+        Header as multiples of four bytes, minimum size being eight
+        bytes:
+
+            real_header_size = (encoded_header_size + 1) * 4;
+
+        If a Block Header bigger than 1024 bytes is needed in the
+        future, a new field can be added between the Block Header and
+        Compressed Data fields. The presence of this new field would
+        be indicated in the Block Header field.
+
+
+3.1.2. Block Flags
+
+        The Block Flags field is a bit field:
+
+            Bit(s)  Mask  Description
+             0-1    0x03  Number of filters (1-4)
+             2-5    0x3C  Reserved for future use; MUST be zero for now.
+              6     0x40  The Compressed Size field is present.
+              7     0x80  The Uncompressed Size field is present.
+
+        If any reserved bit is set, the decoder MUST indicate an error.
+        It is possible that there is a new field present which the
+        decoder is not aware of, and can thus parse the Block Header
+        incorrectly.
+
+
+3.1.3. Compressed Size
+
+        This field is present only if the appropriate bit is set in
+        the Block Flags field (see Section 3.1.2).
+
+        The Compressed Size field contains the size of the Compressed
+        Data field, which MUST be non-zero. Compressed Size is stored
+        using the encoding described in Section 1.2. If the Compressed
+        Size doesn't match the size of the Compressed Data field, the
+        decoder MUST indicate an error.
+
+
+3.1.4. Uncompressed Size
+
+        This field is present only if the appropriate bit is set in
+        the Block Flags field (see Section 3.1.2).
+
+        The Uncompressed Size field contains the size of the Block
+        after uncompressing. Uncompressed Size is stored using the
+        encoding described in Section 1.2. If the Uncompressed Size
+        does not match the real uncompressed size, the decoder MUST
+        indicate an error.
+
+        Storing the Compressed Size and Uncompressed Size fields serves
+        several purposes:
+          - The decoder knows how much memory it needs to allocate
+            for a temporary buffer in multithreaded mode.
+          - Simple error detection: wrong size indicates a broken file.
+          - Seeking forwards to a specific location in streamed mode.
+
+        It should be noted that the only reliable way to determine
+        the real uncompressed size is to uncompress the Block,
+        because the Block Header and Index fields may contain
+        (intentionally or unintentionally) invalid information.
+
+
+3.1.5. List of Filter Flags
+
+        +================+================+     +================+
+        | Filter 0 Flags | Filter 1 Flags | ... | Filter n Flags |
+        +================+================+     +================+
+
+        The number of Filter Flags fields is stored in the Block Flags
+        field (see Section 3.1.2).
+
+        The format of each Filter Flags field is as follows:
+
+            +===========+====================+===================+
+            | Filter ID | Size of Properties | Filter Properties |
+            +===========+====================+===================+
+
+        Both Filter ID and Size of Properties are stored using the
+        encoding described in Section 1.2. Size of Properties indicates
+        the size of the Filter Properties field as bytes. The list of
+        officially defined Filter IDs and the formats of their Filter
+        Properties are described in Section 5.3.
+
+        Filter IDs greater than or equal to 0x4000_0000_0000_0000
+        (2^62) are reserved for implementation-specific internal use.
+        These Filter IDs MUST never be used in List of Filter Flags.
+
+
+3.1.6. Header Padding
+
+        This field contains as many null byte as it is needed to make
+        the Block Header have the size specified in Block Header Size.
+        If any of the bytes are not null bytes, the decoder MUST
+        indicate an error. It is possible that there is a new field
+        present which the decoder is not aware of, and can thus parse
+        the Block Header incorrectly.
+
+
+3.1.7. CRC32
+
+        The CRC32 is calculated over everything in the Block Header
+        field except the CRC32 field itself. It is stored as an
+        unsigned 32-bit little endian integer. If the calculated
+        value does not match the stored one, the decoder MUST indicate
+        an error.
+
+        By verifying the CRC32 of the Block Header before parsing the
+        actual contents allows the decoder to distinguish between
+        corrupt and unsupported files.
+
+
+3.2. Compressed Data
+
+        The format of Compressed Data depends on Block Flags and List
+        of Filter Flags. Excluding the descriptions of the simplest
+        filters in Section 5.3, the format of the filter-specific
+        encoded data is out of scope of this document.
+
+
+3.3. Block Padding
+
+        Block Padding MUST contain 0-3 null bytes to make the size of
+        the Block a multiple of four bytes. This can be needed when
+        the size of Compressed Data is not a multiple of four. If any
+        of the bytes in Block Padding are not null bytes, the decoder
+        MUST indicate an error.
+
+
+3.4. Check
+
+        The type and size of the Check field depends on which bits
+        are set in the Stream Flags field (see Section 2.1.1.2).
+
+        The Check, when used, is calculated from the original
+        uncompressed data. If the calculated Check does not match the
+        stored one, the decoder MUST indicate an error. If the selected
+        type of Check is not supported by the decoder, it SHOULD
+        indicate a warning or error.
+
+
+4. Index
+
+        +-----------------+===================+
+        | Index Indicator | Number of Records |
+        +-----------------+===================+
+
+             +=================+===============+-+-+-+-+
+        ---> | List of Records | Index Padding | CRC32 |
+             +=================+===============+-+-+-+-+
+
+        Index serves several purposes. Using it, one can
+          - verify that all Blocks in a Stream have been processed;
+          - find out the uncompressed size of a Stream; and
+          - quickly access the beginning of any Block (random access).
+
+
+4.1. Index Indicator
+
+        This field overlaps with the Block Header Size field (see
+        Section 3.1.1). The value of Index Indicator is always 0x00.
+
+
+4.2. Number of Records
+
+        This field indicates how many Records there are in the List
+        of Records field, and thus how many Blocks there are in the
+        Stream. The value is stored using the encoding described in
+        Section 1.2. If the decoder has decoded all the Blocks of the
+        Stream, and then notices that the Number of Records doesn't
+        match the real number of Blocks, the decoder MUST indicate an
+        error.
+
+
+4.3. List of Records
+
+        List of Records consists of as many Records as indicated by the
+        Number of Records field:
+
+            +========+========+
+            | Record | Record | ...
+            +========+========+
+
+        Each Record contains information about one Block:
+
+            +===============+===================+
+            | Unpadded Size | Uncompressed Size |
+            +===============+===================+
+
+        If the decoder has decoded all the Blocks of the Stream, it
+        MUST verify that the contents of the Records match the real
+        Unpadded Size and Uncompressed Size of the respective Blocks.
+
+        Implementation hint: It is possible to verify the Index with
+        constant memory usage by calculating for example SHA-256 of
+        both the real size values and the List of Records, then
+        comparing the hash values. Implementing this using
+        non-cryptographic hash like CRC32 SHOULD be avoided unless
+        small code size is important.
+
+        If the decoder supports random-access reading, it MUST verify
+        that Unpadded Size and Uncompressed Size of every completely
+        decoded Block match the sizes stored in the Index. If only
+        partial Block is decoded, the decoder MUST verify that the
+        processed sizes don't exceed the sizes stored in the Index.
+
+
+4.3.1. Unpadded Size
+
+        This field indicates the size of the Block excluding the Block
+        Padding field. That is, Unpadded Size is the size of the Block
+        Header, Compressed Data, and Check fields. Unpadded Size is
+        stored using the encoding described in Section 1.2. The value
+        MUST never be zero; with the current structure of Blocks, the
+        actual minimum value for Unpadded Size is five.
+
+        Implementation note: Because the size of the Block Padding
+        field is not included in Unpadded Size, calculating the total
+        size of a Stream or doing random-access reading requires
+        calculating the actual size of the Blocks by rounding Unpadded
+        Sizes up to the next multiple of four.
+
+        The reason to exclude Block Padding from Unpadded Size is to
+        ease making a raw copy of Compressed Data without Block
+        Padding. This can be useful, for example, if someone wants
+        to convert Streams to some other file format quickly.
+
+
+4.3.2. Uncompressed Size
+
+        This field indicates the Uncompressed Size of the respective
+        Block as bytes. The value is stored using the encoding
+        described in Section 1.2.
+
+
+4.4. Index Padding
+
+        This field MUST contain 0-3 null bytes to pad the Index to
+        a multiple of four bytes. If any of the bytes are not null
+        bytes, the decoder MUST indicate an error.
+
+
+4.5. CRC32
+
+        The CRC32 is calculated over everything in the Index field
+        except the CRC32 field itself. The CRC32 is stored as an
+        unsigned 32-bit little endian integer. If the calculated
+        value does not match the stored one, the decoder MUST indicate
+        an error.
+
+
+5. Filter Chains
+
+        The Block Flags field defines how many filters are used. When
+        more than one filter is used, the filters are chained; that is,
+        the output of one filter is the input of another filter. The
+        following figure illustrates the direction of data flow.
+
+                    v   Uncompressed Data   ^
+                    |       Filter 0        |
+            Encoder |       Filter 1        | Decoder
+                    |       Filter n        |
+                    v    Compressed Data    ^
+
+
+5.1. Alignment
+
+        Alignment of uncompressed input data is usually the job of
+        the application producing the data. For example, to get the
+        best results, an archiver tool should make sure that all
+        PowerPC executable files in the archive stream start at
+        offsets that are multiples of four bytes.
+
+        Some filters, for example LZMA2, can be configured to take
+        advantage of specified alignment of input data. Note that
+        taking advantage of aligned input can be beneficial also when
+        a filter is not the first filter in the chain. For example,
+        if you compress PowerPC executables, you may want to use the
+        PowerPC filter and chain that with the LZMA2 filter. Because
+        not only the input but also the output alignment of the PowerPC
+        filter is four bytes, it is now beneficial to set LZMA2
+        settings so that the LZMA2 encoder can take advantage of its
+        four-byte-aligned input data.
+
+        The output of the last filter in the chain is stored to the
+        Compressed Data field, which is is guaranteed to be aligned
+        to a multiple of four bytes relative to the beginning of the
+        Stream. This can increase
+          - speed, if the filtered data is handled multiple bytes at
+            a time by the filter-specific encoder and decoder,
+            because accessing aligned data in computer memory is
+            usually faster; and
+          - compression ratio, if the output data is later compressed
+            with an external compression tool.
+
+
+5.2. Security
+
+        If filters would be allowed to be chained freely, it would be
+        possible to create malicious files, that would be very slow to
+        decode. Such files could be used to create denial of service
+        attacks.
+
+        Slow files could occur when multiple filters are chained:
+
+            v   Compressed input data
+            |   Filter 1 decoder (last filter)
+            |   Filter 0 decoder (non-last filter)
+            v   Uncompressed output data
+
+        The decoder of the last filter in the chain produces a lot of
+        output from little input. Another filter in the chain takes the
+        output of the last filter, and produces very little output
+        while consuming a lot of input. As a result, a lot of data is
+        moved inside the filter chain, but the filter chain as a whole
+        gets very little work done.
+
+        To prevent this kind of slow files, there are restrictions on
+        how the filters can be chained. These restrictions MUST be
+        taken into account when designing new filters.
+
+        The maximum number of filters in the chain has been limited to
+        four, thus there can be at maximum of three non-last filters.
+        Of these three non-last filters, only two are allowed to change
+        the size of the data.
+
+        The non-last filters, that change the size of the data, MUST
+        have a limit how much the decoder can compress the data: the
+        decoder SHOULD produce at least n bytes of output when the
+        filter is given 2n bytes of input. This  limit is not
+        absolute, but significant deviations MUST be avoided.
+
+        The above limitations guarantee that if the last filter in the
+        chain produces 4n bytes of output, the chain as a whole will
+        produce at least n bytes of output.
+
+
+5.3. Filters
+
+5.3.1. LZMA2
+
+        LZMA (Lempel-Ziv-Markov chain-Algorithm) is a general-purpose
+        compression algorithm with high compression ratio and fast
+        decompression. LZMA is based on LZ77 and range coding
+        algorithms.
+
+        LZMA2 is an extension on top of the original LZMA. LZMA2 uses
+        LZMA internally, but adds support for flushing the encoder,
+        uncompressed chunks, eases stateful decoder implementations,
+        and improves support for multithreading. Thus, the plain LZMA
+        will not be supported in this file format.
+
+            Filter ID:                  0x21
+            Size of Filter Properties:  1 byte
+            Changes size of data:       Yes
+            Allow as a non-last filter: No
+            Allow as the last filter:   Yes
+
+            Preferred alignment:
+                Input data:             Adjustable to 1/2/4/8/16 byte(s)
+                Output data:            1 byte
+
+        The format of the one-byte Filter Properties field is as
+        follows:
+
+            Bits   Mask   Description
+            0-5    0x3F   Dictionary Size
+            6-7    0xC0   Reserved for future use; MUST be zero for now.
+
+        Dictionary Size is encoded with one-bit mantissa and five-bit
+        exponent. The smallest dictionary size is 4 KiB and the biggest
+        is 4 GiB.
+
+            Raw value   Mantissa   Exponent   Dictionary size
+                0           2         11         4 KiB
+                1           3         11         6 KiB
+                2           2         12         8 KiB
+                3           3         12        12 KiB
+                4           2         13        16 KiB
+                5           3         13        24 KiB
+                6           2         14        32 KiB
+              ...         ...        ...      ...
+               35           3         27       768 MiB
+               36           2         28      1024 MiB
+               37           3         29      1536 MiB
+               38           2         30      2048 MiB
+               39           3         30      3072 MiB
+               40           2         31      4096 MiB - 1 B
+
+        Instead of having a table in the decoder, the dictionary size
+        can be decoded using the following C code:
+
+            const uint8_t bits = get_dictionary_flags() & 0x3F;
+            if (bits > 40)
+                return DICTIONARY_TOO_BIG; // Bigger than 4 GiB
+
+            uint32_t dictionary_size;
+            if (bits == 40) {
+                dictionary_size = UINT32_MAX;
+            } else {
+                dictionary_size = 2 | (bits & 1);
+                dictionary_size <<= bits / 2 + 11;
+            }
+
+
+5.3.2. Branch/Call/Jump Filters for Executables
+
+        These filters convert relative branch, call, and jump
+        instructions to their absolute counterparts in executable
+        files. This conversion increases redundancy and thus
+        compression ratio.
+
+            Size of Filter Properties:  0 or 4 bytes
+            Changes size of data:       No
+            Allow as a non-last filter: Yes
+            Allow as the last filter:   No
+
+        Below is the list of filters in this category. The alignment
+        is the same for both input and output data.
+
+            Filter ID   Alignment   Description
+              0x04       1 byte     x86 filter (BCJ)
+              0x05       4 bytes    PowerPC (big endian) filter
+              0x06      16 bytes    IA64 filter
+              0x07       4 bytes    ARM (little endian) filter
+              0x08       2 bytes    ARM Thumb (little endian) filter
+              0x09       4 bytes    SPARC filter
+
+        If the size of Filter Properties is four bytes, the Filter
+        Properties field contains the start offset used for address
+        conversions. It is stored as an unsigned 32-bit little endian
+        integer. The start offset MUST be a multiple of the alignment
+        of the filter as listed in the table above; if it isn't, the
+        decoder MUST indicate an error. If the size of Filter
+        Properties is zero, the start offset is zero.
+
+        Setting the start offset may be useful if an executable has
+        multiple sections, and there are many cross-section calls.
+        Taking advantage of this feature usually requires usage of
+        the Subblock filter, whose design is not complete yet.
+
+
+5.3.3. Delta
+
+        The Delta filter may increase compression ratio when the value
+        of the next byte correlates with the value of an earlier byte
+        at specified distance.
+
+            Filter ID:                  0x03
+            Size of Filter Properties:  1 byte
+            Changes size of data:       No
+            Allow as a non-last filter: Yes
+            Allow as the last filter:   No
+
+            Preferred alignment:
+                Input data:             1 byte
+                Output data:            Same as the original input data
+
+        The Properties byte indicates the delta distance, which can be
+        1-256 bytes backwards from the current byte: 0x00 indicates
+        distance of 1 byte and 0xFF distance of 256 bytes.
+
+
+5.3.3.1. Format of the Encoded Output
+
+        The code below illustrates both encoding and decoding with
+        the Delta filter.
+
+            // Distance is in the range [1, 256].
+            const unsigned int distance = get_properties_byte() + 1;
+            uint8_t pos = 0;
+            uint8_t delta[256];
+
+            memset(delta, 0, sizeof(delta));
+
+            while (1) {
+                const int byte = read_byte();
+                if (byte == EOF)
+                    break;
+
+                uint8_t tmp = delta[(uint8_t)(distance + pos)];
+                if (is_encoder) {
+                    tmp = (uint8_t)(byte) - tmp;
+                    delta[pos] = (uint8_t)(byte);
+                } else {
+                    tmp = (uint8_t)(byte) + tmp;
+                    delta[pos] = tmp;
+                }
+
+                write_byte(tmp);
+                --pos;
+            }
+
+
+5.4. Custom Filter IDs
+
+        If a developer wants to use custom Filter IDs, he has two
+        choices. The first choice is to contact Lasse Collin and ask
+        him to allocate a range of IDs for the developer.
+
+        The second choice is to generate a 40-bit random integer,
+        which the developer can use as his personal Developer ID.
+        To minimize the risk of collisions, Developer ID has to be
+        a randomly generated integer, not manually selected "hex word".
+        The following command, which works on many free operating
+        systems, can be used to generate Developer ID:
+
+            dd if=/dev/urandom bs=5 count=1 | hexdump
+
+        The developer can then use his Developer ID to create unique
+        (well, hopefully unique) Filter IDs.
+
+            Bits    Mask                    Description
+             0-15   0x0000_0000_0000_FFFF   Filter ID
+            16-55   0x00FF_FFFF_FFFF_0000   Developer ID
+            56-62   0x3F00_0000_0000_0000   Static prefix: 0x3F
+
+        The resulting 63-bit integer will use 9 bytes of space when
+        stored using the encoding described in Section 1.2. To get
+        a shorter ID, see the beginning of this Section how to
+        request a custom ID range.
+
+
+5.4.1. Reserved Custom Filter ID Ranges
+
+        Range                       Description
+        0x0000_0300 - 0x0000_04FF   Reserved to ease .7z compatibility
+        0x0002_0000 - 0x0007_FFFF   Reserved to ease .7z compatibility
+        0x0200_0000 - 0x07FF_FFFF   Reserved to ease .7z compatibility
+
+
+6. Cyclic Redundancy Checks
+
+        There are several incompatible variations to calculate CRC32
+        and CRC64. For simplicity and clarity, complete examples are
+        provided to calculate the checks as they are used in this file
+        format. Implementations MAY use different code as long as it
+        gives identical results.
+
+        The program below reads data from standard input, calculates
+        the CRC32 and CRC64 values, and prints the calculated values
+        as big endian hexadecimal strings to standard output.
+
+            #include <stddef.h>
+            #include <inttypes.h>
+            #include <stdio.h>
+
+            uint32_t crc32_table[256];
+            uint64_t crc64_table[256];
+
+            void
+            init(void)
+            {
+                static const uint32_t poly32 = UINT32_C(0xEDB88320);
+                static const uint64_t poly64
+                        = UINT64_C(0xC96C5795D7870F42);
+
+                for (size_t i = 0; i < 256; ++i) {
+                    uint32_t crc32 = i;
+                    uint64_t crc64 = i;
+
+                    for (size_t j = 0; j < 8; ++j) {
+                        if (crc32 & 1)
+                            crc32 = (crc32 >> 1) ^ poly32;
+                        else
+                            crc32 >>= 1;
+
+                        if (crc64 & 1)
+                            crc64 = (crc64 >> 1) ^ poly64;
+                        else
+                            crc64 >>= 1;
+                    }
+
+                    crc32_table[i] = crc32;
+                    crc64_table[i] = crc64;
+                }
+            }
+
+            uint32_t
+            crc32(const uint8_t *buf, size_t size, uint32_t crc)
+            {
+                crc = ~crc;
+                for (size_t i = 0; i < size; ++i)
+                    crc = crc32_table[buf[i] ^ (crc & 0xFF)]
+                            ^ (crc >> 8);
+                return ~crc;
+            }
+
+            uint64_t
+            crc64(const uint8_t *buf, size_t size, uint64_t crc)
+            {
+                crc = ~crc;
+                for (size_t i = 0; i < size; ++i)
+                    crc = crc64_table[buf[i] ^ (crc & 0xFF)]
+                            ^ (crc >> 8);
+                return ~crc;
+            }
+
+            int
+            main()
+            {
+                init();
+
+                uint32_t value32 = 0;
+                uint64_t value64 = 0;
+                uint64_t total_size = 0;
+                uint8_t buf[8192];
+
+                while (1) {
+                    const size_t buf_size
+                            = fread(buf, 1, sizeof(buf), stdin);
+                    if (buf_size == 0)
+                        break;
+
+                    total_size += buf_size;
+                    value32 = crc32(buf, buf_size, value32);
+                    value64 = crc64(buf, buf_size, value64);
+                }
+
+                printf("Bytes:  %" PRIu64 "\n", total_size);
+                printf("CRC-32: 0x%08" PRIX32 "\n", value32);
+                printf("CRC-64: 0x%016" PRIX64 "\n", value64);
+
+                return 0;
+            }
+
+
+7. References
+
+        LZMA SDK - The original LZMA implementation
+        http://7-zip.org/sdk.html
+
+        LZMA Utils - LZMA adapted to POSIX-like systems
+        http://tukaani.org/lzma/
+
+        XZ Utils - The next generation of LZMA Utils
+        http://tukaani.org/xz/
+
+        [RFC-1952]
+        GZIP file format specification version 4.3
+        http://www.ietf.org/rfc/rfc1952.txt
+          - Notation of byte boxes in section "2.1. Overall conventions"
+
+        [RFC-2119]
+        Key words for use in RFCs to Indicate Requirement Levels
+        http://www.ietf.org/rfc/rfc2119.txt
+
+        [GNU-tar]
+        GNU tar 1.21 manual
+        http://www.gnu.org/software/tar/manual/html_node/Blocking-Factor.html
+          - Node 9.4.2 "Blocking Factor", paragraph that begins
+            "gzip will complain about trailing garbage"
+          - Note that this URL points to the latest version of the
+            manual, and may some day not contain the note which is in
+            1.21. For the exact version of the manual, download GNU
+            tar 1.21: ftp://ftp.gnu.org/pub/gnu/tar/tar-1.21.tar.gz
+
diff --git a/dos/Makefile b/dos/Makefile
new file mode 100644
index 0000000..0b8a088
--- /dev/null
+++ b/dos/Makefile
@@ -0,0 +1,255 @@
+###############################################################################
+#
+# Makefile to build XZ Utils using DJGPP
+#
+# Make flags to alter compilation:
+#
+#   DEBUG=1     Enable assertions. Don't use this for production builds!
+#               You may also want to set CFLAGS="-g -O0" to disable
+#               optimizations.
+#
+# The usual CPPFLAGS and CFLAGS are supported too.
+#
+###############################################################################
+#
+# Author: Lasse Collin
+#
+# This file has been put into the public domain.
+# You can do whatever you want with this file.
+#
+###############################################################################
+
+CC = gcc
+AR = ar
+STRIP = strip
+SED = sed
+RM = rm -f
+
+CFLAGS = -g -Wextra -Wfatal-errors -Wall -march=i386 -mtune=i686 -O2
+
+# NOTE: -fgnu89-inline is needed on DJGPP 2.04 beta and GCC 4.3.2
+# because time.h uses GNU-style "extern inline".
+ALL_CFLAGS = -std=gnu99 -fgnu89-inline
+
+ALL_CPPFLAGS = \
+	-I. \
+	-I../lib \
+	-I../src/common \
+	-I../src/liblzma/api \
+	-I../src/liblzma/common \
+	-I../src/liblzma/check \
+	-I../src/liblzma/rangecoder \
+	-I../src/liblzma/lz \
+	-I../src/liblzma/lzma \
+	-I../src/liblzma/delta \
+	-I../src/liblzma/simple \
+	-I../src/liblzma/subblock
+
+ALL_CPPFLAGS += -DHAVE_CONFIG_H
+
+ifdef DEBUG
+STRIP := rem Skipping strip
+else
+ALL_CPPFLAGS += -DNDEBUG
+endif
+
+ALL_CPPFLAGS += $(CPPFLAGS)
+ALL_CFLAGS += $(CFLAGS)
+
+
+################
+# Common rules #
+################
+
+.PHONY: all clean
+all: liblzma.a getopt.a xzdec.exe lzmadec.exe xz.exe
+clean: liblzma-clean getopt-clean xzdec-clean xz-clean
+
+
+#############
+# liblzma.a #
+#############
+
+LIBLZMA_SRCS_C = \
+	../src/liblzma/common/alone_decoder.c \
+	../src/liblzma/common/alone_encoder.c \
+	../src/liblzma/common/auto_decoder.c \
+	../src/liblzma/common/block_buffer_decoder.c \
+	../src/liblzma/common/block_buffer_encoder.c \
+	../src/liblzma/common/block_decoder.c \
+	../src/liblzma/common/block_encoder.c \
+	../src/liblzma/common/block_header_decoder.c \
+	../src/liblzma/common/block_header_encoder.c \
+	../src/liblzma/common/block_util.c \
+	../src/liblzma/common/common.c \
+	../src/liblzma/common/easy_buffer_encoder.c \
+	../src/liblzma/common/easy_decoder_memusage.c \
+	../src/liblzma/common/easy_encoder.c \
+	../src/liblzma/common/easy_encoder_memusage.c \
+	../src/liblzma/common/easy_preset.c \
+	../src/liblzma/common/filter_common.c \
+	../src/liblzma/common/filter_decoder.c \
+	../src/liblzma/common/filter_encoder.c \
+	../src/liblzma/common/filter_flags_decoder.c \
+	../src/liblzma/common/filter_flags_encoder.c \
+	../src/liblzma/common/index.c \
+	../src/liblzma/common/index_decoder.c \
+	../src/liblzma/common/index_encoder.c \
+	../src/liblzma/common/index_hash.c \
+	../src/liblzma/common/stream_buffer_decoder.c \
+	../src/liblzma/common/stream_buffer_encoder.c \
+	../src/liblzma/common/stream_decoder.c \
+	../src/liblzma/common/stream_encoder.c \
+	../src/liblzma/common/stream_flags_common.c \
+	../src/liblzma/common/stream_flags_decoder.c \
+	../src/liblzma/common/stream_flags_encoder.c \
+	../src/liblzma/common/vli_decoder.c \
+	../src/liblzma/common/vli_encoder.c \
+	../src/liblzma/common/vli_size.c \
+	../src/liblzma/check/check.c \
+	../src/liblzma/check/crc32_table.c \
+	../src/liblzma/check/crc64_table.c \
+	../src/liblzma/check/sha256.c \
+	../src/liblzma/rangecoder/price_table.c \
+	../src/liblzma/lz/lz_decoder.c \
+	../src/liblzma/lz/lz_encoder.c \
+	../src/liblzma/lz/lz_encoder_mf.c \
+	../src/liblzma/lzma/fastpos_table.c \
+	../src/liblzma/lzma/lzma2_decoder.c \
+	../src/liblzma/lzma/lzma2_encoder.c \
+	../src/liblzma/lzma/lzma_decoder.c \
+	../src/liblzma/lzma/lzma_encoder.c \
+	../src/liblzma/lzma/lzma_encoder_optimum_fast.c \
+	../src/liblzma/lzma/lzma_encoder_optimum_normal.c \
+	../src/liblzma/lzma/lzma_encoder_presets.c \
+	../src/liblzma/delta/delta_common.c \
+	../src/liblzma/delta/delta_decoder.c \
+	../src/liblzma/delta/delta_encoder.c \
+	../src/liblzma/simple/arm.c \
+	../src/liblzma/simple/armthumb.c \
+	../src/liblzma/simple/ia64.c \
+	../src/liblzma/simple/powerpc.c \
+	../src/liblzma/simple/simple_coder.c \
+	../src/liblzma/simple/simple_decoder.c \
+	../src/liblzma/simple/simple_encoder.c \
+	../src/liblzma/simple/sparc.c \
+	../src/liblzma/simple/x86.c
+
+LIBLZMA_SRCS_ASM = \
+	../src/liblzma/check/crc32_x86.S \
+	../src/liblzma/check/crc64_x86.S
+
+LIBLZMA_OBJS_C = $(LIBLZMA_SRCS_C:.c=.o)
+LIBLZMA_OBJS_ASM = $(LIBLZMA_SRCS_ASM:.S=.o)
+LIBLZMA_OBJS = $(LIBLZMA_OBJS_C) $(LIBLZMA_OBJS_ASM)
+
+$(LIBLZMA_OBJS_C): %.o: %.c
+	$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -c -o $@ $<
+
+$(LIBLZMA_OBJS_ASM): %.o: %.S
+	$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -c -o $@ $<
+
+liblzma.a: $(LIBLZMA_OBJS)
+	$(RM) $@
+	$(AR) rcs $@ $(LIBLZMA_OBJS)
+	$(STRIP) --strip-unneeded $@
+
+# Avoid too long command lines.
+.PHONY: liblzma-clean $(LIBLZMA_OBJS:.o=-clean)
+liblzma-clean: $(LIBLZMA_OBJS:.o=-clean)
+	-$(RM) liblzma.a
+
+$(LIBLZMA_OBJS:.o=-clean):
+	-$(RM) $(@:-clean=.o)
+
+
+###############
+# getopt_long #
+###############
+
+GETOPT_SRCS = \
+	../lib/getopt.c \
+	../lib/getopt1.c
+
+GETOPT_OBJS = $(GETOPT_SRCS:.c=.o)
+
+GETOPT_H = ../lib/getopt.h
+
+$(GETOPT_H): %.h: %.in.h
+	$(SED) "" $< > $@
+
+$(GETOPT_OBJS): %.o: %.c $(GETOPT_H)
+	$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -c -o $@ $<
+
+getopt.a: $(GETOPT_OBJS)
+	$(RM) $@
+	$(AR) rcs $@ $(GETOPT_OBJS)
+	$(STRIP) --strip-unneeded $@
+
+getopt-clean:
+	$(RM) $(GETOPT_H) $(GETOPT_OBJS) getopt.a
+
+
+###########################
+# xzdec.exe & lzmadec.exe #
+###########################
+
+XZDEC_SRCS = ../src/xzdec/xzdec.c
+
+xzdec.exe: getopt.a liblzma.a $(XZDEC_SRCS)
+	$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) $(XZDEC_SRCS) -o $@ getopt.a liblzma.a
+	$(STRIP) --strip-all $@
+	exe2coff $@
+	$(RM) $@
+	copy /b $(DJGPP:DJGPP.ENV=BIN\CWSDSTUB.EXE) + $(@:.exe=) $@
+	$(RM) $(@:.exe=)
+
+lzmadec.exe: getopt.a liblzma.a $(XZDEC_SRCS)
+	$(CC) $(ALL_CPPFLAGS) -DLZMADEC $(ALL_CFLAGS) $(XZDEC_SRCS) -o $@ getopt.a liblzma.a
+	$(STRIP) --strip-all $@
+	exe2coff $@
+	$(RM) $@
+	copy /b $(DJGPP:DJGPP.ENV=BIN\CWSDSTUB.EXE) + $(@:.exe=) $@
+	$(RM) $(@:.exe=)
+
+.PHONY: xzdec-clean
+xzdec-clean:
+	-$(RM) xzdec.exe lzmadec.exe xzdec lzmadec
+
+
+##########
+# xz.exe #
+##########
+
+XZ_SRCS = \
+	../src/xz/args.c \
+	../src/xz/coder.c \
+	../src/xz/file_io.c \
+	../src/xz/hardware.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
+
+XZ_OBJS = $(XZ_SRCS:.c=.o)
+
+$(XZ_OBJS): %.o: %.c
+	$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -c -o $@ $<
+
+xz.exe: getopt.a liblzma.a $(XZ_OBJS)
+	$(CC) $(ALL_CFLAGS) $(XZ_OBJS) -o $@ getopt.a liblzma.a
+	$(STRIP) --strip-all $@
+	exe2coff $@
+	$(RM) $@
+	copy /b $(DJGPP:DJGPP.ENV=BIN\CWSDSTUB.EXE) + $(@:.exe=) $@
+	$(RM) $(@:.exe=)
+
+# Avoid too long command lines.
+.PHONY: xz-clean $(XZ_OBJS:.o=-clean)
+xz-clean: $(XZ_OBJS:.o=-clean)
+	-$(RM) xz.exe xz
+
+$(XZ_OBJS:.o=-clean):
+	-$(RM) $(@:-clean=.o)
diff --git a/dos/README b/dos/README
new file mode 100644
index 0000000..649c58c
--- /dev/null
+++ b/dos/README
@@ -0,0 +1,113 @@
+
+XZ Utils on DOS
+===============
+
+Introduction
+
+    This document explains how to build XZ Utils for DOS using DJGPP.
+    The resulting binaries should run at least on various DOS versions
+    and under Windows 95/98/98SE/ME, which cannot run the Windows version
+    of XZ Utils.
+
+    This is currently experimental and has got very little testing.
+
+
+Getting and Installing DJGPP
+
+    You may use <http://www.delorie.com/djgpp/zip-picker.html> to help
+    deciding what to download, but as of writing (2009-02-13) that may
+    not be the most convenient way taking into account what components
+    are actually required to build XZ Utils. However, using the
+    zip-picker can still be worth doing to get nice short summary of
+    installation instructions (they can be found from readme.1st too).
+
+    For more manual method, first select a mirror from
+    <http://www.delorie.com/djgpp/getting.html>. You need
+    the following files:
+
+        unzip32.exe
+        beta/v2/djdev204.zip
+        v2gnu/bnu219b.zip
+        v2gnu/gcc432b.zip
+        v2gnu/mak3791b.zip
+        v2gnu/sed415b.zip
+        v2misc/csdpmi5b.zip
+
+    If newer versions are available, probably you should try them first.
+    Note that djdev203.zip is too old to build XZ Utils; you need at
+    least djdev204.zip. Also note that you want csdpmi5b.zip even if you
+    run under Windows or DOSEMU, because the XZ Utils Makefile will embed
+    cwsdstub.exe to the resulting binaries.
+
+    See the instructions in readme.1st found from djdev204.zip. Here's
+    a short summary, but you should still read readme.1st.
+
+        C:\> mkdir DJGPP
+        C:\> cd DJGPP
+        C:\DJGPP> c:\download\unzip32 c:\download\djdev204.zip
+        C:\DJGPP> c:\download\unzip32 c:\download\bnu219b.zip
+        C:\DJGPP> c:\download\unzip32 c:\download\gcc432b.zip
+        C:\DJGPP> c:\download\unzip32 c:\download\mak3791b.zip
+        C:\DJGPP> c:\download\unzip32 c:\download\sed415b.zip
+        C:\DJGPP> c:\download\unzip32 c:\download\csdpmi5b.zip
+
+        C:\DJGPP> set PATH=C:\DJGPP\BIN;%PATH%
+        C:\DJGPP> set DJGPP=C:\DJGPP\DJGPP.ENV
+
+    You may want to add the last two lines into AUTOEXEC.BAT or have,
+    for example, DJGPP.BAT which you can run before using DJGPP.
+
+    Make sure you use completely upper case path in the DJGPP environment
+    variable. This is not required by DJGPP, but the XZ Utils Makefile is
+    a bit stupid and expects that everything in DJGPP environment variable
+    is uppercase.
+
+
+Building
+
+    Just run "make" in this directory (the directory containing this
+    README). You should get liblzma.a, xz.exe, xzdec.exe, and
+    lzmadec.exe. Of these, probably xz.exe is the only interesting one.
+
+    Note: You need to have an environment that supports long filenames.
+    Once you have built XZ Utils, the resulting binaries can be run
+    without long filename support.
+
+
+Additional Make Flags and Targets
+
+    You may want to try some additional optimizations, which may or
+    may not make the code faster (and may or may not hit possible
+    compiler bugs more easily):
+
+        make CFLAGS="-O3 -fomit-frame-pointer -funroll-loops"
+
+    If you want to enable assertions (the assert() macro), use DEBUG=1.
+    You may want to disable optimizations too if you plan to actually
+    debug the code. Never use DEBUG=1 for production builds!
+
+        make DEBUG=1 CFLAGS="-g -O0"
+
+
+Bugs
+
+    "make clean" may remove src/xz/hardware.c when it tries to remove
+    src/xz/hardware-fixed.c. This is probably a bug somewhere in the
+    DOS environment I use. Maybe it tries truncated 8.3 name first and
+    since that gives a name of an existing file, it doesn't look for
+    long filename.
+
+    "xz -fc /dev/tty" hangs at least in DOSEMU and cannot be interrupted
+    by pressing C-c. Maybe xz should never accept non-regular files on
+    DOS even when --force is used.
+
+    Using different memory usage limit for encoding and decoding doesn't
+    make sense under pure DOS. Maybe it is still OK when running under
+    Windows.
+
+    The progress indicator of "xz -v" doesn't get updated when running
+    under Dosbox, but it works in DOSEMU. I currently (2009-02-13) don't
+    know if it works in other environments.
+
+    Report bugs to <lasse.collin@tukaani.org> (in English or Finnish).
+
diff --git a/dos/config.h b/dos/config.h
new file mode 100644
index 0000000..dfd6f79
--- /dev/null
+++ b/dos/config.h
@@ -0,0 +1,153 @@
+/* Define to 1 if using x86 assembler optimizations. */
+#define HAVE_ASM_X86 1
+
+/* Define to 1 if crc32 integrity check is enabled. */
+#define HAVE_CHECK_CRC32 1
+
+/* Define to 1 if crc64 integrity check is enabled. */
+#define HAVE_CHECK_CRC64 1
+
+/* Define to 1 if sha256 integrity check is enabled. */
+#define HAVE_CHECK_SHA256 1
+
+/* Define to 1 if decoder components are enabled. */
+#define HAVE_DECODER 1
+
+/* Define to 1 if arm decoder is enabled. */
+#define HAVE_DECODER_ARM 1
+
+/* Define to 1 if armthumb decoder is enabled. */
+#define HAVE_DECODER_ARMTHUMB 1
+
+/* Define to 1 if delta decoder is enabled. */
+#define HAVE_DECODER_DELTA 1
+
+/* Define to 1 if ia64 decoder is enabled. */
+#define HAVE_DECODER_IA64 1
+
+/* Define to 1 if lzma1 decoder is enabled. */
+#define HAVE_DECODER_LZMA1 1
+
+/* Define to 1 if lzma2 decoder is enabled. */
+#define HAVE_DECODER_LZMA2 1
+
+/* Define to 1 if powerpc decoder is enabled. */
+#define HAVE_DECODER_POWERPC 1
+
+/* Define to 1 if sparc decoder is enabled. */
+#define HAVE_DECODER_SPARC 1
+
+/* Define to 1 if subblock decoder is enabled. */
+/* #undef HAVE_DECODER_SUBBLOCK */
+
+/* Define to 1 if x86 decoder is enabled. */
+#define HAVE_DECODER_X86 1
+
+/* Define to 1 if encoder components are enabled. */
+#define HAVE_ENCODER 1
+
+/* Define to 1 if arm encoder is enabled. */
+#define HAVE_ENCODER_ARM 1
+
+/* Define to 1 if armthumb encoder is enabled. */
+#define HAVE_ENCODER_ARMTHUMB 1
+
+/* Define to 1 if delta encoder is enabled. */
+#define HAVE_ENCODER_DELTA 1
+
+/* Define to 1 if ia64 encoder is enabled. */
+#define HAVE_ENCODER_IA64 1
+
+/* Define to 1 if lzma1 encoder is enabled. */
+#define HAVE_ENCODER_LZMA1 1
+
+/* Define to 1 if lzma2 encoder is enabled. */
+#define HAVE_ENCODER_LZMA2 1
+
+/* Define to 1 if powerpc encoder is enabled. */
+#define HAVE_ENCODER_POWERPC 1
+
+/* Define to 1 if sparc encoder is enabled. */
+#define HAVE_ENCODER_SPARC 1
+
+/* Define to 1 if subblock encoder is enabled. */
+/* #undef HAVE_ENCODER_SUBBLOCK */
+
+/* Define to 1 if x86 encoder is enabled. */
+#define HAVE_ENCODER_X86 1
+
+/* Define to 1 if the system supports fast unaligned memory access. */
+#define HAVE_FAST_UNALIGNED_ACCESS 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 to enable bt2 match finder. */
+#define HAVE_MF_BT2 1
+
+/* Define to 1 to enable bt3 match finder. */
+#define HAVE_MF_BT3 1
+
+/* Define to 1 to enable bt4 match finder. */
+#define HAVE_MF_BT4 1
+
+/* Define to 1 to enable hc3 match finder. */
+#define HAVE_MF_HC3 1
+
+/* Define to 1 to enable hc4 match finder. */
+#define HAVE_MF_HC4 1
+
+/* Define to 1 if optimizing for size. */
+/* #undef HAVE_SMALL */
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#define HAVE_STDBOOL_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if the system has the type `uintptr_t'. */
+#define HAVE_UINTPTR_T 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the `utimes' function. */
+#define HAVE_UTIMES 1
+
+/* Define to 1 or 0, depending whether the compiler supports simple visibility
+   declarations. */
+#define HAVE_VISIBILITY 0
+
+/* Define to 1 if the system has the type `_Bool'. */
+#define HAVE__BOOL 1
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "lasse.collin@tukaani.org"
+
+/* Define to the URL of the home page of this package. */
+#define PACKAGE_HOMEPAGE "http://tukaani.org/xz/"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "XZ Utils"
+
+/* The size of `size_t', as computed by sizeof. */
+#define SIZEOF_SIZE_T 4
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
diff --git a/extra/7z2lzma/7z2lzma.bash b/extra/7z2lzma/7z2lzma.bash
new file mode 100755
index 0000000..1777c78
--- /dev/null
+++ b/extra/7z2lzma/7z2lzma.bash
@@ -0,0 +1,115 @@
+#!/bin/bash
+#
+#############################################################################
+#
+# 7z2lzma.bash is very primitive .7z to .lzma converter. The input file must
+# have exactly one LZMA compressed stream, which has been created with the
+# default lc, lp, and pb values. The CRC32 in the .7z archive is not checked,
+# and the script may seem to succeed while it actually created a corrupt .lzma
+# file. You should always try uncompressing both the original .7z and the
+# created .lzma and compare that the output is identical.
+#
+# This script requires basic GNU tools and 7z or 7za tool from p7zip.
+#
+# Last modified: 2009-01-15 14:25+0200
+#
+#############################################################################
+#
+# Author: Lasse Collin <lasse.collin@tukaani.org>
+#
+# This file has been put into the public domain.
+# You can do whatever you want with this file.
+#
+#############################################################################
+
+# You can use 7z or 7za, both will work.
+SEVENZIP=7za
+
+if [ $# != 2 -o -z "$1" -o -z "$2" ]; then
+	echo "Usage: $0 input.7z output.lzma"
+	exit 1
+fi
+
+# Converts an integer variable to little endian binary integer.
+int2bin()
+{
+	local LEN=$1
+	local NUM=$2
+	local HEX=(0 1 2 3 4 5 6 7 8 9 A B C D E F)
+	local I
+	for ((I=0; I < "$LEN"; ++I)); do
+		printf "\\x${HEX[(NUM >> 4) & 0x0F]}${HEX[NUM & 0x0F]}"
+		NUM=$((NUM >> 8))
+	done
+}
+
+# Make sure we get possible errors from pipes.
+set -o pipefail
+
+# Get information about the input file. At least older 7z and 7za versions
+# may return with zero exit status even when an error occurred, so check
+# if the output has any lines beginning with "Error".
+INFO=$("$SEVENZIP" l -slt "$1")
+if [ $? != 0 ] || printf '%s\n' "$INFO" | grep -q ^Error; then
+	printf '%s\n' "$INFO"
+	exit 1
+fi
+
+# Check if the input file has more than one compressed block.
+if printf '%s\n' "$INFO" | grep -q '^Block = 1'; then
+	echo "Cannot convert, because the input file has more than"
+	echo "one compressed block."
+	exit 1
+fi
+
+# Get compressed, uncompressed, and dictionary size.
+CSIZE=$(printf '%s\n' "$INFO" | sed -rn 's|^Packed Size = ([0-9]+$)|\1|p')
+USIZE=$(printf '%s\n' "$INFO" | sed -rn 's|^Size = ([0-9]+$)|\1|p')
+DICT=$(printf '%s\n' "$INFO" | sed -rn 's|^Method = LZMA:([0-9]+[bkm]?)$|\1|p')
+
+if [ -z "$CSIZE" -o -z "$USIZE" -o -z "$DICT" ]; then
+	echo "Parsing output of $SEVENZIP failed. Maybe the file uses some"
+	echo "other compression method than plain LZMA."
+	exit 1
+fi
+
+# The following assumes that the default lc, lp, and pb settings were used.
+# Otherwise the output will be corrupt.
+printf '\x5D' > "$2"
+
+# Dictionary size can be either was power of two, bytes, kibibytes, or
+# mebibytes. We need to convert it to bytes.
+case $DICT in
+	*b)
+		DICT=${DICT%b}
+		;;
+	*k)
+		DICT=${DICT%k}
+		DICT=$((DICT << 10))
+		;;
+	*m)
+		DICT=${DICT%m}
+		DICT=$((DICT << 20))
+		;;
+	*)
+		DICT=$((1 << DICT))
+		;;
+esac
+int2bin 4 "$DICT" >> "$2"
+
+# Uncompressed size
+int2bin 8 "$USIZE" >> "$2"
+
+# Copy the actual compressed data. Using multiple dd commands to avoid
+# copying large amount of data with one-byte block size, which would be
+# annoyingly slow.
+BS=8192
+BIGSIZE=$((CSIZE / BS))
+CSIZE=$((CSIZE % BS))
+{
+	dd of=/dev/null bs=32 count=1 \
+		&& dd bs="$BS" count="$BIGSIZE" \
+		&& dd bs=1 count="$CSIZE"
+} < "$1" >> "$2"
+
+exit $?
diff --git a/extra/scanlzma/scanlzma.c b/extra/scanlzma/scanlzma.c
new file mode 100644
index 0000000..5c3b25b
--- /dev/null
+++ b/extra/scanlzma/scanlzma.c
@@ -0,0 +1,84 @@
+/*
+    scanlzma, scan for lzma compressed data in stdin and echo it to stdout.
+    Copyright (C) 2006 Timo Lindfors
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+*/
+
+/* Usage example:
+
+   $ wget http://www.wifi-shop.cz/Files/produkty/wa2204/wa2204av1.4.1.zip
+   $ unzip wa2204av1.4.1.zip
+   $ gcc scanlzma.c -o scanlzma -Wall
+   $ ./scanlzma 0 < WA2204-FW1.4.1/linux-1.4.bin | lzma -c -d | strings | grep -i "copyright"
+   UpdateDD version 2.5, Copyright (C) 2005 Philipp Benner.
+   Copyright (C) 2005 Philipp Benner.
+   Copyright (C) 2005 Philipp Benner.
+   mawk 1.3%s%s %s, Copyright (C) Michael D. Brennan
+   # Copyright (C) 1998, 1999, 2001  Henry Spencer.
+   ...
+
+*/
+
+
+/* LZMA compressed file format */
+/* --------------------------- */
+/* Offset Size Description */
+/*   0     1   Special LZMA properties for compressed data */
+/*   1     4   Dictionary size (little endian) */
+/*   5     8   Uncompressed size (little endian). -1 means unknown size */
+/*  13         Compressed data */
+
+#define BUFSIZE 4096
+
+int find_lzma_header(unsigned char *buf) {
+	return (buf[0] < 0xE1
+		&& buf[0] == 0x5d
+		&& buf[4] < 0x20
+		&& (memcmp (buf + 10 , "\x00\x00\x00", 3) == 0
+		    || (memcmp (buf + 5, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8) == 0)));
+}
+
+int main(int argc, char *argv[]) {
+	char buf[BUFSIZE];
+	int ret, i, numlzma, blocks=0;
+
+	if (argc != 2) {
+		printf("usage: %s numlzma < infile | lzma -c -d > outfile\n"
+		       "where numlzma is index of lzma file to extract, starting from zero.\n",
+		       argv[0]);
+		exit(1);
+	}
+	numlzma = atoi(argv[1]);
+
+	for (;;) {
+		/* Read data. */
+		ret = fread(buf, BUFSIZE, 1, stdin);
+		if (ret != 1)
+			break;
+
+		/* Scan for signature. */
+		for (i = 0; i<BUFSIZE-23; i++) {
+			if (find_lzma_header(buf+i) && numlzma-- <= 0) {
+				fwrite(buf+i, (BUFSIZE-i), 1, stdout);
+				for (;;) {
+					int ch;
+					ch = getchar();
+					if (ch == EOF)
+						exit(0);
+					putchar(ch);
+				}
+			}
+		}
+		blocks++;
+	}
+	return 1;
+}
diff --git a/lib/Makefile.am b/lib/Makefile.am
new file mode 100644
index 0000000..0dbd9c4
--- /dev/null
+++ b/lib/Makefile.am
@@ -0,0 +1,32 @@
+##
+## Copyright (C) 2004-2007 Free Software Foundation, Inc.
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+
+## Not using gnulib-tool, at least for now. It is likely that we won't
+## need anything else from Gnulib than getopt_long().
+
+noinst_LIBRARIES = libgnu.a
+
+libgnu_a_SOURCES =
+libgnu_a_DEPENDENCIES = $(LIBOBJS)
+libgnu_a_LIBADD = $(LIBOBJS)
+
+EXTRA_DIST = getopt.in.h getopt.c getopt1.c getopt_int.h
+BUILT_SOURCES = $(GETOPT_H)
+MOSTLYCLEANFILES = getopt.h getopt.h-t
+
+getopt.h: getopt.in.h
+	{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
+	  cat $(srcdir)/getopt.in.h; \
+	} > $@-t
+	mv -f $@-t $@
diff --git a/lib/getopt.c b/lib/getopt.c
new file mode 100644
index 0000000..1d14b24
--- /dev/null
+++ b/lib/getopt.c
@@ -0,0 +1,1197 @@
+/* Getopt for GNU.
+   NOTE: getopt is now part of the C library, so if you don't know what
+   "Keep this file name-space clean" means, talk to drepper@gnu.org
+   before changing it!
+   Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004,2006
+	Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2.1, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License along
+   with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _LIBC
+# include <config.h>
+#endif
+
+#include "getopt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef __VMS
+# include <unixlib.h>
+#endif
+
+/* Completely disable NLS for getopt. We won't include translations for it
+   anyway. If the system lacks getopt_long, missing translations probably
+   aren't a problem.  */
+/*
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "gettext.h"
+# define _(msgid) gettext (msgid)
+#endif
+*/
+#define _(msgid) (msgid)
+
+#if defined _LIBC && defined USE_IN_LIBIO
+# include <wchar.h>
+#endif
+
+#ifndef attribute_hidden
+# define attribute_hidden
+#endif
+
+/* Unlike standard Unix `getopt', functions like `getopt_long'
+   let the user intersperse the options with the other arguments.
+
+   As `getopt_long' works, it permutes the elements of ARGV so that,
+   when it is done, all the options precede everything else.  Thus
+   all application programs are extended to handle flexible argument order.
+
+   Using `getopt' or setting the environment variable POSIXLY_CORRECT
+   disables permutation.
+   Then the application's behavior is completely standard.
+
+   GNU application programs can use a third alternative mode in which
+   they can distinguish the relative order of options and other arguments.  */
+
+#include "getopt_int.h"
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns -1, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+/* 1003.2 says this must be 1 before any call.  */
+int optind = 1;
+
+/* Callers store zero here to inhibit the error message
+   for unrecognized options.  */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+   This must be initialized on some systems to avoid linking in the
+   system's own getopt implementation.  */
+
+int optopt = '?';
+
+/* Keep a global copy of all internal members of getopt_data.  */
+
+static struct _getopt_data getopt_data;
+
+
+#if defined HAVE_DECL_GETENV && !HAVE_DECL_GETENV
+extern char *getenv ();
+#endif
+
+#ifdef _LIBC
+/* Stored original parameters.
+   XXX This is no good solution.  We should rather copy the args so
+   that we can compare them later.  But we must not use malloc(3).  */
+extern int __libc_argc;
+extern char **__libc_argv;
+
+/* Bash 2.0 gives us an environment variable containing flags
+   indicating ARGV elements that should not be considered arguments.  */
+
+# ifdef USE_NONOPTION_FLAGS
+/* Defined in getopt_init.c  */
+extern char *__getopt_nonoption_flags;
+# endif
+
+# ifdef USE_NONOPTION_FLAGS
+#  define SWAP_FLAGS(ch1, ch2) \
+  if (d->__nonoption_flags_len > 0)					      \
+    {									      \
+      char __tmp = __getopt_nonoption_flags[ch1];			      \
+      __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2];	      \
+      __getopt_nonoption_flags[ch2] = __tmp;				      \
+    }
+# else
+#  define SWAP_FLAGS(ch1, ch2)
+# endif
+#else	/* !_LIBC */
+# define SWAP_FLAGS(ch1, ch2)
+#endif	/* _LIBC */
+
+/* Exchange two adjacent subsequences of ARGV.
+   One subsequence is elements [first_nonopt,last_nonopt)
+   which contains all the non-options that have been skipped so far.
+   The other is elements [last_nonopt,optind), which contains all
+   the options processed since those non-options were skipped.
+
+   `first_nonopt' and `last_nonopt' are relocated so that they describe
+   the new indices of the non-options in ARGV after they are moved.  */
+
+static void
+exchange (char **argv, struct _getopt_data *d)
+{
+  int bottom = d->__first_nonopt;
+  int middle = d->__last_nonopt;
+  int top = d->optind;
+  char *tem;
+
+  /* Exchange the shorter segment with the far end of the longer segment.
+     That puts the shorter segment into the right place.
+     It leaves the longer segment in the right place overall,
+     but it consists of two parts that need to be swapped next.  */
+
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+  /* First make sure the handling of the `__getopt_nonoption_flags'
+     string can work normally.  Our top argument must be in the range
+     of the string.  */
+  if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len)
+    {
+      /* We must extend the array.  The user plays games with us and
+	 presents new arguments.  */
+      char *new_str = malloc (top + 1);
+      if (new_str == NULL)
+	d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0;
+      else
+	{
+	  memset (__mempcpy (new_str, __getopt_nonoption_flags,
+			     d->__nonoption_flags_max_len),
+		  '\0', top + 1 - d->__nonoption_flags_max_len);
+	  d->__nonoption_flags_max_len = top + 1;
+	  __getopt_nonoption_flags = new_str;
+	}
+    }
+#endif
+
+  while (top > middle && middle > bottom)
+    {
+      if (top - middle > middle - bottom)
+	{
+	  /* Bottom segment is the short one.  */
+	  int len = middle - bottom;
+	  register int i;
+
+	  /* Swap it with the top part of the top segment.  */
+	  for (i = 0; i < len; i++)
+	    {
+	      tem = argv[bottom + i];
+	      argv[bottom + i] = argv[top - (middle - bottom) + i];
+	      argv[top - (middle - bottom) + i] = tem;
+	      SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
+	    }
+	  /* Exclude the moved bottom segment from further swapping.  */
+	  top -= len;
+	}
+      else
+	{
+	  /* Top segment is the short one.  */
+	  int len = top - middle;
+	  register int i;
+
+	  /* Swap it with the bottom part of the bottom segment.  */
+	  for (i = 0; i < len; i++)
+	    {
+	      tem = argv[bottom + i];
+	      argv[bottom + i] = argv[middle + i];
+	      argv[middle + i] = tem;
+	      SWAP_FLAGS (bottom + i, middle + i);
+	    }
+	  /* Exclude the moved top segment from further swapping.  */
+	  bottom += len;
+	}
+    }
+
+  /* Update records for the slots the non-options now occupy.  */
+
+  d->__first_nonopt += (d->optind - d->__last_nonopt);
+  d->__last_nonopt = d->optind;
+}
+
+/* Initialize the internal data when the first call is made.  */
+
+static const char *
+_getopt_initialize (int argc, char **argv, const char *optstring,
+		    int posixly_correct, struct _getopt_data *d)
+{
+  /* Start processing options with ARGV-element 1 (since ARGV-element 0
+     is the program name); the sequence of previously skipped
+     non-option ARGV-elements is empty.  */
+
+  d->__first_nonopt = d->__last_nonopt = d->optind;
+
+  d->__nextchar = NULL;
+
+  d->__posixly_correct = posixly_correct || !!getenv ("POSIXLY_CORRECT");
+
+  /* Determine how to handle the ordering of options and nonoptions.  */
+
+  if (optstring[0] == '-')
+    {
+      d->__ordering = RETURN_IN_ORDER;
+      ++optstring;
+    }
+  else if (optstring[0] == '+')
+    {
+      d->__ordering = REQUIRE_ORDER;
+      ++optstring;
+    }
+  else if (d->__posixly_correct)
+    d->__ordering = REQUIRE_ORDER;
+  else
+    d->__ordering = PERMUTE;
+
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+  if (!d->__posixly_correct
+      && argc == __libc_argc && argv == __libc_argv)
+    {
+      if (d->__nonoption_flags_max_len == 0)
+	{
+	  if (__getopt_nonoption_flags == NULL
+	      || __getopt_nonoption_flags[0] == '\0')
+	    d->__nonoption_flags_max_len = -1;
+	  else
+	    {
+	      const char *orig_str = __getopt_nonoption_flags;
+	      int len = d->__nonoption_flags_max_len = strlen (orig_str);
+	      if (d->__nonoption_flags_max_len < argc)
+		d->__nonoption_flags_max_len = argc;
+	      __getopt_nonoption_flags =
+		(char *) malloc (d->__nonoption_flags_max_len);
+	      if (__getopt_nonoption_flags == NULL)
+		d->__nonoption_flags_max_len = -1;
+	      else
+		memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
+			'\0', d->__nonoption_flags_max_len - len);
+	    }
+	}
+      d->__nonoption_flags_len = d->__nonoption_flags_max_len;
+    }
+  else
+    d->__nonoption_flags_len = 0;
+#endif
+
+  return optstring;
+}
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+   given in OPTSTRING.
+
+   If an element of ARGV starts with '-', and is not exactly "-" or "--",
+   then it is an option element.  The characters of this element
+   (aside from the initial '-') are option characters.  If `getopt'
+   is called repeatedly, it returns successively each of the option characters
+   from each of the option elements.
+
+   If `getopt' finds another option character, it returns that character,
+   updating `optind' and `nextchar' so that the next call to `getopt' can
+   resume the scan with the following option character or ARGV-element.
+
+   If there are no more option characters, `getopt' returns -1.
+   Then `optind' is the index in ARGV of the first ARGV-element
+   that is not an option.  (The ARGV-elements have been permuted
+   so that those that are not options now come last.)
+
+   OPTSTRING is a string containing the legitimate option characters.
+   If an option character is seen that is not listed in OPTSTRING,
+   return '?' after printing an error message.  If you set `opterr' to
+   zero, the error message is suppressed but we still return '?'.
+
+   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+   so the following text in the same ARGV-element, or the text of the following
+   ARGV-element, is returned in `optarg'.  Two colons mean an option that
+   wants an optional arg; if there is text in the current ARGV-element,
+   it is returned in `optarg', otherwise `optarg' is set to zero.
+
+   If OPTSTRING starts with `-' or `+', it requests different methods of
+   handling the non-option ARGV-elements.
+   See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+   Long-named options begin with `--' instead of `-'.
+   Their names may be abbreviated as long as the abbreviation is unique
+   or is an exact match for some defined option.  If they have an
+   argument, it follows the option name in the same ARGV-element, separated
+   from the option name by a `=', or else the in next ARGV-element.
+   When `getopt' finds a long-named option, it returns 0 if that option's
+   `flag' field is nonzero, the value of the option's `val' field
+   if the `flag' field is zero.
+
+   LONGOPTS is a vector of `struct option' terminated by an
+   element containing a name which is zero.
+
+   LONGIND returns the index in LONGOPT of the long-named option found.
+   It is only valid when a long-named option has been found by the most
+   recent call.
+
+   If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+   long-named options.
+
+   If POSIXLY_CORRECT is nonzero, behave as if the POSIXLY_CORRECT
+   environment variable were set.  */
+
+int
+_getopt_internal_r (int argc, char **argv, const char *optstring,
+		    const struct option *longopts, int *longind,
+		    int long_only, int posixly_correct, struct _getopt_data *d)
+{
+  int print_errors = d->opterr;
+  if (optstring[0] == ':')
+    print_errors = 0;
+
+  if (argc < 1)
+    return -1;
+
+  d->optarg = NULL;
+
+  if (d->optind == 0 || !d->__initialized)
+    {
+      if (d->optind == 0)
+	d->optind = 1;	/* Don't scan ARGV[0], the program name.  */
+      optstring = _getopt_initialize (argc, argv, optstring,
+				      posixly_correct, d);
+      d->__initialized = 1;
+    }
+
+  /* Test whether ARGV[optind] points to a non-option argument.
+     Either it does not have option syntax, or there is an environment flag
+     from the shell indicating it is not an option.  The later information
+     is only used when the used in the GNU libc.  */
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \
+		      || (d->optind < d->__nonoption_flags_len		      \
+			  && __getopt_nonoption_flags[d->optind] == '1'))
+#else
+# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')
+#endif
+
+  if (d->__nextchar == NULL || *d->__nextchar == '\0')
+    {
+      /* Advance to the next ARGV-element.  */
+
+      /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
+	 moved back by the user (who may also have changed the arguments).  */
+      if (d->__last_nonopt > d->optind)
+	d->__last_nonopt = d->optind;
+      if (d->__first_nonopt > d->optind)
+	d->__first_nonopt = d->optind;
+
+      if (d->__ordering == PERMUTE)
+	{
+	  /* If we have just processed some options following some non-options,
+	     exchange them so that the options come first.  */
+
+	  if (d->__first_nonopt != d->__last_nonopt
+	      && d->__last_nonopt != d->optind)
+	    exchange ((char **) argv, d);
+	  else if (d->__last_nonopt != d->optind)
+	    d->__first_nonopt = d->optind;
+
+	  /* Skip any additional non-options
+	     and extend the range of non-options previously skipped.  */
+
+	  while (d->optind < argc && NONOPTION_P)
+	    d->optind++;
+	  d->__last_nonopt = d->optind;
+	}
+
+      /* The special ARGV-element `--' means premature end of options.
+	 Skip it like a null option,
+	 then exchange with previous non-options as if it were an option,
+	 then skip everything else like a non-option.  */
+
+      if (d->optind != argc && !strcmp (argv[d->optind], "--"))
+	{
+	  d->optind++;
+
+	  if (d->__first_nonopt != d->__last_nonopt
+	      && d->__last_nonopt != d->optind)
+	    exchange ((char **) argv, d);
+	  else if (d->__first_nonopt == d->__last_nonopt)
+	    d->__first_nonopt = d->optind;
+	  d->__last_nonopt = argc;
+
+	  d->optind = argc;
+	}
+
+      /* If we have done all the ARGV-elements, stop the scan
+	 and back over any non-options that we skipped and permuted.  */
+
+      if (d->optind == argc)
+	{
+	  /* Set the next-arg-index to point at the non-options
+	     that we previously skipped, so the caller will digest them.  */
+	  if (d->__first_nonopt != d->__last_nonopt)
+	    d->optind = d->__first_nonopt;
+	  return -1;
+	}
+
+      /* If we have come to a non-option and did not permute it,
+	 either stop the scan or describe it to the caller and pass it by.  */
+
+      if (NONOPTION_P)
+	{
+	  if (d->__ordering == REQUIRE_ORDER)
+	    return -1;
+	  d->optarg = argv[d->optind++];
+	  return 1;
+	}
+
+      /* We have found another option-ARGV-element.
+	 Skip the initial punctuation.  */
+
+      d->__nextchar = (argv[d->optind] + 1
+		  + (longopts != NULL && argv[d->optind][1] == '-'));
+    }
+
+  /* Decode the current option-ARGV-element.  */
+
+  /* Check whether the ARGV-element is a long option.
+
+     If long_only and the ARGV-element has the form "-f", where f is
+     a valid short option, don't consider it an abbreviated form of
+     a long option that starts with f.  Otherwise there would be no
+     way to give the -f short option.
+
+     On the other hand, if there's a long option "fubar" and
+     the ARGV-element is "-fu", do consider that an abbreviation of
+     the long option, just like "--fu", and not "-f" with arg "u".
+
+     This distinction seems to be the most useful approach.  */
+
+  if (longopts != NULL
+      && (argv[d->optind][1] == '-'
+	  || (long_only && (argv[d->optind][2]
+			    || !strchr (optstring, argv[d->optind][1])))))
+    {
+      char *nameend;
+      const struct option *p;
+      const struct option *pfound = NULL;
+      int exact = 0;
+      int ambig = 0;
+      int indfound = -1;
+      int option_index;
+
+      for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++)
+	/* Do nothing.  */ ;
+
+      /* Test all long options for either exact match
+	 or abbreviated matches.  */
+      for (p = longopts, option_index = 0; p->name; p++, option_index++)
+	if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
+	  {
+	    if ((unsigned int) (nameend - d->__nextchar)
+		== (unsigned int) strlen (p->name))
+	      {
+		/* Exact match found.  */
+		pfound = p;
+		indfound = option_index;
+		exact = 1;
+		break;
+	      }
+	    else if (pfound == NULL)
+	      {
+		/* First nonexact match found.  */
+		pfound = p;
+		indfound = option_index;
+	      }
+	    else if (long_only
+		     || pfound->has_arg != p->has_arg
+		     || pfound->flag != p->flag
+		     || pfound->val != p->val)
+	      /* Second or later nonexact match found.  */
+	      ambig = 1;
+	  }
+
+      if (ambig && !exact)
+	{
+	  if (print_errors)
+	    {
+#if defined _LIBC && defined USE_IN_LIBIO
+	      char *buf;
+
+	      if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"),
+			      argv[0], argv[d->optind]) >= 0)
+		{
+		  _IO_flockfile (stderr);
+
+		  int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+		  ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+		  __fxprintf (NULL, "%s", buf);
+
+		  ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+		  _IO_funlockfile (stderr);
+
+		  free (buf);
+		}
+#else
+	      fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
+		       argv[0], argv[d->optind]);
+#endif
+	    }
+	  d->__nextchar += strlen (d->__nextchar);
+	  d->optind++;
+	  d->optopt = 0;
+	  return '?';
+	}
+
+      if (pfound != NULL)
+	{
+	  option_index = indfound;
+	  d->optind++;
+	  if (*nameend)
+	    {
+	      /* Don't test has_arg with >, because some C compilers don't
+		 allow it to be used on enums.  */
+	      if (pfound->has_arg)
+		d->optarg = nameend + 1;
+	      else
+		{
+		  if (print_errors)
+		    {
+#if defined _LIBC && defined USE_IN_LIBIO
+		      char *buf;
+		      int n;
+#endif
+
+		      if (argv[d->optind - 1][1] == '-')
+			{
+			  /* --option */
+#if defined _LIBC && defined USE_IN_LIBIO
+			  n = __asprintf (&buf, _("\
+%s: option `--%s' doesn't allow an argument\n"),
+					  argv[0], pfound->name);
+#else
+			  fprintf (stderr, _("\
+%s: option `--%s' doesn't allow an argument\n"),
+				   argv[0], pfound->name);
+#endif
+			}
+		      else
+			{
+			  /* +option or -option */
+#if defined _LIBC && defined USE_IN_LIBIO
+			  n = __asprintf (&buf, _("\
+%s: option `%c%s' doesn't allow an argument\n"),
+					  argv[0], argv[d->optind - 1][0],
+					  pfound->name);
+#else
+			  fprintf (stderr, _("\
+%s: option `%c%s' doesn't allow an argument\n"),
+				   argv[0], argv[d->optind - 1][0],
+				   pfound->name);
+#endif
+			}
+
+#if defined _LIBC && defined USE_IN_LIBIO
+		      if (n >= 0)
+			{
+			  _IO_flockfile (stderr);
+
+			  int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+			  ((_IO_FILE *) stderr)->_flags2
+			    |= _IO_FLAGS2_NOTCANCEL;
+
+			  __fxprintf (NULL, "%s", buf);
+
+			  ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+			  _IO_funlockfile (stderr);
+
+			  free (buf);
+			}
+#endif
+		    }
+
+		  d->__nextchar += strlen (d->__nextchar);
+
+		  d->optopt = pfound->val;
+		  return '?';
+		}
+	    }
+	  else if (pfound->has_arg == 1)
+	    {
+	      if (d->optind < argc)
+		d->optarg = argv[d->optind++];
+	      else
+		{
+		  if (print_errors)
+		    {
+#if defined _LIBC && defined USE_IN_LIBIO
+		      char *buf;
+
+		      if (__asprintf (&buf, _("\
+%s: option `%s' requires an argument\n"),
+				      argv[0], argv[d->optind - 1]) >= 0)
+			{
+			  _IO_flockfile (stderr);
+
+			  int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+			  ((_IO_FILE *) stderr)->_flags2
+			    |= _IO_FLAGS2_NOTCANCEL;
+
+			  __fxprintf (NULL, "%s", buf);
+
+			  ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+			  _IO_funlockfile (stderr);
+
+			  free (buf);
+			}
+#else
+		      fprintf (stderr,
+			       _("%s: option `%s' requires an argument\n"),
+			       argv[0], argv[d->optind - 1]);
+#endif
+		    }
+		  d->__nextchar += strlen (d->__nextchar);
+		  d->optopt = pfound->val;
+		  return optstring[0] == ':' ? ':' : '?';
+		}
+	    }
+	  d->__nextchar += strlen (d->__nextchar);
+	  if (longind != NULL)
+	    *longind = option_index;
+	  if (pfound->flag)
+	    {
+	      *(pfound->flag) = pfound->val;
+	      return 0;
+	    }
+	  return pfound->val;
+	}
+
+      /* Can't find it as a long option.  If this is not getopt_long_only,
+	 or the option starts with '--' or is not a valid short
+	 option, then it's an error.
+	 Otherwise interpret it as a short option.  */
+      if (!long_only || argv[d->optind][1] == '-'
+	  || strchr (optstring, *d->__nextchar) == NULL)
+	{
+	  if (print_errors)
+	    {
+#if defined _LIBC && defined USE_IN_LIBIO
+	      char *buf;
+	      int n;
+#endif
+
+	      if (argv[d->optind][1] == '-')
+		{
+		  /* --option */
+#if defined _LIBC && defined USE_IN_LIBIO
+		  n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"),
+				  argv[0], d->__nextchar);
+#else
+		  fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
+			   argv[0], d->__nextchar);
+#endif
+		}
+	      else
+		{
+		  /* +option or -option */
+#if defined _LIBC && defined USE_IN_LIBIO
+		  n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"),
+				  argv[0], argv[d->optind][0], d->__nextchar);
+#else
+		  fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
+			   argv[0], argv[d->optind][0], d->__nextchar);
+#endif
+		}
+
+#if defined _LIBC && defined USE_IN_LIBIO
+	      if (n >= 0)
+		{
+		  _IO_flockfile (stderr);
+
+		  int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+		  ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+		  __fxprintf (NULL, "%s", buf);
+
+		  ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+		  _IO_funlockfile (stderr);
+
+		  free (buf);
+		}
+#endif
+	    }
+	  d->__nextchar = (char *) "";
+	  d->optind++;
+	  d->optopt = 0;
+	  return '?';
+	}
+    }
+
+  /* Look at and handle the next short option-character.  */
+
+  {
+    char c = *d->__nextchar++;
+    char *temp = strchr (optstring, c);
+
+    /* Increment `optind' when we start to process its last character.  */
+    if (*d->__nextchar == '\0')
+      ++d->optind;
+
+    if (temp == NULL || c == ':')
+      {
+	if (print_errors)
+	  {
+#if defined _LIBC && defined USE_IN_LIBIO
+	      char *buf;
+	      int n;
+#endif
+
+	    if (d->__posixly_correct)
+	      {
+		/* 1003.2 specifies the format of this message.  */
+#if defined _LIBC && defined USE_IN_LIBIO
+		n = __asprintf (&buf, _("%s: illegal option -- %c\n"),
+				argv[0], c);
+#else
+		fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c);
+#endif
+	      }
+	    else
+	      {
+#if defined _LIBC && defined USE_IN_LIBIO
+		n = __asprintf (&buf, _("%s: invalid option -- %c\n"),
+				argv[0], c);
+#else
+		fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c);
+#endif
+	      }
+
+#if defined _LIBC && defined USE_IN_LIBIO
+	    if (n >= 0)
+	      {
+		_IO_flockfile (stderr);
+
+		int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+		((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+		__fxprintf (NULL, "%s", buf);
+
+		((_IO_FILE *) stderr)->_flags2 = old_flags2;
+		_IO_funlockfile (stderr);
+
+		free (buf);
+	      }
+#endif
+	  }
+	d->optopt = c;
+	return '?';
+      }
+    /* Convenience. Treat POSIX -W foo same as long option --foo */
+    if (temp[0] == 'W' && temp[1] == ';')
+      {
+	char *nameend;
+	const struct option *p;
+	const struct option *pfound = NULL;
+	int exact = 0;
+	int ambig = 0;
+	int indfound = 0;
+	int option_index;
+
+	/* This is an option that requires an argument.  */
+	if (*d->__nextchar != '\0')
+	  {
+	    d->optarg = d->__nextchar;
+	    /* If we end this ARGV-element by taking the rest as an arg,
+	       we must advance to the next element now.  */
+	    d->optind++;
+	  }
+	else if (d->optind == argc)
+	  {
+	    if (print_errors)
+	      {
+		/* 1003.2 specifies the format of this message.  */
+#if defined _LIBC && defined USE_IN_LIBIO
+		char *buf;
+
+		if (__asprintf (&buf,
+				_("%s: option requires an argument -- %c\n"),
+				argv[0], c) >= 0)
+		  {
+		    _IO_flockfile (stderr);
+
+		    int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+		    ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+		    __fxprintf (NULL, "%s", buf);
+
+		    ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+		    _IO_funlockfile (stderr);
+
+		    free (buf);
+		  }
+#else
+		fprintf (stderr, _("%s: option requires an argument -- %c\n"),
+			 argv[0], c);
+#endif
+	      }
+	    d->optopt = c;
+	    if (optstring[0] == ':')
+	      c = ':';
+	    else
+	      c = '?';
+	    return c;
+	  }
+	else
+	  /* We already incremented `d->optind' once;
+	     increment it again when taking next ARGV-elt as argument.  */
+	  d->optarg = argv[d->optind++];
+
+	/* optarg is now the argument, see if it's in the
+	   table of longopts.  */
+
+	for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '=';
+	     nameend++)
+	  /* Do nothing.  */ ;
+
+	/* Test all long options for either exact match
+	   or abbreviated matches.  */
+	for (p = longopts, option_index = 0; p->name; p++, option_index++)
+	  if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar))
+	    {
+	      if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name))
+		{
+		  /* Exact match found.  */
+		  pfound = p;
+		  indfound = option_index;
+		  exact = 1;
+		  break;
+		}
+	      else if (pfound == NULL)
+		{
+		  /* First nonexact match found.  */
+		  pfound = p;
+		  indfound = option_index;
+		}
+	      else
+		/* Second or later nonexact match found.  */
+		ambig = 1;
+	    }
+	if (ambig && !exact)
+	  {
+	    if (print_errors)
+	      {
+#if defined _LIBC && defined USE_IN_LIBIO
+		char *buf;
+
+		if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"),
+				argv[0], argv[d->optind]) >= 0)
+		  {
+		    _IO_flockfile (stderr);
+
+		    int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+		    ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+		    __fxprintf (NULL, "%s", buf);
+
+		    ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+		    _IO_funlockfile (stderr);
+
+		    free (buf);
+		  }
+#else
+		fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
+			 argv[0], argv[d->optind]);
+#endif
+	      }
+	    d->__nextchar += strlen (d->__nextchar);
+	    d->optind++;
+	    return '?';
+	  }
+	if (pfound != NULL)
+	  {
+	    option_index = indfound;
+	    if (*nameend)
+	      {
+		/* Don't test has_arg with >, because some C compilers don't
+		   allow it to be used on enums.  */
+		if (pfound->has_arg)
+		  d->optarg = nameend + 1;
+		else
+		  {
+		    if (print_errors)
+		      {
+#if defined _LIBC && defined USE_IN_LIBIO
+			char *buf;
+
+			if (__asprintf (&buf, _("\
+%s: option `-W %s' doesn't allow an argument\n"),
+					argv[0], pfound->name) >= 0)
+			  {
+			    _IO_flockfile (stderr);
+
+			    int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+			    ((_IO_FILE *) stderr)->_flags2
+			      |= _IO_FLAGS2_NOTCANCEL;
+
+			    __fxprintf (NULL, "%s", buf);
+
+			    ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+			    _IO_funlockfile (stderr);
+
+			    free (buf);
+			  }
+#else
+			fprintf (stderr, _("\
+%s: option `-W %s' doesn't allow an argument\n"),
+				 argv[0], pfound->name);
+#endif
+		      }
+
+		    d->__nextchar += strlen (d->__nextchar);
+		    return '?';
+		  }
+	      }
+	    else if (pfound->has_arg == 1)
+	      {
+		if (d->optind < argc)
+		  d->optarg = argv[d->optind++];
+		else
+		  {
+		    if (print_errors)
+		      {
+#if defined _LIBC && defined USE_IN_LIBIO
+			char *buf;
+
+			if (__asprintf (&buf, _("\
+%s: option `%s' requires an argument\n"),
+					argv[0], argv[d->optind - 1]) >= 0)
+			  {
+			    _IO_flockfile (stderr);
+
+			    int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+			    ((_IO_FILE *) stderr)->_flags2
+			      |= _IO_FLAGS2_NOTCANCEL;
+
+			    __fxprintf (NULL, "%s", buf);
+
+			    ((_IO_FILE *) stderr)->_flags2 = old_flags2;
+			    _IO_funlockfile (stderr);
+
+			    free (buf);
+			  }
+#else
+			fprintf (stderr,
+				 _("%s: option `%s' requires an argument\n"),
+				 argv[0], argv[d->optind - 1]);
+#endif
+		      }
+		    d->__nextchar += strlen (d->__nextchar);
+		    return optstring[0] == ':' ? ':' : '?';
+		  }
+	      }
+	    d->__nextchar += strlen (d->__nextchar);
+	    if (longind != NULL)
+	      *longind = option_index;
+	    if (pfound->flag)
+	      {
+		*(pfound->flag) = pfound->val;
+		return 0;
+	      }
+	    return pfound->val;
+	  }
+	  d->__nextchar = NULL;
+	  return 'W';	/* Let the application handle it.   */
+      }
+    if (temp[1] == ':')
+      {
+	if (temp[2] == ':')
+	  {
+	    /* This is an option that accepts an argument optionally.  */
+	    if (*d->__nextchar != '\0')
+	      {
+		d->optarg = d->__nextchar;
+		d->optind++;
+	      }
+	    else
+	      d->optarg = NULL;
+	    d->__nextchar = NULL;
+	  }
+	else
+	  {
+	    /* This is an option that requires an argument.  */
+	    if (*d->__nextchar != '\0')
+	      {
+		d->optarg = d->__nextchar;
+		/* If we end this ARGV-element by taking the rest as an arg,
+		   we must advance to the next element now.  */
+		d->optind++;
+	      }
+	    else if (d->optind == argc)
+	      {
+		if (print_errors)
+		  {
+		    /* 1003.2 specifies the format of this message.  */
+#if defined _LIBC && defined USE_IN_LIBIO
+		    char *buf;
+
+		    if (__asprintf (&buf, _("\
+%s: option requires an argument -- %c\n"),
+				    argv[0], c) >= 0)
+		      {
+			_IO_flockfile (stderr);
+
+			int old_flags2 = ((_IO_FILE *) stderr)->_flags2;
+			((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL;
+
+			__fxprintf (NULL, "%s", buf);
+
+			((_IO_FILE *) stderr)->_flags2 = old_flags2;
+			_IO_funlockfile (stderr);
+
+			free (buf);
+		      }
+#else
+		    fprintf (stderr,
+			     _("%s: option requires an argument -- %c\n"),
+			     argv[0], c);
+#endif
+		  }
+		d->optopt = c;
+		if (optstring[0] == ':')
+		  c = ':';
+		else
+		  c = '?';
+	      }
+	    else
+	      /* We already incremented `optind' once;
+		 increment it again when taking next ARGV-elt as argument.  */
+	      d->optarg = argv[d->optind++];
+	    d->__nextchar = NULL;
+	  }
+      }
+    return c;
+  }
+}
+
+int
+_getopt_internal (int argc, char **argv, const char *optstring,
+		  const struct option *longopts, int *longind,
+		  int long_only, int posixly_correct)
+{
+  int result;
+
+  getopt_data.optind = optind;
+  getopt_data.opterr = opterr;
+
+  result = _getopt_internal_r (argc, argv, optstring, longopts, longind,
+			       long_only, posixly_correct, &getopt_data);
+
+  optind = getopt_data.optind;
+  optarg = getopt_data.optarg;
+  optopt = getopt_data.optopt;
+
+  return result;
+}
+
+/* glibc gets a LSB-compliant getopt.
+   Standalone applications get a POSIX-compliant getopt.  */
+#if _LIBC
+enum { POSIXLY_CORRECT = 0 };
+#else
+enum { POSIXLY_CORRECT = 1 };
+#endif
+
+int
+getopt (int argc, char *const *argv, const char *optstring)
+{
+  return _getopt_internal (argc, (char **) argv, optstring, NULL, NULL, 0,
+			   POSIXLY_CORRECT);
+}
+
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+   the above definition of `getopt'.  */
+
+int
+main (int argc, char **argv)
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+
+      c = getopt (argc, argv, "abc:d:0123456789");
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+	  if (digit_optind != 0 && digit_optind != this_option_optind)
+	    printf ("digits occur in two different argv-elements.\n");
+	  digit_optind = this_option_optind;
+	  printf ("option %c\n", c);
+	  break;
+
+	case 'a':
+	  printf ("option a\n");
+	  break;
+
+	case 'b':
+	  printf ("option b\n");
+	  break;
+
+	case 'c':
+	  printf ("option c with value `%s'\n", optarg);
+	  break;
+
+	case '?':
+	  break;
+
+	default:
+	  printf ("?? getopt returned character code 0%o ??\n", c);
+	}
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+	printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
diff --git a/lib/getopt.in.h b/lib/getopt.in.h
new file mode 100644
index 0000000..ea77e3d
--- /dev/null
+++ b/lib/getopt.in.h
@@ -0,0 +1,226 @@
+/* Declarations for getopt.
+   Copyright (C) 1989-1994,1996-1999,2001,2003,2004,2005,2006,2007
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2.1, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License along
+   with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _GETOPT_H
+
+#ifndef __need_getopt
+# define _GETOPT_H 1
+#endif
+
+/* Standalone applications should #define __GETOPT_PREFIX to an
+   identifier that prefixes the external functions and variables
+   defined in this header.  When this happens, include the
+   headers that might declare getopt so that they will not cause
+   confusion if included after this file.  Then systematically rename
+   identifiers so that they do not collide with the system functions
+   and variables.  Renaming avoids problems with some compilers and
+   linkers.  */
+#if defined __GETOPT_PREFIX && !defined __need_getopt
+# include <stdlib.h>
+# include <stdio.h>
+# include <unistd.h>
+# undef __need_getopt
+# undef getopt
+# undef getopt_long
+# undef getopt_long_only
+# undef optarg
+# undef opterr
+# undef optind
+# undef optopt
+# define __GETOPT_CONCAT(x, y) x ## y
+# define __GETOPT_XCONCAT(x, y) __GETOPT_CONCAT (x, y)
+# define __GETOPT_ID(y) __GETOPT_XCONCAT (__GETOPT_PREFIX, y)
+# define getopt __GETOPT_ID (getopt)
+# define getopt_long __GETOPT_ID (getopt_long)
+# define getopt_long_only __GETOPT_ID (getopt_long_only)
+# define optarg __GETOPT_ID (optarg)
+# define opterr __GETOPT_ID (opterr)
+# define optind __GETOPT_ID (optind)
+# define optopt __GETOPT_ID (optopt)
+#endif
+
+/* Standalone applications get correct prototypes for getopt_long and
+   getopt_long_only; they declare "char **argv".  libc uses prototypes
+   with "char *const *argv" that are incorrect because getopt_long and
+   getopt_long_only can permute argv; this is required for backward
+   compatibility (e.g., for LSB 2.0.1).
+
+   This used to be `#if defined __GETOPT_PREFIX && !defined __need_getopt',
+   but it caused redefinition warnings if both unistd.h and getopt.h were
+   included, since unistd.h includes getopt.h having previously defined
+   __need_getopt.
+
+   The only place where __getopt_argv_const is used is in definitions
+   of getopt_long and getopt_long_only below, but these are visible
+   only if __need_getopt is not defined, so it is quite safe to rewrite
+   the conditional as follows:
+*/
+#if !defined __need_getopt
+# if defined __GETOPT_PREFIX
+#  define __getopt_argv_const /* empty */
+# else
+#  define __getopt_argv_const const
+# endif
+#endif
+
+/* If __GNU_LIBRARY__ is not already defined, either we are being used
+   standalone, or this is the first header included in the source file.
+   If we are being used with glibc, we need to include <features.h>, but
+   that does not exist if we are standalone.  So: if __GNU_LIBRARY__ is
+   not defined, include <ctype.h>, which will pull in <features.h> for us
+   if it's from glibc.  (Why ctype.h?  It's guaranteed to exist and it
+   doesn't flood the namespace with stuff the way some other headers do.)  */
+#if !defined __GNU_LIBRARY__
+# include <ctype.h>
+#endif
+
+#ifndef __THROW
+# ifndef __GNUC_PREREQ
+#  define __GNUC_PREREQ(maj, min) (0)
+# endif
+# if defined __cplusplus && __GNUC_PREREQ (2,8)
+#  define __THROW	throw ()
+# else
+#  define __THROW
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+   When `getopt' finds an option that takes an argument,
+   the argument value is returned here.
+   Also, when `ordering' is RETURN_IN_ORDER,
+   each non-option ARGV-element is returned here.  */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+   This is used for communication to and from the caller
+   and for communication between successive calls to `getopt'.
+
+   On entry to `getopt', zero means this is the first call; initialize.
+
+   When `getopt' returns -1, this is the index of the first of the
+   non-option elements that the caller should itself scan.
+
+   Otherwise, `optind' communicates from one call to the next
+   how much of ARGV has been scanned so far.  */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+   for unrecognized options.  */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized.  */
+
+extern int optopt;
+
+#ifndef __need_getopt
+/* Describe the long-named options requested by the application.
+   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+   of `struct option' terminated by an element containing a name which is
+   zero.
+
+   The field `has_arg' is:
+   no_argument		(or 0) if the option does not take an argument,
+   required_argument	(or 1) if the option requires an argument,
+   optional_argument	(or 2) if the option takes an optional argument.
+
+   If the field `flag' is not NULL, it points to a variable that is set
+   to the value given in the field `val' when the option is found, but
+   left unchanged if the option is not found.
+
+   To have a long-named option do something other than set an `int' to
+   a compiled-in constant, such as set a value from `optarg', set the
+   option's `flag' field to zero and its `val' field to a nonzero
+   value (the equivalent single-letter option character, if there is
+   one).  For long options that have a zero `flag' field, `getopt'
+   returns the contents of the `val' field.  */
+
+struct option
+{
+  const char *name;
+  /* has_arg can't be an enum because some compilers complain about
+     type mismatches in all the code that assumes it is an int.  */
+  int has_arg;
+  int *flag;
+  int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'.  */
+
+# define no_argument		0
+# define required_argument	1
+# define optional_argument	2
+#endif	/* need getopt */
+
+
+/* Get definitions and prototypes for functions to process the
+   arguments in ARGV (ARGC of them, minus the program name) for
+   options given in OPTS.
+
+   Return the option character from OPTS just read.  Return -1 when
+   there are no more options.  For unrecognized options, or options
+   missing arguments, `optopt' is set to the option letter, and '?' is
+   returned.
+
+   The OPTS string is a list of characters which are recognized option
+   letters, optionally followed by colons, specifying that that letter
+   takes an argument, to be placed in `optarg'.
+
+   If a letter in OPTS is followed by two colons, its argument is
+   optional.  This behavior is specific to the GNU `getopt'.
+
+   The argument `--' causes premature termination of argument
+   scanning, explicitly telling `getopt' that there are no more
+   options.
+
+   If OPTS begins with `-', then non-option arguments are treated as
+   arguments to the option '\1'.  This behavior is specific to the GNU
+   `getopt'.  If OPTS begins with `+', or POSIXLY_CORRECT is set in
+   the environment, then do not permute arguments.  */
+
+extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
+       __THROW;
+
+#ifndef __need_getopt
+extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv,
+			const char *__shortopts,
+		        const struct option *__longopts, int *__longind)
+       __THROW;
+extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv,
+			     const char *__shortopts,
+		             const struct option *__longopts, int *__longind)
+       __THROW;
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Make sure we later can get all the definitions and declarations.  */
+#undef __need_getopt
+
+#endif /* getopt.h */
diff --git a/lib/getopt1.c b/lib/getopt1.c
new file mode 100644
index 0000000..da5d533
--- /dev/null
+++ b/lib/getopt1.c
@@ -0,0 +1,171 @@
+/* getopt_long and getopt_long_only entry points for GNU getopt.
+   Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98,2004,2006
+     Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as published by
+   the Free Software Foundation; either version 2.1, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License along
+   with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifdef _LIBC
+# include <getopt.h>
+#else
+# include <config.h>
+# include "getopt.h"
+#endif
+#include "getopt_int.h"
+
+#include <stdio.h>
+
+/* This needs to come after some library #include
+   to get __GNU_LIBRARY__ defined.  */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#endif
+
+#ifndef	NULL
+#define NULL 0
+#endif
+
+int
+getopt_long (int argc, char *__getopt_argv_const *argv, const char *options,
+	     const struct option *long_options, int *opt_index)
+{
+  return _getopt_internal (argc, (char **) argv, options, long_options,
+			   opt_index, 0, 0);
+}
+
+int
+_getopt_long_r (int argc, char **argv, const char *options,
+		const struct option *long_options, int *opt_index,
+		struct _getopt_data *d)
+{
+  return _getopt_internal_r (argc, argv, options, long_options, opt_index,
+			     0, 0, d);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+   If an option that starts with '-' (not '--') doesn't match a long option,
+   but does match a short option, it is parsed as a short option
+   instead.  */
+
+int
+getopt_long_only (int argc, char *__getopt_argv_const *argv,
+		  const char *options,
+		  const struct option *long_options, int *opt_index)
+{
+  return _getopt_internal (argc, (char **) argv, options, long_options,
+			   opt_index, 1, 0);
+}
+
+int
+_getopt_long_only_r (int argc, char **argv, const char *options,
+		     const struct option *long_options, int *opt_index,
+		     struct _getopt_data *d)
+{
+  return _getopt_internal_r (argc, argv, options, long_options, opt_index,
+			     1, 0, d);
+}
+
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main (int argc, char **argv)
+{
+  int c;
+  int digit_optind = 0;
+
+  while (1)
+    {
+      int this_option_optind = optind ? optind : 1;
+      int option_index = 0;
+      static struct option long_options[] =
+      {
+	{"add", 1, 0, 0},
+	{"append", 0, 0, 0},
+	{"delete", 1, 0, 0},
+	{"verbose", 0, 0, 0},
+	{"create", 0, 0, 0},
+	{"file", 1, 0, 0},
+	{0, 0, 0, 0}
+      };
+
+      c = getopt_long (argc, argv, "abc:d:0123456789",
+		       long_options, &option_index);
+      if (c == -1)
+	break;
+
+      switch (c)
+	{
+	case 0:
+	  printf ("option %s", long_options[option_index].name);
+	  if (optarg)
+	    printf (" with arg %s", optarg);
+	  printf ("\n");
+	  break;
+
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+	case '8':
+	case '9':
+	  if (digit_optind != 0 && digit_optind != this_option_optind)
+	    printf ("digits occur in two different argv-elements.\n");
+	  digit_optind = this_option_optind;
+	  printf ("option %c\n", c);
+	  break;
+
+	case 'a':
+	  printf ("option a\n");
+	  break;
+
+	case 'b':
+	  printf ("option b\n");
+	  break;
+
+	case 'c':
+	  printf ("option c with value `%s'\n", optarg);
+	  break;
+
+	case 'd':
+	  printf ("option d with value `%s'\n", optarg);
+	  break;
+
+	case '?':
+	  break;
+
+	default:
+	  printf ("?? getopt returned character code 0%o ??\n", c);
+	}
+    }
+
+  if (optind < argc)
+    {
+      printf ("non-option ARGV-elements: ");
+      while (optind < argc)
+	printf ("%s ", argv[optind++]);
+      printf ("\n");
+    }
+
+  exit (0);
+}
+
+#endif /* TEST */
diff --git a/lib/getopt_int.h b/lib/getopt_int.h
new file mode 100644
index 0000000..401579f
--- /dev/null
+++ b/lib/getopt_int.h
@@ -0,0 +1,131 @@
+/* Internal declarations for getopt.
+   Copyright (C) 1989-1994,1996-1999,2001,2003,2004
+   Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef _GETOPT_INT_H
+#define _GETOPT_INT_H	1
+
+extern int _getopt_internal (int ___argc, char **___argv,
+			     const char *__shortopts,
+		             const struct option *__longopts, int *__longind,
+			     int __long_only, int __posixly_correct);
+
+
+/* Reentrant versions which can handle parsing multiple argument
+   vectors at the same time.  */
+
+/* Data type for reentrant functions.  */
+struct _getopt_data
+{
+  /* These have exactly the same meaning as the corresponding global
+     variables, except that they are used for the reentrant
+     versions of getopt.  */
+  int optind;
+  int opterr;
+  int optopt;
+  char *optarg;
+
+  /* Internal members.  */
+
+  /* True if the internal members have been initialized.  */
+  int __initialized;
+
+  /* The next char to be scanned in the option-element
+     in which the last option character we returned was found.
+     This allows us to pick up the scan where we left off.
+
+     If this is zero, or a null string, it means resume the scan
+     by advancing to the next ARGV-element.  */
+  char *__nextchar;
+
+  /* Describe how to deal with options that follow non-option ARGV-elements.
+
+     If the caller did not specify anything,
+     the default is REQUIRE_ORDER if the environment variable
+     POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+     REQUIRE_ORDER means don't recognize them as options;
+     stop option processing when the first non-option is seen.
+     This is what Unix does.
+     This mode of operation is selected by either setting the environment
+     variable POSIXLY_CORRECT, or using `+' as the first character
+     of the list of option characters, or by calling getopt.
+
+     PERMUTE is the default.  We permute the contents of ARGV as we
+     scan, so that eventually all the non-options are at the end.
+     This allows options to be given in any order, even with programs
+     that were not written to expect this.
+
+     RETURN_IN_ORDER is an option available to programs that were
+     written to expect options and other ARGV-elements in any order
+     and that care about the ordering of the two.  We describe each
+     non-option ARGV-element as if it were the argument of an option
+     with character code 1.  Using `-' as the first character of the
+     list of option characters selects this mode of operation.
+
+     The special argument `--' forces an end of option-scanning regardless
+     of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
+     `--' can cause `getopt' to return -1 with `optind' != ARGC.  */
+
+  enum
+    {
+      REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+    } __ordering;
+
+  /* If the POSIXLY_CORRECT environment variable is set
+     or getopt was called.  */
+  int __posixly_correct;
+
+
+  /* Handle permutation of arguments.  */
+
+  /* Describe the part of ARGV that contains non-options that have
+     been skipped.  `first_nonopt' is the index in ARGV of the first
+     of them; `last_nonopt' is the index after the last of them.  */
+
+  int __first_nonopt;
+  int __last_nonopt;
+
+#if defined _LIBC && defined USE_NONOPTION_FLAGS
+  int __nonoption_flags_max_len;
+  int __nonoption_flags_len;
+# endif
+};
+
+/* The initializer is necessary to set OPTIND and OPTERR to their
+   default values and to clear the initialization flag.  */
+#define _GETOPT_DATA_INITIALIZER	{ 1, 1 }
+
+extern int _getopt_internal_r (int ___argc, char **___argv,
+			       const char *__shortopts,
+			       const struct option *__longopts, int *__longind,
+			       int __long_only, int __posixly_correct,
+			       struct _getopt_data *__data);
+
+extern int _getopt_long_r (int ___argc, char **___argv,
+			   const char *__shortopts,
+			   const struct option *__longopts, int *__longind,
+			   struct _getopt_data *__data);
+
+extern int _getopt_long_only_r (int ___argc, char **___argv,
+				const char *__shortopts,
+				const struct option *__longopts,
+				int *__longind,
+				struct _getopt_data *__data);
+
+#endif /* getopt_int.h */
diff --git a/m4/.gitignore b/m4/.gitignore
new file mode 100644
index 0000000..6e6c301
--- /dev/null
+++ b/m4/.gitignore
@@ -0,0 +1,35 @@
+codeset.m4
+gettext.m4
+glibc2.m4
+glibc21.m4
+iconv.m4
+intdiv0.m4
+intl.m4
+intldir.m4
+intmax.m4
+inttypes-pri.m4
+inttypes_h.m4
+lcmessage.m4
+lib-ld.m4
+lib-link.m4
+lib-prefix.m4
+libtool.m4
+lock.m4
+longdouble.m4
+longlong.m4
+ltoptions.m4
+ltsugar.m4
+ltversion.m4
+lt~obsolete.m4
+nls.m4
+po.m4
+printf-posix.m4
+progtest.m4
+size_max.m4
+stdint_h.m4
+uintmax_t.m4
+ulonglong.m4
+visibility.m4
+wchar_t.m4
+wint_t.m4
+xsize.m4
diff --git a/m4/acx_pthread.m4 b/m4/acx_pthread.m4
new file mode 100644
index 0000000..d2b1169
--- /dev/null
+++ b/m4/acx_pthread.m4
@@ -0,0 +1,279 @@
+##### http://autoconf-archive.cryp.to/acx_pthread.html
+#
+# SYNOPSIS
+#
+#   ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+#
+# DESCRIPTION
+#
+#   This macro figures out how to build C programs using POSIX threads.
+#   It sets the PTHREAD_LIBS output variable to the threads library and
+#   linker flags, and the PTHREAD_CFLAGS output variable to any special
+#   C compiler flags that are needed. (The user can also force certain
+#   compiler flags/libs to be tested by setting these environment
+#   variables.)
+#
+#   Also sets PTHREAD_CC to any special C compiler that is needed for
+#   multi-threaded programs (defaults to the value of CC otherwise).
+#   (This is necessary on AIX to use the special cc_r compiler alias.)
+#
+#   NOTE: You are assumed to not only compile your program with these
+#   flags, but also link it with them as well. e.g. you should link
+#   with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS
+#   $LIBS
+#
+#   If you are only building threads programs, you may wish to use
+#   these variables in your default LIBS, CFLAGS, and CC:
+#
+#          LIBS="$PTHREAD_LIBS $LIBS"
+#          CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+#          CC="$PTHREAD_CC"
+#
+#   In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute
+#   constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to
+#   that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
+#
+#   ACTION-IF-FOUND is a list of shell commands to run if a threads
+#   library is found, and ACTION-IF-NOT-FOUND is a list of commands to
+#   run it if it is not found. If ACTION-IF-FOUND is not specified, the
+#   default action will define HAVE_PTHREAD.
+#
+#   Please let the authors know if this macro fails on any platform, or
+#   if you have any other suggestions or comments. This macro was based
+#   on work by SGJ on autoconf scripts for FFTW (http://www.fftw.org/)
+#   (with help from M. Frigo), as well as ac_pthread and hb_pthread
+#   macros posted by Alejandro Forero Cuervo to the autoconf macro
+#   repository. We are also grateful for the helpful feedback of
+#   numerous users.
+#
+# LAST MODIFICATION
+#
+#   2007-07-29
+#
+# COPYLEFT
+#
+#   Copyright (c) 2007 Steven G. Johnson <stevenj@alum.mit.edu>
+#
+#   This program is free software: you can redistribute it and/or
+#   modify it under the terms of the GNU General Public License as
+#   published by the Free Software Foundation, either version 3 of the
+#   License, or (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+#   General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program. If not, see
+#   <http://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright
+#   owner gives unlimited permission to copy, distribute and modify the
+#   configure scripts that are the output of Autoconf when processing
+#   the Macro. You need not follow the terms of the GNU General Public
+#   License when using or distributing such scripts, even though
+#   portions of the text of the Macro appear in them. The GNU General
+#   Public License (GPL) does govern all other use of the material that
+#   constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the
+#   Autoconf Macro released by the Autoconf Macro Archive. When you
+#   make and distribute a modified version of the Autoconf Macro, you
+#   may extend this special exception to the GPL to apply to your
+#   modified version as well.
+
+AC_DEFUN([ACX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_LANG_SAVE
+AC_LANG_C
+acx_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        save_LIBS="$LIBS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
+        AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
+        AC_MSG_RESULT($acx_pthread_ok)
+        if test x"$acx_pthread_ok" = xno; then
+                PTHREAD_LIBS=""
+                PTHREAD_CFLAGS=""
+        fi
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try.  Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all, and "pthread-config"
+# which is a program returning the flags for the Pth emulation library.
+
+acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+
+# The ordering *is* (sometimes) important.  Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+#       other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+#      doesn't hurt to check since this sometimes defines pthreads too;
+#      also defines -D_REENTRANT)
+#      ... -mt is also the pthreads flag for HP/aCC
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+# pthread-config: use pthread-config program (for GNU Pth library)
+
+case "${host_cpu}-${host_os}" in
+        *solaris*)
+
+        # On Solaris (at least, for some versions), libc contains stubbed
+        # (non-functional) versions of the pthreads routines, so link-based
+        # tests will erroneously succeed.  (We need to link with -pthreads/-mt/
+        # -lpthread.)  (The stubs are missing pthread_cleanup_push, or rather
+        # a function called by this macro, so we could check for that, but
+        # who knows whether they'll stub that too in a future libc.)  So,
+        # we'll just look for -pthreads and -lpthread first:
+
+        acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags"
+        ;;
+esac
+
+if test x"$acx_pthread_ok" = xno; then
+for flag in $acx_pthread_flags; do
+
+        case $flag in
+                none)
+                AC_MSG_CHECKING([whether pthreads work without any flags])
+                ;;
+
+                -*)
+                AC_MSG_CHECKING([whether pthreads work with $flag])
+                PTHREAD_CFLAGS="$flag"
+                ;;
+
+		pthread-config)
+		AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no)
+		if test x"$acx_pthread_config" = xno; then continue; fi
+		PTHREAD_CFLAGS="`pthread-config --cflags`"
+		PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+		;;
+
+                *)
+                AC_MSG_CHECKING([for the pthreads library -l$flag])
+                PTHREAD_LIBS="-l$flag"
+                ;;
+        esac
+
+        save_LIBS="$LIBS"
+        save_CFLAGS="$CFLAGS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+        # Check for various functions.  We must include pthread.h,
+        # since some functions may be macros.  (On the Sequent, we
+        # need a special flag -Kthread to make this header compile.)
+        # We check for pthread_join because it is in -lpthread on IRIX
+        # while pthread_create is in libc.  We check for pthread_attr_init
+        # due to DEC craziness with -lpthreads.  We check for
+        # pthread_cleanup_push because it is one of the few pthread
+        # functions on Solaris that doesn't have a non-functional libc stub.
+        # We try pthread_create on general principles.
+        AC_TRY_LINK([#include <pthread.h>],
+                    [pthread_t th; pthread_join(th, 0);
+                     pthread_attr_init(0); pthread_cleanup_push(0, 0);
+                     pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+                    [acx_pthread_ok=yes])
+
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+
+        AC_MSG_RESULT($acx_pthread_ok)
+        if test "x$acx_pthread_ok" = xyes; then
+                break;
+        fi
+
+        PTHREAD_LIBS=""
+        PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$acx_pthread_ok" = xyes; then
+        save_LIBS="$LIBS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+        # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+	AC_MSG_CHECKING([for joinable pthread attribute])
+	attr_name=unknown
+	for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+	    AC_TRY_LINK([#include <pthread.h>], [int attr=$attr; return attr;],
+                        [attr_name=$attr; break])
+	done
+        AC_MSG_RESULT($attr_name)
+        if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
+            AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
+                               [Define to necessary symbol if this constant
+                                uses a non-standard name on your system.])
+        fi
+
+        AC_MSG_CHECKING([if more special flags are required for pthreads])
+        flag=no
+        case "${host_cpu}-${host_os}" in
+            *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
+            *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+        esac
+        AC_MSG_RESULT(${flag})
+        if test "x$flag" != xno; then
+            PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+        fi
+
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+
+        # More AIX lossage: must compile with xlc_r or cc_r
+	if test x"$GCC" != xyes; then
+          AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
+        else
+          PTHREAD_CC=$CC
+	fi
+else
+        PTHREAD_CC="$CC"
+fi
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_CC)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$acx_pthread_ok" = xyes; then
+        ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+        :
+else
+        acx_pthread_ok=no
+        $2
+fi
+AC_LANG_RESTORE
+])dnl ACX_PTHREAD
diff --git a/m4/getopt.m4 b/m4/getopt.m4
new file mode 100644
index 0000000..cfbe40f
--- /dev/null
+++ b/m4/getopt.m4
@@ -0,0 +1,71 @@
+# getopt.m4 serial 14 (modified version)
+dnl Copyright (C) 2002-2006, 2008 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+# The getopt module assume you want GNU getopt, with getopt_long etc,
+# rather than vanilla POSIX getopt.  This means your code should
+# always include <getopt.h> for the getopt prototypes.
+
+AC_DEFUN([gl_GETOPT_SUBSTITUTE],
+[
+  AC_LIBOBJ([getopt])
+  AC_LIBOBJ([getopt1])
+  gl_GETOPT_SUBSTITUTE_HEADER
+])
+
+AC_DEFUN([gl_GETOPT_SUBSTITUTE_HEADER],
+[
+  GETOPT_H=getopt.h
+  AC_DEFINE([__GETOPT_PREFIX], [[rpl_]],
+    [Define to rpl_ if the getopt replacement functions and variables
+     should be used.])
+  AC_SUBST([GETOPT_H])
+])
+
+AC_DEFUN([gl_GETOPT_CHECK_HEADERS],
+[
+  if test -z "$GETOPT_H"; then
+    AC_CHECK_HEADERS([getopt.h], [], [GETOPT_H=getopt.h])
+  fi
+
+  if test -z "$GETOPT_H"; then
+    AC_CHECK_FUNCS([getopt_long], [], [GETOPT_H=getopt.h])
+  fi
+
+  dnl BSD getopt_long uses a way to reset option processing, that is different
+  dnl from GNU and Solaris (which copied the GNU behavior). We support both
+  dnl GNU and BSD style resetting of getopt_long(), so there's no need to use
+  dnl GNU getopt_long() on BSD due to different resetting style.
+  dnl
+  dnl With getopt_long(), some BSD versions have a bug in handling optional
+  dnl arguments. This bug appears only if the environment variable
+  dnl POSIXLY_CORRECT has been set, so it shouldn't be too bad in most
+  dnl cases; probably most don't have that variable set. But if we actually
+  dnl hit this bug, it is a real problem due to our heavy use of optional
+  dnl arguments.
+  dnl
+  dnl According to CVS logs, the bug was introduced in OpenBSD in 2003-09-22
+  dnl and copied to FreeBSD in 2004-02-24. It was fixed in both in 2006-09-22,
+  dnl so the affected versions shouldn't be popular anymore anyway. NetBSD
+  dnl never had this bug. TODO: What about Darwin and others?
+  if test -z "$GETOPT_H"; then
+    AC_CHECK_DECL([optreset],
+      [AC_DEFINE([HAVE_OPTRESET], 1,
+        [Define to 1 if getopt.h declares extern int optreset.])],
+      [], [#include <getopt.h>])
+  fi
+
+  dnl Solaris 10 getopt doesn't handle `+' as a leading character in an
+  dnl option string (as of 2005-05-05). We don't use that feature, so this
+  dnl is not a problem for us. Thus, the respective test was removed here.
+])
+
+AC_DEFUN([gl_GETOPT_IFELSE],
+[
+  AC_REQUIRE([gl_GETOPT_CHECK_HEADERS])
+  AS_IF([test -n "$GETOPT_H"], [$1], [$2])
+])
+
+AC_DEFUN([gl_GETOPT], [gl_GETOPT_IFELSE([gl_GETOPT_SUBSTITUTE])])
diff --git a/m4/posix-shell.m4 b/m4/posix-shell.m4
new file mode 100644
index 0000000..4c56193
--- /dev/null
+++ b/m4/posix-shell.m4
@@ -0,0 +1,63 @@
+# Find a POSIX-conforming shell.
+
+# Copyright (C) 2007-2008 Free Software Foundation, Inc.
+
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# Written by Paul Eggert.
+
+# If a POSIX-conforming shell can be found, set POSIX_SHELL and
+# PREFERABLY_POSIX_SHELL to it.  If not, set POSIX_SHELL to the
+# empty string and PREFERABLY_POSIX_SHELL to '/bin/sh'.
+
+AC_DEFUN([gl_POSIX_SHELL],
+[
+  AC_CACHE_CHECK([for a shell that conforms to POSIX], [gl_cv_posix_shell],
+    [gl_test_posix_shell_script='
+       func_return () {
+	 (exit [$]1)
+       }
+       func_success () {
+	 func_return 0
+       }
+       func_failure () {
+	 func_return 1
+       }
+       func_ret_success () {
+	 return 0
+       }
+       func_ret_failure () {
+	 return 1
+       }
+       subshell_umask_sanity () {
+	 (umask 22; (umask 0); test $(umask) -eq 22)
+       }
+       test "[$](echo foo)" = foo &&
+       func_success &&
+       ! func_failure &&
+       func_ret_success &&
+       ! func_ret_failure &&
+       (set x && func_ret_success y && test x = "[$]1") &&
+       subshell_umask_sanity
+     '
+     for gl_cv_posix_shell in \
+	 "$CONFIG_SHELL" "$SHELL" /bin/sh /bin/bash /bin/ksh /bin/sh5 no; do
+       case $gl_cv_posix_shell in
+         /*)
+	   "$gl_cv_posix_shell" -c "$gl_test_posix_shell_script" 2>/dev/null \
+	     && break;;
+       esac
+     done])
+
+  if test "$gl_cv_posix_shell" != no; then
+    POSIX_SHELL=$gl_cv_posix_shell
+    PREFERABLY_POSIX_SHELL=$POSIX_SHELL
+  else
+    POSIX_SHELL=
+    PREFERABLY_POSIX_SHELL=/bin/sh
+  fi
+  AC_SUBST([POSIX_SHELL])
+  AC_SUBST([PREFERABLY_POSIX_SHELL])
+])
diff --git a/m4/tuklib_common.m4 b/m4/tuklib_common.m4
new file mode 100644
index 0000000..d942a25
--- /dev/null
+++ b/m4/tuklib_common.m4
@@ -0,0 +1,22 @@
+#
+# SYNOPSIS
+#
+#   TUKLIB_COMMON
+#
+# DESCRIPTION
+#
+#   Common checks for tuklib.
+#
+# COPYING
+#
+#   Author: Lasse Collin
+#
+#   This file has been put into the public domain.
+#   You can do whatever you want with this file.
+#
+
+AC_DEFUN_ONCE([TUKLIB_COMMON], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_REQUIRE([AC_PROG_CC_C99])
+AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
+])dnl
diff --git a/m4/tuklib_cpucores.m4 b/m4/tuklib_cpucores.m4
new file mode 100644
index 0000000..9e295c8
--- /dev/null
+++ b/m4/tuklib_cpucores.m4
@@ -0,0 +1,105 @@
+#
+# SYNOPSIS
+#
+#   TUKLIB_CPUCORES
+#
+# DESCRIPTION
+#
+#   Check how to find out the number of available CPU cores in the system.
+#   This information is used by tuklib_cpucores.c.
+#
+#   Supported methods:
+#     - sysctl(): BSDs, OS/2
+#     - sysconf(): GNU/Linux, Solaris, Tru64, IRIX, AIX, Cygwin
+#     - pstat_getdynamic(): HP-UX
+#
+# COPYING
+#
+#   Author: Lasse Collin
+#
+#   This file has been put into the public domain.
+#   You can do whatever you want with this file.
+#
+
+AC_DEFUN_ONCE([TUKLIB_CPUCORES], [
+AC_REQUIRE([TUKLIB_COMMON])
+
+# sys/param.h might be needed by sys/sysctl.h.
+AC_CHECK_HEADERS([sys/param.h])
+
+AC_CACHE_CHECK([how to detect the number of available CPU cores],
+	[tuklib_cv_cpucores_method], [
+
+# Look for sysctl() solution first, because on OS/2, both sysconf()
+# and sysctl() pass the tests in this file, but only sysctl()
+# actually works.
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#include <sys/types.h>
+#ifdef HAVE_SYS_PARAM_H
+#	include <sys/param.h>
+#endif
+#include <sys/sysctl.h>
+int
+main(void)
+{
+	int name[2] = { CTL_HW, HW_NCPU };
+	int cpus;
+	size_t cpus_size = sizeof(cpus);
+	sysctl(name, 2, &cpus, &cpus_size, NULL, 0);
+	return 0;
+}
+]])], [tuklib_cv_cpucores_method=sysctl], [
+
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#include <unistd.h>
+int
+main(void)
+{
+	long i;
+#ifdef _SC_NPROCESSORS_ONLN
+	/* Many systems using sysconf() */
+	i = sysconf(_SC_NPROCESSORS_ONLN);
+#else
+	/* IRIX */
+	i = sysconf(_SC_NPROC_ONLN);
+#endif
+	return 0;
+}
+]])], [tuklib_cv_cpucores_method=sysconf], [
+
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#include <sys/param.h>
+#include <sys/pstat.h>
+
+int
+main(void)
+{
+	struct pst_dynamic pst;
+	pstat_getdynamic(&pst, sizeof(pst), 1, 0);
+	(void)pst.psd_proc_cnt;
+	return 0;
+}
+]])], [tuklib_cv_cpucores_method=pstat_getdynamic], [
+
+	tuklib_cv_cpucores_method=unknown
+])])])])
+
+case $tuklib_cv_cpucores_method in
+	sysctl)
+		AC_DEFINE([TUKLIB_CPUCORES_SYSCTL], [1],
+			[Define to 1 if the number of available CPU cores
+			can be detected with sysctl().])
+		;;
+	sysconf)
+		AC_DEFINE([TUKLIB_CPUCORES_SYSCONF], [1],
+			[Define to 1 if the number of available CPU cores
+			can be detected with sysconf(_SC_NPROCESSORS_ONLN)
+			or sysconf(_SC_NPROC_ONLN).])
+		;;
+	pstat_getdynamic)
+		AC_DEFINE([TUKLIB_CPUCORES_PSTAT_GETDYNAMIC], [1],
+			[Define to 1 if the number of available CPU cores
+			can be detected with pstat_getdynamic().])
+		;;
+esac
+])dnl
diff --git a/m4/tuklib_integer.m4 b/m4/tuklib_integer.m4
new file mode 100644
index 0000000..5fe66ee
--- /dev/null
+++ b/m4/tuklib_integer.m4
@@ -0,0 +1,74 @@
+#
+# SYNOPSIS
+#
+#   TUKLIB_INTEGER
+#
+# DESCRIPTION
+#
+#   Checks for tuklib_integer.h:
+#     - Endianness
+#     - Does operating system provide byte swapping macros
+#     - Does the hardware support fast unaligned access to 16-bit
+#       and 32-bit integers
+#
+# COPYING
+#
+#   Author: Lasse Collin
+#
+#   This file has been put into the public domain.
+#   You can do whatever you want with this file.
+#
+
+AC_DEFUN_ONCE([TUKLIB_INTEGER], [
+AC_REQUIRE([TUKLIB_COMMON])
+AC_REQUIRE([AC_C_BIGENDIAN])
+AC_CHECK_HEADERS([byteswap.h sys/endian.h sys/byteorder.h], [break])
+
+# Even if we have byteswap.h, we may lack the specific macros/functions.
+if test x$ac_cv_header_byteswap_h = xyes ; then
+	m4_foreach([FUNC], [bswap_16,bswap_32,bswap_64], [
+		AC_MSG_CHECKING([if FUNC is available])
+		AC_LINK_IFELSE([AC_LANG_SOURCE([
+#include <byteswap.h>
+int
+main(void)
+{
+	FUNC[](42);
+	return 0;
+}
+		])], [
+			AC_DEFINE(HAVE_[]m4_toupper(FUNC), [1],
+					[Define to 1 if] FUNC [is available.])
+			AC_MSG_RESULT([yes])
+		], [AC_MSG_RESULT([no])])
+
+	])dnl
+fi
+
+AC_MSG_CHECKING([if unaligned memory access should be used])
+AC_ARG_ENABLE([unaligned-access], AC_HELP_STRING([--enable-unaligned-access],
+		[Enable if the system supports *fast* unaligned memory access
+		with 16-bit and 32-bit integers. By default, this is enabled
+		only on x86, x86_64, and big endian PowerPC.]),
+	[], [enable_unaligned_access=auto])
+if test "x$enable_unaligned_access" = xauto ; then
+	# TODO: There may be other architectures, on which unaligned access
+	# is OK.
+	case $host_cpu in
+		i?86|x86_64|powerpc|powerpc64)
+			enable_unaligned_access=yes
+			;;
+		*)
+			enable_unaligned_access=no
+			;;
+	esac
+fi
+if test "x$enable_unaligned_access" = xyes ; then
+	AC_DEFINE([TUKLIB_FAST_UNALIGNED_ACCESS], [1], [Define to 1 if
+		the system supports fast unaligned access to 16-bit and
+		32-bit integers.])
+	AC_MSG_RESULT([yes])
+else
+	AC_MSG_RESULT([no])
+fi
+])dnl
diff --git a/m4/tuklib_physmem.m4 b/m4/tuklib_physmem.m4
new file mode 100644
index 0000000..1249925
--- /dev/null
+++ b/m4/tuklib_physmem.m4
@@ -0,0 +1,211 @@
+#
+# SYNOPSIS
+#
+#   TUKLIB_PHYSMEM
+#
+# DESCRIPTION
+#
+#   Check how to get the amount of physical memory.
+#   This information is used in tuklib_physmem.c.
+#
+#   Supported methods:
+#
+#     - Windows (including Cygwin), OS/2, DJGPP (DOS), and OpenVMS have
+#       operating-system specific functions.
+#
+#     - AIX has _system_configuration.physmem.
+#
+#     - sysconf() works on GNU/Linux and Solaris, and possibly on
+#       some BSDs.
+#
+#     - BSDs use sysctl().
+#
+#     - Tru64 uses getsysinfo().
+#
+#     - HP-UX uses pstat_getstatic().
+#
+#     - IRIX has setinvent_r(), getinvent_r(), and endinvent_r().
+#
+#     - sysinfo() works on Linux/dietlibc and probably on other Linux
+#       systems whose libc may lack sysconf().
+#
+# COPYING
+#
+#   Author: Lasse Collin
+#
+#   This file has been put into the public domain.
+#   You can do whatever you want with this file.
+#
+
+AC_DEFUN_ONCE([TUKLIB_PHYSMEM], [
+AC_REQUIRE([TUKLIB_COMMON])
+
+# sys/param.h might be needed by sys/sysctl.h.
+AC_CHECK_HEADERS([sys/param.h])
+
+AC_CACHE_CHECK([how to detect the amount of physical memory],
+	[tuklib_cv_physmem_method], [
+
+# Maybe checking $host_os would be enough but this matches what
+# tuklib_physmem.c does.
+#
+# NOTE: IRIX has a compiler that doesn't error out with #error, so use
+# a non-compilable text instead of #error to generate an error.
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(__OS2__) \
+		|| defined(__DJGPP__) || defined(__VMS)
+int main(void) { return 0; }
+#else
+compile error
+#endif
+]])], [tuklib_cv_physmem_method=special], [
+
+# Look for AIX-specific solution before sysconf(), because the test
+# for sysconf() will pass on AIX but won't actually work
+# (sysconf(_SC_PHYS_PAGES) compiles but always returns -1 on AIX).
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#include <sys/systemcfg.h>
+
+int
+main(void)
+{
+	(void)_system_configuration.physmem;
+	return 0;
+}
+]])], [tuklib_cv_physmem_method=aix], [
+
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#include <unistd.h>
+int
+main(void)
+{
+	long i;
+	i = sysconf(_SC_PAGESIZE);
+	i = sysconf(_SC_PHYS_PAGES);
+	return 0;
+}
+]])], [tuklib_cv_physmem_method=sysconf], [
+
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#include <sys/types.h>
+#ifdef HAVE_SYS_PARAM_H
+#	include <sys/param.h>
+#endif
+#include <sys/sysctl.h>
+int
+main(void)
+{
+	int name[2] = { CTL_HW, HW_PHYSMEM };
+	unsigned long mem;
+	size_t mem_ptr_size = sizeof(mem);
+	sysctl(name, 2, &mem, &mem_ptr_size, NULL, 0);
+	return 0;
+}
+]])], [tuklib_cv_physmem_method=sysctl], [
+
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#include <sys/sysinfo.h>
+#include <machine/hal_sysinfo.h>
+
+int
+main(void)
+{
+	int memkb;
+	int start = 0;
+	getsysinfo(GSI_PHYSMEM, (caddr_t)&memkb, sizeof(memkb), &start);
+	return 0;
+}
+]])], [tuklib_cv_physmem_method=getsysinfo],[
+
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#include <sys/param.h>
+#include <sys/pstat.h>
+
+int
+main(void)
+{
+	struct pst_static pst;
+	pstat_getstatic(&pst, sizeof(pst), 1, 0);
+	(void)pst.physical_memory;
+	(void)pst.page_size;
+	return 0;
+}
+]])], [tuklib_cv_physmem_method=pstat_getstatic],[
+
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#include <invent.h>
+int
+main(void)
+{
+	inv_state_t *st = NULL;
+	setinvent_r(&st);
+	getinvent_r(st);
+	endinvent_r(st);
+	return 0;
+}
+]])], [tuklib_cv_physmem_method=getinvent_r], [
+
+# This version of sysinfo() is Linux-specific. Some non-Linux systems have
+# different sysinfo() so we must check $host_os.
+case $host_os in
+	linux*)
+		AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#include <sys/sysinfo.h>
+int
+main(void)
+{
+	struct sysinfo si;
+	sysinfo(&si);
+	return 0;
+}
+		]])], [
+			tuklib_cv_physmem_method=sysinfo
+		], [
+			tuklib_cv_physmem_method=unknown
+		])
+		;;
+	*)
+		tuklib_cv_physmem_method=unknown
+		;;
+esac
+])])])])])])])])
+
+case $tuklib_cv_physmem_method in
+	aix)
+		AC_DEFINE([TUKLIB_PHYSMEM_AIX], [1],
+			[Define to 1 if the amount of physical memory
+			can be detected with _system_configuration.physmem.])
+		;;
+	sysconf)
+		AC_DEFINE([TUKLIB_PHYSMEM_SYSCONF], [1],
+			[Define to 1 if the amount of physical memory can
+			be detected with sysconf(_SC_PAGESIZE) and
+			sysconf(_SC_PHYS_PAGES).])
+		;;
+	sysctl)
+		AC_DEFINE([TUKLIB_PHYSMEM_SYSCTL], [1],
+			[Define to 1 if the amount of physical memory can
+			be detected with sysctl().])
+		;;
+	getsysinfo)
+		AC_DEFINE([TUKLIB_PHYSMEM_GETSYSINFO], [1],
+			[Define to 1 if the amount of physical memory can
+			be detected with getsysinfo().])
+		;;
+	pstat_getstatic)
+		AC_DEFINE([TUKLIB_PHYSMEM_PSTAT_GETSTATIC], [1],
+			[Define to 1 if the amount of physical memory can
+			be detected with pstat_getstatic().])
+		;;
+	getinvent_r)
+		AC_DEFINE([TUKLIB_PHYSMEM_GETINVENT_R], [1],
+			[Define to 1 if the amount of physical memory
+			can be detected with getinvent_r().])
+		;;
+	sysinfo)
+		AC_DEFINE([TUKLIB_PHYSMEM_SYSINFO], [1],
+			[Define to 1 if the amount of physical memory
+			can be detected with Linux sysinfo().])
+		;;
+esac
+])dnl
diff --git a/m4/tuklib_progname.m4 b/m4/tuklib_progname.m4
new file mode 100644
index 0000000..f3e158b
--- /dev/null
+++ b/m4/tuklib_progname.m4
@@ -0,0 +1,25 @@
+#
+# SYNOPSIS
+#
+#   TUKLIB_PROGNAME
+#
+# DESCRIPTION
+#
+#   Put argv[0] into a global variable progname. On DOS-like systems,
+#   modify it so that it looks nice (no full path or .exe suffix).
+#
+#   This .m4 file is needed allow this module to use glibc's
+#   program_invocation_name.
+#
+# COPYING
+#
+#   Author: Lasse Collin
+#
+#   This file has been put into the public domain.
+#   You can do whatever you want with this file.
+#
+
+AC_DEFUN_ONCE([TUKLIB_PROGNAME], [
+AC_REQUIRE([TUKLIB_COMMON])
+AC_CHECK_DECLS([program_invocation_name], [], [], [#include <errno.h>])
+])dnl
diff --git a/po/.gitignore b/po/.gitignore
new file mode 100644
index 0000000..d201729
--- /dev/null
+++ b/po/.gitignore
@@ -0,0 +1,31 @@
+# autopoint
+Makefile.in.in
+Makevars.template
+Rules-quot
+boldquot.sed
+en@boldquot.header
+en@quot.header
+insert-header.sin
+quot.sed
+remove-potcdate.sin
+
+# configure
+Makefile.in
+Makefile
+POTFILES
+
+# intermediate files (make)
+stamp-poT
+xz.po
+xz.1po
+xz.2po
+*.new.po
+
+# make
+remove-potcdate.sed
+xz.mo
+stamp-po
+*.gmo
+
+# cached templates (make)
+xz.pot
diff --git a/po/LINGUAS b/po/LINGUAS
new file mode 100644
index 0000000..841618a
--- /dev/null
+++ b/po/LINGUAS
@@ -0,0 +1 @@
+cs
diff --git a/po/Makevars b/po/Makevars
new file mode 100644
index 0000000..dc19bc9
--- /dev/null
+++ b/po/Makevars
@@ -0,0 +1,46 @@
+# Makefile variables for PO directory in any package using GNU gettext.
+
+# Usually the message domain is the same as the package name.
+DOMAIN = $(PACKAGE)
+
+# These two variables depend on the location of this directory.
+subdir = po
+top_builddir = ..
+
+# These options get passed to xgettext.
+XGETTEXT_OPTIONS = --keyword=_ --keyword=N_
+
+# This is the copyright holder that gets inserted into the header of the
+# $(DOMAIN).pot file.  Set this to the copyright holder of the surrounding
+# package.  (Note that the msgstr strings, extracted from the package's
+# sources, belong to the copyright holder of the package.)  Translators are
+# expected to transfer the copyright for their translations to this person
+# or entity, or to disclaim their copyright.  The empty string stands for
+# the public domain; in this case the translators are expected to disclaim
+# their copyright.
+COPYRIGHT_HOLDER =
+
+# This is the email address or URL to which the translators shall report
+# bugs in the untranslated strings:
+# - Strings which are not entire sentences, see the maintainer guidelines
+#   in the GNU gettext documentation, section 'Preparing Strings'.
+# - Strings which use unclear terms or require additional context to be
+#   understood.
+# - Strings which make invalid assumptions about notation of date, time or
+#   money.
+# - Pluralisation problems.
+# - Incorrect English spelling.
+# - Incorrect formatting.
+# It can be your email address, or a mailing list address where translators
+# can write to without being subscribed, or the URL of a web page through
+# which the translators can contact you.
+MSGID_BUGS_ADDRESS =
+
+# This is the list of locale categories, beyond LC_MESSAGES, for which the
+# message catalogs shall be used.  It is usually empty.
+EXTRA_LOCALE_CATEGORIES =
+
+# Although you may need slightly wider terminal than 80 chars, it is
+# much nicer to edit the output of --help when this is set.
+XGETTEXT_OPTIONS += --no-wrap
+MSGMERGE += --no-wrap
diff --git a/po/POTFILES.in b/po/POTFILES.in
new file mode 100644
index 0000000..ee430c5
--- /dev/null
+++ b/po/POTFILES.in
@@ -0,0 +1,10 @@
+# List of source files which contain translatable strings.
+src/xz/args.c
+src/xz/coder.c
+src/xz/file_io.c
+src/xz/hardware.c
+src/xz/main.c
+src/xz/message.c
+src/xz/options.c
+src/xz/suffix.c
+src/xz/util.c
diff --git a/po/cs.po b/po/cs.po
new file mode 100644
index 0000000..a953fd3
--- /dev/null
+++ b/po/cs.po
@@ -0,0 +1,636 @@
+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"
+"Last-Translator: Marek Černocký <marek@manet.cz>\n"
+"Language-Team: Czech <diskuze@lists.l10n.cz>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2\n"
+"X-Poedit-Language: Czech\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+#: src/xz/args.c:306
+#, 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
+#, 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'."
+msgstr ""
+"Můžete zadat pouze jeden soubor spolu s přepínači „--files“ nebo „--files0“"
+
+#: 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/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)"
+
+#: src/xz/coder.c:128
+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
+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
+msgid "The .lzma format supports only the LZMA1 filter"
+msgstr "Formát .lzma podporuje pouze filtr LZMA1"
+
+#: src/xz/coder.c:166
+msgid "LZMA1 cannot be used with the .xz format"
+msgstr "LZMA1 nelze použít s formátem .xz"
+
+#: src/xz/coder.c:186
+#, 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)"
+
+#: src/xz/coder.c:554
+#, 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"
+
+#: src/xz/file_io.c:113
+#, c-format
+msgid "%s: File seems to be moved, not removing"
+msgstr "%s: Vypadá to, že soubor byl přesunut, neodstraní se"
+
+#: src/xz/file_io.c:120 src/xz/file_io.c:527
+#, c-format
+msgid "%s: Cannot remove: %s"
+msgstr "%s: Nelze odstranit: %s"
+
+#: src/xz/file_io.c:145
+#, c-format
+msgid "%s: Cannot set the file owner: %s"
+msgstr "%s: Nelze nastavit vlastníka souboru: %s"
+
+#: src/xz/file_io.c:151
+#, c-format
+msgid "%s: Cannot set the file group: %s"
+msgstr "%s: Nelze nastavit skupinu souboru: %s"
+
+#: src/xz/file_io.c:170
+#, 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
+#, 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
+#, c-format
+msgid "%s: Is a directory, skipping"
+msgstr "%s: Jedná se o složku, vynechává se"
+
+#: src/xz/file_io.c:429
+#, 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
+#, 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
+#, 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
+#, 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
+#, 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
+#, 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
+#, 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
+#, c-format
+msgid "%s: Read error: %s"
+msgstr "%s: Chyba čtení: %s"
+
+#: src/xz/file_io.c:847
+#, c-format
+msgid "%s: Write error: %s"
+msgstr "%s: Chyba zápisu: %s"
+
+#: src/xz/main.c:76
+#, c-format
+msgid "%s: Error reading filenames: %s"
+msgstr "%s: Chyba při čtení názvů souborů: %s"
+
+#: src/xz/main.c:83
+#, 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
+#, c-format
+msgid ""
+"%s: Null character found when reading filenames; maybe you meant to use `--"
+"files0' instead of `--files'?"
+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
+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
+msgid ""
+"Cannot read data from standard input when reading filenames from standard "
+"input"
+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
+msgid "Internal error (bug)"
+msgstr "Interní chyba"
+
+#: src/xz/message.c:848
+msgid "Cannot establish signal handlers"
+msgstr "Nelze ustanovit ovladač signálu"
+
+#: src/xz/message.c:857
+msgid "No integrity check; not verifying file integrity"
+msgstr "Žádná kontrola integrity; integrita souboru se nebude ověřovat"
+
+#: src/xz/message.c:860
+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
+msgid "Memory usage limit reached"
+msgstr "Dosaženo omezení použitelné paměti"
+
+#: src/xz/message.c:870
+msgid "File format not recognized"
+msgstr "Formát souboru nebyl rozpoznán"
+
+#: src/xz/message.c:873
+msgid "Unsupported options"
+msgstr "Nepodporovaná volba"
+
+#: src/xz/message.c:876
+msgid "Compressed data is corrupt"
+msgstr "Komprimovaná data jsou poškozená"
+
+#: src/xz/message.c:879
+msgid "Unexpected end of input"
+msgstr "Neočekávaný konec vstupu"
+
+#: src/xz/message.c:898
+#, c-format
+msgid "%s: Filter chain:"
+msgstr "%s: Omezující filtr:"
+
+#: src/xz/message.c:1009
+#, c-format
+msgid "Try `%s --help' for more information."
+msgstr "Zkuste „%s --help“ pro více informací"
+
+#: src/xz/message.c:1021
+#, c-format
+msgid "%s MiB (%s bytes)\n"
+msgstr "%s MiB (%s bajtů)\n"
+
+#: src/xz/message.c:1049
+#, c-format
+msgid ""
+"Usage: %s [OPTION]... [FILE]...\n"
+"Compress or decompress FILEs in the .xz format.\n"
+"\n"
+msgstr ""
+"Použití: %s [PŘEPÍNAČ]... [SOUBOR]...\n"
+"Komprimuje nebo dekomprimuje SOUBORy ve formátu xz.\n"
+"\n"
+
+#: src/xz/message.c:1053
+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
+msgid " Operation mode:\n"
+msgstr "Operační režim:\n"
+
+#: src/xz/message.c:1060
+msgid ""
+"  -z, --compress      force compression\n"
+"  -d, --decompress    force decompression\n"
+"  -t, --test          test compressed file integrity\n"
+"  -l, --list          list information about 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"
+
+#: src/xz/message.c:1066
+msgid ""
+"\n"
+" Operation modifiers:\n"
+msgstr ""
+"\n"
+"Modifikátory operací:\n"
+
+#: src/xz/message.c:1069
+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            zachovat (nemazat) vstupní soubory\n"
+" -f, --force           vynutit přepis výstupního souboru a de/komprimovat "
+"odkazy\n"
+" -c, --stdout          zapisovat na standardní výstup a nemazat vstupní "
+"soubory"
+
+#: src/xz/message.c:1075
+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       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 "
+"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ý "
+"znak"
+
+#: src/xz/message.c:1083
+msgid ""
+"\n"
+" Basic file format and compression options:\n"
+msgstr ""
+"\n"
+"Základní přepínače pro formát souboru a komprimaci:\n"
+
+#: src/xz/message.c:1085
+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)"
+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)"
+
+#: src/xz/message.c:1092
+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"
+
+#: src/xz/message.c:1096
+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"
+
+#: src/xz/message.c:1101
+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"
+
+#: src/xz/message.c:1106
+msgid ""
+"\n"
+" Custom filter chain for compression (alternative for using presets):"
+msgstr ""
+"\n"
+"Vlastní omezující filtr pro komprimaci (alternativa k použití "
+"přednastavených):"
+
+#: src/xz/message.c:1111
+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"
+"                        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[=VOLBY]       LZMA1 nebo LZMA2; VOLBY je čárkou oddělovaný seznam "
+"žá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 "
+"MiB)\n"
+"                         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"
+"                         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"
+"                         depth=POČ  maximální hloubka prohledávání;\n"
+"                                    0=automaticky (výchozí)"
+
+#: src/xz/message.c:1126
+msgid ""
+"\n"
+"  --x86[=OPTS]        x86 BCJ filter\n"
+"  --powerpc[=OPTS]    PowerPC BCJ filter (big endian only)\n"
+"  --ia64[=OPTS]       IA64 (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[=VOLBY]         Filtr x86 BCJ\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"
+" --armthumb[=VOLBY]    Filtr ARM-Thumb BCJ (pouze little endian)\n"
+" --sparc[=VOLBY]       Filtr SPARC BCJ\n"
+"                       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
+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[=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)"
+
+#: src/xz/message.c:1155
+msgid ""
+"\n"
+" Other options:\n"
+msgstr ""
+"\n"
+" Ostatní přepínače:\n"
+
+#: src/xz/message.c:1158
+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           potlačit varování; zadáním dvakrát, potlačíte i "
+"chyby\n"
+" -v, --verbose         podrobnější zprávy; zadáním dvakrát, budou ještě\n"
+"                       podrobnější"
+
+#: src/xz/message.c:1163
+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
+msgid ""
+"      --robot         use machine-parsable messages (useful for scripts)"
+msgstr ""
+"     --robot           použít strojově analyzovatelné zprávy (užitečné pro "
+"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:1170
+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            zobrazit krátkou nápovědu (vypíše jen základní "
+"přepínače)\n"
+" -H, --long-help       zobrazit tuto úplnou nápovědu a skončit"
+
+#: src/xz/message.c:1174
+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            zobrazit tuto zkrácenou nápovědu a skončit\n"
+" -H, --long-help       zobrazit úplnou nápovědu (vypíše i pokročilé "
+"přepínače)"
+
+#: src/xz/message.c:1179
+msgid "  -V, --version       display the version number and exit"
+msgstr " -V, --version         zobrazit číslo verze a skončit"
+
+#: src/xz/message.c:1181
+msgid ""
+"\n"
+"With no FILE, or when FILE is -, read standard input.\n"
+msgstr ""
+"\n"
+"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
+#, 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
+#, c-format
+msgid "%s home page: <%s>\n"
+msgstr "Domovská stránka %s: <%s>\n"
+
+#: src/xz/options.c:86
+#, c-format
+msgid "%s: Options must be `name=value' pairs separated with commas"
+msgstr "%s: Volby musí být páry „název=hodnota“ oddělené čárkami"
+
+#: src/xz/options.c:93
+#, c-format
+msgid "%s: Invalid option name"
+msgstr "%s: Neplatný název volby"
+
+#: src/xz/options.c:113
+#, c-format
+msgid "%s: Invalid option value"
+msgstr "%s: Neplatná hodnota volby"
+
+#: src/xz/options.c:308
+#, 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:431
+#, c-format
+msgid "The selected match finder requires at least nice=%<PRIu32>"
+msgstr "Vybraný vyhledávač shod vyžaduje minimálně 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: S --format=raw je vyžadováno --sufix=.SUF, vyjma zápisu do standardního "
+"výstupu"
+
+#: src/xz/suffix.c:99
+#, c-format
+msgid "%s: Filename has an unknown suffix, skipping"
+msgstr "%s: Název souboru má neznámou příponu, vynechává se"
+
+#: src/xz/suffix.c:154
+#, c-format
+msgid "%s: File already has `%s' suffix, skipping"
+msgstr "%s: Soubor již má příponu „%s“, vynechává se"
+
+#: src/xz/suffix.c:205
+#, c-format
+msgid "%s: Invalid filename suffix"
+msgstr "%s: Neplatná přípona názvu souboru"
+
+#: src/xz/util.c:53
+#, 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
+#, c-format
+msgid "%s: Invalid multiplier suffix. Valid suffixes:"
+msgstr "%s: Neplatná přípona. Platné přípony jsou:"
+
+#: src/xz/util.c:115
+#, 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
+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“."
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..f03f5a3
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,9 @@
+##
+## Author: Lasse Collin
+##
+## This file has been put into the public domain.
+## You can do whatever you want with this file.
+##
+
+SUBDIRS = liblzma xz xzdec lzmainfo scripts
+EXTRA_DIST = common
diff --git a/src/common/common_w32res.rc b/src/common/common_w32res.rc
new file mode 100644
index 0000000..ad9e165
--- /dev/null
+++ b/src/common/common_w32res.rc
@@ -0,0 +1,53 @@
+/*
+ * Author: Lasse Collin
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ */
+
+#include <winresrc.h>
+#include "config.h"
+#define LZMA_H_INTERNAL
+#define LZMA_H_INTERNAL_RC
+#include "lzma/version.h"
+
+#ifndef MY_BUILD
+# define MY_BUILD 0
+#endif
+#define MY_VERSION LZMA_VERSION_MAJOR,LZMA_VERSION_MINOR,LZMA_VERSION_PATCH,MY_BUILD
+
+#define MY_FILENAME    MY_NAME MY_SUFFIX
+#define MY_COMPANY     "Lasse Collin and Igor Pavlov"
+#define MY_COPYRIGHT   "Public Domain by " MY_COMPANY
+#define MY_COMMENTS    "http://tukaani.org/xz/"
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+VS_VERSION_INFO VERSIONINFO
+  FILEVERSION MY_VERSION
+  PRODUCTVERSION MY_VERSION
+  FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+  FILEFLAGS 0
+  FILEOS VOS_NT_WINDOWS32
+  FILETYPE MY_TYPE
+  FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0"
+        BEGIN
+            VALUE "Comments", MY_COMMENTS
+            VALUE "CompanyName", MY_COMPANY
+            VALUE "FileDescription", MY_DESC
+            VALUE "FileVersion", LZMA_VERSION_STRING
+            VALUE "InternalName", MY_NAME
+            VALUE "LegalCopyright", MY_COPYRIGHT
+            VALUE "OriginalFilename", MY_FILENAME
+            VALUE "ProductName", PACKAGE_NAME
+            VALUE "ProductVersion", LZMA_VERSION_STRING
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
diff --git a/src/common/mythread.h b/src/common/mythread.h
new file mode 100644
index 0000000..476c2fc
--- /dev/null
+++ b/src/common/mythread.h
@@ -0,0 +1,42 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       mythread.h
+/// \brief      Wrappers for threads
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "sysdefs.h"
+
+
+#ifdef HAVE_PTHREAD
+#	include <pthread.h>
+
+#	define mythread_once(func) \
+	do { \
+		static pthread_once_t once_ = PTHREAD_ONCE_INIT; \
+		pthread_once(&once_, &func); \
+	} while (0)
+
+#	define mythread_sigmask(how, set, oset) \
+		pthread_sigmask(how, set, oset)
+
+#else
+
+#	define mythread_once(func) \
+	do { \
+		static bool once_ = false; \
+		if (!once_) { \
+			func(); \
+			once_ = true; \
+		} \
+	} while (0)
+
+#	define mythread_sigmask(how, set, oset) \
+		sigprocmask(how, set, oset)
+
+#endif
diff --git a/src/common/sysdefs.h b/src/common/sysdefs.h
new file mode 100644
index 0000000..1e138b1
--- /dev/null
+++ b/src/common/sysdefs.h
@@ -0,0 +1,169 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       sysdefs.h
+/// \brief      Common includes, definitions, system-specific things etc.
+///
+/// This file is used also by the lzma command line tool, that's why this
+/// file is separate from common.h.
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_SYSDEFS_H
+#define LZMA_SYSDEFS_H
+
+//////////////
+// Includes //
+//////////////
+
+#ifdef HAVE_CONFIG_H
+#	include <config.h>
+#endif
+
+// size_t and NULL
+#include <stddef.h>
+
+#ifdef HAVE_INTTYPES_H
+#	include <inttypes.h>
+#endif
+
+// C99 says that inttypes.h always includes stdint.h, but some systems
+// don't do that, and require including stdint.h separately.
+#ifdef HAVE_STDINT_H
+#	include <stdint.h>
+#endif
+
+// Some pre-C99 systems have SIZE_MAX in limits.h instead of stdint.h. The
+// limits are also used to figure out some macros missing from pre-C99 systems.
+#ifdef HAVE_LIMITS_H
+#	include <limits.h>
+#endif
+
+// Be more compatible with systems that have non-conforming inttypes.h.
+// We assume that int is 32-bit and that long is either 32-bit or 64-bit.
+// Full Autoconf test could be more correct, but this should work well enough.
+// Note that this duplicates some code from lzma.h, but this is better since
+// we can work without inttypes.h thanks to Autoconf tests.
+#ifndef UINT32_C
+#	if UINT_MAX != 4294967295U
+#		error UINT32_C is not defined and unsigned int is not 32-bit.
+#	endif
+#	define UINT32_C(n) n ## U
+#endif
+#ifndef UINT32_MAX
+#	define UINT32_MAX UINT32_C(4294967295)
+#endif
+#ifndef PRIu32
+#	define PRIu32 "u"
+#endif
+#ifndef PRIX32
+#	define PRIX32 "X"
+#endif
+
+#if ULONG_MAX == 4294967295UL
+#	ifndef UINT64_C
+#		define UINT64_C(n) n ## ULL
+#	endif
+#	ifndef PRIu64
+#		define PRIu64 "llu"
+#	endif
+#	ifndef PRIX64
+#		define PRIX64 "llX"
+#	endif
+#else
+#	ifndef UINT64_C
+#		define UINT64_C(n) n ## UL
+#	endif
+#	ifndef PRIu64
+#		define PRIu64 "lu"
+#	endif
+#	ifndef PRIX64
+#		define PRIX64 "lX"
+#	endif
+#endif
+#ifndef UINT64_MAX
+#	define UINT64_MAX UINT64_C(18446744073709551615)
+#endif
+
+// Interix has broken header files, which typedef size_t to unsigned long,
+// but a few lines later define SIZE_MAX to INT32_MAX.
+#ifdef __INTERIX
+#	undef SIZE_MAX
+#endif
+
+// The code currently assumes that size_t is either 32-bit or 64-bit.
+#ifndef SIZE_MAX
+#	if SIZEOF_SIZE_T == 4
+#		define SIZE_MAX UINT32_MAX
+#	elif SIZEOF_SIZE_T == 8
+#		define SIZE_MAX UINT64_MAX
+#	else
+#		error size_t is not 32-bit or 64-bit
+#	endif
+#endif
+#if SIZE_MAX != UINT32_MAX && SIZE_MAX != UINT64_MAX
+#	error size_t is not 32-bit or 64-bit
+#endif
+
+#include <stdlib.h>
+#include <assert.h>
+
+// Pre-C99 systems lack stdbool.h. All the code in LZMA Utils must be written
+// so that it works with fake bool type, for example:
+//
+//    bool foo = (flags & 0x100) != 0;
+//    bool bar = !!(flags & 0x100);
+//
+// This works with the real C99 bool but breaks with fake bool:
+//
+//    bool baz = (flags & 0x100);
+//
+#ifdef HAVE_STDBOOL_H
+#	include <stdbool.h>
+#else
+#	if ! HAVE__BOOL
+typedef unsigned char _Bool;
+#	endif
+#	define bool _Bool
+#	define false 0
+#	define true 1
+#	define __bool_true_false_are_defined 1
+#endif
+
+// string.h should be enough but let's include strings.h and memory.h too if
+// they exists, since that shouldn't do any harm, but may improve portability.
+#ifdef HAVE_STRING_H
+#	include <string.h>
+#endif
+
+#ifdef HAVE_STRINGS_H
+#	include <strings.h>
+#endif
+
+#ifdef HAVE_MEMORY_H
+#	include <memory.h>
+#endif
+
+
+////////////
+// Macros //
+////////////
+
+#undef memzero
+#define memzero(s, n) memset(s, 0, n)
+
+// 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]))
+#endif
+
+#endif
diff --git a/src/common/tuklib_common.h b/src/common/tuklib_common.h
new file mode 100644
index 0000000..31fbab5
--- /dev/null
+++ b/src/common/tuklib_common.h
@@ -0,0 +1,71 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       tuklib_common.h
+/// \brief      Common definitions for tuklib modules
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef TUKLIB_COMMON_H
+#define TUKLIB_COMMON_H
+
+// The config file may be replaced by a package-specific file.
+// It should include at least stddef.h, inttypes.h, and limits.h.
+#include "tuklib_config.h"
+
+// TUKLIB_SYMBOL_PREFIX is prefixed to all symbols exported by
+// the tuklib modules. If you use a tuklib module in a library,
+// you should use TUKLIB_SYMBOL_PREFIX to make sure that there
+// are no symbol conflicts in case someone links your library
+// into application that also uses the same tuklib module.
+#ifndef TUKLIB_SYMBOL_PREFIX
+#	define TUKLIB_SYMBOL_PREFIX
+#endif
+
+#define TUKLIB_CAT_X(a, b) a ## b
+#define TUKLIB_CAT(a, b) TUKLIB_CAT_X(a, b)
+
+#ifndef TUKLIB_SYMBOL
+#	define TUKLIB_SYMBOL(sym) TUKLIB_CAT(TUKLIB_SYMBOL_PREFIX, sym)
+#endif
+
+#ifndef TUKLIB_DECLS_BEGIN
+#	ifdef __cplusplus
+#		define TUKLIB_DECLS_BEGIN extern "C" {
+#	else
+#		define TUKLIB_DECLS_BEGIN
+#	endif
+#endif
+
+#ifndef TUKLIB_DECLS_END
+#	ifdef __cplusplus
+#		define TUKLIB_DECLS_END }
+#	else
+#		define TUKLIB_DECLS_END
+#	endif
+#endif
+
+#if defined(__GNUC__) && defined(__GNUC_MINOR__)
+#	define TUKLIB_GNUC_REQ(major, minor) \
+		((__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)) \
+			|| __GNUC__ > (major))
+#else
+#	define TUKLIB_GNUC_REQ(major, minor) 0
+#endif
+
+#if TUKLIB_GNUC_REQ(2, 5)
+#	define tuklib_attr_noreturn __attribute__((__noreturn__))
+#else
+#	define tuklib_attr_noreturn
+#endif
+
+#if (defined(_WIN32) && !defined(__CYGWIN__)) \
+		|| defined(__OS2__) || defined(__MSDOS__)
+#	define TUKLIB_DOSLIKE 1
+#endif
+
+#endif
diff --git a/src/common/tuklib_config.h b/src/common/tuklib_config.h
new file mode 100644
index 0000000..549cb24
--- /dev/null
+++ b/src/common/tuklib_config.h
@@ -0,0 +1,7 @@
+#ifdef HAVE_CONFIG_H
+#	include "sysdefs.h"
+#else
+#	include <stddef.h>
+#	include <inttypes.h>
+#	include <limits.h>
+#endif
diff --git a/src/common/tuklib_cpucores.c b/src/common/tuklib_cpucores.c
new file mode 100644
index 0000000..1da13df
--- /dev/null
+++ b/src/common/tuklib_cpucores.c
@@ -0,0 +1,62 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       tuklib_cpucores.c
+/// \brief      Get the number of CPU cores online
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "tuklib_cpucores.h"
+
+#if defined(TUKLIB_CPUCORES_SYSCTL)
+#	ifdef HAVE_SYS_PARAM_H
+#		include <sys/param.h>
+#	endif
+#	include <sys/sysctl.h>
+
+#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
+
+
+extern uint32_t
+tuklib_cpucores(void)
+{
+	uint32_t ret = 0;
+
+#if defined(TUKLIB_CPUCORES_SYSCTL)
+	int name[2] = { CTL_HW, HW_NCPU };
+	int cpus;
+	size_t cpus_size = sizeof(cpus);
+	if (sysctl(name, 2, &cpus, &cpus_size, NULL, 0) != -1
+			&& cpus_size == sizeof(cpus) && cpus > 0)
+		ret = cpus;
+
+#elif defined(TUKLIB_CPUCORES_SYSCONF)
+#	ifdef _SC_NPROCESSORS_ONLN
+	// Most systems
+	const long cpus = sysconf(_SC_NPROCESSORS_ONLN);
+#	else
+	// IRIX
+	const long cpus = sysconf(_SC_NPROC_ONLN);
+#	endif
+	if (cpus > 0)
+		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_cpucores.h b/src/common/tuklib_cpucores.h
new file mode 100644
index 0000000..be1ce1c
--- /dev/null
+++ b/src/common/tuklib_cpucores.h
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       tuklib_cpucores.h
+/// \brief      Get the number of CPU cores online
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef TUKLIB_CPUCORES_H
+#define TUKLIB_CPUCORES_H
+
+#include "tuklib_common.h"
+TUKLIB_DECLS_BEGIN
+
+#define tuklib_cpucores TUKLIB_SYMBOL(tuklib_cpucores)
+extern uint32_t tuklib_cpucores(void);
+
+TUKLIB_DECLS_END
+#endif
diff --git a/src/common/tuklib_exit.c b/src/common/tuklib_exit.c
new file mode 100644
index 0000000..c393be6
--- /dev/null
+++ b/src/common/tuklib_exit.c
@@ -0,0 +1,57 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       tuklib_exit.c
+/// \brief      Close stdout and stderr, and exit
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "tuklib_common.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "tuklib_gettext.h"
+#include "tuklib_progname.h"
+#include "tuklib_exit.h"
+
+
+extern void
+tuklib_exit(int status, int err_status, int show_error)
+{
+	if (status != err_status) {
+		// Close stdout. If something goes wrong,
+		// print an error message to stderr.
+		const int ferror_err = ferror(stdout);
+		const int fclose_err = fclose(stdout);
+		if (ferror_err || fclose_err) {
+			status = err_status;
+
+			// If it was fclose() that failed, we have the reason
+			// in errno. If only ferror() indicated an error,
+			// we have no idea what the reason was.
+			if (show_error)
+				fprintf(stderr, "%s: %s: %s\n", progname,
+						_("Writing to standard "
+							"output failed"),
+						fclose_err ? strerror(errno)
+							: _("Unknown error"));
+		}
+	}
+
+	if (status != err_status) {
+		// Close stderr. If something goes wrong, there's
+		// nothing where we could print an error message.
+		// Just set the exit status.
+		const int ferror_err = ferror(stderr);
+		const int fclose_err = fclose(stderr);
+		if (fclose_err || ferror_err)
+			status = err_status;
+	}
+
+	exit(status);
+}
diff --git a/src/common/tuklib_exit.h b/src/common/tuklib_exit.h
new file mode 100644
index 0000000..b11776f
--- /dev/null
+++ b/src/common/tuklib_exit.h
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       tuklib_exit.h
+/// \brief      Close stdout and stderr, and exit
+/// \note       Requires tuklib_progname and tuklib_gettext modules
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef TUKLIB_EXIT_H
+#define TUKLIB_EXIT_H
+
+#include "tuklib_common.h"
+TUKLIB_DECLS_BEGIN
+
+#define tuklib_exit TUKLIB_SYMBOL(tuklib_exit)
+extern void tuklib_exit(int status, int err_status, int show_error)
+		tuklib_attr_noreturn;
+
+TUKLIB_DECLS_END
+#endif
diff --git a/src/common/tuklib_gettext.h b/src/common/tuklib_gettext.h
new file mode 100644
index 0000000..2485213
--- /dev/null
+++ b/src/common/tuklib_gettext.h
@@ -0,0 +1,44 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       tuklib_gettext.h
+/// \brief      Wrapper for gettext and friends
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef TUKLIB_GETTEXT_H
+#define TUKLIB_GETTEXT_H
+
+#include "tuklib_common.h"
+#include <locale.h>
+
+#ifndef TUKLIB_GETTEXT
+#	ifdef ENABLE_NLS
+#		define TUKLIB_GETTEXT 1
+#	else
+#		define TUKLIB_GETTEXT 0
+#	endif
+#endif
+
+#if TUKLIB_GETTEXT
+#	include <libintl.h>
+#	define tuklib_gettext_init(package, localedir) \
+		do { \
+			setlocale(LC_ALL, ""); \
+			bindtextdomain(package, localedir); \
+			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))
+#endif
+
+#endif
diff --git a/src/common/tuklib_integer.h b/src/common/tuklib_integer.h
new file mode 100644
index 0000000..e6daa77
--- /dev/null
+++ b/src/common/tuklib_integer.h
@@ -0,0 +1,523 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       tuklib_integer.h
+/// \brief      Various integer and bit operations
+///
+/// This file provides macros or functions to do some basic integer and bit
+/// operations.
+///
+/// Endianness related integer operations (XX = 16, 32, or 64; Y = b or l):
+///   - Byte swapping: bswapXX(num)
+///   - Byte order conversions to/from native: convXXYe(num)
+///   - Aligned reads: readXXYe(ptr)
+///   - Aligned writes: writeXXYe(ptr, num)
+///   - Unaligned reads (16/32-bit only): unaligned_readXXYe(ptr)
+///   - Unaligned writes (16/32-bit only): unaligned_writeXXYe(ptr, num)
+///
+/// Since they can macros, the arguments should have no side effects since
+/// they may be evaluated more than once.
+///
+/// \todo       PowerPC and possibly some other architectures support
+///             byte swapping load and store instructions. This file
+///             doesn't take advantage of those instructions.
+///
+/// Bit scan operations for non-zero 32-bit integers:
+///   - Bit scan reverse (find highest non-zero bit): bsr32(num)
+///   - Count leading zeros: clz32(num)
+///   - Count trailing zeros: ctz32(num)
+///   - Bit scan forward (simply an alias for ctz32()): bsf32(num)
+///
+/// The above bit scan operations return 0-31. If num is zero,
+/// the result is undefined.
+//
+//  Authors:    Lasse Collin
+//              Joachim Henke
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef TUKLIB_INTEGER_H
+#define TUKLIB_INTEGER_H
+
+#include "tuklib_common.h"
+
+
+////////////////////////////////////////
+// Operating system specific features //
+////////////////////////////////////////
+
+#if defined(HAVE_BYTESWAP_H)
+	// glibc, uClibc, dietlibc
+#	include <byteswap.h>
+#	ifdef HAVE_BSWAP_16
+#		define bswap16(num) bswap_16(num)
+#	endif
+#	ifdef HAVE_BSWAP_32
+#		define bswap32(num) bswap_32(num)
+#	endif
+#	ifdef HAVE_BSWAP_64
+#		define bswap64(num) bswap_64(num)
+#	endif
+
+#elif defined(HAVE_SYS_ENDIAN_H)
+	// *BSDs and Darwin
+#	include <sys/endian.h>
+
+#elif defined(HAVE_SYS_BYTEORDER_H)
+	// Solaris
+#	include <sys/byteorder.h>
+#	ifdef BSWAP_16
+#		define bswap16(num) BSWAP_16(num)
+#	endif
+#	ifdef BSWAP_32
+#		define bswap32(num) BSWAP_32(num)
+#	endif
+#	ifdef BSWAP_64
+#		define bswap64(num) BSWAP_64(num)
+#	endif
+#	ifdef BE_16
+#		define conv16be(num) BE_16(num)
+#	endif
+#	ifdef BE_32
+#		define conv32be(num) BE_32(num)
+#	endif
+#	ifdef BE_64
+#		define conv64be(num) BE_64(num)
+#	endif
+#	ifdef LE_16
+#		define conv16le(num) LE_16(num)
+#	endif
+#	ifdef LE_32
+#		define conv32le(num) LE_32(num)
+#	endif
+#	ifdef LE_64
+#		define conv64le(num) LE_64(num)
+#	endif
+#endif
+
+
+///////////////////
+// Byte swapping //
+///////////////////
+
+#ifndef bswap16
+#	define bswap16(num) \
+		(((uint16_t)(num) << 8) | ((uint16_t)(num) >> 8))
+#endif
+
+#ifndef bswap32
+#	define bswap32(num) \
+		( (((uint32_t)(num) << 24)                       ) \
+		| (((uint32_t)(num) <<  8) & UINT32_C(0x00FF0000)) \
+		| (((uint32_t)(num) >>  8) & UINT32_C(0x0000FF00)) \
+		| (((uint32_t)(num) >> 24)                       ) )
+#endif
+
+#ifndef bswap64
+#	define bswap64(num) \
+		( (((uint64_t)(num) << 56)                               ) \
+		| (((uint64_t)(num) << 40) & UINT64_C(0x00FF000000000000)) \
+		| (((uint64_t)(num) << 24) & UINT64_C(0x0000FF0000000000)) \
+		| (((uint64_t)(num) <<  8) & UINT64_C(0x000000FF00000000)) \
+		| (((uint64_t)(num) >>  8) & UINT64_C(0x00000000FF000000)) \
+		| (((uint64_t)(num) >> 24) & UINT64_C(0x0000000000FF0000)) \
+		| (((uint64_t)(num) >> 40) & UINT64_C(0x000000000000FF00)) \
+		| (((uint64_t)(num) >> 56)                               ) )
+#endif
+
+// Define conversion macros using the basic byte swapping macros.
+#ifdef WORDS_BIGENDIAN
+#	ifndef conv16be
+#		define conv16be(num) ((uint16_t)(num))
+#	endif
+#	ifndef conv32be
+#		define conv32be(num) ((uint32_t)(num))
+#	endif
+#	ifndef conv64be
+#		define conv64be(num) ((uint64_t)(num))
+#	endif
+#	ifndef conv16le
+#		define conv16le(num) bswap16(num)
+#	endif
+#	ifndef conv32le
+#		define conv32le(num) bswap32(num)
+#	endif
+#	ifndef conv64le
+#		define conv64le(num) bswap64(num)
+#	endif
+#else
+#	ifndef conv16be
+#		define conv16be(num) bswap16(num)
+#	endif
+#	ifndef conv32be
+#		define conv32be(num) bswap32(num)
+#	endif
+#	ifndef conv64be
+#		define conv64be(num) bswap64(num)
+#	endif
+#	ifndef conv16le
+#		define conv16le(num) ((uint16_t)(num))
+#	endif
+#	ifndef conv32le
+#		define conv32le(num) ((uint32_t)(num))
+#	endif
+#	ifndef conv64le
+#		define conv64le(num) ((uint64_t)(num))
+#	endif
+#endif
+
+
+//////////////////////////////
+// Aligned reads and writes //
+//////////////////////////////
+
+static inline uint16_t
+read16be(const uint8_t *buf)
+{
+	uint16_t num = *(const uint16_t *)buf;
+	return conv16be(num);
+}
+
+
+static inline uint16_t
+read16le(const uint8_t *buf)
+{
+	uint16_t num = *(const uint16_t *)buf;
+	return conv16le(num);
+}
+
+
+static inline uint32_t
+read32be(const uint8_t *buf)
+{
+	uint32_t num = *(const uint32_t *)buf;
+	return conv32be(num);
+}
+
+
+static inline uint32_t
+read32le(const uint8_t *buf)
+{
+	uint32_t num = *(const uint32_t *)buf;
+	return conv32le(num);
+}
+
+
+static inline uint64_t
+read64be(const uint8_t *buf)
+{
+	uint64_t num = *(const uint64_t *)buf;
+	return conv64be(num);
+}
+
+
+static inline uint64_t
+read64le(const uint8_t *buf)
+{
+	uint64_t num = *(const uint64_t *)buf;
+	return conv64le(num);
+}
+
+
+// NOTE: Possible byte swapping must be done in a macro to allow GCC
+// to optimize byte swapping of constants when using glibc's or *BSD's
+// byte swapping macros. The actual write is done in an inline function
+// to make type checking of the buf pointer possible similarly to readXXYe()
+// functions.
+
+#define write16be(buf, num) write16ne((buf), conv16be(num))
+#define write16le(buf, num) write16ne((buf), conv16le(num))
+#define write32be(buf, num) write32ne((buf), conv32be(num))
+#define write32le(buf, num) write32ne((buf), conv32le(num))
+#define write64be(buf, num) write64ne((buf), conv64be(num))
+#define write64le(buf, num) write64ne((buf), conv64le(num))
+
+
+static inline void
+write16ne(uint8_t *buf, uint16_t num)
+{
+	*(uint16_t *)buf = num;
+	return;
+}
+
+
+static inline void
+write32ne(uint8_t *buf, uint32_t num)
+{
+	*(uint32_t *)buf = num;
+	return;
+}
+
+
+static inline void
+write64ne(uint8_t *buf, uint64_t num)
+{
+	*(uint64_t *)buf = num;
+	return;
+}
+
+
+////////////////////////////////
+// Unaligned reads and writes //
+////////////////////////////////
+
+// NOTE: TUKLIB_FAST_UNALIGNED_ACCESS indicates only support for 16-bit and
+// 32-bit unaligned integer loads and stores. It's possible that 64-bit
+// unaligned access doesn't work or is slower than byte-by-byte access.
+// Since unaligned 64-bit is probably not needed as often as 16-bit or
+// 32-bit, we simply don't support 64-bit unaligned access for now.
+#ifdef TUKLIB_FAST_UNALIGNED_ACCESS
+#	define unaligned_read16be read16be
+#	define unaligned_read16le read16le
+#	define unaligned_read32be read32be
+#	define unaligned_read32le read32le
+#	define unaligned_write16be write16be
+#	define unaligned_write16le write16le
+#	define unaligned_write32be write32be
+#	define unaligned_write32le write32le
+
+#else
+
+static inline uint16_t
+unaligned_read16be(const uint8_t *buf)
+{
+	uint16_t num = ((uint16_t)buf[0] << 8) | (uint16_t)buf[1];
+	return num;
+}
+
+
+static inline uint16_t
+unaligned_read16le(const uint8_t *buf)
+{
+	uint16_t num = ((uint16_t)buf[0]) | ((uint16_t)buf[1] << 8);
+	return num;
+}
+
+
+static inline uint32_t
+unaligned_read32be(const uint8_t *buf)
+{
+	uint32_t num = (uint32_t)buf[0] << 24;
+	num |= (uint32_t)buf[1] << 16;
+	num |= (uint32_t)buf[2] << 8;
+	num |= (uint32_t)buf[3];
+	return num;
+}
+
+
+static inline uint32_t
+unaligned_read32le(const uint8_t *buf)
+{
+	uint32_t num = (uint32_t)buf[0];
+	num |= (uint32_t)buf[1] << 8;
+	num |= (uint32_t)buf[2] << 16;
+	num |= (uint32_t)buf[3] << 24;
+	return num;
+}
+
+
+static inline void
+unaligned_write16be(uint8_t *buf, uint16_t num)
+{
+	buf[0] = num >> 8;
+	buf[1] = num;
+	return;
+}
+
+
+static inline void
+unaligned_write16le(uint8_t *buf, uint16_t num)
+{
+	buf[0] = num;
+	buf[1] = num >> 8;
+	return;
+}
+
+
+static inline void
+unaligned_write32be(uint8_t *buf, uint32_t num)
+{
+	buf[0] = num >> 24;
+	buf[1] = num >> 16;
+	buf[2] = num >> 8;
+	buf[3] = num;
+	return;
+}
+
+
+static inline void
+unaligned_write32le(uint8_t *buf, uint32_t num)
+{
+	buf[0] = num;
+	buf[1] = num >> 8;
+	buf[2] = num >> 16;
+	buf[3] = num >> 24;
+	return;
+}
+
+#endif
+
+
+static inline uint32_t
+bsr32(uint32_t n)
+{
+	// Check for ICC first, since it tends to define __GNUC__ too.
+#if defined(__INTEL_COMPILER)
+	return _bit_scan_reverse(n);
+
+#elif TUKLIB_GNUC_REQ(3, 4) && UINT_MAX == UINT32_MAX
+	// GCC >= 3.4 has __builtin_clz(), which gives good results on
+	// multiple architectures. On x86, __builtin_clz() ^ 31U becomes
+	// either plain BSR (so the XOR gets optimized away) or LZCNT and
+	// XOR (if -march indicates that SSE4a instructions are supported).
+	return __builtin_clz(n) ^ 31U;
+
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+	uint32_t i;
+	__asm__("bsrl %1, %0" : "=r" (i) : "rm" (n));
+	return i;
+
+#elif defined(_MSC_VER) && _MSC_VER >= 1400
+	// MSVC isn't supported by tuklib, but since this code exists,
+	// it doesn't hurt to have it here anyway.
+	uint32_t i;
+	_BitScanReverse((DWORD *)&i, n);
+	return i;
+
+#else
+	uint32_t i = 31;
+
+	if ((n & UINT32_C(0xFFFF0000)) == 0) {
+		n <<= 16;
+		i = 15;
+	}
+
+	if ((n & UINT32_C(0xFF000000)) == 0) {
+		n <<= 8;
+		i -= 8;
+	}
+
+	if ((n & UINT32_C(0xF0000000)) == 0) {
+		n <<= 4;
+		i -= 4;
+	}
+
+	if ((n & UINT32_C(0xC0000000)) == 0) {
+		n <<= 2;
+		i -= 2;
+	}
+
+	if ((n & UINT32_C(0x80000000)) == 0)
+		--i;
+
+	return i;
+#endif
+}
+
+
+static inline uint32_t
+clz32(uint32_t n)
+{
+#if defined(__INTEL_COMPILER)
+	return _bit_scan_reverse(n) ^ 31U;
+
+#elif TUKLIB_GNUC_REQ(3, 4) && UINT_MAX == UINT32_MAX
+	return __builtin_clz(n);
+
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+	uint32_t i;
+	__asm__("bsrl %1, %0\n\t"
+		"xorl $31, %0"
+		: "=r" (i) : "rm" (n));
+	return i;
+
+#elif defined(_MSC_VER) && _MSC_VER >= 1400
+	uint32_t i;
+	_BitScanReverse((DWORD *)&i, n);
+	return i ^ 31U;
+
+#else
+	uint32_t i = 0;
+
+	if ((n & UINT32_C(0xFFFF0000)) == 0) {
+		n <<= 16;
+		i = 16;
+	}
+
+	if ((n & UINT32_C(0xFF000000)) == 0) {
+		n <<= 8;
+		i += 8;
+	}
+
+	if ((n & UINT32_C(0xF0000000)) == 0) {
+		n <<= 4;
+		i += 4;
+	}
+
+	if ((n & UINT32_C(0xC0000000)) == 0) {
+		n <<= 2;
+		i += 2;
+	}
+
+	if ((n & UINT32_C(0x80000000)) == 0)
+		++i;
+
+	return i;
+#endif
+}
+
+
+static inline uint32_t
+ctz32(uint32_t n)
+{
+#if defined(__INTEL_COMPILER)
+	return _bit_scan_forward(n);
+
+#elif TUKLIB_GNUC_REQ(3, 4) && UINT_MAX >= UINT32_MAX
+	return __builtin_ctz(n);
+
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+	uint32_t i;
+	__asm__("bsfl %1, %0" : "=r" (i) : "rm" (n));
+	return i;
+
+#elif defined(_MSC_VER) && _MSC_VER >= 1400
+	uint32_t i;
+	_BitScanForward((DWORD *)&i, n);
+	return i;
+
+#else
+	uint32_t i = 0;
+
+	if ((n & UINT32_C(0x0000FFFF)) == 0) {
+		n >>= 16;
+		i = 16;
+	}
+
+	if ((n & UINT32_C(0x000000FF)) == 0) {
+		n >>= 8;
+		i += 8;
+	}
+
+	if ((n & UINT32_C(0x0000000F)) == 0) {
+		n >>= 4;
+		i += 4;
+	}
+
+	if ((n & UINT32_C(0x00000003)) == 0) {
+		n >>= 2;
+		i += 2;
+	}
+
+	if ((n & UINT32_C(0x00000001)) == 0)
+		++i;
+
+	return i;
+#endif
+}
+
+#define bsf32 ctz32
+
+#endif
diff --git a/src/common/tuklib_open_stdxxx.c b/src/common/tuklib_open_stdxxx.c
new file mode 100644
index 0000000..08bc60d
--- /dev/null
+++ b/src/common/tuklib_open_stdxxx.c
@@ -0,0 +1,55 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       tuklib_open_stdxxx.c
+/// \brief      Make sure that file descriptors 0, 1, and 2 are open
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "tuklib_open_stdxxx.h"
+
+#ifndef TUKLIB_DOSLIKE
+#	include <stdlib.h>
+#	include <errno.h>
+#	include <fcntl.h>
+#	include <unistd.h>
+#endif
+
+
+extern void
+tuklib_open_stdxxx(int err_status)
+{
+#ifdef TUKLIB_DOSLIKE
+	// Do nothing, just silence warnings.
+	(void)err_status;
+
+#else
+	for (int i = 0; i <= 2; ++i) {
+		// We use fcntl() to check if the file descriptor is open.
+		if (fcntl(i, F_GETFD) == -1 && errno == EBADF) {
+			// With stdin, we could use /dev/full so that
+			// writing to stdin would fail. However, /dev/full
+			// is Linux specific, and if the program tries to
+			// write to stdin, there's already a problem anyway.
+			const int fd = open("/dev/null", O_NOCTTY
+					| (i == 0 ? O_WRONLY : O_RDONLY));
+
+			if (fd != i) {
+				// Something went wrong. Exit with the
+				// exit status we were given. Don't try
+				// to print an error message, since stderr
+				// may very well be non-existent. This
+				// error should be extremely rare.
+				(void)close(fd);
+				exit(err_status);
+			}
+		}
+	}
+#endif
+
+	return;
+}
diff --git a/src/common/tuklib_open_stdxxx.h b/src/common/tuklib_open_stdxxx.h
new file mode 100644
index 0000000..b911616
--- /dev/null
+++ b/src/common/tuklib_open_stdxxx.h
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       tuklib_open_stdxxx.h
+/// \brief      Make sure that file descriptors 0, 1, and 2 are open
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef TUKLIB_OPEN_STDXXX_H
+#define TUKLIB_OPEN_STDXXX_H
+
+#include "tuklib_common.h"
+TUKLIB_DECLS_BEGIN
+
+#define tuklib_open_stdxx TUKLIB_SYMBOL(tuklib_open_stdxxx)
+extern void tuklib_open_stdxxx(int err_status);
+
+TUKLIB_DECLS_END
+#endif
diff --git a/src/common/tuklib_physmem.c b/src/common/tuklib_physmem.c
new file mode 100644
index 0000000..623b6e7
--- /dev/null
+++ b/src/common/tuklib_physmem.c
@@ -0,0 +1,196 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       tuklib_physmem.c
+/// \brief      Get the amount of physical memory
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "tuklib_physmem.h"
+
+// We want to use Windows-specific code on Cygwin, which also has memory
+// information available via sysconf(), but on Cygwin 1.5 and older it
+// gives wrong results (from our point of view).
+#if defined(_WIN32) || defined(__CYGWIN__)
+#	ifndef _WIN32_WINNT
+#		define _WIN32_WINNT 0x0500
+#	endif
+#	include <windows.h>
+
+#elif defined(__OS2__)
+#	define INCL_DOSMISC
+#	include <os2.h>
+
+#elif defined(__DJGPP__)
+#	include <dpmi.h>
+
+#elif defined(__VMS)
+#	include <lib$routines.h>
+#	include <syidef.h>
+#	include <ssdef.h>
+
+// AIX
+#elif defined(TUKLIB_PHYSMEM_AIX)
+#	include <sys/systemcfg.h>
+
+#elif defined(TUKLIB_PHYSMEM_SYSCONF)
+#	include <unistd.h>
+
+#elif defined(TUKLIB_PHYSMEM_SYSCTL)
+#	ifdef HAVE_SYS_PARAM_H
+#		include <sys/param.h>
+#	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>
+
+// This sysinfo() is Linux-specific.
+#elif defined(TUKLIB_PHYSMEM_SYSINFO)
+#	include <sys/sysinfo.h>
+#endif
+
+
+extern uint64_t
+tuklib_physmem(void)
+{
+	uint64_t ret = 0;
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+	if ((GetVersion() & 0xFF) >= 5) {
+		// Windows 2000 and later have GlobalMemoryStatusEx() which
+		// supports reporting values greater than 4 GiB. To keep the
+		// code working also on older Windows versions, use
+		// GlobalMemoryStatusEx() conditionally.
+		HMODULE kernel32 = GetModuleHandle("kernel32.dll");
+		if (kernel32 != NULL) {
+			BOOL (WINAPI *gmse)(LPMEMORYSTATUSEX) = GetProcAddress(
+					kernel32, "GlobalMemoryStatusEx");
+			if (gmse != NULL) {
+				MEMORYSTATUSEX meminfo;
+				meminfo.dwLength = sizeof(meminfo);
+				if (gmse(&meminfo))
+					ret = meminfo.ullTotalPhys;
+			}
+		}
+	}
+
+	if (ret == 0) {
+		// GlobalMemoryStatus() is supported by Windows 95 and later,
+		// so it is fine to link against it unconditionally. Note that
+		// GlobalMemoryStatus() has no return value.
+		MEMORYSTATUS meminfo;
+		meminfo.dwLength = sizeof(meminfo);
+		GlobalMemoryStatus(&meminfo);
+		ret = meminfo.dwTotalPhys;
+	}
+
+#elif defined(__OS2__)
+	unsigned long mem;
+	if (DosQuerySysInfo(QSV_TOTPHYSMEM, QSV_TOTPHYSMEM,
+			&mem, sizeof(mem)) == 0)
+		ret = mem;
+
+#elif defined(__DJGPP__)
+	__dpmi_free_mem_info meminfo;
+	if (__dpmi_get_free_memory_information(&meminfo) == 0
+			&& meminfo.total_number_of_physical_pages
+				!= (unsigned long)-1)
+		ret = (uint64_t)meminfo.total_number_of_physical_pages * 4096;
+
+#elif defined(__VMS)
+	int vms_mem;
+	int val = SYI$_MEMSIZE;
+	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)
+		// 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"
+		// being 32-bit will overflow. Casting to uint64_t
+		// hopefully avoids overflows in the near future.
+		ret = (uint64_t)pagesize * (uint64_t)pages;
+
+#elif defined(TUKLIB_PHYSMEM_SYSCTL)
+	int name[2] = {
+		CTL_HW,
+#ifdef HW_PHYSMEM64
+		HW_PHYSMEM64
+#else
+		HW_PHYSMEM
+#endif
+	};
+	union {
+		uint32_t u32;
+		uint64_t u64;
+	} mem;
+	size_t mem_ptr_size = sizeof(mem.u64);
+	if (sysctl(name, 2, &mem.u64, &mem_ptr_size, NULL, 0) != -1) {
+		// IIRC, 64-bit "return value" is possible on some 64-bit
+		// BSD systems even with HW_PHYSMEM (instead of HW_PHYSMEM64),
+		// so support both.
+		if (mem_ptr_size == sizeof(mem.u64))
+			ret = mem.u64;
+		else if (mem_ptr_size == sizeof(mem.u32))
+			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) {
+		inventory_t *i;
+		while ((i = getinvent_r(st)) != NULL) {
+			if (i->inv_class == INV_MEMORY
+					&& i->inv_type == INV_MAIN_MB) {
+				ret = (uint64_t)i->inv_state << 20;
+				break;
+			}
+		}
+
+		endinvent_r(st);
+	}
+
+#elif defined(TUKLIB_PHYSMEM_SYSINFO)
+	struct sysinfo si;
+	if (sysinfo(&si) == 0)
+		ret = (uint64_t)si.totalram * si.mem_unit;
+#endif
+
+	return ret;
+}
diff --git a/src/common/tuklib_physmem.h b/src/common/tuklib_physmem.h
new file mode 100644
index 0000000..09e2a51
--- /dev/null
+++ b/src/common/tuklib_physmem.h
@@ -0,0 +1,28 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       tuklib_physmem.h
+/// \brief      Get the amount of physical memory
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef TUKLIB_PHYSMEM_H
+#define TUKLIB_PHYSMEM_H
+
+#include "tuklib_common.h"
+TUKLIB_DECLS_BEGIN
+
+#define tuklib_physmem TUKLIB_SYMBOL(tuklib_physmem)
+extern uint64_t tuklib_physmem(void);
+///<
+/// \brief      Get the amount of physical memory in bytes
+///
+/// \return     Amount of physical memory in bytes. On error, zero is
+///             returned.
+
+TUKLIB_DECLS_END
+#endif
diff --git a/src/common/tuklib_progname.c b/src/common/tuklib_progname.c
new file mode 100644
index 0000000..7cb7e20
--- /dev/null
+++ b/src/common/tuklib_progname.c
@@ -0,0 +1,50 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       tuklib_progname.c
+/// \brief      Program name to be displayed in messages
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "tuklib_progname.h"
+#include <string.h>
+
+
+#if !HAVE_DECL_PROGRAM_INVOCATION_NAME
+char *progname = NULL;
+#endif
+
+
+extern void
+tuklib_progname_init(char **argv)
+{
+#ifdef TUKLIB_DOSLIKE
+	// On these systems, argv[0] always has the full path and .exe
+	// suffix even if the user just types the plain program name.
+	// We modify argv[0] to make it nicer to read.
+
+	// Strip the leading path.
+	char *p = argv[0] + strlen(argv[0]);
+	while (argv[0] < p && p[-1] != '/' && p[-1] != '\\')
+		--p;
+
+	argv[0] = p;
+
+	// Strip the .exe suffix.
+	p = strrchr(p, '.');
+	if (p != NULL)
+		*p = '\0';
+
+	// Make it lowercase.
+	for (p = argv[0]; *p != '\0'; ++p)
+		if (*p >= 'A' && *p <= 'Z')
+			*p = *p - 'A' + 'a';
+#endif
+
+	progname = argv[0];
+	return;
+}
diff --git a/src/common/tuklib_progname.h b/src/common/tuklib_progname.h
new file mode 100644
index 0000000..791b125
--- /dev/null
+++ b/src/common/tuklib_progname.h
@@ -0,0 +1,32 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       tuklib_progname.h
+/// \brief      Program name to be displayed in messages
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef TUKLIB_PROGNAME_H
+#define TUKLIB_PROGNAME_H
+
+#include "tuklib_common.h"
+#include <errno.h>
+
+TUKLIB_DECLS_BEGIN
+
+#if HAVE_DECL_PROGRAM_INVOCATION_NAME
+#	define progname program_invocation_name
+#else
+#	define progname TUKLIB_SYMBOL(tuklib_progname)
+	extern char *progname;
+#endif
+
+#define tuklib_progname_init TUKLIB_SYMBOL(tuklib_progname_init)
+extern void tuklib_progname_init(char **argv);
+
+TUKLIB_DECLS_END
+#endif
diff --git a/src/liblzma/Makefile.am b/src/liblzma/Makefile.am
new file mode 100644
index 0000000..f6c572b
--- /dev/null
+++ b/src/liblzma/Makefile.am
@@ -0,0 +1,90 @@
+##
+## Author: Lasse Collin
+##
+## This file has been put into the public domain.
+## You can do whatever you want with this file.
+##
+
+SUBDIRS = api
+
+EXTRA_DIST =
+CLEANFILES =
+doc_DATA =
+
+lib_LTLIBRARIES = liblzma.la
+liblzma_la_SOURCES = $(top_srcdir)/src/common/tuklib_physmem.c
+liblzma_la_CPPFLAGS = \
+	-I$(top_srcdir)/src/liblzma/api \
+	-I$(top_srcdir)/src/liblzma/common \
+	-I$(top_srcdir)/src/liblzma/check \
+	-I$(top_srcdir)/src/liblzma/lz \
+	-I$(top_srcdir)/src/liblzma/rangecoder \
+	-I$(top_srcdir)/src/liblzma/lzma \
+	-I$(top_srcdir)/src/liblzma/delta \
+	-I$(top_srcdir)/src/liblzma/simple \
+	-I$(top_srcdir)/src/common \
+	-DTUKLIB_SYMBOL_PREFIX=lzma_
+liblzma_la_LDFLAGS = -no-undefined -version-info 0:0:0
+
+include $(srcdir)/common/Makefile.inc
+include $(srcdir)/check/Makefile.inc
+
+if COND_FILTER_LZ
+include $(srcdir)/lz/Makefile.inc
+endif
+
+if COND_FILTER_LZMA1
+include $(srcdir)/lzma/Makefile.inc
+include $(srcdir)/rangecoder/Makefile.inc
+endif
+
+if COND_FILTER_DELTA
+include $(srcdir)/delta/Makefile.inc
+endif
+
+if COND_FILTER_SIMPLE
+include $(srcdir)/simple/Makefile.inc
+endif
+
+
+## Windows-specific stuff
+
+# Windows resource compiler support. libtool knows what to do with .rc
+# files, but Automake (<= 1.11 at least) doesn't know.
+#
+# We want the resource file only in shared liblzma. To avoid linking it into
+# static liblzma, we overwrite the static object file with an object file
+# compiled from empty input. Note that GNU-specific features are OK here,
+# because on Windows we are compiled with the GNU toolchain.
+.rc.lo:
+	$(LIBTOOL) --mode=compile $(RC) $(DEFS) $(DEFAULT_INCLUDES) \
+		$(INCLUDES) $(liblzma_la_CPPFLAGS) $(CPPFLAGS) $(RCFLAGS) \
+		-i $< -o $@
+	echo > empty.c
+	$(COMPILE) -c empty.c -o $(*D)/$(*F).o
+
+# Remove ordinals from the generated .def file. People must link by name,
+# not by ordinal, because no one is going to track the ordinal numbers.
+liblzma.def: liblzma.la liblzma.def.in
+	sed 's/ \+@ *[0-9]\+//' liblzma.def.in > liblzma.def
+
+# Creating liblzma.def.in is a side effect of linking the library.
+liblzma.def.in: liblzma.la
+
+if COND_W32
+CLEANFILES += liblzma.def liblzma.def.in empty.c
+liblzma_la_SOURCES += liblzma_w32res.rc
+liblzma_la_LDFLAGS += -Xlinker --output-def -Xlinker liblzma.def.in
+
+## liblzma.def.in is created only when building shared liblzma, so don't
+## try to create liblzma.def when not building shared liblzma.
+if COND_SHARED
+doc_DATA += liblzma.def
+endif
+endif
+
+
+## pkg-config
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = liblzma.pc
+EXTRA_DIST += liblzma.pc.in
diff --git a/src/liblzma/api/Makefile.am b/src/liblzma/api/Makefile.am
new file mode 100644
index 0000000..e016de5
--- /dev/null
+++ b/src/liblzma/api/Makefile.am
@@ -0,0 +1,23 @@
+##
+## Author: Lasse Collin
+##
+## This file has been put into the public domain.
+## You can do whatever you want with this file.
+##
+
+nobase_include_HEADERS = \
+	lzma.h \
+	lzma/base.h \
+	lzma/bcj.h \
+	lzma/block.h \
+	lzma/check.h \
+	lzma/container.h \
+	lzma/delta.h \
+	lzma/filter.h \
+	lzma/hardware.h \
+	lzma/index.h \
+	lzma/index_hash.h \
+	lzma/lzma.h \
+	lzma/stream_flags.h \
+	lzma/version.h \
+	lzma/vli.h
diff --git a/src/liblzma/api/lzma.h b/src/liblzma/api/lzma.h
new file mode 100644
index 0000000..fb593a3
--- /dev/null
+++ b/src/liblzma/api/lzma.h
@@ -0,0 +1,313 @@
+/**
+ * \file        api/lzma.h
+ * \brief       The public API of liblzma data compression library
+ *
+ * liblzma is a public domain general-purpose data compression library with
+ * a zlib-like API. The native file format is .xz, but also the old .lzma
+ * format and raw (no headers) streams are supported. Multiple compression
+ * algorithms (filters) are supported. Currently LZMA2 is the primary filter.
+ *
+ * liblzma is part of XZ Utils <http://tukaani.org/xz/>. XZ Utils includes
+ * a gzip-like command line tool named xz and some other tools. XZ Utils
+ * is developed and maintained by Lasse Collin.
+ *
+ * Major parts of liblzma are based on Igor Pavlov's public domain LZMA SDK
+ * <http://7-zip.org/sdk.html>.
+ *
+ * The SHA-256 implementation is based on the public domain code found from
+ * 7-Zip <http://7-zip.org/>, which has a modified version of the public
+ * domain SHA-256 code found from Crypto++ <http://www.cryptopp.com/>.
+ * The SHA-256 code in Crypto++ was written by Kevin Springle and Wei Dai.
+ */
+
+/*
+ * Author: Lasse Collin
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ */
+
+#ifndef LZMA_H
+#define LZMA_H
+
+/*****************************
+ * Required standard headers *
+ *****************************/
+
+/*
+ * liblzma API headers need some standard types and macros. To allow
+ * including lzma.h without requiring the application to include other
+ * headers first, lzma.h includes the required standard headers unless
+ * they already seem to be included already or if LZMA_MANUAL_HEADERS
+ * has been defined.
+ *
+ * Here's what types and macros are needed and from which headers:
+ *  - stddef.h: size_t, NULL
+ *  - stdint.h: uint8_t, uint32_t, uint64_t, UINT32_C(n), uint64_C(n),
+ *    UINT32_MAX, UINT64_MAX
+ *
+ * However, inttypes.h is a little more portable than stdint.h, although
+ * inttypes.h declares some unneeded things compared to plain stdint.h.
+ *
+ * The hacks below aren't perfect, specifically they assume that inttypes.h
+ * exists and that it typedefs at least uint8_t, uint32_t, and uint64_t,
+ * and that, in case of incomplete inttypes.h, unsigned int is 32-bit.
+ * If the application already takes care of setting up all the types and
+ * macros properly (for example by using gnulib's stdint.h or inttypes.h),
+ * we try to detect that the macros are already defined and don't include
+ * inttypes.h here again. However, you may define LZMA_MANUAL_HEADERS to
+ * force this file to never include any system headers.
+ *
+ * Some could argue that liblzma API should provide all the required types,
+ * for example lzma_uint64, LZMA_UINT64_C(n), and LZMA_UINT64_MAX. This was
+ * seen unnecessary mess, since most systems already provide all the necessary
+ * types and macros in the standard headers.
+ *
+ * Note that liblzma API still has lzma_bool, because using stdbool.h would
+ * break C89 and C++ programs on many systems. sizeof(bool) in C99 isn't
+ * necessarily the same as sizeof(bool) in C++.
+ */
+
+#ifndef LZMA_MANUAL_HEADERS
+	/*
+	 * I suppose this works portably also in C++. Note that in C++,
+	 * we need to get size_t into the global namespace.
+	 */
+#	include <stddef.h>
+
+	/*
+	 * Skip inttypes.h if we already have all the required macros. If we
+	 * have the macros, we assume that we have the matching typedefs too.
+	 */
+#	if !defined(UINT32_C) || !defined(UINT64_C) \
+			|| !defined(UINT32_MAX) || !defined(UINT64_MAX)
+		/*
+		 * MSVC has no C99 support, and thus it cannot be used to
+		 * compile liblzma. The liblzma API has to still be usable
+		 * from MSVC, so we need to define the required standard
+		 * integer types here.
+		 */
+#		if defined(_WIN32) && defined(_MSC_VER)
+			typedef unsigned __int8 uint8_t;
+			typedef unsigned __int32 uint32_t;
+			typedef unsigned __int64 uint64_t;
+#		else
+			/* Use the standard inttypes.h. */
+#			ifdef __cplusplus
+				/*
+				 * C99 sections 7.18.2 and 7.18.4 specify
+				 * that C++ implementations define the limit
+				 * and constant macros only if specifically
+				 * requested. Note that if you want the
+				 * format macros (PRIu64 etc.) too, you need
+				 * to define __STDC_FORMAT_MACROS before
+				 * including lzma.h, since re-including
+				 * inttypes.h with __STDC_FORMAT_MACROS
+				 * defined doesn't necessarily work.
+				 */
+#				ifndef __STDC_LIMIT_MACROS
+#					define __STDC_LIMIT_MACROS 1
+#				endif
+#				ifndef __STDC_CONSTANT_MACROS
+#					define __STDC_CONSTANT_MACROS 1
+#				endif
+#			endif
+
+#			include <inttypes.h>
+#		endif
+
+		/*
+		 * Some old systems have only the typedefs in inttypes.h, and
+		 * lack all the macros. For those systems, we need a few more
+		 * hacks. We assume that unsigned int is 32-bit and unsigned
+		 * long is either 32-bit or 64-bit. If these hacks aren't
+		 * enough, the application has to setup the types manually
+		 * before including lzma.h.
+		 */
+#		ifndef UINT32_C
+#			if defined(_WIN32) && defined(_MSC_VER)
+#				define UINT32_C(n) n ## UI32
+#			else
+#				define UINT32_C(n) n ## U
+#			endif
+#		endif
+
+#		ifndef UINT64_C
+#			if defined(_WIN32) && defined(_MSC_VER)
+#				define UINT64_C(n) n ## UI64
+#			else
+				/* Get ULONG_MAX. */
+#				include <limits.h>
+#				if ULONG_MAX == 4294967295UL
+#					define UINT64_C(n) n ## ULL
+#				else
+#					define UINT64_C(n) n ## UL
+#				endif
+#			endif
+#		endif
+
+#		ifndef UINT32_MAX
+#			define UINT32_MAX (UINT32_C(4294967295))
+#		endif
+
+#		ifndef UINT64_MAX
+#			define UINT64_MAX (UINT64_C(18446744073709551615))
+#		endif
+#	endif
+#endif /* ifdef LZMA_MANUAL_HEADERS */
+
+
+/******************
+ * LZMA_API macro *
+ ******************/
+
+/*
+ * Some systems require that the functions and function pointers are
+ * declared specially in the headers. LZMA_API_IMPORT is for importing
+ * symbols and LZMA_API_CALL is to specify the calling convention.
+ *
+ * By default it is assumed that the application will link dynamically
+ * against liblzma. #define LZMA_API_STATIC in your application if you
+ * want to link against static liblzma. If you don't care about portability
+ * to operating systems like Windows, or at least don't care about linking
+ * against static liblzma on them, don't worry about LZMA_API_STATIC. That
+ * is, most developers will never need to use LZMA_API_STATIC.
+ *
+ * The GCC variants are a special case on Windows (Cygwin and MinGW).
+ * We rely on GCC doing the right thing with its auto-import feature,
+ * and thus don't use __declspec(dllimport). This way developers don't
+ * need to worry about LZMA_API_STATIC. Also the calling convention is
+ * omitted on Cygwin but not on MinGW.
+ */
+#ifndef LZMA_API_IMPORT
+#	if !defined(LZMA_API_STATIC) && defined(_WIN32) && !defined(__GNUC__)
+#		define LZMA_API_IMPORT __declspec(dllimport)
+#	else
+#		define LZMA_API_IMPORT
+#	endif
+#endif
+
+#ifndef LZMA_API_CALL
+#	if defined(_WIN32) && !defined(__CYGWIN__)
+#		define LZMA_API_CALL __cdecl
+#	else
+#		define LZMA_API_CALL
+#	endif
+#endif
+
+#ifndef LZMA_API
+#	define LZMA_API(type) LZMA_API_IMPORT type LZMA_API_CALL
+#endif
+
+
+/***********
+ * nothrow *
+ ***********/
+
+/*
+ * None of the functions in liblzma may throw an exception. Even
+ * the functions that use callback functions won't throw exceptions,
+ * because liblzma would break if a callback function threw an exception.
+ */
+#ifndef lzma_nothrow
+#	if defined(__cplusplus)
+#		define lzma_nothrow throw()
+#	elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
+#		define lzma_nothrow __attribute__((__nothrow__))
+#	else
+#		define lzma_nothrow
+#	endif
+#endif
+
+
+/********************
+ * GNU C extensions *
+ ********************/
+
+/*
+ * GNU C extensions are used conditionally in the public API. It doesn't
+ * break anything if these are sometimes enabled and sometimes not, only
+ * affects warnings and optimizations.
+ */
+#if __GNUC__ >= 3
+#	ifndef lzma_attribute
+#		define lzma_attribute(attr) __attribute__(attr)
+#	endif
+
+	/* warn_unused_result was added in GCC 3.4. */
+#	ifndef lzma_attr_warn_unused_result
+#		if __GNUC__ == 3 && __GNUC_MINOR__ < 4
+#			define lzma_attr_warn_unused_result
+#		endif
+#	endif
+
+#else
+#	ifndef lzma_attribute
+#		define lzma_attribute(attr)
+#	endif
+#endif
+
+
+#ifndef lzma_attr_pure
+#	define lzma_attr_pure lzma_attribute((__pure__))
+#endif
+
+#ifndef lzma_attr_const
+#	define lzma_attr_const lzma_attribute((__const__))
+#endif
+
+#ifndef lzma_attr_warn_unused_result
+#	define lzma_attr_warn_unused_result \
+		lzma_attribute((__warn_unused_result__))
+#endif
+
+
+/**************
+ * Subheaders *
+ **************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Subheaders check that this is defined. It is to prevent including
+ * them directly from applications.
+ */
+#define LZMA_H_INTERNAL 1
+
+/* Basic features */
+#include "lzma/version.h"
+#include "lzma/base.h"
+#include "lzma/vli.h"
+#include "lzma/check.h"
+
+/* Filters */
+#include "lzma/filter.h"
+#include "lzma/bcj.h"
+#include "lzma/delta.h"
+#include "lzma/lzma.h"
+
+/* Container formats */
+#include "lzma/container.h"
+
+/* Advanced features */
+#include "lzma/stream_flags.h"
+#include "lzma/block.h"
+#include "lzma/index.h"
+#include "lzma/index_hash.h"
+
+/* Hardware information */
+#include "lzma/hardware.h"
+
+/*
+ * All subheaders included. Undefine LZMA_H_INTERNAL to prevent applications
+ * re-including the subheaders.
+ */
+#undef LZMA_H_INTERNAL
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ifndef LZMA_H */
diff --git a/src/liblzma/api/lzma/base.h b/src/liblzma/api/lzma/base.h
new file mode 100644
index 0000000..993626a
--- /dev/null
+++ b/src/liblzma/api/lzma/base.h
@@ -0,0 +1,596 @@
+/**
+ * \file        lzma/base.h
+ * \brief       Data types and functions used in many places in liblzma API
+ */
+
+/*
+ * 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       Boolean
+ *
+ * This is here because C89 doesn't have stdbool.h. To set a value for
+ * variables having type lzma_bool, you can use
+ *   - C99's `true' and `false' from stdbool.h;
+ *   - C++'s internal `true' and `false'; or
+ *   - integers one (true) and zero (false).
+ */
+typedef unsigned char lzma_bool;
+
+
+/**
+ * \brief       Type of reserved enumeration variable in structures
+ *
+ * To avoid breaking library ABI when new features are added, several
+ * structures contain extra variables that may be used in future. Since
+ * sizeof(enum) can be different than sizeof(int), and sizeof(enum) may
+ * even vary depending on the range of enumeration constants, we specify
+ * a separate type to be used for reserved enumeration variables. All
+ * enumeration constants in liblzma API will be non-negative and less
+ * than 128, which should guarantee that the ABI won't break even when
+ * new constants are added to existing enumerations.
+ */
+typedef enum {
+	LZMA_RESERVED_ENUM      = 0
+} lzma_reserved_enum;
+
+
+/**
+ * \brief       Return values used by several functions in liblzma
+ *
+ * Check the descriptions of specific functions to find out which return
+ * values they can return. With some functions the return values may have
+ * more specific meanings than described here; those differences are
+ * described per-function basis.
+ */
+typedef enum {
+	LZMA_OK                 = 0,
+		/**<
+		 * \brief       Operation completed successfully
+		 */
+
+	LZMA_STREAM_END         = 1,
+		/**<
+		 * \brief       End of stream was reached
+		 *
+		 * In encoder, LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, or
+		 * LZMA_FINISH was finished. In decoder, this indicates
+		 * that all the data was successfully decoded.
+		 *
+		 * In all cases, when LZMA_STREAM_END is returned, the last
+		 * output bytes should be picked from strm->next_out.
+		 */
+
+	LZMA_NO_CHECK           = 2,
+		/**<
+		 * \brief       Input stream has no integrity check
+		 *
+		 * This return value can be returned only if the
+		 * LZMA_TELL_NO_CHECK flag was used when initializing
+		 * the decoder. LZMA_NO_CHECK is just a warning, and
+		 * the decoding can be continued normally.
+		 *
+		 * It is possible to call lzma_get_check() immediately after
+		 * lzma_code has returned LZMA_NO_CHECK. The result will
+		 * naturally be LZMA_CHECK_NONE, but the possibility to call
+		 * lzma_get_check() may be convenient in some applications.
+		 */
+
+	LZMA_UNSUPPORTED_CHECK  = 3,
+		/**<
+		 * \brief       Cannot calculate the integrity check
+		 *
+		 * The usage of this return value is different in encoders
+		 * and decoders.
+		 *
+		 * Encoders can return this value only from the initialization
+		 * function. If initialization fails with this value, the
+		 * encoding cannot be done, because there's no way to produce
+		 * output with the correct integrity check.
+		 *
+		 * Decoders can return this value only from lzma_code() and
+		 * only if the LZMA_TELL_UNSUPPORTED_CHECK flag was used when
+		 * initializing the decoder. The decoding can still be
+		 * continued normally even if the check type is unsupported,
+		 * but naturally the check will not be validated, and possible
+		 * errors may go undetected.
+		 *
+		 * With decoder, it is possible to call lzma_get_check()
+		 * immediately after lzma_code() has returned
+		 * LZMA_UNSUPPORTED_CHECK. This way it is possible to find
+		 * out what the unsupported Check ID was.
+		 */
+
+	LZMA_GET_CHECK          = 4,
+		/**<
+		 * \brief       Integrity check type is now available
+		 *
+		 * This value can be returned only by the lzma_code() function
+		 * and only if the decoder was initialized with the
+		 * LZMA_TELL_ANY_CHECK flag. LZMA_GET_CHECK tells the
+		 * application that it may now call lzma_get_check() to find
+		 * out the Check ID. This can be used, for example, to
+		 * implement a decoder that accepts only files that have
+		 * strong enough integrity check.
+		 */
+
+	LZMA_MEM_ERROR          = 5,
+		/**<
+		 * \brief       Cannot allocate memory
+		 *
+		 * Memory allocation failed, or the size of the allocation
+		 * would be greater than SIZE_MAX.
+		 *
+		 * Due to internal implementation reasons, the coding cannot
+		 * be continued even if more memory were made available after
+		 * LZMA_MEM_ERROR.
+		 */
+
+	LZMA_MEMLIMIT_ERROR     = 6,
+		/**
+		 * \brief       Memory usage limit was reached
+		 *
+		 * Decoder would need more memory than allowed by the
+		 * specified memory usage limit. To continue decoding,
+		 * the memory usage limit has to be increased with
+		 * lzma_memlimit_set().
+		 */
+
+	LZMA_FORMAT_ERROR       = 7,
+		/**<
+		 * \brief       File format not recognized
+		 *
+		 * The decoder did not recognize the input as supported file
+		 * format. This error can occur, for example, when trying to
+		 * decode .lzma format file with lzma_stream_decoder,
+		 * because lzma_stream_decoder accepts only the .xz format.
+		 */
+
+	LZMA_OPTIONS_ERROR      = 8,
+		/**<
+		 * \brief       Invalid or unsupported options
+		 *
+		 * Invalid or unsupported options, for example
+		 *  - unsupported filter(s) or filter options; or
+		 *  - reserved bits set in headers (decoder only).
+		 *
+		 * Rebuilding liblzma with more features enabled, or
+		 * upgrading to a newer version of liblzma may help.
+		 */
+
+	LZMA_DATA_ERROR         = 9,
+		/**<
+		 * \brief       Data is corrupt
+		 *
+		 * The usage of this return value is different in encoders
+		 * and decoders. In both encoder and decoder, the coding
+		 * cannot continue after this error.
+		 *
+		 * Encoders return this if size limits of the target file
+		 * format would be exceeded. These limits are huge, thus
+		 * getting this error from an encoder is mostly theoretical.
+		 * For example, the maximum compressed and uncompressed
+		 * size of a .xz Stream is roughly 8 EiB (2^63 bytes).
+		 *
+		 * Decoders return this error if the input data is corrupt.
+		 * This can mean, for example, invalid CRC32 in headers
+		 * or invalid check of uncompressed data.
+		 */
+
+	LZMA_BUF_ERROR          = 10,
+		/**<
+		 * \brief       No progress is possible
+		 *
+		 * This error code is returned when the coder cannot consume
+		 * any new input and produce any new output. The most common
+		 * reason for this error is that the input stream being
+		 * decoded is truncated or corrupt.
+		 *
+		 * This error is not fatal. Coding can be continued normally
+		 * by providing more input and/or more output space, if
+		 * possible.
+		 *
+		 * Typically the first call to lzma_code() that can do no
+		 * progress returns LZMA_OK instead of LZMA_BUF_ERROR. Only
+		 * the second consecutive call doing no progress will return
+		 * LZMA_BUF_ERROR. This is intentional.
+		 *
+		 * With zlib, Z_BUF_ERROR may be returned even if the
+		 * application is doing nothing wrong, so apps will need
+		 * to handle Z_BUF_ERROR specially. The above hack
+		 * guarantees that liblzma never returns LZMA_BUF_ERROR
+		 * to properly written applications unless the input file
+		 * is truncated or corrupt. This should simplify the
+		 * applications a little.
+		 */
+
+	LZMA_PROG_ERROR         = 11,
+		/**<
+		 * \brief       Programming error
+		 *
+		 * This indicates that the arguments given to the function are
+		 * invalid or the internal state of the decoder is corrupt.
+		 *   - Function arguments are invalid or the structures
+		 *     pointed by the argument pointers are invalid
+		 *     e.g. if strm->next_out has been set to NULL and
+		 *     strm->avail_out > 0 when calling lzma_code().
+		 *   - lzma_* functions have been called in wrong order
+		 *     e.g. lzma_code() was called right after lzma_end().
+		 *   - If errors occur randomly, the reason might be flaky
+		 *     hardware.
+		 *
+		 * If you think that your code is correct, this error code
+		 * can be a sign of a bug in liblzma. See the documentation
+		 * how to report bugs.
+		 */
+} lzma_ret;
+
+
+/**
+ * \brief       The `action' argument for lzma_code()
+ *
+ * After the first use of LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, or LZMA_FINISH,
+ * the same `action' must is used until lzma_code() returns LZMA_STREAM_END.
+ * Also, the amount of input (that is, strm->avail_in) must not be modified
+ * by the application until lzma_code() returns LZMA_STREAM_END. Changing the
+ * `action' or modifying the amount of input will make lzma_code() return
+ * LZMA_PROG_ERROR.
+ */
+typedef enum {
+	LZMA_RUN = 0,
+		/**<
+		 * \brief       Continue coding
+		 *
+		 * Encoder: Encode as much input as possible. Some internal
+		 * buffering will probably be done (depends on the filter
+		 * chain in use), which causes latency: the input used won't
+		 * usually be decodeable from the output of the same
+		 * lzma_code() call.
+		 *
+		 * Decoder: Decode as much input as possible and produce as
+		 * much output as possible.
+		 */
+
+	LZMA_SYNC_FLUSH = 1,
+		/**<
+		 * \brief       Make all the input available at output
+		 *
+		 * Normally the encoder introduces some latency.
+		 * LZMA_SYNC_FLUSH forces all the buffered data to be
+		 * available at output without resetting the internal
+		 * state of the encoder. This way it is possible to use
+		 * compressed stream for example for communication over
+		 * network.
+		 *
+		 * Only some filters support LZMA_SYNC_FLUSH. Trying to use
+		 * LZMA_SYNC_FLUSH with filters that don't support it will
+		 * make lzma_code() return LZMA_OPTIONS_ERROR. For example,
+		 * LZMA1 doesn't support LZMA_SYNC_FLUSH but LZMA2 does.
+		 *
+		 * Using LZMA_SYNC_FLUSH very often can dramatically reduce
+		 * the compression ratio. With some filters (for example,
+		 * LZMA2), fine-tuning the compression options may help
+		 * mitigate this problem significantly.
+		 *
+		 * Decoders don't support LZMA_SYNC_FLUSH.
+		 */
+
+	LZMA_FULL_FLUSH = 2,
+		/**<
+		 * \brief       Make all the input available at output
+		 *
+		 * Finish encoding of the current Block. All the input
+		 * data going to the current Block must have been given
+		 * to the encoder (the last bytes can still be pending in
+		 * next_in). Call lzma_code() with LZMA_FULL_FLUSH until
+		 * it returns LZMA_STREAM_END. Then continue normally with
+		 * LZMA_RUN or finish the Stream with LZMA_FINISH.
+		 *
+		 * This action is currently supported only by Stream encoder
+		 * and easy encoder (which uses Stream encoder). If there is
+		 * no unfinished Block, no empty Block is created.
+		 */
+
+	LZMA_FINISH = 3
+		/**<
+		 * \brief       Finish the coding operation
+		 *
+		 * Finishes the coding operation. All the input data must
+		 * have been given to the encoder (the last bytes can still
+		 * be pending in next_in). Call lzma_code() with LZMA_FINISH
+		 * until it returns LZMA_STREAM_END. Once LZMA_FINISH has
+		 * been used, the amount of input must no longer be changed
+		 * by the application.
+		 *
+		 * When decoding, using LZMA_FINISH is optional unless the
+		 * LZMA_CONCATENATED flag was used when the decoder was
+		 * initialized. When LZMA_CONCATENATED was not used, the only
+		 * effect of LZMA_FINISH is that the amount of input must not
+		 * be changed just like in the encoder.
+		 */
+} lzma_action;
+
+
+/**
+ * \brief       Custom functions for memory handling
+ *
+ * A pointer to lzma_allocator may be passed via lzma_stream structure
+ * to liblzma, and some advanced functions take a pointer to lzma_allocator
+ * as a separate function argument. The library will use the functions
+ * specified in lzma_allocator for memory handling instead of the default
+ * malloc() and free(). C++ users should note that the custom memory
+ * handling functions must not throw exceptions.
+ *
+ * liblzma doesn't make an internal copy of lzma_allocator. Thus, it is
+ * OK to change these function pointers in the middle of the coding
+ * process, but obviously it must be done carefully to make sure that the
+ * replacement `free' can deallocate memory allocated by the earlier
+ * `alloc' function(s).
+ */
+typedef struct {
+	/**
+	 * \brief       Pointer to a custom memory allocation function
+	 *
+	 * If you don't want a custom allocator, but still want
+	 * custom free(), set this to NULL and liblzma will use
+	 * the standard malloc().
+	 *
+	 * \param       opaque  lzma_allocator.opaque (see below)
+	 * \param       nmemb   Number of elements like in calloc(). liblzma
+	 *                      will always set nmemb to 1, so it is safe to
+	 *                      ignore nmemb in a custom allocator if you like.
+	 *                      The nmemb argument exists only for
+	 *                      compatibility with zlib and libbzip2.
+	 * \param       size    Size of an element in bytes.
+	 *                      liblzma never sets this to zero.
+	 *
+	 * \return      Pointer to the beginning of a memory block of
+	 *              `size' bytes, or NULL if allocation fails
+	 *              for some reason. When allocation fails, functions
+	 *              of liblzma return LZMA_MEM_ERROR.
+	 *
+	 * The allocator should not waste time zeroing the allocated buffers.
+	 * This is not only about speed, but also memory usage, since the
+	 * operating system kernel doesn't necessarily allocate the requested
+	 * memory in physical memory until it is actually used. With small
+	 * input files, liblzma may actually need only a fraction of the
+	 * memory that it requested for allocation.
+	 *
+	 * \note        LZMA_MEM_ERROR is also used when the size of the
+	 *              allocation would be greater than SIZE_MAX. Thus,
+	 *              don't assume that the custom allocator must have
+	 *              returned NULL if some function from liblzma
+	 *              returns LZMA_MEM_ERROR.
+	 */
+	void *(LZMA_API_CALL *alloc)(void *opaque, size_t nmemb, size_t size);
+
+	/**
+	 * \brief       Pointer to a custom memory freeing function
+	 *
+	 * If you don't want a custom freeing function, but still
+	 * want a custom allocator, set this to NULL and liblzma
+	 * will use the standard free().
+	 *
+	 * \param       opaque  lzma_allocator.opaque (see below)
+	 * \param       ptr     Pointer returned by lzma_allocator.alloc(),
+	 *                      or when it is set to NULL, a pointer returned
+	 *                      by the standard malloc().
+	 */
+	void (LZMA_API_CALL *free)(void *opaque, void *ptr);
+
+	/**
+	 * \brief       Pointer passed to .alloc() and .free()
+	 *
+	 * opaque is passed as the first argument to lzma_allocator.alloc()
+	 * and lzma_allocator.free(). This intended to ease implementing
+	 * custom memory allocation functions for use with liblzma.
+	 *
+	 * If you don't need this, you should set this to NULL.
+	 */
+	void *opaque;
+
+} lzma_allocator;
+
+
+/**
+ * \brief       Internal data structure
+ *
+ * The contents of this structure is not visible outside the library.
+ */
+typedef struct lzma_internal_s lzma_internal;
+
+
+/**
+ * \brief       Passing data to and from liblzma
+ *
+ * The lzma_stream structure is used for
+ *  - passing pointers to input and output buffers to liblzma;
+ *  - defining custom memory hander functions; and
+ *  - holding a pointer to coder-specific internal data structures.
+ *
+ * Typical usage:
+ *
+ *  - After allocating lzma_stream (on stack or with malloc()), it must be
+ *    initialized to LZMA_STREAM_INIT (see LZMA_STREAM_INIT for details).
+ *
+ *  - Initialize a coder to the lzma_stream, for example by using
+ *    lzma_easy_encoder() or lzma_auto_decoder(). Some notes:
+ *      - In contrast to zlib, strm->next_in and strm->next_out are
+ *        ignored by all initialization functions, thus it is safe
+ *        to not initialize them yet.
+ *      - The initialization functions always set strm->total_in and
+ *        strm->total_out to zero.
+ *      - If the initialization function fails, no memory is left allocated
+ *        that would require freeing with lzma_end() even if some memory was
+ *        associated with the lzma_stream structure when the initialization
+ *        function was called.
+ *
+ *  - Use lzma_code() to do the actual work.
+ *
+ *  - Once the coding has been finished, the existing lzma_stream can be
+ *    reused. It is OK to reuse lzma_stream with different initialization
+ *    function without calling lzma_end() first. Old allocations are
+ *    automatically freed.
+ *
+ *  - Finally, use lzma_end() to free the allocated memory. lzma_end() never
+ *    frees the lzma_stream structure itself.
+ *
+ * Application may modify the values of total_in and total_out as it wants.
+ * They are updated by liblzma to match the amount of data read and
+ * written, but aren't used for anything else.
+ */
+typedef struct {
+	const uint8_t *next_in; /**< Pointer to the next input byte. */
+	size_t avail_in;    /**< Number of available input bytes in next_in. */
+	uint64_t total_in;  /**< Total number of bytes read by liblzma. */
+
+	uint8_t *next_out;  /**< Pointer to the next output position. */
+	size_t avail_out;   /**< Amount of free space in next_out. */
+	uint64_t total_out; /**< Total number of bytes written by liblzma. */
+
+	/**
+	 * \brief       Custom memory allocation functions
+	 *
+	 * In most cases this is NULL which makes liblzma use
+	 * the standard malloc() and free().
+	 */
+	lzma_allocator *allocator;
+
+	/** Internal state is not visible to applications. */
+	lzma_internal *internal;
+
+	/*
+	 * Reserved space to allow possible future extensions without
+	 * breaking the ABI. Excluding the initialization of this structure,
+	 * you should not touch these, because the names of these variables
+	 * may change.
+	 */
+	void *reserved_ptr1;
+	void *reserved_ptr2;
+	uint64_t reserved_int1;
+	uint64_t reserved_int2;
+	lzma_reserved_enum reserved_enum1;
+	lzma_reserved_enum reserved_enum2;
+
+} lzma_stream;
+
+
+/**
+ * \brief       Initialization for lzma_stream
+ *
+ * When you declare an instance of lzma_stream, you can immediately
+ * initialize it so that initialization functions know that no memory
+ * has been allocated yet:
+ *
+ *     lzma_stream strm = LZMA_STREAM_INIT;
+ *
+ * If you need to initialize a dynamically allocated lzma_stream, you can use
+ * memset(strm_pointer, 0, sizeof(lzma_stream)). Strictly speaking, this
+ * violates the C standard since NULL may have different internal
+ * representation than zero, but it should be portable enough in practice.
+ * Anyway, for maximum portability, you can use something like this:
+ *
+ *     lzma_stream tmp = LZMA_STREAM_INIT;
+ *     *strm = tmp;
+ */
+#define LZMA_STREAM_INIT \
+	{ NULL, 0, 0, NULL, 0, 0, NULL, NULL, \
+	NULL, NULL, 0, 0, LZMA_RESERVED_ENUM, LZMA_RESERVED_ENUM }
+
+
+/**
+ * \brief       Encode or decode data
+ *
+ * Once the lzma_stream has been successfully initialized (e.g. with
+ * lzma_stream_encoder()), the actual encoding or decoding is done
+ * using this function. The application has to update strm->next_in,
+ * strm->avail_in, strm->next_out, and strm->avail_out to pass input
+ * to and get output from liblzma.
+ *
+ * See the description of the coder-specific initialization function to find
+ * out what `action' values are supported by the coder.
+ */
+extern LZMA_API(lzma_ret) lzma_code(lzma_stream *strm, lzma_action action)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Free memory allocated for the coder data structures
+ *
+ * \param       strm    Pointer to lzma_stream that is at least initialized
+ *                      with LZMA_STREAM_INIT.
+ *
+ * After lzma_end(strm), strm->internal is guaranteed to be NULL. No other
+ * members of the lzma_stream structure are touched.
+ *
+ * \note        zlib indicates an error if application end()s unfinished
+ *              stream structure. liblzma doesn't do this, and assumes that
+ *              application knows what it is doing.
+ */
+extern LZMA_API(void) lzma_end(lzma_stream *strm) lzma_nothrow;
+
+
+/**
+ * \brief       Get the memory usage of decoder filter chain
+ *
+ * This function is currently supported only when *strm has been initialized
+ * with a function that takes a memlimit argument. With other functions, you
+ * should use e.g. lzma_raw_encoder_memusage() or lzma_raw_decoder_memusage()
+ * to estimate the memory requirements.
+ *
+ * This function is useful e.g. after LZMA_MEMLIMIT_ERROR to find out how big
+ * the memory usage limit should have been to decode the input. Note that
+ * this may give misleading information if decoding .xz Streams that have
+ * multiple Blocks, because each Block can have different memory requirements.
+ *
+ * \return      Rough estimate of how much memory is currently allocated
+ *              for the filter decoders. If no filter chain is currently
+ *              allocated, some non-zero value is still returned, which is
+ *              less than or equal to what any filter chain would indicate
+ *              as its memory requirement.
+ *
+ *              If this function isn't supported by *strm or some other error
+ *              occurs, zero is returned.
+ */
+extern LZMA_API(uint64_t) lzma_memusage(const lzma_stream *strm)
+		lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Get the current memory usage limit
+ *
+ * This function is supported only when *strm has been initialized with
+ * a function that takes a memlimit argument.
+ *
+ * \return      On success, the current memory usage limit is returned
+ *              (always non-zero). On error, zero is returned.
+ */
+extern LZMA_API(uint64_t) lzma_memlimit_get(const lzma_stream *strm)
+		lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Set the memory usage limit
+ *
+ * This function is supported only when *strm has been initialized with
+ * a function that takes a memlimit argument.
+ *
+ * \return      - LZMA_OK: New memory usage limit successfully set.
+ *              - LZMA_MEMLIMIT_ERROR: The new limit is too small.
+ *                The limit was not changed.
+ *              - LZMA_PROG_ERROR: Invalid arguments, e.g. *strm doesn't
+ *                support memory usage limit or memlimit was zero.
+ */
+extern LZMA_API(lzma_ret) lzma_memlimit_set(
+		lzma_stream *strm, uint64_t memlimit) lzma_nothrow;
diff --git a/src/liblzma/api/lzma/bcj.h b/src/liblzma/api/lzma/bcj.h
new file mode 100644
index 0000000..82e4a44
--- /dev/null
+++ b/src/liblzma/api/lzma/bcj.h
@@ -0,0 +1,90 @@
+/**
+ * \file        lzma/bcj.h
+ * \brief       Branch/Call/Jump conversion filters
+ */
+
+/*
+ * 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
+
+
+/* Filter IDs for lzma_filter.id */
+
+#define LZMA_FILTER_X86         LZMA_VLI_C(0x04)
+	/**<
+	 * Filter for x86 binaries
+	 */
+
+#define LZMA_FILTER_POWERPC     LZMA_VLI_C(0x05)
+	/**<
+	 * Filter for Big endian PowerPC binaries
+	 */
+
+#define LZMA_FILTER_IA64        LZMA_VLI_C(0x06)
+	/**<
+	 * Filter for IA64 (Itanium) binaries.
+	 */
+
+#define LZMA_FILTER_ARM         LZMA_VLI_C(0x07)
+	/**<
+	 * Filter for ARM binaries.
+	 */
+
+#define LZMA_FILTER_ARMTHUMB    LZMA_VLI_C(0x08)
+	/**<
+	 * Filter for ARMThumb binaries.
+	 */
+
+#define LZMA_FILTER_SPARC       LZMA_VLI_C(0x09)
+	/**<
+	 * Filter for SPARC binaries.
+	 */
+
+
+/**
+ * \brief       Options for BCJ filters
+ *
+ * The BCJ filters never change the size of the data. Specifying options
+ * for them is optional: if pointer to options is NULL, default value is
+ * used. You probably never need to specify options to BCJ filters, so just
+ * set the options pointer to NULL and be happy.
+ *
+ * If options with non-default values have been specified when encoding,
+ * the same options must also be specified when decoding.
+ *
+ * \note        At the moment, none of the BCJ filters support
+ *              LZMA_SYNC_FLUSH. If LZMA_SYNC_FLUSH is specified,
+ *              LZMA_OPTIONS_ERROR will be returned. If there is need,
+ *              partial support for LZMA_SYNC_FLUSH can be added in future.
+ *              Partial means that flushing would be possible only at
+ *              offsets that are multiple of 2, 4, or 16 depending on
+ *              the filter, except x86 which cannot be made to support
+ *              LZMA_SYNC_FLUSH predictably.
+ */
+typedef struct {
+	/**
+	 * \brief       Start offset for conversions
+	 *
+	 * This setting is useful only when the same filter is used
+	 * _separately_ for multiple sections of the same executable file,
+	 * and the sections contain cross-section branch/call/jump
+	 * instructions. In that case it is beneficial to set the start
+	 * offset of the non-first sections so that the relative addresses
+	 * of the cross-section branch/call/jump instructions will use the
+	 * same absolute addresses as in the first section.
+	 *
+	 * When the pointer to options is NULL, the default value (zero)
+	 * is used.
+	 */
+	uint32_t start_offset;
+
+} lzma_options_bcj;
diff --git a/src/liblzma/api/lzma/block.h b/src/liblzma/api/lzma/block.h
new file mode 100644
index 0000000..8e681ed
--- /dev/null
+++ b/src/liblzma/api/lzma/block.h
@@ -0,0 +1,529 @@
+/**
+ * \file        lzma/block.h
+ * \brief       .xz Block handling
+ */
+
+/*
+ * 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       Options for the Block and Block Header encoders and decoders
+ *
+ * Different Block handling functions use different parts of this structure.
+ * Some read some members, other functions write, and some do both. Only the
+ * members listed for reading need to be initialized when the specified
+ * functions are called. The members marked for writing will be assigned
+ * new values at some point either by calling the given function or by
+ * later calls to lzma_code().
+ */
+typedef struct {
+	/**
+	 * \brief       Block format version
+	 *
+	 * To prevent API and ABI breakages if new features are needed in
+	 * the Block field, a version number is used to indicate which
+	 * fields in this structure are in use. For now, version must always
+	 * be zero. With non-zero version, most Block related functions will
+	 * return LZMA_OPTIONS_ERROR.
+	 *
+	 * Read by:
+	 *  - All functions that take pointer to lzma_block as argument,
+	 *    including lzma_block_header_decode().
+	 *
+	 * Written by:
+	 *  - lzma_block_header_decode()
+	 */
+	uint32_t version;
+
+	/**
+	 * \brief       Size of the Block Header field
+	 *
+	 * This is always a multiple of four.
+	 *
+	 * Read by:
+	 *  - lzma_block_header_encode()
+	 *  - lzma_block_header_decode()
+	 *  - lzma_block_compressed_size()
+	 *  - lzma_block_unpadded_size()
+	 *  - lzma_block_total_size()
+	 *  - lzma_block_decoder()
+	 *  - lzma_block_buffer_decode()
+	 *
+	 * Written by:
+	 *  - lzma_block_header_size()
+	 *  - lzma_block_buffer_encode()
+	 */
+	uint32_t header_size;
+#	define LZMA_BLOCK_HEADER_SIZE_MIN 8
+#	define LZMA_BLOCK_HEADER_SIZE_MAX 1024
+
+	/**
+	 * \brief       Type of integrity Check
+	 *
+	 * The Check ID is not stored into the Block Header, thus its value
+	 * must be provided also when decoding.
+	 *
+	 * Read by:
+	 *  - lzma_block_header_encode()
+	 *  - lzma_block_header_decode()
+	 *  - lzma_block_compressed_size()
+	 *  - lzma_block_unpadded_size()
+	 *  - lzma_block_total_size()
+	 *  - lzma_block_encoder()
+	 *  - lzma_block_decoder()
+	 *  - lzma_block_buffer_encode()
+	 *  - lzma_block_buffer_decode()
+	 */
+	lzma_check check;
+
+	/**
+	 * \brief       Size of the Compressed Data in bytes
+	 *
+	 * Encoding: If this is not LZMA_VLI_UNKNOWN, Block Header encoder
+	 * will store this value to the Block Header. Block encoder doesn't
+	 * care about this value, but will set it once the encoding has been
+	 * finished.
+	 *
+	 * Decoding: If this is not LZMA_VLI_UNKNOWN, Block decoder will
+	 * verify that the size of the Compressed Data field matches
+	 * compressed_size.
+	 *
+	 * Usually you don't know this value when encoding in streamed mode,
+	 * and thus cannot write this field into the Block Header.
+	 *
+	 * In non-streamed mode you can reserve space for this field before
+	 * encoding the actual Block. After encoding the data, finish the
+	 * Block by encoding the Block Header. Steps in detail:
+	 *
+	 *  - Set compressed_size to some big enough value. If you don't know
+	 *    better, use LZMA_VLI_MAX, but remember that bigger values take
+	 *    more space in Block Header.
+	 *
+	 *  - Call lzma_block_header_size() to see how much space you need to
+	 *    reserve for the Block Header.
+	 *
+	 *  - Encode the Block using lzma_block_encoder() and lzma_code().
+	 *    It sets compressed_size to the correct value.
+	 *
+	 *  - Use lzma_block_header_encode() to encode the Block Header.
+	 *    Because space was reserved in the first step, you don't need
+	 *    to call lzma_block_header_size() anymore, because due to
+	 *    reserving, header_size has to be big enough. If it is "too big",
+	 *    lzma_block_header_encode() will add enough Header Padding to
+	 *    make Block Header to match the size specified by header_size.
+	 *
+	 * Read by:
+	 *  - lzma_block_header_size()
+	 *  - lzma_block_header_encode()
+	 *  - lzma_block_compressed_size()
+	 *  - lzma_block_unpadded_size()
+	 *  - lzma_block_total_size()
+	 *  - lzma_block_decoder()
+	 *  - lzma_block_buffer_decode()
+	 *
+	 * Written by:
+	 *  - lzma_block_header_decode()
+	 *  - lzma_block_compressed_size()
+	 *  - lzma_block_encoder()
+	 *  - lzma_block_decoder()
+	 *  - lzma_block_buffer_encode()
+	 *  - lzma_block_buffer_decode()
+	 */
+	lzma_vli compressed_size;
+
+	/**
+	 * \brief       Uncompressed Size in bytes
+	 *
+	 * This is handled very similarly to compressed_size above.
+	 *
+	 * uncompressed_size is needed by fewer functions than
+	 * compressed_size. This is because uncompressed_size isn't
+	 * needed to validate that Block stays within proper limits.
+	 *
+	 * Read by:
+	 *  - lzma_block_header_size()
+	 *  - lzma_block_header_encode()
+	 *  - lzma_block_decoder()
+	 *  - lzma_block_buffer_decode()
+	 *
+	 * Written by:
+	 *  - lzma_block_header_decode()
+	 *  - lzma_block_encoder()
+	 *  - lzma_block_decoder()
+	 *  - lzma_block_buffer_encode()
+	 *  - lzma_block_buffer_decode()
+	 */
+	lzma_vli uncompressed_size;
+
+	/**
+	 * \brief       Array of filters
+	 *
+	 * There can be 1-4 filters. The end of the array is marked with
+	 * .id = LZMA_VLI_UNKNOWN.
+	 *
+	 * Read by:
+	 *  - lzma_block_header_size()
+	 *  - lzma_block_header_encode()
+	 *  - lzma_block_encoder()
+	 *  - lzma_block_decoder()
+	 *  - lzma_block_buffer_encode()
+	 *  - lzma_block_buffer_decode()
+	 *
+	 * Written by:
+	 *  - lzma_block_header_decode(): Note that this does NOT free()
+	 *    the old filter options structures. All unused filters[] will
+	 *    have .id == LZMA_VLI_UNKNOWN and .options == NULL. If
+	 *    decoding fails, all filters[] are guaranteed to be
+	 *    LZMA_VLI_UNKNOWN and NULL.
+	 *
+	 * \note        Because of the array is terminated with
+	 *              .id = LZMA_VLI_UNKNOWN, the actual array must
+	 *              have LZMA_FILTERS_MAX + 1 members or the Block
+	 *              Header decoder will overflow the buffer.
+	 */
+	lzma_filter *filters;
+
+	/**
+	 * \brief       Raw value stored in the Check field
+	 *
+	 * After successful coding, the first lzma_check_size(check) bytes
+	 * of this array contain the raw value stored in the Check field.
+	 *
+	 * Note that CRC32 and CRC64 are stored in little endian byte order.
+	 * Take it into account if you display the Check values to the user.
+	 *
+	 * Written by:
+	 *  - lzma_block_encoder()
+	 *  - lzma_block_decoder()
+	 *  - lzma_block_buffer_encode()
+	 *  - lzma_block_buffer_decode()
+	 */
+	uint8_t raw_check[LZMA_CHECK_SIZE_MAX];
+
+	/*
+	 * Reserved space to allow possible future extensions without
+	 * breaking the ABI. You should not touch these, because the names
+	 * of these variables may change. These are and will never be used
+	 * with the currently supported options, so it is safe to leave these
+	 * uninitialized.
+	 */
+	void *reserved_ptr1;
+	void *reserved_ptr2;
+	void *reserved_ptr3;
+	uint32_t reserved_int1;
+	uint32_t reserved_int2;
+	lzma_vli reserved_int3;
+	lzma_vli reserved_int4;
+	lzma_vli reserved_int5;
+	lzma_vli reserved_int6;
+	lzma_vli reserved_int7;
+	lzma_vli reserved_int8;
+	lzma_reserved_enum reserved_enum1;
+	lzma_reserved_enum reserved_enum2;
+	lzma_reserved_enum reserved_enum3;
+	lzma_reserved_enum reserved_enum4;
+	lzma_bool reserved_bool1;
+	lzma_bool reserved_bool2;
+	lzma_bool reserved_bool3;
+	lzma_bool reserved_bool4;
+	lzma_bool reserved_bool5;
+	lzma_bool reserved_bool6;
+	lzma_bool reserved_bool7;
+	lzma_bool reserved_bool8;
+
+} lzma_block;
+
+
+/**
+ * \brief       Decode the Block Header Size field
+ *
+ * To decode Block Header using lzma_block_header_decode(), the size of the
+ * Block Header has to be known and stored into lzma_block.header_size.
+ * The size can be calculated from the first byte of a Block using this macro.
+ * Note that if the first byte is 0x00, it indicates beginning of Index; use
+ * this macro only when the byte is not 0x00.
+ *
+ * There is no encoding macro, because Block Header encoder is enough for that.
+ */
+#define lzma_block_header_size_decode(b) (((uint32_t)(b) + 1) * 4)
+
+
+/**
+ * \brief       Calculate Block Header Size
+ *
+ * Calculate the minimum size needed for the Block Header field using the
+ * settings specified in the lzma_block structure. Note that it is OK to
+ * increase the calculated header_size value as long as it is a multiple of
+ * four and doesn't exceed LZMA_BLOCK_HEADER_SIZE_MAX. Increasing header_size
+ * just means that lzma_block_header_encode() will add Header Padding.
+ *
+ * \return      - LZMA_OK: Size calculated successfully and stored to
+ *                block->header_size.
+ *              - LZMA_OPTIONS_ERROR: Unsupported version, filters or
+ *                filter options.
+ *              - LZMA_PROG_ERROR: Invalid values like compressed_size == 0.
+ *
+ * \note        This doesn't check that all the options are valid i.e. this
+ *              may return LZMA_OK even if lzma_block_header_encode() or
+ *              lzma_block_encoder() would fail. If you want to validate the
+ *              filter chain, consider using lzma_memlimit_encoder() which as
+ *              a side-effect validates the filter chain.
+ */
+extern LZMA_API(lzma_ret) lzma_block_header_size(lzma_block *block)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Encode Block Header
+ *
+ * The caller must have calculated the size of the Block Header already with
+ * lzma_block_header_size(). If a value larger than the one calculated by
+ * lzma_block_header_size() is used, the Block Header will be padded to the
+ * specified size.
+ *
+ * \param       out         Beginning of the output buffer. This must be
+ *                          at least block->header_size bytes.
+ * \param       block       Block options to be encoded.
+ *
+ * \return      - LZMA_OK: Encoding was successful. block->header_size
+ *                bytes were written to output buffer.
+ *              - LZMA_OPTIONS_ERROR: Invalid or unsupported options.
+ *              - LZMA_PROG_ERROR: Invalid arguments, for example
+ *                block->header_size is invalid or block->filters is NULL.
+ */
+extern LZMA_API(lzma_ret) lzma_block_header_encode(
+		const lzma_block *block, uint8_t *out)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Decode Block Header
+ *
+ * block->version should be set to the highest value supported by the
+ * application; currently the only possible version is zero. This function
+ * will set version to the lowest value that still supports all the features
+ * required by the Block Header.
+ *
+ * The size of the Block Header must have already been decoded with
+ * lzma_block_header_size_decode() macro and stored to block->header_size.
+ *
+ * block->filters must have been allocated, but not necessarily initialized.
+ * Possible existing filter options are _not_ freed.
+ *
+ * \param       block       Destination for Block options.
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() (and also free()
+ *                          if an error occurs).
+ * \param       in          Beginning of the input buffer. This must be
+ *                          at least block->header_size bytes.
+ *
+ * \return      - LZMA_OK: Decoding was successful. block->header_size
+ *                bytes were read from the input buffer.
+ *              - LZMA_OPTIONS_ERROR: The Block Header specifies some
+ *                unsupported options such as unsupported filters. This can
+ *                happen also if block->version was set to a too low value
+ *                compared to what would be required to properly represent
+ *                the information stored in the Block Header.
+ *              - LZMA_DATA_ERROR: Block Header is corrupt, for example,
+ *                the CRC32 doesn't match.
+ *              - LZMA_PROG_ERROR: Invalid arguments, for example
+ *                block->header_size is invalid or block->filters is NULL.
+ */
+extern LZMA_API(lzma_ret) lzma_block_header_decode(lzma_block *block,
+		lzma_allocator *allocator, const uint8_t *in)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Validate and set Compressed Size according to Unpadded Size
+ *
+ * Block Header stores Compressed Size, but Index has Unpadded Size. If the
+ * application has already parsed the Index and is now decoding Blocks,
+ * it can calculate Compressed Size from Unpadded Size. This function does
+ * exactly that with error checking:
+ *
+ *  - Compressed Size calculated from Unpadded Size must be positive integer,
+ *    that is, Unpadded Size must be big enough that after Block Header and
+ *    Check fields there's still at least one byte for Compressed Size.
+ *
+ *  - If Compressed Size was present in Block Header, the new value
+ *    calculated from Unpadded Size is compared against the value
+ *    from Block Header.
+ *
+ * \note        This function must be called _after_ decoding the Block Header
+ *              field so that it can properly validate Compressed Size if it
+ *              was present in Block Header.
+ *
+ * \return      - LZMA_OK: block->compressed_size was set successfully.
+ *              - LZMA_DATA_ERROR: unpadded_size is too small compared to
+ *                block->header_size and lzma_check_size(block->check).
+ *              - LZMA_PROG_ERROR: Some values are invalid. For example,
+ *                block->header_size must be a multiple of four and
+ *                between 8 and 1024 inclusive.
+ */
+extern LZMA_API(lzma_ret) lzma_block_compressed_size(
+		lzma_block *block, lzma_vli unpadded_size)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Calculate Unpadded Size
+ *
+ * The Index field stores Unpadded Size and Uncompressed Size. The latter
+ * can be taken directly from the lzma_block structure after coding a Block,
+ * but Unpadded Size needs to be calculated from Block Header Size,
+ * Compressed Size, and size of the Check field. This is where this function
+ * is needed.
+ *
+ * \return      Unpadded Size on success, or zero on error.
+ */
+extern LZMA_API(lzma_vli) lzma_block_unpadded_size(const lzma_block *block)
+		lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Calculate the total encoded size of a Block
+ *
+ * This is equivalent to lzma_block_unpadded_size() except that the returned
+ * value includes the size of the Block Padding field.
+ *
+ * \return      On success, total encoded size of the Block. On error,
+ *              zero is returned.
+ */
+extern LZMA_API(lzma_vli) lzma_block_total_size(const lzma_block *block)
+		lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Initialize .xz Block encoder
+ *
+ * Valid actions for lzma_code() are LZMA_RUN, LZMA_SYNC_FLUSH (only if the
+ * filter chain supports it), and LZMA_FINISH.
+ *
+ * \return      - LZMA_OK: All good, continue with lzma_code().
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_UNSUPPORTED_CHECK: block->check specifies a Check ID
+ *                that is not supported by this buid of liblzma. Initializing
+ *                the encoder failed.
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_block_encoder(
+		lzma_stream *strm, lzma_block *block)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Initialize .xz Block decoder
+ *
+ * Valid actions for lzma_code() are LZMA_RUN and LZMA_FINISH. Using
+ * LZMA_FINISH is not required. It is supported only for convenience.
+ *
+ * \return      - LZMA_OK: All good, continue with lzma_code().
+ *              - LZMA_UNSUPPORTED_CHECK: Initialization was successful, but
+ *                the given Check ID is not supported, thus Check will be
+ *                ignored.
+ *              - LZMA_PROG_ERROR
+ *              - LZMA_MEM_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_block_decoder(
+		lzma_stream *strm, lzma_block *block)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Calculate maximum output size for single-call Block encoding
+ *
+ * This is equivalent to lzma_stream_buffer_bound() but for .xz Blocks.
+ * See the documentation of lzma_stream_buffer_bound().
+ */
+extern LZMA_API(size_t) lzma_block_buffer_bound(size_t uncompressed_size)
+		lzma_nothrow;
+
+
+/**
+ * \brief       Single-call .xz Block encoder
+ *
+ * In contrast to the multi-call encoder initialized with
+ * lzma_block_encoder(), this function encodes also the Block Header. This
+ * is required to make it possible to write appropriate Block Header also
+ * in case the data isn't compressible, and different filter chain has to be
+ * used to encode the data in uncompressed form using uncompressed chunks
+ * of the LZMA2 filter.
+ *
+ * When the data isn't compressible, header_size, compressed_size, and
+ * uncompressed_size are set just like when the data was compressible, but
+ * it is possible that header_size is too small to hold the filter chain
+ * specified in block->filters, because that isn't necessarily the filter
+ * chain that was actually used to encode the data. lzma_block_unpadded_size()
+ * still works normally, because it doesn't read the filters array.
+ *
+ * \param       block       Block options: block->version, block->check,
+ *                          and block->filters must have been initialized.
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
+ * \param       in          Beginning of the input buffer
+ * \param       in_size     Size of the input buffer
+ * \param       out         Beginning of the output buffer
+ * \param       out_pos     The next byte will be written to out[*out_pos].
+ *                          *out_pos is updated only if encoding succeeds.
+ * \param       out_size    Size of the out buffer; the first byte into
+ *                          which no data is written to is out[out_size].
+ *
+ * \return      - LZMA_OK: Encoding was successful.
+ *              - LZMA_BUF_ERROR: Not enough output buffer space.
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_DATA_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_block_buffer_encode(
+		lzma_block *block, lzma_allocator *allocator,
+		const uint8_t *in, size_t in_size,
+		uint8_t *out, size_t *out_pos, size_t out_size)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Single-call .xz Block decoder
+ *
+ * This is single-call equivalent of lzma_block_decoder(), and requires that
+ * the caller has already decoded Block Header and checked its memory usage.
+ *
+ * \param       block       Block options just like with lzma_block_decoder().
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
+ * \param       in          Beginning of the input buffer
+ * \param       in_pos      The next byte will be read from in[*in_pos].
+ *                          *in_pos is updated only if decoding succeeds.
+ * \param       in_size     Size of the input buffer; the first byte that
+ *                          won't be read is in[in_size].
+ * \param       out         Beginning of the output buffer
+ * \param       out_pos     The next byte will be written to out[*out_pos].
+ *                          *out_pos is updated only if encoding succeeds.
+ * \param       out_size    Size of the out buffer; the first byte into
+ *                          which no data is written to is out[out_size].
+ *
+ * \return      - LZMA_OK: Decoding was successful.
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_DATA_ERROR
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_BUF_ERROR: Output buffer was too small.
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_block_buffer_decode(
+		lzma_block *block, lzma_allocator *allocator,
+		const uint8_t *in, size_t *in_pos, size_t in_size,
+		uint8_t *out, size_t *out_pos, size_t out_size)
+		lzma_nothrow;
diff --git a/src/liblzma/api/lzma/check.h b/src/liblzma/api/lzma/check.h
new file mode 100644
index 0000000..6a243db
--- /dev/null
+++ b/src/liblzma/api/lzma/check.h
@@ -0,0 +1,150 @@
+/**
+ * \file        lzma/check.h
+ * \brief       Integrity checks
+ */
+
+/*
+ * 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       Type of the integrity check (Check ID)
+ *
+ * The .xz format supports multiple types of checks that are calculated
+ * from the uncompressed data. They vary in both speed and ability to
+ * detect errors.
+ */
+typedef enum {
+	LZMA_CHECK_NONE     = 0,
+		/**<
+		 * No Check is calculated.
+		 *
+		 * Size of the Check field: 0 bytes
+		 */
+
+	LZMA_CHECK_CRC32    = 1,
+		/**<
+		 * CRC32 using the polynomial from the IEEE 802.3 standard
+		 *
+		 * Size of the Check field: 4 bytes
+		 */
+
+	LZMA_CHECK_CRC64    = 4,
+		/**<
+		 * CRC64 using the polynomial from the ECMA-182 standard
+		 *
+		 * Size of the Check field: 8 bytes
+		 */
+
+	LZMA_CHECK_SHA256   = 10
+		/**<
+		 * SHA-256
+		 *
+		 * Size of the Check field: 32 bytes
+		 */
+} lzma_check;
+
+
+/**
+ * \brief       Maximum valid Check ID
+ *
+ * The .xz file format specification specifies 16 Check IDs (0-15). Some
+ * of them are only reserved, that is, no actual Check algorithm has been
+ * assigned. When decoding, liblzma still accepts unknown Check IDs for
+ * future compatibility. If a valid but unsupported Check ID is detected,
+ * liblzma can indicate a warning; see the flags LZMA_TELL_NO_CHECK,
+ * LZMA_TELL_UNSUPPORTED_CHECK, and LZMA_TELL_ANY_CHECK in container.h.
+ */
+#define LZMA_CHECK_ID_MAX 15
+
+
+/**
+ * \brief       Test if the given Check ID is supported
+ *
+ * Return true if the given Check ID is supported by this liblzma build.
+ * Otherwise false is returned. It is safe to call this with a value that
+ * is not in the range [0, 15]; in that case the return value is always false.
+ *
+ * You can assume that LZMA_CHECK_NONE and LZMA_CHECK_CRC32 are always
+ * supported (even if liblzma is built with limited features).
+ */
+extern LZMA_API(lzma_bool) lzma_check_is_supported(lzma_check check)
+		lzma_nothrow lzma_attr_const;
+
+
+/**
+ * \brief       Get the size of the Check field with the given Check ID
+ *
+ * Although not all Check IDs have a check algorithm associated, the size of
+ * every Check is already frozen. This function returns the size (in bytes) of
+ * the Check field with the specified Check ID. The values are:
+ * { 0, 4, 4, 4, 8, 8, 8, 16, 16, 16, 32, 32, 32, 64, 64, 64 }
+ *
+ * If the argument is not in the range [0, 15], UINT32_MAX is returned.
+ */
+extern LZMA_API(uint32_t) lzma_check_size(lzma_check check)
+		lzma_nothrow lzma_attr_const;
+
+
+/**
+ * \brief       Maximum size of a Check field
+ */
+#define LZMA_CHECK_SIZE_MAX 64
+
+
+/**
+ * \brief       Calculate CRC32
+ *
+ * Calculate CRC32 using the polynomial from the IEEE 802.3 standard.
+ *
+ * \param       buf     Pointer to the input buffer
+ * \param       size    Size of the input buffer
+ * \param       crc     Previously returned CRC value. This is used to
+ *                      calculate the CRC of a big buffer in smaller chunks.
+ *                      Set to zero when starting a new calculation.
+ *
+ * \return      Updated CRC value, which can be passed to this function
+ *              again to continue CRC calculation.
+ */
+extern LZMA_API(uint32_t) lzma_crc32(
+		const uint8_t *buf, size_t size, uint32_t crc)
+		lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Calculate CRC64
+ *
+ * Calculate CRC64 using the polynomial from the ECMA-182 standard.
+ *
+ * This function is used similarly to lzma_crc32(). See its documentation.
+ */
+extern LZMA_API(uint64_t) lzma_crc64(
+		const uint8_t *buf, size_t size, uint64_t crc)
+		lzma_nothrow lzma_attr_pure;
+
+
+/*
+ * SHA-256 functions are currently not exported to public API.
+ * Contact Lasse Collin if you think it should be.
+ */
+
+
+/**
+ * \brief       Get the type of the integrity check
+ *
+ * This function can be called only immediately after lzma_code() has
+ * returned LZMA_NO_CHECK, LZMA_UNSUPPORTED_CHECK, or LZMA_GET_CHECK.
+ * Calling this function in any other situation has undefined behavior.
+ */
+extern LZMA_API(lzma_check) lzma_get_check(const lzma_stream *strm)
+		lzma_nothrow;
diff --git a/src/liblzma/api/lzma/container.h b/src/liblzma/api/lzma/container.h
new file mode 100644
index 0000000..0d90765
--- /dev/null
+++ b/src/liblzma/api/lzma/container.h
@@ -0,0 +1,404 @@
+/**
+ * \file        lzma/container.h
+ * \brief       File formats
+ */
+
+/*
+ * 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
+
+
+/************
+ * Encoding *
+ ************/
+
+/**
+ * \brief       Default compression preset
+ *
+ * It's not straightforward to recommend a default preset, because in some
+ * cases keeping the resource usage relatively low is more important that
+ * getting the maximum compression ratio.
+ */
+#define LZMA_PRESET_DEFAULT     UINT32_C(6)
+
+
+/**
+ * \brief       Mask for preset level
+ *
+ * This is useful only if you need to extract the level from the preset
+ * variable. That should be rare.
+ */
+#define LZMA_PRESET_LEVEL_MASK  UINT32_C(0x1F)
+
+
+/*
+ * Preset flags
+ *
+ * Currently only one flag is defined.
+ */
+
+/**
+ * \brief       Extreme compression preset
+ *
+ * This flag modifies the preset to make the encoding significantly slower
+ * while improving the compression ratio only marginally. This is useful
+ * when you don't mind wasting time to get as small result as possible.
+ *
+ * This flag doesn't affect the memory usage requirements of the decoder (at
+ * least not significantly). The memory usage of the encoder may be increased
+ * a little but only at the lowest preset levels (0-2).
+ */
+#define LZMA_PRESET_EXTREME       (UINT32_C(1) << 31)
+
+
+/**
+ * \brief       Calculate rough memory usage of easy encoder
+ *
+ * This function is a wrapper for lzma_raw_encoder_memusage().
+ *
+ * \param       preset  Compression preset (level and possible flags)
+ */
+extern LZMA_API(uint64_t) lzma_easy_encoder_memusage(uint32_t preset)
+		lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Calculate rough decoder memory usage of a preset
+ *
+ * This function is a wrapper for lzma_raw_decoder_memusage().
+ *
+ * \param       preset  Compression preset (level and possible flags)
+ */
+extern LZMA_API(uint64_t) lzma_easy_decoder_memusage(uint32_t preset)
+		lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Initialize .xz Stream encoder using a preset number
+ *
+ * This function is intended for those who just want to use the basic features
+ * if liblzma (that is, most developers out there).
+ *
+ * \param       strm    Pointer to lzma_stream that is at least initialized
+ *                      with LZMA_STREAM_INIT.
+ * \param       preset  Compression preset to use. A preset consist of level
+ *                      number and zero or more flags. Usually flags aren't
+ *                      used, so preset is simply a number [0, 9] which match
+ *                      the options -0 .. -9 of the xz command line tool.
+ *                      Additional flags can be be set using bitwise-or with
+ *                      the preset level number, e.g. 6 | LZMA_PRESET_EXTREME.
+ * \param       check   Integrity check type to use. See check.h for available
+ *                      checks. If you are unsure, use LZMA_CHECK_CRC32.
+ *
+ * \return      - LZMA_OK: Initialization succeeded. Use lzma_code() to
+ *                encode your data.
+ *              - LZMA_MEM_ERROR: Memory allocation failed.
+ *              - LZMA_OPTIONS_ERROR: The given compression level is not
+ *                supported by this build of liblzma.
+ *              - LZMA_UNSUPPORTED_CHECK: The given check type is not
+ *                supported by this liblzma build.
+ *              - LZMA_PROG_ERROR: One or more of the parameters have values
+ *                that will never be valid. For example, strm == NULL.
+ *
+ * If initialization fails (return value is not LZMA_OK), all the memory
+ * allocated for *strm by liblzma is always freed. Thus, there is no need
+ * to call lzma_end() after failed initialization.
+ *
+ * If initialization succeeds, use lzma_code() to do the actual encoding.
+ * Valid values for `action' (the second argument of lzma_code()) are
+ * LZMA_RUN, LZMA_SYNC_FLUSH, LZMA_FULL_FLUSH, and LZMA_FINISH. In future,
+ * there may be compression levels or flags that don't support LZMA_SYNC_FLUSH.
+ */
+extern LZMA_API(lzma_ret) lzma_easy_encoder(
+		lzma_stream *strm, uint32_t preset, lzma_check check)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Single-call .xz Stream encoding using a preset number
+ *
+ * The maximum required output buffer size can be calculated with
+ * lzma_stream_buffer_bound().
+ *
+ * \param       preset      Compression preset to use. See the description
+ *                          in lzma_easy_encoder().
+ * \param       check       Type of the integrity check to calculate from
+ *                          uncompressed data.
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
+ * \param       in          Beginning of the input buffer
+ * \param       in_size     Size of the input buffer
+ * \param       out         Beginning of the output buffer
+ * \param       out_pos     The next byte will be written to out[*out_pos].
+ *                          *out_pos is updated only if encoding succeeds.
+ * \param       out_size    Size of the out buffer; the first byte into
+ *                          which no data is written to is out[out_size].
+ *
+ * \return      - LZMA_OK: Encoding was successful.
+ *              - LZMA_BUF_ERROR: Not enough output buffer space.
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_DATA_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_easy_buffer_encode(
+		uint32_t preset, lzma_check check,
+		lzma_allocator *allocator, const uint8_t *in, size_t in_size,
+		uint8_t *out, size_t *out_pos, size_t out_size) lzma_nothrow;
+
+
+/**
+ * \brief       Initialize .xz Stream encoder using a custom filter chain
+ *
+ * \param       strm    Pointer to properly prepared lzma_stream
+ * \param       filters Array of filters. This must be terminated with
+ *                      filters[n].id = LZMA_VLI_UNKNOWN. See filter.h for
+ *                      more information.
+ * \param       check   Type of the integrity check to calculate from
+ *                      uncompressed data.
+ *
+ * \return      - LZMA_OK: Initialization was successful.
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_stream_encoder(lzma_stream *strm,
+		const lzma_filter *filters, lzma_check check)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Initialize .lzma encoder (legacy file format)
+ *
+ * The .lzma format is sometimes called the LZMA_Alone format, which is the
+ * reason for the name of this function. The .lzma format supports only the
+ * LZMA1 filter. There is no support for integrity checks like CRC32.
+ *
+ * Use this function if and only if you need to create files readable by
+ * legacy LZMA tools such as LZMA Utils 4.32.x. Moving to the .xz format
+ * is strongly recommended.
+ *
+ * The valid action values for lzma_code() are LZMA_RUN and LZMA_FINISH.
+ * No kind of flushing is supported, because the file format doesn't make
+ * it possible.
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_alone_encoder(
+		lzma_stream *strm, const lzma_options_lzma *options)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Calculate output buffer size for single-call Stream encoder
+ *
+ * When trying to compress uncompressible data, the encoded size will be
+ * slightly bigger than the input data. This function calculates how much
+ * output buffer space is required to be sure that lzma_stream_buffer_encode()
+ * doesn't return LZMA_BUF_ERROR.
+ *
+ * The calculated value is not exact, but it is guaranteed to be big enough.
+ * The actual maximum output space required may be slightly smaller (up to
+ * about 100 bytes). This should not be a problem in practice.
+ *
+ * If the calculated maximum size doesn't fit into size_t or would make the
+ * Stream grow past LZMA_VLI_MAX (which should never happen in practice),
+ * zero is returned to indicate the error.
+ *
+ * \note        The limit calculated by this function applies only to
+ *              single-call encoding. Multi-call encoding may (and probably
+ *              will) have larger maximum expansion when encoding
+ *              uncompressible data. Currently there is no function to
+ *              calculate the maximum expansion of multi-call encoding.
+ */
+extern LZMA_API(size_t) lzma_stream_buffer_bound(size_t uncompressed_size)
+		lzma_nothrow;
+
+
+/**
+ * \brief       Single-call .xz Stream encoder
+ *
+ * \param       filters     Array of filters. This must be terminated with
+ *                          filters[n].id = LZMA_VLI_UNKNOWN. See filter.h
+ *                          for more information.
+ * \param       check       Type of the integrity check to calculate from
+ *                          uncompressed data.
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
+ * \param       in          Beginning of the input buffer
+ * \param       in_size     Size of the input buffer
+ * \param       out         Beginning of the output buffer
+ * \param       out_pos     The next byte will be written to out[*out_pos].
+ *                          *out_pos is updated only if encoding succeeds.
+ * \param       out_size    Size of the out buffer; the first byte into
+ *                          which no data is written to is out[out_size].
+ *
+ * \return      - LZMA_OK: Encoding was successful.
+ *              - LZMA_BUF_ERROR: Not enough output buffer space.
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_DATA_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_stream_buffer_encode(
+		lzma_filter *filters, lzma_check check,
+		lzma_allocator *allocator, const uint8_t *in, size_t in_size,
+		uint8_t *out, size_t *out_pos, size_t out_size)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/************
+ * Decoding *
+ ************/
+
+/**
+ * This flag makes lzma_code() return LZMA_NO_CHECK if the input stream
+ * being decoded has no integrity check. Note that when used with
+ * lzma_auto_decoder(), all .lzma files will trigger LZMA_NO_CHECK
+ * if LZMA_TELL_NO_CHECK is used.
+ */
+#define LZMA_TELL_NO_CHECK              UINT32_C(0x01)
+
+
+/**
+ * This flag makes lzma_code() return LZMA_UNSUPPORTED_CHECK if the input
+ * stream has an integrity check, but the type of the integrity check is not
+ * supported by this liblzma version or build. Such files can still be
+ * decoded, but the integrity check cannot be verified.
+ */
+#define LZMA_TELL_UNSUPPORTED_CHECK     UINT32_C(0x02)
+
+
+/**
+ * This flag makes lzma_code() return LZMA_GET_CHECK as soon as the type
+ * of the integrity check is known. The type can then be got with
+ * lzma_get_check().
+ */
+#define LZMA_TELL_ANY_CHECK             UINT32_C(0x04)
+
+
+/**
+ * This flag enables decoding of concatenated files with file formats that
+ * allow concatenating compressed files as is. From the formats currently
+ * supported by liblzma, only the .xz format allows concatenated files.
+ * Concatenated files are not allowed with the legacy .lzma format.
+ *
+ * This flag also affects the usage of the `action' argument for lzma_code().
+ * When LZMA_CONCATENATED is used, lzma_code() won't return LZMA_STREAM_END
+ * unless LZMA_FINISH is used as `action'. Thus, the application has to set
+ * LZMA_FINISH in the same way as it does when encoding.
+ *
+ * If LZMA_CONCATENATED is not used, the decoders still accept LZMA_FINISH
+ * as `action' for lzma_code(), but the usage of LZMA_FINISH isn't required.
+ */
+#define LZMA_CONCATENATED               UINT32_C(0x08)
+
+
+/**
+ * \brief       Initialize .xz Stream decoder
+ *
+ * \param       strm        Pointer to properly prepared lzma_stream
+ * \param       memlimit    Rough memory usage limit as bytes
+ * \param       flags       Bitwise-or of zero or more of the decoder flags:
+ *                          LZMA_TELL_NO_CHECK, LZMA_TELL_UNSUPPORTED_CHECK,
+ *                          LZMA_TELL_ANY_CHECK, LZMA_CONCATENATED
+ *
+ * \return      - LZMA_OK: Initialization was successful.
+ *              - LZMA_MEM_ERROR: Cannot allocate memory.
+ *              - LZMA_OPTIONS_ERROR: Unsupported flags
+ */
+extern LZMA_API(lzma_ret) lzma_stream_decoder(
+		lzma_stream *strm, uint64_t memlimit, uint32_t flags)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Decode .xz Streams and .lzma files with autodetection
+ *
+ * This decoder autodetects between the .xz and .lzma file formats, and
+ * calls lzma_stream_decoder() or lzma_alone_decoder() once the type
+ * of the input file has been detected.
+ *
+ * \param       strm        Pointer to properly prepared lzma_stream
+ * \param       memlimit    Rough memory usage limit as bytes
+ * \param       flags       Bitwise-or of flags, or zero for no flags.
+ *
+ * \return      - LZMA_OK: Initialization was successful.
+ *              - LZMA_MEM_ERROR: Cannot allocate memory.
+ *              - LZMA_OPTIONS_ERROR: Unsupported flags
+ */
+extern LZMA_API(lzma_ret) lzma_auto_decoder(
+		lzma_stream *strm, uint64_t memlimit, uint32_t flags)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Initialize .lzma decoder (legacy file format)
+ *
+ * Valid `action' arguments to lzma_code() are LZMA_RUN and LZMA_FINISH.
+ * There is no need to use LZMA_FINISH, but allowing it may simplify
+ * certain types of applications.
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_MEM_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_alone_decoder(
+		lzma_stream *strm, uint64_t memlimit)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Single-call .xz Stream decoder
+ *
+ * \param       memlimit    Pointer to how much memory the decoder is allowed
+ *                          to allocate. The value pointed by this pointer is
+ *                          modified if and only if LZMA_MEMLIMIT_ERROR is
+ *                          returned.
+ * \param       flags       Bitwise-or of zero or more of the decoder flags:
+ *                          LZMA_TELL_NO_CHECK, LZMA_TELL_UNSUPPORTED_CHECK,
+ *                          LZMA_CONCATENATED. Note that LZMA_TELL_ANY_CHECK
+ *                          is not allowed and will return LZMA_PROG_ERROR.
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
+ * \param       in          Beginning of the input buffer
+ * \param       in_pos      The next byte will be read from in[*in_pos].
+ *                          *in_pos is updated only if decoding succeeds.
+ * \param       in_size     Size of the input buffer; the first byte that
+ *                          won't be read is in[in_size].
+ * \param       out         Beginning of the output buffer
+ * \param       out_pos     The next byte will be written to out[*out_pos].
+ *                          *out_pos is updated only if encoding succeeds.
+ * \param       out_size    Size of the out buffer; the first byte into
+ *                          which no data is written to is out[out_size].
+ *
+ * \return      - LZMA_OK: Decoding was successful.
+ *              - LZMA_FORMAT_ERROR
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_DATA_ERROR
+ *              - LZMA_NO_CHECK: This can be returned only if using
+ *                the LZMA_TELL_NO_CHECK flag.
+ *              - LZMA_UNSUPPORTED_CHECK: This can be returned only if using
+ *                the LZMA_TELL_UNSUPPORTED_CHECK flag.
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_MEMLIMIT_ERROR: Memory usage limit was reached.
+ *                The minimum required memlimit value was stored to *memlimit.
+ *              - LZMA_BUF_ERROR: Output buffer was too small.
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_stream_buffer_decode(
+		uint64_t *memlimit, uint32_t flags, lzma_allocator *allocator,
+		const uint8_t *in, size_t *in_pos, size_t in_size,
+		uint8_t *out, size_t *out_pos, size_t out_size)
+		lzma_nothrow lzma_attr_warn_unused_result;
diff --git a/src/liblzma/api/lzma/delta.h b/src/liblzma/api/lzma/delta.h
new file mode 100644
index 0000000..592fc4f
--- /dev/null
+++ b/src/liblzma/api/lzma/delta.h
@@ -0,0 +1,77 @@
+/**
+ * \file        lzma/delta.h
+ * \brief       Delta 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 Delta filter. This is used as lzma_filter.id.
+ */
+#define LZMA_FILTER_DELTA       LZMA_VLI_C(0x03)
+
+
+/**
+ * \brief       Type of the delta calculation
+ *
+ * Currently only byte-wise delta is supported. Other possible types could
+ * be, for example, delta of 16/32/64-bit little/big endian integers, but
+ * these are not currently planned since byte-wise delta is almost as good.
+ */
+typedef enum {
+	LZMA_DELTA_TYPE_BYTE
+} lzma_delta_type;
+
+
+/**
+ * \brief       Options for the Delta filter
+ *
+ * These options are needed by both encoder and decoder.
+ */
+typedef struct {
+	/** For now, this must always be LZMA_DELTA_TYPE_BYTE. */
+	lzma_delta_type type;
+
+	/**
+	 * \brief       Delta distance
+	 *
+	 * With the only currently supported type, LZMA_DELTA_TYPE_BYTE,
+	 * the distance is as bytes.
+	 *
+	 * Examples:
+	 *  - 16-bit stereo audio: distance = 4 bytes
+	 *  - 24-bit RGB image data: distance = 3 bytes
+	 */
+	uint32_t dist;
+#	define LZMA_DELTA_DIST_MIN 1
+#	define LZMA_DELTA_DIST_MAX 256
+
+	/*
+	 * Reserved space to allow possible future extensions without
+	 * breaking the ABI. You should not touch these, because the names
+	 * of these variables may change. These are and will never be used
+	 * when type is LZMA_DELTA_TYPE_BYTE, so it is safe to leave these
+	 * uninitialized.
+	 */
+	uint32_t reserved_int1;
+	uint32_t reserved_int2;
+	uint32_t reserved_int3;
+	uint32_t reserved_int4;
+	void *reserved_ptr1;
+	void *reserved_ptr2;
+
+} lzma_options_delta;
diff --git a/src/liblzma/api/lzma/filter.h b/src/liblzma/api/lzma/filter.h
new file mode 100644
index 0000000..038a933
--- /dev/null
+++ b/src/liblzma/api/lzma/filter.h
@@ -0,0 +1,421 @@
+/**
+ * \file        lzma/filter.h
+ * \brief       Common filter related types
+ */
+
+/*
+ * 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       Maximum number of filters in a chain
+ *
+ * A filter chain can have 1-4 filters, of which three are allowed to change
+ * the size of the data. Usually only one or two filters are needed.
+ */
+#define LZMA_FILTERS_MAX 4
+
+
+/**
+ * \brief       Filter options
+ *
+ * This structure is used to pass Filter ID and a pointer filter's
+ * options to liblzma. A few functions work with a single lzma_filter
+ * structure, while most functions expect a filter chain.
+ *
+ * A filter chain is indicated with an array of lzma_filter structures.
+ * The array is terminated with .id = LZMA_VLI_UNKNOWN. Thus, the filter
+ * array must have LZMA_FILTERS_MAX + 1 elements (that is, five) to
+ * be able to hold any arbitrary filter chain. This is important when
+ * using lzma_block_header_decode() from block.h, because too small
+ * array would make liblzma write past the end of the filters array.
+ */
+typedef struct {
+	/**
+	 * \brief       Filter ID
+	 *
+	 * Use constants whose name begin with `LZMA_FILTER_' to specify
+	 * different filters. In an array of lzma_filter structures, use
+	 * LZMA_VLI_UNKNOWN to indicate end of filters.
+	 *
+	 * \note        This is not an enum, because on some systems enums
+	 *              cannot be 64-bit.
+	 */
+	lzma_vli id;
+
+	/**
+	 * \brief       Pointer to filter-specific options structure
+	 *
+	 * If the filter doesn't need options, set this to NULL. If id is
+	 * set to LZMA_VLI_UNKNOWN, options is ignored, and thus
+	 * doesn't need be initialized.
+	 *
+	 * Some filters support changing the options in the middle of
+	 * the encoding process. These filters store the pointer of the
+	 * options structure and communicate with the application via
+	 * modifications of the options structure.
+	 */
+	void *options;
+
+} lzma_filter;
+
+
+/**
+ * \brief       Test if the given Filter ID is supported for encoding
+ *
+ * Return true if the give Filter ID is supported for encoding by this
+ * liblzma build. Otherwise false is returned.
+ *
+ * There is no way to list which filters are available in this particular
+ * liblzma version and build. It would be useless, because the application
+ * couldn't know what kind of options the filter would need.
+ */
+extern LZMA_API(lzma_bool) lzma_filter_encoder_is_supported(lzma_vli id)
+		lzma_nothrow lzma_attr_const;
+
+
+/**
+ * \brief       Test if the given Filter ID is supported for decoding
+ *
+ * Return true if the give Filter ID is supported for decoding by this
+ * liblzma build. Otherwise false is returned.
+ */
+extern LZMA_API(lzma_bool) lzma_filter_decoder_is_supported(lzma_vli id)
+		lzma_nothrow lzma_attr_const;
+
+
+/**
+ * \brief       Copy the filters array
+ *
+ * Copy the Filter IDs and filter-specific options from src to dest.
+ * Up to LZMA_FILTERS_MAX filters are copied, plus the terminating
+ * .id == LZMA_VLI_UNKNOWN. Thus, dest should have at least
+ * LZMA_FILTERS_MAX + 1 elements space unless the caller knows that
+ * src is smaller than that.
+ *
+ * Unless the filter-specific options is NULL, the Filter ID has to be
+ * supported by liblzma, because liblzma needs to know the size of every
+ * filter-specific options structure. The filter-specific options are not
+ * validated. If options is NULL, any unsupported Filter IDs are copied
+ * without returning an error.
+ *
+ * Old filter-specific options in dest are not freed, so dest doesn't
+ * need to be initialized by the caller in any way.
+ *
+ * If an error occurs, memory possibly already allocated by this function
+ * is always freed.
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_OPTIONS_ERROR: Unsupported Filter ID and its options
+ *                is not NULL.
+ *              - LZMA_PROG_ERROR: src or dest is NULL.
+ */
+extern LZMA_API(lzma_ret) lzma_filters_copy(const lzma_filter *src,
+		lzma_filter *dest, lzma_allocator *allocator) lzma_nothrow;
+
+
+/**
+ * \brief       Calculate rough memory requirements for raw encoder
+ *
+ * Because the calculation is rough, this function can be used to calculate
+ * the memory requirements for Block and Stream encoders too.
+ *
+ * \param       filters     Array of filters terminated with
+ *                          .id == LZMA_VLI_UNKNOWN.
+ *
+ * \return      Rough number of bytes of memory required for the given
+ *              filter chain when encoding.
+ */
+extern LZMA_API(uint64_t) lzma_raw_encoder_memusage(const lzma_filter *filters)
+		lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Calculate rough memory requirements for raw decoder
+ *
+ * Because the calculation is rough, this function can be used to calculate
+ * the memory requirements for Block and Stream decoders too.
+ *
+ * \param       filters     Array of filters terminated with
+ *                          .id == LZMA_VLI_UNKNOWN.
+ *
+ * \return      Rough number of bytes of memory required for the given
+ *              filter chain when decoding.
+ */
+extern LZMA_API(uint64_t) lzma_raw_decoder_memusage(const lzma_filter *filters)
+		lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Initialize raw encoder
+ *
+ * This function may be useful when implementing custom file formats.
+ *
+ * \param       strm    Pointer to properly prepared lzma_stream
+ * \param       filters Array of lzma_filter structures. The end of the
+ *                      array must be marked with .id = LZMA_VLI_UNKNOWN.
+ *
+ * The `action' with lzma_code() can be LZMA_RUN, LZMA_SYNC_FLUSH (if the
+ * filter chain supports it), or LZMA_FINISH.
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_raw_encoder(
+		lzma_stream *strm, const lzma_filter *filters)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Initialize raw decoder
+ *
+ * The initialization of raw decoder goes similarly to raw encoder.
+ *
+ * The `action' with lzma_code() can be LZMA_RUN or LZMA_FINISH. Using
+ * LZMA_FINISH is not required, it is supported just for convenience.
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_raw_decoder(
+		lzma_stream *strm, const lzma_filter *filters)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Update the filter chain in the encoder
+ *
+ * This function is for advanced users only. This function has two slightly
+ * different purposes:
+ *
+ *  - After LZMA_FULL_FLUSH when using Stream encoder: Set a new filter
+ *    chain, which will be used starting from the next Block.
+ *
+ *  - After LZMA_SYNC_FLUSH using Raw, Block, or Stream encoder: Change
+ *    the filter-specific options in the middle of encoding. The actual
+ *    filters in the chain (Filter IDs) cannot be changed. In the future,
+ *    it might become possible to change the filter options without
+ *    using LZMA_SYNC_FLUSH.
+ *
+ * While rarely useful, this function may be called also when no data has
+ * been compressed yet. In that case, this function will behave as if
+ * LZMA_FULL_FLUSH (Stream encoder) or LZMA_SYNC_FLUSH (Raw or Block
+ * encoder) had been used right before calling this function.
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_MEMLIMIT_ERROR
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_filters_update(
+		lzma_stream *strm, const lzma_filter *filters) lzma_nothrow;
+
+
+/**
+ * \brief       Single-call raw encoder
+ *
+ * \param       filters     Array of lzma_filter structures. The end of the
+ *                          array must be marked with .id = LZMA_VLI_UNKNOWN.
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
+ * \param       in          Beginning of the input buffer
+ * \param       in_size     Size of the input buffer
+ * \param       out         Beginning of the output buffer
+ * \param       out_pos     The next byte will be written to out[*out_pos].
+ *                          *out_pos is updated only if encoding succeeds.
+ * \param       out_size    Size of the out buffer; the first byte into
+ *                          which no data is written to is out[out_size].
+ *
+ * \return      - LZMA_OK: Encoding was successful.
+ *              - LZMA_BUF_ERROR: Not enough output buffer space.
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_DATA_ERROR
+ *              - LZMA_PROG_ERROR
+ *
+ * \note        There is no function to calculate how big output buffer
+ *              would surely be big enough. (lzma_stream_buffer_bound()
+ *              works only for lzma_stream_buffer_encode().)
+ */
+extern LZMA_API(lzma_ret) lzma_raw_buffer_encode(
+		const lzma_filter *filters, lzma_allocator *allocator,
+		const uint8_t *in, size_t in_size, uint8_t *out,
+		size_t *out_pos, size_t out_size) lzma_nothrow;
+
+
+/**
+ * \brief       Single-call raw decoder
+ *
+ * \param       filters     Array of lzma_filter structures. The end of the
+ *                          array must be marked with .id = LZMA_VLI_UNKNOWN.
+ * \param       allocator   lzma_allocator for custom allocator functions.
+ *                          Set to NULL to use malloc() and free().
+ * \param       in          Beginning of the input buffer
+ * \param       in_pos      The next byte will be read from in[*in_pos].
+ *                          *in_pos is updated only if decoding succeeds.
+ * \param       in_size     Size of the input buffer; the first byte that
+ *                          won't be read is in[in_size].
+ * \param       out         Beginning of the output buffer
+ * \param       out_pos     The next byte will be written to out[*out_pos].
+ *                          *out_pos is updated only if encoding succeeds.
+ * \param       out_size    Size of the out buffer; the first byte into
+ *                          which no data is written to is out[out_size].
+ */
+extern LZMA_API(lzma_ret) lzma_raw_buffer_decode(
+		const lzma_filter *filters, lzma_allocator *allocator,
+		const uint8_t *in, size_t *in_pos, size_t in_size,
+		uint8_t *out, size_t *out_pos, size_t out_size) lzma_nothrow;
+
+
+/**
+ * \brief       Get the size of the Filter Properties field
+ *
+ * This function may be useful when implementing custom file formats
+ * using the raw encoder and decoder.
+ *
+ * \param       size    Pointer to uint32_t to hold the size of the properties
+ * \param       filter  Filter ID and options (the size of the properties may
+ *                      vary depending on the options)
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_PROG_ERROR
+ *
+ * \note        This function validates the Filter ID, but does not
+ *              necessarily validate the options. Thus, it is possible
+ *              that this returns LZMA_OK while the following call to
+ *              lzma_properties_encode() returns LZMA_OPTIONS_ERROR.
+ */
+extern LZMA_API(lzma_ret) lzma_properties_size(
+		uint32_t *size, const lzma_filter *filter) lzma_nothrow;
+
+
+/**
+ * \brief       Encode the Filter Properties field
+ *
+ * \param       filter  Filter ID and options
+ * \param       props   Buffer to hold the encoded options. The size of
+ *                      buffer must have been already determined with
+ *                      lzma_properties_size().
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_PROG_ERROR
+ *
+ * \note        Even this function won't validate more options than actually
+ *              necessary. Thus, it is possible that encoding the properties
+ *              succeeds but using the same options to initialize the encoder
+ *              will fail.
+ *
+ * \note        It is OK to skip calling this function if
+ *              lzma_properties_size() indicated that the size
+ *              of the Filter Properties field is zero.
+ */
+extern LZMA_API(lzma_ret) lzma_properties_encode(
+		const lzma_filter *filter, uint8_t *props) lzma_nothrow;
+
+
+/**
+ * \brief       Decode the Filter Properties field
+ *
+ * \param       filter      filter->id must have been set to the correct
+ *                          Filter ID. filter->options doesn't need to be
+ *                          initialized (it's not freed by this function). The
+ *                          decoded options will be stored to filter->options.
+ *                          filter->options is set to NULL if there are no
+ *                          properties or if an error occurs.
+ * \param       allocator   Custom memory allocator used to allocate the
+ *                          options. Set to NULL to use the default malloc(),
+ *                          and in case of an error, also free().
+ * \param       props       Input buffer containing the properties.
+ * \param       props_size  Size of the properties. This must be the exact
+ *                          size; giving too much or too little input will
+ *                          return LZMA_OPTIONS_ERROR.
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_MEM_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_properties_decode(
+		lzma_filter *filter, lzma_allocator *allocator,
+		const uint8_t *props, size_t props_size) lzma_nothrow;
+
+
+/**
+ * \brief       Calculate encoded size of a Filter Flags field
+ *
+ * Knowing the size of Filter Flags is useful to know when allocating
+ * memory to hold the encoded Filter Flags.
+ *
+ * \param       size    Pointer to integer to hold the calculated size
+ * \param       filters Filter ID and associated options whose encoded
+ *                      size is to be calculated
+ *
+ * \return      - LZMA_OK: *size set successfully. Note that this doesn't
+ *                guarantee that filters->options is valid, thus
+ *                lzma_filter_flags_encode() may still fail.
+ *              - LZMA_OPTIONS_ERROR: Unknown Filter ID or unsupported options.
+ *              - LZMA_PROG_ERROR: Invalid options
+ *
+ * \note        If you need to calculate size of List of Filter Flags,
+ *              you need to loop over every lzma_filter entry.
+ */
+extern LZMA_API(lzma_ret) lzma_filter_flags_size(
+		uint32_t *size, const lzma_filter *filters)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Encode Filter Flags into given buffer
+ *
+ * In contrast to some functions, this doesn't allocate the needed buffer.
+ * This is due to how this function is used internally by liblzma.
+ *
+ * \param       filters     Filter ID and options to be encoded
+ * \param       out         Beginning of the output buffer
+ * \param       out_pos     out[*out_pos] is the next write position. This
+ *                          is updated by the encoder.
+ * \param       out_size    out[out_size] is the first byte to not write.
+ *
+ * \return      - LZMA_OK: Encoding was successful.
+ *              - LZMA_OPTIONS_ERROR: Invalid or unsupported options.
+ *              - LZMA_PROG_ERROR: Invalid options or not enough output
+ *                buffer space (you should have checked it with
+ *                lzma_filter_flags_size()).
+ */
+extern LZMA_API(lzma_ret) lzma_filter_flags_encode(const lzma_filter *filters,
+		uint8_t *out, size_t *out_pos, size_t out_size)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Decode Filter Flags from given buffer
+ *
+ * The decoded result is stored into *filters. filters->options is
+ * initialized but the old value is NOT free()d.
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_OPTIONS_ERROR
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_filter_flags_decode(
+		lzma_filter *filters, lzma_allocator *allocator,
+		const uint8_t *in, size_t *in_pos, size_t in_size)
+		lzma_nothrow lzma_attr_warn_unused_result;
diff --git a/src/liblzma/api/lzma/hardware.h b/src/liblzma/api/lzma/hardware.h
new file mode 100644
index 0000000..f44cb60
--- /dev/null
+++ b/src/liblzma/api/lzma/hardware.h
@@ -0,0 +1,51 @@
+/**
+ * \file        lzma/hardware.h
+ * \brief       Hardware information
+ *
+ * Since liblzma can consume a lot of system resources, it also provides
+ * ways to limit the resource usage. Applications linking against liblzma
+ * need to do the actual decisions how much resources to let liblzma to use.
+ * To ease making these decisions, liblzma provides functions to find out
+ * the relevant capabilities of the underlaying hardware. Currently there
+ * is only a function to find out the amount of RAM, but in the future there
+ * will be also a function to detect how many concurrent threads the system
+ * can run.
+ *
+ * \note        On some operating systems, these function may temporarily
+ *              load a shared library or open file descriptor(s) to find out
+ *              the requested hardware information. Unless the application
+ *              assumes that specific file descriptors are not touched by
+ *              other threads, this should have no effect on thread safety.
+ *              Possible operations involving file descriptors will restart
+ *              the syscalls if they return EINTR.
+ */
+
+/*
+ * 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       Get the total amount of physical memory (RAM) in bytes
+ *
+ * This function may be useful when determining a reasonable memory
+ * usage limit for decompressing or how much memory it is OK to use
+ * for compressing. For example, the default limit used by the xz
+ * command line tool is 40 % of RAM.
+ *
+ * \return      On success, the total amount of physical memory in bytes
+ *              is returned. If the amount of RAM cannot be determined,
+ *              zero is returned. This can happen if an error occurs
+ *              or if there is no code in liblzma to detect the amount
+ *              of RAM on the specific operating system.
+ */
+extern LZMA_API(uint64_t) lzma_physmem(void) lzma_nothrow;
diff --git a/src/liblzma/api/lzma/index.h b/src/liblzma/api/lzma/index.h
new file mode 100644
index 0000000..5ea12e3
--- /dev/null
+++ b/src/liblzma/api/lzma/index.h
@@ -0,0 +1,676 @@
+/**
+ * \file        lzma/index.h
+ * \brief       Handling of .xz Index and related information
+ */
+
+/*
+ * 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       Opaque data type to hold the Index(es) and other information
+ *
+ * lzma_index often holds just one .xz Index and possibly the Stream Flags
+ * of the same Stream and size of the Stream Padding field. However,
+ * multiple lzma_indexes can be concatenated with lzma_index_cat() and then
+ * there may be information about multiple Streams in the same lzma_index.
+ *
+ * Notes about thread safety: Only one thread may modify lzma_index at
+ * a time. All functions that take non-const pointer to lzma_index
+ * modify it. As long as no thread is modifying the lzma_index, getting
+ * information from the same lzma_index can be done from multiple threads
+ * at the same time with functions that take a const pointer to
+ * lzma_index or use lzma_index_iter. The same iterator must be used
+ * only by one thread at a time, of course, but there can be as many
+ * iterators for the same lzma_index as needed.
+ */
+typedef struct lzma_index_s lzma_index;
+
+
+/**
+ * \brief       Iterator to get information about Blocks and Streams
+ */
+typedef struct {
+	struct {
+		/**
+		 * \brief       Pointer to Stream Flags
+		 *
+		 * This is NULL if Stream Flags have not been set for
+		 * this Stream with lzma_index_stream_flags().
+		 */
+		const lzma_stream_flags *flags;
+
+		const void *reserved_ptr1;
+		const void *reserved_ptr2;
+		const void *reserved_ptr3;
+
+		/**
+		 * \brief       Stream number in the lzma_index
+		 *
+		 * The first Stream is 1.
+		 */
+		lzma_vli number;
+
+		/**
+		 * \brief       Number of Blocks in the Stream
+		 *
+		 * If this is zero, the block structure below has
+		 * undefined values.
+		 */
+		lzma_vli block_count;
+
+		/**
+		 * \brief       Compressed start offset of this Stream
+		 *
+		 * The offset is relative to the beginning of the lzma_index
+		 * (i.e. usually the beginning of the .xz file).
+		 */
+		lzma_vli compressed_offset;
+
+		/**
+		 * \brief       Uncompressed start offset of this Stream
+		 *
+		 * The offset is relative to the beginning of the lzma_index
+		 * (i.e. usually the beginning of the .xz file).
+		 */
+		lzma_vli uncompressed_offset;
+
+		/**
+		 * \brief       Compressed size of this Stream
+		 *
+		 * This includes all headers except the possible
+		 * Stream Padding after this Stream.
+		 */
+		lzma_vli compressed_size;
+
+		/**
+		 * \brief       Uncompressed size of this Stream
+		 */
+		lzma_vli uncompressed_size;
+
+		/**
+		 * \brief       Size of Stream Padding after this Stream
+		 *
+		 * If it hasn't been set with lzma_index_stream_padding(),
+		 * this defaults to zero. Stream Padding is always
+		 * a multiple of four bytes.
+		 */
+		lzma_vli padding;
+
+		lzma_vli reserved_vli1;
+		lzma_vli reserved_vli2;
+		lzma_vli reserved_vli3;
+		lzma_vli reserved_vli4;
+	} stream;
+
+	struct {
+		/**
+		 * \brief       Block number in the file
+		 *
+		 * The first Block is 1.
+		 */
+		lzma_vli number_in_file;
+
+		/**
+		 * \brief       Compressed start offset of this Block
+		 *
+		 * This offset is relative to the beginning of the
+		 * lzma_index (i.e. usually the beginning of the .xz file).
+		 * Normally this is where you should seek in the .xz file
+		 * to start decompressing this Block.
+		 */
+		lzma_vli compressed_file_offset;
+
+		/**
+		 * \brief       Uncompressed start offset of this Block
+		 *
+		 * This offset is relative to the beginning of the lzma_index
+		 * (i.e. usually the beginning of the .xz file).
+		 */
+		lzma_vli uncompressed_file_offset;
+
+		/**
+		 * \brief       Block number in this Stream
+		 *
+		 * The first Block is 1.
+		 */
+		lzma_vli number_in_stream;
+
+		/**
+		 * \brief       Compressed start offset of this Block
+		 *
+		 * This offset is relative to the beginning of the Stream
+		 * containing this Block.
+		 */
+		lzma_vli compressed_stream_offset;
+
+		/**
+		 * \brief       Uncompressed start offset of this Block
+		 *
+		 * This offset is relative to the beginning of the Stream
+		 * containing this Block.
+		 */
+		lzma_vli uncompressed_stream_offset;
+
+		/**
+		 * \brief       Uncompressed size of this Block
+		 *
+		 * You should pass this to the Block decoder if you will
+		 * decode this Block.
+		 *
+		 * When doing random-access reading, it is possible that
+		 * the target offset is not exactly at Block boundary. One
+		 * will need to compare the target offset against
+		 * uncompressed_file_offset or uncompressed_stream_offset,
+		 * and possibly decode and throw away some amount of data
+		 * before reaching the target offset.
+		 */
+		lzma_vli uncompressed_size;
+
+		/**
+		 * \brief       Unpadded size of this Block
+		 *
+		 * You should pass this to the Block decoder if you will
+		 * decode this Block.
+		 */
+		lzma_vli unpadded_size;
+
+		/**
+		 * \brief       Total compressed size
+		 *
+		 * This includes all headers and padding in this Block.
+		 * This is useful if you need to know how many bytes
+		 * the Block decoder will actually read.
+		 */
+		lzma_vli total_size;
+
+		lzma_vli reserved_vli1;
+		lzma_vli reserved_vli2;
+		lzma_vli reserved_vli3;
+		lzma_vli reserved_vli4;
+
+		const void *reserved_ptr1;
+		const void *reserved_ptr2;
+		const void *reserved_ptr3;
+		const void *reserved_ptr4;
+	} block;
+
+	/*
+	 * Internal data which is used to store the state of the iterator.
+	 * The exact format may vary between liblzma versions, so don't
+	 * touch these in any way.
+	 */
+	union {
+		const void *p;
+		size_t s;
+		lzma_vli v;
+	} internal[6];
+} lzma_index_iter;
+
+
+/**
+ * \brief       Operation mode for lzma_index_iter_next()
+ */
+typedef enum {
+	LZMA_INDEX_ITER_ANY             = 0,
+		/**<
+		 * \brief       Get the next Block or Stream
+		 *
+		 * Go to the next Block if the current Stream has at least
+		 * one Block left. Otherwise go to the next Stream even if
+		 * it has no Blocks. If the Stream has no Blocks
+		 * (lzma_index_iter.stream.block_count == 0),
+		 * lzma_index_iter.block will have undefined values.
+		 */
+
+	LZMA_INDEX_ITER_STREAM          = 1,
+		/**<
+		 * \brief       Get the next Stream
+		 *
+		 * Go to the next Stream even if the current Stream has
+		 * unread Blocks left. If the next Stream has at least one
+		 * Block, the iterator will point to the first Block.
+		 * If there are no Blocks, lzma_index_iter.block will have
+		 * undefined values.
+		 */
+
+	LZMA_INDEX_ITER_BLOCK           = 2,
+		/**<
+		 * \brief       Get the next Block
+		 *
+		 * Go to the next Block if the current Stream has at least
+		 * one Block left. If the current Stream has no Blocks left,
+		 * the next Stream with at least one Block is located and
+		 * the iterator will be made to point to the first Block of
+		 * that Stream.
+		 */
+
+	LZMA_INDEX_ITER_NONEMPTY_BLOCK  = 3
+		/**<
+		 * \brief       Get the next non-empty Block
+		 *
+		 * This is like LZMA_INDEX_ITER_BLOCK except that it will
+		 * skip Blocks whose Uncompressed Size is zero.
+		 */
+
+} lzma_index_iter_mode;
+
+
+/**
+ * \brief       Calculate memory usage of lzma_index
+ *
+ * On disk, the size of the Index field depends on both the number of Records
+ * stored and how big values the Records store (due to variable-length integer
+ * encoding). When the Index is kept in lzma_index structure, the memory usage
+ * depends only on the number of Records/Blocks stored in the Index(es), and
+ * in case of concatenated lzma_indexes, the number of Streams. The size in
+ * RAM is almost always significantly bigger than in the encoded form on disk.
+ *
+ * This function calculates an approximate amount of memory needed hold
+ * the given number of Streams and Blocks in lzma_index structure. This
+ * value may vary between CPU architectures and also between liblzma versions
+ * if the internal implementation is modified.
+ */
+extern LZMA_API(uint64_t) lzma_index_memusage(
+		lzma_vli streams, lzma_vli blocks) lzma_nothrow;
+
+
+/**
+ * \brief       Calculate the memory usage of an existing lzma_index
+ *
+ * This is a shorthand for lzma_index_memusage(lzma_index_stream_count(i),
+ * lzma_index_block_count(i)).
+ */
+extern LZMA_API(uint64_t) lzma_index_memused(const lzma_index *i)
+		lzma_nothrow;
+
+
+/**
+ * \brief       Allocate and initialize a new lzma_index structure
+ *
+ * \return      On success, a pointer to an empty initialized lzma_index is
+ *              returned. If allocation fails, NULL is returned.
+ */
+extern LZMA_API(lzma_index *) lzma_index_init(lzma_allocator *allocator)
+		lzma_nothrow;
+
+
+/**
+ * \brief       Deallocate lzma_index
+ *
+ * If i is NULL, this does nothing.
+ */
+extern LZMA_API(void) lzma_index_end(lzma_index *i, lzma_allocator *allocator)
+		lzma_nothrow;
+
+
+/**
+ * \brief       Add a new Block to lzma_index
+ *
+ * \param       i                 Pointer to a lzma_index structure
+ * \param       allocator         Pointer to lzma_allocator, or NULL to
+ *                                use malloc()
+ * \param       unpadded_size     Unpadded Size of a Block. This can be
+ *                                calculated with lzma_block_unpadded_size()
+ *                                after encoding or decoding the Block.
+ * \param       uncompressed_size Uncompressed Size of a Block. This can be
+ *                                taken directly from lzma_block structure
+ *                                after encoding or decoding the Block.
+ *
+ * Appending a new Block does not invalidate iterators. For example,
+ * if an iterator was pointing to the end of the lzma_index, after
+ * lzma_index_append() it is possible to read the next Block with
+ * an existing iterator.
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_DATA_ERROR: Compressed or uncompressed size of the
+ *                Stream or size of the Index field would grow too big.
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_index_append(
+		lzma_index *i, lzma_allocator *allocator,
+		lzma_vli unpadded_size, lzma_vli uncompressed_size)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Set the Stream Flags
+ *
+ * Set the Stream Flags of the last (and typically the only) Stream
+ * in lzma_index. This can be useful when reading information from the
+ * lzma_index, because to decode Blocks, knowing the integrity check type
+ * is needed.
+ *
+ * The given Stream Flags are copied into internal preallocated structure
+ * in the lzma_index, thus the caller doesn't need to keep the *stream_flags
+ * available after calling this function.
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_OPTIONS_ERROR: Unsupported stream_flags->version.
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_index_stream_flags(
+		lzma_index *i, const lzma_stream_flags *stream_flags)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Get the types of integrity Checks
+ *
+ * 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.
+ *
+ * The bitmask is 1 << check_id, e.g. CRC32 is 1 << 1 and SHA-256 is 1 << 10.
+ */
+extern LZMA_API(uint32_t) lzma_index_checks(const lzma_index *i)
+		lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Set the amount of Stream Padding
+ *
+ * Set the amount of Stream Padding of the last (and typically the only)
+ * Stream in the lzma_index. This is needed when planning to do random-access
+ * reading within multiple concatenated Streams.
+ *
+ * By default, the amount of Stream Padding is assumed to be zero bytes.
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_DATA_ERROR: The file size would grow too big.
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_index_stream_padding(
+		lzma_index *i, lzma_vli stream_padding)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Get the number of Streams
+ */
+extern LZMA_API(lzma_vli) lzma_index_stream_count(const lzma_index *i)
+		lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Get the number of Blocks
+ *
+ * This returns the total number of Blocks in lzma_index. To get number
+ * of Blocks in individual Streams, use lzma_index_iter.
+ */
+extern LZMA_API(lzma_vli) lzma_index_block_count(const lzma_index *i)
+		lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Get the size of the Index field as bytes
+ *
+ * This is needed to verify the Backward Size field in the Stream Footer.
+ */
+extern LZMA_API(lzma_vli) lzma_index_size(const lzma_index *i)
+		lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Get the total size of the Stream
+ *
+ * If multiple lzma_indexes have been combined, this works as if the Blocks
+ * were in a single Stream. This is useful if you are going to combine
+ * Blocks from multiple Streams into a single new Stream.
+ */
+extern LZMA_API(lzma_vli) lzma_index_stream_size(const lzma_index *i)
+		lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Get the total size of the Blocks
+ *
+ * This doesn't include the Stream Header, Stream Footer, Stream Padding,
+ * or Index fields.
+ */
+extern LZMA_API(lzma_vli) lzma_index_total_size(const lzma_index *i)
+		lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Get the total size of the file
+ *
+ * When no lzma_indexes have been combined with lzma_index_cat() and there is
+ * no Stream Padding, this function is identical to lzma_index_stream_size().
+ * If multiple lzma_indexes have been combined, this includes also the headers
+ * of each separate Stream and the possible Stream Padding fields.
+ */
+extern LZMA_API(lzma_vli) lzma_index_file_size(const lzma_index *i)
+		lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Get the uncompressed size of the file
+ */
+extern LZMA_API(lzma_vli) lzma_index_uncompressed_size(const lzma_index *i)
+		lzma_nothrow lzma_attr_pure;
+
+
+/**
+ * \brief       Initialize an iterator
+ *
+ * \param       iter    Pointer to a lzma_index_iter structure
+ * \param       i       lzma_index to which the iterator will be associated
+ *
+ * This function associates the iterator with the given lzma_index, and calls
+ * lzma_index_iter_rewind() on the iterator.
+ *
+ * This function doesn't allocate any memory, thus there is no
+ * lzma_index_iter_end(). The iterator is valid as long as the
+ * associated lzma_index is valid, that is, until lzma_index_end() or
+ * using it as source in lzma_index_cat(). Specifically, lzma_index doesn't
+ * become invalid if new Blocks are added to it with lzma_index_append() or
+ * if it is used as the destination in lzma_index_cat().
+ *
+ * It is safe to make copies of an initialized lzma_index_iter, for example,
+ * to easily restart reading at some particular position.
+ */
+extern LZMA_API(void) lzma_index_iter_init(
+		lzma_index_iter *iter, const lzma_index *i) lzma_nothrow;
+
+
+/**
+ * \brief       Rewind the iterator
+ *
+ * Rewind the iterator so that next call to lzma_index_iter_next() will
+ * return the first Block or Stream.
+ */
+extern LZMA_API(void) lzma_index_iter_rewind(lzma_index_iter *iter)
+		lzma_nothrow;
+
+
+/**
+ * \brief       Get the next Block or Stream
+ *
+ * \param       iter    Iterator initialized with lzma_index_iter_init()
+ * \param       mode    Specify what kind of information the caller wants
+ *                      to get. See lzma_index_iter_mode for details.
+ *
+ * \return      If next Block or Stream matching the mode was found, *iter
+ *              is updated and this function returns false. If no Block or
+ *              Stream matching the mode is found, *iter is not modified
+ *              and this function returns true. If mode is set to an unknown
+ *              value, *iter is not modified and this function returns true.
+ */
+extern LZMA_API(lzma_bool) lzma_index_iter_next(
+		lzma_index_iter *iter, lzma_index_iter_mode mode)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Locate a Block
+ *
+ * If it is possible to seek in the .xz file, it is possible to parse
+ * the Index field(s) and use lzma_index_iter_locate() to do random-access
+ * reading with granularity of Block size.
+ *
+ * \param       iter    Iterator that was earlier initialized with
+ *                      lzma_index_iter_init().
+ * \param       target  Uncompressed target offset which the caller would
+ *                      like to locate from the Stream
+ *
+ * If the target is smaller than the uncompressed size of the Stream (can be
+ * checked with lzma_index_uncompressed_size()):
+ *  - Information about the Stream and Block containing the requested
+ *    uncompressed offset is stored into *iter.
+ *  - Internal state of the iterator is adjusted so that
+ *    lzma_index_iter_next() can be used to read subsequent Blocks or Streams.
+ *  - This function returns false.
+ *
+ * If target is greater than the uncompressed size of the Stream, *iter
+ * is not modified, and this function returns true.
+ */
+extern LZMA_API(lzma_bool) lzma_index_iter_locate(
+		lzma_index_iter *iter, lzma_vli target) lzma_nothrow;
+
+
+/**
+ * \brief       Concatenate lzma_indexes
+ *
+ * Concatenating lzma_indexes is useful when doing random-access reading in
+ * multi-Stream .xz file, or when combining multiple Streams into single
+ * Stream.
+ *
+ * \param       dest      lzma_index after which src is appended
+ * \param       src       lzma_index to be appended after dest. If this
+ *                        function succeeds, the memory allocated for src
+ *                        is freed or moved to be part of dest, and all
+ *                        iterators pointing to src will become invalid.
+ * \param       allocator Custom memory allocator; can be NULL to use
+ *                        malloc() and free().
+ *
+ * \return      - LZMA_OK: lzma_indexes were concatenated successfully.
+ *                src is now a dangling pointer.
+ *              - LZMA_DATA_ERROR: *dest would grow too big.
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_index_cat(
+		lzma_index *dest, lzma_index *src, lzma_allocator *allocator)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Duplicate lzma_index
+ *
+ * \return      A copy of the lzma_index, or NULL if memory allocation failed.
+ */
+extern LZMA_API(lzma_index *) lzma_index_dup(
+		const lzma_index *i, lzma_allocator *allocator)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Initialize .xz Index encoder
+ *
+ * \param       strm        Pointer to properly prepared lzma_stream
+ * \param       i           Pointer to lzma_index which should be encoded.
+ *
+ * The only valid action value for lzma_code() is LZMA_RUN.
+ *
+ * \return      - LZMA_OK: Initialization succeeded, continue with lzma_code().
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_index_encoder(
+		lzma_stream *strm, const lzma_index *i)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Initialize .xz Index decoder
+ *
+ * \param       strm        Pointer to properly prepared lzma_stream
+ * \param       i           The decoded Index will be made available via
+ *                          this pointer. Initially this function will
+ *                          set *i to NULL (the old value is ignored). If
+ *                          decoding succeeds (lzma_code() returns
+ *                          LZMA_STREAM_END), *i will be set to point
+ *                          to a new lzma_index, which the application
+ *                          has to later free with lzma_index_end().
+ * \param       memlimit    How much memory the resulting lzma_index is
+ *                          allowed to require.
+ *
+ * The only valid action value for lzma_code() is LZMA_RUN.
+ *
+ * \return      - LZMA_OK: Initialization succeeded, continue with lzma_code().
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_MEMLIMIT_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_index_decoder(
+		lzma_stream *strm, lzma_index **i, uint64_t memlimit)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Single-call .xz Index encoder
+ *
+ * \param       i         lzma_index to be encoded
+ * \param       out       Beginning of the output buffer
+ * \param       out_pos   The next byte will be written to out[*out_pos].
+ *                        *out_pos is updated only if encoding succeeds.
+ * \param       out_size  Size of the out buffer; the first byte into
+ *                        which no data is written to is out[out_size].
+ *
+ * \return      - LZMA_OK: Encoding was successful.
+ *              - LZMA_BUF_ERROR: Output buffer is too small. Use
+ *                lzma_index_size() to find out how much output
+ *                space is needed.
+ *              - LZMA_PROG_ERROR
+ *
+ * \note        This function doesn't take allocator argument since all
+ *              the internal data is allocated on stack.
+ */
+extern LZMA_API(lzma_ret) lzma_index_buffer_encode(const lzma_index *i,
+		uint8_t *out, size_t *out_pos, size_t out_size) lzma_nothrow;
+
+
+/**
+ * \brief       Single-call .xz Index decoder
+ *
+ * \param       i           If decoding succeeds, *i will point to a new
+ *                          lzma_index, which the application has to
+ *                          later free with lzma_index_end(). If an error
+ *                          occurs, *i will be NULL. The old value of *i
+ *                          is always ignored and thus doesn't need to be
+ *                          initialized by the caller.
+ * \param       memlimit    Pointer to how much memory the resulting
+ *                          lzma_index is allowed to require. The value
+ *                          pointed by this pointer is modified if and only
+ *                          if LZMA_MEMLIMIT_ERROR is returned.
+ * \param       allocator   Pointer to lzma_allocator, or NULL to use malloc()
+ * \param       in          Beginning of the input buffer
+ * \param       in_pos      The next byte will be read from in[*in_pos].
+ *                          *in_pos is updated only if decoding succeeds.
+ * \param       in_size     Size of the input buffer; the first byte that
+ *                          won't be read is in[in_size].
+ *
+ * \return      - LZMA_OK: Decoding was successful.
+ *              - LZMA_MEM_ERROR
+ *              - LZMA_MEMLIMIT_ERROR: Memory usage limit was reached.
+ *                The minimum required memlimit value was stored to *memlimit.
+ *              - LZMA_DATA_ERROR
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_index_buffer_decode(lzma_index **i,
+		uint64_t *memlimit, lzma_allocator *allocator,
+		const uint8_t *in, size_t *in_pos, size_t in_size)
+		lzma_nothrow;
diff --git a/src/liblzma/api/lzma/index_hash.h b/src/liblzma/api/lzma/index_hash.h
new file mode 100644
index 0000000..94726e7
--- /dev/null
+++ b/src/liblzma/api/lzma/index_hash.h
@@ -0,0 +1,107 @@
+/**
+ * \file        lzma/index_hash.h
+ * \brief       Validates Index by using a hash function
+ *
+ * Hashing makes it possible to use constant amount of memory to validate
+ * Index of arbitrary size.
+ */
+
+/*
+ * 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       Opaque data type to hold the Index hash
+ */
+typedef struct lzma_index_hash_s lzma_index_hash;
+
+
+/**
+ * \brief       Allocate and initialize a new lzma_index_hash structure
+ *
+ * If index_hash is NULL, a new lzma_index_hash structure is allocated,
+ * initialized, and a pointer to it returned. If allocation fails, NULL
+ * is returned.
+ *
+ * If index_hash is non-NULL, it is reinitialized and the same pointer
+ * returned. In this case, return value cannot be NULL or a different
+ * pointer than the index_hash that was given as an argument.
+ */
+extern LZMA_API(lzma_index_hash *) lzma_index_hash_init(
+		lzma_index_hash *index_hash, lzma_allocator *allocator)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Deallocate lzma_index_hash structure
+ */
+extern LZMA_API(void) lzma_index_hash_end(
+		lzma_index_hash *index_hash, lzma_allocator *allocator)
+		lzma_nothrow;
+
+
+/**
+ * \brief       Add a new Record to an Index hash
+ *
+ * \param       index             Pointer to a lzma_index_hash structure
+ * \param       unpadded_size     Unpadded Size of a Block
+ * \param       uncompressed_size Uncompressed Size of a Block
+ *
+ * \return      - LZMA_OK
+ *              - LZMA_DATA_ERROR: Compressed or uncompressed size of the
+ *                Stream or size of the Index field would grow too big.
+ *              - LZMA_PROG_ERROR: Invalid arguments or this function is being
+ *                used when lzma_index_hash_decode() has already been used.
+ */
+extern LZMA_API(lzma_ret) lzma_index_hash_append(lzma_index_hash *index_hash,
+		lzma_vli unpadded_size, lzma_vli uncompressed_size)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Decode and validate the Index field
+ *
+ * After telling the sizes of all Blocks with lzma_index_hash_append(),
+ * the actual Index field is decoded with this function. Specifically,
+ * once decoding of the Index field has been started, no more Records
+ * can be added using lzma_index_hash_append().
+ *
+ * This function doesn't use lzma_stream structure to pass the input data.
+ * Instead, the input buffer is specified using three arguments. This is
+ * because it matches better the internal APIs of liblzma.
+ *
+ * \param       index_hash      Pointer to a lzma_index_hash structure
+ * \param       in              Pointer to the beginning of the input buffer
+ * \param       in_pos          in[*in_pos] is the next byte to process
+ * \param       in_size         in[in_size] is the first byte not to process
+ *
+ * \return      - LZMA_OK: So far good, but more input is needed.
+ *              - LZMA_STREAM_END: Index decoded successfully and it matches
+ *                the Records given with lzma_index_hash_append().
+ *              - LZMA_DATA_ERROR: Index is corrupt or doesn't match the
+ *                information given with lzma_index_hash_append().
+ *              - LZMA_BUF_ERROR: Cannot progress because *in_pos >= in_size.
+ *              - LZMA_PROG_ERROR
+ */
+extern LZMA_API(lzma_ret) lzma_index_hash_decode(lzma_index_hash *index_hash,
+		const uint8_t *in, size_t *in_pos, size_t in_size)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Get the size of the Index field as bytes
+ *
+ * This is needed to verify the Backward Size field in the Stream Footer.
+ */
+extern LZMA_API(lzma_vli) lzma_index_hash_size(
+		const lzma_index_hash *index_hash)
+		lzma_nothrow lzma_attr_pure;
diff --git a/src/liblzma/api/lzma/lzma.h b/src/liblzma/api/lzma/lzma.h
new file mode 100644
index 0000000..c17736d
--- /dev/null
+++ b/src/liblzma/api/lzma/lzma.h
@@ -0,0 +1,397 @@
+/**
+ * \file        lzma/lzma.h
+ * \brief       LZMA1 and LZMA2 filters
+ */
+
+/*
+ * 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       LZMA1 Filter ID
+ *
+ * LZMA1 is the very same thing as what was called just LZMA in LZMA Utils,
+ * 7-Zip, and LZMA SDK. It's called LZMA1 here to prevent developers from
+ * accidentally using LZMA when they actually want LZMA2.
+ *
+ * LZMA1 shouldn't be used for new applications unless you _really_ know
+ * what you are doing. LZMA2 is almost always a better choice.
+ */
+#define LZMA_FILTER_LZMA1       LZMA_VLI_C(0x4000000000000001)
+
+/**
+ * \brief       LZMA2 Filter ID
+ *
+ * Usually you want this instead of LZMA1. Compared to LZMA1, LZMA2 adds
+ * support for LZMA_SYNC_FLUSH, uncompressed chunks (smaller expansion
+ * when trying to compress uncompressible data), possibility to change
+ * lc/lp/pb in the middle of encoding, and some other internal improvements.
+ */
+#define LZMA_FILTER_LZMA2       LZMA_VLI_C(0x21)
+
+
+/**
+ * \brief       Match finders
+ *
+ * Match finder has major effect on both speed and compression ratio.
+ * Usually hash chains are faster than binary trees.
+ *
+ * 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.
+ */
+typedef enum {
+	LZMA_MF_HC3     = 0x03,
+		/**<
+		 * \brief       Hash Chain with 2- and 3-byte hashing
+		 *
+		 * Minimum nice_len: 3
+		 *
+		 * Memory usage:
+		 *  - dict_size <= 16 MiB: dict_size * 7.5
+		 *  - dict_size > 16 MiB: dict_size * 5.5 + 64 MiB
+		 */
+
+	LZMA_MF_HC4     = 0x04,
+		/**<
+		 * \brief       Hash Chain with 2-, 3-, and 4-byte hashing
+		 *
+		 * Minimum nice_len: 4
+		 *
+		 * Memory usage: dict_size * 7.5
+		 */
+
+	LZMA_MF_BT2     = 0x12,
+		/**<
+		 * \brief       Binary Tree with 2-byte hashing
+		 *
+		 * Minimum nice_len: 2
+		 *
+		 * Memory usage: dict_size * 9.5
+		 */
+
+	LZMA_MF_BT3     = 0x13,
+		/**<
+		 * \brief       Binary Tree with 2- and 3-byte hashing
+		 *
+		 * Minimum nice_len: 3
+		 *
+		 * Memory usage:
+		 *  - dict_size <= 16 MiB: dict_size * 11.5
+		 *  - dict_size > 16 MiB: dict_size * 9.5 + 64 MiB
+		 */
+
+	LZMA_MF_BT4     = 0x14
+		/**<
+		 * \brief       Binary Tree with 2-, 3-, and 4-byte hashing
+		 *
+		 * Minimum nice_len: 4
+		 *
+		 * Memory usage: dict_size * 11.5
+		 */
+} lzma_match_finder;
+
+
+/**
+ * \brief       Test if given match finder is supported
+ *
+ * Return true if the given match finder is supported by this liblzma build.
+ * Otherwise false is returned. It is safe to call this with a value that
+ * isn't listed in lzma_match_finder enumeration; the return value will be
+ * false.
+ *
+ * There is no way to list which match finders are available in this
+ * particular liblzma version and build. It would be useless, because
+ * a new match finder, which the application developer wasn't aware,
+ * could require giving additional options to the encoder that the older
+ * match finders don't need.
+ */
+extern LZMA_API(lzma_bool) lzma_mf_is_supported(lzma_match_finder match_finder)
+		lzma_nothrow lzma_attr_const;
+
+
+/**
+ * \brief       Compression modes
+ *
+ * This selects the function used to analyze the data produced by the match
+ * finder.
+ */
+typedef enum {
+	LZMA_MODE_FAST = 1,
+		/**<
+		 * \brief       Fast compression
+		 *
+		 * Fast mode is usually at its best when combined with
+		 * a hash chain match finder.
+		 */
+
+	LZMA_MODE_NORMAL = 2
+		/**<
+		 * \brief       Normal compression
+		 *
+		 * This is usually notably slower than fast mode. Use this
+		 * together with binary tree match finders to expose the
+		 * full potential of the LZMA1 or LZMA2 encoder.
+		 */
+} lzma_mode;
+
+
+/**
+ * \brief       Test if given compression mode is supported
+ *
+ * Return true if the given compression mode is supported by this liblzma
+ * build. Otherwise false is returned. It is safe to call this with a value
+ * that isn't listed in lzma_mode enumeration; the return value will be false.
+ *
+ * There is no way to list which modes are available in this particular
+ * liblzma version and build. It would be useless, because a new compression
+ * mode, which the application developer wasn't aware, could require giving
+ * additional options to the encoder that the older modes don't need.
+ */
+extern LZMA_API(lzma_bool) lzma_mode_is_supported(lzma_mode mode)
+		lzma_nothrow lzma_attr_const;
+
+
+/**
+ * \brief       Options specific to the LZMA1 and LZMA2 filters
+ *
+ * Since LZMA1 and LZMA2 share most of the code, it's simplest to share
+ * the options structure too. For encoding, all but the reserved variables
+ * need to be initialized unless specifically mentioned otherwise.
+ *
+ * For raw decoding, both LZMA1 and LZMA2 need dict_size, preset_dict, and
+ * preset_dict_size (if preset_dict != NULL). LZMA1 needs also lc, lp, and pb.
+ */
+typedef struct {
+	/**
+	 * \brief       Dictionary size in bytes
+	 *
+	 * Dictionary 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. Thus,
+	 * the bigger the dictionary, the better the compression ratio
+	 * usually is.
+	 *
+	 * Maximum size of the dictionary depends on multiple things:
+	 *  - Memory usage limit
+	 *  - Available address space (not a problem on 64-bit systems)
+	 *  - Selected match finder (encoder only)
+	 *
+	 * Currently the maximum dictionary size for encoding is 1.5 GiB
+	 * (i.e. (UINT32_C(1) << 30) + (UINT32_C(1) << 29)) even on 64-bit
+	 * systems for certain match finder implementation reasons. In the
+	 * future, there may be match finders that support bigger
+	 * dictionaries.
+	 *
+	 * Decoder already supports dictionaries up to 4 GiB - 1 B (i.e.
+	 * UINT32_MAX), so increasing the maximum dictionary size of the
+	 * encoder won't cause problems for old decoders.
+	 *
+	 * Because extremely small dictionaries sizes would have unneeded
+	 * overhead in the decoder, the minimum dictionary size is 4096 bytes.
+	 *
+	 * \note        When decoding, too big dictionary does no other harm
+	 *              than wasting memory.
+	 */
+	uint32_t dict_size;
+#	define LZMA_DICT_SIZE_MIN       UINT32_C(4096)
+#	define LZMA_DICT_SIZE_DEFAULT   (UINT32_C(1) << 23)
+
+	/**
+	 * \brief       Pointer to an initial dictionary
+	 *
+	 * It is possible to initialize the LZ77 history window using
+	 * a preset dictionary. It is useful when compressing many
+	 * similar, relatively small chunks of data independently from
+	 * each other. The preset dictionary should contain typical
+	 * strings that occur in the files being compressed. The most
+	 * probable strings should be near the end of the preset dictionary.
+	 *
+	 * This feature should be used only in special situations. For
+	 * now, it works correctly only with raw encoding and decoding.
+	 * Currently none of the container formats supported by
+	 * liblzma allow preset dictionary when decoding, thus if
+	 * you create a .xz or .lzma file with preset dictionary, it
+	 * cannot be decoded with the regular decoder functions. In the
+	 * future, the .xz format will likely get support for preset
+	 * dictionary though.
+	 */
+	const uint8_t *preset_dict;
+
+	/**
+	 * \brief       Size of the preset dictionary
+	 *
+	 * Specifies the size of the preset dictionary. If the size is
+	 * bigger than dict_size, only the last dict_size bytes are
+	 * processed.
+	 *
+	 * This variable is read only when preset_dict is not NULL.
+	 * If preset_dict is not NULL but preset_dict_size is zero,
+	 * no preset dictionary is used (identical to only setting
+	 * preset_dict to NULL).
+	 */
+	uint32_t preset_dict_size;
+
+	/**
+	 * \brief       Number of literal context bits
+	 *
+	 * How many of the highest bits of the previous uncompressed
+	 * eight-bit byte (also known as `literal') are taken into
+	 * account when predicting the bits of the next literal.
+	 *
+	 * \todo        Example
+	 *
+	 * There is a limit that applies to literal context bits and literal
+	 * position bits together: lc + lp <= 4. Without this limit the
+	 * decoding could become very slow, which could have security related
+	 * results in some cases like email servers doing virus scanning.
+	 * This limit also simplifies the internal implementation in liblzma.
+	 *
+	 * There may be LZMA1 streams that have lc + lp > 4 (maximum possible
+	 * lc would be 8). It is not possible to decode such streams with
+	 * liblzma.
+	 */
+	uint32_t lc;
+#	define LZMA_LCLP_MIN    0
+#	define LZMA_LCLP_MAX    4
+#	define LZMA_LC_DEFAULT  3
+
+	/**
+	 * \brief       Number of literal position bits
+	 *
+	 * How many of the lowest bits of the current position (number
+	 * of bytes from the beginning of the uncompressed data) in the
+	 * uncompressed data is taken into account when predicting the
+	 * bits of the next literal (a single eight-bit byte).
+	 *
+	 * \todo        Example
+	 */
+	uint32_t lp;
+#	define LZMA_LP_DEFAULT  0
+
+	/**
+	 * \brief       Number of position bits
+	 *
+	 * How many of the lowest bits of the current position in the
+	 * uncompressed data is taken into account when estimating
+	 * probabilities of matches. A match is a sequence of bytes for
+	 * which a matching sequence is found from the dictionary and
+	 * thus can be stored as distance-length pair.
+	 *
+	 * Example: If most of the matches occur at byte positions of
+	 * 8 * n + 3, that is, 3, 11, 19, ... set pb to 3, because 2**3 == 8.
+	 */
+	uint32_t pb;
+#	define LZMA_PB_MIN      0
+#	define LZMA_PB_MAX      4
+#	define LZMA_PB_DEFAULT  2
+
+	/** Compression mode */
+	lzma_mode mode;
+
+	/**
+	 * \brief       Nice length of a match
+	 *
+	 * This determines how many bytes the encoder compares from the match
+	 * candidates when looking for the best match. Once a match of at
+	 * least nice_len bytes long is found, the encoder stops looking for
+	 * better candidates and encodes the match. (Naturally, if the found
+	 * match is actually longer than nice_len, the actual length is
+	 * encoded; it's not truncated to nice_len.)
+	 *
+	 * Bigger values usually increase the compression ratio and
+	 * compression time. For most files, 32 to 128 is a good value,
+	 * which gives very good compression ratio at good speed.
+	 *
+	 * The exact minimum value depends on the match finder. The maximum
+	 * is 273, which is the maximum length of a match that LZMA1 and
+	 * LZMA2 can encode.
+	 */
+	uint32_t nice_len;
+
+	/** Match finder ID */
+	lzma_match_finder mf;
+
+	/**
+	 * \brief       Maximum search depth in the match finder
+	 *
+	 * For every input byte, match finder searches through the hash chain
+	 * or binary tree in a loop, each iteration going one step deeper in
+	 * the chain or tree. The searching stops if
+	 *  - a match of at least nice_len bytes long is found;
+	 *  - all match candidates from the hash chain or binary tree have
+	 *    been checked; or
+	 *  - maximum search depth is reached.
+	 *
+	 * Maximum search depth is needed to prevent the match finder from
+	 * wasting too much time in case there are lots of short match
+	 * candidates. On the other hand, stopping the search before all
+	 * candidates have been checked can reduce compression ratio.
+	 *
+	 * Setting depth to zero tells liblzma to use an automatic default
+	 * value, that depends on the selected match finder and nice_len.
+	 * The default is in the range [10, 200] or so (it may vary between
+	 * liblzma versions).
+	 *
+	 * Using a bigger depth value than the default can increase
+	 * compression ratio in some cases. There is no strict maximum value,
+	 * but high values (thousands or millions) should be used with care:
+	 * the encoder could remain fast enough with typical input, but
+	 * malicious input could cause the match finder to slow down
+	 * dramatically, possibly creating a denial of service attack.
+	 */
+	uint32_t depth;
+
+	/*
+	 * Reserved space to allow possible future extensions without
+	 * breaking the ABI. You should not touch these, because the names
+	 * of these variables may change. These are and will never be used
+	 * with the currently supported options, so it is safe to leave these
+	 * uninitialized.
+	 */
+	void *reserved_ptr1;
+	void *reserved_ptr2;
+	uint32_t reserved_int1;
+	uint32_t reserved_int2;
+	uint32_t reserved_int3;
+	uint32_t reserved_int4;
+	uint32_t reserved_int5;
+	uint32_t reserved_int6;
+	uint32_t reserved_int7;
+	uint32_t reserved_int8;
+	lzma_reserved_enum reserved_enum1;
+	lzma_reserved_enum reserved_enum2;
+	lzma_reserved_enum reserved_enum3;
+	lzma_reserved_enum reserved_enum4;
+
+} lzma_options_lzma;
+
+
+/**
+ * \brief       Set a compression preset to lzma_options_lzma structure
+ *
+ * 0 is the fastest and 9 is the slowest. These match the switches -0 .. -9
+ * of the xz command line tool. In addition, it is possible to bitwise-or
+ * flags to the preset. Currently only LZMA_PRESET_EXTREME is supported.
+ * The flags are defined in container.h, because the flags are used also
+ * with lzma_easy_encoder().
+ *
+ * The preset values are subject to changes between liblzma versions.
+ *
+ * This function is available only if LZMA1 or LZMA2 encoder has been enabled
+ * when building liblzma.
+ */
+extern LZMA_API(lzma_bool) lzma_lzma_preset(
+		lzma_options_lzma *options, uint32_t preset) lzma_nothrow;
diff --git a/src/liblzma/api/lzma/stream_flags.h b/src/liblzma/api/lzma/stream_flags.h
new file mode 100644
index 0000000..d255bdd
--- /dev/null
+++ b/src/liblzma/api/lzma/stream_flags.h
@@ -0,0 +1,227 @@
+/**
+ * \file        lzma/stream_flags.h
+ * \brief       .xz Stream Header and Stream Footer encoder and decoder
+ */
+
+/*
+ * 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       Size of Stream Header and Stream Footer
+ *
+ * Stream Header and Stream Footer have the same size and they are not
+ * going to change even if a newer version of the .xz file format is
+ * developed in future.
+ */
+#define LZMA_STREAM_HEADER_SIZE 12
+
+
+/**
+ * \brief       Options for encoding/decoding Stream Header and Stream Footer
+ */
+typedef struct {
+	/**
+	 * \brief       Stream Flags format version
+	 *
+	 * To prevent API and ABI breakages if new features are needed in
+	 * Stream Header or Stream Footer, a version number is used to
+	 * indicate which fields in this structure are in use. For now,
+	 * version must always be zero. With non-zero version, the
+	 * lzma_stream_header_encode() and lzma_stream_footer_encode()
+	 * will return LZMA_OPTIONS_ERROR.
+	 *
+	 * lzma_stream_header_decode() and lzma_stream_footer_decode()
+	 * will always set this to the lowest value that supports all the
+	 * features indicated by the Stream Flags field. The application
+	 * must check that the version number set by the decoding functions
+	 * is supported by the application. Otherwise it is possible that
+	 * the application will decode the Stream incorrectly.
+	 */
+	uint32_t version;
+
+	/**
+	 * \brief       Backward Size
+	 *
+	 * Backward Size must be a multiple of four bytes. In this Stream
+	 * format version, Backward Size is the size of the Index field.
+	 *
+	 * Backward Size isn't actually part of the Stream Flags field, but
+	 * it is convenient to include in this structure anyway. Backward
+	 * Size is present only in the Stream Footer. There is no need to
+	 * initialize backward_size when encoding Stream Header.
+	 *
+	 * lzma_stream_header_decode() always sets backward_size to
+	 * LZMA_VLI_UNKNOWN so that it is convenient to use
+	 * lzma_stream_flags_compare() when both Stream Header and Stream
+	 * Footer have been decoded.
+	 */
+	lzma_vli backward_size;
+#	define LZMA_BACKWARD_SIZE_MIN 4
+#	define LZMA_BACKWARD_SIZE_MAX (LZMA_VLI_C(1) << 34)
+
+	/**
+	 * \brief       Check ID
+	 *
+	 * This indicates the type of the integrity check calculated from
+	 * uncompressed data.
+	 */
+	lzma_check check;
+
+	/*
+	 * Reserved space to allow possible future extensions without
+	 * breaking the ABI. You should not touch these, because the
+	 * names of these variables may change.
+	 *
+	 * (We will never be able to use all of these since Stream Flags
+	 * is just two bytes plus Backward Size of four bytes. But it's
+	 * nice to have the proper types when they are needed.)
+	 */
+	lzma_reserved_enum reserved_enum1;
+	lzma_reserved_enum reserved_enum2;
+	lzma_reserved_enum reserved_enum3;
+	lzma_reserved_enum reserved_enum4;
+	lzma_reserved_enum reserved_enum5;
+	lzma_reserved_enum reserved_enum6;
+	lzma_bool reserved_bool1;
+	lzma_bool reserved_bool2;
+	lzma_bool reserved_bool3;
+	lzma_bool reserved_bool4;
+	lzma_bool reserved_bool5;
+	lzma_bool reserved_bool6;
+	lzma_bool reserved_bool7;
+	lzma_bool reserved_bool8;
+	uint32_t reserved_int1;
+	uint32_t reserved_int2;
+	uint32_t reserved_int3;
+	uint32_t reserved_int4;
+
+} lzma_stream_flags;
+
+
+/**
+ * \brief       Encode Stream Header
+ *
+ * \param       options     Stream Header options to be encoded.
+ *                          options->backward_size is ignored and doesn't
+ *                          need to be initialized.
+ * \param       out         Beginning of the output buffer of
+ *                          LZMA_STREAM_HEADER_SIZE bytes.
+ *
+ * \return      - LZMA_OK: Encoding was successful.
+ *              - LZMA_OPTIONS_ERROR: options->version is not supported by
+ *                this liblzma version.
+ *              - LZMA_PROG_ERROR: Invalid options.
+ */
+extern LZMA_API(lzma_ret) lzma_stream_header_encode(
+		const lzma_stream_flags *options, uint8_t *out)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Encode Stream Footer
+ *
+ * \param       options     Stream Footer options to be encoded.
+ * \param       out         Beginning of the output buffer of
+ *                          LZMA_STREAM_HEADER_SIZE bytes.
+ *
+ * \return      - LZMA_OK: Encoding was successful.
+ *              - LZMA_OPTIONS_ERROR: options->version is not supported by
+ *                this liblzma version.
+ *              - LZMA_PROG_ERROR: Invalid options.
+ */
+extern LZMA_API(lzma_ret) lzma_stream_footer_encode(
+		const lzma_stream_flags *options, uint8_t *out)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Decode Stream Header
+ *
+ * \param       options     Stream Header options to be encoded.
+ * \param       in          Beginning of the input buffer of
+ *                          LZMA_STREAM_HEADER_SIZE bytes.
+ *
+ * options->backward_size is always set to LZMA_VLI_UNKNOWN. This is to
+ * help comparing Stream Flags from Stream Header and Stream Footer with
+ * lzma_stream_flags_compare().
+ *
+ * \return      - LZMA_OK: Decoding was successful.
+ *              - LZMA_FORMAT_ERROR: Magic bytes don't match, thus the given
+ *                buffer cannot be Stream Header.
+ *              - LZMA_DATA_ERROR: CRC32 doesn't match, thus the header
+ *                is corrupt.
+ *              - LZMA_OPTIONS_ERROR: Unsupported options are present
+ *                in the header.
+ *
+ * \note        When decoding .xz files that contain multiple Streams, it may
+ *              make sense to print "file format not recognized" only if
+ *              decoding of the Stream Header of the _first_ Stream gives
+ *              LZMA_FORMAT_ERROR. If non-first Stream Header gives
+ *              LZMA_FORMAT_ERROR, the message used for LZMA_DATA_ERROR is
+ *              probably more appropriate.
+ *
+ *              For example, Stream decoder in liblzma uses LZMA_DATA_ERROR if
+ *              LZMA_FORMAT_ERROR is returned by lzma_stream_header_decode()
+ *              when decoding non-first Stream.
+ */
+extern LZMA_API(lzma_ret) lzma_stream_header_decode(
+		lzma_stream_flags *options, const uint8_t *in)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Decode Stream Footer
+ *
+ * \param       options     Stream Header options to be encoded.
+ * \param       in          Beginning of the input buffer of
+ *                          LZMA_STREAM_HEADER_SIZE bytes.
+ *
+ * \return      - LZMA_OK: Decoding was successful.
+ *              - LZMA_FORMAT_ERROR: Magic bytes don't match, thus the given
+ *                buffer cannot be Stream Footer.
+ *              - LZMA_DATA_ERROR: CRC32 doesn't match, thus the Stream Footer
+ *                is corrupt.
+ *              - LZMA_OPTIONS_ERROR: Unsupported options are present
+ *                in Stream Footer.
+ *
+ * \note        If Stream Header was already decoded successfully, but
+ *              decoding Stream Footer returns LZMA_FORMAT_ERROR, the
+ *              application should probably report some other error message
+ *              than "file format not recognized", since the file more likely
+ *              is corrupt (possibly truncated). Stream decoder in liblzma
+ *              uses LZMA_DATA_ERROR in this situation.
+ */
+extern LZMA_API(lzma_ret) lzma_stream_footer_decode(
+		lzma_stream_flags *options, const uint8_t *in)
+		lzma_nothrow lzma_attr_warn_unused_result;
+
+
+/**
+ * \brief       Compare two lzma_stream_flags structures
+ *
+ * backward_size values are compared only if both are not
+ * LZMA_VLI_UNKNOWN.
+ *
+ * \return      - LZMA_OK: Both are equal. If either had backward_size set
+ *                to LZMA_VLI_UNKNOWN, backward_size values were not
+ *                compared or validated.
+ *              - LZMA_DATA_ERROR: The structures differ.
+ *              - LZMA_OPTIONS_ERROR: version in either structure is greater
+ *                than the maximum supported version (currently zero).
+ *              - LZMA_PROG_ERROR: Invalid value, e.g. invalid check or
+ *                backward_size.
+ */
+extern LZMA_API(lzma_ret) lzma_stream_flags_compare(
+		const lzma_stream_flags *a, const lzma_stream_flags *b)
+		lzma_nothrow lzma_attr_pure;
diff --git a/src/liblzma/api/lzma/version.h b/src/liblzma/api/lzma/version.h
new file mode 100644
index 0000000..0f7c2d3
--- /dev/null
+++ b/src/liblzma/api/lzma/version.h
@@ -0,0 +1,121 @@
+/**
+ * \file        lzma/version.h
+ * \brief       Version number
+ */
+
+/*
+ * 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
+
+
+/*
+ * Version number split into components
+ */
+#define LZMA_VERSION_MAJOR 4
+#define LZMA_VERSION_MINOR 999
+#define LZMA_VERSION_PATCH 9
+#define LZMA_VERSION_STABILITY LZMA_VERSION_STABILITY_BETA
+
+#ifndef LZMA_VERSION_COMMIT
+#	define LZMA_VERSION_COMMIT ""
+#endif
+
+
+/*
+ * Map symbolic stability levels to integers.
+ */
+#define LZMA_VERSION_STABILITY_ALPHA 0
+#define LZMA_VERSION_STABILITY_BETA 1
+#define LZMA_VERSION_STABILITY_STABLE 2
+
+
+/**
+ * \brief       Compile-time version number
+ *
+ * The version number is of format xyyyzzzs where
+ *  - x = major
+ *  - yyy = minor
+ *  - zzz = revision
+ *  - s indicates stability: 0 = alpha, 1 = beta, 2 = stable
+ *
+ * The same xyyyzzz triplet is never reused with different stability levels.
+ * For example, if 5.1.0alpha has been released, there will never be 5.1.0beta
+ * or 5.1.0 stable.
+ *
+ * \note        The version number of liblzma has nothing to with
+ *              the version number of Igor Pavlov's LZMA SDK.
+ */
+#define LZMA_VERSION (LZMA_VERSION_MAJOR * UINT32_C(10000000) \
+		+ LZMA_VERSION_MINOR * UINT32_C(10000) \
+		+ LZMA_VERSION_PATCH * UINT32_C(10) \
+		+ LZMA_VERSION_STABILITY)
+
+
+/*
+ * Macros to construct the compile-time version string
+ */
+#if LZMA_VERSION_STABILITY == LZMA_VERSION_STABILITY_ALPHA
+#	define LZMA_VERSION_STABILITY_STRING "alpha"
+#elif LZMA_VERSION_STABILITY == LZMA_VERSION_STABILITY_BETA
+#	define LZMA_VERSION_STABILITY_STRING "beta"
+#elif LZMA_VERSION_STABILITY == LZMA_VERSION_STABILITY_STABLE
+#	define LZMA_VERSION_STABILITY_STRING ""
+#else
+#	error Incorrect LZMA_VERSION_STABILITY
+#endif
+
+#define LZMA_VERSION_STRING_C_(major, minor, patch, stability, commit) \
+		#major "." #minor "." #patch stability commit
+
+#define LZMA_VERSION_STRING_C(major, minor, patch, stability, commit) \
+		LZMA_VERSION_STRING_C_(major, minor, patch, stability, commit)
+
+
+/**
+ * \brief       Compile-time version as a string
+ *
+ * This can be for example "4.999.5alpha", "4.999.8beta", or "5.0.0" (stable
+ * versions don't have any "stable" suffix). In future, a snapshot built
+ * from source code repository may include an additional suffix, for example
+ * "4.999.8beta-21-g1d92". The commit ID won't be available in numeric form
+ * in LZMA_VERSION macro.
+ */
+#define LZMA_VERSION_STRING LZMA_VERSION_STRING_C( \
+		LZMA_VERSION_MAJOR, LZMA_VERSION_MINOR, \
+		LZMA_VERSION_PATCH, LZMA_VERSION_STABILITY_STRING, \
+		LZMA_VERSION_COMMIT)
+
+
+/* #ifndef is needed for use with windres (MinGW or Cygwin). */
+#ifndef LZMA_H_INTERNAL_RC
+
+/**
+ * \brief       Run-time version number as an integer
+ *
+ * Return the value of LZMA_VERSION macro at the compile time of liblzma.
+ * This allows the application to compare if it was built against the same,
+ * older, or newer version of liblzma that is currently running.
+ */
+extern LZMA_API(uint32_t) lzma_version_number(void)
+		lzma_nothrow lzma_attr_const;
+
+
+/**
+ * \brief       Run-time version as a string
+ *
+ * This function may be useful if you want to display which version of
+ * liblzma your application is currently using.
+ */
+extern LZMA_API(const char *) lzma_version_string(void)
+		lzma_nothrow lzma_attr_const;
+
+#endif
diff --git a/src/liblzma/api/lzma/vli.h b/src/liblzma/api/lzma/vli.h
new file mode 100644
index 0000000..57e3d38
--- /dev/null
+++ b/src/liblzma/api/lzma/vli.h
@@ -0,0 +1,167 @@
+/**
+ * \file        lzma/vli.h
+ * \brief       Variable-length integer handling
+ *
+ * In the .xz format, most integers are encoded in a variable-length
+ * representation, which is sometimes called little endian base-128 encoding.
+ * This saves space when smaller values are more likely than bigger values.
+ *
+ * The encoding scheme encodes seven bits to every byte, using minimum
+ * number of bytes required to represent the given value. Encodings that use
+ * non-minimum number of bytes are invalid, thus every integer has exactly
+ * one encoded representation. The maximum number of bits in a VLI is 63,
+ * thus the vli argument must be less than or equal to UINT64_MAX / 2. You
+ * should use LZMA_VLI_MAX for clarity.
+ */
+
+/*
+ * 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       Maximum supported value of variable-length integer
+ */
+#define LZMA_VLI_MAX (UINT64_MAX / 2)
+
+/**
+ * \brief       VLI value to denote that the value is unknown
+ */
+#define LZMA_VLI_UNKNOWN UINT64_MAX
+
+/**
+ * \brief       Maximum supported length of variable length integers
+ */
+#define LZMA_VLI_BYTES_MAX 9
+
+
+/**
+ * \brief       VLI constant suffix
+ */
+#define LZMA_VLI_C(n) UINT64_C(n)
+
+
+/**
+ * \brief       Variable-length integer type
+ *
+ * This will always be unsigned integer. Valid VLI values are in the range
+ * [0, LZMA_VLI_MAX]. Unknown value is indicated with LZMA_VLI_UNKNOWN,
+ * which is the maximum value of the underlaying integer type.
+ *
+ * In future, even if lzma_vli is defined to be something other than uint64_t,
+ * it is guaranteed that 2 * LZMA_VLI_MAX will not overflow lzma_vli.
+ * This simplifies integer overflow detection.
+ */
+typedef uint64_t lzma_vli;
+
+
+/**
+ * \brief       Simple macro to validate variable-length integer
+ *
+ * This is useful to test that application has given acceptable values
+ * for example in the uncompressed_size and compressed_size variables.
+ *
+ * \return      True if the integer is representable as VLI or if it
+ *              indicates unknown value.
+ */
+#define lzma_vli_is_valid(vli) \
+	((vli) <= LZMA_VLI_MAX || (vli) == LZMA_VLI_UNKNOWN)
+
+
+/**
+ * \brief       Encode a variable-length integer
+ *
+ * This function has two modes: single-call and multi-call. Single-call mode
+ * encodes the whole integer at once; it is an error if the output buffer is
+ * too small. Multi-call mode saves the position in *vli_pos, and thus it is
+ * possible to continue encoding if the buffer becomes full before the whole
+ * integer has been encoded.
+ *
+ * \param       vli       Integer to be encoded
+ * \param       vli_pos   How many VLI-encoded bytes have already been written
+ *                        out. When starting to encode a new integer, *vli_pos
+ *                        must be set to zero. To use single-call encoding,
+ *                        set vli_pos to NULL.
+ * \param       out       Beginning of the output buffer
+ * \param       out_pos   The next byte will be written to out[*out_pos].
+ * \param       out_size  Size of the out buffer; the first byte into
+ *                        which no data is written to is out[out_size].
+ *
+ * \return      Slightly different return values are used in multi-call and
+ *              single-call modes.
+ *
+ *              Single-call (vli_pos == NULL):
+ *              - LZMA_OK: Integer successfully encoded.
+ *              - LZMA_PROG_ERROR: Arguments are not sane. This can be due
+ *                to too little output space; single-call mode doesn't use
+ *                LZMA_BUF_ERROR, since the application should have checked
+ *                the encoded size with lzma_vli_size().
+ *
+ *              Multi-call (vli_pos != NULL):
+ *              - LZMA_OK: So far all OK, but the integer is not
+ *                completely written out yet.
+ *              - LZMA_STREAM_END: Integer successfully encoded.
+ *              - 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 *out, size_t *out_pos, size_t out_size) lzma_nothrow;
+
+
+/**
+ * \brief       Decode a variable-length integer
+ *
+ * Like lzma_vli_encode(), this function has single-call and multi-call modes.
+ *
+ * \param       vli       Pointer to decoded integer. The decoder will
+ *                        initialize it to zero when *vli_pos == 0, so
+ *                        application isn't required to initialize *vli.
+ * \param       vli_pos   How many bytes have already been decoded. When
+ *                        starting to decode a new integer, *vli_pos must
+ *                        be initialized to zero. To use single-call decoding,
+ *                        set this to NULL.
+ * \param       in        Beginning of the input buffer
+ * \param       in_pos    The next byte will be read from in[*in_pos].
+ * \param       in_size   Size of the input buffer; the first byte that
+ *                        won't be read is in[in_size].
+ *
+ * \return      Slightly different return values are used in multi-call and
+ *              single-call modes.
+ *
+ *              Single-call (vli_pos == NULL):
+ *              - LZMA_OK: Integer successfully decoded.
+ *              - LZMA_DATA_ERROR: Integer is corrupt. This includes hitting
+ *                the end of the input buffer before the whole integer was
+ *                decoded; providing no input at all will use LZMA_DATA_ERROR.
+ *              - LZMA_PROG_ERROR: Arguments are not sane.
+ *
+ *              Multi-call (vli_pos != NULL):
+ *              - LZMA_OK: So far all OK, but the integer is not
+ *                completely decoded yet.
+ *              - LZMA_STREAM_END: Integer successfully decoded.
+ *              - LZMA_DATA_ERROR: Integer is corrupt.
+ *              - LZMA_BUF_ERROR: No input was provided.
+ *              - LZMA_PROG_ERROR: Arguments are not sane.
+ */
+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;
+
+
+/**
+ * \brief       Get the number of bytes required to encode a VLI
+ *
+ * \return      Number of bytes on success (1-9). If vli isn't valid,
+ *              zero is returned.
+ */
+extern LZMA_API(uint32_t) lzma_vli_size(lzma_vli vli)
+		lzma_nothrow lzma_attr_pure;
diff --git a/src/liblzma/check/Makefile.inc b/src/liblzma/check/Makefile.inc
new file mode 100644
index 0000000..e4067a9
--- /dev/null
+++ b/src/liblzma/check/Makefile.inc
@@ -0,0 +1,51 @@
+##
+## Author: Lasse Collin
+##
+## This file has been put into the public domain.
+## You can do whatever you want with this file.
+##
+
+EXTRA_DIST += \
+	check/crc32_tablegen.c \
+	check/crc64_tablegen.c
+
+liblzma_la_SOURCES += \
+	check/check.c \
+	check/check.h \
+	check/crc_macros.h
+
+if COND_CHECK_CRC32
+if COND_SMALL
+liblzma_la_SOURCES += check/crc32_small.c
+else
+liblzma_la_SOURCES += \
+	check/crc32_table.c \
+	check/crc32_table_le.h \
+	check/crc32_table_be.h
+if COND_ASM_X86
+liblzma_la_SOURCES += check/crc32_x86.S
+else
+liblzma_la_SOURCES += check/crc32_fast.c
+endif
+endif
+endif
+
+if COND_CHECK_CRC64
+if COND_SMALL
+liblzma_la_SOURCES += check/crc64_small.c
+else
+liblzma_la_SOURCES += \
+	check/crc64_table.c \
+	check/crc64_table_le.h \
+	check/crc64_table_be.h
+if COND_ASM_X86
+liblzma_la_SOURCES += check/crc64_x86.S
+else
+liblzma_la_SOURCES += check/crc64_fast.c
+endif
+endif
+endif
+
+if COND_CHECK_SHA256
+liblzma_la_SOURCES += check/sha256.c
+endif
diff --git a/src/liblzma/check/check.c b/src/liblzma/check/check.c
new file mode 100644
index 0000000..428ddae
--- /dev/null
+++ b/src/liblzma/check/check.c
@@ -0,0 +1,174 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       check.c
+/// \brief      Single API to access different integrity checks
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "check.h"
+
+
+extern LZMA_API(lzma_bool)
+lzma_check_is_supported(lzma_check type)
+{
+	if ((unsigned int)(type) > LZMA_CHECK_ID_MAX)
+		return false;
+
+	static const lzma_bool available_checks[LZMA_CHECK_ID_MAX + 1] = {
+		true,   // LZMA_CHECK_NONE
+
+#ifdef HAVE_CHECK_CRC32
+		true,
+#else
+		false,
+#endif
+
+		false,  // Reserved
+		false,  // Reserved
+
+#ifdef HAVE_CHECK_CRC64
+		true,
+#else
+		false,
+#endif
+
+		false,  // Reserved
+		false,  // Reserved
+		false,  // Reserved
+		false,  // Reserved
+		false,  // Reserved
+
+#ifdef HAVE_CHECK_SHA256
+		true,
+#else
+		false,
+#endif
+
+		false,  // Reserved
+		false,  // Reserved
+		false,  // Reserved
+		false,  // Reserved
+		false,  // Reserved
+	};
+
+	return available_checks[(unsigned int)(type)];
+}
+
+
+extern LZMA_API(uint32_t)
+lzma_check_size(lzma_check type)
+{
+	if ((unsigned int)(type) > LZMA_CHECK_ID_MAX)
+		return UINT32_MAX;
+
+	// See file-format.txt section 2.1.1.2.
+	static const uint8_t check_sizes[LZMA_CHECK_ID_MAX + 1] = {
+		0,
+		4, 4, 4,
+		8, 8, 8,
+		16, 16, 16,
+		32, 32, 32,
+		64, 64, 64
+	};
+
+	return check_sizes[(unsigned int)(type)];
+}
+
+
+extern void
+lzma_check_init(lzma_check_state *check, lzma_check type)
+{
+	switch (type) {
+	case LZMA_CHECK_NONE:
+		break;
+
+#ifdef HAVE_CHECK_CRC32
+	case LZMA_CHECK_CRC32:
+		check->state.crc32 = 0;
+		break;
+#endif
+
+#ifdef HAVE_CHECK_CRC64
+	case LZMA_CHECK_CRC64:
+		check->state.crc64 = 0;
+		break;
+#endif
+
+#ifdef HAVE_CHECK_SHA256
+	case LZMA_CHECK_SHA256:
+		lzma_sha256_init(check);
+		break;
+#endif
+
+	default:
+		break;
+	}
+
+	return;
+}
+
+
+extern void
+lzma_check_update(lzma_check_state *check, lzma_check type,
+		const uint8_t *buf, size_t size)
+{
+	switch (type) {
+#ifdef HAVE_CHECK_CRC32
+	case LZMA_CHECK_CRC32:
+		check->state.crc32 = lzma_crc32(buf, size, check->state.crc32);
+		break;
+#endif
+
+#ifdef HAVE_CHECK_CRC64
+	case LZMA_CHECK_CRC64:
+		check->state.crc64 = lzma_crc64(buf, size, check->state.crc64);
+		break;
+#endif
+
+#ifdef HAVE_CHECK_SHA256
+	case LZMA_CHECK_SHA256:
+		lzma_sha256_update(buf, size, check);
+		break;
+#endif
+
+	default:
+		break;
+	}
+
+	return;
+}
+
+
+extern void
+lzma_check_finish(lzma_check_state *check, lzma_check type)
+{
+	switch (type) {
+#ifdef HAVE_CHECK_CRC32
+	case LZMA_CHECK_CRC32:
+		check->buffer.u32[0] = conv32le(check->state.crc32);
+		break;
+#endif
+
+#ifdef HAVE_CHECK_CRC64
+	case LZMA_CHECK_CRC64:
+		check->buffer.u64[0] = conv64le(check->state.crc64);
+		break;
+#endif
+
+#ifdef HAVE_CHECK_SHA256
+	case LZMA_CHECK_SHA256:
+		lzma_sha256_finish(check);
+		break;
+#endif
+
+	default:
+		break;
+	}
+
+	return;
+}
diff --git a/src/liblzma/check/check.h b/src/liblzma/check/check.h
new file mode 100644
index 0000000..e100d2b
--- /dev/null
+++ b/src/liblzma/check/check.h
@@ -0,0 +1,95 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       check.h
+/// \brief      Internal API to different integrity check functions
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_CHECK_H
+#define LZMA_CHECK_H
+
+#include "common.h"
+
+
+// Index hashing needs the best possible hash function (preferably
+// a cryptographic hash) for maximum reliability.
+#if defined(HAVE_CHECK_SHA256)
+#	define LZMA_CHECK_BEST LZMA_CHECK_SHA256
+#elif defined(HAVE_CHECK_CRC64)
+#	define LZMA_CHECK_BEST LZMA_CHECK_CRC64
+#else
+#	define LZMA_CHECK_BEST LZMA_CHECK_CRC32
+#endif
+
+
+/// \brief      Structure to hold internal state of the check being calculated
+///
+/// \note       This is not in the public API because this structure may
+///             change in future if new integrity check algorithms are added.
+typedef struct {
+	/// Buffer to hold the final result and a temporary buffer for SHA256.
+	union {
+		uint8_t u8[64];
+		uint32_t u32[16];
+		uint64_t u64[8];
+	} buffer;
+
+	/// Check-specific data
+	union {
+		uint32_t crc32;
+		uint64_t crc64;
+
+		struct {
+			/// Internal state
+			uint32_t state[8];
+
+			/// Size of the message excluding padding
+			uint64_t size;
+		} sha256;
+	} state;
+
+} lzma_check_state;
+
+
+/// lzma_crc32_table[0] is needed by LZ encoder so we need to keep
+/// the array two-dimensional.
+#ifdef HAVE_SMALL
+extern uint32_t lzma_crc32_table[1][256];
+extern void lzma_crc32_init(void);
+#else
+extern const uint32_t lzma_crc32_table[8][256];
+extern const uint64_t lzma_crc64_table[4][256];
+#endif
+
+
+/// \brief      Initialize *check depending on type
+///
+/// \return     LZMA_OK on success. LZMA_UNSUPPORTED_CHECK if the type is not
+///             supported by the current version or build of liblzma.
+///             LZMA_PROG_ERROR if type > LZMA_CHECK_ID_MAX.
+extern void lzma_check_init(lzma_check_state *check, lzma_check type);
+
+/// Update the check state
+extern void lzma_check_update(lzma_check_state *check, lzma_check type,
+		const uint8_t *buf, size_t size);
+
+/// Finish the check calculation and store the result to check->buffer.u8.
+extern void lzma_check_finish(lzma_check_state *check, lzma_check type);
+
+
+/// Prepare SHA-256 state for new input.
+extern void lzma_sha256_init(lzma_check_state *check);
+
+/// Update the SHA-256 hash state
+extern void lzma_sha256_update(
+		const uint8_t *buf, size_t size, lzma_check_state *check);
+
+/// Finish the SHA-256 calculation and store the result to check->buffer.u8.
+extern void lzma_sha256_finish(lzma_check_state *check);
+
+#endif
diff --git a/src/liblzma/check/crc32_fast.c b/src/liblzma/check/crc32_fast.c
new file mode 100644
index 0000000..94da855
--- /dev/null
+++ b/src/liblzma/check/crc32_fast.c
@@ -0,0 +1,82 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       crc32.c
+/// \brief      CRC32 calculation
+///
+/// Calculate the CRC32 using the slice-by-eight algorithm.
+/// It is explained in this document:
+/// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
+/// The code in this file is not the same as in Intel's paper, but
+/// the basic principle is identical.
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "check.h"
+#include "crc_macros.h"
+
+
+// If you make any changes, do some bench marking! Seemingly unrelated
+// changes can very easily ruin the performance (and very probably is
+// very compiler dependent).
+extern LZMA_API(uint32_t)
+lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc)
+{
+	crc = ~crc;
+
+#ifdef WORDS_BIGENDIAN
+	crc = bswap32(crc);
+#endif
+
+	if (size > 8) {
+		// Fix the alignment, if needed. The if statement above
+		// ensures that this won't read past the end of buf[].
+		while ((uintptr_t)(buf) & 7) {
+			crc = lzma_crc32_table[0][*buf++ ^ A(crc)] ^ S8(crc);
+			--size;
+		}
+
+		// Calculate the position where to stop.
+		const uint8_t *const limit = buf + (size & ~(size_t)(7));
+
+		// Calculate how many bytes must be calculated separately
+		// before returning the result.
+		size &= (size_t)(7);
+
+		// Calculate the CRC32 using the slice-by-eight algorithm.
+		while (buf < limit) {
+			crc ^= *(const uint32_t *)(buf);
+			buf += 4;
+
+			crc = lzma_crc32_table[7][A(crc)]
+			    ^ lzma_crc32_table[6][B(crc)]
+			    ^ lzma_crc32_table[5][C(crc)]
+			    ^ lzma_crc32_table[4][D(crc)];
+
+			const uint32_t tmp = *(const uint32_t *)(buf);
+			buf += 4;
+
+			// At least with some compilers, it is critical for
+			// performance, that the crc variable is XORed
+			// between the two table-lookup pairs.
+			crc = lzma_crc32_table[3][A(tmp)]
+			    ^ lzma_crc32_table[2][B(tmp)]
+			    ^ crc
+			    ^ lzma_crc32_table[1][C(tmp)]
+			    ^ lzma_crc32_table[0][D(tmp)];
+		}
+	}
+
+	while (size-- != 0)
+		crc = lzma_crc32_table[0][*buf++ ^ A(crc)] ^ S8(crc);
+
+#ifdef WORDS_BIGENDIAN
+	crc = bswap32(crc);
+#endif
+
+	return ~crc;
+}
diff --git a/src/liblzma/check/crc32_small.c b/src/liblzma/check/crc32_small.c
new file mode 100644
index 0000000..5f8a328
--- /dev/null
+++ b/src/liblzma/check/crc32_small.c
@@ -0,0 +1,61 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       crc32_small.c
+/// \brief      CRC32 calculation (size-optimized)
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "check.h"
+
+
+uint32_t lzma_crc32_table[1][256];
+
+
+static void
+crc32_init(void)
+{
+	static const uint32_t poly32 = UINT32_C(0xEDB88320);
+
+	for (size_t b = 0; b < 256; ++b) {
+		uint32_t r = b;
+		for (size_t i = 0; i < 8; ++i) {
+			if (r & 1)
+				r = (r >> 1) ^ poly32;
+			else
+				r >>= 1;
+		}
+
+		lzma_crc32_table[0][b] = r;
+	}
+
+	return;
+}
+
+
+extern void
+lzma_crc32_init(void)
+{
+	mythread_once(crc32_init);
+	return;
+}
+
+
+extern LZMA_API(uint32_t)
+lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc)
+{
+	lzma_crc32_init();
+
+	crc = ~crc;
+
+	while (size != 0) {
+		crc = lzma_crc32_table[0][*buf++ ^ (crc & 0xFF)] ^ (crc >> 8);
+		--size;
+	}
+
+	return ~crc;
+}
diff --git a/src/liblzma/check/crc32_table.c b/src/liblzma/check/crc32_table.c
new file mode 100644
index 0000000..368874e
--- /dev/null
+++ b/src/liblzma/check/crc32_table.c
@@ -0,0 +1,19 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       crc32_table.c
+/// \brief      Precalculated CRC32 table with correct endianness
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+
+#ifdef WORDS_BIGENDIAN
+#	include "crc32_table_be.h"
+#else
+#	include "crc32_table_le.h"
+#endif
diff --git a/src/liblzma/check/crc32_table_be.h b/src/liblzma/check/crc32_table_be.h
new file mode 100644
index 0000000..c483cb6
--- /dev/null
+++ b/src/liblzma/check/crc32_table_be.h
@@ -0,0 +1,525 @@
+/* This file has been automatically generated by crc32_tablegen.c. */
+
+const uint32_t lzma_crc32_table[8][256] = {
+	{
+		0x00000000, 0x96300777, 0x2C610EEE, 0xBA510999,
+		0x19C46D07, 0x8FF46A70, 0x35A563E9, 0xA395649E,
+		0x3288DB0E, 0xA4B8DC79, 0x1EE9D5E0, 0x88D9D297,
+		0x2B4CB609, 0xBD7CB17E, 0x072DB8E7, 0x911DBF90,
+		0x6410B71D, 0xF220B06A, 0x4871B9F3, 0xDE41BE84,
+		0x7DD4DA1A, 0xEBE4DD6D, 0x51B5D4F4, 0xC785D383,
+		0x56986C13, 0xC0A86B64, 0x7AF962FD, 0xECC9658A,
+		0x4F5C0114, 0xD96C0663, 0x633D0FFA, 0xF50D088D,
+		0xC8206E3B, 0x5E10694C, 0xE44160D5, 0x727167A2,
+		0xD1E4033C, 0x47D4044B, 0xFD850DD2, 0x6BB50AA5,
+		0xFAA8B535, 0x6C98B242, 0xD6C9BBDB, 0x40F9BCAC,
+		0xE36CD832, 0x755CDF45, 0xCF0DD6DC, 0x593DD1AB,
+		0xAC30D926, 0x3A00DE51, 0x8051D7C8, 0x1661D0BF,
+		0xB5F4B421, 0x23C4B356, 0x9995BACF, 0x0FA5BDB8,
+		0x9EB80228, 0x0888055F, 0xB2D90CC6, 0x24E90BB1,
+		0x877C6F2F, 0x114C6858, 0xAB1D61C1, 0x3D2D66B6,
+		0x9041DC76, 0x0671DB01, 0xBC20D298, 0x2A10D5EF,
+		0x8985B171, 0x1FB5B606, 0xA5E4BF9F, 0x33D4B8E8,
+		0xA2C90778, 0x34F9000F, 0x8EA80996, 0x18980EE1,
+		0xBB0D6A7F, 0x2D3D6D08, 0x976C6491, 0x015C63E6,
+		0xF4516B6B, 0x62616C1C, 0xD8306585, 0x4E0062F2,
+		0xED95066C, 0x7BA5011B, 0xC1F40882, 0x57C40FF5,
+		0xC6D9B065, 0x50E9B712, 0xEAB8BE8B, 0x7C88B9FC,
+		0xDF1DDD62, 0x492DDA15, 0xF37CD38C, 0x654CD4FB,
+		0x5861B24D, 0xCE51B53A, 0x7400BCA3, 0xE230BBD4,
+		0x41A5DF4A, 0xD795D83D, 0x6DC4D1A4, 0xFBF4D6D3,
+		0x6AE96943, 0xFCD96E34, 0x468867AD, 0xD0B860DA,
+		0x732D0444, 0xE51D0333, 0x5F4C0AAA, 0xC97C0DDD,
+		0x3C710550, 0xAA410227, 0x10100BBE, 0x86200CC9,
+		0x25B56857, 0xB3856F20, 0x09D466B9, 0x9FE461CE,
+		0x0EF9DE5E, 0x98C9D929, 0x2298D0B0, 0xB4A8D7C7,
+		0x173DB359, 0x810DB42E, 0x3B5CBDB7, 0xAD6CBAC0,
+		0x2083B8ED, 0xB6B3BF9A, 0x0CE2B603, 0x9AD2B174,
+		0x3947D5EA, 0xAF77D29D, 0x1526DB04, 0x8316DC73,
+		0x120B63E3, 0x843B6494, 0x3E6A6D0D, 0xA85A6A7A,
+		0x0BCF0EE4, 0x9DFF0993, 0x27AE000A, 0xB19E077D,
+		0x44930FF0, 0xD2A30887, 0x68F2011E, 0xFEC20669,
+		0x5D5762F7, 0xCB676580, 0x71366C19, 0xE7066B6E,
+		0x761BD4FE, 0xE02BD389, 0x5A7ADA10, 0xCC4ADD67,
+		0x6FDFB9F9, 0xF9EFBE8E, 0x43BEB717, 0xD58EB060,
+		0xE8A3D6D6, 0x7E93D1A1, 0xC4C2D838, 0x52F2DF4F,
+		0xF167BBD1, 0x6757BCA6, 0xDD06B53F, 0x4B36B248,
+		0xDA2B0DD8, 0x4C1B0AAF, 0xF64A0336, 0x607A0441,
+		0xC3EF60DF, 0x55DF67A8, 0xEF8E6E31, 0x79BE6946,
+		0x8CB361CB, 0x1A8366BC, 0xA0D26F25, 0x36E26852,
+		0x95770CCC, 0x03470BBB, 0xB9160222, 0x2F260555,
+		0xBE3BBAC5, 0x280BBDB2, 0x925AB42B, 0x046AB35C,
+		0xA7FFD7C2, 0x31CFD0B5, 0x8B9ED92C, 0x1DAEDE5B,
+		0xB0C2649B, 0x26F263EC, 0x9CA36A75, 0x0A936D02,
+		0xA906099C, 0x3F360EEB, 0x85670772, 0x13570005,
+		0x824ABF95, 0x147AB8E2, 0xAE2BB17B, 0x381BB60C,
+		0x9B8ED292, 0x0DBED5E5, 0xB7EFDC7C, 0x21DFDB0B,
+		0xD4D2D386, 0x42E2D4F1, 0xF8B3DD68, 0x6E83DA1F,
+		0xCD16BE81, 0x5B26B9F6, 0xE177B06F, 0x7747B718,
+		0xE65A0888, 0x706A0FFF, 0xCA3B0666, 0x5C0B0111,
+		0xFF9E658F, 0x69AE62F8, 0xD3FF6B61, 0x45CF6C16,
+		0x78E20AA0, 0xEED20DD7, 0x5483044E, 0xC2B30339,
+		0x612667A7, 0xF71660D0, 0x4D476949, 0xDB776E3E,
+		0x4A6AD1AE, 0xDC5AD6D9, 0x660BDF40, 0xF03BD837,
+		0x53AEBCA9, 0xC59EBBDE, 0x7FCFB247, 0xE9FFB530,
+		0x1CF2BDBD, 0x8AC2BACA, 0x3093B353, 0xA6A3B424,
+		0x0536D0BA, 0x9306D7CD, 0x2957DE54, 0xBF67D923,
+		0x2E7A66B3, 0xB84A61C4, 0x021B685D, 0x942B6F2A,
+		0x37BE0BB4, 0xA18E0CC3, 0x1BDF055A, 0x8DEF022D
+	}, {
+		0x00000000, 0x41311B19, 0x82623632, 0xC3532D2B,
+		0x04C56C64, 0x45F4777D, 0x86A75A56, 0xC796414F,
+		0x088AD9C8, 0x49BBC2D1, 0x8AE8EFFA, 0xCBD9F4E3,
+		0x0C4FB5AC, 0x4D7EAEB5, 0x8E2D839E, 0xCF1C9887,
+		0x5112C24A, 0x1023D953, 0xD370F478, 0x9241EF61,
+		0x55D7AE2E, 0x14E6B537, 0xD7B5981C, 0x96848305,
+		0x59981B82, 0x18A9009B, 0xDBFA2DB0, 0x9ACB36A9,
+		0x5D5D77E6, 0x1C6C6CFF, 0xDF3F41D4, 0x9E0E5ACD,
+		0xA2248495, 0xE3159F8C, 0x2046B2A7, 0x6177A9BE,
+		0xA6E1E8F1, 0xE7D0F3E8, 0x2483DEC3, 0x65B2C5DA,
+		0xAAAE5D5D, 0xEB9F4644, 0x28CC6B6F, 0x69FD7076,
+		0xAE6B3139, 0xEF5A2A20, 0x2C09070B, 0x6D381C12,
+		0xF33646DF, 0xB2075DC6, 0x715470ED, 0x30656BF4,
+		0xF7F32ABB, 0xB6C231A2, 0x75911C89, 0x34A00790,
+		0xFBBC9F17, 0xBA8D840E, 0x79DEA925, 0x38EFB23C,
+		0xFF79F373, 0xBE48E86A, 0x7D1BC541, 0x3C2ADE58,
+		0x054F79F0, 0x447E62E9, 0x872D4FC2, 0xC61C54DB,
+		0x018A1594, 0x40BB0E8D, 0x83E823A6, 0xC2D938BF,
+		0x0DC5A038, 0x4CF4BB21, 0x8FA7960A, 0xCE968D13,
+		0x0900CC5C, 0x4831D745, 0x8B62FA6E, 0xCA53E177,
+		0x545DBBBA, 0x156CA0A3, 0xD63F8D88, 0x970E9691,
+		0x5098D7DE, 0x11A9CCC7, 0xD2FAE1EC, 0x93CBFAF5,
+		0x5CD76272, 0x1DE6796B, 0xDEB55440, 0x9F844F59,
+		0x58120E16, 0x1923150F, 0xDA703824, 0x9B41233D,
+		0xA76BFD65, 0xE65AE67C, 0x2509CB57, 0x6438D04E,
+		0xA3AE9101, 0xE29F8A18, 0x21CCA733, 0x60FDBC2A,
+		0xAFE124AD, 0xEED03FB4, 0x2D83129F, 0x6CB20986,
+		0xAB2448C9, 0xEA1553D0, 0x29467EFB, 0x687765E2,
+		0xF6793F2F, 0xB7482436, 0x741B091D, 0x352A1204,
+		0xF2BC534B, 0xB38D4852, 0x70DE6579, 0x31EF7E60,
+		0xFEF3E6E7, 0xBFC2FDFE, 0x7C91D0D5, 0x3DA0CBCC,
+		0xFA368A83, 0xBB07919A, 0x7854BCB1, 0x3965A7A8,
+		0x4B98833B, 0x0AA99822, 0xC9FAB509, 0x88CBAE10,
+		0x4F5DEF5F, 0x0E6CF446, 0xCD3FD96D, 0x8C0EC274,
+		0x43125AF3, 0x022341EA, 0xC1706CC1, 0x804177D8,
+		0x47D73697, 0x06E62D8E, 0xC5B500A5, 0x84841BBC,
+		0x1A8A4171, 0x5BBB5A68, 0x98E87743, 0xD9D96C5A,
+		0x1E4F2D15, 0x5F7E360C, 0x9C2D1B27, 0xDD1C003E,
+		0x120098B9, 0x533183A0, 0x9062AE8B, 0xD153B592,
+		0x16C5F4DD, 0x57F4EFC4, 0x94A7C2EF, 0xD596D9F6,
+		0xE9BC07AE, 0xA88D1CB7, 0x6BDE319C, 0x2AEF2A85,
+		0xED796BCA, 0xAC4870D3, 0x6F1B5DF8, 0x2E2A46E1,
+		0xE136DE66, 0xA007C57F, 0x6354E854, 0x2265F34D,
+		0xE5F3B202, 0xA4C2A91B, 0x67918430, 0x26A09F29,
+		0xB8AEC5E4, 0xF99FDEFD, 0x3ACCF3D6, 0x7BFDE8CF,
+		0xBC6BA980, 0xFD5AB299, 0x3E099FB2, 0x7F3884AB,
+		0xB0241C2C, 0xF1150735, 0x32462A1E, 0x73773107,
+		0xB4E17048, 0xF5D06B51, 0x3683467A, 0x77B25D63,
+		0x4ED7FACB, 0x0FE6E1D2, 0xCCB5CCF9, 0x8D84D7E0,
+		0x4A1296AF, 0x0B238DB6, 0xC870A09D, 0x8941BB84,
+		0x465D2303, 0x076C381A, 0xC43F1531, 0x850E0E28,
+		0x42984F67, 0x03A9547E, 0xC0FA7955, 0x81CB624C,
+		0x1FC53881, 0x5EF42398, 0x9DA70EB3, 0xDC9615AA,
+		0x1B0054E5, 0x5A314FFC, 0x996262D7, 0xD85379CE,
+		0x174FE149, 0x567EFA50, 0x952DD77B, 0xD41CCC62,
+		0x138A8D2D, 0x52BB9634, 0x91E8BB1F, 0xD0D9A006,
+		0xECF37E5E, 0xADC26547, 0x6E91486C, 0x2FA05375,
+		0xE836123A, 0xA9070923, 0x6A542408, 0x2B653F11,
+		0xE479A796, 0xA548BC8F, 0x661B91A4, 0x272A8ABD,
+		0xE0BCCBF2, 0xA18DD0EB, 0x62DEFDC0, 0x23EFE6D9,
+		0xBDE1BC14, 0xFCD0A70D, 0x3F838A26, 0x7EB2913F,
+		0xB924D070, 0xF815CB69, 0x3B46E642, 0x7A77FD5B,
+		0xB56B65DC, 0xF45A7EC5, 0x370953EE, 0x763848F7,
+		0xB1AE09B8, 0xF09F12A1, 0x33CC3F8A, 0x72FD2493
+	}, {
+		0x00000000, 0x376AC201, 0x6ED48403, 0x59BE4602,
+		0xDCA80907, 0xEBC2CB06, 0xB27C8D04, 0x85164F05,
+		0xB851130E, 0x8F3BD10F, 0xD685970D, 0xE1EF550C,
+		0x64F91A09, 0x5393D808, 0x0A2D9E0A, 0x3D475C0B,
+		0x70A3261C, 0x47C9E41D, 0x1E77A21F, 0x291D601E,
+		0xAC0B2F1B, 0x9B61ED1A, 0xC2DFAB18, 0xF5B56919,
+		0xC8F23512, 0xFF98F713, 0xA626B111, 0x914C7310,
+		0x145A3C15, 0x2330FE14, 0x7A8EB816, 0x4DE47A17,
+		0xE0464D38, 0xD72C8F39, 0x8E92C93B, 0xB9F80B3A,
+		0x3CEE443F, 0x0B84863E, 0x523AC03C, 0x6550023D,
+		0x58175E36, 0x6F7D9C37, 0x36C3DA35, 0x01A91834,
+		0x84BF5731, 0xB3D59530, 0xEA6BD332, 0xDD011133,
+		0x90E56B24, 0xA78FA925, 0xFE31EF27, 0xC95B2D26,
+		0x4C4D6223, 0x7B27A022, 0x2299E620, 0x15F32421,
+		0x28B4782A, 0x1FDEBA2B, 0x4660FC29, 0x710A3E28,
+		0xF41C712D, 0xC376B32C, 0x9AC8F52E, 0xADA2372F,
+		0xC08D9A70, 0xF7E75871, 0xAE591E73, 0x9933DC72,
+		0x1C259377, 0x2B4F5176, 0x72F11774, 0x459BD575,
+		0x78DC897E, 0x4FB64B7F, 0x16080D7D, 0x2162CF7C,
+		0xA4748079, 0x931E4278, 0xCAA0047A, 0xFDCAC67B,
+		0xB02EBC6C, 0x87447E6D, 0xDEFA386F, 0xE990FA6E,
+		0x6C86B56B, 0x5BEC776A, 0x02523168, 0x3538F369,
+		0x087FAF62, 0x3F156D63, 0x66AB2B61, 0x51C1E960,
+		0xD4D7A665, 0xE3BD6464, 0xBA032266, 0x8D69E067,
+		0x20CBD748, 0x17A11549, 0x4E1F534B, 0x7975914A,
+		0xFC63DE4F, 0xCB091C4E, 0x92B75A4C, 0xA5DD984D,
+		0x989AC446, 0xAFF00647, 0xF64E4045, 0xC1248244,
+		0x4432CD41, 0x73580F40, 0x2AE64942, 0x1D8C8B43,
+		0x5068F154, 0x67023355, 0x3EBC7557, 0x09D6B756,
+		0x8CC0F853, 0xBBAA3A52, 0xE2147C50, 0xD57EBE51,
+		0xE839E25A, 0xDF53205B, 0x86ED6659, 0xB187A458,
+		0x3491EB5D, 0x03FB295C, 0x5A456F5E, 0x6D2FAD5F,
+		0x801B35E1, 0xB771F7E0, 0xEECFB1E2, 0xD9A573E3,
+		0x5CB33CE6, 0x6BD9FEE7, 0x3267B8E5, 0x050D7AE4,
+		0x384A26EF, 0x0F20E4EE, 0x569EA2EC, 0x61F460ED,
+		0xE4E22FE8, 0xD388EDE9, 0x8A36ABEB, 0xBD5C69EA,
+		0xF0B813FD, 0xC7D2D1FC, 0x9E6C97FE, 0xA90655FF,
+		0x2C101AFA, 0x1B7AD8FB, 0x42C49EF9, 0x75AE5CF8,
+		0x48E900F3, 0x7F83C2F2, 0x263D84F0, 0x115746F1,
+		0x944109F4, 0xA32BCBF5, 0xFA958DF7, 0xCDFF4FF6,
+		0x605D78D9, 0x5737BAD8, 0x0E89FCDA, 0x39E33EDB,
+		0xBCF571DE, 0x8B9FB3DF, 0xD221F5DD, 0xE54B37DC,
+		0xD80C6BD7, 0xEF66A9D6, 0xB6D8EFD4, 0x81B22DD5,
+		0x04A462D0, 0x33CEA0D1, 0x6A70E6D3, 0x5D1A24D2,
+		0x10FE5EC5, 0x27949CC4, 0x7E2ADAC6, 0x494018C7,
+		0xCC5657C2, 0xFB3C95C3, 0xA282D3C1, 0x95E811C0,
+		0xA8AF4DCB, 0x9FC58FCA, 0xC67BC9C8, 0xF1110BC9,
+		0x740744CC, 0x436D86CD, 0x1AD3C0CF, 0x2DB902CE,
+		0x4096AF91, 0x77FC6D90, 0x2E422B92, 0x1928E993,
+		0x9C3EA696, 0xAB546497, 0xF2EA2295, 0xC580E094,
+		0xF8C7BC9F, 0xCFAD7E9E, 0x9613389C, 0xA179FA9D,
+		0x246FB598, 0x13057799, 0x4ABB319B, 0x7DD1F39A,
+		0x3035898D, 0x075F4B8C, 0x5EE10D8E, 0x698BCF8F,
+		0xEC9D808A, 0xDBF7428B, 0x82490489, 0xB523C688,
+		0x88649A83, 0xBF0E5882, 0xE6B01E80, 0xD1DADC81,
+		0x54CC9384, 0x63A65185, 0x3A181787, 0x0D72D586,
+		0xA0D0E2A9, 0x97BA20A8, 0xCE0466AA, 0xF96EA4AB,
+		0x7C78EBAE, 0x4B1229AF, 0x12AC6FAD, 0x25C6ADAC,
+		0x1881F1A7, 0x2FEB33A6, 0x765575A4, 0x413FB7A5,
+		0xC429F8A0, 0xF3433AA1, 0xAAFD7CA3, 0x9D97BEA2,
+		0xD073C4B5, 0xE71906B4, 0xBEA740B6, 0x89CD82B7,
+		0x0CDBCDB2, 0x3BB10FB3, 0x620F49B1, 0x55658BB0,
+		0x6822D7BB, 0x5F4815BA, 0x06F653B8, 0x319C91B9,
+		0xB48ADEBC, 0x83E01CBD, 0xDA5E5ABF, 0xED3498BE
+	}, {
+		0x00000000, 0x6567BCB8, 0x8BC809AA, 0xEEAFB512,
+		0x5797628F, 0x32F0DE37, 0xDC5F6B25, 0xB938D79D,
+		0xEF28B4C5, 0x8A4F087D, 0x64E0BD6F, 0x018701D7,
+		0xB8BFD64A, 0xDDD86AF2, 0x3377DFE0, 0x56106358,
+		0x9F571950, 0xFA30A5E8, 0x149F10FA, 0x71F8AC42,
+		0xC8C07BDF, 0xADA7C767, 0x43087275, 0x266FCECD,
+		0x707FAD95, 0x1518112D, 0xFBB7A43F, 0x9ED01887,
+		0x27E8CF1A, 0x428F73A2, 0xAC20C6B0, 0xC9477A08,
+		0x3EAF32A0, 0x5BC88E18, 0xB5673B0A, 0xD00087B2,
+		0x6938502F, 0x0C5FEC97, 0xE2F05985, 0x8797E53D,
+		0xD1878665, 0xB4E03ADD, 0x5A4F8FCF, 0x3F283377,
+		0x8610E4EA, 0xE3775852, 0x0DD8ED40, 0x68BF51F8,
+		0xA1F82BF0, 0xC49F9748, 0x2A30225A, 0x4F579EE2,
+		0xF66F497F, 0x9308F5C7, 0x7DA740D5, 0x18C0FC6D,
+		0x4ED09F35, 0x2BB7238D, 0xC518969F, 0xA07F2A27,
+		0x1947FDBA, 0x7C204102, 0x928FF410, 0xF7E848A8,
+		0x3D58149B, 0x583FA823, 0xB6901D31, 0xD3F7A189,
+		0x6ACF7614, 0x0FA8CAAC, 0xE1077FBE, 0x8460C306,
+		0xD270A05E, 0xB7171CE6, 0x59B8A9F4, 0x3CDF154C,
+		0x85E7C2D1, 0xE0807E69, 0x0E2FCB7B, 0x6B4877C3,
+		0xA20F0DCB, 0xC768B173, 0x29C70461, 0x4CA0B8D9,
+		0xF5986F44, 0x90FFD3FC, 0x7E5066EE, 0x1B37DA56,
+		0x4D27B90E, 0x284005B6, 0xC6EFB0A4, 0xA3880C1C,
+		0x1AB0DB81, 0x7FD76739, 0x9178D22B, 0xF41F6E93,
+		0x03F7263B, 0x66909A83, 0x883F2F91, 0xED589329,
+		0x546044B4, 0x3107F80C, 0xDFA84D1E, 0xBACFF1A6,
+		0xECDF92FE, 0x89B82E46, 0x67179B54, 0x027027EC,
+		0xBB48F071, 0xDE2F4CC9, 0x3080F9DB, 0x55E74563,
+		0x9CA03F6B, 0xF9C783D3, 0x176836C1, 0x720F8A79,
+		0xCB375DE4, 0xAE50E15C, 0x40FF544E, 0x2598E8F6,
+		0x73888BAE, 0x16EF3716, 0xF8408204, 0x9D273EBC,
+		0x241FE921, 0x41785599, 0xAFD7E08B, 0xCAB05C33,
+		0x3BB659ED, 0x5ED1E555, 0xB07E5047, 0xD519ECFF,
+		0x6C213B62, 0x094687DA, 0xE7E932C8, 0x828E8E70,
+		0xD49EED28, 0xB1F95190, 0x5F56E482, 0x3A31583A,
+		0x83098FA7, 0xE66E331F, 0x08C1860D, 0x6DA63AB5,
+		0xA4E140BD, 0xC186FC05, 0x2F294917, 0x4A4EF5AF,
+		0xF3762232, 0x96119E8A, 0x78BE2B98, 0x1DD99720,
+		0x4BC9F478, 0x2EAE48C0, 0xC001FDD2, 0xA566416A,
+		0x1C5E96F7, 0x79392A4F, 0x97969F5D, 0xF2F123E5,
+		0x05196B4D, 0x607ED7F5, 0x8ED162E7, 0xEBB6DE5F,
+		0x528E09C2, 0x37E9B57A, 0xD9460068, 0xBC21BCD0,
+		0xEA31DF88, 0x8F566330, 0x61F9D622, 0x049E6A9A,
+		0xBDA6BD07, 0xD8C101BF, 0x366EB4AD, 0x53090815,
+		0x9A4E721D, 0xFF29CEA5, 0x11867BB7, 0x74E1C70F,
+		0xCDD91092, 0xA8BEAC2A, 0x46111938, 0x2376A580,
+		0x7566C6D8, 0x10017A60, 0xFEAECF72, 0x9BC973CA,
+		0x22F1A457, 0x479618EF, 0xA939ADFD, 0xCC5E1145,
+		0x06EE4D76, 0x6389F1CE, 0x8D2644DC, 0xE841F864,
+		0x51792FF9, 0x341E9341, 0xDAB12653, 0xBFD69AEB,
+		0xE9C6F9B3, 0x8CA1450B, 0x620EF019, 0x07694CA1,
+		0xBE519B3C, 0xDB362784, 0x35999296, 0x50FE2E2E,
+		0x99B95426, 0xFCDEE89E, 0x12715D8C, 0x7716E134,
+		0xCE2E36A9, 0xAB498A11, 0x45E63F03, 0x208183BB,
+		0x7691E0E3, 0x13F65C5B, 0xFD59E949, 0x983E55F1,
+		0x2106826C, 0x44613ED4, 0xAACE8BC6, 0xCFA9377E,
+		0x38417FD6, 0x5D26C36E, 0xB389767C, 0xD6EECAC4,
+		0x6FD61D59, 0x0AB1A1E1, 0xE41E14F3, 0x8179A84B,
+		0xD769CB13, 0xB20E77AB, 0x5CA1C2B9, 0x39C67E01,
+		0x80FEA99C, 0xE5991524, 0x0B36A036, 0x6E511C8E,
+		0xA7166686, 0xC271DA3E, 0x2CDE6F2C, 0x49B9D394,
+		0xF0810409, 0x95E6B8B1, 0x7B490DA3, 0x1E2EB11B,
+		0x483ED243, 0x2D596EFB, 0xC3F6DBE9, 0xA6916751,
+		0x1FA9B0CC, 0x7ACE0C74, 0x9461B966, 0xF10605DE
+	}, {
+		0x00000000, 0xB029603D, 0x6053C07A, 0xD07AA047,
+		0xC0A680F5, 0x708FE0C8, 0xA0F5408F, 0x10DC20B2,
+		0xC14B7030, 0x7162100D, 0xA118B04A, 0x1131D077,
+		0x01EDF0C5, 0xB1C490F8, 0x61BE30BF, 0xD1975082,
+		0x8297E060, 0x32BE805D, 0xE2C4201A, 0x52ED4027,
+		0x42316095, 0xF21800A8, 0x2262A0EF, 0x924BC0D2,
+		0x43DC9050, 0xF3F5F06D, 0x238F502A, 0x93A63017,
+		0x837A10A5, 0x33537098, 0xE329D0DF, 0x5300B0E2,
+		0x042FC1C1, 0xB406A1FC, 0x647C01BB, 0xD4556186,
+		0xC4894134, 0x74A02109, 0xA4DA814E, 0x14F3E173,
+		0xC564B1F1, 0x754DD1CC, 0xA537718B, 0x151E11B6,
+		0x05C23104, 0xB5EB5139, 0x6591F17E, 0xD5B89143,
+		0x86B821A1, 0x3691419C, 0xE6EBE1DB, 0x56C281E6,
+		0x461EA154, 0xF637C169, 0x264D612E, 0x96640113,
+		0x47F35191, 0xF7DA31AC, 0x27A091EB, 0x9789F1D6,
+		0x8755D164, 0x377CB159, 0xE706111E, 0x572F7123,
+		0x4958F358, 0xF9719365, 0x290B3322, 0x9922531F,
+		0x89FE73AD, 0x39D71390, 0xE9ADB3D7, 0x5984D3EA,
+		0x88138368, 0x383AE355, 0xE8404312, 0x5869232F,
+		0x48B5039D, 0xF89C63A0, 0x28E6C3E7, 0x98CFA3DA,
+		0xCBCF1338, 0x7BE67305, 0xAB9CD342, 0x1BB5B37F,
+		0x0B6993CD, 0xBB40F3F0, 0x6B3A53B7, 0xDB13338A,
+		0x0A846308, 0xBAAD0335, 0x6AD7A372, 0xDAFEC34F,
+		0xCA22E3FD, 0x7A0B83C0, 0xAA712387, 0x1A5843BA,
+		0x4D773299, 0xFD5E52A4, 0x2D24F2E3, 0x9D0D92DE,
+		0x8DD1B26C, 0x3DF8D251, 0xED827216, 0x5DAB122B,
+		0x8C3C42A9, 0x3C152294, 0xEC6F82D3, 0x5C46E2EE,
+		0x4C9AC25C, 0xFCB3A261, 0x2CC90226, 0x9CE0621B,
+		0xCFE0D2F9, 0x7FC9B2C4, 0xAFB31283, 0x1F9A72BE,
+		0x0F46520C, 0xBF6F3231, 0x6F159276, 0xDF3CF24B,
+		0x0EABA2C9, 0xBE82C2F4, 0x6EF862B3, 0xDED1028E,
+		0xCE0D223C, 0x7E244201, 0xAE5EE246, 0x1E77827B,
+		0x92B0E6B1, 0x2299868C, 0xF2E326CB, 0x42CA46F6,
+		0x52166644, 0xE23F0679, 0x3245A63E, 0x826CC603,
+		0x53FB9681, 0xE3D2F6BC, 0x33A856FB, 0x838136C6,
+		0x935D1674, 0x23747649, 0xF30ED60E, 0x4327B633,
+		0x102706D1, 0xA00E66EC, 0x7074C6AB, 0xC05DA696,
+		0xD0818624, 0x60A8E619, 0xB0D2465E, 0x00FB2663,
+		0xD16C76E1, 0x614516DC, 0xB13FB69B, 0x0116D6A6,
+		0x11CAF614, 0xA1E39629, 0x7199366E, 0xC1B05653,
+		0x969F2770, 0x26B6474D, 0xF6CCE70A, 0x46E58737,
+		0x5639A785, 0xE610C7B8, 0x366A67FF, 0x864307C2,
+		0x57D45740, 0xE7FD377D, 0x3787973A, 0x87AEF707,
+		0x9772D7B5, 0x275BB788, 0xF72117CF, 0x470877F2,
+		0x1408C710, 0xA421A72D, 0x745B076A, 0xC4726757,
+		0xD4AE47E5, 0x648727D8, 0xB4FD879F, 0x04D4E7A2,
+		0xD543B720, 0x656AD71D, 0xB510775A, 0x05391767,
+		0x15E537D5, 0xA5CC57E8, 0x75B6F7AF, 0xC59F9792,
+		0xDBE815E9, 0x6BC175D4, 0xBBBBD593, 0x0B92B5AE,
+		0x1B4E951C, 0xAB67F521, 0x7B1D5566, 0xCB34355B,
+		0x1AA365D9, 0xAA8A05E4, 0x7AF0A5A3, 0xCAD9C59E,
+		0xDA05E52C, 0x6A2C8511, 0xBA562556, 0x0A7F456B,
+		0x597FF589, 0xE95695B4, 0x392C35F3, 0x890555CE,
+		0x99D9757C, 0x29F01541, 0xF98AB506, 0x49A3D53B,
+		0x983485B9, 0x281DE584, 0xF86745C3, 0x484E25FE,
+		0x5892054C, 0xE8BB6571, 0x38C1C536, 0x88E8A50B,
+		0xDFC7D428, 0x6FEEB415, 0xBF941452, 0x0FBD746F,
+		0x1F6154DD, 0xAF4834E0, 0x7F3294A7, 0xCF1BF49A,
+		0x1E8CA418, 0xAEA5C425, 0x7EDF6462, 0xCEF6045F,
+		0xDE2A24ED, 0x6E0344D0, 0xBE79E497, 0x0E5084AA,
+		0x5D503448, 0xED795475, 0x3D03F432, 0x8D2A940F,
+		0x9DF6B4BD, 0x2DDFD480, 0xFDA574C7, 0x4D8C14FA,
+		0x9C1B4478, 0x2C322445, 0xFC488402, 0x4C61E43F,
+		0x5CBDC48D, 0xEC94A4B0, 0x3CEE04F7, 0x8CC764CA
+	}, {
+		0x00000000, 0xA5D35CCB, 0x0BA1C84D, 0xAE729486,
+		0x1642919B, 0xB391CD50, 0x1DE359D6, 0xB830051D,
+		0x6D8253EC, 0xC8510F27, 0x66239BA1, 0xC3F0C76A,
+		0x7BC0C277, 0xDE139EBC, 0x70610A3A, 0xD5B256F1,
+		0x9B02D603, 0x3ED18AC8, 0x90A31E4E, 0x35704285,
+		0x8D404798, 0x28931B53, 0x86E18FD5, 0x2332D31E,
+		0xF68085EF, 0x5353D924, 0xFD214DA2, 0x58F21169,
+		0xE0C21474, 0x451148BF, 0xEB63DC39, 0x4EB080F2,
+		0x3605AC07, 0x93D6F0CC, 0x3DA4644A, 0x98773881,
+		0x20473D9C, 0x85946157, 0x2BE6F5D1, 0x8E35A91A,
+		0x5B87FFEB, 0xFE54A320, 0x502637A6, 0xF5F56B6D,
+		0x4DC56E70, 0xE81632BB, 0x4664A63D, 0xE3B7FAF6,
+		0xAD077A04, 0x08D426CF, 0xA6A6B249, 0x0375EE82,
+		0xBB45EB9F, 0x1E96B754, 0xB0E423D2, 0x15377F19,
+		0xC08529E8, 0x65567523, 0xCB24E1A5, 0x6EF7BD6E,
+		0xD6C7B873, 0x7314E4B8, 0xDD66703E, 0x78B52CF5,
+		0x6C0A580F, 0xC9D904C4, 0x67AB9042, 0xC278CC89,
+		0x7A48C994, 0xDF9B955F, 0x71E901D9, 0xD43A5D12,
+		0x01880BE3, 0xA45B5728, 0x0A29C3AE, 0xAFFA9F65,
+		0x17CA9A78, 0xB219C6B3, 0x1C6B5235, 0xB9B80EFE,
+		0xF7088E0C, 0x52DBD2C7, 0xFCA94641, 0x597A1A8A,
+		0xE14A1F97, 0x4499435C, 0xEAEBD7DA, 0x4F388B11,
+		0x9A8ADDE0, 0x3F59812B, 0x912B15AD, 0x34F84966,
+		0x8CC84C7B, 0x291B10B0, 0x87698436, 0x22BAD8FD,
+		0x5A0FF408, 0xFFDCA8C3, 0x51AE3C45, 0xF47D608E,
+		0x4C4D6593, 0xE99E3958, 0x47ECADDE, 0xE23FF115,
+		0x378DA7E4, 0x925EFB2F, 0x3C2C6FA9, 0x99FF3362,
+		0x21CF367F, 0x841C6AB4, 0x2A6EFE32, 0x8FBDA2F9,
+		0xC10D220B, 0x64DE7EC0, 0xCAACEA46, 0x6F7FB68D,
+		0xD74FB390, 0x729CEF5B, 0xDCEE7BDD, 0x793D2716,
+		0xAC8F71E7, 0x095C2D2C, 0xA72EB9AA, 0x02FDE561,
+		0xBACDE07C, 0x1F1EBCB7, 0xB16C2831, 0x14BF74FA,
+		0xD814B01E, 0x7DC7ECD5, 0xD3B57853, 0x76662498,
+		0xCE562185, 0x6B857D4E, 0xC5F7E9C8, 0x6024B503,
+		0xB596E3F2, 0x1045BF39, 0xBE372BBF, 0x1BE47774,
+		0xA3D47269, 0x06072EA2, 0xA875BA24, 0x0DA6E6EF,
+		0x4316661D, 0xE6C53AD6, 0x48B7AE50, 0xED64F29B,
+		0x5554F786, 0xF087AB4D, 0x5EF53FCB, 0xFB266300,
+		0x2E9435F1, 0x8B47693A, 0x2535FDBC, 0x80E6A177,
+		0x38D6A46A, 0x9D05F8A1, 0x33776C27, 0x96A430EC,
+		0xEE111C19, 0x4BC240D2, 0xE5B0D454, 0x4063889F,
+		0xF8538D82, 0x5D80D149, 0xF3F245CF, 0x56211904,
+		0x83934FF5, 0x2640133E, 0x883287B8, 0x2DE1DB73,
+		0x95D1DE6E, 0x300282A5, 0x9E701623, 0x3BA34AE8,
+		0x7513CA1A, 0xD0C096D1, 0x7EB20257, 0xDB615E9C,
+		0x63515B81, 0xC682074A, 0x68F093CC, 0xCD23CF07,
+		0x189199F6, 0xBD42C53D, 0x133051BB, 0xB6E30D70,
+		0x0ED3086D, 0xAB0054A6, 0x0572C020, 0xA0A19CEB,
+		0xB41EE811, 0x11CDB4DA, 0xBFBF205C, 0x1A6C7C97,
+		0xA25C798A, 0x078F2541, 0xA9FDB1C7, 0x0C2EED0C,
+		0xD99CBBFD, 0x7C4FE736, 0xD23D73B0, 0x77EE2F7B,
+		0xCFDE2A66, 0x6A0D76AD, 0xC47FE22B, 0x61ACBEE0,
+		0x2F1C3E12, 0x8ACF62D9, 0x24BDF65F, 0x816EAA94,
+		0x395EAF89, 0x9C8DF342, 0x32FF67C4, 0x972C3B0F,
+		0x429E6DFE, 0xE74D3135, 0x493FA5B3, 0xECECF978,
+		0x54DCFC65, 0xF10FA0AE, 0x5F7D3428, 0xFAAE68E3,
+		0x821B4416, 0x27C818DD, 0x89BA8C5B, 0x2C69D090,
+		0x9459D58D, 0x318A8946, 0x9FF81DC0, 0x3A2B410B,
+		0xEF9917FA, 0x4A4A4B31, 0xE438DFB7, 0x41EB837C,
+		0xF9DB8661, 0x5C08DAAA, 0xF27A4E2C, 0x57A912E7,
+		0x19199215, 0xBCCACEDE, 0x12B85A58, 0xB76B0693,
+		0x0F5B038E, 0xAA885F45, 0x04FACBC3, 0xA1299708,
+		0x749BC1F9, 0xD1489D32, 0x7F3A09B4, 0xDAE9557F,
+		0x62D95062, 0xC70A0CA9, 0x6978982F, 0xCCABC4E4
+	}, {
+		0x00000000, 0xB40B77A6, 0x29119F97, 0x9D1AE831,
+		0x13244FF4, 0xA72F3852, 0x3A35D063, 0x8E3EA7C5,
+		0x674EEF33, 0xD3459895, 0x4E5F70A4, 0xFA540702,
+		0x746AA0C7, 0xC061D761, 0x5D7B3F50, 0xE97048F6,
+		0xCE9CDE67, 0x7A97A9C1, 0xE78D41F0, 0x53863656,
+		0xDDB89193, 0x69B3E635, 0xF4A90E04, 0x40A279A2,
+		0xA9D23154, 0x1DD946F2, 0x80C3AEC3, 0x34C8D965,
+		0xBAF67EA0, 0x0EFD0906, 0x93E7E137, 0x27EC9691,
+		0x9C39BDCF, 0x2832CA69, 0xB5282258, 0x012355FE,
+		0x8F1DF23B, 0x3B16859D, 0xA60C6DAC, 0x12071A0A,
+		0xFB7752FC, 0x4F7C255A, 0xD266CD6B, 0x666DBACD,
+		0xE8531D08, 0x5C586AAE, 0xC142829F, 0x7549F539,
+		0x52A563A8, 0xE6AE140E, 0x7BB4FC3F, 0xCFBF8B99,
+		0x41812C5C, 0xF58A5BFA, 0x6890B3CB, 0xDC9BC46D,
+		0x35EB8C9B, 0x81E0FB3D, 0x1CFA130C, 0xA8F164AA,
+		0x26CFC36F, 0x92C4B4C9, 0x0FDE5CF8, 0xBBD52B5E,
+		0x79750B44, 0xCD7E7CE2, 0x506494D3, 0xE46FE375,
+		0x6A5144B0, 0xDE5A3316, 0x4340DB27, 0xF74BAC81,
+		0x1E3BE477, 0xAA3093D1, 0x372A7BE0, 0x83210C46,
+		0x0D1FAB83, 0xB914DC25, 0x240E3414, 0x900543B2,
+		0xB7E9D523, 0x03E2A285, 0x9EF84AB4, 0x2AF33D12,
+		0xA4CD9AD7, 0x10C6ED71, 0x8DDC0540, 0x39D772E6,
+		0xD0A73A10, 0x64AC4DB6, 0xF9B6A587, 0x4DBDD221,
+		0xC38375E4, 0x77880242, 0xEA92EA73, 0x5E999DD5,
+		0xE54CB68B, 0x5147C12D, 0xCC5D291C, 0x78565EBA,
+		0xF668F97F, 0x42638ED9, 0xDF7966E8, 0x6B72114E,
+		0x820259B8, 0x36092E1E, 0xAB13C62F, 0x1F18B189,
+		0x9126164C, 0x252D61EA, 0xB83789DB, 0x0C3CFE7D,
+		0x2BD068EC, 0x9FDB1F4A, 0x02C1F77B, 0xB6CA80DD,
+		0x38F42718, 0x8CFF50BE, 0x11E5B88F, 0xA5EECF29,
+		0x4C9E87DF, 0xF895F079, 0x658F1848, 0xD1846FEE,
+		0x5FBAC82B, 0xEBB1BF8D, 0x76AB57BC, 0xC2A0201A,
+		0xF2EA1688, 0x46E1612E, 0xDBFB891F, 0x6FF0FEB9,
+		0xE1CE597C, 0x55C52EDA, 0xC8DFC6EB, 0x7CD4B14D,
+		0x95A4F9BB, 0x21AF8E1D, 0xBCB5662C, 0x08BE118A,
+		0x8680B64F, 0x328BC1E9, 0xAF9129D8, 0x1B9A5E7E,
+		0x3C76C8EF, 0x887DBF49, 0x15675778, 0xA16C20DE,
+		0x2F52871B, 0x9B59F0BD, 0x0643188C, 0xB2486F2A,
+		0x5B3827DC, 0xEF33507A, 0x7229B84B, 0xC622CFED,
+		0x481C6828, 0xFC171F8E, 0x610DF7BF, 0xD5068019,
+		0x6ED3AB47, 0xDAD8DCE1, 0x47C234D0, 0xF3C94376,
+		0x7DF7E4B3, 0xC9FC9315, 0x54E67B24, 0xE0ED0C82,
+		0x099D4474, 0xBD9633D2, 0x208CDBE3, 0x9487AC45,
+		0x1AB90B80, 0xAEB27C26, 0x33A89417, 0x87A3E3B1,
+		0xA04F7520, 0x14440286, 0x895EEAB7, 0x3D559D11,
+		0xB36B3AD4, 0x07604D72, 0x9A7AA543, 0x2E71D2E5,
+		0xC7019A13, 0x730AEDB5, 0xEE100584, 0x5A1B7222,
+		0xD425D5E7, 0x602EA241, 0xFD344A70, 0x493F3DD6,
+		0x8B9F1DCC, 0x3F946A6A, 0xA28E825B, 0x1685F5FD,
+		0x98BB5238, 0x2CB0259E, 0xB1AACDAF, 0x05A1BA09,
+		0xECD1F2FF, 0x58DA8559, 0xC5C06D68, 0x71CB1ACE,
+		0xFFF5BD0B, 0x4BFECAAD, 0xD6E4229C, 0x62EF553A,
+		0x4503C3AB, 0xF108B40D, 0x6C125C3C, 0xD8192B9A,
+		0x56278C5F, 0xE22CFBF9, 0x7F3613C8, 0xCB3D646E,
+		0x224D2C98, 0x96465B3E, 0x0B5CB30F, 0xBF57C4A9,
+		0x3169636C, 0x856214CA, 0x1878FCFB, 0xAC738B5D,
+		0x17A6A003, 0xA3ADD7A5, 0x3EB73F94, 0x8ABC4832,
+		0x0482EFF7, 0xB0899851, 0x2D937060, 0x999807C6,
+		0x70E84F30, 0xC4E33896, 0x59F9D0A7, 0xEDF2A701,
+		0x63CC00C4, 0xD7C77762, 0x4ADD9F53, 0xFED6E8F5,
+		0xD93A7E64, 0x6D3109C2, 0xF02BE1F3, 0x44209655,
+		0xCA1E3190, 0x7E154636, 0xE30FAE07, 0x5704D9A1,
+		0xBE749157, 0x0A7FE6F1, 0x97650EC0, 0x236E7966,
+		0xAD50DEA3, 0x195BA905, 0x84414134, 0x304A3692
+	}, {
+		0x00000000, 0x9E00AACC, 0x7D072542, 0xE3078F8E,
+		0xFA0E4A84, 0x640EE048, 0x87096FC6, 0x1909C50A,
+		0xB51BE5D3, 0x2B1B4F1F, 0xC81CC091, 0x561C6A5D,
+		0x4F15AF57, 0xD115059B, 0x32128A15, 0xAC1220D9,
+		0x2B31BB7C, 0xB53111B0, 0x56369E3E, 0xC83634F2,
+		0xD13FF1F8, 0x4F3F5B34, 0xAC38D4BA, 0x32387E76,
+		0x9E2A5EAF, 0x002AF463, 0xE32D7BED, 0x7D2DD121,
+		0x6424142B, 0xFA24BEE7, 0x19233169, 0x87239BA5,
+		0x566276F9, 0xC862DC35, 0x2B6553BB, 0xB565F977,
+		0xAC6C3C7D, 0x326C96B1, 0xD16B193F, 0x4F6BB3F3,
+		0xE379932A, 0x7D7939E6, 0x9E7EB668, 0x007E1CA4,
+		0x1977D9AE, 0x87777362, 0x6470FCEC, 0xFA705620,
+		0x7D53CD85, 0xE3536749, 0x0054E8C7, 0x9E54420B,
+		0x875D8701, 0x195D2DCD, 0xFA5AA243, 0x645A088F,
+		0xC8482856, 0x5648829A, 0xB54F0D14, 0x2B4FA7D8,
+		0x324662D2, 0xAC46C81E, 0x4F414790, 0xD141ED5C,
+		0xEDC29D29, 0x73C237E5, 0x90C5B86B, 0x0EC512A7,
+		0x17CCD7AD, 0x89CC7D61, 0x6ACBF2EF, 0xF4CB5823,
+		0x58D978FA, 0xC6D9D236, 0x25DE5DB8, 0xBBDEF774,
+		0xA2D7327E, 0x3CD798B2, 0xDFD0173C, 0x41D0BDF0,
+		0xC6F32655, 0x58F38C99, 0xBBF40317, 0x25F4A9DB,
+		0x3CFD6CD1, 0xA2FDC61D, 0x41FA4993, 0xDFFAE35F,
+		0x73E8C386, 0xEDE8694A, 0x0EEFE6C4, 0x90EF4C08,
+		0x89E68902, 0x17E623CE, 0xF4E1AC40, 0x6AE1068C,
+		0xBBA0EBD0, 0x25A0411C, 0xC6A7CE92, 0x58A7645E,
+		0x41AEA154, 0xDFAE0B98, 0x3CA98416, 0xA2A92EDA,
+		0x0EBB0E03, 0x90BBA4CF, 0x73BC2B41, 0xEDBC818D,
+		0xF4B54487, 0x6AB5EE4B, 0x89B261C5, 0x17B2CB09,
+		0x909150AC, 0x0E91FA60, 0xED9675EE, 0x7396DF22,
+		0x6A9F1A28, 0xF49FB0E4, 0x17983F6A, 0x899895A6,
+		0x258AB57F, 0xBB8A1FB3, 0x588D903D, 0xC68D3AF1,
+		0xDF84FFFB, 0x41845537, 0xA283DAB9, 0x3C837075,
+		0xDA853B53, 0x4485919F, 0xA7821E11, 0x3982B4DD,
+		0x208B71D7, 0xBE8BDB1B, 0x5D8C5495, 0xC38CFE59,
+		0x6F9EDE80, 0xF19E744C, 0x1299FBC2, 0x8C99510E,
+		0x95909404, 0x0B903EC8, 0xE897B146, 0x76971B8A,
+		0xF1B4802F, 0x6FB42AE3, 0x8CB3A56D, 0x12B30FA1,
+		0x0BBACAAB, 0x95BA6067, 0x76BDEFE9, 0xE8BD4525,
+		0x44AF65FC, 0xDAAFCF30, 0x39A840BE, 0xA7A8EA72,
+		0xBEA12F78, 0x20A185B4, 0xC3A60A3A, 0x5DA6A0F6,
+		0x8CE74DAA, 0x12E7E766, 0xF1E068E8, 0x6FE0C224,
+		0x76E9072E, 0xE8E9ADE2, 0x0BEE226C, 0x95EE88A0,
+		0x39FCA879, 0xA7FC02B5, 0x44FB8D3B, 0xDAFB27F7,
+		0xC3F2E2FD, 0x5DF24831, 0xBEF5C7BF, 0x20F56D73,
+		0xA7D6F6D6, 0x39D65C1A, 0xDAD1D394, 0x44D17958,
+		0x5DD8BC52, 0xC3D8169E, 0x20DF9910, 0xBEDF33DC,
+		0x12CD1305, 0x8CCDB9C9, 0x6FCA3647, 0xF1CA9C8B,
+		0xE8C35981, 0x76C3F34D, 0x95C47CC3, 0x0BC4D60F,
+		0x3747A67A, 0xA9470CB6, 0x4A408338, 0xD44029F4,
+		0xCD49ECFE, 0x53494632, 0xB04EC9BC, 0x2E4E6370,
+		0x825C43A9, 0x1C5CE965, 0xFF5B66EB, 0x615BCC27,
+		0x7852092D, 0xE652A3E1, 0x05552C6F, 0x9B5586A3,
+		0x1C761D06, 0x8276B7CA, 0x61713844, 0xFF719288,
+		0xE6785782, 0x7878FD4E, 0x9B7F72C0, 0x057FD80C,
+		0xA96DF8D5, 0x376D5219, 0xD46ADD97, 0x4A6A775B,
+		0x5363B251, 0xCD63189D, 0x2E649713, 0xB0643DDF,
+		0x6125D083, 0xFF257A4F, 0x1C22F5C1, 0x82225F0D,
+		0x9B2B9A07, 0x052B30CB, 0xE62CBF45, 0x782C1589,
+		0xD43E3550, 0x4A3E9F9C, 0xA9391012, 0x3739BADE,
+		0x2E307FD4, 0xB030D518, 0x53375A96, 0xCD37F05A,
+		0x4A146BFF, 0xD414C133, 0x37134EBD, 0xA913E471,
+		0xB01A217B, 0x2E1A8BB7, 0xCD1D0439, 0x531DAEF5,
+		0xFF0F8E2C, 0x610F24E0, 0x8208AB6E, 0x1C0801A2,
+		0x0501C4A8, 0x9B016E64, 0x7806E1EA, 0xE6064B26
+	}
+};
diff --git a/src/liblzma/check/crc32_table_le.h b/src/liblzma/check/crc32_table_le.h
new file mode 100644
index 0000000..25f4fc4
--- /dev/null
+++ b/src/liblzma/check/crc32_table_le.h
@@ -0,0 +1,525 @@
+/* This file has been automatically generated by crc32_tablegen.c. */
+
+const uint32_t lzma_crc32_table[8][256] = {
+	{
+		0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
+		0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+		0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
+		0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+		0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
+		0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+		0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
+		0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+		0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
+		0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+		0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
+		0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+		0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
+		0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+		0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
+		0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+		0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
+		0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+		0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
+		0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+		0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
+		0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+		0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
+		0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+		0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
+		0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+		0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
+		0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+		0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
+		0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+		0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
+		0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+		0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
+		0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+		0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
+		0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+		0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
+		0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+		0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
+		0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+		0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
+		0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+		0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
+		0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+		0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+		0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+		0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
+		0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+		0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
+		0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+		0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
+		0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+		0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
+		0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+		0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
+		0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+		0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
+		0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+		0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
+		0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+		0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
+		0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+		0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
+		0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+	}, {
+		0x00000000, 0x191B3141, 0x32366282, 0x2B2D53C3,
+		0x646CC504, 0x7D77F445, 0x565AA786, 0x4F4196C7,
+		0xC8D98A08, 0xD1C2BB49, 0xFAEFE88A, 0xE3F4D9CB,
+		0xACB54F0C, 0xB5AE7E4D, 0x9E832D8E, 0x87981CCF,
+		0x4AC21251, 0x53D92310, 0x78F470D3, 0x61EF4192,
+		0x2EAED755, 0x37B5E614, 0x1C98B5D7, 0x05838496,
+		0x821B9859, 0x9B00A918, 0xB02DFADB, 0xA936CB9A,
+		0xE6775D5D, 0xFF6C6C1C, 0xD4413FDF, 0xCD5A0E9E,
+		0x958424A2, 0x8C9F15E3, 0xA7B24620, 0xBEA97761,
+		0xF1E8E1A6, 0xE8F3D0E7, 0xC3DE8324, 0xDAC5B265,
+		0x5D5DAEAA, 0x44469FEB, 0x6F6BCC28, 0x7670FD69,
+		0x39316BAE, 0x202A5AEF, 0x0B07092C, 0x121C386D,
+		0xDF4636F3, 0xC65D07B2, 0xED705471, 0xF46B6530,
+		0xBB2AF3F7, 0xA231C2B6, 0x891C9175, 0x9007A034,
+		0x179FBCFB, 0x0E848DBA, 0x25A9DE79, 0x3CB2EF38,
+		0x73F379FF, 0x6AE848BE, 0x41C51B7D, 0x58DE2A3C,
+		0xF0794F05, 0xE9627E44, 0xC24F2D87, 0xDB541CC6,
+		0x94158A01, 0x8D0EBB40, 0xA623E883, 0xBF38D9C2,
+		0x38A0C50D, 0x21BBF44C, 0x0A96A78F, 0x138D96CE,
+		0x5CCC0009, 0x45D73148, 0x6EFA628B, 0x77E153CA,
+		0xBABB5D54, 0xA3A06C15, 0x888D3FD6, 0x91960E97,
+		0xDED79850, 0xC7CCA911, 0xECE1FAD2, 0xF5FACB93,
+		0x7262D75C, 0x6B79E61D, 0x4054B5DE, 0x594F849F,
+		0x160E1258, 0x0F152319, 0x243870DA, 0x3D23419B,
+		0x65FD6BA7, 0x7CE65AE6, 0x57CB0925, 0x4ED03864,
+		0x0191AEA3, 0x188A9FE2, 0x33A7CC21, 0x2ABCFD60,
+		0xAD24E1AF, 0xB43FD0EE, 0x9F12832D, 0x8609B26C,
+		0xC94824AB, 0xD05315EA, 0xFB7E4629, 0xE2657768,
+		0x2F3F79F6, 0x362448B7, 0x1D091B74, 0x04122A35,
+		0x4B53BCF2, 0x52488DB3, 0x7965DE70, 0x607EEF31,
+		0xE7E6F3FE, 0xFEFDC2BF, 0xD5D0917C, 0xCCCBA03D,
+		0x838A36FA, 0x9A9107BB, 0xB1BC5478, 0xA8A76539,
+		0x3B83984B, 0x2298A90A, 0x09B5FAC9, 0x10AECB88,
+		0x5FEF5D4F, 0x46F46C0E, 0x6DD93FCD, 0x74C20E8C,
+		0xF35A1243, 0xEA412302, 0xC16C70C1, 0xD8774180,
+		0x9736D747, 0x8E2DE606, 0xA500B5C5, 0xBC1B8484,
+		0x71418A1A, 0x685ABB5B, 0x4377E898, 0x5A6CD9D9,
+		0x152D4F1E, 0x0C367E5F, 0x271B2D9C, 0x3E001CDD,
+		0xB9980012, 0xA0833153, 0x8BAE6290, 0x92B553D1,
+		0xDDF4C516, 0xC4EFF457, 0xEFC2A794, 0xF6D996D5,
+		0xAE07BCE9, 0xB71C8DA8, 0x9C31DE6B, 0x852AEF2A,
+		0xCA6B79ED, 0xD37048AC, 0xF85D1B6F, 0xE1462A2E,
+		0x66DE36E1, 0x7FC507A0, 0x54E85463, 0x4DF36522,
+		0x02B2F3E5, 0x1BA9C2A4, 0x30849167, 0x299FA026,
+		0xE4C5AEB8, 0xFDDE9FF9, 0xD6F3CC3A, 0xCFE8FD7B,
+		0x80A96BBC, 0x99B25AFD, 0xB29F093E, 0xAB84387F,
+		0x2C1C24B0, 0x350715F1, 0x1E2A4632, 0x07317773,
+		0x4870E1B4, 0x516BD0F5, 0x7A468336, 0x635DB277,
+		0xCBFAD74E, 0xD2E1E60F, 0xF9CCB5CC, 0xE0D7848D,
+		0xAF96124A, 0xB68D230B, 0x9DA070C8, 0x84BB4189,
+		0x03235D46, 0x1A386C07, 0x31153FC4, 0x280E0E85,
+		0x674F9842, 0x7E54A903, 0x5579FAC0, 0x4C62CB81,
+		0x8138C51F, 0x9823F45E, 0xB30EA79D, 0xAA1596DC,
+		0xE554001B, 0xFC4F315A, 0xD7626299, 0xCE7953D8,
+		0x49E14F17, 0x50FA7E56, 0x7BD72D95, 0x62CC1CD4,
+		0x2D8D8A13, 0x3496BB52, 0x1FBBE891, 0x06A0D9D0,
+		0x5E7EF3EC, 0x4765C2AD, 0x6C48916E, 0x7553A02F,
+		0x3A1236E8, 0x230907A9, 0x0824546A, 0x113F652B,
+		0x96A779E4, 0x8FBC48A5, 0xA4911B66, 0xBD8A2A27,
+		0xF2CBBCE0, 0xEBD08DA1, 0xC0FDDE62, 0xD9E6EF23,
+		0x14BCE1BD, 0x0DA7D0FC, 0x268A833F, 0x3F91B27E,
+		0x70D024B9, 0x69CB15F8, 0x42E6463B, 0x5BFD777A,
+		0xDC656BB5, 0xC57E5AF4, 0xEE530937, 0xF7483876,
+		0xB809AEB1, 0xA1129FF0, 0x8A3FCC33, 0x9324FD72
+	}, {
+		0x00000000, 0x01C26A37, 0x0384D46E, 0x0246BE59,
+		0x0709A8DC, 0x06CBC2EB, 0x048D7CB2, 0x054F1685,
+		0x0E1351B8, 0x0FD13B8F, 0x0D9785D6, 0x0C55EFE1,
+		0x091AF964, 0x08D89353, 0x0A9E2D0A, 0x0B5C473D,
+		0x1C26A370, 0x1DE4C947, 0x1FA2771E, 0x1E601D29,
+		0x1B2F0BAC, 0x1AED619B, 0x18ABDFC2, 0x1969B5F5,
+		0x1235F2C8, 0x13F798FF, 0x11B126A6, 0x10734C91,
+		0x153C5A14, 0x14FE3023, 0x16B88E7A, 0x177AE44D,
+		0x384D46E0, 0x398F2CD7, 0x3BC9928E, 0x3A0BF8B9,
+		0x3F44EE3C, 0x3E86840B, 0x3CC03A52, 0x3D025065,
+		0x365E1758, 0x379C7D6F, 0x35DAC336, 0x3418A901,
+		0x3157BF84, 0x3095D5B3, 0x32D36BEA, 0x331101DD,
+		0x246BE590, 0x25A98FA7, 0x27EF31FE, 0x262D5BC9,
+		0x23624D4C, 0x22A0277B, 0x20E69922, 0x2124F315,
+		0x2A78B428, 0x2BBADE1F, 0x29FC6046, 0x283E0A71,
+		0x2D711CF4, 0x2CB376C3, 0x2EF5C89A, 0x2F37A2AD,
+		0x709A8DC0, 0x7158E7F7, 0x731E59AE, 0x72DC3399,
+		0x7793251C, 0x76514F2B, 0x7417F172, 0x75D59B45,
+		0x7E89DC78, 0x7F4BB64F, 0x7D0D0816, 0x7CCF6221,
+		0x798074A4, 0x78421E93, 0x7A04A0CA, 0x7BC6CAFD,
+		0x6CBC2EB0, 0x6D7E4487, 0x6F38FADE, 0x6EFA90E9,
+		0x6BB5866C, 0x6A77EC5B, 0x68315202, 0x69F33835,
+		0x62AF7F08, 0x636D153F, 0x612BAB66, 0x60E9C151,
+		0x65A6D7D4, 0x6464BDE3, 0x662203BA, 0x67E0698D,
+		0x48D7CB20, 0x4915A117, 0x4B531F4E, 0x4A917579,
+		0x4FDE63FC, 0x4E1C09CB, 0x4C5AB792, 0x4D98DDA5,
+		0x46C49A98, 0x4706F0AF, 0x45404EF6, 0x448224C1,
+		0x41CD3244, 0x400F5873, 0x4249E62A, 0x438B8C1D,
+		0x54F16850, 0x55330267, 0x5775BC3E, 0x56B7D609,
+		0x53F8C08C, 0x523AAABB, 0x507C14E2, 0x51BE7ED5,
+		0x5AE239E8, 0x5B2053DF, 0x5966ED86, 0x58A487B1,
+		0x5DEB9134, 0x5C29FB03, 0x5E6F455A, 0x5FAD2F6D,
+		0xE1351B80, 0xE0F771B7, 0xE2B1CFEE, 0xE373A5D9,
+		0xE63CB35C, 0xE7FED96B, 0xE5B86732, 0xE47A0D05,
+		0xEF264A38, 0xEEE4200F, 0xECA29E56, 0xED60F461,
+		0xE82FE2E4, 0xE9ED88D3, 0xEBAB368A, 0xEA695CBD,
+		0xFD13B8F0, 0xFCD1D2C7, 0xFE976C9E, 0xFF5506A9,
+		0xFA1A102C, 0xFBD87A1B, 0xF99EC442, 0xF85CAE75,
+		0xF300E948, 0xF2C2837F, 0xF0843D26, 0xF1465711,
+		0xF4094194, 0xF5CB2BA3, 0xF78D95FA, 0xF64FFFCD,
+		0xD9785D60, 0xD8BA3757, 0xDAFC890E, 0xDB3EE339,
+		0xDE71F5BC, 0xDFB39F8B, 0xDDF521D2, 0xDC374BE5,
+		0xD76B0CD8, 0xD6A966EF, 0xD4EFD8B6, 0xD52DB281,
+		0xD062A404, 0xD1A0CE33, 0xD3E6706A, 0xD2241A5D,
+		0xC55EFE10, 0xC49C9427, 0xC6DA2A7E, 0xC7184049,
+		0xC25756CC, 0xC3953CFB, 0xC1D382A2, 0xC011E895,
+		0xCB4DAFA8, 0xCA8FC59F, 0xC8C97BC6, 0xC90B11F1,
+		0xCC440774, 0xCD866D43, 0xCFC0D31A, 0xCE02B92D,
+		0x91AF9640, 0x906DFC77, 0x922B422E, 0x93E92819,
+		0x96A63E9C, 0x976454AB, 0x9522EAF2, 0x94E080C5,
+		0x9FBCC7F8, 0x9E7EADCF, 0x9C381396, 0x9DFA79A1,
+		0x98B56F24, 0x99770513, 0x9B31BB4A, 0x9AF3D17D,
+		0x8D893530, 0x8C4B5F07, 0x8E0DE15E, 0x8FCF8B69,
+		0x8A809DEC, 0x8B42F7DB, 0x89044982, 0x88C623B5,
+		0x839A6488, 0x82580EBF, 0x801EB0E6, 0x81DCDAD1,
+		0x8493CC54, 0x8551A663, 0x8717183A, 0x86D5720D,
+		0xA9E2D0A0, 0xA820BA97, 0xAA6604CE, 0xABA46EF9,
+		0xAEEB787C, 0xAF29124B, 0xAD6FAC12, 0xACADC625,
+		0xA7F18118, 0xA633EB2F, 0xA4755576, 0xA5B73F41,
+		0xA0F829C4, 0xA13A43F3, 0xA37CFDAA, 0xA2BE979D,
+		0xB5C473D0, 0xB40619E7, 0xB640A7BE, 0xB782CD89,
+		0xB2CDDB0C, 0xB30FB13B, 0xB1490F62, 0xB08B6555,
+		0xBBD72268, 0xBA15485F, 0xB853F606, 0xB9919C31,
+		0xBCDE8AB4, 0xBD1CE083, 0xBF5A5EDA, 0xBE9834ED
+	}, {
+		0x00000000, 0xB8BC6765, 0xAA09C88B, 0x12B5AFEE,
+		0x8F629757, 0x37DEF032, 0x256B5FDC, 0x9DD738B9,
+		0xC5B428EF, 0x7D084F8A, 0x6FBDE064, 0xD7018701,
+		0x4AD6BFB8, 0xF26AD8DD, 0xE0DF7733, 0x58631056,
+		0x5019579F, 0xE8A530FA, 0xFA109F14, 0x42ACF871,
+		0xDF7BC0C8, 0x67C7A7AD, 0x75720843, 0xCDCE6F26,
+		0x95AD7F70, 0x2D111815, 0x3FA4B7FB, 0x8718D09E,
+		0x1ACFE827, 0xA2738F42, 0xB0C620AC, 0x087A47C9,
+		0xA032AF3E, 0x188EC85B, 0x0A3B67B5, 0xB28700D0,
+		0x2F503869, 0x97EC5F0C, 0x8559F0E2, 0x3DE59787,
+		0x658687D1, 0xDD3AE0B4, 0xCF8F4F5A, 0x7733283F,
+		0xEAE41086, 0x525877E3, 0x40EDD80D, 0xF851BF68,
+		0xF02BF8A1, 0x48979FC4, 0x5A22302A, 0xE29E574F,
+		0x7F496FF6, 0xC7F50893, 0xD540A77D, 0x6DFCC018,
+		0x359FD04E, 0x8D23B72B, 0x9F9618C5, 0x272A7FA0,
+		0xBAFD4719, 0x0241207C, 0x10F48F92, 0xA848E8F7,
+		0x9B14583D, 0x23A83F58, 0x311D90B6, 0x89A1F7D3,
+		0x1476CF6A, 0xACCAA80F, 0xBE7F07E1, 0x06C36084,
+		0x5EA070D2, 0xE61C17B7, 0xF4A9B859, 0x4C15DF3C,
+		0xD1C2E785, 0x697E80E0, 0x7BCB2F0E, 0xC377486B,
+		0xCB0D0FA2, 0x73B168C7, 0x6104C729, 0xD9B8A04C,
+		0x446F98F5, 0xFCD3FF90, 0xEE66507E, 0x56DA371B,
+		0x0EB9274D, 0xB6054028, 0xA4B0EFC6, 0x1C0C88A3,
+		0x81DBB01A, 0x3967D77F, 0x2BD27891, 0x936E1FF4,
+		0x3B26F703, 0x839A9066, 0x912F3F88, 0x299358ED,
+		0xB4446054, 0x0CF80731, 0x1E4DA8DF, 0xA6F1CFBA,
+		0xFE92DFEC, 0x462EB889, 0x549B1767, 0xEC277002,
+		0x71F048BB, 0xC94C2FDE, 0xDBF98030, 0x6345E755,
+		0x6B3FA09C, 0xD383C7F9, 0xC1366817, 0x798A0F72,
+		0xE45D37CB, 0x5CE150AE, 0x4E54FF40, 0xF6E89825,
+		0xAE8B8873, 0x1637EF16, 0x048240F8, 0xBC3E279D,
+		0x21E91F24, 0x99557841, 0x8BE0D7AF, 0x335CB0CA,
+		0xED59B63B, 0x55E5D15E, 0x47507EB0, 0xFFEC19D5,
+		0x623B216C, 0xDA874609, 0xC832E9E7, 0x708E8E82,
+		0x28ED9ED4, 0x9051F9B1, 0x82E4565F, 0x3A58313A,
+		0xA78F0983, 0x1F336EE6, 0x0D86C108, 0xB53AA66D,
+		0xBD40E1A4, 0x05FC86C1, 0x1749292F, 0xAFF54E4A,
+		0x322276F3, 0x8A9E1196, 0x982BBE78, 0x2097D91D,
+		0x78F4C94B, 0xC048AE2E, 0xD2FD01C0, 0x6A4166A5,
+		0xF7965E1C, 0x4F2A3979, 0x5D9F9697, 0xE523F1F2,
+		0x4D6B1905, 0xF5D77E60, 0xE762D18E, 0x5FDEB6EB,
+		0xC2098E52, 0x7AB5E937, 0x680046D9, 0xD0BC21BC,
+		0x88DF31EA, 0x3063568F, 0x22D6F961, 0x9A6A9E04,
+		0x07BDA6BD, 0xBF01C1D8, 0xADB46E36, 0x15080953,
+		0x1D724E9A, 0xA5CE29FF, 0xB77B8611, 0x0FC7E174,
+		0x9210D9CD, 0x2AACBEA8, 0x38191146, 0x80A57623,
+		0xD8C66675, 0x607A0110, 0x72CFAEFE, 0xCA73C99B,
+		0x57A4F122, 0xEF189647, 0xFDAD39A9, 0x45115ECC,
+		0x764DEE06, 0xCEF18963, 0xDC44268D, 0x64F841E8,
+		0xF92F7951, 0x41931E34, 0x5326B1DA, 0xEB9AD6BF,
+		0xB3F9C6E9, 0x0B45A18C, 0x19F00E62, 0xA14C6907,
+		0x3C9B51BE, 0x842736DB, 0x96929935, 0x2E2EFE50,
+		0x2654B999, 0x9EE8DEFC, 0x8C5D7112, 0x34E11677,
+		0xA9362ECE, 0x118A49AB, 0x033FE645, 0xBB838120,
+		0xE3E09176, 0x5B5CF613, 0x49E959FD, 0xF1553E98,
+		0x6C820621, 0xD43E6144, 0xC68BCEAA, 0x7E37A9CF,
+		0xD67F4138, 0x6EC3265D, 0x7C7689B3, 0xC4CAEED6,
+		0x591DD66F, 0xE1A1B10A, 0xF3141EE4, 0x4BA87981,
+		0x13CB69D7, 0xAB770EB2, 0xB9C2A15C, 0x017EC639,
+		0x9CA9FE80, 0x241599E5, 0x36A0360B, 0x8E1C516E,
+		0x866616A7, 0x3EDA71C2, 0x2C6FDE2C, 0x94D3B949,
+		0x090481F0, 0xB1B8E695, 0xA30D497B, 0x1BB12E1E,
+		0x43D23E48, 0xFB6E592D, 0xE9DBF6C3, 0x516791A6,
+		0xCCB0A91F, 0x740CCE7A, 0x66B96194, 0xDE0506F1
+	}, {
+		0x00000000, 0x3D6029B0, 0x7AC05360, 0x47A07AD0,
+		0xF580A6C0, 0xC8E08F70, 0x8F40F5A0, 0xB220DC10,
+		0x30704BC1, 0x0D106271, 0x4AB018A1, 0x77D03111,
+		0xC5F0ED01, 0xF890C4B1, 0xBF30BE61, 0x825097D1,
+		0x60E09782, 0x5D80BE32, 0x1A20C4E2, 0x2740ED52,
+		0x95603142, 0xA80018F2, 0xEFA06222, 0xD2C04B92,
+		0x5090DC43, 0x6DF0F5F3, 0x2A508F23, 0x1730A693,
+		0xA5107A83, 0x98705333, 0xDFD029E3, 0xE2B00053,
+		0xC1C12F04, 0xFCA106B4, 0xBB017C64, 0x866155D4,
+		0x344189C4, 0x0921A074, 0x4E81DAA4, 0x73E1F314,
+		0xF1B164C5, 0xCCD14D75, 0x8B7137A5, 0xB6111E15,
+		0x0431C205, 0x3951EBB5, 0x7EF19165, 0x4391B8D5,
+		0xA121B886, 0x9C419136, 0xDBE1EBE6, 0xE681C256,
+		0x54A11E46, 0x69C137F6, 0x2E614D26, 0x13016496,
+		0x9151F347, 0xAC31DAF7, 0xEB91A027, 0xD6F18997,
+		0x64D15587, 0x59B17C37, 0x1E1106E7, 0x23712F57,
+		0x58F35849, 0x659371F9, 0x22330B29, 0x1F532299,
+		0xAD73FE89, 0x9013D739, 0xD7B3ADE9, 0xEAD38459,
+		0x68831388, 0x55E33A38, 0x124340E8, 0x2F236958,
+		0x9D03B548, 0xA0639CF8, 0xE7C3E628, 0xDAA3CF98,
+		0x3813CFCB, 0x0573E67B, 0x42D39CAB, 0x7FB3B51B,
+		0xCD93690B, 0xF0F340BB, 0xB7533A6B, 0x8A3313DB,
+		0x0863840A, 0x3503ADBA, 0x72A3D76A, 0x4FC3FEDA,
+		0xFDE322CA, 0xC0830B7A, 0x872371AA, 0xBA43581A,
+		0x9932774D, 0xA4525EFD, 0xE3F2242D, 0xDE920D9D,
+		0x6CB2D18D, 0x51D2F83D, 0x167282ED, 0x2B12AB5D,
+		0xA9423C8C, 0x9422153C, 0xD3826FEC, 0xEEE2465C,
+		0x5CC29A4C, 0x61A2B3FC, 0x2602C92C, 0x1B62E09C,
+		0xF9D2E0CF, 0xC4B2C97F, 0x8312B3AF, 0xBE729A1F,
+		0x0C52460F, 0x31326FBF, 0x7692156F, 0x4BF23CDF,
+		0xC9A2AB0E, 0xF4C282BE, 0xB362F86E, 0x8E02D1DE,
+		0x3C220DCE, 0x0142247E, 0x46E25EAE, 0x7B82771E,
+		0xB1E6B092, 0x8C869922, 0xCB26E3F2, 0xF646CA42,
+		0x44661652, 0x79063FE2, 0x3EA64532, 0x03C66C82,
+		0x8196FB53, 0xBCF6D2E3, 0xFB56A833, 0xC6368183,
+		0x74165D93, 0x49767423, 0x0ED60EF3, 0x33B62743,
+		0xD1062710, 0xEC660EA0, 0xABC67470, 0x96A65DC0,
+		0x248681D0, 0x19E6A860, 0x5E46D2B0, 0x6326FB00,
+		0xE1766CD1, 0xDC164561, 0x9BB63FB1, 0xA6D61601,
+		0x14F6CA11, 0x2996E3A1, 0x6E369971, 0x5356B0C1,
+		0x70279F96, 0x4D47B626, 0x0AE7CCF6, 0x3787E546,
+		0x85A73956, 0xB8C710E6, 0xFF676A36, 0xC2074386,
+		0x4057D457, 0x7D37FDE7, 0x3A978737, 0x07F7AE87,
+		0xB5D77297, 0x88B75B27, 0xCF1721F7, 0xF2770847,
+		0x10C70814, 0x2DA721A4, 0x6A075B74, 0x576772C4,
+		0xE547AED4, 0xD8278764, 0x9F87FDB4, 0xA2E7D404,
+		0x20B743D5, 0x1DD76A65, 0x5A7710B5, 0x67173905,
+		0xD537E515, 0xE857CCA5, 0xAFF7B675, 0x92979FC5,
+		0xE915E8DB, 0xD475C16B, 0x93D5BBBB, 0xAEB5920B,
+		0x1C954E1B, 0x21F567AB, 0x66551D7B, 0x5B3534CB,
+		0xD965A31A, 0xE4058AAA, 0xA3A5F07A, 0x9EC5D9CA,
+		0x2CE505DA, 0x11852C6A, 0x562556BA, 0x6B457F0A,
+		0x89F57F59, 0xB49556E9, 0xF3352C39, 0xCE550589,
+		0x7C75D999, 0x4115F029, 0x06B58AF9, 0x3BD5A349,
+		0xB9853498, 0x84E51D28, 0xC34567F8, 0xFE254E48,
+		0x4C059258, 0x7165BBE8, 0x36C5C138, 0x0BA5E888,
+		0x28D4C7DF, 0x15B4EE6F, 0x521494BF, 0x6F74BD0F,
+		0xDD54611F, 0xE03448AF, 0xA794327F, 0x9AF41BCF,
+		0x18A48C1E, 0x25C4A5AE, 0x6264DF7E, 0x5F04F6CE,
+		0xED242ADE, 0xD044036E, 0x97E479BE, 0xAA84500E,
+		0x4834505D, 0x755479ED, 0x32F4033D, 0x0F942A8D,
+		0xBDB4F69D, 0x80D4DF2D, 0xC774A5FD, 0xFA148C4D,
+		0x78441B9C, 0x4524322C, 0x028448FC, 0x3FE4614C,
+		0x8DC4BD5C, 0xB0A494EC, 0xF704EE3C, 0xCA64C78C
+	}, {
+		0x00000000, 0xCB5CD3A5, 0x4DC8A10B, 0x869472AE,
+		0x9B914216, 0x50CD91B3, 0xD659E31D, 0x1D0530B8,
+		0xEC53826D, 0x270F51C8, 0xA19B2366, 0x6AC7F0C3,
+		0x77C2C07B, 0xBC9E13DE, 0x3A0A6170, 0xF156B2D5,
+		0x03D6029B, 0xC88AD13E, 0x4E1EA390, 0x85427035,
+		0x9847408D, 0x531B9328, 0xD58FE186, 0x1ED33223,
+		0xEF8580F6, 0x24D95353, 0xA24D21FD, 0x6911F258,
+		0x7414C2E0, 0xBF481145, 0x39DC63EB, 0xF280B04E,
+		0x07AC0536, 0xCCF0D693, 0x4A64A43D, 0x81387798,
+		0x9C3D4720, 0x57619485, 0xD1F5E62B, 0x1AA9358E,
+		0xEBFF875B, 0x20A354FE, 0xA6372650, 0x6D6BF5F5,
+		0x706EC54D, 0xBB3216E8, 0x3DA66446, 0xF6FAB7E3,
+		0x047A07AD, 0xCF26D408, 0x49B2A6A6, 0x82EE7503,
+		0x9FEB45BB, 0x54B7961E, 0xD223E4B0, 0x197F3715,
+		0xE82985C0, 0x23755665, 0xA5E124CB, 0x6EBDF76E,
+		0x73B8C7D6, 0xB8E41473, 0x3E7066DD, 0xF52CB578,
+		0x0F580A6C, 0xC404D9C9, 0x4290AB67, 0x89CC78C2,
+		0x94C9487A, 0x5F959BDF, 0xD901E971, 0x125D3AD4,
+		0xE30B8801, 0x28575BA4, 0xAEC3290A, 0x659FFAAF,
+		0x789ACA17, 0xB3C619B2, 0x35526B1C, 0xFE0EB8B9,
+		0x0C8E08F7, 0xC7D2DB52, 0x4146A9FC, 0x8A1A7A59,
+		0x971F4AE1, 0x5C439944, 0xDAD7EBEA, 0x118B384F,
+		0xE0DD8A9A, 0x2B81593F, 0xAD152B91, 0x6649F834,
+		0x7B4CC88C, 0xB0101B29, 0x36846987, 0xFDD8BA22,
+		0x08F40F5A, 0xC3A8DCFF, 0x453CAE51, 0x8E607DF4,
+		0x93654D4C, 0x58399EE9, 0xDEADEC47, 0x15F13FE2,
+		0xE4A78D37, 0x2FFB5E92, 0xA96F2C3C, 0x6233FF99,
+		0x7F36CF21, 0xB46A1C84, 0x32FE6E2A, 0xF9A2BD8F,
+		0x0B220DC1, 0xC07EDE64, 0x46EAACCA, 0x8DB67F6F,
+		0x90B34FD7, 0x5BEF9C72, 0xDD7BEEDC, 0x16273D79,
+		0xE7718FAC, 0x2C2D5C09, 0xAAB92EA7, 0x61E5FD02,
+		0x7CE0CDBA, 0xB7BC1E1F, 0x31286CB1, 0xFA74BF14,
+		0x1EB014D8, 0xD5ECC77D, 0x5378B5D3, 0x98246676,
+		0x852156CE, 0x4E7D856B, 0xC8E9F7C5, 0x03B52460,
+		0xF2E396B5, 0x39BF4510, 0xBF2B37BE, 0x7477E41B,
+		0x6972D4A3, 0xA22E0706, 0x24BA75A8, 0xEFE6A60D,
+		0x1D661643, 0xD63AC5E6, 0x50AEB748, 0x9BF264ED,
+		0x86F75455, 0x4DAB87F0, 0xCB3FF55E, 0x006326FB,
+		0xF135942E, 0x3A69478B, 0xBCFD3525, 0x77A1E680,
+		0x6AA4D638, 0xA1F8059D, 0x276C7733, 0xEC30A496,
+		0x191C11EE, 0xD240C24B, 0x54D4B0E5, 0x9F886340,
+		0x828D53F8, 0x49D1805D, 0xCF45F2F3, 0x04192156,
+		0xF54F9383, 0x3E134026, 0xB8873288, 0x73DBE12D,
+		0x6EDED195, 0xA5820230, 0x2316709E, 0xE84AA33B,
+		0x1ACA1375, 0xD196C0D0, 0x5702B27E, 0x9C5E61DB,
+		0x815B5163, 0x4A0782C6, 0xCC93F068, 0x07CF23CD,
+		0xF6999118, 0x3DC542BD, 0xBB513013, 0x700DE3B6,
+		0x6D08D30E, 0xA65400AB, 0x20C07205, 0xEB9CA1A0,
+		0x11E81EB4, 0xDAB4CD11, 0x5C20BFBF, 0x977C6C1A,
+		0x8A795CA2, 0x41258F07, 0xC7B1FDA9, 0x0CED2E0C,
+		0xFDBB9CD9, 0x36E74F7C, 0xB0733DD2, 0x7B2FEE77,
+		0x662ADECF, 0xAD760D6A, 0x2BE27FC4, 0xE0BEAC61,
+		0x123E1C2F, 0xD962CF8A, 0x5FF6BD24, 0x94AA6E81,
+		0x89AF5E39, 0x42F38D9C, 0xC467FF32, 0x0F3B2C97,
+		0xFE6D9E42, 0x35314DE7, 0xB3A53F49, 0x78F9ECEC,
+		0x65FCDC54, 0xAEA00FF1, 0x28347D5F, 0xE368AEFA,
+		0x16441B82, 0xDD18C827, 0x5B8CBA89, 0x90D0692C,
+		0x8DD55994, 0x46898A31, 0xC01DF89F, 0x0B412B3A,
+		0xFA1799EF, 0x314B4A4A, 0xB7DF38E4, 0x7C83EB41,
+		0x6186DBF9, 0xAADA085C, 0x2C4E7AF2, 0xE712A957,
+		0x15921919, 0xDECECABC, 0x585AB812, 0x93066BB7,
+		0x8E035B0F, 0x455F88AA, 0xC3CBFA04, 0x089729A1,
+		0xF9C19B74, 0x329D48D1, 0xB4093A7F, 0x7F55E9DA,
+		0x6250D962, 0xA90C0AC7, 0x2F987869, 0xE4C4ABCC
+	}, {
+		0x00000000, 0xA6770BB4, 0x979F1129, 0x31E81A9D,
+		0xF44F2413, 0x52382FA7, 0x63D0353A, 0xC5A73E8E,
+		0x33EF4E67, 0x959845D3, 0xA4705F4E, 0x020754FA,
+		0xC7A06A74, 0x61D761C0, 0x503F7B5D, 0xF64870E9,
+		0x67DE9CCE, 0xC1A9977A, 0xF0418DE7, 0x56368653,
+		0x9391B8DD, 0x35E6B369, 0x040EA9F4, 0xA279A240,
+		0x5431D2A9, 0xF246D91D, 0xC3AEC380, 0x65D9C834,
+		0xA07EF6BA, 0x0609FD0E, 0x37E1E793, 0x9196EC27,
+		0xCFBD399C, 0x69CA3228, 0x582228B5, 0xFE552301,
+		0x3BF21D8F, 0x9D85163B, 0xAC6D0CA6, 0x0A1A0712,
+		0xFC5277FB, 0x5A257C4F, 0x6BCD66D2, 0xCDBA6D66,
+		0x081D53E8, 0xAE6A585C, 0x9F8242C1, 0x39F54975,
+		0xA863A552, 0x0E14AEE6, 0x3FFCB47B, 0x998BBFCF,
+		0x5C2C8141, 0xFA5B8AF5, 0xCBB39068, 0x6DC49BDC,
+		0x9B8CEB35, 0x3DFBE081, 0x0C13FA1C, 0xAA64F1A8,
+		0x6FC3CF26, 0xC9B4C492, 0xF85CDE0F, 0x5E2BD5BB,
+		0x440B7579, 0xE27C7ECD, 0xD3946450, 0x75E36FE4,
+		0xB044516A, 0x16335ADE, 0x27DB4043, 0x81AC4BF7,
+		0x77E43B1E, 0xD19330AA, 0xE07B2A37, 0x460C2183,
+		0x83AB1F0D, 0x25DC14B9, 0x14340E24, 0xB2430590,
+		0x23D5E9B7, 0x85A2E203, 0xB44AF89E, 0x123DF32A,
+		0xD79ACDA4, 0x71EDC610, 0x4005DC8D, 0xE672D739,
+		0x103AA7D0, 0xB64DAC64, 0x87A5B6F9, 0x21D2BD4D,
+		0xE47583C3, 0x42028877, 0x73EA92EA, 0xD59D995E,
+		0x8BB64CE5, 0x2DC14751, 0x1C295DCC, 0xBA5E5678,
+		0x7FF968F6, 0xD98E6342, 0xE86679DF, 0x4E11726B,
+		0xB8590282, 0x1E2E0936, 0x2FC613AB, 0x89B1181F,
+		0x4C162691, 0xEA612D25, 0xDB8937B8, 0x7DFE3C0C,
+		0xEC68D02B, 0x4A1FDB9F, 0x7BF7C102, 0xDD80CAB6,
+		0x1827F438, 0xBE50FF8C, 0x8FB8E511, 0x29CFEEA5,
+		0xDF879E4C, 0x79F095F8, 0x48188F65, 0xEE6F84D1,
+		0x2BC8BA5F, 0x8DBFB1EB, 0xBC57AB76, 0x1A20A0C2,
+		0x8816EAF2, 0x2E61E146, 0x1F89FBDB, 0xB9FEF06F,
+		0x7C59CEE1, 0xDA2EC555, 0xEBC6DFC8, 0x4DB1D47C,
+		0xBBF9A495, 0x1D8EAF21, 0x2C66B5BC, 0x8A11BE08,
+		0x4FB68086, 0xE9C18B32, 0xD82991AF, 0x7E5E9A1B,
+		0xEFC8763C, 0x49BF7D88, 0x78576715, 0xDE206CA1,
+		0x1B87522F, 0xBDF0599B, 0x8C184306, 0x2A6F48B2,
+		0xDC27385B, 0x7A5033EF, 0x4BB82972, 0xEDCF22C6,
+		0x28681C48, 0x8E1F17FC, 0xBFF70D61, 0x198006D5,
+		0x47ABD36E, 0xE1DCD8DA, 0xD034C247, 0x7643C9F3,
+		0xB3E4F77D, 0x1593FCC9, 0x247BE654, 0x820CEDE0,
+		0x74449D09, 0xD23396BD, 0xE3DB8C20, 0x45AC8794,
+		0x800BB91A, 0x267CB2AE, 0x1794A833, 0xB1E3A387,
+		0x20754FA0, 0x86024414, 0xB7EA5E89, 0x119D553D,
+		0xD43A6BB3, 0x724D6007, 0x43A57A9A, 0xE5D2712E,
+		0x139A01C7, 0xB5ED0A73, 0x840510EE, 0x22721B5A,
+		0xE7D525D4, 0x41A22E60, 0x704A34FD, 0xD63D3F49,
+		0xCC1D9F8B, 0x6A6A943F, 0x5B828EA2, 0xFDF58516,
+		0x3852BB98, 0x9E25B02C, 0xAFCDAAB1, 0x09BAA105,
+		0xFFF2D1EC, 0x5985DA58, 0x686DC0C5, 0xCE1ACB71,
+		0x0BBDF5FF, 0xADCAFE4B, 0x9C22E4D6, 0x3A55EF62,
+		0xABC30345, 0x0DB408F1, 0x3C5C126C, 0x9A2B19D8,
+		0x5F8C2756, 0xF9FB2CE2, 0xC813367F, 0x6E643DCB,
+		0x982C4D22, 0x3E5B4696, 0x0FB35C0B, 0xA9C457BF,
+		0x6C636931, 0xCA146285, 0xFBFC7818, 0x5D8B73AC,
+		0x03A0A617, 0xA5D7ADA3, 0x943FB73E, 0x3248BC8A,
+		0xF7EF8204, 0x519889B0, 0x6070932D, 0xC6079899,
+		0x304FE870, 0x9638E3C4, 0xA7D0F959, 0x01A7F2ED,
+		0xC400CC63, 0x6277C7D7, 0x539FDD4A, 0xF5E8D6FE,
+		0x647E3AD9, 0xC209316D, 0xF3E12BF0, 0x55962044,
+		0x90311ECA, 0x3646157E, 0x07AE0FE3, 0xA1D90457,
+		0x579174BE, 0xF1E67F0A, 0xC00E6597, 0x66796E23,
+		0xA3DE50AD, 0x05A95B19, 0x34414184, 0x92364A30
+	}, {
+		0x00000000, 0xCCAA009E, 0x4225077D, 0x8E8F07E3,
+		0x844A0EFA, 0x48E00E64, 0xC66F0987, 0x0AC50919,
+		0xD3E51BB5, 0x1F4F1B2B, 0x91C01CC8, 0x5D6A1C56,
+		0x57AF154F, 0x9B0515D1, 0x158A1232, 0xD92012AC,
+		0x7CBB312B, 0xB01131B5, 0x3E9E3656, 0xF23436C8,
+		0xF8F13FD1, 0x345B3F4F, 0xBAD438AC, 0x767E3832,
+		0xAF5E2A9E, 0x63F42A00, 0xED7B2DE3, 0x21D12D7D,
+		0x2B142464, 0xE7BE24FA, 0x69312319, 0xA59B2387,
+		0xF9766256, 0x35DC62C8, 0xBB53652B, 0x77F965B5,
+		0x7D3C6CAC, 0xB1966C32, 0x3F196BD1, 0xF3B36B4F,
+		0x2A9379E3, 0xE639797D, 0x68B67E9E, 0xA41C7E00,
+		0xAED97719, 0x62737787, 0xECFC7064, 0x205670FA,
+		0x85CD537D, 0x496753E3, 0xC7E85400, 0x0B42549E,
+		0x01875D87, 0xCD2D5D19, 0x43A25AFA, 0x8F085A64,
+		0x562848C8, 0x9A824856, 0x140D4FB5, 0xD8A74F2B,
+		0xD2624632, 0x1EC846AC, 0x9047414F, 0x5CED41D1,
+		0x299DC2ED, 0xE537C273, 0x6BB8C590, 0xA712C50E,
+		0xADD7CC17, 0x617DCC89, 0xEFF2CB6A, 0x2358CBF4,
+		0xFA78D958, 0x36D2D9C6, 0xB85DDE25, 0x74F7DEBB,
+		0x7E32D7A2, 0xB298D73C, 0x3C17D0DF, 0xF0BDD041,
+		0x5526F3C6, 0x998CF358, 0x1703F4BB, 0xDBA9F425,
+		0xD16CFD3C, 0x1DC6FDA2, 0x9349FA41, 0x5FE3FADF,
+		0x86C3E873, 0x4A69E8ED, 0xC4E6EF0E, 0x084CEF90,
+		0x0289E689, 0xCE23E617, 0x40ACE1F4, 0x8C06E16A,
+		0xD0EBA0BB, 0x1C41A025, 0x92CEA7C6, 0x5E64A758,
+		0x54A1AE41, 0x980BAEDF, 0x1684A93C, 0xDA2EA9A2,
+		0x030EBB0E, 0xCFA4BB90, 0x412BBC73, 0x8D81BCED,
+		0x8744B5F4, 0x4BEEB56A, 0xC561B289, 0x09CBB217,
+		0xAC509190, 0x60FA910E, 0xEE7596ED, 0x22DF9673,
+		0x281A9F6A, 0xE4B09FF4, 0x6A3F9817, 0xA6959889,
+		0x7FB58A25, 0xB31F8ABB, 0x3D908D58, 0xF13A8DC6,
+		0xFBFF84DF, 0x37558441, 0xB9DA83A2, 0x7570833C,
+		0x533B85DA, 0x9F918544, 0x111E82A7, 0xDDB48239,
+		0xD7718B20, 0x1BDB8BBE, 0x95548C5D, 0x59FE8CC3,
+		0x80DE9E6F, 0x4C749EF1, 0xC2FB9912, 0x0E51998C,
+		0x04949095, 0xC83E900B, 0x46B197E8, 0x8A1B9776,
+		0x2F80B4F1, 0xE32AB46F, 0x6DA5B38C, 0xA10FB312,
+		0xABCABA0B, 0x6760BA95, 0xE9EFBD76, 0x2545BDE8,
+		0xFC65AF44, 0x30CFAFDA, 0xBE40A839, 0x72EAA8A7,
+		0x782FA1BE, 0xB485A120, 0x3A0AA6C3, 0xF6A0A65D,
+		0xAA4DE78C, 0x66E7E712, 0xE868E0F1, 0x24C2E06F,
+		0x2E07E976, 0xE2ADE9E8, 0x6C22EE0B, 0xA088EE95,
+		0x79A8FC39, 0xB502FCA7, 0x3B8DFB44, 0xF727FBDA,
+		0xFDE2F2C3, 0x3148F25D, 0xBFC7F5BE, 0x736DF520,
+		0xD6F6D6A7, 0x1A5CD639, 0x94D3D1DA, 0x5879D144,
+		0x52BCD85D, 0x9E16D8C3, 0x1099DF20, 0xDC33DFBE,
+		0x0513CD12, 0xC9B9CD8C, 0x4736CA6F, 0x8B9CCAF1,
+		0x8159C3E8, 0x4DF3C376, 0xC37CC495, 0x0FD6C40B,
+		0x7AA64737, 0xB60C47A9, 0x3883404A, 0xF42940D4,
+		0xFEEC49CD, 0x32464953, 0xBCC94EB0, 0x70634E2E,
+		0xA9435C82, 0x65E95C1C, 0xEB665BFF, 0x27CC5B61,
+		0x2D095278, 0xE1A352E6, 0x6F2C5505, 0xA386559B,
+		0x061D761C, 0xCAB77682, 0x44387161, 0x889271FF,
+		0x825778E6, 0x4EFD7878, 0xC0727F9B, 0x0CD87F05,
+		0xD5F86DA9, 0x19526D37, 0x97DD6AD4, 0x5B776A4A,
+		0x51B26353, 0x9D1863CD, 0x1397642E, 0xDF3D64B0,
+		0x83D02561, 0x4F7A25FF, 0xC1F5221C, 0x0D5F2282,
+		0x079A2B9B, 0xCB302B05, 0x45BF2CE6, 0x89152C78,
+		0x50353ED4, 0x9C9F3E4A, 0x121039A9, 0xDEBA3937,
+		0xD47F302E, 0x18D530B0, 0x965A3753, 0x5AF037CD,
+		0xFF6B144A, 0x33C114D4, 0xBD4E1337, 0x71E413A9,
+		0x7B211AB0, 0xB78B1A2E, 0x39041DCD, 0xF5AE1D53,
+		0x2C8E0FFF, 0xE0240F61, 0x6EAB0882, 0xA201081C,
+		0xA8C40105, 0x646E019B, 0xEAE10678, 0x264B06E6
+	}
+};
diff --git a/src/liblzma/check/crc32_tablegen.c b/src/liblzma/check/crc32_tablegen.c
new file mode 100644
index 0000000..31a4d27
--- /dev/null
+++ b/src/liblzma/check/crc32_tablegen.c
@@ -0,0 +1,117 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       crc32_tablegen.c
+/// \brief      Generate crc32_table_le.h and crc32_table_be.h
+///
+/// Compiling: gcc -std=c99 -o crc32_tablegen crc32_tablegen.c
+/// Add -DWORDS_BIGENDIAN to generate big endian table.
+/// Add -DLZ_HASH_TABLE to generate lz_encoder_hash_table.h (little endian).
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "../../common/tuklib_integer.h"
+
+
+static uint32_t crc32_table[8][256];
+
+
+static void
+init_crc32_table(void)
+{
+	static const uint32_t poly32 = UINT32_C(0xEDB88320);
+
+	for (size_t s = 0; s < 8; ++s) {
+		for (size_t b = 0; b < 256; ++b) {
+			uint32_t r = s == 0 ? b : crc32_table[s - 1][b];
+
+			for (size_t i = 0; i < 8; ++i) {
+				if (r & 1)
+					r = (r >> 1) ^ poly32;
+				else
+					r >>= 1;
+			}
+
+			crc32_table[s][b] = r;
+		}
+	}
+
+#ifdef WORDS_BIGENDIAN
+	for (size_t s = 0; s < 8; ++s)
+		for (size_t b = 0; b < 256; ++b)
+			crc32_table[s][b] = bswap32(crc32_table[s][b]);
+#endif
+
+	return;
+}
+
+
+static void
+print_crc32_table(void)
+{
+	printf("/* This file has been automatically generated by "
+			"crc32_tablegen.c. */\n\n"
+			"const uint32_t lzma_crc32_table[8][256] = {\n\t{");
+
+	for (size_t s = 0; s < 8; ++s) {
+		for (size_t b = 0; b < 256; ++b) {
+			if ((b % 4) == 0)
+				printf("\n\t\t");
+
+			printf("0x%08" PRIX32, crc32_table[s][b]);
+
+			if (b != 255)
+				printf(",%s", (b+1) % 4 == 0 ? "" : " ");
+		}
+
+		if (s == 7)
+			printf("\n\t}\n};\n");
+		else
+			printf("\n\t}, {");
+	}
+
+	return;
+}
+
+
+static void
+print_lz_table(void)
+{
+	printf("/* This file has been automatically generated by "
+			"crc32_tablegen.c. */\n\n"
+			"const uint32_t lzma_lz_hash_table[256] = {");
+
+	for (size_t b = 0; b < 256; ++b) {
+		if ((b % 4) == 0)
+			printf("\n\t");
+
+		printf("0x%08" PRIX32, crc32_table[0][b]);
+
+		if (b != 255)
+			printf(",%s", (b+1) % 4 == 0 ? "" : " ");
+	}
+
+	printf("\n};\n");
+
+	return;
+}
+
+
+int
+main(void)
+{
+	init_crc32_table();
+
+#ifdef LZ_HASH_TABLE
+	print_lz_table();
+#else
+	print_crc32_table();
+#endif
+
+	return 0;
+}
diff --git a/src/liblzma/check/crc32_x86.S b/src/liblzma/check/crc32_x86.S
new file mode 100644
index 0000000..67f68a4
--- /dev/null
+++ b/src/liblzma/check/crc32_x86.S
@@ -0,0 +1,304 @@
+/*
+ * Speed-optimized CRC32 using slicing-by-eight algorithm
+ *
+ * This uses only i386 instructions, but it is optimized for i686 and later
+ * (including e.g. Pentium II/III/IV, Athlon XP, and Core 2). For i586
+ * (e.g. Pentium), slicing-by-four would be better, and even the C version
+ * of slicing-by-eight built with gcc -march=i586 tends to be a little bit
+ * better than this. Very few probably run this code on i586 or older x86
+ * so this shouldn't be a problem in practice.
+ *
+ * Authors: Igor Pavlov (original version)
+ *          Lasse Collin (AT&T syntax, PIC support, better portability)
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ *
+ * This code needs lzma_crc32_table, which can be created using the
+ * following C code:
+
+uint32_t lzma_crc32_table[8][256];
+
+void
+init_table(void)
+{
+	// IEEE-802.3
+	static const uint32_t poly32 = UINT32_C(0xEDB88320);
+
+	// Castagnoli
+	// static const uint32_t poly32 = UINT32_C(0x82F63B78);
+
+	// Koopman
+	// static const uint32_t poly32 = UINT32_C(0xEB31D82E);
+
+	for (size_t s = 0; s < 8; ++s) {
+		for (size_t b = 0; b < 256; ++b) {
+			uint32_t r = s == 0 ? b : lzma_crc32_table[s - 1][b];
+
+			for (size_t i = 0; i < 8; ++i) {
+				if (r & 1)
+					r = (r >> 1) ^ poly32;
+				else
+					r >>= 1;
+			}
+
+			lzma_crc32_table[s][b] = r;
+		}
+	}
+}
+
+ * The prototype of the CRC32 function:
+ * extern uint32_t lzma_crc32(const uint8_t *buf, size_t size, uint32_t crc);
+ */
+
+/*
+ * On some systems, the functions need to be prefixed. The prefix is
+ * usually an underscore.
+ */
+#ifndef __USER_LABEL_PREFIX__
+#	define __USER_LABEL_PREFIX__
+#endif
+#define MAKE_SYM_CAT(prefix, sym) prefix ## sym
+#define MAKE_SYM(prefix, sym) MAKE_SYM_CAT(prefix, sym)
+#define LZMA_CRC32 MAKE_SYM(__USER_LABEL_PREFIX__, lzma_crc32)
+#define LZMA_CRC32_TABLE MAKE_SYM(__USER_LABEL_PREFIX__, lzma_crc32_table)
+
+/*
+ * Solaris assembler doesn't have .p2align, and Darwin uses .align
+ * differently than GNU/Linux and Solaris.
+ */
+#if defined(__APPLE__) || defined(__MSDOS__)
+#	define ALIGN(pow2, abs) .align pow2
+#else
+#	define ALIGN(pow2, abs) .align abs
+#endif
+
+	.text
+	.globl	LZMA_CRC32
+
+#if !defined(__APPLE__) && !defined(_WIN32) && !defined(__CYGWIN__) \
+		&& !defined(__MSDOS__)
+	.type	LZMA_CRC32, @function
+#endif
+
+	ALIGN(4, 16)
+LZMA_CRC32:
+	/*
+	 * Register usage:
+	 * %eax crc
+	 * %esi buf
+	 * %edi size or buf + size
+	 * %ebx lzma_crc32_table
+	 * %ebp Table index
+	 * %ecx Temporary
+	 * %edx Temporary
+	 */
+	pushl	%ebx
+	pushl	%esi
+	pushl	%edi
+	pushl	%ebp
+	movl	0x14(%esp), %esi /* buf */
+	movl	0x18(%esp), %edi /* size */
+	movl	0x1C(%esp), %eax /* crc */
+
+	/*
+	 * Store the address of lzma_crc32_table to %ebx. This is needed to
+	 * get position-independent code (PIC).
+	 *
+	 * The PIC macro is defined by libtool, while __PIC__ is defined
+	 * by GCC but only on some systems. Testing for both makes it simpler
+	 * to test this code without libtool, and keeps the code working also
+	 * when built with libtool but using something else than GCC.
+	 *
+	 * I understood that libtool may define PIC on Windows even though
+	 * the code in Windows DLLs is not PIC in sense that it is in ELF
+	 * binaries, so we need a separate check to always use the non-PIC
+	 * code on Windows.
+	 */
+#if (!defined(PIC) && !defined(__PIC__)) \
+		|| (defined(_WIN32) || defined(__CYGWIN__))
+	/* Not PIC */
+	movl	$ LZMA_CRC32_TABLE, %ebx
+#elif defined(__APPLE__)
+	/* Mach-O */
+	call	.L_get_pc
+.L_pic:
+	leal	.L_lzma_crc32_table$non_lazy_ptr-.L_pic(%ebx), %ebx
+	movl	(%ebx), %ebx
+#else
+	/* ELF */
+	call	.L_get_pc
+	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
+	movl	LZMA_CRC32_TABLE@GOT(%ebx), %ebx
+#endif
+
+	/* Complement the initial value. */
+	notl	%eax
+
+	ALIGN(4, 16)
+.L_align:
+	/*
+	 * Check if there is enough input to use slicing-by-eight.
+	 * We need 16 bytes, because the loop pre-reads eight bytes.
+	 */
+	cmpl	$16, %edi
+	jb	.L_rest
+
+	/* Check if we have reached alignment of eight bytes. */
+	testl	$7, %esi
+	jz	.L_slice
+
+	/* Calculate CRC of the next input byte. */
+	movzbl	(%esi), %ebp
+	incl	%esi
+	movzbl	%al, %ecx
+	xorl	%ecx, %ebp
+	shrl	$8, %eax
+	xorl	(%ebx, %ebp, 4), %eax
+	decl	%edi
+	jmp	.L_align
+
+	ALIGN(2, 4)
+.L_slice:
+	/*
+	 * If we get here, there's at least 16 bytes of aligned input
+	 * available. Make %edi multiple of eight bytes. Store the possible
+	 * remainder over the "size" variable in the argument stack.
+	 */
+	movl	%edi, 0x18(%esp)
+	andl	$-8, %edi
+	subl	%edi, 0x18(%esp)
+
+	/*
+	 * Let %edi be buf + size - 8 while running the main loop. This way
+	 * we can compare for equality to determine when exit the loop.
+	 */
+	addl	%esi, %edi
+	subl	$8, %edi
+
+	/* Read in the first eight aligned bytes. */
+	xorl	(%esi), %eax
+	movl	4(%esi), %ecx
+	movzbl	%cl, %ebp
+
+.L_loop:
+	movl	0x0C00(%ebx, %ebp, 4), %edx
+	movzbl	%ch, %ebp
+	xorl	0x0800(%ebx, %ebp, 4), %edx
+	shrl	$16, %ecx
+	xorl	8(%esi), %edx
+	movzbl	%cl, %ebp
+	xorl	0x0400(%ebx, %ebp, 4), %edx
+	movzbl	%ch, %ebp
+	xorl	(%ebx, %ebp, 4), %edx
+	movzbl	%al, %ebp
+
+	/*
+	 * Read the next four bytes, for which the CRC is calculated
+	 * on the next interation of the loop.
+	 */
+	movl	12(%esi), %ecx
+
+	xorl	0x1C00(%ebx, %ebp, 4), %edx
+	movzbl	%ah, %ebp
+	shrl	$16, %eax
+	xorl	0x1800(%ebx, %ebp, 4), %edx
+	movzbl	%ah, %ebp
+	movzbl	%al, %eax
+	movl	0x1400(%ebx, %eax, 4), %eax
+	addl	$8, %esi
+	xorl	%edx, %eax
+	xorl	0x1000(%ebx, %ebp, 4), %eax
+
+	/* Check for end of aligned input. */
+	cmpl	%edi, %esi
+	movzbl	%cl, %ebp
+	jne	.L_loop
+
+	/*
+	 * Process the remaining eight bytes, which we have already
+	 * copied to %ecx and %edx.
+	 */
+	movl	0x0C00(%ebx, %ebp, 4), %edx
+	movzbl	%ch, %ebp
+	xorl	0x0800(%ebx, %ebp, 4), %edx
+	shrl	$16, %ecx
+	movzbl	%cl, %ebp
+	xorl	0x0400(%ebx, %ebp, 4), %edx
+	movzbl	%ch, %ebp
+	xorl	(%ebx, %ebp, 4), %edx
+	movzbl	%al, %ebp
+
+	xorl	0x1C00(%ebx, %ebp, 4), %edx
+	movzbl	%ah, %ebp
+	shrl	$16, %eax
+	xorl	0x1800(%ebx, %ebp, 4), %edx
+	movzbl	%ah, %ebp
+	movzbl	%al, %eax
+	movl	0x1400(%ebx, %eax, 4), %eax
+	addl	$8, %esi
+	xorl	%edx, %eax
+	xorl	0x1000(%ebx, %ebp, 4), %eax
+
+	/* Copy the number of remaining bytes to %edi. */
+	movl	0x18(%esp), %edi
+
+.L_rest:
+	/* Check for end of input. */
+	testl	%edi, %edi
+	jz	.L_return
+
+	/* Calculate CRC of the next input byte. */
+	movzbl	(%esi), %ebp
+	incl	%esi
+	movzbl	%al, %ecx
+	xorl	%ecx, %ebp
+	shrl	$8, %eax
+	xorl	(%ebx, %ebp, 4), %eax
+	decl	%edi
+	jmp	.L_rest
+
+.L_return:
+	/* Complement the final value. */
+	notl	%eax
+
+	popl	%ebp
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	ret
+
+#if defined(PIC) || defined(__PIC__)
+	ALIGN(4, 16)
+.L_get_pc:
+	movl	(%esp), %ebx
+	ret
+#endif
+
+#if defined(__APPLE__) && (defined(PIC) || defined(__PIC__))
+	/* Mach-O PIC */
+	.section __IMPORT,__pointers,non_lazy_symbol_pointers
+.L_lzma_crc32_table$non_lazy_ptr:
+	.indirect_symbol LZMA_CRC32_TABLE
+	.long 0
+
+#elif defined(_WIN32) || defined(__CYGWIN__)
+#	ifdef DLL_EXPORT
+	/* This is equivalent of __declspec(dllexport). */
+	.section .drectve
+	.ascii " -export:lzma_crc32"
+#	endif
+
+#elif !defined(__MSDOS__)
+	/* ELF */
+	.size	LZMA_CRC32, .-LZMA_CRC32
+#endif
+
+/*
+ * This is needed to support non-executable stack. It's ugly to
+ * use __linux__ here, but I don't know a way to detect when
+ * we are using GNU assembler.
+ */
+#if defined(__ELF__) && defined(__linux__)
+	.section	.note.GNU-stack,"",@progbits
+#endif
diff --git a/src/liblzma/check/crc64_fast.c b/src/liblzma/check/crc64_fast.c
new file mode 100644
index 0000000..52af29e
--- /dev/null
+++ b/src/liblzma/check/crc64_fast.c
@@ -0,0 +1,72 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       crc64.c
+/// \brief      CRC64 calculation
+///
+/// Calculate the CRC64 using the slice-by-four algorithm. This is the same
+/// idea that is used in crc32_fast.c, but for CRC64 we use only four tables
+/// instead of eight to avoid increasing CPU cache usage.
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "check.h"
+#include "crc_macros.h"
+
+
+#ifdef WORDS_BIGENDIAN
+#	define A1(x) ((x) >> 56)
+#else
+#	define A1 A
+#endif
+
+
+// See the comments in crc32_fast.c. They aren't duplicated here.
+extern LZMA_API(uint64_t)
+lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc)
+{
+	crc = ~crc;
+
+#ifdef WORDS_BIGENDIAN
+	crc = bswap64(crc);
+#endif
+
+	if (size > 4) {
+		while ((uintptr_t)(buf) & 3) {
+			crc = lzma_crc64_table[0][*buf++ ^ A1(crc)] ^ S8(crc);
+			--size;
+		}
+
+		const uint8_t *const limit = buf + (size & ~(size_t)(3));
+		size &= (size_t)(3);
+
+		while (buf < limit) {
+#ifdef WORDS_BIGENDIAN
+			const uint32_t tmp = (crc >> 32)
+					^ *(const uint32_t *)(buf);
+#else
+			const uint32_t tmp = crc ^ *(const uint32_t *)(buf);
+#endif
+			buf += 4;
+
+			crc = lzma_crc64_table[3][A(tmp)]
+			    ^ lzma_crc64_table[2][B(tmp)]
+			    ^ S32(crc)
+			    ^ lzma_crc64_table[1][C(tmp)]
+			    ^ lzma_crc64_table[0][D(tmp)];
+		}
+	}
+
+	while (size-- != 0)
+		crc = lzma_crc64_table[0][*buf++ ^ A1(crc)] ^ S8(crc);
+
+#ifdef WORDS_BIGENDIAN
+	crc = bswap64(crc);
+#endif
+
+	return ~crc;
+}
diff --git a/src/liblzma/check/crc64_small.c b/src/liblzma/check/crc64_small.c
new file mode 100644
index 0000000..55d7231
--- /dev/null
+++ b/src/liblzma/check/crc64_small.c
@@ -0,0 +1,53 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       crc64_small.c
+/// \brief      CRC64 calculation (size-optimized)
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "check.h"
+
+
+static uint64_t crc64_table[256];
+
+
+static void
+crc64_init(void)
+{
+	static const uint64_t poly64 = UINT64_C(0xC96C5795D7870F42);
+
+	for (size_t b = 0; b < 256; ++b) {
+		uint64_t r = b;
+		for (size_t i = 0; i < 8; ++i) {
+			if (r & 1)
+				r = (r >> 1) ^ poly64;
+			else
+				r >>= 1;
+		}
+
+		crc64_table[b] = r;
+	}
+
+	return;
+}
+
+
+extern LZMA_API(uint64_t)
+lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc)
+{
+	mythread_once(crc64_init);
+
+	crc = ~crc;
+
+	while (size != 0) {
+		crc = crc64_table[*buf++ ^ (crc & 0xFF)] ^ (crc >> 8);
+		--size;
+	}
+
+	return ~crc;
+}
diff --git a/src/liblzma/check/crc64_table.c b/src/liblzma/check/crc64_table.c
new file mode 100644
index 0000000..1fbcd94
--- /dev/null
+++ b/src/liblzma/check/crc64_table.c
@@ -0,0 +1,19 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       crc64_table.c
+/// \brief      Precalculated CRC64 table with correct endianness
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+
+#ifdef WORDS_BIGENDIAN
+#	include "crc64_table_be.h"
+#else
+#	include "crc64_table_le.h"
+#endif
diff --git a/src/liblzma/check/crc64_table_be.h b/src/liblzma/check/crc64_table_be.h
new file mode 100644
index 0000000..ea074f3
--- /dev/null
+++ b/src/liblzma/check/crc64_table_be.h
@@ -0,0 +1,521 @@
+/* This file has been automatically generated by crc64_tablegen.c. */
+
+const uint64_t lzma_crc64_table[4][256] = {
+	{
+		UINT64_C(0x0000000000000000), UINT64_C(0x6F5FA703BE4C2EB3),
+		UINT64_C(0x5BA040A8573684F4), UINT64_C(0x34FFE7ABE97AAA47),
+		UINT64_C(0x335E8FFF84C3D07B), UINT64_C(0x5C0128FC3A8FFEC8),
+		UINT64_C(0x68FECF57D3F5548F), UINT64_C(0x07A168546DB97A3C),
+		UINT64_C(0x66BC1EFF0987A1F7), UINT64_C(0x09E3B9FCB7CB8F44),
+		UINT64_C(0x3D1C5E575EB12503), UINT64_C(0x5243F954E0FD0BB0),
+		UINT64_C(0x55E291008D44718C), UINT64_C(0x3ABD360333085F3F),
+		UINT64_C(0x0E42D1A8DA72F578), UINT64_C(0x611D76AB643EDBCB),
+		UINT64_C(0x4966335138A19B7D), UINT64_C(0x2639945286EDB5CE),
+		UINT64_C(0x12C673F96F971F89), UINT64_C(0x7D99D4FAD1DB313A),
+		UINT64_C(0x7A38BCAEBC624B06), UINT64_C(0x15671BAD022E65B5),
+		UINT64_C(0x2198FC06EB54CFF2), UINT64_C(0x4EC75B055518E141),
+		UINT64_C(0x2FDA2DAE31263A8A), UINT64_C(0x40858AAD8F6A1439),
+		UINT64_C(0x747A6D066610BE7E), UINT64_C(0x1B25CA05D85C90CD),
+		UINT64_C(0x1C84A251B5E5EAF1), UINT64_C(0x73DB05520BA9C442),
+		UINT64_C(0x4724E2F9E2D36E05), UINT64_C(0x287B45FA5C9F40B6),
+		UINT64_C(0x92CC66A2704237FB), UINT64_C(0xFD93C1A1CE0E1948),
+		UINT64_C(0xC96C260A2774B30F), UINT64_C(0xA633810999389DBC),
+		UINT64_C(0xA192E95DF481E780), UINT64_C(0xCECD4E5E4ACDC933),
+		UINT64_C(0xFA32A9F5A3B76374), UINT64_C(0x956D0EF61DFB4DC7),
+		UINT64_C(0xF470785D79C5960C), UINT64_C(0x9B2FDF5EC789B8BF),
+		UINT64_C(0xAFD038F52EF312F8), UINT64_C(0xC08F9FF690BF3C4B),
+		UINT64_C(0xC72EF7A2FD064677), UINT64_C(0xA87150A1434A68C4),
+		UINT64_C(0x9C8EB70AAA30C283), UINT64_C(0xF3D11009147CEC30),
+		UINT64_C(0xDBAA55F348E3AC86), UINT64_C(0xB4F5F2F0F6AF8235),
+		UINT64_C(0x800A155B1FD52872), UINT64_C(0xEF55B258A19906C1),
+		UINT64_C(0xE8F4DA0CCC207CFD), UINT64_C(0x87AB7D0F726C524E),
+		UINT64_C(0xB3549AA49B16F809), UINT64_C(0xDC0B3DA7255AD6BA),
+		UINT64_C(0xBD164B0C41640D71), UINT64_C(0xD249EC0FFF2823C2),
+		UINT64_C(0xE6B60BA416528985), UINT64_C(0x89E9ACA7A81EA736),
+		UINT64_C(0x8E48C4F3C5A7DD0A), UINT64_C(0xE11763F07BEBF3B9),
+		UINT64_C(0xD5E8845B929159FE), UINT64_C(0xBAB723582CDD774D),
+		UINT64_C(0xA187C3EBCA2BB664), UINT64_C(0xCED864E8746798D7),
+		UINT64_C(0xFA2783439D1D3290), UINT64_C(0x9578244023511C23),
+		UINT64_C(0x92D94C144EE8661F), UINT64_C(0xFD86EB17F0A448AC),
+		UINT64_C(0xC9790CBC19DEE2EB), UINT64_C(0xA626ABBFA792CC58),
+		UINT64_C(0xC73BDD14C3AC1793), UINT64_C(0xA8647A177DE03920),
+		UINT64_C(0x9C9B9DBC949A9367), UINT64_C(0xF3C43ABF2AD6BDD4),
+		UINT64_C(0xF46552EB476FC7E8), UINT64_C(0x9B3AF5E8F923E95B),
+		UINT64_C(0xAFC512431059431C), UINT64_C(0xC09AB540AE156DAF),
+		UINT64_C(0xE8E1F0BAF28A2D19), UINT64_C(0x87BE57B94CC603AA),
+		UINT64_C(0xB341B012A5BCA9ED), UINT64_C(0xDC1E17111BF0875E),
+		UINT64_C(0xDBBF7F457649FD62), UINT64_C(0xB4E0D846C805D3D1),
+		UINT64_C(0x801F3FED217F7996), UINT64_C(0xEF4098EE9F335725),
+		UINT64_C(0x8E5DEE45FB0D8CEE), UINT64_C(0xE10249464541A25D),
+		UINT64_C(0xD5FDAEEDAC3B081A), UINT64_C(0xBAA209EE127726A9),
+		UINT64_C(0xBD0361BA7FCE5C95), UINT64_C(0xD25CC6B9C1827226),
+		UINT64_C(0xE6A3211228F8D861), UINT64_C(0x89FC861196B4F6D2),
+		UINT64_C(0x334BA549BA69819F), UINT64_C(0x5C14024A0425AF2C),
+		UINT64_C(0x68EBE5E1ED5F056B), UINT64_C(0x07B442E253132BD8),
+		UINT64_C(0x00152AB63EAA51E4), UINT64_C(0x6F4A8DB580E67F57),
+		UINT64_C(0x5BB56A1E699CD510), UINT64_C(0x34EACD1DD7D0FBA3),
+		UINT64_C(0x55F7BBB6B3EE2068), UINT64_C(0x3AA81CB50DA20EDB),
+		UINT64_C(0x0E57FB1EE4D8A49C), UINT64_C(0x61085C1D5A948A2F),
+		UINT64_C(0x66A93449372DF013), UINT64_C(0x09F6934A8961DEA0),
+		UINT64_C(0x3D0974E1601B74E7), UINT64_C(0x5256D3E2DE575A54),
+		UINT64_C(0x7A2D961882C81AE2), UINT64_C(0x1572311B3C843451),
+		UINT64_C(0x218DD6B0D5FE9E16), UINT64_C(0x4ED271B36BB2B0A5),
+		UINT64_C(0x497319E7060BCA99), UINT64_C(0x262CBEE4B847E42A),
+		UINT64_C(0x12D3594F513D4E6D), UINT64_C(0x7D8CFE4CEF7160DE),
+		UINT64_C(0x1C9188E78B4FBB15), UINT64_C(0x73CE2FE4350395A6),
+		UINT64_C(0x4731C84FDC793FE1), UINT64_C(0x286E6F4C62351152),
+		UINT64_C(0x2FCF07180F8C6B6E), UINT64_C(0x4090A01BB1C045DD),
+		UINT64_C(0x746F47B058BAEF9A), UINT64_C(0x1B30E0B3E6F6C129),
+		UINT64_C(0x420F87D795576CC9), UINT64_C(0x2D5020D42B1B427A),
+		UINT64_C(0x19AFC77FC261E83D), UINT64_C(0x76F0607C7C2DC68E),
+		UINT64_C(0x715108281194BCB2), UINT64_C(0x1E0EAF2BAFD89201),
+		UINT64_C(0x2AF1488046A23846), UINT64_C(0x45AEEF83F8EE16F5),
+		UINT64_C(0x24B399289CD0CD3E), UINT64_C(0x4BEC3E2B229CE38D),
+		UINT64_C(0x7F13D980CBE649CA), UINT64_C(0x104C7E8375AA6779),
+		UINT64_C(0x17ED16D718131D45), UINT64_C(0x78B2B1D4A65F33F6),
+		UINT64_C(0x4C4D567F4F2599B1), UINT64_C(0x2312F17CF169B702),
+		UINT64_C(0x0B69B486ADF6F7B4), UINT64_C(0x6436138513BAD907),
+		UINT64_C(0x50C9F42EFAC07340), UINT64_C(0x3F96532D448C5DF3),
+		UINT64_C(0x38373B79293527CF), UINT64_C(0x57689C7A9779097C),
+		UINT64_C(0x63977BD17E03A33B), UINT64_C(0x0CC8DCD2C04F8D88),
+		UINT64_C(0x6DD5AA79A4715643), UINT64_C(0x028A0D7A1A3D78F0),
+		UINT64_C(0x3675EAD1F347D2B7), UINT64_C(0x592A4DD24D0BFC04),
+		UINT64_C(0x5E8B258620B28638), UINT64_C(0x31D482859EFEA88B),
+		UINT64_C(0x052B652E778402CC), UINT64_C(0x6A74C22DC9C82C7F),
+		UINT64_C(0xD0C3E175E5155B32), UINT64_C(0xBF9C46765B597581),
+		UINT64_C(0x8B63A1DDB223DFC6), UINT64_C(0xE43C06DE0C6FF175),
+		UINT64_C(0xE39D6E8A61D68B49), UINT64_C(0x8CC2C989DF9AA5FA),
+		UINT64_C(0xB83D2E2236E00FBD), UINT64_C(0xD762892188AC210E),
+		UINT64_C(0xB67FFF8AEC92FAC5), UINT64_C(0xD920588952DED476),
+		UINT64_C(0xEDDFBF22BBA47E31), UINT64_C(0x8280182105E85082),
+		UINT64_C(0x8521707568512ABE), UINT64_C(0xEA7ED776D61D040D),
+		UINT64_C(0xDE8130DD3F67AE4A), UINT64_C(0xB1DE97DE812B80F9),
+		UINT64_C(0x99A5D224DDB4C04F), UINT64_C(0xF6FA752763F8EEFC),
+		UINT64_C(0xC205928C8A8244BB), UINT64_C(0xAD5A358F34CE6A08),
+		UINT64_C(0xAAFB5DDB59771034), UINT64_C(0xC5A4FAD8E73B3E87),
+		UINT64_C(0xF15B1D730E4194C0), UINT64_C(0x9E04BA70B00DBA73),
+		UINT64_C(0xFF19CCDBD43361B8), UINT64_C(0x90466BD86A7F4F0B),
+		UINT64_C(0xA4B98C738305E54C), UINT64_C(0xCBE62B703D49CBFF),
+		UINT64_C(0xCC47432450F0B1C3), UINT64_C(0xA318E427EEBC9F70),
+		UINT64_C(0x97E7038C07C63537), UINT64_C(0xF8B8A48FB98A1B84),
+		UINT64_C(0xE388443C5F7CDAAD), UINT64_C(0x8CD7E33FE130F41E),
+		UINT64_C(0xB8280494084A5E59), UINT64_C(0xD777A397B60670EA),
+		UINT64_C(0xD0D6CBC3DBBF0AD6), UINT64_C(0xBF896CC065F32465),
+		UINT64_C(0x8B768B6B8C898E22), UINT64_C(0xE4292C6832C5A091),
+		UINT64_C(0x85345AC356FB7B5A), UINT64_C(0xEA6BFDC0E8B755E9),
+		UINT64_C(0xDE941A6B01CDFFAE), UINT64_C(0xB1CBBD68BF81D11D),
+		UINT64_C(0xB66AD53CD238AB21), UINT64_C(0xD935723F6C748592),
+		UINT64_C(0xEDCA9594850E2FD5), UINT64_C(0x829532973B420166),
+		UINT64_C(0xAAEE776D67DD41D0), UINT64_C(0xC5B1D06ED9916F63),
+		UINT64_C(0xF14E37C530EBC524), UINT64_C(0x9E1190C68EA7EB97),
+		UINT64_C(0x99B0F892E31E91AB), UINT64_C(0xF6EF5F915D52BF18),
+		UINT64_C(0xC210B83AB428155F), UINT64_C(0xAD4F1F390A643BEC),
+		UINT64_C(0xCC5269926E5AE027), UINT64_C(0xA30DCE91D016CE94),
+		UINT64_C(0x97F2293A396C64D3), UINT64_C(0xF8AD8E3987204A60),
+		UINT64_C(0xFF0CE66DEA99305C), UINT64_C(0x9053416E54D51EEF),
+		UINT64_C(0xA4ACA6C5BDAFB4A8), UINT64_C(0xCBF301C603E39A1B),
+		UINT64_C(0x7144229E2F3EED56), UINT64_C(0x1E1B859D9172C3E5),
+		UINT64_C(0x2AE46236780869A2), UINT64_C(0x45BBC535C6444711),
+		UINT64_C(0x421AAD61ABFD3D2D), UINT64_C(0x2D450A6215B1139E),
+		UINT64_C(0x19BAEDC9FCCBB9D9), UINT64_C(0x76E54ACA4287976A),
+		UINT64_C(0x17F83C6126B94CA1), UINT64_C(0x78A79B6298F56212),
+		UINT64_C(0x4C587CC9718FC855), UINT64_C(0x2307DBCACFC3E6E6),
+		UINT64_C(0x24A6B39EA27A9CDA), UINT64_C(0x4BF9149D1C36B269),
+		UINT64_C(0x7F06F336F54C182E), UINT64_C(0x105954354B00369D),
+		UINT64_C(0x382211CF179F762B), UINT64_C(0x577DB6CCA9D35898),
+		UINT64_C(0x6382516740A9F2DF), UINT64_C(0x0CDDF664FEE5DC6C),
+		UINT64_C(0x0B7C9E30935CA650), UINT64_C(0x642339332D1088E3),
+		UINT64_C(0x50DCDE98C46A22A4), UINT64_C(0x3F83799B7A260C17),
+		UINT64_C(0x5E9E0F301E18D7DC), UINT64_C(0x31C1A833A054F96F),
+		UINT64_C(0x053E4F98492E5328), UINT64_C(0x6A61E89BF7627D9B),
+		UINT64_C(0x6DC080CF9ADB07A7), UINT64_C(0x029F27CC24972914),
+		UINT64_C(0x3660C067CDED8353), UINT64_C(0x593F676473A1ADE0)
+	}, {
+		UINT64_C(0x0000000000000000), UINT64_C(0x0DF1D05C9279E954),
+		UINT64_C(0x1AE2A1B924F3D2A9), UINT64_C(0x171371E5B68A3BFD),
+		UINT64_C(0xB1DA4DDC62497DC1), UINT64_C(0xBC2B9D80F0309495),
+		UINT64_C(0xAB38EC6546BAAF68), UINT64_C(0xA6C93C39D4C3463C),
+		UINT64_C(0xE7AB9517EE3D2210), UINT64_C(0xEA5A454B7C44CB44),
+		UINT64_C(0xFD4934AECACEF0B9), UINT64_C(0xF0B8E4F258B719ED),
+		UINT64_C(0x5671D8CB8C745FD1), UINT64_C(0x5B8008971E0DB685),
+		UINT64_C(0x4C937972A8878D78), UINT64_C(0x4162A92E3AFE642C),
+		UINT64_C(0xCE572B2FDC7B4420), UINT64_C(0xC3A6FB734E02AD74),
+		UINT64_C(0xD4B58A96F8889689), UINT64_C(0xD9445ACA6AF17FDD),
+		UINT64_C(0x7F8D66F3BE3239E1), UINT64_C(0x727CB6AF2C4BD0B5),
+		UINT64_C(0x656FC74A9AC1EB48), UINT64_C(0x689E171608B8021C),
+		UINT64_C(0x29FCBE3832466630), UINT64_C(0x240D6E64A03F8F64),
+		UINT64_C(0x331E1F8116B5B499), UINT64_C(0x3EEFCFDD84CC5DCD),
+		UINT64_C(0x9826F3E4500F1BF1), UINT64_C(0x95D723B8C276F2A5),
+		UINT64_C(0x82C4525D74FCC958), UINT64_C(0x8F358201E685200C),
+		UINT64_C(0x9CAF565EB8F78840), UINT64_C(0x915E86022A8E6114),
+		UINT64_C(0x864DF7E79C045AE9), UINT64_C(0x8BBC27BB0E7DB3BD),
+		UINT64_C(0x2D751B82DABEF581), UINT64_C(0x2084CBDE48C71CD5),
+		UINT64_C(0x3797BA3BFE4D2728), UINT64_C(0x3A666A676C34CE7C),
+		UINT64_C(0x7B04C34956CAAA50), UINT64_C(0x76F51315C4B34304),
+		UINT64_C(0x61E662F0723978F9), UINT64_C(0x6C17B2ACE04091AD),
+		UINT64_C(0xCADE8E953483D791), UINT64_C(0xC72F5EC9A6FA3EC5),
+		UINT64_C(0xD03C2F2C10700538), UINT64_C(0xDDCDFF708209EC6C),
+		UINT64_C(0x52F87D71648CCC60), UINT64_C(0x5F09AD2DF6F52534),
+		UINT64_C(0x481ADCC8407F1EC9), UINT64_C(0x45EB0C94D206F79D),
+		UINT64_C(0xE32230AD06C5B1A1), UINT64_C(0xEED3E0F194BC58F5),
+		UINT64_C(0xF9C0911422366308), UINT64_C(0xF4314148B04F8A5C),
+		UINT64_C(0xB553E8668AB1EE70), UINT64_C(0xB8A2383A18C80724),
+		UINT64_C(0xAFB149DFAE423CD9), UINT64_C(0xA24099833C3BD58D),
+		UINT64_C(0x0489A5BAE8F893B1), UINT64_C(0x097875E67A817AE5),
+		UINT64_C(0x1E6B0403CC0B4118), UINT64_C(0x139AD45F5E72A84C),
+		UINT64_C(0x385FADBC70EF1181), UINT64_C(0x35AE7DE0E296F8D5),
+		UINT64_C(0x22BD0C05541CC328), UINT64_C(0x2F4CDC59C6652A7C),
+		UINT64_C(0x8985E06012A66C40), UINT64_C(0x8474303C80DF8514),
+		UINT64_C(0x936741D93655BEE9), UINT64_C(0x9E969185A42C57BD),
+		UINT64_C(0xDFF438AB9ED23391), UINT64_C(0xD205E8F70CABDAC5),
+		UINT64_C(0xC5169912BA21E138), UINT64_C(0xC8E7494E2858086C),
+		UINT64_C(0x6E2E7577FC9B4E50), UINT64_C(0x63DFA52B6EE2A704),
+		UINT64_C(0x74CCD4CED8689CF9), UINT64_C(0x793D04924A1175AD),
+		UINT64_C(0xF6088693AC9455A1), UINT64_C(0xFBF956CF3EEDBCF5),
+		UINT64_C(0xECEA272A88678708), UINT64_C(0xE11BF7761A1E6E5C),
+		UINT64_C(0x47D2CB4FCEDD2860), UINT64_C(0x4A231B135CA4C134),
+		UINT64_C(0x5D306AF6EA2EFAC9), UINT64_C(0x50C1BAAA7857139D),
+		UINT64_C(0x11A3138442A977B1), UINT64_C(0x1C52C3D8D0D09EE5),
+		UINT64_C(0x0B41B23D665AA518), UINT64_C(0x06B06261F4234C4C),
+		UINT64_C(0xA0795E5820E00A70), UINT64_C(0xAD888E04B299E324),
+		UINT64_C(0xBA9BFFE10413D8D9), UINT64_C(0xB76A2FBD966A318D),
+		UINT64_C(0xA4F0FBE2C81899C1), UINT64_C(0xA9012BBE5A617095),
+		UINT64_C(0xBE125A5BECEB4B68), UINT64_C(0xB3E38A077E92A23C),
+		UINT64_C(0x152AB63EAA51E400), UINT64_C(0x18DB666238280D54),
+		UINT64_C(0x0FC817878EA236A9), UINT64_C(0x0239C7DB1CDBDFFD),
+		UINT64_C(0x435B6EF52625BBD1), UINT64_C(0x4EAABEA9B45C5285),
+		UINT64_C(0x59B9CF4C02D66978), UINT64_C(0x54481F1090AF802C),
+		UINT64_C(0xF2812329446CC610), UINT64_C(0xFF70F375D6152F44),
+		UINT64_C(0xE8638290609F14B9), UINT64_C(0xE59252CCF2E6FDED),
+		UINT64_C(0x6AA7D0CD1463DDE1), UINT64_C(0x67560091861A34B5),
+		UINT64_C(0x7045717430900F48), UINT64_C(0x7DB4A128A2E9E61C),
+		UINT64_C(0xDB7D9D11762AA020), UINT64_C(0xD68C4D4DE4534974),
+		UINT64_C(0xC19F3CA852D97289), UINT64_C(0xCC6EECF4C0A09BDD),
+		UINT64_C(0x8D0C45DAFA5EFFF1), UINT64_C(0x80FD9586682716A5),
+		UINT64_C(0x97EEE463DEAD2D58), UINT64_C(0x9A1F343F4CD4C40C),
+		UINT64_C(0x3CD6080698178230), UINT64_C(0x3127D85A0A6E6B64),
+		UINT64_C(0x2634A9BFBCE45099), UINT64_C(0x2BC579E32E9DB9CD),
+		UINT64_C(0xF5A054D6CA71FB90), UINT64_C(0xF851848A580812C4),
+		UINT64_C(0xEF42F56FEE822939), UINT64_C(0xE2B325337CFBC06D),
+		UINT64_C(0x447A190AA8388651), UINT64_C(0x498BC9563A416F05),
+		UINT64_C(0x5E98B8B38CCB54F8), UINT64_C(0x536968EF1EB2BDAC),
+		UINT64_C(0x120BC1C1244CD980), UINT64_C(0x1FFA119DB63530D4),
+		UINT64_C(0x08E9607800BF0B29), UINT64_C(0x0518B02492C6E27D),
+		UINT64_C(0xA3D18C1D4605A441), UINT64_C(0xAE205C41D47C4D15),
+		UINT64_C(0xB9332DA462F676E8), UINT64_C(0xB4C2FDF8F08F9FBC),
+		UINT64_C(0x3BF77FF9160ABFB0), UINT64_C(0x3606AFA5847356E4),
+		UINT64_C(0x2115DE4032F96D19), UINT64_C(0x2CE40E1CA080844D),
+		UINT64_C(0x8A2D32257443C271), UINT64_C(0x87DCE279E63A2B25),
+		UINT64_C(0x90CF939C50B010D8), UINT64_C(0x9D3E43C0C2C9F98C),
+		UINT64_C(0xDC5CEAEEF8379DA0), UINT64_C(0xD1AD3AB26A4E74F4),
+		UINT64_C(0xC6BE4B57DCC44F09), UINT64_C(0xCB4F9B0B4EBDA65D),
+		UINT64_C(0x6D86A7329A7EE061), UINT64_C(0x6077776E08070935),
+		UINT64_C(0x7764068BBE8D32C8), UINT64_C(0x7A95D6D72CF4DB9C),
+		UINT64_C(0x690F0288728673D0), UINT64_C(0x64FED2D4E0FF9A84),
+		UINT64_C(0x73EDA3315675A179), UINT64_C(0x7E1C736DC40C482D),
+		UINT64_C(0xD8D54F5410CF0E11), UINT64_C(0xD5249F0882B6E745),
+		UINT64_C(0xC237EEED343CDCB8), UINT64_C(0xCFC63EB1A64535EC),
+		UINT64_C(0x8EA4979F9CBB51C0), UINT64_C(0x835547C30EC2B894),
+		UINT64_C(0x94463626B8488369), UINT64_C(0x99B7E67A2A316A3D),
+		UINT64_C(0x3F7EDA43FEF22C01), UINT64_C(0x328F0A1F6C8BC555),
+		UINT64_C(0x259C7BFADA01FEA8), UINT64_C(0x286DABA6487817FC),
+		UINT64_C(0xA75829A7AEFD37F0), UINT64_C(0xAAA9F9FB3C84DEA4),
+		UINT64_C(0xBDBA881E8A0EE559), UINT64_C(0xB04B584218770C0D),
+		UINT64_C(0x1682647BCCB44A31), UINT64_C(0x1B73B4275ECDA365),
+		UINT64_C(0x0C60C5C2E8479898), UINT64_C(0x0191159E7A3E71CC),
+		UINT64_C(0x40F3BCB040C015E0), UINT64_C(0x4D026CECD2B9FCB4),
+		UINT64_C(0x5A111D096433C749), UINT64_C(0x57E0CD55F64A2E1D),
+		UINT64_C(0xF129F16C22896821), UINT64_C(0xFCD82130B0F08175),
+		UINT64_C(0xEBCB50D5067ABA88), UINT64_C(0xE63A8089940353DC),
+		UINT64_C(0xCDFFF96ABA9EEA11), UINT64_C(0xC00E293628E70345),
+		UINT64_C(0xD71D58D39E6D38B8), UINT64_C(0xDAEC888F0C14D1EC),
+		UINT64_C(0x7C25B4B6D8D797D0), UINT64_C(0x71D464EA4AAE7E84),
+		UINT64_C(0x66C7150FFC244579), UINT64_C(0x6B36C5536E5DAC2D),
+		UINT64_C(0x2A546C7D54A3C801), UINT64_C(0x27A5BC21C6DA2155),
+		UINT64_C(0x30B6CDC470501AA8), UINT64_C(0x3D471D98E229F3FC),
+		UINT64_C(0x9B8E21A136EAB5C0), UINT64_C(0x967FF1FDA4935C94),
+		UINT64_C(0x816C801812196769), UINT64_C(0x8C9D504480608E3D),
+		UINT64_C(0x03A8D24566E5AE31), UINT64_C(0x0E590219F49C4765),
+		UINT64_C(0x194A73FC42167C98), UINT64_C(0x14BBA3A0D06F95CC),
+		UINT64_C(0xB2729F9904ACD3F0), UINT64_C(0xBF834FC596D53AA4),
+		UINT64_C(0xA8903E20205F0159), UINT64_C(0xA561EE7CB226E80D),
+		UINT64_C(0xE403475288D88C21), UINT64_C(0xE9F2970E1AA16575),
+		UINT64_C(0xFEE1E6EBAC2B5E88), UINT64_C(0xF31036B73E52B7DC),
+		UINT64_C(0x55D90A8EEA91F1E0), UINT64_C(0x5828DAD278E818B4),
+		UINT64_C(0x4F3BAB37CE622349), UINT64_C(0x42CA7B6B5C1BCA1D),
+		UINT64_C(0x5150AF3402696251), UINT64_C(0x5CA17F6890108B05),
+		UINT64_C(0x4BB20E8D269AB0F8), UINT64_C(0x4643DED1B4E359AC),
+		UINT64_C(0xE08AE2E860201F90), UINT64_C(0xED7B32B4F259F6C4),
+		UINT64_C(0xFA68435144D3CD39), UINT64_C(0xF799930DD6AA246D),
+		UINT64_C(0xB6FB3A23EC544041), UINT64_C(0xBB0AEA7F7E2DA915),
+		UINT64_C(0xAC199B9AC8A792E8), UINT64_C(0xA1E84BC65ADE7BBC),
+		UINT64_C(0x072177FF8E1D3D80), UINT64_C(0x0AD0A7A31C64D4D4),
+		UINT64_C(0x1DC3D646AAEEEF29), UINT64_C(0x1032061A3897067D),
+		UINT64_C(0x9F07841BDE122671), UINT64_C(0x92F654474C6BCF25),
+		UINT64_C(0x85E525A2FAE1F4D8), UINT64_C(0x8814F5FE68981D8C),
+		UINT64_C(0x2EDDC9C7BC5B5BB0), UINT64_C(0x232C199B2E22B2E4),
+		UINT64_C(0x343F687E98A88919), UINT64_C(0x39CEB8220AD1604D),
+		UINT64_C(0x78AC110C302F0461), UINT64_C(0x755DC150A256ED35),
+		UINT64_C(0x624EB0B514DCD6C8), UINT64_C(0x6FBF60E986A53F9C),
+		UINT64_C(0xC9765CD0526679A0), UINT64_C(0xC4878C8CC01F90F4),
+		UINT64_C(0xD394FD697695AB09), UINT64_C(0xDE652D35E4EC425D)
+	}, {
+		UINT64_C(0x0000000000000000), UINT64_C(0xCB6D6A914AE10B3F),
+		UINT64_C(0x96DBD42295C2177E), UINT64_C(0x5DB6BEB3DF231C41),
+		UINT64_C(0x2CB7A9452A852FFC), UINT64_C(0xE7DAC3D4606424C3),
+		UINT64_C(0xBA6C7D67BF473882), UINT64_C(0x710117F6F5A633BD),
+		UINT64_C(0xDD705D247FA5876A), UINT64_C(0x161D37B535448C55),
+		UINT64_C(0x4BAB8906EA679014), UINT64_C(0x80C6E397A0869B2B),
+		UINT64_C(0xF1C7F4615520A896), UINT64_C(0x3AAA9EF01FC1A3A9),
+		UINT64_C(0x671C2043C0E2BFE8), UINT64_C(0xAC714AD28A03B4D7),
+		UINT64_C(0xBAE1BA48FE4A0FD5), UINT64_C(0x718CD0D9B4AB04EA),
+		UINT64_C(0x2C3A6E6A6B8818AB), UINT64_C(0xE75704FB21691394),
+		UINT64_C(0x9656130DD4CF2029), UINT64_C(0x5D3B799C9E2E2B16),
+		UINT64_C(0x008DC72F410D3757), UINT64_C(0xCBE0ADBE0BEC3C68),
+		UINT64_C(0x6791E76C81EF88BF), UINT64_C(0xACFC8DFDCB0E8380),
+		UINT64_C(0xF14A334E142D9FC1), UINT64_C(0x3A2759DF5ECC94FE),
+		UINT64_C(0x4B264E29AB6AA743), UINT64_C(0x804B24B8E18BAC7C),
+		UINT64_C(0xDDFD9A0B3EA8B03D), UINT64_C(0x1690F09A7449BB02),
+		UINT64_C(0xF1DD7B3ED73AC638), UINT64_C(0x3AB011AF9DDBCD07),
+		UINT64_C(0x6706AF1C42F8D146), UINT64_C(0xAC6BC58D0819DA79),
+		UINT64_C(0xDD6AD27BFDBFE9C4), UINT64_C(0x1607B8EAB75EE2FB),
+		UINT64_C(0x4BB10659687DFEBA), UINT64_C(0x80DC6CC8229CF585),
+		UINT64_C(0x2CAD261AA89F4152), UINT64_C(0xE7C04C8BE27E4A6D),
+		UINT64_C(0xBA76F2383D5D562C), UINT64_C(0x711B98A977BC5D13),
+		UINT64_C(0x001A8F5F821A6EAE), UINT64_C(0xCB77E5CEC8FB6591),
+		UINT64_C(0x96C15B7D17D879D0), UINT64_C(0x5DAC31EC5D3972EF),
+		UINT64_C(0x4B3CC1762970C9ED), UINT64_C(0x8051ABE76391C2D2),
+		UINT64_C(0xDDE71554BCB2DE93), UINT64_C(0x168A7FC5F653D5AC),
+		UINT64_C(0x678B683303F5E611), UINT64_C(0xACE602A24914ED2E),
+		UINT64_C(0xF150BC119637F16F), UINT64_C(0x3A3DD680DCD6FA50),
+		UINT64_C(0x964C9C5256D54E87), UINT64_C(0x5D21F6C31C3445B8),
+		UINT64_C(0x00974870C31759F9), UINT64_C(0xCBFA22E189F652C6),
+		UINT64_C(0xBAFB35177C50617B), UINT64_C(0x71965F8636B16A44),
+		UINT64_C(0x2C20E135E9927605), UINT64_C(0xE74D8BA4A3737D3A),
+		UINT64_C(0xE2BBF77CAE758C71), UINT64_C(0x29D69DEDE494874E),
+		UINT64_C(0x7460235E3BB79B0F), UINT64_C(0xBF0D49CF71569030),
+		UINT64_C(0xCE0C5E3984F0A38D), UINT64_C(0x056134A8CE11A8B2),
+		UINT64_C(0x58D78A1B1132B4F3), UINT64_C(0x93BAE08A5BD3BFCC),
+		UINT64_C(0x3FCBAA58D1D00B1B), UINT64_C(0xF4A6C0C99B310024),
+		UINT64_C(0xA9107E7A44121C65), UINT64_C(0x627D14EB0EF3175A),
+		UINT64_C(0x137C031DFB5524E7), UINT64_C(0xD811698CB1B42FD8),
+		UINT64_C(0x85A7D73F6E973399), UINT64_C(0x4ECABDAE247638A6),
+		UINT64_C(0x585A4D34503F83A4), UINT64_C(0x933727A51ADE889B),
+		UINT64_C(0xCE819916C5FD94DA), UINT64_C(0x05ECF3878F1C9FE5),
+		UINT64_C(0x74EDE4717ABAAC58), UINT64_C(0xBF808EE0305BA767),
+		UINT64_C(0xE2363053EF78BB26), UINT64_C(0x295B5AC2A599B019),
+		UINT64_C(0x852A10102F9A04CE), UINT64_C(0x4E477A81657B0FF1),
+		UINT64_C(0x13F1C432BA5813B0), UINT64_C(0xD89CAEA3F0B9188F),
+		UINT64_C(0xA99DB955051F2B32), UINT64_C(0x62F0D3C44FFE200D),
+		UINT64_C(0x3F466D7790DD3C4C), UINT64_C(0xF42B07E6DA3C3773),
+		UINT64_C(0x13668C42794F4A49), UINT64_C(0xD80BE6D333AE4176),
+		UINT64_C(0x85BD5860EC8D5D37), UINT64_C(0x4ED032F1A66C5608),
+		UINT64_C(0x3FD1250753CA65B5), UINT64_C(0xF4BC4F96192B6E8A),
+		UINT64_C(0xA90AF125C60872CB), UINT64_C(0x62679BB48CE979F4),
+		UINT64_C(0xCE16D16606EACD23), UINT64_C(0x057BBBF74C0BC61C),
+		UINT64_C(0x58CD05449328DA5D), UINT64_C(0x93A06FD5D9C9D162),
+		UINT64_C(0xE2A178232C6FE2DF), UINT64_C(0x29CC12B2668EE9E0),
+		UINT64_C(0x747AAC01B9ADF5A1), UINT64_C(0xBF17C690F34CFE9E),
+		UINT64_C(0xA987360A8705459C), UINT64_C(0x62EA5C9BCDE44EA3),
+		UINT64_C(0x3F5CE22812C752E2), UINT64_C(0xF43188B9582659DD),
+		UINT64_C(0x85309F4FAD806A60), UINT64_C(0x4E5DF5DEE761615F),
+		UINT64_C(0x13EB4B6D38427D1E), UINT64_C(0xD88621FC72A37621),
+		UINT64_C(0x74F76B2EF8A0C2F6), UINT64_C(0xBF9A01BFB241C9C9),
+		UINT64_C(0xE22CBF0C6D62D588), UINT64_C(0x2941D59D2783DEB7),
+		UINT64_C(0x5840C26BD225ED0A), UINT64_C(0x932DA8FA98C4E635),
+		UINT64_C(0xCE9B164947E7FA74), UINT64_C(0x05F67CD80D06F14B),
+		UINT64_C(0xC477EFF95CEB18E3), UINT64_C(0x0F1A8568160A13DC),
+		UINT64_C(0x52AC3BDBC9290F9D), UINT64_C(0x99C1514A83C804A2),
+		UINT64_C(0xE8C046BC766E371F), UINT64_C(0x23AD2C2D3C8F3C20),
+		UINT64_C(0x7E1B929EE3AC2061), UINT64_C(0xB576F80FA94D2B5E),
+		UINT64_C(0x1907B2DD234E9F89), UINT64_C(0xD26AD84C69AF94B6),
+		UINT64_C(0x8FDC66FFB68C88F7), UINT64_C(0x44B10C6EFC6D83C8),
+		UINT64_C(0x35B01B9809CBB075), UINT64_C(0xFEDD7109432ABB4A),
+		UINT64_C(0xA36BCFBA9C09A70B), UINT64_C(0x6806A52BD6E8AC34),
+		UINT64_C(0x7E9655B1A2A11736), UINT64_C(0xB5FB3F20E8401C09),
+		UINT64_C(0xE84D819337630048), UINT64_C(0x2320EB027D820B77),
+		UINT64_C(0x5221FCF4882438CA), UINT64_C(0x994C9665C2C533F5),
+		UINT64_C(0xC4FA28D61DE62FB4), UINT64_C(0x0F9742475707248B),
+		UINT64_C(0xA3E60895DD04905C), UINT64_C(0x688B620497E59B63),
+		UINT64_C(0x353DDCB748C68722), UINT64_C(0xFE50B62602278C1D),
+		UINT64_C(0x8F51A1D0F781BFA0), UINT64_C(0x443CCB41BD60B49F),
+		UINT64_C(0x198A75F26243A8DE), UINT64_C(0xD2E71F6328A2A3E1),
+		UINT64_C(0x35AA94C78BD1DEDB), UINT64_C(0xFEC7FE56C130D5E4),
+		UINT64_C(0xA37140E51E13C9A5), UINT64_C(0x681C2A7454F2C29A),
+		UINT64_C(0x191D3D82A154F127), UINT64_C(0xD2705713EBB5FA18),
+		UINT64_C(0x8FC6E9A03496E659), UINT64_C(0x44AB83317E77ED66),
+		UINT64_C(0xE8DAC9E3F47459B1), UINT64_C(0x23B7A372BE95528E),
+		UINT64_C(0x7E011DC161B64ECF), UINT64_C(0xB56C77502B5745F0),
+		UINT64_C(0xC46D60A6DEF1764D), UINT64_C(0x0F000A3794107D72),
+		UINT64_C(0x52B6B4844B336133), UINT64_C(0x99DBDE1501D26A0C),
+		UINT64_C(0x8F4B2E8F759BD10E), UINT64_C(0x4426441E3F7ADA31),
+		UINT64_C(0x1990FAADE059C670), UINT64_C(0xD2FD903CAAB8CD4F),
+		UINT64_C(0xA3FC87CA5F1EFEF2), UINT64_C(0x6891ED5B15FFF5CD),
+		UINT64_C(0x352753E8CADCE98C), UINT64_C(0xFE4A3979803DE2B3),
+		UINT64_C(0x523B73AB0A3E5664), UINT64_C(0x9956193A40DF5D5B),
+		UINT64_C(0xC4E0A7899FFC411A), UINT64_C(0x0F8DCD18D51D4A25),
+		UINT64_C(0x7E8CDAEE20BB7998), UINT64_C(0xB5E1B07F6A5A72A7),
+		UINT64_C(0xE8570ECCB5796EE6), UINT64_C(0x233A645DFF9865D9),
+		UINT64_C(0x26CC1885F29E9492), UINT64_C(0xEDA17214B87F9FAD),
+		UINT64_C(0xB017CCA7675C83EC), UINT64_C(0x7B7AA6362DBD88D3),
+		UINT64_C(0x0A7BB1C0D81BBB6E), UINT64_C(0xC116DB5192FAB051),
+		UINT64_C(0x9CA065E24DD9AC10), UINT64_C(0x57CD0F730738A72F),
+		UINT64_C(0xFBBC45A18D3B13F8), UINT64_C(0x30D12F30C7DA18C7),
+		UINT64_C(0x6D67918318F90486), UINT64_C(0xA60AFB1252180FB9),
+		UINT64_C(0xD70BECE4A7BE3C04), UINT64_C(0x1C668675ED5F373B),
+		UINT64_C(0x41D038C6327C2B7A), UINT64_C(0x8ABD5257789D2045),
+		UINT64_C(0x9C2DA2CD0CD49B47), UINT64_C(0x5740C85C46359078),
+		UINT64_C(0x0AF676EF99168C39), UINT64_C(0xC19B1C7ED3F78706),
+		UINT64_C(0xB09A0B882651B4BB), UINT64_C(0x7BF761196CB0BF84),
+		UINT64_C(0x2641DFAAB393A3C5), UINT64_C(0xED2CB53BF972A8FA),
+		UINT64_C(0x415DFFE973711C2D), UINT64_C(0x8A30957839901712),
+		UINT64_C(0xD7862BCBE6B30B53), UINT64_C(0x1CEB415AAC52006C),
+		UINT64_C(0x6DEA56AC59F433D1), UINT64_C(0xA6873C3D131538EE),
+		UINT64_C(0xFB31828ECC3624AF), UINT64_C(0x305CE81F86D72F90),
+		UINT64_C(0xD71163BB25A452AA), UINT64_C(0x1C7C092A6F455995),
+		UINT64_C(0x41CAB799B06645D4), UINT64_C(0x8AA7DD08FA874EEB),
+		UINT64_C(0xFBA6CAFE0F217D56), UINT64_C(0x30CBA06F45C07669),
+		UINT64_C(0x6D7D1EDC9AE36A28), UINT64_C(0xA610744DD0026117),
+		UINT64_C(0x0A613E9F5A01D5C0), UINT64_C(0xC10C540E10E0DEFF),
+		UINT64_C(0x9CBAEABDCFC3C2BE), UINT64_C(0x57D7802C8522C981),
+		UINT64_C(0x26D697DA7084FA3C), UINT64_C(0xEDBBFD4B3A65F103),
+		UINT64_C(0xB00D43F8E546ED42), UINT64_C(0x7B602969AFA7E67D),
+		UINT64_C(0x6DF0D9F3DBEE5D7F), UINT64_C(0xA69DB362910F5640),
+		UINT64_C(0xFB2B0DD14E2C4A01), UINT64_C(0x3046674004CD413E),
+		UINT64_C(0x414770B6F16B7283), UINT64_C(0x8A2A1A27BB8A79BC),
+		UINT64_C(0xD79CA49464A965FD), UINT64_C(0x1CF1CE052E486EC2),
+		UINT64_C(0xB08084D7A44BDA15), UINT64_C(0x7BEDEE46EEAAD12A),
+		UINT64_C(0x265B50F53189CD6B), UINT64_C(0xED363A647B68C654),
+		UINT64_C(0x9C372D928ECEF5E9), UINT64_C(0x575A4703C42FFED6),
+		UINT64_C(0x0AECF9B01B0CE297), UINT64_C(0xC181932151EDE9A8)
+	}, {
+		UINT64_C(0x0000000000000000), UINT64_C(0xDCA12C225E8AEE1D),
+		UINT64_C(0xB8435944BC14DD3B), UINT64_C(0x64E27566E29E3326),
+		UINT64_C(0x7087B2887829BA77), UINT64_C(0xAC269EAA26A3546A),
+		UINT64_C(0xC8C4EBCCC43D674C), UINT64_C(0x1465C7EE9AB78951),
+		UINT64_C(0xE00E6511F15274EF), UINT64_C(0x3CAF4933AFD89AF2),
+		UINT64_C(0x584D3C554D46A9D4), UINT64_C(0x84EC107713CC47C9),
+		UINT64_C(0x9089D799897BCE98), UINT64_C(0x4C28FBBBD7F12085),
+		UINT64_C(0x28CA8EDD356F13A3), UINT64_C(0xF46BA2FF6BE5FDBE),
+		UINT64_C(0x4503C48DC90A304C), UINT64_C(0x99A2E8AF9780DE51),
+		UINT64_C(0xFD409DC9751EED77), UINT64_C(0x21E1B1EB2B94036A),
+		UINT64_C(0x35847605B1238A3B), UINT64_C(0xE9255A27EFA96426),
+		UINT64_C(0x8DC72F410D375700), UINT64_C(0x5166036353BDB91D),
+		UINT64_C(0xA50DA19C385844A3), UINT64_C(0x79AC8DBE66D2AABE),
+		UINT64_C(0x1D4EF8D8844C9998), UINT64_C(0xC1EFD4FADAC67785),
+		UINT64_C(0xD58A13144071FED4), UINT64_C(0x092B3F361EFB10C9),
+		UINT64_C(0x6DC94A50FC6523EF), UINT64_C(0xB1686672A2EFCDF2),
+		UINT64_C(0x8A06881B93156098), UINT64_C(0x56A7A439CD9F8E85),
+		UINT64_C(0x3245D15F2F01BDA3), UINT64_C(0xEEE4FD7D718B53BE),
+		UINT64_C(0xFA813A93EB3CDAEF), UINT64_C(0x262016B1B5B634F2),
+		UINT64_C(0x42C263D7572807D4), UINT64_C(0x9E634FF509A2E9C9),
+		UINT64_C(0x6A08ED0A62471477), UINT64_C(0xB6A9C1283CCDFA6A),
+		UINT64_C(0xD24BB44EDE53C94C), UINT64_C(0x0EEA986C80D92751),
+		UINT64_C(0x1A8F5F821A6EAE00), UINT64_C(0xC62E73A044E4401D),
+		UINT64_C(0xA2CC06C6A67A733B), UINT64_C(0x7E6D2AE4F8F09D26),
+		UINT64_C(0xCF054C965A1F50D4), UINT64_C(0x13A460B40495BEC9),
+		UINT64_C(0x774615D2E60B8DEF), UINT64_C(0xABE739F0B88163F2),
+		UINT64_C(0xBF82FE1E2236EAA3), UINT64_C(0x6323D23C7CBC04BE),
+		UINT64_C(0x07C1A75A9E223798), UINT64_C(0xDB608B78C0A8D985),
+		UINT64_C(0x2F0B2987AB4D243B), UINT64_C(0xF3AA05A5F5C7CA26),
+		UINT64_C(0x974870C31759F900), UINT64_C(0x4BE95CE149D3171D),
+		UINT64_C(0x5F8C9B0FD3649E4C), UINT64_C(0x832DB72D8DEE7051),
+		UINT64_C(0xE7CFC24B6F704377), UINT64_C(0x3B6EEE6931FAAD6A),
+		UINT64_C(0x91131E980D8418A2), UINT64_C(0x4DB232BA530EF6BF),
+		UINT64_C(0x295047DCB190C599), UINT64_C(0xF5F16BFEEF1A2B84),
+		UINT64_C(0xE194AC1075ADA2D5), UINT64_C(0x3D3580322B274CC8),
+		UINT64_C(0x59D7F554C9B97FEE), UINT64_C(0x8576D976973391F3),
+		UINT64_C(0x711D7B89FCD66C4D), UINT64_C(0xADBC57ABA25C8250),
+		UINT64_C(0xC95E22CD40C2B176), UINT64_C(0x15FF0EEF1E485F6B),
+		UINT64_C(0x019AC90184FFD63A), UINT64_C(0xDD3BE523DA753827),
+		UINT64_C(0xB9D9904538EB0B01), UINT64_C(0x6578BC676661E51C),
+		UINT64_C(0xD410DA15C48E28EE), UINT64_C(0x08B1F6379A04C6F3),
+		UINT64_C(0x6C538351789AF5D5), UINT64_C(0xB0F2AF7326101BC8),
+		UINT64_C(0xA497689DBCA79299), UINT64_C(0x783644BFE22D7C84),
+		UINT64_C(0x1CD431D900B34FA2), UINT64_C(0xC0751DFB5E39A1BF),
+		UINT64_C(0x341EBF0435DC5C01), UINT64_C(0xE8BF93266B56B21C),
+		UINT64_C(0x8C5DE64089C8813A), UINT64_C(0x50FCCA62D7426F27),
+		UINT64_C(0x44990D8C4DF5E676), UINT64_C(0x983821AE137F086B),
+		UINT64_C(0xFCDA54C8F1E13B4D), UINT64_C(0x207B78EAAF6BD550),
+		UINT64_C(0x1B1596839E91783A), UINT64_C(0xC7B4BAA1C01B9627),
+		UINT64_C(0xA356CFC72285A501), UINT64_C(0x7FF7E3E57C0F4B1C),
+		UINT64_C(0x6B92240BE6B8C24D), UINT64_C(0xB7330829B8322C50),
+		UINT64_C(0xD3D17D4F5AAC1F76), UINT64_C(0x0F70516D0426F16B),
+		UINT64_C(0xFB1BF3926FC30CD5), UINT64_C(0x27BADFB03149E2C8),
+		UINT64_C(0x4358AAD6D3D7D1EE), UINT64_C(0x9FF986F48D5D3FF3),
+		UINT64_C(0x8B9C411A17EAB6A2), UINT64_C(0x573D6D38496058BF),
+		UINT64_C(0x33DF185EABFE6B99), UINT64_C(0xEF7E347CF5748584),
+		UINT64_C(0x5E16520E579B4876), UINT64_C(0x82B77E2C0911A66B),
+		UINT64_C(0xE6550B4AEB8F954D), UINT64_C(0x3AF42768B5057B50),
+		UINT64_C(0x2E91E0862FB2F201), UINT64_C(0xF230CCA471381C1C),
+		UINT64_C(0x96D2B9C293A62F3A), UINT64_C(0x4A7395E0CD2CC127),
+		UINT64_C(0xBE18371FA6C93C99), UINT64_C(0x62B91B3DF843D284),
+		UINT64_C(0x065B6E5B1ADDE1A2), UINT64_C(0xDAFA427944570FBF),
+		UINT64_C(0xCE9F8597DEE086EE), UINT64_C(0x123EA9B5806A68F3),
+		UINT64_C(0x76DCDCD362F45BD5), UINT64_C(0xAA7DF0F13C7EB5C8),
+		UINT64_C(0xA739329F30A7E9D6), UINT64_C(0x7B981EBD6E2D07CB),
+		UINT64_C(0x1F7A6BDB8CB334ED), UINT64_C(0xC3DB47F9D239DAF0),
+		UINT64_C(0xD7BE8017488E53A1), UINT64_C(0x0B1FAC351604BDBC),
+		UINT64_C(0x6FFDD953F49A8E9A), UINT64_C(0xB35CF571AA106087),
+		UINT64_C(0x4737578EC1F59D39), UINT64_C(0x9B967BAC9F7F7324),
+		UINT64_C(0xFF740ECA7DE14002), UINT64_C(0x23D522E8236BAE1F),
+		UINT64_C(0x37B0E506B9DC274E), UINT64_C(0xEB11C924E756C953),
+		UINT64_C(0x8FF3BC4205C8FA75), UINT64_C(0x535290605B421468),
+		UINT64_C(0xE23AF612F9ADD99A), UINT64_C(0x3E9BDA30A7273787),
+		UINT64_C(0x5A79AF5645B904A1), UINT64_C(0x86D883741B33EABC),
+		UINT64_C(0x92BD449A818463ED), UINT64_C(0x4E1C68B8DF0E8DF0),
+		UINT64_C(0x2AFE1DDE3D90BED6), UINT64_C(0xF65F31FC631A50CB),
+		UINT64_C(0x0234930308FFAD75), UINT64_C(0xDE95BF2156754368),
+		UINT64_C(0xBA77CA47B4EB704E), UINT64_C(0x66D6E665EA619E53),
+		UINT64_C(0x72B3218B70D61702), UINT64_C(0xAE120DA92E5CF91F),
+		UINT64_C(0xCAF078CFCCC2CA39), UINT64_C(0x165154ED92482424),
+		UINT64_C(0x2D3FBA84A3B2894E), UINT64_C(0xF19E96A6FD386753),
+		UINT64_C(0x957CE3C01FA65475), UINT64_C(0x49DDCFE2412CBA68),
+		UINT64_C(0x5DB8080CDB9B3339), UINT64_C(0x8119242E8511DD24),
+		UINT64_C(0xE5FB5148678FEE02), UINT64_C(0x395A7D6A3905001F),
+		UINT64_C(0xCD31DF9552E0FDA1), UINT64_C(0x1190F3B70C6A13BC),
+		UINT64_C(0x757286D1EEF4209A), UINT64_C(0xA9D3AAF3B07ECE87),
+		UINT64_C(0xBDB66D1D2AC947D6), UINT64_C(0x6117413F7443A9CB),
+		UINT64_C(0x05F5345996DD9AED), UINT64_C(0xD954187BC85774F0),
+		UINT64_C(0x683C7E096AB8B902), UINT64_C(0xB49D522B3432571F),
+		UINT64_C(0xD07F274DD6AC6439), UINT64_C(0x0CDE0B6F88268A24),
+		UINT64_C(0x18BBCC8112910375), UINT64_C(0xC41AE0A34C1BED68),
+		UINT64_C(0xA0F895C5AE85DE4E), UINT64_C(0x7C59B9E7F00F3053),
+		UINT64_C(0x88321B189BEACDED), UINT64_C(0x5493373AC56023F0),
+		UINT64_C(0x3071425C27FE10D6), UINT64_C(0xECD06E7E7974FECB),
+		UINT64_C(0xF8B5A990E3C3779A), UINT64_C(0x241485B2BD499987),
+		UINT64_C(0x40F6F0D45FD7AAA1), UINT64_C(0x9C57DCF6015D44BC),
+		UINT64_C(0x362A2C073D23F174), UINT64_C(0xEA8B002563A91F69),
+		UINT64_C(0x8E69754381372C4F), UINT64_C(0x52C85961DFBDC252),
+		UINT64_C(0x46AD9E8F450A4B03), UINT64_C(0x9A0CB2AD1B80A51E),
+		UINT64_C(0xFEEEC7CBF91E9638), UINT64_C(0x224FEBE9A7947825),
+		UINT64_C(0xD6244916CC71859B), UINT64_C(0x0A85653492FB6B86),
+		UINT64_C(0x6E671052706558A0), UINT64_C(0xB2C63C702EEFB6BD),
+		UINT64_C(0xA6A3FB9EB4583FEC), UINT64_C(0x7A02D7BCEAD2D1F1),
+		UINT64_C(0x1EE0A2DA084CE2D7), UINT64_C(0xC2418EF856C60CCA),
+		UINT64_C(0x7329E88AF429C138), UINT64_C(0xAF88C4A8AAA32F25),
+		UINT64_C(0xCB6AB1CE483D1C03), UINT64_C(0x17CB9DEC16B7F21E),
+		UINT64_C(0x03AE5A028C007B4F), UINT64_C(0xDF0F7620D28A9552),
+		UINT64_C(0xBBED03463014A674), UINT64_C(0x674C2F646E9E4869),
+		UINT64_C(0x93278D9B057BB5D7), UINT64_C(0x4F86A1B95BF15BCA),
+		UINT64_C(0x2B64D4DFB96F68EC), UINT64_C(0xF7C5F8FDE7E586F1),
+		UINT64_C(0xE3A03F137D520FA0), UINT64_C(0x3F01133123D8E1BD),
+		UINT64_C(0x5BE36657C146D29B), UINT64_C(0x87424A759FCC3C86),
+		UINT64_C(0xBC2CA41CAE3691EC), UINT64_C(0x608D883EF0BC7FF1),
+		UINT64_C(0x046FFD5812224CD7), UINT64_C(0xD8CED17A4CA8A2CA),
+		UINT64_C(0xCCAB1694D61F2B9B), UINT64_C(0x100A3AB68895C586),
+		UINT64_C(0x74E84FD06A0BF6A0), UINT64_C(0xA84963F2348118BD),
+		UINT64_C(0x5C22C10D5F64E503), UINT64_C(0x8083ED2F01EE0B1E),
+		UINT64_C(0xE4619849E3703838), UINT64_C(0x38C0B46BBDFAD625),
+		UINT64_C(0x2CA57385274D5F74), UINT64_C(0xF0045FA779C7B169),
+		UINT64_C(0x94E62AC19B59824F), UINT64_C(0x484706E3C5D36C52),
+		UINT64_C(0xF92F6091673CA1A0), UINT64_C(0x258E4CB339B64FBD),
+		UINT64_C(0x416C39D5DB287C9B), UINT64_C(0x9DCD15F785A29286),
+		UINT64_C(0x89A8D2191F151BD7), UINT64_C(0x5509FE3B419FF5CA),
+		UINT64_C(0x31EB8B5DA301C6EC), UINT64_C(0xED4AA77FFD8B28F1),
+		UINT64_C(0x19210580966ED54F), UINT64_C(0xC58029A2C8E43B52),
+		UINT64_C(0xA1625CC42A7A0874), UINT64_C(0x7DC370E674F0E669),
+		UINT64_C(0x69A6B708EE476F38), UINT64_C(0xB5079B2AB0CD8125),
+		UINT64_C(0xD1E5EE4C5253B203), UINT64_C(0x0D44C26E0CD95C1E)
+	}
+};
diff --git a/src/liblzma/check/crc64_table_le.h b/src/liblzma/check/crc64_table_le.h
new file mode 100644
index 0000000..1196b31
--- /dev/null
+++ b/src/liblzma/check/crc64_table_le.h
@@ -0,0 +1,521 @@
+/* This file has been automatically generated by crc64_tablegen.c. */
+
+const uint64_t lzma_crc64_table[4][256] = {
+	{
+		UINT64_C(0x0000000000000000), UINT64_C(0xB32E4CBE03A75F6F),
+		UINT64_C(0xF4843657A840A05B), UINT64_C(0x47AA7AE9ABE7FF34),
+		UINT64_C(0x7BD0C384FF8F5E33), UINT64_C(0xC8FE8F3AFC28015C),
+		UINT64_C(0x8F54F5D357CFFE68), UINT64_C(0x3C7AB96D5468A107),
+		UINT64_C(0xF7A18709FF1EBC66), UINT64_C(0x448FCBB7FCB9E309),
+		UINT64_C(0x0325B15E575E1C3D), UINT64_C(0xB00BFDE054F94352),
+		UINT64_C(0x8C71448D0091E255), UINT64_C(0x3F5F08330336BD3A),
+		UINT64_C(0x78F572DAA8D1420E), UINT64_C(0xCBDB3E64AB761D61),
+		UINT64_C(0x7D9BA13851336649), UINT64_C(0xCEB5ED8652943926),
+		UINT64_C(0x891F976FF973C612), UINT64_C(0x3A31DBD1FAD4997D),
+		UINT64_C(0x064B62BCAEBC387A), UINT64_C(0xB5652E02AD1B6715),
+		UINT64_C(0xF2CF54EB06FC9821), UINT64_C(0x41E11855055BC74E),
+		UINT64_C(0x8A3A2631AE2DDA2F), UINT64_C(0x39146A8FAD8A8540),
+		UINT64_C(0x7EBE1066066D7A74), UINT64_C(0xCD905CD805CA251B),
+		UINT64_C(0xF1EAE5B551A2841C), UINT64_C(0x42C4A90B5205DB73),
+		UINT64_C(0x056ED3E2F9E22447), UINT64_C(0xB6409F5CFA457B28),
+		UINT64_C(0xFB374270A266CC92), UINT64_C(0x48190ECEA1C193FD),
+		UINT64_C(0x0FB374270A266CC9), UINT64_C(0xBC9D3899098133A6),
+		UINT64_C(0x80E781F45DE992A1), UINT64_C(0x33C9CD4A5E4ECDCE),
+		UINT64_C(0x7463B7A3F5A932FA), UINT64_C(0xC74DFB1DF60E6D95),
+		UINT64_C(0x0C96C5795D7870F4), UINT64_C(0xBFB889C75EDF2F9B),
+		UINT64_C(0xF812F32EF538D0AF), UINT64_C(0x4B3CBF90F69F8FC0),
+		UINT64_C(0x774606FDA2F72EC7), UINT64_C(0xC4684A43A15071A8),
+		UINT64_C(0x83C230AA0AB78E9C), UINT64_C(0x30EC7C140910D1F3),
+		UINT64_C(0x86ACE348F355AADB), UINT64_C(0x3582AFF6F0F2F5B4),
+		UINT64_C(0x7228D51F5B150A80), UINT64_C(0xC10699A158B255EF),
+		UINT64_C(0xFD7C20CC0CDAF4E8), UINT64_C(0x4E526C720F7DAB87),
+		UINT64_C(0x09F8169BA49A54B3), UINT64_C(0xBAD65A25A73D0BDC),
+		UINT64_C(0x710D64410C4B16BD), UINT64_C(0xC22328FF0FEC49D2),
+		UINT64_C(0x85895216A40BB6E6), UINT64_C(0x36A71EA8A7ACE989),
+		UINT64_C(0x0ADDA7C5F3C4488E), UINT64_C(0xB9F3EB7BF06317E1),
+		UINT64_C(0xFE5991925B84E8D5), UINT64_C(0x4D77DD2C5823B7BA),
+		UINT64_C(0x64B62BCAEBC387A1), UINT64_C(0xD7986774E864D8CE),
+		UINT64_C(0x90321D9D438327FA), UINT64_C(0x231C512340247895),
+		UINT64_C(0x1F66E84E144CD992), UINT64_C(0xAC48A4F017EB86FD),
+		UINT64_C(0xEBE2DE19BC0C79C9), UINT64_C(0x58CC92A7BFAB26A6),
+		UINT64_C(0x9317ACC314DD3BC7), UINT64_C(0x2039E07D177A64A8),
+		UINT64_C(0x67939A94BC9D9B9C), UINT64_C(0xD4BDD62ABF3AC4F3),
+		UINT64_C(0xE8C76F47EB5265F4), UINT64_C(0x5BE923F9E8F53A9B),
+		UINT64_C(0x1C4359104312C5AF), UINT64_C(0xAF6D15AE40B59AC0),
+		UINT64_C(0x192D8AF2BAF0E1E8), UINT64_C(0xAA03C64CB957BE87),
+		UINT64_C(0xEDA9BCA512B041B3), UINT64_C(0x5E87F01B11171EDC),
+		UINT64_C(0x62FD4976457FBFDB), UINT64_C(0xD1D305C846D8E0B4),
+		UINT64_C(0x96797F21ED3F1F80), UINT64_C(0x2557339FEE9840EF),
+		UINT64_C(0xEE8C0DFB45EE5D8E), UINT64_C(0x5DA24145464902E1),
+		UINT64_C(0x1A083BACEDAEFDD5), UINT64_C(0xA9267712EE09A2BA),
+		UINT64_C(0x955CCE7FBA6103BD), UINT64_C(0x267282C1B9C65CD2),
+		UINT64_C(0x61D8F8281221A3E6), UINT64_C(0xD2F6B4961186FC89),
+		UINT64_C(0x9F8169BA49A54B33), UINT64_C(0x2CAF25044A02145C),
+		UINT64_C(0x6B055FEDE1E5EB68), UINT64_C(0xD82B1353E242B407),
+		UINT64_C(0xE451AA3EB62A1500), UINT64_C(0x577FE680B58D4A6F),
+		UINT64_C(0x10D59C691E6AB55B), UINT64_C(0xA3FBD0D71DCDEA34),
+		UINT64_C(0x6820EEB3B6BBF755), UINT64_C(0xDB0EA20DB51CA83A),
+		UINT64_C(0x9CA4D8E41EFB570E), UINT64_C(0x2F8A945A1D5C0861),
+		UINT64_C(0x13F02D374934A966), UINT64_C(0xA0DE61894A93F609),
+		UINT64_C(0xE7741B60E174093D), UINT64_C(0x545A57DEE2D35652),
+		UINT64_C(0xE21AC88218962D7A), UINT64_C(0x5134843C1B317215),
+		UINT64_C(0x169EFED5B0D68D21), UINT64_C(0xA5B0B26BB371D24E),
+		UINT64_C(0x99CA0B06E7197349), UINT64_C(0x2AE447B8E4BE2C26),
+		UINT64_C(0x6D4E3D514F59D312), UINT64_C(0xDE6071EF4CFE8C7D),
+		UINT64_C(0x15BB4F8BE788911C), UINT64_C(0xA6950335E42FCE73),
+		UINT64_C(0xE13F79DC4FC83147), UINT64_C(0x521135624C6F6E28),
+		UINT64_C(0x6E6B8C0F1807CF2F), UINT64_C(0xDD45C0B11BA09040),
+		UINT64_C(0x9AEFBA58B0476F74), UINT64_C(0x29C1F6E6B3E0301B),
+		UINT64_C(0xC96C5795D7870F42), UINT64_C(0x7A421B2BD420502D),
+		UINT64_C(0x3DE861C27FC7AF19), UINT64_C(0x8EC62D7C7C60F076),
+		UINT64_C(0xB2BC941128085171), UINT64_C(0x0192D8AF2BAF0E1E),
+		UINT64_C(0x4638A2468048F12A), UINT64_C(0xF516EEF883EFAE45),
+		UINT64_C(0x3ECDD09C2899B324), UINT64_C(0x8DE39C222B3EEC4B),
+		UINT64_C(0xCA49E6CB80D9137F), UINT64_C(0x7967AA75837E4C10),
+		UINT64_C(0x451D1318D716ED17), UINT64_C(0xF6335FA6D4B1B278),
+		UINT64_C(0xB199254F7F564D4C), UINT64_C(0x02B769F17CF11223),
+		UINT64_C(0xB4F7F6AD86B4690B), UINT64_C(0x07D9BA1385133664),
+		UINT64_C(0x4073C0FA2EF4C950), UINT64_C(0xF35D8C442D53963F),
+		UINT64_C(0xCF273529793B3738), UINT64_C(0x7C0979977A9C6857),
+		UINT64_C(0x3BA3037ED17B9763), UINT64_C(0x888D4FC0D2DCC80C),
+		UINT64_C(0x435671A479AAD56D), UINT64_C(0xF0783D1A7A0D8A02),
+		UINT64_C(0xB7D247F3D1EA7536), UINT64_C(0x04FC0B4DD24D2A59),
+		UINT64_C(0x3886B22086258B5E), UINT64_C(0x8BA8FE9E8582D431),
+		UINT64_C(0xCC0284772E652B05), UINT64_C(0x7F2CC8C92DC2746A),
+		UINT64_C(0x325B15E575E1C3D0), UINT64_C(0x8175595B76469CBF),
+		UINT64_C(0xC6DF23B2DDA1638B), UINT64_C(0x75F16F0CDE063CE4),
+		UINT64_C(0x498BD6618A6E9DE3), UINT64_C(0xFAA59ADF89C9C28C),
+		UINT64_C(0xBD0FE036222E3DB8), UINT64_C(0x0E21AC88218962D7),
+		UINT64_C(0xC5FA92EC8AFF7FB6), UINT64_C(0x76D4DE52895820D9),
+		UINT64_C(0x317EA4BB22BFDFED), UINT64_C(0x8250E80521188082),
+		UINT64_C(0xBE2A516875702185), UINT64_C(0x0D041DD676D77EEA),
+		UINT64_C(0x4AAE673FDD3081DE), UINT64_C(0xF9802B81DE97DEB1),
+		UINT64_C(0x4FC0B4DD24D2A599), UINT64_C(0xFCEEF8632775FAF6),
+		UINT64_C(0xBB44828A8C9205C2), UINT64_C(0x086ACE348F355AAD),
+		UINT64_C(0x34107759DB5DFBAA), UINT64_C(0x873E3BE7D8FAA4C5),
+		UINT64_C(0xC094410E731D5BF1), UINT64_C(0x73BA0DB070BA049E),
+		UINT64_C(0xB86133D4DBCC19FF), UINT64_C(0x0B4F7F6AD86B4690),
+		UINT64_C(0x4CE50583738CB9A4), UINT64_C(0xFFCB493D702BE6CB),
+		UINT64_C(0xC3B1F050244347CC), UINT64_C(0x709FBCEE27E418A3),
+		UINT64_C(0x3735C6078C03E797), UINT64_C(0x841B8AB98FA4B8F8),
+		UINT64_C(0xADDA7C5F3C4488E3), UINT64_C(0x1EF430E13FE3D78C),
+		UINT64_C(0x595E4A08940428B8), UINT64_C(0xEA7006B697A377D7),
+		UINT64_C(0xD60ABFDBC3CBD6D0), UINT64_C(0x6524F365C06C89BF),
+		UINT64_C(0x228E898C6B8B768B), UINT64_C(0x91A0C532682C29E4),
+		UINT64_C(0x5A7BFB56C35A3485), UINT64_C(0xE955B7E8C0FD6BEA),
+		UINT64_C(0xAEFFCD016B1A94DE), UINT64_C(0x1DD181BF68BDCBB1),
+		UINT64_C(0x21AB38D23CD56AB6), UINT64_C(0x9285746C3F7235D9),
+		UINT64_C(0xD52F0E859495CAED), UINT64_C(0x6601423B97329582),
+		UINT64_C(0xD041DD676D77EEAA), UINT64_C(0x636F91D96ED0B1C5),
+		UINT64_C(0x24C5EB30C5374EF1), UINT64_C(0x97EBA78EC690119E),
+		UINT64_C(0xAB911EE392F8B099), UINT64_C(0x18BF525D915FEFF6),
+		UINT64_C(0x5F1528B43AB810C2), UINT64_C(0xEC3B640A391F4FAD),
+		UINT64_C(0x27E05A6E926952CC), UINT64_C(0x94CE16D091CE0DA3),
+		UINT64_C(0xD3646C393A29F297), UINT64_C(0x604A2087398EADF8),
+		UINT64_C(0x5C3099EA6DE60CFF), UINT64_C(0xEF1ED5546E415390),
+		UINT64_C(0xA8B4AFBDC5A6ACA4), UINT64_C(0x1B9AE303C601F3CB),
+		UINT64_C(0x56ED3E2F9E224471), UINT64_C(0xE5C372919D851B1E),
+		UINT64_C(0xA26908783662E42A), UINT64_C(0x114744C635C5BB45),
+		UINT64_C(0x2D3DFDAB61AD1A42), UINT64_C(0x9E13B115620A452D),
+		UINT64_C(0xD9B9CBFCC9EDBA19), UINT64_C(0x6A978742CA4AE576),
+		UINT64_C(0xA14CB926613CF817), UINT64_C(0x1262F598629BA778),
+		UINT64_C(0x55C88F71C97C584C), UINT64_C(0xE6E6C3CFCADB0723),
+		UINT64_C(0xDA9C7AA29EB3A624), UINT64_C(0x69B2361C9D14F94B),
+		UINT64_C(0x2E184CF536F3067F), UINT64_C(0x9D36004B35545910),
+		UINT64_C(0x2B769F17CF112238), UINT64_C(0x9858D3A9CCB67D57),
+		UINT64_C(0xDFF2A94067518263), UINT64_C(0x6CDCE5FE64F6DD0C),
+		UINT64_C(0x50A65C93309E7C0B), UINT64_C(0xE388102D33392364),
+		UINT64_C(0xA4226AC498DEDC50), UINT64_C(0x170C267A9B79833F),
+		UINT64_C(0xDCD7181E300F9E5E), UINT64_C(0x6FF954A033A8C131),
+		UINT64_C(0x28532E49984F3E05), UINT64_C(0x9B7D62F79BE8616A),
+		UINT64_C(0xA707DB9ACF80C06D), UINT64_C(0x14299724CC279F02),
+		UINT64_C(0x5383EDCD67C06036), UINT64_C(0xE0ADA17364673F59)
+	}, {
+		UINT64_C(0x0000000000000000), UINT64_C(0x54E979925CD0F10D),
+		UINT64_C(0xA9D2F324B9A1E21A), UINT64_C(0xFD3B8AB6E5711317),
+		UINT64_C(0xC17D4962DC4DDAB1), UINT64_C(0x959430F0809D2BBC),
+		UINT64_C(0x68AFBA4665EC38AB), UINT64_C(0x3C46C3D4393CC9A6),
+		UINT64_C(0x10223DEE1795ABE7), UINT64_C(0x44CB447C4B455AEA),
+		UINT64_C(0xB9F0CECAAE3449FD), UINT64_C(0xED19B758F2E4B8F0),
+		UINT64_C(0xD15F748CCBD87156), UINT64_C(0x85B60D1E9708805B),
+		UINT64_C(0x788D87A87279934C), UINT64_C(0x2C64FE3A2EA96241),
+		UINT64_C(0x20447BDC2F2B57CE), UINT64_C(0x74AD024E73FBA6C3),
+		UINT64_C(0x899688F8968AB5D4), UINT64_C(0xDD7FF16ACA5A44D9),
+		UINT64_C(0xE13932BEF3668D7F), UINT64_C(0xB5D04B2CAFB67C72),
+		UINT64_C(0x48EBC19A4AC76F65), UINT64_C(0x1C02B80816179E68),
+		UINT64_C(0x3066463238BEFC29), UINT64_C(0x648F3FA0646E0D24),
+		UINT64_C(0x99B4B516811F1E33), UINT64_C(0xCD5DCC84DDCFEF3E),
+		UINT64_C(0xF11B0F50E4F32698), UINT64_C(0xA5F276C2B823D795),
+		UINT64_C(0x58C9FC745D52C482), UINT64_C(0x0C2085E60182358F),
+		UINT64_C(0x4088F7B85E56AF9C), UINT64_C(0x14618E2A02865E91),
+		UINT64_C(0xE95A049CE7F74D86), UINT64_C(0xBDB37D0EBB27BC8B),
+		UINT64_C(0x81F5BEDA821B752D), UINT64_C(0xD51CC748DECB8420),
+		UINT64_C(0x28274DFE3BBA9737), UINT64_C(0x7CCE346C676A663A),
+		UINT64_C(0x50AACA5649C3047B), UINT64_C(0x0443B3C41513F576),
+		UINT64_C(0xF9783972F062E661), UINT64_C(0xAD9140E0ACB2176C),
+		UINT64_C(0x91D78334958EDECA), UINT64_C(0xC53EFAA6C95E2FC7),
+		UINT64_C(0x380570102C2F3CD0), UINT64_C(0x6CEC098270FFCDDD),
+		UINT64_C(0x60CC8C64717DF852), UINT64_C(0x3425F5F62DAD095F),
+		UINT64_C(0xC91E7F40C8DC1A48), UINT64_C(0x9DF706D2940CEB45),
+		UINT64_C(0xA1B1C506AD3022E3), UINT64_C(0xF558BC94F1E0D3EE),
+		UINT64_C(0x086336221491C0F9), UINT64_C(0x5C8A4FB0484131F4),
+		UINT64_C(0x70EEB18A66E853B5), UINT64_C(0x2407C8183A38A2B8),
+		UINT64_C(0xD93C42AEDF49B1AF), UINT64_C(0x8DD53B3C839940A2),
+		UINT64_C(0xB193F8E8BAA58904), UINT64_C(0xE57A817AE6757809),
+		UINT64_C(0x18410BCC03046B1E), UINT64_C(0x4CA8725E5FD49A13),
+		UINT64_C(0x8111EF70BCAD5F38), UINT64_C(0xD5F896E2E07DAE35),
+		UINT64_C(0x28C31C54050CBD22), UINT64_C(0x7C2A65C659DC4C2F),
+		UINT64_C(0x406CA61260E08589), UINT64_C(0x1485DF803C307484),
+		UINT64_C(0xE9BE5536D9416793), UINT64_C(0xBD572CA48591969E),
+		UINT64_C(0x9133D29EAB38F4DF), UINT64_C(0xC5DAAB0CF7E805D2),
+		UINT64_C(0x38E121BA129916C5), UINT64_C(0x6C0858284E49E7C8),
+		UINT64_C(0x504E9BFC77752E6E), UINT64_C(0x04A7E26E2BA5DF63),
+		UINT64_C(0xF99C68D8CED4CC74), UINT64_C(0xAD75114A92043D79),
+		UINT64_C(0xA15594AC938608F6), UINT64_C(0xF5BCED3ECF56F9FB),
+		UINT64_C(0x088767882A27EAEC), UINT64_C(0x5C6E1E1A76F71BE1),
+		UINT64_C(0x6028DDCE4FCBD247), UINT64_C(0x34C1A45C131B234A),
+		UINT64_C(0xC9FA2EEAF66A305D), UINT64_C(0x9D135778AABAC150),
+		UINT64_C(0xB177A9428413A311), UINT64_C(0xE59ED0D0D8C3521C),
+		UINT64_C(0x18A55A663DB2410B), UINT64_C(0x4C4C23F46162B006),
+		UINT64_C(0x700AE020585E79A0), UINT64_C(0x24E399B2048E88AD),
+		UINT64_C(0xD9D81304E1FF9BBA), UINT64_C(0x8D316A96BD2F6AB7),
+		UINT64_C(0xC19918C8E2FBF0A4), UINT64_C(0x9570615ABE2B01A9),
+		UINT64_C(0x684BEBEC5B5A12BE), UINT64_C(0x3CA2927E078AE3B3),
+		UINT64_C(0x00E451AA3EB62A15), UINT64_C(0x540D28386266DB18),
+		UINT64_C(0xA936A28E8717C80F), UINT64_C(0xFDDFDB1CDBC73902),
+		UINT64_C(0xD1BB2526F56E5B43), UINT64_C(0x85525CB4A9BEAA4E),
+		UINT64_C(0x7869D6024CCFB959), UINT64_C(0x2C80AF90101F4854),
+		UINT64_C(0x10C66C44292381F2), UINT64_C(0x442F15D675F370FF),
+		UINT64_C(0xB9149F60908263E8), UINT64_C(0xEDFDE6F2CC5292E5),
+		UINT64_C(0xE1DD6314CDD0A76A), UINT64_C(0xB5341A8691005667),
+		UINT64_C(0x480F903074714570), UINT64_C(0x1CE6E9A228A1B47D),
+		UINT64_C(0x20A02A76119D7DDB), UINT64_C(0x744953E44D4D8CD6),
+		UINT64_C(0x8972D952A83C9FC1), UINT64_C(0xDD9BA0C0F4EC6ECC),
+		UINT64_C(0xF1FF5EFADA450C8D), UINT64_C(0xA51627688695FD80),
+		UINT64_C(0x582DADDE63E4EE97), UINT64_C(0x0CC4D44C3F341F9A),
+		UINT64_C(0x308217980608D63C), UINT64_C(0x646B6E0A5AD82731),
+		UINT64_C(0x9950E4BCBFA93426), UINT64_C(0xCDB99D2EE379C52B),
+		UINT64_C(0x90FB71CAD654A0F5), UINT64_C(0xC41208588A8451F8),
+		UINT64_C(0x392982EE6FF542EF), UINT64_C(0x6DC0FB7C3325B3E2),
+		UINT64_C(0x518638A80A197A44), UINT64_C(0x056F413A56C98B49),
+		UINT64_C(0xF854CB8CB3B8985E), UINT64_C(0xACBDB21EEF686953),
+		UINT64_C(0x80D94C24C1C10B12), UINT64_C(0xD43035B69D11FA1F),
+		UINT64_C(0x290BBF007860E908), UINT64_C(0x7DE2C69224B01805),
+		UINT64_C(0x41A405461D8CD1A3), UINT64_C(0x154D7CD4415C20AE),
+		UINT64_C(0xE876F662A42D33B9), UINT64_C(0xBC9F8FF0F8FDC2B4),
+		UINT64_C(0xB0BF0A16F97FF73B), UINT64_C(0xE4567384A5AF0636),
+		UINT64_C(0x196DF93240DE1521), UINT64_C(0x4D8480A01C0EE42C),
+		UINT64_C(0x71C2437425322D8A), UINT64_C(0x252B3AE679E2DC87),
+		UINT64_C(0xD810B0509C93CF90), UINT64_C(0x8CF9C9C2C0433E9D),
+		UINT64_C(0xA09D37F8EEEA5CDC), UINT64_C(0xF4744E6AB23AADD1),
+		UINT64_C(0x094FC4DC574BBEC6), UINT64_C(0x5DA6BD4E0B9B4FCB),
+		UINT64_C(0x61E07E9A32A7866D), UINT64_C(0x350907086E777760),
+		UINT64_C(0xC8328DBE8B066477), UINT64_C(0x9CDBF42CD7D6957A),
+		UINT64_C(0xD073867288020F69), UINT64_C(0x849AFFE0D4D2FE64),
+		UINT64_C(0x79A1755631A3ED73), UINT64_C(0x2D480CC46D731C7E),
+		UINT64_C(0x110ECF10544FD5D8), UINT64_C(0x45E7B682089F24D5),
+		UINT64_C(0xB8DC3C34EDEE37C2), UINT64_C(0xEC3545A6B13EC6CF),
+		UINT64_C(0xC051BB9C9F97A48E), UINT64_C(0x94B8C20EC3475583),
+		UINT64_C(0x698348B826364694), UINT64_C(0x3D6A312A7AE6B799),
+		UINT64_C(0x012CF2FE43DA7E3F), UINT64_C(0x55C58B6C1F0A8F32),
+		UINT64_C(0xA8FE01DAFA7B9C25), UINT64_C(0xFC177848A6AB6D28),
+		UINT64_C(0xF037FDAEA72958A7), UINT64_C(0xA4DE843CFBF9A9AA),
+		UINT64_C(0x59E50E8A1E88BABD), UINT64_C(0x0D0C771842584BB0),
+		UINT64_C(0x314AB4CC7B648216), UINT64_C(0x65A3CD5E27B4731B),
+		UINT64_C(0x989847E8C2C5600C), UINT64_C(0xCC713E7A9E159101),
+		UINT64_C(0xE015C040B0BCF340), UINT64_C(0xB4FCB9D2EC6C024D),
+		UINT64_C(0x49C73364091D115A), UINT64_C(0x1D2E4AF655CDE057),
+		UINT64_C(0x216889226CF129F1), UINT64_C(0x7581F0B03021D8FC),
+		UINT64_C(0x88BA7A06D550CBEB), UINT64_C(0xDC53039489803AE6),
+		UINT64_C(0x11EA9EBA6AF9FFCD), UINT64_C(0x4503E72836290EC0),
+		UINT64_C(0xB8386D9ED3581DD7), UINT64_C(0xECD1140C8F88ECDA),
+		UINT64_C(0xD097D7D8B6B4257C), UINT64_C(0x847EAE4AEA64D471),
+		UINT64_C(0x794524FC0F15C766), UINT64_C(0x2DAC5D6E53C5366B),
+		UINT64_C(0x01C8A3547D6C542A), UINT64_C(0x5521DAC621BCA527),
+		UINT64_C(0xA81A5070C4CDB630), UINT64_C(0xFCF329E2981D473D),
+		UINT64_C(0xC0B5EA36A1218E9B), UINT64_C(0x945C93A4FDF17F96),
+		UINT64_C(0x6967191218806C81), UINT64_C(0x3D8E608044509D8C),
+		UINT64_C(0x31AEE56645D2A803), UINT64_C(0x65479CF41902590E),
+		UINT64_C(0x987C1642FC734A19), UINT64_C(0xCC956FD0A0A3BB14),
+		UINT64_C(0xF0D3AC04999F72B2), UINT64_C(0xA43AD596C54F83BF),
+		UINT64_C(0x59015F20203E90A8), UINT64_C(0x0DE826B27CEE61A5),
+		UINT64_C(0x218CD888524703E4), UINT64_C(0x7565A11A0E97F2E9),
+		UINT64_C(0x885E2BACEBE6E1FE), UINT64_C(0xDCB7523EB73610F3),
+		UINT64_C(0xE0F191EA8E0AD955), UINT64_C(0xB418E878D2DA2858),
+		UINT64_C(0x492362CE37AB3B4F), UINT64_C(0x1DCA1B5C6B7BCA42),
+		UINT64_C(0x5162690234AF5051), UINT64_C(0x058B1090687FA15C),
+		UINT64_C(0xF8B09A268D0EB24B), UINT64_C(0xAC59E3B4D1DE4346),
+		UINT64_C(0x901F2060E8E28AE0), UINT64_C(0xC4F659F2B4327BED),
+		UINT64_C(0x39CDD344514368FA), UINT64_C(0x6D24AAD60D9399F7),
+		UINT64_C(0x414054EC233AFBB6), UINT64_C(0x15A92D7E7FEA0ABB),
+		UINT64_C(0xE892A7C89A9B19AC), UINT64_C(0xBC7BDE5AC64BE8A1),
+		UINT64_C(0x803D1D8EFF772107), UINT64_C(0xD4D4641CA3A7D00A),
+		UINT64_C(0x29EFEEAA46D6C31D), UINT64_C(0x7D0697381A063210),
+		UINT64_C(0x712612DE1B84079F), UINT64_C(0x25CF6B4C4754F692),
+		UINT64_C(0xD8F4E1FAA225E585), UINT64_C(0x8C1D9868FEF51488),
+		UINT64_C(0xB05B5BBCC7C9DD2E), UINT64_C(0xE4B2222E9B192C23),
+		UINT64_C(0x1989A8987E683F34), UINT64_C(0x4D60D10A22B8CE39),
+		UINT64_C(0x61042F300C11AC78), UINT64_C(0x35ED56A250C15D75),
+		UINT64_C(0xC8D6DC14B5B04E62), UINT64_C(0x9C3FA586E960BF6F),
+		UINT64_C(0xA0796652D05C76C9), UINT64_C(0xF4901FC08C8C87C4),
+		UINT64_C(0x09AB957669FD94D3), UINT64_C(0x5D42ECE4352D65DE)
+	}, {
+		UINT64_C(0x0000000000000000), UINT64_C(0x3F0BE14A916A6DCB),
+		UINT64_C(0x7E17C29522D4DB96), UINT64_C(0x411C23DFB3BEB65D),
+		UINT64_C(0xFC2F852A45A9B72C), UINT64_C(0xC3246460D4C3DAE7),
+		UINT64_C(0x823847BF677D6CBA), UINT64_C(0xBD33A6F5F6170171),
+		UINT64_C(0x6A87A57F245D70DD), UINT64_C(0x558C4435B5371D16),
+		UINT64_C(0x149067EA0689AB4B), UINT64_C(0x2B9B86A097E3C680),
+		UINT64_C(0x96A8205561F4C7F1), UINT64_C(0xA9A3C11FF09EAA3A),
+		UINT64_C(0xE8BFE2C043201C67), UINT64_C(0xD7B4038AD24A71AC),
+		UINT64_C(0xD50F4AFE48BAE1BA), UINT64_C(0xEA04ABB4D9D08C71),
+		UINT64_C(0xAB18886B6A6E3A2C), UINT64_C(0x94136921FB0457E7),
+		UINT64_C(0x2920CFD40D135696), UINT64_C(0x162B2E9E9C793B5D),
+		UINT64_C(0x57370D412FC78D00), UINT64_C(0x683CEC0BBEADE0CB),
+		UINT64_C(0xBF88EF816CE79167), UINT64_C(0x80830ECBFD8DFCAC),
+		UINT64_C(0xC19F2D144E334AF1), UINT64_C(0xFE94CC5EDF59273A),
+		UINT64_C(0x43A76AAB294E264B), UINT64_C(0x7CAC8BE1B8244B80),
+		UINT64_C(0x3DB0A83E0B9AFDDD), UINT64_C(0x02BB49749AF09016),
+		UINT64_C(0x38C63AD73E7BDDF1), UINT64_C(0x07CDDB9DAF11B03A),
+		UINT64_C(0x46D1F8421CAF0667), UINT64_C(0x79DA19088DC56BAC),
+		UINT64_C(0xC4E9BFFD7BD26ADD), UINT64_C(0xFBE25EB7EAB80716),
+		UINT64_C(0xBAFE7D685906B14B), UINT64_C(0x85F59C22C86CDC80),
+		UINT64_C(0x52419FA81A26AD2C), UINT64_C(0x6D4A7EE28B4CC0E7),
+		UINT64_C(0x2C565D3D38F276BA), UINT64_C(0x135DBC77A9981B71),
+		UINT64_C(0xAE6E1A825F8F1A00), UINT64_C(0x9165FBC8CEE577CB),
+		UINT64_C(0xD079D8177D5BC196), UINT64_C(0xEF72395DEC31AC5D),
+		UINT64_C(0xEDC9702976C13C4B), UINT64_C(0xD2C29163E7AB5180),
+		UINT64_C(0x93DEB2BC5415E7DD), UINT64_C(0xACD553F6C57F8A16),
+		UINT64_C(0x11E6F50333688B67), UINT64_C(0x2EED1449A202E6AC),
+		UINT64_C(0x6FF1379611BC50F1), UINT64_C(0x50FAD6DC80D63D3A),
+		UINT64_C(0x874ED556529C4C96), UINT64_C(0xB845341CC3F6215D),
+		UINT64_C(0xF95917C370489700), UINT64_C(0xC652F689E122FACB),
+		UINT64_C(0x7B61507C1735FBBA), UINT64_C(0x446AB136865F9671),
+		UINT64_C(0x057692E935E1202C), UINT64_C(0x3A7D73A3A48B4DE7),
+		UINT64_C(0x718C75AE7CF7BBE2), UINT64_C(0x4E8794E4ED9DD629),
+		UINT64_C(0x0F9BB73B5E236074), UINT64_C(0x30905671CF490DBF),
+		UINT64_C(0x8DA3F084395E0CCE), UINT64_C(0xB2A811CEA8346105),
+		UINT64_C(0xF3B432111B8AD758), UINT64_C(0xCCBFD35B8AE0BA93),
+		UINT64_C(0x1B0BD0D158AACB3F), UINT64_C(0x2400319BC9C0A6F4),
+		UINT64_C(0x651C12447A7E10A9), UINT64_C(0x5A17F30EEB147D62),
+		UINT64_C(0xE72455FB1D037C13), UINT64_C(0xD82FB4B18C6911D8),
+		UINT64_C(0x9933976E3FD7A785), UINT64_C(0xA6387624AEBDCA4E),
+		UINT64_C(0xA4833F50344D5A58), UINT64_C(0x9B88DE1AA5273793),
+		UINT64_C(0xDA94FDC5169981CE), UINT64_C(0xE59F1C8F87F3EC05),
+		UINT64_C(0x58ACBA7A71E4ED74), UINT64_C(0x67A75B30E08E80BF),
+		UINT64_C(0x26BB78EF533036E2), UINT64_C(0x19B099A5C25A5B29),
+		UINT64_C(0xCE049A2F10102A85), UINT64_C(0xF10F7B65817A474E),
+		UINT64_C(0xB01358BA32C4F113), UINT64_C(0x8F18B9F0A3AE9CD8),
+		UINT64_C(0x322B1F0555B99DA9), UINT64_C(0x0D20FE4FC4D3F062),
+		UINT64_C(0x4C3CDD90776D463F), UINT64_C(0x73373CDAE6072BF4),
+		UINT64_C(0x494A4F79428C6613), UINT64_C(0x7641AE33D3E60BD8),
+		UINT64_C(0x375D8DEC6058BD85), UINT64_C(0x08566CA6F132D04E),
+		UINT64_C(0xB565CA530725D13F), UINT64_C(0x8A6E2B19964FBCF4),
+		UINT64_C(0xCB7208C625F10AA9), UINT64_C(0xF479E98CB49B6762),
+		UINT64_C(0x23CDEA0666D116CE), UINT64_C(0x1CC60B4CF7BB7B05),
+		UINT64_C(0x5DDA28934405CD58), UINT64_C(0x62D1C9D9D56FA093),
+		UINT64_C(0xDFE26F2C2378A1E2), UINT64_C(0xE0E98E66B212CC29),
+		UINT64_C(0xA1F5ADB901AC7A74), UINT64_C(0x9EFE4CF390C617BF),
+		UINT64_C(0x9C4505870A3687A9), UINT64_C(0xA34EE4CD9B5CEA62),
+		UINT64_C(0xE252C71228E25C3F), UINT64_C(0xDD592658B98831F4),
+		UINT64_C(0x606A80AD4F9F3085), UINT64_C(0x5F6161E7DEF55D4E),
+		UINT64_C(0x1E7D42386D4BEB13), UINT64_C(0x2176A372FC2186D8),
+		UINT64_C(0xF6C2A0F82E6BF774), UINT64_C(0xC9C941B2BF019ABF),
+		UINT64_C(0x88D5626D0CBF2CE2), UINT64_C(0xB7DE83279DD54129),
+		UINT64_C(0x0AED25D26BC24058), UINT64_C(0x35E6C498FAA82D93),
+		UINT64_C(0x74FAE74749169BCE), UINT64_C(0x4BF1060DD87CF605),
+		UINT64_C(0xE318EB5CF9EF77C4), UINT64_C(0xDC130A1668851A0F),
+		UINT64_C(0x9D0F29C9DB3BAC52), UINT64_C(0xA204C8834A51C199),
+		UINT64_C(0x1F376E76BC46C0E8), UINT64_C(0x203C8F3C2D2CAD23),
+		UINT64_C(0x6120ACE39E921B7E), UINT64_C(0x5E2B4DA90FF876B5),
+		UINT64_C(0x899F4E23DDB20719), UINT64_C(0xB694AF694CD86AD2),
+		UINT64_C(0xF7888CB6FF66DC8F), UINT64_C(0xC8836DFC6E0CB144),
+		UINT64_C(0x75B0CB09981BB035), UINT64_C(0x4ABB2A430971DDFE),
+		UINT64_C(0x0BA7099CBACF6BA3), UINT64_C(0x34ACE8D62BA50668),
+		UINT64_C(0x3617A1A2B155967E), UINT64_C(0x091C40E8203FFBB5),
+		UINT64_C(0x4800633793814DE8), UINT64_C(0x770B827D02EB2023),
+		UINT64_C(0xCA382488F4FC2152), UINT64_C(0xF533C5C265964C99),
+		UINT64_C(0xB42FE61DD628FAC4), UINT64_C(0x8B2407574742970F),
+		UINT64_C(0x5C9004DD9508E6A3), UINT64_C(0x639BE59704628B68),
+		UINT64_C(0x2287C648B7DC3D35), UINT64_C(0x1D8C270226B650FE),
+		UINT64_C(0xA0BF81F7D0A1518F), UINT64_C(0x9FB460BD41CB3C44),
+		UINT64_C(0xDEA84362F2758A19), UINT64_C(0xE1A3A228631FE7D2),
+		UINT64_C(0xDBDED18BC794AA35), UINT64_C(0xE4D530C156FEC7FE),
+		UINT64_C(0xA5C9131EE54071A3), UINT64_C(0x9AC2F254742A1C68),
+		UINT64_C(0x27F154A1823D1D19), UINT64_C(0x18FAB5EB135770D2),
+		UINT64_C(0x59E69634A0E9C68F), UINT64_C(0x66ED777E3183AB44),
+		UINT64_C(0xB15974F4E3C9DAE8), UINT64_C(0x8E5295BE72A3B723),
+		UINT64_C(0xCF4EB661C11D017E), UINT64_C(0xF045572B50776CB5),
+		UINT64_C(0x4D76F1DEA6606DC4), UINT64_C(0x727D1094370A000F),
+		UINT64_C(0x3361334B84B4B652), UINT64_C(0x0C6AD20115DEDB99),
+		UINT64_C(0x0ED19B758F2E4B8F), UINT64_C(0x31DA7A3F1E442644),
+		UINT64_C(0x70C659E0ADFA9019), UINT64_C(0x4FCDB8AA3C90FDD2),
+		UINT64_C(0xF2FE1E5FCA87FCA3), UINT64_C(0xCDF5FF155BED9168),
+		UINT64_C(0x8CE9DCCAE8532735), UINT64_C(0xB3E23D8079394AFE),
+		UINT64_C(0x64563E0AAB733B52), UINT64_C(0x5B5DDF403A195699),
+		UINT64_C(0x1A41FC9F89A7E0C4), UINT64_C(0x254A1DD518CD8D0F),
+		UINT64_C(0x9879BB20EEDA8C7E), UINT64_C(0xA7725A6A7FB0E1B5),
+		UINT64_C(0xE66E79B5CC0E57E8), UINT64_C(0xD96598FF5D643A23),
+		UINT64_C(0x92949EF28518CC26), UINT64_C(0xAD9F7FB81472A1ED),
+		UINT64_C(0xEC835C67A7CC17B0), UINT64_C(0xD388BD2D36A67A7B),
+		UINT64_C(0x6EBB1BD8C0B17B0A), UINT64_C(0x51B0FA9251DB16C1),
+		UINT64_C(0x10ACD94DE265A09C), UINT64_C(0x2FA73807730FCD57),
+		UINT64_C(0xF8133B8DA145BCFB), UINT64_C(0xC718DAC7302FD130),
+		UINT64_C(0x8604F9188391676D), UINT64_C(0xB90F185212FB0AA6),
+		UINT64_C(0x043CBEA7E4EC0BD7), UINT64_C(0x3B375FED7586661C),
+		UINT64_C(0x7A2B7C32C638D041), UINT64_C(0x45209D785752BD8A),
+		UINT64_C(0x479BD40CCDA22D9C), UINT64_C(0x789035465CC84057),
+		UINT64_C(0x398C1699EF76F60A), UINT64_C(0x0687F7D37E1C9BC1),
+		UINT64_C(0xBBB45126880B9AB0), UINT64_C(0x84BFB06C1961F77B),
+		UINT64_C(0xC5A393B3AADF4126), UINT64_C(0xFAA872F93BB52CED),
+		UINT64_C(0x2D1C7173E9FF5D41), UINT64_C(0x121790397895308A),
+		UINT64_C(0x530BB3E6CB2B86D7), UINT64_C(0x6C0052AC5A41EB1C),
+		UINT64_C(0xD133F459AC56EA6D), UINT64_C(0xEE3815133D3C87A6),
+		UINT64_C(0xAF2436CC8E8231FB), UINT64_C(0x902FD7861FE85C30),
+		UINT64_C(0xAA52A425BB6311D7), UINT64_C(0x9559456F2A097C1C),
+		UINT64_C(0xD44566B099B7CA41), UINT64_C(0xEB4E87FA08DDA78A),
+		UINT64_C(0x567D210FFECAA6FB), UINT64_C(0x6976C0456FA0CB30),
+		UINT64_C(0x286AE39ADC1E7D6D), UINT64_C(0x176102D04D7410A6),
+		UINT64_C(0xC0D5015A9F3E610A), UINT64_C(0xFFDEE0100E540CC1),
+		UINT64_C(0xBEC2C3CFBDEABA9C), UINT64_C(0x81C922852C80D757),
+		UINT64_C(0x3CFA8470DA97D626), UINT64_C(0x03F1653A4BFDBBED),
+		UINT64_C(0x42ED46E5F8430DB0), UINT64_C(0x7DE6A7AF6929607B),
+		UINT64_C(0x7F5DEEDBF3D9F06D), UINT64_C(0x40560F9162B39DA6),
+		UINT64_C(0x014A2C4ED10D2BFB), UINT64_C(0x3E41CD0440674630),
+		UINT64_C(0x83726BF1B6704741), UINT64_C(0xBC798ABB271A2A8A),
+		UINT64_C(0xFD65A96494A49CD7), UINT64_C(0xC26E482E05CEF11C),
+		UINT64_C(0x15DA4BA4D78480B0), UINT64_C(0x2AD1AAEE46EEED7B),
+		UINT64_C(0x6BCD8931F5505B26), UINT64_C(0x54C6687B643A36ED),
+		UINT64_C(0xE9F5CE8E922D379C), UINT64_C(0xD6FE2FC403475A57),
+		UINT64_C(0x97E20C1BB0F9EC0A), UINT64_C(0xA8E9ED51219381C1)
+	}, {
+		UINT64_C(0x0000000000000000), UINT64_C(0x1DEE8A5E222CA1DC),
+		UINT64_C(0x3BDD14BC445943B8), UINT64_C(0x26339EE26675E264),
+		UINT64_C(0x77BA297888B28770), UINT64_C(0x6A54A326AA9E26AC),
+		UINT64_C(0x4C673DC4CCEBC4C8), UINT64_C(0x5189B79AEEC76514),
+		UINT64_C(0xEF7452F111650EE0), UINT64_C(0xF29AD8AF3349AF3C),
+		UINT64_C(0xD4A9464D553C4D58), UINT64_C(0xC947CC137710EC84),
+		UINT64_C(0x98CE7B8999D78990), UINT64_C(0x8520F1D7BBFB284C),
+		UINT64_C(0xA3136F35DD8ECA28), UINT64_C(0xBEFDE56BFFA26BF4),
+		UINT64_C(0x4C300AC98DC40345), UINT64_C(0x51DE8097AFE8A299),
+		UINT64_C(0x77ED1E75C99D40FD), UINT64_C(0x6A03942BEBB1E121),
+		UINT64_C(0x3B8A23B105768435), UINT64_C(0x2664A9EF275A25E9),
+		UINT64_C(0x0057370D412FC78D), UINT64_C(0x1DB9BD5363036651),
+		UINT64_C(0xA34458389CA10DA5), UINT64_C(0xBEAAD266BE8DAC79),
+		UINT64_C(0x98994C84D8F84E1D), UINT64_C(0x8577C6DAFAD4EFC1),
+		UINT64_C(0xD4FE714014138AD5), UINT64_C(0xC910FB1E363F2B09),
+		UINT64_C(0xEF2365FC504AC96D), UINT64_C(0xF2CDEFA2726668B1),
+		UINT64_C(0x986015931B88068A), UINT64_C(0x858E9FCD39A4A756),
+		UINT64_C(0xA3BD012F5FD14532), UINT64_C(0xBE538B717DFDE4EE),
+		UINT64_C(0xEFDA3CEB933A81FA), UINT64_C(0xF234B6B5B1162026),
+		UINT64_C(0xD4072857D763C242), UINT64_C(0xC9E9A209F54F639E),
+		UINT64_C(0x771447620AED086A), UINT64_C(0x6AFACD3C28C1A9B6),
+		UINT64_C(0x4CC953DE4EB44BD2), UINT64_C(0x5127D9806C98EA0E),
+		UINT64_C(0x00AE6E1A825F8F1A), UINT64_C(0x1D40E444A0732EC6),
+		UINT64_C(0x3B737AA6C606CCA2), UINT64_C(0x269DF0F8E42A6D7E),
+		UINT64_C(0xD4501F5A964C05CF), UINT64_C(0xC9BE9504B460A413),
+		UINT64_C(0xEF8D0BE6D2154677), UINT64_C(0xF26381B8F039E7AB),
+		UINT64_C(0xA3EA36221EFE82BF), UINT64_C(0xBE04BC7C3CD22363),
+		UINT64_C(0x9837229E5AA7C107), UINT64_C(0x85D9A8C0788B60DB),
+		UINT64_C(0x3B244DAB87290B2F), UINT64_C(0x26CAC7F5A505AAF3),
+		UINT64_C(0x00F95917C3704897), UINT64_C(0x1D17D349E15CE94B),
+		UINT64_C(0x4C9E64D30F9B8C5F), UINT64_C(0x5170EE8D2DB72D83),
+		UINT64_C(0x7743706F4BC2CFE7), UINT64_C(0x6AADFA3169EE6E3B),
+		UINT64_C(0xA218840D981E1391), UINT64_C(0xBFF60E53BA32B24D),
+		UINT64_C(0x99C590B1DC475029), UINT64_C(0x842B1AEFFE6BF1F5),
+		UINT64_C(0xD5A2AD7510AC94E1), UINT64_C(0xC84C272B3280353D),
+		UINT64_C(0xEE7FB9C954F5D759), UINT64_C(0xF391339776D97685),
+		UINT64_C(0x4D6CD6FC897B1D71), UINT64_C(0x50825CA2AB57BCAD),
+		UINT64_C(0x76B1C240CD225EC9), UINT64_C(0x6B5F481EEF0EFF15),
+		UINT64_C(0x3AD6FF8401C99A01), UINT64_C(0x273875DA23E53BDD),
+		UINT64_C(0x010BEB384590D9B9), UINT64_C(0x1CE5616667BC7865),
+		UINT64_C(0xEE288EC415DA10D4), UINT64_C(0xF3C6049A37F6B108),
+		UINT64_C(0xD5F59A785183536C), UINT64_C(0xC81B102673AFF2B0),
+		UINT64_C(0x9992A7BC9D6897A4), UINT64_C(0x847C2DE2BF443678),
+		UINT64_C(0xA24FB300D931D41C), UINT64_C(0xBFA1395EFB1D75C0),
+		UINT64_C(0x015CDC3504BF1E34), UINT64_C(0x1CB2566B2693BFE8),
+		UINT64_C(0x3A81C88940E65D8C), UINT64_C(0x276F42D762CAFC50),
+		UINT64_C(0x76E6F54D8C0D9944), UINT64_C(0x6B087F13AE213898),
+		UINT64_C(0x4D3BE1F1C854DAFC), UINT64_C(0x50D56BAFEA787B20),
+		UINT64_C(0x3A78919E8396151B), UINT64_C(0x27961BC0A1BAB4C7),
+		UINT64_C(0x01A58522C7CF56A3), UINT64_C(0x1C4B0F7CE5E3F77F),
+		UINT64_C(0x4DC2B8E60B24926B), UINT64_C(0x502C32B8290833B7),
+		UINT64_C(0x761FAC5A4F7DD1D3), UINT64_C(0x6BF126046D51700F),
+		UINT64_C(0xD50CC36F92F31BFB), UINT64_C(0xC8E24931B0DFBA27),
+		UINT64_C(0xEED1D7D3D6AA5843), UINT64_C(0xF33F5D8DF486F99F),
+		UINT64_C(0xA2B6EA171A419C8B), UINT64_C(0xBF586049386D3D57),
+		UINT64_C(0x996BFEAB5E18DF33), UINT64_C(0x848574F57C347EEF),
+		UINT64_C(0x76489B570E52165E), UINT64_C(0x6BA611092C7EB782),
+		UINT64_C(0x4D958FEB4A0B55E6), UINT64_C(0x507B05B56827F43A),
+		UINT64_C(0x01F2B22F86E0912E), UINT64_C(0x1C1C3871A4CC30F2),
+		UINT64_C(0x3A2FA693C2B9D296), UINT64_C(0x27C12CCDE095734A),
+		UINT64_C(0x993CC9A61F3718BE), UINT64_C(0x84D243F83D1BB962),
+		UINT64_C(0xA2E1DD1A5B6E5B06), UINT64_C(0xBF0F57447942FADA),
+		UINT64_C(0xEE86E0DE97859FCE), UINT64_C(0xF3686A80B5A93E12),
+		UINT64_C(0xD55BF462D3DCDC76), UINT64_C(0xC8B57E3CF1F07DAA),
+		UINT64_C(0xD6E9A7309F3239A7), UINT64_C(0xCB072D6EBD1E987B),
+		UINT64_C(0xED34B38CDB6B7A1F), UINT64_C(0xF0DA39D2F947DBC3),
+		UINT64_C(0xA1538E481780BED7), UINT64_C(0xBCBD041635AC1F0B),
+		UINT64_C(0x9A8E9AF453D9FD6F), UINT64_C(0x876010AA71F55CB3),
+		UINT64_C(0x399DF5C18E573747), UINT64_C(0x24737F9FAC7B969B),
+		UINT64_C(0x0240E17DCA0E74FF), UINT64_C(0x1FAE6B23E822D523),
+		UINT64_C(0x4E27DCB906E5B037), UINT64_C(0x53C956E724C911EB),
+		UINT64_C(0x75FAC80542BCF38F), UINT64_C(0x6814425B60905253),
+		UINT64_C(0x9AD9ADF912F63AE2), UINT64_C(0x873727A730DA9B3E),
+		UINT64_C(0xA104B94556AF795A), UINT64_C(0xBCEA331B7483D886),
+		UINT64_C(0xED6384819A44BD92), UINT64_C(0xF08D0EDFB8681C4E),
+		UINT64_C(0xD6BE903DDE1DFE2A), UINT64_C(0xCB501A63FC315FF6),
+		UINT64_C(0x75ADFF0803933402), UINT64_C(0x6843755621BF95DE),
+		UINT64_C(0x4E70EBB447CA77BA), UINT64_C(0x539E61EA65E6D666),
+		UINT64_C(0x0217D6708B21B372), UINT64_C(0x1FF95C2EA90D12AE),
+		UINT64_C(0x39CAC2CCCF78F0CA), UINT64_C(0x24244892ED545116),
+		UINT64_C(0x4E89B2A384BA3F2D), UINT64_C(0x536738FDA6969EF1),
+		UINT64_C(0x7554A61FC0E37C95), UINT64_C(0x68BA2C41E2CFDD49),
+		UINT64_C(0x39339BDB0C08B85D), UINT64_C(0x24DD11852E241981),
+		UINT64_C(0x02EE8F674851FBE5), UINT64_C(0x1F0005396A7D5A39),
+		UINT64_C(0xA1FDE05295DF31CD), UINT64_C(0xBC136A0CB7F39011),
+		UINT64_C(0x9A20F4EED1867275), UINT64_C(0x87CE7EB0F3AAD3A9),
+		UINT64_C(0xD647C92A1D6DB6BD), UINT64_C(0xCBA943743F411761),
+		UINT64_C(0xED9ADD965934F505), UINT64_C(0xF07457C87B1854D9),
+		UINT64_C(0x02B9B86A097E3C68), UINT64_C(0x1F5732342B529DB4),
+		UINT64_C(0x3964ACD64D277FD0), UINT64_C(0x248A26886F0BDE0C),
+		UINT64_C(0x7503911281CCBB18), UINT64_C(0x68ED1B4CA3E01AC4),
+		UINT64_C(0x4EDE85AEC595F8A0), UINT64_C(0x53300FF0E7B9597C),
+		UINT64_C(0xEDCDEA9B181B3288), UINT64_C(0xF02360C53A379354),
+		UINT64_C(0xD610FE275C427130), UINT64_C(0xCBFE74797E6ED0EC),
+		UINT64_C(0x9A77C3E390A9B5F8), UINT64_C(0x879949BDB2851424),
+		UINT64_C(0xA1AAD75FD4F0F640), UINT64_C(0xBC445D01F6DC579C),
+		UINT64_C(0x74F1233D072C2A36), UINT64_C(0x691FA96325008BEA),
+		UINT64_C(0x4F2C37814375698E), UINT64_C(0x52C2BDDF6159C852),
+		UINT64_C(0x034B0A458F9EAD46), UINT64_C(0x1EA5801BADB20C9A),
+		UINT64_C(0x38961EF9CBC7EEFE), UINT64_C(0x257894A7E9EB4F22),
+		UINT64_C(0x9B8571CC164924D6), UINT64_C(0x866BFB923465850A),
+		UINT64_C(0xA05865705210676E), UINT64_C(0xBDB6EF2E703CC6B2),
+		UINT64_C(0xEC3F58B49EFBA3A6), UINT64_C(0xF1D1D2EABCD7027A),
+		UINT64_C(0xD7E24C08DAA2E01E), UINT64_C(0xCA0CC656F88E41C2),
+		UINT64_C(0x38C129F48AE82973), UINT64_C(0x252FA3AAA8C488AF),
+		UINT64_C(0x031C3D48CEB16ACB), UINT64_C(0x1EF2B716EC9DCB17),
+		UINT64_C(0x4F7B008C025AAE03), UINT64_C(0x52958AD220760FDF),
+		UINT64_C(0x74A614304603EDBB), UINT64_C(0x69489E6E642F4C67),
+		UINT64_C(0xD7B57B059B8D2793), UINT64_C(0xCA5BF15BB9A1864F),
+		UINT64_C(0xEC686FB9DFD4642B), UINT64_C(0xF186E5E7FDF8C5F7),
+		UINT64_C(0xA00F527D133FA0E3), UINT64_C(0xBDE1D8233113013F),
+		UINT64_C(0x9BD246C15766E35B), UINT64_C(0x863CCC9F754A4287),
+		UINT64_C(0xEC9136AE1CA42CBC), UINT64_C(0xF17FBCF03E888D60),
+		UINT64_C(0xD74C221258FD6F04), UINT64_C(0xCAA2A84C7AD1CED8),
+		UINT64_C(0x9B2B1FD69416ABCC), UINT64_C(0x86C59588B63A0A10),
+		UINT64_C(0xA0F60B6AD04FE874), UINT64_C(0xBD188134F26349A8),
+		UINT64_C(0x03E5645F0DC1225C), UINT64_C(0x1E0BEE012FED8380),
+		UINT64_C(0x383870E3499861E4), UINT64_C(0x25D6FABD6BB4C038),
+		UINT64_C(0x745F4D278573A52C), UINT64_C(0x69B1C779A75F04F0),
+		UINT64_C(0x4F82599BC12AE694), UINT64_C(0x526CD3C5E3064748),
+		UINT64_C(0xA0A13C6791602FF9), UINT64_C(0xBD4FB639B34C8E25),
+		UINT64_C(0x9B7C28DBD5396C41), UINT64_C(0x8692A285F715CD9D),
+		UINT64_C(0xD71B151F19D2A889), UINT64_C(0xCAF59F413BFE0955),
+		UINT64_C(0xECC601A35D8BEB31), UINT64_C(0xF1288BFD7FA74AED),
+		UINT64_C(0x4FD56E9680052119), UINT64_C(0x523BE4C8A22980C5),
+		UINT64_C(0x74087A2AC45C62A1), UINT64_C(0x69E6F074E670C37D),
+		UINT64_C(0x386F47EE08B7A669), UINT64_C(0x2581CDB02A9B07B5),
+		UINT64_C(0x03B253524CEEE5D1), UINT64_C(0x1E5CD90C6EC2440D)
+	}
+};
diff --git a/src/liblzma/check/crc64_tablegen.c b/src/liblzma/check/crc64_tablegen.c
new file mode 100644
index 0000000..fddaa7e
--- /dev/null
+++ b/src/liblzma/check/crc64_tablegen.c
@@ -0,0 +1,88 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       crc64_tablegen.c
+/// \brief      Generate crc64_table_le.h and crc64_table_be.h
+///
+/// Compiling: gcc -std=c99 -o crc64_tablegen crc64_tablegen.c
+/// Add -DWORDS_BIGENDIAN to generate big endian table.
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <stdio.h>
+#include "../../common/tuklib_integer.h"
+
+
+static uint64_t crc64_table[4][256];
+
+
+extern void
+init_crc64_table(void)
+{
+	static const uint64_t poly64 = UINT64_C(0xC96C5795D7870F42);
+
+	for (size_t s = 0; s < 4; ++s) {
+		for (size_t b = 0; b < 256; ++b) {
+			uint64_t r = s == 0 ? b : crc64_table[s - 1][b];
+
+			for (size_t i = 0; i < 8; ++i) {
+				if (r & 1)
+					r = (r >> 1) ^ poly64;
+				else
+					r >>= 1;
+			}
+
+			crc64_table[s][b] = r;
+		}
+	}
+
+#ifdef WORDS_BIGENDIAN
+	for (size_t s = 0; s < 4; ++s)
+		for (size_t b = 0; b < 256; ++b)
+			crc64_table[s][b] = bswap64(crc64_table[s][b]);
+#endif
+
+	return;
+}
+
+
+static void
+print_crc64_table(void)
+{
+	printf("/* This file has been automatically generated by "
+			"crc64_tablegen.c. */\n\n"
+			"const uint64_t lzma_crc64_table[4][256] = {\n\t{");
+
+	for (size_t s = 0; s < 4; ++s) {
+		for (size_t b = 0; b < 256; ++b) {
+			if ((b % 2) == 0)
+				printf("\n\t\t");
+
+			printf("UINT64_C(0x%016" PRIX64 ")",
+					crc64_table[s][b]);
+
+			if (b != 255)
+				printf(",%s", (b+1) % 2 == 0 ? "" : " ");
+		}
+
+		if (s == 3)
+			printf("\n\t}\n};\n");
+		else
+			printf("\n\t}, {");
+	}
+
+	return;
+}
+
+
+int
+main(void)
+{
+	init_crc64_table();
+	print_crc64_table();
+	return 0;
+}
diff --git a/src/liblzma/check/crc64_x86.S b/src/liblzma/check/crc64_x86.S
new file mode 100644
index 0000000..f5bb84b
--- /dev/null
+++ b/src/liblzma/check/crc64_x86.S
@@ -0,0 +1,287 @@
+/*
+ * Speed-optimized CRC64 using slicing-by-four algorithm
+ *
+ * This uses only i386 instructions, but it is optimized for i686 and later
+ * (including e.g. Pentium II/III/IV, Athlon XP, and Core 2).
+ *
+ * Authors: Igor Pavlov (original CRC32 assembly code)
+ *          Lasse Collin (CRC64 adaptation of the modified CRC32 code)
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ *
+ * This code needs lzma_crc64_table, which can be created using the
+ * following C code:
+
+uint64_t lzma_crc64_table[4][256];
+
+void
+init_table(void)
+{
+	// ECMA-182
+	static const uint64_t poly64 = UINT64_C(0xC96C5795D7870F42);
+
+	for (size_t s = 0; s < 4; ++s) {
+		for (size_t b = 0; b < 256; ++b) {
+			uint64_t r = s == 0 ? b : lzma_crc64_table[s - 1][b];
+
+			for (size_t i = 0; i < 8; ++i) {
+				if (r & 1)
+					r = (r >> 1) ^ poly64;
+				else
+					r >>= 1;
+			}
+
+			lzma_crc64_table[s][b] = r;
+		}
+	}
+}
+
+ * The prototype of the CRC64 function:
+ * extern uint64_t lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc);
+ */
+
+/*
+ * On some systems, the functions need to be prefixed. The prefix is
+ * usually an underscore.
+ */
+#ifndef __USER_LABEL_PREFIX__
+#	define __USER_LABEL_PREFIX__
+#endif
+#define MAKE_SYM_CAT(prefix, sym) prefix ## sym
+#define MAKE_SYM(prefix, sym) MAKE_SYM_CAT(prefix, sym)
+#define LZMA_CRC64 MAKE_SYM(__USER_LABEL_PREFIX__, lzma_crc64)
+#define LZMA_CRC64_TABLE MAKE_SYM(__USER_LABEL_PREFIX__, lzma_crc64_table)
+
+/*
+ * Solaris assembler doesn't have .p2align, and Darwin uses .align
+ * differently than GNU/Linux and Solaris.
+ */
+#if defined(__APPLE__) || defined(__MSDOS__)
+#	define ALIGN(pow2, abs) .align pow2
+#else
+#	define ALIGN(pow2, abs) .align abs
+#endif
+
+	.text
+	.globl	LZMA_CRC64
+
+#if !defined(__APPLE__) && !defined(_WIN32) && !defined(__CYGWIN__) \
+		&& !defined(__MSDOS__)
+	.type	LZMA_CRC64, @function
+#endif
+
+	ALIGN(4, 16)
+LZMA_CRC64:
+	/*
+	 * Register usage:
+	 * %eax crc LSB
+	 * %edx crc MSB
+	 * %esi buf
+	 * %edi size or buf + size
+	 * %ebx lzma_crc64_table
+	 * %ebp Table index
+	 * %ecx Temporary
+	 */
+	pushl	%ebx
+	pushl	%esi
+	pushl	%edi
+	pushl	%ebp
+	movl	0x14(%esp), %esi /* buf */
+	movl	0x18(%esp), %edi /* size */
+	movl	0x1C(%esp), %eax /* crc LSB */
+	movl	0x20(%esp), %edx /* crc MSB */
+
+	/*
+	 * Store the address of lzma_crc64_table to %ebx. This is needed to
+	 * get position-independent code (PIC).
+	 *
+	 * The PIC macro is defined by libtool, while __PIC__ is defined
+	 * by GCC but only on some systems. Testing for both makes it simpler
+	 * to test this code without libtool, and keeps the code working also
+	 * when built with libtool but using something else than GCC.
+	 *
+	 * I understood that libtool may define PIC on Windows even though
+	 * the code in Windows DLLs is not PIC in sense that it is in ELF
+	 * binaries, so we need a separate check to always use the non-PIC
+	 * code on Windows.
+	 */
+#if (!defined(PIC) && !defined(__PIC__)) \
+		|| (defined(_WIN32) || defined(__CYGWIN__))
+	/* Not PIC */
+	movl	$ LZMA_CRC64_TABLE, %ebx
+#elif defined(__APPLE__)
+	/* Mach-O */
+	call	.L_get_pc
+.L_pic:
+	leal	.L_lzma_crc64_table$non_lazy_ptr-.L_pic(%ebx), %ebx
+	movl	(%ebx), %ebx
+#else
+	/* ELF */
+	call	.L_get_pc
+	addl	$_GLOBAL_OFFSET_TABLE_, %ebx
+	movl	LZMA_CRC64_TABLE@GOT(%ebx), %ebx
+#endif
+
+	/* Complement the initial value. */
+	notl	%eax
+	notl	%edx
+
+.L_align:
+	/*
+	 * Check if there is enough input to use slicing-by-four.
+	 * We need eight bytes, because the loop pre-reads four bytes.
+	 */
+	cmpl	$8, %edi
+	jb	.L_rest
+
+	/* Check if we have reached alignment of four bytes. */
+	testl	$3, %esi
+	jz	.L_slice
+
+	/* Calculate CRC of the next input byte. */
+	movzbl	(%esi), %ebp
+	incl	%esi
+	movzbl	%al, %ecx
+	xorl	%ecx, %ebp
+	shrdl	$8, %edx, %eax
+	xorl	(%ebx, %ebp, 8), %eax
+	shrl	$8, %edx
+	xorl	4(%ebx, %ebp, 8), %edx
+	decl	%edi
+	jmp	.L_align
+
+.L_slice:
+	/*
+	 * If we get here, there's at least eight bytes of aligned input
+	 * available. Make %edi multiple of four bytes. Store the possible
+	 * remainder over the "size" variable in the argument stack.
+	 */
+	movl	%edi, 0x18(%esp)
+	andl	$-4, %edi
+	subl	%edi, 0x18(%esp)
+
+	/*
+	 * Let %edi be buf + size - 4 while running the main loop. This way
+	 * we can compare for equality to determine when exit the loop.
+	 */
+	addl	%esi, %edi
+	subl	$4, %edi
+
+	/* Read in the first four aligned bytes. */
+	movl	(%esi), %ecx
+
+.L_loop:
+	xorl	%eax, %ecx
+	movzbl	%cl, %ebp
+	movl	0x1800(%ebx, %ebp, 8), %eax
+	xorl	%edx, %eax
+	movl	0x1804(%ebx, %ebp, 8), %edx
+	movzbl	%ch, %ebp
+	xorl	0x1000(%ebx, %ebp, 8), %eax
+	xorl	0x1004(%ebx, %ebp, 8), %edx
+	shrl	$16, %ecx
+	movzbl	%cl, %ebp
+	xorl	0x0800(%ebx, %ebp, 8), %eax
+	xorl	0x0804(%ebx, %ebp, 8), %edx
+	movzbl	%ch, %ebp
+	addl	$4, %esi
+	xorl	(%ebx, %ebp, 8), %eax
+	xorl	4(%ebx, %ebp, 8), %edx
+
+	/* Check for end of aligned input. */
+	cmpl	%edi, %esi
+
+	/*
+	 * Copy the next input byte to %ecx. It is slightly faster to
+	 * read it here than at the top of the loop.
+	 */
+	movl	(%esi), %ecx
+	jb	.L_loop
+
+	/*
+	 * Process the remaining four bytes, which we have already
+	 * copied to %ecx.
+	 */
+	xorl	%eax, %ecx
+	movzbl	%cl, %ebp
+	movl	0x1800(%ebx, %ebp, 8), %eax
+	xorl	%edx, %eax
+	movl	0x1804(%ebx, %ebp, 8), %edx
+	movzbl	%ch, %ebp
+	xorl	0x1000(%ebx, %ebp, 8), %eax
+	xorl	0x1004(%ebx, %ebp, 8), %edx
+	shrl	$16, %ecx
+	movzbl	%cl, %ebp
+	xorl	0x0800(%ebx, %ebp, 8), %eax
+	xorl	0x0804(%ebx, %ebp, 8), %edx
+	movzbl	%ch, %ebp
+	addl	$4, %esi
+	xorl	(%ebx, %ebp, 8), %eax
+	xorl	4(%ebx, %ebp, 8), %edx
+
+	/* Copy the number of remaining bytes to %edi. */
+	movl	0x18(%esp), %edi
+
+.L_rest:
+	/* Check for end of input. */
+	testl	%edi, %edi
+	jz	.L_return
+
+	/* Calculate CRC of the next input byte. */
+	movzbl	(%esi), %ebp
+	incl	%esi
+	movzbl	%al, %ecx
+	xorl	%ecx, %ebp
+	shrdl	$8, %edx, %eax
+	xorl	(%ebx, %ebp, 8), %eax
+	shrl	$8, %edx
+	xorl	4(%ebx, %ebp, 8), %edx
+	decl	%edi
+	jmp	.L_rest
+
+.L_return:
+	/* Complement the final value. */
+	notl	%eax
+	notl	%edx
+
+	popl	%ebp
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	ret
+
+#if defined(PIC) || defined(__PIC__)
+	ALIGN(4, 16)
+.L_get_pc:
+	movl	(%esp), %ebx
+	ret
+#endif
+
+#if defined(__APPLE__) && (defined(PIC) || defined(__PIC__))
+	/* Mach-O PIC */
+	.section __IMPORT,__pointers,non_lazy_symbol_pointers
+.L_lzma_crc64_table$non_lazy_ptr:
+	.indirect_symbol LZMA_CRC64_TABLE
+	.long 0
+
+#elif defined(_WIN32) || defined(__CYGWIN__)
+#	ifdef DLL_EXPORT
+	/* This is equivalent of __declspec(dllexport). */
+	.section .drectve
+	.ascii " -export:lzma_crc64"
+#	endif
+
+#elif !defined(__MSDOS__)
+	/* ELF */
+	.size	LZMA_CRC64, .-LZMA_CRC64
+#endif
+
+/*
+ * This is needed to support non-executable stack. It's ugly to
+ * use __linux__ here, but I don't know a way to detect when
+ * we are using GNU assembler.
+ */
+#if defined(__ELF__) && defined(__linux__)
+	.section	.note.GNU-stack,"",@progbits
+#endif
diff --git a/src/liblzma/check/crc_macros.h b/src/liblzma/check/crc_macros.h
new file mode 100644
index 0000000..a7c21b7
--- /dev/null
+++ b/src/liblzma/check/crc_macros.h
@@ -0,0 +1,30 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       crc_macros.h
+/// \brief      Some endian-dependent macros for CRC32 and CRC64
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef WORDS_BIGENDIAN
+#	define A(x) ((x) >> 24)
+#	define B(x) (((x) >> 16) & 0xFF)
+#	define C(x) (((x) >> 8) & 0xFF)
+#	define D(x) ((x) & 0xFF)
+
+#	define S8(x) ((x) << 8)
+#	define S32(x) ((x) << 32)
+
+#else
+#	define A(x) ((x) & 0xFF)
+#	define B(x) (((x) >> 8) & 0xFF)
+#	define C(x) (((x) >> 16) & 0xFF)
+#	define D(x) ((x) >> 24)
+
+#	define S8(x) ((x) >> 8)
+#	define S32(x) ((x) >> 32)
+#endif
diff --git a/src/liblzma/check/sha256.c b/src/liblzma/check/sha256.c
new file mode 100644
index 0000000..04231db
--- /dev/null
+++ b/src/liblzma/check/sha256.c
@@ -0,0 +1,201 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       sha256.c
+/// \brief      SHA-256
+///
+/// \todo       Crypto++ has x86 ASM optimizations. They use SSE so if they
+///             are imported to liblzma, SSE instructions need to be used
+///             conditionally to keep the code working on older boxes.
+///             We could also support using some external libary for SHA-256.
+//
+//  This code is based on the code found from 7-Zip, which has a modified
+//  version of the SHA-256 found from Crypto++ <http://www.cryptopp.com/>.
+//  The code was modified a little to fit into liblzma.
+//
+//  Authors:    Kevin Springle
+//              Wei Dai
+//              Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// Avoid bogus warnings in transform().
+#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 2) || __GNUC__ > 4
+#	pragma GCC diagnostic ignored "-Wuninitialized"
+#endif
+
+#include "check.h"
+
+// At least on x86, GCC is able to optimize this to a rotate instruction.
+#define rotr_32(num, amount) ((num) >> (amount) | (num) << (32 - (amount)))
+
+#define blk0(i) (W[i] = data[i])
+#define blk2(i) (W[i & 15] += s1(W[(i - 2) & 15]) + W[(i - 7) & 15] \
+		+ s0(W[(i - 15) & 15]))
+
+#define Ch(x, y, z) (z ^ (x & (y ^ z)))
+#define Maj(x, y, z) ((x & y) | (z & (x | y)))
+
+#define a(i) T[(0 - i) & 7]
+#define b(i) T[(1 - i) & 7]
+#define c(i) T[(2 - i) & 7]
+#define d(i) T[(3 - i) & 7]
+#define e(i) T[(4 - i) & 7]
+#define f(i) T[(5 - i) & 7]
+#define g(i) T[(6 - i) & 7]
+#define h(i) T[(7 - i) & 7]
+
+#define R(i) \
+	h(i) += S1(e(i)) + Ch(e(i), f(i), g(i)) + SHA256_K[i + j] \
+		+ (j ? blk2(i) : blk0(i)); \
+	d(i) += h(i); \
+	h(i) += S0(a(i)) + Maj(a(i), b(i), c(i))
+
+#define S0(x) (rotr_32(x, 2) ^ rotr_32(x, 13) ^ rotr_32(x, 22))
+#define S1(x) (rotr_32(x, 6) ^ rotr_32(x, 11) ^ rotr_32(x, 25))
+#define s0(x) (rotr_32(x, 7) ^ rotr_32(x, 18) ^ (x >> 3))
+#define s1(x) (rotr_32(x, 17) ^ rotr_32(x, 19) ^ (x >> 10))
+
+
+static const uint32_t SHA256_K[64] = {
+	0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
+	0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
+	0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
+	0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
+	0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
+	0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
+	0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
+	0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
+	0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
+	0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
+	0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
+	0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
+	0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
+	0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
+	0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
+	0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
+};
+
+
+static void
+transform(uint32_t state[static 8], const uint32_t data[static 16])
+{
+	uint32_t W[16];
+	uint32_t T[8];
+
+	// Copy state[] to working vars.
+	memcpy(T, state, sizeof(T));
+
+	// 64 operations, partially loop unrolled
+	for (unsigned int j = 0; j < 64; j += 16) {
+		R( 0); R( 1); R( 2); R( 3);
+		R( 4); R( 5); R( 6); R( 7);
+		R( 8); R( 9); R(10); R(11);
+		R(12); R(13); R(14); R(15);
+	}
+
+	// Add the working vars back into state[].
+	state[0] += a(0);
+	state[1] += b(0);
+	state[2] += c(0);
+	state[3] += d(0);
+	state[4] += e(0);
+	state[5] += f(0);
+	state[6] += g(0);
+	state[7] += h(0);
+}
+
+
+static void
+process(lzma_check_state *check)
+{
+#ifdef WORDS_BIGENDIAN
+	transform(check->state.sha256.state, check->buffer.u32);
+
+#else
+	uint32_t data[16];
+
+	for (size_t i = 0; i < 16; ++i)
+		data[i] = bswap32(check->buffer.u32[i]);
+
+	transform(check->state.sha256.state, data);
+#endif
+
+	return;
+}
+
+
+extern void
+lzma_sha256_init(lzma_check_state *check)
+{
+	static const uint32_t s[8] = {
+		0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
+		0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19,
+	};
+
+	memcpy(check->state.sha256.state, s, sizeof(s));
+	check->state.sha256.size = 0;
+
+	return;
+}
+
+
+extern void
+lzma_sha256_update(const uint8_t *buf, size_t size, lzma_check_state *check)
+{
+	// Copy the input data into a properly aligned temporary buffer.
+	// This way we can be called with arbitrarily sized buffers
+	// (no need to be multiple of 64 bytes), and the code works also
+	// on architectures that don't allow unaligned memory access.
+	while (size > 0) {
+		const size_t copy_start = check->state.sha256.size & 0x3F;
+		size_t copy_size = 64 - copy_start;
+		if (copy_size > size)
+			copy_size = size;
+
+		memcpy(check->buffer.u8 + copy_start, buf, copy_size);
+
+		buf += copy_size;
+		size -= copy_size;
+		check->state.sha256.size += copy_size;
+
+		if ((check->state.sha256.size & 0x3F) == 0)
+			process(check);
+	}
+
+	return;
+}
+
+
+extern void
+lzma_sha256_finish(lzma_check_state *check)
+{
+	// Add padding as described in RFC 3174 (it describes SHA-1 but
+	// the same padding style is used for SHA-256 too).
+	size_t pos = check->state.sha256.size & 0x3F;
+	check->buffer.u8[pos++] = 0x80;
+
+	while (pos != 64 - 8) {
+		if (pos == 64) {
+			process(check);
+			pos = 0;
+		}
+
+		check->buffer.u8[pos++] = 0x00;
+	}
+
+	// Convert the message size from bytes to bits.
+	check->state.sha256.size *= 8;
+
+	check->buffer.u64[(64 - 8) / 8] = conv64be(check->state.sha256.size);
+
+	process(check);
+
+	for (size_t i = 0; i < 8; ++i)
+		check->buffer.u32[i] = conv32be(check->state.sha256.state[i]);
+
+	return;
+}
diff --git a/src/liblzma/common/Makefile.inc b/src/liblzma/common/Makefile.inc
new file mode 100644
index 0000000..f154f82
--- /dev/null
+++ b/src/liblzma/common/Makefile.inc
@@ -0,0 +1,67 @@
+##
+## Author: Lasse Collin
+##
+## This file has been put into the public domain.
+## You can do whatever you want with this file.
+##
+
+liblzma_la_SOURCES += \
+	common/common.c \
+	common/common.h \
+	common/block_util.c \
+	common/easy_preset.c \
+	common/easy_preset.h \
+	common/filter_common.c \
+	common/filter_common.h \
+	common/hardware_physmem.c \
+	common/index.c \
+	common/index.h \
+	common/stream_flags_common.c \
+	common/stream_flags_common.h \
+	common/vli_size.c
+
+if COND_MAIN_ENCODER
+liblzma_la_SOURCES += \
+	common/alone_encoder.c \
+	common/block_buffer_encoder.c \
+	common/block_encoder.c \
+	common/block_encoder.h \
+	common/block_header_encoder.c \
+	common/easy_buffer_encoder.c \
+	common/easy_encoder.c \
+	common/easy_encoder_memusage.c \
+	common/filter_buffer_encoder.c \
+	common/filter_encoder.c \
+	common/filter_encoder.h \
+	common/filter_flags_encoder.c \
+	common/index_encoder.c \
+	common/index_encoder.h \
+	common/stream_buffer_encoder.c \
+	common/stream_encoder.c \
+	common/stream_encoder.h \
+	common/stream_flags_encoder.c \
+	common/vli_encoder.c
+endif
+
+if COND_MAIN_DECODER
+liblzma_la_SOURCES += \
+	common/alone_decoder.c \
+	common/alone_decoder.h \
+	common/auto_decoder.c \
+	common/block_buffer_decoder.c \
+	common/block_decoder.c \
+	common/block_decoder.h \
+	common/block_header_decoder.c \
+	common/easy_decoder_memusage.c \
+	common/filter_buffer_decoder.c \
+	common/filter_decoder.c \
+	common/filter_decoder.h \
+	common/filter_flags_decoder.c \
+	common/index_decoder.c \
+	common/index_hash.c \
+	common/stream_buffer_decoder.c \
+	common/stream_decoder.c \
+	common/stream_decoder.h \
+	common/stream_flags_decoder.c \
+	common/vli_decoder.c
+endif
diff --git a/src/liblzma/common/alone_decoder.c b/src/liblzma/common/alone_decoder.c
new file mode 100644
index 0000000..039b428
--- /dev/null
+++ b/src/liblzma/common/alone_decoder.c
@@ -0,0 +1,232 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       alone_decoder.c
+/// \brief      Decoder for LZMA_Alone files
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "alone_decoder.h"
+#include "lzma_decoder.h"
+#include "lz_decoder.h"
+
+
+struct lzma_coder_s {
+	lzma_next_coder next;
+
+	enum {
+		SEQ_PROPERTIES,
+		SEQ_DICTIONARY_SIZE,
+		SEQ_UNCOMPRESSED_SIZE,
+		SEQ_CODER_INIT,
+		SEQ_CODE,
+	} sequence;
+
+	/// Position in the header fields
+	size_t pos;
+
+	/// Uncompressed size decoded from the header
+	lzma_vli uncompressed_size;
+
+	/// Memory usage limit
+	uint64_t memlimit;
+
+	/// Amount of memory actually needed (only an estimate)
+	uint64_t memusage;
+
+	/// Options decoded from the header needed to initialize
+	/// the LZMA decoder
+	lzma_options_lzma options;
+};
+
+
+static lzma_ret
+alone_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)
+{
+	while (*out_pos < out_size
+			&& (coder->sequence == SEQ_CODE || *in_pos < in_size))
+	switch (coder->sequence) {
+	case SEQ_PROPERTIES:
+		if (lzma_lzma_lclppb_decode(&coder->options, in[*in_pos]))
+			return LZMA_FORMAT_ERROR;
+
+		coder->sequence = SEQ_DICTIONARY_SIZE;
+		++*in_pos;
+		break;
+
+	case SEQ_DICTIONARY_SIZE:
+		coder->options.dict_size
+				|= (size_t)(in[*in_pos]) << (coder->pos * 8);
+
+		if (++coder->pos == 4) {
+			if (coder->options.dict_size != UINT32_MAX) {
+				// A hack to ditch tons of false positives:
+				// We allow only dictionary sizes that are
+				// 2^n or 2^n + 2^(n-1). LZMA_Alone created
+				// only files with 2^n, but accepts any
+				// dictionary size. If someone complains, this
+				// will be reconsidered.
+				uint32_t d = coder->options.dict_size - 1;
+				d |= d >> 2;
+				d |= d >> 3;
+				d |= d >> 4;
+				d |= d >> 8;
+				d |= d >> 16;
+				++d;
+
+				if (d != coder->options.dict_size)
+					return LZMA_FORMAT_ERROR;
+			}
+
+			coder->pos = 0;
+			coder->sequence = SEQ_UNCOMPRESSED_SIZE;
+		}
+
+		++*in_pos;
+		break;
+
+	case SEQ_UNCOMPRESSED_SIZE:
+		coder->uncompressed_size
+				|= (lzma_vli)(in[*in_pos]) << (coder->pos * 8);
+		++*in_pos;
+		if (++coder->pos < 8)
+			break;
+
+		// Another hack to ditch false positives: Assume that
+		// if the uncompressed size is known, it must be less
+		// than 256 GiB. Again, if someone complains, this
+		// will be reconsidered.
+		if (coder->uncompressed_size != LZMA_VLI_UNKNOWN
+				&& coder->uncompressed_size
+					>= (LZMA_VLI_C(1) << 38))
+			return LZMA_FORMAT_ERROR;
+
+		// Calculate the memory usage so that it is ready
+		// for SEQ_CODER_INIT.
+		coder->memusage = lzma_lzma_decoder_memusage(&coder->options)
+				+ LZMA_MEMUSAGE_BASE;
+
+		coder->pos = 0;
+		coder->sequence = SEQ_CODER_INIT;
+
+	// Fall through
+
+	case SEQ_CODER_INIT: {
+		if (coder->memusage > coder->memlimit)
+			return LZMA_MEMLIMIT_ERROR;
+
+		lzma_filter_info filters[2] = {
+			{
+				.init = &lzma_lzma_decoder_init,
+				.options = &coder->options,
+			}, {
+				.init = NULL,
+			}
+		};
+
+		const lzma_ret ret = lzma_next_filter_init(&coder->next,
+				allocator, filters);
+		if (ret != LZMA_OK)
+			return ret;
+
+		// Use a hack to set the uncompressed size.
+		lzma_lz_decoder_uncompressed(coder->next.coder,
+				coder->uncompressed_size);
+
+		coder->sequence = SEQ_CODE;
+		break;
+	}
+
+	case SEQ_CODE: {
+		return coder->next.code(coder->next.coder,
+				allocator, in, in_pos, in_size,
+				out, out_pos, out_size, action);
+	}
+
+	default:
+		return LZMA_PROG_ERROR;
+	}
+
+	return LZMA_OK;
+}
+
+
+static void
+alone_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
+{
+	lzma_next_end(&coder->next, allocator);
+	lzma_free(coder, allocator);
+	return;
+}
+
+
+static lzma_ret
+alone_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
+		uint64_t *old_memlimit, uint64_t new_memlimit)
+{
+	*memusage = coder->memusage;
+	*old_memlimit = coder->memlimit;
+
+	if (new_memlimit != 0) {
+		if (new_memlimit < coder->memusage)
+			return LZMA_MEMLIMIT_ERROR;
+
+		coder->memlimit = new_memlimit;
+	}
+
+	return LZMA_OK;
+}
+
+
+extern lzma_ret
+lzma_alone_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		uint64_t memlimit)
+{
+	lzma_next_coder_init(&lzma_alone_decoder_init, next, allocator);
+
+	if (memlimit == 0)
+		return LZMA_PROG_ERROR;
+
+	if (next->coder == NULL) {
+		next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+		if (next->coder == NULL)
+			return LZMA_MEM_ERROR;
+
+		next->code = &alone_decode;
+		next->end = &alone_decoder_end;
+		next->memconfig = &alone_decoder_memconfig;
+		next->coder->next = LZMA_NEXT_CODER_INIT;
+	}
+
+	next->coder->sequence = SEQ_PROPERTIES;
+	next->coder->pos = 0;
+	next->coder->options.dict_size = 0;
+	next->coder->options.preset_dict = NULL;
+	next->coder->options.preset_dict_size = 0;
+	next->coder->uncompressed_size = 0;
+	next->coder->memlimit = memlimit;
+	next->coder->memusage = LZMA_MEMUSAGE_BASE;
+
+	return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_alone_decoder(lzma_stream *strm, uint64_t memlimit)
+{
+	lzma_next_strm_init(lzma_alone_decoder_init, strm, memlimit);
+
+	strm->internal->supported_actions[LZMA_RUN] = true;
+	strm->internal->supported_actions[LZMA_FINISH] = true;
+
+	return LZMA_OK;
+}
diff --git a/src/liblzma/common/alone_decoder.h b/src/liblzma/common/alone_decoder.h
new file mode 100644
index 0000000..70d0d2a
--- /dev/null
+++ b/src/liblzma/common/alone_decoder.h
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       alone_decoder.h
+/// \brief      Decoder for LZMA_Alone files
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_ALONE_DECODER_H
+#define LZMA_ALONE_DECODER_H
+
+#include "common.h"
+
+
+extern lzma_ret lzma_alone_decoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, uint64_t memlimit);
+
+#endif
diff --git a/src/liblzma/common/alone_encoder.c b/src/liblzma/common/alone_encoder.c
new file mode 100644
index 0000000..d8c0170
--- /dev/null
+++ b/src/liblzma/common/alone_encoder.c
@@ -0,0 +1,157 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       alone_decoder.c
+/// \brief      Decoder for LZMA_Alone files
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+#include "lzma_encoder.h"
+
+
+#define ALONE_HEADER_SIZE (1 + 4 + 8)
+
+
+struct lzma_coder_s {
+	lzma_next_coder next;
+
+	enum {
+		SEQ_HEADER,
+		SEQ_CODE,
+	} sequence;
+
+	size_t header_pos;
+	uint8_t header[ALONE_HEADER_SIZE];
+};
+
+
+static lzma_ret
+alone_encode(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)
+{
+	while (*out_pos < out_size)
+	switch (coder->sequence) {
+	case SEQ_HEADER:
+		lzma_bufcpy(coder->header, &coder->header_pos,
+				ALONE_HEADER_SIZE,
+				out, out_pos, out_size);
+		if (coder->header_pos < ALONE_HEADER_SIZE)
+			return LZMA_OK;
+
+		coder->sequence = SEQ_CODE;
+		break;
+
+	case SEQ_CODE:
+		return coder->next.code(coder->next.coder,
+				allocator, in, in_pos, in_size,
+				out, out_pos, out_size, action);
+
+	default:
+		assert(0);
+		return LZMA_PROG_ERROR;
+	}
+
+	return LZMA_OK;
+}
+
+
+static void
+alone_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
+{
+	lzma_next_end(&coder->next, allocator);
+	lzma_free(coder, allocator);
+	return;
+}
+
+
+// At least for now, this is not used by any internal function.
+static lzma_ret
+alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_options_lzma *options)
+{
+	lzma_next_coder_init(&alone_encoder_init, next, allocator);
+
+	if (next->coder == NULL) {
+		next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+		if (next->coder == NULL)
+			return LZMA_MEM_ERROR;
+
+		next->code = &alone_encode;
+		next->end = &alone_encoder_end;
+		next->coder->next = LZMA_NEXT_CODER_INIT;
+	}
+
+	// Basic initializations
+	next->coder->sequence = SEQ_HEADER;
+	next->coder->header_pos = 0;
+
+	// Encode the header:
+	// - Properties (1 byte)
+	if (lzma_lzma_lclppb_encode(options, next->coder->header))
+		return LZMA_OPTIONS_ERROR;
+
+	// - Dictionary size (4 bytes)
+	if (options->dict_size < LZMA_DICT_SIZE_MIN)
+		return LZMA_OPTIONS_ERROR;
+
+	// Round up to to the next 2^n or 2^n + 2^(n - 1) depending on which
+	// one is the next unless it is UINT32_MAX. While the header would
+	// allow any 32-bit integer, we do this to keep the decoder of liblzma
+	// accepting the resulting files.
+	uint32_t d = options->dict_size - 1;
+	d |= d >> 2;
+	d |= d >> 3;
+	d |= d >> 4;
+	d |= d >> 8;
+	d |= d >> 16;
+	if (d != UINT32_MAX)
+		++d;
+
+	unaligned_write32le(next->coder->header + 1, d);
+
+	// - Uncompressed size (always unknown and using EOPM)
+	memset(next->coder->header + 1 + 4, 0xFF, 8);
+
+	// Initialize the LZMA encoder.
+	const lzma_filter_info filters[2] = {
+		{
+			.init = &lzma_lzma_encoder_init,
+			.options = (void *)(options),
+		}, {
+			.init = NULL,
+		}
+	};
+
+	return lzma_next_filter_init(&next->coder->next, allocator, filters);
+}
+
+
+/*
+extern lzma_ret
+lzma_alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_options_alone *options)
+{
+	lzma_next_coder_init(&alone_encoder_init, next, allocator, options);
+}
+*/
+
+
+extern LZMA_API(lzma_ret)
+lzma_alone_encoder(lzma_stream *strm, const lzma_options_lzma *options)
+{
+	lzma_next_strm_init(alone_encoder_init, strm, options);
+
+	strm->internal->supported_actions[LZMA_RUN] = true;
+	strm->internal->supported_actions[LZMA_FINISH] = true;
+
+	return LZMA_OK;
+}
diff --git a/src/liblzma/common/auto_decoder.c b/src/liblzma/common/auto_decoder.c
new file mode 100644
index 0000000..ae6c3e7
--- /dev/null
+++ b/src/liblzma/common/auto_decoder.c
@@ -0,0 +1,186 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       auto_decoder.c
+/// \brief      Autodetect between .xz Stream and .lzma (LZMA_Alone) formats
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "stream_decoder.h"
+#include "alone_decoder.h"
+
+
+struct lzma_coder_s {
+	/// Stream decoder or LZMA_Alone decoder
+	lzma_next_coder next;
+
+	uint64_t memlimit;
+	uint32_t flags;
+
+	enum {
+		SEQ_INIT,
+		SEQ_CODE,
+		SEQ_FINISH,
+	} sequence;
+};
+
+
+static lzma_ret
+auto_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)
+{
+	switch (coder->sequence) {
+	case SEQ_INIT:
+		if (*in_pos >= in_size)
+			return LZMA_OK;
+
+		// Update the sequence now, because we want to continue from
+		// SEQ_CODE even if we return some LZMA_*_CHECK.
+		coder->sequence = SEQ_CODE;
+
+		// Detect the file format. For now this is simple, since if
+		// it doesn't start with 0xFD (the first magic byte of the
+		// new format), it has to be LZMA_Alone, or something that
+		// we don't support at all.
+		if (in[*in_pos] == 0xFD) {
+			return_if_error(lzma_stream_decoder_init(
+					&coder->next, allocator,
+					coder->memlimit, coder->flags));
+		} else {
+			return_if_error(lzma_alone_decoder_init(&coder->next,
+					allocator, coder->memlimit));
+
+			// If the application wants to know about missing
+			// integrity check or about the check in general, we
+			// need to handle it here, because LZMA_Alone decoder
+			// doesn't accept any flags.
+			if (coder->flags & LZMA_TELL_NO_CHECK)
+				return LZMA_NO_CHECK;
+
+			if (coder->flags & LZMA_TELL_ANY_CHECK)
+				return LZMA_GET_CHECK;
+		}
+
+	// Fall through
+
+	case SEQ_CODE: {
+		const lzma_ret ret = coder->next.code(
+				coder->next.coder, allocator,
+				in, in_pos, in_size,
+				out, out_pos, out_size, action);
+		if (ret != LZMA_STREAM_END
+				|| (coder->flags & LZMA_CONCATENATED) == 0)
+			return ret;
+
+		coder->sequence = SEQ_FINISH;
+	}
+
+	// Fall through
+
+	case SEQ_FINISH:
+		// When LZMA_DECODE_CONCATENATED was used and we were decoding
+		// LZMA_Alone file, we need to check check that there is no
+		// trailing garbage and wait for LZMA_FINISH.
+		if (*in_pos < in_size)
+			return LZMA_DATA_ERROR;
+
+		return action == LZMA_FINISH ? LZMA_STREAM_END : LZMA_OK;
+
+	default:
+		assert(0);
+		return LZMA_PROG_ERROR;
+	}
+}
+
+
+static void
+auto_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
+{
+	lzma_next_end(&coder->next, allocator);
+	lzma_free(coder, allocator);
+	return;
+}
+
+
+static lzma_check
+auto_decoder_get_check(const lzma_coder *coder)
+{
+	// It is LZMA_Alone if get_check is NULL.
+	return coder->next.get_check == NULL ? LZMA_CHECK_NONE
+			: coder->next.get_check(coder->next.coder);
+}
+
+
+static lzma_ret
+auto_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
+		uint64_t *old_memlimit, uint64_t new_memlimit)
+{
+	lzma_ret ret;
+
+	if (coder->next.memconfig != NULL) {
+		ret = coder->next.memconfig(coder->next.coder,
+				memusage, old_memlimit, new_memlimit);
+		assert(*old_memlimit == coder->memlimit);
+	} else {
+		// No coder is configured yet. Use the base value as
+		// the current memory usage.
+		*memusage = LZMA_MEMUSAGE_BASE;
+		*old_memlimit = coder->memlimit;
+		ret = LZMA_OK;
+	}
+
+	if (ret == LZMA_OK && new_memlimit != 0)
+		coder->memlimit = new_memlimit;
+
+	return ret;
+}
+
+
+static lzma_ret
+auto_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		uint64_t memlimit, uint32_t flags)
+{
+	lzma_next_coder_init(&auto_decoder_init, next, allocator);
+
+	if (memlimit == 0)
+		return LZMA_PROG_ERROR;
+
+	if (flags & ~LZMA_SUPPORTED_FLAGS)
+		return LZMA_OPTIONS_ERROR;
+
+	if (next->coder == NULL) {
+		next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+		if (next->coder == NULL)
+			return LZMA_MEM_ERROR;
+
+		next->code = &auto_decode;
+		next->end = &auto_decoder_end;
+		next->get_check = &auto_decoder_get_check;
+		next->memconfig = &auto_decoder_memconfig;
+		next->coder->next = LZMA_NEXT_CODER_INIT;
+	}
+
+	next->coder->memlimit = memlimit;
+	next->coder->flags = flags;
+	next->coder->sequence = SEQ_INIT;
+
+	return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_auto_decoder(lzma_stream *strm, uint64_t memlimit, uint32_t flags)
+{
+	lzma_next_strm_init(auto_decoder_init, strm, memlimit, flags);
+
+	strm->internal->supported_actions[LZMA_RUN] = true;
+	strm->internal->supported_actions[LZMA_FINISH] = true;
+
+	return LZMA_OK;
+}
diff --git a/src/liblzma/common/block_buffer_decoder.c b/src/liblzma/common/block_buffer_decoder.c
new file mode 100644
index 0000000..ff27a11
--- /dev/null
+++ b/src/liblzma/common/block_buffer_decoder.c
@@ -0,0 +1,80 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       block_buffer_decoder.c
+/// \brief      Single-call .xz Block decoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "block_decoder.h"
+
+
+extern LZMA_API(lzma_ret)
+lzma_block_buffer_decode(lzma_block *block, lzma_allocator *allocator,
+		const uint8_t *in, size_t *in_pos, size_t in_size,
+		uint8_t *out, size_t *out_pos, size_t out_size)
+{
+	if (in_pos == NULL || (in == NULL && *in_pos != in_size)
+			|| *in_pos > in_size || out_pos == NULL
+			|| (out == NULL && *out_pos != out_size)
+			|| *out_pos > out_size)
+		return LZMA_PROG_ERROR;
+
+	// Initialize the Block decoder.
+	lzma_next_coder block_decoder = LZMA_NEXT_CODER_INIT;
+	lzma_ret ret = lzma_block_decoder_init(
+			&block_decoder, allocator, block);
+
+	if (ret == LZMA_OK) {
+		// Save the positions so that we can restore them in case
+		// an error occurs.
+		const size_t in_start = *in_pos;
+		const size_t out_start = *out_pos;
+
+		// Do the actual decoding.
+		ret = block_decoder.code(block_decoder.coder, allocator,
+				in, in_pos, in_size, out, out_pos, out_size,
+				LZMA_FINISH);
+
+		if (ret == LZMA_STREAM_END) {
+			ret = LZMA_OK;
+		} else {
+			if (ret == LZMA_OK) {
+				// Either the input was truncated or the
+				// output buffer was too small.
+				assert(*in_pos == in_size
+						|| *out_pos == out_size);
+
+				// If all the input was consumed, then the
+				// input is truncated, even if the output
+				// buffer is also full. This is because
+				// processing the last byte of the Block
+				// never produces output.
+				//
+				// NOTE: This assumption may break when new
+				// filters are added, if the end marker of
+				// the filter doesn't consume at least one
+				// complete byte.
+				if (*in_pos == in_size)
+					ret = LZMA_DATA_ERROR;
+				else
+					ret = LZMA_BUF_ERROR;
+			}
+
+			// Restore the positions.
+			*in_pos = in_start;
+			*out_pos = out_start;
+		}
+	}
+
+	// Free the decoder memory. This needs to be done even if
+	// initialization fails, because the internal API doesn't
+	// require the initialization function to free its memory on error.
+	lzma_next_end(&block_decoder, allocator);
+
+	return ret;
+}
diff --git a/src/liblzma/common/block_buffer_encoder.c b/src/liblzma/common/block_buffer_encoder.c
new file mode 100644
index 0000000..a8f71c2
--- /dev/null
+++ b/src/liblzma/common/block_buffer_encoder.c
@@ -0,0 +1,299 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       block_buffer_encoder.c
+/// \brief      Single-call .xz Block encoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "block_encoder.h"
+#include "filter_encoder.h"
+#include "lzma2_encoder.h"
+#include "check.h"
+
+
+/// Estimate the maximum size of the Block Header and Check fields for
+/// a Block that uses LZMA2 uncompressed chunks. We could use
+/// lzma_block_header_size() but this is simpler.
+///
+/// Block Header Size + Block Flags + Compressed Size
+/// + Uncompressed Size + Filter Flags for LZMA2 + CRC32 + Check
+/// and round up to the next multiple of four to take Header Padding
+/// into account.
+#define HEADERS_BOUND ((1 + 1 + 2 * LZMA_VLI_BYTES_MAX + 3 + 4 \
+		+ LZMA_CHECK_SIZE_MAX + 3) & ~3)
+
+
+static lzma_vli
+lzma2_bound(lzma_vli uncompressed_size)
+{
+	// Prevent integer overflow in overhead calculation.
+	if (uncompressed_size > COMPRESSED_SIZE_MAX)
+		return 0;
+
+	// Calculate the exact overhead of the LZMA2 headers: Round
+	// uncompressed_size up to the next multiple of LZMA2_CHUNK_MAX,
+	// multiply by the size of per-chunk header, and add one byte for
+	// the end marker.
+	const lzma_vli overhead = ((uncompressed_size + LZMA2_CHUNK_MAX - 1)
+				/ LZMA2_CHUNK_MAX)
+			* LZMA2_HEADER_UNCOMPRESSED + 1;
+
+	// Catch the possible integer overflow.
+	if (COMPRESSED_SIZE_MAX - overhead < uncompressed_size)
+		return 0;
+
+	return uncompressed_size + overhead;
+}
+
+
+extern LZMA_API(size_t)
+lzma_block_buffer_bound(size_t uncompressed_size)
+{
+	// For now, if the data doesn't compress, we always use uncompressed
+	// chunks of LZMA2. In future we may use Subblock filter too, but
+	// but for simplicity we probably will still use the same bound
+	// calculation even though Subblock filter would have slightly less
+	// overhead.
+	lzma_vli lzma2_size = lzma2_bound(uncompressed_size);
+	if (lzma2_size == 0)
+		return 0;
+
+	// Take Block Padding into account.
+	lzma2_size = (lzma2_size + 3) & ~LZMA_VLI_C(3);
+
+#if SIZE_MAX < LZMA_VLI_MAX
+	// Catch the possible integer overflow on 32-bit systems. There's no
+	// overflow on 64-bit systems, because lzma2_bound() already takes
+	// into account the size of the headers in the Block.
+	if (SIZE_MAX - HEADERS_BOUND < lzma2_size)
+		return 0;
+#endif
+
+	return HEADERS_BOUND + lzma2_size;
+}
+
+
+static lzma_ret
+block_encode_uncompressed(lzma_block *block, const uint8_t *in, size_t in_size,
+		uint8_t *out, size_t *out_pos, size_t out_size)
+{
+	// TODO: Figure out if the last filter is LZMA2 or Subblock and use
+	// that filter to encode the uncompressed chunks.
+
+	// Use LZMA2 uncompressed chunks. We wouldn't need a dictionary at
+	// all, but LZMA2 always requires a dictionary, so use the minimum
+	// value to minimize memory usage of the decoder.
+	lzma_options_lzma lzma2 = {
+		.dict_size = LZMA_DICT_SIZE_MIN,
+	};
+
+	lzma_filter filters[2];
+	filters[0].id = LZMA_FILTER_LZMA2;
+	filters[0].options = &lzma2;
+	filters[1].id = LZMA_VLI_UNKNOWN;
+
+	// Set the above filter options to *block temporarily so that we can
+	// encode the Block Header.
+	lzma_filter *filters_orig = block->filters;
+	block->filters = filters;
+
+	if (lzma_block_header_size(block) != LZMA_OK) {
+		block->filters = filters_orig;
+		return LZMA_PROG_ERROR;
+	}
+
+	// Check that there's enough output space. The caller has already
+	// set block->compressed_size to what lzma2_bound() has returned,
+	// so we can reuse that value. We know that compressed_size is a
+	// known valid VLI and header_size is a small value so their sum
+	// will never overflow.
+	assert(block->compressed_size == lzma2_bound(in_size));
+	if (out_size - *out_pos
+			< block->header_size + block->compressed_size) {
+		block->filters = filters_orig;
+		return LZMA_BUF_ERROR;
+	}
+
+	if (lzma_block_header_encode(block, out + *out_pos) != LZMA_OK) {
+		block->filters = filters_orig;
+		return LZMA_PROG_ERROR;
+	}
+
+	block->filters = filters_orig;
+	*out_pos += block->header_size;
+
+	// Encode the data using LZMA2 uncompressed chunks.
+	size_t in_pos = 0;
+	uint8_t control = 0x01; // Dictionary reset
+
+	while (in_pos < in_size) {
+		// Control byte: Indicate uncompressed chunk, of which
+		// the first resets the dictionary.
+		out[(*out_pos)++] = control;
+		control = 0x02; // No dictionary reset
+
+		// Size of the uncompressed chunk
+		const size_t copy_size
+				= my_min(in_size - in_pos, LZMA2_CHUNK_MAX);
+		out[(*out_pos)++] = (copy_size - 1) >> 8;
+		out[(*out_pos)++] = (copy_size - 1) & 0xFF;
+
+		// The actual data
+		assert(*out_pos + copy_size <= out_size);
+		memcpy(out + *out_pos, in + in_pos, copy_size);
+
+		in_pos += copy_size;
+		*out_pos += copy_size;
+	}
+
+	// End marker
+	out[(*out_pos)++] = 0x00;
+	assert(*out_pos <= out_size);
+
+	return LZMA_OK;
+}
+
+
+static lzma_ret
+block_encode_normal(lzma_block *block, lzma_allocator *allocator,
+		const uint8_t *in, size_t in_size,
+		uint8_t *out, size_t *out_pos, size_t out_size)
+{
+	// Find out the size of the Block Header.
+	block->compressed_size = lzma2_bound(in_size);
+	if (block->compressed_size == 0)
+		return LZMA_DATA_ERROR;
+
+	block->uncompressed_size = in_size;
+	return_if_error(lzma_block_header_size(block));
+
+	// Reserve space for the Block Header and skip it for now.
+	if (out_size - *out_pos <= block->header_size)
+		return LZMA_BUF_ERROR;
+
+	const size_t out_start = *out_pos;
+	*out_pos += block->header_size;
+
+	// Limit out_size so that we stop encoding if the output would grow
+	// bigger than what uncompressed Block would be.
+	if (out_size - *out_pos > block->compressed_size)
+		out_size = *out_pos + block->compressed_size;
+
+	// TODO: In many common cases this could be optimized to use
+	// significantly less memory.
+	lzma_next_coder raw_encoder = LZMA_NEXT_CODER_INIT;
+	lzma_ret ret = lzma_raw_encoder_init(
+			&raw_encoder, allocator, block->filters);
+
+	if (ret == LZMA_OK) {
+		size_t in_pos = 0;
+		ret = raw_encoder.code(raw_encoder.coder, allocator,
+				in, &in_pos, in_size, out, out_pos, out_size,
+				LZMA_FINISH);
+	}
+
+	// NOTE: This needs to be run even if lzma_raw_encoder_init() failed.
+	lzma_next_end(&raw_encoder, allocator);
+
+	if (ret == LZMA_STREAM_END) {
+		// Compression was successful. Write the Block Header.
+		block->compressed_size
+				= *out_pos - (out_start + block->header_size);
+		ret = lzma_block_header_encode(block, out + out_start);
+		if (ret != LZMA_OK)
+			ret = LZMA_PROG_ERROR;
+
+	} else if (ret == LZMA_OK) {
+		// Output buffer became full.
+		ret = LZMA_BUF_ERROR;
+	}
+
+	// Reset *out_pos if something went wrong.
+	if (ret != LZMA_OK)
+		*out_pos = out_start;
+
+	return ret;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_block_buffer_encode(lzma_block *block, lzma_allocator *allocator,
+		const uint8_t *in, size_t in_size,
+		uint8_t *out, size_t *out_pos, size_t out_size)
+{
+	// Sanity checks
+	if (block == NULL || block->filters == NULL
+			|| (in == NULL && in_size != 0) || out == NULL
+			|| out_pos == NULL || *out_pos > out_size)
+		return LZMA_PROG_ERROR;
+
+	// Check the version field.
+	if (block->version != 0)
+		return LZMA_OPTIONS_ERROR;
+
+	// Size of a Block has to be a multiple of four, so limit the size
+	// here already. This way we don't need to check it again when adding
+	// Block Padding.
+	out_size -= (out_size - *out_pos) & 3;
+
+	// Get the size of the Check field.
+	const size_t check_size = lzma_check_size(block->check);
+	if (check_size == UINT32_MAX)
+		return LZMA_PROG_ERROR;
+
+	// Reserve space for the Check field.
+	if (out_size - *out_pos <= check_size)
+		return LZMA_BUF_ERROR;
+
+	out_size -= check_size;
+
+	// Do the actual compression.
+	const lzma_ret ret = block_encode_normal(block, allocator,
+			in, in_size, out, out_pos, out_size);
+	if (ret != LZMA_OK) {
+		// If the error was something else than output buffer
+		// becoming full, return the error now.
+		if (ret != LZMA_BUF_ERROR)
+			return ret;
+
+		// The data was uncompressible (at least with the options
+		// given to us) or the output buffer was too small. Use the
+		// uncompressed chunks of LZMA2 to wrap the data into a valid
+		// Block. If we haven't been given enough output space, even
+		// this may fail.
+		return_if_error(block_encode_uncompressed(block, in, in_size,
+				out, out_pos, out_size));
+	}
+
+	assert(*out_pos <= out_size);
+
+	// Block Padding. No buffer overflow here, because we already adjusted
+	// out_size so that (out_size - out_start) is a multiple of four.
+	// Thus, if the buffer is full, the loop body can never run.
+	for (size_t i = (size_t)(block->compressed_size); i & 3; ++i) {
+		assert(*out_pos < out_size);
+		out[(*out_pos)++] = 0x00;
+	}
+
+	// If there's no Check field, we are done now.
+	if (check_size > 0) {
+		// Calculate the integrity check. We reserved space for
+		// the Check field earlier so we don't need to check for
+		// available output space here.
+		lzma_check_state check;
+		lzma_check_init(&check, block->check);
+		lzma_check_update(&check, block->check, in, in_size);
+		lzma_check_finish(&check, block->check);
+
+		memcpy(block->raw_check, check.buffer.u8, check_size);
+		memcpy(out + *out_pos, check.buffer.u8, check_size);
+		*out_pos += check_size;
+	}
+
+	return LZMA_OK;
+}
diff --git a/src/liblzma/common/block_decoder.c b/src/liblzma/common/block_decoder.c
new file mode 100644
index 0000000..a3ce6f4
--- /dev/null
+++ b/src/liblzma/common/block_decoder.c
@@ -0,0 +1,242 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       block_decoder.c
+/// \brief      Decodes .xz Blocks
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "block_decoder.h"
+#include "filter_decoder.h"
+#include "check.h"
+
+
+struct lzma_coder_s {
+	enum {
+		SEQ_CODE,
+		SEQ_PADDING,
+		SEQ_CHECK,
+	} sequence;
+
+	/// The filters in the chain; initialized with lzma_raw_decoder_init().
+	lzma_next_coder next;
+
+	/// Decoding options; we also write Compressed Size and Uncompressed
+	/// Size back to this structure when the decoding has been finished.
+	lzma_block *block;
+
+	/// Compressed Size calculated while decoding
+	lzma_vli compressed_size;
+
+	/// Uncompressed Size calculated while decoding
+	lzma_vli uncompressed_size;
+
+	/// Maximum allowed Compressed Size; this takes into account the
+	/// size of the Block Header and Check fields when Compressed Size
+	/// is unknown.
+	lzma_vli compressed_limit;
+
+	/// Position when reading the Check field
+	size_t check_pos;
+
+	/// Check of the uncompressed data
+	lzma_check_state check;
+};
+
+
+static inline bool
+update_size(lzma_vli *size, lzma_vli add, lzma_vli limit)
+{
+	if (limit > LZMA_VLI_MAX)
+		limit = LZMA_VLI_MAX;
+
+	if (limit < *size || limit - *size < add)
+		return true;
+
+	*size += add;
+
+	return false;
+}
+
+
+static inline bool
+is_size_valid(lzma_vli size, lzma_vli reference)
+{
+	return reference == LZMA_VLI_UNKNOWN || reference == size;
+}
+
+
+static lzma_ret
+block_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)
+{
+	switch (coder->sequence) {
+	case SEQ_CODE: {
+		const size_t in_start = *in_pos;
+		const size_t out_start = *out_pos;
+
+		const lzma_ret ret = coder->next.code(coder->next.coder,
+				allocator, in, in_pos, in_size,
+				out, out_pos, out_size, action);
+
+		const size_t in_used = *in_pos - in_start;
+		const size_t out_used = *out_pos - out_start;
+
+		// NOTE: We compare to compressed_limit here, which prevents
+		// the total size of the Block growing past LZMA_VLI_MAX.
+		if (update_size(&coder->compressed_size, in_used,
+					coder->compressed_limit)
+				|| update_size(&coder->uncompressed_size,
+					out_used,
+					coder->block->uncompressed_size))
+			return LZMA_DATA_ERROR;
+
+		lzma_check_update(&coder->check, coder->block->check,
+				out + out_start, out_used);
+
+		if (ret != LZMA_STREAM_END)
+			return ret;
+
+		// Compressed and Uncompressed Sizes are now at their final
+		// values. Verify that they match the values given to us.
+		if (!is_size_valid(coder->compressed_size,
+					coder->block->compressed_size)
+				|| !is_size_valid(coder->uncompressed_size,
+					coder->block->uncompressed_size))
+			return LZMA_DATA_ERROR;
+
+		// Copy the values into coder->block. The caller
+		// may use this information to construct Index.
+		coder->block->compressed_size = coder->compressed_size;
+		coder->block->uncompressed_size = coder->uncompressed_size;
+
+		coder->sequence = SEQ_PADDING;
+	}
+
+	// Fall through
+
+	case SEQ_PADDING:
+		// Compressed Data is padded to a multiple of four bytes.
+		while (coder->compressed_size & 3) {
+			if (*in_pos >= in_size)
+				return LZMA_OK;
+
+			// We use compressed_size here just get the Padding
+			// right. The actual Compressed Size was stored to
+			// coder->block already, and won't be modified by
+			// us anymore.
+			++coder->compressed_size;
+
+			if (in[(*in_pos)++] != 0x00)
+				return LZMA_DATA_ERROR;
+		}
+
+		if (coder->block->check == LZMA_CHECK_NONE)
+			return LZMA_STREAM_END;
+
+		lzma_check_finish(&coder->check, coder->block->check);
+		coder->sequence = SEQ_CHECK;
+
+	// Fall through
+
+	case SEQ_CHECK: {
+		const size_t check_size = lzma_check_size(coder->block->check);
+		lzma_bufcpy(in, in_pos, in_size, coder->block->raw_check,
+				&coder->check_pos, check_size);
+		if (coder->check_pos < check_size)
+			return LZMA_OK;
+
+		// Validate the Check only if we support it.
+		// coder->check.buffer may be uninitialized
+		// when the Check ID is not supported.
+		if (lzma_check_is_supported(coder->block->check)
+				&& memcmp(coder->block->raw_check,
+					coder->check.buffer.u8,
+					check_size) != 0)
+			return LZMA_DATA_ERROR;
+
+		return LZMA_STREAM_END;
+	}
+	}
+
+	return LZMA_PROG_ERROR;
+}
+
+
+static void
+block_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
+{
+	lzma_next_end(&coder->next, allocator);
+	lzma_free(coder, allocator);
+	return;
+}
+
+
+extern lzma_ret
+lzma_block_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		lzma_block *block)
+{
+	lzma_next_coder_init(&lzma_block_decoder_init, next, allocator);
+
+	// Validate the options. lzma_block_unpadded_size() does that for us
+	// except for Uncompressed Size and filters. Filters are validated
+	// by the raw decoder.
+	if (lzma_block_unpadded_size(block) == 0
+			|| !lzma_vli_is_valid(block->uncompressed_size))
+		return LZMA_PROG_ERROR;
+
+	// Allocate and initialize *next->coder if needed.
+	if (next->coder == NULL) {
+		next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+		if (next->coder == NULL)
+			return LZMA_MEM_ERROR;
+
+		next->code = &block_decode;
+		next->end = &block_decoder_end;
+		next->coder->next = LZMA_NEXT_CODER_INIT;
+	}
+
+	// Basic initializations
+	next->coder->sequence = SEQ_CODE;
+	next->coder->block = block;
+	next->coder->compressed_size = 0;
+	next->coder->uncompressed_size = 0;
+
+	// If Compressed Size is not known, we calculate the maximum allowed
+	// value so that encoded size of the Block (including Block Padding)
+	// is still a valid VLI and a multiple of four.
+	next->coder->compressed_limit
+			= block->compressed_size == LZMA_VLI_UNKNOWN
+				? (LZMA_VLI_MAX & ~LZMA_VLI_C(3))
+					- block->header_size
+					- lzma_check_size(block->check)
+				: block->compressed_size;
+
+	// Initialize the check. It's caller's problem if the Check ID is not
+	// supported, and the Block decoder cannot verify the Check field.
+	// Caller can test lzma_check_is_supported(block->check).
+	next->coder->check_pos = 0;
+	lzma_check_init(&next->coder->check, block->check);
+
+	// Initialize the filter chain.
+	return lzma_raw_decoder_init(&next->coder->next, allocator,
+			block->filters);
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_block_decoder(lzma_stream *strm, lzma_block *block)
+{
+	lzma_next_strm_init(lzma_block_decoder_init, strm, block);
+
+	strm->internal->supported_actions[LZMA_RUN] = true;
+	strm->internal->supported_actions[LZMA_FINISH] = true;
+
+	return LZMA_OK;
+}
diff --git a/src/liblzma/common/block_decoder.h b/src/liblzma/common/block_decoder.h
new file mode 100644
index 0000000..7da9df6
--- /dev/null
+++ b/src/liblzma/common/block_decoder.h
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       block_decoder.h
+/// \brief      Decodes .xz Blocks
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_BLOCK_DECODER_H
+#define LZMA_BLOCK_DECODER_H
+
+#include "common.h"
+
+
+extern lzma_ret lzma_block_decoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, lzma_block *block);
+
+#endif
diff --git a/src/liblzma/common/block_encoder.c b/src/liblzma/common/block_encoder.c
new file mode 100644
index 0000000..ca51523
--- /dev/null
+++ b/src/liblzma/common/block_encoder.c
@@ -0,0 +1,212 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       block_encoder.c
+/// \brief      Encodes .xz Blocks
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "block_encoder.h"
+#include "filter_encoder.h"
+#include "check.h"
+
+
+struct lzma_coder_s {
+	/// The filters in the chain; initialized with lzma_raw_decoder_init().
+	lzma_next_coder next;
+
+	/// Encoding options; we also write Unpadded Size, Compressed Size,
+	/// and Uncompressed Size back to this structure when the encoding
+	/// has been finished.
+	lzma_block *block;
+
+	enum {
+		SEQ_CODE,
+		SEQ_PADDING,
+		SEQ_CHECK,
+	} sequence;
+
+	/// Compressed Size calculated while encoding
+	lzma_vli compressed_size;
+
+	/// Uncompressed Size calculated while encoding
+	lzma_vli uncompressed_size;
+
+	/// Position in the Check field
+	size_t pos;
+
+	/// Check of the uncompressed data
+	lzma_check_state check;
+};
+
+
+static lzma_ret
+block_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)
+{
+	// Check that our amount of input stays in proper limits.
+	if (LZMA_VLI_MAX - coder->uncompressed_size < in_size - *in_pos)
+		return LZMA_DATA_ERROR;
+
+	switch (coder->sequence) {
+	case SEQ_CODE: {
+		const size_t in_start = *in_pos;
+		const size_t out_start = *out_pos;
+
+		const lzma_ret ret = coder->next.code(coder->next.coder,
+				allocator, in, in_pos, in_size,
+				out, out_pos, out_size, action);
+
+		const size_t in_used = *in_pos - in_start;
+		const size_t out_used = *out_pos - out_start;
+
+		if (COMPRESSED_SIZE_MAX - coder->compressed_size < out_used)
+			return LZMA_DATA_ERROR;
+
+		coder->compressed_size += out_used;
+
+		// No need to check for overflow because we have already
+		// checked it at the beginning of this function.
+		coder->uncompressed_size += in_used;
+
+		lzma_check_update(&coder->check, coder->block->check,
+				in + in_start, in_used);
+
+		if (ret != LZMA_STREAM_END || action == LZMA_SYNC_FLUSH)
+			return ret;
+
+		assert(*in_pos == in_size);
+		assert(action == LZMA_FINISH);
+
+		// Copy the values into coder->block. The caller
+		// may use this information to construct Index.
+		coder->block->compressed_size = coder->compressed_size;
+		coder->block->uncompressed_size = coder->uncompressed_size;
+
+		coder->sequence = SEQ_PADDING;
+	}
+
+	// Fall through
+
+	case SEQ_PADDING:
+		// Pad Compressed Data to a multiple of four bytes. We can
+		// use coder->compressed_size for this since we don't need
+		// it for anything else anymore.
+		while (coder->compressed_size & 3) {
+			if (*out_pos >= out_size)
+				return LZMA_OK;
+
+			out[*out_pos] = 0x00;
+			++*out_pos;
+			++coder->compressed_size;
+		}
+
+		if (coder->block->check == LZMA_CHECK_NONE)
+			return LZMA_STREAM_END;
+
+		lzma_check_finish(&coder->check, coder->block->check);
+
+		coder->sequence = SEQ_CHECK;
+
+	// Fall through
+
+	case SEQ_CHECK: {
+		const size_t check_size = lzma_check_size(coder->block->check);
+		lzma_bufcpy(coder->check.buffer.u8, &coder->pos, check_size,
+				out, out_pos, out_size);
+		if (coder->pos < check_size)
+			return LZMA_OK;
+
+		memcpy(coder->block->raw_check, coder->check.buffer.u8,
+				check_size);
+		return LZMA_STREAM_END;
+	}
+	}
+
+	return LZMA_PROG_ERROR;
+}
+
+
+static void
+block_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
+{
+	lzma_next_end(&coder->next, allocator);
+	lzma_free(coder, allocator);
+	return;
+}
+
+
+static lzma_ret
+block_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
+		const lzma_filter *filters lzma_attribute((unused)),
+		const lzma_filter *reversed_filters)
+{
+	if (coder->sequence != SEQ_CODE)
+		return LZMA_PROG_ERROR;
+
+	return lzma_next_filter_update(
+			&coder->next, allocator, reversed_filters);
+}
+
+
+extern lzma_ret
+lzma_block_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		lzma_block *block)
+{
+	lzma_next_coder_init(&lzma_block_encoder_init, next, allocator);
+
+	if (block->version != 0)
+		return LZMA_OPTIONS_ERROR;
+
+	// If the Check ID is not supported, we cannot calculate the check and
+	// thus not create a proper Block.
+	if ((unsigned int)(block->check) > LZMA_CHECK_ID_MAX)
+		return LZMA_PROG_ERROR;
+
+	if (!lzma_check_is_supported(block->check))
+		return LZMA_UNSUPPORTED_CHECK;
+
+	// Allocate and initialize *next->coder if needed.
+	if (next->coder == NULL) {
+		next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+		if (next->coder == NULL)
+			return LZMA_MEM_ERROR;
+
+		next->code = &block_encode;
+		next->end = &block_encoder_end;
+		next->update = &block_encoder_update;
+		next->coder->next = LZMA_NEXT_CODER_INIT;
+	}
+
+	// Basic initializations
+	next->coder->sequence = SEQ_CODE;
+	next->coder->block = block;
+	next->coder->compressed_size = 0;
+	next->coder->uncompressed_size = 0;
+	next->coder->pos = 0;
+
+	// Initialize the check
+	lzma_check_init(&next->coder->check, block->check);
+
+	// Initialize the requested filters.
+	return lzma_raw_encoder_init(&next->coder->next, allocator,
+			block->filters);
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_block_encoder(lzma_stream *strm, lzma_block *block)
+{
+	lzma_next_strm_init(lzma_block_encoder_init, strm, block);
+
+	strm->internal->supported_actions[LZMA_RUN] = true;
+	strm->internal->supported_actions[LZMA_FINISH] = true;
+
+	return LZMA_OK;
+}
diff --git a/src/liblzma/common/block_encoder.h b/src/liblzma/common/block_encoder.h
new file mode 100644
index 0000000..b9eff0b
--- /dev/null
+++ b/src/liblzma/common/block_encoder.h
@@ -0,0 +1,47 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       block_encoder.h
+/// \brief      Encodes .xz Blocks
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_BLOCK_ENCODER_H
+#define LZMA_BLOCK_ENCODER_H
+
+#include "common.h"
+
+
+/// \brief      Biggest Compressed Size value that the Block encoder supports
+///
+/// The maximum size of a single Block is limited by the maximum size of
+/// a Stream, which in theory is 2^63 - 3 bytes (i.e. LZMA_VLI_MAX - 3).
+/// While the size is really big and no one should hit it in practice, we
+/// take it into account in some places anyway to catch some errors e.g. if
+/// application passes insanely big value to some function.
+///
+/// We could take into account the headers etc. to determine the exact
+/// maximum size of the Compressed Data field, but the complexity would give
+/// us nothing useful. Instead, limit the size of Compressed Data so that
+/// even with biggest possible Block Header and Check fields the total
+/// encoded size of the Block stays as a valid VLI. This doesn't guarantee
+/// that the size of the Stream doesn't grow too big, but that problem is
+/// taken care outside the Block handling code.
+///
+/// ~LZMA_VLI_C(3) is to guarantee that if we need padding at the end of
+/// the Compressed Data field, it will still stay in the proper limit.
+///
+/// This constant is in this file because it is needed in both
+/// block_encoder.c and block_buffer_encoder.c.
+#define COMPRESSED_SIZE_MAX ((LZMA_VLI_MAX - LZMA_BLOCK_HEADER_SIZE_MAX \
+		- LZMA_CHECK_SIZE_MAX) & ~LZMA_VLI_C(3))
+
+
+extern lzma_ret lzma_block_encoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, lzma_block *block);
+
+#endif
diff --git a/src/liblzma/common/block_header_decoder.c b/src/liblzma/common/block_header_decoder.c
new file mode 100644
index 0000000..2c9573e
--- /dev/null
+++ b/src/liblzma/common/block_header_decoder.c
@@ -0,0 +1,116 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       block_header_decoder.c
+/// \brief      Decodes Block Header from .xz files
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+#include "check.h"
+
+
+static void
+free_properties(lzma_block *block, lzma_allocator *allocator)
+{
+	// Free allocated filter options. The last array member is not
+	// touched after the initialization in the beginning of
+	// lzma_block_header_decode(), so we don't need to touch that here.
+	for (size_t i = 0; i < LZMA_FILTERS_MAX; ++i) {
+		lzma_free(block->filters[i].options, allocator);
+		block->filters[i].id = LZMA_VLI_UNKNOWN;
+		block->filters[i].options = NULL;
+	}
+
+	return;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_block_header_decode(lzma_block *block,
+		lzma_allocator *allocator, const uint8_t *in)
+{
+	// NOTE: We consider the header to be corrupt not only when the
+	// CRC32 doesn't match, but also when variable-length integers
+	// are invalid or over 63 bits, or if the header is too small
+	// to contain the claimed information.
+
+	// Initialize the filter options array. This way the caller can
+	// safely free() the options even if an error occurs in this function.
+	for (size_t i = 0; i <= LZMA_FILTERS_MAX; ++i) {
+		block->filters[i].id = LZMA_VLI_UNKNOWN;
+		block->filters[i].options = NULL;
+	}
+
+	// Always zero for now.
+	block->version = 0;
+
+	// Validate Block Header Size and Check type. The caller must have
+	// already set these, so it is a programming error if this test fails.
+	if (lzma_block_header_size_decode(in[0]) != block->header_size
+			|| (unsigned int)(block->check) > LZMA_CHECK_ID_MAX)
+		return LZMA_PROG_ERROR;
+
+	// Exclude the CRC32 field.
+	const size_t in_size = block->header_size - 4;
+
+	// Verify CRC32
+	if (lzma_crc32(in, in_size, 0) != unaligned_read32le(in + in_size))
+		return LZMA_DATA_ERROR;
+
+	// Check for unsupported flags.
+	if (in[1] & 0x3C)
+		return LZMA_OPTIONS_ERROR;
+
+	// Start after the Block Header Size and Block Flags fields.
+	size_t in_pos = 2;
+
+	// Compressed Size
+	if (in[1] & 0x40) {
+		return_if_error(lzma_vli_decode(&block->compressed_size,
+				NULL, in, &in_pos, in_size));
+
+		// Validate Compressed Size. This checks that it isn't zero
+		// and that the total size of the Block is a valid VLI.
+		if (lzma_block_unpadded_size(block) == 0)
+			return LZMA_DATA_ERROR;
+	} else {
+		block->compressed_size = LZMA_VLI_UNKNOWN;
+	}
+
+	// Uncompressed Size
+	if (in[1] & 0x80)
+		return_if_error(lzma_vli_decode(&block->uncompressed_size,
+				NULL, in, &in_pos, in_size));
+	else
+		block->uncompressed_size = LZMA_VLI_UNKNOWN;
+
+	// Filter Flags
+	const size_t filter_count = (in[1] & 3) + 1;
+	for (size_t i = 0; i < filter_count; ++i) {
+		const lzma_ret ret = lzma_filter_flags_decode(
+				&block->filters[i], allocator,
+				in, &in_pos, in_size);
+		if (ret != LZMA_OK) {
+			free_properties(block, allocator);
+			return ret;
+		}
+	}
+
+	// Padding
+	while (in_pos < in_size) {
+		if (in[in_pos++] != 0x00) {
+			free_properties(block, allocator);
+
+			// Possibly some new field present so use
+			// LZMA_OPTIONS_ERROR instead of LZMA_DATA_ERROR.
+			return LZMA_OPTIONS_ERROR;
+		}
+	}
+
+	return LZMA_OK;
+}
diff --git a/src/liblzma/common/block_header_encoder.c b/src/liblzma/common/block_header_encoder.c
new file mode 100644
index 0000000..707dd0c
--- /dev/null
+++ b/src/liblzma/common/block_header_encoder.c
@@ -0,0 +1,132 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       block_header_encoder.c
+/// \brief      Encodes Block Header for .xz files
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+#include "check.h"
+
+
+extern LZMA_API(lzma_ret)
+lzma_block_header_size(lzma_block *block)
+{
+	if (block->version != 0)
+		return LZMA_OPTIONS_ERROR;
+
+	// Block Header Size + Block Flags + CRC32.
+	uint32_t size = 1 + 1 + 4;
+
+	// Compressed Size
+	if (block->compressed_size != LZMA_VLI_UNKNOWN) {
+		const uint32_t add = lzma_vli_size(block->compressed_size);
+		if (add == 0 || block->compressed_size == 0)
+			return LZMA_PROG_ERROR;
+
+		size += add;
+	}
+
+	// Uncompressed Size
+	if (block->uncompressed_size != LZMA_VLI_UNKNOWN) {
+		const uint32_t add = lzma_vli_size(block->uncompressed_size);
+		if (add == 0)
+			return LZMA_PROG_ERROR;
+
+		size += add;
+	}
+
+	// List of Filter Flags
+	if (block->filters == NULL || block->filters[0].id == LZMA_VLI_UNKNOWN)
+		return LZMA_PROG_ERROR;
+
+	for (size_t i = 0; block->filters[i].id != LZMA_VLI_UNKNOWN; ++i) {
+		// Don't allow too many filters.
+		if (i == LZMA_FILTERS_MAX)
+			return LZMA_PROG_ERROR;
+
+		uint32_t add;
+		return_if_error(lzma_filter_flags_size(&add,
+				block->filters + i));
+
+		size += add;
+	}
+
+	// Pad to a multiple of four bytes.
+	block->header_size = (size + 3) & ~UINT32_C(3);
+
+	// NOTE: We don't verify that the encoded size of the Block stays
+	// within limits. This is because it is possible that we are called
+	// with exaggerated Compressed Size (e.g. LZMA_VLI_MAX) to reserve
+	// space for Block Header, and later called again with lower,
+	// real values.
+
+	return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_block_header_encode(const lzma_block *block, uint8_t *out)
+{
+	// Validate everything but filters.
+	if (lzma_block_unpadded_size(block) == 0
+			|| !lzma_vli_is_valid(block->uncompressed_size))
+		return LZMA_PROG_ERROR;
+
+	// Indicate the size of the buffer _excluding_ the CRC32 field.
+	const size_t out_size = block->header_size - 4;
+
+	// Store the Block Header Size.
+	out[0] = out_size / 4;
+
+	// We write Block Flags in pieces.
+	out[1] = 0x00;
+	size_t out_pos = 2;
+
+	// Compressed Size
+	if (block->compressed_size != LZMA_VLI_UNKNOWN) {
+		return_if_error(lzma_vli_encode(block->compressed_size, NULL,
+				out, &out_pos, out_size));
+
+		out[1] |= 0x40;
+	}
+
+	// Uncompressed Size
+	if (block->uncompressed_size != LZMA_VLI_UNKNOWN) {
+		return_if_error(lzma_vli_encode(block->uncompressed_size, NULL,
+				out, &out_pos, out_size));
+
+		out[1] |= 0x80;
+	}
+
+	// Filter Flags
+	if (block->filters == NULL || block->filters[0].id == LZMA_VLI_UNKNOWN)
+		return LZMA_PROG_ERROR;
+
+	size_t filter_count = 0;
+	do {
+		// There can be a maximum of four filters.
+		if (filter_count == LZMA_FILTERS_MAX)
+			return LZMA_PROG_ERROR;
+
+		return_if_error(lzma_filter_flags_encode(
+				block->filters + filter_count,
+				out, &out_pos, out_size));
+
+	} while (block->filters[++filter_count].id != LZMA_VLI_UNKNOWN);
+
+	out[1] |= filter_count - 1;
+
+	// Padding
+	memzero(out + out_pos, out_size - out_pos);
+
+	// CRC32
+	unaligned_write32le(out + out_size, lzma_crc32(out, out_size, 0));
+
+	return LZMA_OK;
+}
diff --git a/src/liblzma/common/block_util.c b/src/liblzma/common/block_util.c
new file mode 100644
index 0000000..62c9345
--- /dev/null
+++ b/src/liblzma/common/block_util.c
@@ -0,0 +1,90 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       block_header.c
+/// \brief      Utility functions to handle lzma_block
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+#include "index.h"
+
+
+extern LZMA_API(lzma_ret)
+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)
+		return LZMA_PROG_ERROR;
+
+	const uint32_t container_size = block->header_size
+			+ lzma_check_size(block->check);
+
+	// Validate that Compressed Size will be greater than zero.
+	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 = unpadded_size - container_size;
+	if (block->compressed_size != LZMA_VLI_UNKNOWN
+			&& block->compressed_size != compressed_size)
+		return LZMA_DATA_ERROR;
+
+	block->compressed_size = compressed_size;
+
+	return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_vli)
+lzma_block_unpadded_size(const lzma_block *block)
+{
+	// Validate the values that we are interested in i.e. all but
+	// Uncompressed Size and the filters.
+	//
+	// NOTE: This function is used for validation too, so it is
+	// essential that these checks are always done even if
+	// Compressed Size is unknown.
+	if (block == NULL || block->version != 0
+			|| block->header_size < LZMA_BLOCK_HEADER_SIZE_MIN
+			|| block->header_size > LZMA_BLOCK_HEADER_SIZE_MAX
+			|| (block->header_size & 3)
+			|| !lzma_vli_is_valid(block->compressed_size)
+			|| block->compressed_size == 0
+			|| (unsigned int)(block->check) > LZMA_CHECK_ID_MAX)
+		return 0;
+
+	// If Compressed Size is unknown, return that we cannot know
+	// size of the Block either.
+	if (block->compressed_size == LZMA_VLI_UNKNOWN)
+		return LZMA_VLI_UNKNOWN;
+
+	// Calculate Unpadded Size and validate it.
+	const lzma_vli unpadded_size = block->compressed_size
+				+ block->header_size
+				+ lzma_check_size(block->check);
+
+	assert(unpadded_size >= UNPADDED_SIZE_MIN);
+	if (unpadded_size > UNPADDED_SIZE_MAX)
+		return 0;
+
+	return unpadded_size;
+}
+
+
+extern LZMA_API(lzma_vli)
+lzma_block_total_size(const lzma_block *block)
+{
+	lzma_vli unpadded_size = lzma_block_unpadded_size(block);
+
+	if (unpadded_size != LZMA_VLI_UNKNOWN)
+		unpadded_size = vli_ceil4(unpadded_size);
+
+	return unpadded_size;
+}
diff --git a/src/liblzma/common/common.c b/src/liblzma/common/common.c
new file mode 100644
index 0000000..07b1d47
--- /dev/null
+++ b/src/liblzma/common/common.c
@@ -0,0 +1,374 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       common.h
+/// \brief      Common functions needed in many places in liblzma
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+
+
+/////////////
+// Version //
+/////////////
+
+extern LZMA_API(uint32_t)
+lzma_version_number(void)
+{
+	return LZMA_VERSION;
+}
+
+
+extern LZMA_API(const char *)
+lzma_version_string(void)
+{
+	return LZMA_VERSION_STRING;
+}
+
+
+///////////////////////
+// Memory allocation //
+///////////////////////
+
+extern void * lzma_attribute((malloc))
+lzma_alloc(size_t size, lzma_allocator *allocator)
+{
+	// Some malloc() variants return NULL if called with size == 0.
+	if (size == 0)
+		size = 1;
+
+	void *ptr;
+
+	if (allocator != NULL && allocator->alloc != NULL)
+		ptr = allocator->alloc(allocator->opaque, 1, size);
+	else
+		ptr = malloc(size);
+
+	return ptr;
+}
+
+
+extern void
+lzma_free(void *ptr, lzma_allocator *allocator)
+{
+	if (allocator != NULL && allocator->free != NULL)
+		allocator->free(allocator->opaque, ptr);
+	else
+		free(ptr);
+
+	return;
+}
+
+
+//////////
+// Misc //
+//////////
+
+extern size_t
+lzma_bufcpy(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)
+{
+	const size_t in_avail = in_size - *in_pos;
+	const size_t out_avail = out_size - *out_pos;
+	const size_t copy_size = my_min(in_avail, out_avail);
+
+	memcpy(out + *out_pos, in + *in_pos, copy_size);
+
+	*in_pos += copy_size;
+	*out_pos += copy_size;
+
+	return copy_size;
+}
+
+
+extern lzma_ret
+lzma_next_filter_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters)
+{
+	lzma_next_coder_init(filters[0].init, next, allocator);
+	next->id = filters[0].id;
+	return filters[0].init == NULL
+			? LZMA_OK : filters[0].init(next, allocator, filters);
+}
+
+
+extern lzma_ret
+lzma_next_filter_update(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter *reversed_filters)
+{
+	// Check that the application isn't trying to change the Filter ID.
+	// End of filters is indicated with LZMA_VLI_UNKNOWN in both
+	// reversed_filters[0].id and next->id.
+	if (reversed_filters[0].id != next->id)
+		return LZMA_PROG_ERROR;
+
+	if (reversed_filters[0].id == LZMA_VLI_UNKNOWN)
+		return LZMA_OK;
+
+	assert(next->update != NULL);
+	return next->update(next->coder, allocator, NULL, reversed_filters);
+}
+
+
+extern void
+lzma_next_end(lzma_next_coder *next, lzma_allocator *allocator)
+{
+	if (next->init != (uintptr_t)(NULL)) {
+		// To avoid tiny end functions that simply call
+		// lzma_free(coder, allocator), we allow leaving next->end
+		// NULL and call lzma_free() here.
+		if (next->end != NULL)
+			next->end(next->coder, allocator);
+		else
+			lzma_free(next->coder, allocator);
+
+		// Reset the variables so the we don't accidentally think
+		// that it is an already initialized coder.
+		*next = LZMA_NEXT_CODER_INIT;
+	}
+
+	return;
+}
+
+
+//////////////////////////////////////
+// External to internal API wrapper //
+//////////////////////////////////////
+
+extern lzma_ret
+lzma_strm_init(lzma_stream *strm)
+{
+	if (strm == NULL)
+		return LZMA_PROG_ERROR;
+
+	if (strm->internal == NULL) {
+		strm->internal = lzma_alloc(sizeof(lzma_internal),
+				strm->allocator);
+		if (strm->internal == NULL)
+			return LZMA_MEM_ERROR;
+
+		strm->internal->next = LZMA_NEXT_CODER_INIT;
+	}
+
+	strm->internal->supported_actions[LZMA_RUN] = false;
+	strm->internal->supported_actions[LZMA_SYNC_FLUSH] = false;
+	strm->internal->supported_actions[LZMA_FULL_FLUSH] = false;
+	strm->internal->supported_actions[LZMA_FINISH] = false;
+	strm->internal->sequence = ISEQ_RUN;
+	strm->internal->allow_buf_error = false;
+
+	strm->total_in = 0;
+	strm->total_out = 0;
+
+	return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_code(lzma_stream *strm, lzma_action action)
+{
+	// Sanity checks
+	if ((strm->next_in == NULL && strm->avail_in != 0)
+			|| (strm->next_out == NULL && strm->avail_out != 0)
+			|| strm->internal == NULL
+			|| strm->internal->next.code == NULL
+			|| (unsigned int)(action) > LZMA_FINISH
+			|| !strm->internal->supported_actions[action])
+		return LZMA_PROG_ERROR;
+
+	switch (strm->internal->sequence) {
+	case ISEQ_RUN:
+		switch (action) {
+		case LZMA_RUN:
+			break;
+
+		case LZMA_SYNC_FLUSH:
+			strm->internal->sequence = ISEQ_SYNC_FLUSH;
+			break;
+
+		case LZMA_FULL_FLUSH:
+			strm->internal->sequence = ISEQ_FULL_FLUSH;
+			break;
+
+		case LZMA_FINISH:
+			strm->internal->sequence = ISEQ_FINISH;
+			break;
+		}
+
+		break;
+
+	case ISEQ_SYNC_FLUSH:
+		// The same action must be used until we return
+		// LZMA_STREAM_END, and the amount of input must not change.
+		if (action != LZMA_SYNC_FLUSH
+				|| strm->internal->avail_in != strm->avail_in)
+			return LZMA_PROG_ERROR;
+
+		break;
+
+	case ISEQ_FULL_FLUSH:
+		if (action != LZMA_FULL_FLUSH
+				|| strm->internal->avail_in != strm->avail_in)
+			return LZMA_PROG_ERROR;
+
+		break;
+
+	case ISEQ_FINISH:
+		if (action != LZMA_FINISH
+				|| strm->internal->avail_in != strm->avail_in)
+			return LZMA_PROG_ERROR;
+
+		break;
+
+	case ISEQ_END:
+		return LZMA_STREAM_END;
+
+	case ISEQ_ERROR:
+	default:
+		return LZMA_PROG_ERROR;
+	}
+
+	size_t in_pos = 0;
+	size_t out_pos = 0;
+	lzma_ret ret = strm->internal->next.code(
+			strm->internal->next.coder, strm->allocator,
+			strm->next_in, &in_pos, strm->avail_in,
+			strm->next_out, &out_pos, strm->avail_out, action);
+
+	strm->next_in += in_pos;
+	strm->avail_in -= in_pos;
+	strm->total_in += in_pos;
+
+	strm->next_out += out_pos;
+	strm->avail_out -= out_pos;
+	strm->total_out += out_pos;
+
+	strm->internal->avail_in = strm->avail_in;
+
+	switch (ret) {
+	case LZMA_OK:
+		// Don't return LZMA_BUF_ERROR when it happens the first time.
+		// This is to avoid returning LZMA_BUF_ERROR when avail_out
+		// was zero but still there was no more data left to written
+		// to next_out.
+		if (out_pos == 0 && in_pos == 0) {
+			if (strm->internal->allow_buf_error)
+				ret = LZMA_BUF_ERROR;
+			else
+				strm->internal->allow_buf_error = true;
+		} else {
+			strm->internal->allow_buf_error = false;
+		}
+		break;
+
+	case LZMA_STREAM_END:
+		if (strm->internal->sequence == ISEQ_SYNC_FLUSH
+				|| strm->internal->sequence == ISEQ_FULL_FLUSH)
+			strm->internal->sequence = ISEQ_RUN;
+		else
+			strm->internal->sequence = ISEQ_END;
+
+	// Fall through
+
+	case LZMA_NO_CHECK:
+	case LZMA_UNSUPPORTED_CHECK:
+	case LZMA_GET_CHECK:
+	case LZMA_MEMLIMIT_ERROR:
+		// Something else than LZMA_OK, but not a fatal error,
+		// that is, coding may be continued (except if ISEQ_END).
+		strm->internal->allow_buf_error = false;
+		break;
+
+	default:
+		// All the other errors are fatal; coding cannot be continued.
+		assert(ret != LZMA_BUF_ERROR);
+		strm->internal->sequence = ISEQ_ERROR;
+		break;
+	}
+
+	return ret;
+}
+
+
+extern LZMA_API(void)
+lzma_end(lzma_stream *strm)
+{
+	if (strm != NULL && strm->internal != NULL) {
+		lzma_next_end(&strm->internal->next, strm->allocator);
+		lzma_free(strm->internal, strm->allocator);
+		strm->internal = NULL;
+	}
+
+	return;
+}
+
+
+extern LZMA_API(lzma_check)
+lzma_get_check(const lzma_stream *strm)
+{
+	// Return LZMA_CHECK_NONE if we cannot know the check type.
+	// It's a bug in the application if this happens.
+	if (strm->internal->next.get_check == NULL)
+		return LZMA_CHECK_NONE;
+
+	return strm->internal->next.get_check(strm->internal->next.coder);
+}
+
+
+extern LZMA_API(uint64_t)
+lzma_memusage(const lzma_stream *strm)
+{
+	uint64_t memusage;
+	uint64_t old_memlimit;
+
+	if (strm == NULL || strm->internal == NULL
+			|| strm->internal->next.memconfig == NULL
+			|| strm->internal->next.memconfig(
+				strm->internal->next.coder,
+				&memusage, &old_memlimit, 0) != LZMA_OK)
+		return 0;
+
+	return memusage;
+}
+
+
+extern LZMA_API(uint64_t)
+lzma_memlimit_get(const lzma_stream *strm)
+{
+	uint64_t old_memlimit;
+	uint64_t memusage;
+
+	if (strm == NULL || strm->internal == NULL
+			|| strm->internal->next.memconfig == NULL
+			|| strm->internal->next.memconfig(
+				strm->internal->next.coder,
+				&memusage, &old_memlimit, 0) != LZMA_OK)
+		return 0;
+
+	return old_memlimit;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_memlimit_set(lzma_stream *strm, uint64_t new_memlimit)
+{
+	// Dummy variables to simplify memconfig functions
+	uint64_t old_memlimit;
+	uint64_t memusage;
+
+	if (strm == NULL || strm->internal == NULL
+			|| strm->internal->next.memconfig == NULL)
+		return LZMA_PROG_ERROR;
+
+	if (new_memlimit != 0 && new_memlimit < LZMA_MEMUSAGE_BASE)
+		return LZMA_MEMLIMIT_ERROR;
+
+	return strm->internal->next.memconfig(strm->internal->next.coder,
+			&memusage, &old_memlimit, new_memlimit);
+}
diff --git a/src/liblzma/common/common.h b/src/liblzma/common/common.h
new file mode 100644
index 0000000..3a85168
--- /dev/null
+++ b/src/liblzma/common/common.h
@@ -0,0 +1,284 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       common.h
+/// \brief      Definitions common to the whole liblzma library
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_COMMON_H
+#define LZMA_COMMON_H
+
+#include "sysdefs.h"
+#include "mythread.h"
+#include "tuklib_integer.h"
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+#	ifdef DLL_EXPORT
+#		define LZMA_API_EXPORT __declspec(dllexport)
+#	else
+#		define LZMA_API_EXPORT
+#	endif
+// Don't use ifdef or defined() below.
+#elif HAVE_VISIBILITY
+#	define LZMA_API_EXPORT __attribute__((__visibility__("default")))
+#else
+#	define LZMA_API_EXPORT
+#endif
+
+#define LZMA_API(type) LZMA_API_EXPORT type LZMA_API_CALL
+
+#include "lzma.h"
+
+// These allow helping the compiler in some often-executed branches, whose
+// result is almost always the same.
+#ifdef __GNUC__
+#	define likely(expr) __builtin_expect(expr, true)
+#	define unlikely(expr) __builtin_expect(expr, false)
+#else
+#	define likely(expr) (expr)
+#	define unlikely(expr) (expr)
+#endif
+
+
+/// Size of temporary buffers needed in some filters
+#define LZMA_BUFFER_SIZE 4096
+
+
+/// Starting value for memory usage estimates. Instead of calculating size
+/// of _every_ structure and taking into account malloc() overhead etc., we
+/// add a base size to all memory usage estimates. It's not very accurate
+/// but should be easily good enough.
+#define LZMA_MEMUSAGE_BASE (UINT64_C(1) << 15)
+
+/// Start of internal Filter ID space. These IDs must never be used
+/// in Streams.
+#define LZMA_FILTER_RESERVED_START (LZMA_VLI_C(1) << 62)
+
+
+/// Supported flags that can be passed to lzma_stream_decoder()
+/// or lzma_auto_decoder().
+#define LZMA_SUPPORTED_FLAGS \
+	( LZMA_TELL_NO_CHECK \
+	| LZMA_TELL_UNSUPPORTED_CHECK \
+	| LZMA_TELL_ANY_CHECK \
+	| LZMA_CONCATENATED )
+
+
+/// Type of encoder/decoder specific data; the actual structure is defined
+/// differently in different coders.
+typedef struct lzma_coder_s lzma_coder;
+
+typedef struct lzma_next_coder_s lzma_next_coder;
+
+typedef struct lzma_filter_info_s lzma_filter_info;
+
+
+/// Type of a function used to initialize a filter encoder or decoder
+typedef lzma_ret (*lzma_init_function)(
+		lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters);
+
+/// Type of a function to do some kind of coding work (filters, Stream,
+/// Block encoders/decoders etc.). Some special coders use don't use both
+/// input and output buffers, but for simplicity they still use this same
+/// function prototype.
+typedef lzma_ret (*lzma_code_function)(
+		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);
+
+/// Type of a function to free the memory allocated for the coder
+typedef void (*lzma_end_function)(
+		lzma_coder *coder, lzma_allocator *allocator);
+
+
+/// Raw coder validates and converts an array of lzma_filter structures to
+/// an array of lzma_filter_info structures. This array is used with
+/// lzma_next_filter_init to initialize the filter chain.
+struct lzma_filter_info_s {
+	/// Filter ID. This is used only by the encoder
+	/// with lzma_filters_update().
+	lzma_vli id;
+
+	/// Pointer to function used to initialize the filter.
+	/// This is NULL to indicate end of array.
+	lzma_init_function init;
+
+	/// Pointer to filter's options structure
+	void *options;
+};
+
+
+/// Hold data and function pointers of the next filter in the chain.
+struct lzma_next_coder_s {
+	/// Pointer to coder-specific data
+	lzma_coder *coder;
+
+	/// Filter ID. This is LZMA_VLI_UNKNOWN when this structure doesn't
+	/// point to a filter coder.
+	lzma_vli id;
+
+	/// "Pointer" to init function. This is never called here.
+	/// We need only to detect if we are initializing a coder
+	/// that was allocated earlier. See lzma_next_coder_init and
+	/// lzma_next_strm_init macros in this file.
+	uintptr_t init;
+
+	/// Pointer to function to do the actual coding
+	lzma_code_function code;
+
+	/// Pointer to function to free lzma_next_coder.coder. This can
+	/// be NULL; in that case, lzma_free is called to free
+	/// lzma_next_coder.coder.
+	lzma_end_function end;
+
+	/// Pointer to function to return the type of the integrity check.
+	/// Most coders won't support this.
+	lzma_check (*get_check)(const lzma_coder *coder);
+
+	/// Pointer to function to get and/or change the memory usage limit.
+	/// If new_memlimit == 0, the limit is not changed.
+	lzma_ret (*memconfig)(lzma_coder *coder, uint64_t *memusage,
+			uint64_t *old_memlimit, uint64_t new_memlimit);
+
+	/// Update the filter-specific options or the whole filter chain
+	/// in the encoder.
+	lzma_ret (*update)(lzma_coder *coder, lzma_allocator *allocator,
+			const lzma_filter *filters,
+			const lzma_filter *reversed_filters);
+};
+
+
+/// Macro to initialize lzma_next_coder structure
+#define LZMA_NEXT_CODER_INIT \
+	(lzma_next_coder){ \
+		.coder = NULL, \
+		.init = (uintptr_t)(NULL), \
+		.id = LZMA_VLI_UNKNOWN, \
+		.code = NULL, \
+		.end = NULL, \
+		.get_check = NULL, \
+		.memconfig = NULL, \
+		.update = NULL, \
+	}
+
+
+/// Internal data for lzma_strm_init, lzma_code, and lzma_end. A pointer to
+/// this is stored in lzma_stream.
+struct lzma_internal_s {
+	/// The actual coder that should do something useful
+	lzma_next_coder next;
+
+	/// Track the state of the coder. This is used to validate arguments
+	/// so that the actual coders can rely on e.g. that LZMA_SYNC_FLUSH
+	/// is used on every call to lzma_code until next.code has returned
+	/// LZMA_STREAM_END.
+	enum {
+		ISEQ_RUN,
+		ISEQ_SYNC_FLUSH,
+		ISEQ_FULL_FLUSH,
+		ISEQ_FINISH,
+		ISEQ_END,
+		ISEQ_ERROR,
+	} sequence;
+
+	/// A copy of lzma_stream avail_in. This is used to verify that the
+	/// amount of input doesn't change once e.g. LZMA_FINISH has been
+	/// used.
+	size_t avail_in;
+
+	/// Indicates which lzma_action values are allowed by next.code.
+	bool supported_actions[4];
+
+	/// If true, lzma_code will return LZMA_BUF_ERROR if no progress was
+	/// made (no input consumed and no output produced by next.code).
+	bool allow_buf_error;
+};
+
+
+/// Allocates memory
+extern void *lzma_alloc(size_t size, lzma_allocator *allocator)
+		lzma_attribute((malloc));
+
+/// Frees memory
+extern void lzma_free(void *ptr, lzma_allocator *allocator);
+
+
+/// Allocates strm->internal if it is NULL, and initializes *strm and
+/// strm->internal. This function is only called via lzma_next_strm_init macro.
+extern lzma_ret lzma_strm_init(lzma_stream *strm);
+
+/// Initializes the next filter in the chain, if any. This takes care of
+/// freeing the memory of previously initialized filter if it is different
+/// than the filter being initialized now. This way the actual filter
+/// initialization functions don't need to use lzma_next_coder_init macro.
+extern lzma_ret lzma_next_filter_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters);
+
+/// Update the next filter in the chain, if any. This checks that
+/// the application is not trying to change the Filter IDs.
+extern lzma_ret lzma_next_filter_update(
+		lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter *reversed_filters);
+
+/// Frees the memory allocated for next->coder either using next->end or,
+/// if next->end is NULL, using lzma_free.
+extern void lzma_next_end(lzma_next_coder *next, lzma_allocator *allocator);
+
+
+/// Copy as much data as possible from in[] to out[] and update *in_pos
+/// and *out_pos accordingly. Returns the number of bytes copied.
+extern size_t lzma_bufcpy(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);
+
+
+/// \brief      Return if expression doesn't evaluate to LZMA_OK
+///
+/// There are several situations where we want to return immediately
+/// with the value of expr if it isn't LZMA_OK. This macro shortens
+/// the code a little.
+#define return_if_error(expr) \
+do { \
+	const lzma_ret ret_ = (expr); \
+	if (ret_ != LZMA_OK) \
+		return ret_; \
+} while (0)
+
+
+/// If next isn't already initialized, free the previous coder. Then mark
+/// that next is _possibly_ initialized for the coder using this macro.
+/// "Possibly" means that if e.g. allocation of next->coder fails, the
+/// structure isn't actually initialized for this coder, but leaving
+/// next->init to func is still OK.
+#define lzma_next_coder_init(func, next, allocator) \
+do { \
+	if ((uintptr_t)(func) != (next)->init) \
+		lzma_next_end(next, allocator); \
+	(next)->init = (uintptr_t)(func); \
+} while (0)
+
+
+/// Initializes lzma_strm and calls func() to initialize strm->internal->next.
+/// (The function being called will use lzma_next_coder_init()). If
+/// initialization fails, memory that wasn't freed by func() is freed
+/// along strm->internal.
+#define lzma_next_strm_init(func, strm, ...) \
+do { \
+	return_if_error(lzma_strm_init(strm)); \
+	const lzma_ret ret_ = func(&(strm)->internal->next, \
+			(strm)->allocator, __VA_ARGS__); \
+	if (ret_ != LZMA_OK) { \
+		lzma_end(strm); \
+		return ret_; \
+	} \
+} while (0)
+
+#endif
diff --git a/src/liblzma/common/easy_buffer_encoder.c b/src/liblzma/common/easy_buffer_encoder.c
new file mode 100644
index 0000000..c4be34c
--- /dev/null
+++ b/src/liblzma/common/easy_buffer_encoder.c
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       easy_buffer_encoder.c
+/// \brief      Easy single-call .xz Stream encoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "easy_preset.h"
+
+
+extern LZMA_API(lzma_ret)
+lzma_easy_buffer_encode(uint32_t preset, lzma_check check,
+		lzma_allocator *allocator, const uint8_t *in, size_t in_size,
+		uint8_t *out, size_t *out_pos, size_t out_size)
+{
+	lzma_options_easy opt_easy;
+	if (lzma_easy_preset(&opt_easy, preset))
+		return LZMA_OPTIONS_ERROR;
+
+	return lzma_stream_buffer_encode(opt_easy.filters, check,
+			allocator, in, in_size, out, out_pos, out_size);
+}
diff --git a/src/liblzma/common/easy_decoder_memusage.c b/src/liblzma/common/easy_decoder_memusage.c
new file mode 100644
index 0000000..20bcd5b
--- /dev/null
+++ b/src/liblzma/common/easy_decoder_memusage.c
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       easy_decoder_memusage.c
+/// \brief      Decoder memory usage calculation to match easy encoder presets
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "easy_preset.h"
+
+
+extern LZMA_API(uint64_t)
+lzma_easy_decoder_memusage(uint32_t preset)
+{
+	lzma_options_easy opt_easy;
+	if (lzma_easy_preset(&opt_easy, preset))
+		return UINT32_MAX;
+
+	return lzma_raw_decoder_memusage(opt_easy.filters);
+}
diff --git a/src/liblzma/common/easy_encoder.c b/src/liblzma/common/easy_encoder.c
new file mode 100644
index 0000000..d13ccd7
--- /dev/null
+++ b/src/liblzma/common/easy_encoder.c
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       easy_encoder.c
+/// \brief      Easy .xz Stream encoder initialization
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "easy_preset.h"
+#include "stream_encoder.h"
+
+
+extern LZMA_API(lzma_ret)
+lzma_easy_encoder(lzma_stream *strm, uint32_t preset, lzma_check check)
+{
+	lzma_options_easy opt_easy;
+	if (lzma_easy_preset(&opt_easy, preset))
+		return LZMA_OPTIONS_ERROR;
+
+	return lzma_stream_encoder(strm, opt_easy.filters, check);
+}
diff --git a/src/liblzma/common/easy_encoder_memusage.c b/src/liblzma/common/easy_encoder_memusage.c
new file mode 100644
index 0000000..e910575
--- /dev/null
+++ b/src/liblzma/common/easy_encoder_memusage.c
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       easy_encoder_memusage.c
+/// \brief      Easy .xz Stream encoder memory usage calculation
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "easy_preset.h"
+
+
+extern LZMA_API(uint64_t)
+lzma_easy_encoder_memusage(uint32_t preset)
+{
+	lzma_options_easy opt_easy;
+	if (lzma_easy_preset(&opt_easy, preset))
+		return UINT32_MAX;
+
+	return lzma_raw_encoder_memusage(opt_easy.filters);
+}
diff --git a/src/liblzma/common/easy_preset.c b/src/liblzma/common/easy_preset.c
new file mode 100644
index 0000000..2f98598
--- /dev/null
+++ b/src/liblzma/common/easy_preset.c
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       easy_preset.c
+/// \brief      Preset handling for easy encoder and decoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "easy_preset.h"
+
+
+extern bool
+lzma_easy_preset(lzma_options_easy *opt_easy, uint32_t preset)
+{
+	if (lzma_lzma_preset(&opt_easy->opt_lzma, preset))
+		return true;
+
+	opt_easy->filters[0].id = LZMA_FILTER_LZMA2;
+	opt_easy->filters[0].options = &opt_easy->opt_lzma;
+	opt_easy->filters[1].id = LZMA_VLI_UNKNOWN;
+
+	return false;
+}
diff --git a/src/liblzma/common/easy_preset.h b/src/liblzma/common/easy_preset.h
new file mode 100644
index 0000000..382ade8
--- /dev/null
+++ b/src/liblzma/common/easy_preset.h
@@ -0,0 +1,32 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       easy_preset.h
+/// \brief      Preset handling for easy encoder and decoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+
+
+typedef struct {
+	/// We need to keep the filters array available in case
+	/// LZMA_FULL_FLUSH is used.
+	lzma_filter filters[LZMA_FILTERS_MAX + 1];
+
+	/// Options for LZMA2
+	lzma_options_lzma opt_lzma;
+
+	// Options for more filters can be added later, so this struct
+	// is not ready to be put into the public API.
+
+} lzma_options_easy;
+
+
+/// Set *easy to the settings given by the preset. Returns true on error,
+/// false on success.
+extern bool lzma_easy_preset(lzma_options_easy *easy, uint32_t preset);
diff --git a/src/liblzma/common/filter_buffer_decoder.c b/src/liblzma/common/filter_buffer_decoder.c
new file mode 100644
index 0000000..2d35ef8
--- /dev/null
+++ b/src/liblzma/common/filter_buffer_decoder.c
@@ -0,0 +1,87 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       filter_buffer_decoder.c
+/// \brief      Single-call raw decoding
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "filter_decoder.h"
+
+
+extern LZMA_API(lzma_ret)
+lzma_raw_buffer_decode(const lzma_filter *filters, lzma_allocator *allocator,
+		const uint8_t *in, size_t *in_pos, size_t in_size,
+		uint8_t *out, size_t *out_pos, size_t out_size)
+{
+	// Validate what isn't validated later in filter_common.c.
+	if (in == NULL || in_pos == NULL || *in_pos > in_size || out == NULL
+			|| out_pos == NULL || *out_pos > out_size)
+		return LZMA_PROG_ERROR;
+
+	// Initialize the decoer.
+	lzma_next_coder next = LZMA_NEXT_CODER_INIT;
+	return_if_error(lzma_raw_decoder_init(&next, allocator, filters));
+
+	// Store the positions so that we can restore them if something
+	// goes wrong.
+	const size_t in_start = *in_pos;
+	const size_t out_start = *out_pos;
+
+	// Do the actual decoding and free decoder's memory.
+	lzma_ret ret = next.code(next.coder, allocator, in, in_pos, in_size,
+			out, out_pos, out_size, LZMA_FINISH);
+
+	if (ret == LZMA_STREAM_END) {
+		ret = LZMA_OK;
+	} else {
+		if (ret == LZMA_OK) {
+			// Either the input was truncated or the
+			// output buffer was too small.
+			assert(*in_pos == in_size || *out_pos == out_size);
+
+			if (*in_pos != in_size) {
+				// Since input wasn't consumed completely,
+				// the output buffer became full and is
+				// too small.
+				ret = LZMA_BUF_ERROR;
+
+			} else if (*out_pos != out_size) {
+				// Since output didn't became full, the input
+				// has to be truncated.
+				ret = LZMA_DATA_ERROR;
+
+			} else {
+				// All the input was consumed and output
+				// buffer is full. Now we don't immediately
+				// know the reason for the error. Try
+				// decoding one more byte. If it succeeds,
+				// then the output buffer was too small. If
+				// we cannot get a new output byte, the input
+				// is truncated.
+				uint8_t tmp[1];
+				size_t tmp_pos = 0;
+				(void)next.code(next.coder, allocator,
+						in, in_pos, in_size,
+						tmp, &tmp_pos, 1, LZMA_FINISH);
+
+				if (tmp_pos == 1)
+					ret = LZMA_BUF_ERROR;
+				else
+					ret = LZMA_DATA_ERROR;
+			}
+		}
+
+		// Restore the positions.
+		*in_pos = in_start;
+		*out_pos = out_start;
+	}
+
+	lzma_next_end(&next, allocator);
+
+	return ret;
+}
diff --git a/src/liblzma/common/filter_buffer_encoder.c b/src/liblzma/common/filter_buffer_encoder.c
new file mode 100644
index 0000000..646e1b3
--- /dev/null
+++ b/src/liblzma/common/filter_buffer_encoder.c
@@ -0,0 +1,54 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       filter_buffer_encoder.c
+/// \brief      Single-call raw encoding
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "filter_encoder.h"
+
+
+extern LZMA_API(lzma_ret)
+lzma_raw_buffer_encode(const lzma_filter *filters, lzma_allocator *allocator,
+		const uint8_t *in, size_t in_size, uint8_t *out,
+		size_t *out_pos, size_t out_size)
+{
+	// Validate what isn't validated later in filter_common.c.
+	if ((in == NULL && in_size != 0) || out == NULL
+			|| out_pos == NULL || *out_pos > out_size)
+		return LZMA_PROG_ERROR;
+
+	// Initialize the encoder
+	lzma_next_coder next = LZMA_NEXT_CODER_INIT;
+	return_if_error(lzma_raw_encoder_init(&next, allocator, filters));
+
+	// Store the output position so that we can restore it if
+	// something goes wrong.
+	const size_t out_start = *out_pos;
+
+	// Do the actual encoding and free coder's memory.
+	size_t in_pos = 0;
+	lzma_ret ret = next.code(next.coder, allocator, in, &in_pos, in_size,
+			out, out_pos, out_size, LZMA_FINISH);
+	lzma_next_end(&next, allocator);
+
+	if (ret == LZMA_STREAM_END) {
+		ret = LZMA_OK;
+	} else {
+		if (ret == LZMA_OK) {
+			// Output buffer was too small.
+			assert(*out_pos == out_size);
+			ret = LZMA_BUF_ERROR;
+		}
+
+		// Restore the output position.
+		*out_pos = out_start;
+	}
+
+	return ret;
+}
diff --git a/src/liblzma/common/filter_common.c b/src/liblzma/common/filter_common.c
new file mode 100644
index 0000000..b157c62
--- /dev/null
+++ b/src/liblzma/common/filter_common.c
@@ -0,0 +1,337 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       filter_common.c
+/// \brief      Filter-specific stuff common for both encoder and decoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "filter_common.h"
+
+
+static const struct {
+	/// Filter ID
+	lzma_vli id;
+
+	/// Size of the filter-specific options structure
+	size_t options_size;
+
+	/// True if it is OK to use this filter as non-last filter in
+	/// the chain.
+	bool non_last_ok;
+
+	/// True if it is OK to use this filter as the last filter in
+	/// the chain.
+	bool last_ok;
+
+	/// True if the filter may change the size of the data (that is, the
+	/// amount of encoded output can be different than the amount of
+	/// uncompressed input).
+	bool changes_size;
+
+} features[] = {
+#if defined (HAVE_ENCODER_LZMA1) || defined(HAVE_DECODER_LZMA1)
+	{
+		.id = LZMA_FILTER_LZMA1,
+		.options_size = sizeof(lzma_options_lzma),
+		.non_last_ok = false,
+		.last_ok = true,
+		.changes_size = true,
+	},
+#endif
+#ifdef HAVE_DECODER_LZMA2
+	{
+		.id = LZMA_FILTER_LZMA2,
+		.options_size = sizeof(lzma_options_lzma),
+		.non_last_ok = false,
+		.last_ok = true,
+		.changes_size = true,
+	},
+#endif
+#ifdef HAVE_DECODER_X86
+	{
+		.id = LZMA_FILTER_X86,
+		.options_size = sizeof(lzma_options_bcj),
+		.non_last_ok = true,
+		.last_ok = false,
+		.changes_size = false,
+	},
+#endif
+#if defined(HAVE_ENCODER_POWERPC) || defined(HAVE_DECODER_POWERPC)
+	{
+		.id = LZMA_FILTER_POWERPC,
+		.options_size = sizeof(lzma_options_bcj),
+		.non_last_ok = true,
+		.last_ok = false,
+		.changes_size = false,
+	},
+#endif
+#ifdef HAVE_DECODER_IA64
+	{
+		.id = LZMA_FILTER_IA64,
+		.options_size = sizeof(lzma_options_bcj),
+		.non_last_ok = true,
+		.last_ok = false,
+		.changes_size = false,
+	},
+#endif
+#if defined(HAVE_ENCODER_ARM) || defined(HAVE_DECODER_ARM)
+	{
+		.id = LZMA_FILTER_ARM,
+		.options_size = sizeof(lzma_options_bcj),
+		.non_last_ok = true,
+		.last_ok = false,
+		.changes_size = false,
+	},
+#endif
+#if defined(HAVE_ENCODER_ARMTHUMB) || defined(HAVE_DECODER_ARMTHUMB)
+	{
+		.id = LZMA_FILTER_ARMTHUMB,
+		.options_size = sizeof(lzma_options_bcj),
+		.non_last_ok = true,
+		.last_ok = false,
+		.changes_size = false,
+	},
+#endif
+#if defined(HAVE_ENCODER_SPARC) || defined(HAVE_DECODER_SPARC)
+	{
+		.id = LZMA_FILTER_SPARC,
+		.options_size = sizeof(lzma_options_bcj),
+		.non_last_ok = true,
+		.last_ok = false,
+		.changes_size = false,
+	},
+#endif
+#if defined(HAVE_ENCODER_DELTA) || defined(HAVE_DECODER_DELTA)
+	{
+		.id = LZMA_FILTER_DELTA,
+		.options_size = sizeof(lzma_options_delta),
+		.non_last_ok = true,
+		.last_ok = false,
+		.changes_size = false,
+	},
+#endif
+	{
+		.id = LZMA_VLI_UNKNOWN
+	}
+};
+
+
+extern LZMA_API(lzma_ret)
+lzma_filters_copy(const lzma_filter *src, lzma_filter *dest,
+		lzma_allocator *allocator)
+{
+	if (src == NULL || dest == NULL)
+		return LZMA_PROG_ERROR;
+
+	lzma_ret ret;
+	size_t i;
+	for (i = 0; src[i].id != LZMA_VLI_UNKNOWN; ++i) {
+		// There must be a maximum of four filters plus
+		// the array terminator.
+		if (i == LZMA_FILTERS_MAX) {
+			ret = LZMA_OPTIONS_ERROR;
+			goto error;
+		}
+
+		dest[i].id = src[i].id;
+
+		if (src[i].options == NULL) {
+			dest[i].options = NULL;
+		} else {
+			// See if the filter is supported only when the
+			// options is not NULL. This might be convenient
+			// sometimes if the app is actually copying only
+			// a partial filter chain with a place holder ID.
+			//
+			// When options is not NULL, the Filter ID must be
+			// supported by us, because otherwise we don't know
+			// how big the options are.
+			size_t j;
+			for (j = 0; src[i].id != features[j].id; ++j) {
+				if (features[j].id == LZMA_VLI_UNKNOWN) {
+					ret = LZMA_OPTIONS_ERROR;
+					goto error;
+				}
+			}
+
+			// Allocate and copy the options.
+			dest[i].options = lzma_alloc(features[j].options_size,
+					allocator);
+			if (dest[i].options == NULL) {
+				ret = LZMA_MEM_ERROR;
+				goto error;
+			}
+
+			memcpy(dest[i].options, src[i].options,
+					features[j].options_size);
+		}
+	}
+
+	// Terminate the filter array.
+	assert(i <= LZMA_FILTERS_MAX + 1);
+	dest[i].id = LZMA_VLI_UNKNOWN;
+	dest[i].options = NULL;
+
+	return LZMA_OK;
+
+error:
+	// Free the options which we have already allocated.
+	while (i-- > 0) {
+		lzma_free(dest[i].options, allocator);
+		dest[i].options = NULL;
+	}
+
+	return ret;
+}
+
+
+static lzma_ret
+validate_chain(const lzma_filter *filters, size_t *count)
+{
+	// There must be at least one filter.
+	if (filters == NULL || filters[0].id == LZMA_VLI_UNKNOWN)
+		return LZMA_PROG_ERROR;
+
+	// Number of non-last filters that may change the size of the data
+	// significantly (that is, more than 1-2 % or so).
+	size_t changes_size_count = 0;
+
+	// True if it is OK to add a new filter after the current filter.
+	bool non_last_ok = true;
+
+	// True if the last filter in the given chain is actually usable as
+	// the last filter. Only filters that support embedding End of Payload
+	// Marker can be used as the last filter in the chain.
+	bool last_ok = false;
+
+	size_t i = 0;
+	do {
+		size_t j;
+		for (j = 0; filters[i].id != features[j].id; ++j)
+			if (features[j].id == LZMA_VLI_UNKNOWN)
+				return LZMA_OPTIONS_ERROR;
+
+		// If the previous filter in the chain cannot be a non-last
+		// filter, the chain is invalid.
+		if (!non_last_ok)
+			return LZMA_OPTIONS_ERROR;
+
+		non_last_ok = features[j].non_last_ok;
+		last_ok = features[j].last_ok;
+		changes_size_count += features[j].changes_size;
+
+	} while (filters[++i].id != LZMA_VLI_UNKNOWN);
+
+	// There must be 1-4 filters. The last filter must be usable as
+	// the last filter in the chain. A maximum of three filters are
+	// allowed to change the size of the data.
+	if (i > LZMA_FILTERS_MAX || !last_ok || changes_size_count > 3)
+		return LZMA_OPTIONS_ERROR;
+
+	*count = i;
+	return LZMA_OK;
+}
+
+
+extern lzma_ret
+lzma_raw_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter *options,
+		lzma_filter_find coder_find, bool is_encoder)
+{
+	// Do some basic validation and get the number of filters.
+	size_t count;
+	return_if_error(validate_chain(options, &count));
+
+	// Set the filter functions and copy the options pointer.
+	lzma_filter_info filters[LZMA_FILTERS_MAX + 1];
+	if (is_encoder) {
+		for (size_t i = 0; i < count; ++i) {
+			// The order of the filters is reversed in the
+			// encoder. It allows more efficient handling
+			// of the uncompressed data.
+			const size_t j = count - i - 1;
+
+			const lzma_filter_coder *const fc
+					= coder_find(options[i].id);
+			if (fc == NULL || fc->init == NULL)
+				return LZMA_OPTIONS_ERROR;
+
+			filters[j].id = options[i].id;
+			filters[j].init = fc->init;
+			filters[j].options = options[i].options;
+		}
+	} else {
+		for (size_t i = 0; i < count; ++i) {
+			const lzma_filter_coder *const fc
+					= coder_find(options[i].id);
+			if (fc == NULL || fc->init == NULL)
+				return LZMA_OPTIONS_ERROR;
+
+			filters[i].id = options[i].id;
+			filters[i].init = fc->init;
+			filters[i].options = options[i].options;
+		}
+	}
+
+	// Terminate the array.
+	filters[count].id = LZMA_VLI_UNKNOWN;
+	filters[count].init = NULL;
+
+	// Initialize the filters.
+	const lzma_ret ret = lzma_next_filter_init(next, allocator, filters);
+	if (ret != LZMA_OK)
+		lzma_next_end(next, allocator);
+
+	return ret;
+}
+
+
+extern uint64_t
+lzma_raw_coder_memusage(lzma_filter_find coder_find,
+		const lzma_filter *filters)
+{
+	// The chain has to have at least one filter.
+	{
+		size_t tmp;
+		if (validate_chain(filters, &tmp) != LZMA_OK)
+			return UINT64_MAX;
+	}
+
+	uint64_t total = 0;
+	size_t i = 0;
+
+	do {
+		const lzma_filter_coder *const fc
+				 = coder_find(filters[i].id);
+		if (fc == NULL)
+			return UINT64_MAX; // Unsupported Filter ID
+
+		if (fc->memusage == NULL) {
+			// This filter doesn't have a function to calculate
+			// the memory usage and validate the options. Such
+			// filters need only little memory, so we use 1 KiB
+			// as a good estimate. They also accept all possible
+			// options, so there's no need to worry about lack
+			// of validation.
+			total += 1024;
+		} else {
+			// Call the filter-specific memory usage calculation
+			// function.
+			const uint64_t usage
+					= fc->memusage(filters[i].options);
+			if (usage == UINT64_MAX)
+				return UINT64_MAX; // Invalid options
+
+			total += usage;
+		}
+	} while (filters[++i].id != LZMA_VLI_UNKNOWN);
+
+	// Add some fixed amount of extra. It's to compensate memory usage
+	// of Stream, Block etc. coders, malloc() overhead, stack etc.
+	return total + LZMA_MEMUSAGE_BASE;
+}
diff --git a/src/liblzma/common/filter_common.h b/src/liblzma/common/filter_common.h
new file mode 100644
index 0000000..cd61fc0
--- /dev/null
+++ b/src/liblzma/common/filter_common.h
@@ -0,0 +1,48 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       filter_common.c
+/// \brief      Filter-specific stuff common for both encoder and decoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_FILTER_COMMON_H
+#define LZMA_FILTER_COMMON_H
+
+#include "common.h"
+
+
+/// Both lzma_filter_encoder and lzma_filter_decoder begin with these members.
+typedef struct {
+	/// Filter ID
+	lzma_vli id;
+
+	/// Initializes the filter encoder and calls lzma_next_filter_init()
+	/// for filters + 1.
+	lzma_init_function init;
+
+	/// Calculates memory usage of the encoder. If the options are
+	/// invalid, UINT64_MAX is returned.
+	uint64_t (*memusage)(const void *options);
+
+} lzma_filter_coder;
+
+
+typedef const lzma_filter_coder *(*lzma_filter_find)(lzma_vli id);
+
+
+extern lzma_ret lzma_raw_coder_init(
+		lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter *filters,
+		lzma_filter_find coder_find, bool is_encoder);
+
+
+extern uint64_t lzma_raw_coder_memusage(lzma_filter_find coder_find,
+		const lzma_filter *filters);
+
+
+#endif
diff --git a/src/liblzma/common/filter_decoder.c b/src/liblzma/common/filter_decoder.c
new file mode 100644
index 0000000..1ebbe2a
--- /dev/null
+++ b/src/liblzma/common/filter_decoder.c
@@ -0,0 +1,183 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       filter_decoder.c
+/// \brief      Filter ID mapping to filter-specific functions
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "filter_decoder.h"
+#include "filter_common.h"
+#include "lzma_decoder.h"
+#include "lzma2_decoder.h"
+#include "simple_decoder.h"
+#include "delta_decoder.h"
+
+
+typedef struct {
+	/// Filter ID
+	lzma_vli id;
+
+	/// Initializes the filter encoder and calls lzma_next_filter_init()
+	/// for filters + 1.
+	lzma_init_function init;
+
+	/// Calculates memory usage of the encoder. If the options are
+	/// invalid, UINT64_MAX is returned.
+	uint64_t (*memusage)(const void *options);
+
+	/// Decodes Filter Properties.
+	///
+	/// \return     - LZMA_OK: Properties decoded successfully.
+	///             - LZMA_OPTIONS_ERROR: Unsupported properties
+	///             - LZMA_MEM_ERROR: Memory allocation failed.
+	lzma_ret (*props_decode)(void **options, lzma_allocator *allocator,
+			const uint8_t *props, size_t props_size);
+
+} lzma_filter_decoder;
+
+
+static const lzma_filter_decoder decoders[] = {
+#ifdef HAVE_DECODER_LZMA1
+	{
+		.id = LZMA_FILTER_LZMA1,
+		.init = &lzma_lzma_decoder_init,
+		.memusage = &lzma_lzma_decoder_memusage,
+		.props_decode = &lzma_lzma_props_decode,
+	},
+#endif
+#ifdef HAVE_DECODER_LZMA2
+	{
+		.id = LZMA_FILTER_LZMA2,
+		.init = &lzma_lzma2_decoder_init,
+		.memusage = &lzma_lzma2_decoder_memusage,
+		.props_decode = &lzma_lzma2_props_decode,
+	},
+#endif
+#ifdef HAVE_DECODER_X86
+	{
+		.id = LZMA_FILTER_X86,
+		.init = &lzma_simple_x86_decoder_init,
+		.memusage = NULL,
+		.props_decode = &lzma_simple_props_decode,
+	},
+#endif
+#ifdef HAVE_DECODER_POWERPC
+	{
+		.id = LZMA_FILTER_POWERPC,
+		.init = &lzma_simple_powerpc_decoder_init,
+		.memusage = NULL,
+		.props_decode = &lzma_simple_props_decode,
+	},
+#endif
+#ifdef HAVE_DECODER_IA64
+	{
+		.id = LZMA_FILTER_IA64,
+		.init = &lzma_simple_ia64_decoder_init,
+		.memusage = NULL,
+		.props_decode = &lzma_simple_props_decode,
+	},
+#endif
+#ifdef HAVE_DECODER_ARM
+	{
+		.id = LZMA_FILTER_ARM,
+		.init = &lzma_simple_arm_decoder_init,
+		.memusage = NULL,
+		.props_decode = &lzma_simple_props_decode,
+	},
+#endif
+#ifdef HAVE_DECODER_ARMTHUMB
+	{
+		.id = LZMA_FILTER_ARMTHUMB,
+		.init = &lzma_simple_armthumb_decoder_init,
+		.memusage = NULL,
+		.props_decode = &lzma_simple_props_decode,
+	},
+#endif
+#ifdef HAVE_DECODER_SPARC
+	{
+		.id = LZMA_FILTER_SPARC,
+		.init = &lzma_simple_sparc_decoder_init,
+		.memusage = NULL,
+		.props_decode = &lzma_simple_props_decode,
+	},
+#endif
+#ifdef HAVE_DECODER_DELTA
+	{
+		.id = LZMA_FILTER_DELTA,
+		.init = &lzma_delta_decoder_init,
+		.memusage = &lzma_delta_coder_memusage,
+		.props_decode = &lzma_delta_props_decode,
+	},
+#endif
+};
+
+
+static const lzma_filter_decoder *
+decoder_find(lzma_vli id)
+{
+	for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i)
+		if (decoders[i].id == id)
+			return decoders + i;
+
+	return NULL;
+}
+
+
+extern LZMA_API(lzma_bool)
+lzma_filter_decoder_is_supported(lzma_vli id)
+{
+	return decoder_find(id) != NULL;
+}
+
+
+extern lzma_ret
+lzma_raw_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter *options)
+{
+	return lzma_raw_coder_init(next, allocator,
+			options, (lzma_filter_find)(&decoder_find), false);
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_raw_decoder(lzma_stream *strm, const lzma_filter *options)
+{
+	lzma_next_strm_init(lzma_raw_decoder_init, strm, options);
+
+	strm->internal->supported_actions[LZMA_RUN] = true;
+	strm->internal->supported_actions[LZMA_FINISH] = true;
+
+	return LZMA_OK;
+}
+
+
+extern LZMA_API(uint64_t)
+lzma_raw_decoder_memusage(const lzma_filter *filters)
+{
+	return lzma_raw_coder_memusage(
+			(lzma_filter_find)(&decoder_find), filters);
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_properties_decode(lzma_filter *filter, lzma_allocator *allocator,
+		const uint8_t *props, size_t props_size)
+{
+	// Make it always NULL so that the caller can always safely free() it.
+	filter->options = NULL;
+
+	const lzma_filter_decoder *const fd = decoder_find(filter->id);
+	if (fd == NULL)
+		return LZMA_OPTIONS_ERROR;
+
+	if (fd->props_decode == NULL)
+		return props_size == 0 ? LZMA_OK : LZMA_OPTIONS_ERROR;
+
+	return fd->props_decode(
+			&filter->options, allocator, props, props_size);
+}
diff --git a/src/liblzma/common/filter_decoder.h b/src/liblzma/common/filter_decoder.h
new file mode 100644
index 0000000..d5c68bd
--- /dev/null
+++ b/src/liblzma/common/filter_decoder.h
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       filter_decoder.c
+/// \brief      Filter ID mapping to filter-specific functions
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_FILTER_DECODER_H
+#define LZMA_FILTER_DECODER_H
+
+#include "common.h"
+
+
+extern lzma_ret lzma_raw_decoder_init(
+		lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter *options);
+
+#endif
diff --git a/src/liblzma/common/filter_encoder.c b/src/liblzma/common/filter_encoder.c
new file mode 100644
index 0000000..436d2cc
--- /dev/null
+++ b/src/liblzma/common/filter_encoder.c
@@ -0,0 +1,286 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       filter_decoder.c
+/// \brief      Filter ID mapping to filter-specific functions
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "filter_encoder.h"
+#include "filter_common.h"
+#include "lzma_encoder.h"
+#include "lzma2_encoder.h"
+#include "simple_encoder.h"
+#include "delta_encoder.h"
+
+
+typedef struct {
+	/// Filter ID
+	lzma_vli id;
+
+	/// Initializes the filter encoder and calls lzma_next_filter_init()
+	/// for filters + 1.
+	lzma_init_function init;
+
+	/// Calculates memory usage of the encoder. If the options are
+	/// invalid, UINT64_MAX is returned.
+	uint64_t (*memusage)(const void *options);
+
+	/// Calculates the minimum sane size for Blocks (or other types of
+	/// chunks) to which the input data can be split to make
+	/// multithreaded encoding possible. If this is NULL, it is assumed
+	/// that the encoder is fast enough with single thread.
+	lzma_vli (*chunk_size)(const void *options);
+
+	/// Tells the size of the Filter Properties field. If options are
+	/// invalid, UINT32_MAX is returned. If this is NULL, props_size_fixed
+	/// is used.
+	lzma_ret (*props_size_get)(uint32_t *size, const void *options);
+	uint32_t props_size_fixed;
+
+	/// Encodes Filter Properties.
+	///
+	/// \return     - LZMA_OK: Properties encoded successfully.
+	///             - LZMA_OPTIONS_ERROR: Unsupported options
+	///             - LZMA_PROG_ERROR: Invalid options or not enough
+	///               output space
+	lzma_ret (*props_encode)(const void *options, uint8_t *out);
+
+} lzma_filter_encoder;
+
+
+static const lzma_filter_encoder encoders[] = {
+#ifdef HAVE_ENCODER_LZMA1
+	{
+		.id = LZMA_FILTER_LZMA1,
+		.init = &lzma_lzma_encoder_init,
+		.memusage = &lzma_lzma_encoder_memusage,
+		.chunk_size = NULL, // FIXME
+		.props_size_get = NULL,
+		.props_size_fixed = 5,
+		.props_encode = &lzma_lzma_props_encode,
+	},
+#endif
+#ifdef HAVE_ENCODER_LZMA2
+	{
+		.id = LZMA_FILTER_LZMA2,
+		.init = &lzma_lzma2_encoder_init,
+		.memusage = &lzma_lzma2_encoder_memusage,
+		.chunk_size = NULL, // FIXME
+		.props_size_get = NULL,
+		.props_size_fixed = 1,
+		.props_encode = &lzma_lzma2_props_encode,
+	},
+#endif
+#ifdef HAVE_ENCODER_X86
+	{
+		.id = LZMA_FILTER_X86,
+		.init = &lzma_simple_x86_encoder_init,
+		.memusage = NULL,
+		.chunk_size = NULL,
+		.props_size_get = &lzma_simple_props_size,
+		.props_encode = &lzma_simple_props_encode,
+	},
+#endif
+#ifdef HAVE_ENCODER_POWERPC
+	{
+		.id = LZMA_FILTER_POWERPC,
+		.init = &lzma_simple_powerpc_encoder_init,
+		.memusage = NULL,
+		.chunk_size = NULL,
+		.props_size_get = &lzma_simple_props_size,
+		.props_encode = &lzma_simple_props_encode,
+	},
+#endif
+#ifdef HAVE_ENCODER_IA64
+	{
+		.id = LZMA_FILTER_IA64,
+		.init = &lzma_simple_ia64_encoder_init,
+		.memusage = NULL,
+		.chunk_size = NULL,
+		.props_size_get = &lzma_simple_props_size,
+		.props_encode = &lzma_simple_props_encode,
+	},
+#endif
+#ifdef HAVE_ENCODER_ARM
+	{
+		.id = LZMA_FILTER_ARM,
+		.init = &lzma_simple_arm_encoder_init,
+		.memusage = NULL,
+		.chunk_size = NULL,
+		.props_size_get = &lzma_simple_props_size,
+		.props_encode = &lzma_simple_props_encode,
+	},
+#endif
+#ifdef HAVE_ENCODER_ARMTHUMB
+	{
+		.id = LZMA_FILTER_ARMTHUMB,
+		.init = &lzma_simple_armthumb_encoder_init,
+		.memusage = NULL,
+		.chunk_size = NULL,
+		.props_size_get = &lzma_simple_props_size,
+		.props_encode = &lzma_simple_props_encode,
+	},
+#endif
+#ifdef HAVE_ENCODER_SPARC
+	{
+		.id = LZMA_FILTER_SPARC,
+		.init = &lzma_simple_sparc_encoder_init,
+		.memusage = NULL,
+		.chunk_size = NULL,
+		.props_size_get = &lzma_simple_props_size,
+		.props_encode = &lzma_simple_props_encode,
+	},
+#endif
+#ifdef HAVE_ENCODER_DELTA
+	{
+		.id = LZMA_FILTER_DELTA,
+		.init = &lzma_delta_encoder_init,
+		.memusage = &lzma_delta_coder_memusage,
+		.chunk_size = NULL,
+		.props_size_get = NULL,
+		.props_size_fixed = 1,
+		.props_encode = &lzma_delta_props_encode,
+	},
+#endif
+};
+
+
+static const lzma_filter_encoder *
+encoder_find(lzma_vli id)
+{
+	for (size_t i = 0; i < ARRAY_SIZE(encoders); ++i)
+		if (encoders[i].id == id)
+			return encoders + i;
+
+	return NULL;
+}
+
+
+extern LZMA_API(lzma_bool)
+lzma_filter_encoder_is_supported(lzma_vli id)
+{
+	return encoder_find(id) != NULL;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_filters_update(lzma_stream *strm, const lzma_filter *filters)
+{
+	if (strm->internal->next.update == NULL)
+		return LZMA_PROG_ERROR;
+
+	// Validate the filter chain.
+	if (lzma_raw_encoder_memusage(filters) == UINT64_MAX)
+		return LZMA_OPTIONS_ERROR;
+
+	// The actual filter chain in the encoder is reversed. Some things
+	// still want the normal order chain, so we provide both.
+	size_t count = 1;
+	while (filters[count].id != LZMA_VLI_UNKNOWN)
+		++count;
+
+	lzma_filter reversed_filters[LZMA_FILTERS_MAX + 1];
+	for (size_t i = 0; i < count; ++i)
+		reversed_filters[count - i - 1] = filters[i];
+
+	reversed_filters[count].id = LZMA_VLI_UNKNOWN;
+
+	return strm->internal->next.update(strm->internal->next.coder,
+			strm->allocator, filters, reversed_filters);
+}
+
+
+extern lzma_ret
+lzma_raw_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter *options)
+{
+	return lzma_raw_coder_init(next, allocator,
+			options, (lzma_filter_find)(&encoder_find), true);
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_raw_encoder(lzma_stream *strm, const lzma_filter *options)
+{
+	lzma_next_strm_init(lzma_raw_coder_init, strm, options,
+			(lzma_filter_find)(&encoder_find), true);
+
+	strm->internal->supported_actions[LZMA_RUN] = true;
+	strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
+	strm->internal->supported_actions[LZMA_FINISH] = true;
+
+	return LZMA_OK;
+}
+
+
+extern LZMA_API(uint64_t)
+lzma_raw_encoder_memusage(const lzma_filter *filters)
+{
+	return lzma_raw_coder_memusage(
+			(lzma_filter_find)(&encoder_find), filters);
+}
+
+
+extern LZMA_API(lzma_vli)
+lzma_chunk_size(const lzma_filter *filters)
+{
+	lzma_vli max = 0;
+
+	for (size_t i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i) {
+		const lzma_filter_encoder *const fe
+				= encoder_find(filters[i].id);
+		if (fe->chunk_size != NULL) {
+			const lzma_vli size
+					= fe->chunk_size(filters[i].options);
+			if (size == LZMA_VLI_UNKNOWN)
+				return LZMA_VLI_UNKNOWN;
+
+			if (size > max)
+				max = size;
+		}
+	}
+
+	return max;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_properties_size(uint32_t *size, const lzma_filter *filter)
+{
+	const lzma_filter_encoder *const fe = encoder_find(filter->id);
+	if (fe == NULL) {
+		// Unknown filter - if the Filter ID is a proper VLI,
+		// return LZMA_OPTIONS_ERROR instead of LZMA_PROG_ERROR,
+		// because it's possible that we just don't have support
+		// compiled in for the requested filter.
+		return filter->id <= LZMA_VLI_MAX
+				? LZMA_OPTIONS_ERROR : LZMA_PROG_ERROR;
+	}
+
+	if (fe->props_size_get == NULL) {
+		// No props_size_get() function, use props_size_fixed.
+		*size = fe->props_size_fixed;
+		return LZMA_OK;
+	}
+
+	return fe->props_size_get(size, filter->options);
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_properties_encode(const lzma_filter *filter, uint8_t *props)
+{
+	const lzma_filter_encoder *const fe = encoder_find(filter->id);
+	if (fe == NULL)
+		return LZMA_PROG_ERROR;
+
+	if (fe->props_encode == NULL)
+		return LZMA_OK;
+
+	return fe->props_encode(filter->options, props);
+}
diff --git a/src/liblzma/common/filter_encoder.h b/src/liblzma/common/filter_encoder.h
new file mode 100644
index 0000000..a978932
--- /dev/null
+++ b/src/liblzma/common/filter_encoder.h
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       filter_encoder.c
+/// \brief      Filter ID mapping to filter-specific functions
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_FILTER_ENCODER_H
+#define LZMA_FILTER_ENCODER_H
+
+#include "common.h"
+
+
+// FIXME !!! Public API
+extern lzma_vli lzma_chunk_size(const lzma_filter *filters);
+
+
+extern lzma_ret lzma_raw_encoder_init(
+		lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter *filters);
+
+#endif
diff --git a/src/liblzma/common/filter_flags_decoder.c b/src/liblzma/common/filter_flags_decoder.c
new file mode 100644
index 0000000..caae10c
--- /dev/null
+++ b/src/liblzma/common/filter_flags_decoder.c
@@ -0,0 +1,46 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       filter_flags_decoder.c
+/// \brief      Decodes a Filter Flags field
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "filter_decoder.h"
+
+
+extern LZMA_API(lzma_ret)
+lzma_filter_flags_decode(
+		lzma_filter *filter, lzma_allocator *allocator,
+		const uint8_t *in, size_t *in_pos, size_t in_size)
+{
+	// Set the pointer to NULL so the caller can always safely free it.
+	filter->options = NULL;
+
+	// Filter ID
+	return_if_error(lzma_vli_decode(&filter->id, NULL,
+			in, in_pos, in_size));
+
+	if (filter->id >= LZMA_FILTER_RESERVED_START)
+		return LZMA_DATA_ERROR;
+
+	// Size of Properties
+	lzma_vli props_size;
+	return_if_error(lzma_vli_decode(&props_size, NULL,
+			in, in_pos, in_size));
+
+	// Filter Properties
+	if (in_size - *in_pos < props_size)
+		return LZMA_DATA_ERROR;
+
+	const lzma_ret ret = lzma_properties_decode(
+			filter, allocator, in + *in_pos, props_size);
+
+	*in_pos += props_size;
+
+	return ret;
+}
diff --git a/src/liblzma/common/filter_flags_encoder.c b/src/liblzma/common/filter_flags_encoder.c
new file mode 100644
index 0000000..d110566
--- /dev/null
+++ b/src/liblzma/common/filter_flags_encoder.c
@@ -0,0 +1,56 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       filter_flags_encoder.c
+/// \brief      Decodes a Filter Flags field
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "filter_encoder.h"
+
+
+extern LZMA_API(lzma_ret)
+lzma_filter_flags_size(uint32_t *size, const lzma_filter *filter)
+{
+	if (filter->id >= LZMA_FILTER_RESERVED_START)
+		return LZMA_PROG_ERROR;
+
+	return_if_error(lzma_properties_size(size, filter));
+
+	*size += lzma_vli_size(filter->id) + lzma_vli_size(*size);
+
+	return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_filter_flags_encode(const lzma_filter *filter,
+		uint8_t *out, size_t *out_pos, size_t out_size)
+{
+	// Filter ID
+	if (filter->id >= LZMA_FILTER_RESERVED_START)
+		return LZMA_PROG_ERROR;
+
+	return_if_error(lzma_vli_encode(filter->id, NULL,
+			out, out_pos, out_size));
+
+	// Size of Properties
+	uint32_t props_size;
+	return_if_error(lzma_properties_size(&props_size, filter));
+	return_if_error(lzma_vli_encode(props_size, NULL,
+			out, out_pos, out_size));
+
+	// Filter Properties
+	if (out_size - *out_pos < props_size)
+		return LZMA_PROG_ERROR;
+
+	return_if_error(lzma_properties_encode(filter, out + *out_pos));
+
+	*out_pos += props_size;
+
+	return LZMA_OK;
+}
diff --git a/src/liblzma/common/hardware_physmem.c b/src/liblzma/common/hardware_physmem.c
new file mode 100644
index 0000000..7405b65
--- /dev/null
+++ b/src/liblzma/common/hardware_physmem.c
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       hardware_physmem.c
+/// \brief      Get the total amount of physical memory (RAM)
+//
+//  Author:     Jonathan Nieder
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+
+#include "tuklib_physmem.h"
+
+
+extern LZMA_API(uint64_t)
+lzma_physmem(void)
+{
+	// It is simpler to make lzma_physmem() a wrapper for
+	// tuklib_physmem() than to hack appropriate symbol visiblity
+	// support for the tuklib modules.
+	return tuklib_physmem();
+}
diff --git a/src/liblzma/common/index.c b/src/liblzma/common/index.c
new file mode 100644
index 0000000..3941e28
--- /dev/null
+++ b/src/liblzma/common/index.c
@@ -0,0 +1,1241 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       index.c
+/// \brief      Handling of .xz Indexes and some other Stream information
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "index.h"
+#include "stream_flags_common.h"
+
+
+/// \brief      How many Records to allocate at once
+///
+/// This should be big enough to avoid making lots of tiny allocations
+/// but small enough to avoid too much unused memory at once.
+#define INDEX_GROUP_SIZE 500
+
+
+/// \brief      How many Records can be allocated at once at maximum
+#define PREALLOC_MAX ((SIZE_MAX - sizeof(index_group)) / sizeof(index_record))
+
+
+/// \brief      Base structure for index_stream and index_group structures
+typedef struct index_tree_node_s index_tree_node;
+struct index_tree_node_s {
+	/// Uncompressed start offset of this Stream (relative to the
+	/// beginning of the file) or Block (relative to the beginning
+	/// of the Stream)
+	lzma_vli uncompressed_base;
+
+	/// Compressed start offset of this Stream or Block
+	lzma_vli compressed_base;
+
+	index_tree_node *parent;
+	index_tree_node *left;
+	index_tree_node *right;
+};
+
+
+/// \brief      AVL tree to hold index_stream or index_group structures
+typedef struct {
+	/// Root node
+	index_tree_node *root;
+
+	/// Leftmost node. Since the tree will be filled sequentially,
+	/// this won't change after the first node has been added to
+	/// the tree.
+	index_tree_node *leftmost;
+
+	/// The rightmost node in the tree. Since the tree is filled
+	/// sequentially, this is always the node where to add the new data.
+	index_tree_node *rightmost;
+
+	/// Number of nodes in the tree
+	uint32_t count;
+
+} index_tree;
+
+
+typedef struct {
+	lzma_vli uncompressed_sum;
+	lzma_vli unpadded_sum;
+} index_record;
+
+
+typedef struct {
+	/// Every Record group is part of index_stream.groups tree.
+	index_tree_node node;
+
+	/// Number of Blocks in this Stream before this group.
+	lzma_vli number_base;
+
+	/// Number of Records that can be put in records[].
+	size_t allocated;
+
+	/// Index of the last Record in use.
+	size_t last;
+
+	/// The sizes in this array are stored as cumulative sums relative
+	/// to the beginning of the Stream. This makes it possible to
+	/// use binary search in lzma_index_locate().
+	///
+	/// Note that the cumulative summing is done specially for
+	/// unpadded_sum: The previous value is rounded up to the next
+	/// multiple of four before adding the Unpadded Size of the new
+	/// Block. The total encoded size of the Blocks in the Stream
+	/// is records[last].unpadded_sum in the last Record group of
+	/// the Stream.
+	///
+	/// For example, if the Unpadded Sizes are 39, 57, and 81, the
+	/// stored values are 39, 97 (40 + 57), and 181 (100 + 181).
+	/// The total encoded size of these Blocks is 184.
+	///
+	/// This is a flexible array, because it makes easy to optimize
+	/// memory usage in case someone concatenates many Streams that
+	/// have only one or few Blocks.
+	index_record records[];
+
+} index_group;
+
+
+typedef struct {
+	/// Every index_stream is a node in the tree of Sreams.
+	index_tree_node node;
+
+	/// Number of this Stream (first one is 1)
+	uint32_t number;
+
+	/// Total number of Blocks before this Stream
+	lzma_vli block_number_base;
+
+	/// Record groups of this Stream are stored in a tree.
+	/// It's a T-tree with AVL-tree balancing. There are
+	/// INDEX_GROUP_SIZE Records per node by default.
+	/// This keeps the number of memory allocations reasonable
+	/// and finding a Record is fast.
+	index_tree groups;
+
+	/// Number of Records in this Stream
+	lzma_vli record_count;
+
+	/// Size of the List of Records field in this Stream. This is used
+	/// together with record_count to calculate the size of the Index
+	/// field and thus the total size of the Stream.
+	lzma_vli index_list_size;
+
+	/// Stream Flags of this Stream. This is meaningful only if
+	/// the Stream Flags have been told us with lzma_index_stream_flags().
+	/// Initially stream_flags.version is set to UINT32_MAX to indicate
+	/// that the Stream Flags are unknown.
+	lzma_stream_flags stream_flags;
+
+	/// Amount of Stream Padding after this Stream. This defaults to
+	/// zero and can be set with lzma_index_stream_padding().
+	lzma_vli stream_padding;
+
+} index_stream;
+
+
+struct lzma_index_s {
+	/// AVL-tree containing the Stream(s). Often there is just one
+	/// Stream, but using a tree keeps lookups fast even when there
+	/// are many concatenated Streams.
+	index_tree streams;
+
+	/// Uncompressed size of all the Blocks in the Stream(s)
+	lzma_vli uncompressed_size;
+
+	/// Total size of all the Blocks in the Stream(s)
+	lzma_vli total_size;
+
+	/// Total number of Records in all Streams in this lzma_index
+	lzma_vli record_count;
+
+	/// Size of the List of Records field if all the Streams in this
+	/// lzma_index were packed into a single Stream (makes it simpler to
+	/// take many .xz files and combine them into a single Stream).
+	///
+	/// This value together with record_count is needed to calculate
+	/// Backward Size that is stored into Stream Footer.
+	lzma_vli index_list_size;
+
+	/// How many Records to allocate at once in lzma_index_append().
+	/// This defaults to INDEX_GROUP_SIZE but can be overriden with
+	/// lzma_index_prealloc().
+	size_t prealloc;
+
+	/// Bitmask indicating what integrity check types have been used
+	/// as set by lzma_index_stream_flags(). The bit of the last Stream
+	/// is not included here, since it is possible to change it by
+	/// calling lzma_index_stream_flags() again.
+	uint32_t checks;
+};
+
+
+static void
+index_tree_init(index_tree *tree)
+{
+	tree->root = NULL;
+	tree->leftmost = NULL;
+	tree->rightmost = NULL;
+	tree->count = 0;
+	return;
+}
+
+
+/// Helper for index_tree_end()
+static void
+index_tree_node_end(index_tree_node *node, lzma_allocator *allocator,
+		void (*free_func)(void *node, lzma_allocator *allocator))
+{
+	// The tree won't ever be very huge, so recursion should be fine.
+	// 20 levels in the tree is likely quite a lot already in practice.
+	if (node->left != NULL)
+		index_tree_node_end(node->left, allocator, free_func);
+
+	if (node->right != NULL)
+		index_tree_node_end(node->right, allocator, free_func);
+
+	if (free_func != NULL)
+		free_func(node, allocator);
+
+	lzma_free(node, allocator);
+	return;
+}
+
+
+/// Free the meory allocated for a tree. If free_func is not NULL,
+/// it is called on each node before freeing the node. This is used
+/// to free the Record groups from each index_stream before freeing
+/// the index_stream itself.
+static void
+index_tree_end(index_tree *tree, lzma_allocator *allocator,
+		void (*free_func)(void *node, lzma_allocator *allocator))
+{
+	if (tree->root != NULL)
+		index_tree_node_end(tree->root, allocator, free_func);
+
+	return;
+}
+
+
+/// Add a new node to the tree. node->uncompressed_base and
+/// node->compressed_base must have been set by the caller already.
+static void
+index_tree_append(index_tree *tree, index_tree_node *node)
+{
+	node->parent = tree->rightmost;
+	node->left = NULL;
+	node->right = NULL;
+
+	++tree->count;
+
+	// Handle the special case of adding the first node.
+	if (tree->root == NULL) {
+		tree->root = node;
+		tree->leftmost = node;
+		tree->rightmost = node;
+		return;
+	}
+
+	// The tree is always filled sequentially.
+	assert(tree->rightmost->uncompressed_base <= node->uncompressed_base);
+	assert(tree->rightmost->compressed_base < node->compressed_base);
+
+	// Add the new node after the rightmost node. It's the correct
+	// place due to the reason above.
+	tree->rightmost->right = node;
+	tree->rightmost = node;
+
+	// Balance the AVL-tree if needed. We don't need to keep the balance
+	// factors in nodes, because we always fill the tree sequentially,
+	// and thus know the state of the tree just by looking at the node
+	// count. From the node count we can calculate how many steps to go
+	// up in the tree to find the rotation root.
+	uint32_t up = tree->count ^ (UINT32_C(1) << bsr32(tree->count));
+	if (up != 0) {
+		// Locate the root node for the rotation.
+		up = ctz32(tree->count) + 2;
+		do {
+			node = node->parent;
+		} while (--up > 0);
+
+		// Rotate left using node as the rotation root.
+		index_tree_node *pivot = node->right;
+
+		if (node->parent == NULL) {
+			tree->root = pivot;
+		} else {
+			assert(node->parent->right == node);
+			node->parent->right = pivot;
+		}
+
+		pivot->parent = node->parent;
+
+		node->right = pivot->left;
+		if (node->right != NULL)
+			node->right->parent = node;
+
+		pivot->left = node;
+		node->parent = pivot;
+	}
+
+	return;
+}
+
+
+/// Get the next node in the tree. Return NULL if there are no more nodes.
+static void *
+index_tree_next(const index_tree_node *node)
+{
+	if (node->right != NULL) {
+		node = node->right;
+		while (node->left != NULL)
+			node = node->left;
+
+		return (void *)(node);
+	}
+
+	while (node->parent != NULL && node->parent->right == node)
+		node = node->parent;
+
+	return (void *)(node->parent);
+}
+
+
+/// Locate a node that contains the given uncompressed offset. It is
+/// caller's job to check that target is not bigger than the uncompressed
+/// size of the tree (the last node would be returned in that case still).
+static void *
+index_tree_locate(const index_tree *tree, lzma_vli target)
+{
+	const index_tree_node *result = NULL;
+	const index_tree_node *node = tree->root;
+
+	assert(tree->leftmost == NULL
+			|| tree->leftmost->uncompressed_base == 0);
+
+	// Consecutive nodes may have the same uncompressed_base.
+	// We must pick the rightmost one.
+	while (node != NULL) {
+		if (node->uncompressed_base > target) {
+			node = node->left;
+		} else {
+			result = node;
+			node = node->right;
+		}
+	}
+
+	return (void *)(result);
+}
+
+
+/// Allocate and initialize a new Stream using the given base offsets.
+static index_stream *
+index_stream_init(lzma_vli compressed_base, lzma_vli uncompressed_base,
+		lzma_vli stream_number, lzma_vli block_number_base,
+		lzma_allocator *allocator)
+{
+	index_stream *s = lzma_alloc(sizeof(index_stream), allocator);
+	if (s == NULL)
+		return NULL;
+
+	s->node.uncompressed_base = uncompressed_base;
+	s->node.compressed_base = compressed_base;
+	s->node.parent = NULL;
+	s->node.left = NULL;
+	s->node.right = NULL;
+
+	s->number = stream_number;
+	s->block_number_base = block_number_base;
+
+	index_tree_init(&s->groups);
+
+	s->record_count = 0;
+	s->index_list_size = 0;
+	s->stream_flags.version = UINT32_MAX;
+	s->stream_padding = 0;
+
+	return s;
+}
+
+
+/// Free the memory allocated for a Stream and its Record groups.
+static void
+index_stream_end(void *node, lzma_allocator *allocator)
+{
+	index_stream *s = node;
+	index_tree_end(&s->groups, allocator, NULL);
+	return;
+}
+
+
+static lzma_index *
+index_init_plain(lzma_allocator *allocator)
+{
+	lzma_index *i = lzma_alloc(sizeof(lzma_index), allocator);
+	if (i != NULL) {
+		index_tree_init(&i->streams);
+		i->uncompressed_size = 0;
+		i->total_size = 0;
+		i->record_count = 0;
+		i->index_list_size = 0;
+		i->prealloc = INDEX_GROUP_SIZE;
+		i->checks = 0;
+	}
+
+	return i;
+}
+
+
+extern LZMA_API(lzma_index *)
+lzma_index_init(lzma_allocator *allocator)
+{
+	lzma_index *i = index_init_plain(allocator);
+	index_stream *s = index_stream_init(0, 0, 1, 0, allocator);
+	if (i == NULL || s == NULL) {
+		index_stream_end(s, allocator);
+		lzma_free(i, allocator);
+	}
+
+	index_tree_append(&i->streams, &s->node);
+
+	return i;
+}
+
+
+extern LZMA_API(void)
+lzma_index_end(lzma_index *i, lzma_allocator *allocator)
+{
+	// NOTE: If you modify this function, check also the bottom
+	// of lzma_index_cat().
+	if (i != NULL) {
+		index_tree_end(&i->streams, allocator, &index_stream_end);
+		lzma_free(i, allocator);
+	}
+
+	return;
+}
+
+
+extern void
+lzma_index_prealloc(lzma_index *i, lzma_vli records)
+{
+	if (records > PREALLOC_MAX)
+		records = PREALLOC_MAX;
+
+	i->prealloc = (size_t)(records);
+	return;
+}
+
+
+extern LZMA_API(uint64_t)
+lzma_index_memusage(lzma_vli streams, lzma_vli blocks)
+{
+	// This calculates an upper bound that is only a little bit
+	// bigger than the exact maximum memory usage with the given
+	// parameters.
+
+	// Typical malloc() overhead is 2 * sizeof(void *) but we take
+	// a little bit extra just in case. Using LZMA_MEMUSAGE_BASE
+	// instead would give too inaccurate estimate.
+	const size_t alloc_overhead = 4 * sizeof(void *);
+
+	// Amount of memory needed for each Stream base structures.
+	// We assume that every Stream has at least one Block and
+	// thus at least one group.
+	const size_t stream_base = sizeof(index_stream)
+			+ sizeof(index_group) + 2 * alloc_overhead;
+
+	// Amount of memory needed per group.
+	const size_t group_base = sizeof(index_group)
+			+ INDEX_GROUP_SIZE * sizeof(index_record)
+			+ alloc_overhead;
+
+	// Number of groups. There may actually be more, but that overhead
+	// has been taken into account in stream_base already.
+	const lzma_vli groups
+			= (blocks + INDEX_GROUP_SIZE - 1) / INDEX_GROUP_SIZE;
+
+	// Memory used by index_stream and index_group structures.
+	const uint64_t streams_mem = streams * stream_base;
+	const uint64_t groups_mem = groups * group_base;
+
+	// Memory used by the base structure.
+	const uint64_t index_base = sizeof(lzma_index) + alloc_overhead;
+
+	// Validate the arguments and catch integer overflows.
+	// Maximum number of Streams is "only" UINT32_MAX, because
+	// that limit is used by the tree containing the Streams.
+	const uint64_t limit = UINT64_MAX - index_base;
+	if (streams == 0 || streams > UINT32_MAX || blocks > LZMA_VLI_MAX
+			|| streams > limit / stream_base
+			|| groups > limit / group_base
+			|| limit - streams_mem < groups_mem)
+		return UINT64_MAX;
+
+	return index_base + streams_mem + groups_mem;
+}
+
+
+extern LZMA_API(uint64_t)
+lzma_index_memused(const lzma_index *i)
+{
+	return lzma_index_memusage(i->streams.count, i->record_count);
+}
+
+
+extern LZMA_API(lzma_vli)
+lzma_index_block_count(const lzma_index *i)
+{
+	return i->record_count;
+}
+
+
+extern LZMA_API(lzma_vli)
+lzma_index_stream_count(const lzma_index *i)
+{
+	return i->streams.count;
+}
+
+
+extern LZMA_API(lzma_vli)
+lzma_index_size(const lzma_index *i)
+{
+	return index_size(i->record_count, i->index_list_size);
+}
+
+
+extern LZMA_API(lzma_vli)
+lzma_index_total_size(const lzma_index *i)
+{
+	return i->total_size;
+}
+
+
+extern LZMA_API(lzma_vli)
+lzma_index_stream_size(const lzma_index *i)
+{
+	// Stream Header + Blocks + Index + Stream Footer
+	return LZMA_STREAM_HEADER_SIZE + i->total_size
+			+ index_size(i->record_count, i->index_list_size)
+			+ LZMA_STREAM_HEADER_SIZE;
+}
+
+
+static lzma_vli
+index_file_size(lzma_vli compressed_base, lzma_vli unpadded_sum,
+		lzma_vli record_count, lzma_vli index_list_size,
+		lzma_vli stream_padding)
+{
+	// Earlier Streams and Stream Paddings + Stream Header
+	// + Blocks + Index + Stream Footer + Stream Padding
+	//
+	// This might go over LZMA_VLI_MAX due to too big unpadded_sum
+	// when this function is used in lzma_index_append().
+	lzma_vli file_size = compressed_base + 2 * LZMA_STREAM_HEADER_SIZE
+			+ stream_padding + vli_ceil4(unpadded_sum);
+	if (file_size > LZMA_VLI_MAX)
+		return LZMA_VLI_UNKNOWN;
+
+	// The same applies here.
+	file_size += index_size(record_count, index_list_size);
+	if (file_size > LZMA_VLI_MAX)
+		return LZMA_VLI_UNKNOWN;
+
+	return file_size;
+}
+
+
+extern LZMA_API(lzma_vli)
+lzma_index_file_size(const lzma_index *i)
+{
+	const index_stream *s = (const index_stream *)(i->streams.rightmost);
+	const index_group *g = (const index_group *)(s->groups.rightmost);
+	return index_file_size(s->node.compressed_base,
+			g == NULL ? 0 : g->records[g->last].unpadded_sum,
+			s->record_count, s->index_list_size,
+			s->stream_padding);
+}
+
+
+extern LZMA_API(lzma_vli)
+lzma_index_uncompressed_size(const lzma_index *i)
+{
+	return i->uncompressed_size;
+}
+
+
+extern LZMA_API(uint32_t)
+lzma_index_checks(const lzma_index *i)
+{
+	uint32_t checks = i->checks;
+
+	// Get the type of the Check of the last Stream too.
+	const index_stream *s = (const index_stream *)(i->streams.rightmost);
+	if (s->stream_flags.version != UINT32_MAX)
+		checks |= UINT32_C(1) << s->stream_flags.check;
+
+	return checks;
+}
+
+
+extern uint32_t
+lzma_index_padding_size(const lzma_index *i)
+{
+	return (LZMA_VLI_C(4) - index_size_unpadded(
+			i->record_count, i->index_list_size)) & 3;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_index_stream_flags(lzma_index *i, const lzma_stream_flags *stream_flags)
+{
+	if (i == NULL || stream_flags == NULL)
+		return LZMA_PROG_ERROR;
+
+	// Validate the Stream Flags.
+	return_if_error(lzma_stream_flags_compare(
+			stream_flags, stream_flags));
+
+	index_stream *s = (index_stream *)(i->streams.rightmost);
+	s->stream_flags = *stream_flags;
+
+	return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_index_stream_padding(lzma_index *i, lzma_vli stream_padding)
+{
+	if (i == NULL || stream_padding > LZMA_VLI_MAX
+			|| (stream_padding & 3) != 0)
+		return LZMA_PROG_ERROR;
+
+	index_stream *s = (index_stream *)(i->streams.rightmost);
+
+	// Check that the new value won't make the file grow too big.
+	const lzma_vli old_stream_padding = s->stream_padding;
+	s->stream_padding = 0;
+	if (lzma_index_file_size(i) + stream_padding > LZMA_VLI_MAX) {
+		s->stream_padding = old_stream_padding;
+		return LZMA_DATA_ERROR;
+	}
+
+	s->stream_padding = stream_padding;
+	return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_index_append(lzma_index *i, lzma_allocator *allocator,
+		lzma_vli unpadded_size, lzma_vli uncompressed_size)
+{
+	// Validate.
+	if (i == NULL || unpadded_size < UNPADDED_SIZE_MIN
+			|| unpadded_size > UNPADDED_SIZE_MAX
+			|| uncompressed_size > LZMA_VLI_MAX)
+		return LZMA_PROG_ERROR;
+
+	index_stream *s = (index_stream *)(i->streams.rightmost);
+	index_group *g = (index_group *)(s->groups.rightmost);
+
+	const lzma_vli compressed_base = g == NULL ? 0
+			: vli_ceil4(g->records[g->last].unpadded_sum);
+	const lzma_vli uncompressed_base = g == NULL ? 0
+			: g->records[g->last].uncompressed_sum;
+	const uint32_t index_list_size_add = lzma_vli_size(unpadded_size)
+			+ lzma_vli_size(uncompressed_size);
+
+	// Check that the file size will stay within limits.
+	if (index_file_size(s->node.compressed_base,
+			compressed_base + unpadded_size, s->record_count + 1,
+			s->index_list_size + index_list_size_add,
+			s->stream_padding) == LZMA_VLI_UNKNOWN)
+		return LZMA_DATA_ERROR;
+
+	// The size of the Index field must not exceed the maximum value
+	// that can be stored in the Backward Size field.
+	if (index_size(i->record_count + 1,
+			i->index_list_size + index_list_size_add)
+			> LZMA_BACKWARD_SIZE_MAX)
+		return LZMA_DATA_ERROR;
+
+	if (g != NULL && g->last + 1 < g->allocated) {
+		// There is space in the last group at least for one Record.
+		++g->last;
+	} else {
+		// We need to allocate a new group.
+		g = lzma_alloc(sizeof(index_group)
+				+ i->prealloc * sizeof(index_record),
+				allocator);
+		if (g == NULL)
+			return LZMA_MEM_ERROR;
+
+		g->last = 0;
+		g->allocated = i->prealloc;
+
+		// Reset prealloc so that if the application happens to
+		// add new Records, the allocation size will be sane.
+		i->prealloc = INDEX_GROUP_SIZE;
+
+		// Set the start offsets of this group.
+		g->node.uncompressed_base = uncompressed_base;
+		g->node.compressed_base = compressed_base;
+		g->number_base = s->record_count + 1;
+
+		// Add the new group to the Stream.
+		index_tree_append(&s->groups, &g->node);
+	}
+
+	// Add the new Record to the group.
+	g->records[g->last].uncompressed_sum
+			= uncompressed_base + uncompressed_size;
+	g->records[g->last].unpadded_sum
+			= compressed_base + unpadded_size;
+
+	// Update the totals.
+	++s->record_count;
+	s->index_list_size += index_list_size_add;
+
+	i->total_size += vli_ceil4(unpadded_size);
+	i->uncompressed_size += uncompressed_size;
+	++i->record_count;
+	i->index_list_size += index_list_size_add;
+
+	return LZMA_OK;
+}
+
+
+/// Structure to pass info to index_cat_helper()
+typedef struct {
+	/// Uncompressed size of the destination
+	lzma_vli uncompressed_size;
+
+	/// Compressed file size of the destination
+	lzma_vli file_size;
+
+	/// Same as above but for Block numbers
+	lzma_vli block_number_add;
+
+	/// Number of Streams that were in the destination index before we
+	/// started appending new Streams from the source index. This is
+	/// used to fix the Stream numbering.
+	uint32_t stream_number_add;
+
+	/// Destination index' Stream tree
+	index_tree *streams;
+
+} index_cat_info;
+
+
+/// Add the Stream nodes from the source index to dest using recursion.
+/// Simplest iterative traversal of the source tree wouldn't work, because
+/// we update the pointers in nodes when moving them to the destination tree.
+static void
+index_cat_helper(const index_cat_info *info, index_stream *this)
+{
+	index_stream *left = (index_stream *)(this->node.left);
+	index_stream *right = (index_stream *)(this->node.right);
+
+	if (left != NULL)
+		index_cat_helper(info, left);
+
+	this->node.uncompressed_base += info->uncompressed_size;
+	this->node.compressed_base += info->file_size;
+	this->number += info->stream_number_add;
+	this->block_number_base += info->block_number_add;
+	index_tree_append(info->streams, &this->node);
+
+	if (right != NULL)
+		index_cat_helper(info, right);
+
+	return;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_index_cat(lzma_index *restrict dest, lzma_index *restrict src,
+		lzma_allocator *allocator)
+{
+	const lzma_vli dest_file_size = lzma_index_file_size(dest);
+
+	// Check that we don't exceed the file size limits.
+	if (dest_file_size + lzma_index_file_size(src) > LZMA_VLI_MAX
+			|| dest->uncompressed_size + src->uncompressed_size
+				> LZMA_VLI_MAX)
+		return LZMA_DATA_ERROR;
+
+	// Check that the encoded size of the combined lzma_indexes stays
+	// within limits. In theory, this should be done only if we know
+	// that the user plans to actually combine the Streams and thus
+	// construct a single Index (probably rare). However, exceeding
+	// this limit is quite theoretical, so we do this check always
+	// to simplify things elsewhere.
+	{
+		const lzma_vli dest_size = index_size_unpadded(
+				dest->record_count, dest->index_list_size);
+		const lzma_vli src_size = index_size_unpadded(
+				src->record_count, src->index_list_size);
+		if (vli_ceil4(dest_size + src_size) > LZMA_BACKWARD_SIZE_MAX)
+			return LZMA_DATA_ERROR;
+	}
+
+	// Optimize the last group to minimize memory usage. Allocation has
+	// to be done before modifying dest or src.
+	{
+		index_stream *s = (index_stream *)(dest->streams.rightmost);
+		index_group *g = (index_group *)(s->groups.rightmost);
+		if (g != NULL && g->last + 1 < g->allocated) {
+			assert(g->node.left == NULL);
+			assert(g->node.right == NULL);
+
+			index_group *newg = lzma_alloc(sizeof(index_group)
+					+ (g->last + 1)
+					* sizeof(index_record),
+					allocator);
+			if (newg == NULL)
+				return LZMA_MEM_ERROR;
+
+			newg->node = g->node;
+			newg->allocated = g->last + 1;
+			newg->last = g->last;
+			newg->number_base = g->number_base;
+
+			memcpy(newg->records, g->records, newg->allocated
+					* sizeof(index_record));
+
+			if (g->node.parent != NULL) {
+				assert(g->node.parent->right == &g->node);
+				g->node.parent->right = &newg->node;
+			}
+
+			if (s->groups.leftmost == &g->node) {
+				assert(s->groups.root == &g->node);
+				s->groups.leftmost = &newg->node;
+				s->groups.root = &newg->node;
+			}
+
+			if (s->groups.rightmost == &g->node)
+				s->groups.rightmost = &newg->node;
+
+			lzma_free(g, allocator);
+		}
+	}
+
+	// Add all the Streams from src to dest. Update the base offsets
+	// of each Stream from src.
+	const index_cat_info info = {
+		.uncompressed_size = dest->uncompressed_size,
+		.file_size = dest_file_size,
+		.stream_number_add = dest->streams.count,
+		.block_number_add = dest->record_count,
+		.streams = &dest->streams,
+	};
+	index_cat_helper(&info, (index_stream *)(src->streams.root));
+
+	// Update info about all the combined Streams.
+	dest->uncompressed_size += src->uncompressed_size;
+	dest->total_size += src->total_size;
+	dest->record_count += src->record_count;
+	dest->index_list_size += src->index_list_size;
+	dest->checks = lzma_index_checks(dest) | src->checks;
+
+	// There's nothing else left in src than the base structure.
+	lzma_free(src, allocator);
+
+	return LZMA_OK;
+}
+
+
+/// Duplicate an index_stream.
+static index_stream *
+index_dup_stream(const index_stream *src, lzma_allocator *allocator)
+{
+	// Catch a somewhat theoretical integer overflow.
+	if (src->record_count > PREALLOC_MAX)
+		return NULL;
+
+	// Allocate and initialize a new Stream.
+	index_stream *dest = index_stream_init(src->node.compressed_base,
+			src->node.uncompressed_base, src->number,
+			src->block_number_base, allocator);
+
+	// Return immediately if allocation failed or if there are
+	// no groups to duplicate.
+	if (dest == NULL || src->groups.leftmost == NULL)
+		return dest;
+
+	// Copy the overall information.
+	dest->record_count = src->record_count;
+	dest->index_list_size = src->index_list_size;
+	dest->stream_flags = src->stream_flags;
+	dest->stream_padding = src->stream_padding;
+
+	// Allocate memory for the Records. We put all the Records into
+	// a single group. It's simplest and also tends to make
+	// lzma_index_locate() a little bit faster with very big Indexes.
+	index_group *destg = lzma_alloc(sizeof(index_group)
+			+ src->record_count * sizeof(index_record),
+			allocator);
+	if (destg == NULL) {
+		index_stream_end(dest, allocator);
+		return NULL;
+	}
+
+	// Initialize destg.
+	destg->node.uncompressed_base = 0;
+	destg->node.compressed_base = 0;
+	destg->number_base = 1;
+	destg->allocated = src->record_count;
+	destg->last = src->record_count - 1;
+
+	// Go through all the groups in src and copy the Records into destg.
+	const index_group *srcg = (const index_group *)(src->groups.leftmost);
+	size_t i = 0;
+	do {
+		memcpy(destg->records + i, srcg->records,
+				(srcg->last + 1) * sizeof(index_record));
+		i += srcg->last + 1;
+		srcg = index_tree_next(&srcg->node);
+	} while (srcg != NULL);
+
+	assert(i == destg->allocated);
+
+	// Add the group to the new Stream.
+	index_tree_append(&dest->groups, &destg->node);
+
+	return dest;
+}
+
+
+extern LZMA_API(lzma_index *)
+lzma_index_dup(const lzma_index *src, lzma_allocator *allocator)
+{
+	// Allocate the base structure (no initial Stream).
+	lzma_index *dest = index_init_plain(allocator);
+	if (dest == NULL)
+		return NULL;
+
+	// Copy the totals.
+	dest->uncompressed_size = src->uncompressed_size;
+	dest->total_size = src->total_size;
+	dest->record_count = src->record_count;
+	dest->index_list_size = src->index_list_size;
+
+	// Copy the Streams and the groups in them.
+	const index_stream *srcstream
+			= (const index_stream *)(src->streams.leftmost);
+	do {
+		index_stream *deststream = index_dup_stream(
+				srcstream, allocator);
+		if (deststream == NULL) {
+			lzma_index_end(dest, allocator);
+			return NULL;
+		}
+
+		index_tree_append(&dest->streams, &deststream->node);
+
+		srcstream = index_tree_next(&srcstream->node);
+	} while (srcstream != NULL);
+
+	return dest;
+}
+
+
+/// Indexing for lzma_index_iter.internal[]
+enum {
+	ITER_INDEX,
+	ITER_STREAM,
+	ITER_GROUP,
+	ITER_RECORD,
+	ITER_METHOD,
+};
+
+
+/// Values for lzma_index_iter.internal[ITER_METHOD].s
+enum {
+	ITER_METHOD_NORMAL,
+	ITER_METHOD_NEXT,
+	ITER_METHOD_LEFTMOST,
+};
+
+
+static void
+iter_set_info(lzma_index_iter *iter)
+{
+	const lzma_index *i = iter->internal[ITER_INDEX].p;
+	const index_stream *stream = iter->internal[ITER_STREAM].p;
+	const index_group *group = iter->internal[ITER_GROUP].p;
+	const size_t record = iter->internal[ITER_RECORD].s;
+
+	// lzma_index_iter.internal must not contain a pointer to the last
+	// group in the index, because that may be reallocated by
+	// lzma_index_cat().
+	if (group == NULL) {
+		// There are no groups.
+		assert(stream->groups.root == NULL);
+		iter->internal[ITER_METHOD].s = ITER_METHOD_LEFTMOST;
+
+	} else if (i->streams.rightmost != &stream->node
+			|| stream->groups.rightmost != &group->node) {
+		// The group is not not the last group in the index.
+		iter->internal[ITER_METHOD].s = ITER_METHOD_NORMAL;
+
+	} else if (stream->groups.leftmost != &group->node) {
+		// The group isn't the only group in the Stream, thus we
+		// know that it must have a parent group i.e. it's not
+		// the root node.
+		assert(stream->groups.root != &group->node);
+		assert(group->node.parent->right == &group->node);
+		iter->internal[ITER_METHOD].s = ITER_METHOD_NEXT;
+		iter->internal[ITER_GROUP].p = group->node.parent;
+
+	} else {
+		// The Stream has only one group.
+		assert(stream->groups.root == &group->node);
+		assert(group->node.parent == NULL);
+		iter->internal[ITER_METHOD].s = ITER_METHOD_LEFTMOST;
+		iter->internal[ITER_GROUP].p = NULL;
+	}
+
+	iter->stream.number = stream->number;
+	iter->stream.block_count = stream->record_count;
+	iter->stream.compressed_offset = stream->node.compressed_base;
+	iter->stream.uncompressed_offset = stream->node.uncompressed_base;
+
+	// iter->stream.flags will be NULL if the Stream Flags haven't been
+	// set with lzma_index_stream_flags().
+	iter->stream.flags = stream->stream_flags.version == UINT32_MAX
+			? NULL : &stream->stream_flags;
+	iter->stream.padding = stream->stream_padding;
+
+	if (stream->groups.rightmost == NULL) {
+		// Stream has no Blocks.
+		iter->stream.compressed_size = index_size(0, 0)
+				+ 2 * LZMA_STREAM_HEADER_SIZE;
+		iter->stream.uncompressed_size = 0;
+	} else {
+		const index_group *g = (const index_group *)(
+				stream->groups.rightmost);
+
+		// Stream Header + Stream Footer + Index + Blocks
+		iter->stream.compressed_size = 2 * LZMA_STREAM_HEADER_SIZE
+				+ index_size(stream->record_count,
+					stream->index_list_size)
+				+ vli_ceil4(g->records[g->last].unpadded_sum);
+		iter->stream.uncompressed_size
+				= g->records[g->last].uncompressed_sum;
+	}
+
+	if (group != NULL) {
+		iter->block.number_in_stream = group->number_base + record;
+		iter->block.number_in_file = iter->block.number_in_stream
+				+ stream->block_number_base;
+
+		iter->block.compressed_stream_offset
+				= record == 0 ? group->node.compressed_base
+				: vli_ceil4(group->records[
+					record - 1].unpadded_sum);
+		iter->block.uncompressed_stream_offset
+				= record == 0 ? group->node.uncompressed_base
+				: group->records[record - 1].uncompressed_sum;
+
+		iter->block.uncompressed_size
+				= group->records[record].uncompressed_sum
+				- iter->block.uncompressed_stream_offset;
+		iter->block.unpadded_size
+				= group->records[record].unpadded_sum
+				- iter->block.compressed_stream_offset;
+		iter->block.total_size = vli_ceil4(iter->block.unpadded_size);
+
+		iter->block.compressed_stream_offset
+				+= LZMA_STREAM_HEADER_SIZE;
+
+		iter->block.compressed_file_offset
+				= iter->block.compressed_stream_offset
+				+ iter->stream.compressed_offset;
+		iter->block.uncompressed_file_offset
+				= iter->block.uncompressed_stream_offset
+				+ iter->stream.uncompressed_offset;
+	}
+
+	return;
+}
+
+
+extern LZMA_API(void)
+lzma_index_iter_init(lzma_index_iter *iter, const lzma_index *i)
+{
+	iter->internal[ITER_INDEX].p = i;
+	lzma_index_iter_rewind(iter);
+	return;
+}
+
+
+extern LZMA_API(void)
+lzma_index_iter_rewind(lzma_index_iter *iter)
+{
+	iter->internal[ITER_STREAM].p = NULL;
+	iter->internal[ITER_GROUP].p = NULL;
+	iter->internal[ITER_RECORD].s = 0;
+	iter->internal[ITER_METHOD].s = ITER_METHOD_NORMAL;
+	return;
+}
+
+
+extern LZMA_API(lzma_bool)
+lzma_index_iter_next(lzma_index_iter *iter, lzma_index_iter_mode mode)
+{
+	// Catch unsupported mode values.
+	if ((unsigned int)(mode) > LZMA_INDEX_ITER_NONEMPTY_BLOCK)
+		return true;
+
+	const lzma_index *i = iter->internal[ITER_INDEX].p;
+	const index_stream *stream = iter->internal[ITER_STREAM].p;
+	const index_group *group = NULL;
+	size_t record = iter->internal[ITER_RECORD].s;
+
+	// If we are being asked for the next Stream, leave group to NULL
+	// so that the rest of the this function thinks that this Stream
+	// has no groups and will thus go to the next Stream.
+	if (mode != LZMA_INDEX_ITER_STREAM) {
+		// Get the pointer to the current group. See iter_set_inf()
+		// for explanation.
+		switch (iter->internal[ITER_METHOD].s) {
+		case ITER_METHOD_NORMAL:
+			group = iter->internal[ITER_GROUP].p;
+			break;
+
+		case ITER_METHOD_NEXT:
+			group = index_tree_next(iter->internal[ITER_GROUP].p);
+			break;
+
+		case ITER_METHOD_LEFTMOST:
+			group = (const index_group *)(
+					stream->groups.leftmost);
+			break;
+		}
+	}
+
+again:
+	if (stream == NULL) {
+		// We at the beginning of the lzma_index.
+		// Locate the first Stream.
+		stream = (const index_stream *)(i->streams.leftmost);
+		if (mode >= LZMA_INDEX_ITER_BLOCK) {
+			// Since we are being asked to return information
+			// about the first a Block, skip Streams that have
+			// no Blocks.
+			while (stream->groups.leftmost == NULL) {
+				stream = index_tree_next(&stream->node);
+				if (stream == NULL)
+					return true;
+			}
+		}
+
+		// Start from the first Record in the Stream.
+		group = (const index_group *)(stream->groups.leftmost);
+		record = 0;
+
+	} else if (group != NULL && record < group->last) {
+		// The next Record is in the same group.
+		++record;
+
+	} else {
+		// This group has no more Records or this Stream has
+		// no Blocks at all.
+		record = 0;
+
+		// If group is not NULL, this Stream has at least one Block
+		// and thus at least one group. Find the next group.
+		if (group != NULL)
+			group = index_tree_next(&group->node);
+
+		if (group == NULL) {
+			// This Stream has no more Records. Find the next
+			// Stream. If we are being asked to return information
+			// about a Block, we skip empty Streams.
+			do {
+				stream = index_tree_next(&stream->node);
+				if (stream == NULL)
+					return true;
+			} while (mode >= LZMA_INDEX_ITER_BLOCK
+					&& stream->groups.leftmost == NULL);
+
+			group = (const index_group *)(
+					stream->groups.leftmost);
+		}
+	}
+
+	if (mode == LZMA_INDEX_ITER_NONEMPTY_BLOCK) {
+		// We need to look for the next Block again if this Block
+		// is empty.
+		if (record == 0) {
+			if (group->node.uncompressed_base
+					== group->records[0].uncompressed_sum)
+				goto again;
+		} else if (group->records[record - 1].uncompressed_sum
+				== group->records[record].uncompressed_sum) {
+			goto again;
+		}
+	}
+
+	iter->internal[ITER_STREAM].p = stream;
+	iter->internal[ITER_GROUP].p = group;
+	iter->internal[ITER_RECORD].s = record;
+
+	iter_set_info(iter);
+
+	return false;
+}
+
+
+extern LZMA_API(lzma_bool)
+lzma_index_iter_locate(lzma_index_iter *iter, lzma_vli target)
+{
+	const lzma_index *i = iter->internal[ITER_INDEX].p;
+
+	// If the target is past the end of the file, return immediately.
+	if (i->uncompressed_size <= target)
+		return true;
+
+	// Locate the Stream containing the target offset.
+	const index_stream *stream = index_tree_locate(&i->streams, target);
+	assert(stream != NULL);
+	target -= stream->node.uncompressed_base;
+
+	// Locate the group containing the target offset.
+	const index_group *group = index_tree_locate(&stream->groups, target);
+	assert(group != NULL);
+
+	// Use binary search to locate the exact Record. It is the first
+	// Record whose uncompressed_sum is greater than target.
+	// This is because we want the rightmost Record that fullfills the
+	// search criterion. It is possible that there are empty Blocks;
+	// we don't want to return them.
+	size_t left = 0;
+	size_t right = group->last;
+
+	while (left < right) {
+		const size_t pos = left + (right - left) / 2;
+		if (group->records[pos].uncompressed_sum <= target)
+			left = pos + 1;
+		else
+			right = pos;
+	}
+
+	iter->internal[ITER_STREAM].p = stream;
+	iter->internal[ITER_GROUP].p = group;
+	iter->internal[ITER_RECORD].s = left;
+
+	iter_set_info(iter);
+
+	return false;
+}
diff --git a/src/liblzma/common/index.h b/src/liblzma/common/index.h
new file mode 100644
index 0000000..64e9724
--- /dev/null
+++ b/src/liblzma/common/index.h
@@ -0,0 +1,73 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       index.h
+/// \brief      Handling of Index
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_INDEX_H
+#define LZMA_INDEX_H
+
+#include "common.h"
+
+
+/// Minimum Unpadded Size
+#define UNPADDED_SIZE_MIN LZMA_VLI_C(5)
+
+/// Maximum Unpadded Size
+#define UNPADDED_SIZE_MAX (LZMA_VLI_MAX & ~LZMA_VLI_C(3))
+
+
+/// Get the size of the Index Padding field. This is needed by Index encoder
+/// and decoder, but applications should have no use for this.
+extern uint32_t lzma_index_padding_size(const lzma_index *i);
+
+
+/// Set for how many Records to allocate memory the next time
+/// lzma_index_append() needs to allocate space for a new Record.
+/// This is used only by the Index decoder.
+extern void lzma_index_prealloc(lzma_index *i, lzma_vli records);
+
+
+/// Round the variable-length integer to the next multiple of four.
+static inline lzma_vli
+vli_ceil4(lzma_vli vli)
+{
+	assert(vli <= LZMA_VLI_MAX);
+	return (vli + 3) & ~LZMA_VLI_C(3);
+}
+
+
+/// Calculate the size of the Index field excluding Index Padding
+static inline lzma_vli
+index_size_unpadded(lzma_vli count, lzma_vli index_list_size)
+{
+	// Index Indicator + Number of Records + List of Records + CRC32
+	return 1 + lzma_vli_size(count) + index_list_size + 4;
+}
+
+
+/// Calculate the size of the Index field including Index Padding
+static inline lzma_vli
+index_size(lzma_vli count, lzma_vli index_list_size)
+{
+	return vli_ceil4(index_size_unpadded(count, index_list_size));
+}
+
+
+/// Calculate the total size of the Stream
+static inline lzma_vli
+index_stream_size(lzma_vli blocks_size,
+		lzma_vli count, lzma_vli index_list_size)
+{
+	return LZMA_STREAM_HEADER_SIZE + blocks_size
+			+ index_size(count, index_list_size)
+			+ LZMA_STREAM_HEADER_SIZE;
+}
+
+#endif
diff --git a/src/liblzma/common/index_decoder.c b/src/liblzma/common/index_decoder.c
new file mode 100644
index 0000000..86a2297
--- /dev/null
+++ b/src/liblzma/common/index_decoder.c
@@ -0,0 +1,343 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       index_decoder.c
+/// \brief      Decodes the Index field
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "index.h"
+#include "check.h"
+
+
+struct lzma_coder_s {
+	enum {
+		SEQ_INDICATOR,
+		SEQ_COUNT,
+		SEQ_MEMUSAGE,
+		SEQ_UNPADDED,
+		SEQ_UNCOMPRESSED,
+		SEQ_PADDING_INIT,
+		SEQ_PADDING,
+		SEQ_CRC32,
+	} sequence;
+
+	/// Memory usage limit
+	uint64_t memlimit;
+
+	/// Target Index
+	lzma_index *index;
+
+	/// Pointer give by the application, which is set after
+	/// successful decoding.
+	lzma_index **index_ptr;
+
+	/// Number of Records left to decode.
+	lzma_vli count;
+
+	/// The most recent Unpadded Size field
+	lzma_vli unpadded_size;
+
+	/// The most recent Uncompressed Size field
+	lzma_vli uncompressed_size;
+
+	/// Position in integers
+	size_t pos;
+
+	/// CRC32 of the List of Records field
+	uint32_t crc32;
+};
+
+
+static lzma_ret
+index_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 lzma_attribute((unused)),
+		size_t *restrict out_pos lzma_attribute((unused)),
+		size_t out_size lzma_attribute((unused)),
+		lzma_action action lzma_attribute((unused)))
+{
+	// Similar optimization as in index_encoder.c
+	const size_t in_start = *in_pos;
+	lzma_ret ret = LZMA_OK;
+
+	while (*in_pos < in_size)
+	switch (coder->sequence) {
+	case SEQ_INDICATOR:
+		// Return LZMA_DATA_ERROR instead of e.g. LZMA_PROG_ERROR or
+		// LZMA_FORMAT_ERROR, because a typical usage case for Index
+		// decoder is when parsing the Stream backwards. If seeking
+		// backward from the Stream Footer gives us something that
+		// doesn't begin with Index Indicator, the file is considered
+		// corrupt, not "programming error" or "unrecognized file
+		// format". One could argue that the application should
+		// verify the Index Indicator before trying to decode the
+		// Index, but well, I suppose it is simpler this way.
+		if (in[(*in_pos)++] != 0x00)
+			return LZMA_DATA_ERROR;
+
+		coder->sequence = SEQ_COUNT;
+		break;
+
+	case SEQ_COUNT:
+		ret = lzma_vli_decode(&coder->count, &coder->pos,
+				in, in_pos, in_size);
+		if (ret != LZMA_STREAM_END)
+			goto out;
+
+		coder->pos = 0;
+		coder->sequence = SEQ_MEMUSAGE;
+
+	// Fall through
+
+	case SEQ_MEMUSAGE:
+		if (lzma_index_memusage(1, coder->count) > coder->memlimit) {
+			ret = LZMA_MEMLIMIT_ERROR;
+			goto out;
+		}
+
+		// Tell the Index handling code how many Records this
+		// Index has to allow it to allocate memory more efficiently.
+		lzma_index_prealloc(coder->index, coder->count);
+
+		ret = LZMA_OK;
+		coder->sequence = coder->count == 0
+				? SEQ_PADDING_INIT : SEQ_UNPADDED;
+		break;
+
+	case SEQ_UNPADDED:
+	case SEQ_UNCOMPRESSED: {
+		lzma_vli *size = coder->sequence == SEQ_UNPADDED
+				? &coder->unpadded_size
+				: &coder->uncompressed_size;
+
+		ret = lzma_vli_decode(size, &coder->pos,
+				in, in_pos, in_size);
+		if (ret != LZMA_STREAM_END)
+			goto out;
+
+		ret = LZMA_OK;
+		coder->pos = 0;
+
+		if (coder->sequence == SEQ_UNPADDED) {
+			// Validate that encoded Unpadded Size isn't too small
+			// or too big.
+			if (coder->unpadded_size < UNPADDED_SIZE_MIN
+					|| coder->unpadded_size
+						> UNPADDED_SIZE_MAX)
+				return LZMA_DATA_ERROR;
+
+			coder->sequence = SEQ_UNCOMPRESSED;
+		} else {
+			// Add the decoded Record to the Index.
+			return_if_error(lzma_index_append(
+					coder->index, allocator,
+					coder->unpadded_size,
+					coder->uncompressed_size));
+
+			// Check if this was the last Record.
+			coder->sequence = --coder->count == 0
+					? SEQ_PADDING_INIT
+					: SEQ_UNPADDED;
+		}
+
+		break;
+	}
+
+	case SEQ_PADDING_INIT:
+		coder->pos = lzma_index_padding_size(coder->index);
+		coder->sequence = SEQ_PADDING;
+
+	// Fall through
+
+	case SEQ_PADDING:
+		if (coder->pos > 0) {
+			--coder->pos;
+			if (in[(*in_pos)++] != 0x00)
+				return LZMA_DATA_ERROR;
+
+			break;
+		}
+
+		// Finish the CRC32 calculation.
+		coder->crc32 = lzma_crc32(in + in_start,
+				*in_pos - in_start, coder->crc32);
+
+		coder->sequence = SEQ_CRC32;
+
+	// Fall through
+
+	case SEQ_CRC32:
+		do {
+			if (*in_pos == in_size)
+				return LZMA_OK;
+
+			if (((coder->crc32 >> (coder->pos * 8)) & 0xFF)
+					!= in[(*in_pos)++])
+				return LZMA_DATA_ERROR;
+
+		} while (++coder->pos < 4);
+
+		// Decoding was successful, now we can let the application
+		// see the decoded Index.
+		*coder->index_ptr = coder->index;
+
+		// Make index NULL so we don't free it unintentionally.
+		coder->index = NULL;
+
+		return LZMA_STREAM_END;
+
+	default:
+		assert(0);
+		return LZMA_PROG_ERROR;
+	}
+
+out:
+	// Update the CRC32,
+	coder->crc32 = lzma_crc32(in + in_start,
+			*in_pos - in_start, coder->crc32);
+
+	return ret;
+}
+
+
+static void
+index_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
+{
+	lzma_index_end(coder->index, allocator);
+	lzma_free(coder, allocator);
+	return;
+}
+
+
+static lzma_ret
+index_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
+		uint64_t *old_memlimit, uint64_t new_memlimit)
+{
+	*memusage = lzma_index_memusage(1, coder->count);
+	*old_memlimit = coder->memlimit;
+
+	if (new_memlimit != 0) {
+		if (new_memlimit < *memusage)
+			return LZMA_MEMLIMIT_ERROR;
+
+		coder->memlimit = new_memlimit;
+	}
+
+	return LZMA_OK;
+}
+
+
+static lzma_ret
+index_decoder_reset(lzma_coder *coder, lzma_allocator *allocator,
+		lzma_index **i, uint64_t memlimit)
+{
+	// Remember the pointer given by the application. We will set it
+	// to point to the decoded Index only if decoding is successful.
+	// Before that, keep it NULL so that applications can always safely
+	// pass it to lzma_index_end() no matter did decoding succeed or not.
+	coder->index_ptr = i;
+	*i = NULL;
+
+	// We always allocate a new lzma_index.
+	coder->index = lzma_index_init(allocator);
+	if (coder->index == NULL)
+		return LZMA_MEM_ERROR;
+
+	// Initialize the rest.
+	coder->sequence = SEQ_INDICATOR;
+	coder->memlimit = memlimit;
+	coder->count = 0; // Needs to be initialized due to _memconfig().
+	coder->pos = 0;
+	coder->crc32 = 0;
+
+	return LZMA_OK;
+}
+
+
+static lzma_ret
+index_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		lzma_index **i, uint64_t memlimit)
+{
+	lzma_next_coder_init(&index_decoder_init, next, allocator);
+
+	if (i == NULL || memlimit == 0)
+		return LZMA_PROG_ERROR;
+
+	if (next->coder == NULL) {
+		next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+		if (next->coder == NULL)
+			return LZMA_MEM_ERROR;
+
+		next->code = &index_decode;
+		next->end = &index_decoder_end;
+		next->memconfig = &index_decoder_memconfig;
+		next->coder->index = NULL;
+	} else {
+		lzma_index_end(next->coder->index, allocator);
+	}
+
+	return index_decoder_reset(next->coder, allocator, i, memlimit);
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_index_decoder(lzma_stream *strm, lzma_index **i, uint64_t memlimit)
+{
+	lzma_next_strm_init(index_decoder_init, strm, i, memlimit);
+
+	strm->internal->supported_actions[LZMA_RUN] = true;
+
+	return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_index_buffer_decode(
+		lzma_index **i, uint64_t *memlimit, lzma_allocator *allocator,
+		const uint8_t *in, size_t *in_pos, size_t in_size)
+{
+	// Sanity checks
+	if (i == NULL || memlimit == NULL
+			|| in == NULL || in_pos == NULL || *in_pos > in_size)
+		return LZMA_PROG_ERROR;
+
+	// Initialize the decoder.
+	lzma_coder coder;
+	return_if_error(index_decoder_reset(&coder, allocator, i, *memlimit));
+
+	// Store the input start position so that we can restore it in case
+	// of an error.
+	const size_t in_start = *in_pos;
+
+	// Do the actual decoding.
+	lzma_ret ret = index_decode(&coder, allocator, in, in_pos, in_size,
+			NULL, NULL, 0, LZMA_RUN);
+
+	if (ret == LZMA_STREAM_END) {
+		ret = LZMA_OK;
+	} else {
+		// Something went wrong, free the Index structure and restore
+		// the input position.
+		lzma_index_end(coder.index, allocator);
+		*in_pos = in_start;
+
+		if (ret == LZMA_OK) {
+			// The input is truncated or otherwise corrupt.
+			// Use LZMA_DATA_ERROR instead of LZMA_BUF_ERROR
+			// like lzma_vli_decode() does in single-call mode.
+			ret = LZMA_DATA_ERROR;
+
+		} else if (ret == LZMA_MEMLIMIT_ERROR) {
+			// Tell the caller how much memory would have
+			// been needed.
+			*memlimit = lzma_index_memusage(1, coder.count);
+		}
+	}
+
+	return ret;
+}
diff --git a/src/liblzma/common/index_encoder.c b/src/liblzma/common/index_encoder.c
new file mode 100644
index 0000000..706f1fd
--- /dev/null
+++ b/src/liblzma/common/index_encoder.c
@@ -0,0 +1,252 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       index_encoder.c
+/// \brief      Encodes the Index field
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "index_encoder.h"
+#include "index.h"
+#include "check.h"
+
+
+struct lzma_coder_s {
+	enum {
+		SEQ_INDICATOR,
+		SEQ_COUNT,
+		SEQ_UNPADDED,
+		SEQ_UNCOMPRESSED,
+		SEQ_NEXT,
+		SEQ_PADDING,
+		SEQ_CRC32,
+	} sequence;
+
+	/// Index being encoded
+	const lzma_index *index;
+
+	/// Iterator for the Index being encoded
+	lzma_index_iter iter;
+
+	/// Position in integers
+	size_t pos;
+
+	/// CRC32 of the List of Records field
+	uint32_t crc32;
+};
+
+
+static lzma_ret
+index_encode(lzma_coder *coder,
+		lzma_allocator *allocator lzma_attribute((unused)),
+		const uint8_t *restrict in lzma_attribute((unused)),
+		size_t *restrict in_pos lzma_attribute((unused)),
+		size_t in_size lzma_attribute((unused)),
+		uint8_t *restrict out, size_t *restrict out_pos,
+		size_t out_size, lzma_action action lzma_attribute((unused)))
+{
+	// Position where to start calculating CRC32. The idea is that we
+	// need to call lzma_crc32() only once per call to index_encode().
+	const size_t out_start = *out_pos;
+
+	// Return value to use if we return at the end of this function.
+	// We use "goto out" to jump out of the while-switch construct
+	// instead of returning directly, because that way we don't need
+	// to copypaste the lzma_crc32() call to many places.
+	lzma_ret ret = LZMA_OK;
+
+	while (*out_pos < out_size)
+	switch (coder->sequence) {
+	case SEQ_INDICATOR:
+		out[*out_pos] = 0x00;
+		++*out_pos;
+		coder->sequence = SEQ_COUNT;
+		break;
+
+	case SEQ_COUNT: {
+		const lzma_vli count = lzma_index_block_count(coder->index);
+		ret = lzma_vli_encode(count, &coder->pos,
+				out, out_pos, out_size);
+		if (ret != LZMA_STREAM_END)
+			goto out;
+
+		ret = LZMA_OK;
+		coder->pos = 0;
+		coder->sequence = SEQ_NEXT;
+		break;
+	}
+
+	case SEQ_NEXT:
+		if (lzma_index_iter_next(
+				&coder->iter, LZMA_INDEX_ITER_BLOCK)) {
+			// Get the size of the Index Padding field.
+			coder->pos = lzma_index_padding_size(coder->index);
+			assert(coder->pos <= 3);
+			coder->sequence = SEQ_PADDING;
+			break;
+		}
+
+		coder->sequence = SEQ_UNPADDED;
+
+	// Fall through
+
+	case SEQ_UNPADDED:
+	case SEQ_UNCOMPRESSED: {
+		const lzma_vli size = coder->sequence == SEQ_UNPADDED
+				? coder->iter.block.unpadded_size
+				: coder->iter.block.uncompressed_size;
+
+		ret = lzma_vli_encode(size, &coder->pos,
+				out, out_pos, out_size);
+		if (ret != LZMA_STREAM_END)
+			goto out;
+
+		ret = LZMA_OK;
+		coder->pos = 0;
+
+		// Advance to SEQ_UNCOMPRESSED or SEQ_NEXT.
+		++coder->sequence;
+		break;
+	}
+
+	case SEQ_PADDING:
+		if (coder->pos > 0) {
+			--coder->pos;
+			out[(*out_pos)++] = 0x00;
+			break;
+		}
+
+		// Finish the CRC32 calculation.
+		coder->crc32 = lzma_crc32(out + out_start,
+				*out_pos - out_start, coder->crc32);
+
+		coder->sequence = SEQ_CRC32;
+
+	// Fall through
+
+	case SEQ_CRC32:
+		// We don't use the main loop, because we don't want
+		// coder->crc32 to be touched anymore.
+		do {
+			if (*out_pos == out_size)
+				return LZMA_OK;
+
+			out[*out_pos] = (coder->crc32 >> (coder->pos * 8))
+					& 0xFF;
+			++*out_pos;
+
+		} while (++coder->pos < 4);
+
+		return LZMA_STREAM_END;
+
+	default:
+		assert(0);
+		return LZMA_PROG_ERROR;
+	}
+
+out:
+	// Update the CRC32.
+	coder->crc32 = lzma_crc32(out + out_start,
+			*out_pos - out_start, coder->crc32);
+
+	return ret;
+}
+
+
+static void
+index_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
+{
+	lzma_free(coder, allocator);
+	return;
+}
+
+
+static void
+index_encoder_reset(lzma_coder *coder, const lzma_index *i)
+{
+	lzma_index_iter_init(&coder->iter, i);
+
+	coder->sequence = SEQ_INDICATOR;
+	coder->index = i;
+	coder->pos = 0;
+	coder->crc32 = 0;
+
+	return;
+}
+
+
+extern lzma_ret
+lzma_index_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_index *i)
+{
+	lzma_next_coder_init(&lzma_index_encoder_init, next, allocator);
+
+	if (i == NULL)
+		return LZMA_PROG_ERROR;
+
+	if (next->coder == NULL) {
+		next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+		if (next->coder == NULL)
+			return LZMA_MEM_ERROR;
+
+		next->code = &index_encode;
+		next->end = &index_encoder_end;
+	}
+
+	index_encoder_reset(next->coder, i);
+
+	return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_index_encoder(lzma_stream *strm, const lzma_index *i)
+{
+	lzma_next_strm_init(lzma_index_encoder_init, strm, i);
+
+	strm->internal->supported_actions[LZMA_RUN] = true;
+
+	return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_index_buffer_encode(const lzma_index *i,
+		uint8_t *out, size_t *out_pos, size_t out_size)
+{
+	// Validate the arguments.
+	if (i == NULL || out == NULL || out_pos == NULL || *out_pos > out_size)
+		return LZMA_PROG_ERROR;
+
+	// Don't try to encode if there's not enough output space.
+	if (out_size - *out_pos < lzma_index_size(i))
+		return LZMA_BUF_ERROR;
+
+	// The Index encoder needs just one small data structure so we can
+	// allocate it on stack.
+	lzma_coder coder;
+	index_encoder_reset(&coder, i);
+
+	// Do the actual encoding. This should never fail, but store
+	// the original *out_pos just in case.
+	const size_t out_start = *out_pos;
+	lzma_ret ret = index_encode(&coder, NULL, NULL, NULL, 0,
+			out, out_pos, out_size, LZMA_RUN);
+
+	if (ret == LZMA_STREAM_END) {
+		ret = LZMA_OK;
+	} else {
+		// We should never get here, but just in case, restore the
+		// output position and set the error accordingly if something
+		// goes wrong and debugging isn't enabled.
+		assert(0);
+		*out_pos = out_start;
+		ret = LZMA_PROG_ERROR;
+	}
+
+	return ret;
+}
diff --git a/src/liblzma/common/index_encoder.h b/src/liblzma/common/index_encoder.h
new file mode 100644
index 0000000..a13c94d
--- /dev/null
+++ b/src/liblzma/common/index_encoder.h
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       index_encoder.h
+/// \brief      Encodes the Index field
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_INDEX_ENCODER_H
+#define LZMA_INDEX_ENCODER_H
+
+#include "common.h"
+
+
+extern lzma_ret lzma_index_encoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_index *i);
+
+
+#endif
diff --git a/src/liblzma/common/index_hash.c b/src/liblzma/common/index_hash.c
new file mode 100644
index 0000000..e3e9386
--- /dev/null
+++ b/src/liblzma/common/index_hash.c
@@ -0,0 +1,332 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       index_hash.c
+/// \brief      Validates Index by using a hash function
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+#include "index.h"
+#include "check.h"
+
+
+typedef struct {
+	/// Sum of the Block sizes (including Block Padding)
+	lzma_vli blocks_size;
+
+	/// Sum of the Uncompressed Size fields
+	lzma_vli uncompressed_size;
+
+	/// Number of Records
+	lzma_vli count;
+
+	/// Size of the List of Index Records as bytes
+	lzma_vli index_list_size;
+
+	/// Check calculated from Unpadded Sizes and Uncompressed Sizes.
+	lzma_check_state check;
+
+} lzma_index_hash_info;
+
+
+struct lzma_index_hash_s {
+	enum {
+		SEQ_BLOCK,
+		SEQ_COUNT,
+		SEQ_UNPADDED,
+		SEQ_UNCOMPRESSED,
+		SEQ_PADDING_INIT,
+		SEQ_PADDING,
+		SEQ_CRC32,
+	} sequence;
+
+	/// Information collected while decoding the actual Blocks.
+	lzma_index_hash_info blocks;
+
+	/// Information collected from the Index field.
+	lzma_index_hash_info records;
+
+	/// Number of Records not fully decoded
+	lzma_vli remaining;
+
+	/// Unpadded Size currently being read from an Index Record.
+	lzma_vli unpadded_size;
+
+	/// Uncompressed Size currently being read from an Index Record.
+	lzma_vli uncompressed_size;
+
+	/// Position in variable-length integers when decoding them from
+	/// the List of Records.
+	size_t pos;
+
+	/// CRC32 of the Index
+	uint32_t crc32;
+};
+
+
+extern LZMA_API(lzma_index_hash *)
+lzma_index_hash_init(lzma_index_hash *index_hash, lzma_allocator *allocator)
+{
+	if (index_hash == NULL) {
+		index_hash = lzma_alloc(sizeof(lzma_index_hash), allocator);
+		if (index_hash == NULL)
+			return NULL;
+	}
+
+	index_hash->sequence = SEQ_BLOCK;
+	index_hash->blocks.blocks_size = 0;
+	index_hash->blocks.uncompressed_size = 0;
+	index_hash->blocks.count = 0;
+	index_hash->blocks.index_list_size = 0;
+	index_hash->records.blocks_size = 0;
+	index_hash->records.uncompressed_size = 0;
+	index_hash->records.count = 0;
+	index_hash->records.index_list_size = 0;
+	index_hash->unpadded_size = 0;
+	index_hash->uncompressed_size = 0;
+	index_hash->pos = 0;
+	index_hash->crc32 = 0;
+
+	// These cannot fail because LZMA_CHECK_BEST is known to be supported.
+	(void)lzma_check_init(&index_hash->blocks.check, LZMA_CHECK_BEST);
+	(void)lzma_check_init(&index_hash->records.check, LZMA_CHECK_BEST);
+
+	return index_hash;
+}
+
+
+extern LZMA_API(void)
+lzma_index_hash_end(lzma_index_hash *index_hash, lzma_allocator *allocator)
+{
+	lzma_free(index_hash, allocator);
+	return;
+}
+
+
+extern LZMA_API(lzma_vli)
+lzma_index_hash_size(const lzma_index_hash *index_hash)
+{
+	// Get the size of the Index from ->blocks instead of ->records for
+	// cases where application wants to know the Index Size before
+	// decoding the Index.
+	return index_size(index_hash->blocks.count,
+			index_hash->blocks.index_list_size);
+}
+
+
+/// Updates the sizes and the hash without any validation.
+static lzma_ret
+hash_append(lzma_index_hash_info *info, lzma_vli unpadded_size,
+		lzma_vli uncompressed_size)
+{
+	info->blocks_size += vli_ceil4(unpadded_size);
+	info->uncompressed_size += uncompressed_size;
+	info->index_list_size += lzma_vli_size(unpadded_size)
+			+ lzma_vli_size(uncompressed_size);
+	++info->count;
+
+	const lzma_vli sizes[2] = { unpadded_size, uncompressed_size };
+	lzma_check_update(&info->check, LZMA_CHECK_BEST,
+			(const uint8_t *)(sizes), sizeof(sizes));
+
+	return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_index_hash_append(lzma_index_hash *index_hash, lzma_vli unpadded_size,
+		lzma_vli uncompressed_size)
+{
+	// Validate the arguments.
+	if (index_hash->sequence != SEQ_BLOCK
+			|| unpadded_size < UNPADDED_SIZE_MIN
+			|| unpadded_size > UNPADDED_SIZE_MAX
+			|| uncompressed_size > LZMA_VLI_MAX)
+		return LZMA_PROG_ERROR;
+
+	// Update the hash.
+	return_if_error(hash_append(&index_hash->blocks,
+			unpadded_size, uncompressed_size));
+
+	// Validate the properties of *info are still in allowed limits.
+	if (index_hash->blocks.blocks_size > LZMA_VLI_MAX
+			|| index_hash->blocks.uncompressed_size > LZMA_VLI_MAX
+			|| index_size(index_hash->blocks.count,
+					index_hash->blocks.index_list_size)
+				> LZMA_BACKWARD_SIZE_MAX
+			|| index_stream_size(index_hash->blocks.blocks_size,
+					index_hash->blocks.count,
+					index_hash->blocks.index_list_size)
+				> LZMA_VLI_MAX)
+		return LZMA_DATA_ERROR;
+
+	return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_index_hash_decode(lzma_index_hash *index_hash, const uint8_t *in,
+		size_t *in_pos, size_t in_size)
+{
+	// Catch zero input buffer here, because in contrast to Index encoder
+	// and decoder functions, applications call this function directly
+	// instead of via lzma_code(), which does the buffer checking.
+	if (*in_pos >= in_size)
+		return LZMA_BUF_ERROR;
+
+	// NOTE: This function has many similarities to index_encode() and
+	// index_decode() functions found from index_encoder.c and
+	// index_decoder.c. See the comments especially in index_encoder.c.
+	const size_t in_start = *in_pos;
+	lzma_ret ret = LZMA_OK;
+
+	while (*in_pos < in_size)
+	switch (index_hash->sequence) {
+	case SEQ_BLOCK:
+		// Check the Index Indicator is present.
+		if (in[(*in_pos)++] != 0x00)
+			return LZMA_DATA_ERROR;
+
+		index_hash->sequence = SEQ_COUNT;
+		break;
+
+	case SEQ_COUNT: {
+		ret = lzma_vli_decode(&index_hash->remaining,
+				&index_hash->pos, in, in_pos, in_size);
+		if (ret != LZMA_STREAM_END)
+			goto out;
+
+		// The count must match the count of the Blocks decoded.
+		if (index_hash->remaining != index_hash->blocks.count)
+			return LZMA_DATA_ERROR;
+
+		ret = LZMA_OK;
+		index_hash->pos = 0;
+
+		// Handle the special case when there are no Blocks.
+		index_hash->sequence = index_hash->remaining == 0
+				? SEQ_PADDING_INIT : SEQ_UNPADDED;
+		break;
+	}
+
+	case SEQ_UNPADDED:
+	case SEQ_UNCOMPRESSED: {
+		lzma_vli *size = index_hash->sequence == SEQ_UNPADDED
+				? &index_hash->unpadded_size
+				: &index_hash->uncompressed_size;
+
+		ret = lzma_vli_decode(size, &index_hash->pos,
+				in, in_pos, in_size);
+		if (ret != LZMA_STREAM_END)
+			goto out;
+
+		ret = LZMA_OK;
+		index_hash->pos = 0;
+
+		if (index_hash->sequence == SEQ_UNPADDED) {
+			if (index_hash->unpadded_size < UNPADDED_SIZE_MIN
+					|| index_hash->unpadded_size
+						> UNPADDED_SIZE_MAX)
+				return LZMA_DATA_ERROR;
+
+			index_hash->sequence = SEQ_UNCOMPRESSED;
+		} else {
+			// Update the hash.
+			return_if_error(hash_append(&index_hash->records,
+					index_hash->unpadded_size,
+					index_hash->uncompressed_size));
+
+			// Verify that we don't go over the known sizes. Note
+			// that this validation is simpler than the one used
+			// in lzma_index_hash_append(), because here we know
+			// that values in index_hash->blocks are already
+			// validated and we are fine as long as we don't
+			// exceed them in index_hash->records.
+			if (index_hash->blocks.blocks_size
+					< index_hash->records.blocks_size
+					|| index_hash->blocks.uncompressed_size
+					< index_hash->records.uncompressed_size
+					|| index_hash->blocks.index_list_size
+					< index_hash->records.index_list_size)
+				return LZMA_DATA_ERROR;
+
+			// Check if this was the last Record.
+			index_hash->sequence = --index_hash->remaining == 0
+					? SEQ_PADDING_INIT : SEQ_UNPADDED;
+		}
+
+		break;
+	}
+
+	case SEQ_PADDING_INIT:
+		index_hash->pos = (LZMA_VLI_C(4) - index_size_unpadded(
+				index_hash->records.count,
+				index_hash->records.index_list_size)) & 3;
+		index_hash->sequence = SEQ_PADDING;
+
+	// Fall through
+
+	case SEQ_PADDING:
+		if (index_hash->pos > 0) {
+			--index_hash->pos;
+			if (in[(*in_pos)++] != 0x00)
+				return LZMA_DATA_ERROR;
+
+			break;
+		}
+
+		// Compare the sizes.
+		if (index_hash->blocks.blocks_size
+				!= index_hash->records.blocks_size
+				|| index_hash->blocks.uncompressed_size
+				!= index_hash->records.uncompressed_size
+				|| index_hash->blocks.index_list_size
+				!= index_hash->records.index_list_size)
+			return LZMA_DATA_ERROR;
+
+		// Finish the hashes and compare them.
+		lzma_check_finish(&index_hash->blocks.check, LZMA_CHECK_BEST);
+		lzma_check_finish(&index_hash->records.check, LZMA_CHECK_BEST);
+		if (memcmp(index_hash->blocks.check.buffer.u8,
+				index_hash->records.check.buffer.u8,
+				lzma_check_size(LZMA_CHECK_BEST)) != 0)
+			return LZMA_DATA_ERROR;
+
+		// Finish the CRC32 calculation.
+		index_hash->crc32 = lzma_crc32(in + in_start,
+				*in_pos - in_start, index_hash->crc32);
+
+		index_hash->sequence = SEQ_CRC32;
+
+	// Fall through
+
+	case SEQ_CRC32:
+		do {
+			if (*in_pos == in_size)
+				return LZMA_OK;
+
+			if (((index_hash->crc32 >> (index_hash->pos * 8))
+					& 0xFF) != in[(*in_pos)++])
+				return LZMA_DATA_ERROR;
+
+		} while (++index_hash->pos < 4);
+
+		return LZMA_STREAM_END;
+
+	default:
+		assert(0);
+		return LZMA_PROG_ERROR;
+	}
+
+out:
+	// Update the CRC32,
+	index_hash->crc32 = lzma_crc32(in + in_start,
+			*in_pos - in_start, index_hash->crc32);
+
+	return ret;
+}
diff --git a/src/liblzma/common/stream_buffer_decoder.c b/src/liblzma/common/stream_buffer_decoder.c
new file mode 100644
index 0000000..ae75315
--- /dev/null
+++ b/src/liblzma/common/stream_buffer_decoder.c
@@ -0,0 +1,91 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       stream_buffer_decoder.c
+/// \brief      Single-call .xz Stream decoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "stream_decoder.h"
+
+
+extern LZMA_API(lzma_ret)
+lzma_stream_buffer_decode(uint64_t *memlimit, uint32_t flags,
+		lzma_allocator *allocator,
+		const uint8_t *in, size_t *in_pos, size_t in_size,
+		uint8_t *out, size_t *out_pos, size_t out_size)
+{
+	// Sanity checks
+	if (in_pos == NULL || (in == NULL && *in_pos != in_size)
+			|| *in_pos > in_size || out_pos == NULL
+			|| (out == NULL && *out_pos != out_size)
+			|| *out_pos > out_size)
+		return LZMA_PROG_ERROR;
+
+	// Catch flags that are not allowed in buffer-to-buffer decoding.
+	if (flags & LZMA_TELL_ANY_CHECK)
+		return LZMA_PROG_ERROR;
+
+	// Initialize the Stream decoder.
+	// TODO: We need something to tell the decoder that it can use the
+	// output buffer as workspace, and thus save significant amount of RAM.
+	lzma_next_coder stream_decoder = LZMA_NEXT_CODER_INIT;
+	lzma_ret ret = lzma_stream_decoder_init(
+			&stream_decoder, allocator, *memlimit, flags);
+
+	if (ret == LZMA_OK) {
+		// Save the positions so that we can restore them in case
+		// an error occurs.
+		const size_t in_start = *in_pos;
+		const size_t out_start = *out_pos;
+
+		// Do the actual decoding.
+		ret = stream_decoder.code(stream_decoder.coder, allocator,
+				in, in_pos, in_size, out, out_pos, out_size,
+				LZMA_FINISH);
+
+		if (ret == LZMA_STREAM_END) {
+			ret = LZMA_OK;
+		} else {
+			// Something went wrong, restore the positions.
+			*in_pos = in_start;
+			*out_pos = out_start;
+
+			if (ret == LZMA_OK) {
+				// Either the input was truncated or the
+				// output buffer was too small.
+				assert(*in_pos == in_size
+						|| *out_pos == out_size);
+
+				// If all the input was consumed, then the
+				// input is truncated, even if the output
+				// buffer is also full. This is because
+				// processing the last byte of the Stream
+				// never produces output.
+				if (*in_pos == in_size)
+					ret = LZMA_DATA_ERROR;
+				else
+					ret = LZMA_BUF_ERROR;
+
+			} else if (ret == LZMA_MEMLIMIT_ERROR) {
+				// Let the caller know how much memory would
+				// have been needed.
+				uint64_t memusage;
+				(void)stream_decoder.memconfig(
+						stream_decoder.coder,
+						memlimit, &memusage, 0);
+			}
+		}
+	}
+
+	// Free the decoder memory. This needs to be done even if
+	// initialization fails, because the internal API doesn't
+	// require the initialization function to free its memory on error.
+	lzma_next_end(&stream_decoder, allocator);
+
+	return ret;
+}
diff --git a/src/liblzma/common/stream_buffer_encoder.c b/src/liblzma/common/stream_buffer_encoder.c
new file mode 100644
index 0000000..f727d85
--- /dev/null
+++ b/src/liblzma/common/stream_buffer_encoder.c
@@ -0,0 +1,131 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       stream_buffer_encoder.c
+/// \brief      Single-call .xz Stream encoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "index.h"
+
+
+/// Maximum size of Index that has exactly one Record.
+/// Index Indicator + Number of Records + Record + CRC32 rounded up to
+/// the next multiple of four.
+#define INDEX_BOUND ((1 + 1 + 2 * LZMA_VLI_BYTES_MAX + 4 + 3) & ~3)
+
+/// Stream Header, Stream Footer, and Index
+#define HEADERS_BOUND (2 * LZMA_STREAM_HEADER_SIZE + INDEX_BOUND)
+
+
+extern LZMA_API(size_t)
+lzma_stream_buffer_bound(size_t uncompressed_size)
+{
+	// Get the maximum possible size of a Block.
+	const size_t block_bound = lzma_block_buffer_bound(uncompressed_size);
+	if (block_bound == 0)
+		return 0;
+
+	// Catch the possible integer overflow and also prevent the size of
+	// the Stream exceeding LZMA_VLI_MAX (theoretically possible on
+	// 64-bit systems).
+	if (my_min(SIZE_MAX, LZMA_VLI_MAX) - block_bound < HEADERS_BOUND)
+		return 0;
+
+	return block_bound + HEADERS_BOUND;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_stream_buffer_encode(lzma_filter *filters, lzma_check check,
+		lzma_allocator *allocator, const uint8_t *in, size_t in_size,
+		uint8_t *out, size_t *out_pos_ptr, size_t out_size)
+{
+	// Sanity checks
+	if (filters == NULL || (unsigned int)(check) > LZMA_CHECK_ID_MAX
+			|| (in == NULL && in_size != 0) || out == NULL
+			|| out_pos_ptr == NULL || *out_pos_ptr > out_size)
+		return LZMA_PROG_ERROR;
+
+	// Note for the paranoids: Index encoder prevents the Stream from
+	// getting too big and still being accepted with LZMA_OK, and Block
+	// encoder catches if the input is too big. So we don't need to
+	// separately check if the buffers are too big.
+
+	// Use a local copy. We update *out_pos_ptr only if everything
+	// succeeds.
+	size_t out_pos = *out_pos_ptr;
+
+	// Check that there's enough space for both Stream Header and
+	// Stream Footer.
+	if (out_size - out_pos <= 2 * LZMA_STREAM_HEADER_SIZE)
+		return LZMA_BUF_ERROR;
+
+	// Reserve space for Stream Footer so we don't need to check for
+	// available space again before encoding Stream Footer.
+	out_size -= LZMA_STREAM_HEADER_SIZE;
+
+	// Encode the Stream Header.
+	lzma_stream_flags stream_flags = {
+		.version = 0,
+		.check = check,
+	};
+
+	if (lzma_stream_header_encode(&stream_flags, out + out_pos)
+			!= LZMA_OK)
+		return LZMA_PROG_ERROR;
+
+	out_pos += LZMA_STREAM_HEADER_SIZE;
+
+	// Block
+	lzma_block block = {
+		.version = 0,
+		.check = check,
+		.filters = filters,
+	};
+
+	return_if_error(lzma_block_buffer_encode(&block, allocator,
+			in, in_size, out, &out_pos, out_size));
+
+	// Index
+	{
+		// Create an Index with one Record.
+		lzma_index *i = lzma_index_init(allocator);
+		if (i == NULL)
+			return LZMA_MEM_ERROR;
+
+		lzma_ret ret = lzma_index_append(i, allocator,
+				lzma_block_unpadded_size(&block),
+				block.uncompressed_size);
+
+		// If adding the Record was successful, encode the Index
+		// and get its size which will be stored into Stream Footer.
+		if (ret == LZMA_OK) {
+			ret = lzma_index_buffer_encode(
+					i, out, &out_pos, out_size);
+
+			stream_flags.backward_size = lzma_index_size(i);
+		}
+
+		lzma_index_end(i, allocator);
+
+		if (ret != LZMA_OK)
+			return ret;
+	}
+
+	// Stream Footer. We have already reserved space for this.
+	if (lzma_stream_footer_encode(&stream_flags, out + out_pos)
+			!= LZMA_OK)
+		return LZMA_PROG_ERROR;
+
+	out_pos += LZMA_STREAM_HEADER_SIZE;
+
+	// Everything went fine, make the new output position available
+	// to the application.
+	*out_pos_ptr = out_pos;
+	return LZMA_OK;
+}
diff --git a/src/liblzma/common/stream_decoder.c b/src/liblzma/common/stream_decoder.c
new file mode 100644
index 0000000..37ea71e
--- /dev/null
+++ b/src/liblzma/common/stream_decoder.c
@@ -0,0 +1,451 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       stream_decoder.c
+/// \brief      Decodes .xz Streams
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "stream_decoder.h"
+#include "block_decoder.h"
+
+
+struct lzma_coder_s {
+	enum {
+		SEQ_STREAM_HEADER,
+		SEQ_BLOCK_HEADER,
+		SEQ_BLOCK,
+		SEQ_INDEX,
+		SEQ_STREAM_FOOTER,
+		SEQ_STREAM_PADDING,
+	} sequence;
+
+	/// Block or Metadata decoder. This takes little memory and the same
+	/// data structure can be used to decode every Block Header, so it's
+	/// a good idea to have a separate lzma_next_coder structure for it.
+	lzma_next_coder block_decoder;
+
+	/// Block options decoded by the Block Header decoder and used by
+	/// the Block decoder.
+	lzma_block block_options;
+
+	/// Stream Flags from Stream Header
+	lzma_stream_flags stream_flags;
+
+	/// Index is hashed so that it can be compared to the sizes of Blocks
+	/// with O(1) memory usage.
+	lzma_index_hash *index_hash;
+
+	/// Memory usage limit
+	uint64_t memlimit;
+
+	/// Amount of memory actually needed (only an estimate)
+	uint64_t memusage;
+
+	/// If true, LZMA_NO_CHECK is returned if the Stream has
+	/// no integrity check.
+	bool tell_no_check;
+
+	/// If true, LZMA_UNSUPPORTED_CHECK is returned if the Stream has
+	/// an integrity check that isn't supported by this liblzma build.
+	bool tell_unsupported_check;
+
+	/// If true, LZMA_GET_CHECK is returned after decoding Stream Header.
+	bool tell_any_check;
+
+	/// If true, we will decode concatenated Streams that possibly have
+	/// Stream Padding between or after them. LZMA_STREAM_END is returned
+	/// once the application isn't giving us any new input, and we aren't
+	/// in the middle of a Stream, and possible Stream Padding is a
+	/// multiple of four bytes.
+	bool concatenated;
+
+	/// When decoding concatenated Streams, this is true as long as we
+	/// are decoding the first Stream. This is needed to avoid misleading
+	/// LZMA_FORMAT_ERROR in case the later Streams don't have valid magic
+	/// bytes.
+	bool first_stream;
+
+	/// Write position in buffer[] and position in Stream Padding
+	size_t pos;
+
+	/// Buffer to hold Stream Header, Block Header, and Stream Footer.
+	/// Block Header has biggest maximum size.
+	uint8_t buffer[LZMA_BLOCK_HEADER_SIZE_MAX];
+};
+
+
+static lzma_ret
+stream_decoder_reset(lzma_coder *coder, lzma_allocator *allocator)
+{
+	// Initialize the Index hash used to verify the Index.
+	coder->index_hash = lzma_index_hash_init(coder->index_hash, allocator);
+	if (coder->index_hash == NULL)
+		return LZMA_MEM_ERROR;
+
+	// Reset the rest of the variables.
+	coder->sequence = SEQ_STREAM_HEADER;
+	coder->pos = 0;
+
+	return LZMA_OK;
+}
+
+
+static lzma_ret
+stream_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)
+{
+	// When decoding the actual Block, it may be able to produce more
+	// output even if we don't give it any new input.
+	while (true)
+	switch (coder->sequence) {
+	case SEQ_STREAM_HEADER: {
+		// Copy the Stream Header to the internal buffer.
+		lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
+				LZMA_STREAM_HEADER_SIZE);
+
+		// Return if we didn't get the whole Stream Header yet.
+		if (coder->pos < LZMA_STREAM_HEADER_SIZE)
+			return LZMA_OK;
+
+		coder->pos = 0;
+
+		// Decode the Stream Header.
+		const lzma_ret ret = lzma_stream_header_decode(
+				&coder->stream_flags, coder->buffer);
+		if (ret != LZMA_OK)
+			return ret == LZMA_FORMAT_ERROR && !coder->first_stream
+					? LZMA_DATA_ERROR : ret;
+
+		// If we are decoding concatenated Streams, and the later
+		// Streams have invalid Header Magic Bytes, we give
+		// LZMA_DATA_ERROR instead of LZMA_FORMAT_ERROR.
+		coder->first_stream = false;
+
+		// Copy the type of the Check so that Block Header and Block
+		// decoders see it.
+		coder->block_options.check = coder->stream_flags.check;
+
+		// Even if we return LZMA_*_CHECK below, we want
+		// to continue from Block Header decoding.
+		coder->sequence = SEQ_BLOCK_HEADER;
+
+		// Detect if there's no integrity check or if it is
+		// unsupported if those were requested by the application.
+		if (coder->tell_no_check && coder->stream_flags.check
+				== LZMA_CHECK_NONE)
+			return LZMA_NO_CHECK;
+
+		if (coder->tell_unsupported_check
+				&& !lzma_check_is_supported(
+					coder->stream_flags.check))
+			return LZMA_UNSUPPORTED_CHECK;
+
+		if (coder->tell_any_check)
+			return LZMA_GET_CHECK;
+	}
+
+	// Fall through
+
+	case SEQ_BLOCK_HEADER: {
+		if (*in_pos >= in_size)
+			return LZMA_OK;
+
+		if (coder->pos == 0) {
+			// Detect if it's Index.
+			if (in[*in_pos] == 0x00) {
+				coder->sequence = SEQ_INDEX;
+				break;
+			}
+
+			// Calculate the size of the Block Header. Note that
+			// Block Header decoder wants to see this byte too
+			// so don't advance *in_pos.
+			coder->block_options.header_size
+					= lzma_block_header_size_decode(
+						in[*in_pos]);
+		}
+
+		// Copy the Block Header to the internal buffer.
+		lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
+				coder->block_options.header_size);
+
+		// Return if we didn't get the whole Block Header yet.
+		if (coder->pos < coder->block_options.header_size)
+			return LZMA_OK;
+
+		coder->pos = 0;
+
+		// Version 0 is currently the only possible version.
+		coder->block_options.version = 0;
+
+		// Set up a buffer to hold the filter chain. Block Header
+		// decoder will initialize all members of this array so
+		// we don't need to do it here.
+		lzma_filter filters[LZMA_FILTERS_MAX + 1];
+		coder->block_options.filters = filters;
+
+		// Decode the Block Header.
+		return_if_error(lzma_block_header_decode(&coder->block_options,
+				allocator, coder->buffer));
+
+		// Check the memory usage limit.
+		const uint64_t memusage = lzma_raw_decoder_memusage(filters);
+		lzma_ret ret;
+
+		if (memusage == UINT64_MAX) {
+			// One or more unknown Filter IDs.
+			ret = LZMA_OPTIONS_ERROR;
+		} else {
+			// Now we can set coder->memusage since we know that
+			// the filter chain is valid. We don't want
+			// lzma_memusage() to return UINT64_MAX in case of
+			// invalid filter chain.
+			coder->memusage = memusage;
+
+			if (memusage > coder->memlimit) {
+				// The chain would need too much memory.
+				ret = LZMA_MEMLIMIT_ERROR;
+			} else {
+				// Memory usage is OK.
+				// Initialize the Block decoder.
+				ret = lzma_block_decoder_init(
+						&coder->block_decoder,
+						allocator,
+						&coder->block_options);
+			}
+		}
+
+		// Free the allocated filter options since they are needed
+		// only to initialize the Block decoder.
+		for (size_t i = 0; i < LZMA_FILTERS_MAX; ++i)
+			lzma_free(filters[i].options, allocator);
+
+		coder->block_options.filters = NULL;
+
+		// Check if memory usage calculation and Block enocoder
+		// initialization succeeded.
+		if (ret != LZMA_OK)
+			return ret;
+
+		coder->sequence = SEQ_BLOCK;
+	}
+
+	// Fall through
+
+	case SEQ_BLOCK: {
+		const lzma_ret ret = coder->block_decoder.code(
+				coder->block_decoder.coder, allocator,
+				in, in_pos, in_size, out, out_pos, out_size,
+				action);
+
+		if (ret != LZMA_STREAM_END)
+			return ret;
+
+		// Block decoded successfully. Add the new size pair to
+		// the Index hash.
+		return_if_error(lzma_index_hash_append(coder->index_hash,
+				lzma_block_unpadded_size(
+					&coder->block_options),
+				coder->block_options.uncompressed_size));
+
+		coder->sequence = SEQ_BLOCK_HEADER;
+		break;
+	}
+
+	case SEQ_INDEX: {
+		// If we don't have any input, don't call
+		// lzma_index_hash_decode() since it would return
+		// LZMA_BUF_ERROR, which we must not do here.
+		if (*in_pos >= in_size)
+			return LZMA_OK;
+
+		// Decode the Index and compare it to the hash calculated
+		// from the sizes of the Blocks (if any).
+		const lzma_ret ret = lzma_index_hash_decode(coder->index_hash,
+				in, in_pos, in_size);
+		if (ret != LZMA_STREAM_END)
+			return ret;
+
+		coder->sequence = SEQ_STREAM_FOOTER;
+	}
+
+	// Fall through
+
+	case SEQ_STREAM_FOOTER: {
+		// Copy the Stream Footer to the internal buffer.
+		lzma_bufcpy(in, in_pos, in_size, coder->buffer, &coder->pos,
+				LZMA_STREAM_HEADER_SIZE);
+
+		// Return if we didn't get the whole Stream Footer yet.
+		if (coder->pos < LZMA_STREAM_HEADER_SIZE)
+			return LZMA_OK;
+
+		coder->pos = 0;
+
+		// Decode the Stream Footer. The decoder gives
+		// LZMA_FORMAT_ERROR if the magic bytes don't match,
+		// so convert that return code to LZMA_DATA_ERROR.
+		lzma_stream_flags footer_flags;
+		const lzma_ret ret = lzma_stream_footer_decode(
+				&footer_flags, coder->buffer);
+		if (ret != LZMA_OK)
+			return ret == LZMA_FORMAT_ERROR
+					? LZMA_DATA_ERROR : ret;
+
+		// Check that Index Size stored in the Stream Footer matches
+		// the real size of the Index field.
+		if (lzma_index_hash_size(coder->index_hash)
+				!= footer_flags.backward_size)
+			return LZMA_DATA_ERROR;
+
+		// Compare that the Stream Flags fields are identical in
+		// both Stream Header and Stream Footer.
+		return_if_error(lzma_stream_flags_compare(
+				&coder->stream_flags, &footer_flags));
+
+		if (!coder->concatenated)
+			return LZMA_STREAM_END;
+
+		coder->sequence = SEQ_STREAM_PADDING;
+	}
+
+	// Fall through
+
+	case SEQ_STREAM_PADDING:
+		assert(coder->concatenated);
+
+		// Skip over possible Stream Padding.
+		while (true) {
+			if (*in_pos >= in_size) {
+				// Unless LZMA_FINISH was used, we cannot
+				// know if there's more input coming later.
+				if (action != LZMA_FINISH)
+					return LZMA_OK;
+
+				// Stream Padding must be a multiple of
+				// four bytes.
+				return coder->pos == 0
+						? LZMA_STREAM_END
+						: LZMA_DATA_ERROR;
+			}
+
+			// If the byte is not zero, it probably indicates
+			// beginning of a new Stream (or the file is corrupt).
+			if (in[*in_pos] != 0x00)
+				break;
+
+			++*in_pos;
+			coder->pos = (coder->pos + 1) & 3;
+		}
+
+		// Stream Padding must be a multiple of four bytes (empty
+		// Stream Padding is OK).
+		if (coder->pos != 0) {
+			++*in_pos;
+			return LZMA_DATA_ERROR;
+		}
+
+		// Prepare to decode the next Stream.
+		return_if_error(stream_decoder_reset(coder, allocator));
+		break;
+
+	default:
+		assert(0);
+		return LZMA_PROG_ERROR;
+	}
+
+	// Never reached
+}
+
+
+static void
+stream_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
+{
+	lzma_next_end(&coder->block_decoder, allocator);
+	lzma_index_hash_end(coder->index_hash, allocator);
+	lzma_free(coder, allocator);
+	return;
+}
+
+
+static lzma_check
+stream_decoder_get_check(const lzma_coder *coder)
+{
+	return coder->stream_flags.check;
+}
+
+
+static lzma_ret
+stream_decoder_memconfig(lzma_coder *coder, uint64_t *memusage,
+		uint64_t *old_memlimit, uint64_t new_memlimit)
+{
+	*memusage = coder->memusage;
+	*old_memlimit = coder->memlimit;
+
+	if (new_memlimit != 0) {
+		if (new_memlimit < coder->memusage)
+			return LZMA_MEMLIMIT_ERROR;
+
+		coder->memlimit = new_memlimit;
+	}
+
+	return LZMA_OK;
+}
+
+
+extern lzma_ret
+lzma_stream_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		uint64_t memlimit, uint32_t flags)
+{
+	lzma_next_coder_init(&lzma_stream_decoder_init, next, allocator);
+
+	if (memlimit == 0)
+		return LZMA_PROG_ERROR;
+
+	if (flags & ~LZMA_SUPPORTED_FLAGS)
+		return LZMA_OPTIONS_ERROR;
+
+	if (next->coder == NULL) {
+		next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+		if (next->coder == NULL)
+			return LZMA_MEM_ERROR;
+
+		next->code = &stream_decode;
+		next->end = &stream_decoder_end;
+		next->get_check = &stream_decoder_get_check;
+		next->memconfig = &stream_decoder_memconfig;
+
+		next->coder->block_decoder = LZMA_NEXT_CODER_INIT;
+		next->coder->index_hash = NULL;
+	}
+
+	next->coder->memlimit = memlimit;
+	next->coder->memusage = LZMA_MEMUSAGE_BASE;
+	next->coder->tell_no_check = (flags & LZMA_TELL_NO_CHECK) != 0;
+	next->coder->tell_unsupported_check
+			= (flags & LZMA_TELL_UNSUPPORTED_CHECK) != 0;
+	next->coder->tell_any_check = (flags & LZMA_TELL_ANY_CHECK) != 0;
+	next->coder->concatenated = (flags & LZMA_CONCATENATED) != 0;
+	next->coder->first_stream = true;
+
+	return stream_decoder_reset(next->coder, allocator);
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_stream_decoder(lzma_stream *strm, uint64_t memlimit, uint32_t flags)
+{
+	lzma_next_strm_init(lzma_stream_decoder_init, strm, memlimit, flags);
+
+	strm->internal->supported_actions[LZMA_RUN] = true;
+	strm->internal->supported_actions[LZMA_FINISH] = true;
+
+	return LZMA_OK;
+}
diff --git a/src/liblzma/common/stream_decoder.h b/src/liblzma/common/stream_decoder.h
new file mode 100644
index 0000000..e54ac28
--- /dev/null
+++ b/src/liblzma/common/stream_decoder.h
@@ -0,0 +1,21 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       stream_decoder.h
+/// \brief      Decodes .xz Streams
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_STREAM_DECODER_H
+#define LZMA_STREAM_DECODER_H
+
+#include "common.h"
+
+extern lzma_ret lzma_stream_decoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, uint64_t memlimit, uint32_t flags);
+
+#endif
diff --git a/src/liblzma/common/stream_encoder.c b/src/liblzma/common/stream_encoder.c
new file mode 100644
index 0000000..48d91da
--- /dev/null
+++ b/src/liblzma/common/stream_encoder.c
@@ -0,0 +1,331 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       stream_encoder.c
+/// \brief      Encodes .xz Streams
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "stream_encoder.h"
+#include "block_encoder.h"
+#include "index_encoder.h"
+
+
+struct lzma_coder_s {
+	enum {
+		SEQ_STREAM_HEADER,
+		SEQ_BLOCK_INIT,
+		SEQ_BLOCK_HEADER,
+		SEQ_BLOCK_ENCODE,
+		SEQ_INDEX_ENCODE,
+		SEQ_STREAM_FOOTER,
+	} sequence;
+
+	/// True if Block encoder has been initialized by
+	/// lzma_stream_encoder_init() or stream_encoder_update()
+	/// and thus doesn't need to be initialized in stream_encode().
+	bool block_encoder_is_initialized;
+
+	/// Block
+	lzma_next_coder block_encoder;
+
+	/// Options for the Block encoder
+	lzma_block block_options;
+
+	/// The filter chain currently in use
+	lzma_filter filters[LZMA_FILTERS_MAX + 1];
+
+	/// Index encoder. This is separate from Block encoder, because this
+	/// doesn't take much memory, and when encoding multiple Streams
+	/// with the same encoding options we avoid reallocating memory.
+	lzma_next_coder index_encoder;
+
+	/// Index to hold sizes of the Blocks
+	lzma_index *index;
+
+	/// Read position in buffer[]
+	size_t buffer_pos;
+
+	/// Total number of bytes in buffer[]
+	size_t buffer_size;
+
+	/// Buffer to hold Stream Header, Block Header, and Stream Footer.
+	/// Block Header has biggest maximum size.
+	uint8_t buffer[LZMA_BLOCK_HEADER_SIZE_MAX];
+};
+
+
+static lzma_ret
+block_encoder_init(lzma_coder *coder, lzma_allocator *allocator)
+{
+	// Prepare the Block options. Even though Block encoder doesn't need
+	// compressed_size, uncompressed_size, and header_size to be
+	// initialized, it is a good idea to do it here, because this way
+	// we catch if someone gave us Filter ID that cannot be used in
+	// Blocks/Streams.
+	coder->block_options.compressed_size = LZMA_VLI_UNKNOWN;
+	coder->block_options.uncompressed_size = LZMA_VLI_UNKNOWN;
+
+	return_if_error(lzma_block_header_size(&coder->block_options));
+
+	// Initialize the actual Block encoder.
+	return lzma_block_encoder_init(&coder->block_encoder, allocator,
+			&coder->block_options);
+}
+
+
+static lzma_ret
+stream_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)
+{
+	// Main loop
+	while (*out_pos < out_size)
+	switch (coder->sequence) {
+	case SEQ_STREAM_HEADER:
+	case SEQ_BLOCK_HEADER:
+	case SEQ_STREAM_FOOTER:
+		lzma_bufcpy(coder->buffer, &coder->buffer_pos,
+				coder->buffer_size, out, out_pos, out_size);
+		if (coder->buffer_pos < coder->buffer_size)
+			return LZMA_OK;
+
+		if (coder->sequence == SEQ_STREAM_FOOTER)
+			return LZMA_STREAM_END;
+
+		coder->buffer_pos = 0;
+		++coder->sequence;
+		break;
+
+	case SEQ_BLOCK_INIT: {
+		if (*in_pos == in_size) {
+			// If we are requested to flush or finish the current
+			// Block, return LZMA_STREAM_END immediately since
+			// there's nothing to do.
+			if (action != LZMA_FINISH)
+				return action == LZMA_RUN
+						? LZMA_OK : LZMA_STREAM_END;
+
+			// The application had used LZMA_FULL_FLUSH to finish
+			// the previous Block, but now wants to finish without
+			// encoding new data, or it is simply creating an
+			// empty Stream with no Blocks.
+			//
+			// Initialize the Index encoder, and continue to
+			// actually encoding the Index.
+			return_if_error(lzma_index_encoder_init(
+					&coder->index_encoder, allocator,
+					coder->index));
+			coder->sequence = SEQ_INDEX_ENCODE;
+			break;
+		}
+
+		// Initialize the Block encoder unless it was already
+		// initialized by lzma_stream_encoder_init() or
+		// stream_encoder_update().
+		if (!coder->block_encoder_is_initialized)
+			return_if_error(block_encoder_init(coder, allocator));
+
+		// Make it false so that we don't skip the initialization
+		// with the next Block.
+		coder->block_encoder_is_initialized = false;
+
+		// Encode the Block Header. This shouldn't fail since we have
+		// already initialized the Block encoder.
+		if (lzma_block_header_encode(&coder->block_options,
+				coder->buffer) != LZMA_OK)
+			return LZMA_PROG_ERROR;
+
+		coder->buffer_size = coder->block_options.header_size;
+		coder->sequence = SEQ_BLOCK_HEADER;
+		break;
+	}
+
+	case SEQ_BLOCK_ENCODE: {
+		static const lzma_action convert[4] = {
+			LZMA_RUN,
+			LZMA_SYNC_FLUSH,
+			LZMA_FINISH,
+			LZMA_FINISH,
+		};
+
+		const lzma_ret ret = coder->block_encoder.code(
+				coder->block_encoder.coder, allocator,
+				in, in_pos, in_size,
+				out, out_pos, out_size, convert[action]);
+		if (ret != LZMA_STREAM_END || action == LZMA_SYNC_FLUSH)
+			return ret;
+
+		// Add a new Index Record.
+		const lzma_vli unpadded_size = lzma_block_unpadded_size(
+				&coder->block_options);
+		assert(unpadded_size != 0);
+		return_if_error(lzma_index_append(coder->index, allocator,
+				unpadded_size,
+				coder->block_options.uncompressed_size));
+
+		coder->sequence = SEQ_BLOCK_INIT;
+		break;
+	}
+
+	case SEQ_INDEX_ENCODE: {
+		// Call the Index encoder. It doesn't take any input, so
+		// those pointers can be NULL.
+		const lzma_ret ret = coder->index_encoder.code(
+				coder->index_encoder.coder, allocator,
+				NULL, NULL, 0,
+				out, out_pos, out_size, LZMA_RUN);
+		if (ret != LZMA_STREAM_END)
+			return ret;
+
+		// Encode the Stream Footer into coder->buffer.
+		const lzma_stream_flags stream_flags = {
+			.version = 0,
+			.backward_size = lzma_index_size(coder->index),
+			.check = coder->block_options.check,
+		};
+
+		if (lzma_stream_footer_encode(&stream_flags, coder->buffer)
+				!= LZMA_OK)
+			return LZMA_PROG_ERROR;
+
+		coder->buffer_size = LZMA_STREAM_HEADER_SIZE;
+		coder->sequence = SEQ_STREAM_FOOTER;
+		break;
+	}
+
+	default:
+		assert(0);
+		return LZMA_PROG_ERROR;
+	}
+
+	return LZMA_OK;
+}
+
+
+static void
+stream_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
+{
+	lzma_next_end(&coder->block_encoder, allocator);
+	lzma_next_end(&coder->index_encoder, allocator);
+	lzma_index_end(coder->index, allocator);
+
+	for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
+		lzma_free(coder->filters[i].options, allocator);
+
+	lzma_free(coder, allocator);
+	return;
+}
+
+
+static lzma_ret
+stream_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
+		const lzma_filter *filters,
+		const lzma_filter *reversed_filters)
+{
+	if (coder->sequence <= SEQ_BLOCK_INIT) {
+		// There is no incomplete Block waiting to be finished,
+		// thus we can change the whole filter chain. Start by
+		// trying to initialize the Block encoder with the new
+		// chain. This way we detect if the chain is valid.
+		coder->block_encoder_is_initialized = false;
+		coder->block_options.filters = (lzma_filter *)(filters);
+		const lzma_ret ret = block_encoder_init(coder, allocator);
+		coder->block_options.filters = coder->filters;
+		if (ret != LZMA_OK)
+			return ret;
+
+		coder->block_encoder_is_initialized = true;
+
+	} else if (coder->sequence <= SEQ_BLOCK_ENCODE) {
+		// We are in the middle of a Block. Try to update only
+		// the filter-specific options.
+		return_if_error(coder->block_encoder.update(
+				coder->block_encoder.coder, allocator,
+				filters, reversed_filters));
+	} else {
+		// Trying to update the filter chain when we are already
+		// encoding Index or Stream Footer.
+		return LZMA_PROG_ERROR;
+	}
+
+	// Free the copy of the old chain and make a copy of the new chain.
+	for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
+		lzma_free(coder->filters[i].options, allocator);
+
+	return lzma_filters_copy(filters, coder->filters, allocator);
+}
+
+
+extern lzma_ret
+lzma_stream_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter *filters, lzma_check check)
+{
+	lzma_next_coder_init(&lzma_stream_encoder_init, next, allocator);
+
+	if (filters == NULL)
+		return LZMA_PROG_ERROR;
+
+	if (next->coder == NULL) {
+		next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+		if (next->coder == NULL)
+			return LZMA_MEM_ERROR;
+
+		next->code = &stream_encode;
+		next->end = &stream_encoder_end;
+		next->update = &stream_encoder_update;
+
+		next->coder->block_encoder = LZMA_NEXT_CODER_INIT;
+		next->coder->index_encoder = LZMA_NEXT_CODER_INIT;
+		next->coder->index = NULL;
+	}
+
+	// Basic initializations
+	next->coder->sequence = SEQ_STREAM_HEADER;
+	next->coder->block_options.version = 0;
+	next->coder->block_options.check = check;
+	next->coder->filters[0].id = LZMA_VLI_UNKNOWN;
+
+	// Initialize the Index
+	lzma_index_end(next->coder->index, allocator);
+	next->coder->index = lzma_index_init(allocator);
+	if (next->coder->index == NULL)
+		return LZMA_MEM_ERROR;
+
+	// Encode the Stream Header
+	lzma_stream_flags stream_flags = {
+		.version = 0,
+		.check = check,
+	};
+	return_if_error(lzma_stream_header_encode(
+			&stream_flags, next->coder->buffer));
+
+	next->coder->buffer_pos = 0;
+	next->coder->buffer_size = LZMA_STREAM_HEADER_SIZE;
+
+	// Initialize the Block encoder. This way we detect unsupported
+	// filter chains when initializing the Stream encoder instead of
+	// giving an error after Stream Header has already written out.
+	return stream_encoder_update(
+			next->coder, allocator, filters, NULL);
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_stream_encoder(lzma_stream *strm,
+		const lzma_filter *filters, lzma_check check)
+{
+	lzma_next_strm_init(lzma_stream_encoder_init, strm, filters, check);
+
+	strm->internal->supported_actions[LZMA_RUN] = true;
+	strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true;
+	strm->internal->supported_actions[LZMA_FULL_FLUSH] = true;
+	strm->internal->supported_actions[LZMA_FINISH] = true;
+
+	return LZMA_OK;
+}
diff --git a/src/liblzma/common/stream_encoder.h b/src/liblzma/common/stream_encoder.h
new file mode 100644
index 0000000..46a7aed
--- /dev/null
+++ b/src/liblzma/common/stream_encoder.h
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       stream_encoder.h
+/// \brief      Encodes .xz Streams
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_STREAM_ENCODER_H
+#define LZMA_STREAM_ENCODER_H
+
+#include "common.h"
+
+
+extern lzma_ret lzma_stream_encoder_init(
+		lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter *filters, lzma_check check);
+
+#endif
diff --git a/src/liblzma/common/stream_flags_common.c b/src/liblzma/common/stream_flags_common.c
new file mode 100644
index 0000000..fbe8eb8
--- /dev/null
+++ b/src/liblzma/common/stream_flags_common.c
@@ -0,0 +1,47 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       stream_flags_common.c
+/// \brief      Common stuff for Stream flags coders
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "stream_flags_common.h"
+
+
+const uint8_t lzma_header_magic[6] = { 0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00 };
+const uint8_t lzma_footer_magic[2] = { 0x59, 0x5A };
+
+
+extern LZMA_API(lzma_ret)
+lzma_stream_flags_compare(
+		const lzma_stream_flags *a, const lzma_stream_flags *b)
+{
+	// We can compare only version 0 structures.
+	if (a->version != 0 || b->version != 0)
+		return LZMA_OPTIONS_ERROR;
+
+	// Check type
+	if ((unsigned int)(a->check) > LZMA_CHECK_ID_MAX
+			|| (unsigned int)(b->check) > LZMA_CHECK_ID_MAX)
+		return LZMA_PROG_ERROR;
+
+	if (a->check != b->check)
+		return LZMA_DATA_ERROR;
+
+	// Backward Sizes are compared only if they are known in both.
+	if (a->backward_size != LZMA_VLI_UNKNOWN
+			&& b->backward_size != LZMA_VLI_UNKNOWN) {
+		if (!is_backward_size_valid(a) || !is_backward_size_valid(b))
+			return LZMA_PROG_ERROR;
+
+		if (a->backward_size != b->backward_size)
+			return LZMA_DATA_ERROR;
+	}
+
+	return LZMA_OK;
+}
diff --git a/src/liblzma/common/stream_flags_common.h b/src/liblzma/common/stream_flags_common.h
new file mode 100644
index 0000000..9f3122a
--- /dev/null
+++ b/src/liblzma/common/stream_flags_common.h
@@ -0,0 +1,33 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       stream_flags_common.h
+/// \brief      Common stuff for Stream flags coders
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_STREAM_FLAGS_COMMON_H
+#define LZMA_STREAM_FLAGS_COMMON_H
+
+#include "common.h"
+
+/// Size of the Stream Flags field
+#define LZMA_STREAM_FLAGS_SIZE 2
+
+extern const uint8_t lzma_header_magic[6];
+extern const uint8_t lzma_footer_magic[2];
+
+
+static inline bool
+is_backward_size_valid(const lzma_stream_flags *options)
+{
+	return options->backward_size >= LZMA_BACKWARD_SIZE_MIN
+			&& options->backward_size <= LZMA_BACKWARD_SIZE_MAX
+			&& (options->backward_size & 3) == 0;
+}
+
+#endif
diff --git a/src/liblzma/common/stream_flags_decoder.c b/src/liblzma/common/stream_flags_decoder.c
new file mode 100644
index 0000000..1bc2f97
--- /dev/null
+++ b/src/liblzma/common/stream_flags_decoder.c
@@ -0,0 +1,82 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       stream_flags_decoder.c
+/// \brief      Decodes Stream Header and Stream Footer from .xz files
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "stream_flags_common.h"
+
+
+static bool
+stream_flags_decode(lzma_stream_flags *options, const uint8_t *in)
+{
+	// Reserved bits must be unset.
+	if (in[0] != 0x00 || (in[1] & 0xF0))
+		return true;
+
+	options->version = 0;
+	options->check = in[1] & 0x0F;
+
+	return false;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_stream_header_decode(lzma_stream_flags *options, const uint8_t *in)
+{
+	// Magic
+	if (memcmp(in, lzma_header_magic, sizeof(lzma_header_magic)) != 0)
+		return LZMA_FORMAT_ERROR;
+
+	// Verify the CRC32 so we can distinguish between corrupt
+	// and unsupported files.
+	const uint32_t crc = lzma_crc32(in + sizeof(lzma_header_magic),
+			LZMA_STREAM_FLAGS_SIZE, 0);
+	if (crc != unaligned_read32le(in + sizeof(lzma_header_magic)
+			+ LZMA_STREAM_FLAGS_SIZE))
+		return LZMA_DATA_ERROR;
+
+	// Stream Flags
+	if (stream_flags_decode(options, in + sizeof(lzma_header_magic)))
+		return LZMA_OPTIONS_ERROR;
+
+	// Set Backward Size to indicate unknown value. That way
+	// lzma_stream_flags_compare() can be used to compare Stream Header
+	// and Stream Footer while keeping it useful also for comparing
+	// two Stream Footers.
+	options->backward_size = LZMA_VLI_UNKNOWN;
+
+	return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_stream_footer_decode(lzma_stream_flags *options, const uint8_t *in)
+{
+	// Magic
+	if (memcmp(in + sizeof(uint32_t) * 2 + LZMA_STREAM_FLAGS_SIZE,
+			lzma_footer_magic, sizeof(lzma_footer_magic)) != 0)
+		return LZMA_FORMAT_ERROR;
+
+	// CRC32
+	const uint32_t crc = lzma_crc32(in + sizeof(uint32_t),
+			sizeof(uint32_t) + LZMA_STREAM_FLAGS_SIZE, 0);
+	if (crc != unaligned_read32le(in))
+		return LZMA_DATA_ERROR;
+
+	// Stream Flags
+	if (stream_flags_decode(options, in + sizeof(uint32_t) * 2))
+		return LZMA_OPTIONS_ERROR;
+
+	// Backward Size
+	options->backward_size = unaligned_read32le(in + sizeof(uint32_t));
+	options->backward_size = (options->backward_size + 1) * 4;
+
+	return LZMA_OK;
+}
diff --git a/src/liblzma/common/stream_flags_encoder.c b/src/liblzma/common/stream_flags_encoder.c
new file mode 100644
index 0000000..4e71715
--- /dev/null
+++ b/src/liblzma/common/stream_flags_encoder.c
@@ -0,0 +1,86 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       stream_flags_encoder.c
+/// \brief      Encodes Stream Header and Stream Footer for .xz files
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "stream_flags_common.h"
+
+
+static bool
+stream_flags_encode(const lzma_stream_flags *options, uint8_t *out)
+{
+	if ((unsigned int)(options->check) > LZMA_CHECK_ID_MAX)
+		return true;
+
+	out[0] = 0x00;
+	out[1] = options->check;
+
+	return false;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_stream_header_encode(const lzma_stream_flags *options, uint8_t *out)
+{
+	assert(sizeof(lzma_header_magic) + LZMA_STREAM_FLAGS_SIZE
+			+ 4 == LZMA_STREAM_HEADER_SIZE);
+
+	if (options->version != 0)
+		return LZMA_OPTIONS_ERROR;
+
+	// Magic
+	memcpy(out, lzma_header_magic, sizeof(lzma_header_magic));
+
+	// Stream Flags
+	if (stream_flags_encode(options, out + sizeof(lzma_header_magic)))
+		return LZMA_PROG_ERROR;
+
+	// CRC32 of the Stream Header
+	const uint32_t crc = lzma_crc32(out + sizeof(lzma_header_magic),
+			LZMA_STREAM_FLAGS_SIZE, 0);
+
+	unaligned_write32le(out + sizeof(lzma_header_magic)
+			+ LZMA_STREAM_FLAGS_SIZE, crc);
+
+	return LZMA_OK;
+}
+
+
+extern LZMA_API(lzma_ret)
+lzma_stream_footer_encode(const lzma_stream_flags *options, uint8_t *out)
+{
+	assert(2 * 4 + LZMA_STREAM_FLAGS_SIZE + sizeof(lzma_footer_magic)
+			== LZMA_STREAM_HEADER_SIZE);
+
+	if (options->version != 0)
+		return LZMA_OPTIONS_ERROR;
+
+	// Backward Size
+	if (!is_backward_size_valid(options))
+		return LZMA_PROG_ERROR;
+
+	unaligned_write32le(out + 4, options->backward_size / 4 - 1);
+
+	// Stream Flags
+	if (stream_flags_encode(options, out + 2 * 4))
+		return LZMA_PROG_ERROR;
+
+	// CRC32
+	const uint32_t crc = lzma_crc32(
+			out + 4, 4 + LZMA_STREAM_FLAGS_SIZE, 0);
+
+	unaligned_write32le(out, crc);
+
+	// Magic
+	memcpy(out + 2 * 4 + LZMA_STREAM_FLAGS_SIZE,
+			lzma_footer_magic, sizeof(lzma_footer_magic));
+
+	return LZMA_OK;
+}
diff --git a/src/liblzma/common/vli_decoder.c b/src/liblzma/common/vli_decoder.c
new file mode 100644
index 0000000..c181828
--- /dev/null
+++ b/src/liblzma/common/vli_decoder.c
@@ -0,0 +1,86 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       vli_decoder.c
+/// \brief      Decodes variable-length integers
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+
+
+extern LZMA_API(lzma_ret)
+lzma_vli_decode(lzma_vli *restrict vli, size_t *vli_pos,
+		const uint8_t *restrict in, size_t *restrict in_pos,
+		size_t in_size)
+{
+	// If we haven't been given vli_pos, work in single-call mode.
+	size_t vli_pos_internal = 0;
+	if (vli_pos == NULL) {
+		vli_pos = &vli_pos_internal;
+		*vli = 0;
+
+		// If there's no input, use LZMA_DATA_ERROR. This way it is
+		// easy to decode VLIs from buffers that have known size,
+		// and get the correct error code in case the buffer is
+		// too short.
+		if (*in_pos >= in_size)
+			return LZMA_DATA_ERROR;
+
+	} else {
+		// Initialize *vli when starting to decode a new integer.
+		if (*vli_pos == 0)
+			*vli = 0;
+
+		// Validate the arguments.
+		if (*vli_pos >= LZMA_VLI_BYTES_MAX
+				|| (*vli >> (*vli_pos * 7)) != 0)
+			return LZMA_PROG_ERROR;;
+
+		if (*in_pos >= in_size)
+			return LZMA_BUF_ERROR;
+	}
+
+	do {
+		// Read the next byte. Use a temporary variable so that we
+		// can update *in_pos immediately.
+		const uint8_t byte = in[*in_pos];
+		++*in_pos;
+
+		// Add the newly read byte to *vli.
+		*vli += (lzma_vli)(byte & 0x7F) << (*vli_pos * 7);
+		++*vli_pos;
+
+		// Check if this is the last byte of a multibyte integer.
+		if ((byte & 0x80) == 0) {
+			// We don't allow using variable-length integers as
+			// padding i.e. the encoding must use the most the
+			// compact form.
+			if (byte == 0x00 && *vli_pos > 1)
+				return LZMA_DATA_ERROR;
+
+			return vli_pos == &vli_pos_internal
+					? LZMA_OK : LZMA_STREAM_END;
+		}
+
+		// There is at least one more byte coming. If we have already
+		// read maximum number of bytes, the integer is considered
+		// corrupt.
+		//
+		// If we need bigger integers in future, old versions liblzma
+		// will confusingly indicate the file being corrupt istead of
+		// unsupported. I suppose it's still better this way, because
+		// in the foreseeable future (writing this in 2008) the only
+		// reason why files would appear having over 63-bit integers
+		// is that the files are simply corrupt.
+		if (*vli_pos == LZMA_VLI_BYTES_MAX)
+			return LZMA_DATA_ERROR;
+
+	} while (*in_pos < in_size);
+
+	return vli_pos == &vli_pos_internal ? LZMA_DATA_ERROR : LZMA_OK;
+}
diff --git a/src/liblzma/common/vli_encoder.c b/src/liblzma/common/vli_encoder.c
new file mode 100644
index 0000000..f864269
--- /dev/null
+++ b/src/liblzma/common/vli_encoder.c
@@ -0,0 +1,69 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       vli_encoder.c
+/// \brief      Encodes variable-length integers
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+
+
+extern LZMA_API(lzma_ret)
+lzma_vli_encode(lzma_vli vli, size_t *vli_pos,
+		uint8_t *restrict out, size_t *restrict out_pos,
+		size_t out_size)
+{
+	// If we haven't been given vli_pos, work in single-call mode.
+	size_t vli_pos_internal = 0;
+	if (vli_pos == NULL) {
+		vli_pos = &vli_pos_internal;
+
+		// In single-call mode, we expect that the caller has
+		// reserved enough output space.
+		if (*out_pos >= out_size)
+			return LZMA_PROG_ERROR;
+	} else {
+		// This never happens when we are called by liblzma, but
+		// may happen if called directly from an application.
+		if (*out_pos >= out_size)
+			return LZMA_BUF_ERROR;
+	}
+
+	// Validate the arguments.
+	if (*vli_pos >= LZMA_VLI_BYTES_MAX || vli > LZMA_VLI_MAX)
+		return LZMA_PROG_ERROR;
+
+	// Shift vli so that the next bits to encode are the lowest. In
+	// single-call mode this never changes vli since *vli_pos is zero.
+	vli >>= *vli_pos * 7;
+
+	// Write the non-last bytes in a loop.
+	while (vli >= 0x80) {
+		// We don't need *vli_pos during this function call anymore,
+		// but update it here so that it is ready if we need to
+		// return before the whole integer has been decoded.
+		++*vli_pos;
+		assert(*vli_pos < LZMA_VLI_BYTES_MAX);
+
+		// Write the next byte.
+		out[*out_pos] = (uint8_t)(vli) | 0x80;
+		vli >>= 7;
+
+		if (++*out_pos == out_size)
+			return vli_pos == &vli_pos_internal
+					? LZMA_PROG_ERROR : LZMA_OK;
+	}
+
+	// Write the last byte.
+	out[*out_pos] = (uint8_t)(vli);
+	++*out_pos;
+	++*vli_pos;
+
+	return vli_pos == &vli_pos_internal ? LZMA_OK : LZMA_STREAM_END;
+
+}
diff --git a/src/liblzma/common/vli_size.c b/src/liblzma/common/vli_size.c
new file mode 100644
index 0000000..ec1b4fa
--- /dev/null
+++ b/src/liblzma/common/vli_size.c
@@ -0,0 +1,30 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       vli_size.c
+/// \brief      Calculates the encoded size of a variable-length integer
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+
+
+extern LZMA_API(uint32_t)
+lzma_vli_size(lzma_vli vli)
+{
+	if (vli > LZMA_VLI_MAX)
+		return 0;
+
+	uint32_t i = 0;
+	do {
+		vli >>= 7;
+		++i;
+	} while (vli != 0);
+
+	assert(i <= LZMA_VLI_BYTES_MAX);
+	return i;
+}
diff --git a/src/liblzma/delta/Makefile.inc b/src/liblzma/delta/Makefile.inc
new file mode 100644
index 0000000..c7739b4
--- /dev/null
+++ b/src/liblzma/delta/Makefile.inc
@@ -0,0 +1,23 @@
+##
+## Author: Lasse Collin
+##
+## This file has been put into the public domain.
+## You can do whatever you want with this file.
+##
+
+liblzma_la_SOURCES += \
+	delta/delta_common.c \
+	delta/delta_common.h \
+	delta/delta_private.h
+
+if COND_ENCODER_DELTA
+liblzma_la_SOURCES += \
+	delta/delta_encoder.c \
+	delta/delta_encoder.h
+endif
+
+if COND_DECODER_DELTA
+liblzma_la_SOURCES += \
+	delta/delta_decoder.c \
+	delta/delta_decoder.h
+endif
diff --git a/src/liblzma/delta/delta_common.c b/src/liblzma/delta/delta_common.c
new file mode 100644
index 0000000..930ad21
--- /dev/null
+++ b/src/liblzma/delta/delta_common.c
@@ -0,0 +1,70 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       delta_common.c
+/// \brief      Common stuff for Delta encoder and decoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "delta_common.h"
+#include "delta_private.h"
+
+
+static void
+delta_coder_end(lzma_coder *coder, lzma_allocator *allocator)
+{
+	lzma_next_end(&coder->next, allocator);
+	lzma_free(coder, allocator);
+	return;
+}
+
+
+extern lzma_ret
+lzma_delta_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters)
+{
+	// Allocate memory for the decoder if needed.
+	if (next->coder == NULL) {
+		next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+		if (next->coder == NULL)
+			return LZMA_MEM_ERROR;
+
+		// End function is the same for encoder and decoder.
+		next->end = &delta_coder_end;
+		next->coder->next = LZMA_NEXT_CODER_INIT;
+	}
+
+	// Validate the options.
+	if (lzma_delta_coder_memusage(filters[0].options) == UINT64_MAX)
+		return LZMA_OPTIONS_ERROR;
+
+	// Set the delta distance.
+	const lzma_options_delta *opt = filters[0].options;
+	next->coder->distance = opt->dist;
+
+	// Initialize the rest of the variables.
+	next->coder->pos = 0;
+	memzero(next->coder->history, LZMA_DELTA_DIST_MAX);
+
+	// Initialize the next decoder in the chain, if any.
+	return lzma_next_filter_init(&next->coder->next,
+			allocator, filters + 1);
+}
+
+
+extern uint64_t
+lzma_delta_coder_memusage(const void *options)
+{
+	const lzma_options_delta *opt = options;
+
+	if (opt == NULL || opt->type != LZMA_DELTA_TYPE_BYTE
+			|| opt->dist < LZMA_DELTA_DIST_MIN
+			|| opt->dist > LZMA_DELTA_DIST_MAX)
+		return UINT64_MAX;
+
+	return sizeof(lzma_coder);
+}
diff --git a/src/liblzma/delta/delta_common.h b/src/liblzma/delta/delta_common.h
new file mode 100644
index 0000000..7e7e1ba
--- /dev/null
+++ b/src/liblzma/delta/delta_common.h
@@ -0,0 +1,20 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       delta_common.h
+/// \brief      Common stuff for Delta encoder and decoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_DELTA_COMMON_H
+#define LZMA_DELTA_COMMON_H
+
+#include "common.h"
+
+extern uint64_t lzma_delta_coder_memusage(const void *options);
+
+#endif
diff --git a/src/liblzma/delta/delta_decoder.c b/src/liblzma/delta/delta_decoder.c
new file mode 100644
index 0000000..2cf60d5
--- /dev/null
+++ b/src/liblzma/delta/delta_decoder.c
@@ -0,0 +1,76 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       delta_decoder.c
+/// \brief      Delta filter decoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "delta_decoder.h"
+#include "delta_private.h"
+
+
+static void
+decode_buffer(lzma_coder *coder, uint8_t *buffer, size_t size)
+{
+	const size_t distance = coder->distance;
+
+	for (size_t i = 0; i < size; ++i) {
+		buffer[i] += coder->history[(distance + coder->pos) & 0xFF];
+		coder->history[coder->pos-- & 0xFF] = buffer[i];
+	}
+}
+
+
+static lzma_ret
+delta_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)
+{
+	assert(coder->next.code != NULL);
+
+	const size_t out_start = *out_pos;
+
+	const lzma_ret ret = coder->next.code(coder->next.coder, allocator,
+			in, in_pos, in_size, out, out_pos, out_size,
+			action);
+
+	decode_buffer(coder, out + out_start, *out_pos - out_start);
+
+	return ret;
+}
+
+
+extern lzma_ret
+lzma_delta_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters)
+{
+	next->code = &delta_decode;
+	return lzma_delta_coder_init(next, allocator, filters);
+}
+
+
+extern lzma_ret
+lzma_delta_props_decode(void **options, lzma_allocator *allocator,
+		const uint8_t *props, size_t props_size)
+{
+	if (props_size != 1)
+		return LZMA_OPTIONS_ERROR;
+
+	lzma_options_delta *opt
+			= lzma_alloc(sizeof(lzma_options_delta), allocator);
+	if (opt == NULL)
+		return LZMA_MEM_ERROR;
+
+	opt->type = LZMA_DELTA_TYPE_BYTE;
+	opt->dist = props[0] + 1;
+
+	*options = opt;
+
+	return LZMA_OK;
+}
diff --git a/src/liblzma/delta/delta_decoder.h b/src/liblzma/delta/delta_decoder.h
new file mode 100644
index 0000000..ae89acc
--- /dev/null
+++ b/src/liblzma/delta/delta_decoder.h
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       delta_decoder.h
+/// \brief      Delta filter decoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_DELTA_DECODER_H
+#define LZMA_DELTA_DECODER_H
+
+#include "delta_common.h"
+
+extern lzma_ret lzma_delta_decoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters);
+
+extern lzma_ret lzma_delta_props_decode(
+		void **options, lzma_allocator *allocator,
+		const uint8_t *props, size_t props_size);
+
+#endif
diff --git a/src/liblzma/delta/delta_encoder.c b/src/liblzma/delta/delta_encoder.c
new file mode 100644
index 0000000..ea1cc2c
--- /dev/null
+++ b/src/liblzma/delta/delta_encoder.c
@@ -0,0 +1,121 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       delta_encoder.c
+/// \brief      Delta filter encoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "delta_encoder.h"
+#include "delta_private.h"
+
+
+/// Copies and encodes the data at the same time. This is used when Delta
+/// is the first filter in the chain (and thus the last filter in the
+/// encoder's filter stack).
+static void
+copy_and_encode(lzma_coder *coder,
+		const uint8_t *restrict in, uint8_t *restrict out, size_t size)
+{
+	const size_t distance = coder->distance;
+
+	for (size_t i = 0; i < size; ++i) {
+		const uint8_t tmp = coder->history[
+				(distance + coder->pos) & 0xFF];
+		coder->history[coder->pos-- & 0xFF] = in[i];
+		out[i] = in[i] - tmp;
+	}
+}
+
+
+/// Encodes the data in place. This is used when we are the last filter
+/// in the chain (and thus non-last filter in the encoder's filter stack).
+static void
+encode_in_place(lzma_coder *coder, uint8_t *buffer, size_t size)
+{
+	const size_t distance = coder->distance;
+
+	for (size_t i = 0; i < size; ++i) {
+		const uint8_t tmp = coder->history[
+				(distance + coder->pos) & 0xFF];
+		coder->history[coder->pos-- & 0xFF] = buffer[i];
+		buffer[i] -= tmp;
+	}
+}
+
+
+static lzma_ret
+delta_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)
+{
+	lzma_ret ret;
+
+	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 = my_min(in_avail, out_avail);
+
+		copy_and_encode(coder, in + *in_pos, out + *out_pos, size);
+
+		*in_pos += size;
+		*out_pos += size;
+
+		ret = action != LZMA_RUN && *in_pos == in_size
+				? LZMA_STREAM_END : LZMA_OK;
+
+	} else {
+		const size_t out_start = *out_pos;
+
+		ret = coder->next.code(coder->next.coder, allocator,
+				in, in_pos, in_size, out, out_pos, out_size,
+				action);
+
+		encode_in_place(coder, out + out_start, *out_pos - out_start);
+	}
+
+	return ret;
+}
+
+
+static lzma_ret
+delta_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
+		const lzma_filter *filters_null lzma_attribute((unused)),
+		const lzma_filter *reversed_filters)
+{
+	// Delta doesn't and will never support changing the options in
+	// the middle of encoding. If the app tries to change them, we
+	// simply ignore them.
+	return lzma_next_filter_update(
+			&coder->next, allocator, reversed_filters + 1);
+}
+
+
+extern lzma_ret
+lzma_delta_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters)
+{
+	next->code = &delta_encode;
+	next->update = &delta_encoder_update;
+	return lzma_delta_coder_init(next, allocator, filters);
+}
+
+
+extern lzma_ret
+lzma_delta_props_encode(const void *options, uint8_t *out)
+{
+	// The caller must have already validated the options, so it's
+	// LZMA_PROG_ERROR if they are invalid.
+	if (lzma_delta_coder_memusage(options) == UINT64_MAX)
+		return LZMA_PROG_ERROR;
+
+	const lzma_options_delta *opt = options;
+	out[0] = opt->dist - LZMA_DELTA_DIST_MIN;
+
+	return LZMA_OK;
+}
diff --git a/src/liblzma/delta/delta_encoder.h b/src/liblzma/delta/delta_encoder.h
new file mode 100644
index 0000000..a447862
--- /dev/null
+++ b/src/liblzma/delta/delta_encoder.h
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       delta_encoder.h
+/// \brief      Delta filter encoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_DELTA_ENCODER_H
+#define LZMA_DELTA_ENCODER_H
+
+#include "delta_common.h"
+
+extern lzma_ret lzma_delta_encoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters);
+
+extern lzma_ret lzma_delta_props_encode(const void *options, uint8_t *out);
+
+#endif
diff --git a/src/liblzma/delta/delta_private.h b/src/liblzma/delta/delta_private.h
new file mode 100644
index 0000000..62b7fed
--- /dev/null
+++ b/src/liblzma/delta/delta_private.h
@@ -0,0 +1,37 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       delta_private.h
+/// \brief      Private common stuff for Delta encoder and decoder
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_DELTA_PRIVATE_H
+#define LZMA_DELTA_PRIVATE_H
+
+#include "delta_common.h"
+
+struct lzma_coder_s {
+	/// Next coder in the chain
+	lzma_next_coder next;
+
+	/// Delta distance
+	size_t distance;
+
+	/// Position in history[]
+	uint8_t pos;
+
+	/// Buffer to hold history of the original data
+	uint8_t history[LZMA_DELTA_DIST_MAX];
+};
+
+
+extern lzma_ret lzma_delta_coder_init(
+		lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters);
+
+#endif
diff --git a/src/liblzma/liblzma.pc.in b/src/liblzma/liblzma.pc.in
new file mode 100644
index 0000000..7f11f1a
--- /dev/null
+++ b/src/liblzma/liblzma.pc.in
@@ -0,0 +1,19 @@
+#
+# Author: Lasse Collin
+#
+# This file has been put into the public domain.
+# You can do whatever you want with this file.
+#
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: liblzma
+Description: General purpose data compression library
+URL: @PACKAGE_URL@
+Version: @PACKAGE_VERSION@
+Cflags: -I${includedir}
+Libs: -L${libdir} -llzma
+Libs.private: @PTHREAD_CFLAGS@ @PTHREAD_LIBS@
diff --git a/src/liblzma/liblzma_w32res.rc b/src/liblzma/liblzma_w32res.rc
new file mode 100644
index 0000000..d4d8159
--- /dev/null
+++ b/src/liblzma/liblzma_w32res.rc
@@ -0,0 +1,12 @@
+/*
+ * Author: Lasse Collin
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ */
+
+#define MY_TYPE VFT_DLL
+#define MY_NAME "liblzma"
+#define MY_SUFFIX ".dll"
+#define MY_DESC "liblzma data compression library"
+#include "common_w32res.rc"
diff --git a/src/liblzma/lz/Makefile.inc b/src/liblzma/lz/Makefile.inc
new file mode 100644
index 0000000..75742a8
--- /dev/null
+++ b/src/liblzma/lz/Makefile.inc
@@ -0,0 +1,22 @@
+##
+## Author: Lasse Collin
+##
+## This file has been put into the public domain.
+## You can do whatever you want with this file.
+##
+
+if COND_ENCODER_LZ
+liblzma_la_SOURCES += \
+	lz/lz_encoder.c \
+	lz/lz_encoder.h \
+	lz/lz_encoder_hash.h \
+	lz/lz_encoder_hash_table.h \
+	lz/lz_encoder_mf.c
+endif
+
+
+if COND_DECODER_LZ
+liblzma_la_SOURCES += \
+	lz/lz_decoder.c \
+	lz/lz_decoder.h
+endif
diff --git a/src/liblzma/lz/lz_decoder.c b/src/liblzma/lz/lz_decoder.c
new file mode 100644
index 0000000..2c57355
--- /dev/null
+++ b/src/liblzma/lz/lz_decoder.c
@@ -0,0 +1,300 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lz_decoder.c
+/// \brief      LZ out window
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// liblzma supports multiple LZ77-based filters. The LZ part is shared
+// between these filters. The LZ code takes care of dictionary handling
+// and passing the data between filters in the chain. The filter-specific
+// part decodes from the input buffer to the dictionary.
+
+
+#include "lz_decoder.h"
+
+
+struct lzma_coder_s {
+	/// Dictionary (history buffer)
+	lzma_dict dict;
+
+	/// The actual LZ-based decoder e.g. LZMA
+	lzma_lz_decoder lz;
+
+	/// Next filter in the chain, if any. Note that LZMA and LZMA2 are
+	/// only allowed as the last filter, but the long-range filter in
+	/// future can be in the middle of the chain.
+	lzma_next_coder next;
+
+	/// True if the next filter in the chain has returned LZMA_STREAM_END.
+	bool next_finished;
+
+	/// True if the LZ decoder (e.g. LZMA) has detected end of payload
+	/// marker. This may become true before next_finished becomes true.
+	bool this_finished;
+
+	/// Temporary buffer needed when the LZ-based 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
+	/// LZ-based decoder.
+	struct {
+		size_t pos;
+		size_t size;
+		uint8_t buffer[LZMA_BUFFER_SIZE];
+	} temp;
+};
+
+
+static void
+lz_decoder_reset(lzma_coder *coder)
+{
+	coder->dict.pos = 0;
+	coder->dict.full = 0;
+	coder->dict.buf[coder->dict.size - 1] = '\0';
+	coder->dict.need_reset = false;
+	return;
+}
+
+
+static lzma_ret
+decode_buffer(lzma_coder *coder,
+		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)
+{
+	while (true) {
+		// Wrap the dictionary if needed.
+		if (coder->dict.pos == coder->dict.size)
+			coder->dict.pos = 0;
+
+		// Store the current dictionary position. It is needed to know
+		// where to start copying to the out[] buffer.
+		const size_t dict_start = coder->dict.pos;
+
+		// Calculate how much we allow coder->lz.code() to decode.
+		// 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
+				+ 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(
+				coder->lz.coder, &coder->dict,
+				in, in_pos, in_size);
+
+		// Copy the decoded data from the dictionary to the out[]
+		// buffer.
+		const size_t copy_size = coder->dict.pos - dict_start;
+		assert(copy_size <= out_size - *out_pos);
+		memcpy(out + *out_pos, coder->dict.buf + dict_start,
+				copy_size);
+		*out_pos += copy_size;
+
+		// Reset the dictionary if so requested by coder->lz.code().
+		if (coder->dict.need_reset) {
+			lz_decoder_reset(coder);
+
+			// Since we reset dictionary, we don't check if
+			// dictionary became full.
+			if (ret != LZMA_OK || *out_pos == out_size)
+				return ret;
+		} else {
+			// Return if everything got decoded or an error
+			// occurred, or if there's no more data to decode.
+			//
+			// Note that detecting if there's something to decode
+			// is done by looking if dictionary become full
+			// instead of looking if *in_pos == in_size. This
+			// is because it is possible that all the input was
+			// consumed already but some data is pending to be
+			// written to the dictionary.
+			if (ret != LZMA_OK || *out_pos == out_size
+					|| coder->dict.pos < coder->dict.size)
+				return ret;
+		}
+	}
+}
+
+
+static lzma_ret
+lz_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)
+{
+	if (coder->next.code == NULL)
+		return decode_buffer(coder, in, in_pos, in_size,
+				out, out_pos, out_size);
+
+	// We aren't the last coder in the chain, we need to decode
+	// our input to a temporary buffer.
+	while (*out_pos < out_size) {
+		// Fill the temporary buffer if it is empty.
+		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 (ret != LZMA_OK || coder->temp.size == 0)
+				return ret;
+		}
+
+		if (coder->this_finished) {
+			if (coder->temp.size != 0)
+				return LZMA_DATA_ERROR;
+
+			if (coder->next_finished)
+				return LZMA_STREAM_END;
+
+			return LZMA_OK;
+		}
+
+		const lzma_ret ret = decode_buffer(coder, coder->temp.buffer,
+				&coder->temp.pos, coder->temp.size,
+				out, out_pos, out_size);
+
+		if (ret == LZMA_STREAM_END)
+			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
+lz_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
+{
+	lzma_next_end(&coder->next, allocator);
+	lzma_free(coder->dict.buf, allocator);
+
+	if (coder->lz.end != NULL)
+		coder->lz.end(coder->lz.coder, allocator);
+	else
+		lzma_free(coder->lz.coder, allocator);
+
+	lzma_free(coder, allocator);
+	return;
+}
+
+
+extern lzma_ret
+lzma_lz_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters,
+		lzma_ret (*lz_init)(lzma_lz_decoder *lz,
+			lzma_allocator *allocator, const void *options,
+			lzma_lz_options *lz_options))
+{
+	// Allocate the base structure if it isn't already allocated.
+	if (next->coder == NULL) {
+		next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+		if (next->coder == NULL)
+			return LZMA_MEM_ERROR;
+
+		next->code = &lz_decode;
+		next->end = &lz_decoder_end;
+
+		next->coder->dict.buf = NULL;
+		next->coder->dict.size = 0;
+		next->coder->lz = LZMA_LZ_DECODER_INIT;
+		next->coder->next = LZMA_NEXT_CODER_INIT;
+	}
+
+	// Allocate and initialize the LZ-based decoder. It will also give
+	// us the dictionary size.
+	lzma_lz_options lz_options;
+	return_if_error(lz_init(&next->coder->lz, allocator,
+			filters[0].options, &lz_options));
+
+	// If the dictionary size is very small, increase it to 4096 bytes.
+	// This is to prevent constant wrapping of the dictionary, which
+	// would slow things down. The downside is that since we don't check
+	// separately for the real dictionary size, we may happily accept
+	// corrupt files.
+	if (lz_options.dict_size < 4096)
+		lz_options.dict_size = 4096;
+
+	// Make dictionary size a multipe of 16. Some LZ-based decoders like
+	// LZMA use the lowest bits lzma_dict.pos to know the alignment of the
+	// data. Aligned buffer is also good when memcpying from the
+	// dictionary to the output buffer, since applications are
+	// recommended to give aligned buffers to liblzma.
+	//
+	// Avoid integer overflow.
+	if (lz_options.dict_size > SIZE_MAX - 15)
+		return LZMA_MEM_ERROR;
+
+	lz_options.dict_size = (lz_options.dict_size + 15) & ~((size_t)(15));
+
+	// Allocate and initialize the dictionary.
+	if (next->coder->dict.size != lz_options.dict_size) {
+		lzma_free(next->coder->dict.buf, allocator);
+		next->coder->dict.buf
+				= lzma_alloc(lz_options.dict_size, allocator);
+		if (next->coder->dict.buf == NULL)
+			return LZMA_MEM_ERROR;
+
+		next->coder->dict.size = lz_options.dict_size;
+	}
+
+	lz_decoder_reset(next->coder);
+
+	// Use the preset dictionary if it was given to us.
+	if (lz_options.preset_dict != NULL
+			&& 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 = 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,
+				copy_size);
+		next->coder->dict.pos = copy_size;
+		next->coder->dict.full = copy_size;
+	}
+
+	// Miscellaneous initializations
+	next->coder->next_finished = false;
+	next->coder->this_finished = false;
+	next->coder->temp.pos = 0;
+	next->coder->temp.size = 0;
+
+	// Initialize the next filter in the chain, if any.
+	return lzma_next_filter_init(&next->coder->next, allocator,
+			filters + 1);
+}
+
+
+extern uint64_t
+lzma_lz_decoder_memusage(size_t dictionary_size)
+{
+	return sizeof(lzma_coder) + (uint64_t)(dictionary_size);
+}
+
+
+extern void
+lzma_lz_decoder_uncompressed(lzma_coder *coder, lzma_vli uncompressed_size)
+{
+	coder->lz.set_uncompressed(coder->lz.coder, uncompressed_size);
+}
diff --git a/src/liblzma/lz/lz_decoder.h b/src/liblzma/lz/lz_decoder.h
new file mode 100644
index 0000000..7266e80
--- /dev/null
+++ b/src/liblzma/lz/lz_decoder.h
@@ -0,0 +1,234 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lz_decoder.h
+/// \brief      LZ out window
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_LZ_DECODER_H
+#define LZMA_LZ_DECODER_H
+
+#include "common.h"
+
+
+typedef struct {
+	/// Pointer to the dictionary buffer. It can be an allocated buffer
+	/// internal to liblzma, or it can a be a buffer given by the
+	/// application when in single-call mode (not implemented yet).
+	uint8_t *buf;
+
+	/// Write position in dictionary. The next byte will be written to
+	/// buf[pos].
+	size_t pos;
+
+	/// Indicates how full the dictionary is. This is used by
+	/// dict_is_distance_valid() to detect corrupt files that would
+	/// read beyond the beginning of the dictionary.
+	size_t full;
+
+	/// Write limit
+	size_t limit;
+
+	/// Size of the dictionary
+	size_t size;
+
+	/// True when dictionary should be reset before decoding more data.
+	bool need_reset;
+
+} lzma_dict;
+
+
+typedef struct {
+	size_t dict_size;
+	const uint8_t *preset_dict;
+	size_t preset_dict_size;
+} lzma_lz_options;
+
+
+typedef struct {
+	/// Data specific to the LZ-based decoder
+	lzma_coder *coder;
+
+	/// Function to decode from in[] to *dict
+	lzma_ret (*code)(lzma_coder *restrict coder,
+			lzma_dict *restrict dict, const uint8_t *restrict in,
+			size_t *restrict in_pos, size_t in_size);
+
+	void (*reset)(lzma_coder *coder, const void *options);
+
+	/// Set the uncompressed size
+	void (*set_uncompressed)(lzma_coder *coder,
+			lzma_vli uncompressed_size);
+
+	/// Free allocated resources
+	void (*end)(lzma_coder *coder, lzma_allocator *allocator);
+
+} lzma_lz_decoder;
+
+
+#define LZMA_LZ_DECODER_INIT \
+	(lzma_lz_decoder){ \
+		.coder = NULL, \
+		.code = NULL, \
+		.reset = NULL, \
+		.set_uncompressed = NULL, \
+		.end = NULL, \
+	}
+
+
+extern lzma_ret lzma_lz_decoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters,
+		lzma_ret (*lz_init)(lzma_lz_decoder *lz,
+			lzma_allocator *allocator, const void *options,
+			lzma_lz_options *lz_options));
+
+extern uint64_t lzma_lz_decoder_memusage(size_t dictionary_size);
+
+extern void lzma_lz_decoder_uncompressed(
+		lzma_coder *coder, lzma_vli uncompressed_size);
+
+
+//////////////////////
+// Inline functions //
+//////////////////////
+
+/// Get a byte from the history buffer.
+static inline uint8_t
+dict_get(const lzma_dict *const dict, const uint32_t distance)
+{
+	return dict->buf[dict->pos - distance - 1
+			+ (distance < dict->pos ? 0 : dict->size)];
+}
+
+
+/// Test if dictionary is empty.
+static inline bool
+dict_is_empty(const lzma_dict *const dict)
+{
+	return dict->full == 0;
+}
+
+
+/// Validate the match distance
+static inline bool
+dict_is_distance_valid(const lzma_dict *const dict, const size_t distance)
+{
+	return dict->full > distance;
+}
+
+
+/// Repeat *len bytes at distance.
+static inline bool
+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 = my_min(dict_avail, *len);
+	*len -= left;
+
+	// Repeat a block of data from the history. Because memcpy() is faster
+	// than copying byte by byte in a loop, the copying process gets split
+	// into three cases.
+	if (distance < left) {
+		// Source and target areas overlap, thus we can't use
+		// memcpy() nor even memmove() safely.
+		do {
+			dict->buf[dict->pos] = dict_get(dict, distance);
+			++dict->pos;
+		} while (--left > 0);
+
+	} else if (distance < dict->pos) {
+		// The easiest and fastest case
+		memcpy(dict->buf + dict->pos,
+				dict->buf + dict->pos - distance - 1,
+				left);
+		dict->pos += left;
+
+	} else {
+		// The bigger the dictionary, the more rare this
+		// case occurs. We need to "wrap" the dict, thus
+		// we might need two memcpy() to copy all the data.
+		assert(dict->full == dict->size);
+		const uint32_t copy_pos
+				= dict->pos - distance - 1 + dict->size;
+		uint32_t copy_size = dict->size - copy_pos;
+
+		if (copy_size < left) {
+			memmove(dict->buf + dict->pos, dict->buf + copy_pos,
+					copy_size);
+			dict->pos += copy_size;
+			copy_size = left - copy_size;
+			memcpy(dict->buf + dict->pos, dict->buf, copy_size);
+			dict->pos += copy_size;
+		} else {
+			memmove(dict->buf + dict->pos, dict->buf + copy_pos,
+					left);
+			dict->pos += left;
+		}
+	}
+
+	// Update how full the dictionary is.
+	if (dict->full < dict->pos)
+		dict->full = dict->pos;
+
+	return unlikely(*len != 0);
+}
+
+
+/// Puts one byte into the dictionary. Returns true if the dictionary was
+/// already full and the byte couldn't be added.
+static inline bool
+dict_put(lzma_dict *dict, uint8_t byte)
+{
+	if (unlikely(dict->pos == dict->limit))
+		return true;
+
+	dict->buf[dict->pos++] = byte;
+
+	if (dict->pos > dict->full)
+		dict->full = dict->pos;
+
+	return false;
+}
+
+
+/// Copies arbitrary amount of data into the dictionary.
+static inline void
+dict_write(lzma_dict *restrict dict, const uint8_t *restrict in,
+		size_t *restrict in_pos, size_t in_size,
+		size_t *restrict left)
+{
+	// NOTE: If we are being given more data than the size of the
+	// dictionary, it could be possible to optimize the LZ decoder
+	// so that not everything needs to go through the dictionary.
+	// This shouldn't be very common thing in practice though, and
+	// the slowdown of one extra memcpy() isn't bad compared to how
+	// much time it would have taken if the data were compressed.
+
+	if (in_size - *in_pos > *left)
+		in_size = *in_pos + *left;
+
+	*left -= lzma_bufcpy(in, in_pos, in_size,
+			dict->buf, &dict->pos, dict->limit);
+
+	if (dict->pos > dict->full)
+		dict->full = dict->pos;
+
+	return;
+}
+
+
+static inline void
+dict_reset(lzma_dict *dict)
+{
+	dict->need_reset = true;
+	return;
+}
+
+#endif
diff --git a/src/liblzma/lz/lz_encoder.c b/src/liblzma/lz/lz_encoder.c
new file mode 100644
index 0000000..9e980a2
--- /dev/null
+++ b/src/liblzma/lz/lz_encoder.c
@@ -0,0 +1,582 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lz_encoder.c
+/// \brief      LZ in window
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "lz_encoder.h"
+#include "lz_encoder_hash.h"
+
+// See lz_encoder_hash.h. This is a bit hackish but avoids making
+// endianness a conditional in makefiles.
+#if defined(WORDS_BIGENDIAN) && !defined(HAVE_SMALL)
+#	include "lz_encoder_hash_table.h"
+#endif
+
+
+struct lzma_coder_s {
+	/// LZ-based encoder e.g. LZMA
+	lzma_lz_encoder lz;
+
+	/// History buffer and match finder
+	lzma_mf mf;
+
+	/// Next coder in the chain
+	lzma_next_coder next;
+};
+
+
+/// \brief      Moves the data in the input window to free space for new data
+///
+/// mf->buffer is a sliding input window, which keeps mf->keep_size_before
+/// bytes of input history available all the time. Now and then we need to
+/// "slide" the buffer to make space for the new data to the end of the
+/// buffer. At the same time, data older than keep_size_before is dropped.
+///
+static void
+move_window(lzma_mf *mf)
+{
+	// Align the move to a multiple of 16 bytes. Some LZ-based encoders
+	// like LZMA use the lowest bits of mf->read_pos to know the
+	// alignment of the uncompressed data. We also get better speed
+	// for memmove() with aligned buffers.
+	assert(mf->read_pos > mf->keep_size_before);
+	const uint32_t move_offset
+		= (mf->read_pos - mf->keep_size_before) & ~UINT32_C(15);
+
+	assert(mf->write_pos > move_offset);
+	const size_t move_size = mf->write_pos - move_offset;
+
+	assert(move_offset + move_size <= mf->size);
+
+	memmove(mf->buffer, mf->buffer + move_offset, move_size);
+
+	mf->offset += move_offset;
+	mf->read_pos -= move_offset;
+	mf->read_limit -= move_offset;
+	mf->write_pos -= move_offset;
+
+	return;
+}
+
+
+/// \brief      Tries to fill the input window (mf->buffer)
+///
+/// If we are the last encoder in the chain, our input data is in in[].
+/// Otherwise we call the next filter in the chain to process in[] and
+/// write its output to mf->buffer.
+///
+/// This function must not be called once it has returned LZMA_STREAM_END.
+///
+static lzma_ret
+fill_window(lzma_coder *coder, lzma_allocator *allocator, const uint8_t *in,
+		size_t *in_pos, size_t in_size, lzma_action action)
+{
+	assert(coder->mf.read_pos <= coder->mf.write_pos);
+
+	// Move the sliding window if needed.
+	if (coder->mf.read_pos >= coder->mf.size - coder->mf.keep_size_after)
+		move_window(&coder->mf);
+
+	// Maybe this is ugly, but lzma_mf uses uint32_t for most things
+	// (which I find cleanest), but we need size_t here when filling
+	// the history window.
+	size_t write_pos = coder->mf.write_pos;
+	lzma_ret ret;
+	if (coder->next.code == NULL) {
+		// Not using a filter, simply memcpy() as much as possible.
+		lzma_bufcpy(in, in_pos, in_size, coder->mf.buffer,
+				&write_pos, coder->mf.size);
+
+		ret = action != LZMA_RUN && *in_pos == in_size
+				? LZMA_STREAM_END : LZMA_OK;
+
+	} else {
+		ret = coder->next.code(coder->next.coder, allocator,
+				in, in_pos, in_size,
+				coder->mf.buffer, &write_pos,
+				coder->mf.size, action);
+	}
+
+	coder->mf.write_pos = write_pos;
+
+	// If end of stream has been reached or flushing completed, we allow
+	// the encoder to process all the input (that is, read_pos is allowed
+	// to reach write_pos). Otherwise we keep keep_size_after bytes
+	// available as prebuffer.
+	if (ret == LZMA_STREAM_END) {
+		assert(*in_pos == in_size);
+		ret = LZMA_OK;
+		coder->mf.action = action;
+		coder->mf.read_limit = coder->mf.write_pos;
+
+	} else if (coder->mf.write_pos > coder->mf.keep_size_after) {
+		// This needs to be done conditionally, because if we got
+		// only little new input, there may be too little input
+		// to do any encoding yet.
+		coder->mf.read_limit = coder->mf.write_pos
+				- coder->mf.keep_size_after;
+	}
+
+	// Restart the match finder after finished LZMA_SYNC_FLUSH.
+	if (coder->mf.pending > 0
+			&& coder->mf.read_pos < coder->mf.read_limit) {
+		// Match finder may update coder->pending and expects it to
+		// start from zero, so use a temporary variable.
+		const size_t pending = coder->mf.pending;
+		coder->mf.pending = 0;
+
+		// Rewind read_pos so that the match finder can hash
+		// the pending bytes.
+		assert(coder->mf.read_pos >= pending);
+		coder->mf.read_pos -= pending;
+
+		// Call the skip function directly instead of using
+		// mf_skip(), since we don't want to touch mf->read_ahead.
+		coder->mf.skip(&coder->mf, pending);
+	}
+
+	return ret;
+}
+
+
+static lzma_ret
+lz_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)
+{
+	while (*out_pos < out_size
+			&& (*in_pos < in_size || action != LZMA_RUN)) {
+		// Read more data to coder->mf.buffer if needed.
+		if (coder->mf.action == LZMA_RUN && coder->mf.read_pos
+				>= coder->mf.read_limit)
+			return_if_error(fill_window(coder, allocator,
+					in, in_pos, in_size, action));
+
+		// Encode
+		const lzma_ret ret = coder->lz.code(coder->lz.coder,
+				&coder->mf, out, out_pos, out_size);
+		if (ret != LZMA_OK) {
+			// Setting this to LZMA_RUN for cases when we are
+			// flushing. It doesn't matter when finishing or if
+			// an error occurred.
+			coder->mf.action = LZMA_RUN;
+			return ret;
+		}
+	}
+
+	return LZMA_OK;
+}
+
+
+static bool
+lz_encoder_prepare(lzma_mf *mf, lzma_allocator *allocator,
+		const lzma_lz_options *lz_options)
+{
+	// For now, the dictionary size is limited to 1.5 GiB. This may grow
+	// in the future if needed, but it needs a little more work than just
+	// changing this check.
+	if (lz_options->dict_size < LZMA_DICT_SIZE_MIN
+			|| lz_options->dict_size
+				> (UINT32_C(1) << 30) + (UINT32_C(1) << 29)
+			|| lz_options->nice_len > lz_options->match_len_max)
+		return true;
+
+	mf->keep_size_before = lz_options->before_size + lz_options->dict_size;
+
+	mf->keep_size_after = lz_options->after_size
+			+ lz_options->match_len_max;
+
+	// To avoid constant memmove()s, allocate some extra space. Since
+	// memmove()s become more expensive when the size of the buffer
+	// increases, we reserve more space when a large dictionary is
+	// used to make the memmove() calls rarer.
+	//
+	// This works with dictionaries up to about 3 GiB. If bigger
+	// dictionary is wanted, some extra work is needed:
+	//   - Several variables in lzma_mf have to be changed from uint32_t
+	//     to size_t.
+	//   - Memory usage calculation needs something too, e.g. use uint64_t
+	//     for mf->size.
+	uint32_t reserve = lz_options->dict_size / 2;
+	if (reserve > (UINT32_C(1) << 30))
+		reserve /= 2;
+
+	reserve += (lz_options->before_size + lz_options->match_len_max
+			+ lz_options->after_size) / 2 + (UINT32_C(1) << 19);
+
+	const uint32_t old_size = mf->size;
+	mf->size = mf->keep_size_before + reserve + mf->keep_size_after;
+
+	// Deallocate the old history buffer if it exists but has different
+	// size than what is needed now.
+	if (mf->buffer != NULL && old_size != mf->size) {
+		lzma_free(mf->buffer, allocator);
+		mf->buffer = NULL;
+	}
+
+	// Match finder options
+	mf->match_len_max = lz_options->match_len_max;
+	mf->nice_len = lz_options->nice_len;
+
+	// cyclic_size has to stay smaller than 2 Gi. Note that this doesn't
+	// mean limiting dictionary size to less than 2 GiB. With a match
+	// finder that uses multibyte resolution (hashes start at e.g. every
+	// fourth byte), cyclic_size would stay below 2 Gi even when
+	// dictionary size is greater than 2 GiB.
+	//
+	// It would be possible to allow cyclic_size >= 2 Gi, but then we
+	// would need to be careful to use 64-bit types in various places
+	// (size_t could do since we would need bigger than 32-bit address
+	// space anyway). It would also require either zeroing a multigigabyte
+	// buffer at initialization (waste of time and RAM) or allow
+	// normalization in lz_encoder_mf.c to access uninitialized
+	// memory to keep the code simpler. The current way is simple and
+	// still allows pretty big dictionaries, so I don't expect these
+	// limits to change.
+	mf->cyclic_size = lz_options->dict_size + 1;
+
+	// Validate the match finder ID and setup the function pointers.
+	switch (lz_options->match_finder) {
+#ifdef HAVE_MF_HC3
+	case LZMA_MF_HC3:
+		mf->find = &lzma_mf_hc3_find;
+		mf->skip = &lzma_mf_hc3_skip;
+		break;
+#endif
+#ifdef HAVE_MF_HC4
+	case LZMA_MF_HC4:
+		mf->find = &lzma_mf_hc4_find;
+		mf->skip = &lzma_mf_hc4_skip;
+		break;
+#endif
+#ifdef HAVE_MF_BT2
+	case LZMA_MF_BT2:
+		mf->find = &lzma_mf_bt2_find;
+		mf->skip = &lzma_mf_bt2_skip;
+		break;
+#endif
+#ifdef HAVE_MF_BT3
+	case LZMA_MF_BT3:
+		mf->find = &lzma_mf_bt3_find;
+		mf->skip = &lzma_mf_bt3_skip;
+		break;
+#endif
+#ifdef HAVE_MF_BT4
+	case LZMA_MF_BT4:
+		mf->find = &lzma_mf_bt4_find;
+		mf->skip = &lzma_mf_bt4_skip;
+		break;
+#endif
+
+	default:
+		return true;
+	}
+
+	// Calculate the sizes of mf->hash and mf->son and check that
+	// nice_len is big enough for the selected match finder.
+	const uint32_t hash_bytes = lz_options->match_finder & 0x0F;
+	if (hash_bytes > mf->nice_len)
+		return true;
+
+	const bool is_bt = (lz_options->match_finder & 0x10) != 0;
+	uint32_t hs;
+
+	if (hash_bytes == 2) {
+		hs = 0xFFFF;
+	} else {
+		// Round dictionary size up to the next 2^n - 1 so it can
+		// be used as a hash mask.
+		hs = lz_options->dict_size - 1;
+		hs |= hs >> 1;
+		hs |= hs >> 2;
+		hs |= hs >> 4;
+		hs |= hs >> 8;
+		hs >>= 1;
+		hs |= 0xFFFF;
+
+		if (hs > (UINT32_C(1) << 24)) {
+			if (hash_bytes == 3)
+				hs = (UINT32_C(1) << 24) - 1;
+			else
+				hs >>= 1;
+		}
+	}
+
+	mf->hash_mask = hs;
+
+	++hs;
+	if (hash_bytes > 2)
+		hs += HASH_2_SIZE;
+	if (hash_bytes > 3)
+		hs += HASH_3_SIZE;
+/*
+	No match finder uses this at the moment.
+	if (mf->hash_bytes > 4)
+		hs += HASH_4_SIZE;
+*/
+
+	// If the above code calculating hs is modified, make sure that
+	// this assertion stays valid (UINT32_MAX / 5 is not strictly the
+	// exact limit). If it doesn't, you need to calculate that
+	// hash_size_sum + sons_count cannot overflow.
+	assert(hs < UINT32_MAX / 5);
+
+	const uint32_t old_count = mf->hash_size_sum + mf->sons_count;
+	mf->hash_size_sum = hs;
+	mf->sons_count = mf->cyclic_size;
+	if (is_bt)
+		mf->sons_count *= 2;
+
+	const uint32_t new_count = mf->hash_size_sum + mf->sons_count;
+
+	// Deallocate the old hash array if it exists and has different size
+	// than what is needed now.
+	if (old_count != new_count) {
+		lzma_free(mf->hash, allocator);
+		mf->hash = NULL;
+	}
+
+	// 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;
+	}
+
+	return false;
+}
+
+
+static bool
+lz_encoder_init(lzma_mf *mf, lzma_allocator *allocator,
+		const lzma_lz_options *lz_options)
+{
+	// Allocate the history buffer.
+	if (mf->buffer == NULL) {
+		mf->buffer = lzma_alloc(mf->size, allocator);
+		if (mf->buffer == NULL)
+			return true;
+	}
+
+	// Use cyclic_size as initial mf->offset. This allows
+	// avoiding a few branches in the match finders. The downside is
+	// that match finder needs to be normalized more often, which may
+	// hurt performance with huge dictionaries.
+	mf->offset = mf->cyclic_size;
+	mf->read_pos = 0;
+	mf->read_ahead = 0;
+	mf->read_limit = 0;
+	mf->write_pos = 0;
+	mf->pending = 0;
+
+	// Allocate match finder's hash array.
+	const size_t alloc_count = mf->hash_size_sum + mf->sons_count;
+
+#if UINT32_MAX >= SIZE_MAX / 4
+	// Check for integer overflow. (Huge dictionaries are not
+	// possible on 32-bit CPU.)
+	if (alloc_count > SIZE_MAX / sizeof(uint32_t))
+		return true;
+#endif
+
+	if (mf->hash == NULL) {
+		mf->hash = lzma_alloc(alloc_count * sizeof(uint32_t),
+				allocator);
+		if (mf->hash == NULL)
+			return true;
+	}
+
+	mf->son = mf->hash + mf->hash_size_sum;
+	mf->cyclic_pos = 0;
+
+	// Initialize the hash table. Since EMPTY_HASH_VALUE is zero, we
+	// can use memset().
+/*
+	for (uint32_t i = 0; i < hash_size_sum; ++i)
+		mf->hash[i] = EMPTY_HASH_VALUE;
+*/
+	memzero(mf->hash, (size_t)(mf->hash_size_sum) * sizeof(uint32_t));
+
+	// We don't need to initialize mf->son, but not doing that will
+	// make Valgrind complain in normalization (see normalize() in
+	// lz_encoder_mf.c).
+	//
+	// Skipping this initialization is *very* good when big dictionary is
+	// used but only small amount of data gets actually compressed: most
+	// of the mf->hash won't get actually allocated by the kernel, so
+	// we avoid wasting RAM and improve initialization speed a lot.
+	//memzero(mf->son, (size_t)(mf->sons_count) * sizeof(uint32_t));
+
+	// Handle preset dictionary.
+	if (lz_options->preset_dict != NULL
+			&& lz_options->preset_dict_size > 0) {
+		// If the preset dictionary is bigger than the actual
+		// dictionary, use only the tail.
+		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);
+		mf->action = LZMA_SYNC_FLUSH;
+		mf->skip(mf, mf->write_pos);
+	}
+
+	mf->action = LZMA_RUN;
+
+	return false;
+}
+
+
+extern uint64_t
+lzma_lz_encoder_memusage(const lzma_lz_options *lz_options)
+{
+	// Old buffers must not exist when calling lz_encoder_prepare().
+	lzma_mf mf = {
+		.buffer = NULL,
+		.hash = NULL,
+		.hash_size_sum = 0,
+		.sons_count = 0,
+	};
+
+	// Setup the size information into mf.
+	if (lz_encoder_prepare(&mf, NULL, lz_options))
+		return UINT64_MAX;
+
+	// Calculate the memory usage.
+	return (uint64_t)(mf.hash_size_sum + mf.sons_count)
+				* sizeof(uint32_t)
+			+ (uint64_t)(mf.size) + sizeof(lzma_coder);
+}
+
+
+static void
+lz_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
+{
+	lzma_next_end(&coder->next, allocator);
+
+	lzma_free(coder->mf.hash, allocator);
+	lzma_free(coder->mf.buffer, allocator);
+
+	if (coder->lz.end != NULL)
+		coder->lz.end(coder->lz.coder, allocator);
+	else
+		lzma_free(coder->lz.coder, allocator);
+
+	lzma_free(coder, allocator);
+	return;
+}
+
+
+static lzma_ret
+lz_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
+		const lzma_filter *filters_null lzma_attribute((unused)),
+		const lzma_filter *reversed_filters)
+{
+	if (coder->lz.options_update == NULL)
+		return LZMA_PROG_ERROR;
+
+	return_if_error(coder->lz.options_update(
+			coder->lz.coder, reversed_filters));
+
+	return lzma_next_filter_update(
+			&coder->next, allocator, reversed_filters + 1);
+}
+
+
+extern lzma_ret
+lzma_lz_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters,
+		lzma_ret (*lz_init)(lzma_lz_encoder *lz,
+			lzma_allocator *allocator, const void *options,
+			lzma_lz_options *lz_options))
+{
+#ifdef HAVE_SMALL
+	// We need that the CRC32 table has been initialized.
+	lzma_crc32_init();
+#endif
+
+	// Allocate and initialize the base data structure.
+	if (next->coder == NULL) {
+		next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+		if (next->coder == NULL)
+			return LZMA_MEM_ERROR;
+
+		next->code = &lz_encode;
+		next->end = &lz_encoder_end;
+		next->update = &lz_encoder_update;
+
+		next->coder->lz.coder = NULL;
+		next->coder->lz.code = NULL;
+		next->coder->lz.end = NULL;
+
+		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;
+	}
+
+	// Initialize the LZ-based encoder.
+	lzma_lz_options lz_options;
+	return_if_error(lz_init(&next->coder->lz, allocator,
+			filters[0].options, &lz_options));
+
+	// Setup the size information into next->coder->mf and deallocate
+	// old buffers if they have wrong size.
+	if (lz_encoder_prepare(&next->coder->mf, allocator, &lz_options))
+		return LZMA_OPTIONS_ERROR;
+
+	// Allocate new buffers if needed, and do the rest of
+	// the initialization.
+	if (lz_encoder_init(&next->coder->mf, allocator, &lz_options))
+		return LZMA_MEM_ERROR;
+
+	// Initialize the next filter in the chain, if any.
+	return lzma_next_filter_init(&next->coder->next, allocator,
+			filters + 1);
+}
+
+
+extern LZMA_API(lzma_bool)
+lzma_mf_is_supported(lzma_match_finder mf)
+{
+	bool ret = false;
+
+#ifdef HAVE_MF_HC3
+	if (mf == LZMA_MF_HC3)
+		ret = true;
+#endif
+
+#ifdef HAVE_MF_HC4
+	if (mf == LZMA_MF_HC4)
+		ret = true;
+#endif
+
+#ifdef HAVE_MF_BT2
+	if (mf == LZMA_MF_BT2)
+		ret = true;
+#endif
+
+#ifdef HAVE_MF_BT3
+	if (mf == LZMA_MF_BT3)
+		ret = true;
+#endif
+
+#ifdef HAVE_MF_BT4
+	if (mf == LZMA_MF_BT4)
+		ret = true;
+#endif
+
+	return ret;
+}
diff --git a/src/liblzma/lz/lz_encoder.h b/src/liblzma/lz/lz_encoder.h
new file mode 100644
index 0000000..741c453
--- /dev/null
+++ b/src/liblzma/lz/lz_encoder.h
@@ -0,0 +1,328 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lz_encoder.h
+/// \brief      LZ in window and match finder API
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_LZ_ENCODER_H
+#define LZMA_LZ_ENCODER_H
+
+#include "common.h"
+
+
+/// A table of these is used by the LZ-based encoder to hold
+/// the length-distance pairs found by the match finder.
+typedef struct {
+	uint32_t len;
+	uint32_t dist;
+} lzma_match;
+
+
+typedef struct lzma_mf_s lzma_mf;
+struct lzma_mf_s {
+	///////////////
+	// In Window //
+	///////////////
+
+	/// Pointer to buffer with data to be compressed
+	uint8_t *buffer;
+
+	/// Total size of the allocated buffer (that is, including all
+	/// the extra space)
+	uint32_t size;
+
+	/// Number of bytes that must be kept available in our input history.
+	/// That is, once keep_size_before bytes have been processed,
+	/// buffer[read_pos - keep_size_before] is the oldest byte that
+	/// must be available for reading.
+	uint32_t keep_size_before;
+
+	/// Number of bytes that must be kept in buffer after read_pos.
+	/// That is, read_pos <= write_pos - keep_size_after as long as
+	/// action is LZMA_RUN; when action != LZMA_RUN, read_pos is allowed
+	/// to reach write_pos so that the last bytes get encoded too.
+	uint32_t keep_size_after;
+
+	/// Match finders store locations of matches using 32-bit integers.
+	/// To avoid adjusting several megabytes of integers every time the
+	/// input window is moved with move_window, we only adjust the
+	/// offset of the buffer. Thus, buffer[value_in_hash_table - offset]
+	/// is the byte pointed by value_in_hash_table.
+	uint32_t offset;
+
+	/// buffer[read_pos] is the next byte to run through the match
+	/// finder. This is incremented in the match finder once the byte
+	/// has been processed.
+	uint32_t read_pos;
+
+	/// Number of bytes that have been ran through the match finder, but
+	/// which haven't been encoded by the LZ-based encoder yet.
+	uint32_t read_ahead;
+
+	/// As long as read_pos is less than read_limit, there is enough
+	/// input available in buffer for at least one encoding loop.
+	///
+	/// Because of the stateful API, read_limit may and will get greater
+	/// than read_pos quite often. This is taken into account when
+	/// calculating the value for keep_size_after.
+	uint32_t read_limit;
+
+	/// buffer[write_pos] is the first byte that doesn't contain valid
+	/// uncompressed data; that is, the next input byte will be copied
+	/// to buffer[write_pos].
+	uint32_t write_pos;
+
+	/// Number of bytes not hashed before read_pos. This is needed to
+	/// restart the match finder after LZMA_SYNC_FLUSH.
+	uint32_t pending;
+
+	//////////////////
+	// Match Finder //
+	//////////////////
+
+	/// Find matches. Returns the number of distance-length pairs written
+	/// to the matches array. This is called only via lzma_mf_find().
+	uint32_t (*find)(lzma_mf *mf, lzma_match *matches);
+
+	/// Skips num bytes. This is like find() but doesn't make the
+	/// distance-length pairs available, thus being a little faster.
+	/// This is called only via mf_skip().
+	void (*skip)(lzma_mf *mf, uint32_t num);
+
+	uint32_t *hash;
+	uint32_t *son;
+	uint32_t cyclic_pos;
+	uint32_t cyclic_size; // Must be dictionary size + 1.
+	uint32_t hash_mask;
+
+	/// Maximum number of loops in the match finder
+	uint32_t depth;
+
+	/// Maximum length of a match that the match finder will try to find.
+	uint32_t nice_len;
+
+	/// Maximum length of a match supported by the LZ-based encoder.
+	/// If the longest match found by the match finder is nice_len,
+	/// mf_find() tries to expand it up to match_len_max bytes.
+	uint32_t match_len_max;
+
+	/// When running out of input, binary tree match finders need to know
+	/// if it is due to flushing or finishing. The action is used also
+	/// by the LZ-based encoders themselves.
+	lzma_action action;
+
+	/// Number of elements in hash[]
+	uint32_t hash_size_sum;
+
+	/// Number of elements in son[]
+	uint32_t sons_count;
+};
+
+
+typedef struct {
+	/// Extra amount of data to keep available before the "actual"
+	/// dictionary.
+	size_t before_size;
+
+	/// Size of the history buffer
+	size_t dict_size;
+
+	/// Extra amount of data to keep available after the "actual"
+	/// dictionary.
+	size_t after_size;
+
+	/// Maximum length of a match that the LZ-based encoder can accept.
+	/// This is used to extend matches of length nice_len to the
+	/// maximum possible length.
+	size_t match_len_max;
+
+	/// Match finder will search matches up to this length.
+	/// This must be less than or equal to match_len_max.
+	size_t nice_len;
+
+	/// Type of the match finder to use
+	lzma_match_finder match_finder;
+
+	/// Maximum search depth
+	uint32_t depth;
+
+	/// TODO: Comment
+	const uint8_t *preset_dict;
+
+	uint32_t preset_dict_size;
+
+} lzma_lz_options;
+
+
+// The total usable buffer space at any moment outside the match finder:
+// before_size + dict_size + after_size + match_len_max
+//
+// In reality, there's some extra space allocated to prevent the number of
+// memmove() calls reasonable. The bigger the dict_size is, the bigger
+// this extra buffer will be since with bigger dictionaries memmove() would
+// also take longer.
+//
+// A single encoder loop in the LZ-based encoder may call the match finder
+// (mf_find() or mf_skip()) at most after_size times. In other words,
+// a single encoder loop may increment lzma_mf.read_pos at most after_size
+// times. Since matches are looked up to
+// lzma_mf.buffer[lzma_mf.read_pos + match_len_max - 1], the total
+// amount of extra buffer needed after dict_size becomes
+// after_size + match_len_max.
+//
+// before_size has two uses. The first one is to keep literals available
+// in cases when the LZ-based encoder has made some read ahead.
+// TODO: Maybe this could be changed by making the LZ-based encoders to
+// store the actual literals as they do with length-distance pairs.
+//
+// Algorithms such as LZMA2 first try to compress a chunk, and then check
+// if the encoded result is smaller than the uncompressed one. If the chunk
+// was uncompressible, it is better to store it in uncompressed form in
+// the output stream. To do this, the whole uncompressed chunk has to be
+// still available in the history buffer. before_size achieves that.
+
+
+typedef struct {
+	/// Data specific to the LZ-based encoder
+	lzma_coder *coder;
+
+	/// Function to encode from *dict to out[]
+	lzma_ret (*code)(lzma_coder *restrict coder,
+			lzma_mf *restrict mf, uint8_t *restrict out,
+			size_t *restrict out_pos, size_t out_size);
+
+	/// Free allocated resources
+	void (*end)(lzma_coder *coder, lzma_allocator *allocator);
+
+	/// Update the options in the middle of the encoding.
+	lzma_ret (*options_update)(lzma_coder *coder,
+			const lzma_filter *filter);
+
+} lzma_lz_encoder;
+
+
+// Basic steps:
+//  1. Input gets copied into the dictionary.
+//  2. Data in dictionary gets run through the match finder byte by byte.
+//  3. The literals and matches are encoded using e.g. LZMA.
+//
+// The bytes that have been ran through the match finder, but not encoded yet,
+// are called `read ahead'.
+
+
+/// Get pointer to the first byte not ran through the match finder
+static inline const uint8_t *
+mf_ptr(const lzma_mf *mf)
+{
+	return mf->buffer + mf->read_pos;
+}
+
+
+/// Get the number of bytes that haven't been ran through the match finder yet.
+static inline uint32_t
+mf_avail(const lzma_mf *mf)
+{
+	return mf->write_pos - mf->read_pos;
+}
+
+
+/// Get the number of bytes that haven't been encoded yet (some of these
+/// bytes may have been ran through the match finder though).
+static inline uint32_t
+mf_unencoded(const lzma_mf *mf)
+{
+	return mf->write_pos - mf->read_pos + mf->read_ahead;
+}
+
+
+/// Calculate the absolute offset from the beginning of the most recent
+/// dictionary reset. Only the lowest four bits are important, so there's no
+/// problem that we don't know the 64-bit size of the data encoded so far.
+///
+/// NOTE: When moving the input window, we need to do it so that the lowest
+/// bits of dict->read_pos are not modified to keep this macro working
+/// as intended.
+static inline uint32_t
+mf_position(const lzma_mf *mf)
+{
+	return mf->read_pos - mf->read_ahead;
+}
+
+
+/// Since everything else begins with mf_, use it also for lzma_mf_find().
+#define mf_find lzma_mf_find
+
+
+/// Skip the given number of bytes. This is used when a good match was found.
+/// For example, if mf_find() finds a match of 200 bytes long, the first byte
+/// of that match was already consumed by mf_find(), and the rest 199 bytes
+/// have to be skipped with mf_skip(mf, 199).
+static inline void
+mf_skip(lzma_mf *mf, uint32_t amount)
+{
+	if (amount != 0) {
+		mf->skip(mf, amount);
+		mf->read_ahead += amount;
+	}
+}
+
+
+/// Copies at most *left number of bytes from the history buffer
+/// to out[]. This is needed by LZMA2 to encode uncompressed chunks.
+static inline void
+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 = my_min(out_avail, *left);
+
+	assert(mf->read_ahead == 0);
+	assert(mf->read_pos >= *left);
+
+	memcpy(out + *out_pos, mf->buffer + mf->read_pos - *left,
+			copy_size);
+
+	*out_pos += copy_size;
+	*left -= copy_size;
+	return;
+}
+
+
+extern lzma_ret lzma_lz_encoder_init(
+		lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters,
+		lzma_ret (*lz_init)(lzma_lz_encoder *lz,
+			lzma_allocator *allocator, const void *options,
+			lzma_lz_options *lz_options));
+
+
+extern uint64_t lzma_lz_encoder_memusage(const lzma_lz_options *lz_options);
+
+
+// These are only for LZ encoder's internal use.
+extern uint32_t lzma_mf_find(
+		lzma_mf *mf, uint32_t *count, lzma_match *matches);
+
+extern uint32_t lzma_mf_hc3_find(lzma_mf *dict, lzma_match *matches);
+extern void lzma_mf_hc3_skip(lzma_mf *dict, uint32_t amount);
+
+extern uint32_t lzma_mf_hc4_find(lzma_mf *dict, lzma_match *matches);
+extern void lzma_mf_hc4_skip(lzma_mf *dict, uint32_t amount);
+
+extern uint32_t lzma_mf_bt2_find(lzma_mf *dict, lzma_match *matches);
+extern void lzma_mf_bt2_skip(lzma_mf *dict, uint32_t amount);
+
+extern uint32_t lzma_mf_bt3_find(lzma_mf *dict, lzma_match *matches);
+extern void lzma_mf_bt3_skip(lzma_mf *dict, uint32_t amount);
+
+extern uint32_t lzma_mf_bt4_find(lzma_mf *dict, lzma_match *matches);
+extern void lzma_mf_bt4_skip(lzma_mf *dict, uint32_t amount);
+
+#endif
diff --git a/src/liblzma/lz/lz_encoder_hash.h b/src/liblzma/lz/lz_encoder_hash.h
new file mode 100644
index 0000000..c398d7d
--- /dev/null
+++ b/src/liblzma/lz/lz_encoder_hash.h
@@ -0,0 +1,108 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lz_encoder_hash.h
+/// \brief      Hash macros for match finders
+//
+//  Author:     Igor Pavlov
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_LZ_ENCODER_HASH_H
+#define LZMA_LZ_ENCODER_HASH_H
+
+#if defined(WORDS_BIGENDIAN) && !defined(HAVE_SMALL)
+	// This is to make liblzma produce the same output on big endian
+	// systems that it does on little endian systems. lz_encoder.c
+	// takes care of including the actual table.
+	extern const uint32_t lzma_lz_hash_table[256];
+#	define hash_table lzma_lz_hash_table
+#else
+#	include "check.h"
+#	define hash_table lzma_crc32_table[0]
+#endif
+
+#define HASH_2_SIZE (UINT32_C(1) << 10)
+#define HASH_3_SIZE (UINT32_C(1) << 16)
+#define HASH_4_SIZE (UINT32_C(1) << 20)
+
+#define HASH_2_MASK (HASH_2_SIZE - 1)
+#define HASH_3_MASK (HASH_3_SIZE - 1)
+#define HASH_4_MASK (HASH_4_SIZE - 1)
+
+#define FIX_3_HASH_SIZE (HASH_2_SIZE)
+#define FIX_4_HASH_SIZE (HASH_2_SIZE + HASH_3_SIZE)
+#define FIX_5_HASH_SIZE (HASH_2_SIZE + HASH_3_SIZE + HASH_4_SIZE)
+
+// Endianness doesn't matter in hash_2_calc() (no effect on the output).
+#ifdef TUKLIB_FAST_UNALIGNED_ACCESS
+#	define hash_2_calc() \
+		const uint32_t hash_value = *(const uint16_t *)(cur);
+#else
+#	define hash_2_calc() \
+		const uint32_t hash_value \
+			= (uint32_t)(cur[0]) | ((uint32_t)(cur[1]) << 8)
+#endif
+
+#define hash_3_calc() \
+	const uint32_t temp = hash_table[cur[0]] ^ cur[1]; \
+	const uint32_t hash_2_value = temp & HASH_2_MASK; \
+	const uint32_t hash_value \
+			= (temp ^ ((uint32_t)(cur[2]) << 8)) & mf->hash_mask
+
+#define hash_4_calc() \
+	const uint32_t temp = hash_table[cur[0]] ^ cur[1]; \
+	const uint32_t hash_2_value = temp & HASH_2_MASK; \
+	const uint32_t hash_3_value \
+			= (temp ^ ((uint32_t)(cur[2]) << 8)) & HASH_3_MASK; \
+	const uint32_t hash_value = (temp ^ ((uint32_t)(cur[2]) << 8) \
+			^ (hash_table[cur[3]] << 5)) & mf->hash_mask
+
+
+// The following are not currently used.
+
+#define hash_5_calc() \
+	const uint32_t temp = hash_table[cur[0]] ^ cur[1]; \
+	const uint32_t hash_2_value = temp & HASH_2_MASK; \
+	const uint32_t hash_3_value \
+			= (temp ^ ((uint32_t)(cur[2]) << 8)) & HASH_3_MASK; \
+	uint32_t hash_4_value = (temp ^ ((uint32_t)(cur[2]) << 8) ^ \
+			^ hash_table[cur[3]] << 5); \
+	const uint32_t hash_value \
+			= (hash_4_value ^ (hash_table[cur[4]] << 3)) \
+				& mf->hash_mask; \
+	hash_4_value &= HASH_4_MASK
+
+/*
+#define hash_zip_calc() \
+	const uint32_t hash_value \
+			= (((uint32_t)(cur[0]) | ((uint32_t)(cur[1]) << 8)) \
+				^ hash_table[cur[2]]) & 0xFFFF
+*/
+
+#define hash_zip_calc() \
+	const uint32_t hash_value \
+			= (((uint32_t)(cur[2]) | ((uint32_t)(cur[0]) << 8)) \
+				^ hash_table[cur[1]]) & 0xFFFF
+
+#define mt_hash_2_calc() \
+	const uint32_t hash_2_value \
+			= (hash_table[cur[0]] ^ cur[1]) & HASH_2_MASK
+
+#define mt_hash_3_calc() \
+	const uint32_t temp = hash_table[cur[0]] ^ cur[1]; \
+	const uint32_t hash_2_value = temp & HASH_2_MASK; \
+	const uint32_t hash_3_value \
+			= (temp ^ ((uint32_t)(cur[2]) << 8)) & HASH_3_MASK
+
+#define mt_hash_4_calc() \
+	const uint32_t temp = hash_table[cur[0]] ^ cur[1]; \
+	const uint32_t hash_2_value = temp & HASH_2_MASK; \
+	const uint32_t hash_3_value \
+			= (temp ^ ((uint32_t)(cur[2]) << 8)) & HASH_3_MASK; \
+	const uint32_t hash_4_value = (temp ^ ((uint32_t)(cur[2]) << 8) ^ \
+			(hash_table[cur[3]] << 5)) & HASH_4_MASK
+
+#endif
diff --git a/src/liblzma/lz/lz_encoder_hash_table.h b/src/liblzma/lz/lz_encoder_hash_table.h
new file mode 100644
index 0000000..8c51717
--- /dev/null
+++ b/src/liblzma/lz/lz_encoder_hash_table.h
@@ -0,0 +1,68 @@
+/* This file has been automatically generated by crc32_tablegen.c. */
+
+const uint32_t lzma_lz_hash_table[256] = {
+	0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
+	0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
+	0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
+	0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
+	0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
+	0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
+	0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
+	0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
+	0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
+	0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
+	0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
+	0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
+	0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
+	0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
+	0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
+	0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
+	0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
+	0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
+	0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
+	0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
+	0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
+	0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
+	0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
+	0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
+	0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
+	0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
+	0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
+	0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
+	0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
+	0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
+	0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
+	0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
+	0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
+	0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
+	0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
+	0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
+	0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
+	0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
+	0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
+	0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
+	0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
+	0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
+	0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
+	0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
+	0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
+	0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
+	0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
+	0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
+	0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
+	0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
+	0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
+	0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
+	0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
+	0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
+	0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
+	0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
+	0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
+	0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
+	0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
+	0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
+	0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
+	0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
+	0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
+	0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
+};
diff --git a/src/liblzma/lz/lz_encoder_mf.c b/src/liblzma/lz/lz_encoder_mf.c
new file mode 100644
index 0000000..f82a1c1
--- /dev/null
+++ b/src/liblzma/lz/lz_encoder_mf.c
@@ -0,0 +1,753 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lz_encoder_mf.c
+/// \brief      Match finders
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "lz_encoder.h"
+#include "lz_encoder_hash.h"
+
+
+/// \brief      Find matches starting from the current byte
+///
+/// \return     The length of the longest match found
+extern uint32_t
+lzma_mf_find(lzma_mf *mf, uint32_t *count_ptr, lzma_match *matches)
+{
+	// Call the match finder. It returns the number of length-distance
+	// pairs found.
+	// FIXME: Minimum count is zero, what _exactly_ is the maximum?
+	const uint32_t count = mf->find(mf, matches);
+
+	// Length of the longest match; assume that no matches were found
+	// and thus the maximum length is zero.
+	uint32_t len_best = 0;
+
+	if (count > 0) {
+#ifndef NDEBUG
+		// Validate the matches.
+		for (uint32_t i = 0; i < count; ++i) {
+			assert(matches[i].len <= mf->nice_len);
+			assert(matches[i].dist < mf->read_pos);
+			assert(memcmp(mf_ptr(mf) - 1,
+				mf_ptr(mf) - matches[i].dist - 2,
+				matches[i].len) == 0);
+		}
+#endif
+
+		// The last used element in the array contains
+		// the longest match.
+		len_best = matches[count - 1].len;
+
+		// If a match of maximum search length was found, try to
+		// extend the match to maximum possible length.
+		if (len_best == mf->nice_len) {
+			// The limit for the match length is either the
+			// maximum match length supported by the LZ-based
+			// encoder or the number of bytes left in the
+			// dictionary, whichever is smaller.
+			uint32_t limit = mf_avail(mf) + 1;
+			if (limit > mf->match_len_max)
+				limit = mf->match_len_max;
+
+			// Pointer to the byte we just ran through
+			// the match finder.
+			const uint8_t *p1 = mf_ptr(mf) - 1;
+
+			// Pointer to the beginning of the match. We need -1
+			// here because the match distances are zero based.
+			const uint8_t *p2 = p1 - matches[count - 1].dist - 1;
+
+			while (len_best < limit
+					&& p1[len_best] == p2[len_best])
+				++len_best;
+		}
+	}
+
+	*count_ptr = count;
+
+	// Finally update the read position to indicate that match finder was
+	// run for this dictionary offset.
+	++mf->read_ahead;
+
+	return len_best;
+}
+
+
+/// Hash value to indicate unused element in the hash. Since we start the
+/// positions from dict_size + 1, zero is always too far to qualify
+/// as usable match position.
+#define EMPTY_HASH_VALUE 0
+
+
+/// Normalization must be done when lzma_mf.offset + lzma_mf.read_pos
+/// reaches MUST_NORMALIZE_POS.
+#define MUST_NORMALIZE_POS UINT32_MAX
+
+
+/// \brief      Normalizes hash values
+///
+/// The hash arrays store positions of match candidates. The positions are
+/// relative to an arbitrary offset that is not the same as the absolute
+/// offset in the input stream. The relative position of the current byte
+/// is lzma_mf.offset + lzma_mf.read_pos. The distances of the matches are
+/// the differences of the current read position and the position found from
+/// the hash.
+///
+/// To prevent integer overflows of the offsets stored in the hash arrays,
+/// we need to "normalize" the stored values now and then. During the
+/// normalization, we drop values that indicate distance greater than the
+/// dictionary size, thus making space for new values.
+static void
+normalize(lzma_mf *mf)
+{
+	assert(mf->read_pos + mf->offset == MUST_NORMALIZE_POS);
+
+	// In future we may not want to touch the lowest bits, because there
+	// may be match finders that use larger resolution than one byte.
+	const uint32_t subvalue
+			= (MUST_NORMALIZE_POS - mf->cyclic_size);
+				// & (~(UINT32_C(1) << 10) - 1);
+
+	const uint32_t count = mf->hash_size_sum + mf->sons_count;
+	uint32_t *hash = mf->hash;
+
+	for (uint32_t i = 0; i < count; ++i) {
+		// If the distance is greater than the dictionary size,
+		// we can simply mark the hash element as empty.
+		//
+		// NOTE: Only the first mf->hash_size_sum elements are
+		// initialized for sure. There may be uninitialized elements
+		// in mf->son. Since we go through both mf->hash and
+		// mf->son here in normalization, Valgrind may complain
+		// that the "if" below depends on uninitialized value. In
+		// this case it is safe to ignore the warning. See also the
+		// comments in lz_encoder_init() in lz_encoder.c.
+		if (hash[i] <= subvalue)
+			hash[i] = EMPTY_HASH_VALUE;
+		else
+			hash[i] -= subvalue;
+	}
+
+	// Update offset to match the new locations.
+	mf->offset -= subvalue;
+
+	return;
+}
+
+
+/// Mark the current byte as processed from point of view of the match finder.
+static void
+move_pos(lzma_mf *mf)
+{
+	if (++mf->cyclic_pos == mf->cyclic_size)
+		mf->cyclic_pos = 0;
+
+	++mf->read_pos;
+	assert(mf->read_pos <= mf->write_pos);
+
+	if (unlikely(mf->read_pos + mf->offset == UINT32_MAX))
+		normalize(mf);
+}
+
+
+/// When flushing, we cannot run the match finder unless there is nice_len
+/// bytes available in the dictionary. Instead, we skip running the match
+/// finder (indicating that no match was found), and count how many bytes we
+/// have ignored this way.
+///
+/// When new data is given after the flushing was completed, the match finder
+/// is restarted by rewinding mf->read_pos backwards by mf->pending. Then
+/// the missed bytes are added to the hash using the match finder's skip
+/// function (with small amount of input, it may start using mf->pending
+/// again if flushing).
+///
+/// Due to this rewinding, we don't touch cyclic_pos or test for
+/// normalization. It will be done when the match finder's skip function
+/// catches up after a flush.
+static void
+move_pending(lzma_mf *mf)
+{
+	++mf->read_pos;
+	assert(mf->read_pos <= mf->write_pos);
+	++mf->pending;
+}
+
+
+/// Calculate len_limit and determine if there is enough input to run
+/// the actual match finder code. Sets up "cur" and "pos". This macro
+/// is used by all find functions and binary tree skip functions. Hash
+/// chain skip function doesn't need len_limit so a simpler code is used
+/// in them.
+#define header(is_bt, len_min, ret_op) \
+	uint32_t len_limit = mf_avail(mf); \
+	if (mf->nice_len <= len_limit) { \
+		len_limit = mf->nice_len; \
+	} else if (len_limit < (len_min) \
+			|| (is_bt && mf->action == LZMA_SYNC_FLUSH)) { \
+		assert(mf->action != LZMA_RUN); \
+		move_pending(mf); \
+		ret_op; \
+	} \
+	const uint8_t *cur = mf_ptr(mf); \
+	const uint32_t pos = mf->read_pos + mf->offset
+
+
+/// Header for find functions. "return 0" indicates that zero matches
+/// were found.
+#define header_find(is_bt, len_min) \
+	header(is_bt, len_min, return 0); \
+	uint32_t matches_count = 0
+
+
+/// Header for a loop in a skip function. "continue" tells to skip the rest
+/// of the code in the loop.
+#define header_skip(is_bt, len_min) \
+	header(is_bt, len_min, continue)
+
+
+/// Calls hc_find_func() or bt_find_func() and calculates the total number
+/// of matches found. Updates the dictionary position and returns the number
+/// of matches found.
+#define call_find(func, len_best) \
+do { \
+	matches_count = func(len_limit, pos, cur, cur_match, mf->depth, \
+				mf->son, mf->cyclic_pos, mf->cyclic_size, \
+				matches + matches_count, len_best) \
+			- matches; \
+	move_pos(mf); \
+	return matches_count; \
+} while (0)
+
+
+////////////////
+// Hash Chain //
+////////////////
+
+#if defined(HAVE_MF_HC3) || defined(HAVE_MF_HC4)
+///
+///
+/// \param      len_limit       Don't look for matches longer than len_limit.
+/// \param      pos             lzma_mf.read_pos + lzma_mf.offset
+/// \param      cur             Pointer to current byte (mf_ptr(mf))
+/// \param      cur_match       Start position of the current match candidate
+/// \param      depth           Maximum length of the hash chain
+/// \param      son             lzma_mf.son (contains the hash chain)
+/// \param      cyclic_pos
+/// \param      cyclic_size
+/// \param      matches         Array to hold the matches.
+/// \param      len_best        The length of the longest match found so far.
+static lzma_match *
+hc_find_func(
+		const uint32_t len_limit,
+		const uint32_t pos,
+		const uint8_t *const cur,
+		uint32_t cur_match,
+		uint32_t depth,
+		uint32_t *const son,
+		const uint32_t cyclic_pos,
+		const uint32_t cyclic_size,
+		lzma_match *matches,
+		uint32_t len_best)
+{
+	son[cyclic_pos] = cur_match;
+
+	while (true) {
+		const uint32_t delta = pos - cur_match;
+		if (depth-- == 0 || delta >= cyclic_size)
+			return matches;
+
+		const uint8_t *const pb = cur - delta;
+		cur_match = son[cyclic_pos - delta
+				+ (delta > cyclic_pos ? cyclic_size : 0)];
+
+		if (pb[len_best] == cur[len_best] && pb[0] == cur[0]) {
+			uint32_t len = 0;
+			while (++len != len_limit)
+				if (pb[len] != cur[len])
+					break;
+
+			if (len_best < len) {
+				len_best = len;
+				matches->len = len;
+				matches->dist = delta - 1;
+				++matches;
+
+				if (len == len_limit)
+					return matches;
+			}
+		}
+	}
+}
+
+
+#define hc_find(len_best) \
+	call_find(hc_find_func, len_best)
+
+
+#define hc_skip() \
+do { \
+	mf->son[mf->cyclic_pos] = cur_match; \
+	move_pos(mf); \
+} while (0)
+
+#endif
+
+
+#ifdef HAVE_MF_HC3
+extern uint32_t
+lzma_mf_hc3_find(lzma_mf *mf, lzma_match *matches)
+{
+	header_find(false, 3);
+
+	hash_3_calc();
+
+	const uint32_t delta2 = pos - mf->hash[hash_2_value];
+	const uint32_t cur_match = mf->hash[FIX_3_HASH_SIZE + hash_value];
+
+	mf->hash[hash_2_value] = pos;
+	mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
+
+	uint32_t len_best = 2;
+
+	if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
+		for ( ; len_best != len_limit; ++len_best)
+			if (*(cur + len_best - delta2) != cur[len_best])
+				break;
+
+		matches[0].len = len_best;
+		matches[0].dist = delta2 - 1;
+		matches_count = 1;
+
+		if (len_best == len_limit) {
+			hc_skip();
+			return 1; // matches_count
+		}
+	}
+
+	hc_find(len_best);
+}
+
+
+extern void
+lzma_mf_hc3_skip(lzma_mf *mf, uint32_t amount)
+{
+	do {
+		if (mf_avail(mf) < 3) {
+			move_pending(mf);
+			continue;
+		}
+
+		const uint8_t *cur = mf_ptr(mf);
+		const uint32_t pos = mf->read_pos + mf->offset;
+
+		hash_3_calc();
+
+		const uint32_t cur_match
+				= mf->hash[FIX_3_HASH_SIZE + hash_value];
+
+		mf->hash[hash_2_value] = pos;
+		mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
+
+		hc_skip();
+
+	} while (--amount != 0);
+}
+#endif
+
+
+#ifdef HAVE_MF_HC4
+extern uint32_t
+lzma_mf_hc4_find(lzma_mf *mf, lzma_match *matches)
+{
+	header_find(false, 4);
+
+	hash_4_calc();
+
+	uint32_t delta2 = pos - mf->hash[hash_2_value];
+	const uint32_t delta3
+			= pos - mf->hash[FIX_3_HASH_SIZE + hash_3_value];
+	const uint32_t cur_match = mf->hash[FIX_4_HASH_SIZE + hash_value];
+
+	mf->hash[hash_2_value ] = pos;
+	mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
+	mf->hash[FIX_4_HASH_SIZE + hash_value] = pos;
+
+	uint32_t len_best = 1;
+
+	if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
+		len_best = 2;
+		matches[0].len = 2;
+		matches[0].dist = delta2 - 1;
+		matches_count = 1;
+	}
+
+	if (delta2 != delta3 && delta3 < mf->cyclic_size
+			&& *(cur - delta3) == *cur) {
+		len_best = 3;
+		matches[matches_count++].dist = delta3 - 1;
+		delta2 = delta3;
+	}
+
+	if (matches_count != 0) {
+		for ( ; len_best != len_limit; ++len_best)
+			if (*(cur + len_best - delta2) != cur[len_best])
+				break;
+
+		matches[matches_count - 1].len = len_best;
+
+		if (len_best == len_limit) {
+			hc_skip();
+			return matches_count;
+		}
+	}
+
+	if (len_best < 3)
+		len_best = 3;
+
+	hc_find(len_best);
+}
+
+
+extern void
+lzma_mf_hc4_skip(lzma_mf *mf, uint32_t amount)
+{
+	do {
+		if (mf_avail(mf) < 4) {
+			move_pending(mf);
+			continue;
+		}
+
+		const uint8_t *cur = mf_ptr(mf);
+		const uint32_t pos = mf->read_pos + mf->offset;
+
+		hash_4_calc();
+
+		const uint32_t cur_match
+				= mf->hash[FIX_4_HASH_SIZE + hash_value];
+
+		mf->hash[hash_2_value] = pos;
+		mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
+		mf->hash[FIX_4_HASH_SIZE + hash_value] = pos;
+
+		hc_skip();
+
+	} while (--amount != 0);
+}
+#endif
+
+
+/////////////////
+// Binary Tree //
+/////////////////
+
+#if defined(HAVE_MF_BT2) || defined(HAVE_MF_BT3) || defined(HAVE_MF_BT4)
+static lzma_match *
+bt_find_func(
+		const uint32_t len_limit,
+		const uint32_t pos,
+		const uint8_t *const cur,
+		uint32_t cur_match,
+		uint32_t depth,
+		uint32_t *const son,
+		const uint32_t cyclic_pos,
+		const uint32_t cyclic_size,
+		lzma_match *matches,
+		uint32_t len_best)
+{
+	uint32_t *ptr0 = son + (cyclic_pos << 1) + 1;
+	uint32_t *ptr1 = son + (cyclic_pos << 1);
+
+	uint32_t len0 = 0;
+	uint32_t len1 = 0;
+
+	while (true) {
+		const uint32_t delta = pos - cur_match;
+		if (depth-- == 0 || delta >= cyclic_size) {
+			*ptr0 = EMPTY_HASH_VALUE;
+			*ptr1 = EMPTY_HASH_VALUE;
+			return matches;
+		}
+
+		uint32_t *const pair = son + ((cyclic_pos - delta
+				+ (delta > cyclic_pos ? cyclic_size : 0))
+				<< 1);
+
+		const uint8_t *const pb = cur - delta;
+		uint32_t len = my_min(len0, len1);
+
+		if (pb[len] == cur[len]) {
+			while (++len != len_limit)
+				if (pb[len] != cur[len])
+					break;
+
+			if (len_best < len) {
+				len_best = len;
+				matches->len = len;
+				matches->dist = delta - 1;
+				++matches;
+
+				if (len == len_limit) {
+					*ptr1 = pair[0];
+					*ptr0 = pair[1];
+					return matches;
+				}
+			}
+		}
+
+		if (pb[len] < cur[len]) {
+			*ptr1 = cur_match;
+			ptr1 = pair + 1;
+			cur_match = *ptr1;
+			len1 = len;
+		} else {
+			*ptr0 = cur_match;
+			ptr0 = pair;
+			cur_match = *ptr0;
+			len0 = len;
+		}
+	}
+}
+
+
+static void
+bt_skip_func(
+		const uint32_t len_limit,
+		const uint32_t pos,
+		const uint8_t *const cur,
+		uint32_t cur_match,
+		uint32_t depth,
+		uint32_t *const son,
+		const uint32_t cyclic_pos,
+		const uint32_t cyclic_size)
+{
+	uint32_t *ptr0 = son + (cyclic_pos << 1) + 1;
+	uint32_t *ptr1 = son + (cyclic_pos << 1);
+
+	uint32_t len0 = 0;
+	uint32_t len1 = 0;
+
+	while (true) {
+		const uint32_t delta = pos - cur_match;
+		if (depth-- == 0 || delta >= cyclic_size) {
+			*ptr0 = EMPTY_HASH_VALUE;
+			*ptr1 = EMPTY_HASH_VALUE;
+			return;
+		}
+
+		uint32_t *pair = son + ((cyclic_pos - delta
+				+ (delta > cyclic_pos ? cyclic_size : 0))
+				<< 1);
+		const uint8_t *pb = cur - delta;
+		uint32_t len = my_min(len0, len1);
+
+		if (pb[len] == cur[len]) {
+			while (++len != len_limit)
+				if (pb[len] != cur[len])
+					break;
+
+			if (len == len_limit) {
+				*ptr1 = pair[0];
+				*ptr0 = pair[1];
+				return;
+			}
+		}
+
+		if (pb[len] < cur[len]) {
+			*ptr1 = cur_match;
+			ptr1 = pair + 1;
+			cur_match = *ptr1;
+			len1 = len;
+		} else {
+			*ptr0 = cur_match;
+			ptr0 = pair;
+			cur_match = *ptr0;
+			len0 = len;
+		}
+	}
+}
+
+
+#define bt_find(len_best) \
+	call_find(bt_find_func, len_best)
+
+#define bt_skip() \
+do { \
+	bt_skip_func(len_limit, pos, cur, cur_match, mf->depth, \
+			mf->son, mf->cyclic_pos, \
+			mf->cyclic_size); \
+	move_pos(mf); \
+} while (0)
+
+#endif
+
+
+#ifdef HAVE_MF_BT2
+extern uint32_t
+lzma_mf_bt2_find(lzma_mf *mf, lzma_match *matches)
+{
+	header_find(true, 2);
+
+	hash_2_calc();
+
+	const uint32_t cur_match = mf->hash[hash_value];
+	mf->hash[hash_value] = pos;
+
+	bt_find(1);
+}
+
+
+extern void
+lzma_mf_bt2_skip(lzma_mf *mf, uint32_t amount)
+{
+	do {
+		header_skip(true, 2);
+
+		hash_2_calc();
+
+		const uint32_t cur_match = mf->hash[hash_value];
+		mf->hash[hash_value] = pos;
+
+		bt_skip();
+
+	} while (--amount != 0);
+}
+#endif
+
+
+#ifdef HAVE_MF_BT3
+extern uint32_t
+lzma_mf_bt3_find(lzma_mf *mf, lzma_match *matches)
+{
+	header_find(true, 3);
+
+	hash_3_calc();
+
+	const uint32_t delta2 = pos - mf->hash[hash_2_value];
+	const uint32_t cur_match = mf->hash[FIX_3_HASH_SIZE + hash_value];
+
+	mf->hash[hash_2_value] = pos;
+	mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
+
+	uint32_t len_best = 2;
+
+	if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
+		for ( ; len_best != len_limit; ++len_best)
+			if (*(cur + len_best - delta2) != cur[len_best])
+				break;
+
+		matches[0].len = len_best;
+		matches[0].dist = delta2 - 1;
+		matches_count = 1;
+
+		if (len_best == len_limit) {
+			bt_skip();
+			return 1; // matches_count
+		}
+	}
+
+	bt_find(len_best);
+}
+
+
+extern void
+lzma_mf_bt3_skip(lzma_mf *mf, uint32_t amount)
+{
+	do {
+		header_skip(true, 3);
+
+		hash_3_calc();
+
+		const uint32_t cur_match
+				= mf->hash[FIX_3_HASH_SIZE + hash_value];
+
+		mf->hash[hash_2_value] = pos;
+		mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
+
+		bt_skip();
+
+	} while (--amount != 0);
+}
+#endif
+
+
+#ifdef HAVE_MF_BT4
+extern uint32_t
+lzma_mf_bt4_find(lzma_mf *mf, lzma_match *matches)
+{
+	header_find(true, 4);
+
+	hash_4_calc();
+
+	uint32_t delta2 = pos - mf->hash[hash_2_value];
+	const uint32_t delta3
+			= pos - mf->hash[FIX_3_HASH_SIZE + hash_3_value];
+	const uint32_t cur_match = mf->hash[FIX_4_HASH_SIZE + hash_value];
+
+	mf->hash[hash_2_value] = pos;
+	mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
+	mf->hash[FIX_4_HASH_SIZE + hash_value] = pos;
+
+	uint32_t len_best = 1;
+
+	if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
+		len_best = 2;
+		matches[0].len = 2;
+		matches[0].dist = delta2 - 1;
+		matches_count = 1;
+	}
+
+	if (delta2 != delta3 && delta3 < mf->cyclic_size
+			&& *(cur - delta3) == *cur) {
+		len_best = 3;
+		matches[matches_count++].dist = delta3 - 1;
+		delta2 = delta3;
+	}
+
+	if (matches_count != 0) {
+		for ( ; len_best != len_limit; ++len_best)
+			if (*(cur + len_best - delta2) != cur[len_best])
+				break;
+
+		matches[matches_count - 1].len = len_best;
+
+		if (len_best == len_limit) {
+			bt_skip();
+			return matches_count;
+		}
+	}
+
+	if (len_best < 3)
+		len_best = 3;
+
+	bt_find(len_best);
+}
+
+
+extern void
+lzma_mf_bt4_skip(lzma_mf *mf, uint32_t amount)
+{
+	do {
+		header_skip(true, 4);
+
+		hash_4_calc();
+
+		const uint32_t cur_match
+				= mf->hash[FIX_4_HASH_SIZE + hash_value];
+
+		mf->hash[hash_2_value] = pos;
+		mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
+		mf->hash[FIX_4_HASH_SIZE + hash_value] = pos;
+
+		bt_skip();
+
+	} while (--amount != 0);
+}
+#endif
diff --git a/src/liblzma/lzma/Makefile.inc b/src/liblzma/lzma/Makefile.inc
new file mode 100644
index 0000000..7fc4d17
--- /dev/null
+++ b/src/liblzma/lzma/Makefile.inc
@@ -0,0 +1,43 @@
+##
+## Author: Lasse Collin
+##
+## This file has been put into the public domain.
+## You can do whatever you want with this file.
+##
+
+EXTRA_DIST += lzma/fastpos_tablegen.c
+
+liblzma_la_SOURCES += lzma/lzma_common.h
+
+if COND_ENCODER_LZMA1
+liblzma_la_SOURCES += \
+	lzma/fastpos.h \
+	lzma/lzma_encoder.h \
+	lzma/lzma_encoder.c \
+	lzma/lzma_encoder_presets.c \
+	lzma/lzma_encoder_private.h \
+	lzma/lzma_encoder_optimum_fast.c \
+	lzma/lzma_encoder_optimum_normal.c
+
+if !COND_SMALL
+liblzma_la_SOURCES += lzma/fastpos_table.c
+endif
+endif
+
+if COND_DECODER_LZMA1
+liblzma_la_SOURCES += \
+	lzma/lzma_decoder.c \
+	lzma/lzma_decoder.h
+endif
+
+if COND_ENCODER_LZMA2
+liblzma_la_SOURCES += \
+	lzma/lzma2_encoder.c \
+	lzma/lzma2_encoder.h
+endif
+
+if COND_DECODER_LZMA2
+liblzma_la_SOURCES += \
+	lzma/lzma2_decoder.c \
+	lzma/lzma2_decoder.h
+endif
diff --git a/src/liblzma/lzma/fastpos.h b/src/liblzma/lzma/fastpos.h
new file mode 100644
index 0000000..4aea231
--- /dev/null
+++ b/src/liblzma/lzma/fastpos.h
@@ -0,0 +1,140 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       fastpos.h
+/// \brief      Kind of two-bit version of bit scan reverse
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_FASTPOS_H
+#define LZMA_FASTPOS_H
+
+// LZMA encodes match distances (positions) by storing the highest two
+// bits using a six-bit value [0, 63], and then the missing lower bits.
+// Dictionary size is also stored using this encoding in the new .lzma
+// file format header.
+//
+// fastpos.h provides a way to quickly find out the correct six-bit
+// values. The following table gives some examples of this encoding:
+//
+//      pos   return
+//       0       0
+//       1       1
+//       2       2
+//       3       3
+//       4       4
+//       5       4
+//       6       5
+//       7       5
+//       8       6
+//      11       6
+//      12       7
+//     ...      ...
+//      15       7
+//      16       8
+//      17       8
+//     ...      ...
+//      23       8
+//      24       9
+//      25       9
+//     ...      ...
+//
+//
+// Provided functions or macros
+// ----------------------------
+//
+// get_pos_slot(pos) is the basic version. get_pos_slot_2(pos)
+// assumes that pos >= FULL_DISTANCES, thus the result is at least
+// FULL_DISTANCES_BITS * 2. Using get_pos_slot(pos) instead of
+// get_pos_slot_2(pos) would give the same result, but get_pos_slot_2(pos)
+// should be tiny bit faster due to the assumption being made.
+//
+//
+// Size vs. speed
+// --------------
+//
+// With some CPUs that have fast BSR (bit scan reverse) instruction, the
+// size optimized version is slightly faster than the bigger table based
+// approach. Such CPUs include Intel Pentium Pro, Pentium II, Pentium III
+// and Core 2 (possibly others). AMD K7 seems to have slower BSR, but that
+// would still have speed roughly comparable to the table version. Older
+// x86 CPUs like the original Pentium have very slow BSR; on those systems
+// the table version is a lot faster.
+//
+// On some CPUs, the table version is a lot faster when using position
+// dependent code, but with position independent code the size optimized
+// version is slightly faster. This occurs at least on 32-bit SPARC (no
+// ASM optimizations).
+//
+// I'm making the table version the default, because that has good speed
+// on all systems I have tried. The size optimized version is sometimes
+// slightly faster, but sometimes it is a lot slower.
+
+#ifdef HAVE_SMALL
+#	define get_pos_slot(pos) ((pos) <= 4 ? (pos) : get_pos_slot_2(pos))
+
+static inline uint32_t
+get_pos_slot_2(uint32_t pos)
+{
+	const uint32_t i = bsr32(pos);
+	return (i + i) + ((pos >> (i - 1)) & 1);
+}
+
+
+#else
+
+#define FASTPOS_BITS 13
+
+extern const uint8_t lzma_fastpos[1 << FASTPOS_BITS];
+
+
+#define fastpos_shift(extra, n) \
+	((extra) + (n) * (FASTPOS_BITS - 1))
+
+#define fastpos_limit(extra, n) \
+	(UINT32_C(1) << (FASTPOS_BITS + fastpos_shift(extra, n)))
+
+#define fastpos_result(pos, extra, n) \
+	lzma_fastpos[(pos) >> fastpos_shift(extra, n)] \
+			+ 2 * fastpos_shift(extra, n)
+
+
+static inline uint32_t
+get_pos_slot(uint32_t pos)
+{
+	// If it is small enough, we can pick the result directly from
+	// the precalculated table.
+	if (pos < fastpos_limit(0, 0))
+		return lzma_fastpos[pos];
+
+	if (pos < fastpos_limit(0, 1))
+		return fastpos_result(pos, 0, 1);
+
+	return fastpos_result(pos, 0, 2);
+}
+
+
+#ifdef FULL_DISTANCES_BITS
+static inline uint32_t
+get_pos_slot_2(uint32_t pos)
+{
+	assert(pos >= FULL_DISTANCES);
+
+	if (pos < fastpos_limit(FULL_DISTANCES_BITS - 1, 0))
+		return fastpos_result(pos, FULL_DISTANCES_BITS - 1, 0);
+
+	if (pos < fastpos_limit(FULL_DISTANCES_BITS - 1, 1))
+		return fastpos_result(pos, FULL_DISTANCES_BITS - 1, 1);
+
+	return fastpos_result(pos, FULL_DISTANCES_BITS - 1, 2);
+}
+#endif
+
+#endif
+
+#endif
diff --git a/src/liblzma/lzma/fastpos_table.c b/src/liblzma/lzma/fastpos_table.c
new file mode 100644
index 0000000..6a3ceac
--- /dev/null
+++ b/src/liblzma/lzma/fastpos_table.c
@@ -0,0 +1,519 @@
+/* This file has been automatically generated by fastpos_tablegen.c. */
+
+#include "common.h"
+#include "fastpos.h"
+
+const uint8_t lzma_fastpos[1 << FASTPOS_BITS] = {
+	  0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,
+	  8,  8,  8,  8,  8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9,
+	 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+	 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+	 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+	 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+	 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+	 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+	 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+	 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+	 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+	 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+	 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+	 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+	 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+	 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+	 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+	 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+	 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+	 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+	 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+	 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+	 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+	 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+	 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+	 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+	 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+	 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+	 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+	 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+	 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+	 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+	 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+	 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+	 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+	 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+	 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+	 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+	 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+	 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+	 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+	 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+	 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+	 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+	 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+	 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+	 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+	 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+	 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+	 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+	 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+	 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+	 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+	 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+	 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+	 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+	 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+	 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+	 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+	 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+	 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+	 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+	 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+	 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+	 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25
+};
diff --git a/src/liblzma/lzma/fastpos_tablegen.c b/src/liblzma/lzma/fastpos_tablegen.c
new file mode 100644
index 0000000..c97e6f4
--- /dev/null
+++ b/src/liblzma/lzma/fastpos_tablegen.c
@@ -0,0 +1,56 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       fastpos_tablegen.c
+/// \brief      Generates the lzma_fastpos[] lookup table
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include "fastpos.h"
+
+
+int
+main(void)
+{
+	uint8_t fastpos[1 << FASTPOS_BITS];
+
+	const uint8_t fast_slots = 2 * FASTPOS_BITS;
+	uint32_t c = 2;
+
+	fastpos[0] = 0;
+	fastpos[1] = 1;
+
+	for (uint8_t slot_fast = 2; slot_fast < fast_slots; ++slot_fast) {
+		const uint32_t k = 1 << ((slot_fast >> 1) - 1);
+		for (uint32_t j = 0; j < k; ++j, ++c)
+			fastpos[c] = slot_fast;
+	}
+
+	printf("/* This file has been automatically generated "
+			"by fastpos_tablegen.c. */\n\n"
+			"#include \"common.h\"\n"
+			"#include \"fastpos.h\"\n\n"
+			"const uint8_t lzma_fastpos[1 << FASTPOS_BITS] = {");
+
+	for (size_t i = 0; i < (1 << FASTPOS_BITS); ++i) {
+		if (i % 16 == 0)
+			printf("\n\t");
+
+		printf("%3u", (unsigned int)(fastpos[i]));
+
+		if (i != (1 << FASTPOS_BITS) - 1)
+			printf(",");
+	}
+
+	printf("\n};\n");
+
+	return 0;
+}
diff --git a/src/liblzma/lzma/lzma2_decoder.c b/src/liblzma/lzma/lzma2_decoder.c
new file mode 100644
index 0000000..b4c2f2d
--- /dev/null
+++ b/src/liblzma/lzma/lzma2_decoder.c
@@ -0,0 +1,305 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma2_decoder.c
+/// \brief      LZMA2 decoder
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "lzma2_decoder.h"
+#include "lz_decoder.h"
+#include "lzma_decoder.h"
+
+
+struct lzma_coder_s {
+	enum sequence {
+		SEQ_CONTROL,
+		SEQ_UNCOMPRESSED_1,
+		SEQ_UNCOMPRESSED_2,
+		SEQ_COMPRESSED_0,
+		SEQ_COMPRESSED_1,
+		SEQ_PROPERTIES,
+		SEQ_LZMA,
+		SEQ_COPY,
+	} sequence;
+
+	/// Sequence after the size fields have been decoded.
+	enum sequence next_sequence;
+
+	/// LZMA decoder
+	lzma_lz_decoder lzma;
+
+	/// Uncompressed size of LZMA chunk
+	size_t uncompressed_size;
+
+	/// Compressed size of the chunk (naturally equals to uncompressed
+	/// size of uncompressed chunk)
+	size_t compressed_size;
+
+	/// True if properties are needed. This is false before the
+	/// first LZMA chunk.
+	bool need_properties;
+
+	/// True if dictionary reset is needed. This is false before the
+	/// first chunk (LZMA or uncompressed).
+	bool need_dictionary_reset;
+
+	lzma_options_lzma options;
+};
+
+
+static lzma_ret
+lzma2_decode(lzma_coder *restrict coder, lzma_dict *restrict dict,
+		const uint8_t *restrict in, size_t *restrict in_pos,
+		size_t in_size)
+{
+	// With SEQ_LZMA it is possible that no new input is needed to do
+	// some progress. The rest of the sequences assume that there is
+	// at least one byte of input.
+	while (*in_pos < in_size || coder->sequence == SEQ_LZMA)
+	switch (coder->sequence) {
+	case SEQ_CONTROL: {
+		const uint32_t control = in[*in_pos];
+		++*in_pos;
+
+		if (control >= 0xE0 || control == 1) {
+			// Dictionary reset implies that next LZMA chunk has
+			// to set new properties.
+			coder->need_properties = true;
+			coder->need_dictionary_reset = true;
+		} else if (coder->need_dictionary_reset) {
+			return LZMA_DATA_ERROR;
+		}
+
+		if (control >= 0x80) {
+			// LZMA chunk. The highest five bits of the
+			// uncompressed size are taken from the control byte.
+			coder->uncompressed_size = (control & 0x1F) << 16;
+			coder->sequence = SEQ_UNCOMPRESSED_1;
+
+			// See if there are new properties or if we need to
+			// reset the state.
+			if (control >= 0xC0) {
+				// When there are new properties, state reset
+				// is done at SEQ_PROPERTIES.
+				coder->need_properties = false;
+				coder->next_sequence = SEQ_PROPERTIES;
+
+			} else if (coder->need_properties) {
+				return LZMA_DATA_ERROR;
+
+			} else {
+				coder->next_sequence = SEQ_LZMA;
+
+				// If only state reset is wanted with old
+				// properties, do the resetting here for
+				// simplicity.
+				if (control >= 0xA0)
+					coder->lzma.reset(coder->lzma.coder,
+							&coder->options);
+			}
+		} else {
+			// End marker
+			if (control == 0x00)
+				return LZMA_STREAM_END;
+
+			// Invalid control values
+			if (control > 2)
+				return LZMA_DATA_ERROR;
+
+			// It's uncompressed chunk
+			coder->sequence = SEQ_COMPRESSED_0;
+			coder->next_sequence = SEQ_COPY;
+		}
+
+		if (coder->need_dictionary_reset) {
+			// Finish the dictionary reset and let the caller
+			// flush the dictionary to the actual output buffer.
+			coder->need_dictionary_reset = false;
+			dict_reset(dict);
+			return LZMA_OK;
+		}
+
+		break;
+	}
+
+	case SEQ_UNCOMPRESSED_1:
+		coder->uncompressed_size += (uint32_t)(in[(*in_pos)++]) << 8;
+		coder->sequence = SEQ_UNCOMPRESSED_2;
+		break;
+
+	case SEQ_UNCOMPRESSED_2:
+		coder->uncompressed_size += in[(*in_pos)++] + 1;
+		coder->sequence = SEQ_COMPRESSED_0;
+		coder->lzma.set_uncompressed(coder->lzma.coder,
+				coder->uncompressed_size);
+		break;
+
+	case SEQ_COMPRESSED_0:
+		coder->compressed_size = (uint32_t)(in[(*in_pos)++]) << 8;
+		coder->sequence = SEQ_COMPRESSED_1;
+		break;
+
+	case SEQ_COMPRESSED_1:
+		coder->compressed_size += in[(*in_pos)++] + 1;
+		coder->sequence = coder->next_sequence;
+		break;
+
+	case SEQ_PROPERTIES:
+		if (lzma_lzma_lclppb_decode(&coder->options, in[(*in_pos)++]))
+			return LZMA_DATA_ERROR;
+
+		coder->lzma.reset(coder->lzma.coder, &coder->options);
+
+		coder->sequence = SEQ_LZMA;
+		break;
+
+	case SEQ_LZMA: {
+		// Store the start offset so that we can update
+		// coder->compressed_size later.
+		const size_t in_start = *in_pos;
+
+		// Decode from in[] to *dict.
+		const lzma_ret ret = coder->lzma.code(coder->lzma.coder,
+				dict, in, in_pos, in_size);
+
+		// Validate and update coder->compressed_size.
+		const size_t in_used = *in_pos - in_start;
+		if (in_used > coder->compressed_size)
+			return LZMA_DATA_ERROR;
+
+		coder->compressed_size -= in_used;
+
+		// Return if we didn't finish the chunk, or an error occurred.
+		if (ret != LZMA_STREAM_END)
+			return ret;
+
+		// The LZMA decoder must have consumed the whole chunk now.
+		// We don't need to worry about uncompressed size since it
+		// is checked by the LZMA decoder.
+		if (coder->compressed_size != 0)
+			return LZMA_DATA_ERROR;
+
+		coder->sequence = SEQ_CONTROL;
+		break;
+	}
+
+	case SEQ_COPY: {
+		// Copy from input to the dictionary as is.
+		// FIXME Can copy too much?
+		dict_write(dict, in, in_pos, in_size, &coder->compressed_size);
+		if (coder->compressed_size != 0)
+			return LZMA_OK;
+
+		coder->sequence = SEQ_CONTROL;
+		break;
+	}
+
+	default:
+		assert(0);
+		return LZMA_PROG_ERROR;
+	}
+
+	return LZMA_OK;
+}
+
+
+static void
+lzma2_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
+{
+	assert(coder->lzma.end == NULL);
+	lzma_free(coder->lzma.coder, allocator);
+
+	lzma_free(coder, allocator);
+
+	return;
+}
+
+
+static lzma_ret
+lzma2_decoder_init(lzma_lz_decoder *lz, lzma_allocator *allocator,
+		const void *opt, lzma_lz_options *lz_options)
+{
+	if (lz->coder == NULL) {
+		lz->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+		if (lz->coder == NULL)
+			return LZMA_MEM_ERROR;
+
+		lz->code = &lzma2_decode;
+		lz->end = &lzma2_decoder_end;
+
+		lz->coder->lzma = LZMA_LZ_DECODER_INIT;
+	}
+
+	const lzma_options_lzma *options = opt;
+
+	lz->coder->sequence = SEQ_CONTROL;
+	lz->coder->need_properties = true;
+	lz->coder->need_dictionary_reset = options->preset_dict == NULL
+			|| options->preset_dict_size == 0;
+
+	return lzma_lzma_decoder_create(&lz->coder->lzma,
+			allocator, options, lz_options);
+}
+
+
+extern lzma_ret
+lzma_lzma2_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters)
+{
+	// LZMA2 can only be the last filter in the chain. This is enforced
+	// by the raw_decoder initialization.
+	assert(filters[1].init == NULL);
+
+	return lzma_lz_decoder_init(next, allocator, filters,
+			&lzma2_decoder_init);
+}
+
+
+extern uint64_t
+lzma_lzma2_decoder_memusage(const void *options)
+{
+	return sizeof(lzma_coder)
+			+ lzma_lzma_decoder_memusage_nocheck(options);
+}
+
+
+extern lzma_ret
+lzma_lzma2_props_decode(void **options, lzma_allocator *allocator,
+		const uint8_t *props, size_t props_size)
+{
+	if (props_size != 1)
+		return LZMA_OPTIONS_ERROR;
+
+	// Check that reserved bits are unset.
+	if (props[0] & 0xC0)
+		return LZMA_OPTIONS_ERROR;
+
+	// Decode the dictionary size.
+	if (props[0] > 40)
+		return LZMA_OPTIONS_ERROR;
+
+	lzma_options_lzma *opt = lzma_alloc(
+			sizeof(lzma_options_lzma), allocator);
+	if (opt == NULL)
+		return LZMA_MEM_ERROR;
+
+	if (props[0] == 40) {
+		opt->dict_size = UINT32_MAX;
+	} else {
+		opt->dict_size = 2 | (props[0] & 1);
+		opt->dict_size <<= props[0] / 2 + 11;
+	}
+
+	opt->preset_dict = NULL;
+	opt->preset_dict_size = 0;
+
+	*options = opt;
+
+	return LZMA_OK;
+}
diff --git a/src/liblzma/lzma/lzma2_decoder.h b/src/liblzma/lzma/lzma2_decoder.h
new file mode 100644
index 0000000..fac4ac4
--- /dev/null
+++ b/src/liblzma/lzma/lzma2_decoder.h
@@ -0,0 +1,28 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma2_decoder.h
+/// \brief      LZMA2 decoder
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_LZMA2_DECODER_H
+#define LZMA_LZMA2_DECODER_H
+
+#include "common.h"
+
+extern lzma_ret lzma_lzma2_decoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters);
+
+extern uint64_t lzma_lzma2_decoder_memusage(const void *options);
+
+extern lzma_ret lzma_lzma2_props_decode(
+		void **options, lzma_allocator *allocator,
+		const uint8_t *props, size_t props_size);
+
+#endif
diff --git a/src/liblzma/lzma/lzma2_encoder.c b/src/liblzma/lzma/lzma2_encoder.c
new file mode 100644
index 0000000..b48e0d6
--- /dev/null
+++ b/src/liblzma/lzma/lzma2_encoder.c
@@ -0,0 +1,393 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma2_encoder.c
+/// \brief      LZMA2 encoder
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "lz_encoder.h"
+#include "lzma_encoder.h"
+#include "fastpos.h"
+#include "lzma2_encoder.h"
+
+
+struct lzma_coder_s {
+	enum {
+		SEQ_INIT,
+		SEQ_LZMA_ENCODE,
+		SEQ_LZMA_COPY,
+		SEQ_UNCOMPRESSED_HEADER,
+		SEQ_UNCOMPRESSED_COPY,
+	} sequence;
+
+	/// LZMA encoder
+	lzma_coder *lzma;
+
+	/// LZMA options currently in use.
+	lzma_options_lzma opt_cur;
+
+	bool need_properties;
+	bool need_state_reset;
+	bool need_dictionary_reset;
+
+	/// Uncompressed size of a chunk
+	size_t uncompressed_size;
+
+	/// Compressed size of a chunk (excluding headers); this is also used
+	/// to indicate the end of buf[] in SEQ_LZMA_COPY.
+	size_t compressed_size;
+
+	/// Read position in buf[]
+	size_t buf_pos;
+
+	/// Buffer to hold the chunk header and LZMA compressed data
+	uint8_t buf[LZMA2_HEADER_MAX + LZMA2_CHUNK_MAX];
+};
+
+
+static void
+lzma2_header_lzma(lzma_coder *coder)
+{
+	assert(coder->uncompressed_size > 0);
+	assert(coder->uncompressed_size <= LZMA2_UNCOMPRESSED_MAX);
+	assert(coder->compressed_size > 0);
+	assert(coder->compressed_size <= LZMA2_CHUNK_MAX);
+
+	size_t pos;
+
+	if (coder->need_properties) {
+		pos = 0;
+
+		if (coder->need_dictionary_reset)
+			coder->buf[pos] = 0x80 + (3 << 5);
+		else
+			coder->buf[pos] = 0x80 + (2 << 5);
+	} else {
+		pos = 1;
+
+		if (coder->need_state_reset)
+			coder->buf[pos] = 0x80 + (1 << 5);
+		else
+			coder->buf[pos] = 0x80;
+	}
+
+	// Set the start position for copying.
+	coder->buf_pos = pos;
+
+	// Uncompressed size
+	size_t size = coder->uncompressed_size - 1;
+	coder->buf[pos++] += size >> 16;
+	coder->buf[pos++] = (size >> 8) & 0xFF;
+	coder->buf[pos++] = size & 0xFF;
+
+	// Compressed size
+	size = coder->compressed_size - 1;
+	coder->buf[pos++] = size >> 8;
+	coder->buf[pos++] = size & 0xFF;
+
+	// Properties, if needed
+	if (coder->need_properties)
+		lzma_lzma_lclppb_encode(&coder->opt_cur, coder->buf + pos);
+
+	coder->need_properties = false;
+	coder->need_state_reset = false;
+	coder->need_dictionary_reset = false;
+
+	// The copying code uses coder->compressed_size to indicate the end
+	// of coder->buf[], so we need add the maximum size of the header here.
+	coder->compressed_size += LZMA2_HEADER_MAX;
+
+	return;
+}
+
+
+static void
+lzma2_header_uncompressed(lzma_coder *coder)
+{
+	assert(coder->uncompressed_size > 0);
+	assert(coder->uncompressed_size <= LZMA2_CHUNK_MAX);
+
+	// If this is the first chunk, we need to include dictionary
+	// reset indicator.
+	if (coder->need_dictionary_reset)
+		coder->buf[0] = 1;
+	else
+		coder->buf[0] = 2;
+
+	coder->need_dictionary_reset = false;
+
+	// "Compressed" size
+	coder->buf[1] = (coder->uncompressed_size - 1) >> 8;
+	coder->buf[2] = (coder->uncompressed_size - 1) & 0xFF;
+
+	// Set the start position for copying.
+	coder->buf_pos = 0;
+	return;
+}
+
+
+static lzma_ret
+lzma2_encode(lzma_coder *restrict coder, lzma_mf *restrict mf,
+		uint8_t *restrict out, size_t *restrict out_pos,
+		size_t out_size)
+{
+	while (*out_pos < out_size)
+	switch (coder->sequence) {
+	case SEQ_INIT:
+		// If there's no input left and we are flushing or finishing,
+		// don't start a new chunk.
+		if (mf_unencoded(mf) == 0) {
+			// Write end of payload marker if finishing.
+			if (mf->action == LZMA_FINISH)
+				out[(*out_pos)++] = 0;
+
+			return mf->action == LZMA_RUN
+					? LZMA_OK : LZMA_STREAM_END;
+		}
+
+		if (coder->need_state_reset)
+			return_if_error(lzma_lzma_encoder_reset(
+					coder->lzma, &coder->opt_cur));
+
+		coder->uncompressed_size = 0;
+		coder->compressed_size = 0;
+		coder->sequence = SEQ_LZMA_ENCODE;
+
+	// Fall through
+
+	case SEQ_LZMA_ENCODE: {
+		// Calculate how much more uncompressed data this chunk
+		// could accept.
+		const uint32_t left = LZMA2_UNCOMPRESSED_MAX
+				- coder->uncompressed_size;
+		uint32_t limit;
+
+		if (left < mf->match_len_max) {
+			// Must flush immediately since the next LZMA symbol
+			// could make the uncompressed size of the chunk too
+			// big.
+			limit = 0;
+		} else {
+			// Calculate maximum read_limit that is OK from point
+			// of view of LZMA2 chunk size.
+			limit = mf->read_pos - mf->read_ahead
+					+ left - mf->match_len_max;
+		}
+
+		// Save the start position so that we can update
+		// coder->uncompressed_size.
+		const uint32_t read_start = mf->read_pos - mf->read_ahead;
+
+		// Call the LZMA encoder until the chunk is finished.
+		const lzma_ret ret = lzma_lzma_encode(coder->lzma, mf,
+				coder->buf + LZMA2_HEADER_MAX,
+				&coder->compressed_size,
+				LZMA2_CHUNK_MAX, limit);
+
+		coder->uncompressed_size += mf->read_pos - mf->read_ahead
+				- read_start;
+
+		assert(coder->compressed_size <= LZMA2_CHUNK_MAX);
+		assert(coder->uncompressed_size <= LZMA2_UNCOMPRESSED_MAX);
+
+		if (ret != LZMA_STREAM_END)
+			return LZMA_OK;
+
+		// See if the chunk compressed. If it didn't, we encode it
+		// as uncompressed chunk. This saves a few bytes of space
+		// and makes decoding faster.
+		if (coder->compressed_size >= coder->uncompressed_size) {
+			coder->uncompressed_size += mf->read_ahead;
+			assert(coder->uncompressed_size
+					<= LZMA2_UNCOMPRESSED_MAX);
+			mf->read_ahead = 0;
+			lzma2_header_uncompressed(coder);
+			coder->need_state_reset = true;
+			coder->sequence = SEQ_UNCOMPRESSED_HEADER;
+			break;
+		}
+
+		// The chunk did compress at least by one byte, so we store
+		// the chunk as LZMA.
+		lzma2_header_lzma(coder);
+
+		coder->sequence = SEQ_LZMA_COPY;
+	}
+
+	// Fall through
+
+	case SEQ_LZMA_COPY:
+		// Copy the compressed chunk along its headers to the
+		// output buffer.
+		lzma_bufcpy(coder->buf, &coder->buf_pos,
+				coder->compressed_size,
+				out, out_pos, out_size);
+		if (coder->buf_pos != coder->compressed_size)
+			return LZMA_OK;
+
+		coder->sequence = SEQ_INIT;
+		break;
+
+	case SEQ_UNCOMPRESSED_HEADER:
+		// Copy the three-byte header to indicate uncompressed chunk.
+		lzma_bufcpy(coder->buf, &coder->buf_pos,
+				LZMA2_HEADER_UNCOMPRESSED,
+				out, out_pos, out_size);
+		if (coder->buf_pos != LZMA2_HEADER_UNCOMPRESSED)
+			return LZMA_OK;
+
+		coder->sequence = SEQ_UNCOMPRESSED_COPY;
+
+	// Fall through
+
+	case SEQ_UNCOMPRESSED_COPY:
+		// Copy the uncompressed data as is from the dictionary
+		// to the output buffer.
+		mf_read(mf, out, out_pos, out_size, &coder->uncompressed_size);
+		if (coder->uncompressed_size != 0)
+			return LZMA_OK;
+
+		coder->sequence = SEQ_INIT;
+		break;
+	}
+
+	return LZMA_OK;
+}
+
+
+static void
+lzma2_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
+{
+	lzma_free(coder->lzma, allocator);
+	lzma_free(coder, allocator);
+	return;
+}
+
+
+static lzma_ret
+lzma2_encoder_options_update(lzma_coder *coder, const lzma_filter *filter)
+{
+	// New options can be set only when there is no incomplete chunk.
+	// This is the case at the beginning of the raw stream and right
+	// after LZMA_SYNC_FLUSH.
+	if (filter->options == NULL || coder->sequence != SEQ_INIT)
+		return LZMA_PROG_ERROR;
+
+	// Look if there are new options. At least for now,
+	// only lc/lp/pb can be changed.
+	const lzma_options_lzma *opt = filter->options;
+	if (coder->opt_cur.lc != opt->lc || coder->opt_cur.lp != opt->lp
+			|| coder->opt_cur.pb != opt->pb) {
+		// Validate the options.
+		if (opt->lc > LZMA_LCLP_MAX || opt->lp > LZMA_LCLP_MAX
+				|| opt->lc + opt->lp > LZMA_LCLP_MAX
+				|| opt->pb > LZMA_PB_MAX)
+			return LZMA_OPTIONS_ERROR;
+
+		// The new options will be used when the encoder starts
+		// a new LZMA2 chunk.
+		coder->opt_cur.lc = opt->lc;
+		coder->opt_cur.lp = opt->lp;
+		coder->opt_cur.pb = opt->pb;
+		coder->need_properties = true;
+		coder->need_state_reset = true;
+	}
+
+	return LZMA_OK;
+}
+
+
+static lzma_ret
+lzma2_encoder_init(lzma_lz_encoder *lz, lzma_allocator *allocator,
+		const void *options, lzma_lz_options *lz_options)
+{
+	if (options == NULL)
+		return LZMA_PROG_ERROR;
+
+	if (lz->coder == NULL) {
+		lz->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+		if (lz->coder == NULL)
+			return LZMA_MEM_ERROR;
+
+		lz->code = &lzma2_encode;
+		lz->end = &lzma2_encoder_end;
+		lz->options_update = &lzma2_encoder_options_update;
+
+		lz->coder->lzma = NULL;
+	}
+
+	lz->coder->opt_cur = *(const lzma_options_lzma *)(options);
+
+	lz->coder->sequence = SEQ_INIT;
+	lz->coder->need_properties = true;
+	lz->coder->need_state_reset = false;
+	lz->coder->need_dictionary_reset
+			= lz->coder->opt_cur.preset_dict == NULL
+			|| lz->coder->opt_cur.preset_dict_size == 0;
+
+	// Initialize LZMA encoder
+	return_if_error(lzma_lzma_encoder_create(&lz->coder->lzma, allocator,
+			&lz->coder->opt_cur, lz_options));
+
+	// Make sure that we will always have enough history available in
+	// case we need to use uncompressed chunks. They are used when the
+	// compressed size of a chunk is not smaller than the uncompressed
+	// size, so we need to have at least LZMA2_COMPRESSED_MAX bytes
+	// history available.
+	if (lz_options->before_size + lz_options->dict_size < LZMA2_CHUNK_MAX)
+		lz_options->before_size
+				= LZMA2_CHUNK_MAX - lz_options->dict_size;
+
+	return LZMA_OK;
+}
+
+
+extern lzma_ret
+lzma_lzma2_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters)
+{
+	return lzma_lz_encoder_init(
+			next, allocator, filters, &lzma2_encoder_init);
+}
+
+
+extern uint64_t
+lzma_lzma2_encoder_memusage(const void *options)
+{
+	const uint64_t lzma_mem = lzma_lzma_encoder_memusage(options);
+	if (lzma_mem == UINT64_MAX)
+		return UINT64_MAX;
+
+	return sizeof(lzma_coder) + lzma_mem;
+}
+
+
+extern lzma_ret
+lzma_lzma2_props_encode(const void *options, uint8_t *out)
+{
+	const lzma_options_lzma *const opt = options;
+	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:
+	--d;
+	d |= d >> 2;
+	d |= d >> 3;
+	d |= d >> 4;
+	d |= d >> 8;
+	d |= d >> 16;
+
+	// Get the highest two bits using the proper encoding:
+	if (d == UINT32_MAX)
+		out[0] = 40;
+	else
+		out[0] = get_pos_slot(d + 1) - 24;
+
+	return LZMA_OK;
+}
diff --git a/src/liblzma/lzma/lzma2_encoder.h b/src/liblzma/lzma/lzma2_encoder.h
new file mode 100644
index 0000000..ca19ef4
--- /dev/null
+++ b/src/liblzma/lzma/lzma2_encoder.h
@@ -0,0 +1,41 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma2_encoder.h
+/// \brief      LZMA2 encoder
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_LZMA2_ENCODER_H
+#define LZMA_LZMA2_ENCODER_H
+
+#include "common.h"
+
+
+/// Maximum number of bytes of actual data per chunk (no headers)
+#define LZMA2_CHUNK_MAX (UINT32_C(1) << 16)
+
+/// Maximum uncompressed size of LZMA chunk (no headers)
+#define LZMA2_UNCOMPRESSED_MAX (UINT32_C(1) << 21)
+
+/// Maximum size of LZMA2 headers
+#define LZMA2_HEADER_MAX 6
+
+/// Size of a header for uncompressed chunk
+#define LZMA2_HEADER_UNCOMPRESSED 3
+
+
+extern lzma_ret lzma_lzma2_encoder_init(
+		lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters);
+
+extern uint64_t lzma_lzma2_encoder_memusage(const void *options);
+
+extern lzma_ret lzma_lzma2_props_encode(const void *options, uint8_t *out);
+
+#endif
diff --git a/src/liblzma/lzma/lzma_common.h b/src/liblzma/lzma/lzma_common.h
new file mode 100644
index 0000000..e31e285
--- /dev/null
+++ b/src/liblzma/lzma/lzma_common.h
@@ -0,0 +1,223 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma_common.h
+/// \brief      Private definitions common to LZMA encoder and decoder
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_LZMA_COMMON_H
+#define LZMA_LZMA_COMMON_H
+
+#include "common.h"
+#include "range_common.h"
+
+
+///////////////////
+// Miscellaneous //
+///////////////////
+
+/// Maximum number of position states. A position state is the lowest pos bits
+/// number of bits of the current uncompressed offset. In some places there
+/// are different sets of probabilities for different pos states.
+#define POS_STATES_MAX (1 << LZMA_PB_MAX)
+
+
+/// Validates lc, lp, and pb.
+static inline bool
+is_lclppb_valid(const lzma_options_lzma *options)
+{
+	return options->lc <= LZMA_LCLP_MAX && options->lp <= LZMA_LCLP_MAX
+			&& options->lc + options->lp <= LZMA_LCLP_MAX
+			&& options->pb <= LZMA_PB_MAX;
+}
+
+
+///////////
+// State //
+///////////
+
+/// This enum is used to track which events have occurred most recently and
+/// in which order. This information is used to predict the next event.
+///
+/// Events:
+///  - Literal: One 8-bit byte
+///  - Match: Repeat a chunk of data at some distance
+///  - Long repeat: Multi-byte match at a recently seen distance
+///  - Short repeat: One-byte repeat at a recently seen distance
+///
+/// The event names are in from STATE_oldest_older_previous. REP means
+/// either short or long repeated match, and NONLIT means any non-literal.
+typedef enum {
+	STATE_LIT_LIT,
+	STATE_MATCH_LIT_LIT,
+	STATE_REP_LIT_LIT,
+	STATE_SHORTREP_LIT_LIT,
+	STATE_MATCH_LIT,
+	STATE_REP_LIT,
+	STATE_SHORTREP_LIT,
+	STATE_LIT_MATCH,
+	STATE_LIT_LONGREP,
+	STATE_LIT_SHORTREP,
+	STATE_NONLIT_MATCH,
+	STATE_NONLIT_REP,
+} lzma_lzma_state;
+
+
+/// Total number of states
+#define STATES 12
+
+/// The lowest 7 states indicate that the previous state was a literal.
+#define LIT_STATES 7
+
+
+/// Indicate that the latest state was a literal.
+#define update_literal(state) \
+	state = ((state) <= STATE_SHORTREP_LIT_LIT \
+			? STATE_LIT_LIT \
+			: ((state) <= STATE_LIT_SHORTREP \
+				? (state) - 3 \
+				: (state) - 6))
+
+/// Indicate that the latest state was a match.
+#define update_match(state) \
+	state = ((state) < LIT_STATES ? STATE_LIT_MATCH : STATE_NONLIT_MATCH)
+
+/// Indicate that the latest state was a long repeated match.
+#define update_long_rep(state) \
+	state = ((state) < LIT_STATES ? STATE_LIT_LONGREP : STATE_NONLIT_REP)
+
+/// Indicate that the latest state was a short match.
+#define update_short_rep(state) \
+	state = ((state) < LIT_STATES ? STATE_LIT_SHORTREP : STATE_NONLIT_REP)
+
+/// Test if the previous state was a literal.
+#define is_literal_state(state) \
+	((state) < LIT_STATES)
+
+
+/////////////
+// Literal //
+/////////////
+
+/// Each literal coder is divided in three sections:
+///   - 0x001-0x0FF: Without match byte
+///   - 0x101-0x1FF: With match byte; match bit is 0
+///   - 0x201-0x2FF: With match byte; match bit is 1
+///
+/// Match byte is used when the previous LZMA symbol was something else than
+/// a literal (that is, it was some kind of match).
+#define LITERAL_CODER_SIZE 0x300
+
+/// Maximum number of literal coders
+#define LITERAL_CODERS_MAX (1 << LZMA_LCLP_MAX)
+
+/// Locate the literal coder for the next literal byte. The choice depends on
+///   - the lowest literal_pos_bits bits of the position of the current
+///     byte; and
+///   - the highest literal_context_bits bits of the previous byte.
+#define literal_subcoder(probs, lc, lp_mask, pos, prev_byte) \
+	((probs)[(((pos) & lp_mask) << lc) + ((prev_byte) >> (8 - lc))])
+
+
+static inline void
+literal_init(probability (*probs)[LITERAL_CODER_SIZE],
+		uint32_t lc, uint32_t lp)
+{
+	assert(lc + lp <= LZMA_LCLP_MAX);
+
+	const uint32_t coders = 1U << (lc + lp);
+
+	for (uint32_t i = 0; i < coders; ++i)
+		for (uint32_t j = 0; j < LITERAL_CODER_SIZE; ++j)
+			bit_reset(probs[i][j]);
+
+	return;
+}
+
+
+//////////////////
+// Match length //
+//////////////////
+
+// Minimum length of a match is two bytes.
+#define MATCH_LEN_MIN 2
+
+// Match length is encoded with 4, 5, or 10 bits.
+//
+// Length   Bits
+//  2-9      4 = Choice=0 + 3 bits
+// 10-17     5 = Choice=1 + Choice2=0 + 3 bits
+// 18-273   10 = Choice=1 + Choice2=1 + 8 bits
+#define LEN_LOW_BITS 3
+#define LEN_LOW_SYMBOLS (1 << LEN_LOW_BITS)
+#define LEN_MID_BITS 3
+#define LEN_MID_SYMBOLS (1 << LEN_MID_BITS)
+#define LEN_HIGH_BITS 8
+#define LEN_HIGH_SYMBOLS (1 << LEN_HIGH_BITS)
+#define LEN_SYMBOLS (LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS + LEN_HIGH_SYMBOLS)
+
+// Maximum length of a match is 273 which is a result of the encoding
+// described above.
+#define MATCH_LEN_MAX (MATCH_LEN_MIN + LEN_SYMBOLS - 1)
+
+
+////////////////////
+// Match distance //
+////////////////////
+
+// Different set of probabilities is used for match distances that have very
+// short match length: Lengths of 2, 3, and 4 bytes have a separate set of
+// probabilities for each length. The matches with longer length use a shared
+// set of probabilities.
+#define LEN_TO_POS_STATES 4
+
+// Macro to get the index of the appropriate probability array.
+#define get_len_to_pos_state(len) \
+	((len) < LEN_TO_POS_STATES + MATCH_LEN_MIN \
+		? (len) - MATCH_LEN_MIN \
+		: LEN_TO_POS_STATES - 1)
+
+// The highest two bits of a match distance (pos slot) are encoded using six
+// bits. See fastpos.h for more explanation.
+#define POS_SLOT_BITS 6
+#define POS_SLOTS (1 << POS_SLOT_BITS)
+
+// Match distances up to 127 are fully encoded using probabilities. Since
+// the highest two bits (pos slot) are always encoded using six bits, the
+// distances 0-3 don't need any additional bits to encode, since the pos
+// slot itself is the same as the actual distance. START_POS_MODEL_INDEX
+// indicates the first pos slot where at least one additional bit is needed.
+#define START_POS_MODEL_INDEX 4
+
+// Match distances greater than 127 are encoded in three pieces:
+//   - pos slot: the highest two bits
+//   - direct bits: 2-26 bits below the highest two bits
+//   - alignment bits: four lowest bits
+//
+// Direct bits don't use any probabilities.
+//
+// The pos slot value of 14 is for distances 128-191 (see the table in
+// fastpos.h to understand why).
+#define END_POS_MODEL_INDEX 14
+
+// Pos slots that indicate a distance <= 127.
+#define FULL_DISTANCES_BITS (END_POS_MODEL_INDEX / 2)
+#define FULL_DISTANCES (1 << FULL_DISTANCES_BITS)
+
+// For match distances greater than 127, only the highest two bits and the
+// lowest four bits (alignment) is encoded using probabilities.
+#define ALIGN_BITS 4
+#define ALIGN_TABLE_SIZE (1 << ALIGN_BITS)
+#define ALIGN_MASK (ALIGN_TABLE_SIZE - 1)
+
+// LZMA remembers the four most recent match distances. Reusing these distances
+// tends to take less space than re-encoding the actual distance value.
+#define REP_DISTANCES 4
+
+#endif
diff --git a/src/liblzma/lzma/lzma_decoder.c b/src/liblzma/lzma/lzma_decoder.c
new file mode 100644
index 0000000..4329e01
--- /dev/null
+++ b/src/liblzma/lzma/lzma_decoder.c
@@ -0,0 +1,1057 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma_decoder.c
+/// \brief      LZMA decoder
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "lz_decoder.h"
+#include "lzma_common.h"
+#include "lzma_decoder.h"
+#include "range_decoder.h"
+
+
+#ifdef HAVE_SMALL
+
+// Macros for (somewhat) size-optimized code.
+#define seq_4(seq) seq
+
+#define seq_6(seq) seq
+
+#define seq_8(seq) seq
+
+#define seq_len(seq) \
+	seq ## _CHOICE, \
+	seq ## _CHOICE2, \
+	seq ## _BITTREE
+
+#define len_decode(target, ld, pos_state, seq) \
+do { \
+case seq ## _CHOICE: \
+	rc_if_0(ld.choice, seq ## _CHOICE) { \
+		rc_update_0(ld.choice); \
+		probs = ld.low[pos_state];\
+		limit = LEN_LOW_SYMBOLS; \
+		target = MATCH_LEN_MIN; \
+	} else { \
+		rc_update_1(ld.choice); \
+case seq ## _CHOICE2: \
+		rc_if_0(ld.choice2, seq ## _CHOICE2) { \
+			rc_update_0(ld.choice2); \
+			probs = ld.mid[pos_state]; \
+			limit = LEN_MID_SYMBOLS; \
+			target = MATCH_LEN_MIN + LEN_LOW_SYMBOLS; \
+		} else { \
+			rc_update_1(ld.choice2); \
+			probs = ld.high; \
+			limit = LEN_HIGH_SYMBOLS; \
+			target = MATCH_LEN_MIN + LEN_LOW_SYMBOLS \
+					+ LEN_MID_SYMBOLS; \
+		} \
+	} \
+	symbol = 1; \
+case seq ## _BITTREE: \
+	do { \
+		rc_bit(probs[symbol], , , seq ## _BITTREE); \
+	} while (symbol < limit); \
+	target += symbol - limit; \
+} while (0)
+
+#else // HAVE_SMALL
+
+// Unrolled versions
+#define seq_4(seq) \
+	seq ## 0, \
+	seq ## 1, \
+	seq ## 2, \
+	seq ## 3
+
+#define seq_6(seq) \
+	seq ## 0, \
+	seq ## 1, \
+	seq ## 2, \
+	seq ## 3, \
+	seq ## 4, \
+	seq ## 5
+
+#define seq_8(seq) \
+	seq ## 0, \
+	seq ## 1, \
+	seq ## 2, \
+	seq ## 3, \
+	seq ## 4, \
+	seq ## 5, \
+	seq ## 6, \
+	seq ## 7
+
+#define seq_len(seq) \
+	seq ## _CHOICE, \
+	seq ## _LOW0, \
+	seq ## _LOW1, \
+	seq ## _LOW2, \
+	seq ## _CHOICE2, \
+	seq ## _MID0, \
+	seq ## _MID1, \
+	seq ## _MID2, \
+	seq ## _HIGH0, \
+	seq ## _HIGH1, \
+	seq ## _HIGH2, \
+	seq ## _HIGH3, \
+	seq ## _HIGH4, \
+	seq ## _HIGH5, \
+	seq ## _HIGH6, \
+	seq ## _HIGH7
+
+#define len_decode(target, ld, pos_state, seq) \
+do { \
+	symbol = 1; \
+case seq ## _CHOICE: \
+	rc_if_0(ld.choice, seq ## _CHOICE) { \
+		rc_update_0(ld.choice); \
+		rc_bit_case(ld.low[pos_state][symbol], , , seq ## _LOW0); \
+		rc_bit_case(ld.low[pos_state][symbol], , , seq ## _LOW1); \
+		rc_bit_case(ld.low[pos_state][symbol], , , seq ## _LOW2); \
+		target = symbol - LEN_LOW_SYMBOLS + MATCH_LEN_MIN; \
+	} else { \
+		rc_update_1(ld.choice); \
+case seq ## _CHOICE2: \
+		rc_if_0(ld.choice2, seq ## _CHOICE2) { \
+			rc_update_0(ld.choice2); \
+			rc_bit_case(ld.mid[pos_state][symbol], , , \
+					seq ## _MID0); \
+			rc_bit_case(ld.mid[pos_state][symbol], , , \
+					seq ## _MID1); \
+			rc_bit_case(ld.mid[pos_state][symbol], , , \
+					seq ## _MID2); \
+			target = symbol - LEN_MID_SYMBOLS \
+					+ MATCH_LEN_MIN + LEN_LOW_SYMBOLS; \
+		} else { \
+			rc_update_1(ld.choice2); \
+			rc_bit_case(ld.high[symbol], , , seq ## _HIGH0); \
+			rc_bit_case(ld.high[symbol], , , seq ## _HIGH1); \
+			rc_bit_case(ld.high[symbol], , , seq ## _HIGH2); \
+			rc_bit_case(ld.high[symbol], , , seq ## _HIGH3); \
+			rc_bit_case(ld.high[symbol], , , seq ## _HIGH4); \
+			rc_bit_case(ld.high[symbol], , , seq ## _HIGH5); \
+			rc_bit_case(ld.high[symbol], , , seq ## _HIGH6); \
+			rc_bit_case(ld.high[symbol], , , seq ## _HIGH7); \
+			target = symbol - LEN_HIGH_SYMBOLS \
+					+ MATCH_LEN_MIN \
+					+ LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS; \
+		} \
+	} \
+} while (0)
+
+#endif // HAVE_SMALL
+
+
+/// Length decoder probabilities; see comments in lzma_common.h.
+typedef struct {
+	probability choice;
+	probability choice2;
+	probability low[POS_STATES_MAX][LEN_LOW_SYMBOLS];
+	probability mid[POS_STATES_MAX][LEN_MID_SYMBOLS];
+	probability high[LEN_HIGH_SYMBOLS];
+} lzma_length_decoder;
+
+
+struct lzma_coder_s {
+	///////////////////
+	// Probabilities //
+	///////////////////
+
+	/// Literals; see comments in lzma_common.h.
+	probability literal[LITERAL_CODERS_MAX][LITERAL_CODER_SIZE];
+
+	/// If 1, it's a match. Otherwise it's a single 8-bit literal.
+	probability is_match[STATES][POS_STATES_MAX];
+
+	/// If 1, it's a repeated match. The distance is one of rep0 .. rep3.
+	probability is_rep[STATES];
+
+	/// If 0, distance of a repeated match is rep0.
+	/// Otherwise check is_rep1.
+	probability is_rep0[STATES];
+
+	/// If 0, distance of a repeated match is rep1.
+	/// Otherwise check is_rep2.
+	probability is_rep1[STATES];
+
+	/// If 0, distance of a repeated match is rep2. Otherwise it is rep3.
+	probability is_rep2[STATES];
+
+	/// If 1, the repeated match has length of one byte. Otherwise
+	/// the length is decoded from rep_len_decoder.
+	probability is_rep0_long[STATES][POS_STATES_MAX];
+
+	/// Probability tree for the highest two bits of the match distance.
+	/// There is a separate probability tree for match lengths of
+	/// 2 (i.e. MATCH_LEN_MIN), 3, 4, and [5, 273].
+	probability pos_slot[LEN_TO_POS_STATES][POS_SLOTS];
+
+	/// Probability trees for additional bits for match distance when the
+	/// distance is in the range [4, 127].
+	probability pos_special[FULL_DISTANCES - END_POS_MODEL_INDEX];
+
+	/// Probability tree for the lowest four bits of a match distance
+	/// that is equal to or greater than 128.
+	probability pos_align[ALIGN_TABLE_SIZE];
+
+	/// Length of a normal match
+	lzma_length_decoder match_len_decoder;
+
+	/// Length of a repeated match
+	lzma_length_decoder rep_len_decoder;
+
+	///////////////////
+	// Decoder state //
+	///////////////////
+
+	// Range coder
+	lzma_range_decoder rc;
+
+	// Types of the most recently seen LZMA symbols
+	lzma_lzma_state state;
+
+	uint32_t rep0;      ///< Distance of the latest match
+	uint32_t rep1;      ///< Distance of second latest match
+	uint32_t rep2;      ///< Distance of third latest match
+	uint32_t rep3;      ///< Distance of fourth latest match
+
+	uint32_t pos_mask; // (1U << pb) - 1
+	uint32_t literal_context_bits;
+	uint32_t literal_pos_mask;
+
+	/// Uncompressed size as bytes, or LZMA_VLI_UNKNOWN if end of
+	/// payload marker is expected.
+	lzma_vli uncompressed_size;
+
+	////////////////////////////////
+	// State of incomplete symbol //
+	////////////////////////////////
+
+	/// Position where to continue the decoder loop
+	enum {
+		SEQ_NORMALIZE,
+		SEQ_IS_MATCH,
+		seq_8(SEQ_LITERAL),
+		seq_8(SEQ_LITERAL_MATCHED),
+		SEQ_LITERAL_WRITE,
+		SEQ_IS_REP,
+		seq_len(SEQ_MATCH_LEN),
+		seq_6(SEQ_POS_SLOT),
+		SEQ_POS_MODEL,
+		SEQ_DIRECT,
+		seq_4(SEQ_ALIGN),
+		SEQ_EOPM,
+		SEQ_IS_REP0,
+		SEQ_SHORTREP,
+		SEQ_IS_REP0_LONG,
+		SEQ_IS_REP1,
+		SEQ_IS_REP2,
+		seq_len(SEQ_REP_LEN),
+		SEQ_COPY,
+	} sequence;
+
+	/// Base of the current probability tree
+	probability *probs;
+
+	/// Symbol being decoded. This is also used as an index variable in
+	/// bittree decoders: probs[symbol]
+	uint32_t symbol;
+
+	/// Used as a loop termination condition on bittree decoders and
+	/// direct bits decoder.
+	uint32_t limit;
+
+	/// Matched literal decoder: 0x100 or 0 to help avoiding branches.
+	/// Bittree reverse decoders: Offset of the next bit: 1 << offset
+	uint32_t offset;
+
+	/// If decoding a literal: match byte.
+	/// If decoding a match: length of the match.
+	uint32_t len;
+};
+
+
+static lzma_ret
+lzma_decode(lzma_coder *restrict coder, lzma_dict *restrict dictptr,
+		const uint8_t *restrict in,
+		size_t *restrict in_pos, size_t in_size)
+{
+	////////////////////
+	// Initialization //
+	////////////////////
+
+	if (!rc_read_init(&coder->rc, in, in_pos, in_size))
+		return LZMA_OK;
+
+	///////////////
+	// Variables //
+	///////////////
+
+	// Making local copies of often-used variables improves both
+	// speed and readability.
+
+	lzma_dict dict = *dictptr;
+
+	const size_t dict_start = dict.pos;
+
+	// Range decoder
+	rc_to_local(coder->rc, *in_pos);
+
+	// State
+	uint32_t state = coder->state;
+	uint32_t rep0 = coder->rep0;
+	uint32_t rep1 = coder->rep1;
+	uint32_t rep2 = coder->rep2;
+	uint32_t rep3 = coder->rep3;
+
+	const uint32_t pos_mask = coder->pos_mask;
+
+	// These variables are actually needed only if we last time ran
+	// out of input in the middle of the decoder loop.
+	probability *probs = coder->probs;
+	uint32_t symbol = coder->symbol;
+	uint32_t limit = coder->limit;
+	uint32_t offset = coder->offset;
+	uint32_t len = coder->len;
+
+	const uint32_t literal_pos_mask = coder->literal_pos_mask;
+	const uint32_t literal_context_bits = coder->literal_context_bits;
+
+	// Temporary variables
+	uint32_t pos_state = dict.pos & pos_mask;
+
+	lzma_ret ret = LZMA_OK;
+
+	// If uncompressed size is known, there must be no end of payload
+	// marker.
+	const bool no_eopm = coder->uncompressed_size
+			!= LZMA_VLI_UNKNOWN;
+	if (no_eopm && coder->uncompressed_size < dict.limit - dict.pos)
+		dict.limit = dict.pos + (size_t)(coder->uncompressed_size);
+
+	// The main decoder loop. The "switch" is used to restart the decoder at
+	// correct location. Once restarted, the "switch" is no longer used.
+	switch (coder->sequence)
+	while (true) {
+		// Calculate new pos_state. This is skipped on the first loop
+		// since we already calculated it when setting up the local
+		// variables.
+		pos_state = dict.pos & pos_mask;
+
+	case SEQ_NORMALIZE:
+	case SEQ_IS_MATCH:
+		if (unlikely(no_eopm && dict.pos == dict.limit))
+			break;
+
+		rc_if_0(coder->is_match[state][pos_state], SEQ_IS_MATCH) {
+			rc_update_0(coder->is_match[state][pos_state]);
+
+			// It's a literal i.e. a single 8-bit byte.
+
+			probs = literal_subcoder(coder->literal,
+					literal_context_bits, literal_pos_mask,
+					dict.pos, dict_get(&dict, 0));
+			symbol = 1;
+
+			if (is_literal_state(state)) {
+				// Decode literal without match byte.
+#ifdef HAVE_SMALL
+	case SEQ_LITERAL:
+				do {
+					rc_bit(probs[symbol], , , SEQ_LITERAL);
+				} while (symbol < (1 << 8));
+#else
+				rc_bit_case(probs[symbol], , , SEQ_LITERAL0);
+				rc_bit_case(probs[symbol], , , SEQ_LITERAL1);
+				rc_bit_case(probs[symbol], , , SEQ_LITERAL2);
+				rc_bit_case(probs[symbol], , , SEQ_LITERAL3);
+				rc_bit_case(probs[symbol], , , SEQ_LITERAL4);
+				rc_bit_case(probs[symbol], , , SEQ_LITERAL5);
+				rc_bit_case(probs[symbol], , , SEQ_LITERAL6);
+				rc_bit_case(probs[symbol], , , SEQ_LITERAL7);
+#endif
+			} else {
+				// Decode literal with match byte.
+				//
+				// We store the byte we compare against
+				// ("match byte") to "len" to minimize the
+				// number of variables we need to store
+				// between decoder calls.
+				len = dict_get(&dict, rep0) << 1;
+
+				// The usage of "offset" allows omitting some
+				// branches, which should give tiny speed
+				// improvement on some CPUs. "offset" gets
+				// set to zero if match_bit didn't match.
+				offset = 0x100;
+
+#ifdef HAVE_SMALL
+	case SEQ_LITERAL_MATCHED:
+				do {
+					const uint32_t match_bit
+							= len & offset;
+					const uint32_t subcoder_index
+							= offset + match_bit
+							+ symbol;
+
+					rc_bit(probs[subcoder_index],
+							offset &= ~match_bit,
+							offset &= match_bit,
+							SEQ_LITERAL_MATCHED);
+
+					// It seems to be faster to do this
+					// here instead of putting it to the
+					// beginning of the loop and then
+					// putting the "case" in the middle
+					// of the loop.
+					len <<= 1;
+
+				} while (symbol < (1 << 8));
+#else
+				// Unroll the loop.
+				uint32_t match_bit;
+				uint32_t subcoder_index;
+
+#	define d(seq) \
+		case seq: \
+			match_bit = len & offset; \
+			subcoder_index = offset + match_bit + symbol; \
+			rc_bit(probs[subcoder_index], \
+					offset &= ~match_bit, \
+					offset &= match_bit, \
+					seq)
+
+				d(SEQ_LITERAL_MATCHED0);
+				len <<= 1;
+				d(SEQ_LITERAL_MATCHED1);
+				len <<= 1;
+				d(SEQ_LITERAL_MATCHED2);
+				len <<= 1;
+				d(SEQ_LITERAL_MATCHED3);
+				len <<= 1;
+				d(SEQ_LITERAL_MATCHED4);
+				len <<= 1;
+				d(SEQ_LITERAL_MATCHED5);
+				len <<= 1;
+				d(SEQ_LITERAL_MATCHED6);
+				len <<= 1;
+				d(SEQ_LITERAL_MATCHED7);
+#	undef d
+#endif
+			}
+
+			//update_literal(state);
+			// Use a lookup table to update to literal state,
+			// since compared to other state updates, this would
+			// need two branches.
+			static const lzma_lzma_state next_state[] = {
+				STATE_LIT_LIT,
+				STATE_LIT_LIT,
+				STATE_LIT_LIT,
+				STATE_LIT_LIT,
+				STATE_MATCH_LIT_LIT,
+				STATE_REP_LIT_LIT,
+				STATE_SHORTREP_LIT_LIT,
+				STATE_MATCH_LIT,
+				STATE_REP_LIT,
+				STATE_SHORTREP_LIT,
+				STATE_MATCH_LIT,
+				STATE_REP_LIT
+			};
+			state = next_state[state];
+
+	case SEQ_LITERAL_WRITE:
+			if (unlikely(dict_put(&dict, symbol))) {
+				coder->sequence = SEQ_LITERAL_WRITE;
+				goto out;
+			}
+
+			continue;
+		}
+
+		// Instead of a new byte we are going to get a byte range
+		// (distance and length) which will be repeated from our
+		// output history.
+
+		rc_update_1(coder->is_match[state][pos_state]);
+
+	case SEQ_IS_REP:
+		rc_if_0(coder->is_rep[state], SEQ_IS_REP) {
+			// Not a repeated match
+			rc_update_0(coder->is_rep[state]);
+			update_match(state);
+
+			// The latest three match distances are kept in
+			// memory in case there are repeated matches.
+			rep3 = rep2;
+			rep2 = rep1;
+			rep1 = rep0;
+
+			// Decode the length of the match.
+			len_decode(len, coder->match_len_decoder,
+					pos_state, SEQ_MATCH_LEN);
+
+			// Prepare to decode the highest two bits of the
+			// match distance.
+			probs = coder->pos_slot[get_len_to_pos_state(len)];
+			symbol = 1;
+
+#ifdef HAVE_SMALL
+	case SEQ_POS_SLOT:
+			do {
+				rc_bit(probs[symbol], , , SEQ_POS_SLOT);
+			} while (symbol < POS_SLOTS);
+#else
+			rc_bit_case(probs[symbol], , , SEQ_POS_SLOT0);
+			rc_bit_case(probs[symbol], , , SEQ_POS_SLOT1);
+			rc_bit_case(probs[symbol], , , SEQ_POS_SLOT2);
+			rc_bit_case(probs[symbol], , , SEQ_POS_SLOT3);
+			rc_bit_case(probs[symbol], , , SEQ_POS_SLOT4);
+			rc_bit_case(probs[symbol], , , SEQ_POS_SLOT5);
+#endif
+			// Get rid of the highest bit that was needed for
+			// indexing of the probability array.
+			symbol -= POS_SLOTS;
+			assert(symbol <= 63);
+
+			if (symbol < START_POS_MODEL_INDEX) {
+				// Match distances [0, 3] have only two bits.
+				rep0 = symbol;
+			} else {
+				// Decode the lowest [1, 29] bits of
+				// the match distance.
+				limit = (symbol >> 1) - 1;
+				assert(limit >= 1 && limit <= 30);
+				rep0 = 2 + (symbol & 1);
+
+				if (symbol < END_POS_MODEL_INDEX) {
+					// Prepare to decode the low bits for
+					// a distance of [4, 127].
+					assert(limit <= 5);
+					rep0 <<= limit;
+					assert(rep0 <= 96);
+					// -1 is fine, because we start
+					// decoding at probs[1], not probs[0].
+					// NOTE: This violates the C standard,
+					// since we are doing pointer
+					// arithmetic past the beginning of
+					// the array.
+					assert((int32_t)(rep0 - symbol - 1)
+							>= -1);
+					assert((int32_t)(rep0 - symbol - 1)
+							<= 82);
+					probs = coder->pos_special + rep0
+							- symbol - 1;
+					symbol = 1;
+					offset = 0;
+	case SEQ_POS_MODEL:
+#ifdef HAVE_SMALL
+					do {
+						rc_bit(probs[symbol], ,
+							rep0 += 1 << offset,
+							SEQ_POS_MODEL);
+					} while (++offset < limit);
+#else
+					switch (limit) {
+					case 5:
+						assert(offset == 0);
+						rc_bit(probs[symbol], ,
+							rep0 += 1,
+							SEQ_POS_MODEL);
+						++offset;
+						--limit;
+					case 4:
+						rc_bit(probs[symbol], ,
+							rep0 += 1 << offset,
+							SEQ_POS_MODEL);
+						++offset;
+						--limit;
+					case 3:
+						rc_bit(probs[symbol], ,
+							rep0 += 1 << offset,
+							SEQ_POS_MODEL);
+						++offset;
+						--limit;
+					case 2:
+						rc_bit(probs[symbol], ,
+							rep0 += 1 << offset,
+							SEQ_POS_MODEL);
+						++offset;
+						--limit;
+					case 1:
+						// We need "symbol" only for
+						// indexing the probability
+						// array, thus we can use
+						// rc_bit_last() here to omit
+						// the unneeded updating of
+						// "symbol".
+						rc_bit_last(probs[symbol], ,
+							rep0 += 1 << offset,
+							SEQ_POS_MODEL);
+					}
+#endif
+				} else {
+					// The distance is >= 128. Decode the
+					// lower bits without probabilities
+					// except the lowest four bits.
+					assert(symbol >= 14);
+					assert(limit >= 6);
+					limit -= ALIGN_BITS;
+					assert(limit >= 2);
+	case SEQ_DIRECT:
+					// Not worth manual unrolling
+					do {
+						rc_direct(rep0, SEQ_DIRECT);
+					} while (--limit > 0);
+
+					// Decode the lowest four bits using
+					// probabilities.
+					rep0 <<= ALIGN_BITS;
+					symbol = 1;
+#ifdef HAVE_SMALL
+					offset = 0;
+	case SEQ_ALIGN:
+					do {
+						rc_bit(coder->pos_align[
+								symbol], ,
+							rep0 += 1 << offset,
+							SEQ_ALIGN);
+					} while (++offset < ALIGN_BITS);
+#else
+	case SEQ_ALIGN0:
+					rc_bit(coder->pos_align[symbol], ,
+							rep0 += 1, SEQ_ALIGN0);
+	case SEQ_ALIGN1:
+					rc_bit(coder->pos_align[symbol], ,
+							rep0 += 2, SEQ_ALIGN1);
+	case SEQ_ALIGN2:
+					rc_bit(coder->pos_align[symbol], ,
+							rep0 += 4, SEQ_ALIGN2);
+	case SEQ_ALIGN3:
+					// Like in SEQ_POS_MODEL, we don't
+					// need "symbol" for anything else
+					// than indexing the probability array.
+					rc_bit_last(coder->pos_align[symbol], ,
+							rep0 += 8, SEQ_ALIGN3);
+#endif
+
+					if (rep0 == UINT32_MAX) {
+						// End of payload marker was
+						// found. It must not be
+						// present if uncompressed
+						// size is known.
+						if (coder->uncompressed_size
+						!= LZMA_VLI_UNKNOWN) {
+							ret = LZMA_DATA_ERROR;
+							goto out;
+						}
+
+	case SEQ_EOPM:
+						// TODO Comment
+						rc_normalize(SEQ_EOPM);
+						ret = LZMA_STREAM_END;
+						goto out;
+					}
+				}
+			}
+
+			// Validate the distance we just decoded.
+			if (unlikely(!dict_is_distance_valid(&dict, rep0))) {
+				ret = LZMA_DATA_ERROR;
+				goto out;
+			}
+
+		} else {
+			rc_update_1(coder->is_rep[state]);
+
+			// Repeated match
+			//
+			// The match distance is a value that we have had
+			// earlier. The latest four match distances are
+			// available as rep0, rep1, rep2 and rep3. We will
+			// now decode which of them is the new distance.
+			//
+			// There cannot be a match if we haven't produced
+			// any output, so check that first.
+			if (unlikely(!dict_is_distance_valid(&dict, 0))) {
+				ret = LZMA_DATA_ERROR;
+				goto out;
+			}
+
+	case SEQ_IS_REP0:
+			rc_if_0(coder->is_rep0[state], SEQ_IS_REP0) {
+				rc_update_0(coder->is_rep0[state]);
+				// The distance is rep0.
+
+	case SEQ_IS_REP0_LONG:
+				rc_if_0(coder->is_rep0_long[state][pos_state],
+						SEQ_IS_REP0_LONG) {
+					rc_update_0(coder->is_rep0_long[
+							state][pos_state]);
+
+					update_short_rep(state);
+
+	case SEQ_SHORTREP:
+					if (unlikely(dict_put(&dict, dict_get(
+							&dict, rep0)))) {
+						coder->sequence = SEQ_SHORTREP;
+						goto out;
+					}
+
+					continue;
+				}
+
+				// Repeating more than one byte at
+				// distance of rep0.
+				rc_update_1(coder->is_rep0_long[
+						state][pos_state]);
+
+			} else {
+				rc_update_1(coder->is_rep0[state]);
+
+	case SEQ_IS_REP1:
+				// The distance is rep1, rep2 or rep3. Once
+				// we find out which one of these three, it
+				// is stored to rep0 and rep1, rep2 and rep3
+				// are updated accordingly.
+				rc_if_0(coder->is_rep1[state], SEQ_IS_REP1) {
+					rc_update_0(coder->is_rep1[state]);
+
+					const uint32_t distance = rep1;
+					rep1 = rep0;
+					rep0 = distance;
+
+				} else {
+					rc_update_1(coder->is_rep1[state]);
+	case SEQ_IS_REP2:
+					rc_if_0(coder->is_rep2[state],
+							SEQ_IS_REP2) {
+						rc_update_0(coder->is_rep2[
+								state]);
+
+						const uint32_t distance = rep2;
+						rep2 = rep1;
+						rep1 = rep0;
+						rep0 = distance;
+
+					} else {
+						rc_update_1(coder->is_rep2[
+								state]);
+
+						const uint32_t distance = rep3;
+						rep3 = rep2;
+						rep2 = rep1;
+						rep1 = rep0;
+						rep0 = distance;
+					}
+				}
+			}
+
+			update_long_rep(state);
+
+			// Decode the length of the repeated match.
+			len_decode(len, coder->rep_len_decoder,
+					pos_state, SEQ_REP_LEN);
+		}
+
+		/////////////////////////////////
+		// Repeat from history buffer. //
+		/////////////////////////////////
+
+		// The length is always between these limits. There is no way
+		// to trigger the algorithm to set len outside this range.
+		assert(len >= MATCH_LEN_MIN);
+		assert(len <= MATCH_LEN_MAX);
+
+	case SEQ_COPY:
+		// Repeat len bytes from distance of rep0.
+		if (unlikely(dict_repeat(&dict, rep0, &len))) {
+			coder->sequence = SEQ_COPY;
+			goto out;
+		}
+	}
+
+	rc_normalize(SEQ_NORMALIZE);
+	coder->sequence = SEQ_IS_MATCH;
+
+out:
+	// Save state
+
+	// NOTE: Must not copy dict.limit.
+	dictptr->pos = dict.pos;
+	dictptr->full = dict.full;
+
+	rc_from_local(coder->rc, *in_pos);
+
+	coder->state = state;
+	coder->rep0 = rep0;
+	coder->rep1 = rep1;
+	coder->rep2 = rep2;
+	coder->rep3 = rep3;
+
+	coder->probs = probs;
+	coder->symbol = symbol;
+	coder->limit = limit;
+	coder->offset = offset;
+	coder->len = len;
+
+	// Update the remaining amount of uncompressed data if uncompressed
+	// size was known.
+	if (coder->uncompressed_size != LZMA_VLI_UNKNOWN) {
+		coder->uncompressed_size -= dict.pos - dict_start;
+
+		// Since there cannot be end of payload marker if the
+		// uncompressed size was known, we check here if we
+		// finished decoding.
+		if (coder->uncompressed_size == 0 && ret == LZMA_OK
+				&& coder->sequence != SEQ_NORMALIZE)
+			ret = coder->sequence == SEQ_IS_MATCH
+					? LZMA_STREAM_END : LZMA_DATA_ERROR;
+	}
+
+	// We can do an additional check in the range decoder to catch some
+	// corrupted files.
+	if (ret == LZMA_STREAM_END) {
+		if (!rc_is_finished(coder->rc))
+			ret = LZMA_DATA_ERROR;
+
+		// Reset the range decoder so that it is ready to reinitialize
+		// for a new LZMA2 chunk.
+		rc_reset(coder->rc);
+	}
+
+	return ret;
+}
+
+
+
+static void
+lzma_decoder_uncompressed(lzma_coder *coder, lzma_vli uncompressed_size)
+{
+	coder->uncompressed_size = uncompressed_size;
+}
+
+/*
+extern void
+lzma_lzma_decoder_uncompressed(void *coder_ptr, lzma_vli uncompressed_size)
+{
+	// This is hack.
+	(*(lzma_coder **)(coder))->uncompressed_size = uncompressed_size;
+}
+*/
+
+static void
+lzma_decoder_reset(lzma_coder *coder, const void *opt)
+{
+	const lzma_options_lzma *options = opt;
+
+	// NOTE: We assume that lc/lp/pb are valid since they were
+	// successfully decoded with lzma_lzma_decode_properties().
+	// FIXME?
+
+	// Calculate pos_mask. We don't need pos_bits as is for anything.
+	coder->pos_mask = (1U << options->pb) - 1;
+
+	// Initialize the literal decoder.
+	literal_init(coder->literal, options->lc, options->lp);
+
+	coder->literal_context_bits = options->lc;
+	coder->literal_pos_mask = (1U << options->lp) - 1;
+
+	// State
+	coder->state = STATE_LIT_LIT;
+	coder->rep0 = 0;
+	coder->rep1 = 0;
+	coder->rep2 = 0;
+	coder->rep3 = 0;
+	coder->pos_mask = (1U << options->pb) - 1;
+
+	// Range decoder
+	rc_reset(coder->rc);
+
+	// Bit and bittree decoders
+	for (uint32_t i = 0; i < STATES; ++i) {
+		for (uint32_t j = 0; j <= coder->pos_mask; ++j) {
+			bit_reset(coder->is_match[i][j]);
+			bit_reset(coder->is_rep0_long[i][j]);
+		}
+
+		bit_reset(coder->is_rep[i]);
+		bit_reset(coder->is_rep0[i]);
+		bit_reset(coder->is_rep1[i]);
+		bit_reset(coder->is_rep2[i]);
+	}
+
+	for (uint32_t i = 0; i < LEN_TO_POS_STATES; ++i)
+		bittree_reset(coder->pos_slot[i], POS_SLOT_BITS);
+
+	for (uint32_t i = 0; i < FULL_DISTANCES - END_POS_MODEL_INDEX; ++i)
+		bit_reset(coder->pos_special[i]);
+
+	bittree_reset(coder->pos_align, ALIGN_BITS);
+
+	// Len decoders (also bit/bittree)
+	const uint32_t num_pos_states = 1U << options->pb;
+	bit_reset(coder->match_len_decoder.choice);
+	bit_reset(coder->match_len_decoder.choice2);
+	bit_reset(coder->rep_len_decoder.choice);
+	bit_reset(coder->rep_len_decoder.choice2);
+
+	for (uint32_t pos_state = 0; pos_state < num_pos_states; ++pos_state) {
+		bittree_reset(coder->match_len_decoder.low[pos_state],
+				LEN_LOW_BITS);
+		bittree_reset(coder->match_len_decoder.mid[pos_state],
+				LEN_MID_BITS);
+
+		bittree_reset(coder->rep_len_decoder.low[pos_state],
+				LEN_LOW_BITS);
+		bittree_reset(coder->rep_len_decoder.mid[pos_state],
+				LEN_MID_BITS);
+	}
+
+	bittree_reset(coder->match_len_decoder.high, LEN_HIGH_BITS);
+	bittree_reset(coder->rep_len_decoder.high, LEN_HIGH_BITS);
+
+	coder->sequence = SEQ_IS_MATCH;
+	coder->probs = NULL;
+	coder->symbol = 0;
+	coder->limit = 0;
+	coder->offset = 0;
+	coder->len = 0;
+
+	return;
+}
+
+
+extern lzma_ret
+lzma_lzma_decoder_create(lzma_lz_decoder *lz, lzma_allocator *allocator,
+		const void *opt, lzma_lz_options *lz_options)
+{
+	if (lz->coder == NULL) {
+		lz->coder = lzma_alloc(sizeof(lzma_coder), allocator);
+		if (lz->coder == NULL)
+			return LZMA_MEM_ERROR;
+
+		lz->code = &lzma_decode;
+		lz->reset = &lzma_decoder_reset;
+		lz->set_uncompressed = &lzma_decoder_uncompressed;
+	}
+
+	// All dictionary sizes are OK here. LZ decoder will take care of
+	// the special cases.
+	const lzma_options_lzma *options = opt;
+	lz_options->dict_size = options->dict_size;
+	lz_options->preset_dict = options->preset_dict;
+	lz_options->preset_dict_size = options->preset_dict_size;
+
+	return LZMA_OK;
+}
+
+
+/// Allocate and initialize LZMA decoder. This is used only via LZ
+/// initialization (lzma_lzma_decoder_init() passes function pointer to
+/// the LZ initialization).
+static lzma_ret
+lzma_decoder_init(lzma_lz_decoder *lz, lzma_allocator *allocator,
+		const void *options, lzma_lz_options *lz_options)
+{
+	if (!is_lclppb_valid(options))
+		return LZMA_PROG_ERROR;
+
+	return_if_error(lzma_lzma_decoder_create(
+			lz, allocator, options, lz_options));
+
+	lzma_decoder_reset(lz->coder, options);
+	lzma_decoder_uncompressed(lz->coder, LZMA_VLI_UNKNOWN);
+
+	return LZMA_OK;
+}
+
+
+extern lzma_ret
+lzma_lzma_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters)
+{
+	// LZMA can only be the last filter in the chain. This is enforced
+	// by the raw_decoder initialization.
+	assert(filters[1].init == NULL);
+
+	return lzma_lz_decoder_init(next, allocator, filters,
+			&lzma_decoder_init);
+}
+
+
+extern bool
+lzma_lzma_lclppb_decode(lzma_options_lzma *options, uint8_t byte)
+{
+	if (byte > (4 * 5 + 4) * 9 + 8)
+		return true;
+
+	// See the file format specification to understand this.
+	options->pb = byte / (9 * 5);
+	byte -= options->pb * 9 * 5;
+	options->lp = byte / 9;
+	options->lc = byte - options->lp * 9;
+
+	return options->lc + options->lp > LZMA_LCLP_MAX;
+}
+
+
+extern uint64_t
+lzma_lzma_decoder_memusage_nocheck(const void *options)
+{
+	const lzma_options_lzma *const opt = options;
+	return sizeof(lzma_coder) + lzma_lz_decoder_memusage(opt->dict_size);
+}
+
+
+extern uint64_t
+lzma_lzma_decoder_memusage(const void *options)
+{
+	if (!is_lclppb_valid(options))
+		return UINT64_MAX;
+
+	return lzma_lzma_decoder_memusage_nocheck(options);
+}
+
+
+extern lzma_ret
+lzma_lzma_props_decode(void **options, lzma_allocator *allocator,
+		const uint8_t *props, size_t props_size)
+{
+	if (props_size != 5)
+		return LZMA_OPTIONS_ERROR;
+
+	lzma_options_lzma *opt
+			= lzma_alloc(sizeof(lzma_options_lzma), allocator);
+	if (opt == NULL)
+		return LZMA_MEM_ERROR;
+
+	if (lzma_lzma_lclppb_decode(opt, props[0]))
+		goto error;
+
+	// All dictionary sizes are accepted, including zero. LZ decoder
+	// will automatically use a dictionary at least a few KiB even if
+	// a smaller dictionary is requested.
+	opt->dict_size = unaligned_read32le(props + 1);
+
+	opt->preset_dict = NULL;
+	opt->preset_dict_size = 0;
+
+	*options = opt;
+
+	return LZMA_OK;
+
+error:
+	lzma_free(opt, allocator);
+	return LZMA_OPTIONS_ERROR;
+}
diff --git a/src/liblzma/lzma/lzma_decoder.h b/src/liblzma/lzma/lzma_decoder.h
new file mode 100644
index 0000000..a463a76
--- /dev/null
+++ b/src/liblzma/lzma/lzma_decoder.h
@@ -0,0 +1,52 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma_decoder.h
+/// \brief      LZMA decoder API
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_LZMA_DECODER_H
+#define LZMA_LZMA_DECODER_H
+
+#include "common.h"
+
+
+/// Allocates and initializes LZMA decoder
+extern lzma_ret lzma_lzma_decoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters);
+
+extern uint64_t lzma_lzma_decoder_memusage(const void *options);
+
+extern lzma_ret lzma_lzma_props_decode(
+		void **options, lzma_allocator *allocator,
+		const uint8_t *props, size_t props_size);
+
+
+/// \brief      Decodes the LZMA Properties byte (lc/lp/pb)
+///
+/// \return     true if error occurred, false on success
+///
+extern bool lzma_lzma_lclppb_decode(
+		lzma_options_lzma *options, uint8_t byte);
+
+
+#ifdef LZMA_LZ_DECODER_H
+/// Allocate and setup function pointers only. This is used by LZMA1 and
+/// LZMA2 decoders.
+extern lzma_ret lzma_lzma_decoder_create(
+		lzma_lz_decoder *lz, lzma_allocator *allocator,
+		const void *opt, lzma_lz_options *lz_options);
+
+/// Gets memory usage without validating lc/lp/pb. This is used by LZMA2
+/// decoder, because raw LZMA2 decoding doesn't need lc/lp/pb.
+extern uint64_t lzma_lzma_decoder_memusage_nocheck(const void *options);
+
+#endif
+
+#endif
diff --git a/src/liblzma/lzma/lzma_encoder.c b/src/liblzma/lzma/lzma_encoder.c
new file mode 100644
index 0000000..0fe992d
--- /dev/null
+++ b/src/liblzma/lzma/lzma_encoder.c
@@ -0,0 +1,675 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma_encoder.c
+/// \brief      LZMA encoder
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "lzma2_encoder.h"
+#include "lzma_encoder_private.h"
+#include "fastpos.h"
+
+
+/////////////
+// Literal //
+/////////////
+
+static inline void
+literal_matched(lzma_range_encoder *rc, probability *subcoder,
+		uint32_t match_byte, uint32_t symbol)
+{
+	uint32_t offset = 0x100;
+	symbol += UINT32_C(1) << 8;
+
+	do {
+		match_byte <<= 1;
+		const uint32_t match_bit = match_byte & offset;
+		const uint32_t subcoder_index
+				= offset + match_bit + (symbol >> 8);
+		const uint32_t bit = (symbol >> 7) & 1;
+		rc_bit(rc, &subcoder[subcoder_index], bit);
+
+		symbol <<= 1;
+		offset &= ~(match_byte ^ symbol);
+
+	} while (symbol < (UINT32_C(1) << 16));
+}
+
+
+static inline void
+literal(lzma_coder *coder, lzma_mf *mf, uint32_t position)
+{
+	// Locate the literal byte to be encoded and the subcoder.
+	const uint8_t cur_byte = mf->buffer[
+			mf->read_pos - mf->read_ahead];
+	probability *subcoder = literal_subcoder(coder->literal,
+			coder->literal_context_bits, coder->literal_pos_mask,
+			position, mf->buffer[mf->read_pos - mf->read_ahead - 1]);
+
+	if (is_literal_state(coder->state)) {
+		// Previous LZMA-symbol was a literal. Encode a normal
+		// literal without a match byte.
+		rc_bittree(&coder->rc, subcoder, 8, cur_byte);
+	} else {
+		// Previous LZMA-symbol was a match. Use the last byte of
+		// the match as a "match byte". That is, compare the bits
+		// of the current literal and the match byte.
+		const uint8_t match_byte = mf->buffer[
+				mf->read_pos - coder->reps[0] - 1
+				- mf->read_ahead];
+		literal_matched(&coder->rc, subcoder, match_byte, cur_byte);
+	}
+
+	update_literal(coder->state);
+}
+
+
+//////////////////
+// Match length //
+//////////////////
+
+static void
+length_update_prices(lzma_length_encoder *lc, const uint32_t pos_state)
+{
+	const uint32_t table_size = lc->table_size;
+	lc->counters[pos_state] = table_size;
+
+	const uint32_t a0 = rc_bit_0_price(lc->choice);
+	const uint32_t a1 = rc_bit_1_price(lc->choice);
+	const uint32_t b0 = a1 + rc_bit_0_price(lc->choice2);
+	const uint32_t b1 = a1 + rc_bit_1_price(lc->choice2);
+	uint32_t *const prices = lc->prices[pos_state];
+
+	uint32_t i;
+	for (i = 0; i < table_size && i < LEN_LOW_SYMBOLS; ++i)
+		prices[i] = a0 + rc_bittree_price(lc->low[pos_state],
+				LEN_LOW_BITS, i);
+
+	for (; i < table_size && i < LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS; ++i)
+		prices[i] = b0 + rc_bittree_price(lc->mid[pos_state],
+				LEN_MID_BITS, i - LEN_LOW_SYMBOLS);
+
+	for (; i < table_size; ++i)
+		prices[i] = b1 + rc_bittree_price(lc->high, LEN_HIGH_BITS,
+				i - LEN_LOW_SYMBOLS - LEN_MID_SYMBOLS);
+
+	return;
+}
+
+
+static inline void
+length(lzma_range_encoder *rc, lzma_length_encoder *lc,
+		const uint32_t pos_state, uint32_t len, const bool fast_mode)
+{
+	assert(len <= MATCH_LEN_MAX);
+	len -= MATCH_LEN_MIN;
+
+	if (len < LEN_LOW_SYMBOLS) {
+		rc_bit(rc, &lc->choice, 0);
+		rc_bittree(rc, lc->low[pos_state], LEN_LOW_BITS, len);
+	} else {
+		rc_bit(rc, &lc->choice, 1);
+		len -= LEN_LOW_SYMBOLS;
+
+		if (len < LEN_MID_SYMBOLS) {
+			rc_bit(rc, &lc->choice2, 0);
+			rc_bittree(rc, lc->mid[pos_state], LEN_MID_BITS, len);
+		} else {
+			rc_bit(rc, &lc->choice2, 1);
+			len -= LEN_MID_SYMBOLS;
+			rc_bittree(rc, lc->high, LEN_HIGH_BITS, len);
+		}
+	}
+
+	// Only getoptimum uses the prices so don't update the table when
+	// in fast mode.
+	if (!fast_mode)
+		if (--lc->counters[pos_state] == 0)
+			length_update_prices(lc, pos_state);
+}
+
+
+///////////
+// Match //
+///////////
+
+static inline void
+match(lzma_coder *coder, const uint32_t pos_state,
+		const uint32_t distance, const uint32_t len)
+{
+	update_match(coder->state);
+
+	length(&coder->rc, &coder->match_len_encoder, pos_state, len,
+			coder->fast_mode);
+
+	const uint32_t pos_slot = get_pos_slot(distance);
+	const uint32_t len_to_pos_state = get_len_to_pos_state(len);
+	rc_bittree(&coder->rc, coder->pos_slot[len_to_pos_state],
+			POS_SLOT_BITS, pos_slot);
+
+	if (pos_slot >= START_POS_MODEL_INDEX) {
+		const uint32_t footer_bits = (pos_slot >> 1) - 1;
+		const uint32_t base = (2 | (pos_slot & 1)) << footer_bits;
+		const uint32_t pos_reduced = distance - base;
+
+		if (pos_slot < END_POS_MODEL_INDEX) {
+			// Careful here: base - pos_slot - 1 can be -1, but
+			// rc_bittree_reverse starts at probs[1], not probs[0].
+			rc_bittree_reverse(&coder->rc,
+				coder->pos_special + base - pos_slot - 1,
+				footer_bits, pos_reduced);
+		} else {
+			rc_direct(&coder->rc, pos_reduced >> ALIGN_BITS,
+					footer_bits - ALIGN_BITS);
+			rc_bittree_reverse(
+					&coder->rc, coder->pos_align,
+					ALIGN_BITS, pos_reduced & ALIGN_MASK);
+			++coder->align_price_count;
+		}
+	}
+
+	coder->reps[3] = coder->reps[2];
+	coder->reps[2] = coder->reps[1];
+	coder->reps[1] = coder->reps[0];
+	coder->reps[0] = distance;
+	++coder->match_price_count;
+}
+
+
+////////////////////
+// Repeated match //
+////////////////////
+
+static inline void
+rep_match(lzma_coder *coder, const uint32_t pos_state,
+		const uint32_t rep, const uint32_t len)
+{
+	if (rep == 0) {
+		rc_bit(&coder->rc, &coder->is_rep0[coder->state], 0);
+		rc_bit(&coder->rc,
+				&coder->is_rep0_long[coder->state][pos_state],
+				len != 1);
+	} else {
+		const uint32_t distance = coder->reps[rep];
+		rc_bit(&coder->rc, &coder->is_rep0[coder->state], 1);
+
+		if (rep == 1) {
+			rc_bit(&coder->rc, &coder->is_rep1[coder->state], 0);
+		} else {
+			rc_bit(&coder->rc, &coder->is_rep1[coder->state], 1);
+			rc_bit(&coder->rc, &coder->is_rep2[coder->state],
+					rep - 2);
+
+			if (rep == 3)
+				coder->reps[3] = coder->reps[2];
+
+			coder->reps[2] = coder->reps[1];
+		}
+
+		coder->reps[1] = coder->reps[0];
+		coder->reps[0] = distance;
+	}
+
+	if (len == 1) {
+		update_short_rep(coder->state);
+	} else {
+		length(&coder->rc, &coder->rep_len_encoder, pos_state, len,
+				coder->fast_mode);
+		update_long_rep(coder->state);
+	}
+}
+
+
+//////////
+// Main //
+//////////
+
+static void
+encode_symbol(lzma_coder *coder, lzma_mf *mf,
+		uint32_t back, uint32_t len, uint32_t position)
+{
+	const uint32_t pos_state = position & coder->pos_mask;
+
+	if (back == UINT32_MAX) {
+		// Literal i.e. eight-bit byte
+		assert(len == 1);
+		rc_bit(&coder->rc,
+				&coder->is_match[coder->state][pos_state], 0);
+		literal(coder, mf, position);
+	} else {
+		// Some type of match
+		rc_bit(&coder->rc,
+			&coder->is_match[coder->state][pos_state], 1);
+
+		if (back < REP_DISTANCES) {
+			// It's a repeated match i.e. the same distance
+			// has been used earlier.
+			rc_bit(&coder->rc, &coder->is_rep[coder->state], 1);
+			rep_match(coder, pos_state, back, len);
+		} else {
+			// Normal match
+			rc_bit(&coder->rc, &coder->is_rep[coder->state], 0);
+			match(coder, pos_state, back - REP_DISTANCES, len);
+		}
+	}
+
+	assert(mf->read_ahead >= len);
+	mf->read_ahead -= len;
+}
+
+
+static bool
+encode_init(lzma_coder *coder, lzma_mf *mf)
+{
+	assert(mf_position(mf) == 0);
+
+	if (mf->read_pos == mf->read_limit) {
+		if (mf->action == LZMA_RUN)
+			return false; // We cannot do anything.
+
+		// We are finishing (we cannot get here when flushing).
+		assert(mf->write_pos == mf->read_pos);
+		assert(mf->action == LZMA_FINISH);
+	} else {
+		// Do the actual initialization. The first LZMA symbol must
+		// always be a literal.
+		mf_skip(mf, 1);
+		mf->read_ahead = 0;
+		rc_bit(&coder->rc, &coder->is_match[0][0], 0);
+		rc_bittree(&coder->rc, coder->literal[0], 8, mf->buffer[0]);
+	}
+
+	// Initialization is done (except if empty file).
+	coder->is_initialized = true;
+
+	return true;
+}
+
+
+static void
+encode_eopm(lzma_coder *coder, uint32_t position)
+{
+	const uint32_t pos_state = position & coder->pos_mask;
+	rc_bit(&coder->rc, &coder->is_match[coder->state][pos_state], 1);
+	rc_bit(&coder->rc, &coder->is_rep[coder->state], 0);
+	match(coder, pos_state, UINT32_MAX, MATCH_LEN_MIN);
+}
+
+
+/// Number of bytes that a single encoding loop in lzma_lzma_encode() can
+/// consume from the dictionary. This limit comes from lzma_lzma_optimum()
+/// and may need to be updated if that function is significantly modified.
+#define LOOP_INPUT_MAX (OPTS + 1)
+
+
+extern lzma_ret
+lzma_lzma_encode(lzma_coder *restrict coder, lzma_mf *restrict mf,
+		uint8_t *restrict out, size_t *restrict out_pos,
+		size_t out_size, uint32_t limit)
+{
+	// Initialize the stream if no data has been encoded yet.
+	if (!coder->is_initialized && !encode_init(coder, mf))
+		return LZMA_OK;
+
+	// Get the lowest bits of the uncompressed offset from the LZ layer.
+	uint32_t position = mf_position(mf);
+
+	while (true) {
+		// Encode pending bits, if any. Calling this before encoding
+		// the next symbol is needed only with plain LZMA, since
+		// LZMA2 always provides big enough buffer to flush
+		// everything out from the range encoder. For the same reason,
+		// rc_encode() never returns true when this function is used
+		// as part of LZMA2 encoder.
+		if (rc_encode(&coder->rc, out, out_pos, out_size)) {
+			assert(limit == UINT32_MAX);
+			return LZMA_OK;
+		}
+
+		// With LZMA2 we need to take care that compressed size of
+		// a chunk doesn't get too big.
+		// TODO
+		if (limit != UINT32_MAX
+				&& (mf->read_pos - mf->read_ahead >= limit
+					|| *out_pos + rc_pending(&coder->rc)
+						>= LZMA2_CHUNK_MAX
+							- LOOP_INPUT_MAX))
+			break;
+
+		// Check that there is some input to process.
+		if (mf->read_pos >= mf->read_limit) {
+			if (mf->action == LZMA_RUN)
+				return LZMA_OK;
+
+			if (mf->read_ahead == 0)
+				break;
+		}
+
+		// Get optimal match (repeat position and length).
+		// Value ranges for pos:
+		//   - [0, REP_DISTANCES): repeated match
+		//   - [REP_DISTANCES, UINT32_MAX):
+		//     match at (pos - REP_DISTANCES)
+		//   - UINT32_MAX: not a match but a literal
+		// Value ranges for len:
+		//   - [MATCH_LEN_MIN, MATCH_LEN_MAX]
+		uint32_t len;
+		uint32_t back;
+
+		if (coder->fast_mode)
+			lzma_lzma_optimum_fast(coder, mf, &back, &len);
+		else
+			lzma_lzma_optimum_normal(
+					coder, mf, &back, &len, position);
+
+		encode_symbol(coder, mf, back, len, position);
+
+		position += len;
+	}
+
+	if (!coder->is_flushed) {
+		coder->is_flushed = true;
+
+		// We don't support encoding plain LZMA streams without EOPM,
+		// and LZMA2 doesn't use EOPM at LZMA level.
+		if (limit == UINT32_MAX)
+			encode_eopm(coder, position);
+
+		// Flush the remaining bytes from the range encoder.
+		rc_flush(&coder->rc);
+
+		// Copy the remaining bytes to the output buffer. If there
+		// isn't enough output space, we will copy out the remaining
+		// bytes on the next call to this function by using
+		// the rc_encode() call in the encoding loop above.
+		if (rc_encode(&coder->rc, out, out_pos, out_size)) {
+			assert(limit == UINT32_MAX);
+			return LZMA_OK;
+		}
+	}
+
+	// Make it ready for the next LZMA2 chunk.
+	coder->is_flushed = false;
+
+	return LZMA_STREAM_END;
+}
+
+
+static lzma_ret
+lzma_encode(lzma_coder *restrict coder, lzma_mf *restrict mf,
+		uint8_t *restrict out, size_t *restrict out_pos,
+		size_t out_size)
+{
+	// Plain LZMA has no support for sync-flushing.
+	if (unlikely(mf->action == LZMA_SYNC_FLUSH))
+		return LZMA_OPTIONS_ERROR;
+
+	return lzma_lzma_encode(coder, mf, out, out_pos, out_size, UINT32_MAX);
+}
+
+
+////////////////////
+// Initialization //
+////////////////////
+
+static bool
+is_options_valid(const lzma_options_lzma *options)
+{
+	// Validate some of the options. LZ encoder validates nice_len too
+	// but we need a valid value here earlier.
+	return is_lclppb_valid(options)
+			&& options->nice_len >= MATCH_LEN_MIN
+			&& options->nice_len <= MATCH_LEN_MAX
+			&& (options->mode == LZMA_MODE_FAST
+				|| options->mode == LZMA_MODE_NORMAL);
+}
+
+
+static void
+set_lz_options(lzma_lz_options *lz_options, const lzma_options_lzma *options)
+{
+	// LZ encoder initialization does the validation for these so we
+	// don't need to validate here.
+	lz_options->before_size = OPTS;
+	lz_options->dict_size = options->dict_size;
+	lz_options->after_size = LOOP_INPUT_MAX;
+	lz_options->match_len_max = MATCH_LEN_MAX;
+	lz_options->nice_len = options->nice_len;
+	lz_options->match_finder = options->mf;
+	lz_options->depth = options->depth;
+	lz_options->preset_dict = options->preset_dict;
+	lz_options->preset_dict_size = options->preset_dict_size;
+	return;
+}
+
+
+static void
+length_encoder_reset(lzma_length_encoder *lencoder,
+		const uint32_t num_pos_states, const bool fast_mode)
+{
+	bit_reset(lencoder->choice);
+	bit_reset(lencoder->choice2);
+
+	for (size_t pos_state = 0; pos_state < num_pos_states; ++pos_state) {
+		bittree_reset(lencoder->low[pos_state], LEN_LOW_BITS);
+		bittree_reset(lencoder->mid[pos_state], LEN_MID_BITS);
+	}
+
+	bittree_reset(lencoder->high, LEN_HIGH_BITS);
+
+	if (!fast_mode)
+		for (size_t pos_state = 0; pos_state < num_pos_states;
+				++pos_state)
+			length_update_prices(lencoder, pos_state);
+
+	return;
+}
+
+
+extern lzma_ret
+lzma_lzma_encoder_reset(lzma_coder *coder, const lzma_options_lzma *options)
+{
+	if (!is_options_valid(options))
+		return LZMA_OPTIONS_ERROR;
+
+	coder->pos_mask = (1U << options->pb) - 1;
+	coder->literal_context_bits = options->lc;
+	coder->literal_pos_mask = (1U << options->lp) - 1;
+
+	// Range coder
+	rc_reset(&coder->rc);
+
+	// State
+	coder->state = STATE_LIT_LIT;
+	for (size_t i = 0; i < REP_DISTANCES; ++i)
+		coder->reps[i] = 0;
+
+	literal_init(coder->literal, options->lc, options->lp);
+
+	// Bit encoders
+	for (size_t i = 0; i < STATES; ++i) {
+		for (size_t j = 0; j <= coder->pos_mask; ++j) {
+			bit_reset(coder->is_match[i][j]);
+			bit_reset(coder->is_rep0_long[i][j]);
+		}
+
+		bit_reset(coder->is_rep[i]);
+		bit_reset(coder->is_rep0[i]);
+		bit_reset(coder->is_rep1[i]);
+		bit_reset(coder->is_rep2[i]);
+	}
+
+	for (size_t i = 0; i < FULL_DISTANCES - END_POS_MODEL_INDEX; ++i)
+		bit_reset(coder->pos_special[i]);
+
+	// Bit tree encoders
+	for (size_t i = 0; i < LEN_TO_POS_STATES; ++i)
+		bittree_reset(coder->pos_slot[i], POS_SLOT_BITS);
+
+	bittree_reset(coder->pos_align, ALIGN_BITS);
+
+	// Length encoders
+	length_encoder_reset(&coder->match_len_encoder,
+			1U << options->pb, coder->fast_mode);
+
+	length_encoder_reset(&coder->rep_len_encoder,
+			1U << options->pb, coder->fast_mode);
+
+	// Price counts are incremented every time appropriate probabilities
+	// are changed. price counts are set to zero when the price tables
+	// are updated, which is done when the appropriate price counts have
+	// big enough value, and lzma_mf.read_ahead == 0 which happens at
+	// least every OPTS (a few thousand) possible price count increments.
+	//
+	// By resetting price counts to UINT32_MAX / 2, we make sure that the
+	// price tables will be initialized before they will be used (since
+	// the value is definitely big enough), and that it is OK to increment
+	// price counts without risk of integer overflow (since UINT32_MAX / 2
+	// is small enough). The current code doesn't increment price counts
+	// before initializing price tables, but it maybe done in future if
+	// we add support for saving the state between LZMA2 chunks.
+	coder->match_price_count = UINT32_MAX / 2;
+	coder->align_price_count = UINT32_MAX / 2;
+
+	coder->opts_end_index = 0;
+	coder->opts_current_index = 0;
+
+	return LZMA_OK;
+}
+
+
+extern lzma_ret
+lzma_lzma_encoder_create(lzma_coder **coder_ptr, lzma_allocator *allocator,
+		const lzma_options_lzma *options, lzma_lz_options *lz_options)
+{
+	// Allocate lzma_coder if it wasn't already allocated.
+	if (*coder_ptr == NULL) {
+		*coder_ptr = lzma_alloc(sizeof(lzma_coder), allocator);
+		if (*coder_ptr == NULL)
+			return LZMA_MEM_ERROR;
+	}
+
+	lzma_coder *coder = *coder_ptr;
+
+	// Set compression mode. We haven't validates the options yet,
+	// but it's OK here, since nothing bad happens with invalid
+	// options in the code below, and they will get rejected by
+	// lzma_lzma_encoder_reset() call at the end of this function.
+	switch (options->mode) {
+		case LZMA_MODE_FAST:
+			coder->fast_mode = true;
+			break;
+
+		case LZMA_MODE_NORMAL: {
+			coder->fast_mode = false;
+
+			// Set dist_table_size.
+			// Round the dictionary size up to next 2^n.
+			uint32_t log_size = 0;
+			while ((UINT32_C(1) << log_size) < options->dict_size)
+				++log_size;
+
+			coder->dist_table_size = log_size * 2;
+
+			// Length encoders' price table size
+			coder->match_len_encoder.table_size
+				= options->nice_len + 1 - MATCH_LEN_MIN;
+			coder->rep_len_encoder.table_size
+				= options->nice_len + 1 - MATCH_LEN_MIN;
+			break;
+		}
+
+		default:
+			return LZMA_OPTIONS_ERROR;
+	}
+
+	// We don't need to write the first byte as literal if there is
+	// a non-empty preset dictionary. encode_init() wouldn't even work
+	// if there is a non-empty preset dictionary, because encode_init()
+	// assumes that position is zero and previous byte is also zero.
+	coder->is_initialized = options->preset_dict != NULL
+			&& options->preset_dict_size > 0;
+	coder->is_flushed = false;
+
+	set_lz_options(lz_options, options);
+
+	return lzma_lzma_encoder_reset(coder, options);
+}
+
+
+static lzma_ret
+lzma_encoder_init(lzma_lz_encoder *lz, lzma_allocator *allocator,
+		const void *options, lzma_lz_options *lz_options)
+{
+	lz->code = &lzma_encode;
+	return lzma_lzma_encoder_create(
+			&lz->coder, allocator, options, lz_options);
+}
+
+
+extern lzma_ret
+lzma_lzma_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters)
+{
+	return lzma_lz_encoder_init(
+			next, allocator, filters, &lzma_encoder_init);
+}
+
+
+extern uint64_t
+lzma_lzma_encoder_memusage(const void *options)
+{
+	if (!is_options_valid(options))
+		return UINT64_MAX;
+
+	lzma_lz_options lz_options;
+	set_lz_options(&lz_options, options);
+
+	const uint64_t lz_memusage = lzma_lz_encoder_memusage(&lz_options);
+	if (lz_memusage == UINT64_MAX)
+		return UINT64_MAX;
+
+	return (uint64_t)(sizeof(lzma_coder)) + lz_memusage;
+}
+
+
+extern bool
+lzma_lzma_lclppb_encode(const lzma_options_lzma *options, uint8_t *byte)
+{
+	if (!is_lclppb_valid(options))
+		return true;
+
+	*byte = (options->pb * 5 + options->lp) * 9 + options->lc;
+	assert(*byte <= (4 * 5 + 4) * 9 + 8);
+
+	return false;
+}
+
+
+#ifdef HAVE_ENCODER_LZMA1
+extern lzma_ret
+lzma_lzma_props_encode(const void *options, uint8_t *out)
+{
+	const lzma_options_lzma *const opt = options;
+
+	if (lzma_lzma_lclppb_encode(opt, out))
+		return LZMA_PROG_ERROR;
+
+	unaligned_write32le(out + 1, opt->dict_size);
+
+	return LZMA_OK;
+}
+#endif
+
+
+extern LZMA_API(lzma_bool)
+lzma_mode_is_supported(lzma_mode mode)
+{
+	return mode == LZMA_MODE_FAST || mode == LZMA_MODE_NORMAL;
+}
diff --git a/src/liblzma/lzma/lzma_encoder.h b/src/liblzma/lzma/lzma_encoder.h
new file mode 100644
index 0000000..835e1f5
--- /dev/null
+++ b/src/liblzma/lzma/lzma_encoder.h
@@ -0,0 +1,54 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma_encoder.h
+/// \brief      LZMA encoder API
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_LZMA_ENCODER_H
+#define LZMA_LZMA_ENCODER_H
+
+#include "common.h"
+
+
+extern lzma_ret lzma_lzma_encoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters);
+
+
+extern uint64_t lzma_lzma_encoder_memusage(const void *options);
+
+extern lzma_ret lzma_lzma_props_encode(const void *options, uint8_t *out);
+
+
+/// Encodes lc/lp/pb into one byte. Returns false on success and true on error.
+extern bool lzma_lzma_lclppb_encode(
+		const lzma_options_lzma *options, uint8_t *byte);
+
+
+#ifdef LZMA_LZ_ENCODER_H
+
+/// Initializes raw LZMA encoder; this is used by LZMA2.
+extern lzma_ret lzma_lzma_encoder_create(
+		lzma_coder **coder_ptr, lzma_allocator *allocator,
+		const lzma_options_lzma *options, lzma_lz_options *lz_options);
+
+
+/// Resets an already initialized LZMA encoder; this is used by LZMA2.
+extern lzma_ret lzma_lzma_encoder_reset(
+		lzma_coder *coder, const lzma_options_lzma *options);
+
+
+extern lzma_ret lzma_lzma_encode(lzma_coder *restrict coder,
+		lzma_mf *restrict mf, uint8_t *restrict out,
+		size_t *restrict out_pos, size_t out_size,
+		uint32_t read_limit);
+
+#endif
+
+#endif
diff --git a/src/liblzma/lzma/lzma_encoder_optimum_fast.c b/src/liblzma/lzma/lzma_encoder_optimum_fast.c
new file mode 100644
index 0000000..f835f69
--- /dev/null
+++ b/src/liblzma/lzma/lzma_encoder_optimum_fast.c
@@ -0,0 +1,179 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma_encoder_optimum_fast.c
+//
+//  Author:     Igor Pavlov
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "lzma_encoder_private.h"
+
+
+#define change_pair(small_dist, big_dist) \
+	(((big_dist) >> 7) > (small_dist))
+
+
+extern void
+lzma_lzma_optimum_fast(lzma_coder *restrict coder, lzma_mf *restrict mf,
+		uint32_t *restrict back_res, uint32_t *restrict len_res)
+{
+	const uint32_t nice_len = mf->nice_len;
+
+	uint32_t len_main;
+	uint32_t matches_count;
+	if (mf->read_ahead == 0) {
+		len_main = mf_find(mf, &matches_count, coder->matches);
+	} else {
+		assert(mf->read_ahead == 1);
+		len_main = coder->longest_match_length;
+		matches_count = coder->matches_count;
+	}
+
+	const uint8_t *buf = mf_ptr(mf) - 1;
+	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.
+		*back_res = UINT32_MAX;
+		*len_res = 1;
+		return;
+	}
+
+	// Look for repeated matches; scan the previous four match distances
+	uint32_t rep_len = 0;
+	uint32_t rep_index = 0;
+
+	for (uint32_t i = 0; i < REP_DISTANCES; ++i) {
+		// Pointer to the beginning of the match candidate
+		const uint8_t *const buf_back = buf - coder->reps[i] - 1;
+
+		// If the first two bytes (2 == MATCH_LEN_MIN) do not match,
+		// this rep is not useful.
+		if (not_equal_16(buf, buf_back))
+			continue;
+
+		// The first two bytes matched.
+		// Calculate the length of the match.
+		uint32_t len;
+		for (len = 2; len < buf_avail
+				&& buf[len] == buf_back[len]; ++len) ;
+
+		// If we have found a repeated match that is at least
+		// nice_len long, return it immediately.
+		if (len >= nice_len) {
+			*back_res = i;
+			*len_res = len;
+			mf_skip(mf, len - 1);
+			return;
+		}
+
+		if (len > rep_len) {
+			rep_index = i;
+			rep_len = len;
+		}
+	}
+
+	// We didn't find a long enough repeated match. Encode it as a normal
+	// match if the match length is at least nice_len.
+	if (len_main >= nice_len) {
+		*back_res = coder->matches[matches_count - 1].dist
+				+ REP_DISTANCES;
+		*len_res = len_main;
+		mf_skip(mf, len_main - 1);
+		return;
+	}
+
+	uint32_t back_main = 0;
+	if (len_main >= 2) {
+		back_main = coder->matches[matches_count - 1].dist;
+
+		while (matches_count > 1 && len_main ==
+				coder->matches[matches_count - 2].len + 1) {
+			if (!change_pair(coder->matches[
+						matches_count - 2].dist,
+					back_main))
+				break;
+
+			--matches_count;
+			len_main = coder->matches[matches_count - 1].len;
+			back_main = coder->matches[matches_count - 1].dist;
+		}
+
+		if (len_main == 2 && back_main >= 0x80)
+			len_main = 1;
+	}
+
+	if (rep_len >= 2) {
+		if (rep_len + 1 >= len_main
+				|| (rep_len + 2 >= len_main
+					&& back_main > (UINT32_C(1) << 9))
+				|| (rep_len + 3 >= len_main
+					&& back_main > (UINT32_C(1) << 15))) {
+			*back_res = rep_index;
+			*len_res = rep_len;
+			mf_skip(mf, rep_len - 1);
+			return;
+		}
+	}
+
+	if (len_main < 2 || buf_avail <= 2) {
+		*back_res = UINT32_MAX;
+		*len_res = 1;
+		return;
+	}
+
+	// Get the matches for the next byte. If we find a better match,
+	// the current byte is encoded as a literal.
+	coder->longest_match_length = mf_find(mf,
+			&coder->matches_count, coder->matches);
+
+	if (coder->longest_match_length >= 2) {
+		const uint32_t new_dist = coder->matches[
+				coder->matches_count - 1].dist;
+
+		if ((coder->longest_match_length >= len_main
+					&& new_dist < back_main)
+				|| (coder->longest_match_length == len_main + 1
+					&& !change_pair(back_main, new_dist))
+				|| (coder->longest_match_length > len_main + 1)
+				|| (coder->longest_match_length + 1 >= len_main
+					&& len_main >= 3
+					&& change_pair(new_dist, back_main))) {
+			*back_res = UINT32_MAX;
+			*len_res = 1;
+			return;
+		}
+	}
+
+	// In contrast to LZMA SDK, dictionary could not have been moved
+	// between mf_find() calls, thus it is safe to just increment
+	// the old buf pointer instead of recalculating it with mf_ptr().
+	++buf;
+
+	const uint32_t limit = len_main - 1;
+
+	for (uint32_t i = 0; i < REP_DISTANCES; ++i) {
+		const uint8_t *const buf_back = buf - coder->reps[i] - 1;
+
+		if (not_equal_16(buf, buf_back))
+			continue;
+
+		uint32_t len;
+		for (len = 2; len < limit
+				&& buf[len] == buf_back[len]; ++len) ;
+
+		if (len >= limit) {
+			*back_res = UINT32_MAX;
+			*len_res = 1;
+			return;
+		}
+	}
+
+	*back_res = back_main + REP_DISTANCES;
+	*len_res = len_main;
+	mf_skip(mf, len_main - 2);
+	return;
+}
diff --git a/src/liblzma/lzma/lzma_encoder_optimum_normal.c b/src/liblzma/lzma/lzma_encoder_optimum_normal.c
new file mode 100644
index 0000000..7e85649
--- /dev/null
+++ b/src/liblzma/lzma/lzma_encoder_optimum_normal.c
@@ -0,0 +1,868 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma_encoder_optimum_normal.c
+//
+//  Author:     Igor Pavlov
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "lzma_encoder_private.h"
+#include "fastpos.h"
+
+
+////////////
+// Prices //
+////////////
+
+static uint32_t
+get_literal_price(const lzma_coder *const coder, const uint32_t pos,
+		const uint32_t prev_byte, const bool match_mode,
+		uint32_t match_byte, uint32_t symbol)
+{
+	const probability *const subcoder = literal_subcoder(coder->literal,
+			coder->literal_context_bits, coder->literal_pos_mask,
+			pos, prev_byte);
+
+	uint32_t price = 0;
+
+	if (!match_mode) {
+		price = rc_bittree_price(subcoder, 8, symbol);
+	} else {
+		uint32_t offset = 0x100;
+		symbol += UINT32_C(1) << 8;
+
+		do {
+			match_byte <<= 1;
+
+			const uint32_t match_bit = match_byte & offset;
+			const uint32_t subcoder_index
+					= offset + match_bit + (symbol >> 8);
+			const uint32_t bit = (symbol >> 7) & 1;
+			price += rc_bit_price(subcoder[subcoder_index], bit);
+
+			symbol <<= 1;
+			offset &= ~(match_byte ^ symbol);
+
+		} while (symbol < (UINT32_C(1) << 16));
+	}
+
+	return price;
+}
+
+
+static inline uint32_t
+get_len_price(const lzma_length_encoder *const lencoder,
+		const uint32_t len, const uint32_t pos_state)
+{
+	// NOTE: Unlike the other price tables, length prices are updated
+	// in lzma_encoder.c
+	return lencoder->prices[pos_state][len - MATCH_LEN_MIN];
+}
+
+
+static inline uint32_t
+get_short_rep_price(const lzma_coder *const coder,
+		const lzma_lzma_state state, const uint32_t pos_state)
+{
+	return rc_bit_0_price(coder->is_rep0[state])
+		+ rc_bit_0_price(coder->is_rep0_long[state][pos_state]);
+}
+
+
+static inline uint32_t
+get_pure_rep_price(const lzma_coder *const coder, const uint32_t rep_index,
+		const lzma_lzma_state state, uint32_t pos_state)
+{
+	uint32_t price;
+
+	if (rep_index == 0) {
+		price = rc_bit_0_price(coder->is_rep0[state]);
+		price += rc_bit_1_price(coder->is_rep0_long[state][pos_state]);
+	} else {
+		price = rc_bit_1_price(coder->is_rep0[state]);
+
+		if (rep_index == 1) {
+			price += rc_bit_0_price(coder->is_rep1[state]);
+		} else {
+			price += rc_bit_1_price(coder->is_rep1[state]);
+			price += rc_bit_price(coder->is_rep2[state],
+					rep_index - 2);
+		}
+	}
+
+	return price;
+}
+
+
+static inline uint32_t
+get_rep_price(const lzma_coder *const coder, const uint32_t rep_index,
+		const uint32_t len, const lzma_lzma_state state,
+		const uint32_t pos_state)
+{
+	return get_len_price(&coder->rep_len_encoder, len, pos_state)
+		+ get_pure_rep_price(coder, rep_index, state, pos_state);
+}
+
+
+static inline uint32_t
+get_pos_len_price(const lzma_coder *const coder, const uint32_t pos,
+		const uint32_t len, const uint32_t pos_state)
+{
+	const uint32_t len_to_pos_state = get_len_to_pos_state(len);
+	uint32_t price;
+
+	if (pos < FULL_DISTANCES) {
+		price = coder->distances_prices[len_to_pos_state][pos];
+	} else {
+		const uint32_t pos_slot = get_pos_slot_2(pos);
+		price = coder->pos_slot_prices[len_to_pos_state][pos_slot]
+				+ coder->align_prices[pos & ALIGN_MASK];
+	}
+
+	price += get_len_price(&coder->match_len_encoder, len, pos_state);
+
+	return price;
+}
+
+
+static void
+fill_distances_prices(lzma_coder *coder)
+{
+	for (uint32_t len_to_pos_state = 0;
+			len_to_pos_state < LEN_TO_POS_STATES;
+			++len_to_pos_state) {
+
+		uint32_t *const pos_slot_prices
+				= coder->pos_slot_prices[len_to_pos_state];
+
+		// Price to encode the pos_slot.
+		for (uint32_t pos_slot = 0;
+				pos_slot < coder->dist_table_size; ++pos_slot)
+			pos_slot_prices[pos_slot] = rc_bittree_price(
+					coder->pos_slot[len_to_pos_state],
+					POS_SLOT_BITS, pos_slot);
+
+		// For matches with distance >= FULL_DISTANCES, add the price
+		// of the direct bits part of the match distance. (Align bits
+		// are handled by fill_align_prices()).
+		for (uint32_t pos_slot = END_POS_MODEL_INDEX;
+				pos_slot < coder->dist_table_size; ++pos_slot)
+			pos_slot_prices[pos_slot] += rc_direct_price(
+					((pos_slot >> 1) - 1) - ALIGN_BITS);
+
+		// Distances in the range [0, 3] are fully encoded with
+		// pos_slot, so they are used for coder->distances_prices
+		// as is.
+		for (uint32_t i = 0; i < START_POS_MODEL_INDEX; ++i)
+			coder->distances_prices[len_to_pos_state][i]
+					= pos_slot_prices[i];
+	}
+
+	// Distances in the range [4, 127] depend on pos_slot and pos_special.
+	// We do this in a loop separate from the above loop to avoid
+	// redundant calls to get_pos_slot().
+	for (uint32_t i = START_POS_MODEL_INDEX; i < FULL_DISTANCES; ++i) {
+		const uint32_t pos_slot = get_pos_slot(i);
+		const uint32_t footer_bits = ((pos_slot >> 1) - 1);
+		const uint32_t base = (2 | (pos_slot & 1)) << footer_bits;
+		const uint32_t price = rc_bittree_reverse_price(
+				coder->pos_special + base - pos_slot - 1,
+				footer_bits, i - base);
+
+		for (uint32_t len_to_pos_state = 0;
+				len_to_pos_state < LEN_TO_POS_STATES;
+				++len_to_pos_state)
+			coder->distances_prices[len_to_pos_state][i]
+					= price + coder->pos_slot_prices[
+						len_to_pos_state][pos_slot];
+	}
+
+	coder->match_price_count = 0;
+	return;
+}
+
+
+static void
+fill_align_prices(lzma_coder *coder)
+{
+	for (uint32_t i = 0; i < ALIGN_TABLE_SIZE; ++i)
+		coder->align_prices[i] = rc_bittree_reverse_price(
+				coder->pos_align, ALIGN_BITS, i);
+
+	coder->align_price_count = 0;
+	return;
+}
+
+
+/////////////
+// Optimal //
+/////////////
+
+static inline void
+make_literal(lzma_optimal *optimal)
+{
+	optimal->back_prev = UINT32_MAX;
+	optimal->prev_1_is_literal = false;
+}
+
+
+static inline void
+make_short_rep(lzma_optimal *optimal)
+{
+	optimal->back_prev = 0;
+	optimal->prev_1_is_literal = false;
+}
+
+
+#define is_short_rep(optimal) \
+	((optimal).back_prev == 0)
+
+
+static void
+backward(lzma_coder *restrict coder, uint32_t *restrict len_res,
+		uint32_t *restrict back_res, uint32_t cur)
+{
+	coder->opts_end_index = cur;
+
+	uint32_t pos_mem = coder->opts[cur].pos_prev;
+	uint32_t back_mem = coder->opts[cur].back_prev;
+
+	do {
+		if (coder->opts[cur].prev_1_is_literal) {
+			make_literal(&coder->opts[pos_mem]);
+			coder->opts[pos_mem].pos_prev = pos_mem - 1;
+
+			if (coder->opts[cur].prev_2) {
+				coder->opts[pos_mem - 1].prev_1_is_literal
+						= false;
+				coder->opts[pos_mem - 1].pos_prev
+						= coder->opts[cur].pos_prev_2;
+				coder->opts[pos_mem - 1].back_prev
+						= coder->opts[cur].back_prev_2;
+			}
+		}
+
+		const uint32_t pos_prev = pos_mem;
+		const uint32_t back_cur = back_mem;
+
+		back_mem = coder->opts[pos_prev].back_prev;
+		pos_mem = coder->opts[pos_prev].pos_prev;
+
+		coder->opts[pos_prev].back_prev = back_cur;
+		coder->opts[pos_prev].pos_prev = cur;
+		cur = pos_prev;
+
+	} while (cur != 0);
+
+	coder->opts_current_index = coder->opts[0].pos_prev;
+	*len_res = coder->opts[0].pos_prev;
+	*back_res = coder->opts[0].back_prev;
+
+	return;
+}
+
+
+//////////
+// Main //
+//////////
+
+static inline uint32_t
+helper1(lzma_coder *restrict coder, lzma_mf *restrict mf,
+		uint32_t *restrict back_res, uint32_t *restrict len_res,
+		uint32_t position)
+{
+	const uint32_t nice_len = mf->nice_len;
+
+	uint32_t len_main;
+	uint32_t matches_count;
+
+	if (mf->read_ahead == 0) {
+		len_main = mf_find(mf, &matches_count, coder->matches);
+	} else {
+		assert(mf->read_ahead == 1);
+		len_main = coder->longest_match_length;
+		matches_count = coder->matches_count;
+	}
+
+	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;
+		return UINT32_MAX;
+	}
+
+	const uint8_t *const buf = mf_ptr(mf) - 1;
+
+	uint32_t rep_lens[REP_DISTANCES];
+	uint32_t rep_max_index = 0;
+
+	for (uint32_t i = 0; i < REP_DISTANCES; ++i) {
+		const uint8_t *const buf_back = buf - coder->reps[i] - 1;
+
+		if (not_equal_16(buf, buf_back)) {
+			rep_lens[i] = 0;
+			continue;
+		}
+
+		uint32_t len_test;
+		for (len_test = 2; len_test < buf_avail
+				&& buf[len_test] == buf_back[len_test];
+				++len_test) ;
+
+		rep_lens[i] = len_test;
+		if (len_test > rep_lens[rep_max_index])
+			rep_max_index = i;
+	}
+
+	if (rep_lens[rep_max_index] >= nice_len) {
+		*back_res = rep_max_index;
+		*len_res = rep_lens[rep_max_index];
+		mf_skip(mf, *len_res - 1);
+		return UINT32_MAX;
+	}
+
+
+	if (len_main >= nice_len) {
+		*back_res = coder->matches[matches_count - 1].dist
+				+ REP_DISTANCES;
+		*len_res = len_main;
+		mf_skip(mf, len_main - 1);
+		return UINT32_MAX;
+	}
+
+	const uint8_t current_byte = *buf;
+	const uint8_t match_byte = *(buf - coder->reps[0] - 1);
+
+	if (len_main < 2 && current_byte != match_byte
+			&& rep_lens[rep_max_index] < 2) {
+		*back_res = UINT32_MAX;
+		*len_res = 1;
+		return UINT32_MAX;
+	}
+
+	coder->opts[0].state = coder->state;
+
+	const uint32_t pos_state = position & coder->pos_mask;
+
+	coder->opts[1].price = rc_bit_0_price(
+				coder->is_match[coder->state][pos_state])
+			+ get_literal_price(coder, position, buf[-1],
+				!is_literal_state(coder->state),
+				match_byte, current_byte);
+
+	make_literal(&coder->opts[1]);
+
+	const uint32_t match_price = rc_bit_1_price(
+			coder->is_match[coder->state][pos_state]);
+	const uint32_t rep_match_price = match_price
+			+ rc_bit_1_price(coder->is_rep[coder->state]);
+
+	if (match_byte == current_byte) {
+		const uint32_t short_rep_price = rep_match_price
+				+ get_short_rep_price(
+					coder, coder->state, pos_state);
+
+		if (short_rep_price < coder->opts[1].price) {
+			coder->opts[1].price = short_rep_price;
+			make_short_rep(&coder->opts[1]);
+		}
+	}
+
+	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;
+		*len_res = 1;
+		return UINT32_MAX;
+	}
+
+	coder->opts[1].pos_prev = 0;
+
+	for (uint32_t i = 0; i < REP_DISTANCES; ++i)
+		coder->opts[0].backs[i] = coder->reps[i];
+
+	uint32_t len = len_end;
+	do {
+		coder->opts[len].price = RC_INFINITY_PRICE;
+	} while (--len >= 2);
+
+
+	for (uint32_t i = 0; i < REP_DISTANCES; ++i) {
+		uint32_t rep_len = rep_lens[i];
+		if (rep_len < 2)
+			continue;
+
+		const uint32_t price = rep_match_price + get_pure_rep_price(
+				coder, i, coder->state, pos_state);
+
+		do {
+			const uint32_t cur_and_len_price = price
+					+ get_len_price(
+						&coder->rep_len_encoder,
+						rep_len, pos_state);
+
+			if (cur_and_len_price < coder->opts[rep_len].price) {
+				coder->opts[rep_len].price = cur_and_len_price;
+				coder->opts[rep_len].pos_prev = 0;
+				coder->opts[rep_len].back_prev = i;
+				coder->opts[rep_len].prev_1_is_literal = false;
+			}
+		} while (--rep_len >= 2);
+	}
+
+
+	const uint32_t normal_match_price = match_price
+			+ rc_bit_0_price(coder->is_rep[coder->state]);
+
+	len = rep_lens[0] >= 2 ? rep_lens[0] + 1 : 2;
+	if (len <= len_main) {
+		uint32_t i = 0;
+		while (len > coder->matches[i].len)
+			++i;
+
+		for(; ; ++len) {
+			const uint32_t dist = coder->matches[i].dist;
+			const uint32_t cur_and_len_price = normal_match_price
+					+ get_pos_len_price(coder,
+						dist, len, pos_state);
+
+			if (cur_and_len_price < coder->opts[len].price) {
+				coder->opts[len].price = cur_and_len_price;
+				coder->opts[len].pos_prev = 0;
+				coder->opts[len].back_prev
+						= dist + REP_DISTANCES;
+				coder->opts[len].prev_1_is_literal = false;
+			}
+
+			if (len == coder->matches[i].len)
+				if (++i == matches_count)
+					break;
+		}
+	}
+
+	return len_end;
+}
+
+
+static inline uint32_t
+helper2(lzma_coder *coder, uint32_t *reps, const uint8_t *buf,
+		uint32_t len_end, uint32_t position, const uint32_t cur,
+		const uint32_t nice_len, const uint32_t buf_avail_full)
+{
+	uint32_t matches_count = coder->matches_count;
+	uint32_t new_len = coder->longest_match_length;
+	uint32_t pos_prev = coder->opts[cur].pos_prev;
+	lzma_lzma_state state;
+
+	if (coder->opts[cur].prev_1_is_literal) {
+		--pos_prev;
+
+		if (coder->opts[cur].prev_2) {
+			state = coder->opts[coder->opts[cur].pos_prev_2].state;
+
+			if (coder->opts[cur].back_prev_2 < REP_DISTANCES)
+				update_long_rep(state);
+			else
+				update_match(state);
+
+		} else {
+			state = coder->opts[pos_prev].state;
+		}
+
+		update_literal(state);
+
+	} else {
+		state = coder->opts[pos_prev].state;
+	}
+
+	if (pos_prev == cur - 1) {
+		if (is_short_rep(coder->opts[cur]))
+			update_short_rep(state);
+		else
+			update_literal(state);
+	} else {
+		uint32_t pos;
+		if (coder->opts[cur].prev_1_is_literal
+				&& coder->opts[cur].prev_2) {
+			pos_prev = coder->opts[cur].pos_prev_2;
+			pos = coder->opts[cur].back_prev_2;
+			update_long_rep(state);
+		} else {
+			pos = coder->opts[cur].back_prev;
+			if (pos < REP_DISTANCES)
+				update_long_rep(state);
+			else
+				update_match(state);
+		}
+
+		if (pos < REP_DISTANCES) {
+			reps[0] = coder->opts[pos_prev].backs[pos];
+
+			uint32_t i;
+			for (i = 1; i <= pos; ++i)
+				reps[i] = coder->opts[pos_prev].backs[i - 1];
+
+			for (; i < REP_DISTANCES; ++i)
+				reps[i] = coder->opts[pos_prev].backs[i];
+
+		} else {
+			reps[0] = pos - REP_DISTANCES;
+
+			for (uint32_t i = 1; i < REP_DISTANCES; ++i)
+				reps[i] = coder->opts[pos_prev].backs[i - 1];
+		}
+	}
+
+	coder->opts[cur].state = state;
+
+	for (uint32_t i = 0; i < REP_DISTANCES; ++i)
+		coder->opts[cur].backs[i] = reps[i];
+
+	const uint32_t cur_price = coder->opts[cur].price;
+
+	const uint8_t current_byte = *buf;
+	const uint8_t match_byte = *(buf - reps[0] - 1);
+
+	const uint32_t pos_state = position & coder->pos_mask;
+
+	const uint32_t cur_and_1_price = cur_price
+			+ rc_bit_0_price(coder->is_match[state][pos_state])
+			+ get_literal_price(coder, position, buf[-1],
+			!is_literal_state(state), match_byte, current_byte);
+
+	bool next_is_literal = false;
+
+	if (cur_and_1_price < coder->opts[cur + 1].price) {
+		coder->opts[cur + 1].price = cur_and_1_price;
+		coder->opts[cur + 1].pos_prev = cur;
+		make_literal(&coder->opts[cur + 1]);
+		next_is_literal = true;
+	}
+
+	const uint32_t match_price = cur_price
+			+ rc_bit_1_price(coder->is_match[state][pos_state]);
+	const uint32_t rep_match_price = match_price
+			+ rc_bit_1_price(coder->is_rep[state]);
+
+	if (match_byte == current_byte
+			&& !(coder->opts[cur + 1].pos_prev < cur
+				&& coder->opts[cur + 1].back_prev == 0)) {
+
+		const uint32_t short_rep_price = rep_match_price
+				+ get_short_rep_price(coder, state, pos_state);
+
+		if (short_rep_price <= coder->opts[cur + 1].price) {
+			coder->opts[cur + 1].price = short_rep_price;
+			coder->opts[cur + 1].pos_prev = cur;
+			make_short_rep(&coder->opts[cur + 1]);
+			next_is_literal = true;
+		}
+	}
+
+	if (buf_avail_full < 2)
+		return len_end;
+
+	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 = my_min(buf_avail_full, nice_len + 1);
+
+		uint32_t len_test = 1;
+		while (len_test < limit && buf[len_test] == buf_back[len_test])
+			++len_test;
+
+		--len_test;
+
+		if (len_test >= 2) {
+			lzma_lzma_state state_2 = state;
+			update_literal(state_2);
+
+			const uint32_t pos_state_next = (position + 1) & coder->pos_mask;
+			const uint32_t next_rep_match_price = cur_and_1_price
+					+ rc_bit_1_price(coder->is_match[state_2][pos_state_next])
+					+ rc_bit_1_price(coder->is_rep[state_2]);
+
+			//for (; len_test >= 2; --len_test) {
+			const uint32_t offset = cur + 1 + len_test;
+
+			while (len_end < offset)
+				coder->opts[++len_end].price = RC_INFINITY_PRICE;
+
+			const uint32_t cur_and_len_price = next_rep_match_price
+					+ get_rep_price(coder, 0, len_test,
+						state_2, pos_state_next);
+
+			if (cur_and_len_price < coder->opts[offset].price) {
+				coder->opts[offset].price = cur_and_len_price;
+				coder->opts[offset].pos_prev = cur + 1;
+				coder->opts[offset].back_prev = 0;
+				coder->opts[offset].prev_1_is_literal = true;
+				coder->opts[offset].prev_2 = false;
+			}
+			//}
+		}
+	}
+
+
+	uint32_t start_len = 2; // speed optimization
+
+	for (uint32_t rep_index = 0; rep_index < REP_DISTANCES; ++rep_index) {
+		const uint8_t *const buf_back = buf - reps[rep_index] - 1;
+		if (not_equal_16(buf, buf_back))
+			continue;
+
+		uint32_t len_test;
+		for (len_test = 2; len_test < buf_avail
+				&& buf[len_test] == buf_back[len_test];
+				++len_test) ;
+
+		while (len_end < cur + len_test)
+			coder->opts[++len_end].price = RC_INFINITY_PRICE;
+
+		const uint32_t len_test_temp = len_test;
+		const uint32_t price = rep_match_price + get_pure_rep_price(
+				coder, rep_index, state, pos_state);
+
+		do {
+			const uint32_t cur_and_len_price = price
+					+ get_len_price(&coder->rep_len_encoder,
+							len_test, pos_state);
+
+			if (cur_and_len_price < coder->opts[cur + len_test].price) {
+				coder->opts[cur + len_test].price = cur_and_len_price;
+				coder->opts[cur + len_test].pos_prev = cur;
+				coder->opts[cur + len_test].back_prev = rep_index;
+				coder->opts[cur + len_test].prev_1_is_literal = false;
+			}
+		} while (--len_test >= 2);
+
+		len_test = len_test_temp;
+
+		if (rep_index == 0)
+			start_len = len_test + 1;
+
+
+		uint32_t len_test_2 = len_test + 1;
+		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];
+				++len_test_2) ;
+
+		len_test_2 -= len_test + 1;
+
+		if (len_test_2 >= 2) {
+			lzma_lzma_state state_2 = state;
+			update_long_rep(state_2);
+
+			uint32_t pos_state_next = (position + len_test) & coder->pos_mask;
+
+			const uint32_t cur_and_len_literal_price = price
+					+ get_len_price(&coder->rep_len_encoder,
+						len_test, pos_state)
+					+ rc_bit_0_price(coder->is_match[state_2][pos_state_next])
+					+ get_literal_price(coder, position + len_test,
+						buf[len_test - 1], true,
+						buf_back[len_test], buf[len_test]);
+
+			update_literal(state_2);
+
+			pos_state_next = (position + len_test + 1) & coder->pos_mask;
+
+			const uint32_t next_rep_match_price = cur_and_len_literal_price
+					+ rc_bit_1_price(coder->is_match[state_2][pos_state_next])
+					+ rc_bit_1_price(coder->is_rep[state_2]);
+
+			//for(; len_test_2 >= 2; len_test_2--) {
+			const uint32_t offset = cur + len_test + 1 + len_test_2;
+
+			while (len_end < offset)
+				coder->opts[++len_end].price = RC_INFINITY_PRICE;
+
+			const uint32_t cur_and_len_price = next_rep_match_price
+					+ get_rep_price(coder, 0, len_test_2,
+						state_2, pos_state_next);
+
+			if (cur_and_len_price < coder->opts[offset].price) {
+				coder->opts[offset].price = cur_and_len_price;
+				coder->opts[offset].pos_prev = cur + len_test + 1;
+				coder->opts[offset].back_prev = 0;
+				coder->opts[offset].prev_1_is_literal = true;
+				coder->opts[offset].prev_2 = true;
+				coder->opts[offset].pos_prev_2 = cur;
+				coder->opts[offset].back_prev_2 = rep_index;
+			}
+			//}
+		}
+	}
+
+
+	//for (uint32_t len_test = 2; len_test <= new_len; ++len_test)
+	if (new_len > buf_avail) {
+		new_len = buf_avail;
+
+		matches_count = 0;
+		while (new_len > coder->matches[matches_count].len)
+			++matches_count;
+
+		coder->matches[matches_count++].len = new_len;
+	}
+
+
+	if (new_len >= start_len) {
+		const uint32_t normal_match_price = match_price
+				+ rc_bit_0_price(coder->is_rep[state]);
+
+		while (len_end < cur + new_len)
+			coder->opts[++len_end].price = RC_INFINITY_PRICE;
+
+		uint32_t i = 0;
+		while (start_len > coder->matches[i].len)
+			++i;
+
+		for (uint32_t len_test = start_len; ; ++len_test) {
+			const uint32_t cur_back = coder->matches[i].dist;
+			uint32_t cur_and_len_price = normal_match_price
+					+ get_pos_len_price(coder,
+						cur_back, len_test, pos_state);
+
+			if (cur_and_len_price < coder->opts[cur + len_test].price) {
+				coder->opts[cur + len_test].price = cur_and_len_price;
+				coder->opts[cur + len_test].pos_prev = cur;
+				coder->opts[cur + len_test].back_prev
+						= cur_back + REP_DISTANCES;
+				coder->opts[cur + len_test].prev_1_is_literal = false;
+			}
+
+			if (len_test == coder->matches[i].len) {
+				// 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 = my_min(buf_avail_full,
+						len_test_2 + nice_len);
+
+				for (; len_test_2 < limit &&
+						buf[len_test_2] == buf_back[len_test_2];
+						++len_test_2) ;
+
+				len_test_2 -= len_test + 1;
+
+				if (len_test_2 >= 2) {
+					lzma_lzma_state state_2 = state;
+					update_match(state_2);
+					uint32_t pos_state_next
+							= (position + len_test) & coder->pos_mask;
+
+					const uint32_t cur_and_len_literal_price = cur_and_len_price
+							+ rc_bit_0_price(
+								coder->is_match[state_2][pos_state_next])
+							+ get_literal_price(coder,
+								position + len_test,
+								buf[len_test - 1],
+								true,
+								buf_back[len_test],
+								buf[len_test]);
+
+					update_literal(state_2);
+					pos_state_next = (pos_state_next + 1) & coder->pos_mask;
+
+					const uint32_t next_rep_match_price
+							= cur_and_len_literal_price
+							+ rc_bit_1_price(
+								coder->is_match[state_2][pos_state_next])
+							+ rc_bit_1_price(coder->is_rep[state_2]);
+
+					// for(; len_test_2 >= 2; --len_test_2) {
+					const uint32_t offset = cur + len_test + 1 + len_test_2;
+
+					while (len_end < offset)
+						coder->opts[++len_end].price = RC_INFINITY_PRICE;
+
+					cur_and_len_price = next_rep_match_price
+							+ get_rep_price(coder, 0, len_test_2,
+								state_2, pos_state_next);
+
+					if (cur_and_len_price < coder->opts[offset].price) {
+						coder->opts[offset].price = cur_and_len_price;
+						coder->opts[offset].pos_prev = cur + len_test + 1;
+						coder->opts[offset].back_prev = 0;
+						coder->opts[offset].prev_1_is_literal = true;
+						coder->opts[offset].prev_2 = true;
+						coder->opts[offset].pos_prev_2 = cur;
+						coder->opts[offset].back_prev_2
+								= cur_back + REP_DISTANCES;
+					}
+					//}
+				}
+
+				if (++i == matches_count)
+					break;
+			}
+		}
+	}
+
+	return len_end;
+}
+
+
+extern void
+lzma_lzma_optimum_normal(lzma_coder *restrict coder, lzma_mf *restrict mf,
+		uint32_t *restrict back_res, uint32_t *restrict len_res,
+		uint32_t position)
+{
+	// If we have symbols pending, return the next pending symbol.
+	if (coder->opts_end_index != coder->opts_current_index) {
+		assert(mf->read_ahead > 0);
+		*len_res = coder->opts[coder->opts_current_index].pos_prev
+				- coder->opts_current_index;
+		*back_res = coder->opts[coder->opts_current_index].back_prev;
+		coder->opts_current_index = coder->opts[
+				coder->opts_current_index].pos_prev;
+		return;
+	}
+
+	// Update the price tables. In LZMA SDK <= 4.60 (and possibly later)
+	// this was done in both initialization function and in the main loop.
+	// In liblzma they were moved into this single place.
+	if (mf->read_ahead == 0) {
+		if (coder->match_price_count >= (1 << 7))
+			fill_distances_prices(coder);
+
+		if (coder->align_price_count >= ALIGN_TABLE_SIZE)
+			fill_align_prices(coder);
+	}
+
+	// TODO: This needs quite a bit of cleaning still. But splitting
+	// the original function into two pieces makes it at least a little
+	// more readable, since those two parts don't share many variables.
+
+	uint32_t len_end = helper1(coder, mf, back_res, len_res, position);
+	if (len_end == UINT32_MAX)
+		return;
+
+	uint32_t reps[REP_DISTANCES];
+	memcpy(reps, coder->reps, sizeof(reps));
+
+	uint32_t cur;
+	for (cur = 1; cur < len_end; ++cur) {
+		assert(cur < OPTS);
+
+		coder->longest_match_length = mf_find(
+				mf, &coder->matches_count, coder->matches);
+
+		if (coder->longest_match_length >= mf->nice_len)
+			break;
+
+		len_end = helper2(coder, reps, mf_ptr(mf) - 1, len_end,
+				position + cur, cur, mf->nice_len,
+				my_min(mf_avail(mf) + 1, OPTS - 1 - cur));
+	}
+
+	backward(coder, len_res, back_res, cur);
+	return;
+}
diff --git a/src/liblzma/lzma/lzma_encoder_presets.c b/src/liblzma/lzma/lzma_encoder_presets.c
new file mode 100644
index 0000000..c4c9c14
--- /dev/null
+++ b/src/liblzma/lzma/lzma_encoder_presets.c
@@ -0,0 +1,52 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma_encoder_presets.c
+/// \brief      Encoder presets
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "common.h"
+
+
+extern LZMA_API(lzma_bool)
+lzma_lzma_preset(lzma_options_lzma *options, uint32_t preset)
+{
+	const uint32_t level = preset & LZMA_PRESET_LEVEL_MASK;
+	const uint32_t flags = preset & ~LZMA_PRESET_LEVEL_MASK;
+	const uint32_t supported_flags = LZMA_PRESET_EXTREME;
+
+	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;
+
+	options->lc = LZMA_LC_DEFAULT;
+	options->lp = LZMA_LP_DEFAULT;
+	options->pb = LZMA_PB_DEFAULT;
+
+	options->mode = level <= 2 ? LZMA_MODE_FAST : LZMA_MODE_NORMAL;
+
+	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 (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;
+	}
+
+	return false;
+}
diff --git a/src/liblzma/lzma/lzma_encoder_private.h b/src/liblzma/lzma/lzma_encoder_private.h
new file mode 100644
index 0000000..6847452
--- /dev/null
+++ b/src/liblzma/lzma/lzma_encoder_private.h
@@ -0,0 +1,148 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzma_encoder_private.h
+/// \brief      Private definitions for LZMA encoder
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_LZMA_ENCODER_PRIVATE_H
+#define LZMA_LZMA_ENCODER_PRIVATE_H
+
+#include "lz_encoder.h"
+#include "range_encoder.h"
+#include "lzma_common.h"
+#include "lzma_encoder.h"
+
+
+// Macro to compare if the first two bytes in two buffers differ. This is
+// needed in lzma_lzma_optimum_*() to test if the match is at least
+// MATCH_LEN_MIN bytes. Unaligned access gives tiny gain so there's no
+// reason to not use it when it is supported.
+#ifdef TUKLIB_FAST_UNALIGNED_ACCESS
+#	define not_equal_16(a, b) \
+		(*(const uint16_t *)(a) != *(const uint16_t *)(b))
+#else
+#	define not_equal_16(a, b) \
+		((a)[0] != (b)[0] || (a)[1] != (b)[1])
+#endif
+
+
+// Optimal - Number of entries in the optimum array.
+#define OPTS (1 << 12)
+
+
+typedef struct {
+	probability choice;
+	probability choice2;
+	probability low[POS_STATES_MAX][LEN_LOW_SYMBOLS];
+	probability mid[POS_STATES_MAX][LEN_MID_SYMBOLS];
+	probability high[LEN_HIGH_SYMBOLS];
+
+	uint32_t prices[POS_STATES_MAX][LEN_SYMBOLS];
+	uint32_t table_size;
+	uint32_t counters[POS_STATES_MAX];
+
+} lzma_length_encoder;
+
+
+typedef struct {
+	lzma_lzma_state state;
+
+	bool prev_1_is_literal;
+	bool prev_2;
+
+	uint32_t pos_prev_2;
+	uint32_t back_prev_2;
+
+	uint32_t price;
+	uint32_t pos_prev;  // pos_next;
+	uint32_t back_prev;
+
+	uint32_t backs[REP_DISTANCES];
+
+} lzma_optimal;
+
+
+struct lzma_coder_s {
+	/// Range encoder
+	lzma_range_encoder rc;
+
+	/// State
+	lzma_lzma_state state;
+
+	/// The four most recent match distances
+	uint32_t reps[REP_DISTANCES];
+
+	/// Array of match candidates
+	lzma_match matches[MATCH_LEN_MAX + 1];
+
+	/// Number of match candidates in matches[]
+	uint32_t matches_count;
+
+	/// Variable to hold the length of the longest match between calls
+	/// to lzma_lzma_optimum_*().
+	uint32_t longest_match_length;
+
+	/// True if using getoptimumfast
+	bool fast_mode;
+
+	/// True if the encoder has been initialized by encoding the first
+	/// byte as a literal.
+	bool is_initialized;
+
+	/// True if the range encoder has been flushed, but not all bytes
+	/// have been written to the output buffer yet.
+	bool is_flushed;
+
+	uint32_t pos_mask;         ///< (1 << pos_bits) - 1
+	uint32_t literal_context_bits;
+	uint32_t literal_pos_mask;
+
+	// These are the same as in lzma_decoder.c. See comments there.
+	probability literal[LITERAL_CODERS_MAX][LITERAL_CODER_SIZE];
+	probability is_match[STATES][POS_STATES_MAX];
+	probability is_rep[STATES];
+	probability is_rep0[STATES];
+	probability is_rep1[STATES];
+	probability is_rep2[STATES];
+	probability is_rep0_long[STATES][POS_STATES_MAX];
+	probability pos_slot[LEN_TO_POS_STATES][POS_SLOTS];
+	probability pos_special[FULL_DISTANCES - END_POS_MODEL_INDEX];
+	probability pos_align[ALIGN_TABLE_SIZE];
+
+	// These are the same as in lzma_decoder.c except that the encoders
+	// include also price tables.
+	lzma_length_encoder match_len_encoder;
+	lzma_length_encoder rep_len_encoder;
+
+	// Price tables
+	uint32_t pos_slot_prices[LEN_TO_POS_STATES][POS_SLOTS];
+	uint32_t distances_prices[LEN_TO_POS_STATES][FULL_DISTANCES];
+	uint32_t dist_table_size;
+	uint32_t match_price_count;
+
+	uint32_t align_prices[ALIGN_TABLE_SIZE];
+	uint32_t align_price_count;
+
+	// Optimal
+	uint32_t opts_end_index;
+	uint32_t opts_current_index;
+	lzma_optimal opts[OPTS];
+};
+
+
+extern void lzma_lzma_optimum_fast(
+		lzma_coder *restrict coder, lzma_mf *restrict mf,
+		uint32_t *restrict back_res, uint32_t *restrict len_res);
+
+extern void lzma_lzma_optimum_normal(lzma_coder *restrict coder,
+		lzma_mf *restrict mf, uint32_t *restrict back_res,
+		uint32_t *restrict len_res, uint32_t position);
+
+#endif
diff --git a/src/liblzma/rangecoder/Makefile.inc b/src/liblzma/rangecoder/Makefile.inc
new file mode 100644
index 0000000..d8a597a
--- /dev/null
+++ b/src/liblzma/rangecoder/Makefile.inc
@@ -0,0 +1,21 @@
+##
+## Author: Lasse Collin
+##
+## This file has been put into the public domain.
+## You can do whatever you want with this file.
+##
+
+EXTRA_DIST += rangecoder/price_tablegen.c
+
+liblzma_la_SOURCES += rangecoder/range_common.h
+
+if COND_ENCODER_LZMA1
+liblzma_la_SOURCES += \
+	rangecoder/range_encoder.h \
+	rangecoder/price.h \
+	rangecoder/price_table.c
+endif
+
+if COND_DECODER_LZMA1
+liblzma_la_SOURCES += rangecoder/range_decoder.h
+endif
diff --git a/src/liblzma/rangecoder/price.h b/src/liblzma/rangecoder/price.h
new file mode 100644
index 0000000..8ae02ca
--- /dev/null
+++ b/src/liblzma/rangecoder/price.h
@@ -0,0 +1,92 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       price.h
+/// \brief      Probability price calculation
+//
+//  Author:     Igor Pavlov
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_PRICE_H
+#define LZMA_PRICE_H
+
+
+#define RC_MOVE_REDUCING_BITS 4
+#define RC_BIT_PRICE_SHIFT_BITS 4
+#define RC_PRICE_TABLE_SIZE (RC_BIT_MODEL_TOTAL >> RC_MOVE_REDUCING_BITS)
+
+#define RC_INFINITY_PRICE (UINT32_C(1) << 30)
+
+
+/// Lookup table for the inline functions defined in this file.
+extern const uint8_t lzma_rc_prices[RC_PRICE_TABLE_SIZE];
+
+
+static inline uint32_t
+rc_bit_price(const probability prob, const uint32_t bit)
+{
+	return lzma_rc_prices[(prob ^ ((UINT32_C(0) - bit)
+			& (RC_BIT_MODEL_TOTAL - 1))) >> RC_MOVE_REDUCING_BITS];
+}
+
+
+static inline uint32_t
+rc_bit_0_price(const probability prob)
+{
+	return lzma_rc_prices[prob >> RC_MOVE_REDUCING_BITS];
+}
+
+
+static inline uint32_t
+rc_bit_1_price(const probability prob)
+{
+	return lzma_rc_prices[(prob ^ (RC_BIT_MODEL_TOTAL - 1))
+			>> RC_MOVE_REDUCING_BITS];
+}
+
+
+static inline uint32_t
+rc_bittree_price(const probability *const probs,
+		const uint32_t bit_levels, uint32_t symbol)
+{
+	uint32_t price = 0;
+	symbol += UINT32_C(1) << bit_levels;
+
+	do {
+		const uint32_t bit = symbol & 1;
+		symbol >>= 1;
+		price += rc_bit_price(probs[symbol], bit);
+	} while (symbol != 1);
+
+	return price;
+}
+
+
+static inline uint32_t
+rc_bittree_reverse_price(const probability *const probs,
+		uint32_t bit_levels, uint32_t symbol)
+{
+	uint32_t price = 0;
+	uint32_t model_index = 1;
+
+	do {
+		const uint32_t bit = symbol & 1;
+		symbol >>= 1;
+		price += rc_bit_price(probs[model_index], bit);
+		model_index = (model_index << 1) + bit;
+	} while (--bit_levels != 0);
+
+	return price;
+}
+
+
+static inline uint32_t
+rc_direct_price(const uint32_t bits)
+{
+	 return bits << RC_BIT_PRICE_SHIFT_BITS;
+}
+
+#endif
diff --git a/src/liblzma/rangecoder/price_table.c b/src/liblzma/rangecoder/price_table.c
new file mode 100644
index 0000000..ac64bf6
--- /dev/null
+++ b/src/liblzma/rangecoder/price_table.c
@@ -0,0 +1,22 @@
+/* This file has been automatically generated by price_tablegen.c. */
+
+#include "range_encoder.h"
+
+const uint8_t lzma_rc_prices[RC_PRICE_TABLE_SIZE] = {
+	 128, 103,  91,  84,  78,  73,  69,  66,
+	  63,  61,  58,  56,  54,  52,  51,  49,
+	  48,  46,  45,  44,  43,  42,  41,  40,
+	  39,  38,  37,  36,  35,  34,  34,  33,
+	  32,  31,  31,  30,  29,  29,  28,  28,
+	  27,  26,  26,  25,  25,  24,  24,  23,
+	  23,  22,  22,  22,  21,  21,  20,  20,
+	  19,  19,  19,  18,  18,  17,  17,  17,
+	  16,  16,  16,  15,  15,  15,  14,  14,
+	  14,  13,  13,  13,  12,  12,  12,  11,
+	  11,  11,  11,  10,  10,  10,  10,   9,
+	   9,   9,   9,   8,   8,   8,   8,   7,
+	   7,   7,   7,   6,   6,   6,   6,   5,
+	   5,   5,   5,   5,   4,   4,   4,   4,
+	   3,   3,   3,   3,   3,   2,   2,   2,
+	   2,   2,   2,   1,   1,   1,   1,   1
+};
diff --git a/src/liblzma/rangecoder/price_tablegen.c b/src/liblzma/rangecoder/price_tablegen.c
new file mode 100644
index 0000000..bf08ce3
--- /dev/null
+++ b/src/liblzma/rangecoder/price_tablegen.c
@@ -0,0 +1,87 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       price_tablegen.c
+/// \brief      Probability price table generator
+///
+/// Compiling: gcc -std=c99 -o price_tablegen price_tablegen.c
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <inttypes.h>
+#include <stdio.h>
+#include "range_common.h"
+#include "price.h"
+
+
+static uint32_t rc_prices[RC_PRICE_TABLE_SIZE];
+
+
+static void
+init_price_table(void)
+{
+	for (uint32_t i = (UINT32_C(1) << RC_MOVE_REDUCING_BITS) / 2;
+			i < RC_BIT_MODEL_TOTAL;
+			i += (UINT32_C(1) << RC_MOVE_REDUCING_BITS)) {
+		const uint32_t cycles_bits = RC_BIT_PRICE_SHIFT_BITS;
+		uint32_t w = i;
+		uint32_t bit_count = 0;
+
+		for (uint32_t j = 0; j < cycles_bits; ++j) {
+			w *= w;
+			bit_count <<= 1;
+
+			while (w >= (UINT32_C(1) << 16)) {
+				w >>= 1;
+				++bit_count;
+			}
+		}
+
+		rc_prices[i >> RC_MOVE_REDUCING_BITS]
+				= (RC_BIT_MODEL_TOTAL_BITS << cycles_bits)
+				- 15 - bit_count;
+	}
+
+	return;
+}
+
+
+static void
+print_price_table(void)
+{
+	printf("/* This file has been automatically generated by "
+			"price_tablegen.c. */\n\n"
+			"#include \"range_encoder.h\"\n\n"
+			"const uint8_t lzma_rc_prices["
+			"RC_PRICE_TABLE_SIZE] = {");
+
+	const size_t array_size = sizeof(lzma_rc_prices)
+			/ sizeof(lzma_rc_prices[0]);
+	for (size_t i = 0; i < array_size; ++i) {
+		if (i % 8 == 0)
+			printf("\n\t");
+
+		printf("%4" PRIu32, rc_prices[i]);
+
+		if (i != array_size - 1)
+			printf(",");
+	}
+
+	printf("\n};\n");
+
+	return;
+}
+
+
+int
+main(void)
+{
+	init_price_table();
+	print_price_table();
+	return 0;
+}
diff --git a/src/liblzma/rangecoder/range_common.h b/src/liblzma/rangecoder/range_common.h
new file mode 100644
index 0000000..0e64241
--- /dev/null
+++ b/src/liblzma/rangecoder/range_common.h
@@ -0,0 +1,73 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       range_common.h
+/// \brief      Common things for range encoder and decoder
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_RANGE_COMMON_H
+#define LZMA_RANGE_COMMON_H
+
+#ifdef HAVE_CONFIG_H
+#	include "common.h"
+#endif
+
+
+///////////////
+// Constants //
+///////////////
+
+#define RC_SHIFT_BITS 8
+#define RC_TOP_BITS 24
+#define RC_TOP_VALUE (UINT32_C(1) << RC_TOP_BITS)
+#define RC_BIT_MODEL_TOTAL_BITS 11
+#define RC_BIT_MODEL_TOTAL (UINT32_C(1) << RC_BIT_MODEL_TOTAL_BITS)
+#define RC_MOVE_BITS 5
+
+
+////////////
+// Macros //
+////////////
+
+// Resets the probability so that both 0 and 1 have probability of 50 %
+#define bit_reset(prob) \
+	prob = RC_BIT_MODEL_TOTAL >> 1
+
+// This does the same for a complete bit tree.
+// (A tree represented as an array.)
+#define bittree_reset(probs, bit_levels) \
+	for (uint32_t bt_i = 0; bt_i < (1 << (bit_levels)); ++bt_i) \
+		bit_reset((probs)[bt_i])
+
+
+//////////////////////
+// Type definitions //
+//////////////////////
+
+/// \brief      Type of probabilities used with range coder
+///
+/// This needs to be at least 12-bit integer, so uint16_t is a logical choice.
+/// However, on some architecture and compiler combinations, a bigger type
+/// may give better speed, because the probability variables are accessed
+/// a lot. On the other hand, bigger probability type increases cache
+/// footprint, since there are 2 to 14 thousand probability variables in
+/// LZMA (assuming the limit of lc + lp <= 4; with lc + lp <= 12 there
+/// would be about 1.5 million variables).
+///
+/// With malicious files, the initialization speed of the LZMA decoder can
+/// become important. In that case, smaller probability variables mean that
+/// there is less bytes to write to RAM, which makes initialization faster.
+/// With big probability type, the initialization can become so slow that it
+/// can be a problem e.g. for email servers doing virus scanning.
+///
+/// I will be sticking to uint16_t unless some specific architectures
+/// are *much* faster (20-50 %) with uint32_t.
+typedef uint16_t probability;
+
+#endif
diff --git a/src/liblzma/rangecoder/range_decoder.h b/src/liblzma/rangecoder/range_decoder.h
new file mode 100644
index 0000000..fb96180
--- /dev/null
+++ b/src/liblzma/rangecoder/range_decoder.h
@@ -0,0 +1,179 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       range_decoder.h
+/// \brief      Range Decoder
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_RANGE_DECODER_H
+#define LZMA_RANGE_DECODER_H
+
+#include "range_common.h"
+
+
+typedef struct {
+	uint32_t range;
+	uint32_t code;
+	uint32_t init_bytes_left;
+} lzma_range_decoder;
+
+
+/// Reads the first five bytes to initialize the range decoder.
+static inline bool
+rc_read_init(lzma_range_decoder *rc, const uint8_t *restrict in,
+		size_t *restrict in_pos, size_t in_size)
+{
+	while (rc->init_bytes_left > 0) {
+		if (*in_pos == in_size)
+			return false;
+
+		rc->code = (rc->code << 8) | in[*in_pos];
+		++*in_pos;
+		--rc->init_bytes_left;
+	}
+
+	return true;
+}
+
+
+/// Makes local copies of range decoder and *in_pos variables. Doing this
+/// improves speed significantly. The range decoder macros expect also
+/// variables `in' and `in_size' to be defined.
+#define rc_to_local(range_decoder, in_pos) \
+	lzma_range_decoder rc = range_decoder; \
+	size_t rc_in_pos = (in_pos); \
+	uint32_t rc_bound
+
+
+/// Stores the local copes back to the range decoder structure.
+#define rc_from_local(range_decoder, in_pos) \
+do { \
+	range_decoder = rc; \
+	in_pos = rc_in_pos; \
+} while (0)
+
+
+/// Resets the range decoder structure.
+#define rc_reset(range_decoder) \
+do { \
+	(range_decoder).range = UINT32_MAX; \
+	(range_decoder).code = 0; \
+	(range_decoder).init_bytes_left = 5; \
+} while (0)
+
+
+/// When decoding has been properly finished, rc.code is always zero unless
+/// the input stream is corrupt. So checking this can catch some corrupt
+/// files especially if they don't have any other integrity check.
+#define rc_is_finished(range_decoder) \
+	((range_decoder).code == 0)
+
+
+/// Read the next input byte if needed. If more input is needed but there is
+/// no more input available, "goto out" is used to jump out of the main
+/// decoder loop.
+#define rc_normalize(seq) \
+do { \
+	if (rc.range < RC_TOP_VALUE) { \
+		if (unlikely(rc_in_pos == in_size)) { \
+			coder->sequence = seq; \
+			goto out; \
+		} \
+		rc.range <<= RC_SHIFT_BITS; \
+		rc.code = (rc.code << RC_SHIFT_BITS) | in[rc_in_pos++]; \
+	} \
+} while (0)
+
+
+/// Start decoding a bit. This must be used together with rc_update_0()
+/// and rc_update_1():
+///
+///     rc_if_0(prob, seq) {
+///         rc_update_0(prob);
+///         // Do something
+///     } else {
+///         rc_update_1(prob);
+///         // Do something else
+///     }
+///
+#define rc_if_0(prob, seq) \
+	rc_normalize(seq); \
+	rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) * (prob); \
+	if (rc.code < rc_bound)
+
+
+/// Update the range decoder state and the used probability variable to
+/// match a decoded bit of 0.
+#define rc_update_0(prob) \
+do { \
+	rc.range = rc_bound; \
+	prob += (RC_BIT_MODEL_TOTAL - (prob)) >> RC_MOVE_BITS; \
+} while (0)
+
+
+/// Update the range decoder state and the used probability variable to
+/// match a decoded bit of 1.
+#define rc_update_1(prob) \
+do { \
+	rc.range -= rc_bound; \
+	rc.code -= rc_bound; \
+	prob -= (prob) >> RC_MOVE_BITS; \
+} while (0)
+
+
+/// Decodes one bit and runs action0 or action1 depending on the decoded bit.
+/// This macro is used as the last step in bittree reverse decoders since
+/// those don't use "symbol" for anything else than indexing the probability
+/// arrays.
+#define rc_bit_last(prob, action0, action1, seq) \
+do { \
+	rc_if_0(prob, seq) { \
+		rc_update_0(prob); \
+		action0; \
+	} else { \
+		rc_update_1(prob); \
+		action1; \
+	} \
+} while (0)
+
+
+/// Decodes one bit, updates "symbol", and runs action0 or action1 depending
+/// on the decoded bit.
+#define rc_bit(prob, action0, action1, seq) \
+	rc_bit_last(prob, \
+		symbol <<= 1; action0, \
+		symbol = (symbol << 1) + 1; action1, \
+		seq);
+
+
+/// Like rc_bit() but add "case seq:" as a prefix. This makes the unrolled
+/// loops more readable because the code isn't littered with "case"
+/// statements. On the other hand this also makes it less readable, since
+/// spotting the places where the decoder loop may be restarted is less
+/// obvious.
+#define rc_bit_case(prob, action0, action1, seq) \
+	case seq: rc_bit(prob, action0, action1, seq)
+
+
+/// Decode a bit without using a probability.
+#define rc_direct(dest, seq) \
+do { \
+	rc_normalize(seq); \
+	rc.range >>= 1; \
+	rc.code -= rc.range; \
+	rc_bound = UINT32_C(0) - (rc.code >> 31); \
+	rc.code += rc.range & rc_bound; \
+	dest = (dest << 1) + (rc_bound + 1); \
+} while (0)
+
+
+// NOTE: No macros are provided for bittree decoding. It seems to be simpler
+// to just write them open in the code.
+
+#endif
diff --git a/src/liblzma/rangecoder/range_encoder.h b/src/liblzma/rangecoder/range_encoder.h
new file mode 100644
index 0000000..1e1c369
--- /dev/null
+++ b/src/liblzma/rangecoder/range_encoder.h
@@ -0,0 +1,231 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       range_encoder.h
+/// \brief      Range Encoder
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_RANGE_ENCODER_H
+#define LZMA_RANGE_ENCODER_H
+
+#include "range_common.h"
+#include "price.h"
+
+
+/// Maximum number of symbols that can be put pending into lzma_range_encoder
+/// structure between calls to lzma_rc_encode(). For LZMA, 52+5 is enough
+/// (match with big distance and length followed by range encoder flush).
+#define RC_SYMBOLS_MAX 58
+
+
+typedef struct {
+	uint64_t low;
+	uint64_t cache_size;
+	uint32_t range;
+	uint8_t cache;
+
+	/// Number of symbols in the tables
+	size_t count;
+
+	/// rc_encode()'s position in the tables
+	size_t pos;
+
+	/// Symbols to encode
+	enum {
+		RC_BIT_0,
+		RC_BIT_1,
+		RC_DIRECT_0,
+		RC_DIRECT_1,
+		RC_FLUSH,
+	} symbols[RC_SYMBOLS_MAX];
+
+	/// Probabilities associated with RC_BIT_0 or RC_BIT_1
+	probability *probs[RC_SYMBOLS_MAX];
+
+} lzma_range_encoder;
+
+
+static inline void
+rc_reset(lzma_range_encoder *rc)
+{
+	rc->low = 0;
+	rc->cache_size = 1;
+	rc->range = UINT32_MAX;
+	rc->cache = 0;
+	rc->count = 0;
+	rc->pos = 0;
+}
+
+
+static inline void
+rc_bit(lzma_range_encoder *rc, probability *prob, uint32_t bit)
+{
+	rc->symbols[rc->count] = bit;
+	rc->probs[rc->count] = prob;
+	++rc->count;
+}
+
+
+static inline void
+rc_bittree(lzma_range_encoder *rc, probability *probs,
+		uint32_t bit_count, uint32_t symbol)
+{
+	uint32_t model_index = 1;
+
+	do {
+		const uint32_t bit = (symbol >> --bit_count) & 1;
+		rc_bit(rc, &probs[model_index], bit);
+		model_index = (model_index << 1) + bit;
+	} while (bit_count != 0);
+}
+
+
+static inline void
+rc_bittree_reverse(lzma_range_encoder *rc, probability *probs,
+		uint32_t bit_count, uint32_t symbol)
+{
+	uint32_t model_index = 1;
+
+	do {
+		const uint32_t bit = symbol & 1;
+		symbol >>= 1;
+		rc_bit(rc, &probs[model_index], bit);
+		model_index = (model_index << 1) + bit;
+	} while (--bit_count != 0);
+}
+
+
+static inline void
+rc_direct(lzma_range_encoder *rc,
+		uint32_t value, uint32_t bit_count)
+{
+	do {
+		rc->symbols[rc->count++]
+				= RC_DIRECT_0 + ((value >> --bit_count) & 1);
+	} while (bit_count != 0);
+}
+
+
+static inline void
+rc_flush(lzma_range_encoder *rc)
+{
+	for (size_t i = 0; i < 5; ++i)
+		rc->symbols[rc->count++] = RC_FLUSH;
+}
+
+
+static inline bool
+rc_shift_low(lzma_range_encoder *rc,
+		uint8_t *out, size_t *out_pos, size_t out_size)
+{
+	if ((uint32_t)(rc->low) < (uint32_t)(0xFF000000)
+			|| (uint32_t)(rc->low >> 32) != 0) {
+		do {
+			if (*out_pos == out_size)
+				return true;
+
+			out[*out_pos] = rc->cache + (uint8_t)(rc->low >> 32);
+			++*out_pos;
+			rc->cache = 0xFF;
+
+		} while (--rc->cache_size != 0);
+
+		rc->cache = (rc->low >> 24) & 0xFF;
+	}
+
+	++rc->cache_size;
+	rc->low = (rc->low & 0x00FFFFFF) << RC_SHIFT_BITS;
+
+	return false;
+}
+
+
+static inline bool
+rc_encode(lzma_range_encoder *rc,
+		uint8_t *out, size_t *out_pos, size_t out_size)
+{
+	assert(rc->count <= RC_SYMBOLS_MAX);
+
+	while (rc->pos < rc->count) {
+		// Normalize
+		if (rc->range < RC_TOP_VALUE) {
+			if (rc_shift_low(rc, out, out_pos, out_size))
+				return true;
+
+			rc->range <<= RC_SHIFT_BITS;
+		}
+
+		// Encode a bit
+		switch (rc->symbols[rc->pos]) {
+		case RC_BIT_0: {
+			probability prob = *rc->probs[rc->pos];
+			rc->range = (rc->range >> RC_BIT_MODEL_TOTAL_BITS)
+					* prob;
+			prob += (RC_BIT_MODEL_TOTAL - prob) >> RC_MOVE_BITS;
+			*rc->probs[rc->pos] = prob;
+			break;
+		}
+
+		case RC_BIT_1: {
+			probability prob = *rc->probs[rc->pos];
+			const uint32_t bound = prob * (rc->range
+					>> RC_BIT_MODEL_TOTAL_BITS);
+			rc->low += bound;
+			rc->range -= bound;
+			prob -= prob >> RC_MOVE_BITS;
+			*rc->probs[rc->pos] = prob;
+			break;
+		}
+
+		case RC_DIRECT_0:
+			rc->range >>= 1;
+			break;
+
+		case RC_DIRECT_1:
+			rc->range >>= 1;
+			rc->low += rc->range;
+			break;
+
+		case RC_FLUSH:
+			// Prevent further normalizations.
+			rc->range = UINT32_MAX;
+
+			// Flush the last five bytes (see rc_flush()).
+			do {
+				if (rc_shift_low(rc, out, out_pos, out_size))
+					return true;
+			} while (++rc->pos < rc->count);
+
+			// Reset the range encoder so we are ready to continue
+			// encoding if we weren't finishing the stream.
+			rc_reset(rc);
+			return false;
+
+		default:
+			assert(0);
+			break;
+		}
+
+		++rc->pos;
+	}
+
+	rc->count = 0;
+	rc->pos = 0;
+
+	return false;
+}
+
+
+static inline uint64_t
+rc_pending(const lzma_range_encoder *rc)
+{
+	return rc->cache_size + 5 - 1;
+}
+
+#endif
diff --git a/src/liblzma/simple/Makefile.inc b/src/liblzma/simple/Makefile.inc
new file mode 100644
index 0000000..8a5e2d7
--- /dev/null
+++ b/src/liblzma/simple/Makefile.inc
@@ -0,0 +1,47 @@
+##
+## Author: Lasse Collin
+##
+## This file has been put into the public domain.
+## You can do whatever you want with this file.
+##
+
+liblzma_la_SOURCES += \
+	simple/simple_coder.c \
+	simple/simple_coder.h \
+	simple/simple_private.h
+
+if COND_ENCODER_SIMPLE
+liblzma_la_SOURCES += \
+	simple/simple_encoder.c \
+	simple/simple_encoder.h
+endif
+
+if COND_DECODER_SIMPLE
+liblzma_la_SOURCES += \
+	simple/simple_decoder.c \
+	simple/simple_decoder.h
+endif
+
+if COND_FILTER_X86
+liblzma_la_SOURCES += simple/x86.c
+endif
+
+if COND_FILTER_POWERPC
+liblzma_la_SOURCES += simple/powerpc.c
+endif
+
+if COND_FILTER_IA64
+liblzma_la_SOURCES += simple/ia64.c
+endif
+
+if COND_FILTER_ARM
+liblzma_la_SOURCES += simple/arm.c
+endif
+
+if COND_FILTER_ARMTHUMB
+liblzma_la_SOURCES += simple/armthumb.c
+endif
+
+if COND_FILTER_SPARC
+liblzma_la_SOURCES += simple/sparc.c
+endif
diff --git a/src/liblzma/simple/arm.c b/src/liblzma/simple/arm.c
new file mode 100644
index 0000000..8fcf643
--- /dev/null
+++ b/src/liblzma/simple/arm.c
@@ -0,0 +1,69 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       arm.c
+/// \brief      Filter for ARM binaries
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "simple_private.h"
+
+
+static size_t
+arm_code(lzma_simple *simple lzma_attribute((unused)),
+		uint32_t now_pos, bool is_encoder,
+		uint8_t *buffer, size_t size)
+{
+	size_t i;
+	for (i = 0; i + 4 <= size; i += 4) {
+		if (buffer[i + 3] == 0xEB) {
+			uint32_t src = (buffer[i + 2] << 16)
+					| (buffer[i + 1] << 8)
+					| (buffer[i + 0]);
+			src <<= 2;
+
+			uint32_t dest;
+			if (is_encoder)
+				dest = now_pos + (uint32_t)(i) + 8 + src;
+			else
+				dest = src - (now_pos + (uint32_t)(i) + 8);
+
+			dest >>= 2;
+			buffer[i + 2] = (dest >> 16);
+			buffer[i + 1] = (dest >> 8);
+			buffer[i + 0] = dest;
+		}
+	}
+
+	return i;
+}
+
+
+static lzma_ret
+arm_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters, bool is_encoder)
+{
+	return lzma_simple_coder_init(next, allocator, filters,
+			&arm_code, 0, 4, 4, is_encoder);
+}
+
+
+extern lzma_ret
+lzma_simple_arm_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters)
+{
+	return arm_coder_init(next, allocator, filters, true);
+}
+
+
+extern lzma_ret
+lzma_simple_arm_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters)
+{
+	return arm_coder_init(next, allocator, filters, false);
+}
diff --git a/src/liblzma/simple/armthumb.c b/src/liblzma/simple/armthumb.c
new file mode 100644
index 0000000..eb6a69d
--- /dev/null
+++ b/src/liblzma/simple/armthumb.c
@@ -0,0 +1,74 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       armthumb.c
+/// \brief      Filter for ARM-Thumb binaries
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "simple_private.h"
+
+
+static size_t
+armthumb_code(lzma_simple *simple lzma_attribute((unused)),
+		uint32_t now_pos, bool is_encoder,
+		uint8_t *buffer, size_t size)
+{
+	size_t i;
+	for (i = 0; i + 4 <= size; i += 2) {
+		if ((buffer[i + 1] & 0xF8) == 0xF0
+				&& (buffer[i + 3] & 0xF8) == 0xF8) {
+			uint32_t src = ((buffer[i + 1] & 0x7) << 19)
+					| (buffer[i + 0] << 11)
+					| ((buffer[i + 3] & 0x7) << 8)
+					| (buffer[i + 2]);
+
+			src <<= 1;
+
+			uint32_t dest;
+			if (is_encoder)
+				dest = now_pos + (uint32_t)(i) + 4 + src;
+			else
+				dest = src - (now_pos + (uint32_t)(i) + 4);
+
+			dest >>= 1;
+			buffer[i + 1] = 0xF0 | ((dest >> 19) & 0x7);
+			buffer[i + 0] = (dest >> 11);
+			buffer[i + 3] = 0xF8 | ((dest >> 8) & 0x7);
+			buffer[i + 2] = (dest);
+			i += 2;
+		}
+	}
+
+	return i;
+}
+
+
+static lzma_ret
+armthumb_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters, bool is_encoder)
+{
+	return lzma_simple_coder_init(next, allocator, filters,
+			&armthumb_code, 0, 4, 2, is_encoder);
+}
+
+
+extern lzma_ret
+lzma_simple_armthumb_encoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters)
+{
+	return armthumb_coder_init(next, allocator, filters, true);
+}
+
+
+extern lzma_ret
+lzma_simple_armthumb_decoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters)
+{
+	return armthumb_coder_init(next, allocator, filters, false);
+}
diff --git a/src/liblzma/simple/ia64.c b/src/liblzma/simple/ia64.c
new file mode 100644
index 0000000..fd263d4
--- /dev/null
+++ b/src/liblzma/simple/ia64.c
@@ -0,0 +1,110 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       ia64.c
+/// \brief      Filter for IA64 (Itanium) binaries
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "simple_private.h"
+
+
+static size_t
+ia64_code(lzma_simple *simple lzma_attribute((unused)),
+		uint32_t now_pos, bool is_encoder,
+		uint8_t *buffer, size_t size)
+{
+	static const uint32_t BRANCH_TABLE[32] = {
+		0, 0, 0, 0, 0, 0, 0, 0,
+		0, 0, 0, 0, 0, 0, 0, 0,
+		4, 4, 6, 6, 0, 0, 7, 7,
+		4, 4, 0, 0, 4, 4, 0, 0
+	};
+
+	size_t i;
+	for (i = 0; i + 16 <= size; i += 16) {
+		const uint32_t instr_template = buffer[i] & 0x1F;
+		const uint32_t mask = BRANCH_TABLE[instr_template];
+		uint32_t bit_pos = 5;
+
+		for (size_t slot = 0; slot < 3; ++slot, bit_pos += 41) {
+			if (((mask >> slot) & 1) == 0)
+				continue;
+
+			const size_t byte_pos = (bit_pos >> 3);
+			const uint32_t bit_res = bit_pos & 0x7;
+			uint64_t instruction = 0;
+
+			for (size_t j = 0; j < 6; ++j)
+				instruction += (uint64_t)(
+						buffer[i + j + byte_pos])
+						<< (8 * j);
+
+			uint64_t inst_norm = instruction >> bit_res;
+
+			if (((inst_norm >> 37) & 0xF) == 0x5
+					&& ((inst_norm >> 9) & 0x7) == 0
+					/* &&  (inst_norm & 0x3F)== 0 */
+					) {
+				uint32_t src = (uint32_t)(
+						(inst_norm >> 13) & 0xFFFFF);
+				src |= ((inst_norm >> 36) & 1) << 20;
+
+				src <<= 4;
+
+				uint32_t dest;
+				if (is_encoder)
+					dest = now_pos + (uint32_t)(i) + src;
+				else
+					dest = src - (now_pos + (uint32_t)(i));
+
+				dest >>= 4;
+
+				inst_norm &= ~((uint64_t)(0x8FFFFF) << 13);
+				inst_norm |= (uint64_t)(dest & 0xFFFFF) << 13;
+				inst_norm |= (uint64_t)(dest & 0x100000)
+						<< (36 - 20);
+
+				instruction &= (1 << bit_res) - 1;
+				instruction |= (inst_norm << bit_res);
+
+				for (size_t j = 0; j < 6; j++)
+					buffer[i + j + byte_pos] = (uint8_t)(
+							instruction
+							>> (8 * j));
+			}
+		}
+	}
+
+	return i;
+}
+
+
+static lzma_ret
+ia64_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters, bool is_encoder)
+{
+	return lzma_simple_coder_init(next, allocator, filters,
+			&ia64_code, 0, 16, 16, is_encoder);
+}
+
+
+extern lzma_ret
+lzma_simple_ia64_encoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters)
+{
+	return ia64_coder_init(next, allocator, filters, true);
+}
+
+
+extern lzma_ret
+lzma_simple_ia64_decoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters)
+{
+	return ia64_coder_init(next, allocator, filters, false);
+}
diff --git a/src/liblzma/simple/powerpc.c b/src/liblzma/simple/powerpc.c
new file mode 100644
index 0000000..aaa14f2
--- /dev/null
+++ b/src/liblzma/simple/powerpc.c
@@ -0,0 +1,73 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       powerpc.c
+/// \brief      Filter for PowerPC (big endian) binaries
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "simple_private.h"
+
+
+static size_t
+powerpc_code(lzma_simple *simple lzma_attribute((unused)),
+		uint32_t now_pos, bool is_encoder,
+		uint8_t *buffer, size_t size)
+{
+	size_t i;
+	for (i = 0; i + 4 <= size; i += 4) {
+		// PowerPC branch 6(48) 24(Offset) 1(Abs) 1(Link)
+		if ((buffer[i] >> 2) == 0x12
+				&& ((buffer[i + 3] & 3) == 1)) {
+
+			const uint32_t src = ((buffer[i + 0] & 3) << 24)
+					| (buffer[i + 1] << 16)
+					| (buffer[i + 2] << 8)
+					| (buffer[i + 3] & (~3));
+
+			uint32_t dest;
+			if (is_encoder)
+				dest = now_pos + (uint32_t)(i) + src;
+			else
+				dest = src - (now_pos + (uint32_t)(i));
+
+			buffer[i + 0] = 0x48 | ((dest >> 24) &  0x03);
+			buffer[i + 1] = (dest >> 16);
+			buffer[i + 2] = (dest >> 8);
+			buffer[i + 3] &= 0x03;
+			buffer[i + 3] |= dest;
+		}
+	}
+
+	return i;
+}
+
+
+static lzma_ret
+powerpc_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters, bool is_encoder)
+{
+	return lzma_simple_coder_init(next, allocator, filters,
+			&powerpc_code, 0, 4, 4, is_encoder);
+}
+
+
+extern lzma_ret
+lzma_simple_powerpc_encoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters)
+{
+	return powerpc_coder_init(next, allocator, filters, true);
+}
+
+
+extern lzma_ret
+lzma_simple_powerpc_decoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters)
+{
+	return powerpc_coder_init(next, allocator, filters, false);
+}
diff --git a/src/liblzma/simple/simple_coder.c b/src/liblzma/simple/simple_coder.c
new file mode 100644
index 0000000..06db86e
--- /dev/null
+++ b/src/liblzma/simple/simple_coder.c
@@ -0,0 +1,280 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       simple_coder.c
+/// \brief      Wrapper for simple filters
+///
+/// Simple filters don't change the size of the data i.e. number of bytes
+/// in equals the number of bytes out.
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "simple_private.h"
+
+
+/// Copied or encodes/decodes more data to out[].
+static lzma_ret
+copy_or_code(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)
+{
+	assert(!coder->end_was_reached);
+
+	if (coder->next.code == NULL) {
+		lzma_bufcpy(in, in_pos, in_size, out, out_pos, out_size);
+
+		// Check if end of stream was reached.
+		if (coder->is_encoder && action == LZMA_FINISH
+				&& *in_pos == in_size)
+			coder->end_was_reached = true;
+
+	} else {
+		// Call the next coder in the chain to provide us some data.
+		// We don't care about uncompressed_size here, because
+		// the next filter in the chain will do it for us (since
+		// we don't change the size of the data).
+		const lzma_ret ret = coder->next.code(
+				coder->next.coder, allocator,
+				in, in_pos, in_size,
+				out, out_pos, out_size, action);
+
+		if (ret == LZMA_STREAM_END) {
+			assert(!coder->is_encoder
+					|| action == LZMA_FINISH);
+			coder->end_was_reached = true;
+
+		} else if (ret != LZMA_OK) {
+			return ret;
+		}
+	}
+
+	return LZMA_OK;
+}
+
+
+static size_t
+call_filter(lzma_coder *coder, uint8_t *buffer, size_t size)
+{
+	const size_t filtered = coder->filter(coder->simple,
+			coder->now_pos, coder->is_encoder,
+			buffer, size);
+	coder->now_pos += filtered;
+	return filtered;
+}
+
+
+static lzma_ret
+simple_code(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)
+{
+	// TODO: Add partial support for LZMA_SYNC_FLUSH. We can support it
+	// in cases when the filter is able to filter everything. With most
+	// simple filters it can be done at offset that is a multiple of 2,
+	// 4, or 16. With x86 filter, it needs good luck, and thus cannot
+	// be made to work predictably.
+	if (action == LZMA_SYNC_FLUSH)
+		return LZMA_OPTIONS_ERROR;
+
+	// Flush already filtered data from coder->buffer[] to out[].
+	if (coder->pos < coder->filtered) {
+		lzma_bufcpy(coder->buffer, &coder->pos, coder->filtered,
+				out, out_pos, out_size);
+
+		// If we couldn't flush all the filtered data, return to
+		// application immediately.
+		if (coder->pos < coder->filtered)
+			return LZMA_OK;
+
+		if (coder->end_was_reached) {
+			assert(coder->filtered == coder->size);
+			return LZMA_STREAM_END;
+		}
+	}
+
+	// If we get here, there is no filtered data left in the buffer.
+	coder->filtered = 0;
+
+	assert(!coder->end_was_reached);
+
+	// If there is more output space left than there is unfiltered data
+	// in coder->buffer[], flush coder->buffer[] to out[], and copy/code
+	// more data to out[] hopefully filling it completely. Then filter
+	// the data in out[]. This step is where most of the data gets
+	// filtered if the buffer sizes used by the application are reasonable.
+	const size_t out_avail = out_size - *out_pos;
+	const size_t buf_avail = coder->size - coder->pos;
+	if (out_avail > buf_avail) {
+		// Store the old position so that we know from which byte
+		// to start filtering.
+		const size_t out_start = *out_pos;
+
+		// Flush data from coder->buffer[] to out[], but don't reset
+		// coder->pos and coder->size yet. This way the coder can be
+		// restarted if the next filter in the chain returns e.g.
+		// LZMA_MEM_ERROR.
+		memcpy(out + *out_pos, coder->buffer + coder->pos, buf_avail);
+		*out_pos += buf_avail;
+
+		// Copy/Encode/Decode more data to out[].
+		{
+			const lzma_ret ret = copy_or_code(coder, allocator,
+					in, in_pos, in_size,
+					out, out_pos, out_size, action);
+			assert(ret != LZMA_STREAM_END);
+			if (ret != LZMA_OK)
+				return ret;
+		}
+
+		// Filter out[].
+		const size_t size = *out_pos - out_start;
+		const size_t filtered = call_filter(
+				coder, out + out_start, size);
+
+		const size_t unfiltered = size - filtered;
+		assert(unfiltered <= coder->allocated / 2);
+
+		// Now we can update coder->pos and coder->size, because
+		// the next coder in the chain (if any) was successful.
+		coder->pos = 0;
+		coder->size = unfiltered;
+
+		if (coder->end_was_reached) {
+			// The last byte has been copied to out[] already.
+			// They are left as is.
+			coder->size = 0;
+
+		} else if (unfiltered > 0) {
+			// There is unfiltered data left in out[]. Copy it to
+			// coder->buffer[] and rewind *out_pos appropriately.
+			*out_pos -= unfiltered;
+			memcpy(coder->buffer, out + *out_pos, unfiltered);
+		}
+	} else if (coder->pos > 0) {
+		memmove(coder->buffer, coder->buffer + coder->pos, buf_avail);
+		coder->size -= coder->pos;
+		coder->pos = 0;
+	}
+
+	assert(coder->pos == 0);
+
+	// If coder->buffer[] isn't empty, try to fill it by copying/decoding
+	// more data. Then filter coder->buffer[] and copy the successfully
+	// filtered data to out[]. It is probable, that some filtered and
+	// unfiltered data will be left to coder->buffer[].
+	if (coder->size > 0) {
+		{
+			const lzma_ret ret = copy_or_code(coder, allocator,
+					in, in_pos, in_size,
+					coder->buffer, &coder->size,
+					coder->allocated, action);
+			assert(ret != LZMA_STREAM_END);
+			if (ret != LZMA_OK)
+				return ret;
+		}
+
+		coder->filtered = call_filter(
+				coder, coder->buffer, coder->size);
+
+		// Everything is considered to be filtered if coder->buffer[]
+		// contains the last bytes of the data.
+		if (coder->end_was_reached)
+			coder->filtered = coder->size;
+
+		// Flush as much as possible.
+		lzma_bufcpy(coder->buffer, &coder->pos, coder->filtered,
+				out, out_pos, out_size);
+	}
+
+	// Check if we got everything done.
+	if (coder->end_was_reached && coder->pos == coder->size)
+		return LZMA_STREAM_END;
+
+	return LZMA_OK;
+}
+
+
+static void
+simple_coder_end(lzma_coder *coder, lzma_allocator *allocator)
+{
+	lzma_next_end(&coder->next, allocator);
+	lzma_free(coder->simple, allocator);
+	lzma_free(coder, allocator);
+	return;
+}
+
+
+static lzma_ret
+simple_coder_update(lzma_coder *coder, lzma_allocator *allocator,
+		const lzma_filter *filters_null lzma_attribute((unused)),
+		const lzma_filter *reversed_filters)
+{
+	// No update support, just call the next filter in the chain.
+	return lzma_next_filter_update(
+			&coder->next, allocator, reversed_filters + 1);
+}
+
+
+extern lzma_ret
+lzma_simple_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters,
+		size_t (*filter)(lzma_simple *simple, uint32_t now_pos,
+			bool is_encoder, uint8_t *buffer, size_t size),
+		size_t simple_size, size_t unfiltered_max,
+		uint32_t alignment, bool is_encoder)
+{
+	// Allocate memory for the lzma_coder structure if needed.
+	if (next->coder == NULL) {
+		// Here we allocate space also for the temporary buffer. We
+		// need twice the size of unfiltered_max, because then it
+		// is always possible to filter at least unfiltered_max bytes
+		// more data in coder->buffer[] if it can be filled completely.
+		next->coder = lzma_alloc(sizeof(lzma_coder)
+				+ 2 * unfiltered_max, allocator);
+		if (next->coder == NULL)
+			return LZMA_MEM_ERROR;
+
+		next->code = &simple_code;
+		next->end = &simple_coder_end;
+		next->update = &simple_coder_update;
+
+		next->coder->next = LZMA_NEXT_CODER_INIT;
+		next->coder->filter = filter;
+		next->coder->allocated = 2 * unfiltered_max;
+
+		// Allocate memory for filter-specific data structure.
+		if (simple_size > 0) {
+			next->coder->simple = lzma_alloc(
+					simple_size, allocator);
+			if (next->coder->simple == NULL)
+				return LZMA_MEM_ERROR;
+		} else {
+			next->coder->simple = NULL;
+		}
+	}
+
+	if (filters[0].options != NULL) {
+		const lzma_options_bcj *simple = filters[0].options;
+		next->coder->now_pos = simple->start_offset;
+		if (next->coder->now_pos & (alignment - 1))
+			return LZMA_OPTIONS_ERROR;
+	} else {
+		next->coder->now_pos = 0;
+	}
+
+	// Reset variables.
+	next->coder->is_encoder = is_encoder;
+	next->coder->end_was_reached = false;
+	next->coder->pos = 0;
+	next->coder->filtered = 0;
+	next->coder->size = 0;
+
+	return lzma_next_filter_init(
+			&next->coder->next, allocator, filters + 1);
+}
diff --git a/src/liblzma/simple/simple_coder.h b/src/liblzma/simple/simple_coder.h
new file mode 100644
index 0000000..0952fad
--- /dev/null
+++ b/src/liblzma/simple/simple_coder.h
@@ -0,0 +1,60 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       simple_coder.h
+/// \brief      Wrapper for simple filters
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_SIMPLE_CODER_H
+#define LZMA_SIMPLE_CODER_H
+
+#include "common.h"
+
+
+extern lzma_ret lzma_simple_x86_encoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters);
+
+extern lzma_ret lzma_simple_x86_decoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters);
+
+
+extern lzma_ret lzma_simple_powerpc_encoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters);
+
+extern lzma_ret lzma_simple_powerpc_decoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters);
+
+
+extern lzma_ret lzma_simple_ia64_encoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters);
+
+extern lzma_ret lzma_simple_ia64_decoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters);
+
+
+extern lzma_ret lzma_simple_arm_encoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters);
+
+extern lzma_ret lzma_simple_arm_decoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters);
+
+
+extern lzma_ret lzma_simple_armthumb_encoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters);
+
+extern lzma_ret lzma_simple_armthumb_decoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters);
+
+
+extern lzma_ret lzma_simple_sparc_encoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters);
+
+extern lzma_ret lzma_simple_sparc_decoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters);
+
+#endif
diff --git a/src/liblzma/simple/simple_decoder.c b/src/liblzma/simple/simple_decoder.c
new file mode 100644
index 0000000..0beccd3
--- /dev/null
+++ b/src/liblzma/simple/simple_decoder.c
@@ -0,0 +1,40 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       simple_decoder.c
+/// \brief      Properties decoder for simple filters
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "simple_decoder.h"
+
+
+extern lzma_ret
+lzma_simple_props_decode(void **options, lzma_allocator *allocator,
+		const uint8_t *props, size_t props_size)
+{
+	if (props_size == 0)
+		return LZMA_OK;
+
+	if (props_size != 4)
+		return LZMA_OPTIONS_ERROR;
+
+	lzma_options_bcj *opt = lzma_alloc(
+			sizeof(lzma_options_bcj), allocator);
+	if (opt == NULL)
+		return LZMA_MEM_ERROR;
+
+	opt->start_offset = unaligned_read32le(props);
+
+	// Don't leave an options structure allocated if start_offset is zero.
+	if (opt->start_offset == 0)
+		lzma_free(opt, allocator);
+	else
+		*options = opt;
+
+	return LZMA_OK;
+}
diff --git a/src/liblzma/simple/simple_decoder.h b/src/liblzma/simple/simple_decoder.h
new file mode 100644
index 0000000..b8bf590
--- /dev/null
+++ b/src/liblzma/simple/simple_decoder.h
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       simple_decoder.h
+/// \brief      Properties decoder for simple filters
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_SIMPLE_DECODER_H
+#define LZMA_SIMPLE_DECODER_H
+
+#include "simple_coder.h"
+
+extern lzma_ret lzma_simple_props_decode(
+		void **options, lzma_allocator *allocator,
+		const uint8_t *props, size_t props_size);
+
+#endif
diff --git a/src/liblzma/simple/simple_encoder.c b/src/liblzma/simple/simple_encoder.c
new file mode 100644
index 0000000..8aa463b
--- /dev/null
+++ b/src/liblzma/simple/simple_encoder.c
@@ -0,0 +1,38 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       simple_encoder.c
+/// \brief      Properties encoder for simple filters
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "simple_encoder.h"
+
+
+extern lzma_ret
+lzma_simple_props_size(uint32_t *size, const void *options)
+{
+	const lzma_options_bcj *const opt = options;
+	*size = (opt == NULL || opt->start_offset == 0) ? 0 : 4;
+	return LZMA_OK;
+}
+
+
+extern lzma_ret
+lzma_simple_props_encode(const void *options, uint8_t *out)
+{
+	const lzma_options_bcj *const opt = options;
+
+	// The default start offset is zero, so we don't need to store any
+	// options unless the start offset is non-zero.
+	if (opt == NULL || opt->start_offset == 0)
+		return LZMA_OK;
+
+	unaligned_write32le(out, opt->start_offset);
+
+	return LZMA_OK;
+}
diff --git a/src/liblzma/simple/simple_encoder.h b/src/liblzma/simple/simple_encoder.h
new file mode 100644
index 0000000..1cee482
--- /dev/null
+++ b/src/liblzma/simple/simple_encoder.h
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       simple_encoder.c
+/// \brief      Properties encoder for simple filters
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_SIMPLE_ENCODER_H
+#define LZMA_SIMPLE_ENCODER_H
+
+#include "simple_coder.h"
+
+
+extern lzma_ret lzma_simple_props_size(uint32_t *size, const void *options);
+
+extern lzma_ret lzma_simple_props_encode(const void *options, uint8_t *out);
+
+#endif
diff --git a/src/liblzma/simple/simple_private.h b/src/liblzma/simple/simple_private.h
new file mode 100644
index 0000000..a69f827
--- /dev/null
+++ b/src/liblzma/simple/simple_private.h
@@ -0,0 +1,76 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       simple_private.h
+/// \brief      Private definitions for so called simple filters
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_SIMPLE_PRIVATE_H
+#define LZMA_SIMPLE_PRIVATE_H
+
+#include "simple_coder.h"
+
+
+typedef struct lzma_simple_s lzma_simple;
+
+struct lzma_coder_s {
+	/// Next filter in the chain
+	lzma_next_coder next;
+
+	/// True if the next coder in the chain has returned LZMA_STREAM_END
+	/// or if we have processed uncompressed_size bytes.
+	bool end_was_reached;
+
+	/// True if filter() should encode the data; false to decode.
+	/// Currently all simple filters use the same function for encoding
+	/// and decoding, because the difference between encoders and decoders
+	/// is very small.
+	bool is_encoder;
+
+	/// Pointer to filter-specific function, which does
+	/// the actual filtering.
+	size_t (*filter)(lzma_simple *simple, uint32_t now_pos,
+			bool is_encoder, uint8_t *buffer, size_t size);
+
+	/// Pointer to filter-specific data, or NULL if filter doesn't need
+	/// any extra data.
+	lzma_simple *simple;
+
+	/// The lowest 32 bits of the current position in the data. Most
+	/// filters need this to do conversions between absolute and relative
+	/// addresses.
+	uint32_t now_pos;
+
+	/// Size of the memory allocated for the buffer.
+	size_t allocated;
+
+	/// Flushing position in the temporary buffer. buffer[pos] is the
+	/// next byte to be copied to out[].
+	size_t pos;
+
+	/// buffer[filtered] is the first unfiltered byte. When pos is smaller
+	/// than filtered, there is unflushed filtered data in the buffer.
+	size_t filtered;
+
+	/// Total number of bytes (both filtered and unfiltered) currently
+	/// in the temporary buffer.
+	size_t size;
+
+	/// Temporary buffer
+	uint8_t buffer[];
+};
+
+
+extern lzma_ret lzma_simple_coder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters,
+		size_t (*filter)(lzma_simple *simple, uint32_t now_pos,
+			bool is_encoder, uint8_t *buffer, size_t size),
+		size_t simple_size, size_t unfiltered_max,
+		uint32_t alignment, bool is_encoder);
+
+#endif
diff --git a/src/liblzma/simple/sparc.c b/src/liblzma/simple/sparc.c
new file mode 100644
index 0000000..808a59a
--- /dev/null
+++ b/src/liblzma/simple/sparc.c
@@ -0,0 +1,81 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       sparc.c
+/// \brief      Filter for SPARC binaries
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "simple_private.h"
+
+
+static size_t
+sparc_code(lzma_simple *simple lzma_attribute((unused)),
+		uint32_t now_pos, bool is_encoder,
+		uint8_t *buffer, size_t size)
+{
+	size_t i;
+	for (i = 0; i + 4 <= size; i += 4) {
+
+		if ((buffer[i] == 0x40 && (buffer[i + 1] & 0xC0) == 0x00)
+				|| (buffer[i] == 0x7F
+				&& (buffer[i + 1] & 0xC0) == 0xC0)) {
+
+			uint32_t src = ((uint32_t)buffer[i + 0] << 24)
+					| ((uint32_t)buffer[i + 1] << 16)
+					| ((uint32_t)buffer[i + 2] << 8)
+					| ((uint32_t)buffer[i + 3]);
+
+			src <<= 2;
+
+			uint32_t dest;
+			if (is_encoder)
+				dest = now_pos + (uint32_t)(i) + src;
+			else
+				dest = src - (now_pos + (uint32_t)(i));
+
+			dest >>= 2;
+
+			dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF)
+					| (dest & 0x3FFFFF)
+					| 0x40000000;
+
+			buffer[i + 0] = (uint8_t)(dest >> 24);
+			buffer[i + 1] = (uint8_t)(dest >> 16);
+			buffer[i + 2] = (uint8_t)(dest >> 8);
+			buffer[i + 3] = (uint8_t)(dest);
+		}
+	}
+
+	return i;
+}
+
+
+static lzma_ret
+sparc_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters, bool is_encoder)
+{
+	return lzma_simple_coder_init(next, allocator, filters,
+			&sparc_code, 0, 4, 4, is_encoder);
+}
+
+
+extern lzma_ret
+lzma_simple_sparc_encoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters)
+{
+	return sparc_coder_init(next, allocator, filters, true);
+}
+
+
+extern lzma_ret
+lzma_simple_sparc_decoder_init(lzma_next_coder *next,
+		lzma_allocator *allocator, const lzma_filter_info *filters)
+{
+	return sparc_coder_init(next, allocator, filters, false);
+}
diff --git a/src/liblzma/simple/x86.c b/src/liblzma/simple/x86.c
new file mode 100644
index 0000000..5d1509b
--- /dev/null
+++ b/src/liblzma/simple/x86.c
@@ -0,0 +1,154 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       x86.c
+/// \brief      Filter for x86 binaries (BCJ filter)
+///
+//  Authors:    Igor Pavlov
+//              Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "simple_private.h"
+
+
+#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
+
+
+struct lzma_simple_s {
+	uint32_t prev_mask;
+	uint32_t prev_pos;
+};
+
+
+static size_t
+x86_code(lzma_simple *simple, uint32_t now_pos, bool is_encoder,
+		uint8_t *buffer, size_t size)
+{
+	static const bool MASK_TO_ALLOWED_STATUS[8]
+		= { true, true, true, false, true, false, false, false };
+
+	static const uint32_t MASK_TO_BIT_NUMBER[8]
+			= { 0, 1, 2, 2, 3, 3, 3, 3 };
+
+	uint32_t prev_mask = simple->prev_mask;
+	uint32_t prev_pos = simple->prev_pos;
+
+	if (size < 5)
+		return 0;
+
+	if (now_pos - prev_pos > 5)
+		prev_pos = now_pos - 5;
+
+	const size_t limit = size - 5;
+	size_t buffer_pos = 0;
+
+	while (buffer_pos <= limit) {
+		uint8_t b = buffer[buffer_pos];
+		if (b != 0xE8 && b != 0xE9) {
+			++buffer_pos;
+			continue;
+		}
+
+		const uint32_t offset = now_pos + (uint32_t)(buffer_pos)
+				- prev_pos;
+		prev_pos = now_pos + (uint32_t)(buffer_pos);
+
+		if (offset > 5) {
+			prev_mask = 0;
+		} else {
+			for (uint32_t i = 0; i < offset; ++i) {
+				prev_mask &= 0x77;
+				prev_mask <<= 1;
+			}
+		}
+
+		b = buffer[buffer_pos + 4];
+
+		if (Test86MSByte(b)
+			&& MASK_TO_ALLOWED_STATUS[(prev_mask >> 1) & 0x7]
+				&& (prev_mask >> 1) < 0x10) {
+
+			uint32_t src = ((uint32_t)(b) << 24)
+				| ((uint32_t)(buffer[buffer_pos + 3]) << 16)
+				| ((uint32_t)(buffer[buffer_pos + 2]) << 8)
+				| (buffer[buffer_pos + 1]);
+
+			uint32_t dest;
+			while (true) {
+				if (is_encoder)
+					dest = src + (now_pos + (uint32_t)(
+							buffer_pos) + 5);
+				else
+					dest = src - (now_pos + (uint32_t)(
+							buffer_pos) + 5);
+
+				if (prev_mask == 0)
+					break;
+
+				const uint32_t i = MASK_TO_BIT_NUMBER[
+						prev_mask >> 1];
+
+				b = (uint8_t)(dest >> (24 - i * 8));
+
+				if (!Test86MSByte(b))
+					break;
+
+				src = dest ^ ((1 << (32 - i * 8)) - 1);
+			}
+
+			buffer[buffer_pos + 4]
+					= (uint8_t)(~(((dest >> 24) & 1) - 1));
+			buffer[buffer_pos + 3] = (uint8_t)(dest >> 16);
+			buffer[buffer_pos + 2] = (uint8_t)(dest >> 8);
+			buffer[buffer_pos + 1] = (uint8_t)(dest);
+			buffer_pos += 5;
+			prev_mask = 0;
+
+		} else {
+			++buffer_pos;
+			prev_mask |= 1;
+			if (Test86MSByte(b))
+				prev_mask |= 0x10;
+		}
+	}
+
+	simple->prev_mask = prev_mask;
+	simple->prev_pos = prev_pos;
+
+	return buffer_pos;
+}
+
+
+static lzma_ret
+x86_coder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters, bool is_encoder)
+{
+	const lzma_ret ret = lzma_simple_coder_init(next, allocator, filters,
+			&x86_code, sizeof(lzma_simple), 5, 1, is_encoder);
+
+	if (ret == LZMA_OK) {
+		next->coder->simple->prev_mask = 0;
+		next->coder->simple->prev_pos = (uint32_t)(-5);
+	}
+
+	return ret;
+}
+
+
+extern lzma_ret
+lzma_simple_x86_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters)
+{
+	return x86_coder_init(next, allocator, filters, true);
+}
+
+
+extern lzma_ret
+lzma_simple_x86_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
+		const lzma_filter_info *filters)
+{
+	return x86_coder_init(next, allocator, filters, false);
+}
diff --git a/src/lzmainfo/Makefile.am b/src/lzmainfo/Makefile.am
new file mode 100644
index 0000000..cbc7e5c
--- /dev/null
+++ b/src/lzmainfo/Makefile.am
@@ -0,0 +1,32 @@
+##
+## Author: Lasse Collin
+##
+## This file has been put into the public domain.
+## You can do whatever you want with this file.
+##
+
+bin_PROGRAMS = lzmainfo
+
+lzmainfo_SOURCES = \
+	lzmainfo.c \
+	$(top_srcdir)/src/common/tuklib_progname.c \
+	$(top_srcdir)/src/common/tuklib_exit.c
+
+lzmainfo_CPPFLAGS = \
+	-DLOCALEDIR=\"$(localedir)\" \
+	-I$(top_srcdir)/src/common \
+	-I$(top_srcdir)/src/liblzma/api \
+	-I$(top_builddir)/lib \
+	$(DYNAMIC_CPPFLAGS)
+
+lzmainfo_LDFLAGS = $(DYNAMIC_LDFLAGS)
+lzmainfo_LDADD = $(top_builddir)/src/liblzma/liblzma.la
+
+if COND_GNULIB
+lzmainfo_LDADD += $(top_builddir)/lib/libgnu.a
+endif
+
+lzmainfo_LDADD += $(LTLIBINTL)
+
+
+dist_man_MANS = lzmainfo.1
diff --git a/src/lzmainfo/lzmainfo.1 b/src/lzmainfo/lzmainfo.1
new file mode 100644
index 0000000..ef736a6
--- /dev/null
+++ b/src/lzmainfo/lzmainfo.1
@@ -0,0 +1,55 @@
+.\"
+.\" Author: Lasse Collin
+.\"
+.\" 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"
+.SH NAME
+lzmainfo \- show infomation stored in the .lzma file header
+.SH SYNOPSIS
+.B lzmainfo
+.RB [ \-\-help ]
+.RB [ \-\-version ]
+.RI [ file ]...
+.SH DESCRIPTION
+.B lzmainfo
+shows information stored in the
+.B .lzma
+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
+.I files
+are given or
+.I file
+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
+.B .lzma
+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
+.TP
+.B 0
+All is good.
+.TP
+.B 1
+An error occurred.
+.SH BUGS
+.B lzmainfo
+uses
+.B MB
+while the correct suffix would be
+.B MiB
+(2^20 bytes).
+This is to keep the output compatible with LZMA Utils.
+.SH SEE ALSO
+.BR xz (1)
diff --git a/src/lzmainfo/lzmainfo.c b/src/lzmainfo/lzmainfo.c
new file mode 100644
index 0000000..af8e66c
--- /dev/null
+++ b/src/lzmainfo/lzmainfo.c
@@ -0,0 +1,210 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       lzmainfo.c
+/// \brief      lzmainfo tool for compatibility with LZMA Utils
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "sysdefs.h"
+#include <stdio.h>
+#include <errno.h>
+
+#include "lzma.h"
+#include "getopt.h"
+#include "tuklib_gettext.h"
+#include "tuklib_progname.h"
+#include "tuklib_exit.h"
+
+
+static void lzma_attribute((noreturn))
+help(void)
+{
+	printf(
+_("Usage: %s [--help] [--version] [FILE]...\n"
+"Show information stored in the .lzma file header"), progname);
+
+	printf(_(
+"\nWith no FILE, or when FILE is -, read standard input.\n"));
+	printf("\n");
+
+	printf(_("Report bugs to <%s> (in English or Finnish).\n"),
+			PACKAGE_BUGREPORT);
+	printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
+
+	tuklib_exit(EXIT_SUCCESS, EXIT_FAILURE, true);
+}
+
+
+static void lzma_attribute((noreturn))
+version(void)
+{
+	puts("lzmainfo (" PACKAGE_NAME ") " PACKAGE_VERSION);
+	tuklib_exit(EXIT_SUCCESS, EXIT_FAILURE, true);
+}
+
+
+/// Parse command line options.
+static void
+parse_args(int argc, char **argv)
+{
+	enum {
+		OPT_HELP,
+		OPT_VERSION,
+	};
+
+	static const struct option long_opts[] = {
+		{ "help",    no_argument, NULL, OPT_HELP },
+		{ "version", no_argument, NULL, OPT_VERSION },
+		{ NULL,      0,           NULL, 0 }
+	};
+
+	int c;
+	while ((c = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
+		switch (c) {
+		case OPT_HELP:
+			help();
+
+		case OPT_VERSION:
+			version();
+
+		default:
+			exit(EXIT_FAILURE);
+		}
+	}
+
+	return;
+}
+
+
+/// Primitive base-2 logarithm for integers
+static uint32_t
+my_log2(uint32_t n)
+{
+	uint32_t e;
+	for (e = 0; n > 1; ++e, n /= 2) ;
+	return e;
+}
+
+
+/// Parse the .lzma header and display information about it.
+static bool
+lzmainfo(const char *name, FILE *f)
+{
+	uint8_t buf[13];
+	const size_t size = fread(buf, 1, sizeof(buf), f);
+	if (size != 13) {
+		fprintf(stderr, "%s: %s: %s\n", progname, name,
+				ferror(f) ? strerror(errno)
+				: _("File is too small to be a .lzma file"));
+		return true;
+	}
+
+	lzma_filter filter = { .id = LZMA_FILTER_LZMA1 };
+
+	// Parse the first five bytes.
+	switch (lzma_properties_decode(&filter, NULL, buf, 5)) {
+	case LZMA_OK:
+		break;
+
+	case LZMA_OPTIONS_ERROR:
+		fprintf(stderr, "%s: %s: %s\n", progname, name,
+				_("Not a .lzma file"));
+		return true;
+
+	case LZMA_MEM_ERROR:
+		fprintf(stderr, "%s: %s\n", progname, strerror(ENOMEM));
+		exit(EXIT_FAILURE);
+
+	default:
+		fprintf(stderr, "%s: %s\n", progname,
+				_("Internal error (bug)"));
+		exit(EXIT_FAILURE);
+	}
+
+	// Uncompressed size
+	uint64_t uncompressed_size = 0;
+	for (size_t i = 0; i < 8; ++i)
+		uncompressed_size |= (uint64_t)(buf[5 + i]) << (i * 8);
+
+	// Display the results. We don't want to translate these and also
+	// will use MB instead of MiB, because someone could be parsing
+	// this output and we don't want to break that when people move
+	// from LZMA Utils to XZ Utils.
+	if (f != stdin)
+		printf("%s\n", name);
+
+	printf("Uncompressed size:             ");
+	if (uncompressed_size == UINT64_MAX)
+		printf("Unknown");
+	else
+		printf("%" PRIu64 " MB (%" PRIu64 " bytes)",
+				(uncompressed_size + 512 * 1024)
+					/ (1024 * 1024),
+				uncompressed_size);
+
+	lzma_options_lzma *opt = filter.options;
+
+	printf("\nDictionary size:               "
+			"%u MB (2^%u bytes)\n"
+			"Literal context bits (lc):     %" PRIu32 "\n"
+			"Literal pos bits (lp):         %" PRIu32 "\n"
+			"Number of pos bits (pb):       %" PRIu32 "\n",
+			(opt->dict_size + 512 * 1024) / (1024 * 1024),
+			my_log2(opt->dict_size), opt->lc, opt->lp, opt->pb);
+
+	free(opt);
+
+	return false;
+}
+
+
+extern int
+main(int argc, char **argv)
+{
+	tuklib_progname_init(argv);
+	tuklib_gettext_init(PACKAGE, LOCALEDIR);
+
+	parse_args(argc, argv);
+
+	int ret = EXIT_SUCCESS;
+
+	// We print empty lines around the output only when reading from
+	// files specified on the command line. This is due to how
+	// LZMA Utils did it.
+	if (optind == argc) {
+		if (lzmainfo("(stdin)", stdin))
+			ret = EXIT_FAILURE;
+	} else {
+		printf("\n");
+
+		do {
+			if (strcmp(argv[optind], "-") == 0) {
+				if (lzmainfo("(stdin)", stdin))
+					ret = EXIT_FAILURE;
+			} else {
+				FILE *f = fopen(argv[optind], "r");
+				if (f == NULL) {
+					ret = EXIT_FAILURE;
+					fprintf(stderr, "%s: %s: %s\n",
+							progname,
+							argv[optind],
+							strerror(errno));
+					continue;
+				}
+
+				if (lzmainfo(argv[optind], f))
+					ret = EXIT_FAILURE;
+
+				printf("\n");
+				fclose(f);
+			}
+		} while (++optind < argc);
+	}
+
+	tuklib_exit(ret, EXIT_FAILURE, true);
+}
diff --git a/src/scripts/Makefile.am b/src/scripts/Makefile.am
new file mode 100644
index 0000000..86f2738
--- /dev/null
+++ b/src/scripts/Makefile.am
@@ -0,0 +1,65 @@
+##
+## Author: Lasse Collin
+##
+## This file has been put into the public domain.
+## You can do whatever you want with this file.
+##
+
+nodist_bin_SCRIPTS = xzdiff xzgrep xzmore xzless
+dist_man_MANS = xzdiff.1 xzgrep.1 xzmore.1 xzless.1
+
+install-exec-hook:
+	cd $(DESTDIR)$(bindir) && \
+	target=`echo xzdiff | sed '$(transform)'` && \
+	for name in xzcmp lzdiff lzcmp; do \
+		link=`echo $$name | sed '$(transform)'` && \
+		rm -f $$link && \
+		$(LN_S) $$target $$link; \
+	done && \
+	target=`echo xzgrep | sed '$(transform)'` && \
+	for name in xzegrep xzfgrep lzgrep lzegrep lzfgrep; do \
+		link=`echo $$name | sed '$(transform)'` && \
+		rm -f $$link && \
+		$(LN_S) $$target $$link; \
+	done && \
+	for name in xzmore xzless; do \
+		target=`echo $$name | sed '$(transform)'` && \
+		link=`echo $$name | sed 's/xz/lz/;$(transform)'` && \
+		rm -f $$link && \
+		$(LN_S) $$target $$link; \
+	done
+
+install-data-hook:
+	cd $(DESTDIR)$(mandir)/man1 && \
+	target=`echo xzdiff | sed '$(transform)'` && \
+	for name in xzcmp lzdiff lzcmp; do \
+		link=`echo $$name | sed '$(transform)'` && \
+		rm -f $$link.1 && \
+		$(LN_S) $$target.1 $$link.1; \
+	done && \
+	target=`echo xzgrep | sed '$(transform)'` && \
+	for name in xzegrep xzfgrep lzgrep lzegrep lzfgrep; do \
+		link=`echo $$name | sed '$(transform)'` && \
+		rm -f $$link.1 && \
+		$(LN_S) $$target.1 $$link.1; \
+	done && \
+	for name in xzmore xzless; do \
+		target=`echo $$name | sed '$(transform)'` && \
+		link=`echo $$name | sed 's/xz/lz/;$(transform)'` && \
+		rm -f $$link.1 && \
+		$(LN_S) $$target.1 $$link.1; \
+	done
+
+uninstall-hook:
+	cd $(DESTDIR)$(bindir) && \
+	for name in xzcmp lzdiff lzcmp xzegrep xzfgrep \
+			lzgrep lzegrep lzfgrep lzmore lzless; do \
+		link=`echo $$name | sed '$(transform)'` && \
+		rm -f $$link; \
+	done
+	cd $(DESTDIR)$(mandir)/man1 && \
+	for name in xzcmp lzdiff lzcmp xzegrep xzfgrep \
+			lzgrep lzegrep lzfgrep lzmore lzless; do \
+		link=`echo $$name | sed '$(transform)'` && \
+		rm -f $$link.1; \
+	done
diff --git a/src/scripts/xzdiff.1 b/src/scripts/xzdiff.1
new file mode 100644
index 0000000..318d06f
--- /dev/null
+++ b/src/scripts/xzdiff.1
@@ -0,0 +1,74 @@
+.\"
+.\" Original zdiff.1 for gzip: Jean-loup Gailly
+.\"
+.\" Modifications for XZ Utils: Lasse Collin
+.\"                             Andrew Dudman
+.\"
+.\" License: GNU GPLv2+
+.\"
+.TH XZDIFF 1 "2009-07-05" "Tukaani" "XZ Utils"
+.SH NAME
+xzcmp, xzdiff, lzcmp, lzdiff \- compare compressed files
+.SH SYNOPSIS
+.B xzcmp
+.RI [ cmp_options "] " file1 " [" file2 ]
+.br
+.B xzdiff
+.RI [ diff_options "] " file1 " [" file2 ]
+.br
+.B lzcmp
+.RI [ cmp_options "] " file1 " [" file2 ]
+.br
+.B lzdiff
+.RI [ diff_options "] " file1 " [" file2 ]
+.SH DESCRIPTION
+.B  xzcmp
+and
+.B xzdiff
+invoke
+.BR cmp (1)
+or
+.BR diff (1)
+on files compressed with
+.BR xz (1),
+.BR lzma (1),
+.BR gzip (1),
+or
+.BR bzip2 (1).
+All options specified are passed directly to
+.B cmp
+or
+.BR diff .
+If only one file is specified, then the files compared are
+.I file1
+(which must have a suffix of a supported compression format) and
+.I file1
+from which the compression format suffix has been stripped.
+If two files are specified, then they are uncompressed if necessary and fed to
+.BR cmp (1)
+or
+.BR diff (1).
+The exit status from
+.B cmp
+or
+.B diff
+is preserved.
+.PP
+The names
+.B lzcmp
+and
+.B lzdiff
+are provided for backward compatibility with LZMA Utils.
+.SH "SEE ALSO"
+.BR cmp (1),
+.BR diff (1),
+.BR xz (1),
+.BR gzip (1),
+.BR bzip2 (1),
+.BR zdiff (1)
+.SH BUGS
+Messages from the
+.BR cmp (1)
+or
+.BR diff (1)
+programs refer to temporary filenames instead of those specified.
diff --git a/src/scripts/xzdiff.in b/src/scripts/xzdiff.in
new file mode 100644
index 0000000..2d6e5da
--- /dev/null
+++ b/src/scripts/xzdiff.in
@@ -0,0 +1,172 @@
+#!@POSIX_SHELL@
+
+# Copyright (C) 1998, 2002, 2006, 2007 Free Software Foundation
+# Copyright (C) 1993 Jean-loup Gailly
+
+# Modified for XZ Utils by Andrew Dudman and Lasse Collin.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+#SET_PATH - This line is a placeholder to ease patching this script.
+
+# Instead of unsetting XZ_OPT, just make sure that xz will use file format
+# autodetection. This way memory usage limit and thread limit can be
+# specified via XZ_OPT. With gzip and bzip2 it's OK to just unset the
+# environment variables.
+xz='@xz@ --format=auto'
+unset GZIP BZIP BZIP2
+
+case ${0##*/} in
+  *cmp*) prog=xzcmp; cmp=${CMP:-cmp};;
+  *)     prog=xzdiff; cmp=${DIFF:-diff};;
+esac
+
+version="$prog (@PACKAGE_NAME@) @VERSION@"
+
+usage="Usage: ${0##*/} [OPTION]... FILE1 [FILE2]
+Compare FILE1 to FILE2, using their uncompressed contents if they are
+compressed.  If FILE2 is omitted, then the files compared are FILE1 and
+FILE1 from which the compression format suffix has been stripped.
+
+Do comparisons like '$cmp' does.  OPTIONs are the same as for '$cmp'.
+
+Report bugs to <@PACKAGE_BUGREPORT@>."
+
+# sed script to escape all ' for the shell, and then (to handle trailing
+# newlines correctly) turn trailing X on last line into '.
+escape='
+  s/'\''/'\''\\'\'''\''/g
+  $s/X$/'\''/
+'
+
+while :; do
+  case $1 in
+    --h*) printf '%s\n' "$usage" || exit 2; exit;;
+    --v*) echo "$version" || exit 2; exit;;
+    --) shift; break;;
+    -*\'*) cmp="$cmp '"`printf '%sX\n' "$1" | sed "$escape"`;;
+    -?*) cmp="$cmp '$1'";;
+    *) break;;
+  esac
+  shift
+done
+cmp="$cmp --"
+
+for file; do
+  test "X$file" = X- || <"$file" || exit 2
+done
+
+xz1=$xz
+xz2=$xz
+xz_status=0
+exec 3>&1
+
+if test $# -eq 1; then
+  case $1 in
+    *[-.]xz | *[-.]lzma | *.t[lx]z)
+      ;;
+    *[-.]bz2 | *.tbz | *.tbz2)
+      xz1=$bzip2;;
+    *[-.][zZ] | *_z | *[-.]gz | *.t[ag]z)
+      xz1=$gzip;;
+    *)
+      echo >&2 "$0: $1: Unknown compressed file name suffix"
+      exit 2;;
+  esac
+  case $1 in
+    *[-.][zZ] | *_z | *[-.][gx]z | *[-.]bz2 | *[-.]lzma)
+      FILE=`expr "X$1" : 'X\(.*\)[-.][abglmxzZ2]*$'`;;
+    *.t[abglx]z)
+      FILE=`expr "X$1" : 'X\(.*[-.]t\)[abglx]z$'`ar;;
+    *.tbz2)
+      FILE=`expr "X$1" : 'X\(.*[-.]t\)bz2$'`ar;;
+  esac
+  xz_status=$(
+    exec 4>&1
+    ($xz1 -cd -- "$1" 4>&-; echo $? >&4) 3>&- | eval "$cmp" - '"$FILE"' >&3
+  )
+elif test $# -eq 2; then
+  case $1 in
+    *[-.]bz2 | *.tbz | *.tbz2) xz1=$bzip2;;
+    *[-.][zZ] | *_z | *[-.]gz | *.t[ag]z) xz1=$gzip;;
+  esac
+  case $2 in
+    *[-.]bz2 | *.tbz | *.tbz2) xz2=$bzip2;;
+    *[-.][zZ] | *_z | *[-.]gz | *.t[ag]z) xz2=$gzip;;
+  esac
+  case $1 in
+    *[-.][zZ] | *_z | *[-.][gx]z | *[-.]bz2 | *[-.]lzma | *.t[abglx]z | *.tbz2 | -)
+      case "$2" in
+        *[-.][zZ] | *_z | *[-.][gx]z | *[-.]bz2 | *[-.]lzma | *.t[abglx]z | *.tbz2 | -)
+          if test "$1$2" = --; then
+            xz_status=$(
+              exec 4>&1
+              ($xz1 -cdfq - 4>&-; echo $? >&4) 3>&- |
+                eval "$cmp" - - >&3
+            )
+          elif # Reject Solaris 8's buggy /bin/bash 2.03.
+              echo X | (echo X | eval "$cmp" /dev/fd/5 - >/dev/null 2>&1) 5<&0; then
+            xz_status=$(
+              exec 4>&1
+              ($xz1 -cdfq -- "$1" 4>&-; echo $? >&4) 3>&- |
+                ( ($xz2 -cdfq -- "$2" 4>&-; echo $? >&4) 3>&- 5<&- </dev/null |
+                eval "$cmp" /dev/fd/5 - >&3) 5<&0
+            )
+            case $xz_status in
+              *[1-9]*) xz_status=1;;
+              *) xz_status=0;;
+            esac
+          else
+            F=`expr "/$2" : '.*/\(.*\)[-.][ablmtxz2]*$'` || F=$prog
+            tmp=
+            trap '
+              test -n "$tmp" && rm -f "$tmp"
+              (exit 2); exit 2
+            ' HUP INT PIPE TERM 0
+            tmp=`mktemp -t -- "$F.XXXXXX"` || exit 2
+            $xz2 -cdfq -- "$2" > "$tmp" || exit 2
+            xz_status=$(
+              exec 4>&1
+              ($xz1 -cdfq -- "$1" 4>&-; echo $? >&4) 3>&- |
+                eval "$cmp" - '"$tmp"' >&3
+            )
+            cmp_status=$?
+            rm -f "$tmp" || xz_status=$?
+            trap - HUP INT PIPE TERM 0
+            (exit $cmp_status)
+          fi;;
+      *)
+        xz_status=$(
+          exec 4>&1
+          ($xz1 -cdfq -- "$1" 4>&-; echo $? >&4) 3>&- |
+            eval "$cmp" - '"$2"' >&3
+        );;
+    esac;;
+  *)
+    case "$2" in
+      *[-.][zZ] | *_z | *[-.][gx]z | *[-.]bz2 | *[-.]lzma | *.t[abglx]z | *.tbz2 | -)
+        xz_status=$(
+          exec 4>&1
+          ($xz2 -cdfq -- "$2" 4>&-; echo $? >&4) 3>&- |
+            eval "$cmp" '"$1"' - >&3
+         );;
+      *)
+        eval "$cmp" '"$1"' '"$2"';;
+    esac;;
+  esac
+else
+  echo >&2 "$0: Invalid number of operands; try \`${0##*/} --help' for help"
+  exit 2
+fi
+
+cmp_status=$?
+test "$xz_status" -eq 0 || exit 2
+exit $cmp_status
diff --git a/src/scripts/xzgrep.1 b/src/scripts/xzgrep.1
new file mode 100644
index 0000000..996d64a
--- /dev/null
+++ b/src/scripts/xzgrep.1
@@ -0,0 +1,94 @@
+.\"
+.\" Original zgrep.1 for gzip: Jean-loup Gailly
+.\"                            Charles Levert <charles@comm.polymtl.ca>
+.\"
+.\" Modifications for XZ Utils: Lasse Collin
+.\"
+.\" License: GNU GPLv2+
+.\"
+.TH XZGREP 1 "2009-07-05" "Tukaani" "XZ Utils"
+.SH NAME
+xzgrep \- search compressed files for a regular expression
+.SH SYNOPSIS
+.B xzgrep
+.RI [ grep_options ]
+.RB  [ \-e ]
+.I pattern
+.IR file ".\|.\|."
+.br
+.B xzegrep
+.RB ...
+.br
+.B xzfgrep
+.RB ...
+.br
+.B lzgrep
+.RB ...
+.br
+.B lzegrep
+.RB ...
+.br
+.B lzfgrep
+.RB ...
+.SH DESCRIPTION
+.B  xzgrep
+invokes
+.BR grep (1)
+on
+.I files
+which may be either uncompressed or compressed with
+.BR xz (1),
+.BR lzma (1),
+.BR gzip (1),
+or
+.BR bzip2 (1).
+All options specified are passed directly to
+.BR grep (1).
+.PP
+If no
+.I file
+is specified, then the standard input is decompressed if necessary and fed to
+.BR grep (1).
+When reading from standard input,
+.BR gzip (1)
+and
+.BR bzip2 (1)
+compressed files are not supported.
+.PP
+If
+.B xzgrep
+is invoked as
+.B xzegrep
+or
+.B xzfgrep
+then
+.BR egrep (1)
+or
+.BR fgrep (1)
+is used instead of
+.BR grep (1).
+The same applies to names
+.BR lzgrep ,
+.BR lzegrep ,
+and
+.BR lzfgrep ,
+which are provided for backward compatibility with LZMA Utils.
+.PP
+.SH ENVIRONMENT
+.TP
+.B GREP
+If the
+.B GREP
+environment variable is set,
+.B xzgrep
+uses it instead of
+.BR grep (1),
+.BR egrep (1),
+or
+.BR fgrep (1).
+.SH "SEE ALSO"
+.BR grep (1),
+.BR xz (1),
+.BR gzip (1),
+.BR bzip2 (1),
+.BR zgrep (1)
diff --git a/src/scripts/xzgrep.in b/src/scripts/xzgrep.in
new file mode 100644
index 0000000..bfa9fb5
--- /dev/null
+++ b/src/scripts/xzgrep.in
@@ -0,0 +1,196 @@
+#!@POSIX_SHELL@
+
+# xzgrep -- a wrapper around a grep program that decompresses files as needed
+# Adapted from a version sent by Charles Levert <charles@comm.polymtl.ca>
+
+# Copyright (C) 1998, 2001, 2002, 2006, 2007 Free Software Foundation
+# Copyright (C) 1993 Jean-loup Gailly
+
+# Modified for XZ Utils by Andrew Dudman and Lasse Collin.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+#SET_PATH - This line is a placeholder to ease patching this script.
+
+# Instead of unsetting XZ_OPT, just make sure that xz will use file format
+# autodetection. This way memory usage limit and thread limit can be
+# specified via XZ_OPT. With gzip and bzip2 it's OK to just unset the
+# environment variables.
+xz='@xz@ --format=auto'
+unset GZIP BZIP BZIP2
+
+case ${0##/*} in
+  *egrep*) prog=xzegrep; grep=${GREP:-egrep};;
+  *fgrep*) prog=xzfgrep; grep=${GREP:-fgrep};;
+  *)       prog=xzgrep; grep=${GREP:-grep};;
+esac
+
+version="$prog (@PACKAGE_NAME@) @VERSION@"
+
+usage="Usage: ${0##/*} [OPTION]... [-e] PATTERN [FILE]...
+Look for instances of PATTERN in the input FILEs, using their
+uncompressed contents if they are compressed.
+
+OPTIONs are the same as for '$grep'.
+
+Report bugs to <@PACKAGE_BUGREPORT@>."
+
+# sed script to escape all ' for the shell, and then (to handle trailing
+# newlines correctly) turn trailing X on last line into '.
+escape='
+  s/'\''/'\''\\'\'''\''/g
+  $s/X$/'\''/
+'
+operands=
+have_pat=0
+files_with_matches=0
+files_without_matches=0
+no_filename=0
+with_filename=0
+
+while test $# -ne 0; do
+  option=$1
+  shift
+  optarg=
+
+  case $option in
+  (-[0123456789abcdhHiIKLlnoqrRsTuUvVwxyzZ]?*)
+    arg2=-\'$(expr "X${option}X" : 'X-.[0-9]*\(.*\)' | sed "$escape")
+    eval "set -- $arg2 "'${1+"$@"}'
+    option=$(expr "X$option" : 'X\(-.[0-9]*\)');;
+  (--binary-*=* | --[lm]a*=* | --reg*=*)
+    ;;
+  (-[ABCDefm] | --binary-* | --file | --[lm]a* | --reg*)
+    case ${1?"$option option requires an argument"} in
+    (*\'*)
+      optarg=" '"$(printf '%sX\n' "$1" | sed "$escape");;
+    (*)
+      optarg=" '$1'";;
+    esac
+    shift;;
+  (--)
+    break;;
+  (-?*)
+    ;;
+  (*)
+    case $option in
+    (*\'*)
+      operands="$operands '"$(printf '%sX\n' "$option" | sed "$escape");;
+    (*)
+      operands="$operands '$option'";;
+    esac
+    ${POSIXLY_CORRECT+break}
+    continue;;
+  esac
+
+  case $option in
+  (-[drRzZ] | --di* | --exc* | --inc* | --rec* | --nu*)
+    printf >&2 '%s: %s: Option not supported\n' "$0" "$option"
+    exit 2;;
+  (-[ef]* | --file | --file=* | --reg*)
+    have_pat=1;;
+  (--h | --he | --hel | --help)
+    echo "$usage" || exit 2
+    exit;;
+  (-H | --wi | --wit | --with | --with- | --with-f | --with-fi \
+  | --with-fil | --with-file | --with-filen | --with-filena | --with-filenam \
+  | --with-filename)
+    with_filename=1
+    continue;;
+  (-l | --files-with-*)
+    files_with_matches=1;;
+  (-L | --files-witho*)
+    files_without_matches=1;;
+  (--no-f*)
+    no_filename=1;;
+  (-V | --v | --ve | --ver | --vers | --versi | --versio | --version)
+    echo "$version" || exit 2
+    exit;;
+  esac
+
+  case $option in
+  (*\'?*)
+    option=\'$(expr "X${option}X" : 'X\(.*\)' | sed "$escape");;
+  (*)
+    option="'$option'";;
+  esac
+
+  grep="$grep $option$optarg"
+done
+
+eval "set -- $operands "'${1+"$@"}'
+
+if test $have_pat -eq 0; then
+  case ${1?"Missing pattern; try \`${0##*/} --help' for help"} in
+  (*\'*)
+    grep="$grep -- '"$(printf '%sX\n' "$1" | sed "$escape");;
+  (*)
+    grep="$grep -- '$1'";;
+  esac
+  shift
+fi
+
+if test $# -eq 0; then
+  set -- -
+fi
+
+exec 3>&1
+res=0
+
+for i; do
+  case $i in
+    *[-.][zZ] | *_z | *[-.]gz | *.t[ag]z) uncompress="gzip -cdfq";;
+    *[-.]bz2 | *[-.]tbz | *.tbz2) uncompress="bzip2 -cdfq";;
+    *) uncompress="$xz -cdfq";;
+  esac
+  # Fail if xz or grep (or sed) fails.
+  xz_status=$(
+    exec 5>&1
+    ($uncompress -- "$i" 5>&-; echo $? >&5) 3>&- |
+    if test $files_with_matches -eq 1; then
+      eval "$grep" -q && { printf '%s\n' "$i" || exit 2; }
+    elif test $files_without_matches -eq 1; then
+      eval "$grep" -q || {
+        r=$?
+        if test $r -eq 1; then
+          printf '%s\n' "$i" || r=2
+        fi
+        exit $r
+      }
+    elif test $with_filename -eq 0 &&
+         { test $# -eq 1 || test $no_filename -eq 1; }; then
+      eval "$grep"
+    else
+      case $i in
+      (*'
+'* | *'&'* | *'\'* | *'|'*)
+        i=$(printf '%s\n' "$i" |
+            sed '
+              $!N
+              $s/[&\|]/\\&/g
+              $s/\n/\\n/g
+            ');;
+      esac
+      sed_script="s|^|$i:|"
+
+      # Fail if grep or sed fails.
+      r=$(
+        exec 4>&1
+        (eval "$grep" 4>&-; echo $? >&4) 3>&- | sed "$sed_script" >&3 4>&-
+      ) || r=2
+      exit $r
+    fi >&3 5>&-
+  )
+  r=$?
+  test "$xz_status" -eq 0 || test "$xz_status" -eq 2 || r=2
+  test $res -lt $r && res=$r
+done
+exit $res
diff --git a/src/scripts/xzless.1 b/src/scripts/xzless.1
new file mode 100644
index 0000000..299806f
--- /dev/null
+++ b/src/scripts/xzless.1
@@ -0,0 +1,66 @@
+.\"
+.\" Authors: Andrew Dudman
+.\"          Lasse Collin
+.\"
+.\" This file has been put into the public domain.
+.\" You can do whatever you want with this file.
+.\"
+.\" (Note that this file is not based on gzip's zless.1.)
+.\"
+.TH XZLESS 1 "2009-07-05" "Tukaani" "XZ Utils"
+.SH NAME
+xzless, lzless \- view xz or lzma compressed (text) files
+.SH SYNOPSIS
+.B xzless
+.RI [ file ...]
+.br
+.B lzless
+.RI [ file ...]
+.SH DESCRIPTION
+.B  xzless
+is a filter that displays text from compressed files to a terminal.
+It works on files compressed with
+.BR xz (1)
+or
+.BR lzma (1).
+If no
+.I files
+are given,
+.B xzless
+reads from standard input.
+.PP
+.B xzless
+uses
+.BR less (1)
+to present its output.  Unlike
+.BR xzmore ,
+its choice of pager cannot be altered by setting an environment variable.
+Commands are based on both
+.BR more (1)
+and
+.BR vi (1)
+and allow back and forth movement and searching.
+See the
+.BR less (1)
+manual for more information.
+.PP
+The command named
+.B lzless
+is provided for backward compatibility with LZMA Utils.
+.SH ENVIRONMENT
+.TP
+.B LESSMETACHARS
+A list of characters special to the shell.  Set by
+.B xzless
+unless it is already set in the environment.
+.TP
+.B LESSOPEN
+Set to a command line to invoke the
+.BR xz (1)
+decompressor for preprocessing the input files to
+.BR less (1).
+.SH "SEE ALSO"
+.BR less (1),
+.BR xz (1),
+.BR xzmore (1),
+.BR zless (1)
diff --git a/src/scripts/xzless.in b/src/scripts/xzless.in
new file mode 100644
index 0000000..a3da697
--- /dev/null
+++ b/src/scripts/xzless.in
@@ -0,0 +1,58 @@
+#!@POSIX_SHELL@
+
+# Copyright (C) 1998, 2002, 2006, 2007 Free Software Foundation
+
+# The original version for gzip was written by Paul Eggert.
+# Modified for XZ Utils by Andrew Dudman and Lasse Collin.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+#SET_PATH - This line is a placeholder to ease patching this script.
+
+# Instead of unsetting XZ_OPT, just make sure that xz will use file format
+# autodetection. This way memory usage limit and thread limit can be
+# specified via XZ_OPT.
+xz='@xz@ --format=auto'
+
+version='xzless (@PACKAGE_NAME@) @VERSION@'
+
+usage="Usage: ${0##*/} [OPTION]... [FILE]...
+Like 'less', but operate on the uncompressed contents of xz compressed FILEs.
+
+Options are the same as for 'less'.
+
+Report bugs to <@PACKAGE_BUGREPORT@>."
+
+case $1 in
+	--help)    echo "$usage" || exit 2; exit;;
+	--version) echo "$version" || exit 2; exit;;
+esac
+
+if test "${LESSMETACHARS+set}" != set; then
+	# Work around a bug in less 394 and earlier;
+	# it mishandles the metacharacters '$%=~'.
+	space=' '
+	tab='	'
+	nl='
+'
+	LESSMETACHARS="$space$tab$nl'"';*?"()<>[|&^`#\$%=~'
+fi
+
+if test "$(less -V | { read ver && echo ${ver#less }; })" -ge 429; then
+	# less 429 or later: LESSOPEN pipe will be used on
+	# standard input if $LESSOPEN begins with |-.
+	LESSOPEN="|-$xz -cdfq -- %s"
+else
+	LESSOPEN="|$xz -cdfq -- %s"
+fi
+export LESSMETACHARS LESSOPEN
+
+exec less "$@"
diff --git a/src/scripts/xzmore.1 b/src/scripts/xzmore.1
new file mode 100644
index 0000000..42542bf
--- /dev/null
+++ b/src/scripts/xzmore.1
@@ -0,0 +1,54 @@
+.\"
+.\" Original zdiff.1 for gzip: Jean-loup Gailly
+.\" Modifications for XZ Utils: Lasse Collin
+.\"
+.\" License: GNU GPLv2+
+.\"
+.TH XZMORE 1 "2009-07-05" "Tukaani" "XZ Utils"
+.SH NAME
+xzmore, lzmore \- view xz or lzma compressed (text) files
+.SH SYNOPSIS
+.B xzmore
+.RI [ "filename ..."  ]
+.br
+.B lzmore
+.RI [ "filename ..."  ]
+.SH DESCRIPTION
+.B  xzmore
+is a filter which allows examination of
+.BR xz (1)
+or
+.BR lzma (1)
+compressed text files one screenful at a time on a soft-copy terminal.
+.PP
+To use a pager other than the default
+.B more,
+set environment variable
+.B PAGER
+to the name of the desired program.
+The name
+.B lzmore
+is provided for backward compatibility with LZMA Utils.
+.TP
+.BR e " or " q
+When the prompt \-\-More\-\-(Next file:
+.IR file )
+is printed, this command causes
+.B xzmore
+to exit.
+.TP
+.B s
+When the prompt \-\-More\-\-(Next file:
+.IR file )
+is printed, this command causes
+.B xzmore
+to skip the next file and continue.
+.PP
+For list of keyboard commands supported while actually viewing the
+content of a file, refer to manual of the pager you use, usually
+.BR more (1).
+.SH "SEE ALSO"
+.BR more (1),
+.BR xz (1),
+.BR xzless (1),
+.BR zmore (1)
diff --git a/src/scripts/xzmore.in b/src/scripts/xzmore.in
new file mode 100644
index 0000000..940d661
--- /dev/null
+++ b/src/scripts/xzmore.in
@@ -0,0 +1,78 @@
+#!@POSIX_SHELL@
+
+# Copyright (C) 2001, 2002, 2007 Free Software Foundation
+# Copyright (C) 1992, 1993 Jean-loup Gailly
+
+# Modified for XZ Utils by Andrew Dudman and Lasse Collin.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+#SET_PATH - This line is a placeholder to ease patching this script.
+
+# Instead of unsetting XZ_OPT, just make sure that xz will use file format
+# autodetection. This way memory usage limit and thread limit can be
+# specified via XZ_OPT.
+xz='@xz@ --format=auto'
+
+version='xzmore (@PACKAGE_NAME@) @VERSION@'
+
+usage="Usage: ${0##*/} [OPTION]... [FILE]...
+Like 'more', but operate on the uncompressed contents of xz compressed FILEs.
+
+Report bugs to <@PACKAGE_BUGREPORT@>."
+
+case $1 in
+	--help)    echo "$usage" || exit 2; exit;;
+	--version) echo "$version" || exit 2; exit;;
+esac
+
+oldtty=`stty -g 2>/dev/null`
+if stty -cbreak 2>/dev/null; then
+	cb='cbreak'; ncb='-cbreak'
+else
+	# 'stty min 1' resets eof to ^a on both SunOS and SysV!
+	cb='min 1 -icanon'; ncb='icanon eof ^d'
+fi
+if test $? -eq 0 && test -n "$oldtty"; then
+	trap 'stty $oldtty 2>/dev/null; exit' 0 2 3 5 10 13 15
+else
+	trap 'stty $ncb echo 2>/dev/null; exit' 0 2 3 5 10 13 15
+fi
+
+if test $# = 0; then
+	if test -t 0; then
+		echo "$usage"; exit 1
+	else
+		$xz -cdfq | eval "${PAGER:-more}"
+	fi
+else
+	FIRST=1
+	for FILE; do
+		< "$FILE" || continue
+		if test $FIRST -eq 0; then
+			printf "%s--More--(Next file: %s)" "" "$FILE"
+			stty $cb -echo 2>/dev/null
+			ANS=`dd bs=1 count=1 2>/dev/null`
+			stty $ncb echo 2>/dev/null
+			echo " "
+			case "$ANS" in
+				[eq]) exit;;
+			esac
+		fi
+		if test "$ANS" != 's'; then
+			echo "------> $FILE <------"
+			$xz -cdfq -- "$FILE" | eval "${PAGER:-more}"
+		fi
+		if test -t 1; then
+			FIRST=0
+		fi
+	done
+fi
diff --git a/src/xz/Makefile.am b/src/xz/Makefile.am
new file mode 100644
index 0000000..4dbe0f2
--- /dev/null
+++ b/src/xz/Makefile.am
@@ -0,0 +1,102 @@
+##
+## Author: Lasse Collin
+##
+## This file has been put into the public domain.
+## You can do whatever you want with this file.
+##
+
+bin_PROGRAMS = xz
+
+xz_SOURCES = \
+	args.c \
+	args.h \
+	coder.c \
+	coder.h \
+	file_io.c \
+	file_io.h \
+	hardware.c \
+	hardware.h \
+	list.c \
+	list.h \
+	main.c \
+	main.h \
+	message.c \
+	message.h \
+	options.c \
+	options.h \
+	private.h \
+	signals.c \
+	signals.h \
+	suffix.c \
+	suffix.h \
+	util.c \
+	util.h \
+	$(top_srcdir)/src/common/tuklib_open_stdxxx.c \
+	$(top_srcdir)/src/common/tuklib_progname.c \
+	$(top_srcdir)/src/common/tuklib_exit.c \
+	$(top_srcdir)/src/common/tuklib_cpucores.c
+
+if COND_W32
+xz_SOURCES += xz_w32res.rc
+endif
+
+xz_CPPFLAGS = \
+	-DLOCALEDIR=\"$(localedir)\" \
+	-I$(top_srcdir)/src/common \
+	-I$(top_srcdir)/src/liblzma/api \
+	-I$(top_builddir)/lib \
+	$(STATIC_CPPFLAGS)
+
+xz_LDFLAGS = $(STATIC_LDFLAGS)
+xz_LDADD = $(top_builddir)/src/liblzma/liblzma.la
+
+if COND_GNULIB
+xz_LDADD += $(top_builddir)/lib/libgnu.a
+endif
+
+# libgnu.a may need these libs, so this must be after libgnu.a.
+xz_LDADD += $(LTLIBINTL)
+
+
+# Windows resource compiler support
+.rc.o:
+	$(RC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+		$(xz_CPPFLAGS) $(CPPFLAGS) $(RCFLAGS) -i $< -o $@
+
+
+dist_man_MANS = xz.1
+
+
+## Create symlinks for unxz and xzcat for convenience. Create symlinks also
+## for lzma, unlzma, and lzcat for compatibility with LZMA Utils 4.32.x.
+xzlinks = unxz xzcat lzma unlzma lzcat
+
+install-exec-hook:
+	cd $(DESTDIR)$(bindir) && \
+	target=`echo xz | sed '$(transform)'`$(EXEEXT) && \
+	for name in $(xzlinks); do \
+		link=`echo $$name | sed '$(transform)'`$(LN_EXEEXT) && \
+		rm -f $$link && \
+		$(LN_S) $$target $$link; \
+	done
+
+install-data-hook:
+	cd $(DESTDIR)$(mandir)/man1 && \
+	target=`echo xz | sed '$(transform)'` && \
+	for name in $(xzlinks); do \
+		link=`echo $$name | sed '$(transform)'` && \
+		rm -f $$link.1 && \
+		$(LN_S) $$target.1 $$link.1; \
+	done
+
+uninstall-hook:
+	cd $(DESTDIR)$(bindir) && \
+	for name in $(xzlinks); do \
+		link=`echo $$name | sed '$(transform)'`$(LN_EXEEXT) && \
+		rm -f $$link; \
+	done
+	cd $(DESTDIR)$(mandir)/man1 && \
+	for name in $(xzlinks); do \
+		link=`echo $$name | sed '$(transform)'` && \
+		rm -f $$link.1; \
+	done
diff --git a/src/xz/args.c b/src/xz/args.c
new file mode 100644
index 0000000..be26bf3
--- /dev/null
+++ b/src/xz/args.c
@@ -0,0 +1,549 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       args.c
+/// \brief      Argument parsing
+///
+/// \note       Filter-specific options parsing is in options.c.
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "private.h"
+
+#include "getopt.h"
+#include <ctype.h>
+
+
+bool opt_stdout = false;
+bool opt_force = false;
+bool opt_keep_original = false;
+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)";
+
+
+static void
+parse_real(args_info *args, int argc, char **argv)
+{
+	enum {
+		OPT_X86 = INT_MIN,
+		OPT_POWERPC,
+		OPT_IA64,
+		OPT_ARM,
+		OPT_ARMTHUMB,
+		OPT_SPARC,
+		OPT_DELTA,
+		OPT_LZMA1,
+		OPT_LZMA2,
+
+		OPT_NO_SPARSE,
+		OPT_FILES,
+		OPT_FILES0,
+		OPT_NO_ADJUST,
+		OPT_INFO_MEMORY,
+		OPT_ROBOT,
+	};
+
+	static const char short_opts[]
+			= "cC:defF:hHlkM:qQrS:tT:vVz0123456789";
+
+	static const struct option long_opts[] = {
+		// Operation mode
+		{ "compress",     no_argument,       NULL,  'z' },
+		{ "decompress",   no_argument,       NULL,  'd' },
+		{ "uncompress",   no_argument,       NULL,  'd' },
+		{ "test",         no_argument,       NULL,  't' },
+		{ "list",         no_argument,       NULL,  'l' },
+
+		// Operation modifiers
+		{ "keep",         no_argument,       NULL,  'k' },
+		{ "force",        no_argument,       NULL,  'f' },
+		{ "stdout",       no_argument,       NULL,  'c' },
+		{ "to-stdout",    no_argument,       NULL,  'c' },
+		{ "no-sparse",    no_argument,       NULL,  OPT_NO_SPARSE },
+		{ "suffix",       required_argument, NULL,  'S' },
+		// { "recursive",      no_argument,       NULL,  'r' }, // TODO
+		{ "files",        optional_argument, NULL,  OPT_FILES },
+		{ "files0",       optional_argument, NULL,  OPT_FILES0 },
+
+		// Basic compression settings
+		{ "format",       required_argument, NULL,  'F' },
+		{ "check",        required_argument, NULL,  'C' },
+		{ "no-adjust",    no_argument,       NULL,  OPT_NO_ADJUST },
+		{ "memory",       required_argument, NULL,  'M' },
+		{ "threads",      required_argument, NULL,  'T' },
+
+		{ "extreme",      no_argument,       NULL,  'e' },
+		{ "fast",         no_argument,       NULL,  '0' },
+		{ "best",         no_argument,       NULL,  '9' },
+
+		// Filters
+		{ "lzma1",        optional_argument, NULL,  OPT_LZMA1 },
+		{ "lzma2",        optional_argument, NULL,  OPT_LZMA2 },
+		{ "x86",          optional_argument, NULL,  OPT_X86 },
+		{ "powerpc",      optional_argument, NULL,  OPT_POWERPC },
+		{ "ia64",         optional_argument, NULL,  OPT_IA64 },
+		{ "arm",          optional_argument, NULL,  OPT_ARM },
+		{ "armthumb",     optional_argument, NULL,  OPT_ARMTHUMB },
+		{ "sparc",        optional_argument, NULL,  OPT_SPARC },
+		{ "delta",        optional_argument, NULL,  OPT_DELTA },
+
+		// Other options
+		{ "quiet",        no_argument,       NULL,  'q' },
+		{ "verbose",      no_argument,       NULL,  'v' },
+		{ "no-warn",      no_argument,       NULL,  'Q' },
+		{ "robot",        no_argument,       NULL,  OPT_ROBOT },
+		{ "info-memory",  no_argument,       NULL,  OPT_INFO_MEMORY },
+		{ "help",         no_argument,       NULL,  'h' },
+		{ "long-help",    no_argument,       NULL,  'H' },
+		{ "version",      no_argument,       NULL,  'V' },
+
+		{ NULL,                 0,                 NULL,   0 }
+	};
+
+	int c;
+
+	while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL))
+			!= -1) {
+		switch (c) {
+		// Compression preset (also for decompression if --format=raw)
+		case '0': case '1': case '2': case '3': case '4':
+		case '5': case '6': case '7': case '8': case '9':
+			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));
+			}
+
+			break;
+		}
+
+		// --suffix
+		case 'S':
+			suffix_set(optarg);
+			break;
+
+		case 'T':
+			hardware_threadlimit_set(str_to_uint64(
+					"threads", optarg, 0, UINT32_MAX));
+			break;
+
+		// --version
+		case 'V':
+			// This doesn't return.
+			message_version();
+
+		// --stdout
+		case 'c':
+			opt_stdout = true;
+			break;
+
+		// --decompress
+		case 'd':
+			opt_mode = MODE_DECOMPRESS;
+			break;
+
+		// --extreme
+		case 'e':
+			coder_set_extreme();
+			break;
+
+		// --force
+		case 'f':
+			opt_force = true;
+			break;
+
+		// --info-memory
+		case OPT_INFO_MEMORY:
+			// This doesn't return.
+			message_memlimit();
+
+		// --help
+		case 'h':
+			// This doesn't return.
+			message_help(false);
+
+		// --long-help
+		case 'H':
+			// This doesn't return.
+			message_help(true);
+
+		// --list
+		case 'l':
+			opt_mode = MODE_LIST;
+			break;
+
+		// --keep
+		case 'k':
+			opt_keep_original = true;
+			break;
+
+		// --quiet
+		case 'q':
+			message_verbosity_decrease();
+			break;
+
+		case 'Q':
+			set_exit_no_warn();
+			break;
+
+		case 't':
+			opt_mode = MODE_TEST;
+			break;
+
+		// --verbose
+		case 'v':
+			message_verbosity_increase();
+			break;
+
+		// --robot
+		case OPT_ROBOT:
+			opt_robot = true;
+
+			// This is to make sure that floating point numbers
+			// always have a dot as decimal separator.
+			setlocale(LC_NUMERIC, "C");
+			break;
+
+		case 'z':
+			opt_mode = MODE_COMPRESS;
+			break;
+
+		// Filter setup
+
+		case OPT_X86:
+			coder_add_filter(LZMA_FILTER_X86,
+					options_bcj(optarg));
+			break;
+
+		case OPT_POWERPC:
+			coder_add_filter(LZMA_FILTER_POWERPC,
+					options_bcj(optarg));
+			break;
+
+		case OPT_IA64:
+			coder_add_filter(LZMA_FILTER_IA64,
+					options_bcj(optarg));
+			break;
+
+		case OPT_ARM:
+			coder_add_filter(LZMA_FILTER_ARM,
+					options_bcj(optarg));
+			break;
+
+		case OPT_ARMTHUMB:
+			coder_add_filter(LZMA_FILTER_ARMTHUMB,
+					options_bcj(optarg));
+			break;
+
+		case OPT_SPARC:
+			coder_add_filter(LZMA_FILTER_SPARC,
+					options_bcj(optarg));
+			break;
+
+		case OPT_DELTA:
+			coder_add_filter(LZMA_FILTER_DELTA,
+					options_delta(optarg));
+			break;
+
+		case OPT_LZMA1:
+			coder_add_filter(LZMA_FILTER_LZMA1,
+					options_lzma(optarg));
+			break;
+
+		case OPT_LZMA2:
+			coder_add_filter(LZMA_FILTER_LZMA2,
+					options_lzma(optarg));
+			break;
+
+		// Other
+
+		// --format
+		case 'F': {
+			// Just in case, support both "lzma" and "alone" since
+			// the latter was used for forward compatibility in
+			// LZMA Utils 4.32.x.
+			static const struct {
+				char str[8];
+				enum format_type format;
+			} types[] = {
+				{ "auto",   FORMAT_AUTO },
+				{ "xz",     FORMAT_XZ },
+				{ "lzma",   FORMAT_LZMA },
+				{ "alone",  FORMAT_LZMA },
+				// { "gzip",   FORMAT_GZIP },
+				// { "gz",     FORMAT_GZIP },
+				{ "raw",    FORMAT_RAW },
+			};
+
+			size_t i = 0;
+			while (strcmp(types[i].str, optarg) != 0)
+				if (++i == ARRAY_SIZE(types))
+					message_fatal(_("%s: Unknown file "
+							"format type"),
+							optarg);
+
+			opt_format = types[i].format;
+			break;
+		}
+
+		// --check
+		case 'C': {
+			static const struct {
+				char str[8];
+				lzma_check check;
+			} types[] = {
+				{ "none",   LZMA_CHECK_NONE },
+				{ "crc32",  LZMA_CHECK_CRC32 },
+				{ "crc64",  LZMA_CHECK_CRC64 },
+				{ "sha256", LZMA_CHECK_SHA256 },
+			};
+
+			size_t i = 0;
+			while (strcmp(types[i].str, optarg) != 0) {
+				if (++i == ARRAY_SIZE(types))
+					message_fatal(_("%s: Unsupported "
+							"integrity "
+							"check type"), optarg);
+			}
+
+			// Use a separate check in case we are using different
+			// liblzma than what was used to compile us.
+			if (!lzma_check_is_supported(types[i].check))
+				message_fatal(_("%s: Unsupported integrity "
+						"check type"), optarg);
+
+			coder_set_check(types[i].check);
+			break;
+		}
+
+		case OPT_NO_SPARSE:
+			io_no_sparse();
+			break;
+
+		case OPT_FILES:
+			args->files_delim = '\n';
+
+		// Fall through
+
+		case OPT_FILES0:
+			if (args->files_name != NULL)
+				message_fatal(_("Only one file can be "
+						"specified with `--files' "
+						"or `--files0'."));
+
+			if (optarg == NULL) {
+				args->files_name = (char *)stdin_filename;
+				args->files_file = stdin;
+			} else {
+				args->files_name = optarg;
+				args->files_file = fopen(optarg,
+						c == OPT_FILES ? "r" : "rb");
+				if (args->files_file == NULL)
+					message_fatal("%s: %s", optarg,
+							strerror(errno));
+			}
+
+			break;
+
+		case OPT_NO_ADJUST:
+			opt_auto_adjust = false;
+			break;
+
+		default:
+			message_try_help();
+			tuklib_exit(E_ERROR, E_ERROR, false);
+		}
+	}
+
+	return;
+}
+
+
+static void
+parse_environment(args_info *args, char *argv0)
+{
+	char *env = getenv("XZ_OPT");
+	if (env == NULL)
+		return;
+
+	// We modify the string, so make a copy of it.
+	env = xstrdup(env);
+
+	// Calculate the number of arguments in env. argc stats at one
+	// to include space for the program name.
+	int argc = 1;
+	bool prev_was_space = true;
+	for (size_t i = 0; env[i] != '\0'; ++i) {
+		// NOTE: Cast to unsigned char is needed so that correct
+		// value gets passed to isspace(), which expects
+		// unsigned char cast to int. Casting to int is done
+		// automatically due to integer promotion, but we need to
+		// force char to unsigned char manually. Otherwise 8-bit
+		// characters would get promoted to wrong value if
+		// char is signed.
+		if (isspace((unsigned char)env[i])) {
+			prev_was_space = true;
+		} else if (prev_was_space) {
+			prev_was_space = false;
+
+			// Keep argc small enough to fit into a singed int
+			// and to keep it usable for memory allocation.
+			if (++argc == my_min(
+					INT_MAX, SIZE_MAX / sizeof(char *)))
+				message_fatal(_("The environment variable "
+						"XZ_OPT contains too many "
+						"arguments"));
+		}
+	}
+
+	// Allocate memory to hold pointers to the arguments. Add one to get
+	// space for the terminating NULL (if some systems happen to need it).
+	char **argv = xmalloc(((size_t)(argc) + 1) * sizeof(char *));
+	argv[0] = argv0;
+	argv[argc] = NULL;
+
+	// Go through the string again. Split the arguments using '\0'
+	// characters and add pointers to the resulting strings to argv.
+	argc = 1;
+	prev_was_space = true;
+	for (size_t i = 0; env[i] != '\0'; ++i) {
+		if (isspace((unsigned char)env[i])) {
+			prev_was_space = true;
+			env[i] = '\0';
+		} else if (prev_was_space) {
+			prev_was_space = false;
+			argv[argc++] = env + i;
+		}
+	}
+
+	// Parse the argument list we got from the environment. All non-option
+	// arguments i.e. filenames are ignored.
+	parse_real(args, argc, argv);
+
+	// Reset the state of the getopt_long() so that we can parse the
+	// command line options too. There are two incompatible ways to
+	// do it.
+#ifdef HAVE_OPTRESET
+	// BSD
+	optind = 1;
+	optreset = 1;
+#else
+	// GNU, Solaris
+	optind = 0;
+#endif
+
+	// We don't need the argument list from environment anymore.
+	free(argv);
+	free(env);
+
+	return;
+}
+
+
+extern void
+args_parse(args_info *args, int argc, char **argv)
+{
+	// Initialize those parts of *args that we need later.
+	args->files_name = NULL;
+	args->files_file = NULL;
+	args->files_delim = '\0';
+
+	// Check how we were called.
+	{
+		// Remove the leading path name, if any.
+		const char *name = strrchr(argv[0], '/');
+		if (name == NULL)
+			name = argv[0];
+		else
+			++name;
+
+		// NOTE: It's possible that name[0] is now '\0' if argv[0]
+		// is weird, but it doesn't matter here.
+
+		// Look for full command names instead of substrings like
+		// "un", "cat", and "lz" to reduce possibility of false
+		// positives when the programs have been renamed.
+		if (strstr(name, "xzcat") != NULL) {
+			opt_mode = MODE_DECOMPRESS;
+			opt_stdout = true;
+		} else if (strstr(name, "unxz") != NULL) {
+			opt_mode = MODE_DECOMPRESS;
+		} else if (strstr(name, "lzcat") != NULL) {
+			opt_format = FORMAT_LZMA;
+			opt_mode = MODE_DECOMPRESS;
+			opt_stdout = true;
+		} else if (strstr(name, "unlzma") != NULL) {
+			opt_format = FORMAT_LZMA;
+			opt_mode = MODE_DECOMPRESS;
+		} else if (strstr(name, "lzma") != NULL) {
+			opt_format = FORMAT_LZMA;
+		}
+	}
+
+	// First the flags from environment
+	parse_environment(args, argv[0]);
+
+	// Then from the command line
+	parse_real(args, argc, argv);
+
+	// Never remove the source file when the destination is not on disk.
+	// In test mode the data is written nowhere, but setting opt_stdout
+	// will make the rest of the code behave well.
+	if (opt_stdout || opt_mode == MODE_TEST) {
+		opt_keep_original = true;
+		opt_stdout = true;
+	}
+
+	// When compressing, if no --format flag was used, or it
+	// was --format=auto, we compress to the .xz format.
+	if (opt_mode == MODE_COMPRESS && opt_format == FORMAT_AUTO)
+		opt_format = FORMAT_XZ;
+
+	// Compression settings need to be validated (options themselves and
+	// their memory usage) when compressing to any file format. It has to
+	// be done also when uncompressing raw data, since for raw decoding
+	// the options given on the command line are used to know what kind
+	// of raw data we are supposed to decode.
+	if (opt_mode == MODE_COMPRESS || opt_format == FORMAT_RAW)
+		coder_set_compression_settings();
+
+	// If no filenames are given, use stdin.
+	if (argv[optind] == NULL && args->files_name == NULL) {
+		// We don't modify or free() the "-" constant. The caller
+		// modifies this so don't make the struct itself const.
+		static char *names_stdin[2] = { (char *)"-", NULL };
+		args->arg_names = names_stdin;
+		args->arg_count = 1;
+	} else {
+		// We got at least one filename from the command line, or
+		// --files or --files0 was specified.
+		args->arg_names = argv + optind;
+		args->arg_count = argc - optind;
+	}
+
+	return;
+}
diff --git a/src/xz/args.h b/src/xz/args.h
new file mode 100644
index 0000000..ac5959b
--- /dev/null
+++ b/src/xz/args.h
@@ -0,0 +1,42 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       args.h
+/// \brief      Argument parsing
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+typedef struct {
+	/// Filenames from command line
+	char **arg_names;
+
+	/// Number of filenames from command line
+	size_t arg_count;
+
+	/// Name of the file from which to read filenames. This is NULL
+	/// if --files or --files0 was not used.
+	char *files_name;
+
+	/// File opened for reading from which filenames are read. This is
+	/// non-NULL only if files_name is non-NULL.
+	FILE *files_file;
+
+	/// Delimiter for filenames read from files_file
+	char files_delim;
+
+} args_info;
+
+
+extern bool opt_stdout;
+extern bool opt_force;
+extern bool opt_keep_original;
+// extern bool opt_recursive;
+extern bool opt_robot;
+
+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
new file mode 100644
index 0000000..ff50d63
--- /dev/null
+++ b/src/xz/coder.c
@@ -0,0 +1,655 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       coder.c
+/// \brief      Compresses or uncompresses a file
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "private.h"
+
+
+/// Return value type for coder_init().
+enum coder_init_ret {
+	CODER_INIT_NORMAL,
+	CODER_INIT_PASSTHRU,
+	CODER_INIT_ERROR,
+};
+
+
+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
+static lzma_stream strm = LZMA_STREAM_INIT;
+
+/// Filters needed for all encoding all formats, and also decoding in raw data
+static lzma_filter filters[LZMA_FILTERS_MAX + 1];
+
+/// Input and output buffers
+static io_buf in_buf;
+static io_buf out_buf;
+
+/// Number of filters. Zero indicates that we are using a preset.
+static size_t filters_count = 0;
+
+/// Number of the preset (0-9)
+static size_t preset_number = 6;
+
+/// 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.
+static bool preset_extreme = false;
+
+/// Integrity check type
+static lzma_check check;
+
+/// This becomes false if the --check=CHECK option is used.
+static bool check_default = true;
+
+
+extern void
+coder_set_check(lzma_check new_check)
+{
+	check = new_check;
+	check_default = false;
+	return;
+}
+
+
+extern void
+coder_set_preset(size_t new_preset)
+{
+	preset_number = new_preset;
+	preset_default = false;
+	return;
+}
+
+
+extern void
+coder_set_extreme(void)
+{
+	preset_extreme = true;
+	return;
+}
+
+
+extern void
+coder_add_filter(lzma_vli id, void *options)
+{
+	if (filters_count == LZMA_FILTERS_MAX)
+		message_fatal(_("Maximum number of filters is four"));
+
+	filters[filters_count].id = id;
+	filters[filters_count].options = options;
+	++filters_count;
+
+	return;
+}
+
+
+static void lzma_attribute((noreturn))
+memlimit_too_small(uint64_t memory_usage)
+{
+	message(V_ERROR, _("Memory usage limit is too low for the given "
+			"filter setup."));
+	message_mem_needed(V_ERROR, memory_usage);
+	tuklib_exit(E_ERROR, E_ERROR, false);
+}
+
+
+extern void
+coder_set_compression_settings(void)
+{
+	// Options for LZMA1 or LZMA2 in case we are using a preset.
+	static lzma_options_lzma opt_lzma;
+
+	if (filters_count == 0) {
+		// We are using a preset. This is not a good idea in raw mode
+		// except when playing around with things. Different versions
+		// of this software may use different options in presets, and
+		// thus make uncompressing the raw data difficult.
+		if (opt_format == FORMAT_RAW) {
+			// The message is shown only if warnings are allowed
+			// but the exit status isn't changed.
+			message(V_WARNING, _("Using a preset in raw mode "
+					"is discouraged."));
+			message(V_WARNING, _("The exact options of the "
+					"presets may vary between software "
+					"versions."));
+		}
+
+		// Get the preset for LZMA1 or LZMA2.
+		if (preset_extreme)
+			preset_number |= LZMA_PRESET_EXTREME;
+
+		if (lzma_lzma_preset(&opt_lzma, preset_number))
+			message_bug();
+
+		// Use LZMA2 except with --format=lzma we use LZMA1.
+		filters[0].id = opt_format == FORMAT_LZMA
+				? LZMA_FILTER_LZMA1 : LZMA_FILTER_LZMA2;
+		filters[0].options = &opt_lzma;
+		filters_count = 1;
+	} else {
+		preset_default = false;
+	}
+
+	// Terminate the filter options array.
+	filters[filters_count].id = LZMA_VLI_UNKNOWN;
+
+	// If we are using the .lzma format, allow exactly one filter
+	// which has to be LZMA1.
+	if (opt_format == FORMAT_LZMA && (filters_count != 1
+			|| filters[0].id != LZMA_FILTER_LZMA1))
+		message_fatal(_("The .lzma format supports only "
+				"the LZMA1 filter"));
+
+	// If we are using the .xz format, make sure that there is no LZMA1
+	// filter to prevent LZMA_PROG_ERROR.
+	if (opt_format == FORMAT_XZ)
+		for (size_t i = 0; i < filters_count; ++i)
+			if (filters[i].id == LZMA_FILTER_LZMA1)
+				message_fatal(_("LZMA1 cannot be used "
+						"with the .xz format"));
+
+	// Print the selected filter chain.
+	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();
+	uint64_t memory_usage;
+	if (opt_mode == MODE_COMPRESS)
+		memory_usage = lzma_raw_encoder_memusage(filters);
+	else
+		memory_usage = lzma_raw_decoder_memusage(filters);
+
+	if (memory_usage == UINT64_MAX)
+		message_fatal(_("Unsupported filter chain or filter options"));
+
+	// Print memory usage info before possible dictionary
+	// size auto-adjusting.
+	message_mem_needed(V_DEBUG, memory_usage);
+
+	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 (!opt_auto_adjust || opt_format == FORMAT_RAW)
+			memlimit_too_small(memory_usage);
+
+		assert(opt_mode == MODE_COMPRESS);
+
+		// Look for the last filter if it is LZMA2 or LZMA1, so
+		// we can make it use less RAM. With other filters we don't
+		// know what to do.
+		size_t i = 0;
+		while (filters[i].id != LZMA_FILTER_LZMA2
+				&& filters[i].id != LZMA_FILTER_LZMA1) {
+			if (filters[i].id == LZMA_VLI_UNKNOWN)
+				memlimit_too_small(memory_usage);
+
+			++i;
+		}
+
+		// Decrease the dictionary size until we meet the memory
+		// usage limit. First round down to full mebibytes.
+		lzma_options_lzma *opt = filters[i].options;
+		const uint32_t orig_dict_size = opt->dict_size;
+		opt->dict_size &= ~((UINT32_C(1) << 20) - 1);
+		while (true) {
+			// If it is below 1 MiB, auto-adjusting failed. We
+			// could be more sophisticated and scale it down even
+			// more, but let's see if many complain about this
+			// version.
+			//
+			// FIXME: Displays the scaled memory usage instead
+			// of the original.
+			if (opt->dict_size < (UINT32_C(1) << 20))
+				memlimit_too_small(memory_usage);
+
+			memory_usage = lzma_raw_encoder_memusage(filters);
+			if (memory_usage == UINT64_MAX)
+				message_bug();
+
+			// Accept it if it is low enough.
+			if (memory_usage <= memory_limit)
+				break;
+
+			// Otherwise 1 MiB down and try again. I hope this
+			// isn't too slow method for cases where the original
+			// dict_size is very big.
+			opt->dict_size -= UINT32_C(1) << 20;
+		}
+
+		// 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));
+	}
+
+/*
+	// Limit the number of worker threads so that memory usage
+	// limit isn't exceeded.
+	assert(memory_usage > 0);
+	size_t thread_limit = memory_limit / memory_usage;
+	if (thread_limit == 0)
+		thread_limit = 1;
+
+	if (opt_threads > thread_limit)
+		opt_threads = thread_limit;
+*/
+
+	if (check_default) {
+		// The default check type is CRC64, but fallback to CRC32
+		// if CRC64 isn't supported by the copy of liblzma we are
+		// using. CRC32 is always supported.
+		check = LZMA_CHECK_CRC64;
+		if (!lzma_check_is_supported(check))
+			check = LZMA_CHECK_CRC32;
+	}
+
+	return;
+}
+
+
+/// Return true if the data in in_buf seems to be in the .xz format.
+static bool
+is_format_xz(void)
+{
+	return strm.avail_in >= 6 && memcmp(in_buf.u8, "\3757zXZ", 6) == 0;
+}
+
+
+/// Return true if the data in in_buf seems to be in the .lzma format.
+static bool
+is_format_lzma(void)
+{
+	// The .lzma header is 13 bytes.
+	if (strm.avail_in < 13)
+		return false;
+
+	// Decode the LZMA1 properties.
+	lzma_filter filter = { .id = LZMA_FILTER_LZMA1 };
+	if (lzma_properties_decode(&filter, NULL, in_buf.u8, 5) != LZMA_OK)
+		return false;
+
+	// A hack to ditch tons of false positives: We allow only dictionary
+	// sizes that are 2^n or 2^n + 2^(n-1) or UINT32_MAX. LZMA_Alone
+	// created only files with 2^n, but accepts any dictionary size.
+	// If someone complains, this will be reconsidered.
+	lzma_options_lzma *opt = filter.options;
+	const uint32_t dict_size = opt->dict_size;
+	free(opt);
+
+	if (dict_size != UINT32_MAX) {
+		uint32_t d = dict_size - 1;
+		d |= d >> 2;
+		d |= d >> 3;
+		d |= d >> 4;
+		d |= d >> 8;
+		d |= d >> 16;
+		++d;
+		if (d != dict_size || dict_size == 0)
+			return false;
+	}
+
+	// Another hack to ditch false positives: Assume that if the
+	// uncompressed size is known, it must be less than 256 GiB.
+	// Again, if someone complains, this will be reconsidered.
+	uint64_t uncompressed_size = 0;
+	for (size_t i = 0; i < 8; ++i)
+		uncompressed_size |= (uint64_t)(in_buf.u8[5 + i]) << (i * 8);
+
+	if (uncompressed_size != UINT64_MAX
+			&& uncompressed_size > (UINT64_C(1) << 38))
+		return false;
+
+	return true;
+}
+
+
+/// Detect the input file type (for now, this done only when decompressing),
+/// and initialize an appropriate coder. Return value indicates if a normal
+/// liblzma-based coder was initialized (CODER_INIT_NORMAL), if passthru
+/// mode should be used (CODER_INIT_PASSTHRU), or if an error occurred
+/// (CODER_INIT_ERROR).
+static enum coder_init_ret
+coder_init(file_pair *pair)
+{
+	lzma_ret ret = LZMA_PROG_ERROR;
+
+	if (opt_mode == MODE_COMPRESS) {
+		switch (opt_format) {
+		case FORMAT_AUTO:
+			// args.c ensures this.
+			assert(0);
+			break;
+
+		case FORMAT_XZ:
+			ret = lzma_stream_encoder(&strm, filters, check);
+			break;
+
+		case FORMAT_LZMA:
+			ret = lzma_alone_encoder(&strm, filters[0].options);
+			break;
+
+		case FORMAT_RAW:
+			ret = lzma_raw_encoder(&strm, filters);
+			break;
+		}
+	} else {
+		const uint32_t flags = LZMA_TELL_UNSUPPORTED_CHECK
+				| LZMA_CONCATENATED;
+
+		// We abuse FORMAT_AUTO to indicate unknown file format,
+		// for which we may consider passthru mode.
+		enum format_type init_format = FORMAT_AUTO;
+
+		switch (opt_format) {
+		case FORMAT_AUTO:
+			if (is_format_xz())
+				init_format = FORMAT_XZ;
+			else if (is_format_lzma())
+				init_format = FORMAT_LZMA;
+			break;
+
+		case FORMAT_XZ:
+			if (is_format_xz())
+				init_format = FORMAT_XZ;
+			break;
+
+		case FORMAT_LZMA:
+			if (is_format_lzma())
+				init_format = FORMAT_LZMA;
+			break;
+
+		case FORMAT_RAW:
+			init_format = FORMAT_RAW;
+			break;
+		}
+
+		switch (init_format) {
+		case FORMAT_AUTO:
+			// Uknown file format. If --decompress --stdout
+			// --force have been given, then we copy the input
+			// as is to stdout. Checking for MODE_DECOMPRESS
+			// is needed, because we don't want to do use
+			// passthru mode with --test.
+			if (opt_mode == MODE_DECOMPRESS
+					&& opt_stdout && opt_force)
+				return CODER_INIT_PASSTHRU;
+
+			ret = LZMA_FORMAT_ERROR;
+			break;
+
+		case FORMAT_XZ:
+			ret = lzma_stream_decoder(&strm,
+					hardware_memlimit_get(), flags);
+			break;
+
+		case FORMAT_LZMA:
+			ret = lzma_alone_decoder(&strm,
+					hardware_memlimit_get());
+			break;
+
+		case FORMAT_RAW:
+			// Memory usage has already been checked in
+			// coder_set_compression_settings().
+			ret = lzma_raw_decoder(&strm, filters);
+			break;
+		}
+
+		// Try to decode the headers. This will catch too low
+		// memory usage limit in case it happens in the first
+		// Block of the first Stream, which is where it very
+		// probably will happen if it is going to happen.
+		if (ret == LZMA_OK && init_format != FORMAT_RAW) {
+			strm.next_out = NULL;
+			strm.avail_out = 0;
+			ret = lzma_code(&strm, LZMA_RUN);
+		}
+	}
+
+	if (ret != LZMA_OK) {
+		message_error("%s: %s", pair->src_name, message_strm(ret));
+		if (ret == LZMA_MEMLIMIT_ERROR)
+			message_mem_needed(V_ERROR, lzma_memusage(&strm));
+
+		return CODER_INIT_ERROR;
+	}
+
+	return CODER_INIT_NORMAL;
+}
+
+
+/// Compress or decompress using liblzma.
+static bool
+coder_normal(file_pair *pair)
+{
+	// Encoder needs to know when we have given all the input to it.
+	// The decoders need to know it too when we are using
+	// LZMA_CONCATENATED. We need to check for src_eof here, because
+	// the first input chunk has been already read, and that may
+	// have been the only chunk we will read.
+	lzma_action action = pair->src_eof ? LZMA_FINISH : LZMA_RUN;
+
+	lzma_ret ret;
+
+	// Assume that something goes wrong.
+	bool success = false;
+
+	strm.next_out = out_buf.u8;
+	strm.avail_out = IO_BUFFER_SIZE;
+
+	while (!user_abort) {
+		// Fill the input buffer if it is empty and we haven't reached
+		// end of file yet.
+		if (strm.avail_in == 0 && !pair->src_eof) {
+			strm.next_in = in_buf.u8;
+			strm.avail_in = io_read(
+					pair, &in_buf, IO_BUFFER_SIZE);
+
+			if (strm.avail_in == SIZE_MAX)
+				break;
+
+			if (pair->src_eof)
+				action = LZMA_FINISH;
+		}
+
+		// Let liblzma do the actual work.
+		ret = lzma_code(&strm, action);
+
+		// Write out if the output buffer became full.
+		if (strm.avail_out == 0) {
+			if (opt_mode != MODE_TEST && io_write(pair, &out_buf,
+					IO_BUFFER_SIZE - strm.avail_out))
+				break;
+
+			strm.next_out = out_buf.u8;
+			strm.avail_out = IO_BUFFER_SIZE;
+		}
+
+		if (ret != LZMA_OK) {
+			// Determine if the return value indicates that we
+			// won't continue coding.
+			const bool stop = ret != LZMA_NO_CHECK
+					&& ret != LZMA_UNSUPPORTED_CHECK;
+
+			if (stop) {
+				// Write the remaining bytes even if something
+				// went wrong, because that way the user gets
+				// as much data as possible, which can be good
+				// when trying to get at least some useful
+				// data out of damaged files.
+				if (opt_mode != MODE_TEST && io_write(pair,
+						&out_buf, IO_BUFFER_SIZE
+							- strm.avail_out))
+					break;
+			}
+
+			if (ret == LZMA_STREAM_END) {
+				// Check that there is no trailing garbage.
+				// This is needed for LZMA_Alone and raw
+				// streams.
+				if (strm.avail_in == 0 && !pair->src_eof) {
+					// Try reading one more byte.
+					// Hopefully we don't get any more
+					// input, and thus pair->src_eof
+					// becomes true.
+					strm.avail_in = io_read(
+							pair, &in_buf, 1);
+					if (strm.avail_in == SIZE_MAX)
+						break;
+
+					assert(strm.avail_in == 0
+							|| strm.avail_in == 1);
+				}
+
+				if (strm.avail_in == 0) {
+					assert(pair->src_eof);
+					success = true;
+					break;
+				}
+
+				// We hadn't reached the end of the file.
+				ret = LZMA_DATA_ERROR;
+				assert(stop);
+			}
+
+			// If we get here and stop is true, something went
+			// wrong and we print an error. Otherwise it's just
+			// a warning and coding can continue.
+			if (stop) {
+				message_error("%s: %s", pair->src_name,
+						message_strm(ret));
+			} else {
+				message_warning("%s: %s", pair->src_name,
+						message_strm(ret));
+
+				// When compressing, all possible errors set
+				// stop to true.
+				assert(opt_mode != MODE_COMPRESS);
+			}
+
+			if (ret == LZMA_MEMLIMIT_ERROR) {
+				// Display how much memory it would have
+				// actually needed.
+				message_mem_needed(V_ERROR,
+						lzma_memusage(&strm));
+			}
+
+			if (stop)
+				break;
+		}
+
+		// Show progress information under certain conditions.
+		message_progress_update();
+	}
+
+	return success;
+}
+
+
+/// Copy from input file to output file without processing the data in any
+/// way. This is used only when trying to decompress unrecognized files
+/// with --decompress --stdout --force, so the output is always stdout.
+static bool
+coder_passthru(file_pair *pair)
+{
+	while (strm.avail_in != 0) {
+		if (user_abort)
+			return false;
+
+		if (io_write(pair, &in_buf, strm.avail_in))
+			return false;
+
+		strm.total_in += strm.avail_in;
+		strm.total_out = strm.total_in;
+		message_progress_update();
+
+		strm.avail_in = io_read(pair, &in_buf, IO_BUFFER_SIZE);
+		if (strm.avail_in == SIZE_MAX)
+			return false;
+	}
+
+	return true;
+}
+
+
+extern void
+coder_run(const char *filename)
+{
+	// Set and possibly print the filename for the progress message.
+	message_filename(filename);
+
+	// Try to open the input file.
+	file_pair *pair = io_open_src(filename);
+	if (pair == NULL)
+		return;
+
+	// Assume that something goes wrong.
+	bool success = false;
+
+	// Read the first chunk of input data. This is needed to detect
+	// the input file type (for now, only for decompression).
+	strm.next_in = in_buf.u8;
+	strm.avail_in = io_read(pair, &in_buf, IO_BUFFER_SIZE);
+
+	if (strm.avail_in != SIZE_MAX) {
+		// Initialize the coder. This will detect the file format
+		// and, in decompression or testing mode, check the memory
+		// usage of the first Block too. This way we don't try to
+		// open the destination file if we see that coding wouldn't
+		// work at all anyway. This also avoids deleting the old
+		// "target" file if --force was used.
+		const enum coder_init_ret init_ret = coder_init(pair);
+
+		if (init_ret != CODER_INIT_ERROR && !user_abort) {
+			// Don't open the destination file when --test
+			// is used.
+			if (opt_mode == MODE_TEST || !io_open_dest(pair)) {
+				// Initialize the progress indicator.
+				const uint64_t in_size
+						= pair->src_st.st_size <= 0
+						? 0 : pair->src_st.st_size;
+				message_progress_start(&strm, in_size);
+
+				// Do the actual coding or passthru.
+				if (init_ret == CODER_INIT_NORMAL)
+					success = coder_normal(pair);
+				else
+					success = coder_passthru(pair);
+
+				message_progress_end(success);
+			}
+		}
+	}
+
+	// Close the file pair. It needs to know if coding was successful to
+	// know if the source or target file should be unlinked.
+	io_close(pair, success);
+
+	return;
+}
diff --git a/src/xz/coder.h b/src/xz/coder.h
new file mode 100644
index 0000000..4626466
--- /dev/null
+++ b/src/xz/coder.h
@@ -0,0 +1,61 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       coder.h
+/// \brief      Compresses or uncompresses a file
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+enum operation_mode {
+	MODE_COMPRESS,
+	MODE_DECOMPRESS,
+	MODE_TEST,
+	MODE_LIST,
+};
+
+
+// NOTE: The order of these is significant in suffix.c.
+enum format_type {
+	FORMAT_AUTO,
+	FORMAT_XZ,
+	FORMAT_LZMA,
+	// HEADER_GZIP,
+	FORMAT_RAW,
+};
+
+
+/// Operation mode of the command line tool. This is set in args.c and read
+/// in several files.
+extern enum operation_mode opt_mode;
+
+/// File format to use when encoding or what format(s) to accept when
+/// decoding. This is a global because it's needed also in suffix.c.
+/// 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);
+
+/// Set preset number
+extern void coder_set_preset(size_t new_preset);
+
+/// Enable extreme mode
+extern void coder_set_extreme(void);
+
+/// Add a filter to the custom filter chain
+extern void coder_add_filter(lzma_vli id, void *options);
+
+///
+extern void coder_set_compression_settings(void);
+
+/// Compress or decompress the given file
+extern void coder_run(const char *filename);
diff --git a/src/xz/file_io.c b/src/xz/file_io.c
new file mode 100644
index 0000000..a78002e
--- /dev/null
+++ b/src/xz/file_io.c
@@ -0,0 +1,957 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       file_io.c
+/// \brief      File opening, unlinking, and closing
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "private.h"
+
+#include <fcntl.h>
+
+#ifdef TUKLIB_DOSLIKE
+#	include <io.h>
+#else
+static bool warn_fchown;
+#endif
+
+#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMES)
+#	include <sys/time.h>
+#elif defined(HAVE_UTIME)
+#	include <utime.h>
+#endif
+
+#include "tuklib_open_stdxxx.h"
+
+#ifndef O_BINARY
+#	define O_BINARY 0
+#endif
+
+#ifndef O_NOCTTY
+#	define O_NOCTTY 0
+#endif
+
+
+/// If true, try to create sparse files when decompressing.
+static bool try_sparse = true;
+
+#ifndef TUKLIB_DOSLIKE
+/// File status flags of standard output. This is used by io_open_dest()
+/// and io_close_dest().
+static int stdout_flags = 0;
+#endif
+
+
+static bool io_write_buf(file_pair *pair, const uint8_t *buf, size_t size);
+
+
+extern void
+io_init(void)
+{
+	// Make sure that stdin, stdout, and and stderr are connected to
+	// a valid file descriptor. Exit immediately with exit code ERROR
+	// if we cannot make the file descriptors valid. Maybe we should
+	// print an error message, but our stderr could be screwed anyway.
+	tuklib_open_stdxxx(E_ERROR);
+
+#ifndef TUKLIB_DOSLIKE
+	// If fchown() fails setting the owner, we warn about it only if
+	// we are root.
+	warn_fchown = geteuid() == 0;
+#endif
+
+#ifdef __DJGPP__
+	// Avoid doing useless things when statting files.
+	// This isn't important but doesn't hurt.
+	_djstat_flags = _STAT_INODE | _STAT_EXEC_EXT
+			| _STAT_EXEC_MAGIC | _STAT_DIRSIZE;
+#endif
+
+	return;
+}
+
+
+extern void
+io_no_sparse(void)
+{
+	try_sparse = false;
+	return;
+}
+
+
+/// \brief      Unlink a file
+///
+/// This tries to verify that the file being unlinked really is the file that
+/// we want to unlink by verifying device and inode numbers. There's still
+/// a small unavoidable race, but this is much better than nothing (the file
+/// could have been moved/replaced even hours earlier).
+static void
+io_unlink(const char *name, const struct stat *known_st)
+{
+#if defined(TUKLIB_DOSLIKE)
+	// On DOS-like systems, st_ino is meaningless, so don't bother
+	// testing it. Just silence a compiler warning.
+	(void)known_st;
+#else
+	struct stat new_st;
+
+	// If --force was used, use stat() instead of lstat(). This way
+	// (de)compressing symlinks works correctly. However, it also means
+	// that xz cannot detect if a regular file foo is renamed to bar
+	// and then a symlink foo -> bar is created. Because of stat()
+	// instead of lstat(), xz will think that foo hasn't been replaced
+	// with another file. Thus, xz will remove foo even though it no
+	// longer is the same file that xz used when it started compressing.
+	// Probably it's not too bad though, so this doesn't need a more
+	// complex fix.
+	const int stat_ret = opt_force
+			? stat(name, &new_st) : lstat(name, &new_st);
+
+	if (stat_ret
+#	ifdef __VMS
+			// st_ino is an array, and we don't want to
+			// compare st_dev at all.
+			|| memcmp(&new_st.st_ino, &known_st->st_ino,
+				sizeof(new_st.st_ino)) != 0
+#	else
+			// Typical POSIX-like system
+			|| new_st.st_dev != known_st->st_dev
+			|| new_st.st_ino != known_st->st_ino
+#	endif
+			)
+		// 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.
+		message_error(_("%s: File seems to have been moved, "
+				"not removing"), name);
+	else
+#endif
+		// There's a race condition between lstat() and unlink()
+		// but at least we have tried to avoid removing wrong file.
+		if (unlink(name))
+			message_error(_("%s: Cannot remove: %s"),
+					name, strerror(errno));
+
+	return;
+}
+
+
+/// \brief      Copies owner/group and permissions
+///
+/// \todo       ACL and EA support
+///
+static void
+io_copy_attrs(const file_pair *pair)
+{
+	// Skip chown and chmod on Windows.
+#ifndef TUKLIB_DOSLIKE
+	// This function is more tricky than you may think at first.
+	// Blindly copying permissions may permit users to access the
+	// destination file who didn't have permission to access the
+	// source file.
+
+	// Try changing the owner of the file. If we aren't root or the owner
+	// isn't already us, fchown() probably doesn't succeed. We warn
+	// about failing fchown() only if we are root.
+	if (fchown(pair->dest_fd, pair->src_st.st_uid, -1) && warn_fchown)
+		message_warning(_("%s: Cannot set the file owner: %s"),
+				pair->dest_name, strerror(errno));
+
+	mode_t mode;
+
+	if (fchown(pair->dest_fd, -1, pair->src_st.st_gid)) {
+		message_warning(_("%s: Cannot set the file group: %s"),
+				pair->dest_name, strerror(errno));
+		// We can still safely copy some additional permissions:
+		// `group' must be at least as strict as `other' and
+		// also vice versa.
+		//
+		// NOTE: After this, the owner of the source file may
+		// get additional permissions. This shouldn't be too bad,
+		// because the owner would have had permission to chmod
+		// the original file anyway.
+		mode = ((pair->src_st.st_mode & 0070) >> 3)
+				& (pair->src_st.st_mode & 0007);
+		mode = (pair->src_st.st_mode & 0700) | (mode << 3) | mode;
+	} else {
+		// Drop the setuid, setgid, and sticky bits.
+		mode = pair->src_st.st_mode & 0777;
+	}
+
+	if (fchmod(pair->dest_fd, mode))
+		message_warning(_("%s: Cannot set the file permissions: %s"),
+				pair->dest_name, strerror(errno));
+#endif
+
+	// Copy the timestamps. We have several possible ways to do this, of
+	// which some are better in both security and precision.
+	//
+	// First, get the nanosecond part of the timestamps. As of writing,
+	// it's not standardized by POSIX, and there are several names for
+	// the same thing in struct stat.
+	long atime_nsec;
+	long mtime_nsec;
+
+#	if defined(HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC)
+	// GNU and Solaris
+	atime_nsec = pair->src_st.st_atim.tv_nsec;
+	mtime_nsec = pair->src_st.st_mtim.tv_nsec;
+
+#	elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC)
+	// BSD
+	atime_nsec = pair->src_st.st_atimespec.tv_nsec;
+	mtime_nsec = pair->src_st.st_mtimespec.tv_nsec;
+
+#	elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
+	// GNU and BSD without extensions
+	atime_nsec = pair->src_st.st_atimensec;
+	mtime_nsec = pair->src_st.st_mtimensec;
+
+#	elif defined(HAVE_STRUCT_STAT_ST_UATIME)
+	// Tru64
+	atime_nsec = pair->src_st.st_uatime * 1000;
+	mtime_nsec = pair->src_st.st_umtime * 1000;
+
+#	elif defined(HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC)
+	// UnixWare
+	atime_nsec = pair->src_st.st_atim.st__tim.tv_nsec;
+	mtime_nsec = pair->src_st.st_mtim.st__tim.tv_nsec;
+
+#	else
+	// Safe fallback
+	atime_nsec = 0;
+	mtime_nsec = 0;
+#	endif
+
+	// Construct a structure to hold the timestamps and call appropriate
+	// function to set the timestamps.
+#if defined(HAVE_FUTIMENS)
+	// Use nanosecond precision.
+	struct timespec tv[2];
+	tv[0].tv_sec = pair->src_st.st_atime;
+	tv[0].tv_nsec = atime_nsec;
+	tv[1].tv_sec = pair->src_st.st_mtime;
+	tv[1].tv_nsec = mtime_nsec;
+
+	(void)futimens(pair->dest_fd, tv);
+
+#elif defined(HAVE_FUTIMES) || defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMES)
+	// Use microsecond precision.
+	struct timeval tv[2];
+	tv[0].tv_sec = pair->src_st.st_atime;
+	tv[0].tv_usec = atime_nsec / 1000;
+	tv[1].tv_sec = pair->src_st.st_mtime;
+	tv[1].tv_usec = mtime_nsec / 1000;
+
+#	if defined(HAVE_FUTIMES)
+	(void)futimes(pair->dest_fd, tv);
+#	elif defined(HAVE_FUTIMESAT)
+	(void)futimesat(pair->dest_fd, NULL, tv);
+#	else
+	// Argh, no function to use a file descriptor to set the timestamp.
+	(void)utimes(pair->dest_name, tv);
+#	endif
+
+#elif defined(HAVE_UTIME)
+	// Use one-second precision. utime() doesn't support using file
+	// descriptor either. Some systems have broken utime() prototype
+	// so don't make this const.
+	struct utimbuf buf = {
+		.actime = pair->src_st.st_atime,
+		.modtime = pair->src_st.st_mtime,
+	};
+
+	// Avoid warnings.
+	(void)atime_nsec;
+	(void)mtime_nsec;
+
+	(void)utime(pair->dest_name, &buf);
+#endif
+
+	return;
+}
+
+
+/// Opens the source file. Returns false on success, true on error.
+static bool
+io_open_src_real(file_pair *pair)
+{
+	// There's nothing to open when reading from stdin.
+	if (pair->src_name == stdin_filename) {
+		pair->src_fd = STDIN_FILENO;
+#ifdef TUKLIB_DOSLIKE
+		setmode(STDIN_FILENO, O_BINARY);
+#endif
+		return false;
+	}
+
+	// Symlinks are not followed unless writing to stdout or --force
+	// was used.
+	const bool follow_symlinks = opt_stdout || opt_force;
+
+	// We accept only regular files if we are writing the output
+	// to disk too. bzip2 allows overriding this with --force but
+	// gzip and xz don't.
+	const bool reg_files_only = !opt_stdout;
+
+	// Flags for open()
+	int flags = O_RDONLY | O_BINARY | O_NOCTTY;
+
+#ifndef TUKLIB_DOSLIKE
+	// If we accept only regular files, we need to be careful to avoid
+	// problems with special files like devices and FIFOs. O_NONBLOCK
+	// prevents blocking when opening such files. When we want to accept
+	// special files, we must not use O_NONBLOCK, or otherwise we won't
+	// block waiting e.g. FIFOs to become readable.
+	if (reg_files_only)
+		flags |= O_NONBLOCK;
+#endif
+
+#if defined(O_NOFOLLOW)
+	if (!follow_symlinks)
+		flags |= O_NOFOLLOW;
+#elif !defined(TUKLIB_DOSLIKE)
+	// Some POSIX-like systems lack O_NOFOLLOW (it's not required
+	// by POSIX). Check for symlinks with a separate lstat() on
+	// these systems.
+	if (!follow_symlinks) {
+		struct stat st;
+		if (lstat(pair->src_name, &st)) {
+			message_error("%s: %s", pair->src_name,
+					strerror(errno));
+			return true;
+
+		} else if (S_ISLNK(st.st_mode)) {
+			message_warning(_("%s: Is a symbolic link, "
+					"skipping"), pair->src_name);
+			return true;
+		}
+	}
+#else
+	// Avoid warnings.
+	(void)follow_symlinks;
+#endif
+
+	// Try to open the file. If we are accepting non-regular files,
+	// unblock the caught signals so that open() can be interrupted
+	// if it blocks e.g. due to a FIFO file.
+	if (!reg_files_only)
+		signals_unblock();
+
+	// Maybe this wouldn't need a loop, since all the signal handlers for
+	// which we don't use SA_RESTART set user_abort to true. But it
+	// doesn't hurt to have it just in case.
+	do {
+		pair->src_fd = open(pair->src_name, flags);
+	} while (pair->src_fd == -1 && errno == EINTR && !user_abort);
+
+	if (!reg_files_only)
+		signals_block();
+
+	if (pair->src_fd == -1) {
+		// If we were interrupted, don't display any error message.
+		if (errno == EINTR) {
+			// All the signals that don't have SA_RESTART
+			// set user_abort.
+			assert(user_abort);
+			return true;
+		}
+
+#ifdef O_NOFOLLOW
+		// Give an understandable error message in if 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
+		// 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.
+		//
+		// FreeBSD associates EMLINK with O_NOFOLLOW and
+		// Tru64 uses ENOTSUP. We use these directly here
+		// and skip the lstat() call and the associated race.
+		// I want to hear if there are other kernels that
+		// fail with something else than ELOOP with O_NOFOLLOW.
+		bool was_symlink = false;
+
+#	if defined(__FreeBSD__) || defined(__DragonFly__)
+		if (errno == EMLINK)
+			was_symlink = true;
+
+#	elif defined(__digital__) && defined(__unix__)
+		if (errno == ENOTSUP)
+			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.
+		if (errno == EFTYPE)
+			was_symlink = true;
+
+#	else
+		if (errno == ELOOP && !follow_symlinks) {
+			const int saved_errno = errno;
+			struct stat st;
+			if (lstat(pair->src_name, &st) == 0
+					&& S_ISLNK(st.st_mode))
+				was_symlink = true;
+
+			errno = saved_errno;
+		}
+#	endif
+
+		if (was_symlink)
+			message_warning(_("%s: Is a symbolic link, "
+					"skipping"), pair->src_name);
+		else
+#endif
+			// Something else than O_NOFOLLOW failing
+			// (assuming that the race conditions didn't
+			// confuse us).
+			message_error("%s: %s", pair->src_name,
+					strerror(errno));
+
+		return true;
+	}
+
+#ifndef TUKLIB_DOSLIKE
+	// Drop O_NONBLOCK, which is used only when we are accepting only
+	// regular files. After the open() call, we want things to block
+	// instead of giving EAGAIN.
+	if (reg_files_only) {
+		flags = fcntl(pair->src_fd, F_GETFL);
+		if (flags == -1)
+			goto error_msg;
+
+		flags &= ~O_NONBLOCK;
+
+		if (fcntl(pair->src_fd, F_SETFL, flags))
+			goto error_msg;
+	}
+#endif
+
+	// Stat the source file. We need the result also when we copy
+	// the permissions, and when unlinking.
+	if (fstat(pair->src_fd, &pair->src_st))
+		goto error_msg;
+
+	if (S_ISDIR(pair->src_st.st_mode)) {
+		message_warning(_("%s: Is a directory, skipping"),
+				pair->src_name);
+		goto error;
+	}
+
+	if (reg_files_only) {
+		if (!S_ISREG(pair->src_st.st_mode)) {
+			message_warning(_("%s: Not a regular file, "
+					"skipping"), pair->src_name);
+			goto error;
+		}
+
+		// These are meaningless on Windows.
+#ifndef TUKLIB_DOSLIKE
+		if (pair->src_st.st_mode & (S_ISUID | S_ISGID)) {
+			// gzip rejects setuid and setgid files even
+			// when --force was used. bzip2 doesn't check
+			// for them, but calls fchown() after fchmod(),
+			// and many systems automatically drop setuid
+			// and setgid bits there.
+			//
+			// We accept setuid and setgid files if
+			// --force was used. We drop these bits
+			// explicitly in io_copy_attr().
+			message_warning(_("%s: File has setuid or "
+					"setgid bit set, skipping"),
+					pair->src_name);
+			goto error;
+		}
+
+		if (pair->src_st.st_mode & S_ISVTX) {
+			message_warning(_("%s: File has sticky bit "
+					"set, skipping"),
+					pair->src_name);
+			goto error;
+		}
+
+		if (pair->src_st.st_nlink > 1) {
+			message_warning(_("%s: Input file has more "
+					"than one hard link, "
+					"skipping"), pair->src_name);
+			goto error;
+		}
+#endif
+	}
+
+	return false;
+
+error_msg:
+	message_error("%s: %s", pair->src_name, strerror(errno));
+error:
+	(void)close(pair->src_fd);
+	return true;
+}
+
+
+extern file_pair *
+io_open_src(const char *src_name)
+{
+	if (is_empty_filename(src_name))
+		return NULL;
+
+	// Since we have only one file open at a time, we can use
+	// a statically allocated structure.
+	static file_pair pair;
+
+	pair = (file_pair){
+		.src_name = src_name,
+		.dest_name = NULL,
+		.src_fd = -1,
+		.dest_fd = -1,
+		.src_eof = false,
+		.dest_try_sparse = false,
+		.dest_pending_sparse = 0,
+	};
+
+	// Block the signals, for which we have a custom signal handler, so
+	// that we don't need to worry about EINTR.
+	signals_block();
+	const bool error = io_open_src_real(&pair);
+	signals_unblock();
+
+	return error ? NULL : &pair;
+}
+
+
+/// \brief      Closes source file of the file_pair structure
+///
+/// \param      pair    File whose src_fd should be closed
+/// \param      success If true, the file will be removed from the disk if
+///                     closing succeeds and --keep hasn't been used.
+static void
+io_close_src(file_pair *pair, bool success)
+{
+	if (pair->src_fd != STDIN_FILENO && pair->src_fd != -1) {
+#ifdef TUKLIB_DOSLIKE
+		(void)close(pair->src_fd);
+#endif
+
+		// If we are going to unlink(), do it before closing the file.
+		// This way there's no risk that someone replaces the file and
+		// happens to get same inode number, which would make us
+		// unlink() wrong file.
+		//
+		// NOTE: DOS-like systems are an exception to this, because
+		// they don't allow unlinking files that are open. *sigh*
+		if (success && !opt_keep_original)
+			io_unlink(pair->src_name, &pair->src_st);
+
+#ifndef TUKLIB_DOSLIKE
+		(void)close(pair->src_fd);
+#endif
+	}
+
+	return;
+}
+
+
+static bool
+io_open_dest_real(file_pair *pair)
+{
+	if (opt_stdout || pair->src_fd == STDIN_FILENO) {
+		// We don't modify or free() this.
+		pair->dest_name = (char *)"(stdout)";
+		pair->dest_fd = STDOUT_FILENO;
+#ifdef TUKLIB_DOSLIKE
+		setmode(STDOUT_FILENO, O_BINARY);
+#endif
+	} else {
+		pair->dest_name = suffix_get_dest_name(pair->src_name);
+		if (pair->dest_name == NULL)
+			return true;
+
+		// If --force was used, unlink the target file first.
+		if (opt_force && unlink(pair->dest_name) && errno != ENOENT) {
+			message_error(_("%s: Cannot remove: %s"),
+					pair->dest_name, strerror(errno));
+			free(pair->dest_name);
+			return true;
+		}
+
+		// Open the file.
+		const int flags = O_WRONLY | O_BINARY | O_NOCTTY
+				| O_CREAT | O_EXCL;
+		const mode_t mode = S_IRUSR | S_IWUSR;
+		pair->dest_fd = open(pair->dest_name, flags, mode);
+
+		if (pair->dest_fd == -1) {
+			message_error("%s: %s", pair->dest_name,
+					strerror(errno));
+			free(pair->dest_name);
+			return true;
+		}
+	}
+
+	// If this really fails... well, we have a safe fallback.
+	if (fstat(pair->dest_fd, &pair->dest_st)) {
+#if defined(__VMS)
+		pair->dest_st.st_ino[0] = 0;
+		pair->dest_st.st_ino[1] = 0;
+		pair->dest_st.st_ino[2] = 0;
+#elif !defined(TUKLIB_DOSLIKE)
+		pair->dest_st.st_dev = 0;
+		pair->dest_st.st_ino = 0;
+#endif
+#ifndef TUKLIB_DOSLIKE
+	} else if (try_sparse && opt_mode == MODE_DECOMPRESS) {
+		// When writing to standard output, we need to be extra
+		// careful:
+		//  - It may be connected to something else than
+		//    a regular file.
+		//  - We aren't necessarily writing to a new empty file
+		//    or to the end of an existing file.
+		//  - O_APPEND may be active.
+		//
+		// TODO: I'm keeping this disabled for DOS-like systems
+		// for now. FAT doesn't support sparse files, but NTFS
+		// does, so maybe this should be enabled on Windows after
+		// some testing.
+		if (pair->dest_fd == STDOUT_FILENO) {
+			if (!S_ISREG(pair->dest_st.st_mode))
+				return false;
+
+			const int flags = fcntl(STDOUT_FILENO, F_GETFL);
+			if (flags == -1)
+				return false;
+
+			if (flags & O_APPEND) {
+				// Creating a sparse file is not possible
+				// when O_APPEND is active (it's used by
+				// shell's >> redirection). As I understand
+				// it, it is safe to temporarily disable
+				// O_APPEND in xz, because if someone
+				// happened to write to the same file at the
+				// same time, results would be bad anyway
+				// (users shouldn't assume that xz uses any
+				// specific block size when writing data).
+				//
+				// The write position may be something else
+				// than the end of the file, so we must fix
+				// it to start writing at the end of the file
+				// to imitate O_APPEND.
+				if (lseek(STDOUT_FILENO, 0, SEEK_END) == -1)
+					return false;
+
+				if (fcntl(STDOUT_FILENO, F_SETFL,
+						stdout_flags & ~O_APPEND))
+					return false;
+
+				// Remember the flags so that io_close_dest()
+				// can restore them.
+				stdout_flags = flags;
+
+			} else if (lseek(STDOUT_FILENO, 0, SEEK_CUR)
+					!= pair->dest_st.st_size) {
+				// Writing won't start exactly at the end
+				// of the file. We cannot use sparse output,
+				// because it would probably corrupt the file.
+				return false;
+			}
+		}
+
+		pair->dest_try_sparse = true;
+#endif
+	}
+
+	return false;
+}
+
+
+extern bool
+io_open_dest(file_pair *pair)
+{
+	signals_block();
+	const bool ret = io_open_dest_real(pair);
+	signals_unblock();
+	return ret;
+}
+
+
+/// \brief      Closes destination file of the file_pair structure
+///
+/// \param      pair    File whose dest_fd should be closed
+/// \param      success If false, the file will be removed from the disk.
+///
+/// \return     Zero if closing succeeds. On error, -1 is returned and
+///             error message printed.
+static bool
+io_close_dest(file_pair *pair, bool success)
+{
+#ifndef TUKLIB_DOSLIKE
+	// If io_open_dest() has disabled O_APPEND, restore it here.
+	if (stdout_flags != 0) {
+		assert(pair->dest_fd == STDOUT_FILENO);
+
+		const int fail = fcntl(STDOUT_FILENO, F_SETFL, stdout_flags);
+		stdout_flags = 0;
+
+		if (fail) {
+			message_error(_("Error restoring the O_APPEND flag "
+					"to standard output: %s"),
+					strerror(errno));
+			return true;
+		}
+	}
+#endif
+
+	if (pair->dest_fd == -1 || pair->dest_fd == STDOUT_FILENO)
+		return false;
+
+	if (close(pair->dest_fd)) {
+		message_error(_("%s: Closing the file failed: %s"),
+				pair->dest_name, strerror(errno));
+
+		// Closing destination file failed, so we cannot trust its
+		// contents. Get rid of junk:
+		io_unlink(pair->dest_name, &pair->dest_st);
+		free(pair->dest_name);
+		return true;
+	}
+
+	// If the operation using this file wasn't successful, we git rid
+	// of the junk file.
+	if (!success)
+		io_unlink(pair->dest_name, &pair->dest_st);
+
+	free(pair->dest_name);
+
+	return false;
+}
+
+
+extern void
+io_close(file_pair *pair, bool success)
+{
+	// Take care of sparseness at the end of the output file.
+	if (success && pair->dest_try_sparse
+			&& pair->dest_pending_sparse > 0) {
+		// Seek forward one byte less than the size of the pending
+		// hole, then write one zero-byte. This way the file grows
+		// to its correct size. An alternative would be to use
+		// ftruncate() but that isn't portable enough (e.g. it
+		// doesn't work with FAT on Linux; FAT isn't that important
+		// since it doesn't support sparse files anyway, but we don't
+		// want to create corrupt files on it).
+		if (lseek(pair->dest_fd, pair->dest_pending_sparse - 1,
+				SEEK_CUR) == -1) {
+			message_error(_("%s: Seeking failed when trying "
+					"to create a sparse file: %s"),
+					pair->dest_name, strerror(errno));
+			success = false;
+		} else {
+			const uint8_t zero[1] = { '\0' };
+			if (io_write_buf(pair, zero, 1))
+				success = false;
+		}
+	}
+
+	signals_block();
+
+	// Copy the file attributes. We need to skip this if destination
+	// file isn't open or it is standard output.
+	if (success && pair->dest_fd != -1 && pair->dest_fd != STDOUT_FILENO)
+		io_copy_attrs(pair);
+
+	// Close the destination first. If it fails, we must not remove
+	// the source file!
+	if (io_close_dest(pair, success))
+		success = false;
+
+	// Close the source file, and unlink it if the operation using this
+	// file pair was successful and we haven't requested to keep the
+	// source file.
+	io_close_src(pair, success);
+
+	signals_unblock();
+
+	return;
+}
+
+
+extern size_t
+io_read(file_pair *pair, io_buf *buf_union, size_t size)
+{
+	// We use small buffers here.
+	assert(size < SSIZE_MAX);
+
+	uint8_t *buf = buf_union->u8;
+	size_t left = size;
+
+	while (left > 0) {
+		const ssize_t amount = read(pair->src_fd, buf, left);
+
+		if (amount == 0) {
+			pair->src_eof = true;
+			break;
+		}
+
+		if (amount == -1) {
+			if (errno == EINTR) {
+				if (user_abort)
+					return SIZE_MAX;
+
+				continue;
+			}
+
+			message_error(_("%s: Read error: %s"),
+					pair->src_name, strerror(errno));
+
+			// FIXME Is this needed?
+			pair->src_eof = true;
+
+			return SIZE_MAX;
+		}
+
+		buf += (size_t)(amount);
+		left -= (size_t)(amount);
+	}
+
+	return size - left;
+}
+
+
+extern bool
+io_pread(file_pair *pair, io_buf *buf, size_t size, off_t pos)
+{
+	// Using lseek() and read() is more portable than pread() and
+	// for us it is as good as real pread().
+	if (lseek(pair->src_fd, pos, SEEK_SET) != pos) {
+		message_error(_("%s: Error seeking the file: %s"),
+				pair->src_name, strerror(errno));
+		return true;
+	}
+
+	const size_t amount = io_read(pair, buf, size);
+	if (amount == SIZE_MAX)
+		return true;
+
+	if (amount != size) {
+		message_error(_("%s: Unexpected end of file"),
+				pair->src_name);
+		return true;
+	}
+
+	return false;
+}
+
+
+static bool
+is_sparse(const io_buf *buf)
+{
+	assert(IO_BUFFER_SIZE % sizeof(uint64_t) == 0);
+
+	for (size_t i = 0; i < ARRAY_SIZE(buf->u64); ++i)
+		if (buf->u64[i] != 0)
+			return false;
+
+	return true;
+}
+
+
+static bool
+io_write_buf(file_pair *pair, const uint8_t *buf, size_t size)
+{
+	assert(size < SSIZE_MAX);
+
+	while (size > 0) {
+		const ssize_t amount = write(pair->dest_fd, buf, size);
+		if (amount == -1) {
+			if (errno == EINTR) {
+				if (user_abort)
+					return -1;
+
+				continue;
+			}
+
+			// Handle broken pipe specially. gzip and bzip2
+			// don't print anything on SIGPIPE. In addition,
+			// gzip --quiet uses exit status 2 (warning) on
+			// broken pipe instead of whatever raise(SIGPIPE)
+			// would make it return. It is there to hide "Broken
+			// pipe" message on some old shells (probably old
+			// GNU bash).
+			//
+			// We don't do anything special with --quiet, which
+			// is what bzip2 does too. If we get SIGPIPE, we
+			// will handle it like other signals by setting
+			// user_abort, and get EPIPE here.
+			if (errno != EPIPE)
+				message_error(_("%s: Write error: %s"),
+					pair->dest_name, strerror(errno));
+
+			return true;
+		}
+
+		buf += (size_t)(amount);
+		size -= (size_t)(amount);
+	}
+
+	return false;
+}
+
+
+extern bool
+io_write(file_pair *pair, const io_buf *buf, size_t size)
+{
+	assert(size <= IO_BUFFER_SIZE);
+
+	if (pair->dest_try_sparse) {
+		// Check if the block is sparse (contains only zeros). If it
+		// sparse, we just store the amount and return. We will take
+		// care of actually skipping over the hole when we hit the
+		// next data block or close the file.
+		//
+		// Since io_close() requires that dest_pending_sparse > 0
+		// if the file ends with sparse block, we must also return
+		// if size == 0 to avoid doing the lseek().
+		if (size == IO_BUFFER_SIZE) {
+			if (is_sparse(buf)) {
+				pair->dest_pending_sparse += size;
+				return false;
+			}
+		} else if (size == 0) {
+			return false;
+		}
+
+		// This is not a sparse block. If we have a pending hole,
+		// skip it now.
+		if (pair->dest_pending_sparse > 0) {
+			if (lseek(pair->dest_fd, pair->dest_pending_sparse,
+					SEEK_CUR) == -1) {
+				message_error(_("%s: Seeking failed when "
+						"trying to create a sparse "
+						"file: %s"), pair->dest_name,
+						strerror(errno));
+				return true;
+			}
+
+			pair->dest_pending_sparse = 0;
+		}
+	}
+
+	return io_write_buf(pair, buf->u8, size);
+}
diff --git a/src/xz/file_io.h b/src/xz/file_io.h
new file mode 100644
index 0000000..967da86
--- /dev/null
+++ b/src/xz/file_io.h
@@ -0,0 +1,129 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       file_io.h
+/// \brief      I/O types and functions
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// Some systems have suboptimal BUFSIZ. Use a bit bigger value on them.
+// We also need that IO_BUFFER_SIZE is a multiple of 8 (sizeof(uint64_t))
+#if BUFSIZ <= 1024
+#	define IO_BUFFER_SIZE 8192
+#else
+#	define IO_BUFFER_SIZE (BUFSIZ & ~7U)
+#endif
+
+
+/// is_sparse() accesses the buffer as uint64_t for maximum speed.
+/// Use an union to make sure that the buffer is properly aligned.
+typedef union {
+	uint8_t u8[IO_BUFFER_SIZE];
+	uint32_t u32[IO_BUFFER_SIZE / sizeof(uint32_t)];
+	uint64_t u64[IO_BUFFER_SIZE / sizeof(uint64_t)];
+} io_buf;
+
+
+typedef struct {
+	/// Name of the source filename (as given on the command line) or
+	/// pointer to static "(stdin)" when reading from standard input.
+	const char *src_name;
+
+	/// Destination filename converted from src_name or pointer to static
+	/// "(stdout)" when writing to standard output.
+	char *dest_name;
+
+	/// File descriptor of the source file
+	int src_fd;
+
+	/// File descriptor of the target file
+	int dest_fd;
+
+	/// True once end of the source file has been detected.
+	bool src_eof;
+
+	/// If true, we look for long chunks of zeros and try to create
+	/// a sparse file.
+	bool dest_try_sparse;
+
+	/// This is used only if dest_try_sparse is true. This holds the
+	/// number of zero bytes we haven't written out, because we plan
+	/// to make that byte range a sparse chunk.
+	off_t dest_pending_sparse;
+
+	/// Stat of the source file.
+	struct stat src_st;
+
+	/// Stat of the destination file.
+	struct stat dest_st;
+
+} file_pair;
+
+
+/// \brief      Initialize the I/O module
+extern void io_init(void);
+
+
+/// \brief      Disable creation of sparse files when decompressing
+extern void io_no_sparse(void);
+
+
+/// \brief      Open the source file
+extern file_pair *io_open_src(const char *src_name);
+
+
+/// \brief      Open the destination file
+extern bool io_open_dest(file_pair *pair);
+
+
+/// \brief      Closes the file descriptors and frees possible allocated memory
+///
+/// The success argument determines if source or destination file gets
+/// unlinked:
+///  - false: The destination file is unlinked.
+///  - true: The source file is unlinked unless writing to stdout or --keep
+///    was used.
+extern void io_close(file_pair *pair, bool success);
+
+
+/// \brief      Reads from the source file to a buffer
+///
+/// \param      pair    File pair having the source file open for reading
+/// \param      buf     Destination buffer to hold the read data
+/// \param      size    Size of the buffer; assumed be smaller than SSIZE_MAX
+///
+/// \return     On success, number of bytes read is returned. On end of
+///             file zero is returned and pair->src_eof set to true.
+///             On error, SIZE_MAX is returned and error message printed.
+extern size_t io_read(file_pair *pair, io_buf *buf, size_t size);
+
+
+/// \brief      Read from source file from given offset to a buffer
+///
+/// This is remotely similar to standard pread(). This uses lseek() though,
+/// so the read offset is changed on each call.
+///
+/// \param      pair    Seekable source file
+/// \param      buf     Destination buffer
+/// \param      size    Amount of data to read
+/// \param      pos     Offset relative to the beginning of the file,
+///                     from which the data should be read.
+///
+/// \return     On success, false is returned. On error, error message
+///             is printed and true is returned.
+extern bool io_pread(file_pair *pair, io_buf *buf, size_t size, off_t pos);
+
+
+/// \brief      Writes a buffer to the destination file
+///
+/// \param      pair    File pair having the destination file open for writing
+/// \param      buf     Buffer containing the data to be written
+/// \param      size    Size of the buffer; assumed be smaller than SSIZE_MAX
+///
+/// \return     On success, zero is returned. On error, -1 is returned
+///             and error message printed.
+extern bool io_write(file_pair *pair, const io_buf *buf, size_t size);
diff --git a/src/xz/hardware.c b/src/xz/hardware.c
new file mode 100644
index 0000000..74742fc
--- /dev/null
+++ b/src/xz/hardware.c
@@ -0,0 +1,112 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       hardware.c
+/// \brief      Detection of available hardware resources
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "private.h"
+#include "tuklib_cpucores.h"
+
+
+/// Maximum number of free *coder* threads. This can be set with
+/// the --threads=NUM command line option.
+static uint32_t threadlimit;
+
+/// Memory usage limit
+static uint64_t memlimit;
+
+/// Total amount of physical RAM
+static uint64_t total_ram;
+
+
+extern void
+hardware_threadlimit_set(uint32_t new_threadlimit)
+{
+	if (new_threadlimit == 0) {
+		// The default is the number of available CPU cores.
+		threadlimit = tuklib_cpucores();
+		if (threadlimit == 0)
+			threadlimit = 1;
+	} else {
+		threadlimit = new_threadlimit;
+	}
+
+	return;
+}
+
+
+extern uint32_t
+hardware_threadlimit_get(void)
+{
+	return threadlimit;
+}
+
+
+extern void
+hardware_memlimit_set(uint64_t new_memlimit)
+{
+	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;
+			}
+		}
+	}
+
+	return;
+}
+
+
+extern void
+hardware_memlimit_set_percentage(uint32_t percentage)
+{
+	assert(percentage > 0);
+	assert(percentage <= 100);
+
+	memlimit = percentage * total_ram / 100;
+	return;
+}
+
+
+extern uint64_t
+hardware_memlimit_get(void)
+{
+	return memlimit;
+}
+
+
+extern void
+hardware_init(void)
+{
+	// Get the amount of RAM. If we cannot determine it,
+	// use the assumption defined by the configure script.
+	total_ram = lzma_physmem();
+	if (total_ram == 0)
+		total_ram = (uint64_t)(ASSUME_RAM) * 1024 * 1024;
+
+	// Set the defaults.
+	hardware_memlimit_set(0);
+	hardware_threadlimit_set(0);
+	return;
+}
diff --git a/src/xz/hardware.h b/src/xz/hardware.h
new file mode 100644
index 0000000..b2cf34c
--- /dev/null
+++ b/src/xz/hardware.h
@@ -0,0 +1,35 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       hardware.h
+/// \brief      Detection of available hardware resources
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+/// Initialize some hardware-specific variables, which are needed by other
+/// hardware_* functions.
+extern void hardware_init(void);
+
+
+/// Set custom value for maximum number of coder threads.
+extern void hardware_threadlimit_set(uint32_t threadlimit);
+
+/// Get the maximum number of coder threads. Some additional helper threads
+/// are allowed on top of this).
+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);
diff --git a/src/xz/list.c b/src/xz/list.c
new file mode 100644
index 0000000..dda7c9b
--- /dev/null
+++ b/src/xz/list.c
@@ -0,0 +1,1032 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       list.c
+/// \brief      Listing information about .xz files
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "private.h"
+#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
+	const char *filter_chain;
+
+} block_header_info;
+
+
+/// Check ID to string mapping
+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",
+};
+
+
+/// 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.
+static struct {
+	uint64_t files;
+	uint64_t streams;
+	uint64_t blocks;
+	uint64_t compressed_size;
+	uint64_t uncompressed_size;
+	uint64_t stream_padding;
+	uint64_t memusage_max;
+	uint32_t checks;
+	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      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.
+///
+// TODO: This function is pretty big. liblzma should have a function that
+// takes a callback function to parse the Index(es) from a .xz file to make
+// it easy for applications.
+static bool
+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);
+		return true;
+	}
+
+	if (pair->src_st.st_size < 2 * LZMA_STREAM_HEADER_SIZE) {
+		message_error(_("%s: Too small to be a valid .xz file"),
+				pair->src_name);
+		return true;
+	}
+
+	io_buf buf;
+	lzma_stream_flags header_flags;
+	lzma_stream_flags footer_flags;
+	lzma_ret ret;
+
+	// lzma_stream for the Index decoder
+	lzma_stream strm = LZMA_STREAM_INIT;
+
+	// All Indexes decoded so far
+	lzma_index *combined_index = NULL;
+
+	// The Index currently being decoded
+	lzma_index *this_index = NULL;
+
+	// Current position in the file. We parse the file backwards so
+	// initialize it to point to the end of the file.
+	off_t pos = pair->src_st.st_size;
+
+	// Each loop iteration decodes one Index.
+	do {
+		// Check that there is enough data left to contain at least
+		// the Stream Header and Stream Footer. This check cannot
+		// fail in the first pass of this loop.
+		if (pos < 2 * LZMA_STREAM_HEADER_SIZE) {
+			message_error("%s: %s", pair->src_name,
+					message_strm(LZMA_DATA_ERROR));
+			goto error;
+		}
+
+		pos -= LZMA_STREAM_HEADER_SIZE;
+		lzma_vli stream_padding = 0;
+
+		// Locate the Stream Footer. There may be Stream Padding which
+		// we must skip when reading backwards.
+		while (true) {
+			if (pos < LZMA_STREAM_HEADER_SIZE) {
+				message_error("%s: %s", pair->src_name,
+						message_strm(
+							LZMA_DATA_ERROR));
+				goto error;
+			}
+
+			if (io_pread(pair, &buf,
+					LZMA_STREAM_HEADER_SIZE, pos))
+				goto error;
+
+			// Stream Padding is always a multiple of four bytes.
+			int i = 2;
+			if (buf.u32[i] != 0)
+				break;
+
+			// To avoid calling io_pread() for every four bytes
+			// of Stream Padding, take advantage that we read
+			// 12 bytes (LZMA_STREAM_HEADER_SIZE) already and
+			// check them too before calling io_pread() again.
+			do {
+				stream_padding += 4;
+				pos -= 4;
+				--i;
+			} while (i >= 0 && buf.u32[i] == 0);
+		}
+
+		// Decode the Stream Footer.
+		ret = lzma_stream_footer_decode(&footer_flags, buf.u8);
+		if (ret != LZMA_OK) {
+			message_error("%s: %s", pair->src_name,
+					message_strm(ret));
+			goto error;
+		}
+
+		// Check that the size of the Index field looks sane.
+		lzma_vli index_size = footer_flags.backward_size;
+		if ((lzma_vli)(pos) < index_size + LZMA_STREAM_HEADER_SIZE) {
+			message_error("%s: %s", pair->src_name,
+					message_strm(LZMA_DATA_ERROR));
+			goto error;
+		}
+
+		// Set pos to the beginning of the Index.
+		pos -= index_size;
+
+		// See how much memory we can use for decoding this Index.
+		uint64_t memlimit = hardware_memlimit_get();
+		uint64_t memused = 0;
+		if (combined_index != NULL) {
+			memused = lzma_index_memused(combined_index);
+			if (memused > memlimit)
+				message_bug();
+
+			memlimit -= memused;
+		}
+
+		// Decode the Index.
+		ret = lzma_index_decoder(&strm, &this_index, memlimit);
+		if (ret != LZMA_OK) {
+			message_error("%s: %s", pair->src_name,
+					message_strm(ret));
+			goto error;
+		}
+
+		do {
+			// Don't give the decoder more input than the
+			// Index size.
+			strm.avail_in = my_min(IO_BUFFER_SIZE, index_size);
+			if (io_pread(pair, &buf, strm.avail_in, pos))
+				goto error;
+
+			pos += strm.avail_in;
+			index_size -= strm.avail_in;
+
+			strm.next_in = buf.u8;
+			ret = lzma_code(&strm, LZMA_RUN);
+
+		} while (ret == LZMA_OK);
+
+		// If the decoding seems to be successful, check also that
+		// the Index decoder consumed as much input as indicated
+		// by the Backward Size field.
+		if (ret == LZMA_STREAM_END)
+			if (index_size != 0 || strm.avail_in != 0)
+				ret = LZMA_DATA_ERROR;
+
+		if (ret != LZMA_STREAM_END) {
+			// LZMA_BUFFER_ERROR means that the Index decoder
+			// would have liked more input than what the Index
+			// size should be according to Stream Footer.
+			// The message for LZMA_DATA_ERROR makes more
+			// sense in that case.
+			if (ret == LZMA_BUF_ERROR)
+				ret = LZMA_DATA_ERROR;
+
+			message_error("%s: %s", pair->src_name,
+					message_strm(ret));
+
+			// If the error was too low memory usage limit,
+			// show also how much memory would have been needed.
+			if (ret == LZMA_MEMLIMIT_ERROR) {
+				uint64_t needed = lzma_memusage(&strm);
+				if (UINT64_MAX - needed < memused)
+					needed = UINT64_MAX;
+				else
+					needed += memused;
+
+				message_mem_needed(V_ERROR, needed);
+			}
+
+			goto error;
+		}
+
+		// Decode the Stream Header and check that its Stream Flags
+		// match the Stream Footer.
+		pos -= footer_flags.backward_size + LZMA_STREAM_HEADER_SIZE;
+		if ((lzma_vli)(pos) < lzma_index_total_size(this_index)) {
+			message_error("%s: %s", pair->src_name,
+					message_strm(LZMA_DATA_ERROR));
+			goto error;
+		}
+
+		pos -= lzma_index_total_size(this_index);
+		if (io_pread(pair, &buf, LZMA_STREAM_HEADER_SIZE, pos))
+			goto error;
+
+		ret = lzma_stream_header_decode(&header_flags, buf.u8);
+		if (ret != LZMA_OK) {
+			message_error("%s: %s", pair->src_name,
+					message_strm(ret));
+			goto error;
+		}
+
+		ret = lzma_stream_flags_compare(&header_flags, &footer_flags);
+		if (ret != LZMA_OK) {
+			message_error("%s: %s", pair->src_name,
+					message_strm(ret));
+			goto error;
+		}
+
+		// Store the decoded Stream Flags into this_index. This is
+		// needed so that we can print which Check is used in each
+		// Stream.
+		ret = lzma_index_stream_flags(this_index, &footer_flags);
+		if (ret != LZMA_OK)
+			message_bug();
+
+		// Store also the size of the Stream Padding field. It is
+		// needed to show the offsets of the Streams correctly.
+		ret = lzma_index_stream_padding(this_index, stream_padding);
+		if (ret != LZMA_OK)
+			message_bug();
+
+		if (combined_index != NULL) {
+			// Append the earlier decoded Indexes
+			// after this_index.
+			ret = lzma_index_cat(
+					this_index, combined_index, NULL);
+			if (ret != LZMA_OK) {
+				message_error("%s: %s", pair->src_name,
+						message_strm(ret));
+				goto error;
+			}
+		}
+
+		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.
+	xfi->idx = combined_index;
+	return false;
+
+error:
+	// Something went wrong, free the allocated memory.
+	lzma_end(&strm);
+	lzma_index_end(combined_index, NULL);
+	lzma_index_end(this_index, NULL);
+	return true;
+}
+
+
+/// \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.
+	bhi->filter_chain = message_filters_to_str(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.
+static const char *
+get_ratio(uint64_t compressed_size, uint64_t uncompressed_size)
+{
+	if (uncompressed_size == 0)
+		return "---";
+
+	const double ratio = (double)(compressed_size)
+			/ (double)(uncompressed_size);
+	if (ratio > 9.999)
+		return "---";
+
+	static char buf[6];
+	snprintf(buf, sizeof(buf), "%.3f", ratio);
+	return buf;
+}
+
+
+/// \brief      Get a comma-separated list of Check names
+///
+/// \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)
+{
+	assert(checks != 0);
+
+	static char buf[sizeof(check_names)];
+	char *pos = buf;
+	size_t left = sizeof(buf);
+
+	const char *sep = space_after_comma ? ", " : ",";
+	bool comma = false;
+
+	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 = true;
+		}
+	}
+
+	return buf;
+}
+
+
+static bool
+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)
+		// 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.
+		puts(_("Strms  Blocks   Compressed Uncompressed  Ratio  "
+				"Check   Filename"));
+	}
+
+	printf("%5s %7s  %11s  %11s  %5s  %-7s %s\n",
+			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)),
+			get_check_names(lzma_index_checks(xfi->idx), false),
+			pair->src_name);
+
+	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, uint64_t stream_padding)
+{
+	printf(_("  Streams:            %s\n"),
+			uint64_to_str(stream_count, 0));
+	printf(_("  Blocks:             %s\n"),
+			uint64_to_str(block_count, 0));
+	printf(_("  Compressed size:    %s\n"),
+			uint64_to_nicestr(compressed_size,
+				NICESTR_B, NICESTR_TIB, true, 0));
+	printf(_("  Uncompressed size:  %s\n"),
+			uint64_to_nicestr(uncompressed_size,
+				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(_("  Stream padding:     %s\n"),
+			uint64_to_nicestr(stream_padding,
+				NICESTR_B, NICESTR_TIB, true, 0));
+	return;
+}
+
+
+static bool
+print_info_adv(xz_file_info *xfi, file_pair *pair)
+{
+	// Print the overall information.
+	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.
+	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)) {
+		printf("    %6s %9s %15s %15s ",
+				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("%15s %15s  %5s  %-10s %7s\n",
+				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));
+
+		// Update the maximum Check size.
+		if (lzma_check_size(iter.stream.flags->check) > check_max)
+			check_max = lzma_check_size(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);
+
+		// Print the headings.
+		printf(_("  Blocks:\n    Stream     Block"
+			"      CompOffset    UncompOffset"
+			"       TotalSize      UncompSize  Ratio  Check"));
+
+		if (detailed)
+			printf(_("      %-*s  Header  Flags        CompSize"
+					"    MemUsage  Filters"),
+					checkval_width, _("CheckVal"));
+
+		putchar('\n');
+
+		lzma_index_iter_init(&iter, xfi->idx);
+
+		// Iterate over the Blocks.
+		while (!lzma_index_iter_next(&iter, LZMA_INDEX_ITER_BLOCK)) {
+			if (detailed && parse_details(pair, &iter, &bhi, xfi))
+					return true;
+
+			printf("    %6s %9s %15s %15s ",
+				uint64_to_str(iter.stream.number, 0),
+				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("%15s %15s  %5s  %-*s",
+				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),
+				detailed ? 11 : 1,
+				check_names[iter.stream.flags->check]);
+
+			if (detailed) {
+				// Show MiB for memory usage, because it
+				// is the only size which is not in bytes.
+				const lzma_vli compressed_size
+						= iter.block.unpadded_size
+						- bhi.header_size
+						- lzma_check_size(
+						iter.stream.flags->check);
+				printf("%-*s  %6s  %-5s %15s %7s MiB  %s",
+					checkval_width, 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);
+			}
+
+			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 bool
+print_info_robot(xz_file_info *xfi, file_pair *pair)
+{
+	printf("name\t%s\n", pair->src_name);
+
+	printf("file\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64
+			"\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)),
+			get_check_names(lzma_index_checks(xfi->idx), false),
+			xfi->stream_padding);
+
+	if (message_verbosity_get() >= V_VERBOSE) {
+		lzma_index_iter iter;
+		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%" 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),
+				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",
+					iter.stream.number,
+					iter.block.number_in_stream,
+					iter.block.number_in_file,
+					iter.block.compressed_file_offset,
+					iter.block.uncompressed_file_offset,
+					iter.block.total_size,
+					iter.block.uncompressed_size,
+					get_ratio(iter.block.total_size,
+						iter.block.uncompressed_size),
+					check_names[iter.stream.flags->check]);
+
+			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');
+		}
+	}
+
+	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 xz_file_info *xfi)
+{
+	// TODO: Integer overflow checks
+	++totals.files;
+	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;
+}
+
+
+static void
+print_totals_basic(void)
+{
+	// Print a separator line.
+	char line[80];
+	memset(line, '-', sizeof(line));
+	line[sizeof(line) - 1] = '\0';
+	puts(line);
+
+	// Print the totals except the file count, which needs
+	// special handling.
+	printf("%5s %7s  %11s  %11s  %5s  %-7s ",
+			uint64_to_str(totals.streams, 0),
+			uint64_to_str(totals.blocks, 1),
+			uint64_to_nicestr(totals.compressed_size,
+				NICESTR_B, NICESTR_TIB, false, 2),
+			uint64_to_nicestr(totals.uncompressed_size,
+				NICESTR_B, NICESTR_TIB, false, 3),
+			get_ratio(totals.compressed_size,
+				totals.uncompressed_size),
+			get_check_names(totals.checks, false));
+
+	// 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.
+	//
+	// 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",
+			totals.files <= ULONG_MAX ? totals.files
+				: (totals.files % 1000000) + 1000000),
+			uint64_to_str(totals.files, 0));
+
+	return;
+}
+
+
+static void
+print_totals_adv(void)
+{
+	putchar('\n');
+	puts(_("Totals:"));
+	printf(_("  Number of files:    %s\n"),
+			uint64_to_str(totals.files, 0));
+	print_adv_helper(totals.streams, totals.blocks,
+			totals.compressed_size, totals.uncompressed_size,
+			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;
+}
+
+
+static void
+print_totals_robot(void)
+{
+	printf("totals\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64
+			"\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),
+			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;
+}
+
+
+extern void
+list_totals(void)
+{
+	if (opt_robot) {
+		// Always print totals in --robot mode. It can be convenient
+		// in some cases and doesn't complicate usage of the
+		// single-file case much.
+		print_totals_robot();
+
+	} else if (totals.files > 1) {
+		// For non-robot mode, totals are printed only if there
+		// is more than one file.
+		if (message_verbosity_get() <= V_WARNING)
+			print_totals_basic();
+		else
+			print_totals_adv();
+	}
+
+	return;
+}
+
+
+extern void
+list_file(const char *filename)
+{
+	if (opt_format != FORMAT_XZ && opt_format != FORMAT_AUTO)
+		message_fatal(_("--list works only on .xz files "
+				"(--format=xz or --format=auto)"));
+
+	message_filename(filename);
+
+	if (filename == stdin_filename) {
+		message_error(_("--list does not support reading from "
+				"standard input"));
+		return;
+	}
+
+	// Unset opt_stdout so that io_open_src() won't accept special files.
+	// Set opt_force so that io_open_src() will follow symlinks.
+	opt_stdout = false;
+	opt_force = true;
+	file_pair *pair = io_open_src(filename);
+	if (pair == NULL)
+		return;
+
+	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
+		//    once or twice
+		//  - Normal --list without --verbose
+		//  - --list with one or two --verbose
+		if (opt_robot)
+			fail = print_info_robot(&xfi, pair);
+		else if (message_verbosity_get() <= V_WARNING)
+			fail = print_info_basic(&xfi, pair);
+		else
+			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(xfi.idx, NULL);
+	}
+
+	io_close(pair, false);
+	return;
+}
diff --git a/src/xz/list.h b/src/xz/list.h
new file mode 100644
index 0000000..a4c6ec7
--- /dev/null
+++ b/src/xz/list.h
@@ -0,0 +1,18 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       list.h
+/// \brief      List information about .xz files
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+/// \brief      List information about the given .xz file
+extern void list_file(const char *filename);
+
+
+/// \brief      Show the totals after all files have been listed
+extern void list_totals(void);
diff --git a/src/xz/main.c b/src/xz/main.c
new file mode 100644
index 0000000..8196c6e
--- /dev/null
+++ b/src/xz/main.c
@@ -0,0 +1,302 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       main.c
+/// \brief      main()
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#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;
+
+
+extern void
+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;
+}
+
+
+extern void
+set_exit_no_warn(void)
+{
+	no_warn = true;
+	return;
+}
+
+
+static const char *
+read_name(const args_info *args)
+{
+	// FIXME: Maybe we should have some kind of memory usage limit here
+	// like the tool has for the actual compression and decompression.
+	// Giving some huge text file with --files0 makes us to read the
+	// whole file in RAM.
+	static char *name = NULL;
+	static size_t size = 256;
+
+	// Allocate the initial buffer. This is never freed, since after it
+	// is no longer needed, the program exits very soon. It is safe to
+	// use xmalloc() and xrealloc() in this function, because while
+	// executing this function, no files are open for writing, and thus
+	// there's no need to cleanup anything before exiting.
+	if (name == NULL)
+		name = xmalloc(size);
+
+	// Write position in name
+	size_t pos = 0;
+
+	// Read one character at a time into name.
+	while (!user_abort) {
+		const int c = fgetc(args->files_file);
+
+		if (ferror(args->files_file)) {
+			// Take care of EINTR since we have established
+			// the signal handlers already.
+			if (errno == EINTR)
+				continue;
+
+			message_error(_("%s: Error reading filenames: %s"),
+					args->files_name, strerror(errno));
+			return NULL;
+		}
+
+		if (feof(args->files_file)) {
+			if (pos != 0)
+				message_error(_("%s: Unexpected end of input "
+						"when reading filenames"),
+						args->files_name);
+
+			return NULL;
+		}
+
+		if (c == args->files_delim) {
+			// We allow consecutive newline (--files) or '\0'
+			// characters (--files0), and ignore such empty
+			// filenames.
+			if (pos == 0)
+				continue;
+
+			// A non-empty name was read. Terminate it with '\0'
+			// and return it.
+			name[pos] = '\0';
+			return name;
+		}
+
+		if (c == '\0') {
+			// A null character was found when using --files,
+			// which expects plain text input separated with
+			// newlines.
+			message_error(_("%s: Null character found when "
+					"reading filenames; maybe you meant "
+					"to use `--files0' instead "
+					"of `--files'?"), args->files_name);
+			return NULL;
+		}
+
+		name[pos++] = c;
+
+		// Allocate more memory if needed. There must always be space
+		// at least for one character to allow terminating the string
+		// with '\0'.
+		if (pos == size) {
+			size *= 2;
+			name = xrealloc(name, size);
+		}
+	}
+
+	return NULL;
+}
+
+
+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);
+
+	// Initialize the file I/O. This makes sure that
+	// stdin, stdout, and stderr are something valid.
+	io_init();
+
+	// Set up the locale and message translations.
+	tuklib_gettext_init(PACKAGE, LOCALEDIR);
+
+	// Initialize handling of error/warning/other messages.
+	message_init();
+
+	// Set hardware-dependent default values. These can be overriden
+	// on the command line, thus this must be done before args_parse().
+	hardware_init();
+
+	// Parse the command line arguments and get an array of filenames.
+	// This doesn't return if something is wrong with the command line
+	// arguments. If there are no arguments, one filename ("-") is still
+	// returned to indicate stdin.
+	args_info args;
+	args_parse(&args, argc, argv);
+
+	if (opt_mode != MODE_LIST && opt_robot)
+		message_fatal(_("Compression and decompression with --robot "
+			"are not supported yet."));
+
+	// Tell the message handling code how many input files there are if
+	// we know it. This way the progress indicator can show it.
+	if (args.files_name != NULL)
+		message_set_files(0);
+	else
+		message_set_files(args.arg_count);
+
+	// Refuse to write compressed data to standard output if it is
+	// a terminal.
+	if (opt_mode == MODE_COMPRESS) {
+		if (opt_stdout || (args.arg_count == 1
+				&& strcmp(args.arg_names[0], "-") == 0)) {
+			if (is_tty_stdout()) {
+				message_try_help();
+				tuklib_exit(E_ERROR, E_ERROR, false);
+			}
+		}
+	}
+
+	// Set up the signal handlers. We don't need these before we
+	// start the actual action and not in --list mode, so this is
+	// done after parsing the command line arguments.
+	//
+	// It's good to keep signal handlers in normal compression and
+	// decompression modes even when only writing to stdout, because
+	// we might need to restore O_APPEND flag on stdout before exiting.
+	// In --test mode, signal handlers aren't really needed, but let's
+	// keep them there for consistency with normal decompression.
+	if (opt_mode != MODE_LIST)
+		signals_init();
+
+	// coder_run() handles compression, decompression, and testing.
+	// list_file() is for --list.
+	void (*run)(const char *filename) = opt_mode == MODE_LIST
+			 ? &list_file : &coder_run;
+
+	// Process the files given on the command line. Note that if no names
+	// were given, args_parse() gave us a fake "-" filename.
+	for (size_t i = 0; i < args.arg_count && !user_abort; ++i) {
+		if (strcmp("-", args.arg_names[i]) == 0) {
+			// Processing from stdin to stdout. Check that we
+			// aren't writing compressed data to a terminal or
+			// reading it from a terminal.
+			if (opt_mode == MODE_COMPRESS) {
+				if (is_tty_stdout())
+					continue;
+			} else if (is_tty_stdin()) {
+				continue;
+			}
+
+			// It doesn't make sense to compress data from stdin
+			// if we are supposed to read filenames from stdin
+			// too (enabled with --files or --files0).
+			if (args.files_name == stdin_filename) {
+				message_error(_("Cannot read data from "
+						"standard input when "
+						"reading filenames "
+						"from standard input"));
+				continue;
+			}
+
+			// Replace the "-" with a special pointer, which is
+			// recognized by coder_run() and other things.
+			// This way error messages get a proper filename
+			// string and the code still knows that it is
+			// handling the special case of stdin.
+			args.arg_names[i] = (char *)stdin_filename;
+		}
+
+		// Do the actual compression or decompression.
+		run(args.arg_names[i]);
+	}
+
+	// If --files or --files0 was used, process the filenames from the
+	// given file or stdin. Note that here we don't consider "-" to
+	// indicate stdin like we do with the command line arguments.
+	if (args.files_name != NULL) {
+		// read_name() checks for user_abort so we don't need to
+		// check it as loop termination condition.
+		while (true) {
+			const char *name = read_name(&args);
+			if (name == NULL)
+				break;
+
+			// read_name() doesn't return empty names.
+			assert(name[0] != '\0');
+			run(name);
+		}
+
+		if (args.files_name != stdin_filename)
+			(void)fclose(args.files_file);
+	}
+
+	// All files have now been handled. If in --list mode, display
+	// the totals before exiting. We don't have signal handlers
+	// enabled in --list mode, so we don't need to check user_abort.
+	if (opt_mode == MODE_LIST) {
+		assert(!user_abort);
+		list_totals();
+	}
+
+	// If we have got a signal, raise it to kill the program instead
+	// 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 (es == E_WARNING && no_warn)
+		es = E_SUCCESS;
+
+	tuklib_exit(es, E_ERROR, message_verbosity_get() != V_SILENT);
+}
diff --git a/src/xz/main.h b/src/xz/main.h
new file mode 100644
index 0000000..323f2f7
--- /dev/null
+++ b/src/xz/main.h
@@ -0,0 +1,30 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       main.h
+/// \brief      Miscellaneous declarations
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+/// Possible exit status values. These are the same as used by gzip and bzip2.
+enum exit_status_type {
+	E_SUCCESS  = 0,
+	E_ERROR    = 1,
+	E_WARNING  = 2,
+};
+
+
+/// Sets the exit status after a warning or error has occurred. If new_status
+/// is E_WARNING and the old exit status was already E_ERROR, the exit
+/// status is not changed.
+extern void set_exit_status(enum exit_status_type new_status);
+
+
+/// Use E_SUCCESS instead of E_WARNING if something worth a warning occurs
+/// but nothing worth an error has occurred. This is called when --no-warn
+/// is specified.
+extern void set_exit_no_warn(void);
diff --git a/src/xz/message.c b/src/xz/message.c
new file mode 100644
index 0000000..5044ea2
--- /dev/null
+++ b/src/xz/message.c
@@ -0,0 +1,1237 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       message.c
+/// \brief      Printing messages
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "private.h"
+
+#ifdef HAVE_SYS_TIME_H
+#	include <sys/time.h>
+#endif
+
+#include <stdarg.h>
+
+
+/// Number of the current file
+static unsigned int files_pos = 0;
+
+/// Total number of input files; zero if unknown.
+static unsigned int files_total;
+
+/// Verbosity level
+static enum message_verbosity verbosity = V_WARNING;
+
+/// Filename which we will print with the verbose messages
+static const char *filename;
+
+/// True once the a filename has been printed to stderr as part of progress
+/// message. If automatic progress updating isn't enabled, this becomes true
+/// after the first progress message has been printed due to user sending
+/// SIGINFO, SIGUSR1, or SIGALRM. Once this variable is true, we will print
+/// an empty line before the next filename to make the output more readable.
+static bool first_filename_printed = false;
+
+/// This is set to true when we have printed the current filename to stderr
+/// as part of a progress message. This variable is useful only if not
+/// updating progress automatically: if user sends many SIGINFO, SIGUSR1, or
+/// SIGALRM signals, we won't print the name of the same file multiple times.
+static bool current_filename_printed = false;
+
+/// True if we should print progress indicator and update it automatically
+/// if also verbose >= V_VERBOSE.
+static bool progress_automatic;
+
+/// True if message_progress_start() has been called but
+/// message_progress_end() hasn't been called yet.
+static bool progress_started = false;
+
+/// This is true when a progress message was printed and the cursor is still
+/// on the same line with the progress message. In that case, a newline has
+/// to be printed before any error messages.
+static bool progress_active = false;
+
+/// Pointer to lzma_stream used to do the encoding or decoding.
+static lzma_stream *progress_strm;
+
+/// Expected size of the input stream is needed to show completion percentage
+/// and estimate remaining time.
+static uint64_t expected_in_size;
+
+/// Time when we started processing the file
+static uint64_t start_time;
+
+
+// Use alarm() and SIGALRM when they are supported. This has two minor
+// advantages over the alternative of polling gettimeofday():
+//  - It is possible for the user to send SIGINFO, SIGUSR1, or SIGALRM to
+//    get intermediate progress information even when --verbose wasn't used
+//    or stderr is not a terminal.
+//  - alarm() + SIGALRM seems to have slightly less overhead than polling
+//    gettimeofday().
+#ifdef SIGALRM
+
+/// The signal handler for SIGALRM sets this to true. It is set back to false
+/// once the progress message has been updated.
+static volatile sig_atomic_t progress_needs_updating = false;
+
+/// Signal handler for SIGALRM
+static void
+progress_signal_handler(int sig lzma_attribute((unused)))
+{
+	progress_needs_updating = true;
+	return;
+}
+
+#else
+
+/// This is true when progress message printing is wanted. Using the same
+/// variable name as above to avoid some ifdefs.
+static bool progress_needs_updating = false;
+
+/// Elapsed time when the next progress message update should be done.
+static uint64_t progress_next_update;
+
+#endif
+
+
+/// Get the current time as microseconds since epoch
+static uint64_t
+my_time(void)
+{
+	struct timeval tv;
+	gettimeofday(&tv, NULL);
+	return (uint64_t)(tv.tv_sec) * UINT64_C(1000000) + tv.tv_usec;
+}
+
+
+extern void
+message_init(void)
+{
+	// If --verbose is used, we use a progress indicator if and only
+	// if stderr is a terminal. If stderr is not a terminal, we print
+	// verbose information only after finishing the file. As a special
+	// exception, even if --verbose was not used, user can send SIGALRM
+	// to make us print progress information once without automatic
+	// updating.
+	progress_automatic = isatty(STDERR_FILENO);
+
+	// Commented out because COLUMNS is rarely exported to environment.
+	// Most users have at least 80 columns anyway, let's think something
+	// fancy here if enough people complain.
+/*
+	if (progress_automatic) {
+		// stderr is a terminal. Check the COLUMNS environment
+		// variable to see if the terminal is wide enough. If COLUMNS
+		// doesn't exist or it has some unparsable value, we assume
+		// that the terminal is wide enough.
+		const char *columns_str = getenv("COLUMNS");
+		if (columns_str != NULL) {
+			char *endptr;
+			const long columns = strtol(columns_str, &endptr, 10);
+			if (*endptr != '\0' || columns < 80)
+				progress_automatic = false;
+		}
+	}
+*/
+
+#ifdef SIGALRM
+	// 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. That way we don't
+	// need to block them either in signals_block() to keep stdio
+	// functions from getting EINTR.
+	static const int sigs[] = {
+		SIGALRM,
+#ifdef SIGINFO
+		SIGINFO,
+#endif
+#ifdef SIGUSR1
+		SIGUSR1,
+#endif
+	};
+
+	struct sigaction sa;
+	sigemptyset(&sa.sa_mask);
+	sa.sa_flags = SA_RESTART;
+	sa.sa_handler = &progress_signal_handler;
+
+	for (size_t i = 0; i < ARRAY_SIZE(sigs); ++i)
+		if (sigaction(sigs[i], &sa, NULL))
+			message_signal_handler();
+#endif
+
+	return;
+}
+
+
+extern void
+message_verbosity_increase(void)
+{
+	if (verbosity < V_DEBUG)
+		++verbosity;
+
+	return;
+}
+
+
+extern void
+message_verbosity_decrease(void)
+{
+	if (verbosity > V_SILENT)
+		--verbosity;
+
+	return;
+}
+
+
+extern enum message_verbosity
+message_verbosity_get(void)
+{
+	return verbosity;
+}
+
+
+extern void
+message_set_files(unsigned int files)
+{
+	files_total = files;
+	return;
+}
+
+
+/// Prints the name of the current file if it hasn't been printed already,
+/// except if we are processing exactly one stream from stdin to stdout.
+/// I think it looks nicer to not print "(stdin)" when --verbose is used
+/// in a pipe and no other files are processed.
+static void
+print_filename(void)
+{
+	if (files_total != 1 || filename != stdin_filename) {
+		signals_block();
+
+		FILE *file = opt_mode == MODE_LIST ? stdout : stderr;
+
+		// If a file was already processed, put an empty line
+		// before the next filename to improve readability.
+		if (first_filename_printed)
+			fputc('\n', file);
+
+		first_filename_printed = true;
+		current_filename_printed = true;
+
+		// If we don't know how many files there will be due
+		// to usage of --files or --files0.
+		if (files_total == 0)
+			fprintf(file, "%s (%u)\n", filename,
+					files_pos);
+		else
+			fprintf(file, "%s (%u/%u)\n", filename,
+					files_pos, files_total);
+
+		signals_unblock();
+	}
+
+	return;
+}
+
+
+extern void
+message_filename(const char *src_name)
+{
+	// Start numbering the files starting from one.
+	++files_pos;
+	filename = src_name;
+
+	if (verbosity >= V_VERBOSE
+			&& (progress_automatic || opt_mode == MODE_LIST))
+		print_filename();
+	else
+		current_filename_printed = false;
+
+	return;
+}
+
+
+extern void
+message_progress_start(lzma_stream *strm, uint64_t in_size)
+{
+	// Store the pointer to the lzma_stream used to do the coding.
+	// It is needed to find out the position in the stream.
+	progress_strm = strm;
+
+	// Store the processing start time of the file and its expected size.
+	// If we aren't printing any statistics, then these are unused. But
+	// since it is possible that the user sends us a signal to show
+	// statistics, we need to have these available anyway.
+	start_time = my_time();
+	expected_in_size = in_size;
+
+	// Indicate that progress info may need to be printed before
+	// printing error messages.
+	progress_started = true;
+
+	// If progress indicator is wanted, print the filename and possibly
+	// the file count now.
+	if (verbosity >= V_VERBOSE && progress_automatic) {
+		// Start the timer to display the first progress message
+		// after one second. An alternative would be to show the
+		// first message almost immediately, but delaying by one
+		// second looks better to me, since extremely early
+		// progress info is pretty much useless.
+#ifdef SIGALRM
+		// First disable a possibly existing alarm.
+		alarm(0);
+		progress_needs_updating = false;
+		alarm(1);
+#else
+		progress_needs_updating = true;
+		progress_next_update = 1000000;
+#endif
+	}
+
+	return;
+}
+
+
+/// Make the string indicating completion percentage.
+static const char *
+progress_percentage(uint64_t in_pos)
+{
+	// If the size of the input file is unknown or the size told us is
+	// clearly wrong since we have processed more data than the alleged
+	// size of the file, show a static string indicating that we have
+	// no idea of the completion percentage.
+	if (expected_in_size == 0 || in_pos > expected_in_size)
+		return "--- %";
+
+	// Never show 100.0 % before we actually are finished.
+	double percentage = (double)(in_pos) / (double)(expected_in_size)
+			* 99.9;
+
+	static char buf[sizeof("99.9 %")];
+	snprintf(buf, sizeof(buf), "%.1f %%", percentage);
+
+	return buf;
+}
+
+
+/// Make the string containing the amount of input processed, amount of
+/// output produced, and the compression ratio.
+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];
+
+	char *pos = buf;
+	size_t left = sizeof(buf);
+
+	// Print the sizes. If this the final message, use more reasonable
+	// units than MiB if the file was small.
+	const enum nicestr_unit unit_min = final ? NICESTR_B : NICESTR_MIB;
+	my_snprintf(&pos, &left, "%s / %s",
+			uint64_to_nicestr(compressed_pos,
+				unit_min, NICESTR_TIB, false, 0),
+			uint64_to_nicestr(uncompressed_pos,
+				unit_min, NICESTR_TIB, false, 1));
+
+	// Avoid division by zero. If we cannot calculate the ratio, set
+	// it to some nice number greater than 10.0 so that it gets caught
+	// in the next if-clause.
+	const double ratio = uncompressed_pos > 0
+			? (double)(compressed_pos) / (double)(uncompressed_pos)
+			: 16.0;
+
+	// If the ratio is very bad, just indicate that it is greater than
+	// 9.999. This way the length of the ratio field stays fixed.
+	if (ratio > 9.999)
+		snprintf(pos, left, " > %.3f", 9.999);
+	else
+		snprintf(pos, left, " = %.3f", ratio);
+
+	return buf;
+}
+
+
+/// Make the string containing the processing speed of uncompressed data.
+static const char *
+progress_speed(uint64_t uncompressed_pos, uint64_t elapsed)
+{
+	// Don't print the speed immediately, since the early values look
+	// somewhat random.
+	if (elapsed < 3000000)
+		return "";
+
+	static const char unit[][8] = {
+		"KiB/s",
+		"MiB/s",
+		"GiB/s",
+	};
+
+	size_t unit_index = 0;
+
+	// Calculate the speed as KiB/s.
+	double speed = (double)(uncompressed_pos)
+			/ ((double)(elapsed) * (1024.0 / 1e6));
+
+	// Adjust the unit of the speed if needed.
+	while (speed > 999.0) {
+		speed /= 1024.0;
+		if (++unit_index == ARRAY_SIZE(unit))
+			return ""; // Way too fast ;-)
+	}
+
+	// Use decimal point only if the number is small. Examples:
+	//  - 0.1 KiB/s
+	//  - 9.9 KiB/s
+	//  - 99 KiB/s
+	//  - 999 KiB/s
+	static char buf[sizeof("999 GiB/s")];
+	snprintf(buf, sizeof(buf), "%.*f %s",
+			speed > 9.9 ? 0 : 1, speed, unit[unit_index]);
+	return buf;
+}
+
+
+/// Make a string indicating elapsed or remaining time. The format is either
+/// M:SS or H:MM:SS depending on if the time is an hour or more.
+static const char *
+progress_time(uint64_t useconds)
+{
+	// 9999 hours = 416 days
+	static char buf[sizeof("9999:59:59")];
+
+	uint32_t seconds = useconds / 1000000;
+
+	// Don't show anything if the time is zero or ridiculously big.
+	if (seconds == 0 || seconds > ((9999 * 60) + 59) * 60 + 59)
+		return "";
+
+	uint32_t minutes = seconds / 60;
+	seconds %= 60;
+
+	if (minutes >= 60) {
+		const uint32_t hours = minutes / 60;
+		minutes %= 60;
+		snprintf(buf, sizeof(buf),
+				"%" PRIu32 ":%02" PRIu32 ":%02" PRIu32,
+				hours, minutes, seconds);
+	} else {
+		snprintf(buf, sizeof(buf), "%" PRIu32 ":%02" PRIu32,
+				minutes, seconds);
+	}
+
+	return buf;
+}
+
+
+/// Return a string containing estimated remaining time when
+/// reasonably possible.
+static const char *
+progress_remaining(uint64_t in_pos, uint64_t elapsed)
+{
+	// Don't show the estimated remaining time when it wouldn't
+	// make sense:
+	//  - Input size is unknown.
+	//  - Input has grown bigger since we started (de)compressing.
+	//  - We haven't processed much data yet, so estimate would be
+	//    too inaccurate.
+	//  - Only a few seconds has passed since we started (de)compressing,
+	//    so estimate would be too inaccurate.
+	if (expected_in_size == 0 || in_pos > expected_in_size
+			|| in_pos < (UINT64_C(1) << 19) || elapsed < 8000000)
+		return "";
+
+	// Calculate the estimate. Don't give an estimate of zero seconds,
+	// since it is possible that all the input has been already passed
+	// to the library, but there is still quite a bit of output pending.
+	uint32_t remaining = (double)(expected_in_size - in_pos)
+			* ((double)(elapsed) / 1e6) / (double)(in_pos);
+	if (remaining < 1)
+		remaining = 1;
+
+	static char buf[sizeof("9 h 55 min")];
+
+	// Select appropriate precision for the estimated remaining time.
+	if (remaining <= 10) {
+		// A maximum of 10 seconds remaining.
+		// Show the number of seconds as is.
+		snprintf(buf, sizeof(buf), "%" PRIu32 " s", remaining);
+
+	} else if (remaining <= 50) {
+		// A maximum of 50 seconds remaining.
+		// Round up to the next multiple of five seconds.
+		remaining = (remaining + 4) / 5 * 5;
+		snprintf(buf, sizeof(buf), "%" PRIu32 " s", remaining);
+
+	} else if (remaining <= 590) {
+		// A maximum of 9 minutes and 50 seconds remaining.
+		// Round up to the next multiple of ten seconds.
+		remaining = (remaining + 9) / 10 * 10;
+		snprintf(buf, sizeof(buf), "%" PRIu32 " min %" PRIu32 " s",
+				remaining / 60, remaining % 60);
+
+	} else if (remaining <= 59 * 60) {
+		// A maximum of 59 minutes remaining.
+		// Round up to the next multiple of a minute.
+		remaining = (remaining + 59) / 60;
+		snprintf(buf, sizeof(buf), "%" PRIu32 " min", remaining);
+
+	} else if (remaining <= 9 * 3600 + 50 * 60) {
+		// A maximum of 9 hours and 50 minutes left.
+		// Round up to the next multiple of ten minutes.
+		remaining = (remaining + 599) / 600 * 10;
+		snprintf(buf, sizeof(buf), "%" PRIu32 " h %" PRIu32 " min",
+				remaining / 60, remaining % 60);
+
+	} else if (remaining <= 23 * 3600) {
+		// A maximum of 23 hours remaining.
+		// Round up to the next multiple of an hour.
+		remaining = (remaining + 3599) / 3600;
+		snprintf(buf, sizeof(buf), "%" PRIu32 " h", remaining);
+
+	} else if (remaining <= 9 * 24 * 3600 + 23 * 3600) {
+		// A maximum of 9 days and 23 hours remaining.
+		// Round up to the next multiple of an hour.
+		remaining = (remaining + 3599) / 3600;
+		snprintf(buf, sizeof(buf), "%" PRIu32 " d %" PRIu32 " h",
+				remaining / 24, remaining % 24);
+
+	} else if (remaining <= 999 * 24 * 3600) {
+		// A maximum of 999 days remaining. ;-)
+		// Round up to the next multiple of a day.
+		remaining = (remaining + 24 * 3600 - 1) / (24 * 3600);
+		snprintf(buf, sizeof(buf), "%" PRIu32 " d", remaining);
+
+	} else {
+		// The estimated remaining time is too big. Don't show it.
+		return "";
+	}
+
+	return buf;
+}
+
+
+/// Calculate the elapsed time as microseconds.
+static uint64_t
+progress_elapsed(void)
+{
+	return my_time() - start_time;
+}
+
+
+/// Get information about position in the stream. This is currently simple,
+/// but it will become more complicated once we have multithreading support.
+static void
+progress_pos(uint64_t *in_pos,
+		uint64_t *compressed_pos, uint64_t *uncompressed_pos)
+{
+	*in_pos = progress_strm->total_in;
+
+	if (opt_mode == MODE_COMPRESS) {
+		*compressed_pos = progress_strm->total_out;
+		*uncompressed_pos = progress_strm->total_in;
+	} else {
+		*compressed_pos = progress_strm->total_in;
+		*uncompressed_pos = progress_strm->total_out;
+	}
+
+	return;
+}
+
+
+extern void
+message_progress_update(void)
+{
+	if (!progress_needs_updating)
+		return;
+
+	// Calculate how long we have been processing this file.
+	const uint64_t elapsed = progress_elapsed();
+
+#ifndef SIGALRM
+	if (progress_next_update > elapsed)
+		return;
+
+	progress_next_update = elapsed + 1000000;
+#endif
+
+	// Get our current position in the stream.
+	uint64_t in_pos;
+	uint64_t compressed_pos;
+	uint64_t uncompressed_pos;
+	progress_pos(&in_pos, &compressed_pos, &uncompressed_pos);
+
+	// Block signals so that fprintf() doesn't get interrupted.
+	signals_block();
+
+	// Print the filename if it hasn't been printed yet.
+	if (!current_filename_printed)
+		print_filename();
+
+	// 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",
+		progress_percentage(in_pos),
+		progress_sizes(compressed_pos, uncompressed_pos, false),
+		progress_speed(uncompressed_pos, elapsed),
+		progress_time(elapsed),
+		progress_remaining(in_pos, elapsed));
+
+#ifdef SIGALRM
+	// Updating the progress info was finished. Reset
+	// progress_needs_updating to wait for the next SIGALRM.
+	//
+	// NOTE: This has to be done before alarm(1) or with (very) bad
+	// luck we could be setting this to false after the alarm has already
+	// been triggered.
+	progress_needs_updating = false;
+
+	if (verbosity >= V_VERBOSE && progress_automatic) {
+		// Mark that the progress indicator is active, so if an error
+		// occurs, the error message gets printed cleanly.
+		progress_active = true;
+
+		// Restart the timer so that progress_needs_updating gets
+		// set to true after about one second.
+		alarm(1);
+	} else {
+		// The progress message was printed because user had sent us
+		// SIGALRM. In this case, each progress message is printed
+		// on its own line.
+		fputc('\n', stderr);
+	}
+#else
+	// When SIGALRM isn't supported and we get here, it's always due to
+	// automatic progress update. We set progress_active here too like
+	// described above.
+	assert(verbosity >= V_VERBOSE);
+	assert(progress_automatic);
+	progress_active = true;
+#endif
+
+	signals_unblock();
+
+	return;
+}
+
+
+static void
+progress_flush(bool finished)
+{
+	if (!progress_started || verbosity < V_VERBOSE)
+		return;
+
+	uint64_t in_pos;
+	uint64_t compressed_pos;
+	uint64_t uncompressed_pos;
+	progress_pos(&in_pos, &compressed_pos, &uncompressed_pos);
+
+	// Avoid printing intermediate progress info if some error occurs
+	// in the beginning of the stream. (If something goes wrong later in
+	// the stream, it is sometimes useful to tell the user where the
+	// error approximately occurred, especially if the error occurs
+	// after a time-consuming operation.)
+	if (!finished && !progress_active
+			&& (compressed_pos == 0 || uncompressed_pos == 0))
+		return;
+
+	progress_active = false;
+
+	const uint64_t elapsed = progress_elapsed();
+
+	signals_block();
+
+	// When using the auto-updating progress indicator, the final
+	// statistics are printed in the same format as the progress
+	// indicator itself.
+	if (progress_automatic) {
+		fprintf(stderr, "\r %6s %35s   %9s %10s   %10s\n",
+			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));
+	} else {
+		// The filename is always printed.
+		fprintf(stderr, "%s: ", filename);
+
+		// Percentage is printed only if we didn't finish yet.
+		if (!finished) {
+			// Don't print the percentage when it isn't known
+			// (starts with a dash).
+			const char *percentage = progress_percentage(in_pos);
+			if (percentage[0] != '-')
+				fprintf(stderr, "%s, ", percentage);
+		}
+
+		// Size information is always printed.
+		fprintf(stderr, "%s", progress_sizes(
+				compressed_pos, uncompressed_pos, true));
+
+		// The speed and elapsed time aren't always shown.
+		const char *speed = progress_speed(uncompressed_pos, elapsed);
+		if (speed[0] != '\0')
+			fprintf(stderr, ", %s", speed);
+
+		const char *elapsed_str = progress_time(elapsed);
+		if (elapsed_str[0] != '\0')
+			fprintf(stderr, ", %s", elapsed_str);
+
+		fputc('\n', stderr);
+	}
+
+	signals_unblock();
+
+	return;
+}
+
+
+extern void
+message_progress_end(bool success)
+{
+	assert(progress_started);
+	progress_flush(success);
+	progress_started = false;
+	return;
+}
+
+
+static void
+vmessage(enum message_verbosity v, const char *fmt, va_list ap)
+{
+	if (v <= verbosity) {
+		signals_block();
+
+		progress_flush(false);
+
+		fprintf(stderr, "%s: ", progname);
+		vfprintf(stderr, fmt, ap);
+		fputc('\n', stderr);
+
+		signals_unblock();
+	}
+
+	return;
+}
+
+
+extern void
+message(enum message_verbosity v, const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	vmessage(v, fmt, ap);
+	va_end(ap);
+	return;
+}
+
+
+extern void
+message_warning(const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	vmessage(V_WARNING, fmt, ap);
+	va_end(ap);
+
+	set_exit_status(E_WARNING);
+	return;
+}
+
+
+extern void
+message_error(const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	vmessage(V_ERROR, fmt, ap);
+	va_end(ap);
+
+	set_exit_status(E_ERROR);
+	return;
+}
+
+
+extern void
+message_fatal(const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	vmessage(V_ERROR, fmt, ap);
+	va_end(ap);
+
+	tuklib_exit(E_ERROR, E_ERROR, false);
+}
+
+
+extern void
+message_bug(void)
+{
+	message_fatal(_("Internal error (bug)"));
+}
+
+
+extern void
+message_signal_handler(void)
+{
+	message_fatal(_("Cannot establish signal handlers"));
+}
+
+
+extern const char *
+message_strm(lzma_ret code)
+{
+	switch (code) {
+	case LZMA_NO_CHECK:
+		return _("No integrity check; not verifying file integrity");
+
+	case LZMA_UNSUPPORTED_CHECK:
+		return _("Unsupported type of integrity check; "
+				"not verifying file integrity");
+
+	case LZMA_MEM_ERROR:
+		return strerror(ENOMEM);
+
+	case LZMA_MEMLIMIT_ERROR:
+		return _("Memory usage limit reached");
+
+	case LZMA_FORMAT_ERROR:
+		return _("File format not recognized");
+
+	case LZMA_OPTIONS_ERROR:
+		return _("Unsupported options");
+
+	case LZMA_DATA_ERROR:
+		return _("Compressed data is corrupt");
+
+	case LZMA_BUF_ERROR:
+		return _("Unexpected end of input");
+
+	case LZMA_OK:
+	case LZMA_STREAM_END:
+	case LZMA_GET_CHECK:
+	case LZMA_PROG_ERROR:
+		return _("Internal error (bug)");
+	}
+
+	return NULL;
+}
+
+
+extern void
+message_mem_needed(enum message_verbosity v, uint64_t memusage)
+{
+	if (v > verbosity)
+		return;
+
+	// Convert memusage to MiB, rounding up to the next full MiB.
+	// This way the user can always use the displayed usage as
+	// the new memory usage limit. (If we rounded to the nearest,
+	// the user might need to +1 MiB to get high enough limit.)
+	memusage = round_up_to_mib(memusage);
+
+	// 2^64 with thousand separators + " MiB" suffix + '\0' = 26 + 4 + 1
+	char memlimitstr[32];
+
+	// 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();
+	if (memlimit < (UINT32_C(1) << 20)) {
+		snprintf(memlimitstr, sizeof(memlimitstr), "%s B",
+				uint64_to_str(memlimit, 1));
+	} else {
+		// Round up just like with memusage. If this function is
+		// called for informational purposes (to just show the
+		// current usage and limit), we should never show that
+		// the usage is higher than the limit, which would give
+		// a false impression that the memory usage limit isn't
+		// properly enforced.
+		snprintf(memlimitstr, sizeof(memlimitstr), "%s MiB",
+				uint64_to_str(round_up_to_mib(memlimit), 1));
+	}
+
+	message(v, _("%s MiB of memory is required. The limit is %s."),
+			uint64_to_str(memusage, 0), memlimitstr);
+
+	return;
+}
+
+
+/// \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)
+{
+	static char buf[16];
+
+	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 const char *
+message_filters_to_str(const lzma_filter *filters, bool all_known)
+{
+	static char buf[512];
+
+	char *pos = buf;
+	size_t left = sizeof(buf);
+
+	for (size_t i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i) {
+		// 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 = 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;
+				}
+			}
+
+			// 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,
+					opt->lc, opt->lp, opt->pb,
+					mode, opt->nice_len, mf, opt->depth);
+			break;
+		}
+
+		case LZMA_FILTER_X86:
+		case LZMA_FILTER_POWERPC:
+		case LZMA_FILTER_IA64:
+		case LZMA_FILTER_ARM:
+		case LZMA_FILTER_ARMTHUMB:
+		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);
+
+			break;
+		}
+
+		case LZMA_FILTER_DELTA: {
+			const lzma_options_delta *opt = filters[i].options;
+			my_snprintf(&pos, &left, "delta=dist=%" PRIu32,
+					opt->dist);
+			break;
+		}
+
+		default:
+			// This should be possible only if liblzma is
+			// newer than the xz tool.
+			my_snprintf(&pos, &left, "UNKNOWN");
+			break;
+		}
+	}
+
+	return buf;
+}
+
+
+extern void
+message_filters_show(enum message_verbosity v, const lzma_filter *filters)
+{
+	if (v > verbosity)
+		return;
+
+	fprintf(stderr, _("%s: Filter chain: %s\n"), progname,
+			message_filters_to_str(filters, true));
+	return;
+}
+
+
+extern void
+message_try_help(void)
+{
+	// 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;
+}
+
+
+extern void
+message_memlimit(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);
+}
+
+
+extern void
+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",
+				LZMA_VERSION, lzma_version_number());
+	} else {
+		printf("xz (" PACKAGE_NAME ") " LZMA_VERSION_STRING "\n");
+		printf("liblzma %s\n", lzma_version_string());
+	}
+
+	tuklib_exit(E_SUCCESS, E_ERROR, verbosity != V_SILENT);
+}
+
+
+extern void
+message_help(bool long_help)
+{
+	printf(_("Usage: %s [OPTION]... [FILE]...\n"
+			"Compress or decompress FILEs in the .xz format.\n\n"),
+			progname);
+
+	puts(_("Mandatory arguments to long options are mandatory for "
+			"short options too.\n"));
+
+	if (long_help)
+		puts(_(" Operation mode:\n"));
+
+	puts(_(
+"  -z, --compress      force compression\n"
+"  -d, --decompress    force decompression\n"
+"  -t, --test          test compressed file integrity\n"
+"  -l, --list          list information about files"));
+
+	if (long_help)
+		puts(_("\n Operation modifiers:\n"));
+
+	puts(_(
+"  -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"));
+
+	if (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"
+"                      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"));
+
+	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)"));
+	}
+
+	puts(_(
+"  -0 .. -9            compression preset; 0-2 fast compression, 3-5 good\n"
+"                      compression, 6-9 excellent compression; default is 6"));
+
+	puts(_(
+"  -e, --extreme       use more CPU time when encoding to increase compression\n"
+"                      ratio without increasing memory usage of the decoder"));
+
+	if (long_help) {
+		puts(_(
+"      --no-adjust     if compression settings exceed the memory usage limit,\n"
+"                      give an error instead of adjusting the settings downwards"));
+		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"));
+	}
+
+	if (long_help) {
+		puts(_(
+"\n Custom filter chain for compression (alternative for using presets):"));
+
+#if defined(HAVE_ENCODER_LZMA1) || defined(HAVE_DECODER_LZMA1) \
+		|| defined(HAVE_ENCODER_LZMA2) || defined(HAVE_DECODER_LZMA2)
+		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"
+"                        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)"));
+#endif
+
+		puts(_(
+"\n"
+"  --x86[=OPTS]        x86 BCJ filter\n"
+"  --powerpc[=OPTS]    PowerPC BCJ filter (big endian only)\n"
+"  --ia64[=OPTS]       IA64 (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)"));
+
+#if defined(HAVE_ENCODER_DELTA) || defined(HAVE_DECODER_DELTA)
+		puts(_(
+"\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)"));
+#endif
+	}
+
+	if (long_help)
+		puts(_("\n Other options:\n"));
+
+	puts(_(
+"  -q, --quiet         suppress warnings; specify twice to suppress errors too\n"
+"  -v, --verbose       be verbose; specify twice for even more verbose"));
+
+	if (long_help) {
+		puts(_(
+"  -Q, --no-warn       make warnings not affect the exit status"));
+		puts(_(
+"      --robot         use machine-parsable messages (useful for scripts)"));
+		puts("");
+		puts(_(
+"      --info-memory   display the memory usage limit and exit"));
+		puts(_(
+"  -h, --help          display the short help (lists only the basic options)\n"
+"  -H, --long-help     display this long help and exit"));
+	} else {
+		puts(_(
+"  -h, --help          display this short help and exit\n"
+"  -H, --long-help     display the long help (lists also the advanced options)"));
+	}
+
+	puts(_(
+"  -V, --version       display the version number and exit"));
+
+	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
+	// address for translation bugs. Thanks.
+	printf(_("Report bugs to <%s> (in English or Finnish).\n"),
+			PACKAGE_BUGREPORT);
+	printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
+
+	tuklib_exit(E_SUCCESS, E_ERROR, verbosity != V_SILENT);
+}
diff --git a/src/xz/message.h b/src/xz/message.h
new file mode 100644
index 0000000..aea4fdf
--- /dev/null
+++ b/src/xz/message.h
@@ -0,0 +1,163 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       message.h
+/// \brief      Printing messages to stderr
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+/// Verbosity levels
+enum message_verbosity {
+	V_SILENT,   ///< No messages
+	V_ERROR,    ///< Only error messages
+	V_WARNING,  ///< Errors and warnings
+	V_VERBOSE,  ///< Errors, warnings, and verbose statistics
+	V_DEBUG,    ///< Debugging, FIXME remove?
+};
+
+
+/// \brief      Initializes the message functions
+///
+/// If an error occurs, this function doesn't return.
+///
+extern void message_init(void);
+
+
+/// Increase verbosity level by one step unless it was at maximum.
+extern void message_verbosity_increase(void);
+
+/// Decrease verbosity level by one step unless it was at minimum.
+extern void message_verbosity_decrease(void);
+
+/// Get the current verbosity level.
+extern enum message_verbosity message_verbosity_get(void);
+
+
+/// \brief      Print a message if verbosity level is at least "verbosity"
+///
+/// This doesn't touch the exit status.
+extern void message(enum message_verbosity verbosity, const char *fmt, ...)
+		lzma_attribute((format(printf, 2, 3)));
+
+
+/// \brief      Prints a warning and possibly sets exit status
+///
+/// The message is printed only if verbosity level is at least V_WARNING.
+/// The exit status is set to WARNING unless it was already at ERROR.
+extern void message_warning(const char *fmt, ...)
+		lzma_attribute((format(printf, 1, 2)));
+
+
+/// \brief      Prints an error message and sets exit status
+///
+/// The message is printed only if verbosity level is at least V_ERROR.
+/// The exit status is set to ERROR.
+extern void message_error(const char *fmt, ...)
+		lzma_attribute((format(printf, 1, 2)));
+
+
+/// \brief      Prints an error message and exits with EXIT_ERROR
+///
+/// The message is printed only if verbosity level is at least V_ERROR.
+extern void message_fatal(const char *fmt, ...)
+		lzma_attribute((format(printf, 1, 2)))
+		lzma_attribute((noreturn));
+
+
+/// Print an error message that an internal error occurred and exit with
+/// EXIT_ERROR.
+extern void message_bug(void) lzma_attribute((noreturn));
+
+
+/// Print a message that establishing signal handlers failed, and exit with
+/// exit status ERROR.
+extern void message_signal_handler(void) lzma_attribute((noreturn));
+
+
+/// Convert lzma_ret to a string.
+extern const char *message_strm(lzma_ret code);
+
+
+/// Display how much memory was needed and how much the limit was.
+extern void message_mem_needed(enum message_verbosity v, uint64_t memusage);
+
+
+/// \brief      Get the filter chain as a 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.
+///
+/// \return     Pointer to a statically allocated buffer.
+extern const char *message_filters_to_str(
+		const lzma_filter *filters, bool all_known);
+
+
+/// Print the filter chain.
+extern void message_filters_show(
+		enum message_verbosity v, const lzma_filter *filters);
+
+
+/// Print a message that user should try --help.
+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));
+
+
+/// Print the help message.
+extern void message_help(bool long_help) lzma_attribute((noreturn));
+
+
+/// \brief      Set the total number of files to be processed
+///
+/// Standard input is counted as a file here. This is used when printing
+/// the filename via message_filename().
+extern void message_set_files(unsigned int files);
+
+
+/// \brief      Set the name of the current file and possibly print it too
+///
+/// The name is printed immediately if --list was used or if --verbose
+/// was used and stderr is a terminal. Even when the filename isn't printed,
+/// it is stored so that it can be printed later if needed for progress
+/// messages.
+extern void message_filename(const char *src_name);
+
+
+/// \brief      Start progress info handling
+///
+/// message_filename() must be called before this function to set
+/// the filename.
+///
+/// This must be paired with a call to message_progress_end() before the
+/// given *strm becomes invalid.
+///
+/// \param      strm      Pointer to lzma_stream used for the coding.
+/// \param      in_size   Size of the input file, or zero if unknown.
+///
+extern void message_progress_start(lzma_stream *strm, uint64_t in_size);
+
+
+/// Update the progress info if in verbose mode and enough time has passed
+/// since the previous update. This can be called only when
+/// message_progress_start() has already been used.
+extern void message_progress_update(void);
+
+
+/// \brief      Finishes the progress message if we were in verbose mode
+///
+/// \param      finished    True if the whole stream was successfully coded
+///                         and output written to the output stream.
+///
+extern void message_progress_end(bool finished);
diff --git a/src/xz/options.c b/src/xz/options.c
new file mode 100644
index 0000000..7186f24
--- /dev/null
+++ b/src/xz/options.c
@@ -0,0 +1,374 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       options.c
+/// \brief      Parser for filter-specific options
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "private.h"
+
+
+///////////////////
+// Generic stuff //
+///////////////////
+
+typedef struct {
+	const char *name;
+	uint64_t id;
+} name_id_map;
+
+
+typedef struct {
+	const char *name;
+	const name_id_map *map;
+	uint64_t min;
+	uint64_t max;
+} option_map;
+
+
+/// Parses option=value pairs that are separated with colons, semicolons,
+/// or commas: opt=val:opt=val;opt=val,opt=val
+///
+/// Each option is a string, that is converted to an integer using the
+/// index where the option string is in the array.
+///
+/// Value can be
+///  - a string-id map mapping a list of possible string values to integers
+///    (opts[i].map != NULL, opts[i].min and opts[i].max are ignored);
+///  - a number with minimum and maximum value limit
+///    (opts[i].map == NULL && opts[i].min != UINT64_MAX);
+///  - a string that will be parsed by the filter-specific code
+///    (opts[i].map == NULL && opts[i].min == UINT64_MAX, opts[i].max ignored)
+///
+/// When parsing both option and value succeed, a filter-specific function
+/// is called, which should update the given value to filter-specific
+/// options structure.
+///
+/// \param      str     String containing the options from the command line
+/// \param      opts    Filter-specific option map
+/// \param      set     Filter-specific function to update filter_options
+/// \param      filter_options  Pointer to filter-specific options structure
+///
+/// \return     Returns only if no errors occur.
+///
+static void
+parse_options(const char *str, const option_map *opts,
+		void (*set)(void *filter_options,
+			uint32_t key, uint64_t value, const char *valuestr),
+		void *filter_options)
+{
+	if (str == NULL || str[0] == '\0')
+		return;
+
+	char *s = xstrdup(str);
+	char *name = s;
+
+	while (*name != '\0') {
+		if (*name == ',') {
+			++name;
+			continue;
+		}
+
+		char *split = strchr(name, ',');
+		if (split != NULL)
+			*split = '\0';
+
+		char *value = strchr(name, '=');
+		if (value != NULL)
+			*value++ = '\0';
+
+		if (value == NULL || value[0] == '\0')
+			message_fatal(_("%s: Options must be `name=value' "
+					"pairs separated with commas"), str);
+
+		// Look for the option name from the option map.
+		size_t i = 0;
+		while (true) {
+			if (opts[i].name == NULL)
+				message_fatal(_("%s: Invalid option name"),
+						name);
+
+			if (strcmp(name, opts[i].name) == 0)
+				break;
+
+			++i;
+		}
+
+		// Option was found from the map. See how we should handle it.
+		if (opts[i].map != NULL) {
+			// value is a string which we should map
+			// to an integer.
+			size_t j;
+			for (j = 0; opts[i].map[j].name != NULL; ++j) {
+				if (strcmp(opts[i].map[j].name, value) == 0)
+					break;
+			}
+
+			if (opts[i].map[j].name == NULL)
+				message_fatal(_("%s: Invalid option value"),
+						value);
+
+			set(filter_options, i, opts[i].map[j].id, value);
+
+		} else if (opts[i].min == UINT64_MAX) {
+			// value is a special string that will be
+			// parsed by set().
+			set(filter_options, i, 0, value);
+
+		} else {
+			// value is an integer.
+			const uint64_t v = str_to_uint64(name, value,
+					opts[i].min, opts[i].max);
+			set(filter_options, i, v, value);
+		}
+
+		// Check if it was the last option.
+		if (split == NULL)
+			break;
+
+		name = split + 1;
+	}
+
+	free(s);
+	return;
+}
+
+
+///////////
+// Delta //
+///////////
+
+enum {
+	OPT_DIST,
+};
+
+
+static void
+set_delta(void *options, uint32_t key, uint64_t value,
+		const char *valuestr lzma_attribute((unused)))
+{
+	lzma_options_delta *opt = options;
+	switch (key) {
+	case OPT_DIST:
+		opt->dist = value;
+		break;
+	}
+}
+
+
+extern lzma_options_delta *
+options_delta(const char *str)
+{
+	static const option_map opts[] = {
+		{ "dist",     NULL,  LZMA_DELTA_DIST_MIN,
+		                     LZMA_DELTA_DIST_MAX },
+		{ NULL,       NULL,  0, 0 }
+	};
+
+	lzma_options_delta *options = xmalloc(sizeof(lzma_options_delta));
+	*options = (lzma_options_delta){
+		// It's hard to give a useful default for this.
+		.type = LZMA_DELTA_TYPE_BYTE,
+		.dist = LZMA_DELTA_DIST_MIN,
+	};
+
+	parse_options(str, opts, &set_delta, options);
+
+	return options;
+}
+
+
+/////////
+// BCJ //
+/////////
+
+enum {
+	OPT_START_OFFSET,
+};
+
+
+static void
+set_bcj(void *options, uint32_t key, uint64_t value,
+		const char *valuestr lzma_attribute((unused)))
+{
+	lzma_options_bcj *opt = options;
+	switch (key) {
+	case OPT_START_OFFSET:
+		opt->start_offset = value;
+		break;
+	}
+}
+
+
+extern lzma_options_bcj *
+options_bcj(const char *str)
+{
+	static const option_map opts[] = {
+		{ "start",    NULL,  0, UINT32_MAX },
+		{ NULL,       NULL,  0, 0 }
+	};
+
+	lzma_options_bcj *options = xmalloc(sizeof(lzma_options_bcj));
+	*options = (lzma_options_bcj){
+		.start_offset = 0,
+	};
+
+	parse_options(str, opts, &set_bcj, options);
+
+	return options;
+}
+
+
+//////////
+// LZMA //
+//////////
+
+enum {
+	OPT_PRESET,
+	OPT_DICT,
+	OPT_LC,
+	OPT_LP,
+	OPT_PB,
+	OPT_MODE,
+	OPT_NICE,
+	OPT_MF,
+	OPT_DEPTH,
+};
+
+
+static void lzma_attribute((noreturn))
+error_lzma_preset(const char *valuestr)
+{
+	message_fatal(_("Unsupported LZMA1/LZMA2 preset: %s"), valuestr);
+}
+
+
+static void
+set_lzma(void *options, uint32_t key, uint64_t value, const char *valuestr)
+{
+	lzma_options_lzma *opt = options;
+
+	switch (key) {
+	case OPT_PRESET: {
+		if (valuestr[0] < '0' || valuestr[0] > '9')
+			error_lzma_preset(valuestr);
+
+		uint32_t preset = valuestr[0] - '0';
+
+		// Currently only "e" is supported as a modifier,
+		// so keep this simple for now.
+		if (valuestr[1] != '\0') {
+			if (valuestr[1] == 'e')
+				preset |= LZMA_PRESET_EXTREME;
+			else
+				error_lzma_preset(valuestr);
+
+			if (valuestr[2] != '\0')
+				error_lzma_preset(valuestr);
+		}
+
+		if (lzma_lzma_preset(options, preset))
+			error_lzma_preset(valuestr);
+
+		break;
+	}
+
+	case OPT_DICT:
+		opt->dict_size = value;
+		break;
+
+	case OPT_LC:
+		opt->lc = value;
+		break;
+
+	case OPT_LP:
+		opt->lp = value;
+		break;
+
+	case OPT_PB:
+		opt->pb = value;
+		break;
+
+	case OPT_MODE:
+		opt->mode = value;
+		break;
+
+	case OPT_NICE:
+		opt->nice_len = value;
+		break;
+
+	case OPT_MF:
+		opt->mf = value;
+		break;
+
+	case OPT_DEPTH:
+		opt->depth = value;
+		break;
+	}
+}
+
+
+extern lzma_options_lzma *
+options_lzma(const char *str)
+{
+	static const name_id_map modes[] = {
+		{ "fast",   LZMA_MODE_FAST },
+		{ "normal", LZMA_MODE_NORMAL },
+		{ NULL,     0 }
+	};
+
+	static const name_id_map mfs[] = {
+		{ "hc3", LZMA_MF_HC3 },
+		{ "hc4", LZMA_MF_HC4 },
+		{ "bt2", LZMA_MF_BT2 },
+		{ "bt3", LZMA_MF_BT3 },
+		{ "bt4", LZMA_MF_BT4 },
+		{ NULL,  0 }
+	};
+
+	static const option_map opts[] = {
+		{ "preset", NULL,   UINT64_MAX, 0 },
+		{ "dict",   NULL,   LZMA_DICT_SIZE_MIN,
+				(UINT32_C(1) << 30) + (UINT32_C(1) << 29) },
+		{ "lc",     NULL,   LZMA_LCLP_MIN, LZMA_LCLP_MAX },
+		{ "lp",     NULL,   LZMA_LCLP_MIN, LZMA_LCLP_MAX },
+		{ "pb",     NULL,   LZMA_PB_MIN, LZMA_PB_MAX },
+		{ "mode",   modes,  0, 0 },
+		{ "nice",   NULL,   2, 273 },
+		{ "mf",     mfs,    0, 0 },
+		{ "depth",  NULL,   0, UINT32_MAX },
+		{ NULL,     NULL,   0, 0 }
+	};
+
+	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,
+	};
+
+	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"));
+
+	const uint32_t nice_len_min = options->mf & 0x0F;
+	if (options->nice_len < nice_len_min)
+		message_fatal(_("The selected match finder requires at "
+				"least nice=%" PRIu32), nice_len_min);
+
+	return options;
+}
diff --git a/src/xz/options.h b/src/xz/options.h
new file mode 100644
index 0000000..61ec8d5
--- /dev/null
+++ b/src/xz/options.h
@@ -0,0 +1,31 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       options.h
+/// \brief      Parser for filter-specific options
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+/// \brief      Parser for Delta options
+///
+/// \return     Pointer to allocated options structure.
+///             Doesn't return on error.
+extern lzma_options_delta *options_delta(const char *str);
+
+
+/// \brief      Parser for BCJ options
+///
+/// \return     Pointer to allocated options structure.
+///             Doesn't return on error.
+extern lzma_options_bcj *options_bcj(const char *str);
+
+
+/// \brief      Parser for LZMA options
+///
+/// \return     Pointer to allocated options structure.
+///             Doesn't return on error.
+extern lzma_options_lzma *options_lzma(const char *str);
diff --git a/src/xz/private.h b/src/xz/private.h
new file mode 100644
index 0000000..15136bf
--- /dev/null
+++ b/src/xz/private.h
@@ -0,0 +1,56 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       private.h
+/// \brief      Common includes, definions, and prototypes
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "sysdefs.h"
+#include "mythread.h"
+#include "lzma.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <signal.h>
+#include <locale.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "tuklib_gettext.h"
+#include "tuklib_progname.h"
+#include "tuklib_exit.h"
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#	define WIN32_LEAN_AND_MEAN
+#	include <windows.h>
+#endif
+
+#ifndef STDIN_FILENO
+#	define STDIN_FILENO (fileno(stdin))
+#endif
+
+#ifndef STDOUT_FILENO
+#	define STDOUT_FILENO (fileno(stdout))
+#endif
+
+#ifndef STDERR_FILENO
+#	define STDERR_FILENO (fileno(stderr))
+#endif
+
+#include "main.h"
+#include "coder.h"
+#include "message.h"
+#include "args.h"
+#include "hardware.h"
+#include "file_io.h"
+#include "options.h"
+#include "signals.h"
+#include "suffix.h"
+#include "util.h"
+#include "list.h"
diff --git a/src/xz/signals.c b/src/xz/signals.c
new file mode 100644
index 0000000..66d6537
--- /dev/null
+++ b/src/xz/signals.c
@@ -0,0 +1,189 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       signals.c
+/// \brief      Handling signals to abort operation
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "private.h"
+
+
+volatile sig_atomic_t user_abort = false;
+
+
+#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
+/// been done.
+static volatile sig_atomic_t exit_signal = 0;
+
+/// Mask of signals for which have have established a signal handler to set
+/// user_abort to true.
+static sigset_t hooked_signals;
+
+/// True once signals_init() has finished. This is used to skip blocking
+/// signals (with uninitialized hooked_signals) if signals_block() and
+/// signals_unblock() are called before signals_init() has been called.
+static bool signals_are_initialized = false;
+
+/// signals_block() and signals_unblock() can be called recursively.
+static size_t signals_block_count = 0;
+
+
+static void
+signal_handler(int sig)
+{
+	exit_signal = sig;
+	user_abort = true;
+	return;
+}
+
+
+extern void
+signals_init(void)
+{
+	// List of signals for which we establish the signal handler.
+	static const int sigs[] = {
+		SIGINT,
+		SIGTERM,
+#ifdef SIGHUP
+		SIGHUP,
+#endif
+#ifdef SIGPIPE
+		SIGPIPE,
+#endif
+#ifdef SIGXCPU
+		SIGXCPU,
+#endif
+#ifdef SIGXFSZ
+		SIGXFSZ,
+#endif
+	};
+
+	// Mask of the signals for which we have established a signal handler.
+	sigemptyset(&hooked_signals);
+	for (size_t i = 0; i < ARRAY_SIZE(sigs); ++i)
+		sigaddset(&hooked_signals, sigs[i]);
+
+	struct sigaction sa;
+
+	// All the signals that we handle we also blocked while the signal
+	// handler runs.
+	sa.sa_mask = hooked_signals;
+
+	// Don't set SA_RESTART, because we want EINTR so that we can check
+	// for user_abort and cleanup before exiting. We block the signals
+	// for which we have established a handler when we don't want EINTR.
+	sa.sa_flags = 0;
+	sa.sa_handler = &signal_handler;
+
+	for (size_t i = 0; i < ARRAY_SIZE(sigs); ++i) {
+		// If the parent process has left some signals ignored,
+		// we don't unignore them.
+		struct sigaction old;
+		if (sigaction(sigs[i], NULL, &old) == 0
+				&& old.sa_handler == SIG_IGN)
+			continue;
+
+		// Establish the signal handler.
+		if (sigaction(sigs[i], &sa, NULL))
+			message_signal_handler();
+	}
+
+	signals_are_initialized = true;
+
+	return;
+}
+
+
+#ifndef __VMS
+extern void
+signals_block(void)
+{
+	if (signals_are_initialized) {
+		if (signals_block_count++ == 0) {
+			const int saved_errno = errno;
+			mythread_sigmask(SIG_BLOCK, &hooked_signals, NULL);
+			errno = saved_errno;
+		}
+	}
+
+	return;
+}
+
+
+extern void
+signals_unblock(void)
+{
+	if (signals_are_initialized) {
+		assert(signals_block_count > 0);
+
+		if (--signals_block_count == 0) {
+			const int saved_errno = errno;
+			mythread_sigmask(SIG_UNBLOCK, &hooked_signals, NULL);
+			errno = saved_errno;
+		}
+	}
+
+	return;
+}
+#endif
+
+
+extern void
+signals_exit(void)
+{
+	const int sig = exit_signal;
+
+	if (sig != 0) {
+		struct sigaction sa;
+		sa.sa_handler = SIG_DFL;
+		sigfillset(&sa.sa_mask);
+		sa.sa_flags = 0;
+		sigaction(sig, &sa, NULL);
+		raise(exit_signal);
+	}
+
+	return;
+}
+
+#else
+
+// While Windows has some very basic signal handling functions as required
+// 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)))
+{
+	// 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.
+	set_exit_status(E_ERROR);
+	user_abort = true;
+	return TRUE;
+}
+
+
+extern void
+signals_init(void)
+{
+	if (!SetConsoleCtrlHandler(&signal_handler, TRUE))
+		message_signal_handler();
+
+	return;
+}
+
+#endif
diff --git a/src/xz/signals.h b/src/xz/signals.h
new file mode 100644
index 0000000..5b125e0
--- /dev/null
+++ b/src/xz/signals.h
@@ -0,0 +1,43 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       signals.h
+/// \brief      Handling signals to abort operation
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+/// If this is true, we will clean up the possibly incomplete output file,
+/// return to main() as soon as practical. That is, the code needs to poll
+/// this variable in various places.
+extern volatile sig_atomic_t user_abort;
+
+
+/// Initialize the signal handler, which will set user_abort to true when
+/// user e.g. presses C-c.
+extern void signals_init(void);
+
+
+#if (defined(_WIN32) && !defined(__CYGWIN__)) || defined(__VMS)
+#	define signals_block() do { } while (0)
+#	define signals_unblock() do { } while (0)
+#else
+/// Block the signals which don't have SA_RESTART and which would just set
+/// user_abort to true. This is handy when we don't want to handle EINTR
+/// and don't want SA_RESTART either.
+extern void signals_block(void);
+
+/// Unblock the signals blocked by signals_block().
+extern void signals_unblock(void);
+#endif
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#	define signals_exit() do { } while (0)
+#else
+/// If user has sent us a signal earlier to terminate the process,
+/// re-raise that signal to actually terminate the process.
+extern void signals_exit(void);
+#endif
diff --git a/src/xz/suffix.c b/src/xz/suffix.c
new file mode 100644
index 0000000..f2a2da2
--- /dev/null
+++ b/src/xz/suffix.c
@@ -0,0 +1,211 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       suffix.c
+/// \brief      Checks filename suffix and creates the destination filename
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "private.h"
+
+// For case-insensitive filename suffix on case-insensitive systems
+#if defined(TUKLIB_DOSLIKE) || defined(__VMS)
+#	define strcmp strcasecmp
+#endif
+
+
+static char *custom_suffix = NULL;
+
+
+struct suffix_pair {
+	const char *compressed;
+	const char *uncompressed;
+};
+
+
+/// \brief      Checks if src_name has given compressed_suffix
+///
+/// \param      suffix      Filename suffix to look for
+/// \param      src_name    Input filename
+/// \param      src_len     strlen(src_name)
+///
+/// \return     If src_name has the suffix, src_len - strlen(suffix) is
+///             returned. It's always a positive integer. Otherwise zero
+///             is returned.
+static size_t
+test_suffix(const char *suffix, const char *src_name, size_t src_len)
+{
+	const size_t suffix_len = strlen(suffix);
+
+	// The filename must have at least one character in addition to
+	// the suffix. src_name may contain path to the filename, so we
+	// need to check for directory separator too.
+	if (src_len <= suffix_len || src_name[src_len - suffix_len - 1] == '/')
+		return 0;
+
+	if (strcmp(suffix, src_name + src_len - suffix_len) == 0)
+		return src_len - suffix_len;
+
+	return 0;
+}
+
+
+/// \brief      Removes the filename suffix of the compressed file
+///
+/// \return     Name of the uncompressed file, or NULL if file has unknown
+///             suffix.
+static char *
+uncompressed_name(const char *src_name, const size_t src_len)
+{
+	static const struct suffix_pair suffixes[] = {
+		{ ".xz",    "" },
+		{ ".txz",   ".tar" }, // .txz abbreviation for .txt.gz is rare.
+		{ ".lzma",  "" },
+		{ ".tlz",   ".tar" },
+		// { ".gz",    "" },
+		// { ".tgz",   ".tar" },
+	};
+
+	const char *new_suffix = "";
+	size_t new_len = 0;
+
+	if (opt_format == FORMAT_RAW) {
+		// Don't check for known suffixes when --format=raw was used.
+		if (custom_suffix == NULL) {
+			message_error(_("%s: With --format=raw, "
+					"--suffix=.SUF is required unless "
+					"writing to stdout"), src_name);
+			return NULL;
+		}
+	} else {
+		for (size_t i = 0; i < ARRAY_SIZE(suffixes); ++i) {
+			new_len = test_suffix(suffixes[i].compressed,
+					src_name, src_len);
+			if (new_len != 0) {
+				new_suffix = suffixes[i].uncompressed;
+				break;
+			}
+		}
+	}
+
+	if (new_len == 0 && custom_suffix != NULL)
+		new_len = test_suffix(custom_suffix, src_name, src_len);
+
+	if (new_len == 0) {
+		message_warning(_("%s: Filename has an unknown suffix, "
+				"skipping"), src_name);
+		return NULL;
+	}
+
+	const size_t new_suffix_len = strlen(new_suffix);
+	char *dest_name = xmalloc(new_len + new_suffix_len + 1);
+
+	memcpy(dest_name, src_name, new_len);
+	memcpy(dest_name + new_len, new_suffix, new_suffix_len);
+	dest_name[new_len + new_suffix_len] = '\0';
+
+	return dest_name;
+}
+
+
+/// \brief      Appends suffix to src_name
+///
+/// In contrast to uncompressed_name(), we check only suffixes that are valid
+/// for the specified file format.
+static char *
+compressed_name(const char *src_name, const size_t src_len)
+{
+	// The order of these must match the order in args.h.
+	static const struct suffix_pair all_suffixes[][3] = {
+		{
+			{ ".xz",    "" },
+			{ ".txz",   ".tar" },
+			{ NULL, NULL }
+		}, {
+			{ ".lzma",  "" },
+			{ ".tlz",   ".tar" },
+			{ NULL,     NULL }
+/*
+		}, {
+			{ ".gz",    "" },
+			{ ".tgz",   ".tar" },
+			{ NULL,     NULL }
+*/
+		}, {
+			// --format=raw requires specifying the suffix
+			// manually or using stdout.
+			{ NULL,     NULL }
+		}
+	};
+
+	// args.c ensures this.
+	assert(opt_format != FORMAT_AUTO);
+
+	const size_t format = opt_format - 1;
+	const struct suffix_pair *const suffixes = all_suffixes[format];
+
+	for (size_t i = 0; suffixes[i].compressed != NULL; ++i) {
+		if (test_suffix(suffixes[i].compressed, src_name, src_len)
+				!= 0) {
+			message_warning(_("%s: File already has `%s' "
+					"suffix, skipping"), src_name,
+					suffixes[i].compressed);
+			return NULL;
+		}
+	}
+
+	// TODO: Hmm, maybe it would be better to validate this in args.c,
+	// since the suffix handling when decoding is weird now.
+	if (opt_format == FORMAT_RAW && custom_suffix == NULL) {
+		message_error(_("%s: With --format=raw, "
+				"--suffix=.SUF is required unless "
+				"writing to stdout"), src_name);
+		return NULL;
+	}
+
+	const char *suffix = custom_suffix != NULL
+			? custom_suffix : suffixes[0].compressed;
+	const size_t suffix_len = strlen(suffix);
+
+	char *dest_name = xmalloc(src_len + suffix_len + 1);
+
+	memcpy(dest_name, src_name, src_len);
+	memcpy(dest_name + src_len, suffix, suffix_len);
+	dest_name[src_len + suffix_len] = '\0';
+
+	return dest_name;
+}
+
+
+extern char *
+suffix_get_dest_name(const char *src_name)
+{
+	assert(src_name != NULL);
+
+	// Length of the name is needed in all cases to locate the end of
+	// the string to compare the suffix, so calculate the length here.
+	const size_t src_len = strlen(src_name);
+
+	return opt_mode == MODE_COMPRESS
+			? compressed_name(src_name, src_len)
+			: uncompressed_name(src_name, src_len);
+}
+
+
+extern void
+suffix_set(const char *suffix)
+{
+	// Empty suffix and suffixes having a slash are rejected. Such
+	// suffixes would break things later.
+	if (suffix[0] == '\0' || strchr(suffix, '/') != NULL)
+		message_fatal(_("%s: Invalid filename suffix"), optarg);
+
+	// Replace the old custom_suffix (if any) with the new suffix.
+	free(custom_suffix);
+	custom_suffix = xstrdup(suffix);
+	return;
+}
diff --git a/src/xz/suffix.h b/src/xz/suffix.h
new file mode 100644
index 0000000..5537d73
--- /dev/null
+++ b/src/xz/suffix.h
@@ -0,0 +1,28 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       suffix.h
+/// \brief      Checks filename suffix and creates the destination filename
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+/// \brief      Get the name of the destination file
+///
+/// Depending on the global variable opt_mode, this tries to find a matching
+/// counterpart for src_name. If the name can be constructed, it is allocated
+/// and returned (caller must free it). On error, a message is printed and
+/// NULL is returned.
+extern char *suffix_get_dest_name(const char *src_name);
+
+
+/// \brief      Set a custom filename suffix
+///
+/// This function calls xstrdup() for the given suffix, thus the caller
+/// doesn't need to keep the memory allocated. There can be only one custom
+/// suffix, thus if this is called multiple times, the old suffixes are freed
+/// and forgotten.
+extern void suffix_set(const char *suffix);
diff --git a/src/xz/util.c b/src/xz/util.c
new file mode 100644
index 0000000..19f5eee
--- /dev/null
+++ b/src/xz/util.c
@@ -0,0 +1,320 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       util.c
+/// \brief      Miscellaneous utility functions
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "private.h"
+#include <stdarg.h>
+
+
+extern void *
+xrealloc(void *ptr, size_t size)
+{
+	assert(size > 0);
+
+	ptr = realloc(ptr, size);
+	if (ptr == NULL)
+		message_fatal("%s", strerror(errno));
+
+	return ptr;
+}
+
+
+extern char *
+xstrdup(const char *src)
+{
+	assert(src != NULL);
+	const size_t size = strlen(src) + 1;
+	char *dest = xmalloc(size);
+	return memcpy(dest, src, size);
+}
+
+
+extern uint64_t
+str_to_uint64(const char *name, const char *value, uint64_t min, uint64_t max)
+{
+	uint64_t result = 0;
+
+	// Skip blanks.
+	while (*value == ' ' || *value == '\t')
+		++value;
+
+	// Accept special value "max". Supporting "min" doesn't seem useful.
+	if (strcmp(value, "max") == 0)
+		return max;
+
+	if (*value < '0' || *value > '9')
+		message_fatal(_("%s: Value is not a non-negative "
+				"decimal integer"), value);
+
+	do {
+		// Don't overflow.
+		if (result > UINT64_MAX / 10)
+			goto error;
+
+		result *= 10;
+
+		// Another overflow check
+		const uint32_t add = *value - '0';
+		if (UINT64_MAX - add < result)
+			goto error;
+
+		result += add;
+		++value;
+	} while (*value >= '0' && *value <= '9');
+
+	if (*value != '\0') {
+		// Look for suffix. Originally this supported both base-2
+		// and base-10, but since there seems to be little need
+		// for base-10 in this program, treat everything as base-2
+		// and also be more relaxed about the case of the first
+		// letter of the 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) {
+			message(V_ERROR, _("%s: Invalid multiplier suffix"),
+					value - 1);
+			message_fatal(_("Valid suffixes are `KiB' (2^10), "
+					"`MiB' (2^20), and `GiB' (2^30)."));
+		}
+
+		// Don't overflow here either.
+		if (result > UINT64_MAX / multiplier)
+			goto error;
+
+		result *= multiplier;
+	}
+
+	if (result < min || result > max)
+		goto error;
+
+	return result;
+
+error:
+	message_fatal(_("Value of the option `%s' must be in the range "
+				"[%" PRIu64 ", %" PRIu64 "]"),
+				name, min, max);
+}
+
+
+extern uint64_t
+round_up_to_mib(uint64_t n)
+{
+	return (n >> 20) + ((n & ((UINT32_C(1) << 20) - 1)) != 0);
+}
+
+
+extern const char *
+uint64_to_str(uint64_t value, 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));
+		thousand = bufs[slot][0] == '1' ? WORKS : BROKEN;
+	}
+
+	if (thousand == WORKS)
+		snprintf(bufs[slot], sizeof(bufs[slot]), "%'" PRIu64, value);
+	else
+		snprintf(bufs[slot], sizeof(bufs[slot]), "%" PRIu64, value);
+
+	return bufs[slot];
+}
+
+
+extern const char *
+uint64_to_nicestr(uint64_t value, enum nicestr_unit unit_min,
+		enum nicestr_unit unit_max, bool always_also_bytes,
+		uint32_t slot)
+{
+	assert(unit_min <= unit_max);
+	assert(unit_max <= NICESTR_TIB);
+
+	enum nicestr_unit unit = NICESTR_B;
+	const char *str;
+
+	if ((unit_min == NICESTR_B && value < 10000)
+			|| unit_max == NICESTR_B) {
+		// The value is shown as bytes.
+		str = uint64_to_str(value, slot);
+	} else {
+		// Scale the value to a nicer unit. Unless unit_min and
+		// unit_max limit us, we will show at most five significant
+		// digits with one decimal place.
+		double d = (double)(value);
+		do {
+			d /= 1024.0;
+			++unit;
+		} while (unit < unit_min || (d > 9999.9 && unit < unit_max));
+
+		str = double_to_str(d);
+	}
+
+	static const char suffix[5][4] = { "B", "KiB", "MiB", "GiB", "TiB" };
+
+	// 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 (thousand == WORKS)
+		snprintf(buf, sizeof(buf), "%'.1f", value);
+	else
+		snprintf(buf, sizeof(buf), "%.1f", value);
+
+	return buf;
+}
+
+
+extern void
+my_snprintf(char **pos, size_t *left, const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	const int len = vsnprintf(*pos, *left, fmt, ap);
+	va_end(ap);
+
+	// 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.
+	if (len < 0 || (size_t)(len) >= *left) {
+		*left = 0;
+	} else {
+		*pos += len;
+		*left -= len;
+	}
+
+	return;
+}
+
+
+/*
+/// \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)
+{
+	if (filename[0] == '\0') {
+		message_error(_("Empty filename, skipping"));
+		return true;
+	}
+
+	return false;
+}
+
+
+extern bool
+is_tty_stdin(void)
+{
+	const bool ret = isatty(STDIN_FILENO);
+
+	if (ret)
+		message_error(_("Compressed data cannot be read from "
+				"a terminal"));
+
+	return ret;
+}
+
+
+extern bool
+is_tty_stdout(void)
+{
+	const bool ret = isatty(STDOUT_FILENO);
+
+	if (ret)
+		message_error(_("Compressed data cannot be written to "
+				"a terminal"));
+
+	return ret;
+}
diff --git a/src/xz/util.h b/src/xz/util.h
new file mode 100644
index 0000000..2e08b4a
--- /dev/null
+++ b/src/xz/util.h
@@ -0,0 +1,129 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       util.h
+/// \brief      Miscellaneous utility functions
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+/// \brief      Safe malloc() that never returns NULL
+///
+/// \note       xmalloc(), xrealloc(), and xstrdup() must not be used when
+///             there are files open for writing, that should be cleaned up
+///             before exiting.
+#define xmalloc(size) xrealloc(NULL, size)
+
+
+/// \brief      Safe realloc() that never returns NULL
+extern void *xrealloc(void *ptr, size_t size);
+
+
+/// \brief      Safe strdup() that never returns NULL
+extern char *xstrdup(const char *src);
+
+
+/// \brief      Fancy version of strtoull()
+///
+/// \param      name    Name of the option to show in case of an error
+/// \param      value   String containing the number to be parsed; may
+///                     contain suffixes "k", "M", "G", "Ki", "Mi", or "Gi"
+/// \param      min     Minimum valid value
+/// \param      max     Maximum valid value
+///
+/// \return     Parsed value that is in the range [min, max]. Does not return
+///             if an error occurs.
+///
+extern uint64_t str_to_uint64(const char *name, const char *value,
+		uint64_t min, uint64_t max);
+
+
+/// \brief      Round an integer up to the next full MiB and convert to MiB
+///
+/// This is used when printing memory usage and limit.
+extern uint64_t round_up_to_mib(uint64_t n);
+
+
+/// \brief      Convert uint64_t to a string
+///
+/// Convert the given value to a string with locale-specific thousand
+/// separators, if supported by the snprintf() implementation. The string
+/// is stored into an internal static buffer indicated by the slot argument.
+/// A pointer to the selected buffer is returned.
+///
+/// This function exists, because non-POSIX systems don't support thousand
+/// separator in format strings. Solving the problem in a simple way doesn't
+/// work, because it breaks gettext (specifically, the xgettext tool).
+extern const char *uint64_to_str(uint64_t value, uint32_t slot);
+
+
+enum nicestr_unit {
+	NICESTR_B,
+	NICESTR_KIB,
+	NICESTR_MIB,
+	NICESTR_GIB,
+	NICESTR_TIB,
+};
+
+
+/// \brief      Convert uint64_t to a nice human readable string
+///
+/// This is like uint64_to_str() but uses B, KiB, MiB, GiB, or TiB suffix
+/// and optionally includes the exact size in parenthesis.
+///
+/// \param      value     Value to be printed
+/// \param      unit_min  Smallest unit to use. This and unit_max are used
+///                       e.g. when showing the progress indicator to force
+///                       the unit to MiB.
+/// \param      unit_max  Biggest unit to use. assert(unit_min <= unit_max).
+/// \param      always_also_bytes
+///                       Show also the exact byte value in parenthesis
+///                       if the nicely formatted string uses bigger unit
+///                       than bytes.
+/// \param      slot      Which static buffer to use to hold the string.
+///                       This is shared with uint64_to_str().
+///
+/// \return     Pointer to statically allocated buffer containing the string.
+///
+/// \note       This uses double_to_str() internally so the static buffer
+///             in double_to_str() will be overwritten.
+///
+extern const char *uint64_to_nicestr(uint64_t value,
+		enum nicestr_unit unit_min, enum nicestr_unit unit_max,
+		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
+/// are updated accordingly.
+extern void my_snprintf(char **pos, size_t *left, const char *fmt, ...)
+		lzma_attribute((format(printf, 3, 4)));
+
+
+/// \brief      Check if filename is empty and print an error message
+extern bool is_empty_filename(const char *filename);
+
+
+/// \brief      Test if stdin is a terminal
+///
+/// If stdin is a terminal, an error message is printed and exit status set
+/// to EXIT_ERROR.
+extern bool is_tty_stdin(void);
+
+
+/// \brief      Test if stdout is a terminal
+///
+/// If stdout is a terminal, an error message is printed and exit status set
+/// to EXIT_ERROR.
+extern bool is_tty_stdout(void);
diff --git a/src/xz/xz.1 b/src/xz/xz.1
new file mode 100644
index 0000000..2c24170
--- /dev/null
+++ b/src/xz/xz.1
@@ -0,0 +1,1707 @@
+'\" t
+.\"
+.\" Author: Lasse Collin
+.\"
+.\" This file has been put into the public domain.
+.\" You can do whatever you want with this file.
+.\"
+.TH XZ 1 "2010-06-15" "Tukaani" "XZ Utils"
+.SH NAME
+xz, unxz, xzcat, lzma, unlzma, lzcat \- Compress or decompress .xz and .lzma files
+.SH SYNOPSIS
+.B xz
+.RI [ option ]...
+.RI [ file ]...
+.PP
+.B unxz
+is equivalent to
+.BR "xz \-\-decompress" .
+.br
+.B xzcat
+is equivalent to
+.BR "xz \-\-decompress \-\-stdout" .
+.br
+.B lzma
+is equivalent to
+.BR "xz \-\-format=lzma" .
+.br
+.B unlzma
+is equivalent to
+.BR "xz \-\-format=lzma \-\-decompress" .
+.br
+.B lzcat
+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
+.B xz
+with appropriate arguments
+.RB ( "xz \-d"
+or
+.BR "xz \-dc" )
+instead of the names
+.B unxz
+and
+.BR xzcat.
+.SH DESCRIPTION
+.B xz
+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
+.B .lzma
+format and raw compressed streams with no container format headers
+are supported.
+.PP
+.B xz
+compresses or decompresses each
+.I file
+according to the selected operation mode.
+If no
+.I files
+are given or
+.I file
+is
+.BR \- ,
+.B xz
+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,
+.B xz
+will refuse to read compressed data from standard input if it is a terminal.
+.PP
+Unless
+.B \-\-stdout
+is specified,
+.I files
+other than
+.B \-
+are written to a new file whose name is derived from the source
+.I file
+name:
+.IP \(bu 3
+When compressing, the suffix of the target file format
+.RB ( .xz
+or
+.BR .lzma )
+is appended to the source filename to get the target filename.
+.IP \(bu 3
+When decompressing, the
+.B .xz
+or
+.B .lzma
+suffix is removed from the filename to get the target filename.
+.B xz
+also recognizes the suffixes
+.B .txz
+and
+.BR .tlz ,
+and replaces them with the
+.B .tar
+suffix.
+.PP
+If the target file already exists, an error is displayed and the
+.I file
+is skipped.
+.PP
+Unless writing to standard output,
+.B xz
+will display a warning and skip the
+.I file
+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.
+.IP \(bu 3
+.I File
+has more than one hard link.
+.IP \(bu 3
+.I File
+has setuid, setgid, or sticky bit set.
+.IP \(bu 3
+The operation mode is set to compress, and the
+.I file
+already has a suffix of the target file format
+.RB ( .xz
+or
+.B .txz
+when compressing to the
+.B .xz
+format, and
+.B .lzma
+or
+.B .tlz
+when compressing to the
+.B .lzma
+format).
+.IP \(bu 3
+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 ,
+.BR .txz ,
+.BR .lzma ,
+or
+.BR .tlz ).
+.PP
+After successfully compressing or decompressing the
+.IR file ,
+.B xz
+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
+.IR file .
+.B xz
+doesn't support copying other metadata like access control lists
+or extended attributes yet.
+.PP
+Once the target file has been successfully closed, the source
+.I file
+is removed unless
+.B \-\-keep
+was specified. The source
+.I file
+is never removed if the output is written to standard output.
+.PP
+Sending
+.B SIGINFO
+or
+.B SIGUSR1
+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
+.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,
+.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 less than 80 MiB, 80\ % of RAM is used as the limit.
+.IP \(bu 3
+Otherwise 80 MiB 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
+.B \-\-format=raw
+or
+.BR \-\-no\-adjust ,
+an error is displayed and
+.B xz
+will exit with exit status
+.BR 1 .
+.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.
+.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 concenated parts
+or after the last part. The padding must be null bytes and the size
+of the padding must be a multiple of four bytes. This can be useful
+if the .xz file is stored on a medium that stores file sizes
+e.g. as 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.
+.TP
+.B KiB
+The integer is multiplied by 1,024 (2^10). Also
+.BR Ki ,
+.BR k ,
+.BR kB ,
+.BR K ,
+and
+.B KB
+are accepted as synonyms for
+.BR KiB .
+.TP
+.B MiB
+The integer is multiplied by 1,048,576 (2^20). Also
+.BR Mi ,
+.BR m ,
+.BR M ,
+and
+.B MB
+are accepted as synonyms for
+.BR MiB .
+.TP
+.B GiB
+The integer is multiplied by 1,073,741,824 (2^30). Also
+.BR Gi ,
+.BR g ,
+.BR G ,
+and
+.B GB
+are accepted as synonyms for
+.BR GiB .
+.PP
+A special value
+.B max
+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.
+.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,
+.B unxz
+implies
+.BR \-\-decompress ).
+.TP
+.BR \-d ", " \-\-decompress ", " \-\-uncompress
+Decompress.
+.TP
+.BR \-t ", " \-\-test
+Test the integrity of compressed
+.IR files .
+No files are created or removed. This option is equivalent to
+.B "\-\-decompress \-\-stdout"
+except that the decompressed data is discarded instead of being
+written to standard output.
+.TP
+.BR \-l ", " \-\-list
+List 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 it 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. To get machine-readable output,
+.B \-\-robot \-\-list
+should be used.
+.SS "Operation modifiers"
+.TP
+.BR \-k ", " \-\-keep
+Keep (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.
+.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.
+.IP \(bu 3
+If combined 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
+.B xzcat
+.B \--force
+like
+.BR cat (1)
+for files that have not been compressed with
+.BR xz .
+Note that in future,
+.B xz
+might support new compressed file formats, which may make
+.B xz
+decompress more types of files instead of copying them as is to
+standard output.
+.BI \-\-format= format
+can be used to restrict
+.B xz
+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 \-\-keep .
+.TP
+.B \-\-no\-sparse
+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.
+.TP
+\fB\-S\fR \fI.suf\fR, \fB\-\-suffix=\fI.suf
+When compressing, use
+.I .suf
+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
+.IR .suf ,
+a warning is displayed and the file is skipped.
+.IP
+When decompressing, recognize also files with the suffix
+.I .suf
+in addition to files with the
+.BR .xz ,
+.BR .txz ,
+.BR .lzma ,
+or
+.B .tlz
+suffix. If the source file has the suffix
+.IR .suf ,
+the suffix is removed to get the target filename.
+.IP
+When compressing or decompressing raw streams
+.RB ( \-\-format=raw ),
+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]
+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
+.RB ( \- )
+is taken as a regular filename; it doesn't mean standard input.
+If filenames are given also as command line arguments, they are
+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.
+.SS "Basic file format and compression options"
+.TP
+\fB\-F\fR \fIformat\fR, \fB\-\-format=\fIformat
+Specify the file format to compress or decompress:
+.RS
+.IP \(bu 3
+.BR 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.
+Note that raw streams (created with
+.BR \-\-format=raw )
+cannot be auto-detected.
+.IP \(bu 3
+.BR xz :
+Compress to the
+.B .xz
+file format, or accept only
+.B .xz
+files when decompressing.
+.IP \(bu 3
+.B lzma
+or
+.BR alone :
+Compress to the legacy
+.B .lzma
+file format, or accept only
+.B .lzma
+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
+.B \-\-format=raw
+but also specify the filter chain, which would normally be stored in the
+container format 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
+.B .xz
+format; the
+.B .lzma
+format doesn't support integrity checks.
+The integrity check (if any) is verified when the
+.B .xz
+file is decompressed.
+.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 :
+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.
+.RE
+.IP
+Integrity of the
+.B .xz
+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,
+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
+and
+.B \-2
+should give compression speed and ratios comparable to
+.B "bzip2 \-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,
+.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.
+.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."
+.RS
+.RS
+.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
+.TE
+.RE
+.RE
+.IP
+When compressing,
+.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.
+.TP
+.BR \-\-fast " and " \-\-best
+These are somewhat misleading aliases for
+.B \-0
+and
+.BR \-9 ,
+respectively.
+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
+.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\-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
+.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 .
+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
+.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 \-\-long-help
+option.
+.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
+.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
+.RB ( \-\-format=raw ),
+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
+.I options
+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
+.B .lzma
+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
+LZMA1 and LZMA2 share the same set of
+.IR options :
+.RS
+.TP
+.BI preset= preset
+Reset all LZMA1 or LZMA2
+.I options
+to
+.IR preset .
+.I Preset
+consist of an integer, which may be followed by single-letter preset
+modifiers. The integer can be from
+.B 0
+to
+.BR 9 ,
+matching the command line options \fB\-0\fR ... \fB\-9\fR.
+The only supported modifier is currently
+.BR e ,
+which matches
+.BR \-\-extreme .
+.IP
+The default
+.I preset
+is
+.BR 6 ,
+from which the default values for the rest of the LZMA1 or LZMA2
+.I options
+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.
+.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 .
+In addition, the sum of
+.I lc
+and
+.I lp
+must not exceed
+.BR 4 .
+.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 .
+.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
+and
+.B normal
+for
+.I presets
+.BR 3 \- 9 .
+.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
+.I dict
+is a power of two.
+.RS
+.TP
+.B hc3
+Hash Chain with 2- and 3-byte hashing
+.br
+Minimum value for
+.IR nice :
+3
+.br
+Memory usage:
+.I dict
+* 7.5 (if
+.I dict
+<= 16 MiB);
+.br
+.I dict
+* 5.5 + 64 MiB (if
+.I dict
+> 16 MiB)
+.TP
+.B hc4
+Hash Chain with 2-, 3-, and 4-byte hashing
+.br
+Minimum value for
+.IR nice :
+4
+.br
+Memory usage:
+.I dict
+* 7.5
+.TP
+.B bt2
+Binary Tree with 2-byte hashing
+.br
+Minimum value for
+.IR nice :
+2
+.br
+Memory usage:
+.I dict
+* 9.5
+.TP
+.B bt3
+Binary Tree with 2- and 3-byte hashing
+.br
+Minimum value for
+.IR nice :
+3
+.br
+Memory usage:
+.I dict
+* 11.5 (if
+.I dict
+<= 16 MiB);
+.br
+.I dict
+* 9.5 + 64 MiB (if
+.I dict
+> 16 MiB)
+.TP
+.B bt4
+Binary Tree with 2-, 3-, and 4-byte hashing
+.br
+Minimum value for
+.IR nice :
+4
+.br
+Memory usage:
+.I dict
+* 11.5
+.RE
+.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
+.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.
+.TP
+.BI depth= depth
+Specify the maximum search depth in the match finder. The default is the
+special value
+.BR 0 ,
+which makes the compressor determine a reasonable
+.I depth
+from
+.I mf
+and
+.IR nice .
+.IP
+Using very high values for
+.I depth
+can make the encoder extremely slow with carefully crafted files.
+Avoid setting the
+.I depth
+over 1000 unless you are prepared to interrupt the compression in case it
+is taking too long.
+.RE
+.IP
+When decoding raw streams
+.RB ( \-\-format=raw ),
+LZMA2 needs only the value of
+.BR dict .
+LZMA1 needs also
+.BR lc ,
+.BR lp ,
+and
+.BR pb.
+.TP
+\fB\-\-x86\fR[\fB=\fIoptions\fR]
+.TP
+\fB\-\-powerpc\fR[\fB=\fIoptions\fR]
+.TP
+\fB\-\-ia64\fR[\fB=\fIoptions\fR]
+.TP
+\fB\-\-arm\fR[\fB=\fIoptions\fR]
+.TP
+\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
+Different instruction sets have have different alignment:
+.RS
+.RS
+.TS
+tab(;);
+l n l
+l n l.
+Filter;Alignment;Notes
+x86;1;32-bit and 64-bit x86
+PowerPC;4;Big endian only
+ARM;4;Little endian only
+ARM-Thumb;2;Little endian only
+IA-64;16;Big or little endian
+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
+.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
+All BCJ filters support the same
+.IR options :
+.RS
+.TP
+.BI start= offset
+Specify the start
+.I offset
+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
+.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
+Supported
+.IR options :
+.RS
+.TP
+.BI dist= distance
+Specify the
+.I distance
+of the delta calculation as bytes.
+.I distance
+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.
+.TP
+.BR \-v ", " \-\-verbose
+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
+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.
+.IP \(bu 3
+Amount of compressed data produced (compressing) or consumed (decompressing).
+.IP \(bu 3
+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.
+.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
+.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
+.B xz
+started processing the file.
+.RE
+.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.
+.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
+.B \-\-quiet
+and
+.B \-\-no\-warn
+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
+.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
+.B xz
+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
+.B xz
+thinks your system has, use
+.BR "\-\-memory=100% \-\-info\-memory" .
+.TP
+.BR \-h ", " \-\-help
+Display a help message describing the most commonly used options,
+and exit successfully.
+.TP
+.BR \-H ", " \-\-long\-help
+Display a help message describing all features of
+.BR xz ,
+and exit successfully
+.TP
+.BR \-V ", " \-\-version
+Display the version number of
+.B xz
+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.
+.PP
+.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.
+.B 0
+is alpha,
+.B 1
+is beta, and
+.B 2
+is stable.
+.I S
+should be always
+.B 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 the current memory usage limit as bytes on a single line.
+To get the total amount of installed RAM, use
+.BR "xz \-\-robot \-\-memory=100% \-\-info-memory" .
+.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:
+.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
+.PP
+The columns of the
+.B stream
+lines:
+.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
+.PP
+The columns of the
+.B block
+lines:
+.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
+.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:
+.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 (as 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
+.PP
+The columns of the
+.B totals
+line:
+.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.
+.RE
+.PP
+If
+.B \-\-verbose
+was specified twice, additional columns are included on the
+.B totals
+line:
+.RS
+.IP 10. 4
+Maximum amount of memory (as 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
+.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
+All is good.
+.TP
+.B 1
+An error occurred.
+.TP
+.B 2
+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.
+.SH ENVIRONMENT
+.TP
+.B XZ_OPT
+A space-separated list of options is parsed from
+.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.
+.SH "LZMA UTILS COMPATIBILITY"
+The command line syntax of
+.B xz
+is practically a superset of
+.BR lzma ,
+.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.
+.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.
+.RS
+.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
+\-6;8 MiB;4 MiB
+\-7;16 MiB;8 MiB
+\-8;32 MiB;16 MiB
+\-9;64 MiB;32 MiB
+.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
+make the difference even bigger:
+.RS
+.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
+\-6;94 MiB;45 MiB
+\-7;186 MiB;83 MiB
+\-8;370 MiB;159 MiB
+\-9;674 MiB;311 MiB
+.TE
+.RE
+.PP
+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.
+.SS "Streamed vs. non-streamed .lzma files"
+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.
+.PP
+.B xz
+supports decompressing
+.B .lzma
+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
+.B .lzma
+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
+.B .lzma
+files with known uncompressed size.
+.SS "Unsupported .lzma files"
+The
+.B .lzma
+format allows
+.I lc
+values up to 8, and
+.I lp
+values up to 4. LZMA Utils can decompress files with any
+.I lc
+and
+.IR lp ,
+but always creates files with
+.B lc=3
+and
+.BR lp=0 .
+Creating files with other
+.I lc
+and
+.I lp
+is possible with
+.B xz
+and with LZMA SDK.
+.PP
+The implementation of the LZMA1 filter in liblzma requires
+that the sum of
+.I lc
+and
+.I lp
+must not exceed 4. Thus,
+.B .lzma
+files which exceed this limitation, cannot be decompressed with
+.BR xz .
+.PP
+LZMA Utils creates only
+.B .lzma
+files which have dictionary size of
+.RI "2^" n
+(a power of 2), but accepts files with any dictionary size.
+liblzma accepts only
+.B .lzma
+files which have dictionary size of
+.RI "2^" n
+or
+.RI "2^" n " + 2^(" n "\-1)."
+This is to decrease false positives when detecting
+.B .lzma
+files.
+.PP
+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
+.B .lzma
+stream. In most situations, this is a bug. This also means that LZMA Utils
+don't support decompressing concatenated
+.B .lzma
+files.
+.PP
+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
+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.
+.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
+implementation, which can then be used with
+.BR \-\-rsyncable .
+.SS Embedded .xz decompressors
+Embedded
+.B .xz
+decompressor implementations like XZ Embedded don't necessarily support files
+created with
+.I check
+types other than
+.B none
+and
+.BR crc32 .
+Since the default is \fB\-\-check=\fIcrc64\fR, you must use
+.B \-\-check=none
+or
+.B \-\-check=crc32
+when creating files for embedded systems.
+.PP
+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
+integrity check if the particular
+.I check
+is not supported.
+.PP
+XZ Embedded supports BCJ filters, but only with the default start offset.
+.SH EXAMPLES
+.SS Basics
+A mix of compressed and uncompressed files can be decompressed
+to standard output with a single command:
+.IP
+.B "xz -dcf a.txt b.txt.xz c.txt d.txt.xz > abcd.txt"
+.SS Parallel compression of many files
+On GNU and *BSD,
+.BR find (1)
+and
+.BR xargs (1)
+can be used to parallellize compression of many files:
+.PP
+.IP
+.B "find . \-type f \e! \-name '*.xz' \-print0 | xargs \-0r \-P4 \-n16 xz"
+.PP
+The
+.B \-P
+option 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
+.BR 1 ;
+with tens of thousands of files,
+.B 100
+or even more may be appropriate to reduce the number of
+.B xz
+processes that
+.BR xargs (1)
+will eventually create.
+.SS Robot mode examples
+Calculating how many bytes have been saved in total after compressing
+multiple files:
+.IP
+.B "xz --robot --list *.xz | awk '/^totals/{print $5\-$4}'"
+.SH "SEE ALSO"
+.BR xzdec (1),
+.BR gzip (1),
+.BR bzip2 (1)
+.PP
+XZ Utils: <http://tukaani.org/xz/>
+.br
+XZ Embedded: <http://tukaani.org/xz/embedded.html>
+.br
+LZMA SDK: <http://7-zip.org/sdk.html>
diff --git a/src/xz/xz_w32res.rc b/src/xz/xz_w32res.rc
new file mode 100644
index 0000000..bad3020
--- /dev/null
+++ b/src/xz/xz_w32res.rc
@@ -0,0 +1,12 @@
+/*
+ * Author: Lasse Collin
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ */
+
+#define MY_TYPE VFT_APP
+#define MY_NAME "xz"
+#define MY_SUFFIX ".exe"
+#define MY_DESC "xz data compression tool for .xz and .lzma files"
+#include "common_w32res.rc"
diff --git a/src/xzdec/Makefile.am b/src/xzdec/Makefile.am
new file mode 100644
index 0000000..ad48772
--- /dev/null
+++ b/src/xzdec/Makefile.am
@@ -0,0 +1,68 @@
+##
+## Author: Lasse Collin
+##
+## This file has been put into the public domain.
+## You can do whatever you want with this file.
+##
+
+# Windows resource compiler support. It's fine to use xz_CPPFLAGS
+# also for lzmadec.
+.rc.o:
+	$(RC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+		$(xzdec_CPPFLAGS) $(CPPFLAGS) $(RCFLAGS) -i $< -o $@
+
+
+bin_PROGRAMS = xzdec lzmadec
+
+xzdec_SOURCES = \
+	xzdec.c \
+	$(top_srcdir)/src/common/tuklib_progname.c \
+	$(top_srcdir)/src/common/tuklib_exit.c
+
+if COND_W32
+xzdec_SOURCES += xzdec_w32res.rc
+endif
+
+xzdec_CPPFLAGS = \
+	-DTUKLIB_GETTEXT=0 \
+	-I$(top_srcdir)/src/common \
+	-I$(top_srcdir)/src/liblzma/api \
+	-I$(top_builddir)/lib \
+	$(STATIC_CPPFLAGS)
+xzdec_LDFLAGS = $(STATIC_LDFLAGS)
+xzdec_LDADD = $(top_builddir)/src/liblzma/liblzma.la
+
+if COND_GNULIB
+xzdec_LDADD += $(top_builddir)/lib/libgnu.a
+endif
+
+xzdec_LDADD += $(LTLIBINTL)
+
+
+lzmadec_SOURCES = \
+	xzdec.c \
+	$(top_srcdir)/src/common/tuklib_progname.c \
+	$(top_srcdir)/src/common/tuklib_exit.c
+
+if COND_W32
+lzmadec_SOURCES += lzmadec_w32res.rc
+endif
+
+lzmadec_CPPFLAGS = $(xzdec_CPPFLAGS) -DLZMADEC
+lzmadec_LDFLAGS = $(xzdec_LDFLAGS)
+lzmadec_LDADD = $(xzdec_LDADD)
+
+
+dist_man_MANS = xzdec.1
+
+install-data-hook:
+	cd $(DESTDIR)$(mandir)/man1 && \
+	target=`echo xzdec | sed '$(transform)'` && \
+	link=`echo lzmadec | sed '$(transform)'` && \
+	rm -f $$link.1 && \
+	$(LN_S) $$target.1 $$link.1
+
+uninstall-hook:
+	cd $(DESTDIR)$(mandir)/man1 && \
+	link=`echo lzmadec | sed '$(transform)'` && \
+	rm -f $$link.1
diff --git a/src/xzdec/lzmadec_w32res.rc b/src/xzdec/lzmadec_w32res.rc
new file mode 100644
index 0000000..2c71a51
--- /dev/null
+++ b/src/xzdec/lzmadec_w32res.rc
@@ -0,0 +1,5 @@
+#define MY_TYPE VFT_APP
+#define MY_NAME "lzmadec"
+#define MY_SUFFIX ".exe"
+#define MY_DESC "lzmadec decompression tool for .lzma files"
+#include "common_w32res.rc"
diff --git a/src/xzdec/xzdec.1 b/src/xzdec/xzdec.1
new file mode 100644
index 0000000..3057c58
--- /dev/null
+++ b/src/xzdec/xzdec.1
@@ -0,0 +1,168 @@
+.\"
+.\" Author: Lasse Collin
+.\"
+.\" 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"
+.SH NAME
+xzdec, lzmadec \- Small .xz and .lzma decompressors
+.SH SYNOPSIS
+.B xzdec
+.RI [ option ]...
+.RI [ file ]...
+.br
+.B lzmadec
+.RI [ option ]...
+.RI [ file ]...
+.SH DESCRIPTION
+.B xzdec
+is a liblzma-based decompression-only tool for
+.B .xz
+(and only
+.BR .xz )
+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
+.B "xz \-\-decompress \-\-stdout"
+(and possibly a few other commonly used options) to decompress
+.B .xz
+files.
+.B lzmadec
+is identical to
+.B xzdec
+except that
+.B lzmadec
+supports
+.B .lzma
+files instead of
+.B .xz
+files.
+.PP
+To reduce the size of the executable,
+.B xzdec
+doesn't support multithreading or localization, and doesn't read options from
+.B XZ_OPT
+environment variable.
+.B xzdec
+doesn't support displaying intermediate progress information: sending
+.B SIGINFO
+to
+.B xzdec
+does nothing, but sending
+.B SIGUSR1
+terminates the process instead of displaying progress information.
+.SH OPTIONS
+.TP
+.BR \-d ", " \-\-decompress ", " \-\-uncompress
+Ignored for
+.BR xz (1)
+compatibility.
+.B xzdec
+supports only decompression.
+.TP
+.BR \-k ", " \-\-keep
+Ignored for
+.BR xz (1)
+compatibility.
+.B xzdec
+never creates or removes any files.
+.TP
+.BR \-c ", " \-\-stdout ", " \-\-to-stdout
+Ignored for
+.BR xz (1)
+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
+never displays any warnings or notices.
+Specify this twice to suppress errors.
+.TP
+.BR \-Q ", " \-\-no-warn
+Ignored for
+.BR xz (1)
+compatibility.
+.B xzdec
+never uses the exit status
+.BR "2" .
+.TP
+.BR \-h ", " \-\-help
+Display a help message and exit successfully.
+.TP
+.BR \-V ", " \-\-version
+Display the version number of
+.B xzdec
+and liblzma.
+.SH "EXIT STATUS"
+.TP
+.B 0
+All was good.
+.TP
+.B 1
+An error occurred.
+.PP
+.B xzdec
+doesn't have any warning messages like
+.BR xz (1)
+has, thus the exit status
+.B 2
+is not used by
+.BR xzdec .
+.SH NOTES
+.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
+.B .xz
+decompressor, consider using XZ Embedded.
+.SH "SEE ALSO"
+.BR xz (1)
+.PP
+XZ Embedded: <http://tukaani.org/xz/embedded.html>
diff --git a/src/xzdec/xzdec.c b/src/xzdec/xzdec.c
new file mode 100644
index 0000000..7f2e0fd
--- /dev/null
+++ b/src/xzdec/xzdec.c
@@ -0,0 +1,491 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       xzdec.c
+/// \brief      Simple single-threaded tool to uncompress .xz or .lzma files
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "sysdefs.h"
+#include "lzma.h"
+
+#include <stdarg.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "getopt.h"
+#include "tuklib_progname.h"
+#include "tuklib_exit.h"
+
+#ifdef TUKLIB_DOSLIKE
+#	include <fcntl.h>
+#	include <io.h>
+#endif
+
+
+#ifdef LZMADEC
+#	define TOOL_FORMAT "lzma"
+#else
+#	define TOOL_FORMAT "xz"
+#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;
+
+
+static void lzma_attribute((format(printf, 1, 2)))
+my_errorf(const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+
+	if (display_errors) {
+		fprintf(stderr, "%s: ", progname);
+		vfprintf(stderr, fmt, ap);
+		fprintf(stderr, "\n");
+	}
+
+	va_end(ap);
+	return;
+}
+
+
+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"
+"\n"
+"  -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"
+"  -V, --version      display the version number and exit\n"
+"\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);
+	tuklib_exit(EXIT_SUCCESS, EXIT_FAILURE, display_errors);
+}
+
+
+static void lzma_attribute((noreturn))
+version(void)
+{
+	printf(TOOL_FORMAT "dec (" PACKAGE_NAME ") " LZMA_VERSION_STRING "\n"
+			"liblzma %s\n", lzma_version_string());
+
+	tuklib_exit(EXIT_SUCCESS, EXIT_FAILURE, display_errors);
+}
+
+
+/// 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. :-(
+/// Since this function is used only for parsing the memory usage limit,
+/// this cheats a little and saturates too big values to UINT64_MAX instead
+/// of giving an error.
+///
+/// \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 / 10)
+			return UINT64_MAX;
+
+		result *= 10;
+
+		// Another overflow check
+		const uint32_t add = *value - '0';
+		if (UINT64_MAX - add < result)
+			return UINT64_MAX;
+
+		result += add;
+		++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)
+{
+	static const char short_opts[] = "cdkM:hqQV";
+	static const struct option long_opts[] = {
+		{ "stdout",       no_argument,         NULL, 'c' },
+		{ "to-stdout",    no_argument,         NULL, 'c' },
+		{ "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' },
+		{ "version",      no_argument,         NULL, 'V' },
+		{ NULL,           0,                   NULL, 0   }
+	};
+
+	int c;
+
+	while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL))
+			!= -1) {
+		switch (c) {
+		case 'c':
+		case 'd':
+		case 'k':
+		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;
+
+			break;
+
+		case 'h':
+			help();
+
+		case 'V':
+			version();
+
+		default:
+			exit(EXIT_FAILURE);
+		}
+	}
+
+	return;
+}
+
+
+static void
+uncompress(lzma_stream *strm, FILE *file, const char *filename)
+{
+	lzma_ret ret;
+
+	// Initialize the decoder
+#ifdef LZMADEC
+	ret = lzma_alone_decoder(strm, memlimit);
+#else
+	ret = lzma_stream_decoder(strm, memlimit, 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)");
+		exit(EXIT_FAILURE);
+	}
+
+	// Input and output buffers
+	uint8_t in_buf[BUFSIZ];
+	uint8_t out_buf[BUFSIZ];
+
+	strm->avail_in = 0;
+	strm->next_out = out_buf;
+	strm->avail_out = BUFSIZ;
+
+	lzma_action action = LZMA_RUN;
+
+	while (true) {
+		if (strm->avail_in == 0) {
+			strm->next_in = in_buf;
+			strm->avail_in = fread(in_buf, 1, BUFSIZ, file);
+
+			if (ferror(file)) {
+				// POSIX says that fread() sets errno if
+				// an error occurred. ferror() doesn't
+				// touch errno.
+				my_errorf("%s: Error reading input file: %s",
+						filename, strerror(errno));
+				exit(EXIT_FAILURE);
+			}
+
+#ifndef LZMADEC
+			// When using LZMA_CONCATENATED, we need to tell
+			// liblzma when it has got all the input.
+			if (feof(file))
+				action = LZMA_FINISH;
+#endif
+		}
+
+		ret = lzma_code(strm, action);
+
+		// Write and check write error before checking decoder error.
+		// This way as much data as possible gets written to output
+		// even if decoder detected an error.
+		if (strm->avail_out == 0 || ret != LZMA_OK) {
+			const size_t write_size = BUFSIZ - strm->avail_out;
+
+			if (fwrite(out_buf, 1, write_size, stdout)
+					!= write_size) {
+				// Wouldn't be a surprise if writing to stderr
+				// would fail too but at least try to show an
+				// error message.
+				my_errorf("Cannot write to standard output: "
+						"%s", strerror(errno));
+				exit(EXIT_FAILURE);
+			}
+
+			strm->next_out = out_buf;
+			strm->avail_out = BUFSIZ;
+		}
+
+		if (ret != LZMA_OK) {
+			if (ret == LZMA_STREAM_END) {
+#ifdef LZMADEC
+				// Check that there's no trailing garbage.
+				if (strm->avail_in != 0
+						|| fread(in_buf, 1, 1, file)
+							!= 0
+						|| !feof(file))
+					ret = LZMA_DATA_ERROR;
+				else
+					return;
+#else
+				// lzma_stream_decoder() already guarantees
+				// that there's no trailing garbage.
+				assert(strm->avail_in == 0);
+				assert(action == LZMA_FINISH);
+				assert(feof(file));
+				return;
+#endif
+			}
+
+			const char *msg;
+			switch (ret) {
+			case LZMA_MEM_ERROR:
+				msg = strerror(ENOMEM);
+				break;
+
+			case LZMA_MEMLIMIT_ERROR:
+				msg = "Memory usage limit reached";
+				break;
+
+			case LZMA_FORMAT_ERROR:
+				msg = "File format not recognized";
+				break;
+
+			case LZMA_OPTIONS_ERROR:
+				// FIXME: Better message?
+				msg = "Unsupported compression options";
+				break;
+
+			case LZMA_DATA_ERROR:
+				msg = "File is corrupt";
+				break;
+
+			case LZMA_BUF_ERROR:
+				msg = "Unexpected end of input";
+				break;
+
+			default:
+				msg = "Internal error (bug)";
+				break;
+			}
+
+			my_errorf("%s: %s", filename, msg);
+			exit(EXIT_FAILURE);
+		}
+	}
+}
+
+
+int
+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);
+
+	// The same lzma_stream is used for all files that we decode. This way
+	// we don't need to reallocate memory for every file if they use same
+	// compression settings.
+	lzma_stream strm = LZMA_STREAM_INIT;
+
+	// Some systems require setting stdin and stdout to binary mode.
+#ifdef TUKLIB_DOSLIKE
+	setmode(fileno(stdin), O_BINARY);
+	setmode(fileno(stdout), O_BINARY);
+#endif
+
+	if (optind == argc) {
+		// No filenames given, decode from stdin.
+		uncompress(&strm, stdin, "(stdin)");
+	} else {
+		// Loop through the filenames given on the command line.
+		do {
+			// "-" indicates stdin.
+			if (strcmp(argv[optind], "-") == 0) {
+				uncompress(&strm, stdin, "(stdin)");
+			} else {
+				FILE *file = fopen(argv[optind], "rb");
+				if (file == NULL) {
+					my_errorf("%s: %s", argv[optind],
+							strerror(errno));
+					exit(EXIT_FAILURE);
+				}
+
+				uncompress(&strm, file, argv[optind]);
+				fclose(file);
+			}
+		} while (++optind < argc);
+	}
+
+#ifndef NDEBUG
+	// Free the memory only when debugging. Freeing wastes some time,
+	// but allows detecting possible memory leaks with Valgrind.
+	lzma_end(&strm);
+#endif
+
+	tuklib_exit(EXIT_SUCCESS, EXIT_FAILURE, display_errors);
+}
diff --git a/src/xzdec/xzdec_w32res.rc b/src/xzdec/xzdec_w32res.rc
new file mode 100644
index 0000000..0e26a22
--- /dev/null
+++ b/src/xzdec/xzdec_w32res.rc
@@ -0,0 +1,12 @@
+/*
+ * Author: Lasse Collin
+ *
+ * This file has been put into the public domain.
+ * You can do whatever you want with this file.
+ */
+
+#define MY_TYPE VFT_APP
+#define MY_NAME "xzdec"
+#define MY_SUFFIX ".exe"
+#define MY_DESC "xzdec decompression tool for .xz files"
+#include "common_w32res.rc"
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644
index 0000000..d01787a
--- /dev/null
+++ b/tests/Makefile.am
@@ -0,0 +1,51 @@
+##
+## Author: Lasse Collin
+##
+## This file has been put into the public domain.
+## You can do whatever you want with this file.
+##
+
+EXTRA_DIST = \
+	files \
+	tests.h \
+	test_files.sh \
+	test_compress.sh \
+	bcj_test.c \
+	compress_prepared_bcj_sparc \
+	compress_prepared_bcj_x86
+
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/src/common \
+	-I$(top_srcdir)/src/liblzma/api \
+	-I$(top_builddir)/lib \
+	$(STATIC_CPPFLAGS)
+
+AM_LDFLAGS = $(STATIC_LDFLAGS)
+
+LDADD = $(top_builddir)/src/liblzma/liblzma.la
+
+if COND_GNULIB
+LDADD += $(top_builddir)/lib/libgnu.a
+endif
+
+LDADD += $(LTLIBINTL)
+
+check_PROGRAMS = \
+	create_compress_files \
+	test_check \
+	test_stream_flags \
+	test_filter_flags \
+	test_block_header \
+	test_index
+
+TESTS = \
+	test_check \
+	test_stream_flags \
+	test_filter_flags \
+	test_block_header \
+	test_index \
+	test_files.sh \
+	test_compress.sh
+
+clean-local:
+	-rm -f compress_generated_*
diff --git a/tests/bcj_test.c b/tests/bcj_test.c
new file mode 100644
index 0000000..05de38a
--- /dev/null
+++ b/tests/bcj_test.c
@@ -0,0 +1,65 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       bcj_test.c
+/// \brief      Source code of compress_prepared_bcj_*
+///
+/// This is a simple program that should make the compiler to generate
+/// PC-relative branches, jumps, and calls. The compiled files can then
+/// be used to test the branch conversion filters. Note that this program
+/// itself does nothing useful.
+///
+/// Compiling: gcc -std=c99 -fPIC -c bcj_test.c
+/// Don't optimize or strip.
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+extern int jump(int a, int b);
+
+
+extern int
+call(int a, int b)
+{
+	if (a < b)
+		a = jump(a, b);
+
+	return a;
+}
+
+
+extern int
+jump(int a, int b)
+{
+	// The loop generates conditional jump backwards.
+	while (1) {
+		if (a < b) {
+			a *= 2;
+			a += 3 * b;
+			break;
+		} else {
+			// Put enough code here to prevent JMP SHORT on x86.
+			a += b;
+			a /= 2;
+			b += b % 5;
+			a -= b / 3;
+			b = 2 * b + a - 1;
+			a *= b + a + 1;
+			b += a - 1;
+			a += b * 2 - a / 5;
+		}
+	}
+
+	return a;
+}
+
+
+int
+main(int argc, char **argv)
+{
+	int a = call(argc, argc + 1);
+	return a == 0;
+}
diff --git a/tests/compress_prepared_bcj_sparc b/tests/compress_prepared_bcj_sparc
new file mode 100644
index 0000000..86ea7dd
--- /dev/null
+++ b/tests/compress_prepared_bcj_sparc
Binary files differ
diff --git a/tests/compress_prepared_bcj_x86 b/tests/compress_prepared_bcj_x86
new file mode 100644
index 0000000..bcc546f
--- /dev/null
+++ b/tests/compress_prepared_bcj_x86
Binary files differ
diff --git a/tests/create_compress_files.c b/tests/create_compress_files.c
new file mode 100644
index 0000000..44367d8
--- /dev/null
+++ b/tests/create_compress_files.c
@@ -0,0 +1,157 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       create_compress_files.c
+/// \brief      Creates bunch of test files to be compressed
+///
+/// Using a test file generator program saves space in the source code
+/// package considerably.
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "sysdefs.h"
+#include <stdio.h>
+
+
+// Avoid re-creating the test files every time the tests are run.
+#define create_test(name) \
+do { \
+	if (!file_exists("compress_generated_" #name)) { \
+		FILE *file = file_create("compress_generated_" #name); \
+		write_ ## name(file); \
+		file_finish(file, "compress_generated_" #name); \
+	} \
+} while (0)
+
+
+static bool
+file_exists(const char *filename)
+{
+	// Trying to be somewhat portable by avoiding stat().
+	FILE *file = fopen(filename, "rb");
+	bool ret;
+
+	if (file != NULL) {
+		fclose(file);
+		ret = true;
+	} else {
+		ret = false;
+	}
+
+	return ret;
+}
+
+
+static FILE *
+file_create(const char *filename)
+{
+	FILE *file = fopen(filename, "wb");
+
+	if (file == NULL) {
+		perror(filename);
+		exit(1);
+	}
+
+	return file;
+}
+
+
+static void
+file_finish(FILE *file, const char *filename)
+{
+	const bool ferror_fail = ferror(file);
+	const bool fclose_fail = fclose(file);
+
+	if (ferror_fail || fclose_fail) {
+		perror(filename);
+		exit(1);
+	}
+}
+
+
+// File that repeats "abc\n" a few thousand times. This is targeted
+// especially at Subblock filter's run-length encoder.
+static void
+write_abc(FILE *file)
+{
+	for (size_t i = 0; i < 12345; ++i)
+		fwrite("abc\n", 4, 1, file);
+}
+
+
+// File that doesn't compress. We always use the same random seed to
+// generate identical files on all systems.
+static void
+write_random(FILE *file)
+{
+	uint32_t n = 5;
+
+	for (size_t i = 0; i < 123456; ++i) {
+		n = 101771 * n + 71777;
+
+		putc(n & 0xFF, file);
+		putc((n >> 8) & 0xFF, file);
+		putc((n >> 16) & 0xFF, file);
+		putc(n >> 24, file);
+	}
+}
+
+
+// Text file
+static void
+write_text(FILE *file)
+{
+	static const char *lorem[] = {
+		"Lorem", "ipsum", "dolor", "sit", "amet,", "consectetur",
+		"adipisicing", "elit,", "sed", "do", "eiusmod", "tempor",
+		"incididunt", "ut", "labore", "et", "dolore", "magna",
+		"aliqua.", "Ut", "enim", "ad", "minim", "veniam,", "quis",
+		"nostrud", "exercitation", "ullamco", "laboris", "nisi",
+		"ut", "aliquip", "ex", "ea", "commodo", "consequat.",
+		"Duis", "aute", "irure", "dolor", "in", "reprehenderit",
+		"in", "voluptate", "velit", "esse", "cillum", "dolore",
+		"eu", "fugiat", "nulla", "pariatur.", "Excepteur", "sint",
+		"occaecat", "cupidatat", "non", "proident,", "sunt", "in",
+		"culpa", "qui", "officia", "deserunt", "mollit", "anim",
+		"id", "est", "laborum."
+	};
+
+	// Let the first paragraph be the original text.
+	for (size_t w = 0; w < ARRAY_SIZE(lorem); ++w) {
+		fprintf(file, "%s ", lorem[w]);
+
+		if (w % 7 == 6)
+			fprintf(file, "\n");
+	}
+
+	// The rest shall be (hopefully) meaningless combinations of
+	// the same words.
+	uint32_t n = 29;
+
+	for (size_t p = 0; p < 500; ++p) {
+		fprintf(file, "\n\n");
+
+		for (size_t w = 0; w < ARRAY_SIZE(lorem); ++w) {
+			n = 101771 * n + 71777;
+
+			fprintf(file, "%s ", lorem[n % ARRAY_SIZE(lorem)]);
+
+			if (w % 7 == 6)
+				fprintf(file, "\n");
+		}
+	}
+}
+
+
+int
+main(void)
+{
+	create_test(abc);
+	create_test(random);
+	create_test(text);
+	return 0;
+}
diff --git a/tests/files/README b/tests/files/README
new file mode 100644
index 0000000..392ff76
--- /dev/null
+++ b/tests/files/README
@@ -0,0 +1,232 @@
+
+.xz Test Files
+----------------
+
+0. Introduction
+
+    This directory contains bunch of files to test handling of .xz files
+    in .xz decoder implementations. Many of the files have been created
+    by hand with a hex editor, thus there is no better "source code" than
+    the files themselves. All the test files (*.xz) and this README have
+    been put into the public domain.
+
+
+1. File Types
+
+    Good files (good-*.xz) must decode successfully without requiring
+    a lot of CPU time or RAM.
+
+    Unsupported files (unsupported-*.xz) are good files, but headers
+    indicate features not supported by the current file format
+    specification.
+
+    Bad files (bad-*.xz) must cause the decoder to give an error. Like
+    with the good files, these files must not require a lot of CPU time
+    or RAM before they get detected to be broken.
+
+
+2. Descriptions of Individual Files
+
+2.1. Good Files
+
+    good-0-empty.xz has one Stream with no Blocks.
+
+    good-0pad-empty.xz has one Stream with no Blocks followed by
+    four-byte Stream Padding.
+
+    good-0cat-empty.xz has two zero-Block Streams concatenated without
+    Stream Padding.
+
+    good-0catpad-empty.xz has two zero-Block Streams concatenated with
+    four-byte Stream Padding between the Streams.
+
+    good-1-check-none.xz has one Stream with one Block with two
+    uncompressed LZMA2 chunks and no integrity check.
+
+    good-1-check-crc32.xz has one Stream with one Block with two
+    uncompressed LZMA2 chunks and CRC32 check.
+
+    good-1-check-crc64.xz is like good-1-check-crc32.xz but with CRC64.
+
+    good-1-check-sha256.xz is like good-1-check-crc32.xz but with
+    SHA256.
+
+    good-2-lzma2.xz has one Stream with two Blocks with one uncompressed
+    LZMA2 chunk in each Block.
+
+    good-1-block_header-1.xz has both Compressed Size and Uncompressed
+    Size in the Block Header. This has also four extra bytes of Header
+    Padding.
+
+    good-1-block_header-2.xz has known Compressed Size.
+
+    good-1-block_header-3.xz has known Uncompressed Size.
+
+    good-1-delta-lzma2.tiff.xz is an image file that compresses
+    better with Delta+LZMA2 than with plain LZMA2.
+
+    good-1-x86-lzma2.xz uses the x86 filter (BCJ) and LZMA2. The
+    uncompressed file is compress_prepared_bcj_x86 found from the tests
+    directory.
+
+    good-1-sparc-lzma2.xz uses the SPARC filter and LZMA. The
+    uncompressed file is compress_prepared_bcj_sparc found from the tests
+    directory.
+
+    good-1-lzma2-1.xz has two LZMA2 chunks, of which the second sets
+    new properties.
+
+    good-1-lzma2-2.xz has two LZMA2 chunks, of which the second resets
+    the state without specifying new properties.
+
+    good-1-lzma2-3.xz has two LZMA2 chunks, of which the first is
+    uncompressed and the second is LZMA. The first chunk resets dictionary
+    and the second sets new properties.
+
+    good-1-lzma2-4.xz has three LZMA2 chunks: First is LZMA, second is
+    uncompressed with dictionary reset, and third is LZMA with new
+    properties but without dictionary reset.
+
+    good-1-3delta-lzma2.xz has three Delta filters and LZMA2.
+
+
+2.2. Unsupported Files
+
+    unsupported-check.xz uses Check ID 0x02 which isn't supported by
+    the current version of the file format. It is implementation-defined
+    how this file handled (it may reject it, or decode it possibly with
+    a warning).
+
+    unsupported-block_header.xz has a non-null byte in Header Padding,
+    which may indicate presence of a new unsupported field.
+
+    unsupported-filter_flags-1.xz has unsupported Filter ID 0x7F.
+
+    unsupported-filter_flags-2.xz specifies only Delta filter in the
+    List of Filter Flags, but Delta isn't allowed as the last filter in
+    the chain. It could be a little more correct to detect this file as
+    corrupt instead of unsupported, but saying it is unsupported is
+    simpler in case of liblzma.
+
+    unsupported-filter_flags-3.xz specifies two LZMA2 filters in the
+    List of Filter Flags. LZMA2 is allowed only as the last filter in the
+    chain. It could be a little more correct to detect this file as
+    corrupt instead of unsupported, but saying it is unsupported is
+    simpler in case of liblzma.
+
+
+2.3. Bad Files
+
+    bad-0pad-empty.xz has one Stream with no Blocks followed by
+    five-byte Stream Padding. Stream Padding must be a multiple of four
+    bytes, thus this file is corrupt.
+
+    bad-0catpad-empty.xz has two zero-Block Streams concatenated with
+    five-byte Stream Padding between the Streams.
+
+    bad-0cat-alone.xz is good-0-empty.xz concatenated with an empty
+    LZMA_Alone file.
+
+    bad-0cat-header_magic.xz is good-0cat-empty.xz but with one byte
+    wrong in the Header Magic Bytes field of the second Stream. liblzma
+    gives LZMA_DATA_ERROR for this. (LZMA_FORMAT_ERROR is used only if
+    the first Stream of a file has invalid Header Magic Bytes.)
+
+    bad-0-header_magic.xz is good-0-empty.xz but with one byte wrong
+    in the Header Magic Bytes field. liblzma gives LZMA_FORMAT_ERROR for
+    this.
+
+    bad-0-footer_magic.xz is good-0-empty.xz but with one byte wrong
+    in the Footer Magic Bytes field. liblzma gives LZMA_DATA_ERROR for
+    this.
+
+    bad-0-empty-truncated.xz is good-0-empty.xz without the last byte
+    of the file.
+
+    bad-0-nonempty_index.xz has no Blocks but Index claims that there is
+    one Block.
+
+    bad-0-backward_size.xz has wrong Backward Size in Stream Footer.
+
+    bad-1-stream_flags-1.xz has different Stream Flags in Stream Header
+    and Stream Footer.
+
+    bad-1-stream_flags-2.xz has wrong CRC32 in Stream Header.
+
+    bad-1-stream_flags-3.xz has wrong CRC32 in Stream Footer.
+
+    bad-1-vli-1.xz has two-byte variable-length integer in the
+    Uncompressed Size field in Block Header while one-byte would be enough
+    for that value. It's important that the file gets rejected due to too
+    big integer encoding instead of due to Uncompressed Size not matching
+    the value stored in the Block Header. That is, the decoder must not
+    try to decode the Compressed Data field.
+
+    bad-1-vli-2.xz has ten-byte variable-length integer as Uncompressed
+    Size in Block Header. It's important that the file gets rejected due
+    to too big integer encoding instead of due to Uncompressed Size not
+    matching the value stored in the Block Header. That is, the decoder
+    must not try to decode the Compressed Data field.
+
+    bad-1-block_header-1.xz has Block Header that ends in the middle of
+    the Filter Flags field.
+
+    bad-1-block_header-2.xz has Block Header that has Compressed Size and
+    Uncompressed Size but no List of Filter Flags field.
+
+    bad-1-block_header-3.xz has wrong CRC32 in Block Header.
+
+    bad-1-block_header-4.xz has too big Compressed Size in Block Header
+    (2^63 - 1 bytes while maximum is a little less, because the whole
+    Block must stay smaller than 2^63). It's important that the file
+    gets rejected due to invalid Compressed Size value; the decoder
+    must not try decoding the Compressed Data field.
+
+    bad-1-block_header-5.xz has zero as Compressed Size in Block Header.
+
+    bad-2-index-1.xz has wrong Unpadded Sizes in Index.
+
+    bad-2-index-2.xz has wrong Uncompressed Sizes in Index.
+
+    bad-2-index-3.xz has non-null byte in Index Padding.
+
+    bad-2-index-4.xz wrong CRC32 in Index.
+
+    bad-2-index-5.xz has zero as Unpadded Size. It is important that the
+    file gets rejected specifically due to Unpadded Size having an invalid
+    value.
+
+    bad-2-compressed_data_padding.xz has non-null byte in the padding of
+    the Compressed Data field of the first Block.
+
+    bad-1-check-crc32.xz has wrong Check (CRC32).
+
+    bad-1-check-crc64.xz has wrong Check (CRC64).
+
+    bad-1-check-sha256.xz has wrong Check (SHA-256).
+
+    bad-1-lzma2-1.xz has LZMA2 stream whose first chunk (uncompressed)
+    doesn't reset the dictionary.
+
+    bad-1-lzma2-2.xz has two LZMA2 chunks, of which the second chunk
+    indicates dictionary reset, but the LZMA compressed data tries to
+    repeat data from the previous chunk.
+
+    bad-1-lzma2-3.xz sets new invalid properties (lc=8, lp=0, pb=0) in
+    the middle of Block.
+
+    bad-1-lzma2-4.xz has two LZMA2 chunks, of which the first is
+    uncompressed and the second is LZMA. The first chunk resets dictionary
+    as it should, but the second chunk tries to reset state without
+    specifying properties for LZMA.
+
+    bad-1-lzma2-5.xz is like bad-1-lzma2-4.xz but doesn't try to reset
+    anything in the header of the second chunk.
+
+    bad-1-lzma2-6.xz has reserved LZMA2 control byte value (0x03).
+
+    bad-1-lzma2-7.xz has EOPM at LZMA level.
+
+    bad-1-lzma2-8.xz is like good-1-lzma2-4.xz but doesn't set new
+    properties in the third LZMA2 chunk.
+
diff --git a/tests/files/bad-0-backward_size.xz b/tests/files/bad-0-backward_size.xz
new file mode 100644
index 0000000..2b46fa9
--- /dev/null
+++ b/tests/files/bad-0-backward_size.xz
Binary files differ
diff --git a/tests/files/bad-0-empty-truncated.xz b/tests/files/bad-0-empty-truncated.xz
new file mode 100644
index 0000000..f879af8
--- /dev/null
+++ b/tests/files/bad-0-empty-truncated.xz
Binary files differ
diff --git a/tests/files/bad-0-footer_magic.xz b/tests/files/bad-0-footer_magic.xz
new file mode 100644
index 0000000..5d9e389
--- /dev/null
+++ b/tests/files/bad-0-footer_magic.xz
Binary files differ
diff --git a/tests/files/bad-0-header_magic.xz b/tests/files/bad-0-header_magic.xz
new file mode 100644
index 0000000..5984a45
--- /dev/null
+++ b/tests/files/bad-0-header_magic.xz
Binary files differ
diff --git a/tests/files/bad-0-nonempty_index.xz b/tests/files/bad-0-nonempty_index.xz
new file mode 100644
index 0000000..ed6e81f
--- /dev/null
+++ b/tests/files/bad-0-nonempty_index.xz
Binary files differ
diff --git a/tests/files/bad-0cat-alone.xz b/tests/files/bad-0cat-alone.xz
new file mode 100644
index 0000000..a915a3a
--- /dev/null
+++ b/tests/files/bad-0cat-alone.xz
Binary files differ
diff --git a/tests/files/bad-0cat-header_magic.xz b/tests/files/bad-0cat-header_magic.xz
new file mode 100644
index 0000000..426bf2d
--- /dev/null
+++ b/tests/files/bad-0cat-header_magic.xz
Binary files differ
diff --git a/tests/files/bad-0catpad-empty.xz b/tests/files/bad-0catpad-empty.xz
new file mode 100644
index 0000000..97c1330
--- /dev/null
+++ b/tests/files/bad-0catpad-empty.xz
Binary files differ
diff --git a/tests/files/bad-0pad-empty.xz b/tests/files/bad-0pad-empty.xz
new file mode 100644
index 0000000..45e00b7
--- /dev/null
+++ b/tests/files/bad-0pad-empty.xz
Binary files differ
diff --git a/tests/files/bad-1-block_header-1.xz b/tests/files/bad-1-block_header-1.xz
new file mode 100644
index 0000000..d991536
--- /dev/null
+++ b/tests/files/bad-1-block_header-1.xz
Binary files differ
diff --git a/tests/files/bad-1-block_header-2.xz b/tests/files/bad-1-block_header-2.xz
new file mode 100644
index 0000000..ae42ecf
--- /dev/null
+++ b/tests/files/bad-1-block_header-2.xz
Binary files differ
diff --git a/tests/files/bad-1-block_header-3.xz b/tests/files/bad-1-block_header-3.xz
new file mode 100644
index 0000000..606cbd2
--- /dev/null
+++ b/tests/files/bad-1-block_header-3.xz
Binary files differ
diff --git a/tests/files/bad-1-block_header-4.xz b/tests/files/bad-1-block_header-4.xz
new file mode 100644
index 0000000..e72dfbf
--- /dev/null
+++ b/tests/files/bad-1-block_header-4.xz
Binary files differ
diff --git a/tests/files/bad-1-block_header-5.xz b/tests/files/bad-1-block_header-5.xz
new file mode 100644
index 0000000..9652112
--- /dev/null
+++ b/tests/files/bad-1-block_header-5.xz
Binary files differ
diff --git a/tests/files/bad-1-check-crc32.xz b/tests/files/bad-1-check-crc32.xz
new file mode 100644
index 0000000..1ebe131
--- /dev/null
+++ b/tests/files/bad-1-check-crc32.xz
Binary files differ
diff --git a/tests/files/bad-1-check-crc64.xz b/tests/files/bad-1-check-crc64.xz
new file mode 100644
index 0000000..cdb7709
--- /dev/null
+++ b/tests/files/bad-1-check-crc64.xz
Binary files differ
diff --git a/tests/files/bad-1-check-sha256.xz b/tests/files/bad-1-check-sha256.xz
new file mode 100644
index 0000000..def7bff
--- /dev/null
+++ b/tests/files/bad-1-check-sha256.xz
Binary files differ
diff --git a/tests/files/bad-1-lzma2-1.xz b/tests/files/bad-1-lzma2-1.xz
new file mode 100644
index 0000000..640f592
--- /dev/null
+++ b/tests/files/bad-1-lzma2-1.xz
Binary files differ
diff --git a/tests/files/bad-1-lzma2-2.xz b/tests/files/bad-1-lzma2-2.xz
new file mode 100644
index 0000000..69ab07d
--- /dev/null
+++ b/tests/files/bad-1-lzma2-2.xz
Binary files differ
diff --git a/tests/files/bad-1-lzma2-3.xz b/tests/files/bad-1-lzma2-3.xz
new file mode 100644
index 0000000..66f48c5
--- /dev/null
+++ b/tests/files/bad-1-lzma2-3.xz
Binary files differ
diff --git a/tests/files/bad-1-lzma2-4.xz b/tests/files/bad-1-lzma2-4.xz
new file mode 100644
index 0000000..ac97041
--- /dev/null
+++ b/tests/files/bad-1-lzma2-4.xz
Binary files differ
diff --git a/tests/files/bad-1-lzma2-5.xz b/tests/files/bad-1-lzma2-5.xz
new file mode 100644
index 0000000..700464d
--- /dev/null
+++ b/tests/files/bad-1-lzma2-5.xz
Binary files differ
diff --git a/tests/files/bad-1-lzma2-6.xz b/tests/files/bad-1-lzma2-6.xz
new file mode 100644
index 0000000..2bda0c4
--- /dev/null
+++ b/tests/files/bad-1-lzma2-6.xz
Binary files differ
diff --git a/tests/files/bad-1-lzma2-7.xz b/tests/files/bad-1-lzma2-7.xz
new file mode 100644
index 0000000..8cc711c
--- /dev/null
+++ b/tests/files/bad-1-lzma2-7.xz
Binary files differ
diff --git a/tests/files/bad-1-lzma2-8.xz b/tests/files/bad-1-lzma2-8.xz
new file mode 100644
index 0000000..f21a71b
--- /dev/null
+++ b/tests/files/bad-1-lzma2-8.xz
Binary files differ
diff --git a/tests/files/bad-1-stream_flags-1.xz b/tests/files/bad-1-stream_flags-1.xz
new file mode 100644
index 0000000..6511773
--- /dev/null
+++ b/tests/files/bad-1-stream_flags-1.xz
Binary files differ
diff --git a/tests/files/bad-1-stream_flags-2.xz b/tests/files/bad-1-stream_flags-2.xz
new file mode 100644
index 0000000..0c66b36
--- /dev/null
+++ b/tests/files/bad-1-stream_flags-2.xz
Binary files differ
diff --git a/tests/files/bad-1-stream_flags-3.xz b/tests/files/bad-1-stream_flags-3.xz
new file mode 100644
index 0000000..a9b1f98
--- /dev/null
+++ b/tests/files/bad-1-stream_flags-3.xz
Binary files differ
diff --git a/tests/files/bad-1-vli-1.xz b/tests/files/bad-1-vli-1.xz
new file mode 100644
index 0000000..6514ab1
--- /dev/null
+++ b/tests/files/bad-1-vli-1.xz
Binary files differ
diff --git a/tests/files/bad-1-vli-2.xz b/tests/files/bad-1-vli-2.xz
new file mode 100644
index 0000000..c16941b
--- /dev/null
+++ b/tests/files/bad-1-vli-2.xz
Binary files differ
diff --git a/tests/files/bad-2-compressed_data_padding.xz b/tests/files/bad-2-compressed_data_padding.xz
new file mode 100644
index 0000000..382d047
--- /dev/null
+++ b/tests/files/bad-2-compressed_data_padding.xz
Binary files differ
diff --git a/tests/files/bad-2-index-1.xz b/tests/files/bad-2-index-1.xz
new file mode 100644
index 0000000..f51ed21
--- /dev/null
+++ b/tests/files/bad-2-index-1.xz
Binary files differ
diff --git a/tests/files/bad-2-index-2.xz b/tests/files/bad-2-index-2.xz
new file mode 100644
index 0000000..d7d00ff
--- /dev/null
+++ b/tests/files/bad-2-index-2.xz
Binary files differ
diff --git a/tests/files/bad-2-index-3.xz b/tests/files/bad-2-index-3.xz
new file mode 100644
index 0000000..62428b8
--- /dev/null
+++ b/tests/files/bad-2-index-3.xz
Binary files differ
diff --git a/tests/files/bad-2-index-4.xz b/tests/files/bad-2-index-4.xz
new file mode 100644
index 0000000..9cf2df6
--- /dev/null
+++ b/tests/files/bad-2-index-4.xz
Binary files differ
diff --git a/tests/files/bad-2-index-5.xz b/tests/files/bad-2-index-5.xz
new file mode 100644
index 0000000..0a79270
--- /dev/null
+++ b/tests/files/bad-2-index-5.xz
Binary files differ
diff --git a/tests/files/good-0-empty.xz b/tests/files/good-0-empty.xz
new file mode 100644
index 0000000..83b95e0
--- /dev/null
+++ b/tests/files/good-0-empty.xz
Binary files differ
diff --git a/tests/files/good-0cat-empty.xz b/tests/files/good-0cat-empty.xz
new file mode 100644
index 0000000..e6fc314
--- /dev/null
+++ b/tests/files/good-0cat-empty.xz
Binary files differ
diff --git a/tests/files/good-0catpad-empty.xz b/tests/files/good-0catpad-empty.xz
new file mode 100644
index 0000000..4f86b7d
--- /dev/null
+++ b/tests/files/good-0catpad-empty.xz
Binary files differ
diff --git a/tests/files/good-0pad-empty.xz b/tests/files/good-0pad-empty.xz
new file mode 100644
index 0000000..c51e3a6
--- /dev/null
+++ b/tests/files/good-0pad-empty.xz
Binary files differ
diff --git a/tests/files/good-1-3delta-lzma2.xz b/tests/files/good-1-3delta-lzma2.xz
new file mode 100644
index 0000000..a0be1d0
--- /dev/null
+++ b/tests/files/good-1-3delta-lzma2.xz
Binary files differ
diff --git a/tests/files/good-1-block_header-1.xz b/tests/files/good-1-block_header-1.xz
new file mode 100644
index 0000000..fea5ad2
--- /dev/null
+++ b/tests/files/good-1-block_header-1.xz
Binary files differ
diff --git a/tests/files/good-1-block_header-2.xz b/tests/files/good-1-block_header-2.xz
new file mode 100644
index 0000000..6b5dcb3
--- /dev/null
+++ b/tests/files/good-1-block_header-2.xz
Binary files differ
diff --git a/tests/files/good-1-block_header-3.xz b/tests/files/good-1-block_header-3.xz
new file mode 100644
index 0000000..1565312
--- /dev/null
+++ b/tests/files/good-1-block_header-3.xz
Binary files differ
diff --git a/tests/files/good-1-check-crc32.xz b/tests/files/good-1-check-crc32.xz
new file mode 100644
index 0000000..6c89593
--- /dev/null
+++ b/tests/files/good-1-check-crc32.xz
Binary files differ
diff --git a/tests/files/good-1-check-crc64.xz b/tests/files/good-1-check-crc64.xz
new file mode 100644
index 0000000..5a9915d
--- /dev/null
+++ b/tests/files/good-1-check-crc64.xz
Binary files differ
diff --git a/tests/files/good-1-check-none.xz b/tests/files/good-1-check-none.xz
new file mode 100644
index 0000000..1e85faf
--- /dev/null
+++ b/tests/files/good-1-check-none.xz
Binary files differ
diff --git a/tests/files/good-1-check-sha256.xz b/tests/files/good-1-check-sha256.xz
new file mode 100644
index 0000000..fdc556b
--- /dev/null
+++ b/tests/files/good-1-check-sha256.xz
Binary files differ
diff --git a/tests/files/good-1-delta-lzma2.tiff.xz b/tests/files/good-1-delta-lzma2.tiff.xz
new file mode 100644
index 0000000..1f033bc
--- /dev/null
+++ b/tests/files/good-1-delta-lzma2.tiff.xz
Binary files differ
diff --git a/tests/files/good-1-lzma2-1.xz b/tests/files/good-1-lzma2-1.xz
new file mode 100644
index 0000000..d8d6489
--- /dev/null
+++ b/tests/files/good-1-lzma2-1.xz
Binary files differ
diff --git a/tests/files/good-1-lzma2-2.xz b/tests/files/good-1-lzma2-2.xz
new file mode 100644
index 0000000..7e8cdf1
--- /dev/null
+++ b/tests/files/good-1-lzma2-2.xz
Binary files differ
diff --git a/tests/files/good-1-lzma2-3.xz b/tests/files/good-1-lzma2-3.xz
new file mode 100644
index 0000000..c4c72be
--- /dev/null
+++ b/tests/files/good-1-lzma2-3.xz
Binary files differ
diff --git a/tests/files/good-1-lzma2-4.xz b/tests/files/good-1-lzma2-4.xz
new file mode 100644
index 0000000..e0d623a
--- /dev/null
+++ b/tests/files/good-1-lzma2-4.xz
Binary files differ
diff --git a/tests/files/good-1-sparc-lzma2.xz b/tests/files/good-1-sparc-lzma2.xz
new file mode 100644
index 0000000..4532bc6
--- /dev/null
+++ b/tests/files/good-1-sparc-lzma2.xz
Binary files differ
diff --git a/tests/files/good-1-x86-lzma2.xz b/tests/files/good-1-x86-lzma2.xz
new file mode 100644
index 0000000..8053917
--- /dev/null
+++ b/tests/files/good-1-x86-lzma2.xz
Binary files differ
diff --git a/tests/files/good-2-lzma2.xz b/tests/files/good-2-lzma2.xz
new file mode 100644
index 0000000..bed5085
--- /dev/null
+++ b/tests/files/good-2-lzma2.xz
Binary files differ
diff --git a/tests/files/unsupported-block_header.xz b/tests/files/unsupported-block_header.xz
new file mode 100644
index 0000000..3830442
--- /dev/null
+++ b/tests/files/unsupported-block_header.xz
Binary files differ
diff --git a/tests/files/unsupported-check.xz b/tests/files/unsupported-check.xz
new file mode 100644
index 0000000..c28355e
--- /dev/null
+++ b/tests/files/unsupported-check.xz
Binary files differ
diff --git a/tests/files/unsupported-filter_flags-1.xz b/tests/files/unsupported-filter_flags-1.xz
new file mode 100644
index 0000000..48b9373
--- /dev/null
+++ b/tests/files/unsupported-filter_flags-1.xz
Binary files differ
diff --git a/tests/files/unsupported-filter_flags-2.xz b/tests/files/unsupported-filter_flags-2.xz
new file mode 100644
index 0000000..c283359
--- /dev/null
+++ b/tests/files/unsupported-filter_flags-2.xz
Binary files differ
diff --git a/tests/files/unsupported-filter_flags-3.xz b/tests/files/unsupported-filter_flags-3.xz
new file mode 100644
index 0000000..2608498
--- /dev/null
+++ b/tests/files/unsupported-filter_flags-3.xz
Binary files differ
diff --git a/tests/test_block.c b/tests/test_block.c
new file mode 100644
index 0000000..0352dce
--- /dev/null
+++ b/tests/test_block.c
@@ -0,0 +1,52 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       test_block.c
+/// \brief      Tests Block coders
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "tests.h"
+
+
+static uint8_t text[] = "Hello world!";
+static uint8_t buffer[4096];
+static lzma_options_block block_options;
+static lzma_stream strm = LZMA_STREAM_INIT;
+
+
+static void
+test1(void)
+{
+
+}
+
+
+int
+main()
+{
+	lzma_init();
+
+	block_options = (lzma_options_block){
+		.check_type = LZMA_CHECK_NONE,
+		.has_eopm = true,
+		.has_uncompressed_size_in_footer = false,
+		.has_backward_size = false,
+		.handle_padding = false,
+		.total_size = LZMA_VLI_UNKNOWN,
+		.compressed_size = LZMA_VLI_UNKNOWN,
+		.uncompressed_size = LZMA_VLI_UNKNOWN,
+		.header_size = 5,
+	};
+	block_options.filters[0].id = LZMA_VLI_UNKNOWN;
+	block_options.filters[0].options = NULL;
+
+
+	lzma_end(&strm);
+
+	return 0;
+}
diff --git a/tests/test_block_header.c b/tests/test_block_header.c
new file mode 100644
index 0000000..3d9b5d9
--- /dev/null
+++ b/tests/test_block_header.c
@@ -0,0 +1,240 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       test_block_header.c
+/// \brief      Tests Block Header coders
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "tests.h"
+
+
+static uint8_t buf[LZMA_BLOCK_HEADER_SIZE_MAX];
+static lzma_block known_options;
+static lzma_block decoded_options;
+
+static lzma_options_lzma opt_lzma;
+
+static lzma_filter filters_none[1] = {
+	{
+		.id = LZMA_VLI_UNKNOWN,
+	},
+};
+
+
+static lzma_filter filters_one[2] = {
+	{
+		.id = LZMA_FILTER_LZMA2,
+		.options = &opt_lzma,
+	}, {
+		.id = LZMA_VLI_UNKNOWN,
+	}
+};
+
+
+static lzma_filter filters_four[5] = {
+	{
+		.id = LZMA_FILTER_X86,
+		.options = NULL,
+	}, {
+		.id = LZMA_FILTER_X86,
+		.options = NULL,
+	}, {
+		.id = LZMA_FILTER_X86,
+		.options = NULL,
+	}, {
+		.id = LZMA_FILTER_LZMA2,
+		.options = &opt_lzma,
+	}, {
+		.id = LZMA_VLI_UNKNOWN,
+	}
+};
+
+
+static lzma_filter filters_five[6] = {
+	{
+		.id = LZMA_FILTER_X86,
+		.options = NULL,
+	}, {
+		.id = LZMA_FILTER_X86,
+		.options = NULL,
+	}, {
+		.id = LZMA_FILTER_X86,
+		.options = NULL,
+	}, {
+		.id = LZMA_FILTER_X86,
+		.options = NULL,
+	}, {
+		.id = LZMA_FILTER_LZMA2,
+		.options = &opt_lzma,
+	}, {
+		.id = LZMA_VLI_UNKNOWN,
+	}
+};
+
+
+static void
+code(void)
+{
+	expect(lzma_block_header_encode(&known_options, buf) == LZMA_OK);
+
+	lzma_filter filters[LZMA_FILTERS_MAX + 1];
+	memcrap(filters, sizeof(filters));
+	memcrap(&decoded_options, sizeof(decoded_options));
+
+	decoded_options.header_size = known_options.header_size;
+	decoded_options.check = known_options.check;
+	decoded_options.filters = filters;
+	expect(lzma_block_header_decode(&decoded_options, NULL, buf)
+			== LZMA_OK);
+
+	expect(known_options.compressed_size
+			== decoded_options.compressed_size);
+	expect(known_options.uncompressed_size
+			== decoded_options.uncompressed_size);
+
+	for (size_t i = 0; known_options.filters[i].id
+			!= LZMA_VLI_UNKNOWN; ++i)
+		expect(known_options.filters[i].id == filters[i].id);
+
+	for (size_t i = 0; i < LZMA_FILTERS_MAX; ++i)
+		free(decoded_options.filters[i].options);
+}
+
+
+static void
+test1(void)
+{
+	known_options = (lzma_block){
+		.check = LZMA_CHECK_NONE,
+		.compressed_size = LZMA_VLI_UNKNOWN,
+		.uncompressed_size = LZMA_VLI_UNKNOWN,
+		.filters = NULL,
+	};
+
+	expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR);
+
+	known_options.filters = filters_none;
+	expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR);
+
+	known_options.filters = filters_five;
+	expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR);
+
+	known_options.filters = filters_one;
+	expect(lzma_block_header_size(&known_options) == LZMA_OK);
+
+	known_options.check = 999; // Some invalid value, which gets ignored.
+	expect(lzma_block_header_size(&known_options) == LZMA_OK);
+
+	known_options.compressed_size = 5;
+	expect(lzma_block_header_size(&known_options) == LZMA_OK);
+
+	known_options.compressed_size = 0; // Cannot be zero.
+	expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR);
+
+	// LZMA_VLI_MAX is too big to keep the total size of the Block
+	// a valid VLI, but lzma_block_header_size() is not meant
+	// to validate it. (lzma_block_header_encode() must validate it.)
+	known_options.compressed_size = LZMA_VLI_MAX;
+	expect(lzma_block_header_size(&known_options) == LZMA_OK);
+
+	known_options.compressed_size = LZMA_VLI_UNKNOWN;
+	known_options.uncompressed_size = 0;
+	expect(lzma_block_header_size(&known_options) == LZMA_OK);
+
+	known_options.uncompressed_size = LZMA_VLI_MAX + 1;
+	expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR);
+}
+
+
+static void
+test2(void)
+{
+	known_options = (lzma_block){
+		.check = LZMA_CHECK_CRC32,
+		.compressed_size = LZMA_VLI_UNKNOWN,
+		.uncompressed_size = LZMA_VLI_UNKNOWN,
+		.filters = filters_four,
+	};
+
+	expect(lzma_block_header_size(&known_options) == LZMA_OK);
+	code();
+
+	known_options.compressed_size = 123456;
+	known_options.uncompressed_size = 234567;
+	expect(lzma_block_header_size(&known_options) == LZMA_OK);
+	code();
+
+	// We can make the sizes smaller while keeping the header size
+	// the same.
+	known_options.compressed_size = 12;
+	known_options.uncompressed_size = 23;
+	code();
+}
+
+
+static void
+test3(void)
+{
+	known_options = (lzma_block){
+		.check = LZMA_CHECK_CRC32,
+		.compressed_size = LZMA_VLI_UNKNOWN,
+		.uncompressed_size = LZMA_VLI_UNKNOWN,
+		.filters = filters_one,
+	};
+
+	expect(lzma_block_header_size(&known_options) == LZMA_OK);
+	known_options.header_size += 4;
+	expect(lzma_block_header_encode(&known_options, buf) == LZMA_OK);
+
+	lzma_filter filters[LZMA_FILTERS_MAX + 1];
+	decoded_options.header_size = known_options.header_size;
+	decoded_options.check = known_options.check;
+	decoded_options.filters = filters;
+
+	// Wrong size
+	++buf[0];
+	expect(lzma_block_header_decode(&decoded_options, NULL, buf)
+			== LZMA_PROG_ERROR);
+	--buf[0];
+
+	// Wrong CRC32
+	buf[known_options.header_size - 1] ^= 1;
+	expect(lzma_block_header_decode(&decoded_options, NULL, buf)
+			== LZMA_DATA_ERROR);
+	buf[known_options.header_size - 1] ^= 1;
+
+	// Unsupported filter
+	// NOTE: This may need updating when new IDs become supported.
+	buf[2] ^= 0x1F;
+	unaligned_write32le(buf + known_options.header_size - 4,
+			lzma_crc32(buf, known_options.header_size - 4, 0));
+	expect(lzma_block_header_decode(&decoded_options, NULL, buf)
+			== LZMA_OPTIONS_ERROR);
+	buf[2] ^= 0x1F;
+
+	// Non-nul Padding
+	buf[known_options.header_size - 4 - 1] ^= 1;
+	unaligned_write32le(buf + known_options.header_size - 4,
+			lzma_crc32(buf, known_options.header_size - 4, 0));
+	expect(lzma_block_header_decode(&decoded_options, NULL, buf)
+			== LZMA_OPTIONS_ERROR);
+	buf[known_options.header_size - 4 - 1] ^= 1;
+}
+
+
+int
+main(void)
+{
+	succeed(lzma_lzma_preset(&opt_lzma, 1));
+
+	test1();
+	test2();
+	test3();
+
+	return 0;
+}
diff --git a/tests/test_check.c b/tests/test_check.c
new file mode 100644
index 0000000..7d4a360
--- /dev/null
+++ b/tests/test_check.c
@@ -0,0 +1,83 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       test_check.c
+/// \brief      Tests integrity checks
+///
+/// \todo       Add SHA256
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "tests.h"
+
+
+static const uint8_t test_string[9] = "123456789";
+static const uint8_t test_unaligned[12] = "xxx123456789";
+
+
+static bool
+test_crc32(void)
+{
+	static const uint32_t test_vector = 0xCBF43926;
+
+	// Test 1
+	uint32_t crc = lzma_crc32(test_string, sizeof(test_string), 0);
+	if (crc != test_vector)
+		return true;
+
+	// Test 2
+	crc = lzma_crc32(test_unaligned + 3, sizeof(test_string), 0);
+	if (crc != test_vector)
+		return true;
+
+	// Test 3
+	crc = 0;
+	for (size_t i = 0; i < sizeof(test_string); ++i)
+		crc = lzma_crc32(test_string + i, 1, crc);
+	if (crc != test_vector)
+		return true;
+
+	return false;
+}
+
+
+static bool
+test_crc64(void)
+{
+	static const uint64_t test_vector = 0x995DC9BBDF1939FA;
+
+	// Test 1
+	uint64_t crc = lzma_crc64(test_string, sizeof(test_string), 0);
+	if (crc != test_vector)
+		return true;
+
+	// Test 2
+	crc = lzma_crc64(test_unaligned + 3, sizeof(test_string), 0);
+	if (crc != test_vector)
+		return true;
+
+	// Test 3
+	crc = 0;
+	for (size_t i = 0; i < sizeof(test_string); ++i)
+		crc = lzma_crc64(test_string + i, 1, crc);
+	if (crc != test_vector)
+		return true;
+
+	return false;
+}
+
+
+int
+main(void)
+{
+	bool error = false;
+
+	error |= test_crc32();
+	error |= test_crc64();
+
+	return error ? 1 : 0;
+}
diff --git a/tests/test_compress.sh b/tests/test_compress.sh
new file mode 100755
index 0000000..ff0cb30
--- /dev/null
+++ b/tests/test_compress.sh
@@ -0,0 +1,129 @@
+#!/bin/sh
+
+###############################################################################
+#
+# Author: Lasse Collin
+#
+# This file has been put into the public domain.
+# You can do whatever you want with this file.
+#
+###############################################################################
+
+# Find out if our shell supports functions.
+eval 'unset foo ; foo() { return 42; } ; foo'
+if test $? != 42 ; then
+	echo "/bin/sh doesn't support functions, skipping this test."
+	(exit 77)
+	exit 77
+fi
+
+test_xz() {
+	if $XZ -c "$@" "$FILE" > tmp_compressed; then
+		:
+	else
+		echo "Compressing failed: $* $FILE"
+		(exit 1)
+		exit 1
+	fi
+
+	if $XZ -cd tmp_compressed > tmp_uncompressed ; then
+		:
+	else
+		echo "Decoding failed: $* $FILE"
+		(exit 1)
+		exit 1
+	fi
+
+	if cmp tmp_uncompressed "$FILE" ; then
+		:
+	else
+		echo "Decoded file does not match the original: $* $FILE"
+		(exit 1)
+		exit 1
+	fi
+
+	if $XZDEC tmp_compressed > tmp_uncompressed ; then
+		:
+	else
+		echo "Decoding failed: $* $FILE"
+		(exit 1)
+		exit 1
+	fi
+
+	if cmp tmp_uncompressed "$FILE" ; then
+		:
+	else
+		echo "Decoded file does not match the original: $* $FILE"
+		(exit 1)
+		exit 1
+	fi
+
+	# Show progress:
+	echo . | tr -d '\n\r'
+}
+
+XZ="../src/xz/xz --memory=28MiB --threads=1"
+XZDEC="../src/xzdec/xzdec --memory=4MiB"
+unset XZ_OPT
+
+# Create the required input files.
+if ./create_compress_files ; then
+	:
+else
+	rm -f compress_*
+	echo "Failed to create files to test compression."
+	(exit 1)
+	exit 1
+fi
+
+# Remove temporary now (in case they are something weird), and on exit.
+rm -f tmp_compressed tmp_uncompressed
+trap 'rm -f tmp_compressed tmp_uncompressed' 0
+
+# Encode and decode each file with various filter configurations.
+# This takes quite a bit of time.
+echo "test_compress.sh:"
+for FILE in compress_generated_* "$srcdir"/compress_prepared_*
+do
+	MSG=`echo "x$FILE" | sed 's,^x,,; s,^.*/,,; s,^compress_,,'`
+	echo "  $MSG" | tr -d '\n\r'
+
+	# Don't test with empty arguments; it breaks some ancient
+	# proprietary /bin/sh versions due to $@ used in test_xz().
+	test_xz -1
+	test_xz -2
+	test_xz -3
+	test_xz -4
+
+	# Disabled until Subblock format is stable.
+#		--subblock \
+#		--subblock=size=1 \
+#		--subblock=size=1,rle=1 \
+#		--subblock=size=1,rle=4 \
+#		--subblock=size=4,rle=4 \
+#		--subblock=size=8,rle=4 \
+#		--subblock=size=8,rle=8 \
+#		--subblock=size=4096,rle=12 \
+#
+	for ARGS in \
+		--delta=dist=1 \
+		--delta=dist=4 \
+		--delta=dist=256 \
+		--x86 \
+		--powerpc \
+		--ia64 \
+		--arm \
+		--armthumb \
+		--sparc
+	do
+		test_xz $ARGS --lzma2=dict=64KiB,nice=32,mode=fast
+
+		# Disabled until Subblock format is stable.
+		# test_xz --subblock $ARGS --lzma2=dict=64KiB,nice=32,mode=fast
+	done
+
+	echo
+done
+
+(exit 0)
+exit 0
diff --git a/tests/test_files.sh b/tests/test_files.sh
new file mode 100755
index 0000000..7dd9a39
--- /dev/null
+++ b/tests/test_files.sh
@@ -0,0 +1,33 @@
+#/bin/sh
+
+###############################################################################
+#
+# Author: Lasse Collin
+#
+# This file has been put into the public domain.
+# You can do whatever you want with this file.
+#
+###############################################################################
+
+for I in "$srcdir"/files/good-*.xz
+do
+	if ../src/xzdec/xzdec "$I" > /dev/null 2> /dev/null ; then
+		:
+	else
+		echo "Good file failed: $I"
+		(exit 1)
+		exit 1
+	fi
+done
+
+for I in "$srcdir"/files/bad-*.xz
+do
+	if ../src/xzdec/xzdec "$I" > /dev/null 2> /dev/null ; then
+		echo "Bad file succeeded: $I"
+		(exit 1)
+		exit 1
+	fi
+done
+
+(exit 0)
+exit 0
diff --git a/tests/test_filter_flags.c b/tests/test_filter_flags.c
new file mode 100644
index 0000000..ccd9ae9
--- /dev/null
+++ b/tests/test_filter_flags.c
@@ -0,0 +1,258 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       test_filter_flags.c
+/// \brief      Tests Filter Flags coders
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "tests.h"
+
+
+static uint8_t buffer[4096];
+static lzma_filter known_flags;
+static lzma_filter decoded_flags;
+static lzma_stream strm = LZMA_STREAM_INIT;
+
+
+static bool
+encode(uint32_t known_size)
+{
+	memcrap(buffer, sizeof(buffer));
+
+	uint32_t tmp;
+	if (lzma_filter_flags_size(&tmp, &known_flags) != LZMA_OK)
+		return true;
+
+	if (tmp != known_size)
+		return true;
+
+	size_t out_pos = 0;
+	if (lzma_filter_flags_encode(&known_flags,
+			buffer, &out_pos, known_size) != LZMA_OK)
+		return true;
+
+	if (out_pos != known_size)
+		return true;
+
+	return false;
+}
+
+
+static bool
+decode_ret(uint32_t known_size, lzma_ret expected_ret)
+{
+	memcrap(&decoded_flags, sizeof(decoded_flags));
+
+	size_t pos = 0;
+	if (lzma_filter_flags_decode(&decoded_flags, NULL,
+				buffer, &pos, known_size) != expected_ret
+			|| pos != known_size)
+		return true;
+
+	return false;
+}
+
+
+static bool
+decode(uint32_t known_size)
+{
+	if (decode_ret(known_size, LZMA_OK))
+		return true;
+
+	if (known_flags.id != decoded_flags.id)
+		return true;
+
+	return false;
+}
+
+
+#if defined(HAVE_ENCODER_X86) && defined(HAVE_DECODER_X86)
+static void
+test_bcj(void)
+{
+	// Test 1
+	known_flags.id = LZMA_FILTER_X86;
+	known_flags.options = NULL;
+
+	expect(!encode(2));
+	expect(!decode(2));
+	expect(decoded_flags.options == NULL);
+
+	// Test 2
+	lzma_options_bcj options;
+	options.start_offset = 0;
+	known_flags.options = &options;
+	expect(!encode(2));
+	expect(!decode(2));
+	expect(decoded_flags.options == NULL);
+
+	// Test 3
+	options.start_offset = 123456;
+	known_flags.options = &options;
+	expect(!encode(6));
+	expect(!decode(6));
+	expect(decoded_flags.options != NULL);
+
+	lzma_options_bcj *decoded = decoded_flags.options;
+	expect(decoded->start_offset == options.start_offset);
+
+	free(decoded);
+}
+#endif
+
+
+#if defined(HAVE_ENCODER_DELTA) && defined(HAVE_DECODER_DELTA)
+static void
+test_delta(void)
+{
+	// Test 1
+	known_flags.id = LZMA_FILTER_DELTA;
+	known_flags.options = NULL;
+	expect(encode(99));
+
+	// Test 2
+	lzma_options_delta options = {
+		.type = LZMA_DELTA_TYPE_BYTE,
+		.dist = 0
+	};
+	known_flags.options = &options;
+	expect(encode(99));
+
+	// Test 3
+	options.dist = LZMA_DELTA_DIST_MIN;
+	expect(!encode(3));
+	expect(!decode(3));
+	expect(((lzma_options_delta *)(decoded_flags.options))->dist
+			== options.dist);
+
+	free(decoded_flags.options);
+
+	// Test 4
+	options.dist = LZMA_DELTA_DIST_MAX;
+	expect(!encode(3));
+	expect(!decode(3));
+	expect(((lzma_options_delta *)(decoded_flags.options))->dist
+			== options.dist);
+
+	free(decoded_flags.options);
+
+	// Test 5
+	options.dist = LZMA_DELTA_DIST_MAX + 1;
+	expect(encode(99));
+}
+#endif
+
+/*
+#ifdef HAVE_FILTER_LZMA
+static void
+validate_lzma(void)
+{
+	const lzma_options_lzma *known = known_flags.options;
+	const lzma_options_lzma *decoded = decoded_flags.options;
+
+	expect(known->dictionary_size <= decoded->dictionary_size);
+
+	if (known->dictionary_size == 1)
+		expect(decoded->dictionary_size == 1);
+	else
+		expect(known->dictionary_size + known->dictionary_size / 2
+				> decoded->dictionary_size);
+
+	expect(known->literal_context_bits == decoded->literal_context_bits);
+	expect(known->literal_pos_bits == decoded->literal_pos_bits);
+	expect(known->pos_bits == decoded->pos_bits);
+}
+
+
+static void
+test_lzma(void)
+{
+	// Test 1
+	known_flags.id = LZMA_FILTER_LZMA1;
+	known_flags.options = NULL;
+	expect(encode(99));
+
+	// Test 2
+	lzma_options_lzma options = {
+		.dictionary_size = 0,
+		.literal_context_bits = 0,
+		.literal_pos_bits = 0,
+		.pos_bits = 0,
+		.preset_dictionary = NULL,
+		.preset_dictionary_size = 0,
+		.mode = LZMA_MODE_INVALID,
+		.fast_bytes = 0,
+		.match_finder = LZMA_MF_INVALID,
+		.match_finder_cycles = 0,
+	};
+
+	// Test 3 (empty dictionary not allowed)
+	known_flags.options = &options;
+	expect(encode(99));
+
+	// Test 4 (brute-force test some valid dictionary sizes)
+	options.dictionary_size = LZMA_DICTIONARY_SIZE_MIN;
+	while (options.dictionary_size != LZMA_DICTIONARY_SIZE_MAX) {
+		if (++options.dictionary_size == 5000)
+			options.dictionary_size = LZMA_DICTIONARY_SIZE_MAX - 5;
+
+		expect(!encode(4));
+		expect(!decode(4));
+		validate_lzma();
+
+		free(decoded_flags.options);
+	}
+
+	// Test 5 (too big dictionary size)
+	options.dictionary_size = LZMA_DICTIONARY_SIZE_MAX + 1;
+	expect(encode(99));
+
+	// Test 6 (brute-force test lc/lp/pb)
+	options.dictionary_size = LZMA_DICTIONARY_SIZE_MIN;
+	for (uint32_t lc = LZMA_LITERAL_CONTEXT_BITS_MIN;
+			lc <= LZMA_LITERAL_CONTEXT_BITS_MAX; ++lc) {
+		for (uint32_t lp = LZMA_LITERAL_POS_BITS_MIN;
+				lp <= LZMA_LITERAL_POS_BITS_MAX; ++lp) {
+			for (uint32_t pb = LZMA_POS_BITS_MIN;
+					pb <= LZMA_POS_BITS_MAX; ++pb) {
+				if (lc + lp > LZMA_LITERAL_BITS_MAX)
+					continue;
+
+				options.literal_context_bits = lc;
+				options.literal_pos_bits = lp;
+				options.pos_bits = pb;
+
+				expect(!encode(4));
+				expect(!decode(4));
+				validate_lzma();
+
+				free(decoded_flags.options);
+			}
+		}
+	}
+}
+#endif
+*/
+
+int
+main(void)
+{
+#if defined(HAVE_ENCODER_X86) && defined(HAVE_DECODER_X86)
+	test_bcj();
+#endif
+#if defined(HAVE_ENCODER_DELTA) && defined(HAVE_DECODER_DELTA)
+	test_delta();
+#endif
+// #ifdef HAVE_FILTER_LZMA
+// 	test_lzma();
+// #endif
+
+	lzma_end(&strm);
+
+	return 0;
+}
diff --git a/tests/test_index.c b/tests/test_index.c
new file mode 100644
index 0000000..06b4d6b
--- /dev/null
+++ b/tests/test_index.c
@@ -0,0 +1,659 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       test_index.c
+/// \brief      Tests functions handling the lzma_index structure
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "tests.h"
+
+#define MEMLIMIT (LZMA_VLI_C(1) << 20)
+
+#define SMALL_COUNT 3
+#define BIG_COUNT 5555
+
+
+static lzma_index *
+create_empty(void)
+{
+	lzma_index *i = lzma_index_init(NULL);
+	expect(i != NULL);
+	return i;
+}
+
+
+static lzma_index *
+create_small(void)
+{
+	lzma_index *i = lzma_index_init(NULL);
+	expect(i != NULL);
+	expect(lzma_index_append(i, NULL, 101, 555) == LZMA_OK);
+	expect(lzma_index_append(i, NULL, 602, 777) == LZMA_OK);
+	expect(lzma_index_append(i, NULL, 804, 999) == LZMA_OK);
+	return i;
+}
+
+
+static lzma_index *
+create_big(void)
+{
+	lzma_index *i = lzma_index_init(NULL);
+	expect(i != NULL);
+
+	lzma_vli total_size = 0;
+	lzma_vli uncompressed_size = 0;
+
+	// Add pseudo-random sizes (but always the same size values).
+	uint32_t n = 11;
+	for (size_t j = 0; j < BIG_COUNT; ++j) {
+		n = 7019 * n + 7607;
+		const uint32_t t = n * 3011;
+		expect(lzma_index_append(i, NULL, t, n) == LZMA_OK);
+		total_size += (t + 3) & ~LZMA_VLI_C(3);
+		uncompressed_size += n;
+	}
+
+	expect(lzma_index_block_count(i) == BIG_COUNT);
+	expect(lzma_index_total_size(i) == total_size);
+	expect(lzma_index_uncompressed_size(i) == uncompressed_size);
+	expect(lzma_index_total_size(i) + lzma_index_size(i)
+				+ 2 * LZMA_STREAM_HEADER_SIZE
+			== lzma_index_stream_size(i));
+
+	return i;
+}
+
+
+static bool
+is_equal(const lzma_index *a, const lzma_index *b)
+{
+	// Compare only the Stream and Block sizes and offsets.
+	lzma_index_iter ra, rb;
+	lzma_index_iter_init(&ra, a);
+	lzma_index_iter_init(&rb, b);
+
+	while (true) {
+		bool reta = lzma_index_iter_next(&ra, LZMA_INDEX_ITER_ANY);
+		bool retb = lzma_index_iter_next(&rb, LZMA_INDEX_ITER_ANY);
+		if (reta)
+			return !(reta ^ retb);
+
+		if (ra.stream.number != rb.stream.number
+				|| ra.stream.block_count
+					!= rb.stream.block_count
+				|| ra.stream.compressed_offset
+					!= rb.stream.compressed_offset
+				|| ra.stream.uncompressed_offset
+					!= rb.stream.uncompressed_offset
+				|| ra.stream.compressed_size
+					!= rb.stream.compressed_size
+				|| ra.stream.uncompressed_size
+					!= rb.stream.uncompressed_size
+				|| ra.stream.padding
+					!= rb.stream.padding)
+			return false;
+
+		if (ra.stream.block_count == 0)
+			continue;
+
+		if (ra.block.number_in_file != rb.block.number_in_file
+				|| ra.block.compressed_file_offset
+					!= rb.block.compressed_file_offset
+				|| ra.block.uncompressed_file_offset
+					!= rb.block.uncompressed_file_offset
+				|| ra.block.number_in_stream
+					!= rb.block.number_in_stream
+				|| ra.block.compressed_stream_offset
+					!= rb.block.compressed_stream_offset
+				|| ra.block.uncompressed_stream_offset
+					!= rb.block.uncompressed_stream_offset
+				|| ra.block.uncompressed_size
+					!= rb.block.uncompressed_size
+				|| ra.block.unpadded_size
+					!= rb.block.unpadded_size
+				|| ra.block.total_size
+					!= rb.block.total_size)
+			return false;
+	}
+}
+
+
+static void
+test_equal(void)
+{
+	lzma_index *a = create_empty();
+	lzma_index *b = create_small();
+	lzma_index *c = create_big();
+	expect(a && b && c);
+
+	expect(is_equal(a, a));
+	expect(is_equal(b, b));
+	expect(is_equal(c, c));
+
+	expect(!is_equal(a, b));
+	expect(!is_equal(a, c));
+	expect(!is_equal(b, c));
+
+	lzma_index_end(a, NULL);
+	lzma_index_end(b, NULL);
+	lzma_index_end(c, NULL);
+}
+
+
+static void
+test_overflow(void)
+{
+	// Integer overflow tests
+	lzma_index *i = create_empty();
+
+	expect(lzma_index_append(i, NULL, LZMA_VLI_MAX - 5, 1234)
+			== LZMA_DATA_ERROR);
+
+	// TODO
+
+	lzma_index_end(i, NULL);
+}
+
+
+static void
+test_copy(const lzma_index *i)
+{
+	lzma_index *d = lzma_index_dup(i, NULL);
+	expect(d != NULL);
+	expect(is_equal(i, d));
+	lzma_index_end(d, NULL);
+}
+
+
+static void
+test_read(lzma_index *i)
+{
+	lzma_index_iter r;
+	lzma_index_iter_init(&r, i);
+
+	// Try twice so we see that rewinding works.
+	for (size_t j = 0; j < 2; ++j) {
+		lzma_vli total_size = 0;
+		lzma_vli uncompressed_size = 0;
+		lzma_vli stream_offset = LZMA_STREAM_HEADER_SIZE;
+		lzma_vli uncompressed_offset = 0;
+		uint32_t count = 0;
+
+		while (!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)) {
+			++count;
+
+			total_size += r.block.total_size;
+			uncompressed_size += r.block.uncompressed_size;
+
+			expect(r.block.compressed_file_offset
+					== stream_offset);
+			expect(r.block.uncompressed_file_offset
+					== uncompressed_offset);
+
+			stream_offset += r.block.total_size;
+			uncompressed_offset += r.block.uncompressed_size;
+		}
+
+		expect(lzma_index_total_size(i) == total_size);
+		expect(lzma_index_uncompressed_size(i) == uncompressed_size);
+		expect(lzma_index_block_count(i) == count);
+
+		lzma_index_iter_rewind(&r);
+	}
+}
+
+
+static void
+test_code(lzma_index *i)
+{
+	const size_t alloc_size = 128 * 1024;
+	uint8_t *buf = malloc(alloc_size);
+	expect(buf != NULL);
+
+	// Encode
+	lzma_stream strm = LZMA_STREAM_INIT;
+	expect(lzma_index_encoder(&strm, i) == LZMA_OK);
+	const lzma_vli index_size = lzma_index_size(i);
+	succeed(coder_loop(&strm, NULL, 0, buf, index_size,
+			LZMA_STREAM_END, LZMA_RUN));
+
+	// Decode
+	lzma_index *d;
+	expect(lzma_index_decoder(&strm, &d, MEMLIMIT) == LZMA_OK);
+	expect(d == NULL);
+	succeed(decoder_loop(&strm, buf, index_size));
+
+	expect(is_equal(i, d));
+
+	lzma_index_end(d, NULL);
+	lzma_end(&strm);
+
+	// Decode with hashing
+	lzma_index_hash *h = lzma_index_hash_init(NULL, NULL);
+	expect(h != NULL);
+	lzma_index_iter r;
+	lzma_index_iter_init(&r, i);
+	while (!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK))
+		expect(lzma_index_hash_append(h, r.block.unpadded_size,
+				r.block.uncompressed_size) == LZMA_OK);
+	size_t pos = 0;
+	while (pos < index_size - 1)
+		expect(lzma_index_hash_decode(h, buf, &pos, pos + 1)
+				== LZMA_OK);
+	expect(lzma_index_hash_decode(h, buf, &pos, pos + 1)
+			== LZMA_STREAM_END);
+
+	lzma_index_hash_end(h, NULL);
+
+	// Encode buffer
+	size_t buf_pos = 1;
+	expect(lzma_index_buffer_encode(i, buf, &buf_pos, index_size)
+			== LZMA_BUF_ERROR);
+	expect(buf_pos == 1);
+
+	succeed(lzma_index_buffer_encode(i, buf, &buf_pos, index_size + 1));
+	expect(buf_pos == index_size + 1);
+
+	// Decode buffer
+	buf_pos = 1;
+	uint64_t memlimit = MEMLIMIT;
+	expect(lzma_index_buffer_decode(&d, &memlimit, NULL, buf, &buf_pos,
+			index_size) == LZMA_DATA_ERROR);
+	expect(buf_pos == 1);
+	expect(d == NULL);
+
+	succeed(lzma_index_buffer_decode(&d, &memlimit, NULL, buf, &buf_pos,
+			index_size + 1));
+	expect(buf_pos == index_size + 1);
+	expect(is_equal(i, d));
+
+	lzma_index_end(d, NULL);
+
+	free(buf);
+}
+
+
+static void
+test_many(lzma_index *i)
+{
+	test_copy(i);
+	test_read(i);
+	test_code(i);
+}
+
+
+static void
+test_cat(void)
+{
+	lzma_index *a, *b, *c;
+	lzma_index_iter r;
+
+	// Empty Indexes
+	a = create_empty();
+	b = create_empty();
+	expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
+	expect(lzma_index_block_count(a) == 0);
+	expect(lzma_index_stream_size(a) == 2 * LZMA_STREAM_HEADER_SIZE + 8);
+	expect(lzma_index_file_size(a)
+			== 2 * (2 * LZMA_STREAM_HEADER_SIZE + 8));
+	lzma_index_iter_init(&r, a);
+	expect(lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK));
+
+	b = create_empty();
+	expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
+	expect(lzma_index_block_count(a) == 0);
+	expect(lzma_index_stream_size(a) == 2 * LZMA_STREAM_HEADER_SIZE + 8);
+	expect(lzma_index_file_size(a)
+			== 3 * (2 * LZMA_STREAM_HEADER_SIZE + 8));
+
+	b = create_empty();
+	c = create_empty();
+	expect(lzma_index_stream_padding(b, 4) == LZMA_OK);
+	expect(lzma_index_cat(b, c, NULL) == LZMA_OK);
+	expect(lzma_index_block_count(b) == 0);
+	expect(lzma_index_stream_size(b) == 2 * LZMA_STREAM_HEADER_SIZE + 8);
+	expect(lzma_index_file_size(b)
+			== 2 * (2 * LZMA_STREAM_HEADER_SIZE + 8) + 4);
+
+	expect(lzma_index_stream_padding(a, 8) == LZMA_OK);
+	expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
+	expect(lzma_index_block_count(a) == 0);
+	expect(lzma_index_stream_size(a) == 2 * LZMA_STREAM_HEADER_SIZE + 8);
+	expect(lzma_index_file_size(a)
+			== 5 * (2 * LZMA_STREAM_HEADER_SIZE + 8) + 4 + 8);
+
+	expect(lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK));
+	lzma_index_iter_rewind(&r);
+	expect(lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK));
+	lzma_index_end(a, NULL);
+
+	// Small Indexes
+	a = create_small();
+	lzma_vli stream_size = lzma_index_stream_size(a);
+	lzma_index_iter_init(&r, a);
+	for (int i = SMALL_COUNT; i >= 0; --i)
+		expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)
+				^ (i == 0));
+
+	b = create_small();
+	expect(lzma_index_stream_padding(a, 4) == LZMA_OK);
+	expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
+	expect(lzma_index_file_size(a) == stream_size * 2 + 4);
+	expect(lzma_index_stream_size(a) > stream_size);
+	expect(lzma_index_stream_size(a) < stream_size * 2);
+	for (int i = SMALL_COUNT; i >= 0; --i)
+		expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)
+				^ (i == 0));
+
+	lzma_index_iter_rewind(&r);
+	for (int i = SMALL_COUNT * 2; i >= 0; --i)
+		expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)
+				^ (i == 0));
+
+	b = create_small();
+	c = create_small();
+	expect(lzma_index_stream_padding(b, 8) == LZMA_OK);
+	expect(lzma_index_cat(b, c, NULL) == LZMA_OK);
+	expect(lzma_index_stream_padding(a, 12) == LZMA_OK);
+	expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
+	expect(lzma_index_file_size(a) == stream_size * 4 + 4 + 8 + 12);
+
+	expect(lzma_index_block_count(a) == SMALL_COUNT * 4);
+	for (int i = SMALL_COUNT * 2; i >= 0; --i)
+		expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)
+				^ (i == 0));
+
+	lzma_index_iter_rewind(&r);
+	for (int i = SMALL_COUNT * 4; i >= 0; --i)
+		expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)
+				^ (i == 0));
+
+	lzma_index_end(a, NULL);
+
+	// Mix of empty and small
+	a = create_empty();
+	b = create_small();
+	expect(lzma_index_stream_padding(a, 4) == LZMA_OK);
+	expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
+	lzma_index_iter_init(&r, a);
+	for (int i = SMALL_COUNT; i >= 0; --i)
+		expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)
+				^ (i == 0));
+
+	lzma_index_end(a, NULL);
+
+	// Big Indexes
+	a = create_big();
+	stream_size = lzma_index_stream_size(a);
+	b = create_big();
+	expect(lzma_index_stream_padding(a, 4) == LZMA_OK);
+	expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
+	expect(lzma_index_file_size(a) == stream_size * 2 + 4);
+	expect(lzma_index_stream_size(a) > stream_size);
+	expect(lzma_index_stream_size(a) < stream_size * 2);
+
+	b = create_big();
+	c = create_big();
+	expect(lzma_index_stream_padding(b, 8) == LZMA_OK);
+	expect(lzma_index_cat(b, c, NULL) == LZMA_OK);
+	expect(lzma_index_stream_padding(a, 12) == LZMA_OK);
+	expect(lzma_index_cat(a, b, NULL) == LZMA_OK);
+	expect(lzma_index_file_size(a) == stream_size * 4 + 4 + 8 + 12);
+
+	lzma_index_iter_init(&r, a);
+	for (int i = BIG_COUNT * 4; i >= 0; --i)
+		expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK)
+				^ (i == 0));
+
+	lzma_index_end(a, NULL);
+}
+
+
+static void
+test_locate(void)
+{
+	lzma_index *i = lzma_index_init(NULL);
+	expect(i != NULL);
+	lzma_index_iter r;
+	lzma_index_iter_init(&r, i);
+
+	// Cannot locate anything from an empty Index.
+	expect(lzma_index_iter_locate(&r, 0));
+	expect(lzma_index_iter_locate(&r, 555));
+
+	// One empty Record: nothing is found since there's no uncompressed
+	// data.
+	expect(lzma_index_append(i, NULL, 16, 0) == LZMA_OK);
+	expect(lzma_index_iter_locate(&r, 0));
+
+	// Non-empty Record and we can find something.
+	expect(lzma_index_append(i, NULL, 32, 5) == LZMA_OK);
+	expect(!lzma_index_iter_locate(&r, 0));
+	expect(r.block.total_size == 32);
+	expect(r.block.uncompressed_size == 5);
+	expect(r.block.compressed_file_offset
+			== LZMA_STREAM_HEADER_SIZE + 16);
+	expect(r.block.uncompressed_file_offset == 0);
+
+	// Still cannot find anything past the end.
+	expect(lzma_index_iter_locate(&r, 5));
+
+	// Add the third Record.
+	expect(lzma_index_append(i, NULL, 40, 11) == LZMA_OK);
+
+	expect(!lzma_index_iter_locate(&r, 0));
+	expect(r.block.total_size == 32);
+	expect(r.block.uncompressed_size == 5);
+	expect(r.block.compressed_file_offset
+			== LZMA_STREAM_HEADER_SIZE + 16);
+	expect(r.block.uncompressed_file_offset == 0);
+
+	expect(!lzma_index_iter_next(&r, LZMA_INDEX_ITER_BLOCK));
+	expect(r.block.total_size == 40);
+	expect(r.block.uncompressed_size == 11);
+	expect(r.block.compressed_file_offset
+			== LZMA_STREAM_HEADER_SIZE + 16 + 32);
+	expect(r.block.uncompressed_file_offset == 5);
+
+	expect(!lzma_index_iter_locate(&r, 2));
+	expect(r.block.total_size == 32);
+	expect(r.block.uncompressed_size == 5);
+	expect(r.block.compressed_file_offset
+			== LZMA_STREAM_HEADER_SIZE + 16);
+	expect(r.block.uncompressed_file_offset == 0);
+
+	expect(!lzma_index_iter_locate(&r, 5));
+	expect(r.block.total_size == 40);
+	expect(r.block.uncompressed_size == 11);
+	expect(r.block.compressed_file_offset
+			== LZMA_STREAM_HEADER_SIZE + 16 + 32);
+	expect(r.block.uncompressed_file_offset == 5);
+
+	expect(!lzma_index_iter_locate(&r, 5 + 11 - 1));
+	expect(r.block.total_size == 40);
+	expect(r.block.uncompressed_size == 11);
+	expect(r.block.compressed_file_offset
+			== LZMA_STREAM_HEADER_SIZE + 16 + 32);
+	expect(r.block.uncompressed_file_offset == 5);
+
+	expect(lzma_index_iter_locate(&r, 5 + 11));
+	expect(lzma_index_iter_locate(&r, 5 + 15));
+
+	// Large Index
+	lzma_index_end(i, NULL);
+	i = lzma_index_init(NULL);
+	expect(i != NULL);
+	lzma_index_iter_init(&r, i);
+
+	for (size_t n = 4; n <= 4 * 5555; n += 4)
+		expect(lzma_index_append(i, NULL, n + 8, n) == LZMA_OK);
+
+	expect(lzma_index_block_count(i) == 5555);
+
+	// First Record
+	expect(!lzma_index_iter_locate(&r, 0));
+	expect(r.block.total_size == 4 + 8);
+	expect(r.block.uncompressed_size == 4);
+	expect(r.block.compressed_file_offset == LZMA_STREAM_HEADER_SIZE);
+	expect(r.block.uncompressed_file_offset == 0);
+
+	expect(!lzma_index_iter_locate(&r, 3));
+	expect(r.block.total_size == 4 + 8);
+	expect(r.block.uncompressed_size == 4);
+	expect(r.block.compressed_file_offset == LZMA_STREAM_HEADER_SIZE);
+	expect(r.block.uncompressed_file_offset == 0);
+
+	// Second Record
+	expect(!lzma_index_iter_locate(&r, 4));
+	expect(r.block.total_size == 2 * 4 + 8);
+	expect(r.block.uncompressed_size == 2 * 4);
+	expect(r.block.compressed_file_offset
+			== LZMA_STREAM_HEADER_SIZE + 4 + 8);
+	expect(r.block.uncompressed_file_offset == 4);
+
+	// Last Record
+	expect(!lzma_index_iter_locate(
+			&r, lzma_index_uncompressed_size(i) - 1));
+	expect(r.block.total_size == 4 * 5555 + 8);
+	expect(r.block.uncompressed_size == 4 * 5555);
+	expect(r.block.compressed_file_offset == lzma_index_total_size(i)
+			+ LZMA_STREAM_HEADER_SIZE - 4 * 5555 - 8);
+	expect(r.block.uncompressed_file_offset
+			== lzma_index_uncompressed_size(i) - 4 * 5555);
+
+	// Allocation chunk boundaries. See INDEX_GROUP_SIZE in
+	// liblzma/common/index.c.
+	const size_t group_multiple = 256 * 4;
+	const size_t radius = 8;
+	const size_t start = group_multiple - radius;
+	lzma_vli ubase = 0;
+	lzma_vli tbase = 0;
+	size_t n;
+	for (n = 1; n < start; ++n) {
+		ubase += n * 4;
+		tbase += n * 4 + 8;
+	}
+
+	while (n < start + 2 * radius) {
+		expect(!lzma_index_iter_locate(&r, ubase + n * 4));
+
+		expect(r.block.compressed_file_offset == tbase + n * 4 + 8
+				+ LZMA_STREAM_HEADER_SIZE);
+		expect(r.block.uncompressed_file_offset == ubase + n * 4);
+
+		tbase += n * 4 + 8;
+		ubase += n * 4;
+		++n;
+
+		expect(r.block.total_size == n * 4 + 8);
+		expect(r.block.uncompressed_size == n * 4);
+	}
+
+	// Do it also backwards.
+	while (n > start) {
+		expect(!lzma_index_iter_locate(&r, ubase + (n - 1) * 4));
+
+		expect(r.block.total_size == n * 4 + 8);
+		expect(r.block.uncompressed_size == n * 4);
+
+		--n;
+		tbase -= n * 4 + 8;
+		ubase -= n * 4;
+
+		expect(r.block.compressed_file_offset == tbase + n * 4 + 8
+				+ LZMA_STREAM_HEADER_SIZE);
+		expect(r.block.uncompressed_file_offset == ubase + n * 4);
+	}
+
+	// Test locating in concatenated Index.
+	lzma_index_end(i, NULL);
+	i = lzma_index_init(NULL);
+	expect(i != NULL);
+	lzma_index_iter_init(&r, i);
+	for (n = 0; n < group_multiple; ++n)
+		expect(lzma_index_append(i, NULL, 8, 0) == LZMA_OK);
+	expect(lzma_index_append(i, NULL, 16, 1) == LZMA_OK);
+	expect(!lzma_index_iter_locate(&r, 0));
+	expect(r.block.total_size == 16);
+	expect(r.block.uncompressed_size == 1);
+	expect(r.block.compressed_file_offset
+			== LZMA_STREAM_HEADER_SIZE + group_multiple * 8);
+	expect(r.block.uncompressed_file_offset == 0);
+
+	lzma_index_end(i, NULL);
+}
+
+
+static void
+test_corrupt(void)
+{
+	const size_t alloc_size = 128 * 1024;
+	uint8_t *buf = malloc(alloc_size);
+	expect(buf != NULL);
+	lzma_stream strm = LZMA_STREAM_INIT;
+
+	lzma_index *i = create_empty();
+	expect(lzma_index_append(i, NULL, 0, 1) == LZMA_PROG_ERROR);
+	lzma_index_end(i, NULL);
+
+	// Create a valid Index and corrupt it in different ways.
+	i = create_small();
+	expect(lzma_index_encoder(&strm, i) == LZMA_OK);
+	succeed(coder_loop(&strm, NULL, 0, buf, 20,
+			LZMA_STREAM_END, LZMA_RUN));
+	lzma_index_end(i, NULL);
+
+	// Wrong Index Indicator
+	buf[0] ^= 1;
+	expect(lzma_index_decoder(&strm, &i, MEMLIMIT) == LZMA_OK);
+	succeed(decoder_loop_ret(&strm, buf, 1, LZMA_DATA_ERROR));
+	buf[0] ^= 1;
+
+	// Wrong Number of Records and thus CRC32 fails.
+	--buf[1];
+	expect(lzma_index_decoder(&strm, &i, MEMLIMIT) == LZMA_OK);
+	succeed(decoder_loop_ret(&strm, buf, 10, LZMA_DATA_ERROR));
+	++buf[1];
+
+	// Padding not NULs
+	buf[15] ^= 1;
+	expect(lzma_index_decoder(&strm, &i, MEMLIMIT) == LZMA_OK);
+	succeed(decoder_loop_ret(&strm, buf, 16, LZMA_DATA_ERROR));
+
+	lzma_end(&strm);
+	free(buf);
+}
+
+
+int
+main(void)
+{
+	test_equal();
+
+	test_overflow();
+
+	lzma_index *i = create_empty();
+	test_many(i);
+	lzma_index_end(i, NULL);
+
+	i = create_small();
+	test_many(i);
+	lzma_index_end(i, NULL);
+
+	i = create_big();
+	test_many(i);
+	lzma_index_end(i, NULL);
+
+	test_cat();
+
+	test_locate();
+
+	test_corrupt();
+
+	return 0;
+}
diff --git a/tests/test_stream_flags.c b/tests/test_stream_flags.c
new file mode 100644
index 0000000..9611459
--- /dev/null
+++ b/tests/test_stream_flags.c
@@ -0,0 +1,180 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       test_stream_flags.c
+/// \brief      Tests Stream Header and Stream Footer coders
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "tests.h"
+
+
+static lzma_stream_flags known_flags;
+static lzma_stream_flags decoded_flags;
+static uint8_t buffer[LZMA_STREAM_HEADER_SIZE];
+
+
+static bool
+validate(void)
+{
+	// TODO: This could require the specific error type as an argument.
+	// We could also test that lzma_stream_flags_compare() gives
+	// the correct return values in different situations.
+	return lzma_stream_flags_compare(&known_flags, &decoded_flags)
+			!= LZMA_OK;
+}
+
+
+static bool
+test_header_decoder(lzma_ret expected_ret)
+{
+	memcrap(&decoded_flags, sizeof(decoded_flags));
+
+	if (lzma_stream_header_decode(&decoded_flags, buffer) != expected_ret)
+		return true;
+
+	if (expected_ret != LZMA_OK)
+		return false;
+
+	// Header doesn't have Backward Size, so make
+	// lzma_stream_flags_compare() ignore it.
+	decoded_flags.backward_size = LZMA_VLI_UNKNOWN;
+	return validate();
+}
+
+
+static void
+test_header(void)
+{
+	memcrap(buffer, sizeof(buffer));
+	expect(lzma_stream_header_encode(&known_flags, buffer) == LZMA_OK);
+	succeed(test_header_decoder(LZMA_OK));
+}
+
+
+static bool
+test_footer_decoder(lzma_ret expected_ret)
+{
+	memcrap(&decoded_flags, sizeof(decoded_flags));
+
+	if (lzma_stream_footer_decode(&decoded_flags, buffer) != expected_ret)
+		return true;
+
+	if (expected_ret != LZMA_OK)
+		return false;
+
+	return validate();
+}
+
+
+static void
+test_footer(void)
+{
+	memcrap(buffer, sizeof(buffer));
+	expect(lzma_stream_footer_encode(&known_flags, buffer) == LZMA_OK);
+	succeed(test_footer_decoder(LZMA_OK));
+}
+
+
+static void
+test_encode_invalid(void)
+{
+	known_flags.check = LZMA_CHECK_ID_MAX + 1;
+	known_flags.backward_size = 1024;
+
+	expect(lzma_stream_header_encode(&known_flags, buffer)
+			== LZMA_PROG_ERROR);
+
+	expect(lzma_stream_footer_encode(&known_flags, buffer)
+			== LZMA_PROG_ERROR);
+
+	known_flags.check = (lzma_check)(-1);
+
+	expect(lzma_stream_header_encode(&known_flags, buffer)
+			== LZMA_PROG_ERROR);
+
+	expect(lzma_stream_footer_encode(&known_flags, buffer)
+			== LZMA_PROG_ERROR);
+
+	known_flags.check = LZMA_CHECK_NONE;
+	known_flags.backward_size = 0;
+
+	// Header encoder ignores backward_size.
+	expect(lzma_stream_header_encode(&known_flags, buffer) == LZMA_OK);
+
+	expect(lzma_stream_footer_encode(&known_flags, buffer)
+			== LZMA_PROG_ERROR);
+
+	known_flags.backward_size = LZMA_VLI_MAX;
+
+	expect(lzma_stream_header_encode(&known_flags, buffer) == LZMA_OK);
+
+	expect(lzma_stream_footer_encode(&known_flags, buffer)
+			== LZMA_PROG_ERROR);
+}
+
+
+static void
+test_decode_invalid(void)
+{
+	known_flags.check = LZMA_CHECK_NONE;
+	known_flags.backward_size = 1024;
+
+	expect(lzma_stream_header_encode(&known_flags, buffer) == LZMA_OK);
+
+	// Test 1 (invalid Magic Bytes)
+	buffer[5] ^= 1;
+	succeed(test_header_decoder(LZMA_FORMAT_ERROR));
+	buffer[5] ^= 1;
+
+	// Test 2a (valid CRC32)
+	uint32_t crc = lzma_crc32(buffer + 6, 2, 0);
+	unaligned_write32le(buffer + 8, crc);
+	succeed(test_header_decoder(LZMA_OK));
+
+	// Test 2b (invalid Stream Flags with valid CRC32)
+	buffer[6] ^= 0x20;
+	crc = lzma_crc32(buffer + 6, 2, 0);
+	unaligned_write32le(buffer + 8, crc);
+	succeed(test_header_decoder(LZMA_OPTIONS_ERROR));
+
+	// Test 3 (invalid CRC32)
+	expect(lzma_stream_header_encode(&known_flags, buffer) == LZMA_OK);
+	buffer[9] ^= 1;
+	succeed(test_header_decoder(LZMA_DATA_ERROR));
+
+	// Test 4 (invalid Stream Flags with valid CRC32)
+	expect(lzma_stream_footer_encode(&known_flags, buffer) == LZMA_OK);
+	buffer[9] ^= 0x40;
+	crc = lzma_crc32(buffer + 4, 6, 0);
+	unaligned_write32le(buffer, crc);
+	succeed(test_footer_decoder(LZMA_OPTIONS_ERROR));
+
+	// Test 5 (invalid Magic Bytes)
+	expect(lzma_stream_footer_encode(&known_flags, buffer) == LZMA_OK);
+	buffer[11] ^= 1;
+	succeed(test_footer_decoder(LZMA_FORMAT_ERROR));
+}
+
+
+int
+main(void)
+{
+	// Valid headers
+	known_flags.backward_size = 1024;
+	for (lzma_check check = LZMA_CHECK_NONE;
+			check <= LZMA_CHECK_ID_MAX; ++check) {
+		test_header();
+		test_footer();
+	}
+
+	// Invalid headers
+	test_encode_invalid();
+	test_decode_invalid();
+
+	return 0;
+}
diff --git a/tests/tests.h b/tests/tests.h
new file mode 100644
index 0000000..8f3c745
--- /dev/null
+++ b/tests/tests.h
@@ -0,0 +1,124 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+/// \file       tests.h
+/// \brief      Common definitions for test applications
+//
+//  Author:     Lasse Collin
+//
+//  This file has been put into the public domain.
+//  You can do whatever you want with this file.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef LZMA_TESTS_H
+#define LZMA_TESTS_H
+
+#include "sysdefs.h"
+#include "tuklib_integer.h"
+#include "lzma.h"
+
+#include <stdio.h>
+
+#define memcrap(buf, size) memset(buf, 0xFD, size)
+
+#define expect(test) ((test) ? 0 : (fprintf(stderr, "%s:%d: %s\n", \
+	__FILE__, __LINE__, #test), abort(), 0))
+
+#define succeed(test) expect(!(test))
+
+#define fail(test) expect(test)
+
+
+static inline const char *
+lzma_ret_sym(lzma_ret ret)
+{
+	if ((unsigned int)(ret) > LZMA_PROG_ERROR)
+		return "UNKNOWN_ERROR";
+
+	static const char *msgs[] = {
+		"LZMA_OK",
+		"LZMA_STREAM_END",
+		"LZMA_NO_CHECK",
+		"LZMA_UNSUPPORTED_CHECK",
+		"LZMA_GET_CHECK",
+		"LZMA_MEM_ERROR",
+		"LZMA_MEMLIMIT_ERROR",
+		"LZMA_FORMAT_ERROR",
+		"LZMA_OPTIONS_ERROR",
+		"LZMA_DATA_ERROR",
+		"LZMA_BUF_ERROR",
+		"LZMA_PROG_ERROR"
+	};
+
+	return msgs[ret];
+}
+
+
+static inline bool
+coder_loop(lzma_stream *strm, uint8_t *in, size_t in_size,
+		uint8_t *out, size_t out_size,
+		lzma_ret expected_ret, lzma_action finishing_action)
+{
+	size_t in_left = in_size;
+	size_t out_left = out_size > 0 ? out_size + 1 : 0;
+	lzma_action action = LZMA_RUN;
+	lzma_ret ret;
+
+	strm->next_in = NULL;
+	strm->avail_in = 0;
+	strm->next_out = NULL;
+	strm->avail_out = 0;
+
+	while (true) {
+		if (in_left > 0) {
+			if (--in_left == 0)
+				action = finishing_action;
+
+			strm->next_in = in++;
+			strm->avail_in = 1;
+		}
+
+		if (out_left > 0) {
+			--out_left;
+			strm->next_out = out++;
+			strm->avail_out = 1;
+		}
+
+		ret = lzma_code(strm, action);
+		if (ret != LZMA_OK)
+			break;
+	}
+
+	bool error = false;
+
+	if (ret != expected_ret)
+		error = true;
+
+	if (expected_ret == LZMA_STREAM_END) {
+		if (strm->total_in != in_size || strm->total_out != out_size)
+			error = true;
+	} else {
+		if (strm->total_in != in_size || strm->total_out != out_size)
+			error = true;
+	}
+
+	return error;
+}
+
+
+static inline bool
+decoder_loop_ret(lzma_stream *strm, uint8_t *in, size_t in_size,
+		lzma_ret expected_ret)
+{
+	return coder_loop(strm, in, in_size, NULL, 0, expected_ret, LZMA_RUN);
+}
+
+
+static inline bool
+decoder_loop(lzma_stream *strm, uint8_t *in, size_t in_size)
+{
+	return coder_loop(strm, in, in_size, NULL, 0,
+			LZMA_STREAM_END, LZMA_RUN);
+}
+
+#endif
diff --git a/version.sh b/version.sh
new file mode 100755
index 0000000..40d0493
--- /dev/null
+++ b/version.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+#############################################################################
+#
+# Get the version string from version.h and print it out without
+# trailing newline. This makes it suitable for use in configure.ac.
+#
+#############################################################################
+#
+# Author: Lasse Collin
+#
+# This file has been put into the public domain.
+# You can do whatever you want with this file.
+#
+#############################################################################
+
+sed -n 's/LZMA_VERSION_STABILITY_ALPHA/alpha/
+	s/LZMA_VERSION_STABILITY_BETA/beta/
+	s/LZMA_VERSION_STABILITY_STABLE//
+	s/^#define LZMA_VERSION_[MPS][AIT][AJNT][A-Z]* //p' \
+	src/liblzma/api/lzma/version.h \
+	| tr '\n' '|' \
+	| sed 's/|/./; s/|/./; s/|//g' \
+	| tr -d '\n'
diff --git a/windows/INSTALL-Windows.txt b/windows/INSTALL-Windows.txt
new file mode 100644
index 0000000..b5ac963
--- /dev/null
+++ b/windows/INSTALL-Windows.txt
@@ -0,0 +1,131 @@
+
+Building XZ Utils on Windows
+============================
+
+Introduction
+------------
+
+    This document explains shortly where to get and how to install the
+    build tool that are needed to build XZ Utils on Windows. The final
+    binary package will be standalone in sense that it will depend only
+    on DLLs that are included in all Windows installations.
+
+    These instructions don't apply to Cygwin. XZ Utils can be built under
+    Cygwin in the same way as many other packages.
+
+    These instructions don't apply to MinGW and MSYS developers either,
+    who may want to package XZ Utils for MinGW or MSYS distributions.
+    You know who you are, and will probably use quite different configure
+    options etc. than what is described here.
+
+
+Installing the toolchain(s)
+---------------------------
+
+    Some of the following is needed:
+      - MSYS is always needed to use the GNU Autotools based build system.
+      - MinGW builds 32-bit x86 binaries.
+      - MingW-w32 builds 32-bit x86 executables too.
+      - MinGW-w64 builds 64-bit x86-64 binaries.
+
+    So you need to pick between MinGW and MinGW-w32 when building
+    32-bit version. You don't need both.
+
+    You might find 7-Zip <http://7-zip.org/> handy when extracting
+    some files (especially the .tar.lzma files). The ready-made
+    build script will also use 7-Zip to create the distributable
+    .zip and .7z files.
+
+    I used the following directory structure but you can use whatever
+    you want. Just note that I will use these in my examples. Each of
+    these should have a subdirectory "bin":
+
+        C:\devel\tools\msys
+        C:\devel\tools\mingw
+        C:\devel\tools\mingw-w32
+        C:\devel\tools\mingw-w64
+
+
+Installing MSYS
+
+    You can download MSYS from MinGW's Sourceforge page:
+
+        http://sourceforge.net/projects/mingw/files/
+
+    It's under "MSYS Base System". I recommend using MSYS 1.0.11
+    (MSYS-1.0.11.exe or msysCORE-1.0.11-bin.tar.gz) because that
+    package includes all the required tools. At least some of the
+    later versions include only a subset and thus you would need to
+    download the rest separately. The old version will work fine for
+    building XZ Utils.
+
+    You can use either the .exe or .tar.gz package. I prefer .tar.gz,
+    because it can be extracted into any directory and later removed
+    without worrying about uninstallers.
+
+
+Installing MinGW
+
+    You can download the required packages from MinGW's Sourceforge page:
+
+        http://sourceforge.net/projects/mingw/files/
+
+    These version numbers were the latest when I wrote this document, but
+    you probably should pick the latest versions:
+
+        MinGW Runtime -> mingwrt-3.17-mingw32-dev.tar.gz
+        MinGW API for MS-Windows -> w32api-3.14-mingw32-dev.tar.gz
+        GNU Binutils -> binutils-2.20-1-bin.tar.gz
+        GCC Version 4 -> gcc-full-4.4.0-mingw32-bin-2.tar.lzma
+
+    The full GCC package is quite big, but if you want a smaller
+    download, you will need to download more than one file, so I'm
+    using the full package in this document for simplicity.
+
+    Extract the packages in the above order, possibly overwriting files
+    from packages that were extracted earlier.
+
+
+Installing MinGW-w32 or MinGW-w64
+
+    You can find the latest MinGW-w32 and MinGW-w64 builds here:
+
+        http://sourceforge.net/projects/mingw-w64/files/
+
+    Locate the appropriate files:
+
+        Toolchains targeting Win32 -> mingw-w32-*-mingw*.zip
+        Toolchains targeting Win64 -> mingw-w64-*-mingw*.zip
+
+    I don't know what is the most recommended one. I used sezero's
+    versions from "Personal Builds", since they seemed to have
+    a stable GCC (judging from the GCC version number only).
+
+    If you will install both MinGW-w32 and MinGW-w64, remember to
+    extract them into different directories.
+
+
+Building XZ Utils
+-----------------
+
+    Start MSYS by going to the directory C:\devel\tools\msys and running
+    msys.bat there (double-click or use command prompt). It will start
+    at "home" directory, which is C:\devel\tools\msys\home\YourUserName.
+
+    If you have xz-5.x.x.tar.gz in C:\devel, you should be able to build
+    it now with the following commands:
+
+        cd /c/devel
+        tar xzf xz-5.x.x.tar.gz
+        cd xz-5.x.x
+        sh windows/build.sh
+
+    If you used some other directory than C:\devel\tools for the build
+    tools, edit the variables near the beginning of build.sh first.
+
+    If you want to build manually, read the buildit() function in
+    build.sh. Look especially at the latter configure invocation.
+
+    Be patient. Running configure and other scripts used by the build
+    system is (very) slow under Windows.
+
diff --git a/windows/README-Windows.txt b/windows/README-Windows.txt
new file mode 100644
index 0000000..536d08f
--- /dev/null
+++ b/windows/README-Windows.txt
@@ -0,0 +1,115 @@
+
+XZ Utils for Windows
+====================
+
+Introduction
+------------
+
+    This package includes command line tools (xz.exe and a few others)
+    and the liblzma compression library from XZ Utils. You can find the
+    latest version and full source code from <http://tukaani.org/xz/>.
+
+    The parts of the XZ Utils source code, that are relevant to this
+    binary package, are in the public domain. XZ Utils have been built
+    for this package with MinGW and linked statically against the MinGW
+    runtime and w32api packages.
+
+    FIXME: Add license info about MinGW runtime and w32api.
+
+
+Package contents
+----------------
+
+    All executables and libraries in this package require msvcrt.dll.
+    It's included in all recent Windows versions. On Windows 95 it
+    might be missing, but once you get it somewhere, XZ Utils should
+    run even on Windows 95.
+
+    There are two different versions of the executable and library files.
+    There is one directory for each type of binaries:
+
+        bin_i486        32-bit x86 (i486 and up), Windows 95 and later
+        bin_x86-64      64-bit x86-64, Windows XP and later
+
+    Each of the above directories have the following files:
+
+        *.exe       Command line tools. (It's useless to double-click
+                    these; use the command prompt instead.) These have
+                    been linked statically against liblzma, so they
+                    don't require liblzma.dll. Thus, you can copy e.g.
+                    xz.exe to a directory that is in PATH without copying
+                    any other files from this package.
+
+        liblzma.dll Shared version of the liblzma compression library.
+                    This file is mostly useful to developers, although
+                    some non-developers might use it to upgrade their
+                    copy of liblzma.
+
+        liblzma.a   Static version of the liblzma compression library.
+                    This file is useful only for developers.
+
+    The rest of the directories contain architecture-independent files:
+
+        doc         Documentation in the plain text (TXT) format. The
+                    manuals of the command line tools are provided also
+                    in the PDF format. liblzma.def is in this directory
+                    too.
+
+        include     C header files for liblzma. These should be
+                    compatible with most C and C++ compilers. If you
+                    have problems, try to fix it and send your fixes
+                    upstream, or at least report a bug, thanks.
+
+
+Linking against liblzma
+-----------------------
+
+MinGW
+
+    If you use MinGW, linking against liblzma.dll or liblzma.a should
+    be straightforward. You don't need an import library to link
+    against liblzma.dll, and for static linking, you don't need to
+    worry about the LZMA_API_STATIC macro.
+
+    Note that the MinGW distribution includes liblzma. If you are
+    building packages that will be part of the MinGW distribution, you
+    probably should use the version of liblzma shipped in MinGW instead
+    of this package.
+
+
+Microsoft Visual C++
+
+    To link against liblzma.dll, you need to create an import library
+    first. You need the "lib" command from MSVC and liblzma.def from
+    the "doc" directory of this package. Here is the command that works
+    on 32-bit x86:
+
+        lib /def:liblzma.def /out:liblzma.lib /machine:ix86
+
+    On x86-64, the /machine argument has to naturally be changed:
+
+        lib /def:liblzma.def /out:liblzma.lib /machine:x64
+
+    Linking against static liblzma should work too. Rename liblzma.a
+    to e.g. liblzma_static.lib and tell MSVC to link against it. You
+    also need to tell lzma.h to not use __declspec(dllimport) by defining
+    the macro LZMA_API_STATIC. You can do it either in the C/C++ code
+
+        #define LZMA_API_STATIC
+        #include <lzma.h>
+
+    or by adding it to compiler options.
+
+
+Other compilers
+
+    If you are using some other compiler, see its documentation how to
+    create an import library (if it is needed). If it is simple, I
+    might consider including the instructions here.
+
+
+Reporting bugs
+--------------
+
+    Report bugs to <lasse.collin@tukaani.org> (in English or Finnish).
+
diff --git a/windows/build.sh b/windows/build.sh
new file mode 100755
index 0000000..3c762dc
--- /dev/null
+++ b/windows/build.sh
@@ -0,0 +1,188 @@
+#!/bin/sh
+#
+###############################################################################
+#
+# Build a binary package on Windows with MinGW and MSYS
+#
+# Set the paths where MinGW, Mingw-w32, or MinGW-w64 are installed. If both
+# MinGW and MinGW-w32 are specified, MinGW will be used. If there is no
+# 32-bit or 64-bit compiler at all, it is simply skipped.
+#
+# Optionally, 7-Zip is used to create the final .zip and .7z packages.
+# If you have installed it in the default directory, this script should
+# find it automatically. Otherwise adjust the path manually.
+#
+# If you want to use a cross-compiler e.g. on GNU/Linux, this script won't
+# work out of the box. You need to omit "make check" commands and replace
+# u2d with some other tool to convert newlines from LF to CR+LF. You will
+# also need to pass the --host option to configure.
+#
+###############################################################################
+#
+# Author: Lasse Collin
+#
+# This file has been put into the public domain.
+# You can do whatever you want with this file.
+#
+###############################################################################
+
+MINGW_DIR=/c/devel/tools/mingw
+MINGW_W32_DIR=/c/devel/tools/mingw-w32
+MINGW_W64_DIR=/c/devel/tools/mingw-w64
+
+for SEVENZ_EXE in "$PROGRAMW6432/7-Zip/7z.exe" "$PROGRAMFILES/7-Zip/7z.exe" \
+		"/c/Program Files/7-Zip/7z.exe"
+do
+	[ -x "$SEVENZ_EXE" ] && break
+done
+
+
+# Abort immediately if something goes wrong.
+set -e
+
+# White spaces in directory names may break things so catch them immediately.
+case $(pwd) in
+	' ' | '	' | '
+') echo "Error: White space in the directory name" >&2; exit 1 ;;
+esac
+
+# This script can be run either at the top-level directory of the package
+# or in the same directory containing this script.
+if [ ! -f windows/build.sh ]; then
+	cd ..
+	if [ ! -f windows/build.sh ]; then
+		echo "You are in a wrong directory." >&2
+		exit 1
+	fi
+fi
+
+# Run configure and copy the binaries to the given directory.
+#
+# The first argument is the directory where to copy the binaries.
+# The rest of the arguments are passed to configure.
+buildit()
+{
+	DESTDIR=$1
+	BUILD=$2
+	CFLAGS=$3
+
+	# Clean up if it was already configured.
+	[ -f Makefile ] && make distclean
+
+	# Build the size-optimized binaries. Note that I don't want to
+	# provide size-optimized liblzma (shared nor static), because
+	# that isn't thread-safe now, and depending on bunch of things,
+	# maybe it will never be on Windows (pthreads-win32 helps but
+	# static liblzma might bit a bit tricky with it).
+	./configure \
+		--prefix= \
+		--disable-nls \
+		--disable-threads \
+		--disable-shared \
+		--enable-small \
+		--build="$BUILD" \
+		CFLAGS="$CFLAGS -Os"
+	make check
+
+	mkdir -pv "$DESTDIR"
+	cp -v src/xzdec/{xz,lzma}dec.exe src/lzmainfo/lzmainfo.exe "$DESTDIR"
+
+	make distclean
+
+	# Build the normal speed-optimized binaries. Note that while
+	# --disable-threads has been documented to make some things
+	# thread-unsafe, it's not actually true with this combination
+	# of configure flags in XZ Utils 5.0.x. Things can (and probably
+	# will) change after 5.0.x, and this script will be updated too.
+	./configure \
+		--prefix= \
+		--disable-nls \
+		--disable-threads \
+		--enable-dynamic=no \
+		--build="$BUILD" \
+		CFLAGS="$CFLAGS -O2"
+	make check
+
+	cp -v src/xz/xz.exe src/liblzma/.libs/liblzma.a "$DESTDIR"
+	cp -v src/liblzma/.libs/liblzma-*.dll "$DESTDIR/liblzma.dll"
+
+	strip -v "$DESTDIR/"*
+}
+
+# Copy files and convert newlines from LF to CR+LF. Optinally add a suffix
+# to the destination filename.
+#
+# The first argument is the destination directory. The second argument is
+# the suffix to append to the filenames; use empty string if no extra suffix
+# is wanted. The rest of the arguments are actual the filenames.
+txtcp()
+{
+	DESTDIR=$1
+	SUFFIX=$2
+	shift 2
+	for SRCFILE; do
+		DESTFILE="$DESTDIR/${SRCFILE##*/}$SUFFIX"
+		echo "Converting \`$SRCFILE' -> \`$DESTFILE'"
+		u2d < "$SRCFILE" > "$DESTFILE"
+	done
+}
+
+# FIXME: Make sure that we don't get i686 or i586 code from the runtime.
+# Actually i586 would be fine, but i686 probably not if the idea is to
+# support even Win95.
+#
+# FIXME: Using i486 in the configure triplet may be wrong.
+if [ -d "$MINGW_DIR" ]; then
+	# 32-bit x86, Win95 or later, using MinGW
+	PATH=$MINGW_DIR/bin:$PATH \
+			buildit \
+			pkg/bin_i486 \
+			i486-pc-mingw32 \
+			'-march=i486 -mtune=generic'
+elif [ -d "$MINGW_W32_DIR" ]; then
+	# 32-bit x86, Win95 or later, using MinGW-w32
+	PATH=$MINGW_W32_DIR/bin:$MINGW_W32_DIR/i686-w64-mingw32/bin:$PATH \
+			buildit \
+			pkg/bin_i486 \
+			i486-w64-mingw32 \
+			'-march=i486 -mtune=generic'
+fi
+
+if [ -d "$MINGW_W64_DIR" ]; then
+	# 64-bit x86, WinXP or later, using MinGW-w64
+	PATH=$MINGW_W64_DIR/bin:$MINGW_W64_DIR/x86_64-w64-mingw32/bin:$PATH \
+			buildit \
+			pkg/bin_x86-64 \
+			x86_64-w64-mingw32 \
+			'-march=x86-64 -mtune=generic'
+fi
+
+# Copy the headers, the .def file, and the docs.
+# They are the same for all architectures and builds.
+mkdir -pv pkg/{include/lzma,doc/manuals}
+txtcp pkg/include "" src/liblzma/api/lzma.h
+txtcp pkg/include/lzma "" src/liblzma/api/lzma/*.h
+txtcp pkg/doc "" src/liblzma/liblzma.def
+txtcp pkg/doc .txt AUTHORS COPYING NEWS README THANKS TODO
+txtcp pkg/doc "" doc/*.txt
+txtcp pkg/doc/manuals "" doc/man/txt/{xz,xzdec,lzmainfo}.txt
+cp -v doc/man/pdf-*/{xz,xzdec,lzmainfo}-*.pdf pkg/doc/manuals
+txtcp pkg "" windows/README-Windows.txt
+
+# Create the package. This requires 7z.exe from 7-Zip. If it wasn't found,
+# this step is skipped and you have to zip it yourself.
+VER=$(sh version.sh)
+cd pkg
+if [ -x "$SEVENZ_EXE" ]; then
+	"$SEVENZ_EXE" a -tzip ../xz-$VER-windows.zip *
+	"$SEVENZ_EXE" a ../xz-$VER-windows.7z *
+else
+	echo
+	echo "NOTE: 7z.exe was not found. xz-$VER-windows.zip"
+	echo "      and xz-$VER-windows.7z were not created."
+	echo "      You can create them yourself from the pkg directory."
+fi
+
+echo
+echo "Build completed successfully."
+echo