diff --git a/LICENSE.TXT b/LICENSE.TXT
new file mode 100644
index 0000000..30ace6a
--- /dev/null
+++ b/LICENSE.TXT
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ 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 .
+
+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:
+
+ {project} Copyright (C) {year} {fullname}
+ 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
+.
+
+ 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
+.
\ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..79abdc1
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,18 @@
+BIN=bootunpack
+CC=gcc
+CFLAGS=-g -Wall -O2
+LIB=-lz
+SRC=$(wildcard *.c)
+
+OBJ=$(SRC:%.c=%.o)
+
+all: $(BIN)
+
+%.o: %.c
+ $(CC) -c $(CFLAGS) -o $@ $<
+
+$(BIN): $(OBJ)
+ $(CC) -o $@ $(OBJ) $(CFLAGS) $(LIB)
+
+clean:
+ rm -f $(BIN) $(OBJ)
diff --git a/bootunpack.c b/bootunpack.c
new file mode 100644
index 0000000..6fc24a4
--- /dev/null
+++ b/bootunpack.c
@@ -0,0 +1,732 @@
+// krnsym_extra.cpp : Defines the entry point for the console application.
+//
+
+#include "stdio.h"
+#include "zlib.h"
+#include "bootunpack.h"
+#include "lzo.h"
+#ifdef _WIN32
+#include "windows.h"
+#pragma comment(lib,"zlib.lib")
+#else
+#include
+#endif
+
+
+int g_save_kernel = 0;
+int g_save_symbol = 0;
+int g_save_ioctl_func = 0;
+
+const char* PathRemoveFileSpec(char* path)
+{
+ int i;
+ size_t length = strlen(path);
+
+ for(i = length ;i > 0 ;i--)
+ {
+#ifdef _WIN32
+ if(path[i] =='\\')
+
+#else
+ if(path[i] =='/')
+#endif
+ {
+ path[i] =0;
+ break;
+ }
+
+ }
+
+ return path;
+}
+
+
+int gzip_decode(void* pbufferin,int bufferin_size,void* pbufferout,int bufferoutsize)
+{
+ int ret;
+ z_stream z;
+
+ memset(&z,0,sizeof(z_stream));
+
+ inflateInit2(&z, 16+MAX_WBITS);
+ z.avail_in = bufferin_size;
+ z.next_in = pbufferin;
+ z.avail_out = bufferoutsize;
+ z.next_out = pbufferout;
+
+ ret = inflate(&z,2);
+ if(ret == Z_OK || ret == Z_STREAM_END)
+ {
+ inflateEnd(&z);
+ return z.total_out;
+ }
+
+ return 0;
+}
+
+int gzdecode_kernel(unsigned char* pdata,int size,int vmlinuz_offs,int compress_size,krninfo* krn)
+{
+ if(vmlinuz_offs && compress_size && krn)
+ {
+ krn->vmlinuz_size = compress_size*4;//assume
+
+#ifdef _WIN32
+ krn->vmlinuzbuffer = (unsigned char*)VirtualAlloc(0,krn->vmlinuz_size,MEM_COMMIT,PAGE_READWRITE);
+#else
+ krn->vmlinuzbuffer = (unsigned char*)mmap(0,krn->vmlinuz_size,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS ,0,0);
+#endif
+ if(krn->vmlinuzbuffer)
+ {
+ memset(krn->vmlinuzbuffer,0,krn->vmlinuz_size);
+ krn->vmlinuz_size = gzip_decode(pdata+vmlinuz_offs,compress_size,krn->vmlinuzbuffer,krn->vmlinuz_size);
+ if(krn->vmlinuz_size == 0)
+ {
+#ifdef _WIN32
+ VirtualFree(krn->vmlinuzbuffer,krn->vmlinuz_size,MEM_RELEASE);
+#else
+ munmap(krn->vmlinuzbuffer,krn->vmlinuz_size);
+#endif
+
+ return 0;
+ }
+ }
+ }
+
+ return krn->vmlinuz_size;
+}
+#include "lzo.h"
+
+int lzodecode_kernel(unsigned char* pdata,int size,int vmlinuz_offs,int compress_size,krninfo* krn)
+{
+ int ret;
+
+ if(vmlinuz_offs && compress_size && krn)
+ {
+ krn->vmlinuz_size = compress_size*2;//assume
+
+#ifdef _WIN32
+ krn->vmlinuzbuffer = (unsigned char*)VirtualAlloc(0,krn->vmlinuz_size,MEM_COMMIT,PAGE_READWRITE);
+#else
+ krn->vmlinuzbuffer = (unsigned char*)mmap(0,krn->vmlinuz_size,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS ,0,0);
+#endif
+ if(krn->vmlinuzbuffer)
+ {
+ memset(krn->vmlinuzbuffer,0,krn->vmlinuz_size);
+ ret = lzo1x_decompress_safe(pdata+vmlinuz_offs,compress_size,krn->vmlinuzbuffer,&krn->vmlinuz_size);
+ if(ret != 0)
+ {
+#ifdef _WIN32
+ VirtualFree(krn->vmlinuzbuffer,krn->vmlinuz_size,MEM_RELEASE);
+#else
+ munmap(krn->vmlinuzbuffer,krn->vmlinuz_size);
+#endif
+
+ krn->vmlinuz_size = 0;
+ return 0;
+ }
+ }
+ }
+
+ return krn->vmlinuz_size;
+}
+
+
+int decode_ramdisk(unsigned char* pdata,int size,int ramdisk_offs,int compress_size,krninfo* krn)
+{
+ if(ramdisk_offs && compress_size )
+ {
+ krn->ramdiskbuffer = malloc(compress_size*4);
+ if(krn->ramdiskbuffer)
+ {
+ memset(krn->ramdiskbuffer,0,compress_size*4);
+ krn->ramdisk_size = gzip_decode(pdata+ramdisk_offs,compress_size,krn->ramdiskbuffer,compress_size*4);
+ if(krn->ramdisk_size == 0)
+ {
+ free(krn->ramdiskbuffer);
+ printf("ramdisk uncompress failed\n");
+ return 0;
+ }
+ }
+ }
+
+ return krn->ramdisk_size;
+}
+
+char * _strstr_(const char *in,size_t size, const char *str)
+{
+ char c;
+ size_t len;
+ const char* end;
+
+ c = *str++;
+ if (!c)
+ return (char *) in;
+
+ len = strlen(str);
+ end = in+size-len;
+ do {
+ char sc;
+
+ do {
+ sc = *in++;
+ if (in > end)
+ return 0;
+ } while (sc != c);
+ } while (strncmp(in, str, len) != 0);
+
+ return (char *) (in - 1);
+}
+
+int is_android_bootimg(unsigned char* pdata,int size)
+{
+ return pdata && strncmp(pdata,"ANDROID!",8) == 0;
+}
+
+int is_zimage(unsigned char* pdata,int size)
+{
+ if(size > 0x1000)
+ {
+ return *(unsigned int*)pdata == 0xe1a00000 && *(unsigned int*)(pdata+8)== 0xe1a00000 &&
+ *(unsigned int*)(pdata+16)== 0xe1a00000 && *(unsigned int*)(pdata+20)== 0xe1a00000;
+ }
+
+ return 0;
+}
+
+
+void show_version(unsigned char* vmlinuz,int size)
+{
+ const char* ver;
+ if(vmlinuz && size)
+ {
+ ver = _strstr_(vmlinuz,size,"Linux version");
+ if(ver)
+ printf("%s\n",ver);
+ }
+}
+
+int dump(unsigned char* pdata,int size,const char* name)
+{
+ FILE* fd;
+
+ if(pdata && size)
+ {
+
+ fd = fopen(name,"wb");
+ if(fd == 0)
+ {
+ printf("dump failed\n");
+ return 0;
+ }
+ fwrite(pdata,1,size,fd);
+ fclose(fd);
+ return 1;
+ }
+
+ return 0;
+}
+
+void freeimg(krninfo* krn)
+{
+#ifdef _WIN32
+ VirtualFree(krn->vmlinuzbuffer,krn->vmlinuz_size,MEM_RELEASE);
+#else
+ munmap(krn->vmlinuzbuffer,krn->vmlinuz_size);
+#endif
+
+ if(krn->ramdiskbuffer)
+ free(krn->ramdiskbuffer);
+}
+
+int is_vmlinuz(unsigned char* pdata,int size)
+{
+ if(pdata && size)
+ {
+ if(strncmp(pdata,"\xd3\xf0\x21\xe3\x10\x9f\x10\xee",8)==0)
+ return 1;
+ }
+
+ return 0;
+}
+
+int get_ramdisk_offset(unsigned char* pdata,unsigned int size)
+{
+ int offset ;
+
+ for(offset = size -4;offset > 0x800;offset--)
+ {
+ if(*(unsigned int*)(pdata+offset) == 0x088b1f)
+ {
+ return offset;
+ }
+ }
+
+ return 0;
+}
+
+//some bootimg have no ramdisk
+
+int get_gzip_offset(unsigned char* pdata,unsigned int size,int start_offset)
+{
+ unsigned int offset = start_offset;
+
+ if(pdata ==0 )
+ return 0;
+
+ for(;offset < size - 4;offset++)
+ {
+ if(*(unsigned int*)(pdata+offset) == 0x088b1f)
+ {
+ return offset;
+ }
+ }
+
+ return 0;
+}
+
+int gzip_decode_kernel(unsigned char* image ,unsigned int size,krninfo* krn)
+{
+ unsigned int compress_size;
+ int gzip_offs =0;
+
+ gzip_offs = get_gzip_offset(image,size,0x800);
+ if(gzip_offs)
+ {
+ compress_size = size - gzip_offs;
+ if(gzdecode_kernel(image,size,gzip_offs,compress_size,krn)==0)
+ {
+ return 0;
+ }
+ if(is_vmlinuz(krn->vmlinuzbuffer,krn->vmlinuz_size))
+ {
+ krn->kernel_offs = gzip_offs;
+ return 1;
+ }
+ else
+ {
+ gzip_offs = get_gzip_offset(image,size,gzip_offs+4);
+ if(gzip_offs)
+ {
+ compress_size = size - gzip_offs;
+ if(gzdecode_kernel(image,size,gzip_offs,compress_size,krn)==0)
+ {
+ return 0;
+ }
+ if(is_vmlinuz(krn->vmlinuzbuffer,krn->vmlinuz_size))
+ {
+ krn->kernel_offs = gzip_offs;
+ return 1;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+int lzo_get_method(header_t *h)
+{
+ /* check method */
+ if (h->method == M_LZO1X_1)
+ {
+ h->method_name = "LZO1X-1";
+ if (h->level == 0)
+ h->level = 3;
+ }
+ else if (h->method == M_LZO1X_1_15)
+ {
+ h->method_name = "LZO1X-1(15)";
+ if (h->level == 0)
+ h->level = 1;
+ }
+ else if (h->method == M_LZO1X_999)
+ {
+ static char s[11+1] = "LZO1X-999 ";
+ s[9] = 0;
+ if (h->level == 0)
+ h->level = 9;
+ else if (h->version >= 0x0950 && h->lib_version >= 0x1020)
+ {
+ s[9] = '/';
+ s[10] = (char) (h->level + '0');
+ }
+ h->method_name = s;
+ }
+ else
+ return -1; /* not a LZO method */
+
+ /* check compression level */
+ if (h->level < 1 || h->level > 9)
+ return 15;
+
+ return 0;
+}
+
+int get_lzopdata_offset(unsigned char* pdata,unsigned int size,int start_offset,header_t* header)
+{
+ int k;
+ unsigned char l;
+ unsigned int checksum;
+ unsigned int adler32 = ADLER32_INIT_VALUE;
+ unsigned int crc32 = CRC32_INIT_VALUE;
+
+ char* p = pdata+start_offset+9;
+ char* q=p;
+
+ if(pdata ==0 || start_offset == 0)
+ return 0;
+
+ header->version = get_be16(p);p+=2;
+ header->lib_version = get_be16(p);p+=2;
+ if(header->version > 0x940)
+ {
+ header->version_needed_to_extract = get_be16(p);p+=2;
+ if(header->version_needed_to_extract > LZOP_VERSION || header->version_needed_to_extract < 0x900)
+ return 0;
+
+ }
+ header->method = *p++;
+ if (header->version >= 0x0940)
+ header->level = *p++;
+ header->flags = get_be32(p);p+=4;
+
+ if (header->flags & F_H_FILTER)
+ {
+ header->filter = get_be32(p);p+=4;
+ }
+
+ header->mode=get_be32(p);p+=4;
+
+ if (header->flags & F_STDIN) /* do not use mode from stdin compression */
+ header->mode = 0;
+
+ header->mtime_low = header->mode=get_be32(p);p+=4;
+
+ if (header->version >= 0x0940)
+ {
+ header->mtime_high = get_be32(p);p+=4;
+ }
+ if (header->version < 0x0120)
+ {
+ if (header->mtime_low == 0xffffffff)
+ header->mtime_low = 0;
+ header->mtime_high = 0;
+ }
+
+ l =*p++;
+ if (l > 0) {
+ char name[255+1];
+ if (memcpy(name,p,l) != l)
+ name[l] = 0;
+
+ }
+
+ header->header_checksum = get_be32(p);
+ adler32 = lzo_adler32(adler32,q,p-q);
+ checksum = (header->flags & F_H_CRC32) ? crc32 : adler32;
+
+ if(checksum !=header->header_checksum)
+ {
+ return 0;
+ }
+
+ p+=4;
+
+ if(lzo_get_method(header)!=0)
+ {
+ return 0;
+ }
+
+ /* skip extra field [not used yet] */
+ if (header->flags & F_H_EXTRA_FIELD)
+ {
+ header->extra_field_len = get_be32(p);p+=4;
+ for (k = 0; k < header->extra_field_len; k++)
+ p++;
+ checksum = (header->flags & F_H_CRC32) ? crc32 : adler32;
+ header->extra_field_checksum = get_be32(p);
+
+ if (header->extra_field_checksum != checksum)
+ return 3;
+ }
+
+ return (p-q)+start_offset+9;
+}
+
+int get_lzop_offset(unsigned char* pdata,unsigned int size,int start_offset)
+{
+ unsigned int offset = start_offset;
+ int value;
+
+ if(pdata ==0 )
+ return 0;
+
+ for(;offset < size - 4;offset++)
+ {
+ if(*(unsigned int*)(pdata+offset)== 0x4f5a4c89)
+ {
+ return offset;
+ }
+ }
+
+ return 0;
+}
+
+int lzop_decode_kernel(unsigned char* image ,unsigned int size,krninfo* krn)
+{
+ int ret;
+ unsigned int data_offset;
+ unsigned int compress_size;
+ int lzop_offs =0;
+ int block_size = BLOCK_SIZE;
+
+ header_t header;
+ lzop_offs = get_lzop_offset(image,size,0x800);
+ while(lzop_offs)
+ {
+ data_offset = get_lzopdata_offset(image,size,lzop_offs,&header);
+ if(data_offset)
+ {
+ krn->vmlinuz_size = (size - data_offset)*2;//assume
+
+#ifdef _WIN32
+ krn->vmlinuzbuffer = (unsigned char*)VirtualAlloc(0,krn->vmlinuz_size,MEM_COMMIT,PAGE_READWRITE);
+#else
+ krn->vmlinuzbuffer = (unsigned char*)mmap(0,krn->vmlinuz_size,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS ,0,0);
+#endif
+ if(krn->vmlinuzbuffer)
+ {
+ memset(krn->vmlinuzbuffer,0,krn->vmlinuz_size);
+ alloc_mem(0, MAX_COMPRESSED_SIZE(block_size), 0);
+ krn->vmlinuz_size = lzo_decompress(image,data_offset,&header,krn->vmlinuzbuffer);
+
+ if(krn->vmlinuz_size == 0)
+ {
+ free_mem();
+#ifdef _WIN32
+ VirtualFree(krn->vmlinuzbuffer,krn->vmlinuz_size,MEM_RELEASE);
+#else
+ munmap(krn->vmlinuzbuffer,krn->vmlinuz_size);
+#endif
+
+ krn->vmlinuz_size = 0;
+ return 0;
+ }
+ }
+ free_mem();
+ if(is_vmlinuz(krn->vmlinuzbuffer,krn->vmlinuz_size))
+ {
+ krn->kernel_offs = lzop_offs;
+ return 1;
+ }
+ }
+
+ lzop_offs = get_lzop_offset(image,size,lzop_offs+4);
+ }
+
+
+ return 0;
+}
+
+int load_bootimg(const char* path)
+{
+ int size;
+ FILE* fd ;
+ krninfo krn;
+ boot_img_hdr* hdr;
+ unsigned char* image;
+ int vmlinuz_offs =0;
+ int ramdisk_offs =0;
+ unsigned int compress_size;
+ char pathbuffer[260]={0};
+
+ fd = fopen(path,"rb");
+ if(fd ==0) return 0;
+ fseek(fd,0,SEEK_END);
+ size = ftell(fd);
+
+ image = (unsigned char*)malloc(size);
+ if(image ==0)
+ {
+ fclose(fd);
+ return 0;
+ }
+
+ fseek(fd,0,SEEK_SET);
+ fread(image,1,size,fd);
+ fclose(fd);
+
+ if(is_zimage(image,size))
+ {
+ printf("looks like zImage\n");
+ goto zimg;
+ }
+
+ if(!is_android_bootimg(image,size))
+ {
+ printf("not an Android boot.img\n");
+ free(image);
+ return 0;
+ }
+
+ hdr = (boot_img_hdr*)image;
+ if(strlen(hdr->cmdline))
+ {
+ printf("%s\n\n",hdr->cmdline);
+ }
+
+ memset(&krn,0,sizeof(krninfo));
+
+zimg:
+ if(_strstr_(image+0xa00,size-0xa00,"Linux version"))
+ {
+ //uncompressed
+ vmlinuz_offs = 0xa00;
+ krn.type = UNCOMPRESS;
+ printf("kenerl compress method: none\n");
+
+ ramdisk_offs = get_ramdisk_offset(image,size);
+ if(ramdisk_offs)
+ {
+ krn.vmlinuz_size = ramdisk_offs-vmlinuz_offs;
+ }
+
+#ifdef _WIN32
+ krn.vmlinuzbuffer = (unsigned char*)VirtualAlloc(0,krn.vmlinuz_size,MEM_COMMIT,PAGE_READWRITE);
+#else
+ krn.vmlinuzbuffer = (unsigned char*)mmap(0,krn.vmlinuz_size,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS ,0,0);
+#endif
+ if(krn.vmlinuzbuffer)
+ {
+ memcpy(krn.vmlinuzbuffer,image+vmlinuz_offs,krn.vmlinuz_size);
+ }
+ }
+ else
+ {
+ if(gzip_decode_kernel(image,size,&krn))
+ {
+ krn.type = GZ;
+ printf("kenerl compress method: gz\n");
+ }
+ else if(lzop_decode_kernel(image,size,&krn))
+ {
+ krn.type = LZO;
+ printf("kenerl compress method: lzo\n");
+ }
+ else
+ {
+ krn.type = UNKNOW;
+ printf("not found packed vmlinuz or unknow compress method\n");
+ }
+ }
+
+ show_version(krn.vmlinuzbuffer,krn.vmlinuz_size);
+ PathRemoveFileSpec(path);
+
+ if(g_save_kernel)
+ {
+#ifdef _WIN32
+ sprintf(pathbuffer,"%s\\vmlinuz",path);
+#else
+ sprintf(pathbuffer,"%s/vmlinuz",path);
+#endif
+ dump(krn.vmlinuzbuffer,krn.vmlinuz_size,pathbuffer);
+ if(krn.type)
+ printf("vmlinuz dump ok\n\n");
+#ifdef _WIN32
+ sprintf(pathbuffer,"%s\\ramdisk",path);
+#else
+ sprintf(pathbuffer,"%s/ramdisk",path);
+#endif
+ ramdisk_offs = get_ramdisk_offset(image,size);
+ if(ramdisk_offs)
+ {
+ compress_size = ramdisk_offs?size-ramdisk_offs:0;
+ decode_ramdisk(image,size,ramdisk_offs,compress_size,&krn);
+ if(strncmp(krn.ramdiskbuffer,"070701",6) == 0)
+ {
+ dump(krn.ramdiskbuffer,krn.ramdisk_size,pathbuffer);
+ printf("ramdisk dump ok\n\n");
+ }
+ else
+ {
+ printf("have no ramdisk \n\n");
+ }
+ }
+ }
+ if( g_save_symbol)
+ {
+ extract_symbol(path,&krn);
+ }
+
+ freeimg(&krn);
+ free(image);
+ return 1;
+}
+
+
+void usage()
+{
+ printf("Android boot.img analyzer 1.3\n");
+ printf("usage: image path option [...]\n");
+ printf("/f save ioctl symbol\n");
+ printf("/e save vmlinuz and ramdisk from image\n");
+ printf("/s save symbols as idc script format\n");
+
+
+}
+int main(int argc, char* argv[])
+{
+ int i;
+ const char* p = 0;
+ char path[260]={0};
+
+ if(argc < 2 )
+ {
+ usage();
+ return 0;
+ }
+
+ for (i = 1; i < argc; i++ )
+ {
+ p = argv[i];
+
+ if (*p == '/' || *p == '-' )
+ {
+ p++;
+
+ switch (toupper(*p))
+ {
+ case 'E':
+ case 'e':
+ g_save_kernel = 1;
+ break;
+ case 'S':
+ case 's':
+ g_save_symbol = 1;
+ break;
+ case 'F':
+ case 'f':
+ g_save_ioctl_func = 1;
+ break;
+ default:
+ usage();
+ return 0;
+ }
+ }
+ }
+
+ for ( i = 1; i < argc; i ++)
+ {
+ p = argv[i];
+ if (*p == '/' || *p == '-') // skip option
+ continue;
+#ifdef _WIN32
+ GetFullPathName(p, 260, path, 0);
+#else
+ realpath(p,path);
+#endif
+ }
+
+ return load_bootimg(path);
+}
diff --git a/bootunpack.h b/bootunpack.h
new file mode 100644
index 0000000..c0cf4b3
--- /dev/null
+++ b/bootunpack.h
@@ -0,0 +1,83 @@
+#ifndef __BOOTUNPACK_H__
+#define __BOOTUNPACK_H__
+
+/*
+ kallsyms varible declare sequence as follows:
+ if sequence is confuse ,can't get the correct value;
+
+ kallsyms_addresses[]
+ int kallsyms_nums
+ kallsyms_markers[]
+ kallsyms_token_table[0x100];
+ kallsyms_token_index[]
+
+*/
+
+#define BOOT_MAGIC_SIZE 8
+#define BOOT_NAME_SIZE 16
+#define BOOT_ARGS_SIZE 512
+
+#define DEFAULT_KERNEL_BASE 0xc0008000
+#define SEMC_KERNEL_BASE 0x80008000
+#define COOLPAD_KERNEL_BASE 0xc0008180
+
+#define KERNEL_VARIBLE_ALIGN(x) ((((unsigned int)x)+0xf)&0xfffffff0)
+
+enum compress
+{
+ UNKNOW,
+ UNCOMPRESS,
+ GZ,
+ BZ2,
+ LZMA,
+ LZO,
+ XZ,
+ TAR,
+};
+
+typedef struct _boot_img_hdr
+{
+ unsigned char magic[BOOT_MAGIC_SIZE];
+ unsigned kernel_size;
+ unsigned kernel_addr;
+ unsigned ramdisk_size;
+ unsigned ramdisk_addr;
+ unsigned second_size;
+ unsigned second_addr;
+ unsigned tags_addr;
+ unsigned page_size;
+ unsigned unused[2];
+ unsigned char name[BOOT_NAME_SIZE] ;
+ unsigned char cmdline[BOOT_ARGS_SIZE];
+ unsigned id[8];//timestamp
+}boot_img_hdr;
+
+
+typedef struct _krninfo
+{
+ unsigned char* vmlinuzbuffer;
+ unsigned int vmlinuz_size;
+ unsigned char* ramdiskbuffer;
+ unsigned int ramdisk_size;
+ ////////////////////////
+ unsigned int kernel_base;
+ unsigned int* kallsyms_addresses;
+ unsigned int kallsyms_num_syms_offs;
+ unsigned int kallsyms_num_syms;
+ unsigned int* kallsyms_markers;
+ unsigned short* kallsyms_token_index;
+ unsigned char* kallsyms_token_table;
+ unsigned char* kallsyms_names;
+ /////////////////////////////
+ unsigned int type;
+ unsigned int kernel_offs;
+}krninfo;
+
+
+
+int get_gzip_offset(unsigned char* pdata,unsigned int size,int start_offs);
+int extract_symbol(const char* directory,krninfo* krn);
+
+
+
+#endif
\ No newline at end of file
diff --git a/bootunpack.sln b/bootunpack.sln
new file mode 100644
index 0000000..4784c54
--- /dev/null
+++ b/bootunpack.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bootunpack", "bootunpack.vcproj", "{846D9CE8-E6F6-4826-9BB8-69C1CCC9B7E3}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {846D9CE8-E6F6-4826-9BB8-69C1CCC9B7E3}.Debug|Win32.ActiveCfg = Debug|Win32
+ {846D9CE8-E6F6-4826-9BB8-69C1CCC9B7E3}.Debug|Win32.Build.0 = Debug|Win32
+ {846D9CE8-E6F6-4826-9BB8-69C1CCC9B7E3}.Release|Win32.ActiveCfg = Release|Win32
+ {846D9CE8-E6F6-4826-9BB8-69C1CCC9B7E3}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/bootunpack.vcproj b/bootunpack.vcproj
new file mode 100644
index 0000000..d6f1254
--- /dev/null
+++ b/bootunpack.vcproj
@@ -0,0 +1,221 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/kallsyms.c b/kallsyms.c
new file mode 100644
index 0000000..e30feb7
--- /dev/null
+++ b/kallsyms.c
@@ -0,0 +1,554 @@
+#include "bootunpack.h"
+#include "stdio.h"
+#include "math.h"
+#ifdef _WIN32
+#include "windows.h"
+#else
+#endif
+/*
+#include "../include/capstone.h"
+#include "../include/arm.h"
+
+int disasm(krninfo* krn)
+{
+ csh handle;
+ cs_insn *insn;
+ size_t count;
+
+
+ if (cs_open(CS_ARCH_ARM, CS_MODE_ARM, &handle) != CS_ERR_OK)
+ return -1;
+ cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
+ count = cs_disasm(handle, krn->vmlinuzbuffer, krn->vmlinuz_size, krn->kernel_base, 0, &insn);
+ if (count > 0) {
+ size_t j;
+ for (j = 0; j < count; j++)
+ {
+ printf("0x%I64x:\t%s\t\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
+ }
+
+ cs_free(insn, count);
+ } else
+ printf("ERROR: Failed to disassemble given code!\n");
+
+ cs_close(&handle);
+}*/
+
+//some you want hardcode kernel address
+extern int g_save_ioctl_func;
+FILE* fdevice_log = 0;
+
+static const char* used_symbol[] =
+{
+ "sys_call_table",
+ "ptmx_fops",
+ "prepare_kernel_cred",
+ "commit_creds",
+ "delayed_rsp_id",
+ "dev_attr_ro",
+ "sys_oabi_semop",
+ "perf_swevent_enabled",
+};
+
+static unsigned int kernel_base[]=
+{
+ 0xc0008000,
+ 0x80008000,
+ 0xc0008180,//coolpad
+ 0xc00081c0,//xiaomi
+};
+
+size_t _strncpy_(char* dst,const char* src,size_t max)
+{
+ int n = 0;
+ if(dst == 0 || src ==0 || max ==0 )
+ return n;
+
+ while(*dst++ = *src++)
+ n++;
+
+ return n;
+}
+
+unsigned int* get_kallsyms_addresses(krninfo* krn)
+{
+ int num = 0;
+ int offset =0;
+ int stext;
+ unsigned int kallsyms_addresses_offset = 0;
+ unsigned int addr;
+ unsigned char * pdata = krn->vmlinuzbuffer;
+ unsigned int highmark = krn->kernel_base>>24;
+ unsigned int next_addr = 0;
+
+ while(krn && kallsyms_addresses_offset < krn->vmlinuz_size-4)
+ {
+ addr = *(unsigned int*)(pdata+kallsyms_addresses_offset);
+ num = 0;
+
+ while(addr >= krn->kernel_base && ((addr >> 24)== highmark) && addr < krn->kernel_base+krn->vmlinuz_size)
+ {
+ if (addr == 0 || num > 0x4000)
+ {
+ stext = *(unsigned int*)(pdata+kallsyms_addresses_offset);
+ if(stext == krn->kernel_base )
+ {
+ printf("kernel base %.8x\n",krn->kernel_base);
+ printf("going on,kall_sym_address offset %x addr %x \n",kallsyms_addresses_offset,kallsyms_addresses_offset+krn->kernel_base);
+ krn->kallsyms_addresses = kallsyms_addresses_offset;
+ return krn->kallsyms_addresses;
+ }
+ else
+ {
+ next_addr = *(unsigned int*)(pdata+kallsyms_addresses_offset+4);
+ if(next_addr == stext && stext >= 0xc0008000)
+ krn->kernel_base = stext;
+ }
+ }
+ num++;
+ offset +=4;
+ addr = *(unsigned int*)(pdata+offset);
+ }
+
+ kallsyms_addresses_offset+=4;
+ offset = kallsyms_addresses_offset;
+ }
+
+ return 0;
+}
+
+int get_kallsyms_nums(krninfo* krn)
+{
+ int num = 0;
+ unsigned int addr = 0;
+ unsigned char * pdata = krn->vmlinuzbuffer;
+ unsigned int highmark = krn->kernel_base>>24;
+ unsigned int offset = krn->kallsyms_addresses;
+
+ if(krn && krn->kallsyms_addresses)
+ {
+ addr = *(unsigned int*)(pdata+offset);
+ num = 0;
+
+ while(addr >= krn->kernel_base && ((addr >> 24)== highmark|| (addr >> 24)== highmark+1) && offset < krn->vmlinuz_size -4)
+ {
+ if (addr == 0 )
+ {
+ break;
+ }
+ num++;
+ offset +=4;
+ addr = *(unsigned int*)(pdata+offset);
+ }
+ }
+
+ //max 4 dwords
+ if(abs(addr-num)<=0x20)
+ {
+ num=addr;
+ printf("good,get kall_sym_nums 0x%x offset 0x%x \n",num,offset);
+ }
+ else
+ {
+ offset +=4;
+ addr = *(unsigned int*)(pdata+offset);
+ if(abs(addr-num)<=0x20)
+ {
+ num=addr;
+ printf("good,get kall_sym_nums 0x%x offset 0x%x \n",num,offset);
+ }
+ else
+ {
+ offset +=4;
+ addr = *(unsigned int*)(pdata+offset);
+ if(abs(addr-num)<=0x20)
+ {
+ num=addr;
+ printf("good,get kall_sym_nums 0x%x offset 0x%x \n",num,offset);
+ }
+ else
+ {
+ offset +=4;
+ addr = *(unsigned int*)(pdata+offset);
+ if(abs(addr-num)<=0x20)
+ {
+ num=addr;
+ printf("good,get kall_sym_nums 0x%x offset 0x%x \n",num,offset);
+ }
+ }
+ }
+ }
+
+ krn->kallsyms_num_syms_offs = offset+4;
+
+ return krn->kallsyms_num_syms = num;
+}
+
+unsigned char* get_kallsyms_markers(krninfo* krn)
+{
+ int i ;
+ unsigned char * pdata;
+
+ if(krn && krn->kallsyms_num_syms_offs)
+ {
+ krn->kallsyms_names = KERNEL_VARIBLE_ALIGN(krn->kallsyms_num_syms_offs+4);
+ pdata = krn->vmlinuzbuffer+(int)krn->kallsyms_names;
+
+ i =0;
+ krn->kallsyms_markers = krn->kallsyms_names;
+ while(*pdata && pdata < krn->vmlinuzbuffer+krn->vmlinuz_size-1)// && *pdata <= 0x58)
+ {
+#ifndef __GNUC__
+ (unsigned char*)krn->kallsyms_markers+=*pdata+1;
+#else
+ krn->kallsyms_markers= (unsigned char*)krn->kallsyms_markers+*pdata+1;
+#endif
+ pdata+=*pdata+1;
+ i++;
+ }
+
+ if(i == krn->kallsyms_num_syms)
+ {
+ krn->kallsyms_markers = KERNEL_VARIBLE_ALIGN(krn->kallsyms_markers);
+ printf("great,found kallsyms_markers offset 0x%x addr 0x%x \n",krn->kallsyms_markers,krn->kernel_base+(int)krn->kallsyms_markers);
+ return krn->kallsyms_markers;
+ }
+ }
+
+ return 0;
+}
+
+unsigned char* get_kallsyms_token_table(krninfo* krn)
+{
+ unsigned char * pdata;
+ unsigned int offs = 0;
+ unsigned int next =0;
+
+ if(krn && krn->kallsyms_markers)
+ {
+ krn->kallsyms_token_table = krn->kallsyms_markers;
+ pdata = krn->vmlinuzbuffer;
+
+ while(krn->kallsyms_token_table < krn->vmlinuz_size-8)
+ {
+ offs = *(unsigned int*)(pdata+(int)krn->kallsyms_token_table);
+ next = *(unsigned int*)(pdata+(int)krn->kallsyms_token_table+4);
+
+ if((next ==0 && next < offs))
+ {
+ krn->kallsyms_token_table = KERNEL_VARIBLE_ALIGN(krn->kallsyms_token_table+4);
+ printf("wonderful,found kallsyms_token_table offset 0x%x addr 0x%x \n",krn->kallsyms_token_table,krn->kernel_base+(int)krn->kallsyms_token_table);
+ return krn->kallsyms_token_table;
+ }
+ else if( abs(next-offs) > 0x10000)
+ {
+ krn->kallsyms_token_table = KERNEL_VARIBLE_ALIGN(krn->kallsyms_token_table+4);
+ printf("wonderful,found kallsyms_token_table offset 0x%x addr 0x%x \n",krn->kallsyms_token_table,krn->kernel_base+(int)krn->kallsyms_token_table);
+ return krn->kallsyms_token_table;
+ }
+#ifndef __GNUC__
+ (unsigned char*)krn->kallsyms_token_table +=4;
+#else
+ krn->kallsyms_token_table = (unsigned char*)krn->kallsyms_token_table + 4;
+#endif
+ }
+ }
+
+ return 0;
+}
+
+int get_kallsyms_token_index(krninfo* krn)
+{
+ int i;
+ int n;
+ unsigned char * pdata;
+ char token_buffer[260];
+
+ if(krn && krn->kallsyms_token_table)
+ {
+ krn->kallsyms_token_index = krn->kallsyms_token_table;
+ pdata = krn->vmlinuzbuffer+(int)krn->kallsyms_token_index;
+ //skip align
+ if(*(unsigned int*)pdata == 0)
+ {
+ krn->kallsyms_token_index = KERNEL_VARIBLE_ALIGN(krn->kallsyms_token_index+4);
+ }
+
+ pdata = krn->vmlinuzbuffer+(int)krn->kallsyms_token_index;
+
+ for(i = 0;i<= 0x100;i++)
+ {
+ n = _strncpy_(token_buffer,pdata,260);
+ if(n == 0 && i == 0x100)
+ {
+ krn->kallsyms_token_index = KERNEL_VARIBLE_ALIGN(krn->kallsyms_token_index);
+ printf("excellent,found kallsyms_token_index offset 0x%x addr 0x%x \n",krn->kallsyms_token_index,krn->kernel_base+(int)krn->kallsyms_token_index);
+ return krn->kallsyms_token_index;
+ }
+#ifndef __GNUC__
+ (unsigned char*)krn->kallsyms_token_index += n+1;
+#else
+ krn->kallsyms_token_index = (unsigned char*)krn->kallsyms_token_index + n+1;
+#endif
+ pdata += n+1;
+ }
+ }
+
+ return 0;
+}
+
+
+int get_symbol(krninfo* krn)
+{
+ int i;
+
+ printf("search kallsyms_address ...\n");
+ for(i = 0; i kernel_base = kernel_base[i];
+
+ if(get_kallsyms_addresses(krn))
+ {
+ return get_kallsyms_nums(krn) &&
+ get_kallsyms_markers(krn) && get_kallsyms_token_table(krn) &&
+ get_kallsyms_token_index(krn);
+ }
+ }
+
+ return 0;
+}
+
+char kallsyms_get_symbol_type(krninfo* krn,unsigned int off)
+{
+ int names = krn->kallsyms_names[off + 1];
+ int token = krn->kallsyms_token_index[names];
+ return krn->kallsyms_token_table[token];
+}
+
+unsigned long get_symbol_pos(krninfo* krn,unsigned long addr, unsigned long *symbolsize,unsigned long *offset)
+{
+ unsigned long symbol_start = 0, symbol_end = 0;
+ unsigned long i, low, high, mid;
+
+
+ /* Do a binary search on the sorted kallsyms_addresses array. */
+ low = 0;
+ high = krn->kallsyms_num_syms;
+
+ while (high - low > 1) {
+ mid = low + (high - low) / 2;
+ if (krn->kallsyms_addresses[mid] <= addr)
+ low = mid;
+ else
+ high = mid;
+ }
+
+ /*
+ * Search for the first aliased symbol. Aliased
+ * symbols are symbols with the same address.
+ */
+ while (low && krn->kallsyms_addresses[low-1] == krn->kallsyms_addresses[low])
+ --low;
+
+ symbol_start = krn->kallsyms_addresses[low];
+
+ /* Search for next non-aliased symbol. */
+ for (i = low + 1; i < krn->kallsyms_num_syms; i++) {
+ if (krn->kallsyms_addresses[i] > symbol_start) {
+ symbol_end =krn->kallsyms_addresses[i];
+ break;
+ }
+ }
+
+ if (symbolsize)
+ *symbolsize = symbol_end - symbol_start;
+ if (offset)
+ *offset = addr - symbol_start;
+
+ return low;
+}
+
+unsigned int kallsyms_expand_symbol(krninfo* krn,unsigned int off, char *result)
+{
+ int len, skipped_first = 0;
+ const unsigned char *tptr, *data;
+
+ /* Get the compressed symbol length from the first symbol byte. */
+ data = &krn->kallsyms_names[off];
+ len = *data;
+ data++;
+
+ /*
+ * Update the offset to return the offset for the next symbol on
+ * the compressed stream.
+ */
+ off += len + 1;
+
+ /*
+ * For every byte on the compressed symbol data, copy the table
+ * entry for that byte.
+ */
+ while (len) {
+ tptr = &krn->kallsyms_token_table[krn->kallsyms_token_index[*data]];
+ data++;
+ len--;
+
+ while (*tptr) {
+ if (skipped_first) {
+ *result = *tptr;
+ result++;
+ } else
+ skipped_first = 1;
+ tptr++;
+ }
+ }
+
+ *result = '\0';
+
+ /* Return to offset to the next symbol. */
+ return off;
+}
+
+void krn_varible_fix(krninfo* krn)
+{
+ if(krn)
+ {
+ krn->kallsyms_addresses=krn->vmlinuzbuffer+(int)krn->kallsyms_addresses;
+ krn->kallsyms_names=krn->vmlinuzbuffer+(int)krn->kallsyms_names;
+ krn->kallsyms_markers=krn->vmlinuzbuffer+(int)krn->kallsyms_markers;
+ krn->kallsyms_token_table=krn->vmlinuzbuffer+(int)krn->kallsyms_token_table;
+ krn->kallsyms_token_index=krn->vmlinuzbuffer+(int)krn->kallsyms_token_index;
+ }
+}
+
+static unsigned int get_symbol_offset(krninfo* krn,unsigned long pos)
+{
+ const unsigned char *name;
+ unsigned int i;
+ int offs;
+
+ offs = krn->kallsyms_markers[pos >> 8];
+
+ name = &krn->kallsyms_names[offs];
+
+ for (i = 0; i < (pos & 0xFF); i++)
+ name = name + (*name) + 1;
+
+ return name - krn->kallsyms_names;
+}
+
+int is_show_symbol(const char* symbol)
+{
+ int i;
+
+ for(i = 0;i < sizeof(used_symbol)/sizeof(int) ;i++)
+ {
+ if(strcmp(used_symbol[i],symbol) ==0 )
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+char *__strrev(char *str)
+{
+ char *p1, *p2;
+
+ if (! str || ! *str)
+ return str;
+ for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2)
+ {
+ *p1 ^= *p2;
+ *p2 ^= *p1;
+ *p1 ^= *p2;
+ }
+ return str;
+}
+
+int is_ioctl_sym(const char* symbol)
+{
+ int i;
+ char sym[512];
+
+ strncpy(sym,symbol,512);
+ __strrev(sym);
+
+ if(strncmp(sym,"ltcoi_",6) == 0)
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+int extract_kallsyms(const char* directory,krninfo* krn)
+{
+ FILE* fidc;
+ unsigned long i;
+ unsigned int pos,offs;
+ char pathbuffer[260] ={0};
+ char namebuf[128];
+#ifdef _WIN32
+ sprintf(pathbuffer,"%s\\kallsyms.idc",directory);
+#else
+ sprintf(pathbuffer,"%s/kallsyms.idc",directory);
+#endif
+ fidc = fopen(pathbuffer,"wb");
+ if(fidc == 0) return 0;
+ fputs("#include \n",fidc);
+ fputs("static main(){\n",fidc);
+
+ for (i = 0; i < krn->kallsyms_num_syms; i++)
+ {
+ pos = get_symbol_pos(krn,krn->kallsyms_addresses[i],0,0);//pos =i*4;
+ offs = get_symbol_offset(krn,pos);
+ kallsyms_expand_symbol(krn,offs, namebuf);
+ if(is_show_symbol(namebuf))
+ {
+ printf("%.8x %c %s\n",krn->kallsyms_addresses[i],kallsyms_get_symbol_type(krn,offs),namebuf);
+ }
+ if(fdevice_log && is_ioctl_sym(namebuf))
+ {
+ memset(pathbuffer,0,260);
+ sprintf(pathbuffer,"%.8x %c %s\r\n",krn->kallsyms_addresses[i],kallsyms_get_symbol_type(krn,offs),namebuf);
+ fputs(pathbuffer,fdevice_log);
+ }
+ //printf("%.8x %c %s\n",krn->kallsyms_addresses[i],kallsyms_get_symbol_type(krn,offs),namebuf);
+ sprintf(pathbuffer," MakeNameEx(0x%.8x, \"%s\", 0);\n",krn->kallsyms_addresses[i],namebuf);
+ fputs(pathbuffer,fidc);
+ memset(namebuf,0,128);
+ }
+ fputs("}\n",fidc);
+ fflush(fidc);
+ fclose(fidc);
+
+ return 1;
+}
+
+int extract_symbol(const char* directory,krninfo* krn)
+{
+ char path[260];
+
+ if(g_save_ioctl_func)
+ {
+ sprintf(path,"%s/device_ioctl.txt",directory);
+ fdevice_log = fopen(path,"wb");
+ }
+
+ if(get_symbol(krn))
+ {
+ printf("found all the kallsyms varibles succeed\n");
+ krn_varible_fix(krn);
+ extract_kallsyms(directory,krn);
+ return 1;
+ }
+
+ printf("analyse kernel failed,exit\n");
+
+ if(fdevice_log)
+ fclose(fdevice_log);
+
+ return 0;
+}
diff --git a/lzo.h b/lzo.h
new file mode 100644
index 0000000..5c63e2c
--- /dev/null
+++ b/lzo.h
@@ -0,0 +1,209 @@
+#ifndef __LZO_H__
+#define __LZO_H__
+/*
+ * LZO Public Kernel Interface
+ * A mini subset of the LZO real-time data compression library
+ *
+ * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer
+ *
+ * The full LZO package can be found at:
+ * http://www.oberhumer.com/opensource/lzo/
+ *
+ * Changed for kernel use by:
+ * Nitin Gupta
+ * Richard Purdie
+ */
+#define LZO_UINT32_C(c) (c##ULL)
+#define LZO1X_MEM_COMPRESS (16384 * sizeof(unsigned char *))
+#define LZO1X_1_MEM_COMPRESS LZO1X_MEM_COMPRESS
+
+#define lzo1x_worst_compress(x) ((x) + ((x) / 16) + 64 + 3)
+
+/* This requires 'workmem' of size LZO1X_1_MEM_COMPRESS */
+int lzo1x_1_compress(const unsigned char *src, int src_len,
+ unsigned char *dst, int *dst_len, void *wrkmem);
+
+/* safe decompression with overrun testing */
+int lzo1x_decompress_safe(const unsigned char *src, int src_len,
+ unsigned char *dst, int *dst_len);
+
+
+/*
+ * Return values (< 0 = Error)
+ */
+#define LZO_E_OK 0
+#define LZO_E_ERROR (-1)
+#define LZO_E_OUT_OF_MEMORY (-2)
+#define LZO_E_NOT_COMPRESSIBLE (-3)
+#define LZO_E_INPUT_OVERRUN (-4)
+#define LZO_E_OUTPUT_OVERRUN (-5)
+#define LZO_E_LOOKBEHIND_OVERRUN (-6)
+#define LZO_E_EOF_NOT_FOUND (-7)
+#define LZO_E_INPUT_NOT_CONSUMED (-8)
+#define LZO_E_NOT_YET_IMPLEMENTED (-9)
+
+
+#define get_unaligned(ptr) (*(ptr))
+#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
+
+
+#define lzo_init() __lzo_init_v2(0x1060,(int)sizeof(short),(int)sizeof(int),\
+ (int)sizeof(long),(int)sizeof(unsigned int),(int)sizeof(unsigned int),\
+ (int)sizeof(char*),(int)sizeof(char *),(int)sizeof(void*),\
+ (int)sizeof(void*))
+
+int __lzo_init_v2(unsigned,int,int,int,int,int,int,int,int,int);
+
+#define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b))
+#define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b))
+
+/* header flags */
+#define F_ADLER32_D 0x00000001L
+#define F_ADLER32_C 0x00000002L
+#define F_STDIN 0x00000004L
+#define F_STDOUT 0x00000008L
+#define F_NAME_DEFAULT 0x00000010L
+#define F_DOSISH 0x00000020L
+#define F_H_EXTRA_FIELD 0x00000040L
+#define F_H_GMTDIFF 0x00000080L
+#define F_CRC32_D 0x00000100L
+#define F_CRC32_C 0x00000200L
+#define F_MULTIPART 0x00000400L
+#define F_H_FILTER 0x00000800L
+#define F_H_CRC32 0x00001000L
+#define F_H_PATH 0x00002000L
+#define F_MASK 0x00003FFFL
+
+/* operating system & file system that created the file [mostly unused] */
+#define F_OS_FAT 0x00000000L /* DOS, OS2, Win95 */
+#define F_OS_AMIGA 0x01000000L
+#define F_OS_VMS 0x02000000L
+#define F_OS_UNIX 0x03000000L
+#define F_OS_VM_CMS 0x04000000L
+#define F_OS_ATARI 0x05000000L
+#define F_OS_OS2 0x06000000L /* OS2 */
+#define F_OS_MAC9 0x07000000L
+#define F_OS_Z_SYSTEM 0x08000000L
+#define F_OS_CPM 0x09000000L
+#define F_OS_TOPS20 0x0a000000L
+#define F_OS_NTFS 0x0b000000L /* Win NT/2000/XP */
+#define F_OS_QDOS 0x0c000000L
+#define F_OS_ACORN 0x0d000000L
+#define F_OS_VFAT 0x0e000000L /* Win32 */
+#define F_OS_MFS 0x0f000000L
+#define F_OS_BEOS 0x10000000L
+#define F_OS_TANDEM 0x11000000L
+#define F_OS_SHIFT 24
+#define F_OS_MASK 0xff000000L
+
+/* character set for file name encoding [mostly unused] */
+#define F_CS_NATIVE 0x00000000L
+#define F_CS_LATIN1 0x00100000L
+#define F_CS_DOS 0x00200000L
+#define F_CS_WIN32 0x00300000L
+#define F_CS_WIN16 0x00400000L
+#define F_CS_UTF8 0x00500000L /* filename is UTF-8 encoded */
+#define F_CS_SHIFT 20
+#define F_CS_MASK 0x00f00000L
+
+/* these bits must be zero */
+#define F_RESERVED ((F_MASK | F_OS_MASK | F_CS_MASK) ^ 0xffffffffL)
+#define LZOP_VERSION 0x1030
+#define ADLER32_INIT_VALUE 1
+#define CRC32_INIT_VALUE 0
+
+#if defined(ACC_OS_DOS16) && !defined(ACC_ARCH_I086PM)
+# define BLOCK_SIZE (128*1024l)
+#else
+# define BLOCK_SIZE (256*1024l)
+#endif
+#define MAX_BLOCK_SIZE (64*1024l*1024l) /* DO NOT CHANGE */
+/* LZO may expand uncompressible data by a small amount */
+#define MAX_COMPRESSED_SIZE(x) ((x) + (x) / 16 + 64 + 3)
+
+/* align a char pointer on a boundary that is a multiple of `size' */
+unsigned short __lzo_align_gap(const void* _ptr, unsigned int _size);
+#define LZO_PTR_ALIGN_UP(_ptr,_size) \
+ ((_ptr) + (unsigned int) __lzo_align_gap((const void*)(_ptr),( unsigned int)(_size)))
+
+/* deprecated - only for backward compatibility */
+#define LZO_ALIGN(_ptr,_size) LZO_PTR_ALIGN_UP(_ptr,_size)
+
+enum {
+ M_LZO1X_1 = 1,
+ M_LZO1X_1_15 = 2,
+ M_LZO1X_999 = 3,
+ M_NRV1A = 0x1a,
+ M_NRV1B = 0x1b,
+ M_NRV2A = 0x2a,
+ M_NRV2B = 0x2b,
+ M_NRV2D = 0x2d,
+ M_ZLIB = 128,
+
+ M_UNUSED
+};
+
+#pragma pack(1)
+typedef struct
+{
+ unsigned short version;
+ unsigned short lib_version;
+ unsigned short version_needed_to_extract;
+ unsigned char method;
+ unsigned char level;
+ unsigned int flags;
+ unsigned int filter;
+ unsigned int mode;
+ unsigned int mtime_low;
+ unsigned int mtime_high;
+ unsigned int header_checksum;
+
+ unsigned int extra_field_len;
+ unsigned int extra_field_checksum;
+
+ /* info */
+ const char *method_name;
+
+ char name[255+1];
+}header_t;
+
+typedef struct
+{
+ /* public */
+ unsigned char* mb_mem;
+ unsigned int mb_size;
+ /* private */
+ unsigned char* mb_mem_alloc;
+ unsigned int mb_size_alloc;
+ unsigned int mb_align;
+ /* the following fields are not yet used but may prove useful for
+ * adding new algorithms */
+ unsigned int mb_flags;
+ unsigned int mb_id;
+ unsigned int mb_len;
+ unsigned int mb_adler32;
+ unsigned int mb_crc32;
+}mblock_t;
+
+union lzo_config_check_union {
+ unsigned int a[2];
+ unsigned char b[2*LZO_MAX(8,sizeof(unsigned int))];
+#ifndef __GNUC__
+ unsigned __int64 c[2];
+#else
+ unsigned long long c[2];
+#endif
+};
+
+#pragma pack()
+
+void free_mem();
+unsigned short get_be16(const unsigned char *b);
+unsigned int get_be32(const unsigned char *b);
+unsigned int lzo_crc32(unsigned int c, const unsigned char* buf, unsigned int len);
+int alloc_mem(unsigned int s1, unsigned int s2, unsigned int w);
+int get_lzo_dataoffset(unsigned char* pdata,int offset,int size);
+int lzo_decompress(unsigned char* pdata, int offset,const header_t *h,unsigned char* pbuffer);
+
+
+#endif
diff --git a/lzo1x_decompress.c b/lzo1x_decompress.c
new file mode 100644
index 0000000..25b56a5
--- /dev/null
+++ b/lzo1x_decompress.c
@@ -0,0 +1,497 @@
+/*
+ * LZO1X Decompressor from MiniLZO
+ *
+ * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer
+ *
+ * The full LZO package can be found at:
+ * http://www.oberhumer.com/opensource/lzo/
+ *
+ * Changed for kernel use by:
+ * Nitin Gupta
+ * Richard Purdie
+ */
+#include "stdio.h"
+#include "stdlib.h"
+#include "string.h"
+#include "lzo.h"
+
+#define M2_MAX_OFFSET 0x800
+#define ALIGN_SIZE 4096
+
+#define HAVE_IP(x, ip_end, ip) ((size_t)(ip_end - ip) < (x))
+#define HAVE_OP(x, op_end, op) ((size_t)(op_end - op) < (x))
+#define HAVE_LB(m_pos, out, op) (m_pos < out || m_pos >= op)
+
+#define COPY4(dst, src) \
+ put_unaligned(get_unaligned((const unsigned int *)(src)), (unsigned int *)(dst))
+
+static const unsigned int block_size = BLOCK_SIZE;
+static mblock_t blocks[2];
+static mblock_t wrkmem;
+
+const unsigned char lzop_magic[9] =
+{ 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a };
+
+#define LZO_BASE 65521u /* largest prime smaller than 65536 */
+#define LZO_NMAX 5552
+
+#define LZO_DO1(buf,i) s1 += buf[i]; s2 += s1
+#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1)
+#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2)
+#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4)
+#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8)
+
+unsigned short get_unaligned_le16(const unsigned char *p)
+{
+ return p[0] | p[1] << 8;
+}
+
+unsigned short get_be16(const unsigned char *b)
+{
+ unsigned short v;
+
+ v = (unsigned short ) b[1] << 0;
+ v |= (unsigned short ) b[0] << 8;
+ return v;
+}
+
+unsigned int get_be32(const unsigned char *b)
+{
+ unsigned int v;
+
+ v = (unsigned int) b[3] << 0;
+ v |= (unsigned int) b[2] << 8;
+ v |= (unsigned int) b[1] << 16;
+ v |= (unsigned int) b[0] << 24;
+ return v;
+}
+
+static void do_init(mblock_t* m, unsigned int size, unsigned int align)
+{
+ memset(m,0,sizeof(*m));
+ m->mb_size = size;
+ m->mb_align = (align > 1) ? align : 1;
+
+ m->mb_adler32 = ADLER32_INIT_VALUE;
+ m->mb_crc32 = CRC32_INIT_VALUE;
+}
+
+void mb_free(mblock_t* m)
+{
+ free(m->mb_mem_alloc);
+ memset(m,0,sizeof(*m));
+}
+
+
+int mb_alloc(mblock_t* m, unsigned int size, unsigned int align)
+{
+ do_init(m,size,align);
+ if (m->mb_size == 0)
+ return 1;
+
+ m->mb_size_alloc = m->mb_size + m->mb_align - 1;
+ m->mb_mem_alloc = (unsigned char *) malloc(m->mb_size_alloc);
+ if (m->mb_mem_alloc == NULL)
+ return 0;
+ memset(m->mb_mem_alloc, 0, m->mb_size_alloc);
+
+ m->mb_mem = m->mb_mem_alloc;
+
+ return 1;
+}
+
+void free_mem()
+{
+ mb_free(&wrkmem);
+ mb_free(&blocks[1]);
+ mb_free(&blocks[0]);
+}
+
+int alloc_mem(unsigned int s1, unsigned int s2, unsigned int w)
+{
+ int r = 1;
+
+ r &= mb_alloc(&blocks[0], s1, ALIGN_SIZE);
+ r &= mb_alloc(&blocks[1], s2, ALIGN_SIZE);
+ r &= mb_alloc(&wrkmem, w, ALIGN_SIZE);
+ if (!r)
+ free_mem();
+ return r;
+}
+
+unsigned int lzo_adler32(unsigned int adler, unsigned char* buf, int len)
+{
+ unsigned int s1 = adler & 0xffff;
+ unsigned int s2 = (adler >> 16) & 0xffff;
+ unsigned k;
+
+ if (buf == 0)
+ return 1;
+
+ while (len > 0)
+ {
+ k = len < LZO_NMAX ? (unsigned short) len : LZO_NMAX;
+ len -= k;
+ if (k >= 16) do
+ {
+ LZO_DO16(buf,0);
+ buf += 16;
+ k -= 16;
+ } while (k >= 16);
+ if (k != 0) do
+ {
+ s1 += *buf++;
+ s2 += s1;
+ } while (--k > 0);
+ s1 %= LZO_BASE;
+ s2 %= LZO_BASE;
+ }
+ return (s2 << 16) | s1;
+}
+
+int lzo1x_decompress_safe(const unsigned char *in, int in_len,
+ unsigned char *out, int *out_len)
+{
+ const unsigned char * const ip_end = in + in_len;
+ unsigned char * const op_end = out + *out_len;
+ const unsigned char *ip = in, *m_pos;
+ unsigned char *op = out;
+ size_t t;
+
+ *out_len = 0;
+
+ if (*ip > 17) {
+ t = *ip++ - 17;
+ if (t < 4)
+ goto match_next;
+ if (HAVE_OP(t, op_end, op))
+ goto output_overrun;
+ if (HAVE_IP(t + 1, ip_end, ip))
+ goto input_overrun;
+ do {
+ *op++ = *ip++;
+ } while (--t > 0);
+ goto first_literal_run;
+ }
+
+ while ((ip < ip_end)) {
+ t = *ip++;
+ if (t >= 16)
+ goto match;
+ if (t == 0) {
+ if (HAVE_IP(1, ip_end, ip))
+ goto input_overrun;
+ while (*ip == 0) {
+ t += 255;
+ ip++;
+ if (HAVE_IP(1, ip_end, ip))
+ goto input_overrun;
+ }
+ t += 15 + *ip++;
+ }
+ if (HAVE_OP(t + 3, op_end, op))
+ goto output_overrun;
+ if (HAVE_IP(t + 4, ip_end, ip))
+ goto input_overrun;
+
+ COPY4(op, ip);
+ op += 4;
+ ip += 4;
+ if (--t > 0) {
+ if (t >= 4) {
+ do {
+ COPY4(op, ip);
+ op += 4;
+ ip += 4;
+ t -= 4;
+ } while (t >= 4);
+ if (t > 0) {
+ do {
+ *op++ = *ip++;
+ } while (--t > 0);
+ }
+ } else {
+ do {
+ *op++ = *ip++;
+ } while (--t > 0);
+ }
+ }
+
+first_literal_run:
+ t = *ip++;
+ if (t >= 16)
+ goto match;
+ m_pos = op - (1 + M2_MAX_OFFSET);
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+
+ if (HAVE_LB(m_pos, out, op))
+ goto lookbehind_overrun;
+
+ if (HAVE_OP(3, op_end, op))
+ goto output_overrun;
+ *op++ = *m_pos++;
+ *op++ = *m_pos++;
+ *op++ = *m_pos;
+
+ goto match_done;
+
+ do {
+match:
+ if (t >= 64) {
+ m_pos = op - 1;
+ m_pos -= (t >> 2) & 7;
+ m_pos -= *ip++ << 3;
+ t = (t >> 5) - 1;
+ if (HAVE_LB(m_pos, out, op))
+ goto lookbehind_overrun;
+ if (HAVE_OP(t + 3 - 1, op_end, op))
+ goto output_overrun;
+ goto copy_match;
+ } else if (t >= 32) {
+ t &= 31;
+ if (t == 0) {
+ if (HAVE_IP(1, ip_end, ip))
+ goto input_overrun;
+ while (*ip == 0) {
+ t += 255;
+ ip++;
+ if (HAVE_IP(1, ip_end, ip))
+ goto input_overrun;
+ }
+ t += 31 + *ip++;
+ }
+ m_pos = op - 1;
+ m_pos -= get_unaligned_le16(ip) >> 2;
+ ip += 2;
+ } else if (t >= 16) {
+ m_pos = op;
+ m_pos -= (t & 8) << 11;
+
+ t &= 7;
+ if (t == 0) {
+ if (HAVE_IP(1, ip_end, ip))
+ goto input_overrun;
+ while (*ip == 0) {
+ t += 255;
+ ip++;
+ if (HAVE_IP(1, ip_end, ip))
+ goto input_overrun;
+ }
+ t += 7 + *ip++;
+ }
+ m_pos -= get_unaligned_le16(ip) >> 2;
+ ip += 2;
+ if (m_pos == op)
+ goto eof_found;
+ m_pos -= 0x4000;
+ } else {
+ m_pos = op - 1;
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+
+ if (HAVE_LB(m_pos, out, op))
+ goto lookbehind_overrun;
+ if (HAVE_OP(2, op_end, op))
+ goto output_overrun;
+
+ *op++ = *m_pos++;
+ *op++ = *m_pos;
+ goto match_done;
+ }
+
+ if (HAVE_LB(m_pos, out, op))
+ goto lookbehind_overrun;
+ if (HAVE_OP(t + 3 - 1, op_end, op))
+ goto output_overrun;
+
+ if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) {
+ COPY4(op, m_pos);
+ op += 4;
+ m_pos += 4;
+ t -= 4 - (3 - 1);
+ do {
+ COPY4(op, m_pos);
+ op += 4;
+ m_pos += 4;
+ t -= 4;
+ } while (t >= 4);
+ if (t > 0)
+ do {
+ *op++ = *m_pos++;
+ } while (--t > 0);
+ } else {
+copy_match:
+ *op++ = *m_pos++;
+ *op++ = *m_pos++;
+ do {
+ *op++ = *m_pos++;
+ } while (--t > 0);
+ }
+match_done:
+ t = ip[-2] & 3;
+ if (t == 0)
+ break;
+match_next:
+ if (HAVE_OP(t, op_end, op))
+ goto output_overrun;
+ if (HAVE_IP(t + 1, ip_end, ip))
+ goto input_overrun;
+
+ *op++ = *ip++;
+ if (t > 1) {
+ *op++ = *ip++;
+ if (t > 2)
+ *op++ = *ip++;
+ }
+
+ t = *ip++;
+ } while (ip < ip_end);
+ }
+
+ *out_len = op - out;
+ return LZO_E_EOF_NOT_FOUND;
+
+eof_found:
+ *out_len = op - out;
+ return (ip == ip_end ? LZO_E_OK :
+ (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
+input_overrun:
+ *out_len = op - out;
+ return LZO_E_INPUT_OVERRUN;
+
+output_overrun:
+ *out_len = op - out;
+ return LZO_E_OUTPUT_OVERRUN;
+
+lookbehind_overrun:
+ *out_len = op - out;
+ return LZO_E_LOOKBEHIND_OVERRUN;
+}
+
+int lzo_decompress(unsigned char* pdata, int offset,const header_t *h,unsigned char* pbuffer)
+{
+ int r;
+ unsigned int src_len, dst_len;
+ unsigned int c_adler32 = ADLER32_INIT_VALUE, d_adler32 = ADLER32_INIT_VALUE;
+ unsigned int c_crc32 = CRC32_INIT_VALUE, d_crc32 = CRC32_INIT_VALUE;
+ unsigned int ok = 0;
+ mblock_t * const block = &blocks[1];
+ unsigned char* b1;
+ unsigned char* const b2 = block->mb_mem;
+ unsigned int in_processed = 0;
+ unsigned int out_processed = 0;
+ unsigned char* p = pdata+offset;
+ unsigned char* dst = pbuffer;
+
+ for (;;)
+ {
+ /* read uncompressed block size */
+ dst_len = get_be32(p);p+=4;
+
+ /* exit if last block */
+ if (dst_len == 0)
+ break;
+
+ /* error if split file */
+ if (dst_len == 0xffffffffUL)
+ {
+ /* should not happen - not yet implemented */
+ printf("this file is a split file\n");
+ ok = 0; break;
+ }
+
+ if (dst_len > MAX_BLOCK_SIZE)
+ {
+ printf("file corrupted\n");
+ ok = 0; break;
+ }
+
+ /* read compressed block size */
+ src_len =get_be32(p);p+=4;
+ if (src_len <= 0 || src_len > dst_len || dst_len > BLOCK_SIZE || dst_len > block_size)
+ {
+ printf("file corrupted\n");
+ ok = 0; break;
+ }
+
+ /* read checksum of uncompressed block */
+ if (h->flags & F_ADLER32_D)
+ {
+ d_adler32 = get_be32(p);p+=4;
+ }
+ if (h->flags & F_CRC32_D)
+ {
+ d_crc32 = get_be32(p);p+=4;
+ }
+
+ /* read checksum of compressed block */
+ if (h->flags & F_ADLER32_C)
+ {
+ if (src_len < dst_len)
+ {
+ c_adler32 = get_be32(p);p+=4;
+ }
+ else
+ {
+ c_adler32 = d_adler32;
+ }
+ }
+ if (h->flags & F_CRC32_C)
+ {
+ if (src_len < dst_len)
+ {
+ c_crc32 = get_be32(p);p+=4;
+ }
+ else
+ {
+ c_crc32 = d_crc32;
+ }
+ }
+
+ /* read the block */
+ b1 = block->mb_mem + block->mb_size - src_len;
+ memcpy(b1,p, src_len);p+=src_len;
+ in_processed += src_len;
+
+ /* verify checksum of compressed block */
+ if ( (h->flags & F_ADLER32_C))
+ {
+ unsigned int c;
+ c = lzo_adler32(ADLER32_INIT_VALUE,b1,src_len);
+ if (c != c_adler32)
+ {
+ printf("Checksum error ( file corrupted)\n");
+ ok = 0; break;
+ }
+ }
+ if ((h->flags & F_CRC32_C))
+ {
+ unsigned int c;
+ c = lzo_crc32(CRC32_INIT_VALUE,b1,src_len);
+ if (c != c_crc32)
+ {
+ printf("Checksum error (file corrupted)\n");
+ ok = 0; break;
+ }
+ }
+
+ if (src_len < dst_len)
+ {
+ unsigned int d = dst_len;
+
+ r = lzo1x_decompress_safe(b1,src_len,b2,&d);
+
+ if (r != LZO_E_OK || dst_len != d )
+ {
+ printf("file corrupted\n");
+ ok = 0; break;
+ }
+ memcpy(dst,b2, d);
+ dst += d;
+ ok += d;
+ }
+ }
+
+ return ok;
+}
\ No newline at end of file
diff --git a/lzo_crc.c b/lzo_crc.c
new file mode 100644
index 0000000..a5f678c
--- /dev/null
+++ b/lzo_crc.c
@@ -0,0 +1,153 @@
+/* lzo_crc.c -- crc checksum for the the LZO library
+
+ This file is part of the LZO real-time data compression library.
+
+ Copyright (C) 1996-2014 Markus Franz Xaver Johannes Oberhumer
+ All Rights Reserved.
+
+ The LZO library 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.
+
+ The LZO 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the LZO library; see the file COPYING.
+ If not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Markus F.X.J. Oberhumer
+
+ http://www.oberhumer.com/opensource/lzo/
+ */
+
+
+#include "lzo.h"
+
+
+/***********************************************************************
+// crc32 checksum
+// adapted from free code by Mark Adler
+// see http://www.zlib.org/
+************************************************************************/
+
+static unsigned int lzo_crc32_table[256] = {
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+ 0x2d02ef8dL
+};
+
+
+unsigned int* lzo_get_crc32_table(void)
+{
+ return lzo_crc32_table;
+}
+
+
+#if 1
+#define LZO_DO1(buf,i) \
+ crc = table[((unsigned)crc ^ buf[i]) & 0xff] ^ (crc >> 8)
+#else
+#define LZO_DO1(buf,i) \
+ crc = table[(unsigned char)((unsigned char)crc ^ buf[i])] ^ (crc >> 8)
+#endif
+#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1)
+#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2)
+#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4)
+#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8)
+
+
+unsigned int lzo_crc32(unsigned int c, const unsigned char* buf, unsigned int len)
+{
+ unsigned int crc;
+#undef table
+#if 1
+# define table lzo_crc32_table
+#else
+ const unsigned int * table = lzo_crc32_table;
+#endif
+
+ if (buf == 0)
+ return 0;
+
+ crc = (c & LZO_UINT32_C(0xffffffff)) ^ LZO_UINT32_C(0xffffffff);
+ if (len >= 16) do
+ {
+ LZO_DO16(buf,0);
+ buf += 16;
+ len -= 16;
+ } while (len >= 16);
+ if (len != 0) do
+ {
+ LZO_DO1(buf,0);
+ buf += 1;
+ len -= 1;
+ } while (len > 0);
+
+ return crc ^ LZO_UINT32_C(0xffffffff);
+#undef table
+}
+
+#undef LZO_DO1
+#undef LZO_DO2
+#undef LZO_DO4
+#undef LZO_DO8
+#undef LZO_DO16
+
+
+/*
+vi:ts=4:et
+*/
diff --git a/zconf.h b/zconf.h
new file mode 100644
index 0000000..03a9431
--- /dev/null
+++ b/zconf.h
@@ -0,0 +1,332 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+# define deflateInit_ z_deflateInit_
+# define deflate z_deflate
+# define deflateEnd z_deflateEnd
+# define inflateInit_ z_inflateInit_
+# define inflate z_inflate
+# define inflateEnd z_inflateEnd
+# define deflateInit2_ z_deflateInit2_
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateCopy z_deflateCopy
+# define deflateReset z_deflateReset
+# define deflateParams z_deflateParams
+# define deflateBound z_deflateBound
+# define deflatePrime z_deflatePrime
+# define inflateInit2_ z_inflateInit2_
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateSync z_inflateSync
+# define inflateSyncPoint z_inflateSyncPoint
+# define inflateCopy z_inflateCopy
+# define inflateReset z_inflateReset
+# define inflateBack z_inflateBack
+# define inflateBackEnd z_inflateBackEnd
+# define compress z_compress
+# define compress2 z_compress2
+# define compressBound z_compressBound
+# define uncompress z_uncompress
+# define adler32 z_adler32
+# define crc32 z_crc32
+# define get_crc_table z_get_crc_table
+# define zError z_zError
+
+# define alloc_func z_alloc_func
+# define free_func z_free_func
+# define in_func z_in_func
+# define out_func z_out_func
+# define Byte z_Byte
+# define uInt z_uInt
+# define uLong z_uLong
+# define Bytef z_Bytef
+# define charf z_charf
+# define intf z_intf
+# define uIntf z_uIntf
+# define uLongf z_uLongf
+# define voidpf z_voidpf
+# define voidp z_voidp
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+# define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+# define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+# ifndef WIN32
+# define WIN32
+# endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+# ifndef SYS16BIT
+# define SYS16BIT
+# endif
+# endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+# ifndef STDC
+# define STDC
+# endif
+# if __STDC_VERSION__ >= 199901L
+# ifndef STDC99
+# define STDC99
+# endif
+# endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+# define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
+# define STDC
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const /* note: need a more gentle solution here */
+# endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+# define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+# if defined(M_I86SM) || defined(M_I86MM)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+# if (defined(__SMALL__) || defined(__MEDIUM__))
+ /* Turbo C small or medium model */
+# define SMALL_MEDIUM
+# ifdef __BORLANDC__
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+ /* If building or using zlib as a DLL, define ZLIB_DLL.
+ * This is not mandatory, but it offers a little performance increase.
+ */
+# ifdef ZLIB_DLL
+# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+# ifdef ZLIB_INTERNAL
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+# endif
+# endif /* ZLIB_DLL */
+ /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+ * define ZLIB_WINAPI.
+ * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+ */
+# ifdef ZLIB_WINAPI
+# ifdef FAR
+# undef FAR
+# endif
+# include
+ /* No need for _export, use ZLIB.DEF instead. */
+ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+# define ZEXPORT WINAPI
+# ifdef WIN32
+# define ZEXPORTVA WINAPIV
+# else
+# define ZEXPORTVA FAR CDECL
+# endif
+# endif
+#endif
+
+#if defined (__BEOS__)
+# ifdef ZLIB_DLL
+# ifdef ZLIB_INTERNAL
+# define ZEXPORT __declspec(dllexport)
+# define ZEXPORTVA __declspec(dllexport)
+# else
+# define ZEXPORT __declspec(dllimport)
+# define ZEXPORTVA __declspec(dllimport)
+# endif
+# endif
+#endif
+
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+# define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void const *voidpc;
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte const *voidpc;
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */
+# include /* for off_t */
+# include /* for SEEK_* and off_t */
+# ifdef VMS
+# include /* for off_t */
+# endif
+# define z_off_t off_t
+#endif
+#ifndef SEEK_SET
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+#if defined(__OS400__)
+# define NO_vsnprintf
+#endif
+
+#if defined(__MVS__)
+# define NO_vsnprintf
+# ifdef FAR
+# undef FAR
+# endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+# pragma map(deflateInit_,"DEIN")
+# pragma map(deflateInit2_,"DEIN2")
+# pragma map(deflateEnd,"DEEND")
+# pragma map(deflateBound,"DEBND")
+# pragma map(inflateInit_,"ININ")
+# pragma map(inflateInit2_,"ININ2")
+# pragma map(inflateEnd,"INEND")
+# pragma map(inflateSync,"INSY")
+# pragma map(inflateSetDictionary,"INSEDI")
+# pragma map(compressBound,"CMBND")
+# pragma map(inflate_table,"INTABL")
+# pragma map(inflate_fast,"INFA")
+# pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/zlib.h b/zlib.h
new file mode 100644
index 0000000..0228179
--- /dev/null
+++ b/zlib.h
@@ -0,0 +1,1357 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.2.3, July 18th, 2005
+
+ Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
+ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.2.3"
+#define ZLIB_VERNUM 0x1230
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed
+ data. This version of the library supports only one compression method
+ (deflation) but other algorithms will be added later and will have the same
+ stream interface.
+
+ Compression can be done in a single step if the buffers are large
+ enough (for example if an input file is mmap'ed), or can be done by
+ repeated calls of the compression function. In the latter case, the
+ application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The compressed data format used by default by the in-memory functions is
+ the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+ around a deflate stream, which is itself documented in RFC 1951.
+
+ The library also supports reading and writing files in gzip (.gz) format
+ with an interface similar to that of stdio using the functions that start
+ with "gz". The gzip format is different from the zlib format. gzip is a
+ gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+ This library can optionally read and write gzip streams in memory as well.
+
+ The zlib format was designed to be compact and fast for use in memory
+ and on communications channels. The gzip format was designed for single-
+ file compression on file systems, has a larger header than zlib to maintain
+ directory information, and uses a different, slower check method than zlib.
+
+ The library does not install any signal handler. The decoder checks
+ the consistency of the compressed data, so the library should never
+ crash even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void (*free_func) OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total nb of input bytes read so far */
+
+ Bytef *next_out; /* next output byte should be put there */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total nb of bytes output so far */
+
+ char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: binary or text */
+ uLong adler; /* adler32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+ gzip header information passed to and from zlib routines. See RFC 1952
+ for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+ int text; /* true if compressed data believed to be text */
+ uLong time; /* modification time */
+ int xflags; /* extra flags (not used when writing a gzip file) */
+ int os; /* operating system */
+ Bytef *extra; /* pointer to extra field or Z_NULL if none */
+ uInt extra_len; /* extra field length (valid if extra != Z_NULL) */
+ uInt extra_max; /* space at extra (only when reading header) */
+ Bytef *name; /* pointer to zero-terminated file name or Z_NULL */
+ uInt name_max; /* space at name (only when reading header) */
+ Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */
+ uInt comm_max; /* space at comment (only when reading header) */
+ int hcrc; /* true if there was or will be a header crc */
+ int done; /* true when done reading gzip header (not used
+ when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
+ The application must update next_in and avail_in when avail_in has
+ dropped to zero. It must update next_out and avail_out when avail_out
+ has dropped to zero. The application must initialize zalloc, zfree and
+ opaque before calling the init function. All other fields are set by the
+ compression library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ If zlib is used in a multi-threaded application, zalloc and zfree must be
+ thread safe.
+
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this
+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+ pointers returned by zalloc for objects of exactly 65536 bytes *must*
+ have their offset normalized to zero. The default allocation function
+ provided by this library ensures this (see zutil.c). To reduce memory
+ requirements and avoid any allocation of 64K objects, at the expense of
+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or
+ progress reports. After compression, total_in holds the total size of
+ the uncompressed data and may be saved for use in the decompressor
+ (particularly if the decompressor wants to decompress everything in
+ a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+#define Z_BLOCK 5
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_RLE 3
+#define Z_FIXED 4
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY 0
+#define Z_TEXT 1
+#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field (though see inflate()) */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+ /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is
+ not compatible with the zlib.h header file used by the application.
+ This check is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller.
+ If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+ use default allocation functions.
+
+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at
+ all (the input data is simply copied a block at a time).
+ Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+ compression (currently equivalent to level 6).
+
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+ with the version assumed by the caller (ZLIB_VERSION).
+ msg is set to null if there is no error message. deflateInit does not
+ perform any compression: this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+ deflate compresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce some
+ output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. deflate performs one or both of the
+ following actions:
+
+ - Compress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in and avail_in are updated and
+ processing will resume at this point for the next call of deflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
+ Forcing flush frequently degrades the compression ratio, so this parameter
+ should be set only when necessary (in interactive applications).
+ Some output may be provided even if flush is not set.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating avail_in or avail_out accordingly; avail_out
+ should never be zero before the call. The application can consume the
+ compressed output when it wants, for example when the output buffer is full
+ (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+ and with zero avail_out, it must be called again after making room in the
+ output buffer because there might be more output pending.
+
+ Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+ decide how much data to accumualte before producing output, in order to
+ maximize compression.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+ flushed to the output buffer and the output is aligned on a byte boundary, so
+ that the decompressor can get all input data available so far. (In particular
+ avail_in is zero after the call if enough output space has been provided
+ before the call.) Flushing may degrade compression for some compression
+ algorithms and so it should be used only when necessary.
+
+ If flush is set to Z_FULL_FLUSH, all output is flushed as with
+ Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+ restart from this point if previous compressed data has been damaged or if
+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+ compression.
+
+ If deflate returns with avail_out == 0, this function must be called again
+ with the same value of the flush parameter and more output space (updated
+ avail_out), until the flush is complete (deflate returns with non-zero
+ avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+ avail_out is greater than six to avoid repeated flush markers due to
+ avail_out == 0 on return.
+
+ If the parameter flush is set to Z_FINISH, pending input is processed,
+ pending output is flushed and deflate returns with Z_STREAM_END if there
+ was enough output space; if deflate returns with Z_OK, this function must be
+ called again with Z_FINISH and more output space (updated avail_out) but no
+ more input data, until it returns with Z_STREAM_END or an error. After
+ deflate has returned Z_STREAM_END, the only possible operations on the
+ stream are deflateReset or deflateEnd.
+
+ Z_FINISH can be used immediately after deflateInit if all the compression
+ is to be done in a single step. In this case, avail_out must be at least
+ the value returned by deflateBound (see below). If deflate does not return
+ Z_STREAM_END, then it must be called again as described above.
+
+ deflate() sets strm->adler to the adler32 checksum of all input read
+ so far (that is, total_in bytes).
+
+ deflate() may update strm->data_type if it can make a good guess about
+ the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered
+ binary. This field is only for information purposes and does not affect
+ the compression algorithm in any manner.
+
+ deflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if all input has been
+ consumed and all output has been produced (only when flush is set to
+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+ if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
+ (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not
+ fatal, and deflate() can be called again with more input and more output
+ space to continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+ prematurely (some input or output was discarded). In the error case,
+ msg may be set but then points to a static string (which must not be
+ deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+ Initializes the internal stream state for decompression. The fields
+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+ the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
+ value depends on the compression method), inflateInit determines the
+ compression method from the zlib header and allocates all data structures
+ accordingly; otherwise the allocation will be deferred to the first call of
+ inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+ use default allocation functions.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller. msg is set to null if there is no error
+ message. inflateInit does not perform any decompression apart from reading
+ the zlib header if present: this will be done by inflate(). (So next_in and
+ avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+ inflate decompresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce
+ some output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. inflate performs one or both of the
+ following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in is updated and processing
+ will resume at this point for the next call of inflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there
+ is no more input data or no more space in the output buffer (see below
+ about the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating the next_* and avail_* values accordingly.
+ The application can consume the uncompressed output when it wants, for
+ example when the output buffer is full (avail_out == 0), or after each
+ call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+ must be called again after making room in the output buffer because there
+ might be more output pending.
+
+ The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH,
+ Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much
+ output as possible to the output buffer. Z_BLOCK requests that inflate() stop
+ if and when it gets to the next deflate block boundary. When decoding the
+ zlib or gzip format, this will cause inflate() to return immediately after
+ the header and before the first block. When doing a raw inflate, inflate()
+ will go ahead and process the first block, and will return when it gets to
+ the end of that block, or when it runs out of data.
+
+ The Z_BLOCK option assists in appending to or combining deflate streams.
+ Also to assist in this, on return inflate() will set strm->data_type to the
+ number of unused bits in the last byte taken from strm->next_in, plus 64
+ if inflate() is currently decoding the last block in the deflate stream,
+ plus 128 if inflate() returned immediately after decoding an end-of-block
+ code or decoding the complete header up to just before the first byte of the
+ deflate stream. The end-of-block will not be indicated until all of the
+ uncompressed data from that block has been written to strm->next_out. The
+ number of unused bits may in general be greater than seven, except when
+ bit 7 of data_type is set, in which case the number of unused bits will be
+ less than eight.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step
+ (a single call of inflate), the parameter flush should be set to
+ Z_FINISH. In this case all pending input is processed and all pending
+ output is flushed; avail_out must be large enough to hold all the
+ uncompressed data. (The size of the uncompressed data may have been saved
+ by the compressor for this purpose.) The next operation on this stream must
+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+ is never required, but can be used to inform inflate that a faster approach
+ may be used for the single inflate() call.
+
+ In this implementation, inflate() always flushes as much output as
+ possible to the output buffer, and always uses the faster approach on the
+ first call. So the only effect of the flush parameter in this implementation
+ is on the return value of inflate(), as noted below, or when it returns early
+ because Z_BLOCK is used.
+
+ If a preset dictionary is needed after this call (see inflateSetDictionary
+ below), inflate sets strm->adler to the adler32 checksum of the dictionary
+ chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+ strm->adler to the adler32 checksum of all output produced so far (that is,
+ total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+ below. At the end of the stream, inflate() checks that its computed adler32
+ checksum is equal to that saved by the compressor and returns Z_STREAM_END
+ only if the checksum is correct.
+
+ inflate() will decompress and check either zlib-wrapped or gzip-wrapped
+ deflate data. The header type is detected automatically. Any information
+ contained in the gzip header is not retained, so applications that need that
+ information should instead use raw inflate, see inflateInit2() below, or
+ inflateBack() and perform their own processing of the gzip header and
+ trailer.
+
+ inflate() returns Z_OK if some progress has been made (more input processed
+ or more output produced), Z_STREAM_END if the end of the compressed data has
+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+ corrupted (input stream not conforming to the zlib format or incorrect check
+ value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+ if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory,
+ Z_BUF_ERROR if no progress is possible or if there was not enough room in the
+ output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and
+ inflate() can be called again with more input and more output space to
+ continue decompressing. If Z_DATA_ERROR is returned, the application may then
+ call inflateSync() to look for a good compression block if a partial recovery
+ of the data is desired.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+ was inconsistent. In the error case, msg may be set but then points to a
+ static string (which must not be deallocated).
+*/
+
+ /* Advanced functions */
+
+/*
+ The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy));
+
+ This is another version of deflateInit with more compression options. The
+ fields next_in, zalloc, zfree and opaque must be initialized before by
+ the caller.
+
+ The method parameter is the compression method. It must be Z_DEFLATED in
+ this version of the library.
+
+ The windowBits parameter is the base two logarithm of the window size
+ (the size of the history buffer). It should be in the range 8..15 for this
+ version of the library. Larger values of this parameter result in better
+ compression at the expense of memory usage. The default value is 15 if
+ deflateInit is used instead.
+
+ windowBits can also be -8..-15 for raw deflate. In this case, -windowBits
+ determines the window size. deflate() will then generate raw deflate data
+ with no zlib header or trailer, and will not compute an adler32 check value.
+
+ windowBits can also be greater than 15 for optional gzip encoding. Add
+ 16 to windowBits to write a simple gzip header and trailer around the
+ compressed data instead of a zlib wrapper. The gzip header will have no
+ file name, no extra data, no comment, no modification time (set to zero),
+ no header crc, and the operating system will be set to 255 (unknown). If a
+ gzip stream is being written, strm->adler is a crc32 instead of an adler32.
+
+ The memLevel parameter specifies how much memory should be allocated
+ for the internal compression state. memLevel=1 uses minimum memory but
+ is slow and reduces compression ratio; memLevel=9 uses maximum memory
+ for optimal speed. The default value is 8. See zconf.h for total memory
+ usage as a function of windowBits and memLevel.
+
+ The strategy parameter is used to tune the compression algorithm. Use the
+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+ filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match), or Z_RLE to limit match distances to one (run-length
+ encoding). Filtered data consists mostly of small values with a somewhat
+ random distribution. In this case, the compression algorithm is tuned to
+ compress them better. The effect of Z_FILTERED is to force more Huffman
+ coding and less string matching; it is somewhat intermediate between
+ Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as
+ Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy
+ parameter only affects the compression ratio but not the correctness of the
+ compressed output even if it is not set appropriately. Z_FIXED prevents the
+ use of dynamic Huffman codes, allowing for a simpler decoder for special
+ applications.
+
+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
+ method). msg is set to null if there is no error message. deflateInit2 does
+ not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the compression dictionary from the given byte sequence
+ without producing any compressed output. This function must be called
+ immediately after deflateInit, deflateInit2 or deflateReset, before any
+ call of deflate. The compressor and decompressor must use exactly the same
+ dictionary (see inflateSetDictionary).
+
+ The dictionary should consist of strings (byte sequences) that are likely
+ to be encountered later in the data to be compressed, with the most commonly
+ used strings preferably put towards the end of the dictionary. Using a
+ dictionary is most useful when the data to be compressed is short and can be
+ predicted with good accuracy; the data can then be compressed better than
+ with the default empty dictionary.
+
+ Depending on the size of the compression data structures selected by
+ deflateInit or deflateInit2, a part of the dictionary may in effect be
+ discarded, for example if the dictionary is larger than the window size in
+ deflate or deflate2. Thus the strings most likely to be useful should be
+ put at the end of the dictionary, not at the front. In addition, the
+ current implementation of deflate will use at most the window size minus
+ 262 bytes of the provided dictionary.
+
+ Upon return of this function, strm->adler is set to the adler32 value
+ of the dictionary; the decompressor may later use this value to determine
+ which dictionary has been used by the compressor. (The adler32 value
+ applies to the whole dictionary even if only a subset of the dictionary is
+ actually used by the compressor.) If a raw deflate was requested, then the
+ adler32 value is not computed and strm->adler is not set.
+
+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent (for example if deflate has already been called for this stream
+ or if the compression method is bsort). deflateSetDictionary does not
+ perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when several compression strategies will be
+ tried, for example when there are several ways of pre-processing the input
+ data with a filter. The streams that will be discarded should then be freed
+ by calling deflateEnd. Note that deflateCopy duplicates the internal
+ compression state which can be quite large, so this strategy is slow and
+ can consume lots of memory.
+
+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to deflateEnd followed by deflateInit,
+ but does not free and reallocate all the internal compression state.
+ The stream will keep the same compression level and any other attributes
+ that may have been set by deflateInit2.
+
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+ int level,
+ int strategy));
+/*
+ Dynamically update the compression level and compression strategy. The
+ interpretation of level and strategy is as in deflateInit2. This can be
+ used to switch between compression and straight copy of the input data, or
+ to switch to a different kind of input data requiring a different
+ strategy. If the compression level is changed, the input available so far
+ is compressed with the old level (and may be flushed); the new level will
+ take effect only at the next call of deflate().
+
+ Before the call of deflateParams, the stream state must be set as for
+ a call of deflate(), since the currently available input may have to
+ be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+ if strm->avail_out was zero.
+*/
+
+ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
+ int good_length,
+ int max_lazy,
+ int nice_length,
+ int max_chain));
+/*
+ Fine tune deflate's internal compression parameters. This should only be
+ used by someone who understands the algorithm used by zlib's deflate for
+ searching for the best matching string, and even then only by the most
+ fanatic optimizer trying to squeeze out the last compressed bit for their
+ specific input data. Read the deflate.c source code for the meaning of the
+ max_lazy, good_length, nice_length, and max_chain parameters.
+
+ deflateTune() can be called after deflateInit() or deflateInit2(), and
+ returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
+ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
+ uLong sourceLen));
+/*
+ deflateBound() returns an upper bound on the compressed size after
+ deflation of sourceLen bytes. It must be called after deflateInit()
+ or deflateInit2(). This would be used to allocate an output buffer
+ for deflation in a single pass, and so would be called before deflate().
+*/
+
+ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
+/*
+ deflatePrime() inserts bits in the deflate output stream. The intent
+ is that this function is used to start off the deflate output with the
+ bits leftover from a previous deflate stream when appending to it. As such,
+ this function can only be used for raw deflate, and must be used before the
+ first deflate() call after a deflateInit2() or deflateReset(). bits must be
+ less than or equal to 16, and that many of the least significant bits of
+ value will be inserted in the output.
+
+ deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ deflateSetHeader() provides gzip header information for when a gzip
+ stream is requested by deflateInit2(). deflateSetHeader() may be called
+ after deflateInit2() or deflateReset() and before the first call of
+ deflate(). The text, time, os, extra field, name, and comment information
+ in the provided gz_header structure are written to the gzip header (xflag is
+ ignored -- the extra flags are set according to the compression level). The
+ caller must assure that, if not Z_NULL, name and comment are terminated with
+ a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+ available there. If hcrc is true, a gzip header crc is included. Note that
+ the current versions of the command-line version of gzip (up through version
+ 1.3.x) do not support header crc's, and will report that it is a "multi-part
+ gzip file" and give up.
+
+ If deflateSetHeader is not used, the default gzip header has text false,
+ the time set to zero, and os set to 255, with no extra, name, or comment
+ fields. The gzip header is returned to the default state by deflateReset().
+
+ deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+ int windowBits));
+
+ This is another version of inflateInit with an extra parameter. The
+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+ before by the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library. The default value is 15 if inflateInit is used
+ instead. windowBits must be greater than or equal to the windowBits value
+ provided to deflateInit2() while compressing, or it must be equal to 15 if
+ deflateInit2() was not used. If a compressed stream with a larger window
+ size is given as input, inflate() will return with the error code
+ Z_DATA_ERROR instead of trying to allocate a larger window.
+
+ windowBits can also be -8..-15 for raw inflate. In this case, -windowBits
+ determines the window size. inflate() will then process raw deflate data,
+ not looking for a zlib or gzip header, not generating a check value, and not
+ looking for any check values for comparison at the end of the stream. This
+ is for use with other formats that use the deflate compressed data format
+ such as zip. Those formats provide their own check values. If a custom
+ format is developed using the raw deflate format for compressed data, it is
+ recommended that a check value such as an adler32 or a crc32 be applied to
+ the uncompressed data as is done in the zlib, gzip, and zip formats. For
+ most applications, the zlib format should be used as is. Note that comments
+ above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+ windowBits can also be greater than 15 for optional gzip decoding. Add
+ 32 to windowBits to enable zlib and gzip decoding with automatic header
+ detection, or add 16 to decode only the gzip format (the zlib format will
+ return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is
+ a crc32 instead of an adler32.
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg
+ is set to null if there is no error message. inflateInit2 does not perform
+ any decompression apart from reading the zlib header if present: this will
+ be done by inflate(). (So next_in and avail_in may be modified, but next_out
+ and avail_out are unchanged.)
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the decompression dictionary from the given uncompressed byte
+ sequence. This function must be called immediately after a call of inflate,
+ if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
+ can be determined from the adler32 value returned by that call of inflate.
+ The compressor and decompressor must use exactly the same dictionary (see
+ deflateSetDictionary). For raw inflate, this function can be called
+ immediately after inflateInit2() or inflateReset() and before any call of
+ inflate() to set the dictionary. The application must insure that the
+ dictionary that was used for compression is provided.
+
+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+ expected one (incorrect adler32 value). inflateSetDictionary does not
+ perform any decompression: this will be done by subsequent calls of
+ inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+ Skips invalid compressed data until a full flush point (see above the
+ description of deflate with Z_FULL_FLUSH) can be found, or until all
+ available input is skipped. No output is provided.
+
+ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+ if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+ case, the application may save the current current value of total_in which
+ indicates where valid compressed data was found. In the error case, the
+ application may repeatedly call inflateSync, providing more input each time,
+ until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when randomly accessing a large stream. The
+ first pass through the stream can periodically record the inflate state,
+ allowing restarting inflate at those points when randomly accessing the
+ stream.
+
+ inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate all the internal decompression state.
+ The stream will keep attributes that may have been set by inflateInit2.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
+/*
+ This function inserts bits in the inflate input stream. The intent is
+ that this function is used to start inflating at a bit position in the
+ middle of a byte. The provided bits will be used before any bytes are used
+ from next_in. This function should only be used with raw inflate, and
+ should be used before the first inflate() call after inflateInit2() or
+ inflateReset(). bits must be less than or equal to 16, and that many of the
+ least significant bits of value will be inserted in the input.
+
+ inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ inflateGetHeader() requests that gzip header information be stored in the
+ provided gz_header structure. inflateGetHeader() may be called after
+ inflateInit2() or inflateReset(), and before the first call of inflate().
+ As inflate() processes the gzip stream, head->done is zero until the header
+ is completed, at which time head->done is set to one. If a zlib stream is
+ being decoded, then head->done is set to -1 to indicate that there will be
+ no gzip header information forthcoming. Note that Z_BLOCK can be used to
+ force inflate() to return immediately after header processing is complete
+ and before any actual data is decompressed.
+
+ The text, time, xflags, and os fields are filled in with the gzip header
+ contents. hcrc is set to true if there is a header CRC. (The header CRC
+ was valid if done is set to one.) If extra is not Z_NULL, then extra_max
+ contains the maximum number of bytes to write to extra. Once done is true,
+ extra_len contains the actual extra field length, and extra contains the
+ extra field, or that field truncated if extra_max is less than extra_len.
+ If name is not Z_NULL, then up to name_max characters are written there,
+ terminated with a zero unless the length is greater than name_max. If
+ comment is not Z_NULL, then up to comm_max characters are written there,
+ terminated with a zero unless the length is greater than comm_max. When
+ any of extra, name, or comment are not Z_NULL and the respective field is
+ not present in the header, then that field is set to Z_NULL to signal its
+ absence. This allows the use of deflateSetHeader() with the returned
+ structure to duplicate the header. However if those fields are set to
+ allocated memory, then the application will need to save those pointers
+ elsewhere so that they can be eventually freed.
+
+ If inflateGetHeader is not used, then the header information is simply
+ discarded. The header is always checked for validity, including the header
+ CRC if present. inflateReset() will reset the process to discard the header
+ information. The application would need to call inflateGetHeader() again to
+ retrieve the header from the next gzip stream.
+
+ inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
+ unsigned char FAR *window));
+
+ Initialize the internal stream state for decompression using inflateBack()
+ calls. The fields zalloc, zfree and opaque in strm must be initialized
+ before the call. If zalloc and zfree are Z_NULL, then the default library-
+ derived memory allocation routines are used. windowBits is the base two
+ logarithm of the window size, in the range 8..15. window is a caller
+ supplied buffer of that size. Except for special applications where it is
+ assured that deflate was used with small window sizes, windowBits must be 15
+ and a 32K byte window must be supplied to be able to decompress general
+ deflate streams.
+
+ See inflateBack() for the usage of these routines.
+
+ inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+ the paramaters are invalid, Z_MEM_ERROR if the internal state could not
+ be allocated, or Z_VERSION_ERROR if the version of the library does not
+ match the version of the header file.
+*/
+
+typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
+typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
+
+ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
+ in_func in, void FAR *in_desc,
+ out_func out, void FAR *out_desc));
+/*
+ inflateBack() does a raw inflate with a single call using a call-back
+ interface for input and output. This is more efficient than inflate() for
+ file i/o applications in that it avoids copying between the output and the
+ sliding window by simply making the window itself the output buffer. This
+ function trusts the application to not change the output buffer passed by
+ the output function, at least until inflateBack() returns.
+
+ inflateBackInit() must be called first to allocate the internal state
+ and to initialize the state with the user-provided window buffer.
+ inflateBack() may then be used multiple times to inflate a complete, raw
+ deflate stream with each call. inflateBackEnd() is then called to free
+ the allocated state.
+
+ A raw deflate stream is one with no zlib or gzip header or trailer.
+ This routine would normally be used in a utility that reads zip or gzip
+ files and writes out uncompressed files. The utility would decode the
+ header and process the trailer on its own, hence this routine expects
+ only the raw deflate stream to decompress. This is different from the
+ normal behavior of inflate(), which expects either a zlib or gzip header and
+ trailer around the deflate stream.
+
+ inflateBack() uses two subroutines supplied by the caller that are then
+ called by inflateBack() for input and output. inflateBack() calls those
+ routines until it reads a complete deflate stream and writes out all of the
+ uncompressed data, or until it encounters an error. The function's
+ parameters and return types are defined above in the in_func and out_func
+ typedefs. inflateBack() will call in(in_desc, &buf) which should return the
+ number of bytes of provided input, and a pointer to that input in buf. If
+ there is no input available, in() must return zero--buf is ignored in that
+ case--and inflateBack() will return a buffer error. inflateBack() will call
+ out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out()
+ should return zero on success, or non-zero on failure. If out() returns
+ non-zero, inflateBack() will return with an error. Neither in() nor out()
+ are permitted to change the contents of the window provided to
+ inflateBackInit(), which is also the buffer that out() uses to write from.
+ The length written by out() will be at most the window size. Any non-zero
+ amount of input may be provided by in().
+
+ For convenience, inflateBack() can be provided input on the first call by
+ setting strm->next_in and strm->avail_in. If that input is exhausted, then
+ in() will be called. Therefore strm->next_in must be initialized before
+ calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called
+ immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in
+ must also be initialized, and then if strm->avail_in is not zero, input will
+ initially be taken from strm->next_in[0 .. strm->avail_in - 1].
+
+ The in_desc and out_desc parameters of inflateBack() is passed as the
+ first parameter of in() and out() respectively when they are called. These
+ descriptors can be optionally used to pass any information that the caller-
+ supplied in() and out() functions need to do their job.
+
+ On return, inflateBack() will set strm->next_in and strm->avail_in to
+ pass back any unused input that was provided by the last in() call. The
+ return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+ if in() or out() returned an error, Z_DATA_ERROR if there was a format
+ error in the deflate stream (in which case strm->msg is set to indicate the
+ nature of the error), or Z_STREAM_ERROR if the stream was not properly
+ initialized. In the case of Z_BUF_ERROR, an input or output error can be
+ distinguished using strm->next_in which will be Z_NULL only if in() returned
+ an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to
+ out() returning non-zero. (in() will always be called before out(), so
+ strm->next_in is assured to be defined if out() returns non-zero.) Note
+ that inflateBack() cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
+/*
+ All memory allocated by inflateBackInit() is freed.
+
+ inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+ state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+/* Return flags indicating compile-time options.
+
+ Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+ 1.0: size of uInt
+ 3.2: size of uLong
+ 5.4: size of voidpf (pointer)
+ 7.6: size of z_off_t
+
+ Compiler, assembler, and debug options:
+ 8: DEBUG
+ 9: ASMV or ASMINF -- use ASM code
+ 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+ 11: 0 (reserved)
+
+ One-time table building (smaller code, but not thread-safe if true):
+ 12: BUILDFIXED -- build static block decoding tables when needed
+ 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+ 14,15: 0 (reserved)
+
+ Library content (indicates missing functionality):
+ 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+ deflate code when not needed)
+ 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+ and decode gzip streams (to avoid linking crc code)
+ 18-19: 0 (reserved)
+
+ Operation variations (changes in library functionality):
+ 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+ 21: FASTEST -- deflate algorithm with only one, lowest compression level
+ 22,23: 0 (reserved)
+
+ The sprintf variant used by gzprintf (zero is best):
+ 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+ 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+ 26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+ Remainder:
+ 27-31: 0 (reserved)
+ */
+
+
+ /* utility functions */
+
+/*
+ The following utility functions are implemented on top of the
+ basic stream-oriented functions. To simplify the interface, some
+ default options are assumed (compression level and memory usage,
+ standard memory allocation functions). The source code of these
+ utility functions can easily be modified if you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be at least the value returned
+ by compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed buffer.
+ This function can be used to compress a whole file at once if the
+ input file is mmap'ed.
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen,
+ int level));
+/*
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least the value returned by
+ compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
+/*
+ compressBound() returns an upper bound on the compressed size after
+ compress() or compress2() on sourceLen bytes. It would be used before
+ a compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+ This function can be used to decompress a whole file at once if the
+ input file is mmap'ed.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
+*/
+
+
+typedef voidp gzFile;
+
+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+/*
+ Opens a gzip (.gz) file for reading or writing. The mode parameter
+ is as in fopen ("rb" or "wb") but can also include a compression level
+ ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+ Huffman only compression as in "wb1h", or 'R' for run-length encoding
+ as in "wb1R". (See the description of deflateInit2 for more information
+ about the strategy parameter.)
+
+ gzopen can be used to read a file which is not in gzip format; in this
+ case gzread will directly read from the file without decompression.
+
+ gzopen returns NULL if the file could not be opened or if there was
+ insufficient memory to allocate the (de)compression state; errno
+ can be checked to distinguish the two cases (if errno is zero, the
+ zlib error is Z_MEM_ERROR). */
+
+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+/*
+ gzdopen() associates a gzFile with the file descriptor fd. File
+ descriptors are obtained from calls like open, dup, creat, pipe or
+ fileno (in the file has been previously opened with fopen).
+ The mode parameter is as in gzopen.
+ The next call of gzclose on the returned gzFile will also close the
+ file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+ descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+ gzdopen returns NULL if there was insufficient memory to allocate
+ the (de)compression state.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+ Dynamically update the compression level or strategy. See the description
+ of deflateInit2 for the meaning of these parameters.
+ gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+ opened for writing.
+*/
+
+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+/*
+ Reads the given number of uncompressed bytes from the compressed file.
+ If the input file was not in gzip format, gzread copies the given number
+ of bytes into the buffer.
+ gzread returns the number of uncompressed bytes actually read (0 for
+ end of file, -1 for error). */
+
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
+ voidpc buf, unsigned len));
+/*
+ Writes the given number of uncompressed bytes into the compressed file.
+ gzwrite returns the number of uncompressed bytes actually written
+ (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...));
+/*
+ Converts, formats, and writes the args to the compressed file under
+ control of the format string, as in fprintf. gzprintf returns the number of
+ uncompressed bytes actually written (0 in case of error). The number of
+ uncompressed bytes written is limited to 4095. The caller should assure that
+ this limit is not exceeded. If it is exceeded, then gzprintf() will return
+ return an error (0) with nothing written. In this case, there may also be a
+ buffer overflow with unpredictable consequences, which is possible only if
+ zlib was compiled with the insecure functions sprintf() or vsprintf()
+ because the secure snprintf() or vsnprintf() functions were not available.
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+ Writes the given null-terminated string to the compressed file, excluding
+ the terminating null character.
+ gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+ Reads bytes from the compressed file until len-1 characters are read, or
+ a newline character is read and transferred to buf, or an end-of-file
+ condition is encountered. The string is then terminated with a null
+ character.
+ gzgets returns buf, or Z_NULL in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
+/*
+ Writes c, converted to an unsigned char, into the compressed file.
+ gzputc returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
+/*
+ Reads one byte from the compressed file. gzgetc returns this byte
+ or -1 in case of end of file or error.
+*/
+
+ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
+/*
+ Push one character back onto the stream to be read again later.
+ Only one character of push-back is allowed. gzungetc() returns the
+ character pushed, or -1 on failure. gzungetc() will fail if a
+ character has been pushed but not read yet, or if c is -1. The pushed
+ character will be discarded if the stream is repositioned with gzseek()
+ or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
+/*
+ Flushes all pending output into the compressed file. The parameter
+ flush is as in the deflate() function. The return value is the zlib
+ error number (see function gzerror below). gzflush returns Z_OK if
+ the flush parameter is Z_FINISH and all output could be flushed.
+ gzflush should be called only when strictly necessary because it can
+ degrade compression.
+*/
+
+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
+ z_off_t offset, int whence));
+/*
+ Sets the starting position for the next gzread or gzwrite on the
+ given compressed file. The offset represents a number of bytes in the
+ uncompressed data stream. The whence parameter is defined as in lseek(2);
+ the value SEEK_END is not supported.
+ If the file is opened for reading, this function is emulated but can be
+ extremely slow. If the file is opened for writing, only forward seeks are
+ supported; gzseek then compresses a sequence of zeroes up to the new
+ starting position.
+
+ gzseek returns the resulting offset location as measured in bytes from
+ the beginning of the uncompressed stream, or -1 in case of error, in
+ particular if the file is opened for writing and the new starting position
+ would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT gzrewind OF((gzFile file));
+/*
+ Rewinds the given file. This function is supported only for reading.
+
+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
+/*
+ Returns the starting position for the next gzread or gzwrite on the
+ given compressed file. This position represents a number of bytes in the
+ uncompressed data stream.
+
+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+ Returns 1 when EOF has previously been detected reading the given
+ input stream, otherwise zero.
+*/
+
+ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
+/*
+ Returns 1 if file is being read directly without decompression, otherwise
+ zero.
+*/
+
+ZEXTERN int ZEXPORT gzclose OF((gzFile file));
+/*
+ Flushes all pending output if necessary, closes the compressed file
+ and deallocates all the (de)compression state. The return value is the zlib
+ error number (see function gzerror below).
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+ Returns the error message for the last error which occurred on the
+ given compressed file. errnum is set to zlib error number. If an
+ error occurred in the file system and not in the compression library,
+ errnum is set to Z_ERRNO and the application may consult errno
+ to get the exact error code.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
+/*
+ Clears the error and end-of-file flags for file. This is analogous to the
+ clearerr() function in stdio. This is useful for continuing to read a gzip
+ file that is being written concurrently.
+*/
+
+ /* checksum functions */
+
+/*
+ These functions are not related to compression but are exported
+ anyway because they might be useful in applications using the
+ compression library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. If buf is NULL, this function returns
+ the required initial value for the checksum.
+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+ much faster. Usage example:
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
+ z_off_t len2));
+/*
+ Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
+ and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+ each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of
+ seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.
+*/
+
+ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
+/*
+ Update a running CRC-32 with the bytes buf[0..len-1] and return the
+ updated CRC-32. If buf is NULL, this function returns the required initial
+ value for the for the crc. Pre- and post-conditioning (one's complement) is
+ performed within this function so it shouldn't be done by the application.
+ Usage example:
+
+ uLong crc = crc32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = crc32(crc, buffer, length);
+ }
+ if (crc != original_crc) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
+
+/*
+ Combine two CRC-32 check values into one. For two sequences of bytes,
+ seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+ calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
+ check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+ len2.
+*/
+
+
+ /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
+ int windowBits, int memLevel,
+ int strategy, const char *version,
+ int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
+ unsigned char FAR *window,
+ const char *version,
+ int stream_size));
+#define deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+#define inflateBackInit(strm, windowBits, window) \
+ inflateBackInit_((strm), (windowBits), (window), \
+ ZLIB_VERSION, sizeof(z_stream))
+
+
+#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
+ struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+ZEXTERN const char * ZEXPORT zError OF((int));
+ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z));
+ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZLIB_H */
diff --git a/zlib.lib b/zlib.lib
new file mode 100644
index 0000000..b32c41f
Binary files /dev/null and b/zlib.lib differ