From fefe84bd3f868e35bd67411300d1175871b77c84 Mon Sep 17 00:00:00 2001 From: Le Minh Tri Date: Sat, 20 May 2023 15:34:55 +0700 Subject: [PATCH] chore: initial commit --- .github/FUNDING.yml | 16 + .github/workflows/go.yml | 38 ++ .gitignore | 22 ++ LICENSE | 661 ++++++++++++++++++++++++++++++++ Makefile | 16 + README.md | 30 ++ decompress.go | 65 ++++ decompress_test.go | 108 ++++++ go.mod | 5 + go.sum | 2 + testdata/sample.tar.xz | Bin 0 -> 18064 bytes testdata/sample/MIT_LICENSE | 21 + testdata/sample/MIT_LICENSE.pdf | Bin 0 -> 18239 bytes 13 files changed, 984 insertions(+) create mode 100644 .github/FUNDING.yml create mode 100644 .github/workflows/go.yml create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 decompress.go create mode 100644 decompress_test.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 testdata/sample.tar.xz create mode 100644 testdata/sample/MIT_LICENSE create mode 100644 testdata/sample/MIT_LICENSE.pdf diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..df86c1e --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,16 @@ +# These are supported funding model platforms + +github: [ansidev] +patreon: ansidev +# open_collective: # Replace with a single Open Collective username +# ko_fi: # Replace with a single Ko-fi username +# tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +# community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +# liberapay: # Replace with a single Liberapay username +# issuehunt: # Replace with a single IssueHunt username +# otechie: # Replace with a single Otechie username +# lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry +custom: + - https://paypal.me/ansidev + - https://buymeacoffee.com/ansidev + - https://me.momo.vn/ansidev diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml new file mode 100644 index 0000000..e5a9913 --- /dev/null +++ b/.github/workflows/go.yml @@ -0,0 +1,38 @@ +name: Go CI +on: + push: + tags: + - v* + branches: + - main + pull_request: +permissions: + contents: read + # Optional: allow read access to pull request. Use with `only-new-issues` option. + # pull-requests: read +jobs: + golangci: + strategy: + matrix: + os: [macos-latest, windows-latest, ubuntu-latest] + go-version: ['1.18', '1.19', '1.20'] + name: lint + runs-on: ${{ matrix.os }} + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup Go environment + uses: actions/setup-go@v4 + with: + go-version: ${{ matrix.go-version }} + + - name: Run golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. + version: v1.52 + args: --timeout=3m + + - name: Test + run: go test -v ./... diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c90dedd --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +# IDE and code editor directories +.vscode/ +.idea/ +.fleet/ + +bin/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0ad25db --- /dev/null +++ b/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 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 Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are 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. + + 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. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + 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 Affero 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. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + 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 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 work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero 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 Affero 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 Affero 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 Affero 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 Affero 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + 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 AGPL, see +. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..075febd --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +prepare: + @echo "Installing golangci-lint" + go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest + # @echo "Install Husky" + # @go install github.com/go-courier/husky/cmd/husky@latest && husky init + +dependency: + @go get -v ./... + +test: dependency + @go test ./... + +coverage: dependency + @go test -cover ./... + +.PHONY: prepare dependency test coverage diff --git a/README.md b/README.md new file mode 100644 index 0000000..5b63c66 --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +# tar-xz + +## Introduction + +A simple Go module for decompressing a tar.xz file. + +## Example + +```go +package main + +import ( + tarXz "github.com/ansidev/tar-xz" +) + +func main() { + err := tarXz.Decompress("archive.tar.xz", "/path/to/output/dir") + if err != nil { + log.Fatal(err) + } +} +``` + +## Contact + +Le Minh Tri [@ansidev](https://ansidev.xyz/about). + +## License + +This source code is available under the [AGPL-3.0 LICENSE](/LICENSE). diff --git a/decompress.go b/decompress.go new file mode 100644 index 0000000..c71f36b --- /dev/null +++ b/decompress.go @@ -0,0 +1,65 @@ +package main + +import ( + "archive/tar" + "bytes" + "io" + "os" + "path/filepath" + + "github.com/xi2/xz" +) + +func Decompress(filePath string, destDir string) error { + f, err := os.ReadFile(filePath) + if err != nil { + return err + } + + // Create an xz Reader to read the compressed data + xr, err := xz.NewReader(bytes.NewReader(f), 0) + if err != nil { + return err + } + + // Open and iterate through the files in the archive. + tr := tar.NewReader(xr) + for { + hdr, err := tr.Next() + if err == io.EOF { + break + } + + if err != nil { + return err + } + + destFilePath := filepath.Join(destDir, hdr.Name) + destFileParentDir := filepath.Dir(destFilePath) + + // Create the parent directory path if it does not exist + err = os.MkdirAll(destFileParentDir, 0755) + if err != nil { + return err + } + + if hdr.Typeflag == tar.TypeDir { + continue + } + + if hdr.Typeflag == tar.TypeReg { + destFile, err := os.Create(destFilePath) + if err != nil { + return err + } + + defer destFile.Close() + + if _, err := io.Copy(destFile, tr); err != nil { + return err + } + } + } + + return nil +} diff --git a/decompress_test.go b/decompress_test.go new file mode 100644 index 0000000..426d72e --- /dev/null +++ b/decompress_test.go @@ -0,0 +1,108 @@ +package main + +import ( + "crypto/sha256" + "fmt" + "os" + "path/filepath" + "testing" +) + +const testDataDir = "testdata" +const testFileHash string = "dc8897816b30ddee02e83f4d285916731d7940d8b6fc03aab4e71185649034fd" + +func getSHA256Checksum(filePath string) (string, error) { + buf, err := os.ReadFile(filePath) + if err != nil { + return "", err + } + + return fmt.Sprintf("%x", sha256.Sum256(buf)), nil +} + +func removeDir(t *testing.T, dirPath string) { + err := os.RemoveAll(dirPath) + if err != nil { + t.Errorf("Failed to remove the directory: %v", err) + } +} + +func compareFileHash(t *testing.T, actualDirPath string, expectedDirPath string, verifyPaths []string) { + for _, path := range verifyPaths { + actualFilePath := filepath.Join(actualDirPath, path) + expectedFilePath := filepath.Join(expectedDirPath, path) + + actualFileHash, err := getSHA256Checksum(actualFilePath) + if err != nil { + t.Errorf("Failed to get SHA256 checksum of the actual file: %v", err) + } + + expectedFileHash, err := getSHA256Checksum(expectedFilePath) + if err != nil { + t.Errorf("Failed to get SHA256 checksum of the expected file: %v", err) + } + + if actualFileHash != expectedFileHash { + t.Errorf("Mismatched checksum. Got: %v, want: %v", actualFileHash, expectedFileHash) + } + } +} + +func testGetSHA256Checksum(t *testing.T) { + sum, err := getSHA256Checksum(filepath.Join(testDataDir, "sample.tar.xz")) + if err != nil { + t.Errorf("Internal function getSHA256Checksum() error: %v", err) + } + + if sum != testFileHash { + t.Errorf("Unmatched test file checksum. Got: %v, want: %v", sum, testFileHash) + } +} + +func TestDecompress(t *testing.T) { + type args struct { + filePath string + destDir string + verifyPaths []string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Decompress sample.tar.xz to ./sample_test", + args: args{ + filePath: filepath.Join(testDataDir, "sample.tar.xz"), + destDir: filepath.Join(testDataDir, "sample_test"), + verifyPaths: []string{ + filepath.Join("sample", "MIT_LICENSE"), + filepath.Join("sample", "MIT_LICENSE.pdf"), + }, + }, + wantErr: false, + }, + } + + // Test getSHA256Checksum first + testGetSHA256Checksum(t) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Remove the directory if exists before running the test case + if _, err := os.Stat(tt.args.destDir); !os.IsNotExist(err) { + removeDir(t, tt.args.destDir) + } + err := Decompress(tt.args.filePath, tt.args.destDir) + + // Remove the directory after running the test case + defer removeDir(t, tt.args.destDir) + + if (err != nil) != tt.wantErr { + t.Errorf("Decompress() error = %v, wantErr %v", err, tt.wantErr) + } else { + compareFileHash(t, testDataDir, tt.args.destDir, tt.args.verifyPaths) + } + }) + } +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..a6a5831 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module github.com/ansidev/tar-xz + +go 1.19 + +require github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..40eb409 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= diff --git a/testdata/sample.tar.xz b/testdata/sample.tar.xz new file mode 100644 index 0000000000000000000000000000000000000000..bbcc64a17317acfcb5e0c719fd1b9c5ea1a64f4e GIT binary patch literal 18064 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 literal 0 HcmV?d00001 diff --git a/testdata/sample/MIT_LICENSE b/testdata/sample/MIT_LICENSE new file mode 100644 index 0000000..8aa2645 --- /dev/null +++ b/testdata/sample/MIT_LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) [year] [fullname] + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/testdata/sample/MIT_LICENSE.pdf b/testdata/sample/MIT_LICENSE.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e6cfe86c8ae2c760d3438d6259ae211b45bee06b GIT binary patch literal 18239 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