From: Michael Vrable Date: Wed, 28 Oct 2015 04:22:57 +0000 (-0700) Subject: Delete old libs3 sources. X-Git-Url: http://git.vrable.net/?p=bluesky.git;a=commitdiff_plain;h=c0202777b783b74e0c9d580f58eaa69889a6874e Delete old libs3 sources. --- diff --git a/libs3-1.4/.gitignore b/libs3-1.4/.gitignore deleted file mode 100644 index 378eac2..0000000 --- a/libs3-1.4/.gitignore +++ /dev/null @@ -1 +0,0 @@ -build diff --git a/libs3-1.4/COPYING b/libs3-1.4/COPYING deleted file mode 100644 index 94a9ed0..0000000 --- a/libs3-1.4/COPYING +++ /dev/null @@ -1,674 +0,0 @@ - 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/libs3-1.4/ChangeLog b/libs3-1.4/ChangeLog deleted file mode 100644 index fc8797a..0000000 --- a/libs3-1.4/ChangeLog +++ /dev/null @@ -1,16 +0,0 @@ -Thu Sep 18 10:03:02 NZST 2008 bryan@ischo.com - * This file is no longer maintained, sorry - -Sat Aug 9 13:44:21 NZST 2008 bryan@ischo.com - * Fixed bug wherein keys with non-URI-safe characters did not work - correctly because they were not being URI-encoded in the request UR - * Split RPM and DEB packages into normal and devel packages - -Fri Aug 8 22:40:19 NZST 2008 bryan@ischo.com - * Branched 0.4 - * Created RPM and Debian packaging - -Tue Aug 5 08:52:33 NZST 2008 bryan@ischo.com - * Bumped version number to 0.3 - * Moved Makefile to GNUmakefile, added shared library build - * Added a bunch of GNU standard files (README, INSTALL, ChangeLog, etc) diff --git a/libs3-1.4/GNUmakefile b/libs3-1.4/GNUmakefile deleted file mode 100644 index eb16954..0000000 --- a/libs3-1.4/GNUmakefile +++ /dev/null @@ -1,307 +0,0 @@ -# GNUmakefile -# -# Copyright 2008 Bryan Ischo -# -# This file is part of libs3. -# -# libs3 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, version 3 of the License. -# -# In addition, as a special exception, the copyright holders give -# permission to link the code of this library and its programs with the -# OpenSSL library, and distribute linked combinations including the two. -# -# libs3 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 version 3 -# along with libs3, in a file named COPYING. If not, see -# . - -# I tried to use the autoconf/automake/autolocal/etc (i.e. autohell) tools -# but I just couldn't stomach them. Since this is a Makefile for POSIX -# systems, I will simply do away with autohell completely and use a GNU -# Makefile. GNU make ought to be available pretty much everywhere, so I -# don't see this being a significant issue for portability. - -# All commands assume a GNU compiler. For systems which do not use a GNU -# compiler, write scripts with the same names as these commands, and taking -# the same arguments, and translate the arguments and commands into the -# appropriate non-POSIX ones as needed. libs3 assumes a GNU toolchain as -# the most portable way to build software possible. Non-POSIX, non-GNU -# systems can do the work of supporting this build infrastructure. - - -# -------------------------------------------------------------------------- -# Set libs3 version number - -LIBS3_VER_MAJOR := 1 -LIBS3_VER_MINOR := 4 -LIBS3_VER := $(LIBS3_VER_MAJOR).$(LIBS3_VER_MINOR) - - -# -------------------------------------------------------------------------- -# BUILD directory -ifndef BUILD - BUILD := build -endif - - -# -------------------------------------------------------------------------- -# DESTDIR directory -ifndef DESTDIR - DESTDIR := /usr -endif - - -# -------------------------------------------------------------------------- -# Acquire configuration information for libraries that libs3 depends upon - -ifndef CURL_LIBS - CURL_LIBS := $(shell curl-config --libs) -endif - -ifndef CURL_CFLAGS - CURL_CFLAGS := $(shell curl-config --cflags) -endif - -ifndef LIBXML2_LIBS - LIBXML2_LIBS := $(shell xml2-config --libs) -endif - -ifndef LIBXML2_CFLAGS - LIBXML2_CFLAGS := $(shell xml2-config --cflags) -endif - - -# -------------------------------------------------------------------------- -# These CFLAGS assume a GNU compiler. For other compilers, write a script -# which converts these arguments into their equivalent for that particular -# compiler. - -ifndef CFLAGS - CFLAGS = -O3 -endif - -CFLAGS += -Wall -Werror -Wshadow -Wextra -Iinc \ - $(CURL_CFLAGS) $(LIBXML2_CFLAGS) \ - -DLIBS3_VER_MAJOR=\"$(LIBS3_VER_MAJOR)\" \ - -DLIBS3_VER_MINOR=\"$(LIBS3_VER_MINOR)\" \ - -DLIBS3_VER=\"$(LIBS3_VER)\" \ - -D__STRICT_ANSI__ \ - -D_ISOC99_SOURCE \ - -D_POSIX_C_SOURCE=200112L - -LDFLAGS = $(CURL_LIBS) $(LIBXML2_LIBS) -lpthread - - -# -------------------------------------------------------------------------- -# Default targets are everything - -.PHONY: all -all: exported test - - -# -------------------------------------------------------------------------- -# Exported targets are the library and driver program - -.PHONY: exported -exported: libs3 s3 headers - - -# -------------------------------------------------------------------------- -# Install target - -.PHONY: install -install: exported - install -Dps -m u+rwx,go+rx $(BUILD)/bin/s3 $(DESTDIR)/bin/s3 - install -Dp -m u+rw,go+r $(BUILD)/include/libs3.h \ - $(DESTDIR)/include/libs3.h - install -Dp -m u+rw,go+r $(BUILD)/lib/libs3.a $(DESTDIR)/lib/libs3.a - install -Dps -m u+rw,go+r $(BUILD)/lib/libs3.so.$(LIBS3_VER_MAJOR) \ - $(DESTDIR)/lib/libs3.so.$(LIBS3_VER) - ln -sf libs3.so.$(LIBS3_VER) $(DESTDIR)/lib/libs3.so.$(LIBS3_VER_MAJOR) - ln -sf libs3.so.$(LIBS3_VER_MAJOR) $(DESTDIR)/lib/libs3.so - - -# -------------------------------------------------------------------------- -# Uninstall target - -.PHONY: uninstall -uninstall: - rm -f $(DESTDIR)/bin/s3 \ - $(DESTDIR)/include/libs3.h \ - $(DESTDIR)/lib/libs3.a \ - $(DESTDIR)/lib/libs3.so \ - $(DESTDIR)/lib/libs3.so.$(LIBS3_VER_MAJOR) \ - $(DESTDIR)/lib/libs3.so.$(LIBS3_VER) \ - - -# -------------------------------------------------------------------------- -# Debian package target - -DEBPKG = $(BUILD)/pkg/libs3_$(LIBS3_VER).deb -DEBDEVPKG = $(BUILD)/pkg/libs3-dev_$(LIBS3_VER).deb - -.PHONY: deb -deb: $(DEBPKG) $(DEBDEVPKG) - -$(DEBPKG): DEBARCH = $(shell dpkg-architecture | grep ^DEB_BUILD_ARCH= | \ - cut -d '=' -f 2) -$(DEBPKG): exported $(BUILD)/deb/DEBIAN/control $(BUILD)/deb/DEBIAN/shlibs \ - $(BUILD)/deb/DEBIAN/postinst \ - $(BUILD)/deb/usr/share/doc/libs3/changelog.gz \ - $(BUILD)/deb/usr/share/doc/libs3/changelog.Debian.gz \ - $(BUILD)/deb/usr/share/doc/libs3/copyright - DESTDIR=$(BUILD)/deb/usr $(MAKE) install - rm -rf $(BUILD)/deb/usr/include - rm -f $(BUILD)/deb/usr/lib/libs3.a - @mkdir -p $(dir $@) - fakeroot dpkg-deb -b $(BUILD)/deb $@ - mv $@ $(BUILD)/pkg/libs3_$(LIBS3_VER)_$(DEBARCH).deb - -$(DEBDEVPKG): DEBARCH = $(shell dpkg-architecture | grep ^DEB_BUILD_ARCH= | \ - cut -d '=' -f 2) -$(DEBDEVPKG): exported $(BUILD)/deb-dev/DEBIAN/control \ - $(BUILD)/deb-dev/usr/share/doc/libs3-dev/changelog.gz \ - $(BUILD)/deb-dev/usr/share/doc/libs3-dev/changelog.Debian.gz \ - $(BUILD)/deb-dev/usr/share/doc/libs3-dev/copyright - DESTDIR=$(BUILD)/deb-dev/usr $(MAKE) install - rm -rf $(BUILD)/deb-dev/usr/bin - rm -f $(BUILD)/deb-dev/usr/lib/libs3.so* - @mkdir -p $(dir $@) - fakeroot dpkg-deb -b $(BUILD)/deb-dev $@ - mv $@ $(BUILD)/pkg/libs3-dev_$(LIBS3_VER)_$(DEBARCH).deb - -$(BUILD)/deb/DEBIAN/control: debian/control - @mkdir -p $(dir $@) - echo -n "Depends: " > $@ - dpkg-shlibdeps -O $(BUILD)/lib/libs3.so.$(LIBS3_VER_MAJOR) | \ - cut -d '=' -f 2- >> $@ - sed -e 's/LIBS3_VERSION/$(LIBS3_VER)/' \ - < $< | sed -e 's/DEBIAN_ARCHITECTURE/$(DEBARCH)/' | \ - grep -v ^Source: >> $@ - -$(BUILD)/deb-dev/DEBIAN/control: debian/control.dev - @mkdir -p $(dir $@) - sed -e 's/LIBS3_VERSION/$(LIBS3_VER)/' \ - < $< | sed -e 's/DEBIAN_ARCHITECTURE/$(DEBARCH)/' > $@ - -$(BUILD)/deb/DEBIAN/shlibs: - echo -n "libs3 $(LIBS3_VER_MAJOR) libs3 " > $@ - echo "(>= $(LIBS3_VER))" >> $@ - -$(BUILD)/deb/DEBIAN/postinst: debian/postinst - @mkdir -p $(dir $@) - cp $< $@ - -$(BUILD)/deb/usr/share/doc/libs3/copyright: LICENSE - @mkdir -p $(dir $@) - cp $< $@ - @echo >> $@ - @echo -n "An alternate location for the GNU General Public " >> $@ - @echo "License version 3 on Debian" >> $@ - @echo "systems is /usr/share/common-licenses/GPL-3." >> $@ - -$(BUILD)/deb-dev/usr/share/doc/libs3-dev/copyright: LICENSE - @mkdir -p $(dir $@) - cp $< $@ - @echo >> $@ - @echo -n "An alternate location for the GNU General Public " >> $@ - @echo "License version 3 on Debian" >> $@ - @echo "systems is /usr/share/common-licenses/GPL-3." >> $@ - -$(BUILD)/deb/usr/share/doc/libs3/changelog.gz: debian/changelog - @mkdir -p $(dir $@) - gzip --best -c $< > $@ - -$(BUILD)/deb-dev/usr/share/doc/libs3-dev/changelog.gz: debian/changelog - @mkdir -p $(dir $@) - gzip --best -c $< > $@ - -$(BUILD)/deb/usr/share/doc/libs3/changelog.Debian.gz: debian/changelog.Debian - @mkdir -p $(dir $@) - gzip --best -c $< > $@ - -$(BUILD)/deb-dev/usr/share/doc/libs3-dev/changelog.Debian.gz: \ - debian/changelog.Debian - @mkdir -p $(dir $@) - gzip --best -c $< > $@ - - -# -------------------------------------------------------------------------- -# Compile target patterns - -$(BUILD)/obj/%.o: src/%.c - @mkdir -p $(dir $@) - gcc $(CFLAGS) -o $@ -c $< - -$(BUILD)/obj/%.do: src/%.c - @mkdir -p $(dir $@) - gcc $(CFLAGS) -fpic -fPIC -o $@ -c $< - - -# -------------------------------------------------------------------------- -# libs3 library targets - -LIBS3_SHARED = $(BUILD)/lib/libs3.so.$(LIBS3_VER_MAJOR) - -.PHONY: libs3 -libs3: $(LIBS3_SHARED) $(BUILD)/lib/libs3.a - -LIBS3_SOURCES := src/acl.c src/bucket.c src/error_parser.c src/general.c \ - src/object.c src/request.c src/request_context.c \ - src/response_headers_handler.c src/service_access_logging.c \ - src/service.c src/simplexml.c src/util.c - -$(LIBS3_SHARED): $(LIBS3_SOURCES:src/%.c=$(BUILD)/obj/%.do) - @mkdir -p $(dir $@) - gcc -shared -Wl,-soname,libs3.so.$(LIBS3_VER_MAJOR) -o $@ $^ $(LDFLAGS) - -$(BUILD)/lib/libs3.a: $(LIBS3_SOURCES:src/%.c=$(BUILD)/obj/%.o) - @mkdir -p $(dir $@) - $(AR) cr $@ $^ - - -# -------------------------------------------------------------------------- -# Driver program targets - -.PHONY: s3 -s3: $(BUILD)/bin/s3 - -$(BUILD)/bin/s3: $(BUILD)/obj/s3.o $(LIBS3_SHARED) - @mkdir -p $(dir $@) - gcc -o $@ $^ $(LDFLAGS) - - -# -------------------------------------------------------------------------- -# libs3 header targets - -.PHONY: headers -headers: $(BUILD)/include/libs3.h - -$(BUILD)/include/libs3.h: inc/libs3.h - @mkdir -p $(dir $@) - cp $< $@ - - -# -------------------------------------------------------------------------- -# Test targets - -.PHONY: test -test: $(BUILD)/bin/testsimplexml - -$(BUILD)/bin/testsimplexml: $(BUILD)/obj/testsimplexml.o $(BUILD)/lib/libs3.a - @mkdir -p $(dir $@) - gcc -o $@ $^ $(LIBXML2_LIBS) - - -# -------------------------------------------------------------------------- -# Clean target - -.PHONY: clean -clean: - rm -rf $(BUILD) diff --git a/libs3-1.4/GNUmakefile.mingw b/libs3-1.4/GNUmakefile.mingw deleted file mode 100644 index aab4f02..0000000 --- a/libs3-1.4/GNUmakefile.mingw +++ /dev/null @@ -1,204 +0,0 @@ -# GNUmakefile -# -# Copyright 2008 Bryan Ischo -# -# This file is part of libs3. -# -# libs3 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, version 3 of the License. -# -# In addition, as a special exception, the copyright holders give -# permission to link the code of this library and its programs with the -# OpenSSL library, and distribute linked combinations including the two. -# -# libs3 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 version 3 -# along with libs3, in a file named COPYING. If not, see -# . - -# I tried to use the autoconf/automake/autolocal/etc (i.e. autohell) tools -# but I just couldn't stomach them. Since this is a Makefile for POSIX -# systems, I will simply do away with autohell completely and use a GNU -# Makefile. GNU make ought to be available pretty much everywhere, so I -# don't see this being a significant issue for portability. - -# All commands assume a GNU compiler. For systems which do not use a GNU -# compiler, write scripts with the same names as these commands, and taking -# the same arguments, and translate the arguments and commands into the -# appropriate non-POSIX ones as needed. libs3 assumes a GNU toolchain as -# the most portable way to build software possible. Non-POSIX, non-GNU -# systems can do the work of supporting this build infrastructure. - - -# -------------------------------------------------------------------------- -# Set libs3 version number - -LIBS3_VER_MAJOR := 1 -LIBS3_VER_MINOR := 4 -LIBS3_VER := $(LIBS3_VER_MAJOR).$(LIBS3_VER_MINOR) - - -# -------------------------------------------------------------------------- -# BUILD directory -ifndef BUILD - BUILD := build -endif - - -# -------------------------------------------------------------------------- -# DESTDIR directory -ifndef DESTDIR - DESTDIR := libs3-$(LIBS3_VER) -endif - - -# -------------------------------------------------------------------------- -# Acquire configuration information for libraries that libs3 depends upon - -ifndef CURL_LIBS - CURL_LIBS := -Lc:\libs3-libs\bin -lcurl -endif - -ifndef CURL_CFLAGS - CURL_CFLAGS := -Ic:\libs3-libs\include -endif - -ifndef LIBXML2_LIBS - LIBXML2_LIBS := -Lc:\libs3-libs\bin -lxml2 -endif - -ifndef LIBXML2_CFLAGS - LIBXML2_CFLAGS := -Ic:\libs3-libs\include -endif - - -# -------------------------------------------------------------------------- -# These CFLAGS assume a GNU compiler. For other compilers, write a script -# which converts these arguments into their equivalent for that particular -# compiler. - -ifndef CFLAGS - CFLAGS = -O3 -endif - -CFLAGS += -Wall -Werror -Wshadow -Wextra -Iinc \ - $(CURL_CFLAGS) $(LIBXML2_CFLAGS) \ - -DLIBS3_VER_MAJOR=\"$(LIBS3_VER_MAJOR)\" \ - -DLIBS3_VER_MINOR=\"$(LIBS3_VER_MINOR)\" \ - -DLIBS3_VER=\"$(LIBS3_VER)\" \ - -D__STRICT_ANSI__ \ - -D_ISOC99_SOURCE \ - -D_POSIX_C_SOURCE=200112L \ - -Dsleep=Sleep -DFOPEN_EXTRA_FLAGS=\"b\" \ - -Iinc/mingw -include windows.h - -LDFLAGS = $(CURL_LIBS) $(LIBXML2_LIBS) - -# -------------------------------------------------------------------------- -# Default targets are everything - -.PHONY: all -all: exported test - - -# -------------------------------------------------------------------------- -# Exported targets are the library and driver program - -.PHONY: exported -exported: libs3 s3 headers - - -# -------------------------------------------------------------------------- -# Install target - -.PHONY: install -install: exported - -@mkdir $(DESTDIR)\bin - -@mkdir $(DESTDIR)\include - -@mkdir $(DESTDIR)\lib - copy $(BUILD)\bin\s3.exe $(DESTDIR)\bin - copy $(BUILD)\bin\libs3.dll $(DESTDIR)\bin - copy $(BUILD)\lib\libs3.a $(DESTDIR)\lib - copy mswin\libs3.def $(DESTDIR)\lib - copy $(BUILD)\include\libs3.h $(DESTDIR)\include - copy LICENSE $(DESTDIR) - copy COPYING $(DESTDIR) - - -# -------------------------------------------------------------------------- -# Compile target patterns - -$(BUILD)/obj/%.o: src/%.c - -@mkdir $(subst /,\,$(dir $@)) - gcc $(CFLAGS) -o $@ -c $< - - -# -------------------------------------------------------------------------- -# libs3 library targets - -LIBS3_SHARED = $(BUILD)/bin/libs3.dll - -.PHONY: libs3 -libs3: $(LIBS3_SHARED) $(BUILD)/lib/libs3.a - -LIBS3_SOURCES := src/acl.c src/bucket.c src/error_parser.c src/general.c \ - src/object.c src/request.c src/request_context.c \ - src/response_headers_handler.c src/service_access_logging.c \ - src/service.c src/simplexml.c src/util.c src/mingw_functions.c - -$(LIBS3_SHARED): $(LIBS3_SOURCES:src/%.c=$(BUILD)/obj/%.o) - -@mkdir $(subst /,\,$(dir $@)) - gcc -shared -o $@ $^ $(LDFLAGS) -lws2_32 - -$(BUILD)/lib/libs3.a: $(LIBS3_SHARED) - -@mkdir $(subst /,\,$(dir $@)) - dlltool --def mswin\libs3.def --dllname $(subst /,\,$<) \ - --output-lib $(subst /,\,$@) - - -# -------------------------------------------------------------------------- -# Driver program targets - -.PHONY: s3 -s3: $(BUILD)/bin/s3.exe - -$(BUILD)/bin/s3.exe: $(BUILD)/obj/s3.o $(BUILD)/obj/mingw_s3_functions.o \ - $(BUILD)/lib/libs3.a - -@mkdir $(subst /,\,$(dir $@)) - gcc -o $@ $^ $(LDFLAGS) -lws2_32 - - -# -------------------------------------------------------------------------- -# libs3 header targets - -.PHONY: headers -headers: $(BUILD)\include\libs3.h - -$(BUILD)\include\libs3.h: inc\libs3.h - -@mkdir $(subst /,\,$(dir $@)) - copy $< $@ - - -# -------------------------------------------------------------------------- -# Test targets - -.PHONY: test -test: $(BUILD)/bin/testsimplexml - -$(BUILD)/bin/testsimplexml: $(BUILD)/obj/testsimplexml.o \ - $(BUILD)/obj/simplexml.o - -@mkdir $(subst /,\,$(dir $@)) - gcc -o $@ $^ $(LIBXML2_LIBS) - - -# -------------------------------------------------------------------------- -# Clean target - -.PHONY: clean -clean: - mswin\rmrf.bat $(BUILD) diff --git a/libs3-1.4/GNUmakefile.osx b/libs3-1.4/GNUmakefile.osx deleted file mode 100644 index 5d4bcbb..0000000 --- a/libs3-1.4/GNUmakefile.osx +++ /dev/null @@ -1,310 +0,0 @@ -# GNUmakefile -# -# Copyright 2008 Bryan Ischo -# -# This file is part of libs3. -# -# libs3 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, version 3 of the License. -# -# In addition, as a special exception, the copyright holders give -# permission to link the code of this library and its programs with the -# OpenSSL library, and distribute linked combinations including the two. -# -# libs3 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 version 3 -# along with libs3, in a file named COPYING. If not, see -# . - -# I tried to use the autoconf/automake/autolocal/etc (i.e. autohell) tools -# but I just couldn't stomach them. Since this is a Makefile for POSIX -# systems, I will simply do away with autohell completely and use a GNU -# Makefile. GNU make ought to be available pretty much everywhere, so I -# don't see this being a significant issue for portability. - -# All commands assume a GNU compiler. For systems which do not use a GNU -# compiler, write scripts with the same names as these commands, and taking -# the same arguments, and translate the arguments and commands into the -# appropriate non-POSIX ones as needed. libs3 assumes a GNU toolchain as -# the most portable way to build software possible. Non-POSIX, non-GNU -# systems can do the work of supporting this build infrastructure. - - -# -------------------------------------------------------------------------- -# Set libs3 version number - -LIBS3_VER_MAJOR := 1 -LIBS3_VER_MINOR := 4 -LIBS3_VER := $(LIBS3_VER_MAJOR).$(LIBS3_VER_MINOR) - - -# -------------------------------------------------------------------------- -# BUILD directory -ifndef BUILD - BUILD := build -endif - - -# -------------------------------------------------------------------------- -# DESTDIR directory -ifndef DESTDIR - DESTDIR := /usr -endif - - -# -------------------------------------------------------------------------- -# Acquire configuration information for libraries that libs3 depends upon - -ifndef CURL_LIBS - CURL_LIBS := $(shell curl-config --libs) -endif - -ifndef CURL_CFLAGS - CURL_CFLAGS := $(shell curl-config --cflags) -endif - -ifndef LIBXML2_LIBS - LIBXML2_LIBS := $(shell xml2-config --libs) -endif - -ifndef LIBXML2_CFLAGS - LIBXML2_CFLAGS := $(shell xml2-config --cflags) -endif - - -# -------------------------------------------------------------------------- -# These CFLAGS assume a GNU compiler. For other compilers, write a script -# which converts these arguments into their equivalent for that particular -# compiler. - -ifndef CFLAGS - CFLAGS = -O3 -endif - -CFLAGS += -Wall -Werror -Wshadow -Wextra -Iinc \ - $(CURL_CFLAGS) $(LIBXML2_CFLAGS) \ - -DLIBS3_VER_MAJOR=\"$(LIBS3_VER_MAJOR)\" \ - -DLIBS3_VER_MINOR=\"$(LIBS3_VER_MINOR)\" \ - -DLIBS3_VER=\"$(LIBS3_VER)\" \ - -D__STRICT_ANSI__ \ - -D_ISOC99_SOURCE \ - -fno-common - -LDFLAGS = $(CURL_LIBS) $(LIBXML2_LIBS) -lpthread - - -# -------------------------------------------------------------------------- -# Default targets are everything - -.PHONY: all -all: exported test - - -# -------------------------------------------------------------------------- -# Exported targets are the library and driver program - -.PHONY: exported -exported: libs3 s3 headers - - -# -------------------------------------------------------------------------- -# Install target - -.PHONY: install -install: exported - install -ps -m u+rwx,go+rx $(BUILD)/bin/s3 $(DESTDIR)/bin/s3 - install -p -m u+rw,go+r $(BUILD)/include/libs3.h \ - $(DESTDIR)/include/libs3.h - install -p -m u+rw,go+r $(BUILD)/lib/libs3.a $(DESTDIR)/lib/libs3.a - install -p -m u+rw,go+r $(BUILD)/lib/libs3.$(LIBS3_VER_MAJOR).dylib \ - $(DESTDIR)/lib/libs3.$(LIBS3_VER).dylib - ln -sf libs3.$(LIBS3_VER).dylib \ - $(DESTDIR)/lib/libs3.$(LIBS3_VER_MAJOR).dylib - ln -sf libs3.$(LIBS3_VER_MAJOR).dylib $(DESTDIR)/lib/libs3.dylib - - -# -------------------------------------------------------------------------- -# Uninstall target - -.PHONY: uninstall -uninstall: - rm -f $(DESTDIR)/bin/s3 \ - $(DESTDIR)/include/libs3.h \ - $(DESTDIR)/lib/libs3.a \ - $(DESTDIR)/lib/libs3.dylib \ - $(DESTDIR)/lib/libs3.$(LIBS3_VER_MAJOR).dylib \ - $(DESTDIR)/lib/libs3.$(LIBS3_VER).dylib \ - - -# -------------------------------------------------------------------------- -# Debian package target - -DEBPKG = $(BUILD)/pkg/libs3_$(LIBS3_VER).deb -DEBDEVPKG = $(BUILD)/pkg/libs3-dev_$(LIBS3_VER).deb - -.PHONY: deb -deb: $(DEBPKG) $(DEBDEVPKG) - -$(DEBPKG): DEBARCH = $(shell dpkg-architecture | grep ^DEB_BUILD_ARCH= | \ - cut -d '=' -f 2) -$(DEBPKG): exported $(BUILD)/deb/DEBIAN/control $(BUILD)/deb/DEBIAN/shlibs \ - $(BUILD)/deb/DEBIAN/postinst \ - $(BUILD)/deb/usr/share/doc/libs3/changelog.gz \ - $(BUILD)/deb/usr/share/doc/libs3/changelog.Debian.gz \ - $(BUILD)/deb/usr/share/doc/libs3/copyright - DESTDIR=$(BUILD)/deb/usr $(MAKE) install - rm -rf $(BUILD)/deb/usr/include - rm -f $(BUILD)/deb/usr/lib/libs3.a - @mkdir -p $(dir $@) - fakeroot dpkg-deb -b $(BUILD)/deb $@ - mv $@ $(BUILD)/pkg/libs3_$(LIBS3_VER)_$(DEBARCH).deb - -$(DEBDEVPKG): DEBARCH = $(shell dpkg-architecture | grep ^DEB_BUILD_ARCH= | \ - cut -d '=' -f 2) -$(DEBDEVPKG): exported $(BUILD)/deb-dev/DEBIAN/control \ - $(BUILD)/deb-dev/usr/share/doc/libs3-dev/changelog.gz \ - $(BUILD)/deb-dev/usr/share/doc/libs3-dev/changelog.Debian.gz \ - $(BUILD)/deb-dev/usr/share/doc/libs3-dev/copyright - DESTDIR=$(BUILD)/deb-dev/usr $(MAKE) install - rm -rf $(BUILD)/deb-dev/usr/bin - rm -f $(BUILD)/deb-dev/usr/lib/libs3*.dylib - @mkdir -p $(dir $@) - fakeroot dpkg-deb -b $(BUILD)/deb-dev $@ - mv $@ $(BUILD)/pkg/libs3-dev_$(LIBS3_VER)_$(DEBARCH).deb - -$(BUILD)/deb/DEBIAN/control: debian/control - @mkdir -p $(dir $@) - echo -n "Depends: " > $@ - dpkg-shlibdeps -O $(BUILD)/lib/libs3.$(LIBS3_VER_MAJOR).dylib | \ - cut -d '=' -f 2- >> $@ - sed -e 's/LIBS3_VERSION/$(LIBS3_VER)/' \ - < $< | sed -e 's/DEBIAN_ARCHITECTURE/$(DEBARCH)/' | \ - grep -v ^Source: >> $@ - -$(BUILD)/deb-dev/DEBIAN/control: debian/control.dev - @mkdir -p $(dir $@) - sed -e 's/LIBS3_VERSION/$(LIBS3_VER)/' \ - < $< | sed -e 's/DEBIAN_ARCHITECTURE/$(DEBARCH)/' > $@ - -$(BUILD)/deb/DEBIAN/shlibs: - echo -n "libs3 $(LIBS3_VER_MAJOR) libs3 " > $@ - echo "(>= $(LIBS3_VER))" >> $@ - -$(BUILD)/deb/DEBIAN/postinst: debian/postinst - @mkdir -p $(dir $@) - cp $< $@ - -$(BUILD)/deb/usr/share/doc/libs3/copyright: LICENSE - @mkdir -p $(dir $@) - cp $< $@ - @echo >> $@ - @echo -n "An alternate location for the GNU General Public " >> $@ - @echo "License version 3 on Debian" >> $@ - @echo "systems is /usr/share/common-licenses/GPL-3." >> $@ - -$(BUILD)/deb-dev/usr/share/doc/libs3-dev/copyright: LICENSE - @mkdir -p $(dir $@) - cp $< $@ - @echo >> $@ - @echo -n "An alternate location for the GNU General Public " >> $@ - @echo "License version 3 on Debian" >> $@ - @echo "systems is /usr/share/common-licenses/GPL-3." >> $@ - -$(BUILD)/deb/usr/share/doc/libs3/changelog.gz: debian/changelog - @mkdir -p $(dir $@) - gzip --best -c $< > $@ - -$(BUILD)/deb-dev/usr/share/doc/libs3-dev/changelog.gz: debian/changelog - @mkdir -p $(dir $@) - gzip --best -c $< > $@ - -$(BUILD)/deb/usr/share/doc/libs3/changelog.Debian.gz: debian/changelog.Debian - @mkdir -p $(dir $@) - gzip --best -c $< > $@ - -$(BUILD)/deb-dev/usr/share/doc/libs3-dev/changelog.Debian.gz: \ - debian/changelog.Debian - @mkdir -p $(dir $@) - gzip --best -c $< > $@ - - -# -------------------------------------------------------------------------- -# Compile target patterns - -$(BUILD)/obj/%.o: src/%.c - @mkdir -p $(dir $@) - gcc $(CFLAGS) -o $@ -c $< - -$(BUILD)/obj/%.do: src/%.c - @mkdir -p $(dir $@) - gcc $(CFLAGS) -fpic -fPIC -o $@ -c $< - - -# -------------------------------------------------------------------------- -# libs3 library targets - -LIBS3_SHARED = $(BUILD)/lib/libs3.$(LIBS3_VER_MAJOR).dylib - -.PHONY: libs3 -libs3: $(LIBS3_SHARED) $(LIBS3_SHARED_MAJOR) $(BUILD)/lib/libs3.a - -LIBS3_SOURCES := src/acl.c src/bucket.c src/error_parser.c src/general.c \ - src/object.c src/request.c src/request_context.c \ - src/response_headers_handler.c src/service_access_logging.c \ - src/service.c src/simplexml.c src/util.c - -$(LIBS3_SHARED): $(LIBS3_SOURCES:src/%.c=$(BUILD)/obj/%.do) - @mkdir -p $(dir $@) - gcc -dynamiclib -install_name libs3.$(LIBS3_VER_MAJOR).dylib \ - -compatibility_version $(LIBS3_VER_MAJOR) \ - -current_version $(LIBS3_VER) -o $@ $^ $(LDFLAGS) - -$(BUILD)/lib/libs3.a: $(LIBS3_SOURCES:src/%.c=$(BUILD)/obj/%.o) - @mkdir -p $(dir $@) - $(AR) cr $@ $^ - - -# -------------------------------------------------------------------------- -# Driver program targets - -.PHONY: s3 -s3: $(BUILD)/bin/s3 - -$(BUILD)/bin/s3: $(BUILD)/obj/s3.o $(LIBS3_SHARED) - @mkdir -p $(dir $@) - gcc -o $@ $^ $(LDFLAGS) - - -# -------------------------------------------------------------------------- -# libs3 header targets - -.PHONY: headers -headers: $(BUILD)/include/libs3.h - -$(BUILD)/include/libs3.h: inc/libs3.h - @mkdir -p $(dir $@) - cp $< $@ - - -# -------------------------------------------------------------------------- -# Test targets - -.PHONY: test -test: $(BUILD)/bin/testsimplexml - -$(BUILD)/bin/testsimplexml: $(BUILD)/obj/testsimplexml.o $(BUILD)/lib/libs3.a - @mkdir -p $(dir $@) - gcc -o $@ $^ $(LIBXML2_LIBS) - - -# -------------------------------------------------------------------------- -# Clean target - -.PHONY: clean -clean: - rm -rf $(BUILD) diff --git a/libs3-1.4/INSTALL b/libs3-1.4/INSTALL deleted file mode 100644 index 54431fc..0000000 --- a/libs3-1.4/INSTALL +++ /dev/null @@ -1,73 +0,0 @@ - -To install libs3 on a POSIX system (except Microsoft Windows): --------------------------------------------------------------- - -Note that all POSIX builds have prerequisites, such as development libraries -that libs3 requires and that must be installed at the time that libs3 is -built. The easiest way to find out what those are, is to run the build -command and then observe the results. - -*** For RPM-based systems (Fedora Core, Mandrake, etc) *** - -* rpmbuild -ta - -for example: - -rpmbuild -ta libs3-0.3.tar.gz - - -*** For dpkg-based systems (Debian, Ubuntu, etc) *** - -* make deb - -This will produce a Debian package in the build/pkg directory. - - -*** For all other systems *** - -* make [DESTDIR=destination root] install - -DESTDIR defaults to /usr - - -To install libs3 on a Microsoft Windows system: ------------------------------------------------ - -*** Using MingW *** - -* libs3 can be built on Windows using the MingW compiler. No other tool - is needed. However, the following libraries are needed to build libs3: - - - curl development libraries - - libxml2 development libraries, and the libraries that it requires: - - iconv - - zlib - - These projects are independent of libs3, and their release schedule and - means of distribution would make it very difficult to provide links to - the files to download and keep them up-to-date in this file, so no attempt - is made here. - - Development libraries and other files can be placed in: - c:\libs3-libs\bin - c:\libs3-libs\include - - If the above locations are used, then the GNUmakefile.mingw will work with - no special caveats. If the above locations are not used, then the following - environment variables should be set: - CURL_LIBS should be set to the MingW compiler flags needed to locate and - link in the curl libraries - CURL_CFLAGS should be set to the MingW compiler flags needed to locate and - include the curl headers - LIBXML2_LIBS should be set to the MingW compiler flags needed to locate and - link in the libxml2 libraries - LIBXML2_CFLAGS should be set to the MingW compiler flags needed to locate and - include the libxml2 headers - -* mingw32-make [DESTDIR=destination] -f GNUmakefile.mingw install - -DESTDIR defaults to libs3- - -* DESTDIR can be zipped up into a .zip file for distribution. For best - results, the dependent libraries (curl, openssl, etc) should be included, - along with their licenses. diff --git a/libs3-1.4/LICENSE b/libs3-1.4/LICENSE deleted file mode 100644 index db90987..0000000 --- a/libs3-1.4/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -Copyright 2008 Bryan Ischo - -libs3 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, version 3 of the License. - -In addition, as a special exception, the copyright holders give -permission to link the code of this library and its programs with the -OpenSSL library, and distribute linked combinations including the two. - -libs3 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 version 3 -along with libs3, in a file named COPYING. If not, see -. - - diff --git a/libs3-1.4/README b/libs3-1.4/README deleted file mode 100644 index c881a77..0000000 --- a/libs3-1.4/README +++ /dev/null @@ -1,4 +0,0 @@ -This directory contains the libs3 library. - -The libs3 library is free software. See the file LICENSE for copying -permission. diff --git a/libs3-1.4/TODO b/libs3-1.4/TODO deleted file mode 100644 index d8821f4..0000000 --- a/libs3-1.4/TODO +++ /dev/null @@ -1,3 +0,0 @@ -* Implement functions for generating form stuff for posting to s3 - -* Write s3 man page diff --git a/libs3-1.4/archlinux/PKGBUILD b/libs3-1.4/archlinux/PKGBUILD deleted file mode 100644 index 801bda1..0000000 --- a/libs3-1.4/archlinux/PKGBUILD +++ /dev/null @@ -1,29 +0,0 @@ -# Contributor: Bryan Ischo -pkgname=libs3 -pkgver=1.4 -pkgrel=1 -pkgdesc="C Library and Tools for Amazon S3 Access" -arch=('i686' 'x86_64') -url="http://libs3.ischo.com/index.html" -license=('GPL') -groups=() -depends=('libxml2' 'openssl') -makedepends=('make') -provides=() -conflicts=() -replaces=() -backup=() -options=() -install= -source=(http://libs3.ischo.com/$pkgname-$pkgver.tar.gz) -noextract=() -md5sums=('source md5') #generate with 'makepkg -g' - -build() { - cd "$srcdir/$pkgname-$pkgver" - - make exported || return 1 - cp -a build/{bin,include,lib} $pkgdir -} - -# vim:set ts=2 sw=2 et: diff --git a/libs3-1.4/debian/changelog b/libs3-1.4/debian/changelog deleted file mode 100644 index 520b2b9..0000000 --- a/libs3-1.4/debian/changelog +++ /dev/null @@ -1,5 +0,0 @@ -libs3 (all) unstable; urgency=low - - * This file is not maintained. See project source code for changes. - - -- Bryan Ischo Wed, 06 Aug 2008 09:36:43 -0400 diff --git a/libs3-1.4/debian/changelog.Debian b/libs3-1.4/debian/changelog.Debian deleted file mode 100644 index 81072be..0000000 --- a/libs3-1.4/debian/changelog.Debian +++ /dev/null @@ -1,6 +0,0 @@ -libs3 (all) unstable; urgency=low - - * libs3 Debian maintainer and upstream author are identical. - Therefore see normal changelog file for Debian changes. - - -- Bryan Ischo Wed, 06 Aug 2008 09:36:43 -0400 diff --git a/libs3-1.4/debian/control b/libs3-1.4/debian/control deleted file mode 100644 index 28ddc6b..0000000 --- a/libs3-1.4/debian/control +++ /dev/null @@ -1,12 +0,0 @@ -Package: libs3 -Source: THIS LINE WILL BE REMOVED, dpkg-shlibdepends NEEDS IT -Version: LIBS3_VERSION -Architecture: DEBIAN_ARCHITECTURE -Section: net -Priority: extra -Maintainer: Bryan Ischo -Homepage: http://libs3.ischo.com/index.html -Description: C Library and Tools for Amazon S3 Access - This package includes the libs3 shared object library, needed to run - applications compiled against libs3, and additionally contains the s3 - utility for accessing Amazon S3. diff --git a/libs3-1.4/debian/control.dev b/libs3-1.4/debian/control.dev deleted file mode 100644 index 5ee5ae7..0000000 --- a/libs3-1.4/debian/control.dev +++ /dev/null @@ -1,26 +0,0 @@ -Package: libs3-dev -Version: LIBS3_VERSION -Architecture: DEBIAN_ARCHITECTURE -Section: libdevel -Priority: extra -Depends: libs3 (>= LIBS3_VERSION) -Maintainer: Bryan Ischo -Homepage: http://libs3.ischo.com/index.html -Description: C Development Library for Amazon S3 Access - This library provides an API for using Amazon's S3 service (see - http://s3.amazonaws.com). Its design goals are: - . - - To provide a simple and straightforward API for accessing all of S3's - functionality - - To not require the developer using libs3 to need to know anything about: - - HTTP - - XML - - SSL - In other words, this API is meant to stand on its own, without requiring - any implicit knowledge of how S3 services are accessed using HTTP - protocols. - - To be usable from multithreaded code - - To be usable by code which wants to process multiple S3 requests - simultaneously from a single thread - - To be usable in the simple, straightforward way using sequentialized - blocking requests diff --git a/libs3-1.4/debian/postinst b/libs3-1.4/debian/postinst deleted file mode 100755 index 2d1871b..0000000 --- a/libs3-1.4/debian/postinst +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -ldconfig diff --git a/libs3-1.4/doxyfile b/libs3-1.4/doxyfile deleted file mode 100644 index cf96076..0000000 --- a/libs3-1.4/doxyfile +++ /dev/null @@ -1,886 +0,0 @@ -# Doxyfile 1.2.14 - -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project -# -# All text after a hash (#) is considered a comment and will be ignored -# The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") - -#--------------------------------------------------------------------------- -# General configuration options -#--------------------------------------------------------------------------- - -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. - -PROJECT_NAME = libs3 - -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. - -PROJECT_NUMBER = 1.4 - -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. - -OUTPUT_DIRECTORY = dox - -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Brazilian, Chinese, Croatian, Czech, Danish, Dutch, Finnish, French, -# German, Greek, Hungarian, Italian, Japanese, Korean, Norwegian, Polish, -# Portuguese, Romanian, Russian, Slovak, Slovene, Spanish and Swedish. - -OUTPUT_LANGUAGE = English - -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = YES - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = YES - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = YES - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these class will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. - -BRIEF_MEMBER_DESC = YES - -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the -# brief descriptions will be completely suppressed. - -REPEAT_BRIEF = YES - -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief -# description. - -ALWAYS_DETAILED_SEC = NO - -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited -# members of a class in the documentation of that class as if those members were -# ordinary class members. Constructors, destructors and assignment operators of -# the base classes will not be shown. - -INLINE_INHERITED_MEMB = NO - -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. - -FULL_PATH_NAMES = NO - -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. It is allowed to use relative paths in the argument list. - -STRIP_FROM_PATH = - -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. - -INTERNAL_DOCS = NO - -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower case letters. If set to YES upper case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# users are adviced to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems -# doesn't support long names like on DOS, Mac, or CD-ROM. - -SHORT_NAMES = NO - -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. - -HIDE_SCOPE_NAMES = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like the Qt-style comments (thus requiring an -# explict @brief command for a brief description. - -JAVADOC_AUTOBRIEF = NO - -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# reimplements. - -INHERIT_DOCS = YES - -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. - -INLINE_INFO = YES - -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = NO - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. - -TAB_SIZE = 8 - -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. - -ALIASES = - -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. - -ENABLED_SECTIONS = - -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consist of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources -# only. Doxygen will then generate output that is more tailored for C. -# For instance some of the names that are used will be different. The list -# of all members will be omitted, etc. - -OPTIMIZE_OUTPUT_FOR_C = NO - -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. - -SHOW_USED_FILES = YES - -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- - -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. - -QUIET = NO - -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. - -WARNINGS = YES - -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. - -WARN_IF_UNDOCUMENTED = YES - -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. - -WARN_FORMAT = "$file:$line: $text" - -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. - -WARN_LOGFILE = - -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- - -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. - -INPUT = inc/libs3.h - -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp -# *.h++ *.idl *.odl - -FILE_PATTERNS = - -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. - -RECURSIVE = YES - -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a -# subdirectory from a directory tree whose root is specified with the INPUT tag. - -EXCLUDE = - -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories -# that are symbolic links (a Unix filesystem feature) are excluded from the input. - -EXCLUDE_SYMLINKS = NO - -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. - -EXCLUDE_PATTERNS = - -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). - -EXAMPLE_PATH = - -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. - -EXAMPLE_PATTERNS = - -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. - -EXAMPLE_RECURSIVE = NO - -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). - -IMAGE_PATH = - -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. - -INPUT_FILTER = - -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse. - -FILTER_SOURCE_FILES = NO - -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- - -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. - -SOURCE_BROWSER = NO - -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. - -INLINE_SOURCES = NO - -# If the REFERENCED_BY_RELATION tag is set to YES (the default) -# then for each documented function all documented -# functions referencing it will be listed. - -REFERENCED_BY_RELATION = YES - -# If the REFERENCES_RELATION tag is set to YES (the default) -# then for each documented function all documented entities -# called/used by that function will be listed. - -REFERENCES_RELATION = YES - -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- - -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. - -ALPHABETICAL_INDEX = NO - -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) - -COLS_IN_ALPHA_INDEX = 5 - -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. - -IGNORE_PREFIX = - -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- - -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. - -GENERATE_HTML = YES - -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. - -HTML_OUTPUT = html - -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. - -HTML_FILE_EXTENSION = .html - -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet - -HTML_STYLESHEET = - -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. - -HTML_ALIGN_MEMBERS = YES - -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) -# of the generated HTML documentation. - -GENERATE_HTMLHELP = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). - -GENERATE_CHI = NO - -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. - -BINARY_TOC = NO - -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the Html help documentation and to the tree view. - -TOC_EXPAND = NO - -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. - -DISABLE_INDEX = NO - -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - -# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be -# generated containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript and frames is required (for instance Mozilla, Netscape 4.0+, -# or Internet explorer 4.0+). Note that for large projects the tree generation -# can take a very long time. In such cases it is better to disable this feature. -# Windows users are probably better off using the HTML help feature. - -GENERATE_TREEVIEW = YES - -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. - -TREEVIEW_WIDTH = 250 - -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- - -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will -# generate Latex output. - -GENERATE_LATEX = NO - -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `latex' will be used as the default path. - -LATEX_OUTPUT = latex - -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_LATEX = NO - -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and -# executive. If left blank a4wide will be used. - -PAPER_TYPE = a4wide - -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX -# packages that should be included in the LaTeX output. - -EXTRA_PACKAGES = - -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a -# standard header. Notice: only use this tag if you know what you are doing! - -LATEX_HEADER = - -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references -# This makes the output suitable for online browsing using a pdf viewer. - -PDF_HYPERLINKS = NO - -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a -# higher quality PDF documentation. - -USE_PDFLATEX = NO - -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. -# This option is also used when generating formulas in HTML. - -LATEX_BATCHMODE = NO - -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- - -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimised for Word 97 and may not look very pretty with -# other RTF readers or editors. - -GENERATE_RTF = NO - -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `rtf' will be used as the default path. - -RTF_OUTPUT = rtf - -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to -# save some trees in general. - -COMPACT_RTF = NO - -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. -# Note: wordpad (write) and others do not support links. - -RTF_HYPERLINKS = NO - -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assigments. You only have to provide -# replacements, missing definitions are set to their default value. - -RTF_STYLESHEET_FILE = - -# Set optional variables used in the generation of an rtf document. -# Syntax is similar to doxygen's config file. - -RTF_EXTENSIONS_FILE = - -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- - -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will -# generate man pages - -GENERATE_MAN = NO - -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `man' will be used as the default path. - -MAN_OUTPUT = man - -# The MAN_EXTENSION tag determines the extension that is added to -# the generated man pages (default is the subroutine's section .3) - -MAN_EXTENSION = .3 - -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command -# would be unable to find the correct page. The default is NO. - -MAN_LINKS = NO - -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- - -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. - -GENERATE_XML = NO - -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- - -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental -# and incomplete at the moment. - -GENERATE_AUTOGEN_DEF = NO - -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- - -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include -# files. - -ENABLE_PREPROCESSING = YES - -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled -# way by setting EXPAND_ONLY_PREDEF to YES. - -MACRO_EXPANSION = NO - -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_PREDEFINED tags. - -EXPAND_ONLY_PREDEF = NO - -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. - -SEARCH_INCLUDES = YES - -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by -# the preprocessor. - -INCLUDE_PATH = - -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will -# be used. - -INCLUDE_FILE_PATTERNS = - -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. - -PREDEFINED = DOXYGEN - -# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. - -EXPAND_AS_DEFINED = - -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line and do not end with a semicolon. Such function macros are typically -# used for boiler-plate code, and will confuse the parser if not removed. - -SKIP_FUNCTION_MACROS = YES - -#--------------------------------------------------------------------------- -# Configuration::addtions related to external references -#--------------------------------------------------------------------------- - -# The TAGFILES tag can be used to specify one or more tagfiles. - -TAGFILES = - -# When a file name is specified after GENERATE_TAGFILE, doxygen will create -# a tag file that is based on the input files it reads. - -GENERATE_TAGFILE = - -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes -# will be listed. - -ALLEXTERNALS = NO - -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will -# be listed. - -EXTERNAL_GROUPS = YES - -# The PERL_PATH should be the absolute path and name of the perl script -# interpreter (i.e. the result of `which perl'). - -PERL_PATH = /usr/bin/perl - -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- - -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in Html, RTF and LaTeX) for classes with base or -# super classes. Setting the tag to NO turns the diagrams off. Note that this -# option is superceded by the HAVE_DOT option below. This is only a fallback. It is -# recommended to install and use dot, since it yield more powerful graphs. - -CLASS_DIAGRAMS = YES - -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) - -HAVE_DOT = NO - -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = YES - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented -# or is not a class. - -HIDE_UNDOC_RELATIONS = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with -# other documented files. - -INCLUDE_GRAPH = YES - -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or -# indirectly include this file. - -INCLUDED_BY_GRAPH = YES - -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. - -GRAPHICAL_HIERARCHY = YES - -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are gif, jpg, and png -# If left blank gif will be used. - -DOT_IMAGE_FORMAT = gif - -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found on the path. - -DOT_PATH = - -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the -# \dotfile command). - -DOTFILE_DIRS = - -# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width -# (in pixels) of the graphs generated by dot. If a graph becomes larger than -# this value, doxygen will try to truncate the graph, so that it fits within -# the specified constraint. Beware that most browsers cannot cope with very -# large images. - -MAX_DOT_GRAPH_WIDTH = 1024 - -# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height -# (in pixels) of the graphs generated by dot. If a graph becomes larger than -# this value, doxygen will try to truncate the graph, so that it fits within -# the specified constraint. Beware that most browsers cannot cope with very -# large images. - -MAX_DOT_GRAPH_HEIGHT = 1024 - -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and -# arrows in the dot generated graphs. - -GENERATE_LEGEND = YES - -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermedate dot files that are used to generate -# the various graphs. - -DOT_CLEANUP = YES - -#--------------------------------------------------------------------------- -# Configuration::addtions related to the search engine -#--------------------------------------------------------------------------- - -# The SEARCHENGINE tag specifies whether or not a search engine should be -# used. If set to NO the values of all tags below this one will be ignored. - -SEARCHENGINE = NO diff --git a/libs3-1.4/inc/error_parser.h b/libs3-1.4/inc/error_parser.h deleted file mode 100644 index 8785201..0000000 --- a/libs3-1.4/inc/error_parser.h +++ /dev/null @@ -1,82 +0,0 @@ -/** ************************************************************************** - * error_parser.h - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -#ifndef ERROR_PARSER_H -#define ERROR_PARSER_H - -#include "libs3.h" -#include "simplexml.h" -#include "string_buffer.h" - - -#define EXTRA_DETAILS_SIZE 8 - -typedef struct ErrorParser -{ - // This is the S3ErrorDetails that this ErrorParser fills in from the - // data that it parses - S3ErrorDetails s3ErrorDetails; - - // This is the error XML parser - SimpleXml errorXmlParser; - - // Set to 1 after the first call to add - int errorXmlParserInitialized; - - // Used to buffer the S3 Error Code as it is read in - string_buffer(code, 1024); - - // Used to buffer the S3 Error Message as it is read in - string_buffer(message, 1024); - - // Used to buffer the S3 Error Resource as it is read in - string_buffer(resource, 1024); - - // Used to buffer the S3 Error Further Details as it is read in - string_buffer(furtherDetails, 1024); - - // The extra details; we support up to EXTRA_DETAILS_SIZE of them - S3NameValue extraDetails[EXTRA_DETAILS_SIZE]; - - // This is the buffer from which the names and values used in extraDetails - // are allocated - string_multibuffer(extraDetailsNamesValues, EXTRA_DETAILS_SIZE * 1024); -} ErrorParser; - - -// Always call this -void error_parser_initialize(ErrorParser *errorParser); - -S3Status error_parser_add(ErrorParser *errorParser, char *buffer, - int bufferSize); - -void error_parser_convert_status(ErrorParser *errorParser, S3Status *status); - -// Always call this -void error_parser_deinitialize(ErrorParser *errorParser); - - -#endif /* ERROR_PARSER_H */ diff --git a/libs3-1.4/inc/libs3.h b/libs3-1.4/inc/libs3.h deleted file mode 100644 index 8f06e31..0000000 --- a/libs3-1.4/inc/libs3.h +++ /dev/null @@ -1,1865 +0,0 @@ -/** ************************************************************************** - * libs3.h - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -#ifndef LIBS3_H -#define LIBS3_H - -#include -#include - - -#ifdef __cplusplus -extern "C" { -#endif - - -/** ************************************************************************** - * Overview - * -------- - * - * This library provides an API for using Amazon's S3 service (see - * http://s3.amazonaws.com). Its design goals are: - * - * - To provide a simple and straightforward API for accessing all of S3's - * functionality - * - To not require the developer using libs3 to need to know anything about: - * - HTTP - * - XML - * - SSL - * In other words, this API is meant to stand on its own, without requiring - * any implicit knowledge of how S3 services are accessed using HTTP - * protocols. - * - To be usable from multithreaded code - * - To be usable by code which wants to process multiple S3 requests - * simultaneously from a single thread - * - To be usable in the simple, straightforward way using sequentialized - * blocking requests - * - * The general usage pattern of libs3 is: - * - * - Initialize libs3 once per program by calling S3_initialize() at program - * start up time - * - Make any number of requests to S3 for getting, putting, or listing - * S3 buckets or objects, or modifying the ACLs associated with buckets - * or objects, using one of three general approaches: - * 1. Simple blocking requests, one at a time - * 2. Multiple threads each making simple blocking requests - * 3. From a single thread, managing multiple S3 requests simultaneously - * using file descriptors and a select()/poll() loop - * - Shut down libs3 at program exit time by calling S3_deinitialize() - * - * All functions which send requests to S3 return their results via a set of - * callback functions which must be supplied to libs3 at the time that the - * request is initiated. libs3 will call these functions back in the thread - * calling the libs3 function if blocking requests are made (i.e., if the - * S3RequestContext for the function invocation is passed in as NULL). - * If an S3RequestContext is used to drive multiple S3 requests - * simultaneously, then the callbacks will be made from the thread which - * calls S3_runall_request_context() or S3_runonce_request_context(), or - * possibly from the thread which calls S3_destroy_request_context(), if - * S3 requests are in progress at the time that this function is called. - * - * NOTE: Response headers from Amazon S3 are limited to 4K (2K of metas is all - * that Amazon supports, and libs3 allows Amazon an additional 2K of headers). - * - * NOTE: Because HTTP and the S3 REST protocol are highly under-specified, - * libs3 must make some assumptions about the maximum length of certain HTTP - * elements (such as headers) that it will accept. While efforts have been - * made to enforce maximums which are beyond that expected to be needed by any - * user of S3, it is always possible that these maximums may be too low in - * some rare circumstances. Bug reports should this unlikely situation occur - * would be most appreciated. - * - * Threading Rules - * --------------- - * - * 1. All arguments passed to any function must not be modified directly until - * the function returns. - * 2. All S3RequestContext and S3Request arguments passed to all functions may - * not be passed to any other libs3 function by any other thread until the - * function returns. - * 3. All functions may be called simultaneously by multiple threads as long - * as (1) and (2) are observed, EXCEPT for S3_initialize(), which must be - * called from one thread at a time only. - * 4. All callbacks will be made in the thread of the caller of the function - * which invoked them, so the caller of all libs3 functions should not hold - * locks that it would try to re-acquire in a callback, as this may - * deadlock. - ************************************************************************** **/ - - -/** ************************************************************************** - * Constants - ************************************************************************** **/ - -/** - * This is the hostname that all S3 requests will go through; virtual-host - * style requests will prepend the bucket name to this host name, and - * path-style requests will use this hostname directly - **/ -#define S3_HOSTNAME "s3.amazonaws.com" - - -/** - * S3_MAX_BUCKET_NAME_SIZE is the maximum size of a bucket name. - **/ - -#define S3_MAX_BUCKET_NAME_SIZE 255 - -/** - * S3_MAX_KEY_SIZE is the maximum size of keys that Amazon S3 supports. - **/ -#define S3_MAX_KEY_SIZE 1024 - - -/** - * S3_MAX_METADATA_SIZE is the maximum number of bytes allowed for - * x-amz-meta header names and values in any request passed to Amazon S3 - **/ -#define S3_MAX_METADATA_SIZE 2048 - - -/** - * S3_METADATA_HEADER_NAME_PREFIX is the prefix of an S3 "meta header" - **/ -#define S3_METADATA_HEADER_NAME_PREFIX "x-amz-meta-" - - -/** - * S3_MAX_METADATA_COUNT is the maximum number of x-amz-meta- headers that - * could be included in a request to S3. The smallest meta header is - * "x-amz-meta-n: v". Since S3 doesn't count the ": " against the total, the - * smallest amount of data to count for a header would be the length of - * "x-amz-meta-nv". - **/ -#define S3_MAX_METADATA_COUNT \ - (S3_MAX_METADATA_SIZE / (sizeof(S3_METADATA_HEADER_NAME_PREFIX "nv") - 1)) - - -/** - * S3_MAX_ACL_GRANT_COUNT is the maximum number of ACL grants that may be - * set on a bucket or object at one time. It is also the maximum number of - * ACL grants that the XML ACL parsing routine will parse. - **/ -#define S3_MAX_ACL_GRANT_COUNT 100 - - -/** - * This is the maximum number of characters (including terminating \0) that - * libs3 supports in an ACL grantee email address. - **/ -#define S3_MAX_GRANTEE_EMAIL_ADDRESS_SIZE 128 - - -/** - * This is the maximum number of characters (including terminating \0) that - * libs3 supports in an ACL grantee user id. - **/ -#define S3_MAX_GRANTEE_USER_ID_SIZE 128 - - -/** - * This is the maximum number of characters (including terminating \0) that - * libs3 supports in an ACL grantee user display name. - **/ -#define S3_MAX_GRANTEE_DISPLAY_NAME_SIZE 128 - - -/** - * This is the maximum number of characters that will be stored in the - * return buffer for the utility function which computes an HTTP authenticated - * query string - **/ -#define S3_MAX_AUTHENTICATED_QUERY_STRING_SIZE \ - (sizeof("https://" S3_HOSTNAME "/") + (S3_MAX_KEY_SIZE * 3) + \ - sizeof("?AWSAccessKeyId=") + 32 + sizeof("&Expires=") + 32 + \ - sizeof("&Signature=") + 28 + 1) - - -/** - * This constant is used by the S3_initialize() function, to specify that - * the winsock library should be initialized by libs3; only relevent on - * Microsoft Windows platforms. - **/ -#define S3_INIT_WINSOCK 1 - - -/** - * This convenience constant is used by the S3_initialize() function to - * indicate that all libraries required by libs3 should be initialized. - **/ -#define S3_INIT_ALL (S3_INIT_WINSOCK) - - -/** ************************************************************************** - * Enumerations - ************************************************************************** **/ - -/** - * S3Status is a status code as returned by a libs3 function. The meaning of - * each status code is defined in the comments for each function which returns - * that status. - **/ -typedef enum -{ - S3StatusOK , - - /** - * Errors that prevent the S3 request from being issued or response from - * being read - **/ - S3StatusInternalError , - S3StatusOutOfMemory , - S3StatusInterrupted , - S3StatusInvalidBucketNameTooLong , - S3StatusInvalidBucketNameFirstCharacter , - S3StatusInvalidBucketNameCharacter , - S3StatusInvalidBucketNameCharacterSequence , - S3StatusInvalidBucketNameTooShort , - S3StatusInvalidBucketNameDotQuadNotation , - S3StatusQueryParamsTooLong , - S3StatusFailedToInitializeRequest , - S3StatusMetaDataHeadersTooLong , - S3StatusBadMetaData , - S3StatusBadContentType , - S3StatusContentTypeTooLong , - S3StatusBadMD5 , - S3StatusMD5TooLong , - S3StatusBadCacheControl , - S3StatusCacheControlTooLong , - S3StatusBadContentDispositionFilename , - S3StatusContentDispositionFilenameTooLong , - S3StatusBadContentEncoding , - S3StatusContentEncodingTooLong , - S3StatusBadIfMatchETag , - S3StatusIfMatchETagTooLong , - S3StatusBadIfNotMatchETag , - S3StatusIfNotMatchETagTooLong , - S3StatusHeadersTooLong , - S3StatusKeyTooLong , - S3StatusUriTooLong , - S3StatusXmlParseFailure , - S3StatusEmailAddressTooLong , - S3StatusUserIdTooLong , - S3StatusUserDisplayNameTooLong , - S3StatusGroupUriTooLong , - S3StatusPermissionTooLong , - S3StatusTargetBucketTooLong , - S3StatusTargetPrefixTooLong , - S3StatusTooManyGrants , - S3StatusBadGrantee , - S3StatusBadPermission , - S3StatusXmlDocumentTooLarge , - S3StatusNameLookupError , - S3StatusFailedToConnect , - S3StatusServerFailedVerification , - S3StatusConnectionFailed , - S3StatusAbortedByCallback , - - /** - * Errors from the S3 service - **/ - S3StatusErrorAccessDenied , - S3StatusErrorAccountProblem , - S3StatusErrorAmbiguousGrantByEmailAddress , - S3StatusErrorBadDigest , - S3StatusErrorBucketAlreadyExists , - S3StatusErrorBucketAlreadyOwnedByYou , - S3StatusErrorBucketNotEmpty , - S3StatusErrorCredentialsNotSupported , - S3StatusErrorCrossLocationLoggingProhibited , - S3StatusErrorEntityTooSmall , - S3StatusErrorEntityTooLarge , - S3StatusErrorExpiredToken , - S3StatusErrorIncompleteBody , - S3StatusErrorIncorrectNumberOfFilesInPostRequest , - S3StatusErrorInlineDataTooLarge , - S3StatusErrorInternalError , - S3StatusErrorInvalidAccessKeyId , - S3StatusErrorInvalidAddressingHeader , - S3StatusErrorInvalidArgument , - S3StatusErrorInvalidBucketName , - S3StatusErrorInvalidDigest , - S3StatusErrorInvalidLocationConstraint , - S3StatusErrorInvalidPayer , - S3StatusErrorInvalidPolicyDocument , - S3StatusErrorInvalidRange , - S3StatusErrorInvalidSecurity , - S3StatusErrorInvalidSOAPRequest , - S3StatusErrorInvalidStorageClass , - S3StatusErrorInvalidTargetBucketForLogging , - S3StatusErrorInvalidToken , - S3StatusErrorInvalidURI , - S3StatusErrorKeyTooLong , - S3StatusErrorMalformedACLError , - S3StatusErrorMalformedXML , - S3StatusErrorMaxMessageLengthExceeded , - S3StatusErrorMaxPostPreDataLengthExceededError , - S3StatusErrorMetadataTooLarge , - S3StatusErrorMethodNotAllowed , - S3StatusErrorMissingAttachment , - S3StatusErrorMissingContentLength , - S3StatusErrorMissingSecurityElement , - S3StatusErrorMissingSecurityHeader , - S3StatusErrorNoLoggingStatusForKey , - S3StatusErrorNoSuchBucket , - S3StatusErrorNoSuchKey , - S3StatusErrorNotImplemented , - S3StatusErrorNotSignedUp , - S3StatusErrorOperationAborted , - S3StatusErrorPermanentRedirect , - S3StatusErrorPreconditionFailed , - S3StatusErrorRedirect , - S3StatusErrorRequestIsNotMultiPartContent , - S3StatusErrorRequestTimeout , - S3StatusErrorRequestTimeTooSkewed , - S3StatusErrorRequestTorrentOfBucketError , - S3StatusErrorSignatureDoesNotMatch , - S3StatusErrorSlowDown , - S3StatusErrorTemporaryRedirect , - S3StatusErrorTokenRefreshRequired , - S3StatusErrorTooManyBuckets , - S3StatusErrorUnexpectedContent , - S3StatusErrorUnresolvableGrantByEmailAddress , - S3StatusErrorUserKeyMustBeSpecified , - S3StatusErrorUnknown , - - /** - * The following are HTTP errors returned by S3 without enough detail to - * distinguish any of the above S3StatusError conditions - **/ - S3StatusHttpErrorMovedTemporarily , - S3StatusHttpErrorBadRequest , - S3StatusHttpErrorForbidden , - S3StatusHttpErrorNotFound , - S3StatusHttpErrorConflict , - S3StatusHttpErrorUnknown -} S3Status; - - -/** - * S3Protocol represents a protocol that may be used for communicating a - * request to the Amazon S3 service. - * - * In general, HTTPS is greatly preferred (and should be the default of any - * application using libs3) because it protects any data being sent to or - * from S3 using strong encryption. However, HTTPS is much more CPU intensive - * than HTTP, and if the caller is absolutely certain that it is OK for the - * data to be viewable by anyone in transit, then HTTP can be used. - **/ -typedef enum -{ - S3ProtocolHTTPS = 0, - S3ProtocolHTTP = 1 -} S3Protocol; - - -/** - * S3UriStyle defines the form that an Amazon S3 URI identifying a bucket or - * object can take. They are of these forms: - * - * Virtual Host: ${protocol}://${bucket}.s3.amazonaws.com/[${key}] - * Path: ${protocol}://s3.amazonaws.com/${bucket}/[${key}] - * - * It is generally better to use the Virual Host URI form, because it ensures - * that the bucket name used is compatible with normal HTTP GETs and POSTs of - * data to/from the bucket. However, if DNS lookups for the bucket are too - * slow or unreliable for some reason, Path URI form may be used. - **/ -typedef enum -{ - S3UriStyleVirtualHost = 0, - S3UriStylePath = 1 -} S3UriStyle; - - -/** - * S3GranteeType defines the type of Grantee used in an S3 ACL Grant. - * Amazon Customer By Email - identifies the Grantee using their Amazon S3 - * account email address - * Canonical User - identifies the Grantee by S3 User ID and Display Name, - * which can only be obtained by making requests to S3, for example, by - * listing owned buckets - * All AWS Users - identifies all authenticated AWS users - * All Users - identifies all users - * Log Delivery - identifies the Amazon group responsible for writing - * server access logs into buckets - **/ -typedef enum -{ - S3GranteeTypeAmazonCustomerByEmail = 0, - S3GranteeTypeCanonicalUser = 1, - S3GranteeTypeAllAwsUsers = 2, - S3GranteeTypeAllUsers = 3, - S3GranteeTypeLogDelivery = 4 -} S3GranteeType; - - -/** - * This is an individual permission granted to a grantee in an S3 ACL Grant. - * Read permission gives the Grantee the permission to list the bucket, or - * read the object or its metadata - * Write permission gives the Grantee the permission to create, overwrite, or - * delete any object in the bucket, and is not supported for objects - * ReadACP permission gives the Grantee the permission to read the ACP for - * the bucket or object; the owner of the bucket or object always has - * this permission implicitly - * WriteACP permission gives the Grantee the permission to overwrite the ACP - * for the bucket or object; the owner of the bucket or object always has - * this permission implicitly - * FullControl permission gives the Grantee all permissions specified by the - * Read, Write, ReadACP, and WriteACP permissions - **/ -typedef enum -{ - S3PermissionRead = 0, - S3PermissionWrite = 1, - S3PermissionReadACP = 2, - S3PermissionWriteACP = 3, - S3PermissionFullControl = 4 -} S3Permission; - - -/** - * S3CannedAcl is an ACL that can be specified when an object is created or - * updated. Each canned ACL has a predefined value when expanded to a full - * set of S3 ACL Grants. - * Private canned ACL gives the owner FULL_CONTROL and no other permissions - * are issued - * Public Read canned ACL gives the owner FULL_CONTROL and all users Read - * permission - * Public Read Write canned ACL gives the owner FULL_CONTROL and all users - * Read and Write permission - * AuthenticatedRead canned ACL gives the owner FULL_CONTROL and authenticated - * S3 users Read permission - **/ -typedef enum -{ - S3CannedAclPrivate = 0, /* private */ - S3CannedAclPublicRead = 1, /* public-read */ - S3CannedAclPublicReadWrite = 2, /* public-read-write */ - S3CannedAclAuthenticatedRead = 3 /* authenticated-read */ -} S3CannedAcl; - - -/** ************************************************************************** - * Data Types - ************************************************************************** **/ - -/** - * An S3RequestContext manages multiple S3 requests simultaneously; see the - * S3_XXX_request_context functions below for details - **/ -typedef struct S3RequestContext S3RequestContext; - - -/** - * S3NameValue represents a single Name - Value pair, used to represent either - * S3 metadata associated with a key, or S3 error details. - **/ -typedef struct S3NameValue -{ - /** - * The name part of the Name - Value pair - **/ - const char *name; - - /** - * The value part of the Name - Value pair - **/ - const char *value; -} S3NameValue; - - -/** - * S3ResponseProperties is passed to the properties callback function which is - * called when the complete response properties have been received. Some of - * the fields of this structure are optional and may not be provided in the - * response, and some will always be provided in the response. - **/ -typedef struct S3ResponseProperties -{ - /** - * This optional field identifies the request ID and may be used when - * reporting problems to Amazon. - **/ - const char *requestId; - - /** - * This optional field identifies the request ID and may be used when - * reporting problems to Amazon. - **/ - const char *requestId2; - - /** - * This optional field is the content type of the data which is returned - * by the request. If not provided, the default can be assumed to be - * "binary/octet-stream". - **/ - const char *contentType; - - /** - * This optional field is the content length of the data which is returned - * in the response. A negative value means that this value was not - * provided in the response. A value of 0 means that there is no content - * provided. A positive value gives the number of bytes in the content of - * the response. - **/ - uint64_t contentLength; - - /** - * This optional field names the server which serviced the request. - **/ - const char *server; - - /** - * This optional field provides a string identifying the unique contents - * of the resource identified by the request, such that the contents can - * be assumed not to be changed if the same eTag is returned at a later - * time decribing the same resource. This is an MD5 sum of the contents. - **/ - const char *eTag; - - /** - * This optional field provides the last modified time, relative to the - * Unix epoch, of the contents. If this value is < 0, then the last - * modified time was not provided in the response. If this value is >= 0, - * then the last modified date of the contents are available as a number - * of seconds since the UNIX epoch. - * - **/ - int64_t lastModified; - - /** - * This is the number of user-provided meta data associated with the - * resource. - **/ - int metaDataCount; - - /** - * These are the meta data associated with the resource. In each case, - * the name will not include any S3-specific header prefixes - * (i.e. x-amz-meta- will have been removed from the beginning), and - * leading and trailing whitespace will have been stripped from the value. - **/ - const S3NameValue *metaData; -} S3ResponseProperties; - - -/** - * S3AclGrant identifies a single grant in the ACL for a bucket or object. An - * ACL is composed of any number of grants, which specify a grantee and the - * permissions given to that grantee. S3 does not normalize ACLs in any way, - * so a redundant ACL specification will lead to a redundant ACL stored in S3. - **/ -typedef struct S3AclGrant -{ - /** - * The granteeType gives the type of grantee specified by this grant. - **/ - S3GranteeType granteeType; - /** - * The identifier of the grantee that is set is determined by the - * granteeType: - * - * S3GranteeTypeAmazonCustomerByEmail - amazonCustomerByEmail.emailAddress - * S3GranteeTypeCanonicalUser - canonicalUser.id, canonicalUser.displayName - * S3GranteeTypeAllAwsUsers - none - * S3GranteeTypeAllUsers - none - **/ - union - { - /** - * This structure is used iff the granteeType is - * S3GranteeTypeAmazonCustomerByEmail. - **/ - struct - { - /** - * This is the email address of the Amazon Customer being granted - * permissions by this S3AclGrant. - **/ - char emailAddress[S3_MAX_GRANTEE_EMAIL_ADDRESS_SIZE]; - } amazonCustomerByEmail; - /** - * This structure is used iff the granteeType is - * S3GranteeTypeCanonicalUser. - **/ - struct - { - /** - * This is the CanonicalUser ID of the grantee - **/ - char id[S3_MAX_GRANTEE_USER_ID_SIZE]; - /** - * This is the display name of the grantee - **/ - char displayName[S3_MAX_GRANTEE_DISPLAY_NAME_SIZE]; - } canonicalUser; - } grantee; - /** - * This is the S3Permission to be granted to the grantee - **/ - S3Permission permission; -} S3AclGrant; - - -/** - * A context for working with objects within a bucket. A bucket context holds - * all information necessary for working with a bucket, and may be used - * repeatedly over many consecutive (or simultaneous) calls into libs3 bucket - * operation functions. - **/ -typedef struct S3BucketContext -{ - /** - * The name of the bucket to use in the bucket context - **/ - const char *bucketName; - - /** - * The protocol to use when accessing the bucket - **/ - S3Protocol protocol; - - /** - * The URI style to use for all URIs sent to Amazon S3 while working with - * this bucket context - **/ - S3UriStyle uriStyle; - - /** - * The Amazon Access Key ID to use for access to the bucket - **/ - const char *accessKeyId; - - /** - * The Amazon Secret Access Key to use for access to the bucket - **/ - const char *secretAccessKey; -} S3BucketContext; - - -/** - * This is a single entry supplied to the list bucket callback by a call to - * S3_list_bucket. It identifies a single matching key from the list - * operation. - **/ -typedef struct S3ListBucketContent -{ - /** - * This is the next key in the list bucket results. - **/ - const char *key; - - /** - * This is the number of seconds since UNIX epoch of the last modified - * date of the object identified by the key. - **/ - int64_t lastModified; - - /** - * This gives a tag which gives a signature of the contents of the object, - * which is the MD5 of the contents of the object. - **/ - const char *eTag; - - /** - * This is the size of the object in bytes. - **/ - uint64_t size; - - /** - * This is the ID of the owner of the key; it is present only if access - * permissions allow it to be viewed. - **/ - const char *ownerId; - - /** - * This is the display name of the owner of the key; it is present only if - * access permissions allow it to be viewed. - **/ - const char *ownerDisplayName; -} S3ListBucketContent; - - -/** - * S3PutProperties is the set of properties that may optionally be set by the - * user when putting objects to S3. Each field of this structure is optional - * and may or may not be present. - **/ -typedef struct S3PutProperties -{ - /** - * If present, this is the Content-Type that should be associated with the - * object. If not provided, S3 defaults to "binary/octet-stream". - **/ - const char *contentType; - - /** - * If present, this provides the MD5 signature of the contents, and is - * used to validate the contents. This is highly recommended by Amazon - * but not required. Its format is as a base64-encoded MD5 sum. - **/ - const char *md5; - - /** - * If present, this gives a Cache-Control header string to be supplied to - * HTTP clients which download this - **/ - const char *cacheControl; - - /** - * If present, this gives the filename to save the downloaded file to, - * whenever the object is downloaded via a web browser. This is only - * relevent for objects which are intended to be shared to users via web - * browsers and which is additionally intended to be downloaded rather - * than viewed. - **/ - const char *contentDispositionFilename; - - /** - * If present, this identifies the content encoding of the object. This - * is only applicable to encoded (usually, compressed) content, and only - * relevent if the object is intended to be downloaded via a browser. - **/ - const char *contentEncoding; - - /** - * If >= 0, this gives an expiration date for the content. This - * information is typically only delivered to users who download the - * content via a web browser. - **/ - int64_t expires; - - /** - * This identifies the "canned ACL" that should be used for this object. - * The default (0) gives only the owner of the object access to it. - **/ - S3CannedAcl cannedAcl; - - /** - * This is the number of values in the metaData field. - **/ - int metaDataCount; - - /** - * These are the meta data to pass to S3. In each case, the name part of - * the Name - Value pair should not include any special S3 HTTP header - * prefix (i.e., should be of the form 'foo', NOT 'x-amz-meta-foo'). - **/ - const S3NameValue *metaData; -} S3PutProperties; - - -/** - * S3GetConditions is used for the get_object operation, and specifies - * conditions which the object must meet in order to be successfully returned. - **/ -typedef struct S3GetConditions -{ - /** - * The request will be processed if the Last-Modification header of the - * object is greater than or equal to this value, specified as a number of - * seconds since Unix epoch. If this value is less than zero, it will not - * be used in the conditional. - **/ - int64_t ifModifiedSince; - - /** - * The request will be processed if the Last-Modification header of the - * object is less than this value, specified as a number of seconds since - * Unix epoch. If this value is less than zero, it will not be used in - * the conditional. - **/ - int64_t ifNotModifiedSince; - - /** - * If non-NULL, this gives an eTag header value which the object must - * match in order to be returned. Note that altough the eTag is simply an - * MD5, this must be presented in the S3 eTag form, which typically - * includes double-quotes. - **/ - const char *ifMatchETag; - - /** - * If non-NULL, this gives an eTag header value which the object must not - * match in order to be returned. Note that altough the eTag is simply an - * MD5, this must be presented in the S3 eTag form, which typically - * includes double-quotes. - **/ - const char *ifNotMatchETag; -} S3GetConditions; - - -/** - * S3ErrorDetails provides detailed information describing an S3 error. This - * is only presented when the error is an S3-generated error (i.e. one of the - * S3StatusErrorXXX values). - **/ -typedef struct S3ErrorDetails -{ - /** - * This is the human-readable message that Amazon supplied describing the - * error - **/ - const char *message; - - /** - * This identifies the resource for which the error occurred - **/ - const char *resource; - - /** - * This gives human-readable further details describing the specifics of - * this error - **/ - const char *furtherDetails; - - /** - * This gives the number of S3NameValue pairs present in the extraDetails - * array - **/ - int extraDetailsCount; - - /** - * S3 can provide extra details in a freeform Name - Value pair format. - * Each error can have any number of these, and this array provides these - * additional extra details. - **/ - S3NameValue *extraDetails; -} S3ErrorDetails; - - -/** ************************************************************************** - * Callback Signatures - ************************************************************************** **/ - -/** - * This callback is made whenever the response properties become available for - * any request. - * - * @param properties are the properties that are available from the response - * @param callbackData is the callback data as specified when the request - * was issued. - * @return S3StatusOK to continue processing the request, anything else to - * immediately abort the request with a status which will be - * passed to the S3ResponseCompleteCallback for this request. - * Typically, this will return either S3StatusOK or - * S3StatusAbortedByCallback. - **/ -typedef S3Status (S3ResponsePropertiesCallback) - (const S3ResponseProperties *properties, void *callbackData); - - -/** - * This callback is made when the response has been completely received, or an - * error has occurred which has prematurely aborted the request, or one of the - * other user-supplied callbacks returned a value intended to abort the - * request. This callback is always made for every request, as the very last - * callback made for that request. - * - * @param status gives the overall status of the response, indicating success - * or failure; use S3_status_is_retryable() as a simple way to detect - * whether or not the status indicates that the request failed but may - * be retried. - * @param errorDetails if non-NULL, gives details as returned by the S3 - * service, describing the error - * @param callbackData is the callback data as specified when the request - * was issued. - **/ -typedef void (S3ResponseCompleteCallback)(S3Status status, - const S3ErrorDetails *errorDetails, - void *callbackData); - - -/** - * This callback is made for each bucket resulting from a list service - * operation. - * - * @param ownerId is the ID of the owner of the bucket - * @param ownerDisplayName is the owner display name of the owner of the bucket - * @param bucketName is the name of the bucket - * @param creationDateSeconds if < 0 indicates that no creation date was - * supplied for the bucket; if >= 0 indicates the number of seconds - * since UNIX Epoch of the creation date of the bucket - * @param callbackData is the callback data as specified when the request - * was issued. - * @return S3StatusOK to continue processing the request, anything else to - * immediately abort the request with a status which will be - * passed to the S3ResponseCompleteCallback for this request. - * Typically, this will return either S3StatusOK or - * S3StatusAbortedByCallback. - **/ -typedef S3Status (S3ListServiceCallback)(const char *ownerId, - const char *ownerDisplayName, - const char *bucketName, - int64_t creationDateSeconds, - void *callbackData); - - -/** - * This callback is made repeatedly as a list bucket operation progresses. - * The contents reported via this callback are only reported once per list - * bucket operation, but multiple calls to this callback may be necessary to - * report all items resulting from the list bucket operation. - * - * @param isTruncated is true if the list bucket request was truncated by the - * S3 service, in which case the remainder of the list may be obtained - * by querying again using the Marker parameter to start the query - * after this set of results - * @param nextMarker if present, gives the largest (alphabetically) key - * returned in the response, which, if isTruncated is true, may be used - * as the marker in a subsequent list buckets operation to continue - * listing - * @param contentsCount is the number of ListBucketContent structures in the - * contents parameter - * @param contents is an array of ListBucketContent structures, each one - * describing an object in the bucket - * @param commonPrefixesCount is the number of common prefixes strings in the - * commonPrefixes parameter - * @param commonPrefixes is an array of strings, each specifing one of the - * common prefixes as returned by S3 - * @param callbackData is the callback data as specified when the request - * was issued. - * @return S3StatusOK to continue processing the request, anything else to - * immediately abort the request with a status which will be - * passed to the S3ResponseCompleteCallback for this request. - * Typically, this will return either S3StatusOK or - * S3StatusAbortedByCallback. - **/ -typedef S3Status (S3ListBucketCallback)(int isTruncated, - const char *nextMarker, - int contentsCount, - const S3ListBucketContent *contents, - int commonPrefixesCount, - const char **commonPrefixes, - void *callbackData); - - -/** - * This callback is made during a put object operation, to obtain the next - * chunk of data to put to the S3 service as the contents of the object. This - * callback is made repeatedly, each time acquiring the next chunk of data to - * write to the service, until a negative or 0 value is returned. - * - * @param bufferSize gives the maximum number of bytes that may be written - * into the buffer parameter by this callback - * @param buffer gives the buffer to fill with at most bufferSize bytes of - * data as the next chunk of data to send to S3 as the contents of this - * object - * @param callbackData is the callback data as specified when the request - * was issued. - * @return < 0 to abort the request with the S3StatusAbortedByCallback, which - * will be pased to the response complete callback for this request, or - * 0 to indicate the end of data, or > 0 to identify the number of - * bytes that were written into the buffer by this callback - **/ -typedef int (S3PutObjectDataCallback)(int bufferSize, char *buffer, - void *callbackData); - - -/** - * This callback is made during a get object operation, to provide the next - * chunk of data available from the S3 service constituting the contents of - * the object being fetched. This callback is made repeatedly, each time - * providing the next chunk of data read, until the complete object contents - * have been passed through the callback in this way, or the callback - * returns an error status. - * - * @param bufferSize gives the number of bytes in buffer - * @param buffer is the data being passed into the callback - * @param callbackData is the callback data as specified when the request - * was issued. - * @return S3StatusOK to continue processing the request, anything else to - * immediately abort the request with a status which will be - * passed to the S3ResponseCompleteCallback for this request. - * Typically, this will return either S3StatusOK or - * S3StatusAbortedByCallback. - **/ -typedef S3Status (S3GetObjectDataCallback)(int bufferSize, const char *buffer, - void *callbackData); - - -/** ************************************************************************** - * Callback Structures - ************************************************************************** **/ - - -/** - * An S3ResponseHandler defines the callbacks which are made for any - * request. - **/ -typedef struct S3ResponseHandler -{ - /** - * The propertiesCallback is made when the response properties have - * successfully been returned from S3. This function may not be called - * if the response properties were not successfully returned from S3. - **/ - S3ResponsePropertiesCallback *propertiesCallback; - - /** - * The completeCallback is always called for every request made to S3, - * regardless of the outcome of the request. It provides the status of - * the request upon its completion, as well as extra error details in the - * event of an S3 error. - **/ - S3ResponseCompleteCallback *completeCallback; -} S3ResponseHandler; - - -/** - * An S3ListServiceHandler defines the callbacks which are made for - * list_service requests. - **/ -typedef struct S3ListServiceHandler -{ - /** - * responseHandler provides the properties and complete callback - **/ - S3ResponseHandler responseHandler; - - /** - * The listServiceCallback is called as items are reported back from S3 as - * responses to the request - **/ - S3ListServiceCallback *listServiceCallback; -} S3ListServiceHandler; - - -/** - * An S3ListBucketHandler defines the callbacks which are made for - * list_bucket requests. - **/ -typedef struct S3ListBucketHandler -{ - /** - * responseHandler provides the properties and complete callback - **/ - S3ResponseHandler responseHandler; - - /** - * The listBucketCallback is called as items are reported back from S3 as - * responses to the request. This may be called more than one time per - * list bucket request, each time providing more items from the list - * operation. - **/ - S3ListBucketCallback *listBucketCallback; -} S3ListBucketHandler; - - -/** - * An S3PutObjectHandler defines the callbacks which are made for - * put_object requests. - **/ -typedef struct S3PutObjectHandler -{ - /** - * responseHandler provides the properties and complete callback - **/ - S3ResponseHandler responseHandler; - - /** - * The putObjectDataCallback is called to acquire data to send to S3 as - * the contents of the put_object request. It is made repeatedly until it - * returns a negative number (indicating that the request should be - * aborted), or 0 (indicating that all data has been supplied). - **/ - S3PutObjectDataCallback *putObjectDataCallback; -} S3PutObjectHandler; - - -/** - * An S3GetObjectHandler defines the callbacks which are made for - * get_object requests. - **/ -typedef struct S3GetObjectHandler -{ - /** - * responseHandler provides the properties and complete callback - **/ - S3ResponseHandler responseHandler; - - /** - * The getObjectDataCallback is called as data is read from S3 as the - * contents of the object being read in the get_object request. It is - * called repeatedly until there is no more data provided in the request, - * or until the callback returns an error status indicating that the - * request should be aborted. - **/ - S3GetObjectDataCallback *getObjectDataCallback; -} S3GetObjectHandler; - - -/** ************************************************************************** - * General Library Functions - ************************************************************************** **/ - -/** - * Initializes libs3 for use. This function must be called before any other - * libs3 function is called. It may be called multiple times, with the same - * effect as calling it once, as long as S3_deinitialize() is called an - * equal number of times when the program has finished. This function is NOT - * thread-safe and must only be called by one thread at a time. - * - * @param userAgentInfo is a string that will be included in the User-Agent - * header of every request made to the S3 service. You may provide - * NULL or the empty string if you don't care about this. The value - * will not be copied by this function and must remain unaltered by the - * caller until S3_deinitialize() is called. - * @param flags is a bitmask of some combination of S3_INIT_XXX flag, or - * S3_INIT_ALL, indicating which of the libraries that libs3 depends - * upon should be initialized by S3_initialize(). Only if your program - * initializes one of these dependency libraries itself should anything - * other than S3_INIT_ALL be passed in for this bitmask. - * - * You should pass S3_INIT_WINSOCK if and only if your application does - * not initialize winsock elsewhere. On non-Microsoft Windows - * platforms it has no effect. - * - * As a convenience, the macro S3_INIT_ALL is provided, which will do - * all necessary initialization; however, be warned that things may - * break if your application re-initializes the dependent libraries - * later. - * @return One of: - * S3StatusOK on success - * S3StatusInternalError if dependent libraries could not be - * initialized - * S3StatusOutOfMemory on failure due to out of memory - **/ -S3Status S3_initialize(const char *userAgentInfo, int flags); - - -/** - * Must be called once per program for each call to libs3_initialize(). After - * this call is complete, no libs3 function may be called except - * S3_initialize(). - **/ -void S3_deinitialize(); - - -/** - * Returns a string with the textual name of an S3Status code - * - * @param status is S3Status code for which the textual name will be returned - * @return a string with the textual name of an S3Status code - **/ -const char *S3_get_status_name(S3Status status); - - -/** - * This function may be used to validate an S3 bucket name as being in the - * correct form for use with the S3 service. Amazon S3 limits the allowed - * characters in S3 bucket names, as well as imposing some additional rules on - * the length of bucket names and their structure. There are actually two - * limits; one for bucket names used only in path-style URIs, and a more - * strict limit used for bucket names used in virtual-host-style URIs. It is - * advisable to use only bucket names which meet the more strict requirements - * regardless of how the bucket expected to be used. - * - * This method does NOT validate that the bucket is available for use in the - * S3 service, so the return value of this function cannot be used to decide - * whether or not a bucket with the give name already exists in Amazon S3 or - * is accessible by the caller. It merely validates that the bucket name is - * valid for use with S3. - * - * @param bucketName is the bucket name to validate - * @param uriStyle gives the URI style to validate the bucket name against. - * It is advisable to always use S3UriStyleVirtuallHost. - * @return One of: - * S3StatusOK if the bucket name was validates successfully - * S3StatusInvalidBucketNameTooLong if the bucket name exceeded the - * length limitation for the URI style, which is 255 bytes for - * path style URIs and 63 bytes for virtual host type URIs - * S3StatusInvalidBucketNameTooShort if the bucket name is less than - * 3 characters - * S3StatusInvalidBucketNameFirstCharacter if the bucket name as an - * invalid first character, which is anything other than - * an alphanumeric character - * S3StatusInvalidBucketNameCharacterSequence if the bucket name - * includes an invalid character sequence, which for virtual host - * style buckets is ".-" or "-." - * S3StatusInvalidBucketNameCharacter if the bucket name includes an - * invalid character, which is anything other than alphanumeric, - * '-', '.', or for path style URIs only, '_'. - * S3StatusInvalidBucketNameDotQuadNotation if the bucket name is in - * dot-quad notation, i.e. the form of an IP address, which is - * not allowed by Amazon S3. - **/ -S3Status S3_validate_bucket_name(const char *bucketName, S3UriStyle uriStyle); - - -/** - * Converts an XML representation of an ACL to a libs3 structured - * representation. This method is not strictly necessary for working with - * ACLs using libs3, but may be convenient for users of the library who read - * ACLs from elsewhere in XML format and need to use these ACLs with libs3. - * - * @param aclXml is the XML representation of the ACL. This must be a - * zero-terminated character string. - * @param ownerId will be filled in with the Owner ID specified in the XML. - * At most MAX_GRANTEE_USER_ID_SIZE bytes will be stored at this - * location. - * @param ownerDisplayName will be filled in with the Owner Display Name - * specified in the XML. At most MAX_GRANTEE_DISPLAY_NAME_SIZE bytes - * will be stored at this location. - * @param aclGrantCountReturn returns the number of S3AclGrant structures - * returned in the aclGrantsReturned array - * @param aclGrants must be passed in as an array of at least S3_ACL_MAXCOUNT - * structures, and on return from this function, the first - * aclGrantCountReturn structures will be filled in with the ACLs - * represented by the input XML. - * @return One of: - * S3StatusOK on successful conversion of the ACL - * S3StatusInternalError on internal error representing a bug in the - * libs3 library - * S3StatusXmlParseFailure if the XML document was malformed - **/ -S3Status S3_convert_acl(char *aclXml, char *ownerId, char *ownerDisplayName, - int *aclGrantCountReturn, S3AclGrant *aclGrants); - - -/** - * Returns nonzero if the status indicates that the request should be - * immediately retried, because the status indicates an error of a nature that - * is likely due to transient conditions on the local system or S3, such as - * network failures, or internal retryable errors reported by S3. Returns - * zero otherwise. - * - * @param status is the status to evaluate - * @return nonzero if the status indicates a retryable error, 0 otherwise - **/ -int S3_status_is_retryable(S3Status status); - - -/** ************************************************************************** - * Request Context Management Functions - ************************************************************************** **/ - -/** - * An S3RequestContext allows muliple requests to be serviced by the same - * thread simultaneously. It is an optional parameter to all libs3 request - * functions, and if provided, the request is managed by the S3RequestContext; - * if not, the request is handled synchronously and is complete when the libs3 - * request function has returned. - * - * @param requestContextReturn returns the newly-created S3RequestContext - * structure, which if successfully returned, must be destroyed via a - * call to S3_destroy_request_context when it is no longer needed. If - * an error status is returned from this function, then - * requestContextReturn will not have been filled in, and - * S3_destroy_request_context should not be called on it - * @return One of: - * S3StatusOK if the request context was successfully created - * S3StatusOutOfMemory if the request context could not be created due - * to an out of memory error - **/ -S3Status S3_create_request_context(S3RequestContext **requestContextReturn); - - -/** - * Destroys an S3RequestContext which was created with - * S3_create_request_context. Any requests which are currently being - * processed by the S3RequestContext will immediately be aborted and their - * request completed callbacks made with the status S3StatusInterrupted. - * - * @param requestContext is the S3RequestContext to destroy - **/ -void S3_destroy_request_context(S3RequestContext *requestContext); - - -/** - * Runs the S3RequestContext until all requests within it have completed, - * or until an error occurs. - * - * @param requestContext is the S3RequestContext to run until all requests - * within it have completed or until an error occurs - * @return One of: - * S3Status if all requests were successfully run to completion - * S3StatusInternalError if an internal error prevented the - * S3RequestContext from running one or more requests - * S3StatusOutOfMemory if requests could not be run to completion - * due to an out of memory error - **/ -S3Status S3_runall_request_context(S3RequestContext *requestContext); - - -/** - * Does some processing of requests within the S3RequestContext. One or more - * requests may have callbacks made on them and may complete. This function - * processes any requests which have immediately available I/O, and will not - * block waiting for I/O on any request. This function would normally be used - * with S3_get_request_context_fdsets. - * - * @param requestContext is the S3RequestContext to process - * @param requestsRemainingReturn returns the number of requests remaining - * and not yet completed within the S3RequestContext after this - * function returns. - * @return One of: - * S3StatusOK if request processing proceeded without error - * S3StatusInternalError if an internal error prevented the - * S3RequestContext from running one or more requests - * S3StatusOutOfMemory if requests could not be processed due to - * an out of memory error - **/ -S3Status S3_runonce_request_context(S3RequestContext *requestContext, - int *requestsRemainingReturn); - - -/** - * This function, in conjunction allows callers to manually manage a set of - * requests using an S3RequestContext. This function returns the set of file - * descriptors which the caller can watch (typically using select()), along - * with any other file descriptors of interest to the caller, and using - * whatever timeout (if any) the caller wishes, until one or more file - * descriptors in the returned sets become ready for I/O, at which point - * S3_runonce_request_context can be called to process requests with available - * I/O. - * - * @param requestContext is the S3RequestContext to get fd_sets from - * @param readFdSet is a pointer to an fd_set which will have all file - * descriptors to watch for read events for the requests in the - * S3RequestContext set into it upon return. Should be zero'd out - * (using FD_ZERO) before being passed into this function. - * @param writeFdSet is a pointer to an fd_set which will have all file - * descriptors to watch for write events for the requests in the - * S3RequestContext set into it upon return. Should be zero'd out - * (using FD_ZERO) before being passed into this function. - * @param exceptFdSet is a pointer to an fd_set which will have all file - * descriptors to watch for exception events for the requests in the - * S3RequestContext set into it upon return. Should be zero'd out - * (using FD_ZERO) before being passed into this function. - * @param maxFd returns the highest file descriptor set into any of the - * fd_sets, or -1 if no file descriptors were set - * @return One of: - * S3StatusOK if all fd_sets were successfully set - * S3StatusInternalError if an internal error prevented this function - * from completing successfully - **/ -S3Status S3_get_request_context_fdsets(S3RequestContext *requestContext, - fd_set *readFdSet, fd_set *writeFdSet, - fd_set *exceptFdSet, int *maxFd); - - -/** - * This function returns the maximum number of milliseconds that the caller of - * S3_runonce_request_context should wait on the fdsets obtained via a call to - * S3_get_request_context_fdsets. In other words, this is essentially the - * select() timeout that needs to be used (shorter values are OK, but no - * longer than this) to ensure that internal timeout code of libs3 can work - * properly. This function should be called right before select() each time - * select() on the request_context fdsets are to be performed by the libs3 - * user. - * - * @param requestContext is the S3RequestContext to get the timeout from - * @return the maximum number of milliseconds to select() on fdsets. Callers - * could wait a shorter time if they wish, but not longer. - **/ -int64_t S3_get_request_context_timeout(S3RequestContext *requestContext); - - -/** ************************************************************************** - * S3 Utility Functions - ************************************************************************** **/ - -/** - * Generates an HTTP authenticated query string, which may then be used by - * a browser (or other web client) to issue the request. The request is - * implicitly a GET request; Amazon S3 is documented to only support this type - * of authenticated query string request. - * - * @param buffer is the output buffer for the authenticated query string. - * It must be at least S3_MAX_AUTHENTICATED_QUERY_STRING_SIZE bytes in - * length. - * @param bucketContext gives the bucket and associated parameters for the - * request to generate. - * @param key gives the key which the authenticated request will GET. - * @param expires gives the number of seconds since Unix epoch for the - * expiration date of the request; after this time, the request will - * no longer be valid. If this value is negative, the largest - * expiration date possible is used (currently, Jan 19, 2038). - * @param resource gives a sub-resource to be fetched for the request, or NULL - * for none. This should be of the form "?", i.e. - * "?torrent". - * @return One of: - * S3StatusUriTooLong if, due to an internal error, the generated URI - * is longer than S3_MAX_AUTHENTICATED_QUERY_STRING_SIZE bytes in - * length and thus will not fit into the supplied buffer - * S3StatusOK on success - **/ -S3Status S3_generate_authenticated_query_string - (char *buffer, const S3BucketContext *bucketContext, - const char *key, int64_t expires, const char *resource); - - -/** ************************************************************************** - * Service Functions - ************************************************************************** **/ - -/** - * Lists all S3 buckets belonging to the access key id. - * - * @param protocol gives the protocol to use for this request - * @param accessKeyId gives the Amazon Access Key ID for which to list owned - * buckets - * @param secretAccessKey gives the Amazon Secret Access Key for which to list - * owned buckets - * @param requestContext if non-NULL, gives the S3RequestContext to add this - * request to, and does not perform the request immediately. If NULL, - * performs the request immediately and synchronously. - * @param handler gives the callbacks to call as the request is processed and - * completed - * @param callbackData will be passed in as the callbackData parameter to - * all callbacks for this request - **/ -void S3_list_service(S3Protocol protocol, const char *accessKeyId, - const char *secretAccessKey, - S3RequestContext *requestContext, - const S3ListServiceHandler *handler, - void *callbackData); - - -/** ************************************************************************** - * Bucket Functions - ************************************************************************** **/ - -/** - * Tests the existence of an S3 bucket, additionally returning the bucket's - * location if it exists and is accessible. - * - * @param protocol gives the protocol to use for this request - * @param uriStyle gives the URI style to use for this request - * @param accessKeyId gives the Amazon Access Key ID for which to list owned - * buckets - * @param secretAccessKey gives the Amazon Secret Access Key for which to list - * owned buckets - * @param bucketName is the bucket name to test - * @param locationConstraintReturnSize gives the number of bytes in the - * locationConstraintReturn parameter - * @param locationConstraintReturn provides the location into which to write - * the name of the location constraint naming the geographic location - * of the S3 bucket. This must have at least as many characters in it - * as specified by locationConstraintReturn, and should start out - * NULL-terminated. On successful completion of this request, this - * will be set to the name of the geographic location of S3 bucket, or - * will be left as a zero-length string if no location was available. - * @param requestContext if non-NULL, gives the S3RequestContext to add this - * request to, and does not perform the request immediately. If NULL, - * performs the request immediately and synchronously. - * @param handler gives the callbacks to call as the request is processed and - * completed - * @param callbackData will be passed in as the callbackData parameter to - * all callbacks for this request - **/ -void S3_test_bucket(S3Protocol protocol, S3UriStyle uriStyle, - const char *accessKeyId, const char *secretAccessKey, - const char *bucketName, int locationConstraintReturnSize, - char *locationConstraintReturn, - S3RequestContext *requestContext, - const S3ResponseHandler *handler, void *callbackData); - - -/** - * Creates a new bucket. - * - * @param protocol gives the protocol to use for this request - * @param accessKeyId gives the Amazon Access Key ID for which to list owned - * buckets - * @param secretAccessKey gives the Amazon Secret Access Key for which to list - * owned buckets - * @param bucketName is the name of the bucket to be created - * @param cannedAcl gives the "REST canned ACL" to use for the created bucket - * @param locationConstraint if non-NULL, gives the geographic location for - * the bucket to create. - * @param requestContext if non-NULL, gives the S3RequestContext to add this - * request to, and does not perform the request immediately. If NULL, - * performs the request immediately and synchronously. - * @param handler gives the callbacks to call as the request is processed and - * completed - * @param callbackData will be passed in as the callbackData parameter to - * all callbacks for this request - **/ -void S3_create_bucket(S3Protocol protocol, const char *accessKeyId, - const char *secretAccessKey, const char *bucketName, - S3CannedAcl cannedAcl, const char *locationConstraint, - S3RequestContext *requestContext, - const S3ResponseHandler *handler, void *callbackData); - - -/** - * Deletes a bucket. The bucket must be empty, or the status - * S3StatusErrorBucketNotEmpty will result. - * - * @param protocol gives the protocol to use for this request - * @param uriStyle gives the URI style to use for this request - * @param accessKeyId gives the Amazon Access Key ID for which to list owned - * buckets - * @param secretAccessKey gives the Amazon Secret Access Key for which to list - * owned buckets - * @param bucketName is the name of the bucket to be deleted - * @param requestContext if non-NULL, gives the S3RequestContext to add this - * request to, and does not perform the request immediately. If NULL, - * performs the request immediately and synchronously. - * @param handler gives the callbacks to call as the request is processed and - * completed - * @param callbackData will be passed in as the callbackData parameter to - * all callbacks for this request - **/ -void S3_delete_bucket(S3Protocol protocol, S3UriStyle uriStyle, - const char *accessKeyId, const char *secretAccessKey, - const char *bucketName, S3RequestContext *requestContext, - const S3ResponseHandler *handler, void *callbackData); - - -/** - * Lists keys within a bucket. - * - * @param bucketContext gives the bucket and associated parameters for this - * request - * @param prefix if present, gives a prefix for matching keys - * @param marker if present, only keys occuring after this value will be - * listed - * @param delimiter if present, causes keys that contain the same string - * between the prefix and the first occurrence of the delimiter to be - * rolled up into a single result element - * @param maxkeys is the maximum number of keys to return - * @param requestContext if non-NULL, gives the S3RequestContext to add this - * request to, and does not perform the request immediately. If NULL, - * performs the request immediately and synchronously. - * @param handler gives the callbacks to call as the request is processed and - * completed - * @param callbackData will be passed in as the callbackData parameter to - * all callbacks for this request - **/ -void S3_list_bucket(const S3BucketContext *bucketContext, - const char *prefix, const char *marker, - const char *delimiter, int maxkeys, - S3RequestContext *requestContext, - const S3ListBucketHandler *handler, void *callbackData); - - -/** ************************************************************************** - * Object Functions - ************************************************************************** **/ - -/** - * Puts object data to S3. This overwrites any existing object at that key; - * note that S3 currently only supports full-object upload. The data to - * upload will be acquired by calling the handler's putObjectDataCallback. - * - * @param bucketContext gives the bucket and associated parameters for this - * request - * @param key is the key of the object to put to - * @param contentLength is required and gives the total number of bytes that - * will be put - * @param putProperties optionally provides additional properties to apply to - * the object that is being put to - * @param requestContext if non-NULL, gives the S3RequestContext to add this - * request to, and does not perform the request immediately. If NULL, - * performs the request immediately and synchronously. - * @param handler gives the callbacks to call as the request is processed and - * completed - * @param callbackData will be passed in as the callbackData parameter to - * all callbacks for this request - **/ -void S3_put_object(const S3BucketContext *bucketContext, const char *key, - uint64_t contentLength, - const S3PutProperties *putProperties, - S3RequestContext *requestContext, - const S3PutObjectHandler *handler, void *callbackData); - - -/** - * Copies an object from one location to another. The object may be copied - * back to itself, which is useful for replacing metadata without changing - * the object. - * - * @param bucketContext gives the source bucket and associated parameters for - * this request - * @param key is the source key - * @param destinationBucket gives the destination bucket into which to copy - * the object. If NULL, the source bucket will be used. - * @param destinationKey gives the destination key into which to copy the - * object. If NULL, the source key will be used. - * @param putProperties optionally provides properties to apply to the object - * that is being put to. If not supplied (i.e. NULL is passed in), - * then the copied object will retain the metadata of the copied - * object. - * @param lastModifiedReturn returns the last modified date of the copied - * object - * @param eTagReturnSize specifies the number of bytes provided in the - * eTagReturn buffer - * @param eTagReturn is a buffer into which the resulting eTag of the copied - * object will be written - * @param handler gives the callbacks to call as the request is processed and - * completed - * @param callbackData will be passed in as the callbackData parameter to - * all callbacks for this request - * @param requestContext if non-NULL, gives the S3RequestContext to add this - * request to, and does not perform the request immediately. If NULL, - * performs the request immediately and synchronously. - * @param handler gives the callbacks to call as the request is processed and - * completed - * @param callbackData will be passed in as the callbackData parameter to - * all callbacks for this request - **/ -void S3_copy_object(const S3BucketContext *bucketContext, - const char *key, const char *destinationBucket, - const char *destinationKey, - const S3PutProperties *putProperties, - int64_t *lastModifiedReturn, int eTagReturnSize, - char *eTagReturn, S3RequestContext *requestContext, - const S3ResponseHandler *handler, void *callbackData); - - -/** - * Gets an object from S3. The contents of the object are returned in the - * handler's getObjectDataCallback. - * - * @param bucketContext gives the bucket and associated parameters for this - * request - * @param key is the key of the object to get - * @param getConditions if non-NULL, gives a set of conditions which must be - * met in order for the request to succeed - * @param startByte gives the start byte for the byte range of the contents - * to be returned - * @param byteCount gives the number of bytes to return; a value of 0 - * indicates that the contents up to the end should be returned - * @param requestContext if non-NULL, gives the S3RequestContext to add this - * request to, and does not perform the request immediately. If NULL, - * performs the request immediately and synchronously. - * @param handler gives the callbacks to call as the request is processed and - * completed - * @param callbackData will be passed in as the callbackData parameter to - * all callbacks for this request - **/ -void S3_get_object(const S3BucketContext *bucketContext, const char *key, - const S3GetConditions *getConditions, - uint64_t startByte, uint64_t byteCount, - S3RequestContext *requestContext, - const S3GetObjectHandler *handler, void *callbackData); - - -/** - * Gets the response properties for the object, but not the object contents. - * - * @param bucketContext gives the bucket and associated parameters for this - * request - * @param key is the key of the object to get the properties of - * @param requestContext if non-NULL, gives the S3RequestContext to add this - * request to, and does not perform the request immediately. If NULL, - * performs the request immediately and synchronously. - * @param handler gives the callbacks to call as the request is processed and - * completed - * @param callbackData will be passed in as the callbackData parameter to - * all callbacks for this request - **/ -void S3_head_object(const S3BucketContext *bucketContext, const char *key, - S3RequestContext *requestContext, - const S3ResponseHandler *handler, void *callbackData); - -/** - * Deletes an object from S3. - * - * @param bucketContext gives the bucket and associated parameters for this - * request - * @param key is the key of the object to delete - * @param requestContext if non-NULL, gives the S3RequestContext to add this - * request to, and does not perform the request immediately. If NULL, - * performs the request immediately and synchronously. - * @param handler gives the callbacks to call as the request is processed and - * completed - * @param callbackData will be passed in as the callbackData parameter to - * all callbacks for this request - **/ -void S3_delete_object(const S3BucketContext *bucketContext, const char *key, - S3RequestContext *requestContext, - const S3ResponseHandler *handler, void *callbackData); - - -/** ************************************************************************** - * Access Control List Functions - ************************************************************************** **/ - -/** - * Gets the ACL for the given bucket or object. - * - * @param bucketContext gives the bucket and associated parameters for this - * request - * @param key is the key of the object to get the ACL of; or NULL to get the - * ACL of the bucket - * @param ownerId must be supplied as a buffer of at least - * S3_MAX_GRANTEE_USER_ID_SIZE bytes, and will be filled in with the - * owner ID of the object/bucket - * @param ownerDisplayName must be supplied as a buffer of at least - * S3_MAX_GRANTEE_DISPLAY_NAME_SIZE bytes, and will be filled in with - * the display name of the object/bucket - * @param aclGrantCountReturn returns the number of S3AclGrant structures - * returned in the aclGrants parameter - * @param aclGrants must be passed in as an array of at least - * S3_MAX_ACL_GRANT_COUNT S3AclGrant structures, which will be filled - * in with the grant information for the ACL - * @param requestContext if non-NULL, gives the S3RequestContext to add this - * request to, and does not perform the request immediately. If NULL, - * performs the request immediately and synchronously. - * @param handler gives the callbacks to call as the request is processed and - * completed - * @param callbackData will be passed in as the callbackData parameter to - * all callbacks for this request - **/ -void S3_get_acl(const S3BucketContext *bucketContext, const char *key, - char *ownerId, char *ownerDisplayName, - int *aclGrantCountReturn, S3AclGrant *aclGrants, - S3RequestContext *requestContext, - const S3ResponseHandler *handler, void *callbackData); - - -/** - * Sets the ACL for the given bucket or object. - * - * @param bucketContext gives the bucket and associated parameters for this - * request - * @param key is the key of the object to set the ACL for; or NULL to set the - * ACL for the bucket - * @param ownerId is the owner ID of the object/bucket. Unfortunately, S3 - * requires this to be valid and thus it must have been fetched by a - * previous S3 request, such as a list_buckets request. - * @param ownerDisplayName is the owner display name of the object/bucket. - * Unfortunately, S3 requires this to be valid and thus it must have - * been fetched by a previous S3 request, such as a list_buckets - * request. - * @param aclGrantCount is the number of ACL grants to set for the - * object/bucket - * @param aclGrants are the ACL grants to set for the object/bucket - * @param requestContext if non-NULL, gives the S3RequestContext to add this - * request to, and does not perform the request immediately. If NULL, - * performs the request immediately and synchronously. - * @param handler gives the callbacks to call as the request is processed and - * completed - * @param callbackData will be passed in as the callbackData parameter to - * all callbacks for this request - **/ -void S3_set_acl(const S3BucketContext *bucketContext, const char *key, - const char *ownerId, const char *ownerDisplayName, - int aclGrantCount, const S3AclGrant *aclGrants, - S3RequestContext *requestContext, - const S3ResponseHandler *handler, void *callbackData); - - -/** ************************************************************************** - * Server Access Log Functions - ************************************************************************** **/ - -/** - * Gets the service access logging settings for a bucket. The service access - * logging settings specify whether or not the S3 service will write service - * access logs for requests made for the given bucket, and if so, several - * settings controlling how these logs will be written. - * - * @param bucketContext gives the bucket and associated parameters for this - * request; this is the bucket for which service access logging is - * being requested - * @param targetBucketReturn must be passed in as a buffer of at least - * (S3_MAX_BUCKET_NAME_SIZE + 1) bytes in length, and will be filled - * in with the target bucket name for access logging for the given - * bucket, which is the bucket into which access logs for the specified - * bucket will be written. This is returned as an empty string if - * service access logging is not enabled for the given bucket. - * @param targetPrefixReturn must be passed in as a buffer of at least - * (S3_MAX_KEY_SIZE + 1) bytes in length, and will be filled in - * with the key prefix for server access logs for the given bucket, - * or the empty string if no such prefix is specified. - * @param aclGrantCountReturn returns the number of ACL grants that are - * associated with the server access logging for the given bucket. - * @param aclGrants must be passed in as an array of at least - * S3_MAX_ACL_GRANT_COUNT S3AclGrant structures, and these will be - * filled in with the target grants associated with the server access - * logging for the given bucket, whose number is returned in the - * aclGrantCountReturn parameter. These grants will be applied to the - * ACL of any server access logging log files generated by the S3 - * service for the given bucket. - * @param requestContext if non-NULL, gives the S3RequestContext to add this - * request to, and does not perform the request immediately. If NULL, - * performs the request immediately and synchronously. - * @param handler gives the callbacks to call as the request is processed and - * completed - * @param callbackData will be passed in as the callbackData parameter to - * all callbacks for this request - **/ -void S3_get_server_access_logging(const S3BucketContext *bucketContext, - char *targetBucketReturn, - char *targetPrefixReturn, - int *aclGrantCountReturn, - S3AclGrant *aclGrants, - S3RequestContext *requestContext, - const S3ResponseHandler *handler, - void *callbackData); - - -/** - * Sets the service access logging settings for a bucket. The service access - * logging settings specify whether or not the S3 service will write service - * access logs for requests made for the given bucket, and if so, several - * settings controlling how these logs will be written. - * - * @param bucketContext gives the bucket and associated parameters for this - * request; this is the bucket for which service access logging is - * being set - * @param targetBucket gives the target bucket name for access logging for the - * given bucket, which is the bucket into which access logs for the - * specified bucket will be written. - * @param targetPrefix is an option parameter which specifies the key prefix - * for server access logs for the given bucket, or NULL if no such - * prefix is to be used. - * @param aclGrantCount specifies the number of ACL grants that are to be - * associated with the server access logging for the given bucket. - * @param aclGrants is as an array of S3AclGrant structures, whose number is - * given by the aclGrantCount parameter. These grants will be applied - * to the ACL of any server access logging log files generated by the - * S3 service for the given bucket. - * @param requestContext if non-NULL, gives the S3RequestContext to add this - * request to, and does not perform the request immediately. If NULL, - * performs the request immediately and synchronously. - * @param handler gives the callbacks to call as the request is processed and - * completed - * @param callbackData will be passed in as the callbackData parameter to - * all callbacks for this request - **/ -void S3_set_server_access_logging(const S3BucketContext *bucketContext, - const char *targetBucket, - const char *targetPrefix, int aclGrantCount, - const S3AclGrant *aclGrants, - S3RequestContext *requestContext, - const S3ResponseHandler *handler, - void *callbackData); - - -#ifdef __cplusplus -} -#endif - -#endif /* LIBS3_H */ diff --git a/libs3-1.4/inc/mingw/pthread.h b/libs3-1.4/inc/mingw/pthread.h deleted file mode 100644 index 674a62a..0000000 --- a/libs3-1.4/inc/mingw/pthread.h +++ /dev/null @@ -1,45 +0,0 @@ -/** ************************************************************************** - * pthread.h - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -#ifndef PTHREAD_H -#define PTHREAD_H - -// This is a minimal implementation of pthreads on Windows, implementing just -// the APIs needed by libs3 - -unsigned long pthread_self(); - -typedef struct -{ - CRITICAL_SECTION criticalSection; -} pthread_mutex_t; - -int pthread_mutex_init(pthread_mutex_t *mutex, void *); -int pthread_mutex_lock(pthread_mutex_t *mutex); -int pthread_mutex_unlock(pthread_mutex_t *mutex); -int pthread_mutex_destroy(pthread_mutex_t *mutex); - -#endif /* PTHREAD_H */ diff --git a/libs3-1.4/inc/mingw/sys/select.h b/libs3-1.4/inc/mingw/sys/select.h deleted file mode 100644 index 0981da2..0000000 --- a/libs3-1.4/inc/mingw/sys/select.h +++ /dev/null @@ -1,30 +0,0 @@ -/** ************************************************************************** - * select.h - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -// This file is used only on a MingW build, and converts an include of -// sys/select.h to its Windows equivalent - -#include diff --git a/libs3-1.4/inc/mingw/sys/utsname.h b/libs3-1.4/inc/mingw/sys/utsname.h deleted file mode 100644 index 1e6b470..0000000 --- a/libs3-1.4/inc/mingw/sys/utsname.h +++ /dev/null @@ -1,41 +0,0 @@ -/** ************************************************************************** - * utsname.h - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -// This file is used only on a MingW build, and provides an implementation -// of POSIX sys/utsname.h - -#ifndef UTSNAME_H -#define UTSNAME_H - -struct utsname -{ - const char *sysname; - const char *machine; -}; - -int uname(struct utsname *); - -#endif /* UTSNAME_H */ diff --git a/libs3-1.4/inc/request.h b/libs3-1.4/inc/request.h deleted file mode 100644 index afb4929..0000000 --- a/libs3-1.4/inc/request.h +++ /dev/null @@ -1,185 +0,0 @@ -/** ************************************************************************** - * request.h - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -#ifndef REQUEST_H -#define REQUEST_H - -#include "libs3.h" -#include "error_parser.h" -#include "response_headers_handler.h" -#include "util.h" - -// Describes a type of HTTP request (these are our supported HTTP "verbs") -typedef enum -{ - HttpRequestTypeGET, - HttpRequestTypeHEAD, - HttpRequestTypePUT, - HttpRequestTypeCOPY, - HttpRequestTypeDELETE -} HttpRequestType; - - -// This completely describes a request. A RequestParams is not required to be -// allocated from the heap and its lifetime is not assumed to extend beyond -// the lifetime of the function to which it has been passed. -typedef struct RequestParams -{ - // Request type, affects the HTTP verb used - HttpRequestType httpRequestType; - - // Bucket context for request - S3BucketContext bucketContext; - - // Key, if any - const char *key; - - // Query params - ready to append to URI (i.e. ?p1=v1?p2=v2) - const char *queryParams; - - // sub resource, like ?acl, ?location, ?torrent, ?logging - const char *subResource; - - // If this is a copy operation, this gives the source bucket - const char *copySourceBucketName; - - // If this is a copy operation, this gives the source key - const char *copySourceKey; - - // Get conditions - const S3GetConditions *getConditions; - - // Start byte - uint64_t startByte; - - // Byte count - uint64_t byteCount; - - // Put properties - const S3PutProperties *putProperties; - - // Callback to be made when headers are available. Might not be called. - S3ResponsePropertiesCallback *propertiesCallback; - - // Callback to be made to supply data to send to S3. Might not be called. - S3PutObjectDataCallback *toS3Callback; - - // Number of bytes total that readCallback will supply - int64_t toS3CallbackTotalSize; - - // Callback to be made that supplies data read from S3. - // Might not be called. - S3GetObjectDataCallback *fromS3Callback; - - // Callback to be made when request is complete. This will *always* be - // called. - S3ResponseCompleteCallback *completeCallback; - - // Data passed to the callbacks - void *callbackData; -} RequestParams; - - -// This is the stuff associated with a request that needs to be on the heap -// (and thus live while a curl_multi is in use). -typedef struct Request -{ - // These put the request on a doubly-linked list of requests in a - // request context, *if* the request is in a request context (else these - // will both be 0) - struct Request *prev, *next; - - // The status of this Request, as will be reported to the user via the - // complete callback - S3Status status; - - // The HTTP code returned by the S3 server, if it is known. Would rather - // not have to keep track of this but S3 doesn't always indicate its - // errors the same way - int httpResponseCode; - - // The HTTP headers to use for the curl request - struct curl_slist *headers; - - // The CURL structure driving the request - CURL *curl; - - // libcurl requires that the uri be stored outside of the curl handle - char uri[MAX_URI_SIZE + 1]; - - // Callback to be made when headers are available. Might not be called. - S3ResponsePropertiesCallback *propertiesCallback; - - // Callback to be made to supply data to send to S3. Might not be called. - S3PutObjectDataCallback *toS3Callback; - - // Number of bytes total that readCallback has left to supply - int64_t toS3CallbackBytesRemaining; - - // Callback to be made that supplies data read from S3. - // Might not be called. - S3GetObjectDataCallback *fromS3Callback; - - // Callback to be made when request is complete. This will *always* be - // called. - S3ResponseCompleteCallback *completeCallback; - - // Data passed to the callbacks - void *callbackData; - - // Handler of response headers - ResponseHeadersHandler responseHeadersHandler; - - // This is set to nonzero after the properties callback has been made - int propertiesCallbackMade; - - // Parser of errors - ErrorParser errorParser; -} Request; - - -// Request functions -// ---------------------------------------------------------------------------- - -// Initialize the API -S3Status request_api_initialize(const char *userAgentInfo, int flags); - -// Deinitialize the API -void request_api_deinitialize(); - -// Perform a request; if context is 0, performs the request immediately; -// otherwise, sets it up to be performed by context. -void request_perform(const RequestParams *params, S3RequestContext *context); - -// Called by the internal request code or internal request context code when a -// curl has finished the request -void request_finish(Request *request); - -// Convert a CURLE code to an S3Status -S3Status request_curl_code_to_status(CURLcode code); - - -#endif /* REQUEST_H */ diff --git a/libs3-1.4/inc/request_context.h b/libs3-1.4/inc/request_context.h deleted file mode 100644 index 8074c50..0000000 --- a/libs3-1.4/inc/request_context.h +++ /dev/null @@ -1,40 +0,0 @@ -/** ************************************************************************** - * request_context.h - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -#ifndef REQUEST_CONTEXT_H -#define REQUEST_CONTEXT_H - -#include "libs3.h" - -struct S3RequestContext -{ - CURLM *curlm; - - struct Request *requests; -}; - - -#endif /* REQUEST_CONTEXT_H */ diff --git a/libs3-1.4/inc/response_headers_handler.h b/libs3-1.4/inc/response_headers_handler.h deleted file mode 100644 index 2813e9a..0000000 --- a/libs3-1.4/inc/response_headers_handler.h +++ /dev/null @@ -1,64 +0,0 @@ -/** ************************************************************************** - * response_headers_handler.h - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -#ifndef RESPONSE_HEADERS_HANDLER_H -#define RESPONSE_HEADERS_HANDLER_H - -#include "libs3.h" -#include "string_buffer.h" -#include "util.h" - - -typedef struct ResponseHeadersHandler -{ - // The structure to pass to the headers callback. This is filled in by - // the ResponseHeadersHandler from the headers added to it. - S3ResponseProperties responseProperties; - - // Set to 1 after the done call has been made - int done; - - // copied into here. We allow 128 bytes for each header, plus \0 term. - string_multibuffer(responsePropertyStrings, 5 * 129); - - // responseproperties.metaHeaders strings get copied into here - string_multibuffer(responseMetaDataStrings, - COMPACTED_METADATA_BUFFER_SIZE); - - // Response meta data - S3NameValue responseMetaData[S3_MAX_METADATA_COUNT]; -} ResponseHeadersHandler; - - -void response_headers_handler_initialize(ResponseHeadersHandler *handler); - -void response_headers_handler_add(ResponseHeadersHandler *handler, - char *data, int dataLen); - -void response_headers_handler_done(ResponseHeadersHandler *handler, - CURL *curl); - -#endif /* RESPONSE_HEADERS_HANDLER_H */ diff --git a/libs3-1.4/inc/simplexml.h b/libs3-1.4/inc/simplexml.h deleted file mode 100644 index 704db07..0000000 --- a/libs3-1.4/inc/simplexml.h +++ /dev/null @@ -1,76 +0,0 @@ -/** ************************************************************************** - * simplexml.h - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -#ifndef SIMPLEXML_H -#define SIMPLEXML_H - -#include "libs3.h" - - -// Simple XML callback. -// -// elementPath: is the full "path" of the element; i.e. -// data would have 'data' in the element -// foo/bar/baz. -// -// Return of anything other than S3StatusOK causes the calling -// simplexml_add() function to immediately stop and return the status. -// -// data is passed in as 0 on end of element -typedef S3Status (SimpleXmlCallback)(const char *elementPath, const char *data, - int dataLen, void *callbackData); - -typedef struct SimpleXml -{ - void *xmlParser; - - SimpleXmlCallback *callback; - - void *callbackData; - - char elementPath[512]; - - int elementPathLen; - - S3Status status; -} SimpleXml; - - -// Simple XML parsing -// ---------------------------------------------------------------------------- - -// Always call this, even if the simplexml doesn't end up being used -void simplexml_initialize(SimpleXml *simpleXml, SimpleXmlCallback *callback, - void *callbackData); - -S3Status simplexml_add(SimpleXml *simpleXml, const char *data, int dataLen); - - -// Always call this -void simplexml_deinitialize(SimpleXml *simpleXml); - - -#endif /* SIMPLEXML_H */ diff --git a/libs3-1.4/inc/string_buffer.h b/libs3-1.4/inc/string_buffer.h deleted file mode 100644 index eed9bd4..0000000 --- a/libs3-1.4/inc/string_buffer.h +++ /dev/null @@ -1,107 +0,0 @@ -/** ************************************************************************** - * string_buffer.h - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -#ifndef STRING_BUFFER_H -#define STRING_BUFFER_H - -#include - - -// Declare a string_buffer with the given name of the given maximum length -#define string_buffer(name, len) \ - char name[len + 1]; \ - int name##Len - - -// Initialize a string_buffer -#define string_buffer_initialize(sb) \ - do { \ - sb[0] = 0; \ - sb##Len = 0; \ - } while (0) - - -// Append [len] bytes of [str] to [sb], setting [all_fit] to 1 if it fit, and -// 0 if it did not -#define string_buffer_append(sb, str, len, all_fit) \ - do { \ - sb##Len += snprintf(&(sb[sb##Len]), sizeof(sb) - sb##Len - 1, \ - "%.*s", (int) (len), str); \ - if (sb##Len > (int) (sizeof(sb) - 1)) { \ - sb##Len = sizeof(sb) - 1; \ - all_fit = 0; \ - } \ - else { \ - all_fit = 1; \ - } \ - } while (0) - - -// Declare a string multibuffer with the given name of the given maximum size -#define string_multibuffer(name, size) \ - char name[size]; \ - int name##Size - - -// Initialize a string_multibuffer -#define string_multibuffer_initialize(smb) \ - do { \ - smb##Size = 0; \ - } while (0) - - -// Evaluates to the current string within the string_multibuffer -#define string_multibuffer_current(smb) \ - &(smb[smb##Size]) - - -// Adds a new string to the string_multibuffer -#define string_multibuffer_add(smb, str, len, all_fit) \ - do { \ - smb##Size += (snprintf(&(smb[smb##Size]), \ - sizeof(smb) - smb##Size, \ - "%.*s", (int) (len), str) + 1); \ - if (smb##Size > (int) sizeof(smb)) { \ - smb##Size = sizeof(smb); \ - all_fit = 0; \ - } \ - else { \ - all_fit = 1; \ - } \ - } while (0) - - -// Appends to the current string in the string_multibuffer. There must be a -// current string, meaning that string_multibuffer_add must have been called -// at least once for this string_multibuffer. -#define string_multibuffer_append(smb, str, len, all_fit) \ - do { \ - smb##Size--; \ - string_multibuffer_add(smb, str, len, all_fit); \ - } while (0) - - -#endif /* STRING_BUFFER_H */ diff --git a/libs3-1.4/inc/util.h b/libs3-1.4/inc/util.h deleted file mode 100644 index 94735a8..0000000 --- a/libs3-1.4/inc/util.h +++ /dev/null @@ -1,90 +0,0 @@ -/** ************************************************************************** - * util.h - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -#ifndef UTIL_H -#define UTIL_H - -#include -#include -#include -#include "libs3.h" - - -// Derived from S3 documentation - -// This is the maximum number of bytes needed in a "compacted meta header" -// buffer, which is a buffer storing all of the compacted meta headers. -#define COMPACTED_METADATA_BUFFER_SIZE \ - (S3_MAX_METADATA_COUNT * sizeof(S3_METADATA_HEADER_NAME_PREFIX "n: v")) - -// Maximum url encoded key size; since every single character could require -// URL encoding, it's 3 times the size of a key (since each url encoded -// character takes 3 characters: %NN) -#define MAX_URLENCODED_KEY_SIZE (3 * S3_MAX_KEY_SIZE) - -// This is the maximum size of a URI that could be passed to S3: -// https://s3.amazonaws.com/${BUCKET}/${KEY}?acl -// 255 is the maximum bucket length -#define MAX_URI_SIZE \ - ((sizeof("https://" S3_HOSTNAME "/") - 1) + 255 + 1 + \ - MAX_URLENCODED_KEY_SIZE + (sizeof("?torrent" - 1)) + 1) - -// Maximum size of a canonicalized resource -#define MAX_CANONICALIZED_RESOURCE_SIZE \ - (1 + 255 + 1 + MAX_URLENCODED_KEY_SIZE + (sizeof("?torrent") - 1) + 1) - - -// Utilities ----------------------------------------------------------------- - -// URL-encodes a string from [src] into [dest]. [dest] must have at least -// 3x the number of characters that [source] has. At most [maxSrcSize] bytes -// from [src] are encoded; if more are present in [src], 0 is returned from -// urlEncode, else nonzero is returned. -int urlEncode(char *dest, const char *src, int maxSrcSize); - -// Returns < 0 on failure >= 0 on success -int64_t parseIso8601Time(const char *str); - -uint64_t parseUnsignedInt(const char *str); - -// base64 encode bytes. The output buffer must have at least -// ((4 * (inLen + 1)) / 3) bytes in it. Returns the number of bytes written -// to [out]. -int base64Encode(const unsigned char *in, int inLen, char *out); - -// Compute HMAC-SHA-1 with key [key] and message [message], storing result -// in [hmac] -void HMAC_SHA1(unsigned char hmac[20], const unsigned char *key, int key_len, - const unsigned char *message, int message_len); - -// Compute a 64-bit hash values given a set of bytes -uint64_t hash(const unsigned char *k, int length); - -// Because Windows seems to be missing isblank(), use our own; it's a very -// easy function to write in any case -int is_blank(char c); - -#endif /* UTIL_H */ diff --git a/libs3-1.4/libs3.spec b/libs3-1.4/libs3.spec deleted file mode 100644 index 52a45b2..0000000 --- a/libs3-1.4/libs3.spec +++ /dev/null @@ -1,81 +0,0 @@ -Summary: C Library and Tools for Amazon S3 Access -Name: libs3 -Version: 1.4 -Release: 1 -License: GPL -Group: Networking/Utilities -URL: http://sourceforge.net/projects/reallibs3 -Source0: libs3-1.4.tar.gz -Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root -# Want to include curl dependencies, but older Fedora Core uses curl-devel, -# and newer Fedora Core uses libcurl-devel ... have to figure out how to -# handle this problem, but for now, just don't check for any curl libraries -# Buildrequires: curl-devel -Buildrequires: libxml2-devel -Buildrequires: openssl-devel -Buildrequires: make -# Requires: libcurl -Requires: libxml2 -Requires: openssl - -%define debug_package %{nil} - -%description -This package includes the libs3 shared object library, needed to run -applications compiled against libs3, and additionally contains the s3 -utility for accessing Amazon S3. - -%package devel -Summary: Headers and documentation for libs3 -Group: Development/Libraries -Requires: %{name} = %{version}-%{release} - -%description devel -This library provides an API for using Amazon's S3 service (see -http://s3.amazonaws.com). Its design goals are: - - - To provide a simple and straightforward API for accessing all of S3's - functionality - - To not require the developer using libs3 to need to know anything about: - - HTTP - - XML - - SSL - In other words, this API is meant to stand on its own, without requiring - any implicit knowledge of how S3 services are accessed using HTTP - protocols. - - To be usable from multithreaded code - - To be usable by code which wants to process multiple S3 requests - simultaneously from a single thread - - To be usable in the simple, straightforward way using sequentialized - blocking requests - - -%prep -%setup -q - -%build -BUILD=$RPM_BUILD_ROOT/build make exported - -%install -BUILD=$RPM_BUILD_ROOT/build DESTDIR=$RPM_BUILD_ROOT/usr make install -rm -rf $RPM_BUILD_ROOT/build - -%clean -rm -rf $RPM_BUILD_ROOT - -%files -%defattr(-,root,root,-) -/usr/bin/s3 -/usr/lib/libs3.so* - -%files devel -%defattr(-,root,root,-) -/usr/include/libs3.h -/usr/lib/libs3.a - -%changelog -* Sat Aug 09 2008 Bryan Ischo -- Split into regular and devel packages. - -* Tue Aug 05 2008 Bryan Ischo -- Initial build. diff --git a/libs3-1.4/mswin/libs3.def b/libs3-1.4/mswin/libs3.def deleted file mode 100644 index c5bd6d8..0000000 --- a/libs3-1.4/mswin/libs3.def +++ /dev/null @@ -1,27 +0,0 @@ -EXPORTS -S3_convert_acl -S3_copy_object -S3_create_bucket -S3_create_request_context -S3_deinitialize -S3_delete_bucket -S3_delete_object -S3_destroy_request_context -S3_generate_authenticated_query_string -S3_get_acl -S3_get_object -S3_get_request_context_fdsets -S3_get_server_access_logging -S3_get_status_name -S3_head_object -S3_initialize -S3_list_bucket -S3_list_service -S3_put_object -S3_runall_request_context -S3_runonce_request_context -S3_set_acl -S3_set_server_access_logging -S3_status_is_retryable -S3_test_bucket -S3_validate_bucket_name diff --git a/libs3-1.4/mswin/rmrf.bat b/libs3-1.4/mswin/rmrf.bat deleted file mode 100644 index 204efd9..0000000 --- a/libs3-1.4/mswin/rmrf.bat +++ /dev/null @@ -1,9 +0,0 @@ -@echo off - -if exist "%1". ( - rmdir /S /Q "%1" -) - -if exist "%1". ( - del /Q "%1" -) diff --git a/libs3-1.4/src/acl.c b/libs3-1.4/src/acl.c deleted file mode 100644 index 2a8272b..0000000 --- a/libs3-1.4/src/acl.c +++ /dev/null @@ -1,349 +0,0 @@ -/** ************************************************************************** - * acl.c - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -#include -#include -#include "libs3.h" -#include "request.h" - -// Use a rather arbitrary max size for the document of 64K -#define ACL_XML_DOC_MAXSIZE (64 * 1024) - - -// get acl ------------------------------------------------------------------- - -typedef struct GetAclData -{ - SimpleXml simpleXml; - - S3ResponsePropertiesCallback *responsePropertiesCallback; - S3ResponseCompleteCallback *responseCompleteCallback; - void *callbackData; - - int *aclGrantCountReturn; - S3AclGrant *aclGrants; - char *ownerId; - char *ownerDisplayName; - string_buffer(aclXmlDocument, ACL_XML_DOC_MAXSIZE); -} GetAclData; - - -static S3Status getAclPropertiesCallback - (const S3ResponseProperties *responseProperties, void *callbackData) -{ - GetAclData *gaData = (GetAclData *) callbackData; - - return (*(gaData->responsePropertiesCallback)) - (responseProperties, gaData->callbackData); -} - - -static S3Status getAclDataCallback(int bufferSize, const char *buffer, - void *callbackData) -{ - GetAclData *gaData = (GetAclData *) callbackData; - - int fit; - - string_buffer_append(gaData->aclXmlDocument, buffer, bufferSize, fit); - - return fit ? S3StatusOK : S3StatusXmlDocumentTooLarge; -} - - -static void getAclCompleteCallback(S3Status requestStatus, - const S3ErrorDetails *s3ErrorDetails, - void *callbackData) -{ - GetAclData *gaData = (GetAclData *) callbackData; - - if (requestStatus == S3StatusOK) { - // Parse the document - requestStatus = S3_convert_acl - (gaData->aclXmlDocument, gaData->ownerId, gaData->ownerDisplayName, - gaData->aclGrantCountReturn, gaData->aclGrants); - } - - (*(gaData->responseCompleteCallback)) - (requestStatus, s3ErrorDetails, gaData->callbackData); - - free(gaData); -} - - -void S3_get_acl(const S3BucketContext *bucketContext, const char *key, - char *ownerId, char *ownerDisplayName, - int *aclGrantCountReturn, S3AclGrant *aclGrants, - S3RequestContext *requestContext, - const S3ResponseHandler *handler, void *callbackData) -{ - // Create the callback data - GetAclData *gaData = (GetAclData *) malloc(sizeof(GetAclData)); - if (!gaData) { - (*(handler->completeCallback))(S3StatusOutOfMemory, 0, callbackData); - return; - } - - gaData->responsePropertiesCallback = handler->propertiesCallback; - gaData->responseCompleteCallback = handler->completeCallback; - gaData->callbackData = callbackData; - - gaData->aclGrantCountReturn = aclGrantCountReturn; - gaData->aclGrants = aclGrants; - gaData->ownerId = ownerId; - gaData->ownerDisplayName = ownerDisplayName; - string_buffer_initialize(gaData->aclXmlDocument); - *aclGrantCountReturn = 0; - - // Set up the RequestParams - RequestParams params = - { - HttpRequestTypeGET, // httpRequestType - { bucketContext->bucketName, // bucketName - bucketContext->protocol, // protocol - bucketContext->uriStyle, // uriStyle - bucketContext->accessKeyId, // accessKeyId - bucketContext->secretAccessKey }, // secretAccessKey - key, // key - 0, // queryParams - "acl", // subResource - 0, // copySourceBucketName - 0, // copySourceKey - 0, // getConditions - 0, // startByte - 0, // byteCount - 0, // putProperties - &getAclPropertiesCallback, // propertiesCallback - 0, // toS3Callback - 0, // toS3CallbackTotalSize - &getAclDataCallback, // fromS3Callback - &getAclCompleteCallback, // completeCallback - gaData // callbackData - }; - - // Perform the request - request_perform(¶ms, requestContext); -} - - -// set acl ------------------------------------------------------------------- - -static S3Status generateAclXmlDocument(const char *ownerId, - const char *ownerDisplayName, - int aclGrantCount, - const S3AclGrant *aclGrants, - int *xmlDocumentLenReturn, - char *xmlDocument, - int xmlDocumentBufferSize) -{ - *xmlDocumentLenReturn = 0; - -#define append(fmt, ...) \ - do { \ - *xmlDocumentLenReturn += snprintf \ - (&(xmlDocument[*xmlDocumentLenReturn]), \ - xmlDocumentBufferSize - *xmlDocumentLenReturn - 1, \ - fmt, __VA_ARGS__); \ - if (*xmlDocumentLenReturn >= xmlDocumentBufferSize) { \ - return S3StatusXmlDocumentTooLarge; \ - } \ - } while (0) - - append("%s%s" - "", ownerId, - ownerDisplayName); - - int i; - for (i = 0; i < aclGrantCount; i++) { - append("%s", "granteeType) { - case S3GranteeTypeAmazonCustomerByEmail: - append("AmazonCustomerByEmail\">%s", - grant->grantee.amazonCustomerByEmail.emailAddress); - break; - case S3GranteeTypeCanonicalUser: - append("CanonicalUser\">%s%s", - grant->grantee.canonicalUser.id, - grant->grantee.canonicalUser.displayName); - break; - default: { // case S3GranteeTypeAllAwsUsers/S3GranteeTypeAllUsers: - const char *grantee; - switch (grant->granteeType) { - case S3GranteeTypeAllAwsUsers: - grantee = "http://acs.amazonaws.com/groups/global/" - "AuthenticatedUsers"; - break; - case S3GranteeTypeAllUsers: - grantee = "http://acs.amazonaws.com/groups/global/" - "AllUsers"; - break; - default: - grantee = "http://acs.amazonaws.com/groups/s3/" - "LogDelivery"; - break; - } - append("Group\">%s", grantee); - } - break; - } - append("%s", - ((grant->permission == S3PermissionRead) ? "READ" : - (grant->permission == S3PermissionWrite) ? "WRITE" : - (grant->permission == S3PermissionReadACP) ? "READ_ACP" : - (grant->permission == S3PermissionWriteACP) ? "WRITE_ACP" : - "FULL_CONTROL")); - } - - append("%s", ""); - - return S3StatusOK; -} - - -typedef struct SetAclData -{ - S3ResponsePropertiesCallback *responsePropertiesCallback; - S3ResponseCompleteCallback *responseCompleteCallback; - void *callbackData; - - int aclXmlDocumentLen; - char aclXmlDocument[ACL_XML_DOC_MAXSIZE]; - int aclXmlDocumentBytesWritten; - -} SetAclData; - - -static S3Status setAclPropertiesCallback - (const S3ResponseProperties *responseProperties, void *callbackData) -{ - SetAclData *paData = (SetAclData *) callbackData; - - return (*(paData->responsePropertiesCallback)) - (responseProperties, paData->callbackData); -} - - -static int setAclDataCallback(int bufferSize, char *buffer, void *callbackData) -{ - SetAclData *paData = (SetAclData *) callbackData; - - int remaining = (paData->aclXmlDocumentLen - - paData->aclXmlDocumentBytesWritten); - - int toCopy = bufferSize > remaining ? remaining : bufferSize; - - if (!toCopy) { - return 0; - } - - memcpy(buffer, &(paData->aclXmlDocument - [paData->aclXmlDocumentBytesWritten]), toCopy); - - paData->aclXmlDocumentBytesWritten += toCopy; - - return toCopy; -} - - -static void setAclCompleteCallback(S3Status requestStatus, - const S3ErrorDetails *s3ErrorDetails, - void *callbackData) -{ - SetAclData *paData = (SetAclData *) callbackData; - - (*(paData->responseCompleteCallback)) - (requestStatus, s3ErrorDetails, paData->callbackData); - - free(paData); -} - - -void S3_set_acl(const S3BucketContext *bucketContext, const char *key, - const char *ownerId, const char *ownerDisplayName, - int aclGrantCount, const S3AclGrant *aclGrants, - S3RequestContext *requestContext, - const S3ResponseHandler *handler, void *callbackData) -{ - if (aclGrantCount > S3_MAX_ACL_GRANT_COUNT) { - (*(handler->completeCallback)) - (S3StatusTooManyGrants, 0, callbackData); - return; - } - - SetAclData *data = (SetAclData *) malloc(sizeof(SetAclData)); - if (!data) { - (*(handler->completeCallback))(S3StatusOutOfMemory, 0, callbackData); - return; - } - - // Convert aclGrants to XML document - S3Status status = generateAclXmlDocument - (ownerId, ownerDisplayName, aclGrantCount, aclGrants, - &(data->aclXmlDocumentLen), data->aclXmlDocument, - sizeof(data->aclXmlDocument)); - if (status != S3StatusOK) { - free(data); - (*(handler->completeCallback))(status, 0, callbackData); - return; - } - - data->responsePropertiesCallback = handler->propertiesCallback; - data->responseCompleteCallback = handler->completeCallback; - data->callbackData = callbackData; - - data->aclXmlDocumentBytesWritten = 0; - - // Set up the RequestParams - RequestParams params = - { - HttpRequestTypePUT, // httpRequestType - { bucketContext->bucketName, // bucketName - bucketContext->protocol, // protocol - bucketContext->uriStyle, // uriStyle - bucketContext->accessKeyId, // accessKeyId - bucketContext->secretAccessKey }, // secretAccessKey - key, // key - 0, // queryParams - "acl", // subResource - 0, // copySourceBucketName - 0, // copySourceKey - 0, // getConditions - 0, // startByte - 0, // byteCount - 0, // putProperties - &setAclPropertiesCallback, // propertiesCallback - &setAclDataCallback, // toS3Callback - data->aclXmlDocumentLen, // toS3CallbackTotalSize - 0, // fromS3Callback - &setAclCompleteCallback, // completeCallback - data // callbackData - }; - - // Perform the request - request_perform(¶ms, requestContext); -} diff --git a/libs3-1.4/src/bucket.c b/libs3-1.4/src/bucket.c deleted file mode 100644 index 9dcc48c..0000000 --- a/libs3-1.4/src/bucket.c +++ /dev/null @@ -1,731 +0,0 @@ -/** ************************************************************************** - * bucket.c - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -#include -#include -#include "libs3.h" -#include "request.h" -#include "simplexml.h" - -// test bucket --------------------------------------------------------------- - -typedef struct TestBucketData -{ - SimpleXml simpleXml; - - S3ResponsePropertiesCallback *responsePropertiesCallback; - S3ResponseCompleteCallback *responseCompleteCallback; - void *callbackData; - - int locationConstraintReturnSize; - char *locationConstraintReturn; - - string_buffer(locationConstraint, 256); -} TestBucketData; - - -static S3Status testBucketXmlCallback(const char *elementPath, - const char *data, int dataLen, - void *callbackData) -{ - TestBucketData *tbData = (TestBucketData *) callbackData; - - int fit; - - if (data && !strcmp(elementPath, "LocationConstraint")) { - string_buffer_append(tbData->locationConstraint, data, dataLen, fit); - } - - return S3StatusOK; -} - - -static S3Status testBucketPropertiesCallback - (const S3ResponseProperties *responseProperties, void *callbackData) -{ - TestBucketData *tbData = (TestBucketData *) callbackData; - - return (*(tbData->responsePropertiesCallback)) - (responseProperties, tbData->callbackData); -} - - -static S3Status testBucketDataCallback(int bufferSize, const char *buffer, - void *callbackData) -{ - TestBucketData *tbData = (TestBucketData *) callbackData; - - return simplexml_add(&(tbData->simpleXml), buffer, bufferSize); -} - - -static void testBucketCompleteCallback(S3Status requestStatus, - const S3ErrorDetails *s3ErrorDetails, - void *callbackData) -{ - TestBucketData *tbData = (TestBucketData *) callbackData; - - // Copy the location constraint into the return buffer - snprintf(tbData->locationConstraintReturn, - tbData->locationConstraintReturnSize, "%s", - tbData->locationConstraint); - - (*(tbData->responseCompleteCallback)) - (requestStatus, s3ErrorDetails, tbData->callbackData); - - simplexml_deinitialize(&(tbData->simpleXml)); - - free(tbData); -} - - -void S3_test_bucket(S3Protocol protocol, S3UriStyle uriStyle, - const char *accessKeyId, const char *secretAccessKey, - const char *bucketName, int locationConstraintReturnSize, - char *locationConstraintReturn, - S3RequestContext *requestContext, - const S3ResponseHandler *handler, void *callbackData) -{ - // Create the callback data - TestBucketData *tbData = - (TestBucketData *) malloc(sizeof(TestBucketData)); - if (!tbData) { - (*(handler->completeCallback))(S3StatusOutOfMemory, 0, callbackData); - return; - } - - simplexml_initialize(&(tbData->simpleXml), &testBucketXmlCallback, tbData); - - tbData->responsePropertiesCallback = handler->propertiesCallback; - tbData->responseCompleteCallback = handler->completeCallback; - tbData->callbackData = callbackData; - - tbData->locationConstraintReturnSize = locationConstraintReturnSize; - tbData->locationConstraintReturn = locationConstraintReturn; - string_buffer_initialize(tbData->locationConstraint); - - // Set up the RequestParams - RequestParams params = - { - HttpRequestTypeGET, // httpRequestType - { bucketName, // bucketName - protocol, // protocol - uriStyle, // uriStyle - accessKeyId, // accessKeyId - secretAccessKey }, // secretAccessKey - 0, // key - 0, // queryParams - "location", // subResource - 0, // copySourceBucketName - 0, // copySourceKey - 0, // getConditions - 0, // startByte - 0, // byteCount - 0, // putProperties - &testBucketPropertiesCallback, // propertiesCallback - 0, // toS3Callback - 0, // toS3CallbackTotalSize - &testBucketDataCallback, // fromS3Callback - &testBucketCompleteCallback, // completeCallback - tbData // callbackData - }; - - // Perform the request - request_perform(¶ms, requestContext); -} - - -// create bucket ------------------------------------------------------------- - -typedef struct CreateBucketData -{ - S3ResponsePropertiesCallback *responsePropertiesCallback; - S3ResponseCompleteCallback *responseCompleteCallback; - void *callbackData; - - char doc[1024]; - int docLen, docBytesWritten; -} CreateBucketData; - - -static S3Status createBucketPropertiesCallback - (const S3ResponseProperties *responseProperties, void *callbackData) -{ - CreateBucketData *cbData = (CreateBucketData *) callbackData; - - return (*(cbData->responsePropertiesCallback)) - (responseProperties, cbData->callbackData); -} - - -static int createBucketDataCallback(int bufferSize, char *buffer, - void *callbackData) -{ - CreateBucketData *cbData = (CreateBucketData *) callbackData; - - if (!cbData->docLen) { - return 0; - } - - int remaining = (cbData->docLen - cbData->docBytesWritten); - - int toCopy = bufferSize > remaining ? remaining : bufferSize; - - if (!toCopy) { - return 0; - } - - memcpy(buffer, &(cbData->doc[cbData->docBytesWritten]), toCopy); - - cbData->docBytesWritten += toCopy; - - return toCopy; -} - - -static void createBucketCompleteCallback(S3Status requestStatus, - const S3ErrorDetails *s3ErrorDetails, - void *callbackData) -{ - CreateBucketData *cbData = (CreateBucketData *) callbackData; - - (*(cbData->responseCompleteCallback)) - (requestStatus, s3ErrorDetails, cbData->callbackData); - - free(cbData); -} - - -void S3_create_bucket(S3Protocol protocol, const char *accessKeyId, - const char *secretAccessKey, const char *bucketName, - S3CannedAcl cannedAcl, const char *locationConstraint, - S3RequestContext *requestContext, - const S3ResponseHandler *handler, void *callbackData) -{ - // Create the callback data - CreateBucketData *cbData = - (CreateBucketData *) malloc(sizeof(CreateBucketData)); - if (!cbData) { - (*(handler->completeCallback))(S3StatusOutOfMemory, 0, callbackData); - return; - } - - cbData->responsePropertiesCallback = handler->propertiesCallback; - cbData->responseCompleteCallback = handler->completeCallback; - cbData->callbackData = callbackData; - - if (locationConstraint) { - cbData->docLen = - snprintf(cbData->doc, sizeof(cbData->doc), - "" - "%s", - locationConstraint); - cbData->docBytesWritten = 0; - } - else { - cbData->docLen = 0; - } - - // Set up S3PutProperties - S3PutProperties properties = - { - 0, // contentType - 0, // md5 - 0, // cacheControl - 0, // contentDispositionFilename - 0, // contentEncoding - 0, // expires - cannedAcl, // cannedAcl - 0, // metaDataCount - 0 // metaData - }; - - // Set up the RequestParams - RequestParams params = - { - HttpRequestTypePUT, // httpRequestType - { bucketName, // bucketName - protocol, // protocol - S3UriStylePath, // uriStyle - accessKeyId, // accessKeyId - secretAccessKey }, // secretAccessKey - 0, // key - 0, // queryParams - 0, // subResource - 0, // copySourceBucketName - 0, // copySourceKey - 0, // getConditions - 0, // startByte - 0, // byteCount - &properties, // putProperties - &createBucketPropertiesCallback, // propertiesCallback - &createBucketDataCallback, // toS3Callback - cbData->docLen, // toS3CallbackTotalSize - 0, // fromS3Callback - &createBucketCompleteCallback, // completeCallback - cbData // callbackData - }; - - // Perform the request - request_perform(¶ms, requestContext); -} - - -// delete bucket ------------------------------------------------------------- - -typedef struct DeleteBucketData -{ - S3ResponsePropertiesCallback *responsePropertiesCallback; - S3ResponseCompleteCallback *responseCompleteCallback; - void *callbackData; -} DeleteBucketData; - - -static S3Status deleteBucketPropertiesCallback - (const S3ResponseProperties *responseProperties, void *callbackData) -{ - DeleteBucketData *dbData = (DeleteBucketData *) callbackData; - - return (*(dbData->responsePropertiesCallback)) - (responseProperties, dbData->callbackData); -} - - -static void deleteBucketCompleteCallback(S3Status requestStatus, - const S3ErrorDetails *s3ErrorDetails, - void *callbackData) -{ - DeleteBucketData *dbData = (DeleteBucketData *) callbackData; - - (*(dbData->responseCompleteCallback)) - (requestStatus, s3ErrorDetails, dbData->callbackData); - - free(dbData); -} - - -void S3_delete_bucket(S3Protocol protocol, S3UriStyle uriStyle, - const char *accessKeyId, const char *secretAccessKey, - const char *bucketName, - S3RequestContext *requestContext, - const S3ResponseHandler *handler, void *callbackData) -{ - // Create the callback data - DeleteBucketData *dbData = - (DeleteBucketData *) malloc(sizeof(DeleteBucketData)); - if (!dbData) { - (*(handler->completeCallback))(S3StatusOutOfMemory, 0, callbackData); - return; - } - - dbData->responsePropertiesCallback = handler->propertiesCallback; - dbData->responseCompleteCallback = handler->completeCallback; - dbData->callbackData = callbackData; - - // Set up the RequestParams - RequestParams params = - { - HttpRequestTypeDELETE, // httpRequestType - { bucketName, // bucketName - protocol, // protocol - uriStyle, // uriStyle - accessKeyId, // accessKeyId - secretAccessKey }, // secretAccessKey - 0, // key - 0, // queryParams - 0, // subResource - 0, // copySourceBucketName - 0, // copySourceKey - 0, // getConditions - 0, // startByte - 0, // byteCount - 0, // putProperties - &deleteBucketPropertiesCallback, // propertiesCallback - 0, // toS3Callback - 0, // toS3CallbackTotalSize - 0, // fromS3Callback - &deleteBucketCompleteCallback, // completeCallback - dbData // callbackData - }; - - // Perform the request - request_perform(¶ms, requestContext); -} - - -// list bucket ---------------------------------------------------------------- - -typedef struct ListBucketContents -{ - string_buffer(key, 1024); - string_buffer(lastModified, 256); - string_buffer(eTag, 256); - string_buffer(size, 24); - string_buffer(ownerId, 256); - string_buffer(ownerDisplayName, 256); -} ListBucketContents; - - -static void initialize_list_bucket_contents(ListBucketContents *contents) -{ - string_buffer_initialize(contents->key); - string_buffer_initialize(contents->lastModified); - string_buffer_initialize(contents->eTag); - string_buffer_initialize(contents->size); - string_buffer_initialize(contents->ownerId); - string_buffer_initialize(contents->ownerDisplayName); -} - -// We read up to 32 Contents at a time -#define MAX_CONTENTS 32 -// We read up to 8 CommonPrefixes at a time -#define MAX_COMMON_PREFIXES 8 - -typedef struct ListBucketData -{ - SimpleXml simpleXml; - - S3ResponsePropertiesCallback *responsePropertiesCallback; - S3ListBucketCallback *listBucketCallback; - S3ResponseCompleteCallback *responseCompleteCallback; - void *callbackData; - - string_buffer(isTruncated, 64); - string_buffer(nextMarker, 1024); - - int contentsCount; - ListBucketContents contents[MAX_CONTENTS]; - - int commonPrefixesCount; - char commonPrefixes[MAX_COMMON_PREFIXES][1024]; - int commonPrefixLens[MAX_COMMON_PREFIXES]; -} ListBucketData; - - -static void initialize_list_bucket_data(ListBucketData *lbData) -{ - lbData->contentsCount = 0; - initialize_list_bucket_contents(lbData->contents); - lbData->commonPrefixesCount = 0; - lbData->commonPrefixes[0][0] = 0; - lbData->commonPrefixLens[0] = 0; -} - - -static S3Status make_list_bucket_callback(ListBucketData *lbData) -{ - int i; - - // Convert IsTruncated - int isTruncated = (!strcmp(lbData->isTruncated, "true") || - !strcmp(lbData->isTruncated, "1")) ? 1 : 0; - - // Convert the contents - S3ListBucketContent contents[lbData->contentsCount]; - - int contentsCount = lbData->contentsCount; - for (i = 0; i < contentsCount; i++) { - S3ListBucketContent *contentDest = &(contents[i]); - ListBucketContents *contentSrc = &(lbData->contents[i]); - contentDest->key = contentSrc->key; - contentDest->lastModified = - parseIso8601Time(contentSrc->lastModified); - contentDest->eTag = contentSrc->eTag; - contentDest->size = parseUnsignedInt(contentSrc->size); - contentDest->ownerId = - contentSrc->ownerId[0] ?contentSrc->ownerId : 0; - contentDest->ownerDisplayName = (contentSrc->ownerDisplayName[0] ? - contentSrc->ownerDisplayName : 0); - } - - // Make the common prefixes array - int commonPrefixesCount = lbData->commonPrefixesCount; - char *commonPrefixes[commonPrefixesCount]; - for (i = 0; i < commonPrefixesCount; i++) { - commonPrefixes[i] = lbData->commonPrefixes[i]; - } - - return (*(lbData->listBucketCallback)) - (isTruncated, lbData->nextMarker, - contentsCount, contents, commonPrefixesCount, - (const char **) commonPrefixes, lbData->callbackData); -} - - -static S3Status listBucketXmlCallback(const char *elementPath, - const char *data, int dataLen, - void *callbackData) -{ - ListBucketData *lbData = (ListBucketData *) callbackData; - - int fit; - - if (data) { - if (!strcmp(elementPath, "ListBucketResult/IsTruncated")) { - string_buffer_append(lbData->isTruncated, data, dataLen, fit); - } - else if (!strcmp(elementPath, "ListBucketResult/NextMarker")) { - string_buffer_append(lbData->nextMarker, data, dataLen, fit); - } - else if (!strcmp(elementPath, "ListBucketResult/Contents/Key")) { - ListBucketContents *contents = - &(lbData->contents[lbData->contentsCount]); - string_buffer_append(contents->key, data, dataLen, fit); - } - else if (!strcmp(elementPath, - "ListBucketResult/Contents/LastModified")) { - ListBucketContents *contents = - &(lbData->contents[lbData->contentsCount]); - string_buffer_append(contents->lastModified, data, dataLen, fit); - } - else if (!strcmp(elementPath, "ListBucketResult/Contents/ETag")) { - ListBucketContents *contents = - &(lbData->contents[lbData->contentsCount]); - string_buffer_append(contents->eTag, data, dataLen, fit); - } - else if (!strcmp(elementPath, "ListBucketResult/Contents/Size")) { - ListBucketContents *contents = - &(lbData->contents[lbData->contentsCount]); - string_buffer_append(contents->size, data, dataLen, fit); - } - else if (!strcmp(elementPath, "ListBucketResult/Contents/Owner/ID")) { - ListBucketContents *contents = - &(lbData->contents[lbData->contentsCount]); - string_buffer_append(contents->ownerId, data, dataLen, fit); - } - else if (!strcmp(elementPath, - "ListBucketResult/Contents/Owner/DisplayName")) { - ListBucketContents *contents = - &(lbData->contents[lbData->contentsCount]); - string_buffer_append - (contents->ownerDisplayName, data, dataLen, fit); - } - else if (!strcmp(elementPath, - "ListBucketResult/CommonPrefixes/Prefix")) { - int which = lbData->commonPrefixesCount; - lbData->commonPrefixLens[which] += - snprintf(lbData->commonPrefixes[which], - sizeof(lbData->commonPrefixes[which]) - - lbData->commonPrefixLens[which] - 1, - "%.*s", dataLen, data); - if (lbData->commonPrefixLens[which] >= - (int) sizeof(lbData->commonPrefixes[which])) { - return S3StatusXmlParseFailure; - } - } - } - else { - if (!strcmp(elementPath, "ListBucketResult/Contents")) { - // Finished a Contents - lbData->contentsCount++; - if (lbData->contentsCount == MAX_CONTENTS) { - // Make the callback - S3Status status = make_list_bucket_callback(lbData); - if (status != S3StatusOK) { - return status; - } - initialize_list_bucket_data(lbData); - } - else { - // Initialize the next one - initialize_list_bucket_contents - (&(lbData->contents[lbData->contentsCount])); - } - } - else if (!strcmp(elementPath, - "ListBucketResult/CommonPrefixes/Prefix")) { - // Finished a Prefix - lbData->commonPrefixesCount++; - if (lbData->commonPrefixesCount == MAX_COMMON_PREFIXES) { - // Make the callback - S3Status status = make_list_bucket_callback(lbData); - if (status != S3StatusOK) { - return status; - } - initialize_list_bucket_data(lbData); - } - else { - // Initialize the next one - lbData->commonPrefixes[lbData->commonPrefixesCount][0] = 0; - lbData->commonPrefixLens[lbData->commonPrefixesCount] = 0; - } - } - } - - return S3StatusOK; -} - - -static S3Status listBucketPropertiesCallback - (const S3ResponseProperties *responseProperties, void *callbackData) -{ - ListBucketData *lbData = (ListBucketData *) callbackData; - - return (*(lbData->responsePropertiesCallback)) - (responseProperties, lbData->callbackData); -} - - -static S3Status listBucketDataCallback(int bufferSize, const char *buffer, - void *callbackData) -{ - ListBucketData *lbData = (ListBucketData *) callbackData; - - return simplexml_add(&(lbData->simpleXml), buffer, bufferSize); -} - - -static void listBucketCompleteCallback(S3Status requestStatus, - const S3ErrorDetails *s3ErrorDetails, - void *callbackData) -{ - ListBucketData *lbData = (ListBucketData *) callbackData; - - // Make the callback if there is anything - if (lbData->contentsCount || lbData->commonPrefixesCount) { - make_list_bucket_callback(lbData); - } - - (*(lbData->responseCompleteCallback)) - (requestStatus, s3ErrorDetails, lbData->callbackData); - - simplexml_deinitialize(&(lbData->simpleXml)); - - free(lbData); -} - - -void S3_list_bucket(const S3BucketContext *bucketContext, const char *prefix, - const char *marker, const char *delimiter, int maxkeys, - S3RequestContext *requestContext, - const S3ListBucketHandler *handler, void *callbackData) -{ - // Compose the query params - string_buffer(queryParams, 4096); - string_buffer_initialize(queryParams); - -#define safe_append(name, value) \ - do { \ - int fit; \ - if (amp) { \ - string_buffer_append(queryParams, "&", 1, fit); \ - if (!fit) { \ - (*(handler->responseHandler.completeCallback)) \ - (S3StatusQueryParamsTooLong, 0, callbackData); \ - return; \ - } \ - } \ - string_buffer_append(queryParams, name "=", \ - sizeof(name "=") - 1, fit); \ - if (!fit) { \ - (*(handler->responseHandler.completeCallback)) \ - (S3StatusQueryParamsTooLong, 0, callbackData); \ - return; \ - } \ - amp = 1; \ - char encoded[3 * 1024]; \ - if (!urlEncode(encoded, value, 1024)) { \ - (*(handler->responseHandler.completeCallback)) \ - (S3StatusQueryParamsTooLong, 0, callbackData); \ - return; \ - } \ - string_buffer_append(queryParams, encoded, strlen(encoded), \ - fit); \ - if (!fit) { \ - (*(handler->responseHandler.completeCallback)) \ - (S3StatusQueryParamsTooLong, 0, callbackData); \ - return; \ - } \ - } while (0) - - - int amp = 0; - if (prefix) { - safe_append("prefix", prefix); - } - if (marker) { - safe_append("marker", marker); - } - if (delimiter) { - safe_append("delimiter", delimiter); - } - if (maxkeys) { - char maxKeysString[64]; - snprintf(maxKeysString, sizeof(maxKeysString), "%d", maxkeys); - safe_append("max-keys", maxKeysString); - } - - ListBucketData *lbData = - (ListBucketData *) malloc(sizeof(ListBucketData)); - - if (!lbData) { - (*(handler->responseHandler.completeCallback)) - (S3StatusOutOfMemory, 0, callbackData); - return; - } - - simplexml_initialize(&(lbData->simpleXml), &listBucketXmlCallback, lbData); - - lbData->responsePropertiesCallback = - handler->responseHandler.propertiesCallback; - lbData->listBucketCallback = handler->listBucketCallback; - lbData->responseCompleteCallback = - handler->responseHandler.completeCallback; - lbData->callbackData = callbackData; - - string_buffer_initialize(lbData->isTruncated); - string_buffer_initialize(lbData->nextMarker); - initialize_list_bucket_data(lbData); - - // Set up the RequestParams - RequestParams params = - { - HttpRequestTypeGET, // httpRequestType - { bucketContext->bucketName, // bucketName - bucketContext->protocol, // protocol - bucketContext->uriStyle, // uriStyle - bucketContext->accessKeyId, // accessKeyId - bucketContext->secretAccessKey }, // secretAccessKey - 0, // key - queryParams[0] ? queryParams : 0, // queryParams - 0, // subResource - 0, // copySourceBucketName - 0, // copySourceKey - 0, // getConditions - 0, // startByte - 0, // byteCount - 0, // putProperties - &listBucketPropertiesCallback, // propertiesCallback - 0, // toS3Callback - 0, // toS3CallbackTotalSize - &listBucketDataCallback, // fromS3Callback - &listBucketCompleteCallback, // completeCallback - lbData // callbackData - }; - - // Perform the request - request_perform(¶ms, requestContext); -} diff --git a/libs3-1.4/src/error_parser.c b/libs3-1.4/src/error_parser.c deleted file mode 100644 index baa206e..0000000 --- a/libs3-1.4/src/error_parser.c +++ /dev/null @@ -1,239 +0,0 @@ -/** ************************************************************************** - * error_parser.c - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -#include -#include "error_parser.h" - - -static S3Status errorXmlCallback(const char *elementPath, const char *data, - int dataLen, void *callbackData) -{ - // We ignore end of element callbacks because we don't care about them - if (!data) { - return S3StatusOK; - } - - ErrorParser *errorParser = (ErrorParser *) callbackData; - - int fit; - - if (!strcmp(elementPath, "Error")) { - // Ignore, this is the Error element itself, we only care about subs - } - else if (!strcmp(elementPath, "Error/Code")) { - string_buffer_append(errorParser->code, data, dataLen, fit); - } - else if (!strcmp(elementPath, "Error/Message")) { - string_buffer_append(errorParser->message, data, dataLen, fit); - errorParser->s3ErrorDetails.message = errorParser->message; - } - else if (!strcmp(elementPath, "Error/Resource")) { - string_buffer_append(errorParser->resource, data, dataLen, fit); - errorParser->s3ErrorDetails.resource = errorParser->resource; - } - else if (!strcmp(elementPath, "Error/FurtherDetails")) { - string_buffer_append(errorParser->furtherDetails, data, dataLen, fit); - errorParser->s3ErrorDetails.furtherDetails = - errorParser->furtherDetails; - } - else { - if (strncmp(elementPath, "Error/", sizeof("Error/") - 1)) { - // If for some weird reason it's not within the Error element, - // ignore it - return S3StatusOK; - } - // It's an unknown error element. See if it matches the most - // recent error element. - const char *elementName = &(elementPath[sizeof("Error/") - 1]); - if (errorParser->s3ErrorDetails.extraDetailsCount && - !strcmp(elementName, errorParser->s3ErrorDetails.extraDetails - [errorParser->s3ErrorDetails.extraDetailsCount - 1].name)) { - // Append the value - string_multibuffer_append(errorParser->extraDetailsNamesValues, - data, dataLen, fit); - // If it didn't fit, remove this extra - if (!fit) { - errorParser->s3ErrorDetails.extraDetailsCount--; - } - return S3StatusOK; - } - // OK, must add another unknown error element, if it will fit. - if (errorParser->s3ErrorDetails.extraDetailsCount == - sizeof(errorParser->extraDetails)) { - // Won't fit. Ignore this one. - return S3StatusOK; - } - // Copy in the name and value - char *name = string_multibuffer_current - (errorParser->extraDetailsNamesValues); - int nameLen = strlen(elementName); - string_multibuffer_add(errorParser->extraDetailsNamesValues, - elementName, nameLen, fit); - if (!fit) { - // Name didn't fit; ignore this one. - return S3StatusOK; - } - char *value = string_multibuffer_current - (errorParser->extraDetailsNamesValues); - string_multibuffer_add(errorParser->extraDetailsNamesValues, - data, dataLen, fit); - if (!fit) { - // Value didn't fit; ignore this one. - return S3StatusOK; - } - S3NameValue *nv = - &(errorParser->extraDetails - [errorParser->s3ErrorDetails.extraDetailsCount++]); - nv->name = name; - nv->value = value; - } - - return S3StatusOK; -} - - -void error_parser_initialize(ErrorParser *errorParser) -{ - errorParser->s3ErrorDetails.message = 0; - errorParser->s3ErrorDetails.resource = 0; - errorParser->s3ErrorDetails.furtherDetails = 0; - errorParser->s3ErrorDetails.extraDetailsCount = 0; - errorParser->s3ErrorDetails.extraDetails = errorParser->extraDetails; - errorParser->errorXmlParserInitialized = 0; - string_buffer_initialize(errorParser->code); - string_buffer_initialize(errorParser->message); - string_buffer_initialize(errorParser->resource); - string_buffer_initialize(errorParser->furtherDetails); - string_multibuffer_initialize(errorParser->extraDetailsNamesValues); -} - - -S3Status error_parser_add(ErrorParser *errorParser, char *buffer, - int bufferSize) -{ - if (!errorParser->errorXmlParserInitialized) { - simplexml_initialize(&(errorParser->errorXmlParser), &errorXmlCallback, - errorParser); - errorParser->errorXmlParserInitialized = 1; - } - - return simplexml_add(&(errorParser->errorXmlParser), buffer, bufferSize); -} - - -void error_parser_convert_status(ErrorParser *errorParser, S3Status *status) -{ - // Convert the error status string into a code - if (!errorParser->codeLen) { - return; - } - -#define HANDLE_CODE(name) \ - do { \ - if (!strcmp(errorParser->code, #name)) { \ - *status = S3StatusError##name; \ - goto code_set; \ - } \ - } while (0) - - HANDLE_CODE(AccessDenied); - HANDLE_CODE(AccountProblem); - HANDLE_CODE(AmbiguousGrantByEmailAddress); - HANDLE_CODE(BadDigest); - HANDLE_CODE(BucketAlreadyExists); - HANDLE_CODE(BucketAlreadyOwnedByYou); - HANDLE_CODE(BucketNotEmpty); - HANDLE_CODE(CredentialsNotSupported); - HANDLE_CODE(CrossLocationLoggingProhibited); - HANDLE_CODE(EntityTooSmall); - HANDLE_CODE(EntityTooLarge); - HANDLE_CODE(ExpiredToken); - HANDLE_CODE(IncompleteBody); - HANDLE_CODE(IncorrectNumberOfFilesInPostRequest); - HANDLE_CODE(InlineDataTooLarge); - HANDLE_CODE(InternalError); - HANDLE_CODE(InvalidAccessKeyId); - HANDLE_CODE(InvalidAddressingHeader); - HANDLE_CODE(InvalidArgument); - HANDLE_CODE(InvalidBucketName); - HANDLE_CODE(InvalidDigest); - HANDLE_CODE(InvalidLocationConstraint); - HANDLE_CODE(InvalidPayer); - HANDLE_CODE(InvalidPolicyDocument); - HANDLE_CODE(InvalidRange); - HANDLE_CODE(InvalidSecurity); - HANDLE_CODE(InvalidSOAPRequest); - HANDLE_CODE(InvalidStorageClass); - HANDLE_CODE(InvalidTargetBucketForLogging); - HANDLE_CODE(InvalidToken); - HANDLE_CODE(InvalidURI); - HANDLE_CODE(KeyTooLong); - HANDLE_CODE(MalformedACLError); - HANDLE_CODE(MalformedXML); - HANDLE_CODE(MaxMessageLengthExceeded); - HANDLE_CODE(MaxPostPreDataLengthExceededError); - HANDLE_CODE(MetadataTooLarge); - HANDLE_CODE(MethodNotAllowed); - HANDLE_CODE(MissingAttachment); - HANDLE_CODE(MissingContentLength); - HANDLE_CODE(MissingSecurityElement); - HANDLE_CODE(MissingSecurityHeader); - HANDLE_CODE(NoLoggingStatusForKey); - HANDLE_CODE(NoSuchBucket); - HANDLE_CODE(NoSuchKey); - HANDLE_CODE(NotImplemented); - HANDLE_CODE(NotSignedUp); - HANDLE_CODE(OperationAborted); - HANDLE_CODE(PermanentRedirect); - HANDLE_CODE(PreconditionFailed); - HANDLE_CODE(Redirect); - HANDLE_CODE(RequestIsNotMultiPartContent); - HANDLE_CODE(RequestTimeout); - HANDLE_CODE(RequestTimeTooSkewed); - HANDLE_CODE(RequestTorrentOfBucketError); - HANDLE_CODE(SignatureDoesNotMatch); - HANDLE_CODE(SlowDown); - HANDLE_CODE(TemporaryRedirect); - HANDLE_CODE(TokenRefreshRequired); - HANDLE_CODE(TooManyBuckets); - HANDLE_CODE(UnexpectedContent); - HANDLE_CODE(UnresolvableGrantByEmailAddress); - HANDLE_CODE(UserKeyMustBeSpecified); - *status = S3StatusErrorUnknown; - - code_set: - - return; -} - - -// Always call this -void error_parser_deinitialize(ErrorParser *errorParser) -{ - if (errorParser->errorXmlParserInitialized) { - simplexml_deinitialize(&(errorParser->errorXmlParser)); - } -} diff --git a/libs3-1.4/src/general.c b/libs3-1.4/src/general.c deleted file mode 100644 index 861c289..0000000 --- a/libs3-1.4/src/general.c +++ /dev/null @@ -1,475 +0,0 @@ -/** ************************************************************************** - * general.c - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -#include -#include -#include "request.h" -#include "simplexml.h" -#include "util.h" - -static int initializeCountG = 0; - -S3Status S3_initialize(const char *userAgentInfo, int flags) -{ - if (initializeCountG++) { - return S3StatusOK; - } - - return request_api_initialize(userAgentInfo, flags); -} - - -void S3_deinitialize() -{ - if (--initializeCountG) { - return; - } - - request_api_deinitialize(); -} - -const char *S3_get_status_name(S3Status status) -{ - switch (status) { -#define handlecase(s) \ - case S3Status##s: \ - return #s - - handlecase(OK); - handlecase(InternalError); - handlecase(OutOfMemory); - handlecase(Interrupted); - handlecase(InvalidBucketNameTooLong); - handlecase(InvalidBucketNameFirstCharacter); - handlecase(InvalidBucketNameCharacter); - handlecase(InvalidBucketNameCharacterSequence); - handlecase(InvalidBucketNameTooShort); - handlecase(InvalidBucketNameDotQuadNotation); - handlecase(QueryParamsTooLong); - handlecase(FailedToInitializeRequest); - handlecase(MetaDataHeadersTooLong); - handlecase(BadMetaData); - handlecase(BadContentType); - handlecase(ContentTypeTooLong); - handlecase(BadMD5); - handlecase(MD5TooLong); - handlecase(BadCacheControl); - handlecase(CacheControlTooLong); - handlecase(BadContentDispositionFilename); - handlecase(ContentDispositionFilenameTooLong); - handlecase(BadContentEncoding); - handlecase(ContentEncodingTooLong); - handlecase(BadIfMatchETag); - handlecase(IfMatchETagTooLong); - handlecase(BadIfNotMatchETag); - handlecase(IfNotMatchETagTooLong); - handlecase(HeadersTooLong); - handlecase(KeyTooLong); - handlecase(UriTooLong); - handlecase(XmlParseFailure); - handlecase(EmailAddressTooLong); - handlecase(UserIdTooLong); - handlecase(UserDisplayNameTooLong); - handlecase(GroupUriTooLong); - handlecase(PermissionTooLong); - handlecase(TargetBucketTooLong); - handlecase(TargetPrefixTooLong); - handlecase(TooManyGrants); - handlecase(BadGrantee); - handlecase(BadPermission); - handlecase(XmlDocumentTooLarge); - handlecase(NameLookupError); - handlecase(FailedToConnect); - handlecase(ServerFailedVerification); - handlecase(ConnectionFailed); - handlecase(AbortedByCallback); - handlecase(ErrorAccessDenied); - handlecase(ErrorAccountProblem); - handlecase(ErrorAmbiguousGrantByEmailAddress); - handlecase(ErrorBadDigest); - handlecase(ErrorBucketAlreadyExists); - handlecase(ErrorBucketAlreadyOwnedByYou); - handlecase(ErrorBucketNotEmpty); - handlecase(ErrorCredentialsNotSupported); - handlecase(ErrorCrossLocationLoggingProhibited); - handlecase(ErrorEntityTooSmall); - handlecase(ErrorEntityTooLarge); - handlecase(ErrorExpiredToken); - handlecase(ErrorIncompleteBody); - handlecase(ErrorIncorrectNumberOfFilesInPostRequest); - handlecase(ErrorInlineDataTooLarge); - handlecase(ErrorInternalError); - handlecase(ErrorInvalidAccessKeyId); - handlecase(ErrorInvalidAddressingHeader); - handlecase(ErrorInvalidArgument); - handlecase(ErrorInvalidBucketName); - handlecase(ErrorInvalidDigest); - handlecase(ErrorInvalidLocationConstraint); - handlecase(ErrorInvalidPayer); - handlecase(ErrorInvalidPolicyDocument); - handlecase(ErrorInvalidRange); - handlecase(ErrorInvalidSecurity); - handlecase(ErrorInvalidSOAPRequest); - handlecase(ErrorInvalidStorageClass); - handlecase(ErrorInvalidTargetBucketForLogging); - handlecase(ErrorInvalidToken); - handlecase(ErrorInvalidURI); - handlecase(ErrorKeyTooLong); - handlecase(ErrorMalformedACLError); - handlecase(ErrorMalformedXML); - handlecase(ErrorMaxMessageLengthExceeded); - handlecase(ErrorMaxPostPreDataLengthExceededError); - handlecase(ErrorMetadataTooLarge); - handlecase(ErrorMethodNotAllowed); - handlecase(ErrorMissingAttachment); - handlecase(ErrorMissingContentLength); - handlecase(ErrorMissingSecurityElement); - handlecase(ErrorMissingSecurityHeader); - handlecase(ErrorNoLoggingStatusForKey); - handlecase(ErrorNoSuchBucket); - handlecase(ErrorNoSuchKey); - handlecase(ErrorNotImplemented); - handlecase(ErrorNotSignedUp); - handlecase(ErrorOperationAborted); - handlecase(ErrorPermanentRedirect); - handlecase(ErrorPreconditionFailed); - handlecase(ErrorRedirect); - handlecase(ErrorRequestIsNotMultiPartContent); - handlecase(ErrorRequestTimeout); - handlecase(ErrorRequestTimeTooSkewed); - handlecase(ErrorRequestTorrentOfBucketError); - handlecase(ErrorSignatureDoesNotMatch); - handlecase(ErrorSlowDown); - handlecase(ErrorTemporaryRedirect); - handlecase(ErrorTokenRefreshRequired); - handlecase(ErrorTooManyBuckets); - handlecase(ErrorUnexpectedContent); - handlecase(ErrorUnresolvableGrantByEmailAddress); - handlecase(ErrorUserKeyMustBeSpecified); - handlecase(ErrorUnknown); - handlecase(HttpErrorMovedTemporarily); - handlecase(HttpErrorBadRequest); - handlecase(HttpErrorForbidden); - handlecase(HttpErrorNotFound); - handlecase(HttpErrorConflict); - handlecase(HttpErrorUnknown); - } - - return "Unknown"; -} - - -S3Status S3_validate_bucket_name(const char *bucketName, S3UriStyle uriStyle) -{ - int virtualHostStyle = (uriStyle == S3UriStyleVirtualHost); - int len = 0, maxlen = virtualHostStyle ? 63 : 255; - const char *b = bucketName; - - int hasDot = 0; - int hasNonDigit = 0; - - while (*b) { - if (len == maxlen) { - return S3StatusInvalidBucketNameTooLong; - } - else if (isalpha(*b)) { - len++, b++; - hasNonDigit = 1; - } - else if (isdigit(*b)) { - len++, b++; - } - else if (len == 0) { - return S3StatusInvalidBucketNameFirstCharacter; - } - else if (*b == '_') { - /* Virtual host style bucket names cannot have underscores */ - if (virtualHostStyle) { - return S3StatusInvalidBucketNameCharacter; - } - len++, b++; - hasNonDigit = 1; - } - else if (*b == '-') { - /* Virtual host style bucket names cannot have .- */ - if (virtualHostStyle && (b > bucketName) && (*(b - 1) == '.')) { - return S3StatusInvalidBucketNameCharacterSequence; - } - len++, b++; - hasNonDigit = 1; - } - else if (*b == '.') { - /* Virtual host style bucket names cannot have -. */ - if (virtualHostStyle && (b > bucketName) && (*(b - 1) == '-')) { - return S3StatusInvalidBucketNameCharacterSequence; - } - len++, b++; - hasDot = 1; - } - else { - return S3StatusInvalidBucketNameCharacter; - } - } - - if (len < 3) { - return S3StatusInvalidBucketNameTooShort; - } - - /* It's not clear from Amazon's documentation exactly what 'IP address - style' means. In its strictest sense, it could mean 'could be a valid - IP address', which would mean that 255.255.255.255 would be invalid, - wherase 256.256.256.256 would be valid. Or it could mean 'has 4 sets - of digits separated by dots'. Who knows. Let's just be really - conservative here: if it has any dots, and no non-digit characters, - then we reject it */ - if (hasDot && !hasNonDigit) { - return S3StatusInvalidBucketNameDotQuadNotation; - } - - return S3StatusOK; -} - - -typedef struct ConvertAclData -{ - char *ownerId; - int ownerIdLen; - char *ownerDisplayName; - int ownerDisplayNameLen; - int *aclGrantCountReturn; - S3AclGrant *aclGrants; - - string_buffer(emailAddress, S3_MAX_GRANTEE_EMAIL_ADDRESS_SIZE); - string_buffer(userId, S3_MAX_GRANTEE_USER_ID_SIZE); - string_buffer(userDisplayName, S3_MAX_GRANTEE_DISPLAY_NAME_SIZE); - string_buffer(groupUri, 128); - string_buffer(permission, 32); -} ConvertAclData; - - -static S3Status convertAclXmlCallback(const char *elementPath, - const char *data, int dataLen, - void *callbackData) -{ - ConvertAclData *caData = (ConvertAclData *) callbackData; - - int fit; - - if (data) { - if (!strcmp(elementPath, "AccessControlPolicy/Owner/ID")) { - caData->ownerIdLen += - snprintf(&(caData->ownerId[caData->ownerIdLen]), - S3_MAX_GRANTEE_USER_ID_SIZE - caData->ownerIdLen - 1, - "%.*s", dataLen, data); - if (caData->ownerIdLen >= S3_MAX_GRANTEE_USER_ID_SIZE) { - return S3StatusUserIdTooLong; - } - } - else if (!strcmp(elementPath, "AccessControlPolicy/Owner/" - "DisplayName")) { - caData->ownerDisplayNameLen += - snprintf(&(caData->ownerDisplayName - [caData->ownerDisplayNameLen]), - S3_MAX_GRANTEE_DISPLAY_NAME_SIZE - - caData->ownerDisplayNameLen - 1, - "%.*s", dataLen, data); - if (caData->ownerDisplayNameLen >= - S3_MAX_GRANTEE_DISPLAY_NAME_SIZE) { - return S3StatusUserDisplayNameTooLong; - } - } - else if (!strcmp(elementPath, - "AccessControlPolicy/AccessControlList/Grant/" - "Grantee/EmailAddress")) { - // AmazonCustomerByEmail - string_buffer_append(caData->emailAddress, data, dataLen, fit); - if (!fit) { - return S3StatusEmailAddressTooLong; - } - } - else if (!strcmp(elementPath, - "AccessControlPolicy/AccessControlList/Grant/" - "Grantee/ID")) { - // CanonicalUser - string_buffer_append(caData->userId, data, dataLen, fit); - if (!fit) { - return S3StatusUserIdTooLong; - } - } - else if (!strcmp(elementPath, - "AccessControlPolicy/AccessControlList/Grant/" - "Grantee/DisplayName")) { - // CanonicalUser - string_buffer_append(caData->userDisplayName, data, dataLen, fit); - if (!fit) { - return S3StatusUserDisplayNameTooLong; - } - } - else if (!strcmp(elementPath, - "AccessControlPolicy/AccessControlList/Grant/" - "Grantee/URI")) { - // Group - string_buffer_append(caData->groupUri, data, dataLen, fit); - if (!fit) { - return S3StatusGroupUriTooLong; - } - } - else if (!strcmp(elementPath, - "AccessControlPolicy/AccessControlList/Grant/" - "Permission")) { - // Permission - string_buffer_append(caData->permission, data, dataLen, fit); - if (!fit) { - return S3StatusPermissionTooLong; - } - } - } - else { - if (!strcmp(elementPath, "AccessControlPolicy/AccessControlList/" - "Grant")) { - // A grant has just been completed; so add the next S3AclGrant - // based on the values read - if (*(caData->aclGrantCountReturn) == S3_MAX_ACL_GRANT_COUNT) { - return S3StatusTooManyGrants; - } - - S3AclGrant *grant = &(caData->aclGrants - [*(caData->aclGrantCountReturn)]); - - if (caData->emailAddress[0]) { - grant->granteeType = S3GranteeTypeAmazonCustomerByEmail; - strcpy(grant->grantee.amazonCustomerByEmail.emailAddress, - caData->emailAddress); - } - else if (caData->userId[0] && caData->userDisplayName[0]) { - grant->granteeType = S3GranteeTypeCanonicalUser; - strcpy(grant->grantee.canonicalUser.id, caData->userId); - strcpy(grant->grantee.canonicalUser.displayName, - caData->userDisplayName); - } - else if (caData->groupUri[0]) { - if (!strcmp(caData->groupUri, - "http://acs.amazonaws.com/groups/global/" - "AuthenticatedUsers")) { - grant->granteeType = S3GranteeTypeAllAwsUsers; - } - else if (!strcmp(caData->groupUri, - "http://acs.amazonaws.com/groups/global/" - "AllUsers")) { - grant->granteeType = S3GranteeTypeAllUsers; - } - else if (!strcmp(caData->groupUri, - "http://acs.amazonaws.com/groups/s3/" - "LogDelivery")) { - grant->granteeType = S3GranteeTypeLogDelivery; - } - else { - return S3StatusBadGrantee; - } - } - else { - return S3StatusBadGrantee; - } - - if (!strcmp(caData->permission, "READ")) { - grant->permission = S3PermissionRead; - } - else if (!strcmp(caData->permission, "WRITE")) { - grant->permission = S3PermissionWrite; - } - else if (!strcmp(caData->permission, "READ_ACP")) { - grant->permission = S3PermissionReadACP; - } - else if (!strcmp(caData->permission, "WRITE_ACP")) { - grant->permission = S3PermissionWriteACP; - } - else if (!strcmp(caData->permission, "FULL_CONTROL")) { - grant->permission = S3PermissionFullControl; - } - else { - return S3StatusBadPermission; - } - - (*(caData->aclGrantCountReturn))++; - - string_buffer_initialize(caData->emailAddress); - string_buffer_initialize(caData->userId); - string_buffer_initialize(caData->userDisplayName); - string_buffer_initialize(caData->groupUri); - string_buffer_initialize(caData->permission); - } - } - - return S3StatusOK; -} - - -S3Status S3_convert_acl(char *aclXml, char *ownerId, char *ownerDisplayName, - int *aclGrantCountReturn, S3AclGrant *aclGrants) -{ - ConvertAclData data; - - data.ownerId = ownerId; - data.ownerIdLen = 0; - data.ownerId[0] = 0; - data.ownerDisplayName = ownerDisplayName; - data.ownerDisplayNameLen = 0; - data.ownerDisplayName[0] = 0; - data.aclGrantCountReturn = aclGrantCountReturn; - data.aclGrants = aclGrants; - *aclGrantCountReturn = 0; - string_buffer_initialize(data.emailAddress); - string_buffer_initialize(data.userId); - string_buffer_initialize(data.userDisplayName); - string_buffer_initialize(data.groupUri); - string_buffer_initialize(data.permission); - - // Use a simplexml parser - SimpleXml simpleXml; - simplexml_initialize(&simpleXml, &convertAclXmlCallback, &data); - - S3Status status = simplexml_add(&simpleXml, aclXml, strlen(aclXml)); - - simplexml_deinitialize(&simpleXml); - - return status; -} - - -int S3_status_is_retryable(S3Status status) -{ - switch (status) { - case S3StatusNameLookupError: - case S3StatusFailedToConnect: - case S3StatusConnectionFailed: - case S3StatusErrorInternalError: - case S3StatusErrorOperationAborted: - case S3StatusErrorRequestTimeout: - return 1; - default: - return 0; - } -} diff --git a/libs3-1.4/src/mingw_functions.c b/libs3-1.4/src/mingw_functions.c deleted file mode 100644 index 0e2b7b2..0000000 --- a/libs3-1.4/src/mingw_functions.c +++ /dev/null @@ -1,119 +0,0 @@ -/** ************************************************************************** - * mingw_functions.c - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -#include -#include - -unsigned long pthread_self() -{ - return (unsigned long) GetCurrentThreadId(); -} - - -int pthread_mutex_init(pthread_mutex_t *mutex, void *v) -{ - (void) v; - - InitializeCriticalSection(&(mutex->criticalSection)); - - return 0; -} - - -int pthread_mutex_lock(pthread_mutex_t *mutex) -{ - EnterCriticalSection(&(mutex->criticalSection)); - - return 0; -} - - -int pthread_mutex_unlock(pthread_mutex_t *mutex) -{ - LeaveCriticalSection(&(mutex->criticalSection)); - - return 0; -} - - -int pthread_mutex_destroy(pthread_mutex_t *mutex) -{ - DeleteCriticalSection(&(mutex->criticalSection)); - - return 0; -} - - -int uname(struct utsname *u) -{ - OSVERSIONINFO info; - info.dwOSVersionInfoSize = sizeof(info); - - if (!GetVersionEx(&info)) { - return -1; - } - - u->machine = ""; - - switch (info.dwMajorVersion) { - case 4: - switch (info.dwMinorVersion) { - case 0: - u->sysname = "Microsoft Windows NT 4.0"; - break; - case 10: - u->sysname = "Microsoft Windows 98"; - break; - case 90: - u->sysname = "Microsoft Windows Me"; - break; - default: - return -1; - } - break; - - case 5: - switch (info.dwMinorVersion) { - case 0: - u->sysname = "Microsoft Windows 2000"; - break; - case 1: - u->sysname = "Microsoft Windows XP"; - break; - case 2: - u->sysname = "Microsoft Server 2003"; - break; - default: - return -1; - } - break; - - default: - return -1; - } - - return 0; -} diff --git a/libs3-1.4/src/mingw_s3_functions.c b/libs3-1.4/src/mingw_s3_functions.c deleted file mode 100644 index 142569d..0000000 --- a/libs3-1.4/src/mingw_s3_functions.c +++ /dev/null @@ -1,37 +0,0 @@ -/** ************************************************************************** - * mingw_s3_functions.c - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -int setenv(const char *a, const char *b, int c) -{ - (void) c; - - return SetEnvironmentVariable(a, b); -} - -int unsetenv(const char *a) -{ - return SetEnvironmentVariable(a, 0); -} diff --git a/libs3-1.4/src/object.c b/libs3-1.4/src/object.c deleted file mode 100644 index 4c8fd1c..0000000 --- a/libs3-1.4/src/object.c +++ /dev/null @@ -1,337 +0,0 @@ -/** ************************************************************************** - * object.c - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -#include -#include -#include "libs3.h" -#include "request.h" - - -// put object ---------------------------------------------------------------- - -void S3_put_object(const S3BucketContext *bucketContext, const char *key, - uint64_t contentLength, - const S3PutProperties *putProperties, - S3RequestContext *requestContext, - const S3PutObjectHandler *handler, void *callbackData) -{ - // Set up the RequestParams - RequestParams params = - { - HttpRequestTypePUT, // httpRequestType - { bucketContext->bucketName, // bucketName - bucketContext->protocol, // protocol - bucketContext->uriStyle, // uriStyle - bucketContext->accessKeyId, // accessKeyId - bucketContext->secretAccessKey }, // secretAccessKey - key, // key - 0, // queryParams - 0, // subResource - 0, // copySourceBucketName - 0, // copySourceKey - 0, // getConditions - 0, // startByte - 0, // byteCount - putProperties, // putProperties - handler->responseHandler.propertiesCallback, // propertiesCallback - handler->putObjectDataCallback, // toS3Callback - contentLength, // toS3CallbackTotalSize - 0, // fromS3Callback - handler->responseHandler.completeCallback, // completeCallback - callbackData // callbackData - }; - - // Perform the request - request_perform(¶ms, requestContext); -} - - -// copy object --------------------------------------------------------------- - - -typedef struct CopyObjectData -{ - SimpleXml simpleXml; - - S3ResponsePropertiesCallback *responsePropertiesCallback; - S3ResponseCompleteCallback *responseCompleteCallback; - void *callbackData; - - int64_t *lastModifiedReturn; - int eTagReturnSize; - char *eTagReturn; - int eTagReturnLen; - - string_buffer(lastModified, 256); -} CopyObjectData; - - -static S3Status copyObjectXmlCallback(const char *elementPath, - const char *data, int dataLen, - void *callbackData) -{ - CopyObjectData *coData = (CopyObjectData *) callbackData; - - int fit; - - if (data) { - if (!strcmp(elementPath, "CopyObjectResult/LastModified")) { - string_buffer_append(coData->lastModified, data, dataLen, fit); - } - else if (!strcmp(elementPath, "CopyObjectResult/ETag")) { - if (coData->eTagReturnSize && coData->eTagReturn) { - coData->eTagReturnLen += - snprintf(&(coData->eTagReturn[coData->eTagReturnLen]), - coData->eTagReturnSize - - coData->eTagReturnLen - 1, - "%.*s", dataLen, data); - if (coData->eTagReturnLen >= coData->eTagReturnSize) { - return S3StatusXmlParseFailure; - } - } - } - } - - return S3StatusOK; -} - - -static S3Status copyObjectPropertiesCallback - (const S3ResponseProperties *responseProperties, void *callbackData) -{ - CopyObjectData *coData = (CopyObjectData *) callbackData; - - return (*(coData->responsePropertiesCallback)) - (responseProperties, coData->callbackData); -} - - -static S3Status copyObjectDataCallback(int bufferSize, const char *buffer, - void *callbackData) -{ - CopyObjectData *coData = (CopyObjectData *) callbackData; - - return simplexml_add(&(coData->simpleXml), buffer, bufferSize); -} - - -static void copyObjectCompleteCallback(S3Status requestStatus, - const S3ErrorDetails *s3ErrorDetails, - void *callbackData) -{ - CopyObjectData *coData = (CopyObjectData *) callbackData; - - if (coData->lastModifiedReturn) { - time_t lastModified = -1; - if (coData->lastModifiedLen) { - lastModified = parseIso8601Time(coData->lastModified); - } - - *(coData->lastModifiedReturn) = lastModified; - } - - (*(coData->responseCompleteCallback)) - (requestStatus, s3ErrorDetails, coData->callbackData); - - simplexml_deinitialize(&(coData->simpleXml)); - - free(coData); -} - - -void S3_copy_object(const S3BucketContext *bucketContext, const char *key, - const char *destinationBucket, const char *destinationKey, - const S3PutProperties *putProperties, - int64_t *lastModifiedReturn, int eTagReturnSize, - char *eTagReturn, S3RequestContext *requestContext, - const S3ResponseHandler *handler, void *callbackData) -{ - // Create the callback data - CopyObjectData *data = - (CopyObjectData *) malloc(sizeof(CopyObjectData)); - if (!data) { - (*(handler->completeCallback))(S3StatusOutOfMemory, 0, callbackData); - return; - } - - simplexml_initialize(&(data->simpleXml), ©ObjectXmlCallback, data); - - data->responsePropertiesCallback = handler->propertiesCallback; - data->responseCompleteCallback = handler->completeCallback; - data->callbackData = callbackData; - - data->lastModifiedReturn = lastModifiedReturn; - data->eTagReturnSize = eTagReturnSize; - data->eTagReturn = eTagReturn; - if (data->eTagReturnSize && data->eTagReturn) { - data->eTagReturn[0] = 0; - } - data->eTagReturnLen = 0; - string_buffer_initialize(data->lastModified); - - // Set up the RequestParams - RequestParams params = - { - HttpRequestTypeCOPY, // httpRequestType - { destinationBucket ? destinationBucket : - bucketContext->bucketName, // bucketName - bucketContext->protocol, // protocol - bucketContext->uriStyle, // uriStyle - bucketContext->accessKeyId, // accessKeyId - bucketContext->secretAccessKey }, // secretAccessKey - destinationKey ? destinationKey : key, // key - 0, // queryParams - 0, // subResource - bucketContext->bucketName, // copySourceBucketName - key, // copySourceKey - 0, // getConditions - 0, // startByte - 0, // byteCount - putProperties, // putProperties - ©ObjectPropertiesCallback, // propertiesCallback - 0, // toS3Callback - 0, // toS3CallbackTotalSize - ©ObjectDataCallback, // fromS3Callback - ©ObjectCompleteCallback, // completeCallback - data // callbackData - }; - - // Perform the request - request_perform(¶ms, requestContext); -} - - -// get object ---------------------------------------------------------------- - -void S3_get_object(const S3BucketContext *bucketContext, const char *key, - const S3GetConditions *getConditions, - uint64_t startByte, uint64_t byteCount, - S3RequestContext *requestContext, - const S3GetObjectHandler *handler, void *callbackData) -{ - // Set up the RequestParams - RequestParams params = - { - HttpRequestTypeGET, // httpRequestType - { bucketContext->bucketName, // bucketName - bucketContext->protocol, // protocol - bucketContext->uriStyle, // uriStyle - bucketContext->accessKeyId, // accessKeyId - bucketContext->secretAccessKey }, // secretAccessKey - key, // key - 0, // queryParams - 0, // subResource - 0, // copySourceBucketName - 0, // copySourceKey - getConditions, // getConditions - startByte, // startByte - byteCount, // byteCount - 0, // putProperties - handler->responseHandler.propertiesCallback, // propertiesCallback - 0, // toS3Callback - 0, // toS3CallbackTotalSize - handler->getObjectDataCallback, // fromS3Callback - handler->responseHandler.completeCallback, // completeCallback - callbackData // callbackData - }; - - // Perform the request - request_perform(¶ms, requestContext); -} - - -// head object --------------------------------------------------------------- - -void S3_head_object(const S3BucketContext *bucketContext, const char *key, - S3RequestContext *requestContext, - const S3ResponseHandler *handler, void *callbackData) -{ - // Set up the RequestParams - RequestParams params = - { - HttpRequestTypeHEAD, // httpRequestType - { bucketContext->bucketName, // bucketName - bucketContext->protocol, // protocol - bucketContext->uriStyle, // uriStyle - bucketContext->accessKeyId, // accessKeyId - bucketContext->secretAccessKey }, // secretAccessKey - key, // key - 0, // queryParams - 0, // subResource - 0, // copySourceBucketName - 0, // copySourceKey - 0, // getConditions - 0, // startByte - 0, // byteCount - 0, // putProperties - handler->propertiesCallback, // propertiesCallback - 0, // toS3Callback - 0, // toS3CallbackTotalSize - 0, // fromS3Callback - handler->completeCallback, // completeCallback - callbackData // callbackData - }; - - // Perform the request - request_perform(¶ms, requestContext); -} - - -// delete object -------------------------------------------------------------- - -void S3_delete_object(const S3BucketContext *bucketContext, const char *key, - S3RequestContext *requestContext, - const S3ResponseHandler *handler, void *callbackData) -{ - // Set up the RequestParams - RequestParams params = - { - HttpRequestTypeDELETE, // httpRequestType - { bucketContext->bucketName, // bucketName - bucketContext->protocol, // protocol - bucketContext->uriStyle, // uriStyle - bucketContext->accessKeyId, // accessKeyId - bucketContext->secretAccessKey }, // secretAccessKey - key, // key - 0, // queryParams - 0, // subResource - 0, // copySourceBucketName - 0, // copySourceKey - 0, // getConditions - 0, // startByte - 0, // byteCount - 0, // putProperties - handler->propertiesCallback, // propertiesCallback - 0, // toS3Callback - 0, // toS3CallbackTotalSize - 0, // fromS3Callback - handler->completeCallback, // completeCallback - callbackData // callbackData - }; - - // Perform the request - request_perform(¶ms, requestContext); -} diff --git a/libs3-1.4/src/request.c b/libs3-1.4/src/request.c deleted file mode 100644 index f06e1a6..0000000 --- a/libs3-1.4/src/request.c +++ /dev/null @@ -1,1377 +0,0 @@ -/** ************************************************************************** - * request.c - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -#include -#include -#include -#include -#include -#include "request.h" -#include "request_context.h" -#include "response_headers_handler.h" -#include "util.h" - - -#define USER_AGENT_SIZE 256 -#define REQUEST_STACK_SIZE 32 - -static char userAgentG[USER_AGENT_SIZE]; - -static pthread_mutex_t requestStackMutexG; - -static Request *requestStackG[REQUEST_STACK_SIZE]; - -static int requestStackCountG; - - -typedef struct RequestComputedValues -{ - // All x-amz- headers, in normalized form (i.e. NAME: VALUE, no other ws) - char *amzHeaders[S3_MAX_METADATA_COUNT + 2]; // + 2 for acl and date - - // The number of x-amz- headers - int amzHeadersCount; - - // Storage for amzHeaders (the +256 is for x-amz-acl and x-amz-date) - char amzHeadersRaw[COMPACTED_METADATA_BUFFER_SIZE + 256 + 1]; - - // Canonicalized x-amz- headers - string_multibuffer(canonicalizedAmzHeaders, - COMPACTED_METADATA_BUFFER_SIZE + 256 + 1); - - // URL-Encoded key - char urlEncodedKey[MAX_URLENCODED_KEY_SIZE + 1]; - - // Canonicalized resource - char canonicalizedResource[MAX_CANONICALIZED_RESOURCE_SIZE + 1]; - - // Cache-Control header (or empty) - char cacheControlHeader[128]; - - // Content-Type header (or empty) - char contentTypeHeader[128]; - - // Content-MD5 header (or empty) - char md5Header[128]; - - // Content-Disposition header (or empty) - char contentDispositionHeader[128]; - - // Content-Encoding header (or empty) - char contentEncodingHeader[128]; - - // Expires header (or empty) - char expiresHeader[128]; - - // If-Modified-Since header - char ifModifiedSinceHeader[128]; - - // If-Unmodified-Since header - char ifUnmodifiedSinceHeader[128]; - - // If-Match header - char ifMatchHeader[128]; - - // If-None-Match header - char ifNoneMatchHeader[128]; - - // Range header - char rangeHeader[128]; - - // Authorization header - char authorizationHeader[128]; -} RequestComputedValues; - - -// Called whenever we detect that the request headers have been completely -// processed; which happens either when we get our first read/write callback, -// or the request is finished being procesed. Returns nonzero on success, -// zero on failure. -static void request_headers_done(Request *request) -{ - if (request->propertiesCallbackMade) { - return; - } - - request->propertiesCallbackMade = 1; - - // Get the http response code - long httpResponseCode; - request->httpResponseCode = 0; - if (curl_easy_getinfo(request->curl, CURLINFO_RESPONSE_CODE, - &httpResponseCode) != CURLE_OK) { - // Not able to get the HTTP response code - error - request->status = S3StatusInternalError; - return; - } - else { - request->httpResponseCode = httpResponseCode; - } - - response_headers_handler_done(&(request->responseHeadersHandler), - request->curl); - - // Only make the callback if it was a successful request; otherwise we're - // returning information about the error response itself - if (request->propertiesCallback && - (request->httpResponseCode >= 200) && - (request->httpResponseCode <= 299)) { - request->status = (*(request->propertiesCallback)) - (&(request->responseHeadersHandler.responseProperties), - request->callbackData); - } -} - - -static size_t curl_header_func(void *ptr, size_t size, size_t nmemb, - void *data) -{ - Request *request = (Request *) data; - - int len = size * nmemb; - - response_headers_handler_add - (&(request->responseHeadersHandler), (char *) ptr, len); - - return len; -} - - -static size_t curl_read_func(void *ptr, size_t size, size_t nmemb, void *data) -{ - Request *request = (Request *) data; - - int len = size * nmemb; - - request_headers_done(request); - - if (request->status != S3StatusOK) { - return CURL_READFUNC_ABORT; - } - - // If there is no data callback, or the data callback has already returned - // contentLength bytes, return 0; - if (!request->toS3Callback || !request->toS3CallbackBytesRemaining) { - return 0; - } - - // Don't tell the callback that we are willing to accept more data than we - // really are - if (len > request->toS3CallbackBytesRemaining) { - len = request->toS3CallbackBytesRemaining; - } - - // Otherwise, make the data callback - int ret = (*(request->toS3Callback)) - (len, (char *) ptr, request->callbackData); - if (ret < 0) { - request->status = S3StatusAbortedByCallback; - return CURL_READFUNC_ABORT; - } - else { - if (ret > request->toS3CallbackBytesRemaining) { - ret = request->toS3CallbackBytesRemaining; - } - request->toS3CallbackBytesRemaining -= ret; - return ret; - } -} - - -static size_t curl_write_func(void *ptr, size_t size, size_t nmemb, - void *data) -{ - Request *request = (Request *) data; - - int len = size * nmemb; - - request_headers_done(request); - - if (request->status != S3StatusOK) { - return 0; - } - - // On HTTP error, we expect to parse an HTTP error response - if ((request->httpResponseCode < 200) || - (request->httpResponseCode > 299)) { - request->status = error_parser_add - (&(request->errorParser), (char *) ptr, len); - } - // If there was a callback registered, make it - else if (request->fromS3Callback) { - request->status = (*(request->fromS3Callback)) - (len, (char *) ptr, request->callbackData); - } - // Else, consider this an error - S3 has sent back data when it was not - // expected - else { - request->status = S3StatusInternalError; - } - - return ((request->status == S3StatusOK) ? len : 0); -} - - -// This function 'normalizes' all x-amz-meta headers provided in -// params->requestHeaders, which means it removes all whitespace from -// them such that they all look exactly like this: -// x-amz-meta-${NAME}: ${VALUE} -// It also adds the x-amz-acl, x-amz-copy-source, and x-amz-metadata-directive -// headers if necessary, and always adds the x-amz-date header. It copies the -// raw string values into params->amzHeadersRaw, and creates an array of -// string pointers representing these headers in params->amzHeaders (and also -// sets params->amzHeadersCount to be the count of the total number of x-amz- -// headers thus created). -static S3Status compose_amz_headers(const RequestParams *params, - RequestComputedValues *values) -{ - const S3PutProperties *properties = params->putProperties; - - values->amzHeadersCount = 0; - values->amzHeadersRaw[0] = 0; - int len = 0; - - // Append a header to amzHeaders, trimming whitespace from the end. - // Does NOT trim whitespace from the beginning. -#define headers_append(isNewHeader, format, ...) \ - do { \ - if (isNewHeader) { \ - values->amzHeaders[values->amzHeadersCount++] = \ - &(values->amzHeadersRaw[len]); \ - } \ - len += snprintf(&(values->amzHeadersRaw[len]), \ - sizeof(values->amzHeadersRaw) - len, \ - format, __VA_ARGS__); \ - if (len >= (int) sizeof(values->amzHeadersRaw)) { \ - return S3StatusMetaDataHeadersTooLong; \ - } \ - while ((len > 0) && (values->amzHeadersRaw[len - 1] == ' ')) { \ - len--; \ - } \ - values->amzHeadersRaw[len++] = 0; \ - } while (0) - -#define header_name_tolower_copy(str, l) \ - do { \ - values->amzHeaders[values->amzHeadersCount++] = \ - &(values->amzHeadersRaw[len]); \ - if ((len + l) >= (int) sizeof(values->amzHeadersRaw)) { \ - return S3StatusMetaDataHeadersTooLong; \ - } \ - int todo = l; \ - while (todo--) { \ - if ((*(str) >= 'A') && (*(str) <= 'Z')) { \ - values->amzHeadersRaw[len++] = 'a' + (*(str) - 'A'); \ - } \ - else { \ - values->amzHeadersRaw[len++] = *(str); \ - } \ - (str)++; \ - } \ - } while (0) - - // Check and copy in the x-amz-meta headers - if (properties) { - int i; - for (i = 0; i < properties->metaDataCount; i++) { - const S3NameValue *property = &(properties->metaData[i]); - char headerName[S3_MAX_METADATA_SIZE - sizeof(": v")]; - int l = snprintf(headerName, sizeof(headerName), - S3_METADATA_HEADER_NAME_PREFIX "%s", - property->name); - char *hn = headerName; - header_name_tolower_copy(hn, l); - // Copy in the value - headers_append(0, ": %s", property->value); - } - - // Add the x-amz-acl header, if necessary - const char *cannedAclString; - switch (params->putProperties->cannedAcl) { - case S3CannedAclPrivate: - cannedAclString = 0; - break; - case S3CannedAclPublicRead: - cannedAclString = "public-read"; - break; - case S3CannedAclPublicReadWrite: - cannedAclString = "public-read-write"; - break; - default: // S3CannedAclAuthenticatedRead - cannedAclString = "authenticated-read"; - break; - } - if (cannedAclString) { - headers_append(1, "x-amz-acl: %s", cannedAclString); - } - } - - // Add the x-amz-date header - time_t now = time(NULL); - char date[64]; - strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now)); - headers_append(1, "x-amz-date: %s", date); - - if (params->httpRequestType == HttpRequestTypeCOPY) { - // Add the x-amz-copy-source header - if (params->copySourceBucketName && params->copySourceBucketName[0] && - params->copySourceKey && params->copySourceKey[0]) { - headers_append(1, "x-amz-copy-source: /%s/%s", - params->copySourceBucketName, - params->copySourceKey); - } - // And the x-amz-metadata-directive header - if (params->putProperties) { - headers_append(1, "%s", "x-amz-metadata-directive: REPLACE"); - } - } - - return S3StatusOK; -} - - -// Composes the other headers -static S3Status compose_standard_headers(const RequestParams *params, - RequestComputedValues *values) -{ - -#define do_put_header(fmt, sourceField, destField, badError, tooLongError) \ - do { \ - if (params->putProperties && \ - params->putProperties-> sourceField && \ - params->putProperties-> sourceField[0]) { \ - /* Skip whitespace at beginning of val */ \ - const char *val = params->putProperties-> sourceField; \ - while (*val && is_blank(*val)) { \ - val++; \ - } \ - if (!*val) { \ - return badError; \ - } \ - /* Compose header, make sure it all fit */ \ - int len = snprintf(values-> destField, \ - sizeof(values-> destField), fmt, val); \ - if (len >= (int) sizeof(values-> destField)) { \ - return tooLongError; \ - } \ - /* Now remove the whitespace at the end */ \ - while (is_blank(values-> destField[len])) { \ - len--; \ - } \ - values-> destField[len] = 0; \ - } \ - else { \ - values-> destField[0] = 0; \ - } \ - } while (0) - -#define do_get_header(fmt, sourceField, destField, badError, tooLongError) \ - do { \ - if (params->getConditions && \ - params->getConditions-> sourceField && \ - params->getConditions-> sourceField[0]) { \ - /* Skip whitespace at beginning of val */ \ - const char *val = params->getConditions-> sourceField; \ - while (*val && is_blank(*val)) { \ - val++; \ - } \ - if (!*val) { \ - return badError; \ - } \ - /* Compose header, make sure it all fit */ \ - int len = snprintf(values-> destField, \ - sizeof(values-> destField), fmt, val); \ - if (len >= (int) sizeof(values-> destField)) { \ - return tooLongError; \ - } \ - /* Now remove the whitespace at the end */ \ - while (is_blank(values-> destField[len])) { \ - len--; \ - } \ - values-> destField[len] = 0; \ - } \ - else { \ - values-> destField[0] = 0; \ - } \ - } while (0) - - // Cache-Control - do_put_header("Cache-Control: %s", cacheControl, cacheControlHeader, - S3StatusBadCacheControl, S3StatusCacheControlTooLong); - - // ContentType - do_put_header("Content-Type: %s", contentType, contentTypeHeader, - S3StatusBadContentType, S3StatusContentTypeTooLong); - - // MD5 - do_put_header("Content-MD5: %s", md5, md5Header, S3StatusBadMD5, - S3StatusMD5TooLong); - - // Content-Disposition - do_put_header("Content-Disposition: attachment; filename=\"%s\"", - contentDispositionFilename, contentDispositionHeader, - S3StatusBadContentDispositionFilename, - S3StatusContentDispositionFilenameTooLong); - - // ContentEncoding - do_put_header("Content-Encoding: %s", contentEncoding, - contentEncodingHeader, S3StatusBadContentEncoding, - S3StatusContentEncodingTooLong); - - // Expires - if (params->putProperties && (params->putProperties->expires >= 0)) { - time_t t = (time_t) params->putProperties->expires; - strftime(values->expiresHeader, sizeof(values->expiresHeader), - "Expires: %a, %d %b %Y %H:%M:%S UTC", gmtime(&t)); - } - else { - values->expiresHeader[0] = 0; - } - - // If-Modified-Since - if (params->getConditions && - (params->getConditions->ifModifiedSince >= 0)) { - time_t t = (time_t) params->getConditions->ifModifiedSince; - strftime(values->ifModifiedSinceHeader, - sizeof(values->ifModifiedSinceHeader), - "If-Modified-Since: %a, %d %b %Y %H:%M:%S UTC", gmtime(&t)); - } - else { - values->ifModifiedSinceHeader[0] = 0; - } - - // If-Unmodified-Since header - if (params->getConditions && - (params->getConditions->ifNotModifiedSince >= 0)) { - time_t t = (time_t) params->getConditions->ifNotModifiedSince; - strftime(values->ifUnmodifiedSinceHeader, - sizeof(values->ifUnmodifiedSinceHeader), - "If-Unmodified-Since: %a, %d %b %Y %H:%M:%S UTC", gmtime(&t)); - } - else { - values->ifUnmodifiedSinceHeader[0] = 0; - } - - // If-Match header - do_get_header("If-Match: %s", ifMatchETag, ifMatchHeader, - S3StatusBadIfMatchETag, S3StatusIfMatchETagTooLong); - - // If-None-Match header - do_get_header("If-None-Match: %s", ifNotMatchETag, ifNoneMatchHeader, - S3StatusBadIfNotMatchETag, - S3StatusIfNotMatchETagTooLong); - - // Range header - if (params->startByte || params->byteCount) { - if (params->byteCount) { - snprintf(values->rangeHeader, sizeof(values->rangeHeader), - "Range: bytes=%llu-%llu", - (unsigned long long) params->startByte, - (unsigned long long) (params->startByte + - params->byteCount - 1)); - } - else { - snprintf(values->rangeHeader, sizeof(values->rangeHeader), - "Range: bytes=%llu-", - (unsigned long long) params->startByte); - } - } - else { - values->rangeHeader[0] = 0; - } - - return S3StatusOK; -} - - -// URL encodes the params->key value into params->urlEncodedKey -static S3Status encode_key(const RequestParams *params, - RequestComputedValues *values) -{ - return (urlEncode(values->urlEncodedKey, params->key, S3_MAX_KEY_SIZE) ? - S3StatusOK : S3StatusUriTooLong); -} - - -// Simple comparison function for comparing two HTTP header names that are -// embedded within an HTTP header line, returning true if header1 comes -// before header2 alphabetically, false if not -static int headerle(const char *header1, const char *header2) -{ - while (1) { - if (*header1 == ':') { - return (*header2 == ':'); - } - else if (*header2 == ':') { - return 0; - } - else if (*header2 < *header1) { - return 0; - } - else if (*header2 > *header1) { - return 1; - } - header1++, header2++; - } -} - - -// Replace this with merge sort eventually, it's the best stable sort. But -// since typically the number of elements being sorted is small, it doesn't -// matter that much which sort is used, and gnome sort is the world's simplest -// stable sort. Added a slight twist to the standard gnome_sort - don't go -// forward +1, go forward to the last highest index considered. This saves -// all the string comparisons that would be done "going forward", and thus -// only does the necessary string comparisons to move values back into their -// sorted position. -static void header_gnome_sort(const char **headers, int size) -{ - int i = 0, last_highest = 0; - - while (i < size) { - if ((i == 0) || headerle(headers[i - 1], headers[i])) { - i = ++last_highest; - } - else { - const char *tmp = headers[i]; - headers[i] = headers[i - 1]; - headers[--i] = tmp; - } - } -} - - -// Canonicalizes the x-amz- headers into the canonicalizedAmzHeaders buffer -static void canonicalize_amz_headers(RequestComputedValues *values) -{ - // Make a copy of the headers that will be sorted - const char *sortedHeaders[S3_MAX_METADATA_COUNT]; - - memcpy(sortedHeaders, values->amzHeaders, - (values->amzHeadersCount * sizeof(sortedHeaders[0]))); - - // Now sort these - header_gnome_sort(sortedHeaders, values->amzHeadersCount); - - // Now copy this sorted list into the buffer, all the while: - // - folding repeated headers into single lines, and - // - folding multiple lines - // - removing the space after the colon - int lastHeaderLen = 0, i; - char *buffer = values->canonicalizedAmzHeaders; - for (i = 0; i < values->amzHeadersCount; i++) { - const char *header = sortedHeaders[i]; - const char *c = header; - // If the header names are the same, append the next value - if ((i > 0) && - !strncmp(header, sortedHeaders[i - 1], lastHeaderLen)) { - // Replacing the previous newline with a comma - *(buffer - 1) = ','; - // Skip the header name and space - c += (lastHeaderLen + 1); - } - // Else this is a new header - else { - // Copy in everything up to the space in the ": " - while (*c != ' ') { - *buffer++ = *c++; - } - // Save the header len since it's a new header - lastHeaderLen = c - header; - // Skip the space - c++; - } - // Now copy in the value, folding the lines - while (*c) { - // If c points to a \r\n[whitespace] sequence, then fold - // this newline out - if ((*c == '\r') && (*(c + 1) == '\n') && is_blank(*(c + 2))) { - c += 3; - while (is_blank(*c)) { - c++; - } - // Also, what has most recently been copied into buffer amy - // have been whitespace, and since we're folding whitespace - // out around this newline sequence, back buffer up over - // any whitespace it contains - while (is_blank(*(buffer - 1))) { - buffer--; - } - continue; - } - *buffer++ = *c++; - } - // Finally, add the newline - *buffer++ = '\n'; - } - - // Terminate the buffer - *buffer = 0; -} - - -// Canonicalizes the resource into params->canonicalizedResource -static void canonicalize_resource(const char *bucketName, - const char *subResource, - const char *urlEncodedKey, - char *buffer) -{ - int len = 0; - - *buffer = 0; - -#define append(str) len += sprintf(&(buffer[len]), "%s", str) - - if (bucketName && bucketName[0]) { - buffer[len++] = '/'; - append(bucketName); - } - - append("/"); - - if (urlEncodedKey && urlEncodedKey[0]) { - append(urlEncodedKey); - } - - if (subResource && subResource[0]) { - append("?"); - append(subResource); - } -} - - -// Convert an HttpRequestType to an HTTP Verb string -static const char *http_request_type_to_verb(HttpRequestType requestType) -{ - switch (requestType) { - case HttpRequestTypeGET: - return "GET"; - case HttpRequestTypeHEAD: - return "HEAD"; - case HttpRequestTypePUT: - case HttpRequestTypeCOPY: - return "PUT"; - default: // HttpRequestTypeDELETE - return "DELETE"; - } -} - - -// Composes the Authorization header for the request -static S3Status compose_auth_header(const RequestParams *params, - RequestComputedValues *values) -{ - // We allow for: - // 17 bytes for HTTP-Verb + \n - // 129 bytes for Content-MD5 + \n - // 129 bytes for Content-Type + \n - // 1 byte for empty Date + \n - // CanonicalizedAmzHeaders & CanonicalizedResource - char signbuf[17 + 129 + 129 + 1 + - (sizeof(values->canonicalizedAmzHeaders) - 1) + - (sizeof(values->canonicalizedResource) - 1) + 1]; - int len = 0; - -#define signbuf_append(format, ...) \ - len += snprintf(&(signbuf[len]), sizeof(signbuf) - len, \ - format, __VA_ARGS__) - - signbuf_append - ("%s\n", http_request_type_to_verb(params->httpRequestType)); - - // For MD5 and Content-Type, use the value in the actual header, because - // it's already been trimmed - signbuf_append("%s\n", values->md5Header[0] ? - &(values->md5Header[sizeof("Content-MD5: ") - 1]) : ""); - - signbuf_append - ("%s\n", values->contentTypeHeader[0] ? - &(values->contentTypeHeader[sizeof("Content-Type: ") - 1]) : ""); - - signbuf_append("%s", "\n"); // Date - we always use x-amz-date - - signbuf_append("%s", values->canonicalizedAmzHeaders); - - signbuf_append("%s", values->canonicalizedResource); - - // Generate an HMAC-SHA-1 of the signbuf - unsigned char hmac[20]; - - HMAC_SHA1(hmac, (unsigned char *) params->bucketContext.secretAccessKey, - strlen(params->bucketContext.secretAccessKey), - (unsigned char *) signbuf, len); - - // Now base-64 encode the results - char b64[((20 + 1) * 4) / 3]; - int b64Len = base64Encode(hmac, 20, b64); - - snprintf(values->authorizationHeader, sizeof(values->authorizationHeader), - "Authorization: AWS %s:%.*s", params->bucketContext.accessKeyId, - b64Len, b64); - - return S3StatusOK; -} - - -// Compose the URI to use for the request given the request parameters -static S3Status compose_uri(char *buffer, int bufferSize, - const S3BucketContext *bucketContext, - const char *urlEncodedKey, - const char *subResource, const char *queryParams) -{ - int len = 0; - -#define uri_append(fmt, ...) \ - do { \ - len += snprintf(&(buffer[len]), bufferSize - len, fmt, __VA_ARGS__); \ - if (len >= bufferSize) { \ - return S3StatusUriTooLong; \ - } \ - } while (0) - - uri_append("http%s://", - (bucketContext->protocol == S3ProtocolHTTP) ? "" : "s"); - - if (bucketContext->bucketName && - bucketContext->bucketName[0]) { - if (bucketContext->uriStyle == S3UriStyleVirtualHost) { - uri_append("%s.s3.amazonaws.com", bucketContext->bucketName); - } - else { - uri_append("s3.amazonaws.com/%s", bucketContext->bucketName); - } - } - else { - uri_append("%s", "s3.amazonaws.com"); - } - - uri_append("%s", "/"); - - uri_append("%s", urlEncodedKey); - - if (subResource && subResource[0]) { - uri_append("?%s", subResource); - } - - if (queryParams) { - uri_append("%s%s", (subResource && subResource[0]) ? "&" : "?", - queryParams); - } - - return S3StatusOK; -} - - -// Sets up the curl handle given the completely computed RequestParams -static S3Status setup_curl(Request *request, - const RequestParams *params, - const RequestComputedValues *values) -{ - CURLcode status; - -#define curl_easy_setopt_safe(opt, val) \ - if ((status = curl_easy_setopt \ - (request->curl, opt, val)) != CURLE_OK) { \ - return S3StatusFailedToInitializeRequest; \ - } - - // Debugging only - // curl_easy_setopt_safe(CURLOPT_VERBOSE, 1); - - // Set private data to request for the benefit of S3RequestContext - curl_easy_setopt_safe(CURLOPT_PRIVATE, request); - - // Set header callback and data - curl_easy_setopt_safe(CURLOPT_HEADERDATA, request); - curl_easy_setopt_safe(CURLOPT_HEADERFUNCTION, &curl_header_func); - - // Set read callback, data, and readSize - curl_easy_setopt_safe(CURLOPT_READFUNCTION, &curl_read_func); - curl_easy_setopt_safe(CURLOPT_READDATA, request); - - // Set write callback and data - curl_easy_setopt_safe(CURLOPT_WRITEFUNCTION, &curl_write_func); - curl_easy_setopt_safe(CURLOPT_WRITEDATA, request); - - // Ask curl to parse the Last-Modified header. This is easier than - // parsing it ourselves. - curl_easy_setopt_safe(CURLOPT_FILETIME, 1); - - // Curl docs suggest that this is necessary for multithreaded code. - // However, it also points out that DNS timeouts will not be honored - // during DNS lookup, which can be worked around by using the c-ares - // library, which we do not do yet. - curl_easy_setopt_safe(CURLOPT_NOSIGNAL, 1); - - // Turn off Curl's built-in progress meter - curl_easy_setopt_safe(CURLOPT_NOPROGRESS, 1); - - // xxx todo - support setting the proxy for Curl to use (can't use https - // for proxies though) - - // xxx todo - support setting the network interface for Curl to use - - // I think this is useful - we don't need interactive performance, we need - // to complete large operations quickly - curl_easy_setopt_safe(CURLOPT_TCP_NODELAY, 1); - - // Don't use Curl's 'netrc' feature - curl_easy_setopt_safe(CURLOPT_NETRC, CURL_NETRC_IGNORED); - - // Don't verify S3's certificate, there are known to be issues with - // them sometimes - // xxx todo - support an option for verifying the S3 CA (default false) - curl_easy_setopt_safe(CURLOPT_SSL_VERIFYPEER, 0); - - // Follow any redirection directives that S3 sends - curl_easy_setopt_safe(CURLOPT_FOLLOWLOCATION, 1); - - // A safety valve in case S3 goes bananas with redirects - curl_easy_setopt_safe(CURLOPT_MAXREDIRS, 10); - - // Set the User-Agent; maybe Amazon will track these? - curl_easy_setopt_safe(CURLOPT_USERAGENT, userAgentG); - - // Set the low speed limit and time; we abort transfers that stay at - // less than 1K per second for more than 15 seconds. - // xxx todo - make these configurable - // xxx todo - allow configurable max send and receive speed - curl_easy_setopt_safe(CURLOPT_LOW_SPEED_LIMIT, 1024); - curl_easy_setopt_safe(CURLOPT_LOW_SPEED_TIME, 15); - - // Append standard headers -#define append_standard_header(fieldName) \ - if (values-> fieldName [0]) { \ - request->headers = curl_slist_append(request->headers, \ - values-> fieldName); \ - } - - // Would use CURLOPT_INFILESIZE_LARGE, but it is buggy in libcurl - if (params->httpRequestType == HttpRequestTypePUT) { - char header[256]; - snprintf(header, sizeof(header), "Content-Length: %llu", - (unsigned long long) params->toS3CallbackTotalSize); - request->headers = curl_slist_append(request->headers, header); - request->headers = curl_slist_append(request->headers, - "Transfer-Encoding:"); - } - else if (params->httpRequestType == HttpRequestTypeCOPY) { - request->headers = curl_slist_append(request->headers, - "Transfer-Encoding:"); - } - - append_standard_header(cacheControlHeader); - append_standard_header(contentTypeHeader); - append_standard_header(md5Header); - append_standard_header(contentDispositionHeader); - append_standard_header(contentEncodingHeader); - append_standard_header(expiresHeader); - append_standard_header(ifModifiedSinceHeader); - append_standard_header(ifUnmodifiedSinceHeader); - append_standard_header(ifMatchHeader); - append_standard_header(ifNoneMatchHeader); - append_standard_header(rangeHeader); - append_standard_header(authorizationHeader); - - // Append x-amz- headers - int i; - for (i = 0; i < values->amzHeadersCount; i++) { - request->headers = - curl_slist_append(request->headers, values->amzHeaders[i]); - } - - // Set the HTTP headers - curl_easy_setopt_safe(CURLOPT_HTTPHEADER, request->headers); - - // Set URI - curl_easy_setopt_safe(CURLOPT_URL, request->uri); - - // Set request type. - switch (params->httpRequestType) { - case HttpRequestTypeHEAD: - curl_easy_setopt_safe(CURLOPT_NOBODY, 1); - break; - case HttpRequestTypePUT: - case HttpRequestTypeCOPY: - curl_easy_setopt_safe(CURLOPT_UPLOAD, 1); - break; - case HttpRequestTypeDELETE: - curl_easy_setopt_safe(CURLOPT_CUSTOMREQUEST, "DELETE"); - break; - default: // HttpRequestTypeGET - break; - } - - return S3StatusOK; -} - - -static void request_deinitialize(Request *request) -{ - if (request->headers) { - curl_slist_free_all(request->headers); - } - - error_parser_deinitialize(&(request->errorParser)); - - // curl_easy_reset prevents connections from being re-used for some - // reason. This makes HTTP Keep-Alive meaningless and is very bad for - // performance. But it is necessary to allow curl to work properly. - // xxx todo figure out why - curl_easy_reset(request->curl); -} - - -static S3Status request_get(const RequestParams *params, - const RequestComputedValues *values, - Request **reqReturn) -{ - Request *request = 0; - - // Try to get one from the request stack. We hold the lock for the - // shortest time possible here. - pthread_mutex_lock(&requestStackMutexG); - - if (requestStackCountG) { - request = requestStackG[--requestStackCountG]; - } - - pthread_mutex_unlock(&requestStackMutexG); - - // If we got one, deinitialize it for re-use - if (request) { - request_deinitialize(request); - } - // Else there wasn't one available in the request stack, so create one - else { - if (!(request = (Request *) malloc(sizeof(Request)))) { - return S3StatusOutOfMemory; - } - if (!(request->curl = curl_easy_init())) { - free(request); - return S3StatusFailedToInitializeRequest; - } - } - - // Initialize the request - request->prev = 0; - request->next = 0; - - // Request status is initialized to no error, will be updated whenever - // an error occurs - request->status = S3StatusOK; - - S3Status status; - - // Start out with no headers - request->headers = 0; - - // Compute the URL - if ((status = compose_uri - (request->uri, sizeof(request->uri), - &(params->bucketContext), values->urlEncodedKey, - params->subResource, params->queryParams)) != S3StatusOK) { - curl_easy_cleanup(request->curl); - free(request); - return status; - } - - // Set all of the curl handle options - if ((status = setup_curl(request, params, values)) != S3StatusOK) { - curl_easy_cleanup(request->curl); - free(request); - return status; - } - - request->propertiesCallback = params->propertiesCallback; - - request->toS3Callback = params->toS3Callback; - - request->toS3CallbackBytesRemaining = params->toS3CallbackTotalSize; - - request->fromS3Callback = params->fromS3Callback; - - request->completeCallback = params->completeCallback; - - request->callbackData = params->callbackData; - - response_headers_handler_initialize(&(request->responseHeadersHandler)); - - request->propertiesCallbackMade = 0; - - error_parser_initialize(&(request->errorParser)); - - *reqReturn = request; - - return S3StatusOK; -} - - -static void request_destroy(Request *request) -{ - request_deinitialize(request); - curl_easy_cleanup(request->curl); - free(request); -} - - -static void request_release(Request *request) -{ - pthread_mutex_lock(&requestStackMutexG); - - // If the request stack is full, destroy this one - if (requestStackCountG == REQUEST_STACK_SIZE) { - pthread_mutex_unlock(&requestStackMutexG); - request_destroy(request); - } - // Else put this one at the front of the request stack; we do this because - // we want the most-recently-used curl handle to be re-used on the next - // request, to maximize our chances of re-using a TCP connection before it - // times out - else { - requestStackG[requestStackCountG++] = request; - pthread_mutex_unlock(&requestStackMutexG); - } -} - - -S3Status request_api_initialize(const char *userAgentInfo, int flags) -{ - if (curl_global_init(CURL_GLOBAL_ALL & - ~((flags & S3_INIT_WINSOCK) ? 0 : CURL_GLOBAL_WIN32)) - != CURLE_OK) { - return S3StatusInternalError; - } - - pthread_mutex_init(&requestStackMutexG, 0); - - requestStackCountG = 0; - - if (!userAgentInfo || !*userAgentInfo) { - userAgentInfo = "Unknown"; - } - - char platform[96]; - struct utsname utsn; - if (uname(&utsn)) { - strncpy(platform, "Unknown", sizeof(platform)); - // Because strncpy doesn't always zero terminate - platform[sizeof(platform) - 1] = 0; - } - else { - snprintf(platform, sizeof(platform), "%s%s%s", utsn.sysname, - utsn.machine[0] ? " " : "", utsn.machine); - } - - snprintf(userAgentG, sizeof(userAgentG), - "Mozilla/4.0 (Compatible; %s; libs3 %s.%s; %s)", - userAgentInfo, LIBS3_VER_MAJOR, LIBS3_VER_MINOR, platform); - - return S3StatusOK; -} - - -void request_api_deinitialize() -{ - pthread_mutex_destroy(&requestStackMutexG); - - while (requestStackCountG--) { - request_destroy(requestStackG[requestStackCountG]); - } -} - - -void request_perform(const RequestParams *params, S3RequestContext *context) -{ - Request *request; - S3Status status; - -#define return_status(status) \ - (*(params->completeCallback))(status, 0, params->callbackData); \ - return - - // These will hold the computed values - RequestComputedValues computed; - - // Validate the bucket name - if (params->bucketContext.bucketName && - ((status = S3_validate_bucket_name - (params->bucketContext.bucketName, - params->bucketContext.uriStyle)) != S3StatusOK)) { - return_status(status); - } - - // Compose the amz headers - if ((status = compose_amz_headers(params, &computed)) != S3StatusOK) { - return_status(status); - } - - // Compose standard headers - if ((status = compose_standard_headers - (params, &computed)) != S3StatusOK) { - return_status(status); - } - - // URL encode the key - if ((status = encode_key(params, &computed)) != S3StatusOK) { - return_status(status); - } - - // Compute the canonicalized amz headers - canonicalize_amz_headers(&computed); - - // Compute the canonicalized resource - canonicalize_resource(params->bucketContext.bucketName, - params->subResource, computed.urlEncodedKey, - computed.canonicalizedResource); - - // Compose Authorization header - if ((status = compose_auth_header(params, &computed)) != S3StatusOK) { - return_status(status); - } - - // Get an initialized Request structure now - if ((status = request_get(params, &computed, &request)) != S3StatusOK) { - return_status(status); - } - - // If a RequestContext was provided, add the request to the curl multi - if (context) { - CURLMcode code = curl_multi_add_handle(context->curlm, request->curl); - if (code == CURLM_OK) { - if (context->requests) { - request->prev = context->requests->prev; - request->next = context->requests; - context->requests->prev->next = request; - context->requests->prev = request; - } - else { - context->requests = request->next = request->prev = request; - } - } - else { - if (request->status == S3StatusOK) { - request->status = (code == CURLM_OUT_OF_MEMORY) ? - S3StatusOutOfMemory : S3StatusInternalError; - } - request_finish(request); - } - } - // Else, perform the request immediately - else { - CURLcode code = curl_easy_perform(request->curl); - if ((code != CURLE_OK) && (request->status == S3StatusOK)) { - request->status = request_curl_code_to_status(code); - } - // Finish the request, ensuring that all callbacks have been made, and - // also releases the request - request_finish(request); - } -} - - -void request_finish(Request *request) -{ - // If we haven't detected this already, we now know that the headers are - // definitely done being read in - request_headers_done(request); - - // If there was no error processing the request, then possibly there was - // an S3 error parsed, which should be converted into the request status - if (request->status == S3StatusOK) { - error_parser_convert_status(&(request->errorParser), - &(request->status)); - // If there still was no error recorded, then it is possible that - // there was in fact an error but that there was no error XML - // detailing the error - if ((request->status == S3StatusOK) && - ((request->httpResponseCode < 200) || - (request->httpResponseCode > 299))) { - switch (request->httpResponseCode) { - case 0: - // This happens if the request never got any HTTP response - // headers at all, we call this a ConnectionFailed error - request->status = S3StatusConnectionFailed; - break; - case 100: // Some versions of libcurl erroneously set HTTP - // status to this - break; - case 301: - request->status = S3StatusErrorPermanentRedirect; - break; - case 307: - request->status = S3StatusHttpErrorMovedTemporarily; - break; - case 400: - request->status = S3StatusHttpErrorBadRequest; - break; - case 403: - request->status = S3StatusHttpErrorForbidden; - break; - case 404: - request->status = S3StatusHttpErrorNotFound; - break; - case 405: - request->status = S3StatusErrorMethodNotAllowed; - break; - case 409: - request->status = S3StatusHttpErrorConflict; - break; - case 411: - request->status = S3StatusErrorMissingContentLength; - break; - case 412: - request->status = S3StatusErrorPreconditionFailed; - break; - case 416: - request->status = S3StatusErrorInvalidRange; - break; - case 500: - request->status = S3StatusErrorInternalError; - break; - case 501: - request->status = S3StatusErrorNotImplemented; - break; - case 503: - request->status = S3StatusErrorSlowDown; - break; - default: - request->status = S3StatusHttpErrorUnknown; - break; - } - } - } - - (*(request->completeCallback)) - (request->status, &(request->errorParser.s3ErrorDetails), - request->callbackData); - - request_release(request); -} - - -S3Status request_curl_code_to_status(CURLcode code) -{ - switch (code) { - case CURLE_OUT_OF_MEMORY: - return S3StatusOutOfMemory; - case CURLE_COULDNT_RESOLVE_PROXY: - case CURLE_COULDNT_RESOLVE_HOST: - return S3StatusNameLookupError; - case CURLE_COULDNT_CONNECT: - return S3StatusFailedToConnect; - case CURLE_WRITE_ERROR: - case CURLE_OPERATION_TIMEDOUT: - return S3StatusConnectionFailed; - case CURLE_PARTIAL_FILE: - return S3StatusOK; - case CURLE_SSL_CACERT: - return S3StatusServerFailedVerification; - default: - return S3StatusInternalError; - } -} - - -S3Status S3_generate_authenticated_query_string - (char *buffer, const S3BucketContext *bucketContext, - const char *key, int64_t expires, const char *resource) -{ -#define MAX_EXPIRES (((int64_t) 1 << 31) - 1) - // S3 seems to only accept expiration dates up to the number of seconds - // representably by a signed 32-bit integer - if (expires < 0) { - expires = MAX_EXPIRES; - } - else if (expires > MAX_EXPIRES) { - expires = MAX_EXPIRES; - } - - // xxx todo: rework this so that it can be incorporated into shared code - // with request_perform(). It's really unfortunate that this code is not - // shared with request_perform(). - - // URL encode the key - char urlEncodedKey[S3_MAX_KEY_SIZE * 3]; - if (key) { - urlEncode(urlEncodedKey, key, strlen(key)); - } - else { - urlEncodedKey[0] = 0; - } - - // Compute canonicalized resource - char canonicalizedResource[MAX_CANONICALIZED_RESOURCE_SIZE]; - canonicalize_resource(bucketContext->bucketName, resource, urlEncodedKey, - canonicalizedResource); - - // We allow for: - // 17 bytes for HTTP-Verb + \n - // 1 byte for empty Content-MD5 + \n - // 1 byte for empty Content-Type + \n - // 20 bytes for Expires + \n - // 0 bytes for CanonicalizedAmzHeaders - // CanonicalizedResource - char signbuf[17 + 1 + 1 + 1 + 20 + sizeof(canonicalizedResource) + 1]; - int len = 0; - -#define signbuf_append(format, ...) \ - len += snprintf(&(signbuf[len]), sizeof(signbuf) - len, \ - format, __VA_ARGS__) - - signbuf_append("%s\n", "GET"); // HTTP-Verb - signbuf_append("%s\n", ""); // Content-MD5 - signbuf_append("%s\n", ""); // Content-Type - signbuf_append("%llu\n", (unsigned long long) expires); - signbuf_append("%s", canonicalizedResource); - - // Generate an HMAC-SHA-1 of the signbuf - unsigned char hmac[20]; - - HMAC_SHA1(hmac, (unsigned char *) bucketContext->secretAccessKey, - strlen(bucketContext->secretAccessKey), - (unsigned char *) signbuf, len); - - // Now base-64 encode the results - char b64[((20 + 1) * 4) / 3]; - int b64Len = base64Encode(hmac, 20, b64); - - // Now urlEncode that - char signature[sizeof(b64) * 3]; - urlEncode(signature, b64, b64Len); - - // Finally, compose the uri, with params: - // ?AWSAccessKeyId=xxx[&Expires=]&Signature=xxx - char queryParams[sizeof("AWSAccessKeyId=") + 20 + - sizeof("&Expires=") + 20 + - sizeof("&Signature=") + sizeof(signature) + 1]; - - sprintf(queryParams, "AWSAccessKeyId=%s&Expires=%ld&Signature=%s", - bucketContext->accessKeyId, (long) expires, signature); - - return compose_uri(buffer, S3_MAX_AUTHENTICATED_QUERY_STRING_SIZE, - bucketContext, urlEncodedKey, resource, queryParams); -} diff --git a/libs3-1.4/src/request_context.c b/libs3-1.4/src/request_context.c deleted file mode 100644 index ae48e55..0000000 --- a/libs3-1.4/src/request_context.c +++ /dev/null @@ -1,190 +0,0 @@ -/** ************************************************************************** - * request_context.c - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -#include -#include -#include -#include "request.h" -#include "request_context.h" - - -S3Status S3_create_request_context(S3RequestContext **requestContextReturn) -{ - *requestContextReturn = - (S3RequestContext *) malloc(sizeof(S3RequestContext)); - - if (!*requestContextReturn) { - return S3StatusOutOfMemory; - } - - if (!((*requestContextReturn)->curlm = curl_multi_init())) { - free(*requestContextReturn); - return S3StatusOutOfMemory; - } - - (*requestContextReturn)->requests = 0; - - return S3StatusOK; -} - - -void S3_destroy_request_context(S3RequestContext *requestContext) -{ - curl_multi_cleanup(requestContext->curlm); - - // For each request in the context, call back its done method with - // 'interrupted' status - Request *r = requestContext->requests, *rFirst = r; - - if (r) do { - r->status = S3StatusInterrupted; - Request *rNext = r->next; - request_finish(r); - r = rNext; - } while (r != rFirst); - - free(requestContext); -} - - -S3Status S3_runall_request_context(S3RequestContext *requestContext) -{ - int requestsRemaining; - do { - fd_set readfds, writefds, exceptfds; - FD_ZERO(&readfds); - FD_ZERO(&writefds); - FD_ZERO(&exceptfds); - int maxfd; - S3Status status = S3_get_request_context_fdsets - (requestContext, &readfds, &writefds, &exceptfds, &maxfd); - if (status != S3StatusOK) { - return status; - } - // curl will return -1 if it hasn't even created any fds yet because - // none of the connections have started yet. In this case, don't - // do the select at all, because it will wait forever; instead, just - // skip it and go straight to running the underlying CURL handles - if (maxfd != -1) { - int64_t timeout = S3_get_request_context_timeout(requestContext); - struct timeval tv = { timeout / 1000, (timeout % 1000) * 1000 }; - select(maxfd + 1, &readfds, &writefds, &exceptfds, - (timeout == -1) ? 0 : &tv); - } - status = S3_runonce_request_context(requestContext, - &requestsRemaining); - if (status != S3StatusOK) { - return status; - } - } while (requestsRemaining); - - return S3StatusOK; -} - - -S3Status S3_runonce_request_context(S3RequestContext *requestContext, - int *requestsRemainingReturn) -{ - CURLMcode status; - - do { - status = curl_multi_perform(requestContext->curlm, - requestsRemainingReturn); - - switch (status) { - case CURLM_OK: - case CURLM_CALL_MULTI_PERFORM: - break; - case CURLM_OUT_OF_MEMORY: - return S3StatusOutOfMemory; - default: - return S3StatusInternalError; - } - - CURLMsg *msg; - int junk; - while ((msg = curl_multi_info_read(requestContext->curlm, &junk))) { - if (msg->msg != CURLMSG_DONE) { - return S3StatusInternalError; - } - Request *request; - if (curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, - (char **) (char *) &request) != CURLE_OK) { - return S3StatusInternalError; - } - // Remove the request from the list of requests - if (request->prev == request->next) { - // It was the only one on the list - requestContext->requests = 0; - } - else { - // It doesn't matter what the order of them are, so just in - // case request was at the head of the list, put the one after - // request to the head of the list - requestContext->requests = request->next; - request->prev->next = request->next; - request->next->prev = request->prev; - } - if ((msg->data.result != CURLE_OK) && - (request->status == S3StatusOK)) { - request->status = request_curl_code_to_status - (msg->data.result); - } - if (curl_multi_remove_handle(requestContext->curlm, - msg->easy_handle) != CURLM_OK) { - return S3StatusInternalError; - } - // Finish the request, ensuring that all callbacks have been made, - // and also releases the request - request_finish(request); - // Now, since a callback was made, there may be new requests - // queued up to be performed immediately, so do so - status = CURLM_CALL_MULTI_PERFORM; - } - } while (status == CURLM_CALL_MULTI_PERFORM); - - return S3StatusOK; -} - -S3Status S3_get_request_context_fdsets(S3RequestContext *requestContext, - fd_set *readFdSet, fd_set *writeFdSet, - fd_set *exceptFdSet, int *maxFd) -{ - return ((curl_multi_fdset(requestContext->curlm, readFdSet, writeFdSet, - exceptFdSet, maxFd) == CURLM_OK) ? - S3StatusOK : S3StatusInternalError); -} - -int64_t S3_get_request_context_timeout(S3RequestContext *requestContext) -{ - long timeout; - - if (curl_multi_timeout(requestContext->curlm, &timeout) != CURLM_OK) { - timeout = 0; - } - - return timeout; -} diff --git a/libs3-1.4/src/response_headers_handler.c b/libs3-1.4/src/response_headers_handler.c deleted file mode 100644 index e506ea4..0000000 --- a/libs3-1.4/src/response_headers_handler.c +++ /dev/null @@ -1,205 +0,0 @@ -/** ************************************************************************** - * response_headers_handler.c - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -#include -#include -#include "response_headers_handler.h" - - -void response_headers_handler_initialize(ResponseHeadersHandler *handler) -{ - handler->responseProperties.requestId = 0; - handler->responseProperties.requestId2 = 0; - handler->responseProperties.contentType = 0; - handler->responseProperties.contentLength = 0; - handler->responseProperties.server = 0; - handler->responseProperties.eTag = 0; - handler->responseProperties.lastModified = -1; - handler->responseProperties.metaDataCount = 0; - handler->responseProperties.metaData = 0; - handler->done = 0; - string_multibuffer_initialize(handler->responsePropertyStrings); - string_multibuffer_initialize(handler->responseMetaDataStrings); -} - - -void response_headers_handler_add(ResponseHeadersHandler *handler, - char *header, int len) -{ - S3ResponseProperties *responseProperties = &(handler->responseProperties); - char *end = &(header[len]); - - // Curl might call back the header function after the body has been - // received, for 'chunked encoded' contents. We don't handle this as of - // yet, and it's not clear that it would ever be useful. - if (handler->done) { - return; - } - - // If we've already filled up the response headers, ignore this data. - // This sucks, but it shouldn't happen - S3 should not be sending back - // really long headers. - if (handler->responsePropertyStringsSize == - (sizeof(handler->responsePropertyStrings) - 1)) { - return; - } - - // It should not be possible to have a header line less than 3 long - if (len < 3) { - return; - } - - // Skip whitespace at beginning of header; there never should be any, - // but just to be safe - while (is_blank(*header)) { - header++; - } - - // The header must end in \r\n, so skip back over it, and also over any - // trailing whitespace - end -= 3; - while ((end > header) && is_blank(*end)) { - end--; - } - if (!is_blank(*end)) { - end++; - } - - if (end == header) { - // totally bogus - return; - } - - *end = 0; - - // Find the colon to split the header up - char *c = header; - while (*c && (*c != ':')) { - c++; - } - - int namelen = c - header; - - // Now walk c past the colon - c++; - // Now skip whitespace to the beginning of the value - while (is_blank(*c)) { - c++; - } - - int valuelen = (end - c) + 1, fit; - - if (!strncmp(header, "x-amz-request-id", namelen)) { - responseProperties->requestId = - string_multibuffer_current(handler->responsePropertyStrings); - string_multibuffer_add(handler->responsePropertyStrings, c, - valuelen, fit); - } - else if (!strncmp(header, "x-amz-id-2", namelen)) { - responseProperties->requestId2 = - string_multibuffer_current(handler->responsePropertyStrings); - string_multibuffer_add(handler->responsePropertyStrings, c, - valuelen, fit); - } - else if (!strncmp(header, "Content-Type", namelen)) { - responseProperties->contentType = - string_multibuffer_current(handler->responsePropertyStrings); - string_multibuffer_add(handler->responsePropertyStrings, c, - valuelen, fit); - } - else if (!strncmp(header, "Content-Length", namelen)) { - handler->responseProperties.contentLength = 0; - while (*c) { - handler->responseProperties.contentLength *= 10; - handler->responseProperties.contentLength += (*c++ - '0'); - } - } - else if (!strncmp(header, "Server", namelen)) { - responseProperties->server = - string_multibuffer_current(handler->responsePropertyStrings); - string_multibuffer_add(handler->responsePropertyStrings, c, - valuelen, fit); - } - else if (!strncmp(header, "ETag", namelen)) { - responseProperties->eTag = - string_multibuffer_current(handler->responsePropertyStrings); - string_multibuffer_add(handler->responsePropertyStrings, c, - valuelen, fit); - } - else if (!strncmp(header, S3_METADATA_HEADER_NAME_PREFIX, - sizeof(S3_METADATA_HEADER_NAME_PREFIX) - 1)) { - // Make sure there is room for another x-amz-meta header - if (handler->responseProperties.metaDataCount == - sizeof(handler->responseMetaData)) { - return; - } - // Copy the name in - char *metaName = &(header[sizeof(S3_METADATA_HEADER_NAME_PREFIX) - 1]); - int metaNameLen = - (namelen - (sizeof(S3_METADATA_HEADER_NAME_PREFIX) - 1)); - char *copiedName = - string_multibuffer_current(handler->responseMetaDataStrings); - string_multibuffer_add(handler->responseMetaDataStrings, metaName, - metaNameLen, fit); - if (!fit) { - return; - } - - // Copy the value in - char *copiedValue = - string_multibuffer_current(handler->responseMetaDataStrings); - string_multibuffer_add(handler->responseMetaDataStrings, - c, valuelen, fit); - if (!fit) { - return; - } - - if (!handler->responseProperties.metaDataCount) { - handler->responseProperties.metaData = - handler->responseMetaData; - } - - S3NameValue *metaHeader = - &(handler->responseMetaData - [handler->responseProperties.metaDataCount++]); - metaHeader->name = copiedName; - metaHeader->value = copiedValue; - } -} - - -void response_headers_handler_done(ResponseHeadersHandler *handler, CURL *curl) -{ - // Now get the last modification time from curl, since it's easiest to let - // curl parse it - time_t lastModified; - if (curl_easy_getinfo - (curl, CURLINFO_FILETIME, &lastModified) == CURLE_OK) { - handler->responseProperties.lastModified = lastModified; - } - - handler->done = 1; -} diff --git a/libs3-1.4/src/s3.c b/libs3-1.4/src/s3.c deleted file mode 100644 index 227b380..0000000 --- a/libs3-1.4/src/s3.c +++ /dev/null @@ -1,2767 +0,0 @@ -/** ************************************************************************** - * s3.c - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -/** - * This is a 'driver' program that simply converts command-line input into - * calls to libs3 functions, and prints the results. - **/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "libs3.h" - -// Some Windows stuff -#ifndef FOPEN_EXTRA_FLAGS -#define FOPEN_EXTRA_FLAGS "" -#endif - -// Also needed for Windows, because somehow MinGW doesn't define this -extern int putenv(char *); - - -// Command-line options, saved as globals ------------------------------------ - -static int forceG = 0; -static int showResponsePropertiesG = 0; -static S3Protocol protocolG = S3ProtocolHTTPS; -static S3UriStyle uriStyleG = S3UriStylePath; -static int retriesG = 5; - - -// Environment variables, saved as globals ---------------------------------- - -static const char *accessKeyIdG = 0; -static const char *secretAccessKeyG = 0; - - -// Request results, saved as globals ----------------------------------------- - -static int statusG = 0; -static char errorDetailsG[4096] = { 0 }; - - -// Other globals ------------------------------------------------------------- - -static char putenvBufG[256]; - - -// Option prefixes ----------------------------------------------------------- - -#define LOCATION_PREFIX "location=" -#define LOCATION_PREFIX_LEN (sizeof(LOCATION_PREFIX) - 1) -#define CANNED_ACL_PREFIX "cannedAcl=" -#define CANNED_ACL_PREFIX_LEN (sizeof(CANNED_ACL_PREFIX) - 1) -#define PREFIX_PREFIX "prefix=" -#define PREFIX_PREFIX_LEN (sizeof(PREFIX_PREFIX) - 1) -#define MARKER_PREFIX "marker=" -#define MARKER_PREFIX_LEN (sizeof(MARKER_PREFIX) - 1) -#define DELIMITER_PREFIX "delimiter=" -#define DELIMITER_PREFIX_LEN (sizeof(DELIMITER_PREFIX) - 1) -#define MAXKEYS_PREFIX "maxkeys=" -#define MAXKEYS_PREFIX_LEN (sizeof(MAXKEYS_PREFIX) - 1) -#define FILENAME_PREFIX "filename=" -#define FILENAME_PREFIX_LEN (sizeof(FILENAME_PREFIX) - 1) -#define CONTENT_LENGTH_PREFIX "contentLength=" -#define CONTENT_LENGTH_PREFIX_LEN (sizeof(CONTENT_LENGTH_PREFIX) - 1) -#define CACHE_CONTROL_PREFIX "cacheControl=" -#define CACHE_CONTROL_PREFIX_LEN (sizeof(CACHE_CONTROL_PREFIX) - 1) -#define CONTENT_TYPE_PREFIX "contentType=" -#define CONTENT_TYPE_PREFIX_LEN (sizeof(CONTENT_TYPE_PREFIX) - 1) -#define MD5_PREFIX "md5=" -#define MD5_PREFIX_LEN (sizeof(MD5_PREFIX) - 1) -#define CONTENT_DISPOSITION_FILENAME_PREFIX "contentDispositionFilename=" -#define CONTENT_DISPOSITION_FILENAME_PREFIX_LEN \ - (sizeof(CONTENT_DISPOSITION_FILENAME_PREFIX) - 1) -#define CONTENT_ENCODING_PREFIX "contentEncoding=" -#define CONTENT_ENCODING_PREFIX_LEN (sizeof(CONTENT_ENCODING_PREFIX) - 1) -#define EXPIRES_PREFIX "expires=" -#define EXPIRES_PREFIX_LEN (sizeof(EXPIRES_PREFIX) - 1) -#define X_AMZ_META_PREFIX "x-amz-meta-" -#define X_AMZ_META_PREFIX_LEN (sizeof(X_AMZ_META_PREFIX) - 1) -#define IF_MODIFIED_SINCE_PREFIX "ifModifiedSince=" -#define IF_MODIFIED_SINCE_PREFIX_LEN (sizeof(IF_MODIFIED_SINCE_PREFIX) - 1) -#define IF_NOT_MODIFIED_SINCE_PREFIX "ifNotmodifiedSince=" -#define IF_NOT_MODIFIED_SINCE_PREFIX_LEN \ - (sizeof(IF_NOT_MODIFIED_SINCE_PREFIX) - 1) -#define IF_MATCH_PREFIX "ifMatch=" -#define IF_MATCH_PREFIX_LEN (sizeof(IF_MATCH_PREFIX) - 1) -#define IF_NOT_MATCH_PREFIX "ifNotMatch=" -#define IF_NOT_MATCH_PREFIX_LEN (sizeof(IF_NOT_MATCH_PREFIX) - 1) -#define START_BYTE_PREFIX "startByte=" -#define START_BYTE_PREFIX_LEN (sizeof(START_BYTE_PREFIX) - 1) -#define BYTE_COUNT_PREFIX "byteCount=" -#define BYTE_COUNT_PREFIX_LEN (sizeof(BYTE_COUNT_PREFIX) - 1) -#define ALL_DETAILS_PREFIX "allDetails=" -#define ALL_DETAILS_PREFIX_LEN (sizeof(ALL_DETAILS_PREFIX) - 1) -#define NO_STATUS_PREFIX "noStatus=" -#define NO_STATUS_PREFIX_LEN (sizeof(NO_STATUS_PREFIX) - 1) -#define RESOURCE_PREFIX "resource=" -#define RESOURCE_PREFIX_LEN (sizeof(RESOURCE_PREFIX) - 1) -#define TARGET_BUCKET_PREFIX "targetBucket=" -#define TARGET_BUCKET_PREFIX_LEN (sizeof(TARGET_BUCKET_PREFIX) - 1) -#define TARGET_PREFIX_PREFIX "targetPrefix=" -#define TARGET_PREFIX_PREFIX_LEN (sizeof(TARGET_PREFIX_PREFIX) - 1) - - -// util ---------------------------------------------------------------------- - -static void S3_init() -{ - S3Status status; - if ((status = S3_initialize("s3", S3_INIT_ALL)) - != S3StatusOK) { - fprintf(stderr, "Failed to initialize libs3: %s\n", - S3_get_status_name(status)); - exit(-1); - } -} - - -static void printError() -{ - if (statusG < S3StatusErrorAccessDenied) { - fprintf(stderr, "\nERROR: %s\n", S3_get_status_name(statusG)); - } - else { - fprintf(stderr, "\nERROR: %s\n", S3_get_status_name(statusG)); - fprintf(stderr, "%s\n", errorDetailsG); - } -} - - -static void usageExit(FILE *out) -{ - fprintf(out, -"\n Options:\n" -"\n" -" Command Line:\n" -"\n" -" -f/--force : force operation despite warnings\n" -" -h/--vhost-style : use virtual-host-style URIs (default is " - "path-style)\n" -" -u/--unencrypted : unencrypted (use HTTP instead of HTTPS)\n" -" -s/--show-properties : show response properties on stdout\n" -" -r/--retries : retry retryable failures this number of times\n" -" (default is 5)\n" -"\n" -" Environment:\n" -"\n" -" S3_ACCESS_KEY_ID : S3 access key ID (required)\n" -" S3_SECRET_ACCESS_KEY : S3 secret access key (required)\n" -"\n" -" Commands (with and [optional parameters]) :\n" -"\n" -" (NOTE: all command parameters take a value and are specified using the\n" -" pattern parameter=value)\n" -"\n" -" help : Prints this help text\n" -"\n" -" list : Lists owned buckets\n" -" [allDetails] : Show full details\n" -"\n" -" test : Tests a bucket for existence and accessibility\n" -" : Bucket to test\n" -"\n" -" create : Create a new bucket\n" -" : Bucket to create\n" -" [cannedAcl] : Canned ACL for the bucket (see Canned ACLs)\n" -" [location] : Location for bucket (for example, EU)\n" -"\n" -" delete : Delete a bucket or key\n" -" [/] : Bucket or bucket/key to delete\n" -"\n" -" list : List bucket contents\n" -" : Bucket to list\n" -" [prefix] : Prefix for results set\n" -" [marker] : Where in results set to start listing\n" -" [delimiter] : Delimiter for rolling up results set\n" -" [maxkeys] : Maximum number of keys to return in results set\n" -" [allDetails] : Show full details for each key\n" -"\n" -" getacl : Get the ACL of a bucket or key\n" -" [/] : Bucket or bucket/key to get the ACL of\n" -" [filename] : Output filename for ACL (default is stdout)\n" -"\n" -" setacl : Set the ACL of a bucket or key\n" -" [/] : Bucket or bucket/key to set the ACL of\n" -" [filename] : Input filename for ACL (default is stdin)\n" -"\n" -" getlogging : Get the logging status of a bucket\n" -" : Bucket to get the logging status of\n" -" [filename] : Output filename for ACL (default is stdout)\n" -"\n" -" setlogging : Set the logging status of a bucket\n" -" : Bucket to set the logging status of\n" -" [targetBucket] : Target bucket to log to; if not present, disables\n" -" logging\n" -" [targetPrefix] : Key prefix to use for logs\n" -" [filename] : Input filename for ACL (default is stdin)\n" -"\n" -" put : Puts an object\n" -" / : Bucket/key to put object to\n" -" [filename] : Filename to read source data from " - "(default is stdin)\n" -" [contentLength] : How many bytes of source data to put (required if\n" -" source file is stdin)\n" -" [cacheControl] : Cache-Control HTTP header string to associate with\n" -" object\n" -" [contentType] : Content-Type HTTP header string to associate with\n" -" object\n" -" [md5] : MD5 for validating source data\n" -" [contentDispositionFilename] : Content-Disposition filename string to\n" -" associate with object\n" -" [contentEncoding] : Content-Encoding HTTP header string to associate\n" -" with object\n" -" [expires] : Expiration date to associate with object\n" -" [cannedAcl] : Canned ACL for the object (see Canned ACLs)\n" -" [x-amz-meta-...]] : Metadata headers to associate with the object\n" -"\n" -" copy : Copies an object; if any options are set, the " - "entire\n" -" metadata of the object is replaced\n" -" / : Source bucket/key\n" -" / : Destination bucket/key\n" -" [cacheControl] : Cache-Control HTTP header string to associate with\n" -" object\n" -" [contentType] : Content-Type HTTP header string to associate with\n" -" object\n" -" [contentDispositionFilename] : Content-Disposition filename string to\n" -" associate with object\n" -" [contentEncoding] : Content-Encoding HTTP header string to associate\n" -" with object\n" -" [expires] : Expiration date to associate with object\n" -" [cannedAcl] : Canned ACL for the object (see Canned ACLs)\n" -" [x-amz-meta-...]] : Metadata headers to associate with the object\n" -"\n" -" get : Gets an object\n" -" / : Bucket/key of object to get\n" -" [filename] : Filename to write object data to (required if -s\n" -" command line parameter was used)\n" -" [ifModifiedSince] : Only return the object if it has been modified " - "since\n" -" this date\n" -" [ifNotmodifiedSince] : Only return the object if it has not been " - "modified\n" -" since this date\n" -" [ifMatch] : Only return the object if its ETag header matches\n" -" this string\n" -" [ifNotMatch] : Only return the object if its ETag header does " - "not\n" -" match this string\n" -" [startByte] : First byte of byte range to return\n" -" [byteCount] : Number of bytes of byte range to return\n" -"\n" -" head : Gets only the headers of an object, implies -s\n" -" / : Bucket/key of object to get headers of\n" -"\n" -" gqs : Generates an authenticated query string\n" -" [/] : Bucket or bucket/key to generate query string for\n" -" [expires] : Expiration date for query string\n" -" [resource] : Sub-resource of key for query string, without a\n" -" leading '?', for example, \"torrent\"\n" -"\n" -" Canned ACLs:\n" -"\n" -" The following canned ACLs are supported:\n" -" private (default), public-read, public-read-write, authenticated-read\n" -"\n" -" ACL Format:\n" -"\n" -" For the getacl and setacl commands, the format of the ACL list is:\n" -" 1) An initial line giving the owner id in this format:\n" -" OwnerID \n" -" 2) Optional header lines, giving column headers, starting with the\n" -" word \"Type\", or with some number of dashes\n" -" 3) Grant lines, of the form:\n" -" (whitespace) (whitespace) \n" -" where Grant Type is one of: Email, UserID, or Group, and\n" -" Grantee is the identification of the grantee based on this type,\n" -" and Permission is one of: READ, WRITE, READ_ACP, or FULL_CONTROL.\n" -"\n" -" Note that the easiest way to modify an ACL is to first get it, saving it\n" -" into a file, then modifying the file, and then setting the modified file\n" -" back as the new ACL for the bucket/object.\n" -"\n" -" Date Format:\n" -"\n" -" The format for dates used in parameters is as ISO 8601 dates, i.e.\n" -" YYYY-MM-DDTHH:MM:SS[.s...][T/+-dd:dd]. Examples:\n" -" 2008-07-29T20:36:14.0023T\n" -" 2008-07-29T20:36:14.0023+06:00\n" -" 2008-07-29T20:36:14.0023-10:00\n" -"\n"); - - exit(-1); -} - - -static uint64_t convertInt(const char *str, const char *paramName) -{ - uint64_t ret = 0; - - while (*str) { - if (!isdigit(*str)) { - fprintf(stderr, "\nERROR: Nondigit in %s parameter: %c\n", - paramName, *str); - usageExit(stderr); - } - ret *= 10; - ret += (*str++ - '0'); - } - - return ret; -} - - -typedef struct growbuffer -{ - // The total number of bytes, and the start byte - int size; - // The start byte - int start; - // The blocks - char data[64 * 1024]; - struct growbuffer *prev, *next; -} growbuffer; - - -// returns nonzero on success, zero on out of memory -static int growbuffer_append(growbuffer **gb, const char *data, int dataLen) -{ - while (dataLen) { - growbuffer *buf = *gb ? (*gb)->prev : 0; - if (!buf || (buf->size == sizeof(buf->data))) { - buf = (growbuffer *) malloc(sizeof(growbuffer)); - if (!buf) { - return 0; - } - buf->size = 0; - buf->start = 0; - if (*gb) { - buf->prev = (*gb)->prev; - buf->next = *gb; - (*gb)->prev->next = buf; - (*gb)->prev = buf; - } - else { - buf->prev = buf->next = buf; - *gb = buf; - } - } - - int toCopy = (sizeof(buf->data) - buf->size); - if (toCopy > dataLen) { - toCopy = dataLen; - } - - memcpy(&(buf->data[buf->size]), data, toCopy); - - buf->size += toCopy, data += toCopy, dataLen -= toCopy; - } - - return 1; -} - - -static void growbuffer_read(growbuffer **gb, int amt, int *amtReturn, - char *buffer) -{ - *amtReturn = 0; - - growbuffer *buf = *gb; - - if (!buf) { - return; - } - - *amtReturn = (buf->size > amt) ? amt : buf->size; - - memcpy(buffer, &(buf->data[buf->start]), *amtReturn); - - buf->start += *amtReturn, buf->size -= *amtReturn; - - if (buf->size == 0) { - if (buf->next == buf) { - *gb = 0; - } - else { - *gb = buf->next; - } - free(buf); - } -} - - -static void growbuffer_destroy(growbuffer *gb) -{ - growbuffer *start = gb; - - while (gb) { - growbuffer *next = gb->next; - free(gb); - gb = (next == start) ? 0 : next; - } -} - - -// Convenience utility for making the code look nicer. Tests a string -// against a format; only the characters specified in the format are -// checked (i.e. if the string is longer than the format, the string still -// checks out ok). Format characters are: -// d - is a digit -// anything else - is that character -// Returns nonzero the string checks out, zero if it does not. -static int checkString(const char *str, const char *format) -{ - while (*format) { - if (*format == 'd') { - if (!isdigit(*str)) { - return 0; - } - } - else if (*str != *format) { - return 0; - } - str++, format++; - } - - return 1; -} - - -static int64_t parseIso8601Time(const char *str) -{ - // Check to make sure that it has a valid format - if (!checkString(str, "dddd-dd-ddTdd:dd:dd")) { - return -1; - } - -#define nextnum() (((*str - '0') * 10) + (*(str + 1) - '0')) - - // Convert it - struct tm stm; - memset(&stm, 0, sizeof(stm)); - - stm.tm_year = (nextnum() - 19) * 100; - str += 2; - stm.tm_year += nextnum(); - str += 3; - - stm.tm_mon = nextnum() - 1; - str += 3; - - stm.tm_mday = nextnum(); - str += 3; - - stm.tm_hour = nextnum(); - str += 3; - - stm.tm_min = nextnum(); - str += 3; - - stm.tm_sec = nextnum(); - str += 2; - - stm.tm_isdst = -1; - - // This is hokey but it's the recommended way ... - char *tz = getenv("TZ"); - snprintf(putenvBufG, sizeof(putenvBufG), "TZ=UTC"); - putenv(putenvBufG); - - int64_t ret = mktime(&stm); - - snprintf(putenvBufG, sizeof(putenvBufG), "TZ=%s", tz ? tz : ""); - putenv(putenvBufG); - - // Skip the millis - - if (*str == '.') { - str++; - while (isdigit(*str)) { - str++; - } - } - - if (checkString(str, "-dd:dd") || checkString(str, "+dd:dd")) { - int sign = (*str++ == '-') ? -1 : 1; - int hours = nextnum(); - str += 3; - int minutes = nextnum(); - ret += (-sign * (((hours * 60) + minutes) * 60)); - } - // Else it should be Z to be a conformant time string, but we just assume - // that it is rather than enforcing that - - return ret; -} - - -// Simple ACL format: Lines of this format: -// Type - ignored -// Starting with a dash - ignored -// Email email_address permission -// UserID user_id (display_name) permission -// Group Authenticated AWS Users permission -// Group All Users permission -// permission is one of READ, WRITE, READ_ACP, WRITE_ACP, FULL_CONTROL -static int convert_simple_acl(char *aclXml, char *ownerId, - char *ownerDisplayName, - int *aclGrantCountReturn, - S3AclGrant *aclGrants) -{ - *aclGrantCountReturn = 0; - *ownerId = 0; - *ownerDisplayName = 0; - -#define SKIP_SPACE(require_more) \ - do { \ - while (isspace(*aclXml)) { \ - aclXml++; \ - } \ - if (require_more && !*aclXml) { \ - return 0; \ - } \ - } while (0) - -#define COPY_STRING_MAXLEN(field, maxlen) \ - do { \ - SKIP_SPACE(1); \ - int len = 0; \ - while ((len < maxlen) && !isspace(*aclXml)) { \ - field[len++] = *aclXml++; \ - } \ - field[len] = 0; \ - } while (0) - -#define COPY_STRING(field) \ - COPY_STRING_MAXLEN(field, (int) (sizeof(field) - 1)) - - while (1) { - SKIP_SPACE(0); - - if (!*aclXml) { - break; - } - - // Skip Type lines and dash lines - if (!strncmp(aclXml, "Type", sizeof("Type") - 1) || - (*aclXml == '-')) { - while (*aclXml && ((*aclXml != '\n') && (*aclXml != '\r'))) { - aclXml++; - } - continue; - } - - if (!strncmp(aclXml, "OwnerID", sizeof("OwnerID") - 1)) { - aclXml += sizeof("OwnerID") - 1; - COPY_STRING_MAXLEN(ownerId, S3_MAX_GRANTEE_USER_ID_SIZE); - SKIP_SPACE(1); - COPY_STRING_MAXLEN(ownerDisplayName, - S3_MAX_GRANTEE_DISPLAY_NAME_SIZE); - continue; - } - - if (*aclGrantCountReturn == S3_MAX_ACL_GRANT_COUNT) { - return 0; - } - - S3AclGrant *grant = &(aclGrants[(*aclGrantCountReturn)++]); - - if (!strncmp(aclXml, "Email", sizeof("Email") - 1)) { - grant->granteeType = S3GranteeTypeAmazonCustomerByEmail; - aclXml += sizeof("Email") - 1; - COPY_STRING(grant->grantee.amazonCustomerByEmail.emailAddress); - } - else if (!strncmp(aclXml, "UserID", sizeof("UserID") - 1)) { - grant->granteeType = S3GranteeTypeCanonicalUser; - aclXml += sizeof("UserID") - 1; - COPY_STRING(grant->grantee.canonicalUser.id); - SKIP_SPACE(1); - // Now do display name - COPY_STRING(grant->grantee.canonicalUser.displayName); - } - else if (!strncmp(aclXml, "Group", sizeof("Group") - 1)) { - aclXml += sizeof("Group") - 1; - SKIP_SPACE(1); - if (!strncmp(aclXml, "Authenticated AWS Users", - sizeof("Authenticated AWS Users") - 1)) { - grant->granteeType = S3GranteeTypeAllAwsUsers; - aclXml += (sizeof("Authenticated AWS Users") - 1); - } - else if (!strncmp(aclXml, "All Users", sizeof("All Users") - 1)) { - grant->granteeType = S3GranteeTypeAllUsers; - aclXml += (sizeof("All Users") - 1); - } - else if (!strncmp(aclXml, "Log Delivery", - sizeof("Log Delivery") - 1)) { - grant->granteeType = S3GranteeTypeLogDelivery; - aclXml += (sizeof("Log Delivery") - 1); - } - else { - return 0; - } - } - else { - return 0; - } - - SKIP_SPACE(1); - - if (!strncmp(aclXml, "READ_ACP", sizeof("READ_ACP") - 1)) { - grant->permission = S3PermissionReadACP; - aclXml += (sizeof("READ_ACP") - 1); - } - else if (!strncmp(aclXml, "READ", sizeof("READ") - 1)) { - grant->permission = S3PermissionRead; - aclXml += (sizeof("READ") - 1); - } - else if (!strncmp(aclXml, "WRITE_ACP", sizeof("WRITE_ACP") - 1)) { - grant->permission = S3PermissionWriteACP; - aclXml += (sizeof("WRITE_ACP") - 1); - } - else if (!strncmp(aclXml, "WRITE", sizeof("WRITE") - 1)) { - grant->permission = S3PermissionWrite; - aclXml += (sizeof("WRITE") - 1); - } - else if (!strncmp(aclXml, "FULL_CONTROL", - sizeof("FULL_CONTROL") - 1)) { - grant->permission = S3PermissionFullControl; - aclXml += (sizeof("FULL_CONTROL") - 1); - } - } - - return 1; -} - - -static int should_retry() -{ - if (retriesG--) { - // Sleep before next retry; start out with a 1 second sleep - static int retrySleepInterval = 1; - sleep(retrySleepInterval); - // Next sleep 1 second longer - retrySleepInterval++; - return 1; - } - - return 0; -} - - -static struct option longOptionsG[] = -{ - { "force", no_argument, 0, 'f' }, - { "vhost-style", no_argument, 0, 'h' }, - { "unencrypted", no_argument, 0, 'u' }, - { "show-properties", no_argument, 0, 's' }, - { "retries", required_argument, 0, 'r' }, - { 0, 0, 0, 0 } -}; - - -// response properties callback ---------------------------------------------- - -// This callback does the same thing for every request type: prints out the -// properties if the user has requested them to be so -static S3Status responsePropertiesCallback - (const S3ResponseProperties *properties, void *callbackData) -{ - (void) callbackData; - - if (!showResponsePropertiesG) { - return S3StatusOK; - } - -#define print_nonnull(name, field) \ - do { \ - if (properties-> field) { \ - printf("%s: %s\n", name, properties-> field); \ - } \ - } while (0) - - print_nonnull("Content-Type", contentType); - print_nonnull("Request-Id", requestId); - print_nonnull("Request-Id-2", requestId2); - if (properties->contentLength > 0) { - printf("Content-Length: %lld\n", - (unsigned long long) properties->contentLength); - } - print_nonnull("Server", server); - print_nonnull("ETag", eTag); - if (properties->lastModified > 0) { - char timebuf[256]; - time_t t = (time_t) properties->lastModified; - // gmtime is not thread-safe but we don't care here. - strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", gmtime(&t)); - printf("Last-Modified: %s\n", timebuf); - } - int i; - for (i = 0; i < properties->metaDataCount; i++) { - printf("x-amz-meta-%s: %s\n", properties->metaData[i].name, - properties->metaData[i].value); - } - - return S3StatusOK; -} - - -// response complete callback ------------------------------------------------ - -// This callback does the same thing for every request type: saves the status -// and error stuff in global variables -static void responseCompleteCallback(S3Status status, - const S3ErrorDetails *error, - void *callbackData) -{ - (void) callbackData; - - statusG = status; - // Compose the error details message now, although we might not use it. - // Can't just save a pointer to [error] since it's not guaranteed to last - // beyond this callback - int len = 0; - if (error && error->message) { - len += snprintf(&(errorDetailsG[len]), sizeof(errorDetailsG) - len, - " Message: %s\n", error->message); - } - if (error && error->resource) { - len += snprintf(&(errorDetailsG[len]), sizeof(errorDetailsG) - len, - " Resource: %s\n", error->resource); - } - if (error && error->furtherDetails) { - len += snprintf(&(errorDetailsG[len]), sizeof(errorDetailsG) - len, - " Further Details: %s\n", error->furtherDetails); - } - if (error && error->extraDetailsCount) { - len += snprintf(&(errorDetailsG[len]), sizeof(errorDetailsG) - len, - "%s", " Extra Details:\n"); - int i; - for (i = 0; i < error->extraDetailsCount; i++) { - len += snprintf(&(errorDetailsG[len]), - sizeof(errorDetailsG) - len, " %s: %s\n", - error->extraDetails[i].name, - error->extraDetails[i].value); - } - } -} - - -// list service -------------------------------------------------------------- - -typedef struct list_service_data -{ - int headerPrinted; - int allDetails; -} list_service_data; - - -static void printListServiceHeader(int allDetails) -{ - printf("%-56s %-20s", " Bucket", - " Created"); - if (allDetails) { - printf(" %-64s %-12s", - " Owner ID", - "Display Name"); - } - printf("\n"); - printf("-------------------------------------------------------- " - "--------------------"); - if (allDetails) { - printf(" -------------------------------------------------" - "--------------- ------------"); - } - printf("\n"); -} - - -static S3Status listServiceCallback(const char *ownerId, - const char *ownerDisplayName, - const char *bucketName, - int64_t creationDate, void *callbackData) -{ - list_service_data *data = (list_service_data *) callbackData; - - if (!data->headerPrinted) { - data->headerPrinted = 1; - printListServiceHeader(data->allDetails); - } - - char timebuf[256]; - if (creationDate >= 0) { - time_t t = (time_t) creationDate; - strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", gmtime(&t)); - } - else { - timebuf[0] = 0; - } - - printf("%-56s %-20s", bucketName, timebuf); - if (data->allDetails) { - printf(" %-64s %-12s", ownerId ? ownerId : "", - ownerDisplayName ? ownerDisplayName : ""); - } - printf("\n"); - - return S3StatusOK; -} - - -static void list_service(int allDetails) -{ - list_service_data data; - - data.headerPrinted = 0; - data.allDetails = allDetails; - - S3_init(); - - S3ListServiceHandler listServiceHandler = - { - { &responsePropertiesCallback, &responseCompleteCallback }, - &listServiceCallback - }; - - do { - S3_list_service(protocolG, accessKeyIdG, secretAccessKeyG, 0, - &listServiceHandler, &data); - } while (S3_status_is_retryable(statusG) && should_retry()); - - if (statusG == S3StatusOK) { - if (!data.headerPrinted) { - printListServiceHeader(allDetails); - } - } - else { - printError(); - } - - S3_deinitialize(); -} - - -// test bucket --------------------------------------------------------------- - -static void test_bucket(int argc, char **argv, int optindex) -{ - // test bucket - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: bucket\n"); - usageExit(stderr); - } - - const char *bucketName = argv[optindex++]; - - if (optindex != argc) { - fprintf(stderr, "\nERROR: Extraneous parameter: %s\n", argv[optindex]); - usageExit(stderr); - } - - S3_init(); - - S3ResponseHandler responseHandler = - { - &responsePropertiesCallback, &responseCompleteCallback - }; - - char locationConstraint[64]; - do { - S3_test_bucket(protocolG, uriStyleG, accessKeyIdG, secretAccessKeyG, - bucketName, sizeof(locationConstraint), - locationConstraint, 0, &responseHandler, 0); - } while (S3_status_is_retryable(statusG) && should_retry()); - - const char *result; - - switch (statusG) { - case S3StatusOK: - // bucket exists - result = locationConstraint[0] ? locationConstraint : "USA"; - break; - case S3StatusErrorNoSuchBucket: - result = "Does Not Exist"; - break; - case S3StatusErrorAccessDenied: - result = "Access Denied"; - break; - default: - result = 0; - break; - } - - if (result) { - printf("%-56s %-20s\n", " Bucket", - " Status"); - printf("-------------------------------------------------------- " - "--------------------\n"); - printf("%-56s %-20s\n", bucketName, result); - } - else { - printError(); - } - - S3_deinitialize(); -} - - -// create bucket ------------------------------------------------------------- - -static void create_bucket(int argc, char **argv, int optindex) -{ - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: bucket\n"); - usageExit(stderr); - } - - const char *bucketName = argv[optindex++]; - - if (!forceG && (S3_validate_bucket_name - (bucketName, S3UriStyleVirtualHost) != S3StatusOK)) { - fprintf(stderr, "\nWARNING: Bucket name is not valid for " - "virtual-host style URI access.\n"); - fprintf(stderr, "Bucket not created. Use -f option to force the " - "bucket to be created despite\n"); - fprintf(stderr, "this warning.\n\n"); - exit(-1); - } - - const char *locationConstraint = 0; - S3CannedAcl cannedAcl = S3CannedAclPrivate; - while (optindex < argc) { - char *param = argv[optindex++]; - if (!strncmp(param, LOCATION_PREFIX, LOCATION_PREFIX_LEN)) { - locationConstraint = &(param[LOCATION_PREFIX_LEN]); - } - else if (!strncmp(param, CANNED_ACL_PREFIX, CANNED_ACL_PREFIX_LEN)) { - char *val = &(param[CANNED_ACL_PREFIX_LEN]); - if (!strcmp(val, "private")) { - cannedAcl = S3CannedAclPrivate; - } - else if (!strcmp(val, "public-read")) { - cannedAcl = S3CannedAclPublicRead; - } - else if (!strcmp(val, "public-read-write")) { - cannedAcl = S3CannedAclPublicReadWrite; - } - else if (!strcmp(val, "authenticated-read")) { - cannedAcl = S3CannedAclAuthenticatedRead; - } - else { - fprintf(stderr, "\nERROR: Unknown canned ACL: %s\n", val); - usageExit(stderr); - } - } - else { - fprintf(stderr, "\nERROR: Unknown param: %s\n", param); - usageExit(stderr); - } - } - - S3_init(); - - S3ResponseHandler responseHandler = - { - &responsePropertiesCallback, &responseCompleteCallback - }; - - do { - S3_create_bucket(protocolG, accessKeyIdG, secretAccessKeyG, - bucketName, cannedAcl, locationConstraint, 0, - &responseHandler, 0); - } while (S3_status_is_retryable(statusG) && should_retry()); - - if (statusG == S3StatusOK) { - printf("Bucket successfully created.\n"); - } - else { - printError(); - } - - S3_deinitialize(); -} - - -// delete bucket ------------------------------------------------------------- - -static void delete_bucket(int argc, char **argv, int optindex) -{ - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: bucket\n"); - usageExit(stderr); - } - - const char *bucketName = argv[optindex++]; - - if (optindex != argc) { - fprintf(stderr, "\nERROR: Extraneous parameter: %s\n", argv[optindex]); - usageExit(stderr); - } - - S3_init(); - - S3ResponseHandler responseHandler = - { - &responsePropertiesCallback, &responseCompleteCallback - }; - - do { - S3_delete_bucket(protocolG, uriStyleG, accessKeyIdG, secretAccessKeyG, - bucketName, 0, &responseHandler, 0); - } while (S3_status_is_retryable(statusG) && should_retry()); - - if (statusG != S3StatusOK) { - printError(); - } - - S3_deinitialize(); -} - - -// list bucket --------------------------------------------------------------- - -typedef struct list_bucket_callback_data -{ - int isTruncated; - char nextMarker[1024]; - int keyCount; - int allDetails; -} list_bucket_callback_data; - - -static void printListBucketHeader(int allDetails) -{ - printf("%-50s %-20s %-5s", - " Key", - " Last Modified", "Size"); - if (allDetails) { - printf(" %-34s %-64s %-12s", - " ETag", - " Owner ID", - "Display Name"); - } - printf("\n"); - printf("-------------------------------------------------- " - "-------------------- -----"); - if (allDetails) { - printf(" ---------------------------------- " - "-------------------------------------------------" - "--------------- ------------"); - } - printf("\n"); -} - - -static S3Status listBucketCallback(int isTruncated, const char *nextMarker, - int contentsCount, - const S3ListBucketContent *contents, - int commonPrefixesCount, - const char **commonPrefixes, - void *callbackData) -{ - list_bucket_callback_data *data = - (list_bucket_callback_data *) callbackData; - - data->isTruncated = isTruncated; - // This is tricky. S3 doesn't return the NextMarker if there is no - // delimiter. Why, I don't know, since it's still useful for paging - // through results. We want NextMarker to be the last content in the - // list, so set it to that if necessary. - if ((!nextMarker || !nextMarker[0]) && contentsCount) { - nextMarker = contents[contentsCount - 1].key; - } - if (nextMarker) { - snprintf(data->nextMarker, sizeof(data->nextMarker), "%s", - nextMarker); - } - else { - data->nextMarker[0] = 0; - } - - if (contentsCount && !data->keyCount) { - printListBucketHeader(data->allDetails); - } - - int i; - for (i = 0; i < contentsCount; i++) { - const S3ListBucketContent *content = &(contents[i]); - char timebuf[256]; - if (0) { - time_t t = (time_t) content->lastModified; - strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", - gmtime(&t)); - printf("\nKey: %s\n", content->key); - printf("Last Modified: %s\n", timebuf); - printf("ETag: %s\n", content->eTag); - printf("Size: %llu\n", (unsigned long long) content->size); - if (content->ownerId) { - printf("Owner ID: %s\n", content->ownerId); - } - if (content->ownerDisplayName) { - printf("Owner Display Name: %s\n", content->ownerDisplayName); - } - } - else { - time_t t = (time_t) content->lastModified; - strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", - gmtime(&t)); - char sizebuf[16]; - if (content->size < 100000) { - sprintf(sizebuf, "%5llu", (unsigned long long) content->size); - } - else if (content->size < (1024 * 1024)) { - sprintf(sizebuf, "%4lluK", - ((unsigned long long) content->size) / 1024ULL); - } - else if (content->size < (10 * 1024 * 1024)) { - float f = content->size; - f /= (1024 * 1024); - sprintf(sizebuf, "%1.2fM", f); - } - else if (content->size < (1024 * 1024 * 1024)) { - sprintf(sizebuf, "%4lluM", - ((unsigned long long) content->size) / - (1024ULL * 1024ULL)); - } - else { - float f = (content->size / 1024); - f /= (1024 * 1024); - sprintf(sizebuf, "%1.2fG", f); - } - printf("%-50s %s %s", content->key, timebuf, sizebuf); - if (data->allDetails) { - printf(" %-34s %-64s %-12s", - content->eTag, - content->ownerId ? content->ownerId : "", - content->ownerDisplayName ? - content->ownerDisplayName : ""); - } - printf("\n"); - } - } - - data->keyCount += contentsCount; - - for (i = 0; i < commonPrefixesCount; i++) { - printf("\nCommon Prefix: %s\n", commonPrefixes[i]); - } - - return S3StatusOK; -} - - -static void list_bucket(const char *bucketName, const char *prefix, - const char *marker, const char *delimiter, - int maxkeys, int allDetails) -{ - S3_init(); - - S3BucketContext bucketContext = - { - bucketName, - protocolG, - uriStyleG, - accessKeyIdG, - secretAccessKeyG - }; - - S3ListBucketHandler listBucketHandler = - { - { &responsePropertiesCallback, &responseCompleteCallback }, - &listBucketCallback - }; - - list_bucket_callback_data data; - - snprintf(data.nextMarker, sizeof(data.nextMarker), "%s", marker); - data.keyCount = 0; - data.allDetails = allDetails; - - do { - data.isTruncated = 0; - do { - S3_list_bucket(&bucketContext, prefix, data.nextMarker, - delimiter, maxkeys, 0, &listBucketHandler, &data); - } while (S3_status_is_retryable(statusG) && should_retry()); - if (statusG != S3StatusOK) { - break; - } - marker = data.nextMarker; - } while (data.isTruncated && (!maxkeys || (data.keyCount < maxkeys))); - - if (statusG == S3StatusOK) { - if (!data.keyCount) { - printListBucketHeader(allDetails); - } - } - else { - printError(); - } - - S3_deinitialize(); -} - - -static void list(int argc, char **argv, int optindex) -{ - if (optindex == argc) { - list_service(0); - return; - } - - const char *bucketName = 0; - - const char *prefix = 0, *marker = 0, *delimiter = 0; - int maxkeys = 0, allDetails = 0; - while (optindex < argc) { - char *param = argv[optindex++]; - if (!strncmp(param, PREFIX_PREFIX, PREFIX_PREFIX_LEN)) { - prefix = &(param[PREFIX_PREFIX_LEN]); - } - else if (!strncmp(param, MARKER_PREFIX, MARKER_PREFIX_LEN)) { - marker = &(param[MARKER_PREFIX_LEN]); - } - else if (!strncmp(param, DELIMITER_PREFIX, DELIMITER_PREFIX_LEN)) { - delimiter = &(param[DELIMITER_PREFIX_LEN]); - } - else if (!strncmp(param, MAXKEYS_PREFIX, MAXKEYS_PREFIX_LEN)) { - maxkeys = convertInt(&(param[MAXKEYS_PREFIX_LEN]), "maxkeys"); - } - else if (!strncmp(param, ALL_DETAILS_PREFIX, - ALL_DETAILS_PREFIX_LEN)) { - const char *ad = &(param[ALL_DETAILS_PREFIX_LEN]); - if (!strcmp(ad, "true") || !strcmp(ad, "TRUE") || - !strcmp(ad, "yes") || !strcmp(ad, "YES") || - !strcmp(ad, "1")) { - allDetails = 1; - } - } - else if (!bucketName) { - bucketName = param; - } - else { - fprintf(stderr, "\nERROR: Unknown param: %s\n", param); - usageExit(stderr); - } - } - - if (bucketName) { - list_bucket(bucketName, prefix, marker, delimiter, maxkeys, - allDetails); - } - else { - list_service(allDetails); - } -} - - - -// delete object ------------------------------------------------------------- - -static void delete_object(int argc, char **argv, int optindex) -{ - (void) argc; - - // Split bucket/key - char *slash = argv[optindex]; - - // We know there is a slash in there, put_object is only called if so - while (*slash && (*slash != '/')) { - slash++; - } - *slash++ = 0; - - const char *bucketName = argv[optindex++]; - const char *key = slash; - - S3_init(); - - S3BucketContext bucketContext = - { - bucketName, - protocolG, - uriStyleG, - accessKeyIdG, - secretAccessKeyG - }; - - S3ResponseHandler responseHandler = - { - 0, - &responseCompleteCallback - }; - - do { - S3_delete_object(&bucketContext, key, 0, &responseHandler, 0); - } while (S3_status_is_retryable(statusG) && should_retry()); - - if ((statusG != S3StatusOK) && - (statusG != S3StatusErrorPreconditionFailed)) { - printError(); - } - - S3_deinitialize(); -} - - -// put object ---------------------------------------------------------------- - -typedef struct put_object_callback_data -{ - FILE *infile; - growbuffer *gb; - uint64_t contentLength, originalContentLength; - int noStatus; -} put_object_callback_data; - - -static int putObjectDataCallback(int bufferSize, char *buffer, - void *callbackData) -{ - put_object_callback_data *data = - (put_object_callback_data *) callbackData; - - int ret = 0; - - if (data->contentLength) { - int toRead = ((data->contentLength > (unsigned) bufferSize) ? - (unsigned) bufferSize : data->contentLength); - if (data->gb) { - growbuffer_read(&(data->gb), toRead, &ret, buffer); - } - else if (data->infile) { - ret = fread(buffer, 1, toRead, data->infile); - } - } - - data->contentLength -= ret; - - if (data->contentLength && !data->noStatus) { - // Avoid a weird bug in MingW, which won't print the second integer - // value properly when it's in the same call, so print separately - printf("%llu bytes remaining ", - (unsigned long long) data->contentLength); - printf("(%d%% complete) ...\n", - (int) (((data->originalContentLength - - data->contentLength) * 100) / - data->originalContentLength)); - } - - return ret; -} - - -static void put_object(int argc, char **argv, int optindex) -{ - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: bucket/key\n"); - usageExit(stderr); - } - - // Split bucket/key - char *slash = argv[optindex]; - while (*slash && (*slash != '/')) { - slash++; - } - if (!*slash || !*(slash + 1)) { - fprintf(stderr, "\nERROR: Invalid bucket/key name: %s\n", - argv[optindex]); - usageExit(stderr); - } - *slash++ = 0; - - const char *bucketName = argv[optindex++]; - const char *key = slash; - - const char *filename = 0; - uint64_t contentLength = 0; - const char *cacheControl = 0, *contentType = 0, *md5 = 0; - const char *contentDispositionFilename = 0, *contentEncoding = 0; - int64_t expires = -1; - S3CannedAcl cannedAcl = S3CannedAclPrivate; - int metaPropertiesCount = 0; - S3NameValue metaProperties[S3_MAX_METADATA_COUNT]; - int noStatus = 0; - - while (optindex < argc) { - char *param = argv[optindex++]; - if (!strncmp(param, FILENAME_PREFIX, FILENAME_PREFIX_LEN)) { - filename = &(param[FILENAME_PREFIX_LEN]); - } - else if (!strncmp(param, CONTENT_LENGTH_PREFIX, - CONTENT_LENGTH_PREFIX_LEN)) { - contentLength = convertInt(&(param[CONTENT_LENGTH_PREFIX_LEN]), - "contentLength"); - if (contentLength > (5LL * 1024 * 1024 * 1024)) { - fprintf(stderr, "\nERROR: contentLength must be no greater " - "than 5 GB\n"); - usageExit(stderr); - } - } - else if (!strncmp(param, CACHE_CONTROL_PREFIX, - CACHE_CONTROL_PREFIX_LEN)) { - cacheControl = &(param[CACHE_CONTROL_PREFIX_LEN]); - } - else if (!strncmp(param, CONTENT_TYPE_PREFIX, - CONTENT_TYPE_PREFIX_LEN)) { - contentType = &(param[CONTENT_TYPE_PREFIX_LEN]); - } - else if (!strncmp(param, MD5_PREFIX, MD5_PREFIX_LEN)) { - md5 = &(param[MD5_PREFIX_LEN]); - } - else if (!strncmp(param, CONTENT_DISPOSITION_FILENAME_PREFIX, - CONTENT_DISPOSITION_FILENAME_PREFIX_LEN)) { - contentDispositionFilename = - &(param[CONTENT_DISPOSITION_FILENAME_PREFIX_LEN]); - } - else if (!strncmp(param, CONTENT_ENCODING_PREFIX, - CONTENT_ENCODING_PREFIX_LEN)) { - contentEncoding = &(param[CONTENT_ENCODING_PREFIX_LEN]); - } - else if (!strncmp(param, EXPIRES_PREFIX, EXPIRES_PREFIX_LEN)) { - expires = parseIso8601Time(&(param[EXPIRES_PREFIX_LEN])); - if (expires < 0) { - fprintf(stderr, "\nERROR: Invalid expires time " - "value; ISO 8601 time format required\n"); - usageExit(stderr); - } - } - else if (!strncmp(param, X_AMZ_META_PREFIX, X_AMZ_META_PREFIX_LEN)) { - if (metaPropertiesCount == S3_MAX_METADATA_COUNT) { - fprintf(stderr, "\nERROR: Too many x-amz-meta- properties, " - "limit %lu: %s\n", - (unsigned long) S3_MAX_METADATA_COUNT, param); - usageExit(stderr); - } - char *name = &(param[X_AMZ_META_PREFIX_LEN]); - char *value = name; - while (*value && (*value != '=')) { - value++; - } - if (!*value || !*(value + 1)) { - fprintf(stderr, "\nERROR: Invalid parameter: %s\n", param); - usageExit(stderr); - } - *value++ = 0; - metaProperties[metaPropertiesCount].name = name; - metaProperties[metaPropertiesCount++].value = value; - } - else if (!strncmp(param, CANNED_ACL_PREFIX, CANNED_ACL_PREFIX_LEN)) { - char *val = &(param[CANNED_ACL_PREFIX_LEN]); - if (!strcmp(val, "private")) { - cannedAcl = S3CannedAclPrivate; - } - else if (!strcmp(val, "public-read")) { - cannedAcl = S3CannedAclPublicRead; - } - else if (!strcmp(val, "public-read-write")) { - cannedAcl = S3CannedAclPublicReadWrite; - } - else if (!strcmp(val, "authenticated-read")) { - cannedAcl = S3CannedAclAuthenticatedRead; - } - else { - fprintf(stderr, "\nERROR: Unknown canned ACL: %s\n", val); - usageExit(stderr); - } - } - else if (!strncmp(param, NO_STATUS_PREFIX, NO_STATUS_PREFIX_LEN)) { - const char *ns = &(param[NO_STATUS_PREFIX_LEN]); - if (!strcmp(ns, "true") || !strcmp(ns, "TRUE") || - !strcmp(ns, "yes") || !strcmp(ns, "YES") || - !strcmp(ns, "1")) { - noStatus = 1; - } - } - else { - fprintf(stderr, "\nERROR: Unknown param: %s\n", param); - usageExit(stderr); - } - } - - put_object_callback_data data; - - data.infile = 0; - data.gb = 0; - data.noStatus = noStatus; - - if (filename) { - if (!contentLength) { - struct stat statbuf; - // Stat the file to get its length - if (stat(filename, &statbuf) == -1) { - fprintf(stderr, "\nERROR: Failed to stat file %s: ", - filename); - perror(0); - exit(-1); - } - contentLength = statbuf.st_size; - } - // Open the file - if (!(data.infile = fopen(filename, "r" FOPEN_EXTRA_FLAGS))) { - fprintf(stderr, "\nERROR: Failed to open input file %s: ", - filename); - perror(0); - exit(-1); - } - } - else { - // Read from stdin. If contentLength is not provided, we have - // to read it all in to get contentLength. - if (!contentLength) { - // Read all if stdin to get the data - char buffer[64 * 1024]; - while (1) { - int amtRead = fread(buffer, 1, sizeof(buffer), stdin); - if (amtRead == 0) { - break; - } - if (!growbuffer_append(&(data.gb), buffer, amtRead)) { - fprintf(stderr, "\nERROR: Out of memory while reading " - "stdin\n"); - exit(-1); - } - contentLength += amtRead; - if (amtRead < (int) sizeof(buffer)) { - break; - } - } - } - else { - data.infile = stdin; - } - } - - data.contentLength = data.originalContentLength = contentLength; - - S3_init(); - - S3BucketContext bucketContext = - { - bucketName, - protocolG, - uriStyleG, - accessKeyIdG, - secretAccessKeyG - }; - - S3PutProperties putProperties = - { - contentType, - md5, - cacheControl, - contentDispositionFilename, - contentEncoding, - expires, - cannedAcl, - metaPropertiesCount, - metaProperties - }; - - S3PutObjectHandler putObjectHandler = - { - { &responsePropertiesCallback, &responseCompleteCallback }, - &putObjectDataCallback - }; - - do { - S3_put_object(&bucketContext, key, contentLength, &putProperties, 0, - &putObjectHandler, &data); - } while (S3_status_is_retryable(statusG) && should_retry()); - - if (data.infile) { - fclose(data.infile); - } - else if (data.gb) { - growbuffer_destroy(data.gb); - } - - if (statusG != S3StatusOK) { - printError(); - } - else if (data.contentLength) { - fprintf(stderr, "\nERROR: Failed to read remaining %llu bytes from " - "input\n", (unsigned long long) data.contentLength); - } - - S3_deinitialize(); -} - - -// copy object --------------------------------------------------------------- - -static void copy_object(int argc, char **argv, int optindex) -{ - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: source bucket/key\n"); - usageExit(stderr); - } - - // Split bucket/key - char *slash = argv[optindex]; - while (*slash && (*slash != '/')) { - slash++; - } - if (!*slash || !*(slash + 1)) { - fprintf(stderr, "\nERROR: Invalid source bucket/key name: %s\n", - argv[optindex]); - usageExit(stderr); - } - *slash++ = 0; - - const char *sourceBucketName = argv[optindex++]; - const char *sourceKey = slash; - - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: " - "destination bucket/key\n"); - usageExit(stderr); - } - - // Split bucket/key - slash = argv[optindex]; - while (*slash && (*slash != '/')) { - slash++; - } - if (!*slash || !*(slash + 1)) { - fprintf(stderr, "\nERROR: Invalid destination bucket/key name: %s\n", - argv[optindex]); - usageExit(stderr); - } - *slash++ = 0; - - const char *destinationBucketName = argv[optindex++]; - const char *destinationKey = slash; - - const char *cacheControl = 0, *contentType = 0; - const char *contentDispositionFilename = 0, *contentEncoding = 0; - int64_t expires = -1; - S3CannedAcl cannedAcl = S3CannedAclPrivate; - int metaPropertiesCount = 0; - S3NameValue metaProperties[S3_MAX_METADATA_COUNT]; - int anyPropertiesSet = 0; - - while (optindex < argc) { - char *param = argv[optindex++]; - if (!strncmp(param, CACHE_CONTROL_PREFIX, - CACHE_CONTROL_PREFIX_LEN)) { - cacheControl = &(param[CACHE_CONTROL_PREFIX_LEN]); - anyPropertiesSet = 1; - } - else if (!strncmp(param, CONTENT_TYPE_PREFIX, - CONTENT_TYPE_PREFIX_LEN)) { - contentType = &(param[CONTENT_TYPE_PREFIX_LEN]); - anyPropertiesSet = 1; - } - else if (!strncmp(param, CONTENT_DISPOSITION_FILENAME_PREFIX, - CONTENT_DISPOSITION_FILENAME_PREFIX_LEN)) { - contentDispositionFilename = - &(param[CONTENT_DISPOSITION_FILENAME_PREFIX_LEN]); - anyPropertiesSet = 1; - } - else if (!strncmp(param, CONTENT_ENCODING_PREFIX, - CONTENT_ENCODING_PREFIX_LEN)) { - contentEncoding = &(param[CONTENT_ENCODING_PREFIX_LEN]); - anyPropertiesSet = 1; - } - else if (!strncmp(param, EXPIRES_PREFIX, EXPIRES_PREFIX_LEN)) { - expires = parseIso8601Time(&(param[EXPIRES_PREFIX_LEN])); - if (expires < 0) { - fprintf(stderr, "\nERROR: Invalid expires time " - "value; ISO 8601 time format required\n"); - usageExit(stderr); - } - anyPropertiesSet = 1; - } - else if (!strncmp(param, X_AMZ_META_PREFIX, X_AMZ_META_PREFIX_LEN)) { - if (metaPropertiesCount == S3_MAX_METADATA_COUNT) { - fprintf(stderr, "\nERROR: Too many x-amz-meta- properties, " - "limit %lu: %s\n", - (unsigned long) S3_MAX_METADATA_COUNT, param); - usageExit(stderr); - } - char *name = &(param[X_AMZ_META_PREFIX_LEN]); - char *value = name; - while (*value && (*value != '=')) { - value++; - } - if (!*value || !*(value + 1)) { - fprintf(stderr, "\nERROR: Invalid parameter: %s\n", param); - usageExit(stderr); - } - *value++ = 0; - metaProperties[metaPropertiesCount].name = name; - metaProperties[metaPropertiesCount++].value = value; - anyPropertiesSet = 1; - } - else if (!strncmp(param, CANNED_ACL_PREFIX, CANNED_ACL_PREFIX_LEN)) { - char *val = &(param[CANNED_ACL_PREFIX_LEN]); - if (!strcmp(val, "private")) { - cannedAcl = S3CannedAclPrivate; - } - else if (!strcmp(val, "public-read")) { - cannedAcl = S3CannedAclPublicRead; - } - else if (!strcmp(val, "public-read-write")) { - cannedAcl = S3CannedAclPublicReadWrite; - } - else if (!strcmp(val, "authenticated-read")) { - cannedAcl = S3CannedAclAuthenticatedRead; - } - else { - fprintf(stderr, "\nERROR: Unknown canned ACL: %s\n", val); - usageExit(stderr); - } - anyPropertiesSet = 1; - } - else { - fprintf(stderr, "\nERROR: Unknown param: %s\n", param); - usageExit(stderr); - } - } - - S3_init(); - - S3BucketContext bucketContext = - { - sourceBucketName, - protocolG, - uriStyleG, - accessKeyIdG, - secretAccessKeyG - }; - - S3PutProperties putProperties = - { - contentType, - 0, - cacheControl, - contentDispositionFilename, - contentEncoding, - expires, - cannedAcl, - metaPropertiesCount, - metaProperties - }; - - S3ResponseHandler responseHandler = - { - &responsePropertiesCallback, - &responseCompleteCallback - }; - - int64_t lastModified; - char eTag[256]; - - do { - S3_copy_object(&bucketContext, sourceKey, destinationBucketName, - destinationKey, anyPropertiesSet ? &putProperties : 0, - &lastModified, sizeof(eTag), eTag, 0, - &responseHandler, 0); - } while (S3_status_is_retryable(statusG) && should_retry()); - - if (statusG == S3StatusOK) { - if (lastModified >= 0) { - char timebuf[256]; - time_t t = (time_t) lastModified; - strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%SZ", - gmtime(&t)); - printf("Last-Modified: %s\n", timebuf); - } - if (eTag[0]) { - printf("ETag: %s\n", eTag); - } - } - else { - printError(); - } - - S3_deinitialize(); -} - - -// get object ---------------------------------------------------------------- - -static S3Status getObjectDataCallback(int bufferSize, const char *buffer, - void *callbackData) -{ - FILE *outfile = (FILE *) callbackData; - - size_t wrote = fwrite(buffer, 1, bufferSize, outfile); - - return ((wrote < (size_t) bufferSize) ? - S3StatusAbortedByCallback : S3StatusOK); -} - - -static void get_object(int argc, char **argv, int optindex) -{ - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: bucket/key\n"); - usageExit(stderr); - } - - // Split bucket/key - char *slash = argv[optindex]; - while (*slash && (*slash != '/')) { - slash++; - } - if (!*slash || !*(slash + 1)) { - fprintf(stderr, "\nERROR: Invalid bucket/key name: %s\n", - argv[optindex]); - usageExit(stderr); - } - *slash++ = 0; - - const char *bucketName = argv[optindex++]; - const char *key = slash; - - const char *filename = 0; - int64_t ifModifiedSince = -1, ifNotModifiedSince = -1; - const char *ifMatch = 0, *ifNotMatch = 0; - uint64_t startByte = 0, byteCount = 0; - - while (optindex < argc) { - char *param = argv[optindex++]; - if (!strncmp(param, FILENAME_PREFIX, FILENAME_PREFIX_LEN)) { - filename = &(param[FILENAME_PREFIX_LEN]); - } - else if (!strncmp(param, IF_MODIFIED_SINCE_PREFIX, - IF_MODIFIED_SINCE_PREFIX_LEN)) { - // Parse ifModifiedSince - ifModifiedSince = parseIso8601Time - (&(param[IF_MODIFIED_SINCE_PREFIX_LEN])); - if (ifModifiedSince < 0) { - fprintf(stderr, "\nERROR: Invalid ifModifiedSince time " - "value; ISO 8601 time format required\n"); - usageExit(stderr); - } - } - else if (!strncmp(param, IF_NOT_MODIFIED_SINCE_PREFIX, - IF_NOT_MODIFIED_SINCE_PREFIX_LEN)) { - // Parse ifModifiedSince - ifNotModifiedSince = parseIso8601Time - (&(param[IF_NOT_MODIFIED_SINCE_PREFIX_LEN])); - if (ifNotModifiedSince < 0) { - fprintf(stderr, "\nERROR: Invalid ifNotModifiedSince time " - "value; ISO 8601 time format required\n"); - usageExit(stderr); - } - } - else if (!strncmp(param, IF_MATCH_PREFIX, IF_MATCH_PREFIX_LEN)) { - ifMatch = &(param[IF_MATCH_PREFIX_LEN]); - } - else if (!strncmp(param, IF_NOT_MATCH_PREFIX, - IF_NOT_MATCH_PREFIX_LEN)) { - ifNotMatch = &(param[IF_NOT_MATCH_PREFIX_LEN]); - } - else if (!strncmp(param, START_BYTE_PREFIX, START_BYTE_PREFIX_LEN)) { - startByte = convertInt - (&(param[START_BYTE_PREFIX_LEN]), "startByte"); - } - else if (!strncmp(param, BYTE_COUNT_PREFIX, BYTE_COUNT_PREFIX_LEN)) { - byteCount = convertInt - (&(param[BYTE_COUNT_PREFIX_LEN]), "byteCount"); - } - else { - fprintf(stderr, "\nERROR: Unknown param: %s\n", param); - usageExit(stderr); - } - } - - FILE *outfile = 0; - - if (filename) { - // Stat the file, and if it doesn't exist, open it in w mode - struct stat buf; - if (stat(filename, &buf) == -1) { - outfile = fopen(filename, "w" FOPEN_EXTRA_FLAGS); - } - else { - // Open in r+ so that we don't truncate the file, just in case - // there is an error and we write no bytes, we leave the file - // unmodified - outfile = fopen(filename, "r+" FOPEN_EXTRA_FLAGS); - } - - if (!outfile) { - fprintf(stderr, "\nERROR: Failed to open output file %s: ", - filename); - perror(0); - exit(-1); - } - } - else if (showResponsePropertiesG) { - fprintf(stderr, "\nERROR: get -s requires a filename parameter\n"); - usageExit(stderr); - } - else { - outfile = stdout; - } - - S3_init(); - - S3BucketContext bucketContext = - { - bucketName, - protocolG, - uriStyleG, - accessKeyIdG, - secretAccessKeyG - }; - - S3GetConditions getConditions = - { - ifModifiedSince, - ifNotModifiedSince, - ifMatch, - ifNotMatch - }; - - S3GetObjectHandler getObjectHandler = - { - { &responsePropertiesCallback, &responseCompleteCallback }, - &getObjectDataCallback - }; - - do { - S3_get_object(&bucketContext, key, &getConditions, startByte, - byteCount, 0, &getObjectHandler, outfile); - } while (S3_status_is_retryable(statusG) && should_retry()); - - if (statusG != S3StatusOK) { - printError(); - } - - fclose(outfile); - - S3_deinitialize(); -} - - -// head object --------------------------------------------------------------- - -static void head_object(int argc, char **argv, int optindex) -{ - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: bucket/key\n"); - usageExit(stderr); - } - - // Head implies showing response properties - showResponsePropertiesG = 1; - - // Split bucket/key - char *slash = argv[optindex]; - - while (*slash && (*slash != '/')) { - slash++; - } - if (!*slash || !*(slash + 1)) { - fprintf(stderr, "\nERROR: Invalid bucket/key name: %s\n", - argv[optindex]); - usageExit(stderr); - } - *slash++ = 0; - - const char *bucketName = argv[optindex++]; - const char *key = slash; - - if (optindex != argc) { - fprintf(stderr, "\nERROR: Extraneous parameter: %s\n", argv[optindex]); - usageExit(stderr); - } - - S3_init(); - - S3BucketContext bucketContext = - { - bucketName, - protocolG, - uriStyleG, - accessKeyIdG, - secretAccessKeyG - }; - - S3ResponseHandler responseHandler = - { - &responsePropertiesCallback, - &responseCompleteCallback - }; - - do { - S3_head_object(&bucketContext, key, 0, &responseHandler, 0); - } while (S3_status_is_retryable(statusG) && should_retry()); - - if ((statusG != S3StatusOK) && - (statusG != S3StatusErrorPreconditionFailed)) { - printError(); - } - - S3_deinitialize(); -} - - -// generate query string ------------------------------------------------------ - -static void generate_query_string(int argc, char **argv, int optindex) -{ - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: bucket[/key]\n"); - usageExit(stderr); - } - - const char *bucketName = argv[optindex]; - const char *key = 0; - - // Split bucket/key - char *slash = argv[optindex++]; - while (*slash && (*slash != '/')) { - slash++; - } - if (*slash) { - *slash++ = 0; - key = slash; - } - else { - key = 0; - } - - int64_t expires = -1; - - const char *resource = 0; - - while (optindex < argc) { - char *param = argv[optindex++]; - if (!strncmp(param, EXPIRES_PREFIX, EXPIRES_PREFIX_LEN)) { - expires = parseIso8601Time(&(param[EXPIRES_PREFIX_LEN])); - if (expires < 0) { - fprintf(stderr, "\nERROR: Invalid expires time " - "value; ISO 8601 time format required\n"); - usageExit(stderr); - } - } - else if (!strncmp(param, RESOURCE_PREFIX, RESOURCE_PREFIX_LEN)) { - resource = &(param[RESOURCE_PREFIX_LEN]); - } - else { - fprintf(stderr, "\nERROR: Unknown param: %s\n", param); - usageExit(stderr); - } - } - - S3_init(); - - S3BucketContext bucketContext = - { - bucketName, - protocolG, - uriStyleG, - accessKeyIdG, - secretAccessKeyG - }; - - char buffer[S3_MAX_AUTHENTICATED_QUERY_STRING_SIZE]; - - S3Status status = S3_generate_authenticated_query_string - (buffer, &bucketContext, key, expires, resource); - - if (status != S3StatusOK) { - printf("Failed to generate authenticated query string: %s\n", - S3_get_status_name(status)); - } - else { - printf("%s\n", buffer); - } - - S3_deinitialize(); -} - - -// get acl ------------------------------------------------------------------- - -void get_acl(int argc, char **argv, int optindex) -{ - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: bucket[/key]\n"); - usageExit(stderr); - } - - const char *bucketName = argv[optindex]; - const char *key = 0; - - // Split bucket/key - char *slash = argv[optindex++]; - while (*slash && (*slash != '/')) { - slash++; - } - if (*slash) { - *slash++ = 0; - key = slash; - } - else { - key = 0; - } - - const char *filename = 0; - - while (optindex < argc) { - char *param = argv[optindex++]; - if (!strncmp(param, FILENAME_PREFIX, FILENAME_PREFIX_LEN)) { - filename = &(param[FILENAME_PREFIX_LEN]); - } - else { - fprintf(stderr, "\nERROR: Unknown param: %s\n", param); - usageExit(stderr); - } - } - - FILE *outfile = 0; - - if (filename) { - // Stat the file, and if it doesn't exist, open it in w mode - struct stat buf; - if (stat(filename, &buf) == -1) { - outfile = fopen(filename, "w" FOPEN_EXTRA_FLAGS); - } - else { - // Open in r+ so that we don't truncate the file, just in case - // there is an error and we write no bytes, we leave the file - // unmodified - outfile = fopen(filename, "r+" FOPEN_EXTRA_FLAGS); - } - - if (!outfile) { - fprintf(stderr, "\nERROR: Failed to open output file %s: ", - filename); - perror(0); - exit(-1); - } - } - else if (showResponsePropertiesG) { - fprintf(stderr, "\nERROR: getacl -s requires a filename parameter\n"); - usageExit(stderr); - } - else { - outfile = stdout; - } - - int aclGrantCount; - S3AclGrant aclGrants[S3_MAX_ACL_GRANT_COUNT]; - char ownerId[S3_MAX_GRANTEE_USER_ID_SIZE]; - char ownerDisplayName[S3_MAX_GRANTEE_DISPLAY_NAME_SIZE]; - - S3_init(); - - S3BucketContext bucketContext = - { - bucketName, - protocolG, - uriStyleG, - accessKeyIdG, - secretAccessKeyG - }; - - S3ResponseHandler responseHandler = - { - &responsePropertiesCallback, - &responseCompleteCallback - }; - - do { - S3_get_acl(&bucketContext, key, ownerId, ownerDisplayName, - &aclGrantCount, aclGrants, 0, &responseHandler, 0); - } while (S3_status_is_retryable(statusG) && should_retry()); - - if (statusG == S3StatusOK) { - fprintf(outfile, "OwnerID %s %s\n", ownerId, ownerDisplayName); - fprintf(outfile, "%-6s %-90s %-12s\n", " Type", - " User Identifier", - " Permission"); - fprintf(outfile, "------ " - "------------------------------------------------------------" - "------------------------------ ------------\n"); - int i; - for (i = 0; i < aclGrantCount; i++) { - S3AclGrant *grant = &(aclGrants[i]); - const char *type; - char composedId[S3_MAX_GRANTEE_USER_ID_SIZE + - S3_MAX_GRANTEE_DISPLAY_NAME_SIZE + 16]; - const char *id; - - switch (grant->granteeType) { - case S3GranteeTypeAmazonCustomerByEmail: - type = "Email"; - id = grant->grantee.amazonCustomerByEmail.emailAddress; - break; - case S3GranteeTypeCanonicalUser: - type = "UserID"; - snprintf(composedId, sizeof(composedId), - "%s (%s)", grant->grantee.canonicalUser.id, - grant->grantee.canonicalUser.displayName); - id = composedId; - break; - case S3GranteeTypeAllAwsUsers: - type = "Group"; - id = "Authenticated AWS Users"; - break; - case S3GranteeTypeAllUsers: - type = "Group"; - id = "All Users"; - break; - default: - type = "Group"; - id = "Log Delivery"; - break; - } - const char *perm; - switch (grant->permission) { - case S3PermissionRead: - perm = "READ"; - break; - case S3PermissionWrite: - perm = "WRITE"; - break; - case S3PermissionReadACP: - perm = "READ_ACP"; - break; - case S3PermissionWriteACP: - perm = "WRITE_ACP"; - break; - default: - perm = "FULL_CONTROL"; - break; - } - fprintf(outfile, "%-6s %-90s %-12s\n", type, id, perm); - } - } - else { - printError(); - } - - fclose(outfile); - - S3_deinitialize(); -} - - -// set acl ------------------------------------------------------------------- - -void set_acl(int argc, char **argv, int optindex) -{ - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: bucket[/key]\n"); - usageExit(stderr); - } - - const char *bucketName = argv[optindex]; - const char *key = 0; - - // Split bucket/key - char *slash = argv[optindex++]; - while (*slash && (*slash != '/')) { - slash++; - } - if (*slash) { - *slash++ = 0; - key = slash; - } - else { - key = 0; - } - - const char *filename = 0; - - while (optindex < argc) { - char *param = argv[optindex++]; - if (!strncmp(param, FILENAME_PREFIX, FILENAME_PREFIX_LEN)) { - filename = &(param[FILENAME_PREFIX_LEN]); - } - else { - fprintf(stderr, "\nERROR: Unknown param: %s\n", param); - usageExit(stderr); - } - } - - FILE *infile; - - if (filename) { - if (!(infile = fopen(filename, "r" FOPEN_EXTRA_FLAGS))) { - fprintf(stderr, "\nERROR: Failed to open input file %s: ", - filename); - perror(0); - exit(-1); - } - } - else { - infile = stdin; - } - - // Read in the complete ACL - char aclBuf[65536]; - aclBuf[fread(aclBuf, 1, sizeof(aclBuf), infile)] = 0; - char ownerId[S3_MAX_GRANTEE_USER_ID_SIZE]; - char ownerDisplayName[S3_MAX_GRANTEE_DISPLAY_NAME_SIZE]; - - // Parse it - int aclGrantCount; - S3AclGrant aclGrants[S3_MAX_ACL_GRANT_COUNT]; - if (!convert_simple_acl(aclBuf, ownerId, ownerDisplayName, - &aclGrantCount, aclGrants)) { - fprintf(stderr, "\nERROR: Failed to parse ACLs\n"); - fclose(infile); - exit(-1); - } - - S3_init(); - - S3BucketContext bucketContext = - { - bucketName, - protocolG, - uriStyleG, - accessKeyIdG, - secretAccessKeyG - }; - - S3ResponseHandler responseHandler = - { - &responsePropertiesCallback, - &responseCompleteCallback - }; - - do { - S3_set_acl(&bucketContext, key, ownerId, ownerDisplayName, - aclGrantCount, aclGrants, 0, &responseHandler, 0); - } while (S3_status_is_retryable(statusG) && should_retry()); - - if (statusG != S3StatusOK) { - printError(); - } - - fclose(infile); - - S3_deinitialize(); -} - - -// get logging ---------------------------------------------------------------- - -void get_logging(int argc, char **argv, int optindex) -{ - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: bucket\n"); - usageExit(stderr); - } - - const char *bucketName = argv[optindex++]; - const char *filename = 0; - - while (optindex < argc) { - char *param = argv[optindex++]; - if (!strncmp(param, FILENAME_PREFIX, FILENAME_PREFIX_LEN)) { - filename = &(param[FILENAME_PREFIX_LEN]); - } - else { - fprintf(stderr, "\nERROR: Unknown param: %s\n", param); - usageExit(stderr); - } - } - - FILE *outfile = 0; - - if (filename) { - // Stat the file, and if it doesn't exist, open it in w mode - struct stat buf; - if (stat(filename, &buf) == -1) { - outfile = fopen(filename, "w" FOPEN_EXTRA_FLAGS); - } - else { - // Open in r+ so that we don't truncate the file, just in case - // there is an error and we write no bytes, we leave the file - // unmodified - outfile = fopen(filename, "r+" FOPEN_EXTRA_FLAGS); - } - - if (!outfile) { - fprintf(stderr, "\nERROR: Failed to open output file %s: ", - filename); - perror(0); - exit(-1); - } - } - else if (showResponsePropertiesG) { - fprintf(stderr, "\nERROR: getlogging -s requires a filename " - "parameter\n"); - usageExit(stderr); - } - else { - outfile = stdout; - } - - int aclGrantCount; - S3AclGrant aclGrants[S3_MAX_ACL_GRANT_COUNT]; - char targetBucket[S3_MAX_BUCKET_NAME_SIZE]; - char targetPrefix[S3_MAX_KEY_SIZE]; - - S3_init(); - - S3BucketContext bucketContext = - { - bucketName, - protocolG, - uriStyleG, - accessKeyIdG, - secretAccessKeyG - }; - - S3ResponseHandler responseHandler = - { - &responsePropertiesCallback, - &responseCompleteCallback - }; - - do { - S3_get_server_access_logging(&bucketContext, targetBucket, targetPrefix, - &aclGrantCount, aclGrants, 0, - &responseHandler, 0); - } while (S3_status_is_retryable(statusG) && should_retry()); - - if (statusG == S3StatusOK) { - if (targetBucket[0]) { - printf("Target Bucket: %s\n", targetBucket); - if (targetPrefix[0]) { - printf("Target Prefix: %s\n", targetPrefix); - } - fprintf(outfile, "%-6s %-90s %-12s\n", " Type", - " User Identifier", - " Permission"); - fprintf(outfile, "------ " - "---------------------------------------------------------" - "--------------------------------- ------------\n"); - int i; - for (i = 0; i < aclGrantCount; i++) { - S3AclGrant *grant = &(aclGrants[i]); - const char *type; - char composedId[S3_MAX_GRANTEE_USER_ID_SIZE + - S3_MAX_GRANTEE_DISPLAY_NAME_SIZE + 16]; - const char *id; - - switch (grant->granteeType) { - case S3GranteeTypeAmazonCustomerByEmail: - type = "Email"; - id = grant->grantee.amazonCustomerByEmail.emailAddress; - break; - case S3GranteeTypeCanonicalUser: - type = "UserID"; - snprintf(composedId, sizeof(composedId), - "%s (%s)", grant->grantee.canonicalUser.id, - grant->grantee.canonicalUser.displayName); - id = composedId; - break; - case S3GranteeTypeAllAwsUsers: - type = "Group"; - id = "Authenticated AWS Users"; - break; - default: - type = "Group"; - id = "All Users"; - break; - } - const char *perm; - switch (grant->permission) { - case S3PermissionRead: - perm = "READ"; - break; - case S3PermissionWrite: - perm = "WRITE"; - break; - case S3PermissionReadACP: - perm = "READ_ACP"; - break; - case S3PermissionWriteACP: - perm = "WRITE_ACP"; - break; - default: - perm = "FULL_CONTROL"; - break; - } - fprintf(outfile, "%-6s %-90s %-12s\n", type, id, perm); - } - } - else { - printf("Service logging is not enabled for this bucket.\n"); - } - } - else { - printError(); - } - - fclose(outfile); - - S3_deinitialize(); -} - - -// set logging ---------------------------------------------------------------- - -void set_logging(int argc, char **argv, int optindex) -{ - if (optindex == argc) { - fprintf(stderr, "\nERROR: Missing parameter: bucket\n"); - usageExit(stderr); - } - - const char *bucketName = argv[optindex++]; - - const char *targetBucket = 0, *targetPrefix = 0, *filename = 0; - - while (optindex < argc) { - char *param = argv[optindex++]; - if (!strncmp(param, TARGET_BUCKET_PREFIX, TARGET_BUCKET_PREFIX_LEN)) { - targetBucket = &(param[TARGET_BUCKET_PREFIX_LEN]); - } - else if (!strncmp(param, TARGET_PREFIX_PREFIX, - TARGET_PREFIX_PREFIX_LEN)) { - targetPrefix = &(param[TARGET_PREFIX_PREFIX_LEN]); - } - else if (!strncmp(param, FILENAME_PREFIX, FILENAME_PREFIX_LEN)) { - filename = &(param[FILENAME_PREFIX_LEN]); - } - else { - fprintf(stderr, "\nERROR: Unknown param: %s\n", param); - usageExit(stderr); - } - } - - int aclGrantCount = 0; - S3AclGrant aclGrants[S3_MAX_ACL_GRANT_COUNT]; - - if (targetBucket) { - FILE *infile; - - if (filename) { - if (!(infile = fopen(filename, "r" FOPEN_EXTRA_FLAGS))) { - fprintf(stderr, "\nERROR: Failed to open input file %s: ", - filename); - perror(0); - exit(-1); - } - } - else { - infile = stdin; - } - - // Read in the complete ACL - char aclBuf[65536]; - aclBuf[fread(aclBuf, 1, sizeof(aclBuf), infile)] = 0; - char ownerId[S3_MAX_GRANTEE_USER_ID_SIZE]; - char ownerDisplayName[S3_MAX_GRANTEE_DISPLAY_NAME_SIZE]; - - // Parse it - if (!convert_simple_acl(aclBuf, ownerId, ownerDisplayName, - &aclGrantCount, aclGrants)) { - fprintf(stderr, "\nERROR: Failed to parse ACLs\n"); - fclose(infile); - exit(-1); - } - - fclose(infile); - } - - S3_init(); - - S3BucketContext bucketContext = - { - bucketName, - protocolG, - uriStyleG, - accessKeyIdG, - secretAccessKeyG - }; - - S3ResponseHandler responseHandler = - { - &responsePropertiesCallback, - &responseCompleteCallback - }; - - do { - S3_set_server_access_logging(&bucketContext, targetBucket, - targetPrefix, aclGrantCount, aclGrants, - 0, &responseHandler, 0); - } while (S3_status_is_retryable(statusG) && should_retry()); - - if (statusG != S3StatusOK) { - printError(); - } - - S3_deinitialize(); -} - - -// main ---------------------------------------------------------------------- - -int main(int argc, char **argv) -{ - // Parse args - while (1) { - int idx = 0; - int c = getopt_long(argc, argv, "fhusr:", longOptionsG, &idx); - - if (c == -1) { - // End of options - break; - } - - switch (c) { - case 'f': - forceG = 1; - break; - case 'h': - uriStyleG = S3UriStyleVirtualHost; - break; - case 'u': - protocolG = S3ProtocolHTTP; - break; - case 's': - showResponsePropertiesG = 1; - break; - case 'r': { - const char *v = optarg; - while (*v) { - retriesG *= 10; - retriesG += *v - '0'; - v++; - } - break; - } - default: - fprintf(stderr, "\nERROR: Unknown option: -%c\n", c); - // Usage exit - usageExit(stderr); - } - } - - // The first non-option argument gives the operation to perform - if (optind == argc) { - fprintf(stderr, "\n\nERROR: Missing argument: command\n\n"); - usageExit(stderr); - } - - const char *command = argv[optind++]; - - if (!strcmp(command, "help")) { - fprintf(stdout, "\ns3 is a program for performing single requests " - "to Amazon S3.\n"); - usageExit(stdout); - } - - accessKeyIdG = getenv("S3_ACCESS_KEY_ID"); - if (!accessKeyIdG) { - fprintf(stderr, "Missing environment variable: S3_ACCESS_KEY_ID\n"); - return -1; - } - secretAccessKeyG = getenv("S3_SECRET_ACCESS_KEY"); - if (!secretAccessKeyG) { - fprintf(stderr, - "Missing environment variable: S3_SECRET_ACCESS_KEY\n"); - return -1; - } - - if (!strcmp(command, "list")) { - list(argc, argv, optind); - } - else if (!strcmp(command, "test")) { - test_bucket(argc, argv, optind); - } - else if (!strcmp(command, "create")) { - create_bucket(argc, argv, optind); - } - else if (!strcmp(command, "delete")) { - if (optind == argc) { - fprintf(stderr, - "\nERROR: Missing parameter: bucket or bucket/key\n"); - usageExit(stderr); - } - char *val = argv[optind]; - int hasSlash = 0; - while (*val) { - if (*val++ == '/') { - hasSlash = 1; - break; - } - } - if (hasSlash) { - delete_object(argc, argv, optind); - } - else { - delete_bucket(argc, argv, optind); - } - } - else if (!strcmp(command, "put")) { - put_object(argc, argv, optind); - } - else if (!strcmp(command, "copy")) { - copy_object(argc, argv, optind); - } - else if (!strcmp(command, "get")) { - get_object(argc, argv, optind); - } - else if (!strcmp(command, "head")) { - head_object(argc, argv, optind); - } - else if (!strcmp(command, "gqs")) { - generate_query_string(argc, argv, optind); - } - else if (!strcmp(command, "getacl")) { - get_acl(argc, argv, optind); - } - else if (!strcmp(command, "setacl")) { - set_acl(argc, argv, optind); - } - else if (!strcmp(command, "getlogging")) { - get_logging(argc, argv, optind); - } - else if (!strcmp(command, "setlogging")) { - set_logging(argc, argv, optind); - } - else { - fprintf(stderr, "Unknown command: %s\n", command); - return -1; - } - - return 0; -} diff --git a/libs3-1.4/src/service.c b/libs3-1.4/src/service.c deleted file mode 100644 index 216b981..0000000 --- a/libs3-1.4/src/service.c +++ /dev/null @@ -1,187 +0,0 @@ -/** ************************************************************************** - * service.c - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -#include -#include -#include -#include -#include "request.h" - - -typedef struct XmlCallbackData -{ - SimpleXml simpleXml; - - S3ResponsePropertiesCallback *responsePropertiesCallback; - S3ListServiceCallback *listServiceCallback; - S3ResponseCompleteCallback *responseCompleteCallback; - void *callbackData; - - string_buffer(ownerId, 256); - string_buffer(ownerDisplayName, 256); - string_buffer(bucketName, 256); - string_buffer(creationDate, 128); -} XmlCallbackData; - - -static S3Status xmlCallback(const char *elementPath, const char *data, - int dataLen, void *callbackData) -{ - XmlCallbackData *cbData = (XmlCallbackData *) callbackData; - - int fit; - - if (data) { - if (!strcmp(elementPath, "ListAllMyBucketsResult/Owner/ID")) { - string_buffer_append(cbData->ownerId, data, dataLen, fit); - } - else if (!strcmp(elementPath, - "ListAllMyBucketsResult/Owner/DisplayName")) { - string_buffer_append(cbData->ownerDisplayName, data, dataLen, fit); - } - else if (!strcmp(elementPath, - "ListAllMyBucketsResult/Buckets/Bucket/Name")) { - string_buffer_append(cbData->bucketName, data, dataLen, fit); - } - else if (!strcmp - (elementPath, - "ListAllMyBucketsResult/Buckets/Bucket/CreationDate")) { - string_buffer_append(cbData->creationDate, data, dataLen, fit); - } - } - else { - if (!strcmp(elementPath, "ListAllMyBucketsResult/Buckets/Bucket")) { - // Parse date. Assume ISO-8601 date format. - time_t creationDate = parseIso8601Time(cbData->creationDate); - - // Make the callback - a bucket just finished - S3Status status = (*(cbData->listServiceCallback)) - (cbData->ownerId, cbData->ownerDisplayName, - cbData->bucketName, creationDate, cbData->callbackData); - - string_buffer_initialize(cbData->bucketName); - string_buffer_initialize(cbData->creationDate); - - return status; - } - } - - return S3StatusOK; -} - - -static S3Status propertiesCallback - (const S3ResponseProperties *responseProperties, void *callbackData) -{ - XmlCallbackData *cbData = (XmlCallbackData *) callbackData; - - return (*(cbData->responsePropertiesCallback)) - (responseProperties, cbData->callbackData); -} - - -static S3Status dataCallback(int bufferSize, const char *buffer, - void *callbackData) -{ - XmlCallbackData *cbData = (XmlCallbackData *) callbackData; - - return simplexml_add(&(cbData->simpleXml), buffer, bufferSize); -} - - -static void completeCallback(S3Status requestStatus, - const S3ErrorDetails *s3ErrorDetails, - void *callbackData) -{ - XmlCallbackData *cbData = (XmlCallbackData *) callbackData; - - (*(cbData->responseCompleteCallback)) - (requestStatus, s3ErrorDetails, cbData->callbackData); - - simplexml_deinitialize(&(cbData->simpleXml)); - - free(cbData); -} - - -void S3_list_service(S3Protocol protocol, const char *accessKeyId, - const char *secretAccessKey, - S3RequestContext *requestContext, - const S3ListServiceHandler *handler, void *callbackData) -{ - // Create and set up the callback data - XmlCallbackData *data = - (XmlCallbackData *) malloc(sizeof(XmlCallbackData)); - if (!data) { - (*(handler->responseHandler.completeCallback)) - (S3StatusOutOfMemory, 0, callbackData); - return; - } - - simplexml_initialize(&(data->simpleXml), &xmlCallback, data); - - data->responsePropertiesCallback = - handler->responseHandler.propertiesCallback; - data->listServiceCallback = handler->listServiceCallback; - data->responseCompleteCallback = handler->responseHandler.completeCallback; - data->callbackData = callbackData; - - string_buffer_initialize(data->ownerId); - string_buffer_initialize(data->ownerDisplayName); - string_buffer_initialize(data->bucketName); - string_buffer_initialize(data->creationDate); - - // Set up the RequestParams - RequestParams params = - { - HttpRequestTypeGET, // httpRequestType - { 0, // bucketName - protocol, // protocol - S3UriStylePath, // uriStyle - accessKeyId, // accessKeyId - secretAccessKey }, // secretAccessKey - 0, // key - 0, // queryParams - 0, // subResource - 0, // copySourceBucketName - 0, // copySourceKey - 0, // getConditions - 0, // startByte - 0, // byteCount - 0, // requestProperties - &propertiesCallback, // propertiesCallback - 0, // toS3Callback - 0, // toS3CallbackTotalSize - &dataCallback, // fromS3Callback - &completeCallback, // completeCallback - data // callbackData - }; - - // Perform the request - request_perform(¶ms, requestContext); -} - - diff --git a/libs3-1.4/src/service_access_logging.c b/libs3-1.4/src/service_access_logging.c deleted file mode 100644 index cbed2c1..0000000 --- a/libs3-1.4/src/service_access_logging.c +++ /dev/null @@ -1,556 +0,0 @@ -/** ************************************************************************** - * server_access_logging.c - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -#include -#include -#include "libs3.h" -#include "request.h" - - -// get server access logging--------------------------------------------------- - -typedef struct ConvertBlsData -{ - char *targetBucketReturn; - int targetBucketReturnLen; - char *targetPrefixReturn; - int targetPrefixReturnLen; - int *aclGrantCountReturn; - S3AclGrant *aclGrants; - - string_buffer(emailAddress, S3_MAX_GRANTEE_EMAIL_ADDRESS_SIZE); - string_buffer(userId, S3_MAX_GRANTEE_USER_ID_SIZE); - string_buffer(userDisplayName, S3_MAX_GRANTEE_DISPLAY_NAME_SIZE); - string_buffer(groupUri, 128); - string_buffer(permission, 32); -} ConvertBlsData; - - -static S3Status convertBlsXmlCallback(const char *elementPath, - const char *data, int dataLen, - void *callbackData) -{ - ConvertBlsData *caData = (ConvertBlsData *) callbackData; - - int fit; - - if (data) { - if (!strcmp(elementPath, "BucketLoggingStatus/LoggingEnabled/" - "TargetBucket")) { - caData->targetBucketReturnLen += - snprintf(&(caData->targetBucketReturn - [caData->targetBucketReturnLen]), - 255 - caData->targetBucketReturnLen - 1, - "%.*s", dataLen, data); - if (caData->targetBucketReturnLen >= 255) { - return S3StatusTargetBucketTooLong; - } - } - else if (!strcmp(elementPath, "BucketLoggingStatus/LoggingEnabled/" - "TargetPrefix")) { - caData->targetPrefixReturnLen += - snprintf(&(caData->targetPrefixReturn - [caData->targetPrefixReturnLen]), - 255 - caData->targetPrefixReturnLen - 1, - "%.*s", dataLen, data); - if (caData->targetPrefixReturnLen >= 255) { - return S3StatusTargetPrefixTooLong; - } - } - else if (!strcmp(elementPath, "BucketLoggingStatus/LoggingEnabled/" - "TargetGrants/Grant/Grantee/EmailAddress")) { - // AmazonCustomerByEmail - string_buffer_append(caData->emailAddress, data, dataLen, fit); - if (!fit) { - return S3StatusEmailAddressTooLong; - } - } - else if (!strcmp(elementPath, - "AccessControlPolicy/AccessControlList/Grant/" - "Grantee/ID")) { - // CanonicalUser - string_buffer_append(caData->userId, data, dataLen, fit); - if (!fit) { - return S3StatusUserIdTooLong; - } - } - else if (!strcmp(elementPath, "BucketLoggingStatus/LoggingEnabled/" - "TargetGrants/Grant/Grantee/DisplayName")) { - // CanonicalUser - string_buffer_append(caData->userDisplayName, data, dataLen, fit); - if (!fit) { - return S3StatusUserDisplayNameTooLong; - } - } - else if (!strcmp(elementPath, "BucketLoggingStatus/LoggingEnabled/" - "TargetGrants/Grant/Grantee/URI")) { - // Group - string_buffer_append(caData->groupUri, data, dataLen, fit); - if (!fit) { - return S3StatusGroupUriTooLong; - } - } - else if (!strcmp(elementPath, "BucketLoggingStatus/LoggingEnabled/" - "TargetGrants/Grant/Permission")) { - // Permission - string_buffer_append(caData->permission, data, dataLen, fit); - if (!fit) { - return S3StatusPermissionTooLong; - } - } - } - else { - if (!strcmp(elementPath, "BucketLoggingStatus/LoggingEnabled/" - "TargetGrants/Grant")) { - // A grant has just been completed; so add the next S3AclGrant - // based on the values read - if (*(caData->aclGrantCountReturn) == S3_MAX_ACL_GRANT_COUNT) { - return S3StatusTooManyGrants; - } - - S3AclGrant *grant = &(caData->aclGrants - [*(caData->aclGrantCountReturn)]); - - if (caData->emailAddress[0]) { - grant->granteeType = S3GranteeTypeAmazonCustomerByEmail; - strcpy(grant->grantee.amazonCustomerByEmail.emailAddress, - caData->emailAddress); - } - else if (caData->userId[0] && caData->userDisplayName[0]) { - grant->granteeType = S3GranteeTypeCanonicalUser; - strcpy(grant->grantee.canonicalUser.id, caData->userId); - strcpy(grant->grantee.canonicalUser.displayName, - caData->userDisplayName); - } - else if (caData->groupUri[0]) { - if (!strcmp(caData->groupUri, - "http://acs.amazonaws.com/groups/global/" - "AuthenticatedUsers")) { - grant->granteeType = S3GranteeTypeAllAwsUsers; - } - else if (!strcmp(caData->groupUri, - "http://acs.amazonaws.com/groups/global/" - "AllUsers")) { - grant->granteeType = S3GranteeTypeAllUsers; - } - else { - return S3StatusBadGrantee; - } - } - else { - return S3StatusBadGrantee; - } - - if (!strcmp(caData->permission, "READ")) { - grant->permission = S3PermissionRead; - } - else if (!strcmp(caData->permission, "WRITE")) { - grant->permission = S3PermissionWrite; - } - else if (!strcmp(caData->permission, "READ_ACP")) { - grant->permission = S3PermissionReadACP; - } - else if (!strcmp(caData->permission, "WRITE_ACP")) { - grant->permission = S3PermissionWriteACP; - } - else if (!strcmp(caData->permission, "FULL_CONTROL")) { - grant->permission = S3PermissionFullControl; - } - else { - return S3StatusBadPermission; - } - - (*(caData->aclGrantCountReturn))++; - - string_buffer_initialize(caData->emailAddress); - string_buffer_initialize(caData->userId); - string_buffer_initialize(caData->userDisplayName); - string_buffer_initialize(caData->groupUri); - string_buffer_initialize(caData->permission); - } - } - - return S3StatusOK; -} - - -static S3Status convert_bls(char *blsXml, char *targetBucketReturn, - char *targetPrefixReturn, int *aclGrantCountReturn, - S3AclGrant *aclGrants) -{ - ConvertBlsData data; - - data.targetBucketReturn = targetBucketReturn; - data.targetBucketReturn[0] = 0; - data.targetBucketReturnLen = 0; - data.targetPrefixReturn = targetPrefixReturn; - data.targetPrefixReturn[0] = 0; - data.targetPrefixReturnLen = 0; - data.aclGrantCountReturn = aclGrantCountReturn; - data.aclGrants = aclGrants; - *aclGrantCountReturn = 0; - string_buffer_initialize(data.emailAddress); - string_buffer_initialize(data.userId); - string_buffer_initialize(data.userDisplayName); - string_buffer_initialize(data.groupUri); - string_buffer_initialize(data.permission); - - // Use a simplexml parser - SimpleXml simpleXml; - simplexml_initialize(&simpleXml, &convertBlsXmlCallback, &data); - - S3Status status = simplexml_add(&simpleXml, blsXml, strlen(blsXml)); - - simplexml_deinitialize(&simpleXml); - - return status; -} - - -// Use a rather arbitrary max size for the document of 64K -#define BLS_XML_DOC_MAXSIZE (64 * 1024) - - -typedef struct GetBlsData -{ - SimpleXml simpleXml; - - S3ResponsePropertiesCallback *responsePropertiesCallback; - S3ResponseCompleteCallback *responseCompleteCallback; - void *callbackData; - - char *targetBucketReturn; - char *targetPrefixReturn; - int *aclGrantCountReturn; - S3AclGrant *aclGrants; - string_buffer(blsXmlDocument, BLS_XML_DOC_MAXSIZE); -} GetBlsData; - - -static S3Status getBlsPropertiesCallback - (const S3ResponseProperties *responseProperties, void *callbackData) -{ - GetBlsData *gsData = (GetBlsData *) callbackData; - - return (*(gsData->responsePropertiesCallback)) - (responseProperties, gsData->callbackData); -} - - -static S3Status getBlsDataCallback(int bufferSize, const char *buffer, - void *callbackData) -{ - GetBlsData *gsData = (GetBlsData *) callbackData; - - int fit; - - string_buffer_append(gsData->blsXmlDocument, buffer, bufferSize, fit); - - return fit ? S3StatusOK : S3StatusXmlDocumentTooLarge; -} - - -static void getBlsCompleteCallback(S3Status requestStatus, - const S3ErrorDetails *s3ErrorDetails, - void *callbackData) -{ - GetBlsData *gsData = (GetBlsData *) callbackData; - - if (requestStatus == S3StatusOK) { - // Parse the document - requestStatus = convert_bls - (gsData->blsXmlDocument, gsData->targetBucketReturn, - gsData->targetPrefixReturn, gsData->aclGrantCountReturn, - gsData->aclGrants); - } - - (*(gsData->responseCompleteCallback)) - (requestStatus, s3ErrorDetails, gsData->callbackData); - - free(gsData); -} - - -void S3_get_server_access_logging(const S3BucketContext *bucketContext, - char *targetBucketReturn, - char *targetPrefixReturn, - int *aclGrantCountReturn, - S3AclGrant *aclGrants, - S3RequestContext *requestContext, - const S3ResponseHandler *handler, - void *callbackData) -{ - // Create the callback data - GetBlsData *gsData = (GetBlsData *) malloc(sizeof(GetBlsData)); - if (!gsData) { - (*(handler->completeCallback))(S3StatusOutOfMemory, 0, callbackData); - return; - } - - gsData->responsePropertiesCallback = handler->propertiesCallback; - gsData->responseCompleteCallback = handler->completeCallback; - gsData->callbackData = callbackData; - - gsData->targetBucketReturn = targetBucketReturn; - gsData->targetPrefixReturn = targetPrefixReturn; - gsData->aclGrantCountReturn = aclGrantCountReturn; - gsData->aclGrants = aclGrants; - string_buffer_initialize(gsData->blsXmlDocument); - *aclGrantCountReturn = 0; - - // Set up the RequestParams - RequestParams params = - { - HttpRequestTypeGET, // httpRequestType - { bucketContext->bucketName, // bucketName - bucketContext->protocol, // protocol - bucketContext->uriStyle, // uriStyle - bucketContext->accessKeyId, // accessKeyId - bucketContext->secretAccessKey }, // secretAccessKey - 0, // key - 0, // queryParams - "logging", // subResource - 0, // copySourceBucketName - 0, // copySourceKey - 0, // getConditions - 0, // startByte - 0, // byteCount - 0, // putProperties - &getBlsPropertiesCallback, // propertiesCallback - 0, // toS3Callback - 0, // toS3CallbackTotalSize - &getBlsDataCallback, // fromS3Callback - &getBlsCompleteCallback, // completeCallback - gsData // callbackData - }; - - // Perform the request - request_perform(¶ms, requestContext); -} - - - -// set server access logging--------------------------------------------------- - -static S3Status generateSalXmlDocument(const char *targetBucket, - const char *targetPrefix, - int aclGrantCount, - const S3AclGrant *aclGrants, - int *xmlDocumentLenReturn, - char *xmlDocument, - int xmlDocumentBufferSize) -{ - *xmlDocumentLenReturn = 0; - -#define append(fmt, ...) \ - do { \ - *xmlDocumentLenReturn += snprintf \ - (&(xmlDocument[*xmlDocumentLenReturn]), \ - xmlDocumentBufferSize - *xmlDocumentLenReturn - 1, \ - fmt, __VA_ARGS__); \ - if (*xmlDocumentLenReturn >= xmlDocumentBufferSize) { \ - return S3StatusXmlDocumentTooLarge; \ - } \ - } while (0) - - append("%s", ""); - - if (targetBucket && targetBucket[0]) { - append("%s", targetBucket); - append("%s", - targetPrefix ? targetPrefix : ""); - - if (aclGrantCount) { - append("%s", ""); - int i; - for (i = 0; i < aclGrantCount; i++) { - append("%s", "granteeType) { - case S3GranteeTypeAmazonCustomerByEmail: - append("AmazonCustomerByEmail\">%s" - "", - grant->grantee.amazonCustomerByEmail.emailAddress); - break; - case S3GranteeTypeCanonicalUser: - append("CanonicalUser\">%s%s" - "", - grant->grantee.canonicalUser.id, - grant->grantee.canonicalUser.displayName); - break; - default: // case S3GranteeTypeAllAwsUsers/S3GranteeTypeAllUsers: - append("Group\">http://acs.amazonaws.com/groups/" - "global/%s", - (grant->granteeType == S3GranteeTypeAllAwsUsers) ? - "AuthenticatedUsers" : "AllUsers"); - break; - } - append("%s", - ((grant->permission == S3PermissionRead) ? "READ" : - (grant->permission == S3PermissionWrite) ? "WRITE" : - (grant->permission == - S3PermissionReadACP) ? "READ_ACP" : - (grant->permission == - S3PermissionWriteACP) ? "WRITE_ACP" : "FULL_CONTROL")); - } - append("%s", ""); - } - append("%s", ""); - } - - append("%s", ""); - - return S3StatusOK; -} - - -typedef struct SetSalData -{ - S3ResponsePropertiesCallback *responsePropertiesCallback; - S3ResponseCompleteCallback *responseCompleteCallback; - void *callbackData; - - int salXmlDocumentLen; - char salXmlDocument[BLS_XML_DOC_MAXSIZE]; - int salXmlDocumentBytesWritten; - -} SetSalData; - - -static S3Status setSalPropertiesCallback - (const S3ResponseProperties *responseProperties, void *callbackData) -{ - SetSalData *paData = (SetSalData *) callbackData; - - return (*(paData->responsePropertiesCallback)) - (responseProperties, paData->callbackData); -} - - -static int setSalDataCallback(int bufferSize, char *buffer, void *callbackData) -{ - SetSalData *paData = (SetSalData *) callbackData; - - int remaining = (paData->salXmlDocumentLen - - paData->salXmlDocumentBytesWritten); - - int toCopy = bufferSize > remaining ? remaining : bufferSize; - - if (!toCopy) { - return 0; - } - - memcpy(buffer, &(paData->salXmlDocument - [paData->salXmlDocumentBytesWritten]), toCopy); - - paData->salXmlDocumentBytesWritten += toCopy; - - return toCopy; -} - - -static void setSalCompleteCallback(S3Status requestStatus, - const S3ErrorDetails *s3ErrorDetails, - void *callbackData) -{ - SetSalData *paData = (SetSalData *) callbackData; - - (*(paData->responseCompleteCallback)) - (requestStatus, s3ErrorDetails, paData->callbackData); - - free(paData); -} - - -void S3_set_server_access_logging(const S3BucketContext *bucketContext, - const char *targetBucket, - const char *targetPrefix, int aclGrantCount, - const S3AclGrant *aclGrants, - S3RequestContext *requestContext, - const S3ResponseHandler *handler, - void *callbackData) -{ - if (aclGrantCount > S3_MAX_ACL_GRANT_COUNT) { - (*(handler->completeCallback)) - (S3StatusTooManyGrants, 0, callbackData); - return; - } - - SetSalData *data = (SetSalData *) malloc(sizeof(SetSalData)); - if (!data) { - (*(handler->completeCallback))(S3StatusOutOfMemory, 0, callbackData); - return; - } - - // Convert aclGrants to XML document - S3Status status = generateSalXmlDocument - (targetBucket, targetPrefix, aclGrantCount, aclGrants, - &(data->salXmlDocumentLen), data->salXmlDocument, - sizeof(data->salXmlDocument)); - if (status != S3StatusOK) { - free(data); - (*(handler->completeCallback))(status, 0, callbackData); - return; - } - - data->responsePropertiesCallback = handler->propertiesCallback; - data->responseCompleteCallback = handler->completeCallback; - data->callbackData = callbackData; - - data->salXmlDocumentBytesWritten = 0; - - // Set up the RequestParams - RequestParams params = - { - HttpRequestTypePUT, // httpRequestType - { bucketContext->bucketName, // bucketName - bucketContext->protocol, // protocol - bucketContext->uriStyle, // uriStyle - bucketContext->accessKeyId, // accessKeyId - bucketContext->secretAccessKey }, // secretAccessKey - 0, // key - 0, // queryParams - "logging", // subResource - 0, // copySourceBucketName - 0, // copySourceKey - 0, // getConditions - 0, // startByte - 0, // byteCount - 0, // putProperties - &setSalPropertiesCallback, // propertiesCallback - &setSalDataCallback, // toS3Callback - data->salXmlDocumentLen, // toS3CallbackTotalSize - 0, // fromS3Callback - &setSalCompleteCallback, // completeCallback - data // callbackData - }; - - // Perform the request - request_perform(¶ms, requestContext); -} diff --git a/libs3-1.4/src/simplexml.c b/libs3-1.4/src/simplexml.c deleted file mode 100644 index bd8616b..0000000 --- a/libs3-1.4/src/simplexml.c +++ /dev/null @@ -1,207 +0,0 @@ -/** ************************************************************************** - * simplexml.c - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -#include -#include -#include "simplexml.h" - -// Use libxml2 for parsing XML. XML is severely overused in modern -// computing. It is useful for only a very small subset of tasks, but -// software developers who don't know better and are afraid to go against the -// grain use it for everything, and in most cases, it is completely -// inappropriate. Usually, the document structure is severely under-specified -// as well, as is the case with S3. We do our best by just caring about the -// most important aspects of the S3 "XML document" responses: the elements and -// their values. The SAX API (just about the lamest API ever devised and -// proof that XML sucks - well, the real proof is how crappy all of the XML -// parsing libraries are, including libxml2 - but I digress) is used here -// because we don't need much from the parser and SAX is fast and low memory. -// -// Note that for simplicity we assume all ASCII here. No attempts are made to -// detect non-ASCII sequences in utf-8 and convert them into ASCII in any way. -// S3 appears to only use ASCII anyway. - - -static xmlEntityPtr saxGetEntity(void *user_data, const xmlChar *name) -{ - (void) user_data; - - return xmlGetPredefinedEntity(name); -} - - -static void saxStartElement(void *user_data, const xmlChar *nameUtf8, - const xmlChar **attr) -{ - (void) attr; - - SimpleXml *simpleXml = (SimpleXml *) user_data; - - if (simpleXml->status != S3StatusOK) { - return; - } - - // Assume that name has no non-ASCII in it - char *name = (char *) nameUtf8; - - // Append the element to the element path - int len = strlen(name); - - if ((simpleXml->elementPathLen + len + 1) >= - (int) sizeof(simpleXml->elementPath)) { - // Cannot handle this element, stop! - simpleXml->status = S3StatusXmlParseFailure; - return; - } - - if (simpleXml->elementPathLen) { - simpleXml->elementPath[simpleXml->elementPathLen++] = '/'; - } - strcpy(&(simpleXml->elementPath[simpleXml->elementPathLen]), name); - simpleXml->elementPathLen += len; -} - - -static void saxEndElement(void *user_data, const xmlChar *name) -{ - (void) name; - - SimpleXml *simpleXml = (SimpleXml *) user_data; - - if (simpleXml->status != S3StatusOK) { - return; - } - - // Call back with 0 data - simpleXml->status = (*(simpleXml->callback)) - (simpleXml->elementPath, 0, 0, simpleXml->callbackData); - - while ((simpleXml->elementPathLen > 0) && - (simpleXml->elementPath[simpleXml->elementPathLen] != '/')) { - simpleXml->elementPathLen--; - } - - simpleXml->elementPath[simpleXml->elementPathLen] = 0; -} - - -static void saxCharacters(void *user_data, const xmlChar *ch, int len) -{ - SimpleXml *simpleXml = (SimpleXml *) user_data; - - if (simpleXml->status != S3StatusOK) { - return; - } - - simpleXml->status = (*(simpleXml->callback)) - (simpleXml->elementPath, (char *) ch, len, simpleXml->callbackData); -} - - -static void saxError(void *user_data, const char *msg, ...) -{ - (void) msg; - - SimpleXml *simpleXml = (SimpleXml *) user_data; - - if (simpleXml->status != S3StatusOK) { - return; - } - - simpleXml->status = S3StatusXmlParseFailure; -} - - -static struct _xmlSAXHandler saxHandlerG = -{ - 0, // internalSubsetSAXFunc - 0, // isStandaloneSAXFunc - 0, // hasInternalSubsetSAXFunc - 0, // hasExternalSubsetSAXFunc - 0, // resolveEntitySAXFunc - &saxGetEntity, // getEntitySAXFunc - 0, // entityDeclSAXFunc - 0, // notationDeclSAXFunc - 0, // attributeDeclSAXFunc - 0, // elementDeclSAXFunc - 0, // unparsedEntityDeclSAXFunc - 0, // setDocumentLocatorSAXFunc - 0, // startDocumentSAXFunc - 0, // endDocumentSAXFunc - &saxStartElement, // startElementSAXFunc - &saxEndElement, // endElementSAXFunc - 0, // referenceSAXFunc - &saxCharacters, // charactersSAXFunc - 0, // ignorableWhitespaceSAXFunc - 0, // processingInstructionSAXFunc - 0, // commentSAXFunc - 0, // warningSAXFunc - &saxError, // errorSAXFunc - &saxError, // fatalErrorSAXFunc - 0, // getParameterEntitySAXFunc - &saxCharacters, // cdataBlockSAXFunc - 0, // externalSubsetSAXFunc - 0, // initialized - 0, // _private - 0, // startElementNsSAX2Func - 0, // endElementNsSAX2Func - 0 // xmlStructuredErrorFunc serror; -}; - -void simplexml_initialize(SimpleXml *simpleXml, - SimpleXmlCallback *callback, void *callbackData) -{ - simpleXml->callback = callback; - simpleXml->callbackData = callbackData; - simpleXml->elementPathLen = 0; - simpleXml->status = S3StatusOK; - simpleXml->xmlParser = 0; -} - - -void simplexml_deinitialize(SimpleXml *simpleXml) -{ - if (simpleXml->xmlParser) { - xmlFreeParserCtxt(simpleXml->xmlParser); - } -} - - -S3Status simplexml_add(SimpleXml *simpleXml, const char *data, int dataLen) -{ - if (!simpleXml->xmlParser && - (!(simpleXml->xmlParser = xmlCreatePushParserCtxt - (&saxHandlerG, simpleXml, 0, 0, 0)))) { - return S3StatusInternalError; - } - - if (xmlParseChunk((xmlParserCtxtPtr) simpleXml->xmlParser, - data, dataLen, 0)) { - return S3StatusXmlParseFailure; - } - - return simpleXml->status; -} diff --git a/libs3-1.4/src/testsimplexml.c b/libs3-1.4/src/testsimplexml.c deleted file mode 100644 index 57fba7d..0000000 --- a/libs3-1.4/src/testsimplexml.c +++ /dev/null @@ -1,87 +0,0 @@ -/** ************************************************************************** - * testsimplexml.c - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -#include -#include -#include -#include -#include "simplexml.h" - -static S3Status simpleXmlCallback(const char *elementPath, const char *data, - int dataLen, void *callbackData) -{ - (void) callbackData; - - printf("[%s]: [%.*s]\n", elementPath, dataLen, data); - - return S3StatusOK; -} - - -// The only argument allowed is a specification of the random seed to use -int main(int argc, char **argv) -{ - if (argc > 1) { - char *arg = argv[1]; - int seed = 0; - while (*arg) { - seed *= 10; - seed += (*arg++ - '0'); - } - - srand(seed); - } - else { - srand(time(0)); - } - - SimpleXml simpleXml; - - simplexml_initialize(&simpleXml, &simpleXmlCallback, 0); - - // Read chunks of 10K from stdin, and then feed them in random chunks - // to simplexml_add - char inbuf[10000]; - - int amt_read; - while ((amt_read = fread(inbuf, 1, sizeof(inbuf), stdin)) > 0) { - char *buf = inbuf; - while (amt_read) { - int amt = (rand() % amt_read) + 1; - S3Status status = simplexml_add(&simpleXml, buf, amt); - if (status != S3StatusOK) { - fprintf(stderr, "ERROR: Parse failure: %d\n", status); - simplexml_deinitialize(&simpleXml); - return -1; - } - buf += amt, amt_read -= amt; - } - } - - simplexml_deinitialize(&simpleXml); - - return 0; -} diff --git a/libs3-1.4/src/util.c b/libs3-1.4/src/util.c deleted file mode 100644 index 25397cc..0000000 --- a/libs3-1.4/src/util.c +++ /dev/null @@ -1,567 +0,0 @@ -/** ************************************************************************** - * util.c - * - * Copyright 2008 Bryan Ischo - * - * This file is part of libs3. - * - * libs3 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, version 3 of the License. - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of this library and its programs with the - * OpenSSL library, and distribute linked combinations including the two. - * - * libs3 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 version 3 - * along with libs3, in a file named COPYING. If not, see - * . - * - ************************************************************************** **/ - -#include -#include -#include "util.h" - - -// Convenience utility for making the code look nicer. Tests a string -// against a format; only the characters specified in the format are -// checked (i.e. if the string is longer than the format, the string still -// checks out ok). Format characters are: -// d - is a digit -// anything else - is that character -// Returns nonzero the string checks out, zero if it does not. -static int checkString(const char *str, const char *format) -{ - while (*format) { - if (*format == 'd') { - if (!isdigit(*str)) { - return 0; - } - } - else if (*str != *format) { - return 0; - } - str++, format++; - } - - return 1; -} - - -int urlEncode(char *dest, const char *src, int maxSrcSize) -{ - static const char *urlSafe = "-_.!~*'()/"; - static const char *hex = "0123456789ABCDEF"; - - int len = 0; - - if (src) while (*src) { - if (++len > maxSrcSize) { - *dest = 0; - return 0; - } - const char *urlsafe = urlSafe; - int isurlsafe = 0; - while (*urlsafe) { - if (*urlsafe == *src) { - isurlsafe = 1; - break; - } - urlsafe++; - } - if (isurlsafe || isalnum(*src)) { - *dest++ = *src++; - } - else if (*src == ' ') { - *dest++ = '+'; - src++; - } - else { - *dest++ = '%'; - *dest++ = hex[*src / 16]; - *dest++ = hex[*src % 16]; - src++; - } - } - - *dest = 0; - - return 1; -} - - -int64_t parseIso8601Time(const char *str) -{ - // Check to make sure that it has a valid format - if (!checkString(str, "dddd-dd-ddTdd:dd:dd")) { - return -1; - } - -#define nextnum() (((*str - '0') * 10) + (*(str + 1) - '0')) - - // Convert it - struct tm stm; - memset(&stm, 0, sizeof(stm)); - - stm.tm_year = (nextnum() - 19) * 100; - str += 2; - stm.tm_year += nextnum(); - str += 3; - - stm.tm_mon = nextnum() - 1; - str += 3; - - stm.tm_mday = nextnum(); - str += 3; - - stm.tm_hour = nextnum(); - str += 3; - - stm.tm_min = nextnum(); - str += 3; - - stm.tm_sec = nextnum(); - str += 2; - - stm.tm_isdst = -1; - - int64_t ret = mktime(&stm); - - // Skip the millis - - if (*str == '.') { - str++; - while (isdigit(*str)) { - str++; - } - } - - if (checkString(str, "-dd:dd") || checkString(str, "+dd:dd")) { - int sign = (*str++ == '-') ? -1 : 1; - int hours = nextnum(); - str += 3; - int minutes = nextnum(); - ret += (-sign * (((hours * 60) + minutes) * 60)); - } - // Else it should be Z to be a conformant time string, but we just assume - // that it is rather than enforcing that - - return ret; -} - - -uint64_t parseUnsignedInt(const char *str) -{ - // Skip whitespace - while (is_blank(*str)) { - str++; - } - - uint64_t ret = 0; - - while (isdigit(*str)) { - ret *= 10; - ret += (*str++ - '0'); - } - - return ret; -} - - -int base64Encode(const unsigned char *in, int inLen, char *out) -{ - static const char *ENC = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - char *original_out = out; - - while (inLen) { - // first 6 bits of char 1 - *out++ = ENC[*in >> 2]; - if (!--inLen) { - // last 2 bits of char 1, 4 bits of 0 - *out++ = ENC[(*in & 0x3) << 4]; - *out++ = '='; - *out++ = '='; - break; - } - // last 2 bits of char 1, first 4 bits of char 2 - *out++ = ENC[((*in & 0x3) << 4) | (*(in + 1) >> 4)]; - in++; - if (!--inLen) { - // last 4 bits of char 2, 2 bits of 0 - *out++ = ENC[(*in & 0xF) << 2]; - *out++ = '='; - break; - } - // last 4 bits of char 2, first 2 bits of char 3 - *out++ = ENC[((*in & 0xF) << 2) | (*(in + 1) >> 6)]; - in++; - // last 6 bits of char 3 - *out++ = ENC[*in & 0x3F]; - in++, inLen--; - } - - return (out - original_out); -} - - -#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) - -#define blk0L(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) \ - | (rol(block->l[i], 8) & 0x00FF00FF)) - -#define blk0B(i) (block->l[i]) - -#define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ \ - block->l[(i + 8) & 15] ^ \ - block->l[(i + 2) & 15] ^ \ - block->l[i & 15], 1)) - -#define R0_L(v, w, x, y, z, i) \ - z += ((w & (x ^ y)) ^ y) + blk0L(i) + 0x5A827999 + rol(v, 5); \ - w = rol(w, 30); -#define R0_B(v, w, x, y, z, i) \ - z += ((w & (x ^ y)) ^ y) + blk0B(i) + 0x5A827999 + rol(v, 5); \ - w = rol(w, 30); -#define R1(v, w, x, y, z, i) \ - z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \ - w = rol(w, 30); -#define R2(v, w, x, y, z, i) \ - z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); \ - w = rol(w, 30); -#define R3(v, w, x, y, z, i) \ - z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \ - w = rol(w, 30); -#define R4(v, w, x, y, z, i) \ - z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \ - w = rol(w, 30); - -#define R0A_L(i) R0_L(a, b, c, d, e, i) -#define R0B_L(i) R0_L(b, c, d, e, a, i) -#define R0C_L(i) R0_L(c, d, e, a, b, i) -#define R0D_L(i) R0_L(d, e, a, b, c, i) -#define R0E_L(i) R0_L(e, a, b, c, d, i) - -#define R0A_B(i) R0_B(a, b, c, d, e, i) -#define R0B_B(i) R0_B(b, c, d, e, a, i) -#define R0C_B(i) R0_B(c, d, e, a, b, i) -#define R0D_B(i) R0_B(d, e, a, b, c, i) -#define R0E_B(i) R0_B(e, a, b, c, d, i) - -#define R1A(i) R1(a, b, c, d, e, i) -#define R1B(i) R1(b, c, d, e, a, i) -#define R1C(i) R1(c, d, e, a, b, i) -#define R1D(i) R1(d, e, a, b, c, i) -#define R1E(i) R1(e, a, b, c, d, i) - -#define R2A(i) R2(a, b, c, d, e, i) -#define R2B(i) R2(b, c, d, e, a, i) -#define R2C(i) R2(c, d, e, a, b, i) -#define R2D(i) R2(d, e, a, b, c, i) -#define R2E(i) R2(e, a, b, c, d, i) - -#define R3A(i) R3(a, b, c, d, e, i) -#define R3B(i) R3(b, c, d, e, a, i) -#define R3C(i) R3(c, d, e, a, b, i) -#define R3D(i) R3(d, e, a, b, c, i) -#define R3E(i) R3(e, a, b, c, d, i) - -#define R4A(i) R4(a, b, c, d, e, i) -#define R4B(i) R4(b, c, d, e, a, i) -#define R4C(i) R4(c, d, e, a, b, i) -#define R4D(i) R4(d, e, a, b, c, i) -#define R4E(i) R4(e, a, b, c, d, i) - - -static void SHA1_transform(uint32_t state[5], const unsigned char buffer[64]) -{ - uint32_t a, b, c, d, e; - - typedef union { - unsigned char c[64]; - uint32_t l[16]; - } u; - - unsigned char w[64]; - u *block = (u *) w; - - memcpy(block, buffer, 64); - - a = state[0]; - b = state[1]; - c = state[2]; - d = state[3]; - e = state[4]; - - static uint32_t endianness_indicator = 0x1; - if (((unsigned char *) &endianness_indicator)[0]) { - R0A_L( 0); - R0E_L( 1); R0D_L( 2); R0C_L( 3); R0B_L( 4); R0A_L( 5); - R0E_L( 6); R0D_L( 7); R0C_L( 8); R0B_L( 9); R0A_L(10); - R0E_L(11); R0D_L(12); R0C_L(13); R0B_L(14); R0A_L(15); - } - else { - R0A_B( 0); - R0E_B( 1); R0D_B( 2); R0C_B( 3); R0B_B( 4); R0A_B( 5); - R0E_B( 6); R0D_B( 7); R0C_B( 8); R0B_B( 9); R0A_B(10); - R0E_B(11); R0D_B(12); R0C_B(13); R0B_B(14); R0A_B(15); - } - R1E(16); R1D(17); R1C(18); R1B(19); R2A(20); - R2E(21); R2D(22); R2C(23); R2B(24); R2A(25); - R2E(26); R2D(27); R2C(28); R2B(29); R2A(30); - R2E(31); R2D(32); R2C(33); R2B(34); R2A(35); - R2E(36); R2D(37); R2C(38); R2B(39); R3A(40); - R3E(41); R3D(42); R3C(43); R3B(44); R3A(45); - R3E(46); R3D(47); R3C(48); R3B(49); R3A(50); - R3E(51); R3D(52); R3C(53); R3B(54); R3A(55); - R3E(56); R3D(57); R3C(58); R3B(59); R4A(60); - R4E(61); R4D(62); R4C(63); R4B(64); R4A(65); - R4E(66); R4D(67); R4C(68); R4B(69); R4A(70); - R4E(71); R4D(72); R4C(73); R4B(74); R4A(75); - R4E(76); R4D(77); R4C(78); R4B(79); - - state[0] += a; - state[1] += b; - state[2] += c; - state[3] += d; - state[4] += e; -} - - -typedef struct -{ - uint32_t state[5]; - uint32_t count[2]; - unsigned char buffer[64]; -} SHA1Context; - - -static void SHA1_init(SHA1Context *context) -{ - context->state[0] = 0x67452301; - context->state[1] = 0xEFCDAB89; - context->state[2] = 0x98BADCFE; - context->state[3] = 0x10325476; - context->state[4] = 0xC3D2E1F0; - context->count[0] = context->count[1] = 0; -} - - -static void SHA1_update(SHA1Context *context, const unsigned char *data, - unsigned int len) -{ - uint32_t i, j; - - j = (context->count[0] >> 3) & 63; - - if ((context->count[0] += len << 3) < (len << 3)) { - context->count[1]++; - } - - context->count[1] += (len >> 29); - - if ((j + len) > 63) { - memcpy(&(context->buffer[j]), data, (i = 64 - j)); - SHA1_transform(context->state, context->buffer); - for ( ; (i + 63) < len; i += 64) { - SHA1_transform(context->state, &(data[i])); - } - j = 0; - } - else { - i = 0; - } - - memcpy(&(context->buffer[j]), &(data[i]), len - i); -} - - -static void SHA1_final(unsigned char digest[20], SHA1Context *context) -{ - uint32_t i; - unsigned char finalcount[8]; - - for (i = 0; i < 8; i++) { - finalcount[i] = (unsigned char) - ((context->count[(i >= 4 ? 0 : 1)] >> - ((3 - (i & 3)) * 8)) & 255); - } - - SHA1_update(context, (unsigned char *) "\200", 1); - - while ((context->count[0] & 504) != 448) { - SHA1_update(context, (unsigned char *) "\0", 1); - } - - SHA1_update(context, finalcount, 8); - - for (i = 0; i < 20; i++) { - digest[i] = (unsigned char) - ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); - } - - memset(context->buffer, 0, 64); - memset(context->state, 0, 20); - memset(context->count, 0, 8); - memset(&finalcount, 0, 8); - - SHA1_transform(context->state, context->buffer); -} - - -// HMAC-SHA-1: -// -// K - is key padded with zeros to 512 bits -// m - is message -// OPAD - 0x5c5c5c... -// IPAD - 0x363636... -// -// HMAC(K,m) = SHA1((K ^ OPAD) . SHA1((K ^ IPAD) . m)) -void HMAC_SHA1(unsigned char hmac[20], const unsigned char *key, int key_len, - const unsigned char *message, int message_len) -{ - unsigned char kopad[64], kipad[64]; - int i; - - if (key_len > 64) { - key_len = 64; - } - - for (i = 0; i < key_len; i++) { - kopad[i] = key[i] ^ 0x5c; - kipad[i] = key[i] ^ 0x36; - } - - for ( ; i < 64; i++) { - kopad[i] = 0 ^ 0x5c; - kipad[i] = 0 ^ 0x36; - } - - unsigned char digest[20]; - - SHA1Context context; - - SHA1_init(&context); - SHA1_update(&context, kipad, 64); - SHA1_update(&context, message, message_len); - SHA1_final(digest, &context); - - SHA1_init(&context); - SHA1_update(&context, kopad, 64); - SHA1_update(&context, digest, 20); - SHA1_final(hmac, &context); -} - -#define rot(x,k) (((x) << (k)) | ((x) >> (32 - (k)))) - -uint64_t hash(const unsigned char *k, int length) -{ - uint32_t a, b, c; - - a = b = c = 0xdeadbeef + ((uint32_t) length); - - static uint32_t endianness_indicator = 0x1; - if (((unsigned char *) &endianness_indicator)[0]) { - while (length > 12) { - a += k[0]; - a += ((uint32_t) k[1]) << 8; - a += ((uint32_t) k[2]) << 16; - a += ((uint32_t) k[3]) << 24; - b += k[4]; - b += ((uint32_t) k[5]) << 8; - b += ((uint32_t) k[6]) << 16; - b += ((uint32_t) k[7]) << 24; - c += k[8]; - c += ((uint32_t) k[9]) << 8; - c += ((uint32_t) k[10]) << 16; - c += ((uint32_t) k[11]) << 24; - a -= c; a ^= rot(c, 4); c += b; - b -= a; b ^= rot(a, 6); a += c; - c -= b; c ^= rot(b, 8); b += a; - a -= c; a ^= rot(c, 16); c += b; - b -= a; b ^= rot(a, 19); a += c; - c -= b; c ^= rot(b, 4); b += a; - length -= 12; - k += 12; - } - - switch(length) { - case 12: c += ((uint32_t) k[11]) << 24; - case 11: c += ((uint32_t) k[10]) << 16; - case 10: c += ((uint32_t) k[9]) << 8; - case 9 : c += k[8]; - case 8 : b += ((uint32_t) k[7]) << 24; - case 7 : b += ((uint32_t) k[6]) << 16; - case 6 : b += ((uint32_t) k[5]) << 8; - case 5 : b += k[4]; - case 4 : a += ((uint32_t) k[3]) << 24; - case 3 : a += ((uint32_t) k[2]) << 16; - case 2 : a += ((uint32_t) k[1]) << 8; - case 1 : a += k[0]; break; - case 0 : goto end; - } - } - else { - while (length > 12) { - a += ((uint32_t) k[0]) << 24; - a += ((uint32_t) k[1]) << 16; - a += ((uint32_t) k[2]) << 8; - a += ((uint32_t) k[3]); - b += ((uint32_t) k[4]) << 24; - b += ((uint32_t) k[5]) << 16; - b += ((uint32_t) k[6]) << 8; - b += ((uint32_t) k[7]); - c += ((uint32_t) k[8]) << 24; - c += ((uint32_t) k[9]) << 16; - c += ((uint32_t) k[10]) << 8; - c += ((uint32_t) k[11]); - a -= c; a ^= rot(c, 4); c += b; - b -= a; b ^= rot(a, 6); a += c; - c -= b; c ^= rot(b, 8); b += a; - a -= c; a ^= rot(c, 16); c += b; - b -= a; b ^= rot(a, 19); a += c; - c -= b; c ^= rot(b, 4); b += a; - length -= 12; - k += 12; - } - - switch(length) { - case 12: c += k[11]; - case 11: c += ((uint32_t) k[10]) << 8; - case 10: c += ((uint32_t) k[9]) << 16; - case 9 : c += ((uint32_t) k[8]) << 24; - case 8 : b += k[7]; - case 7 : b += ((uint32_t) k[6]) << 8; - case 6 : b += ((uint32_t) k[5]) << 16; - case 5 : b += ((uint32_t) k[4]) << 24; - case 4 : a += k[3]; - case 3 : a += ((uint32_t) k[2]) << 8; - case 2 : a += ((uint32_t) k[1]) << 16; - case 1 : a += ((uint32_t) k[0]) << 24; break; - case 0 : goto end; - } - } - - c ^= b; c -= rot(b, 14); - a ^= c; a -= rot(c, 11); - b ^= a; b -= rot(a, 25); - c ^= b; c -= rot(b, 16); - a ^= c; a -= rot(c, 4); - b ^= a; b -= rot(a, 14); - c ^= b; c -= rot(b, 24); - - end: - return ((((uint64_t) c) << 32) | b); -} - -int is_blank(char c) -{ - return ((c == ' ') || (c == '\t')); -} diff --git a/libs3-1.4/test/badxml_01.xml b/libs3-1.4/test/badxml_01.xml deleted file mode 100644 index e991702..0000000 --- a/libs3-1.4/test/badxml_01.xml +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Data - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs3-1.4/test/goodxml_01.xml b/libs3-1.4/test/goodxml_01.xml deleted file mode 100644 index 687214e..0000000 --- a/libs3-1.4/test/goodxml_01.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - NoSuchKey - The resource & then]]> you requested does not exist & so there - /mybucket/myfoto.jpg - 4442587FB7D0A2F9 - diff --git a/libs3-1.4/test/goodxml_02.xml b/libs3-1.4/test/goodxml_02.xml deleted file mode 100644 index d713bc6..0000000 --- a/libs3-1.4/test/goodxml_02.xml +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Data - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libs3-1.4/test/goodxml_03.xml b/libs3-1.4/test/goodxml_03.xml deleted file mode 100644 index 9a85166..0000000 --- a/libs3-1.4/test/goodxml_03.xml +++ /dev/null @@ -1,13 +0,0 @@ - - -1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 -12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 -12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 -12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 -12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 -12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 -12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 -12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 -12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 - - diff --git a/libs3-1.4/test/test.sh b/libs3-1.4/test/test.sh deleted file mode 100755 index 3acfc86..0000000 --- a/libs3-1.4/test/test.sh +++ /dev/null @@ -1,173 +0,0 @@ -#!/bin/sh - -# Environment: -# S3_ACCESS_KEY_ID - must be set to S3 Access Key ID -# S3_SECRET_ACCESS_KEY - must be set to S3 Secret Access Key -# TEST_BUCKET_PREFIX - must be set to the test bucket prefix to use -# S3_COMMAND - may be set to s3 command to use (i.e. valgrind s3); defaults -# to "s3" - -if [ -z "$S3_ACCESS_KEY_ID" ]; then - echo "S3_ACCESS_KEY_ID required" - exit -1; -fi - -if [ -z "$S3_SECRET_ACCESS_KEY" ]; then - echo "S3_SECRET_ACCESS_KEY required" - exit -1; -fi - -if [ -z "$TEST_BUCKET_PREFIX" ]; then - echo "TEST_BUCKET_PREFIX required" - exit -1; -fi - -if [ -z "$S3_COMMAND" ]; then - S3_COMMAND=s3 -fi - -TEST_BUCKET=${TEST_BUCKET_PREFIX}.testbucket - -# Create the test bucket in EU -echo "$S3_COMMAND create $TEST_BUCKET locationConstraint=EU" -$S3_COMMAND create $TEST_BUCKET - -# List to find it -echo "$S3_COMMAND list | grep $TEST_BUCKET" -$S3_COMMAND list | grep $TEST_BUCKET - -# Test it -echo "$S3_COMMAND test $TEST_BUCKET" -$S3_COMMAND test $TEST_BUCKET - -# List to ensure that it is empty -echo "$S3_COMMAND list $TEST_BUCKET" -$S3_COMMAND list $TEST_BUCKET - -# Put some data -rm -f seqdata -seq 1 10000 > seqdata -echo "$S3_COMMAND put $TEST_BUCKET/testkey filename=seqdata noStatus=1" -$S3_COMMAND put $TEST_BUCKET/testkey filename=seqdata noStatus=1 - -rm -f testkey -# Get the data and make sure that it matches -echo "$S3_COMMAND get $TEST_BUCKET/testkey filename=testkey" -$S3_COMMAND get $TEST_BUCKET/testkey filename=testkey -diff seqdata testkey -rm -f seqdata testkey - -# Delete the file -echo "$S3_COMMAND delete $TEST_BUCKET/testkey" -$S3_COMMAND delete $TEST_BUCKET/testkey - -# Remove the test bucket -echo "$S3_COMMAND delete $TEST_BUCKET" -$S3_COMMAND delete $TEST_BUCKET - -# Make sure it's not there -echo "$S3_COMMAND list | grep $TEST_BUCKET" -$S3_COMMAND list | grep $TEST_BUCKET - -# Now create it again -echo "$S3_COMMAND create $TEST_BUCKET" -$S3_COMMAND create $TEST_BUCKET - -# Put 10 files in it -for i in `seq 0 9`; do - echo "echo \"Hello\" | $S3_COMMAND put $TEST_BUCKET/key_$i" - echo "Hello" | $S3_COMMAND put $TEST_BUCKET/key_$i -done - -# List with all details -echo "$S3_COMMAND list $TEST_BUCKET allDetails=1" -$S3_COMMAND list $TEST_BUCKET allDetails=1 - -COPY_BUCKET=${TEST_BUCKET_PREFIX}.copybucket - -# Create another test bucket and copy a file into it -echo "$S3_COMMAND create $COPY_BUCKET" -$S3_COMMAND create $COPY_BUCKET -echo <> acl -Group Authenticated AWS Users READ -EOF -echo <> acl -Group All Users READ_ACP -EOF -echo "$S3_COMMAND setacl $TEST_BUCKET filename=acl" -$S3_COMMAND setacl $TEST_BUCKET filename=acl - -# Test to make sure that it worked -rm -f acl_new -echo "$S3_COMMAND getacl $TEST_BUCKET filename=acl_new allDetails=1" -$S3_COMMAND getacl $TEST_BUCKET filename=acl_new allDetails=1 -diff acl acl_new -rm -f acl acl_new - -# Get the key acl -rm -f acl -echo "$S3_COMMAND getacl $TEST_BUCKET/aclkey filename=acl allDetails=1" -$S3_COMMAND getacl $TEST_BUCKET/aclkey filename=acl allDetails=1 - -# Add READ for all AWS users, and READ_ACP for everyone -echo <> acl -Group Authenticated AWS Users READ -EOF -echo <> acl -Group All Users READ_ACP -EOF -echo "$S3_COMMAND setacl $TEST_BUCKET/aclkey filename=acl" -$S3_COMMAND setacl $TEST_BUCKET/aclkey filename=acl - -# Test to make sure that it worked -rm -f acl_new -echo "$S3_COMMAND getacl $TEST_BUCKET/aclkey filename=acl_new allDetails=1" -$S3_COMMAND getacl $TEST_BUCKET/aclkey filename=acl_new allDetails=1 -diff acl acl_new -rm -f acl acl_new - -# Remove the test file -echo "$S3_COMMAND delete $TEST_BUCKET/aclkey" -$S3_COMMAND delete $TEST_BUCKET/aclkey -echo "$S3_COMMAND delete $TEST_BUCKET" -$S3_COMMAND delete $TEST_BUCKET