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