From 1e3a72bdaacf5cc662c658206e969a70111cbe0f Mon Sep 17 00:00:00 2001 From: Bastian Kleineidam Date: Sun, 21 Feb 2010 12:14:57 +0100 Subject: [PATCH] Initial commit --- .gitignore | 3 + COPYING | 676 +++++++++++++++++++++++++++++++++++++++++ Makefile | 48 +++ doc/patool.1 | 91 ++++++ doc/patool.txt | 77 +++++ doc/todo.txt | 3 + patool | 50 +++ patoolib/__init__.py | 302 ++++++++++++++++++ patoolib/arj.py | 39 +++ patoolib/bzip2.py | 32 ++ patoolib/cabextract.py | 34 +++ patoolib/cpio.py | 42 +++ patoolib/dpkg.py | 35 +++ patoolib/echo.py | 32 ++ patoolib/gzip.py | 45 +++ patoolib/lzop.py | 37 +++ patoolib/p7zip.py | 61 ++++ patoolib/pbzip2.py | 18 ++ patoolib/rar.py | 36 +++ patoolib/rpm.py | 25 ++ patoolib/rpm2cpio.py | 34 +++ patoolib/star.py | 46 +++ patoolib/tar.py | 36 +++ patoolib/uncompress.py | 31 ++ patoolib/unrar.py | 36 +++ patoolib/unzip.py | 33 ++ patoolib/util.py | 93 ++++++ setup.py | 44 +++ tests/__init__.py | 60 ++++ tests/data/t.7z | Bin 0 -> 158 bytes tests/data/t.Z | Bin 0 -> 375 bytes tests/data/t.arj | Bin 0 -> 123 bytes tests/data/t.bz2 | Bin 0 -> 40 bytes tests/data/t.cab | Bin 0 -> 79 bytes tests/data/t.cpio | Bin 0 -> 512 bytes tests/data/t.deb | Bin 0 -> 2004 bytes tests/data/t.gz | Bin 0 -> 25 bytes tests/data/t.jar | Bin 0 -> 447 bytes tests/data/t.lzo | Bin 0 -> 58 bytes tests/data/t.rar | Bin 0 -> 111 bytes tests/data/t.rpm | Bin 0 -> 10288 bytes tests/data/t.tar | Bin 0 -> 10240 bytes tests/data/t.tar.Z | Bin 0 -> 285 bytes tests/data/t.tar.bz2 | Bin 0 -> 153 bytes tests/data/t.tar.gz | Bin 0 -> 151 bytes tests/data/t.tbz2 | Bin 0 -> 153 bytes tests/data/t.txt.gz | Bin 0 -> 29 bytes tests/data/t.zip | Bin 0 -> 299 bytes tests/test_archives.py | 130 ++++++++ tests/test_config.py | 33 ++ 50 files changed, 2262 insertions(+) create mode 100644 .gitignore create mode 100644 COPYING create mode 100644 Makefile create mode 100644 doc/patool.1 create mode 100644 doc/patool.txt create mode 100644 doc/todo.txt create mode 100755 patool create mode 100644 patoolib/__init__.py create mode 100644 patoolib/arj.py create mode 100644 patoolib/bzip2.py create mode 100644 patoolib/cabextract.py create mode 100644 patoolib/cpio.py create mode 100644 patoolib/dpkg.py create mode 100644 patoolib/echo.py create mode 100644 patoolib/gzip.py create mode 100644 patoolib/lzop.py create mode 100644 patoolib/p7zip.py create mode 100644 patoolib/pbzip2.py create mode 100644 patoolib/rar.py create mode 100644 patoolib/rpm.py create mode 100644 patoolib/rpm2cpio.py create mode 100644 patoolib/star.py create mode 100644 patoolib/tar.py create mode 100644 patoolib/uncompress.py create mode 100644 patoolib/unrar.py create mode 100644 patoolib/unzip.py create mode 100644 patoolib/util.py create mode 100644 setup.py create mode 100644 tests/__init__.py create mode 100644 tests/data/t.7z create mode 100644 tests/data/t.Z create mode 100644 tests/data/t.arj create mode 100644 tests/data/t.bz2 create mode 100644 tests/data/t.cab create mode 100644 tests/data/t.cpio create mode 100644 tests/data/t.deb create mode 100644 tests/data/t.gz create mode 100644 tests/data/t.jar create mode 100644 tests/data/t.lzo create mode 100644 tests/data/t.rar create mode 100644 tests/data/t.rpm create mode 100644 tests/data/t.tar create mode 100644 tests/data/t.tar.Z create mode 100644 tests/data/t.tar.bz2 create mode 100644 tests/data/t.tar.gz create mode 100644 tests/data/t.tbz2 create mode 100644 tests/data/t.txt.gz create mode 100644 tests/data/t.zip create mode 100644 tests/test_archives.py create mode 100644 tests/test_config.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..899daba --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.pyc +*.pyo +/build diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..4432540 --- /dev/null +++ b/COPYING @@ -0,0 +1,676 @@ + + 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. + + + Copyright (C) + + 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: + + Copyright (C) + 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 +. + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5b7ee17 --- /dev/null +++ b/Makefile @@ -0,0 +1,48 @@ +PY_FILES_DIRS := patool setup.py patoolib tests +# This Makefile is only used by developers. +TESTS ?= tests/ +# set test options, eg. to "--nologcapture" +TESTOPTS= + +all: + + +.PHONY: chmod +chmod: + -chmod -R a+rX,u+w,go-w -- * + find . -type d -exec chmod 755 {} \; + +.PHONY: dist +dist: + git archive --format=zip --prefix=patool-devel/ HEAD > $(HOME)/temp/share/patool-devel.zip +# cd .. && zip -r - patool-git -x "**/.git/**" > $(HOME)/temp/share/patool-devel.zip + +# The check programs used here are mostly local scripts on my private system. +# So for other developers there is no need to execute this target. +.PHONY: check +check: + [ ! -d .svn ] || check-nosvneolstyle -v + check-copyright + check-pofiles -v + py-tabdaddy + $(MAKE) pyflakes + +.PHONY: pyflakes +pyflakes: + pyflakes $(PY_FILES_DIRS) + +.PHONY: count +count: + @sloccount patool patoolib | grep "Total Physical Source Lines of Code" + +.PHONY: clean +clean: + find . -name \*.pyc -delete + find . -name \*.pyo -delete + +.PHONY: test +test: + nosetests -v -m "^test_.*" $(TESTOPTS) $(TESTS) + +doc/patool.txt: doc/patool.1 + man -l doc/patool.1 | perl -pe 's/.\cH//g' > doc/patool.txt diff --git a/doc/patool.1 b/doc/patool.1 new file mode 100644 index 0000000..657bc26 --- /dev/null +++ b/doc/patool.1 @@ -0,0 +1,91 @@ +.\" -*- nroff -*- +.\" Copyright (C) 2010 Bastian Kleineidam +.\" +.\" 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. +.\" +.TH PATOOL "1" "February 2010" "patool" +.SH NAME +patool - simple manager for file archives of various types +.SH SYNOPSIS +\fBpatool\fP <\fIcommand\fP> [\fIoptions\fP] <\fIarchive-file\fP> +.SH DESCRIPTION +Various archive types can be created, extracted and listed by +\fBpatool\fP. +The archive format is determined by the archive file extension and +as a fallback with file(1). +.PP +\fBpatool\fP supports 7z (.7z), ZIP (.zip, .jar), GZIP (.gz), compress (.Z), +BZIP2 (.bz2), TAR (.tar), ARJ (.arj), CAB (.cab), CPIO (.cpio), +RPM (.rpm), DEB (.deb), LZOP (.lzo)and RAR (.rar) formats. +It relies on helper applications to handle those archive formats +(for example bzip2 for BZIP2 archives). +.SH COMMANDS +Several commands and options are available. +.SS \fBextract\fP +Extract files from an archive4. Often one wants +to extract all files in an archive to a single subdirectory. +However, some archives contain multiple files in their root +directories. The patool program overcomes this problem by +first extracting files to a unique (temporary) directory, and +then moving its contents back if possible. This also prevents +local files from being overwritten by mistake. +.TP +\fB--force\fP +Allow overwriting of local files. +.TP +\fB\-\-verbose\fP +Be verbose when extracting (if the helper application supports it). +.TP +\fB\-\-help\fP +Show help for this command. +.SS \fBlist\fP +List files in an archive. +.TP +\fB\-\-verbose\fP +Verbose archive listing (if the helper application supports it). +.TP +\fB\-\-help\fP +Show help for this command. +.SS \fBformats\fP +Show all supported archive formats. +.TP +\fB\-\-help\fP +Show help for this command. +.SH CONFIGURATION +The configuration files (see FILES) can specify which program to use +for each archive format. Per default a list of programs are searched +and the first one will be used for an archive. +.br +Additionally, default options like verbosity and force overwrite can +be configured. +.br +The configuration format is the Windows INI format. + +.SS \fB[DEFAULT]\fP +.TP +\fBforce=0\fP +Set the force option to 1 or 0. +.TP +\fBverbose=0\fP +Set the verbose option to 1 or 0. +.SS \fB[\fP\fI\fP\fB]\fP +Supported archive formats are listed by the \fBformats\fP command. +.TP +\fImode\fP\fB=/usr/bin/mycommand\fP +Set the application to handle the archive format for given mode. +\fImode\fP can be one of \fBextract\fP, \fBlist\fP. +.SH FILES +\fB/etc/patool.conf\fP, \fB~/.patool.conf\fP - +configuration files +.SH AUTHOR +Bastian Kleineidam +.SH COPYRIGHT +Copyright \(co 2010 Bastian Kleineidam diff --git a/doc/patool.txt b/doc/patool.txt new file mode 100644 index 0000000..10959b1 --- /dev/null +++ b/doc/patool.txt @@ -0,0 +1,77 @@ +PATOOL(1) PATOOL(1) + + + +NAME + patool - simple manager for file archives of various types + +SYNOPSIS + patool [options] + +DESCRIPTION + Various archive types can be created, extracted and listed by patool. The archive format is determined by the archive file extension and as a fallback with file(1). + + patool supports 7z (.7z), ZIP (.zip, .jar), GZIP (.gz), compress (.Z), BZIP2 (.bz2), TAR (.tar), ARJ (.arj), CAB (.cab), CPIO (.cpio), RPM (.rpm), DEB (.deb), LZOP + (.lzo)and RAR (.rar) formats. It relies on helper applications to handle those archive formats (for example bzip2 for BZIP2 archives). + +COMMANDS + Several commands and options are available. + + extract + Extract files from an archive4. Often one wants to extract all files in an archive to a single subdirectory. However, some archives contain multiple files in their + root directories. The patool program overcomes this problem by first extracting files to a unique (temporary) directory, and then moving its contents back if possible. + This also prevents local files from being overwritten by mistake. + + --force + Allow overwriting of local files. + + --verbose + Be verbose when extracting (if the helper application supports it). + + --help Show help for this command. + + list + List files in an archive. + + --verbose + Verbose archive listing (if the helper application supports it). + + --help Show help for this command. + + formats + Show all supported archive formats. + + --help Show help for this command. + +CONFIGURATION + The configuration files (see FILES) can specify which program to use for each archive format. Per default a list of programs are searched and the first one will be used + for an archive. + Additionally, default options like verbosity and force overwrite can be configured. + The configuration format is the Windows INI format. + + + [DEFAULT] + force=0 + Set the force option to 1 or 0. + + verbose=0 + Set the verbose option to 1 or 0. + + [] + Supported archive formats are listed by the formats command. + + mode=/usr/bin/mycommand + Set the application to handle the archive format for given mode. mode can be one of extract, list. + +FILES + /etc/patool.conf, ~/.patool.conf - configuration files + +AUTHOR + Bastian Kleineidam + +COPYRIGHT + Copyright © 2010 Bastian Kleineidam + + + +patool February 2010 PATOOL(1) diff --git a/doc/todo.txt b/doc/todo.txt new file mode 100644 index 0000000..1e99398 --- /dev/null +++ b/doc/todo.txt @@ -0,0 +1,3 @@ +- add project to github +- add create mode? +- add test mode? diff --git a/patool b/patool new file mode 100755 index 0000000..26e1d50 --- /dev/null +++ b/patool @@ -0,0 +1,50 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +""" +patool [extract|list] [sub-command-options] +""" +import sys +if not hasattr(sys, "version_info") or sys.version_info < (2, 5, 0, "final", 0): + raise SystemExit("Error, this script needs Python >= 2.5 installed") +import baker +import patoolib + + +@baker.command +def extract (archive, verbose=False, force=False): + """Extract files from an archive.""" + return patoolib.handle_archive(archive, 'extract') + + +@baker.command +def list (archive, verbose=False): + """List files in an archive.""" + return patoolib.handle_archive(archive, 'list') + + +#@baker.command +#def create (archive, *args): +# """Create an archive from given files.""" +# return patoolib.handle_archive(archive, 'create', *args) + + +@baker.command +def formats (): + return patoolib.list_formats() + + +sys.exit(baker.run()) diff --git a/patoolib/__init__.py b/patoolib/__init__.py new file mode 100644 index 0000000..4e8e7e3 --- /dev/null +++ b/patoolib/__init__.py @@ -0,0 +1,302 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +import os +import shutil +from distutils.spawn import find_executable +from . import util + +# Supported command modes +CommandModes = ('list', 'extract') + +# Supported archive formats +ArchiveFormats = ('gzip', 'bzip2', 'tar', 'zip', 'compress', '7z', 'rar', + 'cab', 'arj', 'cpio', 'rpm', 'deb', 'lzop') + +# Supported encodings (used with tar for example) +# Note that all encodings must also be archive formats +ArchiveEncodings = ('gzip', 'bzip2', 'compress') + +# Map MIME types to archive format +ArchiveMimetypes = { + 'application/x-bzip2': 'bzip2', + 'application/x-tar': 'tar', + 'application/x-gzip': 'gzip', + 'application/zip': 'zip', + 'application/java-archive': 'zip', + 'application/x-7z-compressed': '7z', + 'application/x-compress': 'compress', + 'application/x-rar': 'rar', + 'application/rar': 'rar', + 'application/x-cab': 'cab', + 'application/vnd.ms-cab-compressed': 'cab', + 'application/x-arj': 'arj', + 'application/x-cpio': 'cpio', + 'application/x-redhat-package-manager': 'rpm', + 'application/x-rpm': 'rpm', + 'application/x-debian-package': 'deb', + 'application/x-lzop': 'lzop', +} + +# List of programs supporting the given archive format and mode. +# If mode is None, the program supports all modes (list, extract, ...) +ArchivePrograms = { + 'bzip2': { + 'extract': ('pbzip2', 'bzip2', '7z'), + 'list': ('7z', 'echo',), + }, + 'tar': { + None: ('tar', 'star',), + }, + 'zip': { + 'extract': ('unzip', '7z'), + 'list': ('unzip', '7z'), + }, + 'gzip': { + None: ('gzip', '7z'), + }, + 'compress': { + 'extract': ('gzip', '7z', 'uncompress.real'), + 'list': ('7z', 'echo',), + }, + '7z': { + None: ('7z',), + }, + 'rar': { + None: ('rar',), + 'extract': ('unrar', '7z'), + 'list': ('unrar', '7z'), + }, + 'cab': { + 'extract': ('cabextract', '7z'), + 'list': ('cabextract', '7z'), + }, + 'arj': { + 'extract': ('arj', '7z'), + 'list': ('arj', '7z'), + }, + 'cpio': { + 'extract': ('cpio', '7z'), + 'list': ('cpio', '7z'), + }, + 'rpm': { + # XXX rpm2cpio depends on cpio which is not checked + 'extract': ('rpm2cpio', '7z'), + 'list': ('rpm', '7z'), + }, + 'deb': { + 'extract': ('dpkg-deb', '7z'), + 'list': ('dpkg-deb', '7z'), + }, + 'lzop': { + None: ('lzop',), + }, +} + +# only list those programs that have different python module names +ProgramModules = { + '7z': 'p7zip', + 'uncompress.real': 'uncompress', + 'dpkg-deb': 'dpkg', +} + + +def get_archive_format (filename): + """Detect filename archive format.""" + mime, encoding = util.guess_mime(filename) + if not mime: + raise util.PatoolError("unknown archive format for file `%s'" % filename) + if mime in ArchiveMimetypes: + format = ArchiveMimetypes[mime] + elif encoding in ArchiveEncodings: + # Files like 't.txt.gz' are recognized with encoding as format, and + # an unsupported mime-type like 'text/plain'. Fix this. + format, encoding = encoding, None + else: + raise util.PatoolError("unknown archive format for file `%s' (mime-type is `%s')" % (filename, mime)) + return format, encoding + + +def check_archive_format (format, encoding): + if format not in ArchiveFormats: + raise util.PatoolError("unknown archive format `%s'" % format) + if encoding is not None and encoding not in ArchiveEncodings: + raise util.PatoolError("unkonwn archive encoding `%s'" % encoding) + + +def check_command_mode (mode): + if mode not in CommandModes: + raise util.PatoolError("invalid command mode `%s'" % mode) + + +def find_archive_program (format, mode): + """Find suitable archive program for given format and mode.""" + modes = ArchivePrograms[format] + programs = [] + # first try the universal programs with key None + for key in (None, mode): + if key in modes: + programs.extend(modes[key]) + # return the first existing program + for program in programs: + exe = find_executable(program) + if exe: + return exe + # no programs found + raise util.PatoolError("could not find an executable program to %s format %s; candidates are (%s)," % (mode, format, ",".join(programs))) + + +def list_formats (): + for format in ArchiveFormats: + print format, "files:" + for mode in CommandModes: + program = find_archive_program(format, mode) + if program: + print " %8s: %s" % (mode, program) + else: + print " %8s: NOT SUPPORTED" + return 0 + + +def parse_config (format, mode, **kwargs): + """The configuration determines which program to use for which + archive format for the given mode. + """ + config = { + 'verbose': False, + 'force': False, + } + configfile = parse_config_file() + if configfile.has_option(None, "verbose"): + config['verbose'] = configfile.getboolean(None, "verbose") + if configfile.has_option(None, "force"): + config['verbose'] = configfile.getboolean(None, "force") + if configfile.has_option(format, mode): + config['cmd'] = configfile.get(format, mode) + else: + config['cmd'] = find_archive_program(format, mode) + for key, value in kwargs.items(): + if value is not None: + config[key] = value + return config + + +def parse_config_file (): + """Parse system-wide and then user-specific configuration.""" + import ConfigParser + config = ConfigParser.RawConfigParser() + files = [] + # system wide config settings + files.append("/etc/patool.conf") + # per user config settings + files.append(os.path.expanduser("~/.patool.conf")) + # weed out invalid files + files = [f for f in files if os.path.isfile(f) and os.path.exists(f)] + config.read(files) + return config + + +def move_outdir_orphan (outdir, force): + """Move a single file or directory inside outdir a level up. + Overwrite files if force evaluates True. + Return (True, outfile) if successful, (False, reason) if not.""" + entries = os.listdir(outdir) + reason = "" + if len(entries) == 1: + src = os.path.join(outdir, entries[0]) + dst = os.path.join(os.path.dirname(outdir), entries[0]) + if os.path.exists(dst): + if not force: + return (False, "local file exists") + if os.path.isdir(dst): + shutil.rmtree(dst) + else: + os.unlink(dst) + shutil.move(src, dst) + os.rmdir(outdir) + return (True, entries[0]) + return (False, "multiple files in root") + + +def run_archive_cmd (archive_cmd): + """Handle result of archive command function.""" + # archive_cmd is a command list with optional keyword arguments + if isinstance(archive_cmd, tuple): + cmdlist, runkwargs = archive_cmd + else: + cmdlist, runkwargs = archive_cmd, {} + util.run(cmdlist, **runkwargs) + + +def cleanup_outdir (archive, outdir, force): + """Cleanup outdir after extraction and return target file name.""" + if outdir: + # move single directory or file in outdir + (res, msg) = move_outdir_orphan(outdir, force) + if res: + target = "`%s'" % msg + else: + target = "`%s' (%s)" % (outdir, msg) + else: + target = "`%s'" % util.stripext(archive) + return target + + +def _handle_archive (archive, mode, **kwargs): + util.check_filename(archive) + encoding = None + format, encoding = get_archive_format(archive) + check_archive_format(format, encoding) + check_command_mode(mode) + config = parse_config(format, mode, **kwargs) + cmd = config['cmd'] + # get python module for given archive program + program = os.path.basename(cmd).lower() + module = ProgramModules.get(program, program) + # import archive handler (eg. patoolib.star.extract_tar()) + exec "from patoolib.%s import %s_%s as func" % (module, mode, format) + get_archive_cmd = locals()['func'] + # prepare func() call arguments + kwargs = dict(verbose=config['verbose']) + outdir = None + if mode == 'extract': + outdir = util.tmpdir(dir=os.getcwd()) + kwargs['outdir'] = outdir + try: + archive_cmd = get_archive_cmd(archive, encoding, cmd, **kwargs) + run_archive_cmd(archive_cmd) + if mode == 'extract': + target = cleanup_outdir(archive, outdir, config['force']) + print "%s: extracted to %s" % (archive, target) + finally: + if outdir: + try: + os.rmdir(outdir) + except OSError: + pass + + +def handle_archive (archive, mode, **kwargs): + """Handle archive file in given mode.""" + try: + _handle_archive(archive, mode, **kwargs) + res = 0 + except util.PatoolError, msg: + util.log_error(msg) + res = 1 + except StandardError, msg: + util.log_internal_error() + res = 1 + return res diff --git a/patoolib/arj.py b/patoolib/arj.py new file mode 100644 index 0000000..e890f35 --- /dev/null +++ b/patoolib/arj.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +"""Archive commands for the arj program.""" + +def extract_arj (archive, encoding, cmd, **kwargs): + """Extract a ARJ archive.""" + cmdlist = [cmd] + cmdlist.append('x') + cmdlist.append('-r') + cmdlist.append('-y') + if kwargs['verbose']: + cmdlist.append('-v') + cmdlist.extend([archive, kwargs['outdir']]) + return cmdlist + +def list_arj (archive, encoding, cmd, **kwargs): + """List a ARJ archive.""" + cmdlist = [cmd] + if kwargs['verbose']: + cmdlist.append('v') + else: + cmdlist.append('l') + cmdlist.append('-r') + cmdlist.append('-y') + cmdlist.extend([archive]) + return cmdlist diff --git a/patoolib/bzip2.py b/patoolib/bzip2.py new file mode 100644 index 0000000..0f3aa33 --- /dev/null +++ b/patoolib/bzip2.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +"""Archive commands for the bzip2 program.""" +import os +from . import util + + +def extract_bzip2 (archive, encoding, cmd, **kwargs): + """Extract a BZIP2 archive.""" + cmdlist = [cmd] + if kwargs['verbose']: + cmdlist.append('-v') + cmdlist.extend(['-c', '-d']) + outfile = os.path.join(kwargs['outdir'], util.stripext(archive)) + cmdlist.append('--') + cmdlist.extend([archive, '>', outfile]) + # note that for shell calls the command must be a string + cmd = " ".join([util.shell_quote(x) for x in cmdlist]) + return (cmd, {'shell': True}) diff --git a/patoolib/cabextract.py b/patoolib/cabextract.py new file mode 100644 index 0000000..7536001 --- /dev/null +++ b/patoolib/cabextract.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +"""Archive commands for the cabextract program.""" + +def extract_cab (archive, encoding, cmd, **kwargs): + """Extract a CAB archive.""" + cmdlist = [cmd] + cmdlist.extend(['-d', kwargs['outdir']]) + if kwargs['verbose']: + cmdlist.append('-v') + cmdlist.append(archive) + return cmdlist + +def list_cab (archive, encoding, cmd, **kwargs): + """List a CAB archive.""" + cmdlist = [cmd] + cmdlist.append('-l') + if kwargs['verbose']: + cmdlist.append('-v') + cmdlist.extend([archive]) + return cmdlist diff --git a/patoolib/cpio.py b/patoolib/cpio.py new file mode 100644 index 0000000..0a9aa11 --- /dev/null +++ b/patoolib/cpio.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +"""Archive commands for the cpio program.""" +from . import util + +def extract_cpio (archive, encoding, cmd, **kwargs): + """Extract a CPIO archive.""" + cmdlist = [cmd] + cmdlist.append('--extract') + cmdlist.append('--make-directories') + cmdlist.append('--preserve-modification-time') + cmdlist.append('--no-absolute-filenames') + cmdlist.append('--force-local') + cmdlist.extend(['--nonmatching', '"*\.\.*"']) + if kwargs['verbose']: + cmdlist.append('-v') + cmdlist.extend(['<', archive]) + cmd = " ".join([util.shell_quote(x) for x in cmdlist]) + return (cmd, {'cwd': kwargs['outdir'], 'shell': True}) + + +def list_cpio (archive, encoding, cmd, **kwargs): + """List a CPIO archive.""" + cmdlist = [cmd] + cmdlist.append('-t') + if kwargs['verbose']: + cmdlist.append('-v') + cmdlist.extend(['-F', archive]) + return cmdlist diff --git a/patoolib/dpkg.py b/patoolib/dpkg.py new file mode 100644 index 0000000..dbc8920 --- /dev/null +++ b/patoolib/dpkg.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +"""Archive commands for the dpkg-deb program.""" + +def extract_deb (archive, encoding, cmd, **kwargs): + """Extract a DEB archive.""" + cmdlist = [cmd] + if kwargs['verbose']: + cmdlist.append('--vextract') + else: + cmdlist.append('--extract') + cmdlist.append('--') + cmdlist.extend([archive, kwargs['outdir']]) + return cmdlist + +def list_deb (archive, encoding, cmd, **kwargs): + """List a DEB archive.""" + cmdlist = [cmd] + cmdlist.append('--contents') + cmdlist.append('--') + cmdlist.extend([archive]) + return cmdlist diff --git a/patoolib/echo.py b/patoolib/echo.py new file mode 100644 index 0000000..15bb96e --- /dev/null +++ b/patoolib/echo.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +"""Archive commands for the echo program.""" +from . import util + + +def list_bzip2 (archive, encoding, cmd, **kwargs): + """List a BZIP2 archive.""" + return stripext(cmd, archive) + + +def list_compress (archive, encoding, cmd, **kwargs): + """List a compress archive.""" + return stripext(cmd, archive) + + +def stripext (cmd, archive): + """Echo the name without suffix.""" + return [cmd, util.stripext(archive)] diff --git a/patoolib/gzip.py b/patoolib/gzip.py new file mode 100644 index 0000000..cd6300f --- /dev/null +++ b/patoolib/gzip.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +"""Archive commands for the gzip program.""" +import os +from . import util + + +def extract_gzip (archive, encoding, cmd, **kwargs): + """Extract a GZIP archive.""" + cmdlist = [cmd] + if kwargs['verbose']: + cmdlist.append('-v') + cmdlist.extend(['-c', '-d']) + cmdlist.append('--') + outfile = os.path.join(kwargs['outdir'], util.stripext(archive)) + cmdlist.extend([archive, '>', outfile]) + # note that for shell calls the command must be a string + cmd = " ".join([util.shell_quote(x) for x in cmdlist]) + return (cmd, {'shell': True}) + +extract_compress = extract_gzip + +def list_gzip (archive, encoding, cmd, **kwargs): + """List a GZIP archive.""" + cmdlist = [cmd] + if kwargs['verbose']: + cmdlist.append('-v') + cmdlist.append('-l') + cmdlist.append('--') + cmdlist.append(archive) + return cmdlist + diff --git a/patoolib/lzop.py b/patoolib/lzop.py new file mode 100644 index 0000000..918cda7 --- /dev/null +++ b/patoolib/lzop.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +"""Archive commands for the lzop program.""" +import os +from . import util + + +def extract_lzop (archive, encoding, cmd, **kwargs): + """Extract a LZOP archive.""" + cmdlist = [cmd] + cmdlist.append('--decompress') + if kwargs['verbose']: + cmdlist.append('--verbose') + cmdlist.extend(['-p%s' % kwargs["outdir"], '--', archive]) + return cmdlist + +def list_lzop (archive, encoding, cmd, **kwargs): + """List a LZOP archive.""" + cmdlist = [cmd] + cmdlist.append('--list') + if kwargs['verbose']: + cmdlist.append('--verbose') + cmdlist.extend(['--', archive]) + return cmdlist diff --git a/patoolib/p7zip.py b/patoolib/p7zip.py new file mode 100644 index 0000000..df7bd88 --- /dev/null +++ b/patoolib/p7zip.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +"""Archive commands for the 7z program.""" + +def extract_7z (archive, encoding, cmd, **kwargs): + """Extract a 7z archive.""" + cmdlist = [cmd] + cmdlist.append('x') + if not kwargs['verbose']: + cmdlist.append('-bd') + cmdlist.extend(['-o%s' % kwargs['outdir']]) + cmdlist.append('--') + cmdlist.append(archive) + return cmdlist + +extract_bzip2 = \ + extract_gzip = \ + extract_zip = \ + extract_compress = \ + extract_rar = \ + extract_cab = \ + extract_arj = \ + extract_cpio = \ + extract_rpm = \ + extract_deb = \ + extract_7z + +def list_7z (archive, encoding, cmd, **kwargs): + """List a 7z archive.""" + cmdlist = [cmd] + cmdlist.append('l') + if not kwargs['verbose']: + cmdlist.append('-bd') + cmdlist.append('--') + cmdlist.append(archive) + return cmdlist + +list_bzip2 = \ + list_gzip = \ + list_zip = \ + list_compress = \ + list_rar = \ + list_cab = \ + list_arj = \ + list_cpio = \ + list_rpm = \ + list_deb = \ + list_7z diff --git a/patoolib/pbzip2.py b/patoolib/pbzip2.py new file mode 100644 index 0000000..d985023 --- /dev/null +++ b/patoolib/pbzip2.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +"""Archive commands for the pbzip2 program.""" +# bzip2 and pbzip2 are compatible +from .bzip2 import extract_bzip2 diff --git a/patoolib/rar.py b/patoolib/rar.py new file mode 100644 index 0000000..8d95bf4 --- /dev/null +++ b/patoolib/rar.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +"""Archive commands for the unrar program.""" + +def extract_rar (archive, encoding, cmd, **kwargs): + """Extract a RAR archive.""" + cmdlist = [cmd] + cmdlist.append('x') + if not kwargs['verbose']: + cmdlist.append('-c-') + cmdlist.extend(['-r', '--', archive, kwargs['outdir']]) + return cmdlist + +def list_rar (archive, encoding, cmd, **kwargs): + """List a RAR archive.""" + cmdlist = [cmd] + if kwargs['verbose']: + cmdlist.append('v') + else: + cmdlist.append('l') + cmdlist.append('-c-') + cmdlist.extend(['--', archive]) + return cmdlist diff --git a/patoolib/rpm.py b/patoolib/rpm.py new file mode 100644 index 0000000..bb3171a --- /dev/null +++ b/patoolib/rpm.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +"""Archive commands for the rpm program.""" + +def list_rpm (archive, encoding, cmd, **kwargs): + """List a RPM archive.""" + cmdlist = [cmd] + cmdlist.extend(['-q', '-l']) + if kwargs['verbose']: + cmdlist.append('-v') + cmdlist.extend(['-p', '--', archive]) + return cmdlist diff --git a/patoolib/rpm2cpio.py b/patoolib/rpm2cpio.py new file mode 100644 index 0000000..f95c174 --- /dev/null +++ b/patoolib/rpm2cpio.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +"""Archive commands for the rpm2cpio program.""" +import os +from . import util + +def extract_rpm (archive, encoding, cmd, **kwargs): + """Extract a DEB archive.""" + cmdlist = [cmd] + cmdlist.extend([os.path.abspath(archive), "|"]) + cmdlist.append('cpio') + cmdlist.append('--extract') + cmdlist.append('--make-directories') + cmdlist.append('--preserve-modification-time') + cmdlist.append('--no-absolute-filenames') + cmdlist.append('--force-local') + cmdlist.extend(['--nonmatching', '"*\.\.*"']) + if kwargs['verbose']: + cmdlist.append('-v') + cmd = " ".join([util.shell_quote(x) for x in cmdlist]) + return (cmd, {'cwd': kwargs['outdir'], 'shell': True}) diff --git a/patoolib/star.py b/patoolib/star.py new file mode 100644 index 0000000..6be9d55 --- /dev/null +++ b/patoolib/star.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +"""Archive commands for the star program.""" + +def extract_tar (archive, encoding, cmd, **kwargs): + """Extract a TAR archive.""" + cmdlist = [cmd, '-x'] + # Note that star autodetects encoding compression, but displays a warning + # which we want to avoie. + if encoding == 'gzip': + cmdlist.append('-z') + elif encoding == 'compress': + cmdlist.append('-Z') + elif encoding == 'bzip2': + cmdlist.append('-bz') + if kwargs['verbose']: + cmdlist.append('-v') + cmdlist.extend(['-C', kwargs['outdir'], 'file=%s' % archive]) + return cmdlist + +def list_tar (archive, encoding, cmd, **kwargs): + """List a TAR archive.""" + cmdlist = [cmd, '-n'] + if encoding == 'gzip': + cmdlist.append('-z') + elif encoding == 'compress': + cmdlist.append('-Z') + elif encoding == 'bzip2': + cmdlist.append('-bz') + if kwargs['verbose']: + cmdlist.append('-v') + cmdlist.append("file=%s" % archive) + return cmdlist diff --git a/patoolib/tar.py b/patoolib/tar.py new file mode 100644 index 0000000..832eda0 --- /dev/null +++ b/patoolib/tar.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +"""Archive commands for the GNU tar program.""" + +def extract_tar (archive, encoding, cmd, **kwargs): + """Extract a TAR archive.""" + cmdlist = [cmd, '--extract'] + if encoding: + cmdlist.append('--%s' % encoding) + if kwargs['verbose']: + cmdlist.append('--verbose') + cmdlist.extend(["--file", archive, '--directory', kwargs['outdir']]) + return cmdlist + +def list_tar (archive, encoding, cmd, **kwargs): + """List a TAR archive.""" + cmdlist = [cmd, '--list'] + if encoding: + cmdlist.append('--%s' % encoding) + if kwargs['verbose']: + cmdlist.append('--verbose') + cmdlist.extend(["--file", archive]) + return cmdlist diff --git a/patoolib/uncompress.py b/patoolib/uncompress.py new file mode 100644 index 0000000..5f8762d --- /dev/null +++ b/patoolib/uncompress.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +"""Archive commands for the uncompress.real program.""" +import os +from . import util + + +def extract_compress (archive, encoding, cmd, **kwargs): + """Extract a compressed archive.""" + cmdlist = [cmd] + if kwargs['verbose']: + cmdlist.append('-v') + cmdlist.append('-c') + outfile = os.path.join(kwargs['outdir'], util.stripext(archive)) + cmdlist.extend([archive, '>', outfile]) + # note that for shell calls the command must be a string + cmd = " ".join([util.shell_quote(x) for x in cmdlist]) + return (cmd, {'shell': True}) diff --git a/patoolib/unrar.py b/patoolib/unrar.py new file mode 100644 index 0000000..8d95bf4 --- /dev/null +++ b/patoolib/unrar.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +"""Archive commands for the unrar program.""" + +def extract_rar (archive, encoding, cmd, **kwargs): + """Extract a RAR archive.""" + cmdlist = [cmd] + cmdlist.append('x') + if not kwargs['verbose']: + cmdlist.append('-c-') + cmdlist.extend(['-r', '--', archive, kwargs['outdir']]) + return cmdlist + +def list_rar (archive, encoding, cmd, **kwargs): + """List a RAR archive.""" + cmdlist = [cmd] + if kwargs['verbose']: + cmdlist.append('v') + else: + cmdlist.append('l') + cmdlist.append('-c-') + cmdlist.extend(['--', archive]) + return cmdlist diff --git a/patoolib/unzip.py b/patoolib/unzip.py new file mode 100644 index 0000000..9a5adbe --- /dev/null +++ b/patoolib/unzip.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +"""Archive commands for the unzip program.""" + +def extract_zip (archive, encoding, cmd, **kwargs): + """Extract a ZIP archive.""" + cmdlist = [cmd] + if kwargs['verbose']: + cmdlist.append('-v') + cmdlist.extend(['--', archive, '-d', kwargs['outdir']]) + return cmdlist + +def list_zip (archive, encoding, cmd, **kwargs): + """List a ZIP archive.""" + cmdlist = [cmd] + cmdlist.append('-l') + if kwargs['verbose']: + cmdlist.append('-v') + cmdlist.extend(['--', archive]) + return cmdlist diff --git a/patoolib/util.py b/patoolib/util.py new file mode 100644 index 0000000..cdb87a7 --- /dev/null +++ b/patoolib/util.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +"""Utility functions.""" +import os +import sys +import subprocess +import mimetypes +import tempfile +import traceback + +mimedb = mimetypes.MimeTypes(strict=False) +# add missing encodings for Python <=2.5 +mimedb.encodings_map['.bz2'] = 'bzip2' +mimedb.suffix_map['.tbz2'] = '.tar.bz2' +mimedb.add_type('application/x-lzop', '.lzo', strict=False) + + +class PatoolError (StandardError): + """Raised when errors occur.""" + pass + + +def backtick (cmd): + """Return output from command.""" + return subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0] + + +def run (cmd, **kwargs): + """Run command and raise subprocess.CalledProcessError on error.""" + subprocess.check_call(cmd, **kwargs) + + +def guess_mime (filename): + """Guess the MIME type of given filename. Uses first mimetypes + and then file(1) as fallback.""" + mime, encoding = mimedb.guess_type(filename, strict=False) + if mime is None: + cmd = ["file", "--brief", "--mime-type", filename] + try: + mime = backtick(cmd).strip() + except OSError, msg: + pass + return mime, encoding + + +def check_filename (filename): + """Ensure that given filename is a valid, existing file.""" + if not os.path.isfile(filename): + raise PatoolError("`%s' is not a file." % filename) + if not os.path.exists(filename): + raise PatoolError("File `%s' not found." % filename) + if not os.access(filename, os.R_OK): + raise PatoolError("File `%s' not readable." % filename) + + +def tmpdir (dir=None): + """Return a temporary directory for extraction.""" + return tempfile.mkdtemp(suffix='', prefix='Unpack_', dir=dir) + + +def shell_quote (value): + """Quote all shell metacharacters in given string value.""" + return '%s' % value + + +def stripext (filename): + """Return the basename without extension of given filename.""" + return os.path.splitext(os.path.basename(filename))[0] + + +def log_error (msg, out=sys.stderr): + print >> out, "patool error:", msg + + +def log_internal_error (out=sys.stderr): + print >> out, "patool: internal error" + etype, value = sys.exc_info()[:2] + traceback.print_exc() + print >> out, "System info:" + print >> out, "Python %s on %s" % (sys.version, sys.platform) diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..6c431de --- /dev/null +++ b/setup.py @@ -0,0 +1,44 @@ +#!/usr/bin/python +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +""" +Setup file for the distuils module. +""" + +import sys +if not (hasattr(sys, 'version_info') or + sys.version_info < (2, 5, 0, 'final', 0)): + raise SystemExit("This program requires Python 2.5 or later.") + +from distutils.core import setup + +AppName = "patool" +AppVersion = "0.1" +MyName = "Bastian Kleineidam" +MyEmail = "calvin@users.sourceforge.net" + +setup ( + name = AppName, + version = AppVersion, + description = "simple manager for file archives of various types", + author = MyName, + author_email = MyEmail, + maintainer = MyName, + maintainer_email = MyEmail, + license = "GPL", + packages = ['patoolib'], + scripts = ['patool'], +) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..f1915f4 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +import unittest +import os +import shutil +import nose +import patoolib +from distutils.spawn import find_executable + +basedir = os.path.dirname(__file__) +datadir = os.path.join(basedir, 'data') + +class ArchiveTest (unittest.TestCase): + """Helper class for achive tests.""" + + def archive_test (self, filename, cmd): + self.archive_list(filename, cmd) + self.archive_extract(filename, cmd) + + def archive_extract (self, filename, cmd): + archive = os.path.join(datadir, filename) + # create a temporary directory for extraction + tmpdir = patoolib.util.tmpdir(dir=basedir) + os.chdir(tmpdir) + try: + patoolib._handle_archive(archive, 'extract', cmd=cmd) + patoolib._handle_archive(archive, 'extract', cmd=cmd, force=True) + finally: + os.chdir(basedir) + shutil.rmtree(tmpdir) + + def archive_list (self, filename, cmd): + archive = os.path.join(datadir, filename) + patoolib._handle_archive(archive, 'list', cmd=cmd) + patoolib._handle_archive(archive, 'list', cmd=cmd, verbose=True) + + +def needs_cmd (cmd): + """Decorator skipping test if given command is not available.""" + def check_prog (f): + def newfunc (*args, **kwargs): + if not find_executable(cmd): + raise nose.SkipTest("command `%s' not available" % cmd) + return f(*args, **kwargs) + newfunc.func_name = f.func_name + return newfunc + return check_prog diff --git a/tests/data/t.7z b/tests/data/t.7z new file mode 100644 index 0000000000000000000000000000000000000000..32772431a1b52a454a484b4eae79492e3b9adf15 GIT binary patch literal 158 zcmXr7+Ou9=hJiV|&iHm50|Y2Q>0S4%o-#=B)OxM~2{anBuj4;wfB1QamZ7}ORdIK- zk~=Tnyx;t*e9>&q_Ndd_v@Rd#ea)Bea{rAH>pwQBiS1D=;wO4Pf6a=@4f`YNxuH0? z==`;UH8(?hE^|*e)b|IPDbB{h$Qj1K&dtccsLagB$QsKaz`($h$i)~r>3|;t0|46s BG*18k literal 0 HcmV?d00001 diff --git a/tests/data/t.Z b/tests/data/t.Z new file mode 100644 index 0000000000000000000000000000000000000000..e421820a88b0877bd13aa8ecd029aa8399e8977b GIT binary patch literal 375 zcmV--0f_z|osdl4$SKnXL>f4A>J%jNhK)cFbJEZO5vENUIxIkpdE;iz#fx?1Knz3X z;G8jO+?)YXhK)oy89kB#QL-WkHyjn_VVOown>RD*5QOtErJXcn>bRL$XCj+0Vg#09 zIgz2mfgsw1IpZb_MVE2vm^m}g)Dctm%s@98ai;akc}*Iv zoJYDDBlq!~i2(-|G^vngW04UjR=ij@H$j64ds}@NoT5dv8#{iK3!J1$lqy+nhM9J4 z8k;!X=;Y}WCA3dR4G%ZP^JD|j#VpHuVKK7C2JO~Oq$=d^;TSS)pZvLdC9R? z8GZc~Mqq;#2Et*tDOLw#SC#SDL}f@;24!tnhM7j2b@o|kqm_1AYI}LaS{Sau<`rSH V)yC3oAQ-n>atr+ikwnfBrvR;hMVSyk-_sQ4>@BKgw;+5!^=#^BIFfa&csN7&+Ffrmvc*Vc~0I(<+*8l(j literal 0 HcmV?d00001 diff --git a/tests/data/t.bz2 b/tests/data/t.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..99ca112240a0399a4fa77499b0bdd74353e2cc2c GIT binary patch literal 40 wcmZ>Y%CIzaj8qGby!NJdJ_7@z2LpqE2!jHH;ta{g#B!D3R!-i$6E{Bq0PXh-k^lez literal 0 HcmV?d00001 diff --git a/tests/data/t.cab b/tests/data/t.cab new file mode 100644 index 0000000000000000000000000000000000000000..f9a1bbf6cb221486613496b968ca760f4c755549 GIT binary patch literal 79 zcmeYbc6MU`0)G$z1Ue9kftit!ff2~Q#KOSf0;EA~W~dwkL$HmkodQEiOo?7eMF|6^ NkvUL~nZd+}3jq2v2aNy# literal 0 HcmV?d00001 diff --git a/tests/data/t.cpio b/tests/data/t.cpio new file mode 100644 index 0000000000000000000000000000000000000000..22709db928112a971ae42e14a3bcd9b9add7f1d7 GIT binary patch literal 512 zcmX?J$o|i*>4oD9<`>LN3=9l)-cw9KGy_8k!*QToK+}RokQ^geF3N-hNHa5(=$Gh~ nRFp877;ynrfmA~PNEHZhgUOH}M^7KuAVoz*Fn5#~gdqR`PL~!& literal 0 HcmV?d00001 diff --git a/tests/data/t.deb b/tests/data/t.deb new file mode 100644 index 0000000000000000000000000000000000000000..7bb4cbd173b5e633f98f05a8a6c6bf7ef4dd758c GIT binary patch literal 2004 zcma)+dpHvcAIGQh5;jZalA6s>Czm#NVq_6RnxwGUM9e~IZXsdfaC#|(RU5J-9k<*o zmqXiOB+H$OM7hl5nl;<0=Xu}rod4eU^ZcIg^Zfq!{`LDjKe#0^{6Y{~)<3|HL=4sQ zBZU&fV_+~C%D~Xvz}U#Z%n$}c{@DMUC?wLv$Os1eG5>)eYoL#my$}{k2@kuZPa%fu z2VVO>`le=o_ti6G06*CQ=8tbN@O2fxB z2djE;Qa5y?)x}Dim0!i~El?NZBhzs+tCdXQ^p-LnPj7{!1Q|?HM8lOXWf5nF4#jkp zpZt?{?@q?Pg|XU^{2hdXj%!uCYh(P{s0Z&3cuQOBBCc0!GmNtB5<_$voBMe#TVCDT z#?2l|ETb0-(Alb!3K{L3MS8%em<8(t!SdImS%OOc^+u5s4!3Qc63g5SPE|9@o9U+I zwgblnT3?K+_Ny^aJwwky%Xo*D!y~DMv1&NBR*8x+&8y~Uz5wzdBCjWtlIaCx~l^AE?XHm74pw$s%OwMhADtU z0DwP{Li}5cA2nFOg6u!c@bnHF!$Mw@w{`5X>VRFzO&*T>4$!ng79>Rp zQtm-=^>Fl=X}jlSH^vk3b`R|+ocf5mwm(KgDmHRsykP5M7(r>n2cLduJ=l2bxTnaO zuE%*Y$a&?)3@U2zIpVQV*xUg8wM1hF!S!;*(5Tg*NPX`!h$HS>$G3*`Gv&0E)}tb( ztE8ULT8m#U0 zMbu=1$y%9m7CkhqWgB&MtF$_=8?l;jpQ&sC6bb~sHBaV5Vp-vlr$Uj*mhUss*^IgX zkqo_@K!e`s~srZ1dFs$ zwWwSK7)ivr#teK*fJ0ZA#7o(btmPvL;S%MuV)V`6ni`AXZlj z+>;^@c8S06>?KUI&`|}-q?vQ!Kxk+obm+SJ&>vzeX;x0rbS z&N}mXN#<5=U-e!?>mLF&wOV*IFZc}B3Zv0Cs>800&`LI-;~sGAV-`rUT2-KJ3X1){EEaBT2{ z#2ov7(|VsGFt315PN;?74=k9deFcv0+pzTxFqBFAiqy|fU(L@xb@*}|o)IoMlq3BP zT6n=J1i!YE6+*i>6by1nyL!b7r~RY@*#aLX)6<3lEv?OdUiIJ=v+lD6vLs%O{|vDI=9JLQpBZt z)a|kliTiVxvEiQ$-aib+gCkArBg*_|$-X*JCb1&NfD<5)##6YC$)QG`+D2Tjzqi$>V zE0+6E&AbdW4ARw literal 0 HcmV?d00001 diff --git a/tests/data/t.gz b/tests/data/t.gz new file mode 100644 index 0000000000000000000000000000000000000000..6434a262640aa9cfb575ab75d0ea7be8d7f980a2 GIT binary patch literal 25 gcmb2|=HMtdt@CDJE@3b>e8j|HsM&UrnSp@;08Oj~qW}N^ literal 0 HcmV?d00001 diff --git a/tests/data/t.jar b/tests/data/t.jar new file mode 100644 index 0000000000000000000000000000000000000000..259e76502ed0eee4375ad75a727a20d837071e73 GIT binary patch literal 447 zcmWIWW@h1H0D-^TLTtbcD8UJ&eO*Hwbv^yu^aD_oiDsX$(f~?>un4j;Uq?SrH`m}0 zJzqE9#JtS3)Z!A|u+*aB%=|nn1w%apF6W}u#FEq$U8hPb1p_@x3ob5%$u@SuC=Or( znp^_6nS((VC~v6Qc99h*&J4utVEGcgl8O>z!$(XE0p5&ETnxB915}O#ki3Sf4c&7H zJ?cOvTpN;CkuApN34{raKqkmbFdMOZ3ZZ@>SUuQ_0p6@^APE*Aya%LDgE$NT+f6|q literal 0 HcmV?d00001 diff --git a/tests/data/t.lzo b/tests/data/t.lzo new file mode 100644 index 0000000000000000000000000000000000000000..100be4dcdfc7187346a15032322dda5677b316c6 GIT binary patch literal 58 zcmeD5iSlRQ<&xqOP*5=7bYNsiY`Z9H7i=SI%+9c&k%6HkrbMr# wqJ)S2%jqwL(|>OI|7BLPe940bMW}v=HU=A@77+tRh8K=NEk|st864Od0E{Ub%m4rY literal 0 HcmV?d00001 diff --git a/tests/data/t.rpm b/tests/data/t.rpm new file mode 100644 index 0000000000000000000000000000000000000000..8df4390b150af4af513904668215c377880dbaa7 GIT binary patch literal 10288 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 He->Zhf}}bj literal 0 HcmV?d00001 diff --git a/tests/data/t.tar.gz b/tests/data/t.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..e39819f466d34b7a9f9f185a4fa62c9cbc64e473 GIT binary patch literal 151 zcmb2|=3tm%Qs>RU{PvwQF&QHL`P{FZ0vsh={_OV^ z<9u?k+i%wC%?r<;zS3T)yy~5Ep|SQP({O2(uWuK3%J3V$3!Zd#hpq4K=jHFe*=y~J zIBq%XUj)~>r=kDr-pAj4_HXMf?^C|Pv41Q79}Tx0#7SgMk46@NPsL literal 0 HcmV?d00001 diff --git a/tests/data/t.tbz2 b/tests/data/t.tbz2 new file mode 100644 index 0000000000000000000000000000000000000000..f4a0f05b1fc939c3433783a804c7af3932e58439 GIT binary patch literal 153 zcmV;K0A~L}T4*^jL0KkKS#$WZ{{R4{dxXJ|0Rlh)|9}7?XeA#&00ICAAOMjKA{ar5 zrhv(s2^14TWNDLX3`U-gcj-1(A#{6#&B4O0B&tn8}i#IT*BAb@a55MIQsP0;k~EHwIW7>A8y77!GhE0^;sSrwS4d He->Zhf}}bj literal 0 HcmV?d00001 diff --git a/tests/data/t.txt.gz b/tests/data/t.txt.gz new file mode 100644 index 0000000000000000000000000000000000000000..c5a72cf6ce4a6246594bd62f063a4217eda52045 GIT binary patch literal 29 kcmb2|=HPH!UGL4nT%uP}QNmzs_=t(YP_ykKGXnzy0C(aCcK`qY literal 0 HcmV?d00001 diff --git a/tests/data/t.zip b/tests/data/t.zip new file mode 100644 index 0000000000000000000000000000000000000000..8b9719c87d213d6b0f75b6a82d1d3f7182eca5db GIT binary patch literal 299 zcmWIWW@h1H0D;YR!8Tw9lwe|zVJOiL4dG;9E;Oz4E(7Ay3T_5QmKV$n3}7Mvu2&YQ z*HE+VB2b0_gxSG*OY}-AO27t0nbdigV;W#$#1-Jp$Rx*%%LNipw+Jx2a0D?y?qP+v t2g5B0b1+>4F^3Uo!h%MSCrk99ZUY(yavO$WtZX3bn1FC9kZu5R7yvtkEt&uT literal 0 HcmV?d00001 diff --git a/tests/test_archives.py b/tests/test_archives.py new file mode 100644 index 0000000..e7caacf --- /dev/null +++ b/tests/test_archives.py @@ -0,0 +1,130 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +from . import ArchiveTest, needs_cmd + +class TestArchives (ArchiveTest): + + @needs_cmd('tar') + def test_tar (self): + self.tar_test('tar') + + @needs_cmd('star') + def test_star (self): + self.tar_test('star') + + def tar_test (self, cmd): + self.archive_test('t.tar', cmd) + self.archive_test('t.tar.gz', cmd) + self.archive_test('t.tar.Z', cmd) + self.archive_test('t.tar.bz2', cmd) + self.archive_test('t.tbz2', cmd) + + @needs_cmd('bzip2') + def test_bzip2 (self): + self.archive_extract('t.bz2', 'bzip2') + + @needs_cmd('pbzip2') + def test_pbzip2 (self): + self.archive_extract('t.bz2', 'pbzip2') + + @needs_cmd('echo') + def test_echo (self): + self.archive_list('t.bz2', 'echo') + self.archive_list('t.Z', 'echo') + + @needs_cmd('unzip') + def test_unzip (self): + self.archive_test('t.zip', 'unzip') + self.archive_test('t.jar', 'unzip') + + @needs_cmd('gzip') + def test_gzip (self): + self.archive_test('t.gz', 'gzip') + self.archive_test('t.txt.gz', 'gzip') + self.archive_extract('t.Z', 'gzip') + + @needs_cmd('uncompress.real') + def test_uncompress (self): + self.archive_extract('t.Z', 'uncompress.real') + + @needs_cmd('7z') + def test_p7zip (self): + self.archive_test('t.7z', '7z') + self.archive_list('t.gz', '7z') + self.archive_list('t.bz2', '7z') + self.archive_list('t.zip', '7z') + self.archive_list('t.jar', '7z') + self.archive_list('t.Z', '7z') + self.archive_list('t.rar', '7z') + self.archive_list('t.cab', '7z') + self.archive_list('t.arj', '7z') + self.archive_list('t.cpio', '7z') + self.archive_list('t.rpm', '7z') + self.archive_list('t.deb', '7z') + self.archive_extract('t.gz', '7z') + self.archive_extract('t.bz2', '7z') + self.archive_extract('t.zip', '7z') + self.archive_extract('t.jar', '7z') + self.archive_extract('t.Z', '7z') + self.archive_extract('t.rar', '7z') + self.archive_extract('t.cab', '7z') + self.archive_extract('t.arj', '7z') + self.archive_extract('t.cpio', '7z') + self.archive_extract('t.rpm', '7z') + self.archive_extract('t.deb', '7z') + + @needs_cmd('unrar') + def test_unrar (self): + self.archive_list('t.rar', 'unrar') + self.archive_extract('t.rar', 'unrar') + + @needs_cmd('rar') + def test_rar (self): + self.archive_test('t.rar', 'rar') + + @needs_cmd('cabextract') + def test_capextract (self): + self.archive_list('t.cab', 'cabextract') + self.archive_extract('t.cab', 'cabextract') + + @needs_cmd('arj') + def test_arj (self): + self.archive_list('t.arj', 'arj') + self.archive_extract('t.arj', 'arj') + + @needs_cmd('cpio') + def test_cpio (self): + self.archive_list('t.cpio', 'cpio') + self.archive_extract('t.cpio', 'cpio') + + @needs_cmd('rpm') + def test_rpm (self): + self.archive_list('t.rpm', 'rpm') + + @needs_cmd('rpm2cpio') + @needs_cmd('cpio') + def test_rpm_extract (self): + self.archive_extract('t.rpm', 'rpm2cpio') + + @needs_cmd('dpkg-deb') + def test_dpkg (self): + self.archive_list('t.deb', 'dpkg') + self.archive_extract('t.deb', 'dpkg') + + @needs_cmd('lzop') + def test_lzop (self): + self.archive_test('t.lzo', 'lzop') + diff --git a/tests/test_config.py b/tests/test_config.py new file mode 100644 index 0000000..0babc07 --- /dev/null +++ b/tests/test_config.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2010 Bastian Kleineidam +# +# 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 . +import unittest +import patoolib + +class TestConfiguration (unittest.TestCase): + + def test_archive_mimetypes (self): + # test that each format has a MIME type + self.assertEqual(set(patoolib.ArchiveFormats), + set(patoolib.ArchiveMimetypes.values())) + + def test_archive_programs (self): + # test that the key is an archive format + self.assertEqual(set(patoolib.ArchiveFormats), + set(patoolib.ArchivePrograms.keys())) + for modes in patoolib.ArchivePrograms.values(): + for mode in modes: + if mode is not None: + self.assertTrue(mode in patoolib.CommandModes)