commit 8d2a0b593ed03c6880bd668af6ea33b8128a3408 Author: Mario Fetka Date: Mon Jan 7 14:06:15 2019 +0100 Imported Upstream version 11.2 diff --git a/.version b/.version new file mode 100644 index 0000000..3913853 --- /dev/null +++ b/.version @@ -0,0 +1 @@ +11.2 \ No newline at end of file diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..5d68c7c --- /dev/null +++ b/AUTHORS @@ -0,0 +1,27 @@ +SnapRAID AUTHORS +================ + +The author of SnapRAID is Andrea Mazzoleni. + +You can contact me sending an email at: + + amadvance@gmail.com + +Please don't send support requests at this address, but use the +SnapRAID Forum. + + +ACKNOWLEDGMENTS +=============== + +Special thanks to Leifi, the king of the Forum! + +Thanks for the testing, suggestions and bug reports to klbl, +jwill42, tholiin, uhclem, reardonia, Jens, rubylaser and the +whole SnapRAID Forum. + +Thanks to Maxim Tikhonov for making the Ubuntu packages. + +Also thanks for the support to Ben_in_COSprings, Darin, micksh, RamanRB +and the whole AVS Forum. + diff --git a/CHECK b/CHECK new file mode 100644 index 0000000..f0be0ab --- /dev/null +++ b/CHECK @@ -0,0 +1,32 @@ +SnapRAID CHECK +============== + +The regression test of SnapRAID is run using the command: + + make check + +You can also run the regression test in valgrind with: + + ./configure --enable-valgrind + make check + +To run a coverage test you should use: + + ./configure --enable-coverage + make lcov_reset + make check + make lcov_capture + make lcov_html + +and open the file ./cov/index.html in your browser to see the results. + +Please note that in the coverage analysis we exclude the handling of all +the error conditions that result in an immediate termination of the program. +You can recognize this excluded code because it's enclosed between +the LCOV_EXCL_START and LCOV_EXCL_STOP keywords. + +To test with the clang static analyzer use: + + scan-build ./configure + scan-build make + diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + 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/HISTORY b/HISTORY new file mode 100644 index 0000000..2cb15d9 --- /dev/null +++ b/HISTORY @@ -0,0 +1,763 @@ +SnapRAID HISTORY +================ + +11.2 2017/12 +============ + * Fixed recognition of NTFS hardlinks. They behave differently than + standard Unix hardlinks and this could result in SnapRAID reporting + internal inconsistency errors for detecting links to the same file + with different metadata attributes. + * More efficient 'pool' command that updates only the links + that need to be updated. This ensures that no change is + done, avoiding to trigger a directory rescan of other programs. + * In Linux use by default the advise "discard" mode instead of "flush". + This avoids to swap-out the other process memory, leaving the system + more responsive. + * Changed the fallocate() use to work better with Btrfs with parity disks. + * Changed the --test-io-stats screen to print the file name in process + for each disk. + +11.1 2017/05 +============ + * Fixed the check command to correctly ignore errors on unused parity. + This was broken in version 9.0. + * Allow increasing the number of parity splits of existing parity. + * Fixed quoting when printing in Linux. This fixes the UTF-8 screen + output. Windows version was not affected. + * Fixed recognition of 'hashsize' in the configuration file. + The previous incorrect 'hash_size' is still supported for backward + compatibility. + * Fixed building in platforms that don't provide major/minor definitions + in sys/types.h. + * When creating 'pool' symbolic links, set their time as the linked files. + * Added support for the Windows 10 symbolic link unprivileged creation, + using SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE. + * Windows binaries built with gcc 4.9.4 using the MXE cross compiler at + commit ae56efa2b23a793b0146508bfef33027cdb09fd2 with targets + i686-w64-mingw32 and x86_64-w64-mingw32 and optimization -O2. + +11.0 2016/11 +============ + * Added support for splitting the parity in multiple partitions. You + can now specify multiple files for a single parity. As soon a file + cannot grow anymore, the next one starts growing. + In the configuration file, just put more files in the same 'parity' + line, separated by , (comma). + Note that if this feature is used, the saved content file won't be + read by older SnapRAID versions. + In Windows, 256 MB are left free in each disk to avoid the warning + about full disks. + * Added a new 'hashsize' configuration option. It could be useful in + systems with low memory, to reduce the memory usage. + Note that if this feature is used, the saved content file won't be + read by older SnapRAID versions. + * In Linux added the missing support for Btrfs file-systems. Note that + to have full support you need also the 'libblkid' library, otherwise + you won't get the UUIDs. + * In screen messages don't print the disk directory in file path. You + can control the format with the test option: + --test-fmt file|disk|path. + * In Windows allows to use the escape char '^' to handle file patterns + containing real characters matching the globbing '*?[]' ones. In Unix + it was already possible to do the same escaping with '\'. + * Added a new -R, --force-realloc option to reallocate all the + parity information keeping the precomputed hash. + This is the previous -F, --force-full that instead now maintains the + same parity organization and just recomputes it. + * Added test options for selecting the file advise mode to use: + --test-io-advise-none for standard mode + --test-io-advise-sequential advise sequential access (Linux/Windows) + --test-io-advise-flush flush cache after every operation (Linux) + --test-io-advise-flush-window flush cache every 8 MB (Linux) + --test-io-advise-discard discard cache after every operation (Linux) + --test-io-advise-discard-window discard cache every 8 MB (Linux) + --test-io-advise-direct use direct/unbuffered mode (Linux/Windows) + The new default mode is 'flush' in Linux (before it was 'sequential'), + and 'sequential' in Windows (like before). + * For Seagate SMR (Shingled Magnetic Recording) ignore the SMART + attribute Command_Timeout 188 as not reliable. + * Fixed running in Windows platforms that miss the RtlGenRandom() + function. + * Added the --test-io-cache=1 option to disable the multi-thread IO + mode. + +10.0 2016/02 +============ + * Boosts the speed of the 'sync' and 'scrub' commands with a new + multi-thread implementation. It uses one thread for each disk, + dedicated exclusively to read-ahead data and parity and to + write-behind parity. This maximizes the data throughput keeping + disks always busy. + You can control the number of blocks to cache with the option + --test-io-cache=NUMBER, where the number is between 3 and 128. + The default is 8 MiB of blocks. + You can show run-time stats during the process with the + --test-io-stats option. You will see a graph with the number of + cached blocks, and a graph with the wait time percentage for all the + disks and computations. + * The -h, --pre-hash command, saves the content file only after having + verified all the hashes. This allows recovering of moved files in + case a silent error is found during the hash verification check. + * Allows to use the -d, --filter-disk option in the 'up' and 'down' + commands. + * Allows to run the 'smart' command without a configuration file. + In such case it operates on all the disks of the machine. + * In the configuration file 'data' is now a synonymous of 'disk'. + * Adds the 'touch' command intended to arbitrarily set all the zero + sub-second timestamps. This improves the SnapRAID capabilities to + identify files. The 'status' command recommends to run 'touch' if + required. + * Restores the functionality of the -D, --force-device option when used + to workaround the use of the same disk for two logical data drives + when running the 'fix' command. + * Uses a correct shell quoting in the example commands that involve + files. + * The minimum Windows version supported is now Windows Vista. This is + required to use the native Windows thread support for the new + multi-thread implementation. If you need to run on Windows XP, you + have to stick on SnapRAID 9.x. + +9.3 2016/01 +=========== + * Fixes an invalid assumption in the copy detection mechanism that + could result in an internal inconsistency, and with the impossibility + to run the 'sync' and 'diff' commands. + This was triggered by a very specific pattern of identical files. + At least three of them, with one already in the parity, and at a + higher disk number than the others that should be instead new ones. + This had no bad effect, if not preventing the 'sync' command to run. + A workaround was to just run 'sync' one time with the -N, + --force-nocopy option to disable the copy detection. + * Restored the -O2 optimization option for Windows binaries, as -Og has + a too big performance penality. + +9.2 2016/01 +=========== + * Fixes support for symlinks pointing to an empty target. Before they + were only partially supported, and their presence could result in a + content file not readable. + This also disables multi-thread content write, as this was the issue + we tried to detect with this feature, and it doesn't provide a + performance advantage. Content verification is instead still multi + thread. + * Autorename disks using the matching UUID. To rename a disk you can + now change directly the name in the configuration file, and run a + 'sync' command. + * Improves the physical offset ordering for the Btrfs file-system, + correctly detecting files that have not a physical offset, for + whatever reason. + * Adds UUID support to Btrfs file-systems. It's present only if the + 'libblkid' development library is available on the system. + Usually this requires to install the libblkid-dev or libblkid-devel + package. + * Added a new --no-warnings option to disable some repetitive warnings + that could be annoying to power users. + * Improves the error reporting, printing a complete stack trace, that + can be used to track down bugs more easily. + For this reason the Windows binaries are now built with optimization + option -Og, instead than -O2. + +9.1 2015/11 +=========== + * Fixes a bug when reading a content file with a deleted entry bigger + than 4 GB. This was a regression introduced in version 9.0 that could + result in the impossibility to read a valid content file, after a + deletion of a file bigger than 4 GB in the array. + If this happened to you, just upgrading to 9.1 fixes the issue, and + it allows you to continue to work. + Note that this bug only prevented to run 9.0, but your data was still + protected and could have been recovered using the versions 8.1 or + 9.1. + * In Windows disables the file zero check requiring the --force-zero + option. This check is intended for possible case using ext3/4 in + Linux, and there is no evidence that in Windows it's possible at all. + * Windows binaries built with gcc 4.9.3 using the MXE cross compiler at + commit 62bcdbee56e87c81f1faa105b8777a5879d4e2e with targets + i686-w64-mingw32 and x86_64-w64-mingw32 and optimization -O2. + +9.0 2015/11 +=========== + * Fixes an invalid assumption that could happen when using the -e, + --filter-error option with "fix" or "check". + This was triggered by a very specific pattern of fragmented files + and bad blocks combination, not so easy to reproduce. + This had no bad effect, if not preventing the command to run. + * Drastically reduces the memory usage. For each block, it now uses 17 + bytes of memory, instead of the previous 28 bytes (for 32 bit) or 36 + bytes (for 64 bit). + This could result is a memory saving of up the 50%. + * The -p, --plan option (old --percentage) can be used to define a + scrub plan: "new", "bad" and "full". + The "new" plan scrubs all the new synced blocks not yet scrubbed. + This allows to verify as early as possible that the written parity + during sync is really correct. You can use the "status" command to + show the amount blocks not yet scrubbed. + The "bad" plan scrubs only bad blocks. + The "full" plan scrubs all blocks. + * The graph in the "status" command now show scrubbed blocks with '*', + and synced, but not yet scrubbed, blocks with 'o'. + Note that when upgrading from a previous version, all blocks are + assumed scrubbed the first time. + * Content files are now written asynchronously from different threads + to avoid the unfortunate condition that a memory error affects all of + them in the same way. + After writing, they are read again to verify their CRC. + This is done to ensure that they are really OK, even in the case of + the worst possible silent errors. + * Extends the -D, --force-device option to ignore more erroneous + conditions in the 'fix' command, like inaccessible disks, or disks + sharing the same physical device. + * Extends the -d, --filter-disk option to allow to filter also by + parity disk. + * Extends the -h, --pre-hash option to also verify moved and copied + files into the array before running a 'sync'. + * Updates 'best' RAID functions for recent Atom CPUs. + * Validates filters specifications rejecting relative paths. + +8.1 2015/05 +=========== + * Fixes build issues in generic Unix platforms, including Mac OS X. + * The "diff" command returns with error code 2 if a "sync" is required, + to differentiate with the generic error code 1. + * Reduces the effect of SMART attribute 193 on the failure probability + to avoid some false positive reports. + +8.0 2015/04 +=========== + * Allows "sync" and "scrub" to continue after the first bunch of disk + errors. Blocks with errors are marked as bad, and you can fix them + with the "fix -e" command. + The fix is expected to force the disk firmware to reallocate the + bad sector, likely fixing the problem. + You can control the number of allowed errors with the new + -L, --error-limit option. The default is 100. + * The -e, --filter-error option doesn't write anymore fixes to + unsynced files. This helps in case you are running it on a not + synced array, removing the risk to revert some files to an old state. + * The -e, --filter-error option is now optimal and reads only the + minimal amount of data necessary to fix the errors. + * The "diff" command returns with an error code if a "sync" is + required. + * Adds new "smart" command to print a SMART report of the array. + * Adds new "up" and "down" commands to spin up and down the disks of + the array. + * Adds new "devices" command to print the devices associations in the + array. + * Changes the log handling. If no log file is specified, all the + warnings and not fatal errors messages goes to stderr. If a log file + is specified, only fatal error messages are printed on the screen. + You can control the amount of informative messages on stdout with + the -q, --quiet and -v, --verbose options, that can be specified + multiple times to be more quiet or verbose. + * In the "status" command the "Wasted" column now shows a negative + number for the amount of space that you can still waste without + filling up the parity. + * In the "status" and others commands we now use GB instead of GiB, + when referring to disk space. + * Renames the -s and -t options to -S and -B as they are intended to + be manual only operations. + * Windows binary built with gcc 4.8.1 using the MXE cross compiler + 2.23, with targets i686-w64-mingw32 and x86_64-w64-mingw32. Before + the x86 target was i686-pc-mingw32. + +7.1 2015/01 +=========== + * In 'scrub' and 'sync' detects and reports Input/Output errors + separately from generic file system errors. + * In 'diff' doesn't print the "add" entry if a "copy" one is already + printed. + * Fixes build with old compilers in the x64 platforms [Leigh Phillips]. + * Fixes out-of-dir builds [Christoph Junghans]. + +7.0 2014/11 +=========== + * In 'check' and 'fix' the array is scanned to find any moved files + that could be used to recover missing data. Files are identified by + time-stamp, and then they are recognized also if moved to a different + disk. Note that even if there are false positive they are identified + checking the hash, so they have not effect, besides making the + process a little slower. To disable this new behavior you can use + the -N, --force-nocopy option. + * The -i, --import command now identifies files by time-stamp making it + very fast in importing directories. + * More detailed 'status' report with single disk stats and free space + available. + * A lot faster directory listing for Windows. + * Adds AVX2 support to improve parity generation speed. + * Prints the time spent waiting for each disk also in 'scrub'. + * The CPU usage, speed and ETA estimations are now based on the last + 100 seconds rather than from the start. + * Keeps track of the UUID of the parity disks to check them before + operating. + * Windows binary built with gcc 4.8.1 using the MXE cross compiler + 2.23. + +6.4 2014/11 +=========== + * Adds support for the new binary format of SnapRAID 7.0. + This allows to downgrade from version 7.0 to 6.x or previous. + +6.3 2014/7 +========== + * The -N, --force-nocopy option now also works if you used previously + "sync" commands without it. + * In 'sync' keeps stats about the amount of time spent waiting for each + disk and what is spent in CPU computation. + * Auto exclude the lock file. + * A more precise counting of how may block to scrub. Now it's exact + regardless the order of the blocks timing. + * Don't prints the 'UUID set' message anymore because it's the normal + condition for empty disks. + * In Windows, if the disk doesn't support reading physical offsets, + allows SnapRAID to continue anyway. + * Added a new -F, --force-full option that forces a full sync reusing + the hash data present in the content file. + +6.2 2014/5 +========== + * Fixed the regression test when run as root. + * Added a new heuristic to detect file copies. Now a file is assumed + to be a copy if name, size and nanosecond time-stamp are matching, + but if the nanosecond part of the time-stamp is 0, it requires + the full path matching and not only the name. + * Added the -N, --force-nocopy option to disable completely the copy + detection. SnapRAID also suggests to use this option in the error + message of a data mismatch if likely caused by the copy detection. + +6.1 2014/4 +========== + * Fixed build and regression test in Mac OS X. + +6.0 2014/3 +========== + * In "sync", even if a silent error is found, continue to update the + parity if it's possible to correct the error. + Note that the block will be marked bad, and the data will be fixed + only at the next "fix -e" call. + But any new data added will be protected if you are using enough + parity to fix both the silent error and at least another potential + error. + * Detect copied files from one disk to another and reuse the already + computed hash information to validate them in "sync". + Files are assumed copied if they matches the name, size and + time-stamp. + * For "sync", added a new -h, --pre-hash option to run a preliminary + hashing step for all the new files to ensure to detect silent errors + caused by the heavy machine usage of the parity computation. + * In "fix", if a previous fixing attempt was made resulting in a + .unrecoverable file, uses this file as starting point for the + new attempt. + * In the log file name allows the use of the '>>', %D, %T modifiers + to select append mode, and to insert the date and time in the name. + * The options -p, --percentage and -o, --older-than now keep their + default value even if the other one is specified. + * Moved the .lock file in the same dir of the first specified content + file. This avoid to spin-up the parity disks in all commands. + * The "diff", "list", "dup", "status" and "pool" commands don't access + anymore the parity disks that can now stay powered down. + * The default configuration file in Windows is now searched in the same + directory where the snapraid.exe file resides. + * New source code organization. The RAID engine is now an external + component usable also in other projects. + +5.3 2014/3 +========== + * Don't warn about UUID changed if it's for an empty disk. + * Fixed the number of blocks that scrub has to process when + selecting a high percentage of the array. + * Removed duplicate recovery attempts in synced state. + +5.2 2013/12 +=========== + * If a disk changes UUID, automatically disable the inode + recognition, because this is likely a new file-system with + all the inodes reassigned, and we don't want to risk a false + positive when searching for inode/time-stamp/size. + * Allow to run a fix command with disks that doesn't need to be + fixed mounted as read-only. + * After a failed sync, always reallocates new files with a not + yet computed parity to ensure to minimize the parity usage, + if some other file is deleted in the meantime. + * Doesn't count empty dirs as files in the diff counters. + * Added a new "share" configuration option to allow to share + in the network the pool directory also in Windows. + * Fixed build problems in OpenBSD due the old assembler. + * Fixed build problems in platforms different than x86. + +5.1 2013/12 +=========== + * Fixed a potential crash if a file is deleted during a "sync/scrub". + This is a problem introduced in version 5.0 due new logging. + If happened to you to have a crash in sync, you don't need to take + any special action, just run "sync" again. + * Restored the functionality of -C, --gen-conf command. + * Prints the files with duplicate physical offset if the -v, --verbose + option is specified. + +5.0 2013/11 +=========== + * Added support for up to six levels of parity. + * Added a specific and faster triple parity format for CPUs that + don't support SSSE3 instructions like ARM and AMD Phenom, Athlon + and Opteron. + * Faster RAID5 and RAID6 implementation for ARM 64 bit CPUs. + * If a silent error is found during a "sync" command, directly marks + the block as bad like in "scrub", without stopping the the "sync" + process. + * Sort files by inode when listing the directory. This improves + the scanning performance. + * For files with changes only in some blocks, updates the parity + only for blocks that really are changed. + This improves the performance in sync for modified files. + * Added a new "list" command to see the stored list of files. + * Removed the detailed list of errors from the screen output. + To get it you must explicitly use the -l, --log option. + It's now too detailed for the screen, because it contains a lot + of info. + * Changed the output format of some commands to make it similar + at the new "list" one. + * Reduced memory usage removing some unnecessary allocations. + * Added a memory test on the memory buffers used in sync, scrub, check, + fix before using them. + +4.4 2013/10 +=========== + * Relaxed the check about small parity files, to allow to recover after + a failed sync before resizing the parity files. + +4.3 2013/10 +=========== + * Fixed the scrub command with the -p0 option. Now it really scrubs + only the blocks marked as bad and not the full array. + +4.2 2013/10 +=========== + * Fixed the wrong warning about physical offsets not supported caused + by files not having a real offset because too small. + For example, in NTFS it's possible to store such files in the MFT. + It's just a cosmetic change, and not a functional one. + * Remove unexpected 'Restore' entries in the diff output when dealing + with file-system without persistent inodes like NTFS in Linux. + * Added support for filenames containing newlines. This happens in Mac + OS X. + +4.1 2013/9 +========== + * If the underline file-system doesn't support the FIEMAP command, + automatically fall back to use FIBMAP for sorting files. + * Fixed the import of content files from previous version of SnapRAID + that are the result of an incomplete sync. + * Added a new -C, --gen-conf option to generate a dummy configuration + file from the info in the content file. + Just in case that you lose everything, except the content file. + * At the end of sync/scrub/check/fix prints "Everything OK" if no error + was found. This should make clear that everything is really OK. + +4.0 2013/9 +========== + * New 'scrub' command to periodically check the oldest blocks for + silent errors without the need to scan the whole array. + * New 'status' command to check the fragmentation, the last check time + distribution, and the silent error status of the array. + * Added the new Spooky hash. It's faster in 64 bit architectures. + To convert you can use the new 'rehash' command. + * Changed to a binary content file to improve speed and reduce size. + * Removed the --find-by-name, -N option. Now it always searches + by name if a file is not found searching by inode, automatically + reassigning inodes in restored files without needing to sync + again the file. + This happens only if the file has the same path, size and timestamp + at nanosecond precision. + * Added a hash seed to make harder intentional collision attacks. + * When inserting files for the first time, sort them by their physical + address to improve read performance. + * Optimized the cache use for the all the RAID computations. + This improves a lot the RAID performance. + * Better selection of the RAID6 implementation for different CPUs. + * Added RAID5/RAID6 mmx and sse2 implementations with unrolling by 4. + They are a little faster than the previous unroll by 2. + * Added a lock file to avoid multiple running instances on the same + array. The file is named as parity file adding the .lock extension. + There is also the undocumented --test-skip-lock to avoid to check it. + * Automatically ignores, with warning, mount points inside the array + directory tree. + * Changes the 'dup' output format to include the size of each duplicate + file. + +3.2 2013/7 +========== + * Fixed a directory creation problem in Windows when the "disk" option + points to the root directory of a drive. Now SnapRAID won't complain + about the inability to create such directory. + If you encounter this problem when trying to recover your data, just + upgrade to this version, and you'll be able to complete the + recovering process. + No need to upgrade for platforms different than Windows. + +3.1 2013/5 +========== + * Direct use of Windows API for disk access to improve error reporting. + * If the 'fix' process is aborted, it removes all the new files + partially recovered, to allow to reuse again the -m, --filter-missing + flag. + * In Windows don't exclude anymore system files. Only system + directories are excluded. + * In Windows applies filters in case insensitive way. + * The Windows binaries are now built with gcc 4.7.2. + * Reduced memory occupation for hardlinks and directories. + * In 'dup' don't list files with 0 size. + +3.0 2013/3 +========== + * Added pooling support with the new 'pool' command. It creates a + virtual view of the array using symbolic links pointing to the + original files. + * Added a new -m, --filter-missing option that allow to undelete files, + without checking/fixing the others. + * Added a new -i, --import option to automatically import deleted files + when fixing. + * Added a new -l, --log option to save to disk the detailed log. + * Added support for hardlinks and empty directories. + * Added support to save symlinks to files in Windows. Note that only + the symlink is saved and not the linked file. + Note that Windows Symlinks to dirs and junctions are still not + supported. + * Files without read permission generate an error instead of a warning. + You now must explicitly exclude them in the configuration file with + exclusion rules. + * In 'check' and 'fix', if verbose is enabled, prints the result for + each processed file. + * Added an UUID check to detect when a disk is replaced, and to prevent + unwanted disk swaps. + +2.1 2013/1 +========== + * Checks for wrong empty fields in the configuration file. + * Filter rules for files are not anymore applied to directories. + +2.0 2012/12 +=========== + * Added a new -a option to make the 'check' command to only check file + hashes without checking the parity data. + * Added a new -d option to filter by disk name. + * The file modification time is now saved using nanosecond precision. + This allows to restore the exact modification time in 'fix'. + The new 'content' files written with this version are not backward + compatible, but it's still possible to read the old format. + * Fixed hard-links automatic exclusion. All the hardlinks after the + first one are now correctly ignored. + * If it isn't possible to grow a parity file, prints the list of files + outside the maximum size allocated. + * Autosave isn't triggered if we are near the end of the 'sync' + process. + * Before starting a 'sync', we wait for two seconds, to workaround the + FAT limitation of having two seconds modification time precision. + This a safe measure to be 100% sure to always detect file changes. + * Always fill the memory after allocating it to avoid the OOM (Out Of + Memory) killer in Linux. + * Fixed compilation in Solaris/OpenIndiana for lacking both futimes() + and futimens(). + * Now 'sync' ensures that the parity files are not too small to contain + the just loaded data. + * Removed the '-H,--filter-nohidden' option. It doesn't make sense to + have it as command line option. + You must use the 'nohidden' option in the configuration file. + * When opening files in read-only mode, also specify the noatime flag, + to avoid to update the file access time. + * Exclude rules for files are now also applied to directories. + This allows to excludes some file/directory without the need to call + the stat() function on them. + * The -N, --find-by-name option also ignores the nanosecond part of + timestamps to work with copy programs not supporting nanoseconds. + * Fixed deduplicated files handling in Windows Server 2012. + * Removed MD5 support. + +1.13 2012/11 +============ + * Fixed a Segmentation Fault when checking/fixing if there are three + or more errors in a specific block. + +1.12 2012/9 +=========== + * Fixed file renaming in Windows during a 'fix' command. + This is only a Windows only issue, no reason to upgrade for other + platforms. + +1.11 2012/7 +=========== + * Fixed again directories inclusion. Exclusion rules for directories + were ignored. + +1.10 2012/6 +=========== + * Fixed directory inclusion, in case the last rule is an "include" one. + * Fixed very long paths in Windows. We now always use the special '\\?' + prefix to remove the 260 chars limitation. + * If a file is excluded, it prints explicitly which attribute caused + the exclusion. + * Automatically excludes also the temporary copy of content file, + the one with the ".tmp" extension. + * Avoid Windows to go in automatic sleep mode when running. + +1.9 2012/3 +========== + * Implemented a more sophisticated recovering in case a harddisk + failure happens during a 'sync' command. + When using RAID6 it improves the chances of recovering data with + partially computed parity, after an aborted 'sync'. + * Fixed the count of new files. + * Added a new 'autosave' configuration option to save the intermediate + 'sync' state. + * Supported file-systems with read requests returning less data than + requested. + * In Windows ensures that the disk serial number is not zero. + +1.8 2012/1 +========== + * Added a new "dup" command to find all the duplicate files. + * Added a new option "--filter-nohidden" to exclude hidden files. + * Faster and parallel writing of content files. + * The example configuration files now put the content files in the data + disks instead than in the parity disks. + * Added a checksum at the content file to ensure its integrity. + * Using fallocate() instead posix_fallocate() to avoid the very slow + posix_fallocate() fall back of writing the whole file. + +1.7 2011/11 +=========== + * If a file is modified or removed during a sync, the sync process + doesn't stop anymore, but it will simply skip the file, resulting in + an incomplete sync. Note that the sync will terminate with an error. + * If the content file is placed in a data disk, it's automatically + excluded from the sync process. + * Increased by one the minimum number of content files. Before it was + only a suggestion, but now it's a requirement because you are allowed + to put content files in data disks. + * Added checks to ensure that data and parity disks are different, and + to correctly count the number of copies of "content" files in + different disks. + * Removed the dependency of the "disk" order specification in the + configuration file. The used order is now saved in the content file + to avoid to damage the dual parity in case the order is changed by + the user. It easily allows to remove or add disks from the array when + using a dual parity. + * Improved the "fix" performance when a lot of files or the parity have + to be recreated from scratch. + * When getting unrecoverable errors, the printed log line now starts + with "unrecoverable:" instead of "error:" to allow an easier + identification. + * Added a new option "--find-by-name" to allow to sync using only the + file path and not the inode. This is useful to avoid long sync when + you replace one disk with another copying manually the files. + * If "fix" cannot recover a file, it's renamed adding the + ".unrecoverable" extension. + * Checking and fixing also empty files with size 0. + +1.6 2011/9 +========== + * The content file is now saved also at the start of the "sync" + command. This avoids parity errors if the sync process is aborted + without saving the content file and you made changes at the disk + array before another "sync" command was done. + More specifically, deletions or truncations of not yet synced files + after the aborted sync, and before the next sync command, may have + damaged the parity data. New file additions were instead safe. + If these conditions may have happened to you a "check" command (also + with older version of the program) is recommended to ensure the + correctness of your parity data. + * The "diff" command now recognizes the reuse of inodes. + * Windows hidden files are now saved like any other files. + * Symbolic links are now saved in *nix. Not supported in Windows. + * The "fix" command restores also the original modification time. + * The message asking to use the --force-empty option now lists all the + empty disks. + +1.5 2011/7 +========== + * Ignores extra spaces in the configuration file. + * Changed the output of check/fix to allow a more easy post-processing + with other tools like awk and sort. + * Added the hidden option -G/--gui to enable the output of progress + information for a potential GUI for SnapRAID. + * Added a new "diff" command to print the list of changes detected at + file level. + * Faster loading of content file. Approx three times faster. + +1.4 2011/6 +========== + * Ignoring in sync System and Hidden files in Windows. + * Files without read permission are ignored in sync. + * If a file is ignored a warning message is printed. You have to + exclude it to remove the warning. + * In fixing, if a file cannot be written for missing permission, an + error is reported only if a write is effectively required. + * Ignores any symbolic links. They are not saved. + +1.3 2011/5 +========== + * Fixed the restore of directory with unicode chars in Windows. + * Fixed support of file names starting or ending with a space. + * Removes files before inserting new ones to minimize the parity size. + +1.2 2011/5 +========== + * Fixed use of file names out of the codepage in Windows. All the names + are now stored in UTF8 in the content file. + +1.1 2011/5 +========== + * Fixed a bug in the check command when detecting garbage data over the + expected end of the file. + The parity data was anyway computed correctly, and no special action + is required to update. + * Changed the default checksum to Murmur3 hash. It's a lot faster than + MD5. You can check its speed with the "snapraid -T" command. + MD5 is still supported for backward compatibility. + To convert to the new Murmur3 hash, simply remove the 'content' file, + and start a new complete 'sync'. + * Added RAID6 support. It's used the very good RAID6 library made by H. + Peter Anvin also used in the Linux Kernel. It contains optimized + implementations for SSE2 and MMX. + * Added support for multiple 'content' files. You can save extra copies + to be able to verify the checksums also if you lose all the 'content' + files in the parity disks. + * Added a filtering include logic, where anything not explicitly + included is excluded. For example, it allow to include only the files + in a predefined set of directories. + * The check command returns with an error code if any kind of error is + present. Previously it was returning an error only if unrecoverable + errors were present. + * Opening the files in sequential mode in Windows. This should give a + speedup in Windows. + * In Windows you can use the backslash \ in the filter definitions + instead of the forward slash /. + +1.0 2011/4 +========== + * No relevant change. + +0.4 2011/4 +========== + * Added hidden 'dry' command mainly for speed measurement. + * As default, uses the OpenSSL crypto MD5 implementation. + +0.3 2011/4 +========== + * Added --filter option to select a subset of file in check and fix. + * Better ETA estimation in all the commands. + * Added support for OpenSSL crypto library to use its optimized MD5 + implementation. + * Added test vectors and a speed test for MD5. + +0.2 2011/3 +========== + * Second public test release of SnapRAID. + * Functionally complete in check and fix. + * Files are identified by inode and not anymore by name. + * Exclusion list of files and directories. + * Precise error management. + * More regression tests. + +0.1 2011/3 +========== + * First public test release of SnapRAID. diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..f210349 --- /dev/null +++ b/INSTALL @@ -0,0 +1,31 @@ +SnapRAID INSTALL +================ + +To build and install SnapRAID you need to download the source +code from http://www.snapraid.it and unpack it with: + + tar xf snapraid-*.tar.gz + cd snapraid-* + +To configure and build run: + + ./configure + make + +To check for correctness of the application run: + + make check + +If it terminates with "Success", you can install the application and +the documentation running as root: + + sudo make install + +To start using SnapRAID you have to change the example configuration +file snapraid.conf.example to fit your needs and copy it in /etc/snapraid.conf + +To get more help, see the "Getting Started" section in the snapraid manpage +typing: + + man snapraid + diff --git a/INSTALL.windows b/INSTALL.windows new file mode 100644 index 0000000..bd0c21e --- /dev/null +++ b/INSTALL.windows @@ -0,0 +1,9 @@ +SnapRAID INSTALL for Windows +============================ + +To start using SnapRAID you have to change the example configuration +file snapraid.conf.example to fit your needs and copy it with the +name snapraid.conf in the directory where you run snapraid.exe. + +To get more help, see the "Getting Started" section in snapraid.txt. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..4c0c167 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,1039 @@ +bin_PROGRAMS = snapraid +check_PROGRAMS = mktest mkstream + +AM_CPPFLAGS = -DSYSCONFDIR="\"${sysconfdir}\"" + +snapraid_SOURCES = \ + raid/raid.c \ + raid/check.c \ + raid/module.c \ + raid/tables.c \ + raid/int.c \ + raid/x86.c \ + raid/intz.c \ + raid/x86z.c \ + raid/helper.c \ + raid/memory.c \ + raid/test.c \ + raid/tag.c \ + tommyds/tommy.c \ + cmdline/snapraid.c \ + cmdline/io.c \ + cmdline/util.c \ + cmdline/stream.c \ + cmdline/support.c \ + cmdline/elem.c \ + cmdline/state.c \ + cmdline/scan.c \ + cmdline/sync.c \ + cmdline/check.c \ + cmdline/dry.c \ + cmdline/rehash.c \ + cmdline/scrub.c \ + cmdline/status.c \ + cmdline/dup.c \ + cmdline/list.c \ + cmdline/pool.c \ + cmdline/parity.c \ + cmdline/handle.c \ + cmdline/touch.c \ + cmdline/device.c \ + cmdline/fnmatch.c \ + cmdline/selftest.c \ + cmdline/speed.c \ + cmdline/import.c \ + cmdline/search.c \ + cmdline/mingw.c \ + cmdline/unix.c + +noinst_HEADERS = \ + raid/raid.h \ + raid/helper.h \ + raid/internal.h \ + raid/cpu.h \ + raid/gf.h \ + raid/combo.h \ + raid/memory.h \ + raid/test.h \ + tommyds/tommyarray.h \ + tommyds/tommyarrayblkof.h \ + tommyds/tommychain.h \ + tommyds/tommyhash.h \ + tommyds/tommyhashdyn.h \ + tommyds/tommylist.h \ + tommyds/tommytree.h \ + tommyds/tommytypes.h \ + tommyds/tommyarray.c \ + tommyds/tommyarrayblkof.c \ + tommyds/tommyhash.c \ + tommyds/tommyhashdyn.c \ + tommyds/tommylist.c \ + tommyds/tommytree.c \ + cmdline/portable.h \ + cmdline/snapraid.h \ + cmdline/io.h \ + cmdline/util.h \ + cmdline/stream.h \ + cmdline/support.h \ + cmdline/elem.h \ + cmdline/state.h \ + cmdline/parity.h \ + cmdline/handle.h \ + cmdline/murmur3.c \ + cmdline/murmur3test.c \ + cmdline/spooky2.c \ + cmdline/spooky2test.c \ + cmdline/fnmatch.h \ + cmdline/import.h \ + cmdline/search.h \ + cmdline/mingw.h \ + cmdline/unix.h + +mktest_SOURCES = \ + cmdline/mktest.c \ + cmdline/mingw.c \ + cmdline/unix.c \ + cmdline/support.c + +mkstream_SOURCES = \ + cmdline/mkstream.c \ + cmdline/mingw.c \ + cmdline/unix.c \ + cmdline/support.c \ + cmdline/util.c \ + cmdline/stream.c \ + raid/memory.c + +# Add the .version file in the distribution +dist-hook: + $(srcdir)/autover.sh > $(distdir)/.version + +EXTRA_DIST = \ + autogen.sh autover.sh \ + README AUTHORS HISTORY INSTALL COPYING TODO CHECK INSTALL.windows \ + snapraid.d snapraid.1 snapraid.txt \ + test/test-par1.conf \ + test/test-par2.conf \ + test/test-par3.conf \ + test/test-par4.conf \ + test/test-par5.conf \ + test/test-par6.conf \ + test/test-par6-hole.conf \ + test/test-par6-noaccess.conf \ + test/test-par6-rename.conf \ + snapraid.conf.example \ + configure.windows-x86 configure.windows-x64 snapraid.conf.example.windows \ + acinclude.m4 \ + tommyds/LICENSE \ + raid/COPYING \ + raid/test/Makefile \ + raid/test/fulltest.c \ + raid/test/selftest.c \ + raid/test/speedtest.c \ + raid/test/invtest.c + +man_MANS = snapraid.1 + +clean-local: + rm -f valgrind.log callgrind.log cachegrind.log + rm -rf bench + rm -f test*.log output.log stream*.bin + rm -f cmdline/*.gcda cmdline/*.gcno cmdline/*.gcov + rm -f raid/*.gcda raid/*.gcno raid/*.gcov + rm -f tommyds/*.gcda tommyds/*.gcno tommyds/*.gcov + rm -f lcov.info + rm -f gmon.out + +maintainer-clean-local: + rm -f snapraid.1 snapraid.txt + +# Automatic testing + +# Common options +# --test-skip-device +# Is required to allow testing in the same disk +# +# --test-skip-self +# It just makes the test a little faster +CHECKFLAGS_COMMON = --test-skip-device --test-skip-self --test-force-progress --no-warnings --test-parity-limit=3333333 + +# --test-force-order-alpha +# Ensures to process files always in the same order despites +# the inode, physical location, and dir order assigned by the OS. +CHECKFLAGS_ALPHA = $(CHECKFLAGS_COMMON) --test-force-order-alpha + +# Physical offset options +CHECKFLAGS_PHYSICAL = $(CHECKFLAGS_COMMON) --test-force-order-physical -q -q -q + +# Verbose options +CHECKFLAGS_VERBOSE = $(CHECKFLAGS_ALPHA) -v -G + +# Quiet options +CHECKFLAGS = $(CHECKFLAGS_ALPHA) -q -q -q + +# Number of files to create +if !HAVE_MEMORY_CHECKER +if HAVE_POSIX +CHECKCOUNT = 1000 +else +CHECKCOUNT = 500 +endif +else +CHECKCOUNT = 500 +endif + +# Size of files to create +if !HAVE_MEMORY_CHECKER +CHECKSIZE = 4000 +else +CHECKSIZE = 100 +endif + +CONF = $(srcdir)/test/test-par6.conf +HOLE = $(srcdir)/test/test-par6-hole.conf +NOACCESS = $(srcdir)/test/test-par6-noaccess.conf +RENAME = $(srcdir)/test/test-par6-rename.conf +PAR1 = $(srcdir)/test/test-par1.conf +PAR2 = $(srcdir)/test/test-par2.conf +PAR3 = $(srcdir)/test/test-par3.conf +PAR4 = $(srcdir)/test/test-par4.conf +PAR5 = $(srcdir)/test/test-par5.conf +PAR6 = $(srcdir)/test/test-par6.conf +MSG = @echo ===== + +check-local: + rm -rf bench + rm -f test.log + mkdir bench + mkdir bench/disk1 + mkdir bench/disk2 + mkdir bench/disk3 + mkdir bench/disk4 + mkdir bench/disk5 + mkdir bench/disk6 + mkdir bench/pool + $(MSG) Stream + $(TESTENV) ./mkstream$(EXEEXT) +if HAVE_THREAD_CHECKER +#### THREAD TEST #### + $(MSG) Create some files + $(TESTENV) ./mktest$(EXEEXT) generate 1 6 $(CHECKCOUNT) $(CHECKSIZE) + $(MSG) Some commands that use threads +# First sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +# Remove, move and add some more + rm bench/disk4/a/9* + rm bench/disk5/a/9* + rm bench/disk6/a/9* + mv bench/disk1/a/9* bench/disk4/a + mv bench/disk2/a/9* bench/disk5/a + mv bench/disk3/a/9* bench/disk6/a + $(TESTENV) ./mktest$(EXEEXT) change 2 500 bench/disk2/b/* bench/disk3/b/* +# Sync again + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +# Other commands that uses threads + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) test-rewrite + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) scrub -p full + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) scrub -p full --test-io-cache 3 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) scrub -p full --test-io-cache 128 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync -F --test-io-cache 1 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) scrub -p full --test-io-cache 1 +else +#### COMMAND LINE #### + $(MSG) Pre test + $(TESTENV) ./snapraid$(EXEEXT) --test-skip-device -H + $(TESTENV) ./snapraid$(EXEEXT) --test-skip-device -V + $(TESTENV) ./snapraid$(EXEEXT) test + $(TESTENV) ./mktest$(EXEEXT) +if !HAVE_MEMORY_CHECKER +if HAVE_EMULATOR + $(MSG) Speed +# Run the self test in AVX2 + $(TESTENV_AVX2) ./snapraid$(EXEEXT) --test-skip-device -c $(CONF) status +# Run the speed test in different architectures + $(TESTENV_SSE2) ./snapraid$(EXEEXT) --test-skip-device -T + $(TESTENV_SSSE3) ./snapraid$(EXEEXT) --test-skip-device -T + $(TESTENV_SSE42) ./snapraid$(EXEEXT) --test-skip-device -T + $(TESTENV_AVX2) ./snapraid$(EXEEXT) --test-skip-device -T +else +# Run the self test natively + $(TESTENV) ./snapraid$(EXEEXT) --test-skip-device -c $(CONF) status +# Run the speed test natively + $(TESTENV) ./snapraid$(EXEEXT) --test-skip-device -T +endif +endif +#### EMPTY #### + $(MSG) Some commands with empty array + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) diff + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) dup + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) list > output.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status -l ">&1" + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status -l ">&2" + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status -l ">>test.log" + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status -l test-%D-%T.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) up + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) down -d parity -d disk1 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) devices + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) smart --no-warnings + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) smart --test-fake-device --test-expect-failure +if HAVE_POSIX + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) pool +endif + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -a check +#### CONTROLLED #### + $(MSG) Filesystem allocation test + head -c 8192 /dev/zero > bench/disk1/TEST +# Copy the file to trigger the copy optimization check + cp -a bench/disk1/TEST bench/disk2/TEST + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +# Now delete the file, and do a partial sync to force a deallocation in the middle of a file + rm bench/disk1/TEST + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -E -S 1 -B 1 sync +# Now force a deallocation at the end + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -E -S 7 -B 1 sync + rm bench/disk2/TEST +# Have the sync to fail for empty disk + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync --test-expect-failure +# Now sync will complete with -E + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -E sync + $(MSG) Filesystem fragmentation test + head -c 8192 /dev/zero > bench/disk1/TEST1 + head -c 8192 /dev/zero > bench/disk1/TEST2 + head -c 8192 /dev/zero > bench/disk1/TEST3 + head -c 8192 /dev/zero > bench/disk1/TEST4 + head -c 8192 /dev/zero > bench/disk1/TEST5 + head -c 8192 /dev/zero > bench/disk1/TEST6 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +# Now delete some files, and create a bigger one to fill the holes + rm bench/disk1/TEST1 + rm bench/disk1/TEST3 + rm bench/disk1/TEST5 + head -c 65536 /dev/zero > bench/disk1/TESTX + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync -l ">&1" + rm -r bench/disk1/TEST* + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -E sync +# Now enforce copy detection of a file without parity +# Create a file in a high number disk + head -c 8192 /dev/urandom > bench/disk6/STEP1 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +# Create two new copies. The one in disk1 will copy +# the hash from the one in disk6, and the one in disk2 +# will copy the hash from the one in disk1, that +# doesn't have parity + cp -a bench/disk6/STEP1 bench/disk1/STEP1 + cp -a bench/disk6/STEP1 bench/disk2/STEP1 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +# Now create, duplicate, move and partial sync + head -c 8192 /dev/zero > bench/disk1/INVA1 + head -c 8192 /dev/zero > bench/disk1/INVA2 + head -c 8192 /dev/zero > bench/disk1/INVA3 + head -c 8192 /dev/zero > bench/disk1/MOVE1 + cp -a bench/disk1/MOVE1 bench/disk1/MOVE2 + cp -a bench/disk1/MOVE1 bench/disk1/MOVE3 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + mv bench/disk1/MOVE2 bench/disk2/MOVE2 + mv bench/disk1/MOVE3 bench/disk3/MOVE3 + head -c 8192 /dev/zero > bench/disk4/MOVE4 + cp -a bench/disk1/INVA1 bench/disk1/EXTRA1 + cp -a bench/disk1/INVA2 bench/disk1/EXTRA2 + cp -a bench/disk1/INVA3 bench/disk1/EXTRA3 + rm bench/disk1/INVA1 + touch bench/disk1/INVA2 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-kill-after-sync sync +# Diff should report the need of a sync for invalid parity + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(PAR1) --test-expect-need-sync diff + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status + mv bench/disk2/MOVE2 bench/disk4/MOVE4 + mv bench/disk3/MOVE3 bench/disk5/MOVE5 + mv bench/disk4/MOVE4 bench/disk6/MOVE6 + rm bench/disk1/EXTRA1 + touch bench/disk1/EXTRA2 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -E sync +# Change UUID + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-fake-uuid sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +#### NOT EMPTY #### + $(MSG) Create some files + $(TESTENV) ./mktest$(EXEEXT) generate 1 6 $(CHECKCOUNT) $(CHECKSIZE) + echo DUP > bench/disk1/DUP1 + echo DUP > bench/disk1/DUP2 + echo -n > bench/disk1/ZERO + $(MSG) Some commands with a not empty array +# Run a sync using physical offset + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_PHYSICAL) -c $(CONF) --test-expect-need-sync diff > output.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_PHYSICAL) -c $(CONF) sync +# Now reset the array, as we normally test with alpha order and murmur3 + rm bench/content bench/?-content +# Now rebuild the array with alpha order and murmur3 and do some commands +# Later we will convert it to spooky2 to test both hashes + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) --test-expect-need-sync diff > output.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-force-murmur3 --test-force-autosave-at 100 sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) dup -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) list -l test.log > output.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) test-rewrite + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) test-read + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status -l test.log +if HAVE_POSIX + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) pool +endif + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -a check + $(MSG) Dry + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) test-dry + $(MSG) Copy detection +# Create a file and sync with it + echo 123 > bench/disk1/COPY + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +# Corrupt and move it to another disk + $(TESTENV) ./mktest$(EXEEXT) damage 1 1 1 bench/disk1/COPY + mv bench/disk1/COPY bench/disk2/COPY +# Now sync with failure as the data won't match. We have two points of failure, pre-hash and sync + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-expect-failure -h sync + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-expect-failure sync +# Now sync with force-nocopy + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --force-nocopy sync + $(MSG) Nano + touch -t 200102011234.56 bench/disk1/a/a* + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) touch + $(MSG) Check the --gen-conf command + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --gen-conf bench/content + $(MSG) Filter + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) -d disk1 check > output.log +if HAVE_POSIX +# Only in real unix, as with MingW the * trigger path replacement +# Like /b/a* -> B:/a* and SnapRAID then complain about relative paths + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) -f \\*a -f a/ -f /b/a\\* check > output.log +endif + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) --test-expect-failure -f . check > output.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) --test-expect-failure -f ./ check > output.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) --test-expect-failure -f a/a check > output.log + $(MSG) Delete some files and sync + rm bench/disk4/a/9* + rm bench/disk5/a/9* + rm bench/disk6/a/9* + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) --test-expect-need-sync diff > output.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) sync -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(MSG) Move some files, sync and check + mv bench/disk1/a/9* bench/disk4/a + mv bench/disk2/a/9* bench/disk5/a + mv bench/disk3/a/9* bench/disk6/a + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) --test-expect-need-sync diff > output.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +#### MORE FILES #### + $(MSG) Create some more files, hardlinks and empty directories, delete others, sync PAR1 and check + rm bench/disk4/a/8* + rm bench/disk5/a/8* + rm bench/disk6/a/8* + $(TESTENV) ./mktest$(EXEEXT) generate 2 6 $(CHECKCOUNT) $(CHECKSIZE) + mkdir bench/disk1/empty1 + mkdir bench/disk2/empty2 + mkdir bench/disk3/empty3a + mkdir bench/disk3/empty3a/emptyinner + mkdir bench/disk3/empty3b + echo TARGET1 > bench/disk1/target1 + ln bench/disk1/target1 bench/disk1/file_hardlink1 + ln bench/disk1/target1 bench/disk1/file_hardlink2 + ln bench/disk1/target1 bench/disk1/file_hardlink3 +if HAVE_POSIX + ln -s bench/disk1/target1 bench/disk1/file_symlink1 + ln -s bench/disk1/target1 bench/disk1/file_symlink2 + ln -s bench/disk1/target1 bench/disk1/file_symlink3 +endif + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(PAR1) --test-expect-need-sync diff > output.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-fallocate -c $(PAR1) sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-io-advise-none -c $(PAR1) sync -F --test-io-cache 1 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-io-advise-sequential -c $(PAR1) sync -F --test-io-stats + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-io-advise-flush-window -c $(PAR1) sync -F + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-io-advise-discard-window -c $(PAR1) sync -F +#### CHANGE LINKS #### +# Use a different size ("22" instead of "1") to ensure to recognize the file different +# even if it gets the same timestamp in case subsecond timestamp is no available + echo TARGET22 > bench/disk1/target2 + rm bench/disk1/file_hardlink1 + ln bench/disk1/target2 bench/disk1/file_hardlink1 +if HAVE_POSIX + rm bench/disk1/file_symlink1 + ln -s bench/disk1/target2 bench/disk1/file_symlink1 +endif + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) --test-expect-need-sync diff > output.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) sync -l ">&1" + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) check -l ">&1" +#### MISC COMMANDS #### + $(MSG) Some commands with a not empty array + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(PAR1) dup + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(PAR1) list --test-fmt file > output.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(PAR1) list --test-fmt disk > output.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(PAR1) list --test-fmt path > output.log +if HAVE_POSIX + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) pool +endif + $(MSG) Extend PAR1 to max parity with fix and check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(CONF) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) fix -d 2-parity -d 3-parity -d 4-parity -d 5-parity -d 6-parity -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check -l ">&1" + $(MSG) Fix with unaccessible parity and disk + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(NOACCESS) fix --test-expect-failure + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(NOACCESS) fix --force-device --test-expect-recoverable -l test.log + $(MSG) Rename a disk + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RENAME) --test-match-first-uuid sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-match-first-uuid sync +#### SCRUB #### + $(MSG) Scrub some times + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-force-scrub-at 100 scrub + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-force-scrub-at 1000 scrub + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-force-scrub-at 100000 scrub + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status +#### SYNC WITH RUNTIME CHANGE #### + $(MSG) Modify files during a sync + echo RUN > bench/disk1/RUN-RM + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-run "rm bench/disk1/RUN-RM" --test-expect-failure sync + echo RUN > bench/disk1/RUN-CHMOD +if HAVE_POSIX +# Doesn't run this test as root because the root user overrride permissions + if [[ $$EUID -ne 0 ]]; then \ + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-run "chmod a-r bench/disk1/RUN-CHMOD" --test-expect-failure sync; \ + fi +endif + echo RUN > bench/disk1/RUN-SIZE + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-run "echo RUNRUN > bench/disk1/RUN-SIZE" --test-expect-failure sync + echo RUN > bench/disk1/RUN-TOUCH + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-run "touch -t 200001011200 bench/disk1/RUN-TOUCH" --test-expect-failure sync + echo RUN > bench/disk1/RUN-INODE + cp -p bench/disk1/RUN-INODE bench/disk1/RUN-INODE-COPY + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-run "mv bench/disk1/RUN-INODE-COPY bench/disk1/RUN-INODE" --test-expect-failure sync + rm bench/disk1/RUN-CHMOD + rm bench/disk1/RUN-SIZE + rm bench/disk1/RUN-TOUCH + rm bench/disk1/RUN-INODE + echo HASH > bench/disk1/HASH-RM + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-run "rm bench/disk1/HASH-RM" --test-expect-failure -h sync + echo HASH > bench/disk1/HASH-CHMOD +if HAVE_POSIX +# Doesn't run this test as root because the root user override permissions + if [[ $$EUID -ne 0 ]]; then \ + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-run "chmod a-r bench/disk1/HASH-CHMOD" --test-expect-failure -h sync; \ + fi +endif + echo HASH > bench/disk1/HASH-SIZE + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-run "echo HASHHASH > bench/disk1/HASH-SIZE" --test-expect-failure -h sync + echo HASH > bench/disk1/HASH-TOUCH + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-run "touch -t 200001011200 bench/disk1/HASH-TOUCH" --test-expect-failure -h sync + echo HASH > bench/disk1/HASH-INODE + cp -p bench/disk1/HASH-INODE bench/disk1/HASH-INODE-COPY + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-run "mv bench/disk1/HASH-INODE-COPY bench/disk1/HASH-INODE" --test-expect-failure -h sync + rm bench/disk1/HASH-CHMOD + rm bench/disk1/HASH-SIZE + rm bench/disk1/HASH-TOUCH + rm bench/disk1/HASH-INODE + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +#### SILENT ERRORS #### + $(MSG) Silently corrupt some files, scrub and fix filtering for error. Test scrub patterns. + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(TESTENV) ./mktest$(EXEEXT) damage 1 1 1 bench/disk1/a/* + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-expect-recoverable --test-force-scrub-at 100000 scrub + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) fix -e + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --percentage bad scrub + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --plan 1 scrub + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -o 0 scrub + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -p full scrub + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -p new scrub + $(MSG) Silently corrupt some files, and sync with error presents + $(TESTENV) ./mktest$(EXEEXT) write 2 1 1 bench/disk1/a/* + $(TESTENV) ./mktest$(EXEEXT) damage 3 1 1 bench/disk2/a/* + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-expect-recoverable sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status +# Note that this fix -e command doesn't fix all the errors because +# only the blocks touched by the sync are marked bad + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) fix -e + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check --test-expect-recoverable + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) fix + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -p full scrub + $(MSG) Full sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -F sync + $(MSG) Realloc sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -R sync +#### SYNC PARTIAL #### + $(MSG) Abort sync with additions. Delete some of them, and add others and sync again. + $(MSG) This triggers files reallocation inside parity + mkdir bench/disk1/c + mkdir bench/disk1/d + mkdir bench/disk1/e + cp -pR bench/disk2/a/c* bench/disk1/c + cp -pR bench/disk2/a/d* bench/disk1/d + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-kill-after-sync sync + rm -r bench/disk1/c + cp -pR bench/disk2/a/e* bench/disk1/e + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(MSG) Abort sync with both deletions and additions. And delete and add some more and sync again. +# Note that here we are depending of the previous state leaving dirs "d" and "e" + mkdir bench/disk1/f + cp -pR bench/disk3/a/f* bench/disk1/f + rm -r bench/disk1/d + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-kill-after-sync sync + mkdir bench/disk1/g + cp -pR bench/disk4/a/g* bench/disk1/g + rm -r bench/disk1/e + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + rm -r bench/disk1/f + rm -r bench/disk1/g + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(MSG) Make a hole in the disk array and sync with --force-empty + mv bench/disk2 bench/disk2.old + mkdir bench/disk2 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --force-empty sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(MSG) Use with the hole + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(HOLE) sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(HOLE) check + rm -r bench/disk1/a + rm -r bench/disk3/a + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(HOLE) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(HOLE) check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(HOLE) test-dry + $(MSG) Fill the hole with a new disk + rm -r bench/disk2 + mv bench/disk2.old bench/disk2 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(MSG) Corrupt the content file + $(TESTENV) ./mktest$(EXEEXT) write 1 100 100 bench/content + $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-failure -c $(CONF) sync + rm bench/content +#### AGAIN MORE FILES #### + $(MSG) Delete some files, create some new, sync and check + rm bench/disk1/a/1* + rm bench/disk2/a/2* + rm bench/disk3/a/3* + rm bench/disk4/a/4* + $(TESTENV) ./mktest$(EXEEXT) generate 3 6 $(CHECKCOUNT) $(CHECKSIZE) + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(MSG) Move some files, sync and check + mv bench/disk1/a/7* bench/disk1/b/ + mv bench/disk2/a/7* bench/disk2/b/ + mv bench/disk3/a/7* bench/disk3/b/ + mv bench/disk4/a/7* bench/disk4/b/ + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +if !HAVE_MEMORY_CHECKER +#### RECOVER 1 #### + $(MSG) Delete one disk, fix and check with PAR1 + rm -r bench/disk3 + mkdir bench/disk3 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR1) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +#### RECOVER 2 #### + $(MSG) Delete two disks, fix and check with PAR2 + rm -r bench/disk1 + mkdir bench/disk1 + rm -r bench/disk2 + mkdir bench/disk2 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(PAR1) fix -l test-fail-strategy1.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR2) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +#### RECOVER 3 #### + $(MSG) Delete three disks, fix and check with PAR3 + rm -r bench/disk1 + mkdir bench/disk1 + rm -r bench/disk2 + mkdir bench/disk2 + rm -r bench/disk3 + mkdir bench/disk3 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(PAR2) fix -l test-fail-strategy2.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR3) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR3) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +#### RECOVER 4 #### + $(MSG) Delete four disks, fix and check with PAR4 + rm -r bench/disk3 + mkdir bench/disk3 + rm -r bench/disk4 + mkdir bench/disk4 + rm -r bench/disk5 + mkdir bench/disk5 + rm -r bench/disk6 + mkdir bench/disk6 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(PAR3) fix -l test-fail-strategy3.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR4) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR4) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +#### RECOVER 5 #### + $(MSG) Delete five disks, fix and check with PAR5 + rm -r bench/disk1 + mkdir bench/disk1 + rm -r bench/disk2 + mkdir bench/disk2 + rm -r bench/disk3 + mkdir bench/disk3 + rm -r bench/disk5 + mkdir bench/disk5 + rm -r bench/disk6 + mkdir bench/disk6 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(PAR4) fix -l test-fail-strategy4.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR5) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR5) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +#### RECOVER 6 #### + $(MSG) Delete six disks, fix and check with PAR6 + rm -r bench/disk1 + mkdir bench/disk1 + rm -r bench/disk2 + mkdir bench/disk2 + rm -r bench/disk3 + mkdir bench/disk3 + rm -r bench/disk4 + mkdir bench/disk4 + rm -r bench/disk5 + mkdir bench/disk5 + rm -r bench/disk6 + mkdir bench/disk6 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(PAR5) fix -l test-fail-strategy5.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR6) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR6) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +endif +#### MULTI STEP #### + $(MSG) Delete some files and create some new, sync and check in multiple steps + rm bench/disk1/a/4* + rm bench/disk2/a/5* + rm bench/disk3/a/6* + rm bench/disk4/a/6* + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -B 10 sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check -l test.log + $(TESTENV) ./mktest$(EXEEXT) generate 4 6 $(CHECKCOUNT) $(CHECKSIZE) + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -B 100 sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -B 1000 sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(MSG) Rehash to spooky2 and rehash even blocks + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-force-spooky2 rehash + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-force-scrub-even scrub + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(MSG) Full sync to complete rehash + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -F sync + $(MSG) Delete files from three disks and check/fix with import by data in PAR2 + rm -r bench/disk1/a + rm -r bench/disk2/a + mv bench/disk3/a bench/a + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-import-content bench/a -c $(PAR2) fix -l test.log + rm -r bench/a + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(MSG) Delete files from three disks and check/fix with import by timestamp in PAR2 + rm -r bench/disk1/a + rm -r bench/disk2/a + mv bench/disk3/a bench/a + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -i bench/a -c $(PAR2) fix -l test.log + rm -r bench/a + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(MSG) Delete files from three disks and check/fix with automatic import in PAR2 + rm -r bench/disk1/a + rm -r bench/disk2/a + mv bench/disk3/a bench/disk1/a_from_disk3 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log + rm -r bench/disk1/a_from_disk3 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +#### SYNC ABORT #### + $(MSG) Abort sync late with additions, delete them and recover with PAR2 + $(MSG) This triggers the recovering with q using p to check the validity + cp -pR bench/disk1/a bench/disk1/a_copy + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-kill-after-sync -c $(CONF) sync + rm -r bench/disk1/a_copy + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log + rm -r bench/disk1/a_copy + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(MSG) Abort sync early with additions, delete them and recover with PAR2 + $(MSG) This triggers the recovering with q using p to check the validity, but failing for new blocks being filled with zero + cp -pR bench/disk1/a bench/disk1/a_copy +# Ensure that there is at least one zero filled file + head -c 8192 /dev/zero > bench/disk1/a_copy/ZERO_FILLED + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -B 1 --test-kill-after-sync -c $(CONF) sync + rm -r bench/disk1/a_copy + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(PAR2) fix -l test-fail-earlysyncadd.log + rm -r bench/disk1/a_copy + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(MSG) Abort sync late with additions with prehash and then delete the new additions and sync again + cp -pR bench/disk1/a bench/disk1/a_copy + cp -pR bench/disk2/a bench/disk2/a_copy + cp -pR bench/disk3/a bench/disk3/a_copy + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-kill-after-sync -c $(CONF) -h sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + rm -r bench/disk1/a_copy + rm -r bench/disk2/a_copy + rm -r bench/disk3/a_copy + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(MSG) Abort sync late with additions and then delete the new additions and sync again + cp -pR bench/disk1/a bench/disk1/a_copy + cp -pR bench/disk2/a bench/disk2/a_copy + cp -pR bench/disk3/a bench/disk3/a_copy + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-kill-after-sync -c $(CONF) sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + rm -r bench/disk1/a_copy + rm -r bench/disk2/a_copy + rm -r bench/disk3/a_copy + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(MSG) Abort sync late with additions and then delete some unchanged stuff and fix with PAR1 + cp -pR bench/disk1/b bench/disk1/b_copy + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) --test-kill-after-sync sync + rm -r bench/disk2 + mkdir bench/disk2 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) fix -l test.log + $(MSG) Fixes again to restore all the parity + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) fix -l test.log + rm -r bench/disk1/b_copy + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(MSG) Abort sync late with more deletions than additions and then delete some unchanged stuff and fix with PAR1 + cp -pR bench/disk1/a bench/disk1/a_copy + mv bench/disk1/a bench/a + mv bench/disk1/b bench/b + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-kill-after-sync sync + rm -r bench/disk2 + mkdir bench/disk2 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) fix -l test.log + $(MSG) Fixes again to restore all the parity + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) fix -l test.log + -rm -r bench/disk1/a + -rm -r bench/disk1/b + rm -r bench/disk1/a_copy + mv bench/a bench/disk1/a + mv bench/b bench/disk1/b + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(MSG) Abort sync early with more deletions than additions and then delete some unchanged stuff and fix with PAR2 + cp -pR bench/disk1/a bench/disk1/a_copy + mv bench/disk1/a bench/a + mv bench/disk1/b bench/b + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -B 1 --test-kill-after-sync sync + rm -r bench/disk2 + mkdir bench/disk2 + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(PAR1) fix -l test-fail-earlysyncdel.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log + -rm -r bench/disk1/a + -rm -r bench/disk1/b + rm -r bench/disk1/a_copy + mv bench/a bench/disk1/a + mv bench/b bench/disk1/b + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +#### RECOVER MISSING #### + $(MSG) Delete some files, fix with -m and check with PAR1 + rm bench/disk1/a/8* + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR1) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) -m fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(MSG) Delete some dirs in six disk, fix with -m and check + rm -r bench/disk1/b + rm -r bench/disk2/b + rm -r bench/disk3/b + rm -r bench/disk4/b + rm -r bench/disk5/b + rm -r bench/disk6/b + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(PAR5) fix -l test-full5.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(CONF) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -m fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +#### RECOVER BY DISK #### + $(MSG) Delete some dirs in two disks, fix and check with PAR2 using the -d option for each disk + rm -r bench/disk2/b + rm -r bench/disk5/b + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(PAR1) check -l test-full1.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) -d disk2 fix -l test-part1.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) -d disk5 fix -l test-part2.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +#### RECOVER PARITY #### + $(MSG) Delete the parity, fix and check with PAR1 + rm bench/parity* + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(MSG) Delete the parity and the 2-parity, fix and check with PAR2 + rm bench/parity* + rm bench/2-parity* + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(MSG) Delete the parity and a disk, fix and check with PAR2 + rm bench/parity* + rm -r bench/disk2/b + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(MSG) Delete the 2-parity and a disk, fix and check with PAR2 + rm bench/2-parity* + rm -r bench/disk3/a + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(MSG) Corrupt the parity, fix and check with PAR1 + $(TESTENV) ./mktest$(EXEEXT) write 1 100 10000 bench/parity* + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR1) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) -a check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(MSG) Corrupt the parity and the 2-parity, fix and check with PAR2 + $(TESTENV) ./mktest$(EXEEXT) write 2 100 10000 bench/parity* + $(TESTENV) ./mktest$(EXEEXT) write 2 100 10000 bench/2-parity* + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR2) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -a check + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +#### RECOVER FILES AND PARITY #### + $(MSG) Corrupt some files, fix and check with PAR1 + $(TESTENV) ./mktest$(EXEEXT) change 3 500 bench/disk2/b/* + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR1) -a check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR1) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(MSG) Corrupt some files, fix and check with PAR2 in verbose mode + $(TESTENV) ./mktest$(EXEEXT) change 4 500 bench/disk2/b/* + $(TESTENV) ./mktest$(EXEEXT) change 4 500 bench/disk3/b/* + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) --test-expect-unrecoverable -c $(PAR1) check -l test.log > /dev/null + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) --test-expect-unrecoverable -c $(PAR1) fix -l test-fail-corrupt-verbose.log > /dev/null + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR2) -a check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR2) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(MSG) Corrupt some files, fix and check with PAR2 + $(TESTENV) ./mktest$(EXEEXT) change 5 500 bench/disk2/b/* + $(TESTENV) ./mktest$(EXEEXT) change 5 500 bench/disk3/b/* + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(PAR1) check -l test-fail-corrupt-data.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR2) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(MSG) Corrupt the parity and some files, fix and check with PAR2 + $(TESTENV) ./mktest$(EXEEXT) write 6 100 10000 bench/parity* + $(TESTENV) ./mktest$(EXEEXT) change 6 500 bench/disk1/a/* + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(PAR1) check -l test-fail-corrupt-parity.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR2) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(MSG) Corrupt the 2-parity and some files, fix and check with PAR2 + $(TESTENV) ./mktest$(EXEEXT) write 7 100 10000 bench/2-parity* + $(TESTENV) ./mktest$(EXEEXT) change 7 500 bench/disk1/a/* + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR1) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR2) check -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(MSG) Sync after all the fixes + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync + $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +endif + $(MSG) Regression test completed with SUCCESS! + $(MSG) Please ignore any error message printed above, they are expected! + $(MSG) Everything OK + +# Manual testing + +MANUAL = ./snapraid --test-skip-device -c test/test-par1.conf sync + +valgrind: + valgrind \ + --tool=memcheck \ + --track-origins=yes \ + --read-var-info=yes \ + --leak-check=full \ + -v $(MANUAL) \ + 2> valgrind.log + tail valgrind.log + +callgrind: + valgrind \ + --tool=callgrind \ + --dump-instr=yes \ + --trace-jump=yes \ + --collect-systime=yes \ + -v $(MANUAL) \ + 2> callgrind.log + tail callgrind.log + +cachegrind: + valgrind \ + --tool=cachegrind \ + -v $(MANUAL) \ + 2> cachegrind.log + tail cachegrind.log + +lcov_reset: + lcov --directory . -z + rm -f ./lcov.info + +lcov_capture: + lcov --directory . --capture -o lcov.info + +lcov_html: + rm -rf ./cov + mkdir cov + genhtml -o ./cov lcov.info + +# Rules for documentation + +if HAVE_ADVD2 +snapraid.1 : snapraid.d + advd2 man < $(srcdir)/$< > $@ + +snapraid.txt : snapraid.d + advd2 txt < $(srcdir)/$< | todos > $@ + +snapraid.html : snapraid.d + advd2 html < $(srcdir)/$< > $@ + +snapraid.hh : snapraid.d + advd2 frame < $(srcdir)/$< > $@ +endif + +# Windows distribution + +DISTWIN = \ + snapraid.txt \ + snapraid.exe + +distwindows-x86: $(DISTWIN) + rm -f $(PACKAGE)-$(VERSION)-windows-x86.zip + mkdir tmp + cp $(DISTWIN) tmp + cp support/smartctl.exe tmp/smartctl.exe + todos < snapraid.conf.example.windows > tmp/snapraid.conf.example + todos < INSTALL.windows > tmp/install.txt + todos < README > tmp/readme.txt + todos < AUTHORS > tmp/authors.txt + todos < HISTORY > tmp/history.txt + todos < COPYING > tmp/copying.txt + todos < TODO > tmp/todo.txt + cd tmp && zip -r ../$(PACKAGE)-$(VERSION)-windows-x86.zip * + rm -r tmp + +distwindows-x64: $(DISTWIN) + rm -f $(PACKAGE)-$(VERSION)-windows-x64.zip + mkdir tmp + cp $(DISTWIN) tmp + cp support/smartctl.exe tmp/smartctl.exe + todos < snapraid.conf.example.windows > tmp/snapraid.conf.example + todos < INSTALL.windows > tmp/install.txt + todos < README > tmp/readme.txt + todos < AUTHORS > tmp/authors.txt + todos < HISTORY > tmp/history.txt + todos < COPYING > tmp/copying.txt + todos < TODO > tmp/todo.txt + cd tmp && zip -r ../$(PACKAGE)-$(VERSION)-windows-x64.zip * + rm -r tmp + diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..73f8ac5 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,1934 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +bin_PROGRAMS = snapraid$(EXEEXT) +check_PROGRAMS = mktest$(EXEEXT) mkstream$(EXEEXT) +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(noinst_HEADERS) $(am__DIST_COMMON) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" +PROGRAMS = $(bin_PROGRAMS) +am__dirstamp = $(am__leading_dot)dirstamp +am_mkstream_OBJECTS = cmdline/mkstream.$(OBJEXT) \ + cmdline/mingw.$(OBJEXT) cmdline/unix.$(OBJEXT) \ + cmdline/support.$(OBJEXT) cmdline/util.$(OBJEXT) \ + cmdline/stream.$(OBJEXT) raid/memory.$(OBJEXT) +mkstream_OBJECTS = $(am_mkstream_OBJECTS) +mkstream_LDADD = $(LDADD) +am_mktest_OBJECTS = cmdline/mktest.$(OBJEXT) cmdline/mingw.$(OBJEXT) \ + cmdline/unix.$(OBJEXT) cmdline/support.$(OBJEXT) +mktest_OBJECTS = $(am_mktest_OBJECTS) +mktest_LDADD = $(LDADD) +am_snapraid_OBJECTS = raid/raid.$(OBJEXT) raid/check.$(OBJEXT) \ + raid/module.$(OBJEXT) raid/tables.$(OBJEXT) raid/int.$(OBJEXT) \ + raid/x86.$(OBJEXT) raid/intz.$(OBJEXT) raid/x86z.$(OBJEXT) \ + raid/helper.$(OBJEXT) raid/memory.$(OBJEXT) \ + raid/test.$(OBJEXT) raid/tag.$(OBJEXT) tommyds/tommy.$(OBJEXT) \ + cmdline/snapraid.$(OBJEXT) cmdline/io.$(OBJEXT) \ + cmdline/util.$(OBJEXT) cmdline/stream.$(OBJEXT) \ + cmdline/support.$(OBJEXT) cmdline/elem.$(OBJEXT) \ + cmdline/state.$(OBJEXT) cmdline/scan.$(OBJEXT) \ + cmdline/sync.$(OBJEXT) cmdline/check.$(OBJEXT) \ + cmdline/dry.$(OBJEXT) cmdline/rehash.$(OBJEXT) \ + cmdline/scrub.$(OBJEXT) cmdline/status.$(OBJEXT) \ + cmdline/dup.$(OBJEXT) cmdline/list.$(OBJEXT) \ + cmdline/pool.$(OBJEXT) cmdline/parity.$(OBJEXT) \ + cmdline/handle.$(OBJEXT) cmdline/touch.$(OBJEXT) \ + cmdline/device.$(OBJEXT) cmdline/fnmatch.$(OBJEXT) \ + cmdline/selftest.$(OBJEXT) cmdline/speed.$(OBJEXT) \ + cmdline/import.$(OBJEXT) cmdline/search.$(OBJEXT) \ + cmdline/mingw.$(OBJEXT) cmdline/unix.$(OBJEXT) +snapraid_OBJECTS = $(am_snapraid_OBJECTS) +snapraid_LDADD = $(LDADD) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = +am__depfiles_maybe = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(mkstream_SOURCES) $(mktest_SOURCES) $(snapraid_SOURCES) +DIST_SOURCES = $(mkstream_SOURCES) $(mktest_SOURCES) \ + $(snapraid_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +man1dir = $(mandir)/man1 +NROFF = nroff +MANS = $(man_MANS) +HEADERS = $(noinst_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ + $(LISP)config.h.in +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +CSCOPE = cscope +AM_RECURSIVE_TARGETS = cscope +am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in AUTHORS \ + COPYING INSTALL README TODO compile config.guess config.sub \ + install-sh missing +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +DIST_TARGETS = dist-gzip +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +ADVD2 = @ADVD2@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FAILENV = @FAILENV@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +SDE = @SDE@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TESTENV = @TESTENV@ +TESTENV_AVX2 = @TESTENV_AVX2@ +TESTENV_SSE2 = @TESTENV_SSE2@ +TESTENV_SSE42 = @TESTENV_SSE42@ +TESTENV_SSSE3 = @TESTENV_SSSE3@ +VALGRIND = @VALGRIND@ +VERSION = @VERSION@ +WINE = @WINE@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +am__leading_dot = @am__leading_dot@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AM_CPPFLAGS = -DSYSCONFDIR="\"${sysconfdir}\"" +snapraid_SOURCES = \ + raid/raid.c \ + raid/check.c \ + raid/module.c \ + raid/tables.c \ + raid/int.c \ + raid/x86.c \ + raid/intz.c \ + raid/x86z.c \ + raid/helper.c \ + raid/memory.c \ + raid/test.c \ + raid/tag.c \ + tommyds/tommy.c \ + cmdline/snapraid.c \ + cmdline/io.c \ + cmdline/util.c \ + cmdline/stream.c \ + cmdline/support.c \ + cmdline/elem.c \ + cmdline/state.c \ + cmdline/scan.c \ + cmdline/sync.c \ + cmdline/check.c \ + cmdline/dry.c \ + cmdline/rehash.c \ + cmdline/scrub.c \ + cmdline/status.c \ + cmdline/dup.c \ + cmdline/list.c \ + cmdline/pool.c \ + cmdline/parity.c \ + cmdline/handle.c \ + cmdline/touch.c \ + cmdline/device.c \ + cmdline/fnmatch.c \ + cmdline/selftest.c \ + cmdline/speed.c \ + cmdline/import.c \ + cmdline/search.c \ + cmdline/mingw.c \ + cmdline/unix.c + +noinst_HEADERS = \ + raid/raid.h \ + raid/helper.h \ + raid/internal.h \ + raid/cpu.h \ + raid/gf.h \ + raid/combo.h \ + raid/memory.h \ + raid/test.h \ + tommyds/tommyarray.h \ + tommyds/tommyarrayblkof.h \ + tommyds/tommychain.h \ + tommyds/tommyhash.h \ + tommyds/tommyhashdyn.h \ + tommyds/tommylist.h \ + tommyds/tommytree.h \ + tommyds/tommytypes.h \ + tommyds/tommyarray.c \ + tommyds/tommyarrayblkof.c \ + tommyds/tommyhash.c \ + tommyds/tommyhashdyn.c \ + tommyds/tommylist.c \ + tommyds/tommytree.c \ + cmdline/portable.h \ + cmdline/snapraid.h \ + cmdline/io.h \ + cmdline/util.h \ + cmdline/stream.h \ + cmdline/support.h \ + cmdline/elem.h \ + cmdline/state.h \ + cmdline/parity.h \ + cmdline/handle.h \ + cmdline/murmur3.c \ + cmdline/murmur3test.c \ + cmdline/spooky2.c \ + cmdline/spooky2test.c \ + cmdline/fnmatch.h \ + cmdline/import.h \ + cmdline/search.h \ + cmdline/mingw.h \ + cmdline/unix.h + +mktest_SOURCES = \ + cmdline/mktest.c \ + cmdline/mingw.c \ + cmdline/unix.c \ + cmdline/support.c + +mkstream_SOURCES = \ + cmdline/mkstream.c \ + cmdline/mingw.c \ + cmdline/unix.c \ + cmdline/support.c \ + cmdline/util.c \ + cmdline/stream.c \ + raid/memory.c + +EXTRA_DIST = \ + autogen.sh autover.sh \ + README AUTHORS HISTORY INSTALL COPYING TODO CHECK INSTALL.windows \ + snapraid.d snapraid.1 snapraid.txt \ + test/test-par1.conf \ + test/test-par2.conf \ + test/test-par3.conf \ + test/test-par4.conf \ + test/test-par5.conf \ + test/test-par6.conf \ + test/test-par6-hole.conf \ + test/test-par6-noaccess.conf \ + test/test-par6-rename.conf \ + snapraid.conf.example \ + configure.windows-x86 configure.windows-x64 snapraid.conf.example.windows \ + acinclude.m4 \ + tommyds/LICENSE \ + raid/COPYING \ + raid/test/Makefile \ + raid/test/fulltest.c \ + raid/test/selftest.c \ + raid/test/speedtest.c \ + raid/test/invtest.c + +man_MANS = snapraid.1 + +# Automatic testing + +# Common options +# --test-skip-device +# Is required to allow testing in the same disk +# +# --test-skip-self +# It just makes the test a little faster +CHECKFLAGS_COMMON = --test-skip-device --test-skip-self --test-force-progress --no-warnings --test-parity-limit=3333333 + +# --test-force-order-alpha +# Ensures to process files always in the same order despites +# the inode, physical location, and dir order assigned by the OS. +CHECKFLAGS_ALPHA = $(CHECKFLAGS_COMMON) --test-force-order-alpha + +# Physical offset options +CHECKFLAGS_PHYSICAL = $(CHECKFLAGS_COMMON) --test-force-order-physical -q -q -q + +# Verbose options +CHECKFLAGS_VERBOSE = $(CHECKFLAGS_ALPHA) -v -G + +# Quiet options +CHECKFLAGS = $(CHECKFLAGS_ALPHA) -q -q -q +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_POSIX_FALSE@CHECKCOUNT = 500 + +# Number of files to create +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_POSIX_TRUE@CHECKCOUNT = 1000 +@HAVE_MEMORY_CHECKER_TRUE@CHECKCOUNT = 500 + +# Size of files to create +@HAVE_MEMORY_CHECKER_FALSE@CHECKSIZE = 4000 +@HAVE_MEMORY_CHECKER_TRUE@CHECKSIZE = 100 +CONF = $(srcdir)/test/test-par6.conf +HOLE = $(srcdir)/test/test-par6-hole.conf +NOACCESS = $(srcdir)/test/test-par6-noaccess.conf +RENAME = $(srcdir)/test/test-par6-rename.conf +PAR1 = $(srcdir)/test/test-par1.conf +PAR2 = $(srcdir)/test/test-par2.conf +PAR3 = $(srcdir)/test/test-par3.conf +PAR4 = $(srcdir)/test/test-par4.conf +PAR5 = $(srcdir)/test/test-par5.conf +PAR6 = $(srcdir)/test/test-par6.conf +MSG = @echo ===== + +# Manual testing +MANUAL = ./snapraid --test-skip-device -c test/test-par1.conf sync + +# Windows distribution +DISTWIN = \ + snapraid.txt \ + snapraid.exe + +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .o .obj +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign --ignore-deps'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign --ignore-deps \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign --ignore-deps Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign --ignore-deps Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @test -f $@ || rm -f stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) + +clean-checkPROGRAMS: + -test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS) +cmdline/$(am__dirstamp): + @$(MKDIR_P) cmdline + @: > cmdline/$(am__dirstamp) +cmdline/mkstream.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/mingw.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/unix.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/support.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/util.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/stream.$(OBJEXT): cmdline/$(am__dirstamp) +raid/$(am__dirstamp): + @$(MKDIR_P) raid + @: > raid/$(am__dirstamp) +raid/memory.$(OBJEXT): raid/$(am__dirstamp) + +mkstream$(EXEEXT): $(mkstream_OBJECTS) $(mkstream_DEPENDENCIES) $(EXTRA_mkstream_DEPENDENCIES) + @rm -f mkstream$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(mkstream_OBJECTS) $(mkstream_LDADD) $(LIBS) +cmdline/mktest.$(OBJEXT): cmdline/$(am__dirstamp) + +mktest$(EXEEXT): $(mktest_OBJECTS) $(mktest_DEPENDENCIES) $(EXTRA_mktest_DEPENDENCIES) + @rm -f mktest$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(mktest_OBJECTS) $(mktest_LDADD) $(LIBS) +raid/raid.$(OBJEXT): raid/$(am__dirstamp) +raid/check.$(OBJEXT): raid/$(am__dirstamp) +raid/module.$(OBJEXT): raid/$(am__dirstamp) +raid/tables.$(OBJEXT): raid/$(am__dirstamp) +raid/int.$(OBJEXT): raid/$(am__dirstamp) +raid/x86.$(OBJEXT): raid/$(am__dirstamp) +raid/intz.$(OBJEXT): raid/$(am__dirstamp) +raid/x86z.$(OBJEXT): raid/$(am__dirstamp) +raid/helper.$(OBJEXT): raid/$(am__dirstamp) +raid/test.$(OBJEXT): raid/$(am__dirstamp) +raid/tag.$(OBJEXT): raid/$(am__dirstamp) +tommyds/$(am__dirstamp): + @$(MKDIR_P) tommyds + @: > tommyds/$(am__dirstamp) +tommyds/tommy.$(OBJEXT): tommyds/$(am__dirstamp) +cmdline/snapraid.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/io.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/elem.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/state.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/scan.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/sync.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/check.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/dry.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/rehash.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/scrub.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/status.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/dup.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/list.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/pool.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/parity.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/handle.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/touch.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/device.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/fnmatch.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/selftest.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/speed.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/import.$(OBJEXT): cmdline/$(am__dirstamp) +cmdline/search.$(OBJEXT): cmdline/$(am__dirstamp) + +snapraid$(EXEEXT): $(snapraid_OBJECTS) $(snapraid_DEPENDENCIES) $(EXTRA_snapraid_DEPENDENCIES) + @rm -f snapraid$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(snapraid_OBJECTS) $(snapraid_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f cmdline/*.$(OBJEXT) + -rm -f raid/*.$(OBJEXT) + -rm -f tommyds/*.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +.c.o: + $(AM_V_CC)$(COMPILE) -c -o $@ $< + +.c.obj: + $(AM_V_CC)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +install-man1: $(man_MANS) + @$(NORMAL_INSTALL) + @list1=''; \ + list2='$(man_MANS)'; \ + test -n "$(man1dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.1[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ + done; } + +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man1dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.1[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) +clean-cscope: + -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__post_remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) + +dist-tarZ: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__post_remove_distdir) + +dist-shar: distdir + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__post_remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__post_remove_distdir) + +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=../.. --prefix="$$dc_install_base" \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__post_remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-local +check: check-am +all-am: Makefile $(PROGRAMS) $(MANS) $(HEADERS) config.h +installdirs: + for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f cmdline/$(am__dirstamp) + -rm -f raid/$(am__dirstamp) + -rm -f tommyds/$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ + clean-local mostlyclean-am + +distclean: distclean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-hdr distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-man + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: install-man1 + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic \ + maintainer-clean-local + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-man + +uninstall-man: uninstall-man1 + +.MAKE: all check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--refresh check check-am \ + check-local clean clean-binPROGRAMS clean-checkPROGRAMS \ + clean-cscope clean-generic clean-local cscope cscopelist-am \ + ctags ctags-am dist dist-all dist-bzip2 dist-gzip dist-hook \ + dist-lzip dist-shar dist-tarZ dist-xz dist-zip distcheck \ + distclean distclean-compile distclean-generic distclean-hdr \ + distclean-tags distcleancheck distdir distuninstallcheck dvi \ + dvi-am html html-am info info-am install install-am \ + install-binPROGRAMS install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-man1 install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + maintainer-clean-local mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-binPROGRAMS uninstall-man \ + uninstall-man1 + +.PRECIOUS: Makefile + + +# Add the .version file in the distribution +dist-hook: + $(srcdir)/autover.sh > $(distdir)/.version + +clean-local: + rm -f valgrind.log callgrind.log cachegrind.log + rm -rf bench + rm -f test*.log output.log stream*.bin + rm -f cmdline/*.gcda cmdline/*.gcno cmdline/*.gcov + rm -f raid/*.gcda raid/*.gcno raid/*.gcov + rm -f tommyds/*.gcda tommyds/*.gcno tommyds/*.gcov + rm -f lcov.info + rm -f gmon.out + +maintainer-clean-local: + rm -f snapraid.1 snapraid.txt + +check-local: + rm -rf bench + rm -f test.log + mkdir bench + mkdir bench/disk1 + mkdir bench/disk2 + mkdir bench/disk3 + mkdir bench/disk4 + mkdir bench/disk5 + mkdir bench/disk6 + mkdir bench/pool + $(MSG) Stream + $(TESTENV) ./mkstream$(EXEEXT) +#### THREAD TEST #### +@HAVE_THREAD_CHECKER_TRUE@ $(MSG) Create some files +@HAVE_THREAD_CHECKER_TRUE@ $(TESTENV) ./mktest$(EXEEXT) generate 1 6 $(CHECKCOUNT) $(CHECKSIZE) +@HAVE_THREAD_CHECKER_TRUE@ $(MSG) Some commands that use threads +# First sync +@HAVE_THREAD_CHECKER_TRUE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +# Remove, move and add some more +@HAVE_THREAD_CHECKER_TRUE@ rm bench/disk4/a/9* +@HAVE_THREAD_CHECKER_TRUE@ rm bench/disk5/a/9* +@HAVE_THREAD_CHECKER_TRUE@ rm bench/disk6/a/9* +@HAVE_THREAD_CHECKER_TRUE@ mv bench/disk1/a/9* bench/disk4/a +@HAVE_THREAD_CHECKER_TRUE@ mv bench/disk2/a/9* bench/disk5/a +@HAVE_THREAD_CHECKER_TRUE@ mv bench/disk3/a/9* bench/disk6/a +@HAVE_THREAD_CHECKER_TRUE@ $(TESTENV) ./mktest$(EXEEXT) change 2 500 bench/disk2/b/* bench/disk3/b/* +# Sync again +@HAVE_THREAD_CHECKER_TRUE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +# Other commands that uses threads +@HAVE_THREAD_CHECKER_TRUE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) test-rewrite +@HAVE_THREAD_CHECKER_TRUE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) scrub -p full +@HAVE_THREAD_CHECKER_TRUE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) scrub -p full --test-io-cache 3 +@HAVE_THREAD_CHECKER_TRUE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) scrub -p full --test-io-cache 128 +@HAVE_THREAD_CHECKER_TRUE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync -F --test-io-cache 1 +@HAVE_THREAD_CHECKER_TRUE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) scrub -p full --test-io-cache 1 +#### COMMAND LINE #### +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Pre test +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) --test-skip-device -H +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) --test-skip-device -V +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) test +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./mktest$(EXEEXT) +@HAVE_EMULATOR_TRUE@@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Speed +# Run the self test in AVX2 +@HAVE_EMULATOR_TRUE@@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV_AVX2) ./snapraid$(EXEEXT) --test-skip-device -c $(CONF) status +# Run the speed test in different architectures +@HAVE_EMULATOR_TRUE@@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV_SSE2) ./snapraid$(EXEEXT) --test-skip-device -T +@HAVE_EMULATOR_TRUE@@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV_SSSE3) ./snapraid$(EXEEXT) --test-skip-device -T +@HAVE_EMULATOR_TRUE@@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV_SSE42) ./snapraid$(EXEEXT) --test-skip-device -T +@HAVE_EMULATOR_TRUE@@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV_AVX2) ./snapraid$(EXEEXT) --test-skip-device -T +# Run the self test natively +@HAVE_EMULATOR_FALSE@@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) --test-skip-device -c $(CONF) status +# Run the speed test natively +@HAVE_EMULATOR_FALSE@@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) --test-skip-device -T +#### EMPTY #### +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Some commands with empty array +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) diff +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) dup +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) list > output.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status -l ">&1" +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status -l ">&2" +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status -l ">>test.log" +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status -l test-%D-%T.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) up +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) down -d parity -d disk1 +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) devices +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) smart --no-warnings +@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) smart --test-fake-device --test-expect-failure +@HAVE_POSIX_TRUE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) pool +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -a check +#### CONTROLLED #### +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Filesystem allocation test +@HAVE_THREAD_CHECKER_FALSE@ head -c 8192 /dev/zero > bench/disk1/TEST +# Copy the file to trigger the copy optimization check +@HAVE_THREAD_CHECKER_FALSE@ cp -a bench/disk1/TEST bench/disk2/TEST +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +# Now delete the file, and do a partial sync to force a deallocation in the middle of a file +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk1/TEST +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -E -S 1 -B 1 sync +# Now force a deallocation at the end +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -E -S 7 -B 1 sync +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk2/TEST +# Have the sync to fail for empty disk +@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync --test-expect-failure +# Now sync will complete with -E +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -E sync +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Filesystem fragmentation test +@HAVE_THREAD_CHECKER_FALSE@ head -c 8192 /dev/zero > bench/disk1/TEST1 +@HAVE_THREAD_CHECKER_FALSE@ head -c 8192 /dev/zero > bench/disk1/TEST2 +@HAVE_THREAD_CHECKER_FALSE@ head -c 8192 /dev/zero > bench/disk1/TEST3 +@HAVE_THREAD_CHECKER_FALSE@ head -c 8192 /dev/zero > bench/disk1/TEST4 +@HAVE_THREAD_CHECKER_FALSE@ head -c 8192 /dev/zero > bench/disk1/TEST5 +@HAVE_THREAD_CHECKER_FALSE@ head -c 8192 /dev/zero > bench/disk1/TEST6 +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +# Now delete some files, and create a bigger one to fill the holes +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk1/TEST1 +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk1/TEST3 +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk1/TEST5 +@HAVE_THREAD_CHECKER_FALSE@ head -c 65536 /dev/zero > bench/disk1/TESTX +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync -l ">&1" +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1/TEST* +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -E sync +# Now enforce copy detection of a file without parity +# Create a file in a high number disk +@HAVE_THREAD_CHECKER_FALSE@ head -c 8192 /dev/urandom > bench/disk6/STEP1 +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +# Create two new copies. The one in disk1 will copy +# the hash from the one in disk6, and the one in disk2 +# will copy the hash from the one in disk1, that +# doesn't have parity +@HAVE_THREAD_CHECKER_FALSE@ cp -a bench/disk6/STEP1 bench/disk1/STEP1 +@HAVE_THREAD_CHECKER_FALSE@ cp -a bench/disk6/STEP1 bench/disk2/STEP1 +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +# Now create, duplicate, move and partial sync +@HAVE_THREAD_CHECKER_FALSE@ head -c 8192 /dev/zero > bench/disk1/INVA1 +@HAVE_THREAD_CHECKER_FALSE@ head -c 8192 /dev/zero > bench/disk1/INVA2 +@HAVE_THREAD_CHECKER_FALSE@ head -c 8192 /dev/zero > bench/disk1/INVA3 +@HAVE_THREAD_CHECKER_FALSE@ head -c 8192 /dev/zero > bench/disk1/MOVE1 +@HAVE_THREAD_CHECKER_FALSE@ cp -a bench/disk1/MOVE1 bench/disk1/MOVE2 +@HAVE_THREAD_CHECKER_FALSE@ cp -a bench/disk1/MOVE1 bench/disk1/MOVE3 +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ mv bench/disk1/MOVE2 bench/disk2/MOVE2 +@HAVE_THREAD_CHECKER_FALSE@ mv bench/disk1/MOVE3 bench/disk3/MOVE3 +@HAVE_THREAD_CHECKER_FALSE@ head -c 8192 /dev/zero > bench/disk4/MOVE4 +@HAVE_THREAD_CHECKER_FALSE@ cp -a bench/disk1/INVA1 bench/disk1/EXTRA1 +@HAVE_THREAD_CHECKER_FALSE@ cp -a bench/disk1/INVA2 bench/disk1/EXTRA2 +@HAVE_THREAD_CHECKER_FALSE@ cp -a bench/disk1/INVA3 bench/disk1/EXTRA3 +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk1/INVA1 +@HAVE_THREAD_CHECKER_FALSE@ touch bench/disk1/INVA2 +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-kill-after-sync sync +# Diff should report the need of a sync for invalid parity +@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(PAR1) --test-expect-need-sync diff +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status +@HAVE_THREAD_CHECKER_FALSE@ mv bench/disk2/MOVE2 bench/disk4/MOVE4 +@HAVE_THREAD_CHECKER_FALSE@ mv bench/disk3/MOVE3 bench/disk5/MOVE5 +@HAVE_THREAD_CHECKER_FALSE@ mv bench/disk4/MOVE4 bench/disk6/MOVE6 +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk1/EXTRA1 +@HAVE_THREAD_CHECKER_FALSE@ touch bench/disk1/EXTRA2 +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -E sync +# Change UUID +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-fake-uuid sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +#### NOT EMPTY #### +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Create some files +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./mktest$(EXEEXT) generate 1 6 $(CHECKCOUNT) $(CHECKSIZE) +@HAVE_THREAD_CHECKER_FALSE@ echo DUP > bench/disk1/DUP1 +@HAVE_THREAD_CHECKER_FALSE@ echo DUP > bench/disk1/DUP2 +@HAVE_THREAD_CHECKER_FALSE@ echo -n > bench/disk1/ZERO +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Some commands with a not empty array +# Run a sync using physical offset +@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_PHYSICAL) -c $(CONF) --test-expect-need-sync diff > output.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_PHYSICAL) -c $(CONF) sync +# Now reset the array, as we normally test with alpha order and murmur3 +@HAVE_THREAD_CHECKER_FALSE@ rm bench/content bench/?-content +# Now rebuild the array with alpha order and murmur3 and do some commands +# Later we will convert it to spooky2 to test both hashes +@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) --test-expect-need-sync diff > output.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-force-murmur3 --test-force-autosave-at 100 sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) dup -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) list -l test.log > output.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) test-rewrite +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) test-read +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status -l test.log +@HAVE_POSIX_TRUE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) pool +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) check +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -a check +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Dry +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) test-dry +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Copy detection +# Create a file and sync with it +@HAVE_THREAD_CHECKER_FALSE@ echo 123 > bench/disk1/COPY +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +# Corrupt and move it to another disk +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./mktest$(EXEEXT) damage 1 1 1 bench/disk1/COPY +@HAVE_THREAD_CHECKER_FALSE@ mv bench/disk1/COPY bench/disk2/COPY +# Now sync with failure as the data won't match. We have two points of failure, pre-hash and sync +@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-expect-failure -h sync +@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-expect-failure sync +# Now sync with force-nocopy +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --force-nocopy sync +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Nano +@HAVE_THREAD_CHECKER_FALSE@ touch -t 200102011234.56 bench/disk1/a/a* +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) touch +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Check the --gen-conf command +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --gen-conf bench/content +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Filter +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) -d disk1 check > output.log +# Only in real unix, as with MingW the * trigger path replacement +# Like /b/a* -> B:/a* and SnapRAID then complain about relative paths +@HAVE_POSIX_TRUE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) -f \\*a -f a/ -f /b/a\\* check > output.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) --test-expect-failure -f . check > output.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) --test-expect-failure -f ./ check > output.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) --test-expect-failure -f a/a check > output.log +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Delete some files and sync +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk4/a/9* +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk5/a/9* +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk6/a/9* +@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) --test-expect-need-sync diff > output.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) sync -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Move some files, sync and check +@HAVE_THREAD_CHECKER_FALSE@ mv bench/disk1/a/9* bench/disk4/a +@HAVE_THREAD_CHECKER_FALSE@ mv bench/disk2/a/9* bench/disk5/a +@HAVE_THREAD_CHECKER_FALSE@ mv bench/disk3/a/9* bench/disk6/a +@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(CONF) --test-expect-need-sync diff > output.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +#### MORE FILES #### +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Create some more files, hardlinks and empty directories, delete others, sync PAR1 and check +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk4/a/8* +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk5/a/8* +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk6/a/8* +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./mktest$(EXEEXT) generate 2 6 $(CHECKCOUNT) $(CHECKSIZE) +@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk1/empty1 +@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk2/empty2 +@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk3/empty3a +@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk3/empty3a/emptyinner +@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk3/empty3b +@HAVE_THREAD_CHECKER_FALSE@ echo TARGET1 > bench/disk1/target1 +@HAVE_THREAD_CHECKER_FALSE@ ln bench/disk1/target1 bench/disk1/file_hardlink1 +@HAVE_THREAD_CHECKER_FALSE@ ln bench/disk1/target1 bench/disk1/file_hardlink2 +@HAVE_THREAD_CHECKER_FALSE@ ln bench/disk1/target1 bench/disk1/file_hardlink3 +@HAVE_POSIX_TRUE@@HAVE_THREAD_CHECKER_FALSE@ ln -s bench/disk1/target1 bench/disk1/file_symlink1 +@HAVE_POSIX_TRUE@@HAVE_THREAD_CHECKER_FALSE@ ln -s bench/disk1/target1 bench/disk1/file_symlink2 +@HAVE_POSIX_TRUE@@HAVE_THREAD_CHECKER_FALSE@ ln -s bench/disk1/target1 bench/disk1/file_symlink3 +@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(PAR1) --test-expect-need-sync diff > output.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-skip-fallocate -c $(PAR1) sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-io-advise-none -c $(PAR1) sync -F --test-io-cache 1 +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-io-advise-sequential -c $(PAR1) sync -F --test-io-stats +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-io-advise-flush-window -c $(PAR1) sync -F +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-io-advise-discard-window -c $(PAR1) sync -F +#### CHANGE LINKS #### +# Use a different size ("22" instead of "1") to ensure to recognize the file different +# even if it gets the same timestamp in case subsecond timestamp is no available +@HAVE_THREAD_CHECKER_FALSE@ echo TARGET22 > bench/disk1/target2 +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk1/file_hardlink1 +@HAVE_THREAD_CHECKER_FALSE@ ln bench/disk1/target2 bench/disk1/file_hardlink1 +@HAVE_POSIX_TRUE@@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk1/file_symlink1 +@HAVE_POSIX_TRUE@@HAVE_THREAD_CHECKER_FALSE@ ln -s bench/disk1/target2 bench/disk1/file_symlink1 +@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) --test-expect-need-sync diff > output.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) sync -l ">&1" +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) check -l ">&1" +#### MISC COMMANDS #### +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Some commands with a not empty array +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(PAR1) dup +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(PAR1) list --test-fmt file > output.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(PAR1) list --test-fmt disk > output.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) -c $(PAR1) list --test-fmt path > output.log +@HAVE_POSIX_TRUE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) pool +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Extend PAR1 to max parity with fix and check +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(CONF) check -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) fix -d 2-parity -d 3-parity -d 4-parity -d 5-parity -d 6-parity -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check -l ">&1" +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Fix with unaccessible parity and disk +@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(NOACCESS) fix --test-expect-failure +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(NOACCESS) fix --force-device --test-expect-recoverable -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Rename a disk +@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(RENAME) --test-match-first-uuid sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-match-first-uuid sync +#### SCRUB #### +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Scrub some times +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-force-scrub-at 100 scrub +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-force-scrub-at 1000 scrub +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-force-scrub-at 100000 scrub +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status +#### SYNC WITH RUNTIME CHANGE #### +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Modify files during a sync +@HAVE_THREAD_CHECKER_FALSE@ echo RUN > bench/disk1/RUN-RM +@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-run "rm bench/disk1/RUN-RM" --test-expect-failure sync +@HAVE_THREAD_CHECKER_FALSE@ echo RUN > bench/disk1/RUN-CHMOD +# Doesn't run this test as root because the root user overrride permissions +@HAVE_POSIX_TRUE@@HAVE_THREAD_CHECKER_FALSE@ if [[ $$EUID -ne 0 ]]; then \ +@HAVE_POSIX_TRUE@@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-run "chmod a-r bench/disk1/RUN-CHMOD" --test-expect-failure sync; \ +@HAVE_POSIX_TRUE@@HAVE_THREAD_CHECKER_FALSE@ fi +@HAVE_THREAD_CHECKER_FALSE@ echo RUN > bench/disk1/RUN-SIZE +@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-run "echo RUNRUN > bench/disk1/RUN-SIZE" --test-expect-failure sync +@HAVE_THREAD_CHECKER_FALSE@ echo RUN > bench/disk1/RUN-TOUCH +@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-run "touch -t 200001011200 bench/disk1/RUN-TOUCH" --test-expect-failure sync +@HAVE_THREAD_CHECKER_FALSE@ echo RUN > bench/disk1/RUN-INODE +@HAVE_THREAD_CHECKER_FALSE@ cp -p bench/disk1/RUN-INODE bench/disk1/RUN-INODE-COPY +@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-run "mv bench/disk1/RUN-INODE-COPY bench/disk1/RUN-INODE" --test-expect-failure sync +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk1/RUN-CHMOD +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk1/RUN-SIZE +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk1/RUN-TOUCH +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk1/RUN-INODE +@HAVE_THREAD_CHECKER_FALSE@ echo HASH > bench/disk1/HASH-RM +@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-run "rm bench/disk1/HASH-RM" --test-expect-failure -h sync +@HAVE_THREAD_CHECKER_FALSE@ echo HASH > bench/disk1/HASH-CHMOD +# Doesn't run this test as root because the root user override permissions +@HAVE_POSIX_TRUE@@HAVE_THREAD_CHECKER_FALSE@ if [[ $$EUID -ne 0 ]]; then \ +@HAVE_POSIX_TRUE@@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-run "chmod a-r bench/disk1/HASH-CHMOD" --test-expect-failure -h sync; \ +@HAVE_POSIX_TRUE@@HAVE_THREAD_CHECKER_FALSE@ fi +@HAVE_THREAD_CHECKER_FALSE@ echo HASH > bench/disk1/HASH-SIZE +@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-run "echo HASHHASH > bench/disk1/HASH-SIZE" --test-expect-failure -h sync +@HAVE_THREAD_CHECKER_FALSE@ echo HASH > bench/disk1/HASH-TOUCH +@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-run "touch -t 200001011200 bench/disk1/HASH-TOUCH" --test-expect-failure -h sync +@HAVE_THREAD_CHECKER_FALSE@ echo HASH > bench/disk1/HASH-INODE +@HAVE_THREAD_CHECKER_FALSE@ cp -p bench/disk1/HASH-INODE bench/disk1/HASH-INODE-COPY +@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-run "mv bench/disk1/HASH-INODE-COPY bench/disk1/HASH-INODE" --test-expect-failure -h sync +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk1/HASH-CHMOD +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk1/HASH-SIZE +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk1/HASH-TOUCH +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk1/HASH-INODE +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +#### SILENT ERRORS #### +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Silently corrupt some files, scrub and fix filtering for error. Test scrub patterns. +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./mktest$(EXEEXT) damage 1 1 1 bench/disk1/a/* +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-expect-recoverable --test-force-scrub-at 100000 scrub +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) fix -e +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --percentage bad scrub +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --plan 1 scrub +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -o 0 scrub +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -p full scrub +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -p new scrub +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Silently corrupt some files, and sync with error presents +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./mktest$(EXEEXT) write 2 1 1 bench/disk1/a/* +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./mktest$(EXEEXT) damage 3 1 1 bench/disk2/a/* +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-expect-recoverable sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status +# Note that this fix -e command doesn't fix all the errors because +# only the blocks touched by the sync are marked bad +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) fix -e +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check --test-expect-recoverable +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) fix +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -p full scrub +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Full sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -F sync +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Realloc sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -R sync +#### SYNC PARTIAL #### +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Abort sync with additions. Delete some of them, and add others and sync again. +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) This triggers files reallocation inside parity +@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk1/c +@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk1/d +@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk1/e +@HAVE_THREAD_CHECKER_FALSE@ cp -pR bench/disk2/a/c* bench/disk1/c +@HAVE_THREAD_CHECKER_FALSE@ cp -pR bench/disk2/a/d* bench/disk1/d +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-kill-after-sync sync +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1/c +@HAVE_THREAD_CHECKER_FALSE@ cp -pR bench/disk2/a/e* bench/disk1/e +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Abort sync with both deletions and additions. And delete and add some more and sync again. +# Note that here we are depending of the previous state leaving dirs "d" and "e" +@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk1/f +@HAVE_THREAD_CHECKER_FALSE@ cp -pR bench/disk3/a/f* bench/disk1/f +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1/d +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-kill-after-sync sync +@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk1/g +@HAVE_THREAD_CHECKER_FALSE@ cp -pR bench/disk4/a/g* bench/disk1/g +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1/e +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1/f +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1/g +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Make a hole in the disk array and sync with --force-empty +@HAVE_THREAD_CHECKER_FALSE@ mv bench/disk2 bench/disk2.old +@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk2 +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --force-empty sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Use with the hole +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(HOLE) sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(HOLE) check +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1/a +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk3/a +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(HOLE) fix -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(HOLE) check +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(HOLE) test-dry +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Fill the hole with a new disk +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk2 +@HAVE_THREAD_CHECKER_FALSE@ mv bench/disk2.old bench/disk2 +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Corrupt the content file +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./mktest$(EXEEXT) write 1 100 100 bench/content +@HAVE_THREAD_CHECKER_FALSE@ $(FAILENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-failure -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ rm bench/content +#### AGAIN MORE FILES #### +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Delete some files, create some new, sync and check +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk1/a/1* +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk2/a/2* +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk3/a/3* +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk4/a/4* +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./mktest$(EXEEXT) generate 3 6 $(CHECKCOUNT) $(CHECKSIZE) +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Move some files, sync and check +@HAVE_THREAD_CHECKER_FALSE@ mv bench/disk1/a/7* bench/disk1/b/ +@HAVE_THREAD_CHECKER_FALSE@ mv bench/disk2/a/7* bench/disk2/b/ +@HAVE_THREAD_CHECKER_FALSE@ mv bench/disk3/a/7* bench/disk3/b/ +@HAVE_THREAD_CHECKER_FALSE@ mv bench/disk4/a/7* bench/disk4/b/ +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +#### RECOVER 1 #### +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Delete one disk, fix and check with PAR1 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk3 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk3 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR1) check -l test.log +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) fix -l test.log +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +#### RECOVER 2 #### +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Delete two disks, fix and check with PAR2 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk1 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk2 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk2 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(PAR1) fix -l test-fail-strategy1.log +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR2) check -l test.log +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +#### RECOVER 3 #### +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Delete three disks, fix and check with PAR3 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk1 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk2 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk2 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk3 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk3 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(PAR2) fix -l test-fail-strategy2.log +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR3) check -l test.log +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR3) fix -l test.log +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +#### RECOVER 4 #### +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Delete four disks, fix and check with PAR4 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk3 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk3 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk4 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk4 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk5 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk5 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk6 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk6 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(PAR3) fix -l test-fail-strategy3.log +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR4) check -l test.log +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR4) fix -l test.log +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +#### RECOVER 5 #### +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Delete five disks, fix and check with PAR5 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk1 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk2 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk2 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk3 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk3 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk5 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk5 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk6 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk6 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(PAR4) fix -l test-fail-strategy4.log +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR5) check -l test.log +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR5) fix -l test.log +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +#### RECOVER 6 #### +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Delete six disks, fix and check with PAR6 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk1 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk2 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk2 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk3 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk3 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk4 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk4 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk5 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk5 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk6 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk6 +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(PAR5) fix -l test-fail-strategy5.log +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR6) check -l test.log +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR6) fix -l test.log +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_MEMORY_CHECKER_FALSE@@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +#### MULTI STEP #### +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Delete some files and create some new, sync and check in multiple steps +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk1/a/4* +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk2/a/5* +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk3/a/6* +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk4/a/6* +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -B 10 sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./mktest$(EXEEXT) generate 4 6 $(CHECKCOUNT) $(CHECKSIZE) +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -B 100 sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -B 1000 sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Rehash to spooky2 and rehash even blocks +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-force-spooky2 rehash +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-force-scrub-even scrub +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) status +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Full sync to complete rehash +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -F sync +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Delete files from three disks and check/fix with import by data in PAR2 +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1/a +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk2/a +@HAVE_THREAD_CHECKER_FALSE@ mv bench/disk3/a bench/a +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-import-content bench/a -c $(PAR2) fix -l test.log +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/a +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Delete files from three disks and check/fix with import by timestamp in PAR2 +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1/a +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk2/a +@HAVE_THREAD_CHECKER_FALSE@ mv bench/disk3/a bench/a +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -i bench/a -c $(PAR2) fix -l test.log +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/a +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Delete files from three disks and check/fix with automatic import in PAR2 +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1/a +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk2/a +@HAVE_THREAD_CHECKER_FALSE@ mv bench/disk3/a bench/disk1/a_from_disk3 +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1/a_from_disk3 +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +#### SYNC ABORT #### +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Abort sync late with additions, delete them and recover with PAR2 +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) This triggers the recovering with q using p to check the validity +@HAVE_THREAD_CHECKER_FALSE@ cp -pR bench/disk1/a bench/disk1/a_copy +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-kill-after-sync -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1/a_copy +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1/a_copy +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Abort sync early with additions, delete them and recover with PAR2 +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) This triggers the recovering with q using p to check the validity, but failing for new blocks being filled with zero +@HAVE_THREAD_CHECKER_FALSE@ cp -pR bench/disk1/a bench/disk1/a_copy +# Ensure that there is at least one zero filled file +@HAVE_THREAD_CHECKER_FALSE@ head -c 8192 /dev/zero > bench/disk1/a_copy/ZERO_FILLED +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -B 1 --test-kill-after-sync -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1/a_copy +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(PAR2) fix -l test-fail-earlysyncadd.log +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1/a_copy +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Abort sync late with additions with prehash and then delete the new additions and sync again +@HAVE_THREAD_CHECKER_FALSE@ cp -pR bench/disk1/a bench/disk1/a_copy +@HAVE_THREAD_CHECKER_FALSE@ cp -pR bench/disk2/a bench/disk2/a_copy +@HAVE_THREAD_CHECKER_FALSE@ cp -pR bench/disk3/a bench/disk3/a_copy +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-kill-after-sync -c $(CONF) -h sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1/a_copy +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk2/a_copy +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk3/a_copy +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Abort sync late with additions and then delete the new additions and sync again +@HAVE_THREAD_CHECKER_FALSE@ cp -pR bench/disk1/a bench/disk1/a_copy +@HAVE_THREAD_CHECKER_FALSE@ cp -pR bench/disk2/a bench/disk2/a_copy +@HAVE_THREAD_CHECKER_FALSE@ cp -pR bench/disk3/a bench/disk3/a_copy +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-kill-after-sync -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1/a_copy +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk2/a_copy +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk3/a_copy +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Abort sync late with additions and then delete some unchanged stuff and fix with PAR1 +@HAVE_THREAD_CHECKER_FALSE@ cp -pR bench/disk1/b bench/disk1/b_copy +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) --test-kill-after-sync sync +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk2 +@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk2 +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) fix -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Fixes again to restore all the parity +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) fix -l test.log +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1/b_copy +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Abort sync late with more deletions than additions and then delete some unchanged stuff and fix with PAR1 +@HAVE_THREAD_CHECKER_FALSE@ cp -pR bench/disk1/a bench/disk1/a_copy +@HAVE_THREAD_CHECKER_FALSE@ mv bench/disk1/a bench/a +@HAVE_THREAD_CHECKER_FALSE@ mv bench/disk1/b bench/b +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) --test-kill-after-sync sync +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk2 +@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk2 +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) fix -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Fixes again to restore all the parity +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) fix -l test.log +@HAVE_THREAD_CHECKER_FALSE@ -rm -r bench/disk1/a +@HAVE_THREAD_CHECKER_FALSE@ -rm -r bench/disk1/b +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1/a_copy +@HAVE_THREAD_CHECKER_FALSE@ mv bench/a bench/disk1/a +@HAVE_THREAD_CHECKER_FALSE@ mv bench/b bench/disk1/b +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Abort sync early with more deletions than additions and then delete some unchanged stuff and fix with PAR2 +@HAVE_THREAD_CHECKER_FALSE@ cp -pR bench/disk1/a bench/disk1/a_copy +@HAVE_THREAD_CHECKER_FALSE@ mv bench/disk1/a bench/a +@HAVE_THREAD_CHECKER_FALSE@ mv bench/disk1/b bench/b +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -B 1 --test-kill-after-sync sync +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk2 +@HAVE_THREAD_CHECKER_FALSE@ mkdir bench/disk2 +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(PAR1) fix -l test-fail-earlysyncdel.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log +@HAVE_THREAD_CHECKER_FALSE@ -rm -r bench/disk1/a +@HAVE_THREAD_CHECKER_FALSE@ -rm -r bench/disk1/b +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1/a_copy +@HAVE_THREAD_CHECKER_FALSE@ mv bench/a bench/disk1/a +@HAVE_THREAD_CHECKER_FALSE@ mv bench/b bench/disk1/b +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +#### RECOVER MISSING #### +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Delete some files, fix with -m and check with PAR1 +@HAVE_THREAD_CHECKER_FALSE@ rm bench/disk1/a/8* +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR1) check -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) -m fix -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Delete some dirs in six disk, fix with -m and check +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk1/b +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk2/b +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk3/b +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk4/b +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk5/b +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk6/b +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(PAR5) fix -l test-full5.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(CONF) check -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -m fix -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +#### RECOVER BY DISK #### +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Delete some dirs in two disks, fix and check with PAR2 using the -d option for each disk +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk2/b +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk5/b +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(PAR1) check -l test-full1.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) -d disk2 fix -l test-part1.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) -d disk5 fix -l test-part2.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +#### RECOVER PARITY #### +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Delete the parity, fix and check with PAR1 +@HAVE_THREAD_CHECKER_FALSE@ rm bench/parity* +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) check -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) fix -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Delete the parity and the 2-parity, fix and check with PAR2 +@HAVE_THREAD_CHECKER_FALSE@ rm bench/parity* +@HAVE_THREAD_CHECKER_FALSE@ rm bench/2-parity* +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Delete the parity and a disk, fix and check with PAR2 +@HAVE_THREAD_CHECKER_FALSE@ rm bench/parity* +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk2/b +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Delete the 2-parity and a disk, fix and check with PAR2 +@HAVE_THREAD_CHECKER_FALSE@ rm bench/2-parity* +@HAVE_THREAD_CHECKER_FALSE@ rm -r bench/disk3/a +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Corrupt the parity, fix and check with PAR1 +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./mktest$(EXEEXT) write 1 100 10000 bench/parity* +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR1) check -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) -a check +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) fix -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Corrupt the parity and the 2-parity, fix and check with PAR2 +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./mktest$(EXEEXT) write 2 100 10000 bench/parity* +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./mktest$(EXEEXT) write 2 100 10000 bench/2-parity* +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR2) check -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) -a check +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +#### RECOVER FILES AND PARITY #### +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Corrupt some files, fix and check with PAR1 +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./mktest$(EXEEXT) change 3 500 bench/disk2/b/* +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR1) -a check -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR1) check -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR1) fix -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Corrupt some files, fix and check with PAR2 in verbose mode +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./mktest$(EXEEXT) change 4 500 bench/disk2/b/* +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./mktest$(EXEEXT) change 4 500 bench/disk3/b/* +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) --test-expect-unrecoverable -c $(PAR1) check -l test.log > /dev/null +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS_VERBOSE) --test-expect-unrecoverable -c $(PAR1) fix -l test-fail-corrupt-verbose.log > /dev/null +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR2) -a check -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR2) check -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Corrupt some files, fix and check with PAR2 +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./mktest$(EXEEXT) change 5 500 bench/disk2/b/* +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./mktest$(EXEEXT) change 5 500 bench/disk3/b/* +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(PAR1) check -l test-fail-corrupt-data.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR2) check -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Corrupt the parity and some files, fix and check with PAR2 +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./mktest$(EXEEXT) write 6 100 10000 bench/parity* +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./mktest$(EXEEXT) change 6 500 bench/disk1/a/* +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-unrecoverable -c $(PAR1) check -l test-fail-corrupt-parity.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR2) check -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Corrupt the 2-parity and some files, fix and check with PAR2 +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./mktest$(EXEEXT) write 7 100 10000 bench/2-parity* +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./mktest$(EXEEXT) change 7 500 bench/disk1/a/* +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR1) check -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) --test-expect-recoverable -c $(PAR2) check -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(PAR2) fix -l test.log +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check +@HAVE_THREAD_CHECKER_FALSE@ $(MSG) Sync after all the fixes +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) sync +@HAVE_THREAD_CHECKER_FALSE@ $(TESTENV) ./snapraid$(EXEEXT) $(CHECKFLAGS) -c $(CONF) check + $(MSG) Regression test completed with SUCCESS! + $(MSG) Please ignore any error message printed above, they are expected! + $(MSG) Everything OK + +valgrind: + valgrind \ + --tool=memcheck \ + --track-origins=yes \ + --read-var-info=yes \ + --leak-check=full \ + -v $(MANUAL) \ + 2> valgrind.log + tail valgrind.log + +callgrind: + valgrind \ + --tool=callgrind \ + --dump-instr=yes \ + --trace-jump=yes \ + --collect-systime=yes \ + -v $(MANUAL) \ + 2> callgrind.log + tail callgrind.log + +cachegrind: + valgrind \ + --tool=cachegrind \ + -v $(MANUAL) \ + 2> cachegrind.log + tail cachegrind.log + +lcov_reset: + lcov --directory . -z + rm -f ./lcov.info + +lcov_capture: + lcov --directory . --capture -o lcov.info + +lcov_html: + rm -rf ./cov + mkdir cov + genhtml -o ./cov lcov.info + +# Rules for documentation + +@HAVE_ADVD2_TRUE@snapraid.1 : snapraid.d +@HAVE_ADVD2_TRUE@ advd2 man < $(srcdir)/$< > $@ + +@HAVE_ADVD2_TRUE@snapraid.txt : snapraid.d +@HAVE_ADVD2_TRUE@ advd2 txt < $(srcdir)/$< | todos > $@ + +@HAVE_ADVD2_TRUE@snapraid.html : snapraid.d +@HAVE_ADVD2_TRUE@ advd2 html < $(srcdir)/$< > $@ + +@HAVE_ADVD2_TRUE@snapraid.hh : snapraid.d +@HAVE_ADVD2_TRUE@ advd2 frame < $(srcdir)/$< > $@ + +distwindows-x86: $(DISTWIN) + rm -f $(PACKAGE)-$(VERSION)-windows-x86.zip + mkdir tmp + cp $(DISTWIN) tmp + cp support/smartctl.exe tmp/smartctl.exe + todos < snapraid.conf.example.windows > tmp/snapraid.conf.example + todos < INSTALL.windows > tmp/install.txt + todos < README > tmp/readme.txt + todos < AUTHORS > tmp/authors.txt + todos < HISTORY > tmp/history.txt + todos < COPYING > tmp/copying.txt + todos < TODO > tmp/todo.txt + cd tmp && zip -r ../$(PACKAGE)-$(VERSION)-windows-x86.zip * + rm -r tmp + +distwindows-x64: $(DISTWIN) + rm -f $(PACKAGE)-$(VERSION)-windows-x64.zip + mkdir tmp + cp $(DISTWIN) tmp + cp support/smartctl.exe tmp/smartctl.exe + todos < snapraid.conf.example.windows > tmp/snapraid.conf.example + todos < INSTALL.windows > tmp/install.txt + todos < README > tmp/readme.txt + todos < AUTHORS > tmp/authors.txt + todos < HISTORY > tmp/history.txt + todos < COPYING > tmp/copying.txt + todos < TODO > tmp/todo.txt + cd tmp && zip -r ../$(PACKAGE)-$(VERSION)-windows-x64.zip * + rm -r tmp + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/README b/README new file mode 100644 index 0000000..52a90b7 --- /dev/null +++ b/README @@ -0,0 +1,32 @@ +SnapRAID +======== + +SnapRAID is a backup program for disk arrays. It stores parity +information of your data and it recovers from up to six disk +failures. + +SnapRAID is mainly targeted for a home media center, where you +have a lot of big files that rarely change. + +Beside the ability to recover from disk failures, the other +features of SnapRAID are: + +* All your data is hashed to ensure data integrity and to avoid + silent corruption. +* If the failed disks are too many to allow a recovery, + you lose the data only on the failed disks. + All the data in the other disks is safe. +* If you accidentally delete some files in a disk, you can + recover them. +* You can start with already filled disks. +* The disks can have different sizes. +* You can add disks at any time. +* It doesn't lock-in your data. You can stop using SnapRAID at any + time without the need to reformat or move data. +* To access a file, a single disk needs to spin, saving power and + producing less noise. + +The official site of SnapRAID is: + + http://www.snapraid.it/ + diff --git a/TODO b/TODO new file mode 100644 index 0000000..ad2a21c --- /dev/null +++ b/TODO @@ -0,0 +1,360 @@ +SnapRAID TODO +============= + +This is the list of TODO items for SnapRAID. + +- Next + +- Minor + +* Add a new -u, --filter-updated command that filters files +with a different timestamp, to be able to restore only them to the previous state. +See: https://sourceforge.net/p/snapraid/discussion/1677233/thread/e26e787d/ + +* Allow to filter in diff/list by disk name. +Not checked disks should be allowed to be missing. + +* Add an option to ignore subsecond timestamp. +Like when you copy data to a filesystem with less timestamp precision. + +* Extend haspdeep to support the SnapRAID hash : +https://github.com/jessek/hashdeep/ +https://sourceforge.net/p/snapraid/discussion/1677233/thread/90b0e9b2/?limit=25 + +* Add a "noaccessdenied" config option to exclude not readable files/dirs. +Like the "nohidden". +See: https://sourceforge.net/p/snapraid/discussion/1677233/thread/1409c26a/ + +* Don't insert new files if they are new opened by other applications. +Not yet sure how to check if a file is open in a fast way. +In case we can exclude files created too recently, like with a --min-age option. +See: https://sourceforge.net/p/snapraid/discussion/1677233/thread/a1683dd9/?limit=25#1e16 + +* Add markdown support for output +See: https://sourceforge.net/p/snapraid/discussion/1677233/thread/661cce8b/ + +* Add ZFS support for SMART and UUID. +See latest messages at: https://sourceforge.net/p/snapraid/discussion/1677233/thread/42defa3b/ + +* Change all the path printed in the terminal as relative and not absolute. +https://sourceforge.net/p/snapraid/discussion/1677233/thread/648955ec/ (Leifi in diff) +https://sourceforge.net/p/snapraid/discussion/1677233/thread/5b6ef1b9/ (Miles in check + filter) +Partially done. Now you can control it with --test-fmt + +* Add ReFS support with 128 bits inode +See: https://sourceforge.net/p/snapraid/discussion/1677233/thread/2be14f63/ +https://github.com/Microsoft/Windows-driver-samples/blob/master/filesys/miniFilter/avscan/filter/utility.h +https://github.com/Microsoft/Windows-driver-samples/blob/master/filesys/miniFilter/avscan/filter/utility.c +https://github.com/Microsoft/Windows-driver-samples/blob/master/filesys/miniFilter/delete/delete.c +Partially done. Until the inodes are less than 64 bit, everything works. +If a 128 bit inode is found, it aborts with "Invalid inode number! Is this ReFS?" + +* When a disk is replaced, and SnapRAID detect this by a UUID change, we could clear the +scrub information for that disk. +https://sourceforge.net/p/snapraid/discussion/1677233/thread/ee87901b/ + +* In fix, automatic --import excluded directory in the config file. +https://sourceforge.net/p/snapraid/discussion/1677233/thread/c80c42e5/?limit=25 + +* Allow to have "partial" parity disks, smaller than required ? +https://sourceforge.net/p/snapraid/discussion/1677233/thread/e924c663/ + +* How to handle corrupt copied/moved files ? At now pre-hash checks them, +but if a corruption is found, it stops the sync process. +This is not optimal, because the 'sync' command is stopped instead to continue. +A possible solution could be: +If a copied block is corrupt, we can recover the original one from parity (if moved), +or read it directly from disk (if copied), and we can use this one to build the parity, +working around the corruption, that can be later fixed with "fix". +This requires to allocate blocks of moved files in parity positions *after* the +currently used one. + +* Some programs are misusing the FILE_ATTRIBUTE_TEMPORARY. +In fact, it makes sense as it's a good way to control the cache on the file, +so, despite the name, that usage could be common for not temporary files. +https://sourceforge.net/p/snapraid/discussion/1677233/thread/57d40108/ + +* Restore ownership and permissions, at least in Unix. + +* Restore directory timestamps. + +* Add an option for dup to list only duplicates with different name. +This supposing that if a file has the same name, it's intentionally duplicated. + +* In fix an existing symlink with the same name of a file to be recovered may stop +the process making the create() operation to fail. +The same for directories, when recreating the directory tree. + +* If a directory exists with the same name of a parity/content file be more explicative +on the error message. See: https://sourceforge.net/projects/snapraid/forums/forum/1677233/topic/4861034 + +* We don't try to do partial block recovering. A block is correct or not. +But if only some bytes, or a sector, is wrong, it should be possible to recover all the +rest of the block. +The problem is that we don't have any hash to ensure that the block is partially recovered, +or completely garbage. But it makes sense to anyway write the "most likely" correct one. + +- Naming + +* A new 'init' command to differentiate the first 'sync' operation. +This 'init' will work also without a content file, and parity files. +Instead 'sync' will require all of them. +This will also help when running with the parity filesystem unmounted. + +* Rename sync->backup and fix->restore. It seems to me a naming expressing +better the meaning of the commands. But not yet sure. + +- Pooling + +* Add a new "commit" command to move changes from the pool to the array. +It should: +- Move files copied into the pool (that are no links) to the array. +The files should be moved to the disk that contains most of the files +in the directory. If no space, try with the disk with less files +in the directory, and eventually the disk in the array with more free space. +- Detect renames, and apply them in the array. +The file will be renamed and moved to the new directory, if changed, +but kept in the same disk of the array. +- Detect deletes, and move file in the array to a "/trash/" directory +of the same disk. For safety no real deletion is done. +File with the same name will get an extra extension like ".1", ".2". + +- Major + +* Uses a separated file for storing hashes, to allow to use a memory +mapped file to decrease memory utilization. +The file can contains hashes stored in the same order they are accessed +in sync/check/scrub. ++ A lot less memory utilization +- It will be slow in --pre-hash as the files are accessed in another order, +but no much slow. +- How to handle multiple .content file copy ? When working we can have +only a single file. When storing the .content we'll have to copy it +in all the places. +* Can we mix the existing and new approach ? We can create this +hash file at startup in a memory mapped "temporary" file. +It may takes some time to create it, but then it will be fast. +See: https://sourceforge.net/p/snapraid/discussion/1677233/thread/cdea773f/ + +* Allocate parity minimizing concurrent use of it +Each parity allocation should check for a parity +range with less utilization by other disks. +We need to take care do disable this meachnism when the parity space +is near to fillup the parity partition. +See: https://sourceforge.net/p/snapraid/discussion/1677233/thread/1797bf7d/ ++ This increase the possibility of recovering with multiple failures with not +enough parity, as the benefit of existing parity is maximized. +- Possible increase of fragmentation of parity allocation +- No real benefit when the array is filled + + +Rejected TODO +============= + +This is a list of rejected TODO items. + +* Allow multiple parity files and to coexist with data +in the same disk. +This is possible if the data in the same disk uses parity addresses not +contained in the parity file present in the same disk. ++ It's a nice trick. The disk containing parity, will have less space available, +and then it will need less parity, resolving the problem of the parity disk being too small. ++ We can also think at an automated parity files naming and creation, removing +the need of the user to specify that. We can also completely remove the +concept of parity drive, automatically allocating parity in the most free data drives. +- It won't be not nice to have the program to automatically +choose where to create the parity, because the choice cannot be optimal. +With a dedicated disk manually chosen, it's instead optimal. ++ We can limit this coexist possibility only to latest parity file, +allowing the user to choose where to put it. +- It won't work with disks of different size. +Suppose to have all disks of size N, with only one of size M>N. +To fully use the M space, you can allocate a full N parity in such disk, +but the remaning space will also need additional parity in the other disks, +in fact requiring a total of M parity for the array. +In the end, we cannot avoid that the first biggest disk added is fully +dedicated to parity, even if it means to leave some space unused. + +* Directly access disks for parity skipping the filesystem layer +- No real performance or space gain compared to a custom filesystem configuration like: +mkfs.ext3 -i 16777216 -m0 -O ^dir_index,large_file,sparse_super /dev/sdX1 +See: https://sourceforge.net/p/snapraid/discussion/1677233/thread/9c0ef324/?limit=25 + +* Allow to specify more than one disk directories to cover the case of multi partitions. +Different partitions have duplicate inode. The only way to support this is to +add also a kind of device_id, increasing the memory required. +But it should be only few bits for each file. So, it should be manageable. +A lot of discussions about this feature :) +https://sourceforge.net/p/snapraid/discussion/1677233/thread/b2cd9385/ +- The only benefit is to distribute better the data. This could help the recovery process, +in case of multiple failures. But no real usability or funtionality benefit in the normal +case. + +* https://sourceforge.net/p/snapraid/discussion/1677233/thread/2cb97e8a/ +Have two hashes for each file. One for the first segment, that may use only a part of the first parity block. +And a second hash that takes care of the final segment, also using only part of a parity block. +Intermediate blocks can be handled like now. +The first and last segment can use only a part of the parity block, sharing it with other files, +and then allowing big parity blocks. ++ Big parity block, like 1MB, and small file allocation, like 4KB. +- It won't be possible to copy hash info from one disk to another, as copied files +may have a different block splitting. Copied file should be allocated with the same exact +splitting. +- Dup detection can be handled with a dedicated hash covering the full file. But increasing +the number of hash for each file to three. +- No way to handle block import. + +* Create a filesystem snapshot at every sync, and use it in all the other commands +automatically. +At the next sync, drop the old snapshot and create a new one. +This should help recovering, because we'll have the exact copy used by sync. +This feature can be enabled with a specific option, and available +in Windows using Shadow Copy, and in Linux using Btrfs, and in a generic +Unix using ZFS. +See Jens's Windows script at: http://sourceforge.net/p/snapraid/discussion/1677233/thread/a1707211/ +Note that a different between Windows and Unix is that in Windows old snapshots +are automatically deleted. + +* Checks if splitting hash/parity computation in 4K pages +can improve speed in sync. That should increase cache locality, +because we read the data two times for hash and and parity, +and if we manage to keep it in the cache, we should save time. +- We now hash first the faster disks, and this could +reduce performance as we'll have to wait for all disks. + +* Use threads to scan all the disks at the same time. +- After 7.0 Windows changes it seems fast enough even +with a mono thread implementation. + +* Enable storing of creation time NTFS, crtime/birth time EXT4. +But see: http://unix.stackexchange.com/questions/50177/birth-is-empty-on-ext4 +coreutils stat has an example, but it doesn't work in Linux (see lib/stat-time.h) +- Not supported in Linux. + +* In the content file save the timestamp of the parity files. +If they do not match, stop the processing. +This can be done to avoid to use not synchronized parity and content files, +resulting in wrong data. +But if the sync process is killed we need a way to resyncronize them. +Or maybe we should allow parity newer than content, but not viceversa. +- The corner cases are too many. A fixed parity may be never. +A someway modified content may be never. So, the time is not really significant. + +* Use Async IO for Linux (libaio). +See thread: https://sourceforge.net/p/snapraid/discussion/1677233/thread/a300a10b/ +Docs at: http://www.fsl.cs.sunysb.edu/~vass/linux-aio.txt +- Implemented for scrub in the "libaio" branch, but it's slower of +about 20% in my machine. + +* Allow to put parity directly into the underline block device without the need +of any filesystem. +That would allow to increase a lot the free space for parity. +We can implement some kind of filesystem detection to avoid to overwrite an already +existing filesystem. +- Still risky if stuffs go wrong. +- In Linux with largefile4 there is only a very small amount of space wasted. +In the order of 0.01%. Not really worth to do it. +- With NTFS the saving is also limited, because the "reserved" MFT of 12.5% is +not really exclusively reserved, but can be used also for normal files, +when all the remaining space is filled. + +* The data could be compressed before processing, resulting in parity block of +fixed size, but matching different data block sizes. +The complexity is that a file blocks will have to be allocated at runtime, +and you may run out of them in the middle of the processing. +We need also a way to compress a stream until the compressed data reach the +block size, but no more, and then start a new block. +For each block, we'll have also to store. "size_uncompressed", "size_compressed", +"hash". +- It will be too slow. +- Not addressing the problem of a lot of small files, as still one block will be +allocated for each file. + +* Uses different block size for parity and file allocation. +We can use a big size, like 1MB for parity allocation and hash computation, +and at the same time using a 4K blocks for files allocation. +This means that a parity blocks may contain more than one file. +- We'll have to drop the dup and import feature, +because it won't be possible anymore to compare the hash of files, +as it would depend also on the start address inside the parity block. +- When a hash fail, it won't be possible to tell which file is really +broken, because more file may share the same parity block. + +* Have special parity blocks containing the last blocks of more files +until it's filled up. +For such parity blocks, we'll have more than one hash. One for each +file contained. +- Parity will be too fragmented, because we'll have parity blocks +containing the last blocks of many files. + +* In "pool" for Windows, and for unique directories a junction to the +directory could be used, avoiding to use symlinks to files. +This allows to overcome the problem of sharing symlinks. +- It would work, in fact it would work to well. The problem is that +Windows will treat the junction as the real directory, like *really* +deleting its content from Explorer pressing "del" and also from the +command line with "rd". Too dangerous. + +* When fixing, before overwriting the present file, make a copy of it just in +case that the original file cannot be completely recovered. +We can always open files in read-only mode, if a write is required, we close it, +rename it to with a .bak extension, and rewrite it up to the required size. +The same for symlink if a file with the same name exist or viceversa. +- The idea behind this is to avoid to leave untouched a file if we cannot +restore it completely. But it's debatable what's better in this case. +Anyway, considering the typical use, it's not really relevant. + +* In the import list, uses also all the blocks in the array. +But we must cover the case of bad blocks. Likely we can just check the +hash after reading, and in case, skip it, and retry with another copy. +- It will work only for duplicate files. Not really worth do to it. + +* Save the content file in compressed .gz format to save space. +- Compression is too slow. Even using the very fast lzo. +$ time lzop -1 < content > content.lzo +real 1m23.014s +user 0m40.822s +sys 0m3.389s + +$ time ./gzip -1 < content > content.gz +real 1m47.463s +user 1m23.732s +sys 0m3.290s + +$ time ./gzip --huffonly < content > contentH.gz +real 1m51.607s +user 1m30.032s +sys 0m3.245s + +Similar command done with snapraid without compression, and involving also decoding +and encoding takes less time. + +$ time ./snapraid --test-skip-device --test-skip-self -v -c ./test.conf test-rewrite +real 0m59.087s +user 0m14.164s +sys 0m4.398s + +* Recognizes that a file is moved from one disk to another, and if the parity +data doesn't overlap, do not recompute it. +- It's going to work only in RAID5 mode and only in special cases. + +* Implements a multithread sync command to share HASH and RAID computations +to different CPUs. +- At now it's questionable if it will result in a performance improvement. +The murmur3 hash, and the RAID5/6 computations are so fast that even a single +thread should be able to do them. +Use the "snapraid -T" comment to see the speed. + +* In the repair() function the heuristic to detect if we recovered after the sync, +can be extended to all the previous blocks, because we always proceed in block +order during a sync. +So, if for a block we can detect that we recovered using updated parity data, +also for all the previous blocks this is true. +Anyway, the case where this information could be useful should be present +only if changes are committed after an aborted sync. +- No real advantage on that, beside some speed gain in fix. +The risk would be instead to miss some recovery opportunity. +So, makes sense to have it a little slower but trying any +possible recovery strategy. + + diff --git a/acinclude.m4 b/acinclude.m4 new file mode 100644 index 0000000..1b92cc9 --- /dev/null +++ b/acinclude.m4 @@ -0,0 +1,19 @@ +dnl @synopsis AC_CHECK_CC_OPT(flag, ifyes, ifno) +dnl +dnl Shows a message as like "checking wether gcc accepts flag ... no" +dnl and executess ifyes or ifno. + +AC_DEFUN([AC_CHECK_CC_OPT], +[ +AC_MSG_CHECKING([whether ${CC-cc} accepts $1]) +echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -c $1 conftest.c 2>&1`"; then + AC_MSG_RESULT([yes]) + $2 +else + AC_MSG_RESULT([no]) + $3 +fi +rm -f conftest* +]) + diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 0000000..09c00d5 --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,838 @@ +# generated automatically by aclocal 1.15 -*- Autoconf -*- + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) + +# Copyright (C) 2002-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.15' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.15], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.15])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is '.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. +m4_define([AC_PROG_CC], +m4_defn([AC_PROG_CC]) +[_AM_PROG_CC_C_O +]) + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.65])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[AC_DIAGNOSE([obsolete], + [$0: two- and three-arguments forms are deprecated.]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if( + m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl +]) +AC_REQUIRE([AM_SILENT_RULES])dnl +dnl The testsuite driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This +dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) + fi +fi +dnl The trailing newline in this macro's definition is deliberate, for +dnl backward compatibility and to allow trailing 'dnl'-style comments +dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. +]) + +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST([install_sh])]) + +# Copyright (C) 2003-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it is modern enough. +# If it is, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + AC_MSG_WARN(['missing' script is too old or missing]) +fi +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_CC_C_O +# --------------- +# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC +# to automatically call this. +AC_DEFUN([_AM_PROG_CC_C_O], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +AC_LANG_PUSH([C])dnl +AC_CACHE_CHECK( + [whether $CC understands -c and -o together], + [am_cv_prog_cc_c_o], + [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i]) +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +AC_LANG_POP([C])]) + +# For backward compatibility. +AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken + alias in your environment]) + fi + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT([yes]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) + +# Copyright (C) 2009-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# ("yes" being less verbose, "no" or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], [dnl +AS_HELP_STRING( + [--enable-silent-rules], + [less verbose build output (undo: "make V=1")]) +AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])dnl +]) +case $enable_silent_rules in @%:@ ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +dnl +dnl A few 'make' implementations (e.g., NonStop OS and NextStep) +dnl do not support nested variable expansions. +dnl See automake bug#9928 and bug#10237. +am_make=${MAKE-make} +AC_CACHE_CHECK([whether $am_make supports nested variables], + [am_cv_make_support_nested_variables], + [if AS_ECHO([['TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi]) +if test $am_cv_make_support_nested_variables = yes; then + dnl Using '$V' instead of '$(V)' breaks IRIX make. + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AC_SUBST([AM_V])dnl +AM_SUBST_NOTMAKE([AM_V])dnl +AC_SUBST([AM_DEFAULT_V])dnl +AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor 'install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in "make install-strip", and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2014 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +# +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' + +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + + [m4_case([$1], + [ustar], + [# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) + if test $am_uid -le $am_max_uid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi + AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) + if test $am_gid -le $am_max_gid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi], + + [pax], + [], + + [m4_fatal([Unknown tar format])]) + + AC_MSG_CHECKING([how to create a $1 tar archive]) + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_$1-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) + AC_MSG_RESULT([$am_cv_prog_tar_$1])]) + +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([acinclude.m4]) diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..8152272 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# +echo "Generating build information using autoreconf" + +# All is done by autoreconf +autoreconf -f -i + +# Run configure for this platform +echo "Now you are ready to run ./configure" + diff --git a/autover.sh b/autover.sh new file mode 100755 index 0000000..48f08eb --- /dev/null +++ b/autover.sh @@ -0,0 +1,19 @@ +#!/bin/sh +# + +if [ -d .git ]; then + # Get version from git tags, removing the 'v' prefix + VERSION=`git describe --match 'v*' 2>/dev/null | sed 's/^v//'` +fi + +if [ -f .version ]; then + # Get version from the .version file + VERSION=`cat .version` +fi + +if [ -z $VERSION ]; then + VERSION="none" +fi + +printf '%s' "$VERSION" + diff --git a/cmdline/check.c b/cmdline/check.c new file mode 100644 index 0000000..72012df --- /dev/null +++ b/cmdline/check.c @@ -0,0 +1,2049 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "support.h" +#include "util.h" +#include "elem.h" +#include "import.h" +#include "search.h" +#include "state.h" +#include "parity.h" +#include "handle.h" +#include "raid/raid.h" +#include "raid/combo.h" + +/****************************************************************************/ +/* check */ + +/** + * A block that failed the hash check, or that was deleted. + */ +struct failed_struct { + /** + * If we know for sure that the block is garbage or missing + * and it needs to be recovered and rewritten to the disk. + */ + int is_bad; + + /** + * If that we have recovered may be not updated data, + * an old version, or just garbage. + * + * Essentially, it means that we are not sure what we have recovered + * is really correct. It's just our best guess. + * + * These "recovered" block are also written to the disk if the block is marked as ::is_bad. + * But these files are marked also as FILE_IS_DAMAGED, and then renamed to .unrecoverable. + * + * Note that this could happen only for CHG blocks. + */ + int is_outofdate; + + unsigned index; /**< Index of the failed block. */ + struct snapraid_block* block; /**< The failed block */ + struct snapraid_disk* disk; /**< The failed disk. */ + struct snapraid_file* file; /**< The failed file. 0 for DELETED block. */ + block_off_t file_pos; /**< Offset inside the file */ + struct snapraid_handle* handle; /**< The handle containing the failed block, or 0 for a DELETED block */ +}; + +/** + * Check if a block hash matches the specified buffer. + * Return ==0 if equal + */ +static int blockcmp(struct snapraid_state* state, int rehash, struct snapraid_block* block, unsigned pos_size, unsigned char* buffer, unsigned char* buffer_zero) +{ + unsigned char hash[HASH_MAX]; + + /* now compute the hash of the valid part */ + if (rehash) { + memhash(state->prevhash, state->prevhashseed, hash, buffer, pos_size); + } else { + memhash(state->hash, state->hashseed, hash, buffer, pos_size); + } + + /* compare the hash */ + if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { + return -1; + } + + /* compare to the end of the block */ + if (pos_size < state->block_size) { + if (memcmp(buffer + pos_size, buffer_zero + pos_size, state->block_size - pos_size) != 0) { + return -1; + } + } + + return 0; +} + +/** + * Check if the hash of all the failed block we are expecting to recover are now matching. + */ +static int is_hash_matching(struct snapraid_state* state, int rehash, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void* buffer_zero) +{ + unsigned j; + int hash_checked; + + hash_checked = 0; /* keep track if we check at least one block */ + + /* check if the recovered blocks are OK */ + for (j = 0; j < failed_count; ++j) { + /* if we are expected to recover this block */ + if (!failed[failed_map[j]].is_outofdate + /* if the block has a hash to check */ + && block_has_updated_hash(failed[failed_map[j]].block) + ) { + /* if a hash doesn't match, fail the check */ + unsigned pos_size = file_block_size(failed[failed_map[j]].file, failed[failed_map[j]].file_pos, state->block_size); + if (blockcmp(state, rehash, failed[failed_map[j]].block, pos_size, buffer[failed[failed_map[j]].index], buffer_zero) != 0) { + log_tag("hash_error: Hash mismatch on entry %u\n", failed_map[j]); + return 0; + } + + hash_checked = 1; + } + } + + /* if nothing checked, we reject it */ + /* note that we are excluding this case at upper level */ + /* but checking again doesn't hurt */ + if (!hash_checked) { + /* LCOV_EXCL_START */ + return 0; + /* LCOV_EXCL_STOP */ + } + + /* if we checked something, and no block failed the check */ + /* recompute all the redundancy information */ + raid_gen(diskmax, state->level, state->block_size, buffer); + return 1; +} + +/** + * Check if specified parity is now matching with a recomputed one. + */ +static int is_parity_matching(struct snapraid_state* state, unsigned diskmax, unsigned i, void** buffer, void** buffer_recov) +{ + /* recompute parity, note that we don't need parity over i */ + raid_gen(diskmax, i + 1, state->block_size, buffer); + + /* if the recovered parity block matches */ + if (memcmp(buffer[diskmax + i], buffer_recov[i], state->block_size) == 0) { + /* recompute all the redundancy information */ + raid_gen(diskmax, state->level, state->block_size, buffer); + return 1; + } + + return 0; +} + +/** + * Repair errors. + * Return <0 if failure for missing strategy, >0 if data is wrong and we cannot rebuild correctly, 0 on success. + * If success, the parity are computed in the buffer variable. + */ +static int repair_step(struct snapraid_state* state, int rehash, unsigned pos, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void** buffer_recov, void* buffer_zero) +{ + unsigned i, n; + int error; + int has_hash; + int id[LEV_MAX]; + int ip[LEV_MAX]; + + /* no fix required, already checked at higher level, but just to be sure */ + if (failed_count == 0) { + /* LCOV_EXCL_START */ + /* recompute only the parity */ + raid_gen(diskmax, state->level, state->block_size, buffer); + return 0; + /* LCOV_EXCL_STOP */ + } + + n = state->level; + error = 0; + + /* setup vector of failed disk indexes */ + for (i = 0; i < failed_count; ++i) + id[i] = failed[failed_map[i]].index; + + /* check if there is at least a failed block that can be checked for correctness using the hash */ + /* if there isn't, we have to sacrifice a parity block to check that the result is correct */ + has_hash = 0; + for (i = 0; i < failed_count; ++i) { + /* if we are expected to recover this block */ + if (!failed[failed_map[i]].is_outofdate + /* if the block has a hash to check */ + && block_has_updated_hash(failed[failed_map[i]].block) + ) + has_hash = 1; + } + + /* if we don't have a hash, but we have an extra parity */ + /* (strictly-less failures than number of parities) */ + if (!has_hash && failed_count < n) { + /* number of parity to use, one more to check the recovering */ + unsigned r = failed_count + 1; + + /* all combinations (r of n) parities */ + combination_first(r, n, ip); + do { + /* if a parity is missing, do nothing */ + for (i = 0; i < r; ++i) { + if (buffer_recov[ip[i]] == 0) + break; + } + if (i != r) + continue; + + /* copy the parities to use, one less because the last is used for checking */ + for (i = 0; i < r - 1; ++i) + memcpy(buffer[diskmax + ip[i]], buffer_recov[ip[i]], state->block_size); + + /* recover using one less parity, the ip[r-1] one */ + raid_data(r - 1, id, ip, diskmax, state->block_size, buffer); + + /* use the remaining ip[r-1] parity to check the result */ + if (is_parity_matching(state, diskmax, ip[r - 1], buffer, buffer_recov)) + return 0; + + /* log */ + log_tag("parity_error:%u:", pos); + for (i = 0; i < r; ++i) { + if (i != 0) + log_tag("/"); + log_tag("%s", lev_config_name(ip[i])); + } + log_tag(":parity: Parity mismatch\n"); + ++error; + } while (combination_next(r, n, ip)); + } + + /* if we have a hash, and enough parities */ + /* (less-or-equal failures than number of parities) */ + if (has_hash && failed_count <= n) { + /* number of parities to use equal at the number of failures */ + unsigned r = failed_count; + + /* all combinations (r of n) parities */ + combination_first(r, n, ip); + do { + /* if a parity is missing, do nothing */ + for (i = 0; i < r; ++i) { + if (buffer_recov[ip[i]] == 0) + break; + } + if (i != r) + continue; + + /* copy the parities to use */ + for (i = 0; i < r; ++i) + memcpy(buffer[diskmax + ip[i]], buffer_recov[ip[i]], state->block_size); + + /* recover */ + raid_data(r, id, ip, diskmax, state->block_size, buffer); + + /* use the hash to check the result */ + if (is_hash_matching(state, rehash, diskmax, failed, failed_map, failed_count, buffer, buffer_zero)) + return 0; + + /* log */ + log_tag("parity_error:%u:", pos); + for (i = 0; i < r; ++i) { + if (i != 0) + log_tag("/"); + log_tag("%s", lev_config_name(ip[i])); + } + log_tag(":hash: Hash mismatch\n"); + ++error; + } while (combination_next(r, n, ip)); + } + + /* return the number of failed attempts, or -1 if no strategy */ + if (error) + return error; + + log_tag("strategy_error:%u: No strategy to recover from %u failures with %u parity %s hash\n", + pos, failed_count, n, has_hash ? "with" : "without"); + return -1; +} + +static int repair(struct snapraid_state* state, int rehash, unsigned pos, unsigned diskmax, struct failed_struct* failed, unsigned* failed_map, unsigned failed_count, void** buffer, void** buffer_recov, void* buffer_zero) +{ + int ret; + int error; + unsigned j; + int n; + int something_to_recover; + int something_unsynced; + char esc_buffer[ESC_MAX]; + + error = 0; + + /* if nothing failed, just recompute the parity */ + if (failed_count == 0) { + raid_gen(diskmax, state->level, state->block_size, buffer); + return 0; + } + + /* logs the status */ + for (j = 0; j < failed_count; ++j) { + const char* desc; + const char* hash; + const char* data; + struct snapraid_block* block = failed[j].block; + unsigned block_state = block_state_get(block); + + switch (block_state) { + case BLOCK_STATE_DELETED : desc = "delete"; break; + case BLOCK_STATE_CHG : desc = "change"; break; + case BLOCK_STATE_REP : desc = "replace"; break; + case BLOCK_STATE_BLK : desc = "block"; break; + /* LCOV_EXCL_START */ + default : desc = "unknown"; break; + /* LCOV_EXCL_STOP */ + } + + if (hash_is_invalid(block->hash)) { + hash = "lost"; + } else if (hash_is_zero(block->hash)) { + hash = "zero"; + } else { + hash = "known"; + } + + if (failed[j].is_bad) + data = "bad"; + else + data = "good"; + + if (failed[j].file) { + struct snapraid_disk* disk = failed[j].disk; + struct snapraid_file* file = failed[j].file; + block_off_t file_pos = failed[j].file_pos; + + log_tag("entry:%u:%s:%s:%s:%s:%s:%u:\n", j, desc, hash, data, disk->name, esc_tag(file->sub, esc_buffer), file_pos); + } else { + log_tag("entry:%u:%s:%s:%s:\n", j, desc, hash, data); + } + } + + /* Here we have to try two different strategies to recover, because in case the 'sync' */ + /* process is aborted, we don't know if the parity data is really updated just like after 'sync', */ + /* or if it still represents the state before the 'sync'. */ + + /* Note that if the 'sync' ends normally, we don't have any DELETED, REP and CHG blocks */ + /* and the two strategies are identical */ + + /* As first, we assume that the parity IS updated for the current state */ + /* and that we are going to recover the state after the last 'sync'. */ + /* In this case, parity contains info from BLK, REP and CHG blocks, */ + /* but not for DELETED. */ + /* We need to put in the recovering process only the bad blocks, because all the */ + /* others already contains the correct data read from disk, and the parity is correctly computed for them. */ + /* We are interested to recover BLK, REP and CHG blocks if they are marked as bad, */ + /* but we are not interested in DELETED ones. */ + + n = 0; + something_to_recover = 0; /* keep track if there is at least one block to fix */ + for (j = 0; j < failed_count; ++j) { + if (failed[j].is_bad) { + unsigned block_state = block_state_get(failed[j].block); + + assert(block_state != BLOCK_STATE_DELETED); /* we cannot have bad DELETED blocks */ + + /* if we have the hash for it */ + if ((block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP) + /* try to fetch the block using the known hash */ + && (state_import_fetch(state, rehash, failed[j].block, buffer[failed[j].index]) == 0 + || state_search_fetch(state, rehash, failed[j].file, failed[j].file_pos, failed[j].block, buffer[failed[j].index]) == 0) + ) { + /* we already have corrected it! */ + log_tag("hash_import: Fixed entry %u\n", j); + } else { + /* otherwise try to recover it */ + failed_map[n] = j; + ++n; + + /* we have something to try to recover */ + something_to_recover = 1; + } + } + } + + /* if nothing to fix */ + if (!something_to_recover) { + log_tag("recover_sync:%u:%u: Skipped for already recovered\n", pos, n); + + /* recompute only the parity */ + raid_gen(diskmax, state->level, state->block_size, buffer); + return 0; + } + + ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_recov, buffer_zero); + if (ret == 0) { + /* reprocess the CHG blocks, for which we don't have a hash to check */ + /* if they were BAD we have to use some heuristics to ensure that we have recovered */ + /* the state after the sync. If unsure, we assume the worst case */ + + for (j = 0; j < failed_count; ++j) { + /* we take care only of BAD blocks we have to write back */ + if (failed[j].is_bad) { + unsigned block_state = block_state_get(failed[j].block); + + /* BLK and REP blocks are always OK, because at this point */ + /* we have already checked their hash */ + if (block_state != BLOCK_STATE_CHG) { + assert(block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP); + continue; + } + + /* for CHG blocks we have to 'guess' if they are correct or not */ + + /* if the hash is invalid we cannot check the result */ + /* this could happen if we have lost this information */ + /* after an aborted sync */ + if (hash_is_invalid(failed[j].block->hash)) { + /* it may contain garbage */ + failed[j].is_outofdate = 1; + + log_tag("hash_unknown: Unknown hash on entry %u\n", j); + } else if (hash_is_zero(failed[j].block->hash)) { + /* if the block is not filled with 0, we are sure to have */ + /* restored it to the state after the 'sync' */ + /* instead, if the block is filled with 0, it could be either that the */ + /* block after the sync is really filled by 0, or that */ + /* we restored the block before the 'sync'. */ + if (memcmp(buffer[failed[j].index], buffer_zero, state->block_size) == 0) { + /* it may contain garbage */ + failed[j].is_outofdate = 1; + + log_tag("hash_unknown: Maybe old zero on entry %u\n", j); + } + } else { + /* if the hash is different than the previous one, we are sure to have */ + /* restored it to the state after the 'sync' */ + /* instead, if the hash matches, it could be either that the */ + /* block after the sync has this hash, or that */ + /* we restored the block before the 'sync'. */ + unsigned pos_size = file_block_size(failed[j].file, failed[j].file_pos, state->block_size); + if (blockcmp(state, rehash, failed[j].block, pos_size, buffer[failed[j].index], buffer_zero) == 0) { + /* it may contain garbage */ + failed[j].is_outofdate = 1; + + log_tag("hash_unknown: Maybe old data on entry %u\n", j); + } + } + } + } + + return 0; + } + if (ret > 0) + error += ret; + + if (ret < 0) + log_tag("recover_sync:%u:%u: Failed with no attempts\n", pos, n); + else + log_tag("recover_sync:%u:%u: Failed with %d attempts\n", pos, n, ret); + + /* Now assume that the parity IS NOT updated at the current state, */ + /* but still represent the state before the last 'sync' process. */ + /* In this case, parity contains info from BLK, REP (old version), CHG (old version) and DELETED blocks, */ + /* but not for REP (new version) and CHG (new version). */ + /* We are interested to recover BLK ones marked as bad, */ + /* but we are not interested to recover CHG (new version) and REP (new version) blocks, */ + /* even if marked as bad, because we don't have parity for them and it's just impossible, */ + /* and we are not interested to recover DELETED ones. */ + n = 0; + something_to_recover = 0; /* keep track if there is at least one block to fix */ + something_unsynced = 0; /* keep track if we have some unsynced info to process */ + for (j = 0; j < failed_count; ++j) { + unsigned block_state = block_state_get(failed[j].block); + + if (block_state == BLOCK_STATE_DELETED + || block_state == BLOCK_STATE_CHG + || block_state == BLOCK_STATE_REP + ) { + /* If the block is CHG, REP or DELETED, we don't have the original content of block, */ + /* and we must try to recover it. */ + /* This apply to CHG and REP blocks even if they are not marked bad, */ + /* because the parity is computed with old content, and not with the new one. */ + /* Note that this recovering is done just to make possible to recover any other BLK one, */ + /* we are not really interested in DELETED, CHG (old version) and REP (old version). */ + something_unsynced = 1; + + if (block_state == BLOCK_STATE_CHG + && hash_is_zero(failed[j].block->hash) + ) { + /* If the block was a ZERO block, restore it to the original 0 as before the 'sync' */ + /* We do this to just allow recovering of other BLK ones */ + + memset(buffer[failed[j].index], 0, state->block_size); + /* note that from now the buffer is definitively lost */ + /* we can do this only because it's the last retry of recovering */ + + /* try to fetch the old block using the old hash for CHG and DELETED blocks */ + } else if ((block_state == BLOCK_STATE_CHG || block_state == BLOCK_STATE_DELETED) + && hash_is_unique(failed[j].block->hash) + && state_import_fetch(state, rehash, failed[j].block, buffer[failed[j].index]) == 0) { + + /* note that from now the buffer is definitively lost */ + /* we can do this only because it's the last retry of recovering */ + } else { + /* otherwise try to recover it */ + failed_map[n] = j; + ++n; + + /* note that we don't set something_to_recover, because we are */ + /* not really interested to recover *only* old blocks. */ + } + + /* avoid to use the hash of this block to verify the recovering */ + /* this applies to REP blocks because we are going to recover the old state */ + /* and the REP hash represent the new one */ + /* it also applies to CHG and DELETE blocks because we want to have */ + /* a successful recovering only if a BLK one is matching */ + failed[j].is_outofdate = 1; + } else if (failed[j].is_bad) { + /* If the block is bad we don't know its content, and we try to recover it */ + /* At this point, we can have only BLK ones */ + + assert(block_state == BLOCK_STATE_BLK); + + /* we have something we are interested to recover */ + something_to_recover = 1; + + /* we try to recover it */ + failed_map[n] = j; + ++n; + } + } + + /* if nothing to fix, we just don't try */ + /* if nothing unsynced we also don't retry, because it's the same try as before */ + if (something_to_recover && something_unsynced) { + ret = repair_step(state, rehash, pos, diskmax, failed, failed_map, n, buffer, buffer_recov, buffer_zero); + if (ret == 0) { + /* reprocess the REP and CHG blocks, for which we have recovered and old state */ + /* that we don't want to save into disk */ + /* we have already marked them, but we redo it for logging */ + + for (j = 0; j < failed_count; ++j) { + /* we take care only of BAD blocks we have to write back */ + if (failed[j].is_bad) { + unsigned block_state = block_state_get(failed[j].block); + + if (block_state == BLOCK_STATE_CHG + || block_state == BLOCK_STATE_REP + ) { + /* mark that we have restored an old state */ + /* and we don't want to write it to the disk */ + failed[j].is_outofdate = 1; + + log_tag("hash_unknown: Surely old data on entry %u\n", j); + } + } + } + + return 0; + } + if (ret > 0) + error += ret; + + if (ret < 0) + log_tag("recover_unsync:%u:%u: Failed with no attempts\n", pos, n); + else + log_tag("recover_unsync:%u:%u: Failed with %d attempts\n", pos, n, ret); + } else { + log_tag("recover_unsync:%u:%u: Skipped for%s%s\n", pos, n, + !something_to_recover ? " nothing to recover" : "", + !something_unsynced ? " nothing unsynched" : "" + ); + } + + /* return the number of failed attempts, or -1 if no strategy */ + if (error) + return error; + else + return -1; +} + +/** + * Post process all the files at the specified block index ::i. + * For each file, if we are at the last block, closes it, + * adjust the timestamp, and print the result. + * + * This works with the assumption to always process the whole files to + * fix. This assumption is not always correct, and in such case we have to + * skip the whole postprocessing. And example, is when fixing only bad blocks. + */ +static int file_post(struct snapraid_state* state, int fix, unsigned i, struct snapraid_handle* handle, unsigned diskmax) +{ + unsigned j; + int ret; + char esc_buffer[ESC_MAX]; + char esc_buffer_alt[ESC_MAX]; + + /* if we are processing only bad blocks, we don't have to do any post-processing */ + /* as we don't have any guarantee to process the last block of the fixed files */ + if (state->opt.badonly) + return 0; + + /* for all the files print the final status, and does the final time fix */ + /* we also ensure to close files after processing the last block */ + for (j = 0; j < diskmax; ++j) { + struct snapraid_block* block; + struct snapraid_disk* disk; + struct snapraid_file* collide_file; + struct snapraid_file* file; + block_off_t file_pos; + char path[PATH_MAX]; + uint64_t inode; + + disk = handle[j].disk; + if (!disk) { + /* if no disk, nothing to do */ + continue; + } + + block = fs_par2block_find(disk, i); + if (!block_has_file(block)) { + /* if no file, nothing to do */ + continue; + } + + file = fs_par2file_get(disk, i, &file_pos); + pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub); + + /* if it isn't the last block in the file */ + if (!file_block_is_last(file, file_pos)) { + /* nothing to do */ + continue; + } + + /* if the file is excluded, we have nothing to adjust as the file is never written */ + if (file_flag_has(file, FILE_IS_EXCLUDED) + || (state->opt.syncedonly && file_flag_has(file, FILE_IS_UNSYNCED))) { + /* nothing to do, but close the file */ + goto close_and_continue; + } + + /* finish the fix process if it's the last block of the files */ + if (fix) { + /* mark that we finished with this file */ + /* to identify later any NOT finished ones */ + file_flag_set(file, FILE_IS_FINISHED); + + /* if the file is damaged, meaning that a fix failed */ + if (file_flag_has(file, FILE_IS_DAMAGED)) { + /* rename it to .unrecoverable */ + char path_to[PATH_MAX]; + + pathprint(path_to, sizeof(path_to), "%s%s.unrecoverable", disk->dir, file->sub); + + /* ensure to close the file before renaming */ + if (handle[j].file == file) { + ret = handle_close(&handle[j]); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); + log_fatal("DANGER! Unexpected close error in a data disk.\n"); + return -1; + /* LCOV_EXCL_STOP */ + } + } + + ret = rename(path, path_to); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error renaming '%s' to '%s'. %s.\n", path, path_to, strerror(errno)); + log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + return -1; + /* LCOV_EXCL_STOP */ + } + + log_tag("status:unrecoverable:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + msg_info("unrecoverable %s\n", fmt_term(disk, file->sub, esc_buffer)); + + /* and do not set the time if damaged */ + goto close_and_continue; + } + + /* if the file is not fixed, meaning that it is untouched */ + if (!file_flag_has(file, FILE_IS_FIXED)) { + /* nothing to do, but close the file */ + goto close_and_continue; + } + + /* if the file is closed or different than the one expected, reopen it */ + /* a different open file could happen when filtering for bad blocks */ + if (handle[j].file != file) { + /* close a potential different file */ + ret = handle_close(&handle[j]); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc_tag(handle[j].file->sub, esc_buffer), strerror(errno)); + log_fatal("DANGER! Unexpected close error in a data disk.\n"); + return -1; + /* LCOV_EXCL_STOP */ + } + + /* reopen it as readonly, as to set the mtime readonly access it's enough */ + /* we know that the file exists because it has the FILE_IS_FIXED tag */ + ret = handle_open(&handle[j], file, state->file_mode, log_error, 0); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_tag("error:%u:%s:%s: Open error. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); + log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + return -1; + /* LCOV_EXCL_STOP */ + } + } + + log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + msg_info("recovered %s\n", fmt_term(disk, file->sub, esc_buffer)); + + inode = handle[j].st.st_ino; + + /* search for the corresponding inode */ + collide_file = tommy_hashdyn_search(&disk->inodeset, file_inode_compare_to_arg, &inode, file_inode_hash(inode)); + + /* if the inode is already in the database and it refers at a different file name, */ + /* we can fix the file time ONLY if the time and size allow to differentiate */ + /* between the two files */ + + /* for example, suppose we delete a bunch of files with all the same size and time, */ + /* when recreating them the inodes may be reused in a different order, */ + /* and at the next sync some files may have matching inode/size/time even if different name */ + /* not allowing sync to detect that the file is changed and not renamed */ + if (!collide_file /* if not in the database, there is no collision */ + || strcmp(collide_file->sub, file->sub) == 0 /* if the name is the same, it's the right collision */ + || collide_file->size != file->size /* if the size is different, the collision is identified */ + || collide_file->mtime_sec != file->mtime_sec /* if the mtime is different, the collision is identified */ + || collide_file->mtime_nsec != file->mtime_nsec /* same for mtime_nsec */ + ) { + /* set the original modification time */ + ret = handle_utime(&handle[j]); + if (ret == -1) { + /* LCOV_EXCL_START */ + /* mark the file as damaged */ + file_flag_set(file, FILE_IS_DAMAGED); + log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + return -1; + /* LCOV_EXCL_STOP */ + } + } else { + log_tag("collision:%s:%s:%s: Not setting modification time to avoid inode collision\n", disk->name, esc_tag(file->sub, esc_buffer), esc_tag(collide_file->sub, esc_buffer_alt)); + } + } else { + /* we are not fixing, but only checking */ + /* print just the final status */ + if (file_flag_has(file, FILE_IS_DAMAGED)) { + if (state->opt.auditonly) { + log_tag("status:damaged:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + msg_info("damaged %s\n", fmt_term(disk, file->sub, esc_buffer)); + } else { + log_tag("status:unrecoverable:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + msg_info("unrecoverable %s\n", fmt_term(disk, file->sub, esc_buffer)); + } + } else if (file_flag_has(file, FILE_IS_FIXED)) { + log_tag("status:recoverable:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + msg_info("recoverable %s\n", fmt_term(disk, file->sub, esc_buffer)); + } else { + /* we don't use msg_verbose() because it also goes into the log */ + if (msg_level >= MSG_VERBOSE) { + log_tag("status:correct:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + msg_info("correct %s\n", fmt_term(disk, file->sub, esc_buffer)); + } + } + } + +close_and_continue: + /* if the opened file is the correct one, close it */ + /* in case of excluded and fragmented files it's possible */ + /* that the opened file is not the current one */ + if (handle[j].file == file) { + /* ensure to close the file just after finishing with it */ + /* to avoid to keep it open without any possible use */ + ret = handle_close(&handle[j]); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); + log_fatal("DANGER! Unexpected close error in a data disk.\n"); + return -1; + /* LCOV_EXCL_STOP */ + } + } + } + + return 0; +} + +/** + * Check if we have to process the specified block index ::i. + */ +static int block_is_enabled(struct snapraid_state* state, block_off_t i, struct snapraid_handle* handle, unsigned diskmax) +{ + snapraid_info info; + unsigned j; + unsigned l; + + /* get block specific info */ + info = info_get(&state->infoarr, i); + + /* if we filter for only bad blocks */ + if (state->opt.badonly) { + /* skip if this is not bad */ + if (!info_get_bad(info)) + return 0; + } + + /* now apply the filters */ + + /* if a parity is not excluded, include all blocks, even unused ones */ + for (l = 0; l < state->level; ++l) { + if (!state->parity[l].is_excluded_by_filter) { + return 1; + } + } + + /* otherwise include only used blocks */ + for (j = 0; j < diskmax; ++j) { + struct snapraid_block* block; + + /* if no disk, nothing to check */ + if (!handle[j].disk) + continue; + + block = fs_par2block_find(handle[j].disk, i); + + /* try to recover all files, even the ones without hash */ + /* because in some cases we can recover also them */ + if (block_has_file(block)) { + struct snapraid_file* file = fs_par2file_get(handle[j].disk, i, 0); + if (!file_flag_has(file, FILE_IS_EXCLUDED)) { /* only if the file is not filtered out */ + return 1; + } + } + } + + return 0; +} + +static int state_check_process(struct snapraid_state* state, int fix, struct snapraid_parity_handle** parity, block_off_t blockstart, block_off_t blockmax) +{ + struct snapraid_handle* handle; + unsigned diskmax; + block_off_t i; + unsigned j; + void* buffer_alloc; + void** buffer; + unsigned buffermax; + int ret; + data_off_t countsize; + block_off_t countpos; + block_off_t countmax; + unsigned error; + unsigned unrecoverable_error; + unsigned recovered_error; + struct failed_struct* failed; + unsigned* failed_map; + unsigned l; + char esc_buffer[ESC_MAX]; + char esc_buffer_alt[ESC_MAX]; + + handle = handle_mapping(state, &diskmax); + + /* we need 1 * data + 2 * parity + 1 * zero */ + buffermax = diskmax + 2 * state->level + 1; + + buffer = malloc_nofail_vector_align(diskmax, buffermax, state->block_size, &buffer_alloc); + if (!state->opt.skip_self) + mtest_vector(buffermax, state->block_size, buffer); + + /* fill up the zero buffer */ + memset(buffer[buffermax - 1], 0, state->block_size); + raid_zero(buffer[buffermax - 1]); + + failed = malloc_nofail(diskmax * sizeof(struct failed_struct)); + failed_map = malloc_nofail(diskmax * sizeof(unsigned)); + + error = 0; + unrecoverable_error = 0; + recovered_error = 0; + + /* first count the number of blocks to process */ + countmax = 0; + for (i = blockstart; i < blockmax; ++i) { + if (!block_is_enabled(state, i, handle, diskmax)) + continue; + ++countmax; + } + + /* check all the blocks in files */ + countsize = 0; + countpos = 0; + state_progress_begin(state, blockstart, blockmax, countmax); + for (i = blockstart; i < blockmax; ++i) { + unsigned failed_count; + int valid_parity; + int used_parity; + snapraid_info info; + int rehash; + + if (!block_is_enabled(state, i, handle, diskmax)) { + /* post process the files */ + ret = file_post(state, fix, i, handle, diskmax); + if (ret == -1) { + /* LCOV_EXCL_START */ + log_fatal("Stopping at block %u\n", i); + ++unrecoverable_error; + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* and now continue with the next block */ + continue; + } + + /* If we have valid parity, and it makes sense to check its content. */ + /* If we already know that the parity is invalid, we just read the file */ + /* but we don't report parity errors */ + /* Note that with auditonly, we anyway skip the full parity check, */ + /* because we also don't read it at all */ + valid_parity = 1; + + /* If the parity is used by at least one file */ + used_parity = 0; + + /* keep track of the number of failed blocks */ + failed_count = 0; + + /* get block specific info */ + info = info_get(&state->infoarr, i); + + /* if we have to use the old hash */ + rehash = info_get_rehash(info); + + /* for each disk, process the block */ + for (j = 0; j < diskmax; ++j) { + int read_size; + unsigned char hash[HASH_MAX]; + struct snapraid_disk* disk; + struct snapraid_block* block; + struct snapraid_file* file; + block_off_t file_pos; + unsigned block_state; + + /* if the disk position is not used */ + disk = handle[j].disk; + if (!disk) { + /* use an empty block */ + memset(buffer[j], 0, state->block_size); + continue; + } + + /* if the disk block is not used */ + block = fs_par2block_find(disk, i); + if (block == BLOCK_NULL) { + /* use an empty block */ + memset(buffer[j], 0, state->block_size); + continue; + } + + /* get the state of the block */ + block_state = block_state_get(block); + + /* if the parity is not valid */ + if (block_has_invalid_parity(block)) { + /* mark the parity as invalid, and don't try to check/fix it */ + /* because it will be recomputed at the next sync */ + valid_parity = 0; + /* follow */ + } + + /* if the block is DELETED */ + if (block_state == BLOCK_STATE_DELETED) { + /* use an empty block */ + memset(buffer[j], 0, state->block_size); + + /* store it in the failed set, because potentially */ + /* the parity may be still computed with the previous content */ + failed[failed_count].is_bad = 0; /* note that is_bad==0 <=> file==0 */ + failed[failed_count].is_outofdate = 0; + failed[failed_count].index = j; + failed[failed_count].block = block; + failed[failed_count].disk = disk; + failed[failed_count].file = 0; + failed[failed_count].file_pos = 0; + failed[failed_count].handle = 0; + ++failed_count; + continue; + } + + /* here we are sure that the parity is used by a file */ + used_parity = 1; + + /* get the file of this block */ + file = fs_par2file_get(disk, i, &file_pos); + + /* if we are only hashing, we can skip excluded files and don't even read them */ + if (state->opt.auditonly && file_flag_has(file, FILE_IS_EXCLUDED)) { + /* use an empty block */ + /* in true, this is unnecessary, because we are not checking any parity */ + /* but we keep it for completeness */ + memset(buffer[j], 0, state->block_size); + continue; + } + + /* if the file is closed or different than the current one */ + if (handle[j].file == 0 || handle[j].file != file) { + /* close the old one, if any */ + ret = handle_close(&handle[j]); + if (ret == -1) { + /* LCOV_EXCL_START */ + log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc_tag(handle[j].file->sub, esc_buffer), strerror(errno)); + log_fatal("DANGER! Unexpected close error in a data disk.\n"); + log_fatal("Stopping at block %u\n", i); + ++unrecoverable_error; + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* if fixing, and the file is not excluded, we must open for writing */ + if (fix && !file_flag_has(file, FILE_IS_EXCLUDED)) { + /* if fixing, create the file, open for writing and resize if required */ + ret = handle_create(&handle[j], file, state->file_mode); + if (ret == -1) { + /* LCOV_EXCL_START */ + if (errno == EACCES) { + log_fatal("WARNING! Please give write permission to the file.\n"); + } else { + log_fatal("DANGER! Without a working data disk, it isn't possible to fix errors on it.\n"); + } + log_fatal("Stopping at block %u\n", i); + ++unrecoverable_error; + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* check if the file was just created */ + if (handle[j].created != 0) { + /* if fragmented, it may be reopened, so remember that the file */ + /* was originally missing */ + file_flag_set(file, FILE_IS_CREATED); + } + } else { + /* open the file only for reading */ + if (!file_flag_has(file, FILE_IS_MISSING)) + ret = handle_open(&handle[j], file, state->file_mode, + log_error, state->opt.expected_missing ? log_expected : 0); + else + ret = -1; /* if the file is missing, we cannot open it */ + if (ret == -1) { + /* save the failed block for the check/fix */ + failed[failed_count].is_bad = 1; + failed[failed_count].is_outofdate = 0; + failed[failed_count].index = j; + failed[failed_count].block = block; + failed[failed_count].disk = disk; + failed[failed_count].file = file; + failed[failed_count].file_pos = file_pos; + failed[failed_count].handle = &handle[j]; + ++failed_count; + + log_tag("error:%u:%s:%s: Open error at position %u\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos); + ++error; + + /* mark the file as missing, to avoid to retry to open it again */ + /* note that this can be done only if we are not fixing it */ + /* otherwise, it could be recreated */ + file_flag_set(file, FILE_IS_MISSING); + continue; + } + } + + /* if it's the first open, and not excluded */ + if (!file_flag_has(file, FILE_IS_OPENED) + && !file_flag_has(file, FILE_IS_EXCLUDED)) { + + /* check if the file is changed */ + if (handle[j].st.st_size != file->size + || handle[j].st.st_mtime != file->mtime_sec + || STAT_NSEC(&handle[j].st) != file->mtime_nsec + /* don't check the inode to support file-system without persistent inodes */ + ) { + /* report that the file is not synced */ + file_flag_set(file, FILE_IS_UNSYNCED); + } + } + + /* if it's the first open, and not excluded and larger */ + if (!file_flag_has(file, FILE_IS_OPENED) + && !file_flag_has(file, FILE_IS_EXCLUDED) + && !(state->opt.syncedonly && file_flag_has(file, FILE_IS_UNSYNCED)) + && handle[j].st.st_size > file->size + ) { + log_error("File '%s' is larger than expected.\n", handle[j].path); + log_tag("error:%u:%s:%s: Size error\n", i, disk->name, esc_tag(file->sub, esc_buffer)); + ++error; + + if (fix) { + ret = handle_truncate(&handle[j], file); + if (ret == -1) { + /* LCOV_EXCL_START */ + log_fatal("DANGER! Unexpected truncate error in a data disk, it isn't possible to fix.\n"); + log_fatal("Stopping at block %u\n", i); + ++unrecoverable_error; + goto bail; + /* LCOV_EXCL_STOP */ + } + + log_tag("fixed:%u:%s:%s: Fixed size\n", i, disk->name, esc_tag(file->sub, esc_buffer)); + ++recovered_error; + } + } + + /* mark the file as opened at least one time */ + /* this is used to avoid to check the unsynced and size */ + /* more than one time, in case the file is reopened later */ + file_flag_set(file, FILE_IS_OPENED); + } + + /* read from the file */ + read_size = handle_read(&handle[j], file_pos, buffer[j], state->block_size, + log_error, state->opt.expected_missing ? log_expected : 0); + if (read_size == -1) { + /* save the failed block for the check/fix */ + failed[failed_count].is_bad = 1; /* it's bad because we cannot read it */ + failed[failed_count].is_outofdate = 0; + failed[failed_count].index = j; + failed[failed_count].block = block; + failed[failed_count].disk = disk; + failed[failed_count].file = file; + failed[failed_count].file_pos = file_pos; + failed[failed_count].handle = &handle[j]; + ++failed_count; + + log_tag("error:%u:%s:%s: Read error at position %u\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos); + ++error; + continue; + } + + countsize += read_size; + + /* always insert CHG blocks, the repair functions needs all of them */ + /* because the parity may be still referring at the old state */ + /* and the repair must be aware of it */ + if (block_state == BLOCK_STATE_CHG) { + /* we DO NOT mark them as bad to avoid to overwrite them with wrong data. */ + /* if we don't have a hash, we always assume the first read of the block correct. */ + failed[failed_count].is_bad = 0; /* we assume the CHG block correct */ + failed[failed_count].is_outofdate = 0; + failed[failed_count].index = j; + failed[failed_count].block = block; + failed[failed_count].disk = disk; + failed[failed_count].file = file; + failed[failed_count].file_pos = file_pos; + failed[failed_count].handle = &handle[j]; + ++failed_count; + continue; + } + + assert(block_state == BLOCK_STATE_BLK || block_state == BLOCK_STATE_REP); + + /* compute the hash of the block just read */ + if (rehash) { + memhash(state->prevhash, state->prevhashseed, hash, buffer[j], read_size); + } else { + memhash(state->hash, state->hashseed, hash, buffer[j], read_size); + } + + /* compare the hash */ + if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { + unsigned diff = memdiff(hash, block->hash, BLOCK_HASH_SIZE); + + /* save the failed block for the check/fix */ + failed[failed_count].is_bad = 1; /* it's bad because the hash doesn't match */ + failed[failed_count].is_outofdate = 0; + failed[failed_count].index = j; + failed[failed_count].block = block; + failed[failed_count].disk = disk; + failed[failed_count].file = file; + failed[failed_count].file_pos = file_pos; + failed[failed_count].handle = &handle[j]; + ++failed_count; + + log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u/%u\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff, BLOCK_HASH_SIZE * 8); + ++error; + continue; + } + + /* always insert REP blocks, the repair functions needs all of them */ + /* because the parity may be still referring at the old state */ + /* and the repair must be aware of it */ + if (block_state == BLOCK_STATE_REP) { + failed[failed_count].is_bad = 0; /* it's not bad */ + failed[failed_count].is_outofdate = 0; + failed[failed_count].index = j; + failed[failed_count].block = block; + failed[failed_count].disk = disk; + failed[failed_count].file = file; + failed[failed_count].file_pos = file_pos; + failed[failed_count].handle = &handle[j]; + ++failed_count; + continue; + } + } + + /* now read and check the parity if requested */ + if (!state->opt.auditonly) { + void* buffer_recov[LEV_MAX]; + void* buffer_zero; + + /* buffers for parity read and not computed */ + for (l = 0; l < state->level; ++l) + buffer_recov[l] = buffer[diskmax + state->level + l]; + for (; l < LEV_MAX; ++l) + buffer_recov[l] = 0; + + /* the zero buffer is the last one */ + buffer_zero = buffer[buffermax - 1]; + + /* read the parity */ + for (l = 0; l < state->level; ++l) { + if (parity[l]) { + ret = parity_read(parity[l], i, buffer_recov[l], state->block_size, log_error); + if (ret == -1) { + buffer_recov[l] = 0; /* no parity to use */ + + log_tag("parity_error:%u:%s: Read error\n", i, lev_config_name(l)); + ++error; + } + } else { + buffer_recov[l] = 0; + } + } + + /* try all the recovering strategies */ + ret = repair(state, rehash, i, diskmax, failed, failed_map, failed_count, buffer, buffer_recov, buffer_zero); + if (ret != 0) { + /* increment the number of errors */ + if (ret > 0) + error += ret; + ++unrecoverable_error; + + /* print a list of all the errors in files */ + for (j = 0; j < failed_count; ++j) { + if (failed[j].is_bad) + log_tag("unrecoverable:%u:%s:%s: Unrecoverable error at position %u\n", i, failed[j].disk->name, esc_tag(failed[j].file->sub, esc_buffer), failed[j].file_pos); + } + + /* keep track of damaged files */ + for (j = 0; j < failed_count; ++j) { + if (failed[j].is_bad) + file_flag_set(failed[j].file, FILE_IS_DAMAGED); + } + } else { + /* now counts partial recovers */ + /* note that this could happen only when we have an incomplete 'sync' */ + /* and that we have recovered is the state before the 'sync' */ + int partial_recover_error = 0; + + /* print a list of all the errors in files */ + for (j = 0; j < failed_count; ++j) { + if (failed[j].is_bad && failed[j].is_outofdate) { + ++partial_recover_error; + log_tag("unrecoverable:%u:%s:%s: Unrecoverable unsynced error at position %u\n", i, failed[j].disk->name, esc_tag(failed[j].file->sub, esc_buffer), failed[j].file_pos); + } + } + if (partial_recover_error != 0) { + error += partial_recover_error; + ++unrecoverable_error; + } + + /* + * Check parities, but only if all the blocks have it computed and it's used. + * + * If you check/fix after a partial sync, it's OK to have parity errors + * on the blocks with invalid parity and doesn't make sense to try to fix it. + * + * It's also OK to have data errors on unused parity, because sync doesn't + * update it. + */ + if (used_parity && valid_parity) { + /* check the parity */ + for (l = 0; l < state->level; ++l) { + if (buffer_recov[l] != 0 && memcmp(buffer_recov[l], buffer[diskmax + l], state->block_size) != 0) { + unsigned diff = memdiff(buffer_recov[l], buffer[diskmax + l], state->block_size); + + /* mark that the read parity is wrong, setting ptr to 0 */ + buffer_recov[l] = 0; + + log_tag("parity_error:%u:%s: Data error, diff bits %u/%u\n", i, lev_config_name(l), diff, state->block_size * 8); + ++error; + } + } + } + + /* now write recovered files */ + if (fix) { + /* update the fixed files */ + for (j = 0; j < failed_count; ++j) { + /* nothing to do if it doesn't need recovering */ + if (!failed[j].is_bad) + continue; + + /* do not fix if the file is excluded */ + if (file_flag_has(failed[j].file, FILE_IS_EXCLUDED) + || (state->opt.syncedonly && file_flag_has(failed[j].file, FILE_IS_UNSYNCED))) + continue; + + ret = handle_write(failed[j].handle, failed[j].file_pos, buffer[failed[j].index], state->block_size); + if (ret == -1) { + /* LCOV_EXCL_START */ + /* mark the file as damaged */ + file_flag_set(failed[j].file, FILE_IS_DAMAGED); + + if (errno == EACCES) { + log_fatal("WARNING! Please give write permission to the file.\n"); + } else { + /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ + log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + } + log_fatal("Stopping at block %u\n", i); + ++unrecoverable_error; + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* if we are not sure that the recovered content is uptodate */ + if (failed[j].is_outofdate) { + /* mark the file as damaged */ + file_flag_set(failed[j].file, FILE_IS_DAMAGED); + continue; + } + + /* mark the file as containing some fixes */ + /* note that it could be also marked as damaged in other iterations */ + file_flag_set(failed[j].file, FILE_IS_FIXED); + + log_tag("fixed:%u:%s:%s: Fixed data error at position %u\n", i, failed[j].disk->name, esc_tag(failed[j].file->sub, esc_buffer), failed[j].file_pos); + ++recovered_error; + } + + /* + * Update parity only if all the blocks have it computed and it's used. + * + * If you check/fix after a partial sync, you do not want to fix parity + * for blocks that are going to have it computed in the sync completion. + * + * For unused parity there is no need to write it, because when fixing + * we already have allocated space for it on parity file creation, + * and its content doesn't matter. + */ + if (used_parity && valid_parity) { + /* update the parity */ + for (l = 0; l < state->level; ++l) { + /* if the parity on disk is wrong */ + if (buffer_recov[l] == 0 + /* and we have access at the parity */ + && parity[l] != 0 + /* and the parity is not excluded */ + && !state->parity[l].is_excluded_by_filter + ) { + ret = parity_write(parity[l], i, buffer[diskmax + l], state->block_size); + if (ret == -1) { + /* LCOV_EXCL_START */ + /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ + log_fatal("WARNING! Without a working %s disk, it isn't possible to fix errors on it.\n", lev_name(l)); + log_fatal("Stopping at block %u\n", i); + ++unrecoverable_error; + goto bail; + /* LCOV_EXCL_STOP */ + } + + log_tag("parity_fixed:%u:%s: Fixed data error\n", i, lev_config_name(l)); + ++recovered_error; + } + } + } + } else { + /* if we are not fixing, we just set the FIXED flag */ + /* meaning that we could fix this file if we try */ + for (j = 0; j < failed_count; ++j) { + if (failed[j].is_bad) { + file_flag_set(failed[j].file, FILE_IS_FIXED); + } + } + } + } + } else { + /* if we are not checking, we just set the DAMAGED flag */ + /* to report that the file is damaged, and we don't know if we can fix it */ + for (j = 0; j < failed_count; ++j) { + if (failed[j].is_bad) { + file_flag_set(failed[j].file, FILE_IS_DAMAGED); + } + } + } + + /* post process the files */ + ret = file_post(state, fix, i, handle, diskmax); + if (ret == -1) { + /* LCOV_EXCL_START */ + log_fatal("Stopping at block %u\n", i); + ++unrecoverable_error; + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* count the number of processed block */ + ++countpos; + + /* progress */ + if (state_progress(state, 0, i, countpos, countmax, countsize)) { + /* LCOV_EXCL_START */ + break; + /* LCOV_EXCL_STOP */ + } + } + + /* for each disk, recover empty files, symlinks and empty dirs */ + for (i = 0; i < diskmax; ++i) { + tommy_node* node; + struct snapraid_disk* disk; + + if (!handle[i].disk) + continue; + + /* for each empty file in the disk */ + disk = handle[i].disk; + node = disk->filelist; + while (node) { + char path[PATH_MAX]; + struct stat st; + struct snapraid_file* file; + int unsuccesful = 0; + + file = node->data; + node = node->next; /* next node */ + + /* if not empty, it's already checked and continue to the next one */ + if (file->size != 0) { + continue; + } + + /* if excluded continue to the next one */ + if (file_flag_has(file, FILE_IS_EXCLUDED)) { + continue; + } + + /* stat the file */ + pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub); + ret = stat(path, &st); + if (ret == -1) { + unsuccesful = 1; + + log_error("Error stating empty file '%s'. %s.\n", path, strerror(errno)); + log_tag("error:%s:%s: Empty file stat error\n", disk->name, esc_tag(file->sub, esc_buffer)); + ++error; + } else if (!S_ISREG(st.st_mode)) { + unsuccesful = 1; + + log_tag("error:%s:%s: Empty file error for not regular file\n", disk->name, esc_tag(file->sub, esc_buffer)); + ++error; + } else if (st.st_size != 0) { + unsuccesful = 1; + + log_tag("error:%s:%s: Empty file error for size '%" PRIu64 "'\n", disk->name, esc_tag(file->sub, esc_buffer), (uint64_t)st.st_size); + ++error; + } + + if (fix && unsuccesful) { + int f; + + /* create the ancestor directories */ + ret = mkancestor(path); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + log_fatal("Stopping\n"); + ++unrecoverable_error; + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* create it */ + /* O_NOFOLLOW: do not follow links to ensure to open the real file */ + f = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_NOFOLLOW, 0600); + if (f == -1) { + /* LCOV_EXCL_START */ + log_fatal("Error creating empty file '%s'. %s.\n", path, strerror(errno)); + if (errno == EACCES) { + log_fatal("WARNING! Please give write permission to the file.\n"); + } else { + /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ + log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + } + log_fatal("Stopping\n"); + ++unrecoverable_error; + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* set the original modification time */ + ret = fmtime(f, file->mtime_sec, file->mtime_nsec); + if (ret != 0) { + /* LCOV_EXCL_START */ + close(f); + + log_fatal("Error timing file '%s'. %s.\n", file->sub, strerror(errno)); + log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + log_fatal("Stopping\n"); + ++unrecoverable_error; + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* close it */ + ret = close(f); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + log_fatal("Stopping\n"); + ++unrecoverable_error; + goto bail; + /* LCOV_EXCL_STOP */ + } + + log_tag("fixed:%s:%s: Fixed empty file\n", disk->name, esc_tag(file->sub, esc_buffer)); + ++recovered_error; + + log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + msg_info("recovered %s\n", fmt_term(disk, file->sub, esc_buffer)); + } + } + + /* for each link in the disk */ + disk = handle[i].disk; + node = disk->linklist; + while (node) { + char path[PATH_MAX]; + char pathto[PATH_MAX]; + char linkto[PATH_MAX]; + struct stat st; + struct stat stto; + struct snapraid_link* slink; + int unsuccesful = 0; + int unrecoverable = 0; + + slink = node->data; + node = node->next; /* next node */ + + /* if excluded continue to the next one */ + if (link_flag_has(slink, FILE_IS_EXCLUDED)) { + continue; + } + + if (link_flag_has(slink, FILE_IS_HARDLINK)) { + /* stat the link */ + pathprint(path, sizeof(path), "%s%s", disk->dir, slink->sub); + ret = stat(path, &st); + if (ret == -1) { + unsuccesful = 1; + + log_error("Error stating hardlink '%s'. %s.\n", path, strerror(errno)); + log_tag("hardlink_error:%s:%s:%s: Hardlink stat error\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt)); + ++error; + } else if (!S_ISREG(st.st_mode)) { + unsuccesful = 1; + + log_tag("hardlink_error:%s:%s:%s: Hardlink error for not regular file\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt)); + ++error; + } + + /* stat the "to" file */ + pathprint(pathto, sizeof(pathto), "%s%s", disk->dir, slink->linkto); + ret = stat(pathto, &stto); + if (ret == -1) { + unsuccesful = 1; + + if (errno == ENOENT) { + unrecoverable = 1; + if (fix) { + /* if the target doesn't exist, it's unrecoverable */ + /* because we cannot create an hardlink of a file that */ + /* doesn't exists */ + ++unrecoverable_error; + } else { + /* but in check, we can assume that fixing will recover */ + /* such missing file, so we assume a less drastic error */ + ++error; + } + } + + log_error("Error stating hardlink-to '%s'. %s.\n", pathto, strerror(errno)); + log_tag("hardlink_error:%s:%s:%s: Hardlink to stat error\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt)); + ++error; + } else if (!S_ISREG(stto.st_mode)) { + unsuccesful = 1; + + log_tag("hardlink_error:%s:%s:%s: Hardlink-to error for not regular file\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt)); + ++error; + } else if (!unsuccesful && st.st_ino != stto.st_ino) { + unsuccesful = 1; + + log_error("Mismatch hardlink '%s' and '%s'. Different inode.\n", path, pathto); + log_tag("hardlink_error:%s:%s:%s: Hardlink mismatch for different inode\n", disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt)); + ++error; + } + } else { + /* read the symlink */ + pathprint(path, sizeof(path), "%s%s", disk->dir, slink->sub); + ret = readlink(path, linkto, sizeof(linkto)); + if (ret < 0) { + unsuccesful = 1; + + log_error("Error reading symlink '%s'. %s.\n", path, strerror(errno)); + log_tag("symlink_error:%s:%s: Symlink read error\n", disk->name, esc_tag(slink->sub, esc_buffer)); + ++error; + } else if (ret >= PATH_MAX) { + unsuccesful = 1; + + log_error("Error reading symlink '%s'. Symlink too long.\n", path); + log_tag("symlink_error:%s:%s: Symlink read error\n", disk->name, esc_tag(slink->sub, esc_buffer)); + ++error; + } else { + linkto[ret] = 0; + + if (strcmp(linkto, slink->linkto) != 0) { + unsuccesful = 1; + + log_tag("symlink_error:%s:%s: Symlink data error '%s' instead of '%s'\n", disk->name, esc_tag(slink->sub, esc_buffer), linkto, slink->linkto); + ++error; + } + } + } + + if (fix && unsuccesful && !unrecoverable) { + /* create the ancestor directories */ + ret = mkancestor(path); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + log_fatal("Stopping\n"); + ++unrecoverable_error; + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* if it exists, it must be deleted before recreating */ + ret = remove(path); + if (ret != 0 && errno != ENOENT) { + /* LCOV_EXCL_START */ + log_fatal("Error removing '%s'. %s.\n", path, strerror(errno)); + log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + log_fatal("Stopping\n"); + ++unrecoverable_error; + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* create it */ + if (link_flag_has(slink, FILE_IS_HARDLINK)) { + ret = hardlink(pathto, path); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error writing hardlink '%s' to '%s'. %s.\n", path, pathto, strerror(errno)); + if (errno == EACCES) { + log_fatal("WARNING! Please give write permission to the hardlink.\n"); + } else { + /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ + log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + } + log_fatal("Stopping\n"); + ++unrecoverable_error; + goto bail; + /* LCOV_EXCL_STOP */ + } + + log_tag("hardlink_fixed:%s:%s: Fixed hardlink error\n", disk->name, esc_tag(slink->sub, esc_buffer)); + ++recovered_error; + } else { + ret = symlink(slink->linkto, path); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error writing symlink '%s' to '%s'. %s.\n", path, slink->linkto, strerror(errno)); + if (errno == EACCES) { + log_fatal("WARNING! Please give write permission to the symlink.\n"); + } else { + /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ + log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + } + log_fatal("Stopping\n"); + ++unrecoverable_error; + goto bail; + /* LCOV_EXCL_STOP */ + } + + log_tag("symlink_fixed:%s:%s: Fixed symlink error\n", disk->name, esc_tag(slink->sub, esc_buffer)); + ++recovered_error; + } + + log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(slink->sub, esc_buffer)); + msg_info("recovered %s\n", fmt_term(disk, slink->sub, esc_buffer)); + } + } + + /* for each dir in the disk */ + disk = handle[i].disk; + node = disk->dirlist; + while (node) { + char path[PATH_MAX]; + struct stat st; + struct snapraid_dir* dir; + int unsuccesful = 0; + + dir = node->data; + node = node->next; /* next node */ + + /* if excluded continue to the next one */ + if (dir_flag_has(dir, FILE_IS_EXCLUDED)) { + continue; + } + + /* stat the dir */ + pathprint(path, sizeof(path), "%s%s", disk->dir, dir->sub); + ret = stat(path, &st); + if (ret == -1) { + unsuccesful = 1; + + log_error("Error stating dir '%s'. %s.\n", path, strerror(errno)); + log_tag("dir_error:%s:%s: Dir stat error\n", disk->name, esc_tag(dir->sub, esc_buffer)); + ++error; + } else if (!S_ISDIR(st.st_mode)) { + unsuccesful = 1; + + log_tag("dir_error:%s:%s: Dir error for not directory\n", disk->name, esc_tag(dir->sub, esc_buffer)); + ++error; + } + + if (fix && unsuccesful) { + /* create the ancestor directories */ + ret = mkancestor(path); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + log_fatal("Stopping\n"); + ++unrecoverable_error; + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* create it */ + ret = mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error creating dir '%s'. %s.\n", path, strerror(errno)); + if (errno == EACCES) { + log_fatal("WARNING! Please give write permission to the dir.\n"); + } else { + /* we do not use DANGER because it could be ENOSPC which is not always correctly reported */ + log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + } + log_fatal("Stopping\n"); + ++unrecoverable_error; + goto bail; + /* LCOV_EXCL_STOP */ + } + + log_tag("dir_fixed:%s:%s: Fixed dir error\n", disk->name, esc_tag(dir->sub, esc_buffer)); + ++recovered_error; + + log_tag("status:recovered:%s:%s\n", disk->name, esc_tag(dir->sub, esc_buffer)); + msg_info("recovered %s\n", fmt_term(disk, dir->sub, esc_buffer)); + } + } + } + + state_progress_end(state, countpos, countmax, countsize); + +bail: + /* close all the files left open */ + for (j = 0; j < diskmax; ++j) { + struct snapraid_file* file = handle[j].file; + struct snapraid_disk* disk = handle[j].disk; + ret = handle_close(&handle[j]); + if (ret == -1) { + /* LCOV_EXCL_START */ + log_tag("error:%u:%s:%s: Close error. %s\n", blockmax, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); + log_fatal("DANGER! Unexpected close error in a data disk.\n"); + ++unrecoverable_error; + /* continue, as we are already exiting */ + /* LCOV_EXCL_STOP */ + } + } + + /* remove all the files created from scratch that have not finished the processing */ + /* it happens only when aborting pressing Ctrl+C or other reason. */ + if (fix) { + /* for each disk */ + for (i = 0; i < diskmax; ++i) { + tommy_node* node; + struct snapraid_disk* disk; + + if (!handle[i].disk) + continue; + + /* for each file in the disk */ + disk = handle[i].disk; + node = disk->filelist; + while (node) { + char path[PATH_MAX]; + struct snapraid_file* file; + + file = node->data; + node = node->next; /* next node */ + + /* if the file was not created, meaning that it was already existing */ + if (!file_flag_has(file, FILE_IS_CREATED)) { + /* nothing to do */ + continue; + } + + /* if processing was finished */ + if (file_flag_has(file, FILE_IS_FINISHED)) { + /* nothing to do */ + continue; + } + + /* if the file was originally missing, and processing not yet finished */ + /* we have to throw it away to ensure that at the next run we will retry */ + /* to fix it, in case we select to undelete missing files */ + pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub); + + ret = remove(path); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error removing '%s'. %s.\n", path, strerror(errno)); + log_fatal("WARNING! Without a working data disk, it isn't possible to fix errors on it.\n"); + ++unrecoverable_error; + /* continue, as we are already exiting */ + /* LCOV_EXCL_STOP */ + } + } + } + } + + if (error || recovered_error || unrecoverable_error) { + msg_status("\n"); + msg_status("%8u errors\n", error); + if (fix) { + msg_status("%8u recovered errors\n", recovered_error); + } + if (unrecoverable_error) { + msg_status("%8u UNRECOVERABLE errors\n", unrecoverable_error); + } else { + /* without checking, we don't know if they are really recoverable or not */ + if (!state->opt.auditonly) + msg_status("%8u unrecoverable errors\n", unrecoverable_error); + if (fix) + msg_status("Everything OK\n"); + } + } else { + msg_status("Everything OK\n"); + } + + if (error && !fix) + log_fatal("WARNING! There are errors!\n"); + if (unrecoverable_error) + log_fatal("DANGER! There are unrecoverable errors!\n"); + + log_tag("summary:error:%u\n", error); + if (fix) + log_tag("summary:error_recovered:%u\n", recovered_error); + if (!state->opt.auditonly) + log_tag("summary:error_unrecoverable:%u\n", unrecoverable_error); + if (fix) { + if (error + recovered_error + unrecoverable_error == 0) + log_tag("summary:exit:ok\n"); + else if (unrecoverable_error == 0) + log_tag("summary:exit:recovered\n"); + else + log_tag("summary:exit:unrecoverable\n"); + } else if (!state->opt.auditonly) { + if (error + unrecoverable_error == 0) + log_tag("summary:exit:ok\n"); + else if (unrecoverable_error == 0) + log_tag("summary:exit:recoverable\n"); + else + log_tag("summary:exit:unrecoverable\n"); + } else { /* audit only */ + if (error == 0) + log_tag("summary:exit:ok\n"); + else + log_tag("summary:exit:error\n"); + } + log_flush(); + + free(failed); + free(failed_map); + free(handle); + free(buffer_alloc); + free(buffer); + + /* fail if some error are present after the run */ + if (fix) { + if (state->opt.expect_unrecoverable) { + if (unrecoverable_error == 0) + return -1; + } else { + if (unrecoverable_error != 0) + return -1; + } + } else { + if (state->opt.expect_unrecoverable) { + if (unrecoverable_error == 0) + return -1; + } else if (state->opt.expect_recoverable) { + if (unrecoverable_error != 0 || error == 0) + return -1; + } else { + if (error != 0 || unrecoverable_error != 0) + return -1; + } + } + + return 0; +} + +int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, block_off_t blockcount) +{ + block_off_t blockmax; + data_off_t size; + int ret; + struct snapraid_parity_handle parity[LEV_MAX]; + struct snapraid_parity_handle* parity_ptr[LEV_MAX]; + unsigned error; + unsigned l; + + msg_progress("Initializing...\n"); + + blockmax = parity_allocated_size(state); + size = blockmax * (data_off_t)state->block_size; + + if (blockstart > blockmax) { + /* LCOV_EXCL_START */ + log_fatal("Error in the specified starting block %u. It's bigger than the parity size %u.\n", blockstart, blockmax); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* adjust the number of block to process */ + if (blockcount != 0 && blockstart + blockcount < blockmax) { + blockmax = blockstart + blockcount; + } + + if (fix) { + /* if fixing, create the file and open for writing */ + /* if it fails, we cannot continue */ + for (l = 0; l < state->level; ++l) { + /* skip parity disks that are not accessible */ + if (state->parity[l].skip_access) { + parity_ptr[l] = 0; + continue; + } + + parity_ptr[l] = &parity[l]; + ret = parity_create(parity_ptr[l], &state->parity[l], l, state->file_mode, state->block_size, state->opt.parity_limit_size); + if (ret == -1) { + /* LCOV_EXCL_START */ + log_fatal("WARNING! Without an accessible %s file, it isn't possible to fix any error.\n", lev_name(l)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + ret = parity_chsize(parity_ptr[l], &state->parity[l], 0, size, state->block_size, state->opt.skip_fallocate, state->opt.skip_space_holder); + if (ret == -1) { + /* LCOV_EXCL_START */ + log_fatal("WARNING! Without an accessible %s file, it isn't possible to sync.\n", lev_name(l)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + } else if (!state->opt.auditonly) { + /* if checking, open the file for reading */ + /* it may fail if the file doesn't exist, in this case we continue to check the files */ + for (l = 0; l < state->level; ++l) { + parity_ptr[l] = &parity[l]; + ret = parity_open(parity_ptr[l], &state->parity[l], l, state->file_mode, state->block_size, state->opt.parity_limit_size); + if (ret == -1) { + msg_status("No accessible %s file, only files will be checked.\n", lev_name(l)); + /* continue anyway */ + parity_ptr[l] = 0; + } + } + } else { + /* otherwise don't use any parity */ + for (l = 0; l < state->level; ++l) + parity_ptr[l] = 0; + } + + if (fix) + msg_progress("Fixing...\n"); + else if (!state->opt.auditonly) + msg_progress("Checking...\n"); + else + msg_progress("Hashing...\n"); + + error = 0; + + /* skip degenerated cases of empty parity, or skipping all */ + if (blockstart < blockmax) { + ret = state_check_process(state, fix, parity_ptr, blockstart, blockmax); + if (ret == -1) { + /* LCOV_EXCL_START */ + ++error; + /* continue, as we are already exiting */ + /* LCOV_EXCL_STOP */ + } + } + + /* try to close only if opened */ + for (l = 0; l < state->level; ++l) { + if (parity_ptr[l]) { + ret = parity_close(parity_ptr[l]); + /* LCOV_EXCL_START */ + if (ret == -1) { + log_fatal("DANGER! Unexpected close error in %s disk.\n", lev_name(l)); + ++error; + /* continue, as we are already exiting */ + } + /* LCOV_EXCL_STOP */ + } + } + + /* abort if error are present */ + if (error != 0) + return -1; + return 0; +} + diff --git a/cmdline/device.c b/cmdline/device.c new file mode 100644 index 0000000..f170ad6 --- /dev/null +++ b/cmdline/device.c @@ -0,0 +1,1001 @@ +/* + * Copyright (C) 2015 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "support.h" +#include "state.h" +#include "raid/raid.h" + +/** + * The following are Failure Rate tables computed from the data that + * BackBlaze made available at: + * + * Reliability Data Set For 41,000 Hard Drives Now Open Source + * https://www.backblaze.com/blog/hard-drive-data-feb2015/ + * + * Hard Drive Data Sets + * https://www.backblaze.com/hard-drive-test-data.html + * + * Note that in this data: + * - Disks all passed the load-testing and have made it to production, + * and then Dead On Arrival (DOA) failures are excluded. + * - Disks that are predicted to fail by BackBlaze are removed before + * they really fail, not counting as a failure. + * + * The following tables are computed using the data from 2014-02-14 to 2014-12-31 + * because it's the period when more SMART attributes were gathered. + * + * In this period there are 47322 disk seen, with 1988 removed because failed, + * and with 4121 removed because predicted to fail. + */ + +/** + * Number of data point in each table. + */ +#define SMART_MEASURES 256 + +/* + * Divider for SMART attribute 5 + */ +static unsigned SMART_5_STEP = 1; + +/* + * Failure rate for 30 days, for a disk + * with SMART attribute 5 at a given value. + */ +static double SMART_5_R[SMART_MEASURES] = { + 0.0026, 0.0748, 0.0919, 0.1013, 0.1079, + 0.1137, 0.1194, 0.1235, 0.1301, 0.1398, + 0.1453, 0.1490, 0.1528, 0.1566, 0.1595, + 0.1635, 0.1656, 0.1701, 0.1718, 0.1740, + 0.1762, 0.1787, 0.1808, 0.1833, 0.1858, + 0.1885, 0.1901, 0.1915, 0.1934, 0.1958, + 0.1975, 0.1993, 0.2014, 0.2048, 0.2068, + 0.2088, 0.2109, 0.2120, 0.2137, 0.2160, + 0.2173, 0.2214, 0.2226, 0.2237, 0.2262, + 0.2277, 0.2292, 0.2304, 0.2338, 0.2369, + 0.2381, 0.2396, 0.2411, 0.2427, 0.2445, + 0.2462, 0.2472, 0.2488, 0.2496, 0.2504, + 0.2514, 0.2525, 0.2535, 0.2544, 0.2554, + 0.2571, 0.2583, 0.2601, 0.2622, 0.2631, + 0.2635, 0.2644, 0.2659, 0.2675, 0.2682, + 0.2692, 0.2701, 0.2707, 0.2712, 0.2726, + 0.2745, 0.2767, 0.2778, 0.2784, 0.2800, + 0.2814, 0.2834, 0.2839, 0.2851, 0.2877, + 0.2883, 0.2891, 0.2900, 0.2907, 0.2916, + 0.2934, 0.2950, 0.2969, 0.2975, 0.2983, + 0.2999, 0.3006, 0.3013, 0.3021, 0.3033, + 0.3054, 0.3066, 0.3074, 0.3082, 0.3094, + 0.3106, 0.3112, 0.3120, 0.3137, 0.3141, + 0.3145, 0.3151, 0.3159, 0.3169, 0.3174, + 0.3181, 0.3194, 0.3215, 0.3219, 0.3231, + 0.3234, 0.3237, 0.3242, 0.3255, 0.3270, + 0.3283, 0.3286, 0.3289, 0.3304, 0.3315, + 0.3322, 0.3347, 0.3361, 0.3382, 0.3384, + 0.3395, 0.3398, 0.3401, 0.3405, 0.3411, + 0.3431, 0.3435, 0.3442, 0.3447, 0.3450, + 0.3455, 0.3464, 0.3472, 0.3486, 0.3497, + 0.3501, 0.3509, 0.3517, 0.3531, 0.3535, + 0.3540, 0.3565, 0.3569, 0.3576, 0.3579, + 0.3584, 0.3590, 0.3594, 0.3599, 0.3621, + 0.3627, 0.3642, 0.3649, 0.3655, 0.3658, + 0.3667, 0.3683, 0.3699, 0.3704, 0.3707, + 0.3711, 0.3715, 0.3718, 0.3721, 0.3727, + 0.3740, 0.3744, 0.3748, 0.3753, 0.3756, + 0.3761, 0.3766, 0.3775, 0.3794, 0.3801, + 0.3804, 0.3813, 0.3817, 0.3823, 0.3831, + 0.3847, 0.3875, 0.3881, 0.3886, 0.3890, + 0.3893, 0.3896, 0.3900, 0.3907, 0.3923, + 0.3925, 0.3933, 0.3936, 0.3961, 0.3971, + 0.3981, 0.3989, 0.4007, 0.4012, 0.4018, + 0.4023, 0.4027, 0.4041, 0.4048, 0.4056, + 0.4073, 0.4079, 0.4086, 0.4104, 0.4107, + 0.4109, 0.4112, 0.4118, 0.4133, 0.4139, + 0.4144, 0.4146, 0.4148, 0.4164, 0.4165, + 0.4174, 0.4191, 0.4197, 0.4201, 0.4204, + 0.4210, 0.4213, 0.4216, 0.4221, 0.4231, + 0.4235, 0.4237, 0.4239, 0.4241, 0.4244, + 0.4249, +}; + +/* + * Divider for SMART attribute 187 + */ +static unsigned SMART_187_STEP = 1; + +/* + * Failure rate for 30 days, for a disk + * with SMART attribute 187 at a given value. + */ +static double SMART_187_R[SMART_MEASURES] = { + 0.0039, 0.1287, 0.1579, 0.1776, 0.1905, + 0.2013, 0.2226, 0.3263, 0.3612, 0.3869, + 0.4086, 0.4292, 0.4559, 0.5278, 0.5593, + 0.5847, 0.6124, 0.6345, 0.6517, 0.6995, + 0.7308, 0.7541, 0.7814, 0.8122, 0.8306, + 0.8839, 0.9100, 0.9505, 0.9906, 1.0254, + 1.0483, 1.1060, 1.1280, 1.1624, 1.1895, + 1.2138, 1.2452, 1.2864, 1.3120, 1.3369, + 1.3705, 1.3894, 1.4055, 1.4218, 1.4434, + 1.4670, 1.4834, 1.4993, 1.5174, 1.5400, + 1.5572, 1.5689, 1.5808, 1.6198, 1.6346, + 1.6405, 1.6570, 1.6618, 1.6755, 1.6877, + 1.7100, 1.7258, 1.7347, 1.7814, 1.7992, + 1.8126, 1.8225, 1.8269, 1.8341, 1.8463, + 1.8765, 1.8850, 1.9005, 1.9281, 1.9398, + 1.9618, 1.9702, 1.9905, 2.0099, 2.0480, + 2.0565, 2.0611, 2.0709, 2.0846, 2.0895, + 2.0958, 2.1008, 2.1055, 2.1097, 2.1235, + 2.1564, 2.1737, 2.1956, 2.1989, 2.2015, + 2.2148, 2.2355, 2.2769, 2.2940, 2.3045, + 2.3096, 2.3139, 2.3344, 2.3669, 2.3779, + 2.3941, 2.4036, 2.4396, 2.4473, 2.4525, + 2.4656, 2.4762, 2.4787, 2.5672, 2.5732, + 2.5755, 2.5794, 2.5886, 2.6100, 2.6144, + 2.6341, 2.6614, 2.6679, 2.6796, 2.6847, + 2.6872, 2.6910, 2.6934, 2.6995, 2.7110, + 2.7179, 2.7204, 2.7232, 2.7282, 2.7355, + 2.7375, 2.7422, 2.7558, 2.7580, 2.7643, + 2.7767, 2.7770, 2.8016, 2.9292, 2.9294, + 2.9337, 2.9364, 2.9409, 2.9436, 2.9457, + 2.9466, 2.9498, 2.9543, 2.9570, 2.9573, + 2.9663, 2.9708, 2.9833, 2.9859, 2.9895, + 2.9907, 2.9932, 2.9935, 3.0021, 3.0035, + 3.0079, 3.0103, 3.0126, 3.0151, 3.0266, + 3.0288, 3.0320, 3.0330, 3.0343, 3.0373, + 3.0387, 3.0438, 3.0570, 3.0579, 3.0616, + 3.0655, 3.0728, 3.0771, 3.0794, 3.0799, + 3.0812, 3.1769, 3.1805, 3.1819, 3.1860, + 3.1869, 3.2004, 3.2016, 3.2025, 3.2070, + 3.2129, 3.2173, 3.2205, 3.2254, 3.2263, + 3.2300, 3.2413, 3.2543, 3.2580, 3.2595, + 3.2611, 3.2624, 3.2787, 3.2798, 3.2809, + 3.2823, 3.2833, 3.2834, 3.2853, 3.2866, + 3.3332, 3.3580, 3.3595, 3.3625, 3.3631, + 3.3667, 3.3702, 3.3737, 3.3742, 3.3747, + 3.3769, 3.3775, 3.3791, 3.3809, 3.3813, + 3.3814, 3.3822, 3.3827, 3.3828, 3.3833, + 3.3833, 3.3843, 3.3882, 3.3963, 3.4047, + 3.4057, 3.4213, 3.4218, 3.4230, 3.4231, + 3.4240, 3.4262, 3.4283, 3.4283, 3.4288, + 3.4293, 3.4302, 3.4317, 3.4478, 3.4486, + 3.4520, +}; + +/* + * Divider for SMART attribute 188 + */ +static unsigned SMART_188_STEP = 1; + +/* + * Failure rate for 30 days, for a disk + * with SMART attribute 188 at a given value. + */ +static double SMART_188_R[SMART_MEASURES] = { + 0.0025, 0.0129, 0.0182, 0.0215, 0.0236, + 0.0257, 0.0279, 0.0308, 0.0341, 0.0382, + 0.0430, 0.0491, 0.0565, 0.0658, 0.0770, + 0.0906, 0.1037, 0.1197, 0.1355, 0.1525, + 0.1686, 0.1864, 0.2011, 0.2157, 0.2281, + 0.2404, 0.2505, 0.2591, 0.2676, 0.2766, + 0.2827, 0.2913, 0.2999, 0.3100, 0.3185, + 0.3298, 0.3361, 0.3446, 0.3506, 0.3665, + 0.3699, 0.3820, 0.3890, 0.4059, 0.4108, + 0.4255, 0.4290, 0.4424, 0.4473, 0.4617, + 0.4667, 0.4770, 0.4829, 0.4977, 0.4997, + 0.5102, 0.5137, 0.5283, 0.5316, 0.5428, + 0.5480, 0.5597, 0.5634, 0.5791, 0.5826, + 0.5929, 0.5945, 0.6025, 0.6102, 0.6175, + 0.6245, 0.6313, 0.6421, 0.6468, 0.6497, + 0.6557, 0.6570, 0.6647, 0.6698, 0.6769, + 0.6849, 0.6884, 0.6925, 0.7025, 0.7073, + 0.7161, 0.7223, 0.7256, 0.7280, 0.7411, + 0.7445, 0.7530, 0.7628, 0.7755, 0.7900, + 0.8006, 0.8050, 0.8098, 0.8132, 0.8192, + 0.8230, 0.8293, 0.8356, 0.8440, 0.8491, + 0.8672, 0.8766, 0.8907, 0.8934, 0.8992, + 0.9062, 0.9111, 0.9209, 0.9290, 0.9329, + 0.9378, 0.9385, 0.9402, 0.9427, 0.9448, + 0.9459, 0.9568, 0.9626, 0.9628, 0.9730, + 0.9765, 0.9797, 0.9825, 0.9873, 0.9902, + 0.9926, 0.9991, 1.0031, 1.0044, 1.0062, + 1.0120, 1.0148, 1.0188, 1.0218, 1.0231, + 1.0249, 1.0277, 1.0335, 1.0355, 1.0417, + 1.0467, 1.0474, 1.0510, 1.0529, 1.0532, + 1.0562, 1.0610, 1.0702, 1.0708, 1.0800, + 1.0804, 1.0845, 1.1120, 1.1191, 1.1225, + 1.1264, 1.1265, 1.1335, 1.1347, 1.1479, + 1.1479, 1.1519, 1.1545, 1.1645, 1.1646, + 1.1647, 1.1649, 1.1678, 1.1713, 1.1723, + 1.1733, 1.1736, 1.1736, 1.1738, 1.1739, + 1.1739, 1.1741, 1.1741, 1.1746, 1.1746, + 1.1748, 1.1750, 1.1760, 1.1794, 1.1854, + 1.1908, 1.1912, 1.1912, 1.1971, 1.2033, + 1.2033, 1.2120, 1.2166, 1.2185, 1.2185, + 1.2189, 1.2211, 1.2226, 1.2234, 1.2320, + 1.2345, 1.2345, 1.2347, 1.2350, 1.2350, + 1.2407, 1.2408, 1.2408, 1.2408, 1.2409, + 1.2460, 1.2518, 1.2519, 1.2519, 1.2519, + 1.2520, 1.2520, 1.2521, 1.2521, 1.2521, + 1.2593, 1.2745, 1.2760, 1.2772, 1.2831, + 1.2833, 1.2890, 1.2906, 1.3166, 1.3201, + 1.3202, 1.3202, 1.3202, 1.3204, 1.3204, + 1.3314, 1.3422, 1.3423, 1.3441, 1.3491, + 1.3583, 1.3602, 1.3606, 1.3636, 1.3650, + 1.3661, 1.3703, 1.3708, 1.3716, 1.3730, + 1.3731, +}; + +/* + * Divider for SMART attribute 193 + */ +static unsigned SMART_193_STEP = 649; + +/* + * Failure rate for 30 days, for a disk + * with SMART attribute 193 at a given value. + */ +static double SMART_193_R[SMART_MEASURES] = { + 0.0000, 0.0016, 0.0032, 0.0036, 0.0039, + 0.0042, 0.0046, 0.0049, 0.0052, 0.0054, + 0.0057, 0.0060, 0.0062, 0.0065, 0.0068, + 0.0071, 0.0074, 0.0077, 0.0080, 0.0083, + 0.0086, 0.0091, 0.0094, 0.0098, 0.0101, + 0.0104, 0.0108, 0.0111, 0.0119, 0.0122, + 0.0127, 0.0130, 0.0134, 0.0137, 0.0141, + 0.0144, 0.0146, 0.0152, 0.0155, 0.0159, + 0.0163, 0.0165, 0.0168, 0.0172, 0.0176, + 0.0179, 0.0184, 0.0188, 0.0190, 0.0194, + 0.0197, 0.0201, 0.0204, 0.0207, 0.0209, + 0.0213, 0.0215, 0.0219, 0.0221, 0.0225, + 0.0229, 0.0234, 0.0241, 0.0246, 0.0253, + 0.0263, 0.0278, 0.0286, 0.0293, 0.0298, + 0.0302, 0.0306, 0.0311, 0.0315, 0.0319, + 0.0322, 0.0329, 0.0334, 0.0338, 0.0343, + 0.0348, 0.0352, 0.0358, 0.0362, 0.0367, + 0.0371, 0.0374, 0.0378, 0.0383, 0.0388, + 0.0393, 0.0397, 0.0401, 0.0404, 0.0410, + 0.0416, 0.0422, 0.0428, 0.0436, 0.0443, + 0.0449, 0.0454, 0.0457, 0.0462, 0.0468, + 0.0473, 0.0479, 0.0483, 0.0488, 0.0491, + 0.0493, 0.0497, 0.0500, 0.0504, 0.0507, + 0.0510, 0.0514, 0.0519, 0.0523, 0.0528, + 0.0533, 0.0538, 0.0542, 0.0547, 0.0551, + 0.0556, 0.0560, 0.0565, 0.0572, 0.0577, + 0.0584, 0.0590, 0.0594, 0.0599, 0.0603, + 0.0607, 0.0611, 0.0616, 0.0621, 0.0626, + 0.0632, 0.0639, 0.0647, 0.0655, 0.0661, + 0.0669, 0.0676, 0.0683, 0.0691, 0.0699, + 0.0708, 0.0713, 0.0719, 0.0724, 0.0730, + 0.0736, 0.0745, 0.0751, 0.0759, 0.0769, + 0.0779, 0.0787, 0.0796, 0.0804, 0.0815, + 0.0825, 0.0833, 0.0840, 0.0847, 0.0854, + 0.0859, 0.0865, 0.0873, 0.0881, 0.0890, + 0.0900, 0.0912, 0.0919, 0.0929, 0.0942, + 0.0956, 0.0965, 0.0976, 0.0986, 0.0995, + 0.1006, 0.1019, 0.1031, 0.1038, 0.1045, + 0.1051, 0.1058, 0.1066, 0.1072, 0.1077, + 0.1084, 0.1091, 0.1099, 0.1104, 0.1111, + 0.1118, 0.1127, 0.1135, 0.1142, 0.1149, + 0.1157, 0.1163, 0.1168, 0.1173, 0.1179, + 0.1184, 0.1189, 0.1195, 0.1203, 0.1208, + 0.1213, 0.1223, 0.1231, 0.1240, 0.1246, + 0.1252, 0.1260, 0.1269, 0.1276, 0.1287, + 0.1303, 0.1311, 0.1319, 0.1328, 0.1335, + 0.1341, 0.1348, 0.1362, 0.1373, 0.1380, + 0.1387, 0.1392, 0.1398, 0.1403, 0.1408, + 0.1412, 0.1418, 0.1422, 0.1428, 0.1434, + 0.1439, 0.1445, 0.1451, 0.1457, 0.1464, + 0.1469, 0.1475, 0.1480, 0.1486, 0.1491, + 0.1498, +}; + +/* + * Divider for SMART attribute 197 + */ +static unsigned SMART_197_STEP = 1; + +/* + * Failure rate for 30 days, for a disk + * with SMART attribute 197 at a given value. + */ +static double SMART_197_R[SMART_MEASURES] = { + 0.0028, 0.2972, 0.3883, 0.4363, 0.4644, + 0.4813, 0.4948, 0.5051, 0.5499, 0.8535, + 0.8678, 0.8767, 0.8882, 0.8933, 0.9012, + 0.9076, 0.9368, 1.1946, 1.2000, 1.2110, + 1.2177, 1.2305, 1.2385, 1.2447, 1.2699, + 1.4713, 1.4771, 1.4802, 1.4887, 1.5292, + 1.5384, 1.5442, 1.5645, 1.7700, 1.7755, + 1.7778, 1.7899, 1.7912, 1.7991, 1.7998, + 1.8090, 1.9974, 1.9992, 2.0088, 2.0132, + 2.0146, 2.0161, 2.0171, 2.0273, 2.1845, + 2.1866, 2.1877, 2.1900, 2.1922, 2.1944, + 2.1974, 2.2091, 2.3432, 2.3459, 2.3463, + 2.3468, 2.3496, 2.3503, 2.3533, 2.3593, + 2.4604, 2.4606, 2.4609, 2.4612, 2.4620, + 2.4626, 2.4638, 2.4689, 2.5575, 2.5581, + 2.5586, 2.5586, 2.5588, 2.5602, 2.5602, + 2.5648, 2.6769, 2.6769, 2.6769, 2.6794, + 2.6805, 2.6811, 2.6814, 2.6862, 2.7742, + 2.7755, 2.7771, 2.7780, 2.7790, 2.7797, + 2.7807, 2.7871, 2.9466, 2.9478, 2.9492, + 2.9612, 2.9618, 2.9624, 2.9628, 2.9669, + 3.1467, 3.1481, 3.1494, 3.1499, 3.1504, + 3.1507, 3.1509, 3.1532, 3.2675, 3.2681, + 3.2703, 3.2712, 3.2714, 3.2726, 3.2726, + 3.2743, 3.3376, 3.3379, 3.3382, 3.3397, + 3.3403, 3.3410, 3.3410, 3.3429, 3.4052, + 3.4052, 3.4052, 3.4052, 3.4052, 3.4053, + 3.4053, 3.4075, 3.4616, 3.4616, 3.4616, + 3.4616, 3.4616, 3.4616, 3.4620, 3.4634, + 3.4975, 3.4975, 3.4975, 3.4975, 3.4979, + 3.4979, 3.4979, 3.4998, 3.5489, 3.5489, + 3.5489, 3.5489, 3.5489, 3.5493, 3.5497, + 3.5512, 3.5827, 3.5828, 3.5828, 3.5828, + 3.5828, 3.5828, 3.5828, 3.5844, 3.6251, + 3.6251, 3.6251, 3.6267, 3.6267, 3.6271, + 3.6271, 3.6279, 3.6562, 3.6562, 3.6563, + 3.7206, 3.7242, 3.7332, 3.7332, 3.7346, + 3.7548, 3.7548, 3.7553, 3.7576, 3.7581, + 3.7586, 3.7587, 3.7600, 3.7773, 3.7812, + 3.7836, 3.7841, 3.7842, 3.7851, 3.7856, + 3.7876, 3.8890, 3.8890, 3.8890, 3.8890, + 3.8890, 3.8890, 3.8890, 3.8897, 3.9111, + 3.9114, 3.9114, 3.9114, 3.9114, 3.9114, + 3.9114, 3.9126, 3.9440, 3.9440, 3.9440, + 3.9440, 3.9440, 3.9498, 3.9498, 3.9509, + 3.9783, 3.9783, 3.9784, 3.9784, 3.9784, + 3.9784, 4.0012, 4.0019, 4.0406, 4.0413, + 4.0413, 4.0413, 4.0413, 4.0414, 4.0414, + 4.0421, 4.0552, 4.0552, 4.0558, 4.0558, + 4.0558, 4.0558, 4.0558, 4.0563, 4.0753, + 4.0753, 4.0760, 4.1131, 4.1131, 4.1131, + 4.1131, +}; + +/* + * Divider for SMART attribute 198 + */ +static unsigned SMART_198_STEP = 1; + +/* + * Failure rate for 30 days, for a disk + * with SMART attribute 198 at a given value. + */ +static double SMART_198_R[SMART_MEASURES] = { + 0.0030, 0.5479, 0.5807, 0.5949, 0.6046, + 0.6086, 0.6139, 0.6224, 0.6639, 1.0308, + 1.0329, 1.0364, 1.0371, 1.0387, 1.0399, + 1.0421, 1.0675, 1.3730, 1.3733, 1.3741, + 1.3741, 1.3752, 1.3794, 1.3800, 1.3985, + 1.6291, 1.6303, 1.6309, 1.6352, 1.6384, + 1.6448, 1.6464, 1.6645, 1.8949, 1.8951, + 1.8962, 1.9073, 1.9073, 1.9152, 1.9161, + 1.9240, 2.1308, 2.1315, 2.1328, 2.1328, + 2.1328, 2.1328, 2.1329, 2.1439, 2.3203, + 2.3205, 2.3205, 2.3205, 2.3205, 2.3205, + 2.3205, 2.3265, 2.4729, 2.4729, 2.4729, + 2.4729, 2.4729, 2.4729, 2.4729, 2.4778, + 2.5900, 2.5900, 2.5901, 2.5901, 2.5901, + 2.5901, 2.5901, 2.5949, 2.6964, 2.6965, + 2.6965, 2.6965, 2.6965, 2.6965, 2.6965, + 2.7010, 2.8328, 2.8328, 2.8328, 2.8329, + 2.8329, 2.8329, 2.8329, 2.8366, 2.9405, + 2.9405, 2.9405, 2.9405, 2.9405, 2.9405, + 2.9405, 2.9442, 3.1344, 3.1344, 3.1346, + 3.1463, 3.1463, 3.1463, 3.1463, 3.1493, + 3.3076, 3.3076, 3.3076, 3.3076, 3.3076, + 3.3077, 3.3077, 3.3097, 3.4456, 3.4456, + 3.4456, 3.4456, 3.4456, 3.4456, 3.4456, + 3.4473, 3.5236, 3.5236, 3.5236, 3.5236, + 3.5236, 3.5236, 3.5236, 3.5249, 3.6004, + 3.6004, 3.6004, 3.6004, 3.6004, 3.6004, + 3.6004, 3.6026, 3.6684, 3.6684, 3.6684, + 3.6684, 3.6684, 3.6684, 3.6684, 3.6697, + 3.7121, 3.7121, 3.7121, 3.7121, 3.7121, + 3.7121, 3.7121, 3.7136, 3.7744, 3.7744, + 3.7744, 3.7744, 3.7744, 3.7745, 3.7745, + 3.7756, 3.8151, 3.8151, 3.8151, 3.8151, + 3.8151, 3.8151, 3.8151, 3.8163, 3.8673, + 3.8673, 3.8673, 3.8673, 3.8673, 3.8673, + 3.8673, 3.8680, 3.9044, 3.9044, 3.9044, + 3.9044, 3.9044, 3.9044, 3.9044, 3.9056, + 3.9297, 3.9297, 3.9297, 3.9297, 3.9297, + 3.9297, 3.9297, 3.9305, 3.9494, 3.9494, + 3.9494, 3.9494, 3.9494, 3.9494, 3.9494, + 3.9514, 4.0725, 4.0725, 4.0725, 4.0725, + 4.0725, 4.0725, 4.0725, 4.0731, 4.0990, + 4.0993, 4.0993, 4.0993, 4.0993, 4.0993, + 4.0993, 4.1004, 4.1385, 4.1385, 4.1385, + 4.1386, 4.1386, 4.1387, 4.1387, 4.1398, + 4.1732, 4.2284, 4.2284, 4.2284, 4.2284, + 4.2284, 4.2284, 4.2290, 4.2781, 4.2781, + 4.2963, 4.2963, 4.2963, 4.2963, 4.2963, + 4.2971, 4.3141, 4.3141, 4.3141, 4.3141, + 4.3141, 4.3141, 4.3141, 4.3146, 4.3393, + 4.3393, 4.3393, 4.3393, 4.3393, 4.3393, + 4.3393, +}; + +/** + * Computes the estimated Annual Failure Rate from the specified table. + */ +static double smart_afr_value(double* tab, unsigned step, uint64_t value) +{ + value /= step; + + if (value >= SMART_MEASURES) + value = SMART_MEASURES - 1; + + /* table rates are for a month, so we scale to a year */ + return 365.0 / 30.0 * tab[value]; +} + +/** + * Computes the estimated Annual Failure Rate of a set of SMART attributes. + * + * We define the Annual Failure Rate as the average number of + * failures you expect in a year from a disk slot: + * + * AFR = 8760/MTBF (Mean Time Between Failures in hours). + * + * Note that this definition is different from the one given + * by Seagate, that defines AFR = 1 - exp(-8760/MTBF), that + * instead represents the probability of a failure in the next + * year. + * + * To combine the different AFR from different SMART attributes, + * we use the maximum rate reported, and we do not sum them, + * because the attributes are not independent. + */ +static double smart_afr(uint64_t* smart, const char* model) +{ + double afr = 0; + uint64_t mask32 = 0xffffffffU; + uint64_t mask16 = 0xffffU; + + if (smart[5] != SMART_UNASSIGNED) { + double r = smart_afr_value(SMART_5_R, SMART_5_STEP, smart[5] & mask32); + if (afr < r) + afr = r; + } + + if (smart[187] != SMART_UNASSIGNED) { + /* with some disks, only the lower 16 bits are significative */ + /* See: http://web.archive.org/web/20130507072056/http://media.kingston.com/support/downloads/MKP_306_SMART_attribute.pdf */ + double r = smart_afr_value(SMART_187_R, SMART_187_STEP, smart[187] & mask16); + if (afr < r) + afr = r; + } + + if ( + /** + * Don't check Command_Timeout (188) for Seagate disks. + * + * It's reported by users that for Archive SMR (Shingled Magnetic Recording) + * and IronWolf disks to be a not significative test as + * this value increases too often also on sane disks. + */ + strncmp(model, "ST", 2) != 0 && smart[188] != SMART_UNASSIGNED + ) { + /* with Seagate disks, there are three different 16 bits value reported */ + /* the lowest one is the most significant */ + double r = smart_afr_value(SMART_188_R, SMART_188_STEP, smart[188] & mask16); + if (afr < r) + afr = r; + } + + if (smart[193] != SMART_UNASSIGNED) { + double r = smart_afr_value(SMART_193_R, SMART_193_STEP, smart[193] & mask32); + if (afr < r) + afr = r; + } + + if (smart[197] != SMART_UNASSIGNED) { + double r = smart_afr_value(SMART_197_R, SMART_197_STEP, smart[197] & mask32); + if (afr < r) + afr = r; + } + + if (smart[198] != SMART_UNASSIGNED) { + double r = smart_afr_value(SMART_198_R, SMART_198_STEP, smart[198] & mask32); + if (afr < r) + afr = r; + } + + return afr; +} + +/** + * Factorial. + */ +static double fact(unsigned n) +{ + double v = 1; + + while (n > 1) + v *= n--; + + return v; +} + +/** + * Probability of having exactly ::n events in a Poisson + * distribution with rate ::rate in a time unit. + */ +static double poisson_prob_n_failures(double rate, unsigned n) +{ + return pow(rate, n) * exp(-rate) / fact(n); +} + +/** + * Probability of having ::n or more events in a Poisson + * distribution with rate ::rate in a time unit. + */ +static double poisson_prob_n_or_more_failures(double rate, unsigned n) +{ + double p_neg = 0; + unsigned i; + + for (i = 0; i < n; ++i) + p_neg += poisson_prob_n_failures(rate, n - 1 - i); + + return 1 - p_neg; +} + +/** + * Probability of having data loss in a RAID system with the specified ::redundancy + * supposing the specified ::array_failure_rate, and ::replace_rate. + */ +static double raid_prob_of_one_or_more_failures(double array_failure_rate, double replace_rate, unsigned n, unsigned redundancy) +{ + unsigned i; + double MTBF; + double MTTR; + double MTTDL; + double raid_failure_rate; + + /* + * Use the MTTDL model (Mean Time To Data Loss) to estimate the + * failure rate of the array. + * + * See: + * Garth Alan Gibson, "Redundant Disk Arrays: Reliable, Parallel Secondary Storage", 1990 + */ + + /* avoid division by zero */ + if (array_failure_rate == 0) + return 0; + + /* get the Mean Time Between Failure of a single disk */ + /* from the array failure rate */ + MTBF = n / array_failure_rate; + + /* get the Mean Time Between Repair (the time that a failed disk is replaced) */ + /* from the repair rate */ + MTTR = 1.0 / replace_rate; + + /* use the approximated MTTDL equation */ + MTTDL = pow(MTBF, redundancy + 1) / pow(MTTR, redundancy); + for (i = 0; i < redundancy + 1; ++i) + MTTDL /= n - i; + + /* the raid failure rate is just the inverse of the MTTDL */ + raid_failure_rate = 1.0 / MTTDL; + + /* probability of at least one RAID failure */ + /* note that is almost equal at the probability of */ + /* the first failure. */ + return poisson_prob_n_or_more_failures(raid_failure_rate, 1); +} + +static void state_smart(unsigned n, tommy_list* low) +{ + tommy_node* i; + unsigned j; + size_t device_pad; + size_t serial_pad; + int have_parent; + double array_failure_rate; + double p_at_least_one_failure; + int make_it_fail = 0; + uint64_t mask32 = 0xffffffffU; + uint64_t mask16 = 0xffffU; + char esc_buffer[ESC_MAX]; + + /* compute lengths for padding */ + device_pad = 0; + serial_pad = 0; + have_parent = 0; + for (i = tommy_list_head(low); i != 0; i = i->next) { + size_t len; + devinfo_t* devinfo = i->data; + + len = strlen(devinfo->file); + if (len > device_pad) + device_pad = len; + + len = strlen(devinfo->smart_serial); + if (len > serial_pad) + serial_pad = len; + + if (devinfo->parent != 0) + have_parent = 1; + } + + printf("SnapRAID SMART report:\n"); + printf("\n"); + printf(" Temp"); + printf(" Power"); + printf(" Error"); + printf(" FP"); + printf(" Size"); + printf("\n"); + printf(" C"); + printf(" OnDays"); + printf(" Count"); + printf(" "); + printf(" TB"); + printf(" "); printl("Serial", serial_pad); + printf(" "); printl("Device", device_pad); + printf(" Disk"); + printf("\n"); + /* |<##################################################################72>|####80>| */ + printf(" -----------------------------------------------------------------------\n"); + + array_failure_rate = 0; + for (i = tommy_list_head(low); i != 0; i = i->next) { + devinfo_t* devinfo = i->data; + double afr; + uint64_t flag; + + if (devinfo->smart[SMART_TEMPERATURE_CELSIUS] != SMART_UNASSIGNED) + printf("%7" PRIu64, devinfo->smart[SMART_TEMPERATURE_CELSIUS] & mask16); + else if (devinfo->smart[SMART_AIRFLOW_TEMPERATURE_CELSIUS] != SMART_UNASSIGNED) + printf("%7" PRIu64, devinfo->smart[SMART_AIRFLOW_TEMPERATURE_CELSIUS] & mask16); + else + printf(" -"); + + if (devinfo->smart[SMART_POWER_ON_HOURS] != SMART_UNASSIGNED) + printf("%7" PRIu64, (devinfo->smart[SMART_POWER_ON_HOURS] & mask32) / 24); + else + printf(" -"); + + if (devinfo->smart[SMART_FLAGS] != SMART_UNASSIGNED) + flag = devinfo->smart[SMART_FLAGS]; + else + flag = 0; + if (flag & SMARTCTL_FLAG_FAIL) + printf(" FAIL"); + else if (flag & SMARTCTL_FLAG_PREFAIL) + printf(" PREFAIL"); + else if (flag & SMARTCTL_FLAG_PREFAIL_LOGGED) + printf(" logfail"); + else if (devinfo->smart[SMART_ERROR] != SMART_UNASSIGNED + && devinfo->smart[SMART_ERROR] != 0) + printf("%8" PRIu64, devinfo->smart[SMART_ERROR]); + else if (flag & SMARTCTL_FLAG_ERROR) + printf(" logerr"); + else if (flag & SMARTCTL_FLAG_ERROR_LOGGED) + printf(" selferr"); + else if (devinfo->smart[SMART_ERROR] == 0) + printf(" 0"); + else + printf(" -"); + + /* if some fail/prefail attribute, make the command to fail */ + if (flag & (SMARTCTL_FLAG_FAIL | SMARTCTL_FLAG_PREFAIL)) + make_it_fail = 1; + + /* note that in older smartmontools, like 5.x, rotation rate is not present */ + /* and then it could remain unassigned */ + + if (flag & (SMARTCTL_FLAG_UNSUPPORTED | SMARTCTL_FLAG_OPEN)) { + /* if error running smartctl, skip AFR estimation */ + afr = 0; + printf(" n/a"); + } else if (devinfo->smart[SMART_ROTATION_RATE] == 0) { + /* if SSD, skip AFR estimation as data is from not SSD disks */ + afr = 0; + printf(" SSD"); + } else { + afr = smart_afr(devinfo->smart, devinfo->smart_model); + + if (afr == 0) { + /* this happens only if no data */ + printf(" -"); + } else { + /* use only the disks in the array */ + if (devinfo->parent != 0 || !have_parent) + array_failure_rate += afr; + + printf("%4.0f%%", poisson_prob_n_or_more_failures(afr, 1) * 100); + } + } + + if (devinfo->smart[SMART_SIZE] != SMART_UNASSIGNED) + printf(" %4.1f", devinfo->smart[SMART_SIZE] / 1E12); + else + printf(" -"); + + printf(" "); + if (*devinfo->smart_serial) + printl(devinfo->smart_serial, serial_pad); + else + printl("-", serial_pad); + + printf(" "); + if (*devinfo->file) + printl(devinfo->file, device_pad); + else + printl("-", device_pad); + + printf(" "); + if (*devinfo->name) + printf("%s", devinfo->name); + else + printf("-"); + + printf("\n"); + + log_tag("smart:%s:%s\n", devinfo->file, devinfo->name); + if (devinfo->smart_serial[0]) + log_tag("attr:%s:%s:serial:%s\n", devinfo->file, devinfo->name, esc_tag(devinfo->smart_serial, esc_buffer)); + if (devinfo->smart_vendor[0]) + log_tag("attr:%s:%s:vendor:%s\n", devinfo->file, devinfo->name, esc_tag(devinfo->smart_vendor, esc_buffer)); + if (devinfo->smart_model[0]) + log_tag("attr:%s:%s:model:%s\n", devinfo->file, devinfo->name, esc_tag(devinfo->smart_model, esc_buffer)); + if (afr != 0) + log_tag("attr:%s:%s:afr:%g:%g\n", devinfo->file, devinfo->name, afr, poisson_prob_n_or_more_failures(afr, 1)); + if (devinfo->smart[SMART_SIZE] != SMART_UNASSIGNED) + log_tag("attr:%s:%s:size:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_SIZE]); + if (devinfo->smart[SMART_ERROR] != SMART_UNASSIGNED) + log_tag("attr:%s:%s:error:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_ERROR]); + if (devinfo->smart[SMART_ROTATION_RATE] != SMART_UNASSIGNED) + log_tag("attr:%s:%s:rotationrate:%" PRIu64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_ROTATION_RATE]); + if (devinfo->smart[SMART_FLAGS] != SMART_UNASSIGNED) + log_tag("attr:%s:%s:flags:%" PRIu64 ":%" PRIx64 "\n", devinfo->file, devinfo->name, devinfo->smart[SMART_FLAGS], devinfo->smart[SMART_FLAGS]); + for (j = 0; j < 256; ++j) + if (devinfo->smart[j] != SMART_UNASSIGNED) + log_tag("attr:%s:%s:%u:%" PRIu64 ":%" PRIx64 "\n", devinfo->file, devinfo->name, j, devinfo->smart[j], devinfo->smart[j]); + } + + printf("\n"); + + /* |<##################################################################72>|####80>| */ + printf("The FP column is the estimated probability (in percentage) that the disk\n"); + printf("is going to fail in the next year.\n"); + printf("\n"); + + /* + * The probability of one and of at least one failure is computed assuming + * a Poisson distribution with the estimated array failure rate. + */ + p_at_least_one_failure = poisson_prob_n_or_more_failures(array_failure_rate, 1); + + printf("Probability that at least one disk is going to fail in the next year is %.0f%%.\n", p_at_least_one_failure * 100); + log_tag("summary:array_failure:%g:%g\n", array_failure_rate, p_at_least_one_failure); + + /* print extra stats only in verbose mode */ + if (msg_level < MSG_VERBOSE) + goto bail; + + /* |<##################################################################72>|####80>| */ + printf("\n"); + printf("Probability of data loss in the next year for different parity and\n"); + printf("combined scrub and repair time:\n"); + printf("\n"); + printf(" Parity 1 Week 1 Month 3 Months\n"); + printf(" -----------------------------------------------------------------------\n"); + for (j = 0; j < RAID_PARITY_MAX; ++j) { + printf("%6u", j + 1); + printf(" "); + printp(raid_prob_of_one_or_more_failures(array_failure_rate, 365.0 / 7, n, j + 1) * 100, 19); + printf(" "); + printp(raid_prob_of_one_or_more_failures(array_failure_rate, 365.0 / 30, n, j + 1) * 100, 17); + printf(" "); + printp(raid_prob_of_one_or_more_failures(array_failure_rate, 365.0 / 90, n, j + 1) * 100, 13); + printf("\n"); + } + + printf("\n"); + + /* |<##################################################################72>|####80>| */ + printf("These values are the probabilities that in the next year you'll have a\n"); + printf("sequence of failures that the parity WONT be able to recover, assuming\n"); + printf("that you regularly scrub, and in case repair, the array in the specified\n"); + printf("time.\n"); + +bail: + if (make_it_fail) { + printf("\n"); + printf("DANGER! SMART is reporting that one or more disks are FAILING!\n"); + printf("Please take immediate action!\n"); + exit(EXIT_FAILURE); + } +} + +/** + * Fill with fake data the device list. + */ +static int devtest(tommy_list* low, int operation) +{ + unsigned c; + + if (operation != DEVICE_SMART) + return -1; + + /* add some fake data */ + for (c = 0; c < 16; ++c) { + devinfo_t* entry; + int j; + + entry = calloc_nofail(1, sizeof(devinfo_t)); + + entry->device = c; + + tommy_list_insert_tail(low, &entry->node, entry); + + for (j = 0; j < 256; ++j) { + switch (c) { + case 0 : entry->smart[j] = 0; break; + case 1 : entry->smart[j] = SMART_UNASSIGNED; break; + default : + if (j == 193) + entry->smart[j] = c - 2; + else + entry->smart[j] = 0; + break; + } + } + + if (c == 0) { + entry->smart_serial[0] = 0; + entry->smart_vendor[0] = 0; + entry->smart_model[0] = 0; + entry->file[0] = 0; + entry->name[0] = 0; + entry->smart[SMART_SIZE] = SMART_UNASSIGNED; + entry->smart[SMART_ROTATION_RATE] = 0; + } else { + snprintf(entry->smart_serial, sizeof(entry->smart_serial), "S%u", c); + snprintf(entry->smart_vendor, sizeof(entry->smart_vendor), "V%u", c); + snprintf(entry->smart_model, sizeof(entry->smart_model), "M%u", c); + pathcpy(entry->file, sizeof(entry->name), "file"); + pathcpy(entry->name, sizeof(entry->name), "name"); + entry->smart[SMART_SIZE] = c * TERA; + entry->smart[SMART_ROTATION_RATE] = 7200; + } + + entry->smart[SMART_ERROR] = 0; + entry->smart[SMART_FLAGS] = SMART_UNASSIGNED; + + switch (c) { + case 3 : entry->smart[SMART_ERROR] = 1; break; + case 4 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_UNSUPPORTED; break; + case 5 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_COMMAND; break; + case 6 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_OPEN; break; + case 7 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_FAIL; break; + case 8 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_PREFAIL; break; + case 9 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_PREFAIL_LOGGED; break; + case 10 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_ERROR; break; + case 11 : entry->smart[SMART_FLAGS] = SMARTCTL_FLAG_ERROR_LOGGED; break; + } + } + + return 0; +} + +void state_device(struct snapraid_state* state, int operation, tommy_list* filterlist_disk) +{ + tommy_node* i; + unsigned j; + tommy_list high; + tommy_list low; + int ret; + + switch (operation) { + case DEVICE_UP : msg_progress("Spinup...\n"); break; + case DEVICE_DOWN : msg_progress("Spindown...\n"); break; + } + + tommy_list_init(&high); + tommy_list_init(&low); + + /* for all disks */ + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* disk = i->data; + devinfo_t* entry; + + if (filterlist_disk != 0 && filter_path(filterlist_disk, 0, disk->name, 0) != 0) + continue; + + entry = calloc_nofail(1, sizeof(devinfo_t)); + + entry->device = disk->device; + pathcpy(entry->name, sizeof(entry->name), disk->name); + pathcpy(entry->mount, sizeof(entry->mount), disk->dir); + pathcpy(entry->smartctl, sizeof(entry->smartctl), disk->smartctl); + + tommy_list_insert_tail(&high, &entry->node, entry); + } + + /* for all parities */ + for (j = 0; j < state->level; ++j) { + devinfo_t* entry; + unsigned s; + + if (filterlist_disk != 0 && filter_path(filterlist_disk, 0, lev_config_name(j), 0) != 0) + continue; + + for (s = 0; s < state->parity[j].split_mac; ++s) { + entry = calloc_nofail(1, sizeof(devinfo_t)); + + entry->device = state->parity[j].split_map[s].device; + pathcpy(entry->name, sizeof(entry->name), lev_config_name(j)); + pathcpy(entry->mount, sizeof(entry->mount), state->parity[j].split_map[s].path); + pathcpy(entry->smartctl, sizeof(entry->smartctl), state->parity[j].smartctl); + pathcut(entry->mount); /* remove the parity file */ + + tommy_list_insert_tail(&high, &entry->node, entry); + } + } + + if (state->opt.fake_device) { + ret = devtest(&low, operation); + } else { + int others = operation == DEVICE_SMART; + + ret = devquery(&high, &low, operation, others); + } + + /* if the list is empty, it's not supported in this platform */ + if (ret == 0 && tommy_list_empty(&low)) + ret = -1; + + if (ret != 0) { + const char* ope = 0; + switch (operation) { + case DEVICE_UP : ope = "Spinup"; break; + case DEVICE_DOWN : ope = "Spindown"; break; + case DEVICE_LIST : ope = "Device listing"; break; + case DEVICE_SMART : ope = "Smart"; break; + } + log_fatal("%s is unsupported in this platform.\n", ope); + } else { + if (operation == DEVICE_LIST) { + for (i = tommy_list_head(&low); i != 0; i = i->next) { + devinfo_t* devinfo = i->data; + devinfo_t* parent = devinfo->parent; +#ifdef _WIN32 + printf("%" PRIu64 "\t%s\t%08" PRIx64 "\t%s\t%s\n", devinfo->device, devinfo->wfile, parent->device, parent->wfile, parent->name); +#else + printf("%u:%u\t%s\t%u:%u\t%s\t%s\n", major(devinfo->device), minor(devinfo->device), devinfo->file, major(parent->device), minor(parent->device), parent->file, parent->name); +#endif + } + } + + if (operation == DEVICE_SMART) + state_smart(state->level + tommy_list_count(&state->disklist), &low); + } + + tommy_list_foreach(&high, free); + tommy_list_foreach(&low, free); +} + diff --git a/cmdline/dry.c b/cmdline/dry.c new file mode 100644 index 0000000..2fc3b18 --- /dev/null +++ b/cmdline/dry.c @@ -0,0 +1,470 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "util.h" +#include "elem.h" +#include "state.h" +#include "parity.h" +#include "handle.h" +#include "io.h" +#include "raid/raid.h" + +/****************************************************************************/ +/* dry */ + +/** + * Check if we have to process the specified block index ::i. + */ +static int block_is_enabled(void* void_plan, block_off_t i) +{ + (void)void_plan; + (void)i; + + return 1; +} + +static void dry_data_reader(struct snapraid_worker* worker, struct snapraid_task* task) +{ + struct snapraid_io* io = worker->io; + struct snapraid_state* state = io->state; + struct snapraid_handle* handle = worker->handle; + struct snapraid_disk* disk = handle->disk; + block_off_t blockcur = task->position; + unsigned char* buffer = task->buffer; + int ret; + char esc_buffer[ESC_MAX]; + + /* if the disk position is not used */ + if (!disk) { + /* use an empty block */ + memset(buffer, 0, state->block_size); + task->state = TASK_STATE_DONE; + return; + } + + /* get the block */ + task->block = fs_par2block_find(disk, blockcur); + + /* if the block is not used */ + if (!block_has_file(task->block)) { + /* use an empty block */ + memset(buffer, 0, state->block_size); + task->state = TASK_STATE_DONE; + return; + } + + /* get the file of this block */ + task->file = fs_par2file_get(disk, blockcur, &task->file_pos); + + /* if the file is different than the current one, close it */ + if (handle->file != 0 && handle->file != task->file) { + /* keep a pointer at the file we are going to close for error reporting */ + struct snapraid_file* report = handle->file; + ret = handle_close(handle); + if (ret == -1) { + /* LCOV_EXCL_START */ + /* This one is really an unexpected error, because we are only reading */ + /* and closing a descriptor should never fail */ + if (errno == EIO) { + log_tag("error:%u:%s:%s: Close EIO error. %s\n", blockcur, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno)); + log_fatal("DANGER! Unexpected input/output close error in a data disk, it isn't possible to dry.\n"); + log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle->path); + log_fatal("Stopping at block %u\n", blockcur); + task->state = TASK_STATE_IOERROR; + return; + } + + log_tag("error:%u:%s:%s: Close error. %s\n", blockcur, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno)); + log_fatal("WARNING! Unexpected close error in a data disk, it isn't possible to dry.\n"); + log_fatal("Ensure that file '%s' can be accessed.\n", handle->path); + log_fatal("Stopping at block %u\n", blockcur); + task->state = TASK_STATE_ERROR; + return; + /* LCOV_EXCL_STOP */ + } + } + + ret = handle_open(handle, task->file, state->file_mode, log_error, 0); + if (ret == -1) { + if (errno == EIO) { + /* LCOV_EXCL_START */ + log_tag("error:%u:%s:%s: Open EIO error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno)); + log_fatal("DANGER! Unexpected input/output open error in a data disk, it isn't possible to dry.\n"); + log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle->path); + log_fatal("Stopping at block %u\n", blockcur); + task->state = TASK_STATE_IOERROR; + return; + /* LCOV_EXCL_STOP */ + } + + log_tag("error:%u:%s:%s: Open error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno)); + task->state = TASK_STATE_ERROR_CONTINUE; + return; + } + + task->read_size = handle_read(handle, task->file_pos, buffer, state->block_size, log_error, 0); + if (task->read_size == -1) { + if (errno == EIO) { + log_tag("error:%u:%s:%s: Read EIO error at position %u. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), task->file_pos, strerror(errno)); + log_error("Input/Output error in file '%s' at position '%u'\n", handle->path, task->file_pos); + task->state = TASK_STATE_IOERROR_CONTINUE; + return; + } + + log_tag("error:%u:%s:%s: Read error at position %u. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), task->file_pos, strerror(errno)); + task->state = TASK_STATE_ERROR_CONTINUE; + return; + } + + /* store the path of the opened file */ + pathcpy(task->path, sizeof(task->path), handle->path); + + task->state = TASK_STATE_DONE; +} + +static void dry_parity_reader(struct snapraid_worker* worker, struct snapraid_task* task) +{ + struct snapraid_io* io = worker->io; + struct snapraid_state* state = io->state; + struct snapraid_parity_handle* parity_handle = worker->parity_handle; + unsigned level = parity_handle->level; + block_off_t blockcur = task->position; + unsigned char* buffer = task->buffer; + int ret; + + /* read the parity */ + ret = parity_read(parity_handle, blockcur, buffer, state->block_size, log_error); + if (ret == -1) { + if (errno == EIO) { + log_tag("parity_error:%u:%s: Read EIO error. %s\n", blockcur, lev_config_name(level), strerror(errno)); + log_error("Input/Output error in parity '%s' at position '%u'\n", lev_config_name(level), blockcur); + task->state = TASK_STATE_IOERROR_CONTINUE; + return; + } + + log_tag("parity_error:%u:%s: Read error. %s\n", blockcur, lev_config_name(level), strerror(errno)); + task->state = TASK_STATE_ERROR_CONTINUE; + return; + } + + task->state = TASK_STATE_DONE; +} + +static int state_dry_process(struct snapraid_state* state, struct snapraid_parity_handle* parity_handle, block_off_t blockstart, block_off_t blockmax) +{ + struct snapraid_io io; + struct snapraid_handle* handle; + unsigned diskmax; + block_off_t blockcur; + unsigned j; + unsigned buffermax; + int ret; + data_off_t countsize; + block_off_t countpos; + block_off_t countmax; + unsigned error; + unsigned io_error; + unsigned l; + unsigned* waiting_map; + unsigned waiting_mac; + char esc_buffer[ESC_MAX]; + + handle = handle_mapping(state, &diskmax); + + /* we need 1 * data + 2 * parity */ + buffermax = diskmax + 2 * state->level; + + /* initialize the io threads */ + io_init(&io, state, state->opt.io_cache, buffermax, dry_data_reader, handle, diskmax, dry_parity_reader, 0, parity_handle, state->level); + + /* possibly waiting disks */ + waiting_mac = diskmax > RAID_PARITY_MAX ? diskmax : RAID_PARITY_MAX; + waiting_map = malloc_nofail(waiting_mac * sizeof(unsigned)); + + error = 0; + io_error = 0; + + /* drop until now */ + state_usage_waste(state); + + countmax = blockmax - blockstart; + countsize = 0; + countpos = 0; + + /* start all the worker threads */ + io_start(&io, blockstart, blockmax, &block_is_enabled, 0); + + state_progress_begin(state, blockstart, blockmax, countmax); + while (1) { + void** buffer; + + /* go to the next block */ + blockcur = io_read_next(&io, &buffer); + if (blockcur >= blockmax) + break; + + /* until now is scheduling */ + state_usage_sched(state); + + /* for each disk, process the block */ + for (j = 0; j < diskmax; ++j) { + struct snapraid_task* task; + int read_size; + struct snapraid_block* block; + struct snapraid_disk* disk; + unsigned diskcur; + + /* until now is misc */ + state_usage_misc(state); + + /* get the next task */ + task = io_data_read(&io, &diskcur, waiting_map, &waiting_mac); + + /* until now is disk */ + state_usage_disk(state, handle, waiting_map, waiting_mac); + + /* get the task results */ + disk = task->disk; + block = task->block; + read_size = task->read_size; + + /* if the disk position is not used */ + if (!disk) + continue; + + state_usage_file(state, disk, task->file); + + /* if the block is not used */ + if (!block_has_file(block)) + continue; + + /* handle error conditions */ + if (task->state == TASK_STATE_IOERROR) { + /* LCOV_EXCL_START */ + ++io_error; + goto bail; + /* LCOV_EXCL_STOP */ + } + if (task->state == TASK_STATE_ERROR) { + /* LCOV_EXCL_START */ + ++error; + goto bail; + /* LCOV_EXCL_STOP */ + } + if (task->state == TASK_STATE_ERROR_CONTINUE) { + ++error; + continue; + } + if (task->state == TASK_STATE_IOERROR_CONTINUE) { + ++io_error; + if (io_error >= state->opt.io_error_limit) { + /* LCOV_EXCL_START */ + log_fatal("DANGER! Too many input/output read error in a data disk, it isn't possible to scrub.\n"); + log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, task->path); + log_fatal("Stopping at block %u\n", blockcur); + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* otherwise continue */ + continue; + } + if (task->state != TASK_STATE_DONE) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in task state\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + countsize += read_size; + } + + /* until now is misc */ + state_usage_misc(state); + + /* read the parity */ + for (l = 0; l < state->level; ++l) { + struct snapraid_task* task; + unsigned levcur; + + task = io_parity_read(&io, &levcur, waiting_map, &waiting_mac); + + /* until now is parity */ + state_usage_parity(state, waiting_map, waiting_mac); + + /* handle error conditions */ + if (task->state == TASK_STATE_IOERROR) { + /* LCOV_EXCL_START */ + ++io_error; + goto bail; + /* LCOV_EXCL_STOP */ + } + if (task->state == TASK_STATE_ERROR) { + /* LCOV_EXCL_START */ + ++error; + goto bail; + /* LCOV_EXCL_STOP */ + } + if (task->state == TASK_STATE_ERROR_CONTINUE) { + ++error; + continue; + } + if (task->state == TASK_STATE_IOERROR_CONTINUE) { + ++io_error; + if (io_error >= state->opt.io_error_limit) { + /* LCOV_EXCL_START */ + log_fatal("DANGER! Too many input/output read error in the %s disk, it isn't possible to scrub.\n", lev_name(levcur)); + log_fatal("Ensure that disk '%s' is sane and can be read.\n", lev_config_name(levcur)); + log_fatal("Stopping at block %u\n", blockcur); + goto bail; + /* LCOV_EXCL_STOP */ + } + continue; + } + if (task->state != TASK_STATE_DONE) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in task state\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + } + + /* count the number of processed block */ + ++countpos; + + /* progress */ + if (state_progress(state, &io, blockcur, countpos, countmax, countsize)) { + /* LCOV_EXCL_START */ + break; + /* LCOV_EXCL_STOP */ + } + } + + state_progress_end(state, countpos, countmax, countsize); + + state_usage_print(state); + +bail: + /* stop all the worker threads */ + io_stop(&io); + + for (j = 0; j < diskmax; ++j) { + struct snapraid_file* file = handle[j].file; + struct snapraid_disk* disk = handle[j].disk; + ret = handle_close(&handle[j]); + if (ret == -1) { + /* LCOV_EXCL_START */ + log_tag("error:%u:%s:%s: Close error. %s\n", blockmax, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); + log_fatal("DANGER! Unexpected close error in a data disk.\n"); + ++error; + /* continue, as we are already exiting */ + /* LCOV_EXCL_STOP */ + } + } + + if (error || io_error) { + msg_status("\n"); + msg_status("%8u file errors\n", error); + msg_status("%8u io errors\n", io_error); + } else { + msg_status("Everything OK\n"); + } + + if (error) + log_fatal("DANGER! Unexpected errors!\n"); + if (io_error) + log_fatal("DANGER! Unexpected input/output errors!\n"); + + free(handle); + free(waiting_map); + io_done(&io); + + if (error + io_error != 0) + return -1; + return 0; +} + +void state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t blockcount) +{ + block_off_t blockmax; + int ret; + struct snapraid_parity_handle parity_handle[LEV_MAX]; + unsigned error; + unsigned l; + + msg_progress("Drying...\n"); + + blockmax = parity_allocated_size(state); + + if (blockstart > blockmax) { + /* LCOV_EXCL_START */ + log_fatal("Error in the specified starting block %u. It's bigger than the parity size %u.\n", blockstart, blockmax); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* adjust the number of block to process */ + if (blockcount != 0 && blockstart + blockcount < blockmax) { + blockmax = blockstart + blockcount; + } + + /* open the file for reading */ + /* it may fail if the file doesn't exist, in this case we continue to dry the files */ + for (l = 0; l < state->level; ++l) { + ret = parity_open(&parity_handle[l], &state->parity[l], l, state->file_mode, state->block_size, state->opt.parity_limit_size); + if (ret == -1) { + /* LCOV_EXCL_START */ + log_fatal("WARNING! Without an accessible %s file, it isn't possible to dry.\n", lev_name(l)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + error = 0; + + /* skip degenerated cases of empty parity, or skipping all */ + if (blockstart < blockmax) { + ret = state_dry_process(state, parity_handle, blockstart, blockmax); + if (ret == -1) { + /* LCOV_EXCL_START */ + ++error; + /* continue, as we are already exiting */ + /* LCOV_EXCL_STOP */ + } + } + + /* try to close only if opened */ + for (l = 0; l < state->level; ++l) { + ret = parity_close(&parity_handle[l]); + if (ret == -1) { + /* LCOV_EXCL_START */ + ++error; + /* continue, as we are already exiting */ + /* LCOV_EXCL_STOP */ + } + } + + /* abort if required */ + if (error != 0) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } +} + diff --git a/cmdline/dup.c b/cmdline/dup.c new file mode 100644 index 0000000..2bcfcee --- /dev/null +++ b/cmdline/dup.c @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "support.h" +#include "util.h" +#include "elem.h" +#include "state.h" +#include "parity.h" +#include "handle.h" + +/****************************************************************************/ +/* dup */ + +struct snapraid_hash { + struct snapraid_disk* disk; /**< Disk. */ + struct snapraid_file* file; /**< File. */ + unsigned char hash[HASH_MAX]; /**< Hash of the whole file. */ + + /* nodes for data structures */ + tommy_hashdyn_node node; +}; + +struct snapraid_hash* hash_alloc(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file) +{ + struct snapraid_hash* hash; + block_off_t i; + unsigned char* buf; + + hash = malloc_nofail(sizeof(struct snapraid_hash)); + hash->disk = disk; + hash->file = file; + + buf = malloc_nofail(file->blockmax * BLOCK_HASH_SIZE); + + /* set the back pointer */ + for (i = 0; i < file->blockmax; ++i) { + struct snapraid_block* block = fs_file2block_get(file, i); + + memcpy(buf + i * BLOCK_HASH_SIZE, block->hash, BLOCK_HASH_SIZE); + + if (!block_has_updated_hash(block)) { + free(buf); + free(hash); + return 0; + } + } + + memhash(state->besthash, state->hashseed, hash->hash, buf, file->blockmax * BLOCK_HASH_SIZE); + + free(buf); + + return hash; +} + +static inline tommy_uint32_t hash_hash(struct snapraid_hash* hash) +{ + return tommy_hash_u32(0, hash->hash, HASH_MAX); +} + +void hash_free(struct snapraid_hash* hash) +{ + free(hash); +} + +int hash_compare(const void* void_arg, const void* void_data) +{ + const char* arg = void_arg; + const struct snapraid_hash* hash = void_data; + + return memcmp(arg, hash->hash, HASH_MAX); +} + +void state_dup(struct snapraid_state* state) +{ + tommy_hashdyn hashset; + tommy_node* i; + unsigned count; + data_off_t size; + char esc_buffer[ESC_MAX]; + char esc_buffer_alt[ESC_MAX]; + + tommy_hashdyn_init(&hashset); + + count = 0; + size = 0; + + msg_progress("Comparing...\n"); + + /* for each disk */ + for (i = state->disklist; i != 0; i = i->next) { + tommy_node* j; + struct snapraid_disk* disk = i->data; + + /* for each file */ + for (j = disk->filelist; j != 0; j = j->next) { + struct snapraid_file* file = j->data; + struct snapraid_hash* hash; + tommy_hash_t hash32; + + /* if empty, skip it */ + if (file->size == 0) + continue; + + hash = hash_alloc(state, disk, file); + + /* if no hash, skip it */ + if (!hash) + continue; + + hash32 = hash_hash(hash); + + struct snapraid_hash* found = tommy_hashdyn_search(&hashset, hash_compare, hash->hash, hash32); + if (found) { + ++count; + size += found->file->size; + log_tag("dup:%s:%s:%s:%s:%" PRIu64 ": dup\n", disk->name, esc_tag(file->sub, esc_buffer), found->disk->name, esc_tag(found->file->sub, esc_buffer_alt), found->file->size); + printf("%12" PRIu64 " %s = %s\n", file->size, fmt_term(disk, file->sub, esc_buffer), fmt_term(found->disk, found->file->sub, esc_buffer_alt)); + hash_free(hash); + } else { + tommy_hashdyn_insert(&hashset, &hash->node, hash, hash32); + } + } + } + + tommy_hashdyn_foreach(&hashset, (tommy_foreach_func*)hash_free); + tommy_hashdyn_done(&hashset); + + msg_status("\n"); + msg_status("%8u duplicates, for %" PRIu64 " GB\n", count, size / GIGA); + if (count) + msg_status("There are duplicates!\n"); + else + msg_status("No duplicates\n"); + + log_tag("summary:dup_count:%u\n", count); + log_tag("summary:dup_size:%" PRIu64 "\n", size); + if (count == 0) { + log_tag("summary:exit:unique\n"); + } else { + log_tag("summary:exit:dup\n"); + } + log_flush(); +} + diff --git a/cmdline/elem.c b/cmdline/elem.c new file mode 100644 index 0000000..a597c07 --- /dev/null +++ b/cmdline/elem.c @@ -0,0 +1,1461 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "elem.h" +#include "support.h" +#include "util.h" + +/****************************************************************************/ +/* snapraid */ + +int BLOCK_HASH_SIZE = HASH_MAX; + +struct snapraid_content* content_alloc(const char* path, uint64_t dev) +{ + struct snapraid_content* content; + + content = malloc_nofail(sizeof(struct snapraid_content)); + pathimport(content->content, sizeof(content->content), path); + content->device = dev; + + return content; +} + +void content_free(struct snapraid_content* content) +{ + free(content); +} + +struct snapraid_filter* filter_alloc_file(int direction, const char* pattern) +{ + struct snapraid_filter* filter; + char* i; + char* first; + char* last; + int token_is_valid; + int token_is_filled; + + filter = malloc_nofail(sizeof(struct snapraid_filter)); + pathimport(filter->pattern, sizeof(filter->pattern), pattern); + filter->direction = direction; + + /* find first and last slash */ + first = 0; + last = 0; + /* reject invalid tokens, like "", ".", ".." and more dots */ + token_is_valid = 0; + token_is_filled = 0; + for (i = filter->pattern; *i; ++i) { + if (*i == '/') { + /* reject invalid tokens, but accept an empty one as first */ + if (!token_is_valid && (first != 0 || token_is_filled)) { + free(filter); + return 0; + } + token_is_valid = 0; + token_is_filled = 0; + + /* update slash position */ + if (!first) + first = i; + last = i; + } else if (*i != '.') { + token_is_valid = 1; + token_is_filled = 1; + } else { + token_is_filled = 1; + } + } + + /* reject invalid tokens, but accept an empty one as last, but not if it's the only one */ + if (!token_is_valid && (first == 0 || token_is_filled)) { + free(filter); + return 0; + } + + /* it's a file filter */ + filter->is_disk = 0; + + if (first == 0) { + /* no slash */ + filter->is_path = 0; + filter->is_dir = 0; + } else if (first == last && last[1] == 0) { + /* one slash at the end */ + filter->is_path = 0; + filter->is_dir = 1; + last[0] = 0; + } else { + /* at least a slash not at the end */ + filter->is_path = 1; + if (last[1] == 0) { + filter->is_dir = 1; + last[0] = 0; + } else { + filter->is_dir = 0; + } + + /* a slash must be the first char, as we don't support PATH/FILE and PATH/DIR/ */ + if (filter->pattern[0] != '/') { + free(filter); + return 0; + } + } + + return filter; +} + +struct snapraid_filter* filter_alloc_disk(int direction, const char* pattern) +{ + struct snapraid_filter* filter; + + filter = malloc_nofail(sizeof(struct snapraid_filter)); + pathimport(filter->pattern, sizeof(filter->pattern), pattern); + filter->direction = direction; + + /* it's a disk filter */ + filter->is_disk = 1; + filter->is_path = 0; + filter->is_dir = 0; + + /* no slash allowed in disk names */ + if (strchr(filter->pattern, '/') != 0) { + /* LCOV_EXCL_START */ + free(filter); + return 0; + /* LCOV_EXCL_STOP */ + } + + return filter; +} + +void filter_free(struct snapraid_filter* filter) +{ + free(filter); +} + +const char* filter_type(struct snapraid_filter* filter, char* out, size_t out_size) +{ + const char* direction; + + if (filter->direction < 0) + direction = "exclude"; + else + direction = "include"; + + if (filter->is_disk) + pathprint(out, out_size, "%s %s:", direction, filter->pattern); + else if (filter->is_dir) + pathprint(out, out_size, "%s %s/", direction, filter->pattern); + else + pathprint(out, out_size, "%s %s", direction, filter->pattern); + + return out; +} + +static int filter_apply(struct snapraid_filter* filter, struct snapraid_filter** reason, const char* path, const char* name, int is_dir) +{ + int ret = 0; + + /* match dirs with dirs and files with files */ + if (filter->is_dir && !is_dir) + return 0; + if (!filter->is_dir && is_dir) + return 0; + + if (filter->is_path) { + /* skip initial slash, as always missing from the path */ + if (fnmatch(filter->pattern + 1, path, FNM_PATHNAME | FNM_CASEINSENSITIVE_FOR_WIN) == 0) + ret = filter->direction; + } else { + if (fnmatch(filter->pattern, name, FNM_CASEINSENSITIVE_FOR_WIN) == 0) + ret = filter->direction; + } + + if (reason != 0 && ret < 0) + *reason = filter; + + return ret; +} + +static int filter_recurse(struct snapraid_filter* filter, struct snapraid_filter** reason, const char* const_path, int is_dir) +{ + char path[PATH_MAX]; + char* name; + unsigned i; + + pathcpy(path, sizeof(path), const_path); + + /* filter for all the directories */ + name = path; + for (i = 0; path[i] != 0; ++i) { + if (path[i] == '/') { + /* set a terminator */ + path[i] = 0; + + /* filter the directory */ + if (filter_apply(filter, reason, path, name, 1) != 0) + return filter->direction; + + /* restore the slash */ + path[i] = '/'; + + /* next name */ + name = path + i + 1; + } + } + + /* filter the final file */ + if (filter_apply(filter, reason, path, name, is_dir) != 0) + return filter->direction; + + return 0; +} + +static int filter_element(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub, int is_dir, int is_def_include) +{ + tommy_node* i; + + int direction = 1; /* by default include all */ + + /* for each filter */ + for (i = tommy_list_head(filterlist); i != 0; i = i->next) { + int ret; + struct snapraid_filter* filter = i->data; + + if (filter->is_disk) { + if (fnmatch(filter->pattern, disk, FNM_CASEINSENSITIVE_FOR_WIN) == 0) + ret = filter->direction; + else + ret = 0; + if (reason != 0 && ret < 0) + *reason = filter; + } else { + ret = filter_recurse(filter, reason, sub, is_dir); + } + + if (ret > 0) { + /* include the file */ + return 0; + } else if (ret < 0) { + /* exclude the file */ + return -1; + } else { + /* default is opposite of the last filter */ + direction = -filter->direction; + if (reason != 0 && direction < 0) + *reason = filter; + /* continue with the next one */ + } + } + + /* directories are always included by default, otherwise we cannot apply rules */ + /* to the contained files */ + if (is_def_include) + return 0; + + /* files are excluded/included depending of the last rule processed */ + if (direction < 0) + return -1; + + return 0; +} + +int filter_path(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub) +{ + return filter_element(filterlist, reason, disk, sub, 0, 0); +} + +int filter_subdir(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub) +{ + return filter_element(filterlist, reason, disk, sub, 1, 1); +} + +int filter_emptydir(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub) +{ + return filter_element(filterlist, reason, disk, sub, 1, 0); +} + +int filter_existence(int filter_missing, const char* dir, const char* sub) +{ + char path[PATH_MAX]; + struct stat st; + + if (!filter_missing) + return 0; + + /* we directly check if in the disk the file is present or not */ + pathprint(path, sizeof(path), "%s%s", dir, sub); + + if (lstat(path, &st) != 0) { + /* if the file doesn't exist, we don't filter it out */ + if (errno == ENOENT) + return 0; + /* LCOV_EXCL_START */ + log_fatal("Error in stat file '%s'. %s.\n", path, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* the file is present, so we filter it out */ + return 1; +} + +int filter_correctness(int filter_error, tommy_arrayblkof* infoarr, struct snapraid_disk* disk, struct snapraid_file* file) +{ + unsigned i; + + if (!filter_error) + return 0; + + /* check each block of the file */ + for (i = 0; i < file->blockmax; ++i) { + block_off_t parity_pos = fs_file2par_get(disk, file, i); + snapraid_info info = info_get(infoarr, parity_pos); + + /* if the file has a bad block, don't exclude it */ + if (info_get_bad(info)) + return 0; + } + + /* the file is correct, so we filter it out */ + return 1; +} + +int filter_content(tommy_list* contentlist, const char* path) +{ + tommy_node* i; + + for (i = tommy_list_head(contentlist); i != 0; i = i->next) { + struct snapraid_content* content = i->data; + char tmp[PATH_MAX]; + + if (pathcmp(content->content, path) == 0) + return -1; + + /* exclude also the ".tmp" copy used to save it */ + pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); + if (pathcmp(tmp, path) == 0) + return -1; + + /* exclude also the ".lock" file */ + pathprint(tmp, sizeof(tmp), "%s.lock", content->content); + if (pathcmp(tmp, path) == 0) + return -1; + } + + return 0; +} + +struct snapraid_file* file_alloc(unsigned block_size, const char* sub, data_off_t size, uint64_t mtime_sec, int mtime_nsec, uint64_t inode, uint64_t physical) +{ + struct snapraid_file* file; + block_off_t i; + + file = malloc_nofail(sizeof(struct snapraid_file)); + file->sub = strdup_nofail(sub); + file->size = size; + file->blockmax = (size + block_size - 1) / block_size; + file->mtime_sec = mtime_sec; + file->mtime_nsec = mtime_nsec; + file->inode = inode; + file->physical = physical; + file->flag = 0; + file->blockvec = malloc_nofail(file->blockmax * block_sizeof()); + + for (i = 0; i < file->blockmax; ++i) { + struct snapraid_block* block = file_block(file, i); + block_state_set(block, BLOCK_STATE_CHG); + hash_invalid_set(block->hash); + } + + return file; +} + +struct snapraid_file* file_dup(struct snapraid_file* copy) +{ + struct snapraid_file* file; + block_off_t i; + + file = malloc_nofail(sizeof(struct snapraid_file)); + file->sub = strdup_nofail(copy->sub); + file->size = copy->size; + file->blockmax = copy->blockmax; + file->mtime_sec = copy->mtime_sec; + file->mtime_nsec = copy->mtime_nsec; + file->inode = copy->inode; + file->physical = copy->physical; + file->flag = copy->flag; + file->blockvec = malloc_nofail(file->blockmax * block_sizeof()); + + for (i = 0; i < file->blockmax; ++i) { + struct snapraid_block* block = file_block(file, i); + struct snapraid_block* copy_block = file_block(copy, i); + block->state = copy_block->state; + memcpy(block->hash, copy_block->hash, BLOCK_HASH_SIZE); + } + + return file; +} + +void file_free(struct snapraid_file* file) +{ + free(file->sub); + file->sub = 0; + free(file->blockvec); + file->blockvec = 0; + free(file); +} + +void file_rename(struct snapraid_file* file, const char* sub) +{ + free(file->sub); + file->sub = strdup_nofail(sub); +} + +void file_copy(struct snapraid_file* src_file, struct snapraid_file* dst_file) +{ + block_off_t i; + + if (src_file->size != dst_file->size) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in copy file with different size\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + if (src_file->mtime_sec != dst_file->mtime_sec) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in copy file with different mtime_sec\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + if (src_file->mtime_nsec != dst_file->mtime_nsec) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in copy file with different mtime_nsec\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + for (i = 0; i < dst_file->blockmax; ++i) { + /* set a block with hash computed but without parity */ + block_state_set(file_block(dst_file, i), BLOCK_STATE_REP); + + /* copy the hash */ + memcpy(file_block(dst_file, i)->hash, file_block(src_file, i)->hash, BLOCK_HASH_SIZE); + } + + file_flag_set(dst_file, FILE_IS_COPY); +} + +const char* file_name(const struct snapraid_file* file) +{ + const char* r = strrchr(file->sub, '/'); + + if (!r) + r = file->sub; + else + ++r; + return r; +} + +unsigned file_block_size(struct snapraid_file* file, block_off_t file_pos, unsigned block_size) +{ + /* if it's the last block */ + if (file_pos + 1 == file->blockmax) { + unsigned block_remainder; + if (file->size == 0) + return 0; + block_remainder = file->size % block_size; + if (block_remainder == 0) + block_remainder = block_size; + return block_remainder; + } + + return block_size; +} + +int file_block_is_last(struct snapraid_file* file, block_off_t file_pos) +{ + if (file_pos == 0 && file->blockmax == 0) + return 1; + + if (file_pos >= file->blockmax) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in file block position\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + return file_pos == file->blockmax - 1; +} + +int file_inode_compare_to_arg(const void* void_arg, const void* void_data) +{ + const uint64_t* arg = void_arg; + const struct snapraid_file* file = void_data; + + if (*arg < file->inode) + return -1; + if (*arg > file->inode) + return 1; + return 0; +} + +int file_inode_compare(const void* void_a, const void* void_b) +{ + const struct snapraid_file* file_a = void_a; + const struct snapraid_file* file_b = void_b; + + if (file_a->inode < file_b->inode) + return -1; + if (file_a->inode > file_b->inode) + return 1; + return 0; +} + +int file_path_compare(const void* void_a, const void* void_b) +{ + const struct snapraid_file* file_a = void_a; + const struct snapraid_file* file_b = void_b; + + return strcmp(file_a->sub, file_b->sub); +} + +int file_physical_compare(const void* void_a, const void* void_b) +{ + const struct snapraid_file* file_a = void_a; + const struct snapraid_file* file_b = void_b; + + if (file_a->physical < file_b->physical) + return -1; + if (file_a->physical > file_b->physical) + return 1; + return 0; +} + +int file_path_compare_to_arg(const void* void_arg, const void* void_data) +{ + const char* arg = void_arg; + const struct snapraid_file* file = void_data; + + return strcmp(arg, file->sub); +} + +int file_name_compare(const void* void_a, const void* void_b) +{ + const struct snapraid_file* file_a = void_a; + const struct snapraid_file* file_b = void_b; + const char* name_a = file_name(file_a); + const char* name_b = file_name(file_b); + + return strcmp(name_a, name_b); +} + +int file_stamp_compare(const void* void_a, const void* void_b) +{ + const struct snapraid_file* file_a = void_a; + const struct snapraid_file* file_b = void_b; + + if (file_a->size < file_b->size) + return -1; + if (file_a->size > file_b->size) + return 1; + + if (file_a->mtime_sec < file_b->mtime_sec) + return -1; + if (file_a->mtime_sec > file_b->mtime_sec) + return 1; + + if (file_a->mtime_nsec < file_b->mtime_nsec) + return -1; + if (file_a->mtime_nsec > file_b->mtime_nsec) + return 1; + + return 0; +} + +int file_namestamp_compare(const void* void_a, const void* void_b) +{ + int ret; + + ret = file_name_compare(void_a, void_b); + if (ret != 0) + return ret; + + return file_stamp_compare(void_a, void_b); +} + +int file_pathstamp_compare(const void* void_a, const void* void_b) +{ + int ret; + + ret = file_path_compare(void_a, void_b); + if (ret != 0) + return ret; + + return file_stamp_compare(void_a, void_b); +} + +struct snapraid_extent* extent_alloc(block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos, block_off_t count) +{ + struct snapraid_extent* extent; + + if (count == 0) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency when allocating empty extent for file '%s' at position '%u/%u'\n", file->sub, file_pos, file->blockmax); + os_abort(); + /* LCOV_EXCL_STOP */ + } + if (file_pos + count > file->blockmax) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency when allocating overflowing extent for file '%s' at position '%u:%u/%u'\n", file->sub, file_pos, count, file->blockmax); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + extent = malloc_nofail(sizeof(struct snapraid_extent)); + extent->parity_pos = parity_pos; + extent->file = file; + extent->file_pos = file_pos; + extent->count = count; + + return extent; +} + +void extent_free(struct snapraid_extent* extent) +{ + free(extent); +} + +int extent_parity_compare(const void* void_a, const void* void_b) +{ + const struct snapraid_extent* arg_a = void_a; + const struct snapraid_extent* arg_b = void_b; + + if (arg_a->parity_pos < arg_b->parity_pos) + return -1; + if (arg_a->parity_pos > arg_b->parity_pos) + return 1; + + return 0; +} + +int extent_file_compare(const void* void_a, const void* void_b) +{ + const struct snapraid_extent* arg_a = void_a; + const struct snapraid_extent* arg_b = void_b; + + if (arg_a->file < arg_b->file) + return -1; + if (arg_a->file > arg_b->file) + return 1; + + if (arg_a->file_pos < arg_b->file_pos) + return -1; + if (arg_a->file_pos > arg_b->file_pos) + return 1; + + return 0; +} + +struct snapraid_link* link_alloc(const char* sub, const char* linkto, unsigned link_flag) +{ + struct snapraid_link* slink; + + slink = malloc_nofail(sizeof(struct snapraid_link)); + slink->sub = strdup_nofail(sub); + slink->linkto = strdup_nofail(linkto); + slink->flag = link_flag; + + return slink; +} + +void link_free(struct snapraid_link* slink) +{ + free(slink->sub); + free(slink->linkto); + free(slink); +} + +int link_name_compare_to_arg(const void* void_arg, const void* void_data) +{ + const char* arg = void_arg; + const struct snapraid_link* slink = void_data; + + return strcmp(arg, slink->sub); +} + +int link_alpha_compare(const void* void_a, const void* void_b) +{ + const struct snapraid_link* slink_a = void_a; + const struct snapraid_link* slink_b = void_b; + + return strcmp(slink_a->sub, slink_b->sub); +} + +struct snapraid_dir* dir_alloc(const char* sub) +{ + struct snapraid_dir* dir; + + dir = malloc_nofail(sizeof(struct snapraid_dir)); + dir->sub = strdup_nofail(sub); + dir->flag = 0; + + return dir; +} + +void dir_free(struct snapraid_dir* dir) +{ + free(dir->sub); + free(dir); +} + +int dir_name_compare(const void* void_arg, const void* void_data) +{ + const char* arg = void_arg; + const struct snapraid_dir* dir = void_data; + + return strcmp(arg, dir->sub); +} + +struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev, const char* uuid, int skip) +{ + struct snapraid_disk* disk; + + disk = malloc_nofail(sizeof(struct snapraid_disk)); + pathcpy(disk->name, sizeof(disk->name), name); + pathimport(disk->dir, sizeof(disk->dir), dir); + pathcpy(disk->uuid, sizeof(disk->uuid), uuid); + + /* ensure that the dir terminate with "/" if it isn't empty */ + pathslash(disk->dir, sizeof(disk->dir)); + +#if HAVE_PTHREAD + thread_mutex_init(&disk->fs_mutex, 0); +#endif + + disk->smartctl[0] = 0; + disk->device = dev; + disk->tick = 0; + disk->cached_blocks = 0; + disk->progress_file = 0; + disk->total_blocks = 0; + disk->free_blocks = 0; + disk->first_free_block = 0; + disk->has_volatile_inodes = 0; + disk->has_volatile_hardlinks = 0; + disk->has_unreliable_physical = 0; + disk->has_different_uuid = 0; + disk->has_unsupported_uuid = *uuid == 0; /* empty UUID means unsupported */ + disk->had_empty_uuid = 0; + disk->mapping_idx = -1; + disk->skip_access = skip; + tommy_list_init(&disk->filelist); + tommy_list_init(&disk->deletedlist); + tommy_hashdyn_init(&disk->inodeset); + tommy_hashdyn_init(&disk->pathset); + tommy_hashdyn_init(&disk->stampset); + tommy_list_init(&disk->linklist); + tommy_hashdyn_init(&disk->linkset); + tommy_list_init(&disk->dirlist); + tommy_hashdyn_init(&disk->dirset); + tommy_tree_init(&disk->fs_parity, extent_parity_compare); + tommy_tree_init(&disk->fs_file, extent_file_compare); + disk->fs_last = 0; + + return disk; +} + +void disk_free(struct snapraid_disk* disk) +{ + tommy_list_foreach(&disk->filelist, (tommy_foreach_func*)file_free); + tommy_list_foreach(&disk->deletedlist, (tommy_foreach_func*)file_free); + tommy_tree_foreach(&disk->fs_file, (tommy_foreach_func*)extent_free); + tommy_hashdyn_done(&disk->inodeset); + tommy_hashdyn_done(&disk->pathset); + tommy_hashdyn_done(&disk->stampset); + tommy_list_foreach(&disk->linklist, (tommy_foreach_func*)link_free); + tommy_hashdyn_done(&disk->linkset); + tommy_list_foreach(&disk->dirlist, (tommy_foreach_func*)dir_free); + tommy_hashdyn_done(&disk->dirset); + +#if HAVE_PTHREAD + thread_mutex_destroy(&disk->fs_mutex); +#endif + + free(disk); +} + +static inline void fs_lock(struct snapraid_disk* disk) +{ +#if HAVE_PTHREAD + thread_mutex_lock(&disk->fs_mutex); +#else + (void)disk; +#endif +} + +static inline void fs_unlock(struct snapraid_disk* disk) +{ +#if HAVE_PTHREAD + thread_mutex_unlock(&disk->fs_mutex); +#else + (void)disk; +#endif +} + +struct extent_disk_empty { + block_off_t blockmax; +}; + +/** + * Compare the extent if inside the specified blockmax. + */ +static int extent_disk_empty_compare_unlock(const void* void_a, const void* void_b) +{ + const struct extent_disk_empty* arg_a = void_a; + const struct snapraid_extent* arg_b = void_b; + + /* if the block is inside the specified blockmax, it's found */ + if (arg_a->blockmax > arg_b->parity_pos) + return 0; + + /* otherwise search for a smaller one */ + return -1; +} + +int fs_is_empty(struct snapraid_disk* disk, block_off_t blockmax) +{ + struct extent_disk_empty arg = { blockmax }; + + /* if there is an element, it's not empty */ + /* even if links and dirs have no block allocation */ + if (!tommy_list_empty(&disk->filelist)) + return 0; + if (!tommy_list_empty(&disk->linklist)) + return 0; + if (!tommy_list_empty(&disk->dirlist)) + return 0; + + fs_lock(disk); + + /* search for any extent inside blockmax */ + if (tommy_tree_search_compare(&disk->fs_parity, extent_disk_empty_compare_unlock, &arg) != 0) { + fs_unlock(disk); + return 0; + } + + /* finally, it's empty */ + fs_unlock(disk); + return 1; +} + +struct extent_disk_size { + block_off_t size; +}; + +/** + * Compare the extent by highest parity position. + * + * The maximum parity position is stored as size. + */ +static int extent_disk_size_compare_unlock(const void* void_a, const void* void_b) +{ + struct extent_disk_size* arg_a = (void*)void_a; + const struct snapraid_extent* arg_b = void_b; + + /* get the maximum size */ + if (arg_a->size < arg_b->parity_pos + arg_b->count) + arg_a->size = arg_b->parity_pos + arg_b->count; + + /* search always for a bigger one */ + return 1; +} + +block_off_t fs_size(struct snapraid_disk* disk) +{ + struct extent_disk_size arg = { 0 }; + + fs_lock(disk); + + tommy_tree_search_compare(&disk->fs_parity, extent_disk_size_compare_unlock, &arg); + + fs_unlock(disk); + + return arg.size; +} + +struct extent_check { + const struct snapraid_extent* prev; + int result; +}; + +static void extent_parity_check_foreach_unlock(void* void_arg, void* void_obj) +{ + struct extent_check* arg = void_arg; + const struct snapraid_extent* obj = void_obj; + const struct snapraid_extent* prev = arg->prev; + + /* set the next previous block */ + arg->prev = obj; + + /* stop reporting if too many errors */ + if (arg->result > 100) { + /* LCOV_EXCL_START */ + return; + /* LCOV_EXCL_STOP */ + } + + if (obj->count == 0) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in parity count zero for file '%s' at '%u'\n", + obj->file->sub, obj->parity_pos); + ++arg->result; + return; + /* LCOV_EXCL_STOP */ + } + + /* check only if there is a previous block */ + if (!prev) + return; + + /* check the order */ + if (prev->parity_pos >= obj->parity_pos) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in parity order for files '%s' at '%u:%u' and '%s' at '%u:%u'\n", + prev->file->sub, prev->parity_pos, prev->count, obj->file->sub, obj->parity_pos, obj->count); + ++arg->result; + return; + /* LCOV_EXCL_STOP */ + } + + /* check that the extents don't overlap */ + if (prev->parity_pos + prev->count > obj->parity_pos) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency for parity overlap for files '%s' at '%u:%u' and '%s' at '%u:%u'\n", + prev->file->sub, prev->parity_pos, prev->count, obj->file->sub, obj->parity_pos, obj->count); + ++arg->result; + return; + /* LCOV_EXCL_STOP */ + } +} + +static void extent_file_check_foreach_unlock(void* void_arg, void* void_obj) +{ + struct extent_check* arg = void_arg; + const struct snapraid_extent* obj = void_obj; + const struct snapraid_extent* prev = arg->prev; + + /* set the next previous block */ + arg->prev = obj; + + /* stop reporting if too many errors */ + if (arg->result > 100) { + /* LCOV_EXCL_START */ + return; + /* LCOV_EXCL_STOP */ + } + + if (obj->count == 0) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in file count zero for file '%s' at '%u'\n", + obj->file->sub, obj->file_pos); + ++arg->result; + return; + /* LCOV_EXCL_STOP */ + } + + /* note that for deleted files, some extents may be missing */ + + /* if the files are different */ + if (!prev || prev->file != obj->file) { + if (prev != 0) { + if (file_flag_has(prev->file, FILE_IS_DELETED)) { + /* check that the extent doesn't overflow the file */ + if (prev->file_pos + prev->count > prev->file->blockmax) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in delete end for file '%s' at '%u:%u' overflowing size '%u'\n", + prev->file->sub, prev->file_pos, prev->count, prev->file->blockmax); + ++arg->result; + return; + /* LCOV_EXCL_STOP */ + } + } else { + /* check that the extent ends the file */ + if (prev->file_pos + prev->count != prev->file->blockmax) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in file end for file '%s' at '%u:%u' instead of size '%u'\n", + prev->file->sub, prev->file_pos, prev->count, prev->file->blockmax); + ++arg->result; + return; + /* LCOV_EXCL_STOP */ + } + } + } + + if (file_flag_has(obj->file, FILE_IS_DELETED)) { + /* check that the extent doesn't overflow the file */ + if (obj->file_pos + obj->count > obj->file->blockmax) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in delete start for file '%s' at '%u:%u' overflowing size '%u'\n", + obj->file->sub, obj->file_pos, obj->count, obj->file->blockmax); + ++arg->result; + return; + /* LCOV_EXCL_STOP */ + } + } else { + /* check that the extent starts the file */ + if (obj->file_pos != 0) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in file start for file '%s' at '%u:%u'\n", + obj->file->sub, obj->file_pos, obj->count); + ++arg->result; + return; + /* LCOV_EXCL_STOP */ + } + } + } else { + /* check the order */ + if (prev->file_pos >= obj->file_pos) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in file order for file '%s' at '%u:%u' and at '%u:%u'\n", + prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count); + ++arg->result; + return; + /* LCOV_EXCL_STOP */ + } + + if (file_flag_has(obj->file, FILE_IS_DELETED)) { + /* check that the extents don't overlap */ + if (prev->file_pos + prev->count > obj->file_pos) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in delete sequence for file '%s' at '%u:%u' and at '%u:%u'\n", + prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count); + ++arg->result; + return; + /* LCOV_EXCL_STOP */ + } + } else { + /* check that the extents are sequential */ + if (prev->file_pos + prev->count != obj->file_pos) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in file sequence for file '%s' at '%u:%u' and at '%u:%u'\n", + prev->file->sub, prev->file_pos, prev->count, obj->file_pos, obj->count); + ++arg->result; + return; + /* LCOV_EXCL_STOP */ + } + } + } +} + +int fs_check(struct snapraid_disk* disk) +{ + struct extent_check arg; + + /* error count starts from 0 */ + arg.result = 0; + + fs_lock(disk); + + /* check parity sequence */ + arg.prev = 0; + tommy_tree_foreach_arg(&disk->fs_parity, extent_parity_check_foreach_unlock, &arg); + + /* check file sequence */ + arg.prev = 0; + tommy_tree_foreach_arg(&disk->fs_file, extent_file_check_foreach_unlock, &arg); + + fs_unlock(disk); + + if (arg.result != 0) + return -1; + + return 0; +} + +struct extent_parity_inside { + block_off_t parity_pos; +}; + +/** + * Compare the extent if containing the specified parity position. + */ +static int extent_parity_inside_compare_unlock(const void* void_a, const void* void_b) +{ + const struct extent_parity_inside* arg_a = void_a; + const struct snapraid_extent* arg_b = void_b; + + if (arg_a->parity_pos < arg_b->parity_pos) + return -1; + if (arg_a->parity_pos >= arg_b->parity_pos + arg_b->count) + return 1; + + return 0; +} + +/** + * Search the extent at the specified parity position. + * The search is optimized for sequential accesses. + * \return If not found return 0 + */ +static struct snapraid_extent* fs_par2extent_get_unlock(struct snapraid_disk* disk, struct snapraid_extent** fs_last, block_off_t parity_pos) +{ + struct snapraid_extent* extent; + + /* check if the last accessed extent matches */ + if (*fs_last + && parity_pos >= (*fs_last)->parity_pos + && parity_pos < (*fs_last)->parity_pos + (*fs_last)->count + ) { + extent = *fs_last; + } else { + struct extent_parity_inside arg = { parity_pos }; + extent = tommy_tree_search_compare(&disk->fs_parity, extent_parity_inside_compare_unlock, &arg); + } + + if (!extent) + return 0; + + /* store the last accessed extent */ + *fs_last = extent; + + return extent; +} + +struct extent_file_inside { + struct snapraid_file* file; + block_off_t file_pos; +}; + +/** + * Compare the extent if containing the specified file position. + */ +static int extent_file_inside_compare_unlock(const void* void_a, const void* void_b) +{ + const struct extent_file_inside* arg_a = void_a; + const struct snapraid_extent* arg_b = void_b; + + if (arg_a->file < arg_b->file) + return -1; + if (arg_a->file > arg_b->file) + return 1; + + if (arg_a->file_pos < arg_b->file_pos) + return -1; + if (arg_a->file_pos >= arg_b->file_pos + arg_b->count) + return 1; + + return 0; +} + +/** + * Search the extent at the specified file position. + * The search is optimized for sequential accesses. + * \return If not found return 0 + */ +static struct snapraid_extent* fs_file2extent_get_unlock(struct snapraid_disk* disk, struct snapraid_extent** fs_last, struct snapraid_file* file, block_off_t file_pos) +{ + struct snapraid_extent* extent; + + /* check if the last accessed extent matches */ + if (*fs_last + && file == (*fs_last)->file + && file_pos >= (*fs_last)->file_pos + && file_pos < (*fs_last)->file_pos + (*fs_last)->count + ) { + extent = *fs_last; + } else { + struct extent_file_inside arg = { file, file_pos }; + extent = tommy_tree_search_compare(&disk->fs_file, extent_file_inside_compare_unlock, &arg); + } + + if (!extent) + return 0; + + /* store the last accessed extent */ + *fs_last = extent; + + return extent; +} + +struct snapraid_file* fs_par2file_find(struct snapraid_disk* disk, block_off_t parity_pos, block_off_t* file_pos) +{ + struct snapraid_extent* extent; + struct snapraid_file* file; + + fs_lock(disk); + + extent = fs_par2extent_get_unlock(disk, &disk->fs_last, parity_pos); + + if (!extent) { + fs_unlock(disk); + return 0; + } + + if (file_pos) + *file_pos = extent->file_pos + (parity_pos - extent->parity_pos); + + file = extent->file; + + fs_unlock(disk); + return file; +} + +block_off_t fs_file2par_find(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos) +{ + struct snapraid_extent* extent; + block_off_t ret; + + fs_lock(disk); + + extent = fs_file2extent_get_unlock(disk, &disk->fs_last, file, file_pos); + if (!extent) { + fs_unlock(disk); + return POS_NULL; + } + + ret = extent->parity_pos + (file_pos - extent->file_pos); + + fs_unlock(disk); + return ret; +} + +void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos) +{ + struct snapraid_extent* extent; + struct snapraid_extent* parity_extent; + struct snapraid_extent* file_extent; + + fs_lock(disk); + + if (file_pos > 0) { + /* search an existing extent for the previous file_pos */ + extent = fs_file2extent_get_unlock(disk, &disk->fs_last, file, file_pos - 1); + + if (extent != 0 && parity_pos == extent->parity_pos + extent->count) { + /* ensure that we are extending the extent at the end */ + if (file_pos != extent->file_pos + extent->count) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency when allocating file '%s' at position '%u/%u' in the middle of extent '%u:%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, extent->file_pos, extent->count, disk->name); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* extend the existing extent */ + ++extent->count; + + fs_unlock(disk); + return; + } + } + + /* a extent doesn't exist, and we have to create a new one */ + extent = extent_alloc(parity_pos, file, file_pos, 1); + + /* insert the extent in the trees */ + parity_extent = tommy_tree_insert(&disk->fs_parity, &extent->parity_node, extent); + file_extent = tommy_tree_insert(&disk->fs_file, &extent->file_node, extent); + + if (parity_extent != extent || file_extent != extent) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency when allocating file '%s' at position '%u/%u' for existing extent '%u:%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, extent->file_pos, extent->count, disk->name); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* store the last accessed extent */ + disk->fs_last = extent; + + fs_unlock(disk); +} + +void fs_deallocate(struct snapraid_disk* disk, block_off_t parity_pos) +{ + struct snapraid_extent* extent; + struct snapraid_extent* second_extent; + struct snapraid_extent* parity_extent; + struct snapraid_extent* file_extent; + block_off_t first_count, second_count; + + fs_lock(disk); + + extent = fs_par2extent_get_unlock(disk, &disk->fs_last, parity_pos); + if (!extent) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency when deallocating parity position '%u' for not existing extent in disk '%s'\n", parity_pos, disk->name); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* if it's the only block of the extent, delete it */ + if (extent->count == 1) { + /* remove from the trees */ + tommy_tree_remove(&disk->fs_parity, extent); + tommy_tree_remove(&disk->fs_file, extent); + + /* deallocate */ + extent_free(extent); + + /* clear the last accessed extent */ + disk->fs_last = 0; + + fs_unlock(disk); + return; + } + + /* if it's at the start of the extent, shrink the extent */ + if (parity_pos == extent->parity_pos) { + ++extent->parity_pos; + ++extent->file_pos; + --extent->count; + + fs_unlock(disk); + return; + } + + /* if it's at the end of the extent, shrink the extent */ + if (parity_pos == extent->parity_pos + extent->count - 1) { + --extent->count; + + fs_unlock(disk); + return; + } + + /* otherwise it's in the middle */ + first_count = parity_pos - extent->parity_pos; + second_count = extent->count - first_count - 1; + + /* adjust the first extent */ + extent->count = first_count; + + /* allocate the second extent */ + second_extent = extent_alloc(extent->parity_pos + first_count + 1, extent->file, extent->file_pos + first_count + 1, second_count); + + /* insert the extent in the trees */ + parity_extent = tommy_tree_insert(&disk->fs_parity, &second_extent->parity_node, second_extent); + file_extent = tommy_tree_insert(&disk->fs_file, &second_extent->file_node, second_extent); + + if (parity_extent != second_extent || file_extent != second_extent) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency when deallocating parity position '%u' for splitting extent '%u:%u' in disk '%s'\n", parity_pos, second_extent->file_pos, second_extent->count, disk->name); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* store the last accessed extent */ + disk->fs_last = second_extent; + + fs_unlock(disk); +} + +struct snapraid_block* fs_file2block_get(struct snapraid_file* file, block_off_t file_pos) +{ + if (file_pos >= file->blockmax) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency when dereferencing file '%s' at position '%u/%u'\n", file->sub, file_pos, file->blockmax); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + return file_block(file, file_pos); +} + +struct snapraid_block* fs_par2block_find(struct snapraid_disk* disk, block_off_t parity_pos) +{ + struct snapraid_file* file; + block_off_t file_pos; + + file = fs_par2file_find(disk, parity_pos, &file_pos); + if (file == 0) + return BLOCK_NULL; + + return fs_file2block_get(file, file_pos); +} + +struct snapraid_map* map_alloc(const char* name, unsigned position, block_off_t total_blocks, block_off_t free_blocks, const char* uuid) +{ + struct snapraid_map* map; + + map = malloc_nofail(sizeof(struct snapraid_map)); + pathcpy(map->name, sizeof(map->name), name); + map->position = position; + map->total_blocks = total_blocks; + map->free_blocks = free_blocks; + pathcpy(map->uuid, sizeof(map->uuid), uuid); + + return map; +} + +void map_free(struct snapraid_map* map) +{ + free(map); +} + +int time_compare(const void* void_a, const void* void_b) +{ + const time_t* time_a = void_a; + const time_t* time_b = void_b; + + if (*time_a < *time_b) + return -1; + if (*time_a > *time_b) + return 1; + return 0; +} + +/****************************************************************************/ +/* format */ + +int FMT_MODE = FMT_FILE; + +/** + * Format a file path for poll reference + */ +const char* fmt_poll(const struct snapraid_disk* disk, const char* str, char* buffer) +{ + (void)disk; + return esc_shell(str, buffer); +} + +/** + * Format a path name for terminal reference + */ +const char* fmt_term(const struct snapraid_disk* disk, const char* str, char* buffer) +{ + const char* out[3]; + + switch (FMT_MODE) { + case FMT_FILE : + default : + return esc_shell(str, buffer); + case FMT_DISK : + out[0] = disk->name; + out[1] = ":"; + out[2] = str; + return esc_shell_multi(out, 3, buffer); + case FMT_PATH : + out[0] = disk->dir; + out[1] = str; + return esc_shell_multi(out, 2, buffer); + } +} + diff --git a/cmdline/elem.h b/cmdline/elem.h new file mode 100644 index 0000000..e821e41 --- /dev/null +++ b/cmdline/elem.h @@ -0,0 +1,1234 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#ifndef __ELEM_H +#define __ELEM_H + +#include "util.h" +#include "support.h" +#include "tommyds/tommyhash.h" +#include "tommyds/tommylist.h" +#include "tommyds/tommytree.h" +#include "tommyds/tommyhashdyn.h" +#include "tommyds/tommyarray.h" +#include "tommyds/tommyarrayblkof.h" + +/****************************************************************************/ +/* snapraid */ + +/** + * Number of measures of the operation progress. + */ +#define PROGRESS_MAX 100 + +/** + * Max UUID length. + */ +#define UUID_MAX 128 + +/** + * Invalid position. + */ +#define POS_NULL ((block_off_t)-1) + +/** + * Content file specification. + */ +struct snapraid_content { + char content[PATH_MAX]; /**< Path of the content file. */ + uint64_t device; /**< Device identifier. */ + void* context; /**< Context used for multithread operations. */ + tommy_node node; /**< Next node in the list. */ +}; + +/** + * Filter for paths. + */ +struct snapraid_filter { + char pattern[PATH_MAX]; /**< Filter pattern. */ + int is_disk; /**< If the pattern is a disk one. */ + int is_path; /**< If the pattern is only for the complete path. */ + int is_dir; /**< If the pattern is only for dir. */ + int direction; /**< If it's an inclusion (=1) or an exclusion (=-1). */ + tommy_node node; /**< Next node in the list. */ +}; + +/** + * Block pointer used to represent unused blocks. + */ +#define BLOCK_NULL 0 + +/** + * This block is an empty one. + * Note that an empty block is represent with ::BLOCK_NULL. + */ +#define BLOCK_STATE_EMPTY 0 + +/** + * The block has both the hash and the parity computed. + * This is the normal state of a saved block. + * + * The block hash field IS set. + * The parity for this disk is updated. + */ +#define BLOCK_STATE_BLK 1 + +/** + * The block is new and not yet hashed. + * This happens when a new block overwrite a just removed block, or an empty space. + * + * The block hash field MAY be set and it represents the hash of the OLD data. + * The hash may be also INVALID or ZERO. + * + * If the OLD block was empty, the hash is set to the special ZERO value. + * If the OLD block was lost, the hash is set to the special INVALID value. + * + * The parity for this disk is not updated, but it contains the old data referenced by the hash. + * + * If the state is read from an incomplete sync, we don't really know if the hash is referring at the + * data used to compute the parity, because the sync process was interrupted at an unknown point, + * and the parity may or may not be updated. + * + * For this reason we clear all such hashes when reading the state from an incomplete sync before + * starting a new sync, because sync is affected by such hashes, as sync updates the parity, only + * if the new data read for CHG blocks has a mismatching hash. + * Clearing is done setting the ::clear_past_hash flag before reading the state. + * No clearing is done in other commands, as check and fix are instead able to work with unsynced + * hashes, and scrub ignores CHG/DELETED blocks. + */ +#define BLOCK_STATE_CHG 2 + +/** + * The block is new and hashed. + * This happens when a new block overwrite a just removed block, or an empty space. + * + * Note that when the file copy heuristic is enabled, the REP blocks may be set + * using this heuristic, meaning that the hash may be wrong. + * + * For this reason, when the ::force_nocopy flag is enabled in sync, we convert all the REP blocks + * to CHG, invalidating the stored hash. + * Clearing is done setting the ::clear_past_hash flag before reading the state. + * No clearing is done in other commands, as they don't stop the process like in sync + * when there is a false silent error. + * + * The block hash field IS set, and it represents the hash of the new data. + * The parity for this disk is not updated. + */ +#define BLOCK_STATE_REP 3 + +/** + * This block is a deleted one. + * This happens when a file is deleted. + * + * The block hash field IS set, and it represents the hash of the previous data, + * but only if it's different by all 0. + * The parity for this disk is not updated, but it contains the old data referenced by the hash. + * + * If the state is read from an incomplete sync, we don't really know if the hash is referring at the + * data used to compute the parity, because the sync process was interrupted at an unknown point, + * and the parity may or may not be updated. + * + * A now the sync process is not affected by DELETED hash, so clearing won't be really needed, + * but considering that we have to do it for CHG blocks, we do it also for DELETED ones, + * clearing all the past hashes. + * Clearing is done setting the ::clear_past_hash flag before reading the state. + * No clearing is done in other commands, as check and fix are instead able to work with unsynced + * hashes, and scrub ignores CHG/DELETED blocks. + */ +#define BLOCK_STATE_DELETED 4 + +/** + * Block hash size. + * + * At max HASH_MAX. + */ +extern int BLOCK_HASH_SIZE; + +/** + * Block of a file. + */ +struct snapraid_block { + unsigned char state; /**< State of the block. */ + + /** + * Hash of the block. + * + * The effective stored size is BLOCK_HASH_SIZE. + */ + unsigned char hash[HASH_MAX]; +}; + +/** + * If a file is present in the disk. + * It's used only in scan to detect present and missing files. + */ +#define FILE_IS_PRESENT 0x01 + +/** + * If it's an excluded file from the processing. + * It's used in both check and fix to mark files to exclude from the processing. + */ +#define FILE_IS_EXCLUDED 0x02 + +/** + * If a fix was attempted but it failed. + * It's used only in fix to mark that some data is unrecoverable. + */ +#define FILE_IS_DAMAGED 0x04 + +/** + * If a fix was done. + * It's used only in fix to mark that some data was recovered. + */ +#define FILE_IS_FIXED 0x08 + +/** + * If the file was originally missing, and it was created in the fix process. + * It's used only in fix to mark files recovered from scratch, + * meaning that they don't have any previous content. + * This is important because it means that deleting them, you are not going + * to lose something that cannot be recovered. + * Note that excluded files won't ever get this flag. + */ +#define FILE_IS_CREATED 0x10 + +/** + * If the file has completed its processing, meaning that it won't be opened anymore. + * It's used only in fix to mark when we finish processing one file. + * Note that excluded files won't ever get this flag. + */ +#define FILE_IS_FINISHED 0x20 + +/** + * If the file hash was obtained from a file copy + * identified by the same name, size and stamp. + */ +#define FILE_IS_COPY 0x40 + +/** + * If the file was opened. + * It's used in fix to detect if it's the first time a file is opened. + */ +#define FILE_IS_OPENED 0x80 + +/** + * If the file is modified from the latest sync. + * It's used in fix to store if the state of the file before being modified. + */ +#define FILE_IS_UNSYNCED 0x100 + +/** + * If the file is without inode. + * It could happen in file-system where inodes are not persistent, + * or when restoring a full disk with "fix". + * In such cases we have to clear any stored duplicate inode. + * After the scan process completes, no file should have this flag set. + */ +#define FILE_IS_WITHOUT_INODE 0x200 + +/** + * The file is deleted. + * This happens when a file is deleted from the array, + * but it's keep inside the parity until the next sync. + * + * During the file-system check we needs this information, + * because deleted files may be present only partially. + */ +#define FILE_IS_DELETED 0x400 + +/** + * The file is missing. + * This happens in fix/check when a file is cannot be opened, + * and marking it as such prevents to retry to open it again. + */ +#define FILE_IS_MISSING 0x800 + +#define FILE_IS_HARDLINK 0x1000 /**< If it's an hardlink. */ +#define FILE_IS_SYMLINK 0x2000 /**< If it's a file symlink. */ +#define FILE_IS_SYMDIR 0x4000 /**< If it's a dir symlink for Windows. Not yet supported. */ +#define FILE_IS_JUNCTION 0x8000 /**< If it's a junction for Windows. Not yet supported. */ +#define FILE_IS_LINK_MASK 0xF000 /**< Mask for link type. */ + +/** + * File. + */ +struct snapraid_file { + int64_t mtime_sec; /**< Modification time. */ + uint64_t inode; /**< Inode. */ + uint64_t physical; /**< Physical offset of the file. */ + data_off_t size; /**< Size of the file. */ + struct snapraid_block* blockvec; /**< All the blocks of the file. */ + int mtime_nsec; /**< Modification time nanoseconds. In the range 0 <= x < 1,000,000,000, or STAT_NSEC_INVALID if not present. */ + block_off_t blockmax; /**< Number of blocks. */ + unsigned flag; /**< FILE_IS_* flags. */ + char* sub; /**< Sub path of the file. Without the disk dir. The disk is implicit. */ + + /* nodes for data structures */ + tommy_node nodelist; + tommy_hashdyn_node nodeset; + tommy_hashdyn_node pathset; + tommy_hashdyn_node stampset; +}; + +/** + * Symbolic Link. + */ +struct snapraid_link { + unsigned flag; /**< FILE_IS_* flags. */ + char* sub; /**< Sub path of the file. Without the disk dir. The disk is implicit. */ + char* linkto; /**< Link to. */ + + /* nodes for data structures */ + tommy_node nodelist; + tommy_hashdyn_node nodeset; +}; + +/** + * Dir. + */ +struct snapraid_dir { + unsigned flag; /**< FILE_IS_* flags. */ + char* sub; /**< Sub path of the file. Without the disk dir. The disk is implicit. */ + + /* nodes for data structures */ + tommy_node nodelist; + tommy_hashdyn_node nodeset; +}; + +/** + * Chunk. + * + * A extent represents a fragment of a file mapped into the parity. + */ +struct snapraid_extent { + struct snapraid_file* file; /**< File containing this extent. */ + block_off_t parity_pos; /**< Parity position. */ + block_off_t file_pos; /**< Position in the file. */ + block_off_t count; /**< Number of sequential blocks in the file and parity. */ + tommy_tree_node parity_node; /**< Tree sorted by . */ + tommy_tree_node file_node; /**< Tree sorter by . */ +}; + +/** + * Disk. + */ +struct snapraid_disk { + char name[PATH_MAX]; /**< Name of the disk. */ + char dir[PATH_MAX]; /**< Mount point of the disk. It always terminates with /. */ + char smartctl[PATH_MAX]; /**< Custom command for smartctl. Empty means auto. */ + char uuid[UUID_MAX]; /**< UUID of the disk. */ + + uint64_t device; /**< Device identifier. */ + block_off_t total_blocks; /**< Number of total blocks. */ + block_off_t free_blocks; /**< Number of free blocks at the last sync. */ + + uint64_t tick; /**< Usage time. */ + uint64_t progress_tick[PROGRESS_MAX]; /**< Last ticks of progress. */ + unsigned cached_blocks; /**< Number of IO blocks cached. */ + struct snapraid_file* progress_file; /**< File in progress. */ + + /** + * First free searching block. + * Note that it doesn't necessarily point at the first free block, + * but it just tell you that no free block is present before this position. + */ + block_off_t first_free_block; + + int has_volatile_inodes; /**< If the underline file-system has not persistent inodes. */ + int has_volatile_hardlinks; /**< If the underline file-system has not syncronized metadata for hardlink (NTFS). */ + int has_unreliable_physical; /**< If the physical offset of files has duplicates. */ + int has_different_uuid; /**< If the disk has a different UUID, meaning that it is not the same file-system. */ + int has_unsupported_uuid; /**< If the disk doesn't report UUID, meaning it's not supported. */ + int had_empty_uuid; /**< If the disk had an empty UUID, meaning that it's a new disk. */ + int mapping_idx; /**< Index in the mapping vector. Used only as buffer when writing the content file. */ + int skip_access; /**< If the disk is inaccessible and it should be skipped. */ + +#if HAVE_PTHREAD + /** + * Mutex for protecting the filesystem structure. + * + * Specifically, this protects ::fs_parity, ::fs_file, and ::fs_last, + * meaning that it protects only extents. + * + * Files, links and dirs are not protected as they are not expected to + * change during multithread processing. + */ + pthread_mutex_t fs_mutex; +#endif + + /** + * Mapping of extents in the parity. + * Sorted by and by + */ + tommy_tree fs_parity; + tommy_tree fs_file; + + /** + * Last extent we accessed. + * It's used to optimize access of sequential blocks. + */ + struct snapraid_extent* fs_last; + + /** + * List of all the snapraid_file for the disk. + */ + tommy_list filelist; + + /** + * List of all the deleted file for the disk. + * + * These files are kept allocated, because the blocks are still referenced in + * the ::blockarr. + */ + tommy_list deletedlist; + + tommy_hashdyn inodeset; /**< Hashtable by inode of all the files. */ + tommy_hashdyn pathset; /**< Hashtable by path of all the files. */ + tommy_hashdyn stampset; /**< Hashtable by stamp (size and time) of all the files. */ + tommy_list linklist; /**< List of all the links. */ + tommy_hashdyn linkset; /**< Hashtable by name of all the links. */ + tommy_list dirlist; /**< List of all the empty dirs. */ + tommy_hashdyn dirset; /**< Hashtable by name of all the empty dirs. */ + + /* nodes for data structures */ + tommy_node node; +}; + +/** + * Disk mapping. + */ +struct snapraid_map { + char name[PATH_MAX]; /**< Name of the disk. */ + char uuid[UUID_MAX]; /**< UUID of the disk. Empty if unknown. */ + block_off_t total_blocks; /**< Number of total blocks. */ + block_off_t free_blocks; /**< Number of free blocks at last 'sync'. */ + unsigned position; /**< Position of the disk in the parity. */ + + /* nodes for data structures */ + tommy_node node; +}; + +/** + * Max number of parity split. + */ +#define SPLIT_MAX 8 + +/** + * Invalid parity size. + * + * This value is used to identify new parities, + * like when you alter the configuration adding + * a new parity level, creating it with 'fix'. + * Given that 'fix' doesn't write the content file, + * the new size will be written only at the next + * 'sync'. + */ +#define PARITY_SIZE_INVALID -1LL + +/** + * Parity split. + */ +struct snapraid_split { + char path[PATH_MAX]; /**< Path of the parity file. */ + char uuid[UUID_MAX]; /**< UUID of the disk. Empty if unknown. */ + + /** + * Size of the parity split. + * Only the latest not zero size is allowed to grow. + * If the value is unset, it's PARITY_SIZE_INVALID. + */ + data_off_t size; + + uint64_t device; /**< Device identifier of the parity. */ +}; + +/** + * Parity. + */ +struct snapraid_parity { + struct snapraid_split split_map[SPLIT_MAX]; /**< Parity splits. */ + unsigned split_mac; /**< Number of parity splits. */ + char smartctl[PATH_MAX]; /**< Custom command for smartctl. Empty means auto. */ + block_off_t total_blocks; /**< Number of total blocks. */ + block_off_t free_blocks; /**< Number of free blocks at the last sync. */ + int is_excluded_by_filter; /**< If the parity is excluded by filters. */ + int skip_access; /**< If at least one of the parity disk is inaccessible and it should be skipped. */ + uint64_t tick; /**< Usage time. */ + uint64_t progress_tick[PROGRESS_MAX]; /**< Last cpu ticks of progress. */ + unsigned cached_blocks; /**< Number of IO blocks cached. */ +}; + +/** + * Info. + */ +typedef uint32_t snapraid_info; + +/** + * Allocate a content. + */ +struct snapraid_content* content_alloc(const char* path, uint64_t dev); + +/** + * Deallocate a content. + */ +void content_free(struct snapraid_content* content); + +/** + * Allocate a filter pattern for files and directories. + */ +struct snapraid_filter* filter_alloc_file(int is_include, const char* pattern); + +/** + * Allocate a filter pattern for disks. + */ +struct snapraid_filter* filter_alloc_disk(int is_include, const char* pattern); + +/** + * Deallocate an exclusion. + */ +void filter_free(struct snapraid_filter* filter); + +/** + * Filter type description. + */ +const char* filter_type(struct snapraid_filter* filter, char* out, size_t out_size); + +/** + * Filter hidden files. + * Return !=0 if it matches and it should be excluded. + */ +static inline int filter_hidden(int enable, struct dirent* dd) +{ + if (enable && dirent_hidden(dd)) { + return 1; /* filter out */ + } + + return 0; +} + +/** + * Filter a path using a list of filters. + * For each element of the path all the filters are applied, until the first one that matches. + * Return !=0 if it should be excluded. + */ +int filter_path(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub); + +/** + * Filter a file/link/dir if missing. + * This call imply a disk check for the file presence. + * Return !=0 if the file is present and it should be excluded. + */ +int filter_existence(int filter_missing, const char* dir, const char* sub); + +/** + * Filter a file if bad. + * Return !=0 if the file is correct and it should be excluded. + */ +int filter_correctness(int filter_error, tommy_arrayblkof* infoarr, struct snapraid_disk* disk, struct snapraid_file* file); + +/** + * Filter a dir using a list of filters. + * For each element of the path all the filters are applied, until the first one that matches. + * Thesesdir are always by included by default, to allow to apply rules at the contained files. + * Return !=0 if should be excluded. + */ +int filter_subdir(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub); + +/** + * Filter a dir using a list of filters. + * For each element of the path all the filters are applied, until the first one that matches. + * Return !=0 if should be excluded. + */ +int filter_emptydir(tommy_list* filterlist, struct snapraid_filter** reason, const char* disk, const char* sub); + +/** + * Filter a path if it's a content file. + * Return !=0 if should be excluded. + */ +int filter_content(tommy_list* contentlist, const char* path); + +/** + * Check if the specified hash is invalid. + * + * An invalid hash is represented with all bytes at 0x00. + * + * If working with reduced hash lengths, this function always return 0. + */ +static inline int hash_is_invalid(const unsigned char* hash) +{ + int i; + + /* if the hash is reduced, we cannot grant that it's a specific kind of hash */ + if (BLOCK_HASH_SIZE != HASH_MAX) + return 0; + + for (i = 0; i < BLOCK_HASH_SIZE; ++i) + if (hash[i] != 0x00) + return 0; + + return 1; +} + +/** + * Check if the specified hash represent the zero block. + * + * A zero hash is represented with all bytes at 0xFF. + * + * If working with reduced hash lengths, this function always return 0. + */ +static inline int hash_is_zero(const unsigned char* hash) +{ + int i; + + /* if the hash is reduced, we cannot grant that it's a specific kind of hash */ + if (BLOCK_HASH_SIZE != HASH_MAX) + return 0; + + for (i = 0; i < BLOCK_HASH_SIZE; ++i) + if (hash[i] != 0xFF) + return 0; + + return 1; +} + +/** + * Check if the specified hash is unequivocally representing the data. + * + * If working with reduced hash lengths, this function always return 0. + */ +static inline int hash_is_unique(const unsigned char* hash) +{ + /* if the hash is reduced, we cannot grant that it's a specific kind of hash */ + if (BLOCK_HASH_SIZE != HASH_MAX) + return 0; + + return !hash_is_zero(hash) && !hash_is_invalid(hash); +} + +/** + * Set the hash to the special INVALID value. + */ +static inline void hash_invalid_set(unsigned char* hash) +{ + memset(hash, 0x00, BLOCK_HASH_SIZE); +} + +/** + * Set the hash to the special ZERO value. + */ +static inline void hash_zero_set(unsigned char* hash) +{ + memset(hash, 0xFF, BLOCK_HASH_SIZE); +} + +/** + * Allocated space for block. + */ +static inline size_t block_sizeof(void) +{ + return 1 + BLOCK_HASH_SIZE; +} + +/** + * Get the state of the block. + * + * For this function, it's allowed to pass a NULL block + * pointer than results in the BLOCK_STATE_EMPTY state. + */ +static inline unsigned block_state_get(const struct snapraid_block* block) +{ + if (block == BLOCK_NULL) + return BLOCK_STATE_EMPTY; + + return block->state; +} + +/** + * Set the state of the block. + */ +static inline void block_state_set(struct snapraid_block* block, unsigned state) +{ + block->state = state; +} + +/** + * Check if the specified block has an updated hash. + * + * Note that EMPTY / CHG / DELETED return 0. + */ +static inline int block_has_updated_hash(const struct snapraid_block* block) +{ + unsigned state = block_state_get(block); + + return state == BLOCK_STATE_BLK || state == BLOCK_STATE_REP; +} + +/** + * Check if the specified block has a past hash, + * i.e. the hash of the data that it's now overwritten or lost. + * + * Note that EMPTY / BLK / REP return 0. + */ +static inline int block_has_past_hash(const struct snapraid_block* block) +{ + unsigned state = block_state_get(block); + + return state == BLOCK_STATE_CHG || state == BLOCK_STATE_DELETED; +} + +/** + * Check if the specified block is part of a file. + * + * Note that EMPTY / DELETED return 0. + */ +static inline int block_has_file(const struct snapraid_block* block) +{ + unsigned state = block_state_get(block); + + return state == BLOCK_STATE_BLK + || state == BLOCK_STATE_CHG || state == BLOCK_STATE_REP; +} + +/** + * Check if the block has an invalid parity than needs to be updated. + * + * Note that EMPTY / BLK return 0. + */ +static inline int block_has_invalid_parity(const struct snapraid_block* block) +{ + unsigned state = block_state_get(block); + + return state == BLOCK_STATE_DELETED + || state == BLOCK_STATE_CHG || state == BLOCK_STATE_REP; +} + +/** + * Check if the block is part of a file with valid parity. + * + * Note that anything different than BLK return 0. + */ +static inline int block_has_file_and_valid_parity(const struct snapraid_block* block) +{ + unsigned state = block_state_get(block); + + return state == BLOCK_STATE_BLK; +} + +static inline int file_flag_has(const struct snapraid_file* file, unsigned mask) +{ + return (file->flag & mask) == mask; +} + +static inline void file_flag_set(struct snapraid_file* file, unsigned mask) +{ + file->flag |= mask; +} + +static inline void file_flag_clear(struct snapraid_file* file, unsigned mask) +{ + file->flag &= ~mask; +} + +/** + * Allocate a file. + */ +struct snapraid_file* file_alloc(unsigned block_size, const char* sub, data_off_t size, uint64_t mtime_sec, int mtime_nsec, uint64_t inode, uint64_t physical); + +/** + * Duplicate a file. + */ +struct snapraid_file* file_dup(struct snapraid_file* copy); + +/** + * Deallocate a file. + */ +void file_free(struct snapraid_file* file); + +/** + * Rename a file. + */ +void file_rename(struct snapraid_file* file, const char* sub); + +/** + * Copy a file. + */ +void file_copy(struct snapraid_file* src_file, struct snapraid_file* dest_file); + +/** + * Return the block at the specified position. + * + * Note that the block size if a runtime value. + */ +static inline struct snapraid_block* file_block(struct snapraid_file* file, size_t pos) +{ + unsigned char* ptr = (unsigned char*)file->blockvec; + + return (struct snapraid_block*)(ptr + pos * block_sizeof()); +} + +/** + * Return the name of the file, without the dir. + */ +const char* file_name(const struct snapraid_file* file); + +/** + * Check if the block is the last in the file. + */ +int file_block_is_last(struct snapraid_file* file, block_off_t file_pos); + +/** + * Get the size in bytes of the block. + * If it's the last block of a file it could be less than block_size. + */ +unsigned file_block_size(struct snapraid_file* file, block_off_t file_pos, unsigned block_size); + +/** + * Compare a file with an inode. + */ +int file_inode_compare_to_arg(const void* void_arg, const void* void_data); + +/** + * Compare files by inode. + */ +int file_inode_compare(const void* void_a, const void* void_b); + +/** + * Compare files by path. + */ +int file_path_compare(const void* void_a, const void* void_b); + +/** + * Compare files by physical address. + */ +int file_physical_compare(const void* void_a, const void* void_b); + +/** + * Compute the hash of a file inode. + */ +static inline tommy_uint32_t file_inode_hash(uint64_t inode) +{ + return (tommy_uint32_t)tommy_inthash_u64(inode); +} + +/** + * Compare a file with a path. + */ +int file_path_compare_to_arg(const void* void_arg, const void* void_data); + +/** + * Compare a file with another file for name, stamp, and both. + */ +int file_name_compare(const void* void_a, const void* void_b); +int file_stamp_compare(const void* void_a, const void* void_b); +int file_namestamp_compare(const void* void_a, const void* void_b); +int file_pathstamp_compare(const void* void_a, const void* void_b); + +/** + * Compute the hash of a file path. + */ +static inline tommy_uint32_t file_path_hash(const char* sub) +{ + return tommy_hash_u32(0, sub, strlen(sub)); +} + +/** + * Compute the hash of a file stamp. + */ +static inline tommy_uint32_t file_stamp_hash(data_off_t size, int64_t mtime_sec, int mtime_nsec) +{ + return tommy_inthash_u32((tommy_uint32_t)size ^ tommy_inthash_u32(mtime_sec ^ tommy_inthash_u32(mtime_nsec))); +} + +/** + * Allocate a extent. + */ +struct snapraid_extent* extent_alloc(block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos, block_off_t count); + +/** + * Deallocate a extent. + */ +void extent_free(struct snapraid_extent* extent); + +/** + * Compare extent by parity position. + */ +int extent_parity_compare(const void* void_a, const void* void_b); + +/** + * Compare extent by file and file position. + */ +int extent_file_compare(const void* void_a, const void* void_b); + +static inline int link_flag_has(const struct snapraid_link* slink, unsigned mask) +{ + return (slink->flag & mask) == mask; +} + +static inline void link_flag_set(struct snapraid_link* slink, unsigned mask) +{ + slink->flag |= mask; +} + +static inline void link_flag_clear(struct snapraid_link* slink, unsigned mask) +{ + slink->flag &= ~mask; +} + +static inline void link_flag_let(struct snapraid_link* slink, unsigned flag, unsigned mask) +{ + slink->flag &= ~mask; + slink->flag |= flag & mask; +} + +static inline unsigned link_flag_get(struct snapraid_link* slink, unsigned mask) +{ + return slink->flag & mask; +} + +/** + * Allocate a link. + */ +struct snapraid_link* link_alloc(const char* name, const char* slink, unsigned link_flag); + +/** + * Deallocate a link. + */ +void link_free(struct snapraid_link* slink); + +/** + * Compare a link with a name. + */ +int link_name_compare_to_arg(const void* void_arg, const void* void_data); + +/** + * Compare links by path. + */ +int link_alpha_compare(const void* void_a, const void* void_b); + +/** + * Compute the hash of a link name. + */ +static inline tommy_uint32_t link_name_hash(const char* name) +{ + return tommy_hash_u32(0, name, strlen(name)); +} + +static inline int dir_flag_has(const struct snapraid_dir* dir, unsigned mask) +{ + return (dir->flag & mask) == mask; +} + +static inline void dir_flag_set(struct snapraid_dir* dir, unsigned mask) +{ + dir->flag |= mask; +} + +static inline void dir_flag_clear(struct snapraid_dir* dir, unsigned mask) +{ + dir->flag &= ~mask; +} + +/** + * Allocate a dir. + */ +struct snapraid_dir* dir_alloc(const char* name); + +/** + * Deallocate a dir. + */ +void dir_free(struct snapraid_dir* dir); + +/** + * Compare a dir with a name. + */ +int dir_name_compare(const void* void_arg, const void* void_data); + +/** + * Compute the hash of a dir name. + */ +static inline tommy_uint32_t dir_name_hash(const char* name) +{ + return tommy_hash_u32(0, name, strlen(name)); +} + +/** + * Allocate a disk. + */ +struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev, const char* uuid, int skip); + +/** + * Deallocate a disk. + */ +void disk_free(struct snapraid_disk* disk); + +/** + * Get the size of the disk in blocks. + */ +block_off_t fs_size(struct snapraid_disk* disk); + +/** + * Check if a disk is totally empty and can be discarded from the content file. + * A disk is empty if it doesn't contain any file, symlink, hardlink or dir + * and without any DELETED block. + * The blockmax is used to limit the search of DELETED block up to blockmax. + */ +int fs_is_empty(struct snapraid_disk* disk, block_off_t blockmax); + +/** + * Check the file-system for errors. + * Return 0 if it's OK. + */ +int fs_check(struct snapraid_disk* disk); + +/** + * Allocate a parity position for the specified file position. + * + * After this call you can use the par2file/par2block operations + * to query the relation. + * + * \note This function is NOT thread-safe as it uses the the disk cache. + + */ +void fs_allocate(struct snapraid_disk* disk, block_off_t parity_pos, struct snapraid_file* file, block_off_t file_pos); + +/** + * Deallocate the parity position. + * + * After this call the par2file/par2block operations + * won't find anymore the parity association. + * + * \note This function is NOT thread-safe as it uses the the disk cache. + */ +void fs_deallocate(struct snapraid_disk* disk, block_off_t pos); + +/** + * Get the block from the file position. + */ +struct snapraid_block* fs_file2block_get(struct snapraid_file* file, block_off_t file_pos); + +/** + * Get the file position from the parity position. + * Return 0 if no file is using it. + */ +struct snapraid_file* fs_par2file_find(struct snapraid_disk* disk, block_off_t parity_pos, block_off_t* file_pos); + +/** + * Get the file position from the parity position. + */ +static inline struct snapraid_file* fs_par2file_get(struct snapraid_disk* disk, block_off_t parity_pos, block_off_t* file_pos) +{ + struct snapraid_file* ret; + + ret = fs_par2file_find(disk, parity_pos, file_pos); + if (ret == 0) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency when deresolving parity to file at position '%u' in disk '%s'\n", parity_pos, disk->name); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + return ret; +} + +/** + * Get the parity position from the file position. + * Return POS_NULL if no parity is allocated. + */ +block_off_t fs_file2par_find(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos); + +/** + * Get the parity position from the file position. + */ +static inline block_off_t fs_file2par_get(struct snapraid_disk* disk, struct snapraid_file* file, block_off_t file_pos) +{ + block_off_t ret; + + ret = fs_file2par_find(disk, file, file_pos); + if (ret == POS_NULL) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency when resolving file '%s' at position '%u/%u' in disk '%s'\n", file->sub, file_pos, file->blockmax, disk->name); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + return ret; +} + +/** + * Get the block from the parity position. + * Return BLOCK_NULL==0 if the block is over the end of the disk or not used. + */ +struct snapraid_block* fs_par2block_find(struct snapraid_disk* disk, block_off_t parity_pos); + +/** + * Get the block from the parity position. + */ +static inline struct snapraid_block* fs_par2block_get(struct snapraid_disk* disk, block_off_t parity_pos) +{ + struct snapraid_block* ret; + + ret = fs_par2block_find(disk, parity_pos); + if (ret == BLOCK_NULL) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency when deresolving parity to block at position '%u' in disk '%s'\n", parity_pos, disk->name); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + return ret; +} + +/** + * Allocate a disk mapping. + * Uses uuid="" if not available. + */ +struct snapraid_map* map_alloc(const char* name, unsigned position, block_off_t total_blocks, block_off_t free_blocks, const char* uuid); + +/** + * Deallocate a disk mapping. + */ +void map_free(struct snapraid_map* map); + +/** + * Mask used to store additional information in the info bits. + * + * These bits reduce the granularity of the time in the memory representation. + */ +#define INFO_MASK 0x7 + +/** + * Make an info. + */ +static inline snapraid_info info_make(time_t last_access, int error, int rehash, int justsynced) +{ + /* clear the lowest bits as reserved for other information */ + snapraid_info info = last_access & ~INFO_MASK; + + if (error != 0) + info |= 0x1; + if (rehash != 0) + info |= 0x2; + if (justsynced != 0) + info |= 0x4; + return info; +} + +/** + * Extract the time information. + * This is the last time when the block was know to be correct. + * The "scrubbed" info tells if the time is referreing at the latest sync or scrub. + */ +static inline time_t info_get_time(snapraid_info info) +{ + return info & ~INFO_MASK; +} + +/** + * Extract the error information. + * Report if the block address had some problem. + */ +static inline int info_get_bad(snapraid_info info) +{ + return (info & 0x1) != 0; +} + +/** + * Extract the rehash information. + * Report if the block address is using the old hash and needs to be rehashed. + */ +static inline int info_get_rehash(snapraid_info info) +{ + return (info & 0x2) != 0; +} + +/** + * Extract the scrubbed information. + * Report if the block address was never scrubbed. + */ +static inline int info_get_justsynced(snapraid_info info) +{ + return (info & 0x4) != 0; +} + +/** + * Mark the block address as with error. + */ +static inline snapraid_info info_set_bad(snapraid_info info) +{ + return info | 0x1; +} + +/** + * Mark the block address as with rehash. + */ +static inline snapraid_info info_set_rehash(snapraid_info info) +{ + return info | 0x2; +} + +/** + * Set the info at the specified position. + * The position is allocated if not yet done. + */ +static inline void info_set(tommy_arrayblkof* array, block_off_t pos, snapraid_info info) +{ + tommy_arrayblkof_grow(array, pos + 1); + + memcpy(tommy_arrayblkof_ref(array, pos), &info, sizeof(snapraid_info)); +} + +/** + * Get the info at the specified position. + * For not allocated position, 0 is returned. + */ +static inline snapraid_info info_get(tommy_arrayblkof* array, block_off_t pos) +{ + snapraid_info info; + + if (pos >= tommy_arrayblkof_size(array)) + return 0; + + memcpy(&info, tommy_arrayblkof_ref(array, pos), sizeof(snapraid_info)); + + return info; +} + +/** + * Compare times + */ +int time_compare(const void* void_a, const void* void_b); + +/****************************************************************************/ +/* format */ + +#define FMT_FILE 0 /**< Print only the file. */ +#define FMT_DISK 1 /**< Print the disk name and the file. */ +#define FMT_PATH 2 /**< Print the full path. */ + +extern int FMT_MODE; + +/** + * Format a file path for poll reference + */ +const char* fmt_poll(const struct snapraid_disk* disk, const char* str, char* buffer); + +/** + * Format a path name for terminal reference + */ +const char* fmt_term(const struct snapraid_disk* disk, const char* str, char* buffer); + +#endif + diff --git a/cmdline/fnmatch.c b/cmdline/fnmatch.c new file mode 100644 index 0000000..073f0aa --- /dev/null +++ b/cmdline/fnmatch.c @@ -0,0 +1,500 @@ +/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library 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 . */ + +#if HAVE_CONFIG_H +# include +#endif + +#if !HAVE_FNMATCH + +/* Enable GNU extensions in fnmatch.h. */ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +#include +#if HAVE_FNMATCH_H +#include +#else +#include "fnmatch.h" +#endif +#include + +#if HAVE_STRING_H || defined _LIBC +# include +#else +# include +#endif + +#if defined STDC_HEADERS || defined _LIBC +# include +#endif + +/* For platforms which support the ISO C amendment 1 functionality we + support user defined character classes. */ +#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) +/* Solaris 2.5 has a bug: must be included before . */ +# include +# include +#endif + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined _LIBC || !defined __GNU_LIBRARY__ + + +# if defined STDC_HEADERS || !defined isascii +# define ISASCII(c) 1 +# else +# define ISASCII(c) isascii(c) +# endif + +# ifdef isblank +# define ISBLANK(c) (ISASCII (c) && isblank (c)) +# else +# define ISBLANK(c) ((c) == ' ' || (c) == '\t') +# endif +# ifdef isgraph +# define ISGRAPH(c) (ISASCII (c) && isgraph (c)) +# else +# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) +# endif + +# define ISPRINT(c) (ISASCII (c) && isprint (c)) +# define ISDIGIT(c) (ISASCII (c) && isdigit (c)) +# define ISALNUM(c) (ISASCII (c) && isalnum (c)) +# define ISALPHA(c) (ISASCII (c) && isalpha (c)) +# define ISCNTRL(c) (ISASCII (c) && iscntrl (c)) +# define ISLOWER(c) (ISASCII (c) && islower (c)) +# define ISPUNCT(c) (ISASCII (c) && ispunct (c)) +# define ISSPACE(c) (ISASCII (c) && isspace (c)) +# define ISUPPER(c) (ISASCII (c) && isupper (c)) +# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c)) + +# define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) + +# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) +/* The GNU C library provides support for user-defined character classes + and the functions from ISO C amendment 1. */ +# ifdef CHARCLASS_NAME_MAX +# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX +# else +/* This shouldn't happen but some implementation might still have this + problem. Use a reasonable default value. */ +# define CHAR_CLASS_MAX_LENGTH 256 +# endif + +# ifdef _LIBC +# define IS_CHAR_CLASS(string) __wctype (string) +# else +# define IS_CHAR_CLASS(string) wctype (string) +# endif +# else +# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ + +# define IS_CHAR_CLASS(string) \ + (STREQ (string, "alpha") || STREQ (string, "upper") \ + || STREQ (string, "lower") || STREQ (string, "digit") \ + || STREQ (string, "alnum") || STREQ (string, "xdigit") \ + || STREQ (string, "space") || STREQ (string, "print") \ + || STREQ (string, "punct") || STREQ (string, "graph") \ + || STREQ (string, "cntrl") || STREQ (string, "blank")) +# endif + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +# if !defined _LIBC && !defined getenv +extern char *getenv (); +# endif + +# ifndef errno +extern int errno; +# endif + +/* This function doesn't exist on most systems. */ + +# if !defined HAVE___STRCHRNUL && !defined _LIBC +static char * +__strchrnul (s, c) + const char *s; + int c; +{ + char *result = strchr (s, c); + if (result == NULL) + result = strchr (s, '\0'); + return result; +} +# endif + +# ifndef internal_function +/* Inside GNU libc we mark some function in a special way. In other + environments simply ignore the marking. */ +# define internal_function +# endif + +/* Match STRING against the filename pattern PATTERN, returning zero if + it matches, nonzero if not. */ +static int internal_fnmatch __P ((const char *pattern, const char *string, + int no_leading_period, int flags)) + internal_function; +static int +internal_function +internal_fnmatch (pattern, string, no_leading_period, flags) + const char *pattern; + const char *string; + int no_leading_period; + int flags; +{ + register const char *p = pattern, *n = string; + register unsigned char c; + +/* Note that this evaluates C many times. */ +# ifdef _LIBC +# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c)) +# else +# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c)) +# endif + + while ((c = *p++) != '\0') + { + c = FOLD (c); + + switch (c) + { + case '?': + if (*n == '\0') + return FNM_NOMATCH; + else if (*n == '/' && (flags & FNM_FILE_NAME)) + return FNM_NOMATCH; + else if (*n == '.' && no_leading_period + && (n == string + || (n[-1] == '/' && (flags & FNM_FILE_NAME)))) + return FNM_NOMATCH; + break; + + case '\\': + if (!(flags & FNM_NOESCAPE)) + { + c = *p++; + if (c == '\0') + /* Trailing \ loses. */ + return FNM_NOMATCH; + c = FOLD (c); + } + if (FOLD ((unsigned char) *n) != c) + return FNM_NOMATCH; + break; + + case '*': + if (*n == '.' && no_leading_period + && (n == string + || (n[-1] == '/' && (flags & FNM_FILE_NAME)))) + return FNM_NOMATCH; + + for (c = *p++; c == '?' || c == '*'; c = *p++) + { + if (*n == '/' && (flags & FNM_FILE_NAME)) + /* A slash does not match a wildcard under FNM_FILE_NAME. */ + return FNM_NOMATCH; + else if (c == '?') + { + /* A ? needs to match one character. */ + if (*n == '\0') + /* There isn't another character; no match. */ + return FNM_NOMATCH; + else + /* One character of the string is consumed in matching + this ? wildcard, so *??? won't match if there are + less than three characters. */ + ++n; + } + } + + if (c == '\0') + /* The wildcard(s) is/are the last element of the pattern. + If the name is a file name and contains another slash + this does mean it cannot match. */ + return ((flags & FNM_FILE_NAME) && strchr (n, '/') != NULL + ? FNM_NOMATCH : 0); + else + { + const char *endp; + + endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0'); + + if (c == '[') + { + int flags2 = ((flags & FNM_FILE_NAME) + ? flags : (flags & ~FNM_PERIOD)); + + for (--p; n < endp; ++n) + if (internal_fnmatch (p, n, + (no_leading_period + && (n == string + || (n[-1] == '/' + && (flags + & FNM_FILE_NAME)))), + flags2) + == 0) + return 0; + } + else if (c == '/' && (flags & FNM_FILE_NAME)) + { + while (*n != '\0' && *n != '/') + ++n; + if (*n == '/' + && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD, + flags) == 0)) + return 0; + } + else + { + int flags2 = ((flags & FNM_FILE_NAME) + ? flags : (flags & ~FNM_PERIOD)); + + if (c == '\\' && !(flags & FNM_NOESCAPE)) + c = *p; + c = FOLD (c); + for (--p; n < endp; ++n) + if (FOLD ((unsigned char) *n) == c + && (internal_fnmatch (p, n, + (no_leading_period + && (n == string + || (n[-1] == '/' + && (flags + & FNM_FILE_NAME)))), + flags2) == 0)) + return 0; + } + } + + /* If we come here no match is possible with the wildcard. */ + return FNM_NOMATCH; + + case '[': + { + /* Nonzero if the sense of the character class is inverted. */ + static int posixly_correct; + register int not; + char cold; + + if (posixly_correct == 0) + posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; + + if (*n == '\0') + return FNM_NOMATCH; + + if (*n == '.' && no_leading_period && (n == string + || (n[-1] == '/' + && (flags + & FNM_FILE_NAME)))) + return FNM_NOMATCH; + + if (*n == '/' && (flags & FNM_FILE_NAME)) + /* `/' cannot be matched. */ + return FNM_NOMATCH; + + not = (*p == '!' || (posixly_correct < 0 && *p == '^')); + if (not) + ++p; + + c = *p++; + for (;;) + { + unsigned char fn = FOLD ((unsigned char) *n); + + if (!(flags & FNM_NOESCAPE) && c == '\\') + { + if (*p == '\0') + return FNM_NOMATCH; + c = FOLD ((unsigned char) *p); + ++p; + + if (c == fn) + goto matched; + } + else if (c == '[' && *p == ':') + { + /* Leave room for the null. */ + char str[CHAR_CLASS_MAX_LENGTH + 1]; + size_t c1 = 0; +# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) + wctype_t wt; +# endif + const char *startp = p; + + for (;;) + { + if (c1 == CHAR_CLASS_MAX_LENGTH) + /* The name is too long and therefore the pattern + is ill-formed. */ + return FNM_NOMATCH; + + c = *++p; + if (c == ':' && p[1] == ']') + { + p += 2; + break; + } + if (c < 'a' || c >= 'z') + { + /* This cannot possibly be a character class name. + Match it as a normal range. */ + p = startp; + c = '['; + goto normal_bracket; + } + str[c1++] = c; + } + str[c1] = '\0'; + +# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) + wt = IS_CHAR_CLASS (str); + if (wt == 0) + /* Invalid character class name. */ + return FNM_NOMATCH; + + if (__iswctype (__btowc ((unsigned char) *n), wt)) + goto matched; +# else + if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n)) + || (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n)) + || (STREQ (str, "blank") && ISBLANK ((unsigned char) *n)) + || (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n)) + || (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n)) + || (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n)) + || (STREQ (str, "lower") && ISLOWER ((unsigned char) *n)) + || (STREQ (str, "print") && ISPRINT ((unsigned char) *n)) + || (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n)) + || (STREQ (str, "space") && ISSPACE ((unsigned char) *n)) + || (STREQ (str, "upper") && ISUPPER ((unsigned char) *n)) + || (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n))) + goto matched; +# endif + } + else if (c == '\0') + /* [ (unterminated) loses. */ + return FNM_NOMATCH; + else + { + normal_bracket: + if (FOLD (c) == fn) + goto matched; + + cold = c; + c = *p++; + + if (c == '-' && *p != ']') + { + /* It is a range. */ + unsigned char cend = *p++; + if (!(flags & FNM_NOESCAPE) && cend == '\\') + cend = *p++; + if (cend == '\0') + return FNM_NOMATCH; + + if (cold <= fn && fn <= FOLD (cend)) + goto matched; + + c = *p++; + } + } + + if (c == ']') + break; + } + + if (!not) + return FNM_NOMATCH; + break; + + matched: + /* Skip the rest of the [...] that already matched. */ + while (c != ']') + { + if (c == '\0') + /* [... (unterminated) loses. */ + return FNM_NOMATCH; + + c = *p++; + if (!(flags & FNM_NOESCAPE) && c == '\\') + { + if (*p == '\0') + return FNM_NOMATCH; + /* XXX 1003.2d11 is unclear if this is right. */ + ++p; + } + else if (c == '[' && *p == ':') + { + do + if (*++p == '\0') + return FNM_NOMATCH; + while (*p != ':' || p[1] == ']'); + p += 2; + c = *p; + } + } + if (not) + return FNM_NOMATCH; + } + break; + + default: + if (c != FOLD ((unsigned char) *n)) + return FNM_NOMATCH; + } + + ++n; + } + + if (*n == '\0') + return 0; + + if ((flags & FNM_LEADING_DIR) && *n == '/') + /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ + return 0; + + return FNM_NOMATCH; + +# undef FOLD +} + + +int +fnmatch (pattern, string, flags) + const char *pattern; + const char *string; + int flags; +{ + return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags); +} + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#else + +/* avoid the warning: ISO C forbids an empty translation unit */ +extern int make_iso_compilers_happy; + +#endif + diff --git a/cmdline/fnmatch.h b/cmdline/fnmatch.h new file mode 100644 index 0000000..0348b53 --- /dev/null +++ b/cmdline/fnmatch.h @@ -0,0 +1,82 @@ +/* Copyright (C) 1991, 92, 93, 96, 97, 98, 99 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library 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 . */ + +#ifndef _FNMATCH_H +#define _FNMATCH_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32 +# if !defined __GLIBC__ || !defined __P +# undef __P +# define __P(protos) protos +# endif +#else /* Not C++ or ANSI C. */ +# undef __P +# define __P(protos) () +/* We can get away without defining `const' here only because in this file + it is used only inside the prototype for `fnmatch', which is elided in + non-ANSI C where `const' is problematical. */ +#endif /* C++ or ANSI C. */ + +#ifndef const +# if (defined __STDC__ && __STDC__) || defined __cplusplus +# define __const const +# else +# define __const +# endif +#endif + +/* We #undef these before defining them because some losing systems + (HP-UX A.08.07 for example) define these in . */ +#undef FNM_PATHNAME +#undef FNM_NOESCAPE +#undef FNM_PERIOD + +/* Bits set in the FLAGS argument to `fnmatch'. */ +#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */ +#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */ +#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */ + +#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE +# define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */ +# define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */ +# define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */ +#endif + +/* Value returned by `fnmatch' if STRING does not match PATTERN. */ +#define FNM_NOMATCH 1 + +/* This value is returned if the implementation does not support + `fnmatch'. Since this is not the case here it will never be + returned but the conformance test suites still require the symbol + to be defined. */ +#ifdef _XOPEN_SOURCE +# define FNM_NOSYS (-1) +#endif + +/* Match NAME against the filename pattern PATTERN, + returning zero if it matches, FNM_NOMATCH if not. */ +extern int fnmatch __P ((__const char *__pattern, __const char *__name, + int __flags)); + +#ifdef __cplusplus +} +#endif + +#endif /* fnmatch.h */ diff --git a/cmdline/handle.c b/cmdline/handle.c new file mode 100644 index 0000000..e7fa682 --- /dev/null +++ b/cmdline/handle.c @@ -0,0 +1,403 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "elem.h" +#include "support.h" +#include "handle.h" + +/****************************************************************************/ +/* handle */ + +int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, int mode) +{ + int ret; + int flags; + + /* if it's the same file, and already opened, nothing to do */ + if (handle->file == file && handle->f != -1) { + return 0; + } + + advise_init(&handle->advise, mode); + pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub); + + ret = mkancestor(handle->path); + if (ret != 0) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + + /* initial values, changed later if required */ + handle->created = 0; + + /* flags for opening */ + /* O_BINARY: open as binary file (Windows only) */ + /* O_NOFOLLOW: do not follow links to ensure to open the real file */ + flags = O_BINARY | O_NOFOLLOW | advise_flags(&handle->advise); + + /* open for read write */ + handle->f = open(handle->path, flags | O_RDWR); + + /* if failed for missing write permission */ + if (handle->f == -1 && (errno == EACCES || errno == EROFS)) { + /* open for real-only */ + handle->f = open(handle->path, flags | O_RDONLY); + } + + /* if failed for missing file */ + if (handle->f == -1 && errno == ENOENT) { + char path_from[PATH_MAX]; + + /* check if exists a .unrecoverable copy, and rename to the real one */ + pathprint(path_from, sizeof(path_from), "%s.unrecoverable", handle->path); + + if (rename(path_from, handle->path) == 0) { + /* open for read write */ + handle->f = open(handle->path, flags | O_RDWR); + } else { + /* create it */ + handle->f = open(handle->path, flags | O_RDWR | O_CREAT, 0600); + if (handle->f != -1) { + /* mark it as created if really done */ + handle->created = 1; + } + } + } + + if (handle->f == -1) { + /* LCOV_EXCL_START */ + /* invalidate for error */ + handle->file = 0; + handle->f = -1; + handle->valid_size = 0; + + log_fatal("Error opening file '%s'. %s.\n", handle->path, strerror(errno)); + return -1; + /* LCOV_EXCL_STOP */ + } + + /* just opened */ + handle->file = file; + + /* get the stat info */ + ret = fstat(handle->f, &handle->st); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error accessing file '%s'. %s.\n", handle->path, strerror(errno)); + return -1; + /* LCOV_EXCL_STOP */ + } + + /* get the size of the existing data */ + handle->valid_size = handle->st.st_size; + + ret = advise_open(&handle->advise, handle->f); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error advising file '%s'. %s.\n", handle->path, strerror(errno)); + return -1; + /* LCOV_EXCL_STOP */ + } + + return 0; +} + +int handle_truncate(struct snapraid_handle* handle, struct snapraid_file* file) +{ + int ret; + + ret = ftruncate(handle->f, file->size); + if (ret != 0) { + /* LCOV_EXCL_START */ + if (errno == EACCES) { + log_fatal("Failed to truncate file '%s' for missing write permission.\n", handle->path); + } else { + log_fatal("Error truncating file '%s'. %s.\n", handle->path, strerror(errno)); + } + return -1; + /* LCOV_EXCL_STOP */ + } + + /* adjust the size to the truncated size */ + handle->valid_size = file->size; + + return 0; +} + +int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int mode, fptr* out, fptr* out_missing) +{ + int ret; + int flags; + + if (!out_missing) + out_missing = out; + + /* if already opened, nothing to do */ + if (handle->file == file && handle->file != 0 && handle->f != -1) { + return 0; + } + + advise_init(&handle->advise, mode); + pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub); + + /* for sure not created */ + handle->created = 0; + + /* flags for opening */ + /* O_BINARY: open as binary file (Windows only) */ + /* O_NOFOLLOW: do not follow links to ensure to open the real file */ + flags = O_BINARY | O_NOFOLLOW | advise_flags(&handle->advise); + + /* open for read */ + handle->f = open_noatime(handle->path, flags | O_RDONLY); + if (handle->f == -1) { + /* invalidate for error */ + handle->file = 0; + handle->f = -1; + handle->valid_size = 0; + + if (errno == ENOENT) + out_missing("Missing file '%s'.\n", handle->path); + else + out("Error opening file '%s'. %s.\n", handle->path, strerror(errno)); + return -1; + } + + /* just opened */ + handle->file = file; + + /* get the stat info */ + ret = fstat(handle->f, &handle->st); + if (ret != 0) { + /* LCOV_EXCL_START */ + out("Error accessing file '%s'. %s.\n", handle->path, strerror(errno)); + return -1; + /* LCOV_EXCL_STOP */ + } + + /* get the size of the existing data */ + handle->valid_size = handle->st.st_size; + + ret = advise_open(&handle->advise, handle->f); + if (ret != 0) { + /* LCOV_EXCL_START */ + out("Error advising file '%s'. %s.\n", handle->path, strerror(errno)); + return -1; + /* LCOV_EXCL_STOP */ + } + + return 0; +} + +int handle_close(struct snapraid_handle* handle) +{ + int ret; + + /* close if open */ + if (handle->f != -1) { + ret = close(handle->f); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error closing file '%s'. %s.\n", handle->file->sub, strerror(errno)); + + /* invalidate for error */ + handle->file = 0; + handle->f = -1; + handle->valid_size = 0; + return -1; + /* LCOV_EXCL_STOP */ + } + } + + /* reset the descriptor */ + handle->file = 0; + handle->f = -1; + handle->valid_size = 0; + + return 0; +} + +int handle_read(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size, fptr* out, fptr* out_missing) +{ + ssize_t read_ret; + data_off_t offset; + unsigned read_size; + unsigned count; + int ret; + + offset = file_pos * (data_off_t)block_size; + + if (!out_missing) + out_missing = out; + + /* check if we are going to read only not initialized data */ + if (offset >= handle->valid_size) { + /* if the file is missing, it's at 0 size, or it's rebuilt while reading */ + if (offset == handle->valid_size || handle->valid_size == 0) + out_missing("Reading data from missing file '%s' at offset %" PRIu64 ".\n", handle->path, offset); + else + out("Reading missing data from file '%s' at offset %" PRIu64 ".\n", handle->path, offset); + return -1; + } + + read_size = file_block_size(handle->file, file_pos, block_size); + + count = 0; + do { + /* read the full block to support O_DIRECT */ + read_ret = pread(handle->f, block_buffer + count, block_size - count, offset + count); + if (read_ret < 0) { + /* LCOV_EXCL_START */ + out("Error reading file '%s' at offset %" PRIu64 " for size %u. %s.\n", handle->path, offset + count, block_size - count, strerror(errno)); + return -1; + /* LCOV_EXCL_STOP */ + } + if (read_ret == 0) { + out("Unexpected end of file '%s' at offset %" PRIu64 ". %s.\n", handle->path, offset, strerror(errno)); + return -1; + } + + count += read_ret; + } while (count < read_size); + + /* pad with 0 */ + if (read_size < block_size) { + memset(block_buffer + read_size, 0, block_size - read_size); + } + + ret = advise_read(&handle->advise, handle->f, offset, block_size); + if (ret != 0) { + /* LCOV_EXCL_START */ + out("Error advising file '%s'. %s.\n", handle->path, strerror(errno)); + return -1; + /* LCOV_EXCL_STOP */ + } + + return read_size; +} + +int handle_write(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size) +{ + ssize_t write_ret; + data_off_t offset; + unsigned write_size; + int ret; + + offset = file_pos * (data_off_t)block_size; + + write_size = file_block_size(handle->file, file_pos, block_size); + + write_ret = pwrite(handle->f, block_buffer, write_size, offset); + if (write_ret != (ssize_t)write_size) { /* conversion is safe because block_size is always small */ + /* LCOV_EXCL_START */ + log_fatal("Error writing file '%s'. %s.\n", handle->path, strerror(errno)); + return -1; + /* LCOV_EXCL_STOP */ + } + + /* adjust the size of the valid data */ + if (handle->valid_size < offset + write_size) { + handle->valid_size = offset + write_size; + } + + ret = advise_write(&handle->advise, handle->f, offset, block_size); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error advising file '%s'. %s.\n", handle->path, strerror(errno)); + return -1; + /* LCOV_EXCL_STOP */ + } + + return 0; +} + +int handle_utime(struct snapraid_handle* handle) +{ + int ret; + + /* do nothing if not opened */ + if (handle->f == -1) + return 0; + + ret = fmtime(handle->f, handle->file->mtime_sec, handle->file->mtime_nsec); + + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error timing file '%s'. %s.\n", handle->file->sub, strerror(errno)); + return -1; + /* LCOV_EXCL_STOP */ + } + + return 0; +} + +struct snapraid_handle* handle_mapping(struct snapraid_state* state, unsigned* handlemax) +{ + tommy_node* i; + unsigned j; + unsigned size = 0; + struct snapraid_handle* handle; + + /* get the size of the mapping */ + size = 0; + for (i = state->maplist; i != 0; i = i->next) { + struct snapraid_map* map = i->data; + if (map->position > size) + size = map->position; + } + ++size; /* size is one more than the max */ + + handle = malloc_nofail(size * sizeof(struct snapraid_handle)); + + for (j = 0; j < size; ++j) { + /* default for empty position */ + handle[j].disk = 0; + handle[j].file = 0; + handle[j].f = -1; + handle[j].valid_size = 0; + } + + /* set the vector */ + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_map* map; + struct snapraid_disk* disk = i->data; + tommy_node* k; + + /* search the mapping for this disk */ + map = 0; + for (k = state->maplist; k != 0; k = k->next) { + map = k->data; + if (strcmp(disk->name, map->name) == 0) + break; + } + if (!map) { + /* LCOV_EXCL_START */ + log_fatal("Internal error for inconsistent disk mapping.\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + handle[map->position].disk = disk; + } + + *handlemax = size; + return handle; +} + diff --git a/cmdline/handle.h b/cmdline/handle.h new file mode 100644 index 0000000..f9521db --- /dev/null +++ b/cmdline/handle.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#ifndef __HANDLE_H +#define __HANDLE_H + +#include "state.h" +#include "support.h" + +/****************************************************************************/ +/* handle */ + +struct snapraid_handle { + char path[PATH_MAX]; /**< Path of the file. */ + struct snapraid_disk* disk; /**< Disk of the file. */ + struct snapraid_file* file; /**< File opened. When the file is closed, it's set to 0. */ + int f; /**< Handle of the file. */ + struct stat st; /**< Stat info of the opened file. */ + struct advise_struct advise; /**< Advise information. */ + data_off_t valid_size; /**< Size of the valid data. */ + int created; /**< If the file was created, otherwise it was already existing. */ +}; + +/** + * Create a file. + * The file is created if missing, and opened with write access. + * If the file is created, the handle->created is set. + * The initial size of the file is stored in the file->st struct. + * If the file cannot be opened for write access, it's opened with read-only access. + * The read-only access works only if the file has already the correct size and doesn't need to be modified. + */ +int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, int mode); + +/** + * Truncate a file if required. + */ +int handle_truncate(struct snapraid_handle* handle, struct snapraid_file* file); + +/** + * Open a file. + * The file is opened for reading. + */ +int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int mode, fptr* out, fptr* out_missing); + +/** + * Close a file. + */ +int handle_close(struct snapraid_handle* handle); + +/** + * Read a block from a file. + * If the read block is shorter, it's padded with 0. + */ +int handle_read(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size, fptr* out, fptr* out_missing); + +/** + * Write a block to a file. + */ +int handle_write(struct snapraid_handle* handle, block_off_t file_pos, unsigned char* block_buffer, unsigned block_size); + +/** + * Change the modification time of the file to the saved value. + */ +int handle_utime(struct snapraid_handle* handle); + +/** + * Map the unsorted list of disk to an ordered vector. + * \param diskmax The size of the vector. + * \return The allocated vector of pointers. + */ +struct snapraid_handle* handle_mapping(struct snapraid_state* state, unsigned* diskmax); + +#endif + diff --git a/cmdline/import.c b/cmdline/import.c new file mode 100644 index 0000000..91d42c5 --- /dev/null +++ b/cmdline/import.c @@ -0,0 +1,322 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "support.h" +#include "import.h" + +/****************************************************************************/ +/* import */ + +/** + * Compare the hash of two import blocks. + */ +int import_block_hash_compare(const void* void_arg, const void* void_data) +{ + const unsigned char* arg = void_arg; + const struct snapraid_import_block* block = void_data; + + return memcmp(arg, block->hash, BLOCK_HASH_SIZE); +} + +int import_block_prevhash_compare(const void* void_arg, const void* void_data) +{ + const unsigned char* arg = void_arg; + const struct snapraid_import_block* block = void_data; + + return memcmp(arg, block->prevhash, BLOCK_HASH_SIZE); +} + +/** + * Compute the hash of the hash for an import block. + * We just use the first 32 bit of the hash itself. + */ +static inline tommy_uint32_t import_block_hash(const unsigned char* hash) +{ + /* the hash data is not aligned, and we cannot access it with a direct cast */ + return hash[0] | ((uint32_t)hash[1] << 8) | ((uint32_t)hash[2] << 16) | ((uint32_t)hash[3] << 24); +} + +static void import_file(struct snapraid_state* state, const char* path, uint64_t size) +{ + struct snapraid_import_file* file; + block_off_t i; + data_off_t offset; + void* buffer; + int ret; + int f; + int flags; + unsigned block_size = state->block_size; + struct advise_struct advise; + + file = malloc_nofail(sizeof(struct snapraid_import_file)); + file->path = strdup_nofail(path); + file->size = size; + file->blockmax = (size + block_size - 1) / block_size; + file->blockimp = malloc_nofail(file->blockmax * sizeof(struct snapraid_import_block)); + + buffer = malloc_nofail(block_size); + + advise_init(&advise, state->file_mode); + + /* open for read */ + flags = O_RDONLY | O_BINARY | advise_flags(&advise); + f = open(path, flags); + if (f == -1) { + /* LCOV_EXCL_START */ + log_fatal("Error opening file '%s'. %s.\n", path, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + ret = advise_open(&advise, f); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error advising file '%s'. %s.\n", path, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + offset = 0; + for (i = 0; i < file->blockmax; ++i) { + struct snapraid_import_block* block = &file->blockimp[i]; + unsigned read_size = block_size; + if (read_size > size) + read_size = size; + + ret = read(f, buffer, read_size); + if (ret < 0 || (unsigned)ret != read_size) { + /* LCOV_EXCL_START */ + log_fatal("Error reading file '%s'. %s.\n", path, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + block->file = file; + block->offset = offset; + block->size = read_size; + + memhash(state->hash, state->hashseed, block->hash, buffer, read_size); + tommy_hashdyn_insert(&state->importset, &block->nodeset, block, import_block_hash(block->hash)); + + /* if we are in a rehash state */ + if (state->prevhash != HASH_UNDEFINED) { + /* compute also the previous hash */ + memhash(state->prevhash, state->prevhashseed, block->prevhash, buffer, read_size); + tommy_hashdyn_insert(&state->previmportset, &block->prevnodeset, block, import_block_hash(block->prevhash)); + } + + offset += read_size; + size -= read_size; + } + + ret = close(f); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error closing file '%s'. %s.\n", path, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + tommy_list_insert_tail(&state->importlist, &file->nodelist, file); + + free(buffer); +} + +void import_file_free(struct snapraid_import_file* file) +{ + free(file->path); + free(file->blockimp); + free(file); +} + +int state_import_fetch(struct snapraid_state* state, int rehash, struct snapraid_block* missing_block, unsigned char* buffer) +{ + struct snapraid_import_block* block; + int ret; + int f; + const unsigned char* hash = missing_block->hash; + unsigned block_size = state->block_size; + unsigned read_size; + unsigned char buffer_hash[HASH_MAX]; + const char* path; + + if (rehash) { + block = tommy_hashdyn_search(&state->previmportset, import_block_prevhash_compare, hash, import_block_hash(hash)); + } else { + block = tommy_hashdyn_search(&state->importset, import_block_hash_compare, hash, import_block_hash(hash)); + } + if (!block) + return -1; + + path = block->file->path; + read_size = block->size; + + f = open(path, O_RDONLY | O_BINARY); + if (f == -1) { + /* LCOV_EXCL_START */ + if (errno == ENOENT) { + log_fatal("DANGER! file '%s' disappeared.\n", path); + log_fatal("If you moved it, please rerun the same command.\n"); + } else { + log_fatal("Error opening file '%s'. %s.\n", path, strerror(errno)); + } + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + ret = pread(f, buffer, read_size, block->offset); + if (ret < 0 || (unsigned)ret != read_size) { + /* LCOV_EXCL_START */ + log_fatal("Error reading file '%s'. %s.\n", path, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + ret = close(f); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error closing file '%s'. %s.\n", path, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (read_size != block_size) { + /* fill the remaining with 0 */ + memset(buffer + read_size, 0, block_size - read_size); + } + + /* recheck the hash */ + if (rehash) + memhash(state->prevhash, state->prevhashseed, buffer_hash, buffer, read_size); + else + memhash(state->hash, state->hashseed, buffer_hash, buffer, read_size); + + if (memcmp(buffer_hash, hash, BLOCK_HASH_SIZE) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error in data reading file '%s'.\n", path); + log_fatal("Please don't change imported files while running.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + return 0; +} + +static void import_dir(struct snapraid_state* state, const char* dir) +{ + DIR* d; + + d = opendir(dir); + if (!d) { + /* LCOV_EXCL_START */ + log_fatal("Error opening directory '%s'. %s.\n", dir, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + while (1) { + char path_next[PATH_MAX]; + struct stat st; + const char* name; + struct dirent* dd; + + /* clear errno to detect erroneous conditions */ + errno = 0; + dd = readdir(d); + if (dd == 0 && errno != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error reading directory '%s'. %s.\n", dir, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (dd == 0) { + break; /* finished */ + } + + /* skip "." and ".." files */ + name = dd->d_name; + if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) + continue; + + pathprint(path_next, sizeof(path_next), "%s%s", dir, name); + +#if HAVE_STRUCT_DIRENT_D_STAT + /* convert dirent to lstat result */ + dirent_lstat(dd, &st); + + /* if the st_mode field is missing, takes care to fill it using normal lstat() */ + /* at now this can happen only in Windows (with HAVE_STRUCT_DIRENT_D_STAT defined), */ + /* because we use a directory reading method that doesn't read info about ReparsePoint. */ + /* Note that here we cannot call here lstat_sync(), because we don't know what kind */ + /* of file is it, and lstat_sync() doesn't always work */ + if (st.st_mode == 0) { + if (lstat(path_next, &st) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } +#else + /* get lstat info about the file */ + if (lstat(path_next, &st) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } +#endif + + if (S_ISREG(st.st_mode)) { + import_file(state, path_next, st.st_size); + } else if (S_ISDIR(st.st_mode)) { + pathslash(path_next, sizeof(path_next)); + import_dir(state, path_next); + } + } + + if (closedir(d) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error closing directory '%s'. %s.\n", dir, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } +} + +void state_import(struct snapraid_state* state, const char* dir) +{ + char path[PATH_MAX]; + + msg_progress("Importing...\n"); + + /* if the hash is not full */ + if (BLOCK_HASH_SIZE != HASH_MAX) { + /* LCOV_EXCL_START */ + log_fatal("You cannot import files when using a reduced hash.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* add the final slash */ + pathimport(path, sizeof(path), dir); + pathslash(path, sizeof(path)); + + import_dir(state, path); +} + diff --git a/cmdline/import.h b/cmdline/import.h new file mode 100644 index 0000000..abc79cb --- /dev/null +++ b/cmdline/import.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 . + */ + +#ifndef __IMPORT_H +#define __IMPORT_H + +#include "elem.h" +#include "state.h" + +/****************************************************************************/ +/* import */ + +/** + * Import block. + * Block used to import data external when recovering by hash. + */ +struct snapraid_import_block { + struct snapraid_import_file* file; /**< Back pointer to the file owning this block. */ + unsigned size; /**< Size of the block. */ + data_off_t offset; /**< Position of the block in the file. */ + unsigned char hash[HASH_MAX]; /**< Hash of the block. */ + unsigned char prevhash[HASH_MAX]; /**< Previous hash of the block. Valid only if we are in rehash state. */ + + /* nodes for data structures */ + tommy_hashdyn_node nodeset; + tommy_hashdyn_node prevnodeset; +}; + +/** + * Import file. + * File used to import data external when recovering by hash. + */ +struct snapraid_import_file { + data_off_t size; /**< Size of the file. */ + struct snapraid_import_block* blockimp; /**< All the blocks of the file. */ + block_off_t blockmax; /**< Number of blocks. */ + char* path; /**< Full path of the file. */ + + /* nodes for data structures */ + tommy_node nodelist; +}; + +/** + * Deallocate an import file. + */ +void import_file_free(struct snapraid_import_file* file); + +/** + * Fetch a block from the specified hash. + * Return ==0 if the block is found, and copied into buffer. + */ +int state_import_fetch(struct snapraid_state* state, int prevhash, struct snapraid_block* missing_block, unsigned char* buffer); + +/** + * Import files from the specified directory. + */ +void state_import(struct snapraid_state* state, const char* dir); + +#endif + diff --git a/cmdline/io.c b/cmdline/io.c new file mode 100644 index 0000000..bafea0d --- /dev/null +++ b/cmdline/io.c @@ -0,0 +1,1006 @@ +/* + * Copyright (C) 2016 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "io.h" + +/** + * Get the next block position to process. + */ +static block_off_t io_position_next(struct snapraid_io* io) +{ + block_off_t blockcur; + + /* get the next position */ + while (io->block_next < io->block_max && !io->block_is_enabled(io->block_arg, io->block_next)) + ++io->block_next; + + blockcur = io->block_next; + + /* next block for the next call */ + ++io->block_next; + + return blockcur; +} + +/** + * Setup the next pending task for all readers. + */ +static void io_reader_sched(struct snapraid_io* io, int task_index, block_off_t blockcur) +{ + unsigned i; + + for (i = 0; i < io->reader_max; ++i) { + struct snapraid_worker* worker = &io->reader_map[i]; + struct snapraid_task* task = &worker->task_map[task_index]; + + /* setup the new pending task */ + if (blockcur < io->block_max) + task->state = TASK_STATE_READY; + else + task->state = TASK_STATE_EMPTY; + + task->path[0] = 0; + if (worker->handle) + task->disk = worker->handle->disk; + else + task->disk = 0; + task->buffer = io->buffer_map[task_index][worker->buffer_skew + i]; + task->position = blockcur; + task->block = 0; + task->file = 0; + task->file_pos = 0; + task->read_size = 0; + task->is_timestamp_different = 0; + } +} + +/** + * Setup the next pending task for all writers. + */ +static void io_writer_sched(struct snapraid_io* io, int task_index, block_off_t blockcur) +{ + unsigned i; + + for (i = 0; i < io->writer_max; ++i) { + struct snapraid_worker* worker = &io->writer_map[i]; + struct snapraid_task* task = &worker->task_map[task_index]; + + /* setup the new pending task */ + task->state = TASK_STATE_READY; + task->path[0] = 0; + task->disk = 0; + task->buffer = io->buffer_map[task_index][worker->buffer_skew + i]; + task->position = blockcur; + task->block = 0; + task->file = 0; + task->file_pos = 0; + task->read_size = 0; + task->is_timestamp_different = 0; + } +} + +/** + * Setup an empty next pending task for all writers. + */ +static void io_writer_sched_empty(struct snapraid_io* io, int task_index, block_off_t blockcur) +{ + unsigned i; + + for (i = 0; i < io->writer_max; ++i) { + struct snapraid_worker* worker = &io->writer_map[i]; + struct snapraid_task* task = &worker->task_map[task_index]; + + /* setup the new pending task */ + task->state = TASK_STATE_EMPTY; + task->path[0] = 0; + task->disk = 0; + task->buffer = 0; + task->position = blockcur; + task->block = 0; + task->file = 0; + task->file_pos = 0; + task->read_size = 0; + task->is_timestamp_different = 0; + } +} + +/*****************************************************************************/ +/* mono thread */ + +static block_off_t io_read_next_mono(struct snapraid_io* io, void*** buffer) +{ + block_off_t blockcur_schedule; + + /* reset the index */ + io->reader_index = 0; + + blockcur_schedule = io_position_next(io); + + /* schedule the next read */ + io_reader_sched(io, 0, blockcur_schedule); + + /* set the buffer to use */ + *buffer = io->buffer_map[0]; + + return blockcur_schedule; +} + +static void io_write_preset_mono(struct snapraid_io* io, block_off_t blockcur, int skip) +{ + unsigned i; + + /* reset the index */ + io->writer_index = 0; + + /* clear errors */ + for (i = 0; i < IO_WRITER_ERROR_MAX; ++i) + io->writer_error[i] = 0; + + if (skip) { + /* skip the next write */ + io_writer_sched_empty(io, 0, blockcur); + } else { + /* schedule the next write */ + io_writer_sched(io, 0, blockcur); + } +} + +static void io_write_next_mono(struct snapraid_io* io, block_off_t blockcur, int skip, int* writer_error) +{ + unsigned i; + + (void)blockcur; + (void)skip; + + /* report errors */ + for (i = 0; i < IO_WRITER_ERROR_MAX; ++i) + writer_error[i] = io->writer_error[i]; +} + +static void io_refresh_mono(struct snapraid_io* io) +{ + (void)io; +} + +static struct snapraid_task* io_task_read_mono(struct snapraid_io* io, unsigned base, unsigned count, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac) +{ + struct snapraid_worker* worker; + struct snapraid_task* task; + unsigned i; + + /* get the next task */ + i = io->reader_index++; + + assert(base <= i && i < base + count); + + worker = &io->reader_map[i]; + task = &worker->task_map[0]; + + /* do the work */ + if (task->state != TASK_STATE_EMPTY) + worker->func(worker, task); + + /* return the position */ + *pos = i - base; + + /* store the waiting index */ + waiting_map[0] = i - base; + *waiting_mac = 1; + + return task; +} + +static struct snapraid_task* io_data_read_mono(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac) +{ + return io_task_read_mono(io, io->data_base, io->data_count, pos, waiting_map, waiting_mac); +} + +static struct snapraid_task* io_parity_read_mono(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac) +{ + return io_task_read_mono(io, io->parity_base, io->parity_count, pos, waiting_map, waiting_mac); +} + +static void io_parity_write_mono(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac) +{ + struct snapraid_worker* worker; + struct snapraid_task* task; + unsigned i; + + /* get the next task */ + i = io->writer_index++; + + worker = &io->writer_map[i]; + task = &worker->task_map[0]; + + io->writer_error[i] = 0; + + /* do the work */ + if (task->state != TASK_STATE_EMPTY) + worker->func(worker, task); + + /* return the position */ + *pos = i; + + /* store the waiting index */ + waiting_map[0] = i; + *waiting_mac = 1; +} + +static void io_start_mono(struct snapraid_io* io, + block_off_t blockstart, block_off_t blockmax, + int (*block_is_enabled)(void* arg, block_off_t), void* blockarg) +{ + io->block_start = blockstart; + io->block_max = blockmax; + io->block_is_enabled = block_is_enabled; + io->block_arg = blockarg; + io->block_next = blockstart; +} + +static void io_stop_mono(struct snapraid_io* io) +{ + (void)io; +} + +/*****************************************************************************/ +/* multi thread */ + +/* disable multithread if pthread is not present */ +#if HAVE_PTHREAD + +/** + * Get the next task to work on for a reader. + * + * This is the synchronization point for workers with the io. + */ +static struct snapraid_task* io_reader_step(struct snapraid_worker* worker) +{ + struct snapraid_io* io = worker->io; + + /* the synchronization is protected by the io mutex */ + thread_mutex_lock(&io->io_mutex); + + while (1) { + unsigned next_index; + + /* check if the worker has to exit */ + /* even if there is work to do */ + if (io->done) { + thread_mutex_unlock(&io->io_mutex); + return 0; + } + + /* get the next pending task */ + next_index = (worker->index + 1) % io->io_max; + + /* if the queue of pending tasks is not empty */ + if (next_index != io->reader_index) { + struct snapraid_task* task; + + /* the index that the IO may be waiting for */ + unsigned waiting_index = io->reader_index; + + /* the index that worker just completed */ + unsigned done_index = worker->index; + + /* get the new working task */ + worker->index = next_index; + task = &worker->task_map[worker->index]; + + /* if the just completed task is at this index */ + if (done_index == waiting_index) { + /* notify the IO that a new read is complete */ + thread_cond_signal_and_unlock(&io->read_done, &io->io_mutex); + } else { + thread_mutex_unlock(&io->io_mutex); + } + + /* return the new task */ + return task; + } + + /* otherwise wait for a read_sched event */ + thread_cond_wait(&io->read_sched, &io->io_mutex); + } +} + +/** + * Get the next task to work on for a writer. + * + * This is the synchronization point for workers with the io. + */ +static struct snapraid_task* io_writer_step(struct snapraid_worker* worker, int state) +{ + struct snapraid_io* io = worker->io; + int error_index; + + /* the synchronization is protected by the io mutex */ + thread_mutex_lock(&io->io_mutex); + + /* counts the number of errors in the global state */ + error_index = state - IO_WRITER_ERROR_BASE; + if (error_index >= 0 && error_index < IO_WRITER_ERROR_MAX) + ++io->writer_error[error_index]; + + while (1) { + unsigned next_index; + + /* get the next pending task */ + next_index = (worker->index + 1) % io->io_max; + + /* if the queue of pending tasks is not empty */ + if (next_index != io->writer_index) { + struct snapraid_task* task; + + /* the index that the IO may be waiting for */ + unsigned waiting_index = (io->writer_index + 1) % io->io_max; + + /* the index that worker just completed */ + unsigned done_index = worker->index; + + /* get the new working task */ + worker->index = next_index; + task = &worker->task_map[worker->index]; + + /* if the just completed task is at this index */ + if (done_index == waiting_index) { + /* notify the IO that a new write is complete */ + thread_cond_signal_and_unlock(&io->write_done, &io->io_mutex); + } else { + thread_mutex_unlock(&io->io_mutex); + } + + /* return the new task */ + return task; + } + + /* check if the worker has to exit */ + /* but only if there is no work to do */ + if (io->done) { + thread_mutex_unlock(&io->io_mutex); + return 0; + } + + /* otherwise wait for a write_sched event */ + thread_cond_wait(&io->write_sched, &io->io_mutex); + } +} + +/** + * Get the next block position to operate on. + * + * This is the synchronization point for workers with the io. + */ +static block_off_t io_read_next_thread(struct snapraid_io* io, void*** buffer) +{ + block_off_t blockcur_schedule; + block_off_t blockcur_caller; + unsigned i; + + /* get the next parity position to process */ + blockcur_schedule = io_position_next(io); + + /* ensure that all data/parity was read */ + assert(io->reader_list[0] == io->reader_max); + + /* setup the list of workers to process */ + for (i = 0; i <= io->reader_max; ++i) + io->reader_list[i] = i; + + /* the synchronization is protected by the io mutex */ + thread_mutex_lock(&io->io_mutex); + + /* schedule the next read */ + io_reader_sched(io, io->reader_index, blockcur_schedule); + + /* set the index for the tasks to return to the caller */ + io->reader_index = (io->reader_index + 1) % io->io_max; + + /* get the position to operate at high level from one task */ + blockcur_caller = io->reader_map[0].task_map[io->reader_index].position; + + /* set the buffer to use */ + *buffer = io->buffer_map[io->reader_index]; + + /* signal all the workers that there is a new pending task */ + thread_cond_broadcast_and_unlock(&io->read_sched, &io->io_mutex); + + return blockcur_caller; +} + +static void io_write_preset_thread(struct snapraid_io* io, block_off_t blockcur, int skip) +{ + (void)io; + (void)blockcur; + (void)skip; +} + +static void io_write_next_thread(struct snapraid_io* io, block_off_t blockcur, int skip, int* writer_error) +{ + unsigned i; + + /* ensure that all parity was written */ + assert(io->writer_list[0] == io->writer_max); + + /* setup the list of workers to process */ + for (i = 0; i <= io->writer_max; ++i) + io->writer_list[i] = i; + + /* the synchronization is protected by the io mutex */ + thread_mutex_lock(&io->io_mutex); + + /* report errors */ + for (i = 0; i < IO_WRITER_ERROR_MAX; ++i) { + writer_error[i] = io->writer_error[i]; + io->writer_error[i] = 0; + } + + if (skip) { + /* skip the next write */ + io_writer_sched_empty(io, io->writer_index, blockcur); + } else { + /* schedule the next write */ + io_writer_sched(io, io->writer_index, blockcur); + } + + /* at this point the writers must be in sync with the readers */ + assert(io->writer_index == io->reader_index); + + /* set the index to be used for the next write */ + io->writer_index = (io->writer_index + 1) % io->io_max; + + /* signal all the workers that there is a new pending task */ + thread_cond_broadcast_and_unlock(&io->write_sched, &io->io_mutex); +} + +static void io_refresh_thread(struct snapraid_io* io) +{ + unsigned i; + + /* the synchronization is protected by the io mutex */ + thread_mutex_lock(&io->io_mutex); + + /* for all readers, count the number of read blocks */ + for (i = 0; i < io->reader_max; ++i) { + unsigned begin, end, cached; + struct snapraid_worker* worker = &io->reader_map[i]; + + /* the first block read */ + begin = io->reader_index + 1; + /* the block in reading */ + end = worker->index; + if (begin > end) + end += io->io_max; + cached = end - begin; + + if (worker->parity_handle) + io->state->parity[worker->parity_handle->level].cached_blocks = cached; + else + worker->handle->disk->cached_blocks = cached; + } + + /* for all writers, count the number of written blocks */ + /* note that this is a kind of "opposite" of cached blocks */ + for (i = 0; i < io->writer_max; ++i) { + unsigned begin, end, cached; + struct snapraid_worker* worker = &io->writer_map[i]; + + /* the first block written */ + begin = io->writer_index + 1; + /* the block in writing */ + end = worker->index; + if (begin > end) + end += io->io_max; + cached = end - begin; + + io->state->parity[worker->parity_handle->level].cached_blocks = cached; + } + + thread_mutex_unlock(&io->io_mutex); +} + +static struct snapraid_task* io_task_read_thread(struct snapraid_io* io, unsigned base, unsigned count, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac) +{ + unsigned waiting_cycle; + + /* count the waiting cycle */ + waiting_cycle = 0; + + /* clear the waiting indexes */ + *waiting_mac = 0; + + /* the synchronization is protected by the io mutex */ + thread_mutex_lock(&io->io_mutex); + + while (1) { + unsigned char* let; + unsigned busy_index; + + /* get the index the IO is using */ + /* we must ensure that this index has not a read in progress */ + /* to avoid a concurrent access */ + busy_index = io->reader_index; + + /* search for a worker that has already finished */ + let = &io->reader_list[0]; + while (1) { + unsigned i = *let; + + /* if we are at the end */ + if (i == io->reader_max) + break; + + /* if it's in range */ + if (base <= i && i < base + count) { + struct snapraid_worker* worker; + + /* if it's the first cycle */ + if (waiting_cycle == 0) { + /* store the waiting indexes */ + waiting_map[(*waiting_mac)++] = i - base; + } + + worker = &io->reader_map[i]; + + /* if the worker has finished this index */ + if (busy_index != worker->index) { + struct snapraid_task* task; + + task = &worker->task_map[io->reader_index]; + + thread_mutex_unlock(&io->io_mutex); + + /* mark the worker as processed */ + /* setting the previous one to point at the next one */ + *let = io->reader_list[i + 1]; + + /* return the position */ + *pos = i - base; + + /* on the first cycle, no one is waiting */ + if (waiting_cycle == 0) + *waiting_mac = 0; + + return task; + } + } + + /* next position to check */ + let = &io->reader_list[i + 1]; + } + + /* if no worker is ready, wait for an event */ + thread_cond_wait(&io->read_done, &io->io_mutex); + + /* count the cycles */ + ++waiting_cycle; + } +} + +static struct snapraid_task* io_data_read_thread(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac) +{ + return io_task_read_thread(io, io->data_base, io->data_count, pos, waiting_map, waiting_mac); +} + +static struct snapraid_task* io_parity_read_thread(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac) +{ + return io_task_read_thread(io, io->parity_base, io->parity_count, pos, waiting_map, waiting_mac); +} + +static void io_parity_write_thread(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac) +{ + unsigned waiting_cycle; + + /* count the waiting cycle */ + waiting_cycle = 0; + + /* clear the waiting indexes */ + *waiting_mac = 0; + + /* the synchronization is protected by the io mutex */ + thread_mutex_lock(&io->io_mutex); + + while (1) { + unsigned char* let; + unsigned busy_index; + + /* get the next index the IO is going to use */ + /* we must ensure that this index has not a write in progress */ + /* to avoid a concurrent access */ + /* note that we are already sure that a write is not in progress */ + /* at the index the IO is using at now */ + busy_index = (io->writer_index + 1) % io->io_max; + + /* search for a worker that has already finished */ + let = &io->writer_list[0]; + while (1) { + unsigned i = *let; + struct snapraid_worker* worker; + + /* if we are at the end */ + if (i == io->writer_max) + break; + + /* if it's the first cycle */ + if (waiting_cycle == 0) { + /* store the waiting indexes */ + waiting_map[(*waiting_mac)++] = i; + } + + worker = &io->writer_map[i]; + + /* the two indexes cannot be equal */ + assert(io->writer_index != worker->index); + + /* if the worker has finished this index */ + if (busy_index != worker->index) { + thread_mutex_unlock(&io->io_mutex); + + /* mark the worker as processed */ + /* setting the previous one to point at the next one */ + *let = io->writer_list[i + 1]; + + /* return the position */ + *pos = i; + + /* on the first cycle, no one is waiting */ + if (waiting_cycle == 0) + *waiting_mac = 0; + + return; + } + + /* next position to check */ + let = &io->writer_list[i + 1]; + } + + /* if no worker is ready, wait for an event */ + thread_cond_wait(&io->write_done, &io->io_mutex); + + /* count the cycles */ + ++waiting_cycle; + } +} + +static void io_reader_worker(struct snapraid_worker* worker, struct snapraid_task* task) +{ + /* if we reached the end */ + if (task->position >= worker->io->block_max) { + /* complete a dummy task */ + task->state = TASK_STATE_EMPTY; + } else { + worker->func(worker, task); + } +} + +static void* io_reader_thread(void* arg) +{ + struct snapraid_worker* worker = arg; + + /* force completion of the first task */ + io_reader_worker(worker, &worker->task_map[0]); + + while (1) { + struct snapraid_task* task; + + /* get the new task */ + task = io_reader_step(worker); + + /* if no task, it means to exit */ + if (!task) + break; + + /* nothing more to do */ + if (task->state == TASK_STATE_EMPTY) + continue; + + assert(task->state == TASK_STATE_READY); + + /* work on the assigned task */ + io_reader_worker(worker, task); + } + + return 0; +} + +static void* io_writer_thread(void* arg) +{ + struct snapraid_worker* worker = arg; + int latest_state = TASK_STATE_DONE; + + while (1) { + struct snapraid_task* task; + + /* get the new task */ + task = io_writer_step(worker, latest_state); + + /* if no task, it means to exit */ + if (!task) + break; + + /* nothing more to do */ + if (task->state == TASK_STATE_EMPTY) { + latest_state = TASK_STATE_DONE; + continue; + } + + assert(task->state == TASK_STATE_READY); + + /* work on the assigned task */ + worker->func(worker, task); + + /* save the resulting state */ + latest_state = task->state; + } + + return 0; +} + +static void io_start_thread(struct snapraid_io* io, + block_off_t blockstart, block_off_t blockmax, + int (*block_is_enabled)(void* arg, block_off_t), void* blockarg) +{ + unsigned i; + + io->block_start = blockstart; + io->block_max = blockmax; + io->block_is_enabled = block_is_enabled; + io->block_arg = blockarg; + io->block_next = blockstart; + + io->done = 0; + io->reader_index = io->io_max - 1; + io->writer_index = 0; + + /* clear writer errors */ + for (i = 0; i < IO_WRITER_ERROR_MAX; ++i) + io->writer_error[i] = 0; + + /* setup the initial read pending tasks, except the latest one, */ + /* the latest will be initialized at the fist io_read_next() call */ + for (i = 0; i < io->io_max - 1; ++i) { + block_off_t blockcur = io_position_next(io); + + io_reader_sched(io, i, blockcur); + } + + /* setup the lists of workers to process */ + io->reader_list[0] = io->reader_max; + for (i = 0; i <= io->writer_max; ++i) + io->writer_list[i] = i; + + /* start the reader threads */ + for (i = 0; i < io->reader_max; ++i) { + struct snapraid_worker* worker = &io->reader_map[i]; + + worker->index = 0; + + thread_create(&worker->thread, 0, io_reader_thread, worker); + } + + /* start the writer threads */ + for (i = 0; i < io->writer_max; ++i) { + struct snapraid_worker* worker = &io->writer_map[i]; + + worker->index = io->io_max - 1; + + thread_create(&worker->thread, 0, io_writer_thread, worker); + } +} + +static void io_stop_thread(struct snapraid_io* io) +{ + unsigned i; + + thread_mutex_lock(&io->io_mutex); + + /* mark that we are stopping */ + io->done = 1; + + /* signal all the threads to recognize the new state */ + thread_cond_broadcast(&io->read_sched); + thread_cond_broadcast(&io->write_sched); + + thread_mutex_unlock(&io->io_mutex); + + /* wait for all readers to terminate */ + for (i = 0; i < io->reader_max; ++i) { + struct snapraid_worker* worker = &io->reader_map[i]; + void* retval; + + /* wait for thread termination */ + thread_join(worker->thread, &retval); + } + + /* wait for all writers to terminate */ + for (i = 0; i < io->writer_max; ++i) { + struct snapraid_worker* worker = &io->writer_map[i]; + void* retval; + + /* wait for thread termination */ + thread_join(worker->thread, &retval); + } +} + +#endif + +/*****************************************************************************/ +/* global */ + +void io_init(struct snapraid_io* io, struct snapraid_state* state, + unsigned io_cache, unsigned buffer_max, + void (*data_reader)(struct snapraid_worker*, struct snapraid_task*), + struct snapraid_handle* handle_map, unsigned handle_max, + void (*parity_reader)(struct snapraid_worker*, struct snapraid_task*), + void (*parity_writer)(struct snapraid_worker*, struct snapraid_task*), + struct snapraid_parity_handle* parity_handle_map, unsigned parity_handle_max) +{ + unsigned i; + size_t allocated; + + io->state = state; + +#if HAVE_PTHREAD + if (io_cache == 0) { + /* default is 8 MiB of cache */ + /* this seems to be a good tradeoff between speed and memory usage */ + io->io_max = 8 * 1024 * 1024 / state->block_size; + if (io->io_max < IO_MIN) + io->io_max = IO_MIN; + if (io->io_max > IO_MAX) + io->io_max = IO_MAX; + } else { + io->io_max = io_cache; + } +#else + (void)io_cache; + + /* without pthread force the mono thread mode */ + io->io_max = 1; +#endif + + assert(io->io_max == 1 || (io->io_max >= IO_MIN && io->io_max <= IO_MAX)); + + io->buffer_max = buffer_max; + allocated = 0; + for (i = 0; i < io->io_max; ++i) { + if (state->file_mode != ADVISE_DIRECT) + io->buffer_map[i] = malloc_nofail_vector_align(handle_max, buffer_max, state->block_size, &io->buffer_alloc_map[i]); + else + io->buffer_map[i] = malloc_nofail_vector_direct(handle_max, buffer_max, state->block_size, &io->buffer_alloc_map[i]); + if (!state->opt.skip_self) + mtest_vector(io->buffer_max, state->block_size, io->buffer_map[i]); + allocated += state->block_size * buffer_max; + } + + msg_progress("Using %u MiB of memory for %u blocks of IO cache.\n", (unsigned)(allocated / MEBI), io->io_max); + + if (parity_writer) { + io->reader_max = handle_max; + io->writer_max = parity_handle_max; + } else { + io->reader_max = handle_max + parity_handle_max; + io->writer_max = 0; + } + + io->reader_map = malloc_nofail(sizeof(struct snapraid_worker) * io->reader_max); + io->reader_list = malloc_nofail(io->reader_max + 1); + io->writer_map = malloc_nofail(sizeof(struct snapraid_worker) * io->writer_max); + io->writer_list = malloc_nofail(io->writer_max + 1); + + io->data_base = 0; + io->data_count = handle_max; + io->parity_base = handle_max; + io->parity_count = parity_handle_max; + + for (i = 0; i < io->reader_max; ++i) { + struct snapraid_worker* worker = &io->reader_map[i]; + + worker->io = io; + + if (i < handle_max) { + /* it's a data read */ + worker->handle = &handle_map[i]; + worker->parity_handle = 0; + worker->func = data_reader; + + /* data read is put in lower buffer index */ + worker->buffer_skew = 0; + } else { + /* it's a parity read */ + worker->handle = 0; + worker->parity_handle = &parity_handle_map[i - handle_max]; + worker->func = parity_reader; + + /* parity read is put after data and computed parity */ + worker->buffer_skew = parity_handle_max; + } + } + + for (i = 0; i < io->writer_max; ++i) { + struct snapraid_worker* worker = &io->writer_map[i]; + + worker->io = io; + + /* it's a parity write */ + worker->handle = 0; + worker->parity_handle = &parity_handle_map[i]; + worker->func = parity_writer; + + /* parity to write is put after data */ + worker->buffer_skew = handle_max; + } + +#if HAVE_PTHREAD + if (io->io_max > 1) { + io_read_next = io_read_next_thread; + io_write_preset = io_write_preset_thread; + io_write_next = io_write_next_thread; + io_refresh = io_refresh_thread; + io_data_read = io_data_read_thread; + io_parity_read = io_parity_read_thread; + io_parity_write = io_parity_write_thread; + io_start = io_start_thread; + io_stop = io_stop_thread; + + thread_mutex_init(&io->io_mutex, 0); + thread_cond_init(&io->read_done, 0); + thread_cond_init(&io->read_sched, 0); + thread_cond_init(&io->write_done, 0); + thread_cond_init(&io->write_sched, 0); + } else +#endif + { + io_read_next = io_read_next_mono; + io_write_preset = io_write_preset_mono; + io_write_next = io_write_next_mono; + io_refresh = io_refresh_mono; + io_data_read = io_data_read_mono; + io_parity_read = io_parity_read_mono; + io_parity_write = io_parity_write_mono; + io_start = io_start_mono; + io_stop = io_stop_mono; + } +} + +void io_done(struct snapraid_io* io) +{ + unsigned i; + + for (i = 0; i < io->io_max; ++i) { + free(io->buffer_map[i]); + free(io->buffer_alloc_map[i]); + } + + free(io->reader_map); + free(io->reader_list); + free(io->writer_map); + free(io->writer_list); + +#if HAVE_PTHREAD + if (io->io_max > 1) { + thread_mutex_destroy(&io->io_mutex); + thread_cond_destroy(&io->read_done); + thread_cond_destroy(&io->read_sched); + thread_cond_destroy(&io->write_done); + thread_cond_destroy(&io->write_sched); + } +#endif +} + diff --git a/cmdline/io.h b/cmdline/io.h new file mode 100644 index 0000000..82ec744 --- /dev/null +++ b/cmdline/io.h @@ -0,0 +1,400 @@ +/* + * Copyright (C) 2016 Andrea Mazzoleni + * + * 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 . + */ + +#ifndef __IO_H +#define __IO_H + +#include "state.h" +#include "support.h" +#include "handle.h" +#include "parity.h" + +/** + * Number of read-ahead buffers. + * + * More buffers always result in better performance. + * + * This is the scrub performance on my machine with different buffers: + * + * 1 - 380 MB/s, CPU 26%, speed 100% [SnapRAID 9.2] + * 2 - 426 MB/s, CPU 46%, speed 112% + * 4 - 452 MB/s, CPU 54%, speed 118% + * 8 - 487 MB/s, CPU 60%, speed 128% + * 16 - 505 MB/s, CPU 63%, speed 132% + * 32 - 520 MB/s, CPU 64%, speed 136% + * 64 - 524 MB/s, CPU 65%, speed 137% + * 128 - 525 MB/s, CPU 66%, speed 138% + */ +#define IO_MIN 3 /* required by writers, readers can work also with 2 */ +#define IO_MAX 128 + +/** + * State of the task. + */ +#define TASK_STATE_IOERROR_CONTINUE -4 /**< IO error. Continuation requested. */ +#define TASK_STATE_ERROR_CONTINUE -3 /**< Generic error. Continuation requested. */ +#define TASK_STATE_IOERROR -2 /**< IO error. Failure requested. */ +#define TASK_STATE_ERROR -1 /**< Generic error. Failure requested. */ +#define TASK_STATE_EMPTY 0 /**< Nothing to do. */ +#define TASK_STATE_READY 1 /**< Ready to start. */ +#define TASK_STATE_DONE 2 /**< Task completed. */ + +/** + * Task of work. + * + * This represents the minimal element of work that worker threads are + * going to be asked to do. + * + * It consists in reading a block of data from a disk. + * + * Note that the disk to use is defined implicitly in the worker thread. + */ +struct snapraid_task { + int state; /**< State of the task. One of the TASK_STATE_*. */ + char path[PATH_MAX]; /**< Path of the file. */ + struct snapraid_disk* disk; /**< Disk of the file. */ + unsigned char* buffer; /**< Where to read the data. */ + block_off_t position; /**< Parity position to read. */ + + /** + * Result of the task. + */ + struct snapraid_block* block; + struct snapraid_file* file; + block_off_t file_pos; + int read_size; /**< Size of the data read. */ + int is_timestamp_different; /**< Report if file has a changed timestamp. */ +}; + +/** + * Worker for tasks. + * + * This represents a worker thread designated to read data + * from a specific disk. + */ +struct snapraid_worker { +#if HAVE_PTHREAD + pthread_t thread; /**< Thread context for the worker. */ +#endif + + struct snapraid_io* io; /**< Parent pointer. */ + + void (*func)(struct snapraid_worker*, struct snapraid_task*); + + /** + * Handle to data or parity. + * + * Only one of the two is valid, the other is 0. + */ + struct snapraid_handle* handle; /**< Handle at the file on the disk. */ + struct snapraid_parity_handle* parity_handle; /**< Handle at the parity on the disk. */ + + /** + * Vector of tasks. + * + * It's a ring of tasks reused cycle after cycle. + */ + struct snapraid_task task_map[IO_MAX]; + + /** + * The task in progress by the worker thread. + * + * It's an index inside in the ::task_map vector. + */ + unsigned index; + + /** + * Which buffer base index should be used for destination. + */ + unsigned buffer_skew; +}; + +/** + * Number of error kind for writers. + */ +#define IO_WRITER_ERROR_BASE TASK_STATE_IOERROR_CONTINUE +#define IO_WRITER_ERROR_MAX (-IO_WRITER_ERROR_BASE) + +/** + * Reader. + * + * This represents the pool of worker threads dedicated to read + * data from the disks. + */ +struct snapraid_io { + struct snapraid_state* state; + + /** + * Number of read-ahead buffers to use. + * + * Between IO_MIN and IO_MAX for thread use. + * + * If equal to 1, it means to work without any thread. + */ + unsigned io_max; + +#if HAVE_PTHREAD + /** + * Mutex used to protect the synchronization + * between the io and the workers. + */ + pthread_mutex_t io_mutex; + + /** + * Condition for a new read is completed. + * + * The workers signal this condition when a new read is completed. + * The IO waits on this condition when it's waiting for + * a new read to be completed. + */ + pthread_cond_t read_done; + + /** + * Condition for a new read scheduled. + * + * The workers wait on this condition when they are waiting for a new + * read to process. + * The IO signals this condition when new reads are scheduled. + */ + pthread_cond_t read_sched; + + /** + * Condition for a new write is completed. + * + * The workers signal this condition when a new write is completed. + * The IO waits on this condition when it's waiting for + * a new write to be completed. + */ + pthread_cond_t write_done; + + /** + * Condition for a new write scheduled. + * + * The workers wait on this condition when they are waiting for a new + * write to process. + * The IO signals this condition when new writes are scheduled. + */ + pthread_cond_t write_sched; +#endif + + /** + * Base position for workers. + * + * It's the index in the ::worker_map[]. + */ + unsigned data_base; + unsigned data_count; + unsigned parity_base; + unsigned parity_count; + + /** + * Callbacks for workers. + */ + void (*data_reader)(struct snapraid_worker*, struct snapraid_task*); + void (*parity_reader)(struct snapraid_worker*, struct snapraid_task*); + void (*parity_writer)(struct snapraid_worker*, struct snapraid_task*); + + /** + * Blocks mapping. + * + * This info is used to obtain the sequence of block + * positions to process. + */ + block_off_t block_start; + block_off_t block_max; + block_off_t block_next; + int (*block_is_enabled)(void* arg, block_off_t); + void* block_arg; + + /** + * Buffers for data. + * + * A pool of buffers used to store the data read. + */ + unsigned buffer_max; /**< Number of buffers. */ + void* buffer_alloc_map[IO_MAX]; /**< Allocation map for buffers. */ + void** buffer_map[IO_MAX]; /**< Buffers for data. */ + + /** + * Workers. + * + * A vector of readers, each one representing a different thread. + */ + unsigned reader_max; /**< Number of workers. */ + struct snapraid_worker* reader_map; /**< Vector of workers. */ + unsigned writer_max; /**< Number of workers. */ + struct snapraid_worker* writer_map; /**< Vector of workers. */ + + /** + * List of not yet processed workers. + * + * The list has ::reader_max + 1 elements. Each element contains + * the number of the reader to process. + * + * At initialization the list is filled with [0..reader_max]. + * To get the next element to process we use i = list[i + 1]. + * The end is when i == reader_max. + */ + unsigned char* reader_list; + unsigned char* writer_list; + + /** + * Exit condition for all threads. + */ + int done; + + /** + * The task currently used by the caller. + * + * It's a rolling counter, when reaching ::io_max + * it goes again to 0. + * + * When the caller finish with the current index, + * it's incremented, and a read_sched() signal is sent. + * + * In monothread mode it isn't the task index, + * but the worker index. + */ + unsigned reader_index; + + /** + * The task currently used by the caller. + * + * It's a rolling counter, when reaching ::io_max + * it goes again to 0. + * + * When the caller finish with the current index, + * it's incremented, and a write_sched() signal is sent. + * + * In monothread mode it isn't the task index, + * but the worker index. + */ + unsigned writer_index; + + /** + * Counts the error happening in the writers. + */ + int writer_error[IO_WRITER_ERROR_MAX]; +}; + +/** + * Initialize the InputOutput workers. + * + * \param io_cache The number of IO buffers for read-ahead and write-behind. 0 for default. + * \param buffer_max The number of data/parity buffers to allocate. + */ +void io_init(struct snapraid_io* io, struct snapraid_state* state, + unsigned io_cache, unsigned buffer_max, + void (*data_reader)(struct snapraid_worker*, struct snapraid_task*), + struct snapraid_handle* handle_map, unsigned handle_max, + void (*parity_reader)(struct snapraid_worker*, struct snapraid_task*), + void (*parity_writer)(struct snapraid_worker*, struct snapraid_task*), + struct snapraid_parity_handle* parity_handle_map, unsigned parity_handle_max); + +/** + * Deinitialize te InputOutput workers. + */ +void io_done(struct snapraid_io* io); + +/** + * Start all the worker threads. + */ +void (*io_start)(struct snapraid_io* io, + block_off_t blockstart, block_off_t blockmax, + int (*block_is_enabled)(void* arg, block_off_t), void* blockarg); + +/** + * Stop all the worker threads. + */ +void (*io_stop)(struct snapraid_io* io); + +/** + * Next read position. + * + * This call starts the reading process. + * It must be called before io_data_read() and io_parity_read(). + * + * \param io InputOutput context. + * \param buffer The data buffers to use for this position. + * \return The parity position. + */ +block_off_t (*io_read_next)(struct snapraid_io* io, void*** buffer); + +/** + * Read a data block. + * + * It must be called exactly ::handle_max times. + * + * \param io InputOutput context. + * \param diskcur The position of the data block in the ::handle_map vector. + * \return The completed task. + */ +struct snapraid_task* (*io_data_read)(struct snapraid_io* io, unsigned* diskcur, unsigned* waiting_map, unsigned* waiting_mac); + +/** + * Read a parity block. + * + * It must be called exactly ::parity_handle_max times. + * + * \param io InputOutput context. + * \param levcur The position of the parity block in the ::parity_handle_map vector. + * \return The completed task. + */ +struct snapraid_task* (*io_parity_read)(struct snapraid_io* io, unsigned* levcur, unsigned* waiting_map, unsigned* waiting_mac); + +/** + * Write of a parity block. + * + * It must be called exactly ::parity_handle_max times. + * + * \param io InputOutput context. + * \param levcur The position of the parity block in the ::parity_handle_map vector. + */ +void (*io_parity_write)(struct snapraid_io* io, unsigned* levcur, unsigned* waiting_map, unsigned* waiting_mac); + +/** + * Preset the write position. + * + * This call starts the write process. + * It must be called before io_parity_write(). + * + * \param io InputOutput context. + * \param blockcur The parity position to write. + * \param skip Skip the writes, in case parity doesn't need to be updated. + */ +void (*io_write_preset)(struct snapraid_io* io, block_off_t blockcur, int skip); + +/** + * Next write position. + * + * This call ends the write process. + * It must be called after io_parity_write(). + * + * \param io InputOutput context. + * \param blockcur The parity position to write. + * \param skip Skip the writes, in case parity doesn't need to be updated. + * \param writer_error Return the number of errors. Vector of IO_WRITER_ERROR_MAX elements. + */ +void (*io_write_next)(struct snapraid_io* io, block_off_t blockcur, int skip, int* writer_error); + +/** + * Refresh the number of cached blocks for all data and parity disks. + */ +void (*io_refresh)(struct snapraid_io* io); + +#endif + diff --git a/cmdline/list.c b/cmdline/list.c new file mode 100644 index 0000000..a73cca4 --- /dev/null +++ b/cmdline/list.c @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "util.h" +#include "elem.h" +#include "state.h" +#include "parity.h" +#include "handle.h" + +/****************************************************************************/ +/* list */ + +void state_list(struct snapraid_state* state) +{ + tommy_node* i; + unsigned file_count; + data_off_t file_size; + unsigned link_count; + char esc_buffer[ESC_MAX]; + char esc_buffer_alt[ESC_MAX]; + + file_count = 0; + file_size = 0; + link_count = 0; + + msg_progress("Listing...\n"); + + /* for each disk */ + for (i = state->disklist; i != 0; i = i->next) { + tommy_node* j; + struct snapraid_disk* disk = i->data; + + /* sort by name */ + tommy_list_sort(&disk->filelist, file_path_compare); + + /* for each file */ + for (j = disk->filelist; j != 0; j = j->next) { + struct snapraid_file* file = j->data; +#if HAVE_LOCALTIME_R + struct tm tm_res; +#endif + struct tm* tm; + time_t t; + + ++file_count; + file_size += file->size; + + log_tag("file:%s:%s:%" PRIu64 ":%" PRIi64 ":%u:%" PRIi64 "\n", disk->name, esc_tag(file->sub, esc_buffer), file->size, file->mtime_sec, file->mtime_nsec, file->inode); + + t = file->mtime_sec; +#if HAVE_LOCALTIME_R + tm = localtime_r(&t, &tm_res); +#else + tm = localtime(&t); +#endif + + printf("%12" PRIu64 " ", file->size); + if (tm) { + printf("%04u/%02u/%02u %02u:%02u", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min); + if (msg_level >= MSG_VERBOSE) + printf(":%02u.%03u", tm->tm_sec, file->mtime_nsec / 1000000); + printf(" "); + } + printf("%s\n", fmt_term(disk, file->sub, esc_buffer)); + } + + /* sort by name */ + tommy_list_sort(&disk->linklist, link_alpha_compare); + + /* for each link */ + for (j = disk->linklist; j != 0; j = j->next) { + struct snapraid_link* slink = j->data; + const char* type; + + switch (slink->flag & FILE_IS_LINK_MASK) { + case FILE_IS_HARDLINK : type = "hardlink"; break; + case FILE_IS_SYMLINK : type = "symlink"; break; + case FILE_IS_SYMDIR : type = "symdir"; break; + case FILE_IS_JUNCTION : type = "junction"; break; + /* LCOV_EXCL_START */ + default : type = "unknown"; break; + /* LCOV_EXCL_STOP */ + } + + ++link_count; + + log_tag("link_%s:%s:%s:%s\n", type, disk->name, esc_tag(slink->sub, esc_buffer), esc_tag(slink->linkto, esc_buffer_alt)); + + printf("%12s ", type); + printf(" "); + if (msg_level >= MSG_VERBOSE) + printf(" "); + printf("%s -> %s\n", fmt_term(disk, slink->sub, esc_buffer), fmt_term(disk, slink->linkto, esc_buffer_alt)); + } + } + + msg_status("\n"); + msg_status("%8u files, for %" PRIu64 " GB\n", file_count, file_size / GIGA); + msg_status("%8u links\n", link_count); + + log_tag("summary:file_count:%u\n", file_count); + log_tag("summary:file_size:%" PRIu64 "\n", file_size); + log_tag("summary:link_count:%u\n", link_count); + log_tag("summary:exit:ok\n"); + log_flush(); +} + diff --git a/cmdline/mingw.c b/cmdline/mingw.c new file mode 100644 index 0000000..2805378 --- /dev/null +++ b/cmdline/mingw.c @@ -0,0 +1,2797 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#ifdef __MINGW32__ /* Only for MingW */ + +#include "support.h" + +/** + * Exit codes. + */ +int exit_success = 0; +int exit_failure = 1; +int exit_sync_needed = 2; + +/* Add missing Windows declaration */ + +/* For SetThreadExecutionState */ +#define WIN32_ES_SYSTEM_REQUIRED 0x00000001L +#define WIN32_ES_DISPLAY_REQUIRED 0x00000002L +#define WIN32_ES_USER_PRESENT 0x00000004L +#define WIN32_ES_AWAYMODE_REQUIRED 0x00000040L +#define WIN32_ES_CONTINUOUS 0x80000000L + +/* File Index */ +#define FILE_INVALID_FILE_ID ((ULONGLONG)-1LL) + +/** + * Direct access to RtlGenRandom(). + * This function is accessible only with LoadLibrary() and it's available from Windows XP. + */ +static BOOLEAN (WINAPI* ptr_RtlGenRandom)(PVOID, ULONG); + +/** + * Direct access to GetTickCount64(). + * This function is available only from Windows Vista. + */ +static ULONGLONG (WINAPI* ptr_GetTickCount64)(void); + +/** + * Description of the last error. + * It's stored in the thread local storage. + */ +static pthread_key_t last_error; + +/** + * Monotone tick counter + */ +static pthread_mutex_t tick_lock; +static uint64_t tick_last; + +/** + * If we are running in Wine. + */ +static int is_wine; + +/** + * If we should use the legacy FindFirst/Next way to list directories. + */ +static int is_scan_winfind; + +/** + * Loaded ADVAPI32.DLL. + */ +static HMODULE dll_advapi32; + +/** + * Executable dir. + * + * Or empty or terminating with '\'. + */ +static WCHAR exedir[MAX_PATH]; + +/** + * Set the executable dir. + */ +static void exedir_init(void) +{ + DWORD size; + WCHAR* slash; + + size = GetModuleFileNameW(0, exedir, MAX_PATH); + if (size == 0 || size == MAX_PATH) { + /* use empty dir */ + exedir[0] = 0; + return; + } + + slash = wcsrchr(exedir, L'\\'); + if (!slash) { + /* use empty dir */ + exedir[0] = 0; + return; + } + + /* cut exe name */ + slash[1] = 0; +} + +void os_init(int opt) +{ + HMODULE ntdll, kernel32; + + is_scan_winfind = opt != 0; + + /* initialize the thread local storage for strerror(), using free() as destructor */ + if (pthread_key_create(&last_error, free) != 0) { + log_fatal("Error calling pthread_key_create().\n"); + exit(EXIT_FAILURE); + } + + tick_last = 0; + if (pthread_mutex_init(&tick_lock, 0) != 0) { + log_fatal("Error calling pthread_mutex_init().\n"); + exit(EXIT_FAILURE); + } + + ntdll = GetModuleHandle("NTDLL.DLL"); + if (!ntdll) { + log_fatal("Error loading the NTDLL module.\n"); + exit(EXIT_FAILURE); + } + + kernel32 = GetModuleHandle("KERNEL32.DLL"); + if (!kernel32) { + log_fatal("Error loading the KERNEL32 module.\n"); + exit(EXIT_FAILURE); + } + + dll_advapi32 = LoadLibrary("ADVAPI32.DLL"); + if (!dll_advapi32) { + log_fatal("Error loading the ADVAPI32 module.\n"); + exit(EXIT_FAILURE); + } + + /* check for Wine presence */ + is_wine = GetProcAddress(ntdll, "wine_get_version") != 0; + + /* setup the standard random generator used as fallback */ + srand(GetTickCount()); + + /* get pointer to RtlGenRandom, note that it was reported missing in some cases */ + ptr_RtlGenRandom = (void*)GetProcAddress(dll_advapi32, "SystemFunction036"); + + /* get pointer to RtlGenRandom, note that it was reported missing in some cases */ + ptr_GetTickCount64 = (void*)GetProcAddress(kernel32, "GetTickCount64"); + + /* set the thread execution level to avoid sleep */ + /* first try for Windows 7 */ + if (SetThreadExecutionState(WIN32_ES_CONTINUOUS | WIN32_ES_SYSTEM_REQUIRED | WIN32_ES_AWAYMODE_REQUIRED) == 0) { + /* retry with the XP variant */ + SetThreadExecutionState(WIN32_ES_CONTINUOUS | WIN32_ES_SYSTEM_REQUIRED); + } + + exedir_init(); +} + +void os_done(void) +{ + /* delete the thread local storage for strerror() */ + pthread_key_delete(last_error); + + pthread_mutex_destroy(&tick_lock); + + /* restore the normal execution level */ + SetThreadExecutionState(WIN32_ES_CONTINUOUS); + + FreeLibrary(dll_advapi32); +} + +void os_abort(void) +{ + void* stack[32]; + size_t size; + unsigned i; + + printf("Stacktrace of " PACKAGE " v" VERSION); + printf(", mingw"); +#ifdef __GNUC__ + printf(", gcc " __VERSION__); +#endif + printf(", %d-bit", (int)sizeof(void *) * 8); + printf(", PATH_MAX=%d", PATH_MAX); + printf("\n"); + + /* get stackstrace, but without symbols */ + size = CaptureStackBackTrace(0, 32, stack, NULL); + + for (i = 0; i < size; ++i) + printf("[bt] %02u: %p\n", i, stack[i]); + + printf("Please report this error to the SnapRAID Forum:\n"); + printf("https://sourceforge.net/p/snapraid/discussion/1677233/\n"); + + /* use exit() and not abort to avoid the Windows abort dialog */ + exit(EXIT_FAILURE); +} + +void os_clear(void) +{ + HANDLE console; + CONSOLE_SCREEN_BUFFER_INFO screen; + COORD coord; + DWORD written; + + /* get the console */ + console = GetStdHandle(STD_OUTPUT_HANDLE); + if (console == INVALID_HANDLE_VALUE) + return; + + /* get the screen size */ + if (!GetConsoleScreenBufferInfo(console, &screen)) + return; + + /* fill the screen with spaces */ + coord.X = 0; + coord.Y = 0; + FillConsoleOutputCharacterA(console, ' ', screen.dwSize.X * screen.dwSize.Y, coord, &written); + + /* set the cursor at the top left corner */ + SetConsoleCursorPosition(console, coord); +} + +/** + * Size in chars of conversion buffers for u8to16() and u16to8(). + */ +#define CONV_MAX PATH_MAX + +/** + * Convert a generic string from UTF8 to UTF16. + */ +static wchar_t* u8tou16(wchar_t* conv_buf, const char* src) +{ + int ret; + + ret = MultiByteToWideChar(CP_UTF8, 0, src, -1, conv_buf, CONV_MAX); + + if (ret <= 0) { + log_fatal("Error converting name '%s' from UTF-8 to UTF-16\n", src); + exit(EXIT_FAILURE); + } + + return conv_buf; +} + +/** + * Convert a generic string from UTF16 to UTF8. + */ +static char* u16tou8ex(char* conv_buf, const wchar_t* src, size_t number_of_wchar, size_t* result_length_without_terminator) +{ + int ret; + + ret = WideCharToMultiByte(CP_UTF8, 0, src, number_of_wchar, conv_buf, CONV_MAX, 0, 0); + if (ret <= 0) { + log_fatal("Error converting from UTF-16 to UTF-8\n"); + exit(EXIT_FAILURE); + } + + *result_length_without_terminator = ret; + + return conv_buf; +} + +static char* u16tou8(char* conv_buf, const wchar_t* src) +{ + size_t len; + + /* convert also the 0 terminator */ + return u16tou8ex(conv_buf, src, wcslen(src) + 1, &len); +} + +/** + * Check if the char is a forward or back slash. + */ +static int is_slash(char c) +{ + return c == '/' || c == '\\'; +} + +/** + * Convert a path to the Windows format. + * + * If only_is_required is 1, the extended-length format is used only if required. + * + * The exact operation done is: + * - If it's a '\\?\' or '\\.\' path, convert any '/' to '\'. + * - If it's a disk designator path, like 'D:\' or 'D:/', it prepends '\\?\' to the path and convert any '/' to '\'. + * - If it's a UNC path, like ''\\server'', it prepends '\\?\UNC\' to the path and convert any '/' to '\'. + * - Otherwise, only the UTF conversion is done. In this case Windows imposes a limit of 260 chars, and automatically convert any '/' to '\'. + * + * For more details see: + * Naming Files, Paths, and Namespaces + * http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx#maxpath + */ +static wchar_t* convert_arg(wchar_t* conv_buf, const char* src, int only_if_required) +{ + int ret; + wchar_t* dst; + int count; + + dst = conv_buf; + + /* note that we always check for both / and \ because the path is blindly */ + /* converted to unix format by path_import() */ + + if (only_if_required && strlen(src) < 260 - 12) { + /* it's a short path */ + /* 260 is the MAX_PATH, note that it includes the space for the terminating NUL */ + /* 12 is an additional space for filename, required when creating directory */ + + /* do nothing */ + } else if (is_slash(src[0]) && is_slash(src[1]) && (src[2] == '?' || src[2] == '.') && is_slash(src[3])) { + /* if it's already a '\\?\' or '\\.\' path */ + + /* do nothing */ + } else if (is_slash(src[0]) && is_slash(src[1])) { + /* if it is a UNC path, like '\\server' */ + + /* prefix with '\\?\UNC\' */ + *dst++ = L'\\'; + *dst++ = L'\\'; + *dst++ = L'?'; + *dst++ = L'\\'; + *dst++ = L'U'; + *dst++ = L'N'; + *dst++ = L'C'; + *dst++ = L'\\'; + + /* skip initial '\\' */ + src += 2; + } else if (src[0] != 0 && src[1] == ':' && is_slash(src[2])) { + /* if it is a disk designator path, like 'D:\' or 'D:/' */ + + /* prefix with '\\?\' */ + *dst++ = L'\\'; + *dst++ = L'\\'; + *dst++ = L'?'; + *dst++ = L'\\'; + } + + /* chars already used */ + count = dst - conv_buf; + + ret = MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, CONV_MAX - count); + + if (ret <= 0) { + log_fatal("Error converting name '%s' from UTF-8 to UTF-16\n", src); + exit(EXIT_FAILURE); + } + + /* convert any / to \ */ + /* note that in UTF-16, it's not possible to have '/' used as part */ + /* of a pair of codes representing a single UNICODE char */ + /* See: http://en.wikipedia.org/wiki/UTF-16 */ + while (*dst) { + if (*dst == L'/') + *dst = L'\\'; + ++dst; + } + + return conv_buf; +} + +#define convert(buf, a) convert_arg(buf, a, 0) +#define convert_if_required(buf, a) convert_arg(buf, a, 1) + +static BOOL GetReparseTagInfoByHandle(HANDLE hFile, FILE_ATTRIBUTE_TAG_INFO* lpFileAttributeTagInfo, DWORD dwFileAttributes) +{ + /* if not a reparse point, return no info */ + if ((dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0) { + lpFileAttributeTagInfo->FileAttributes = dwFileAttributes; + lpFileAttributeTagInfo->ReparseTag = 0; + return TRUE; + } + + /* do the real call */ + return GetFileInformationByHandleEx(hFile, FileAttributeTagInfo, lpFileAttributeTagInfo, sizeof(FILE_ATTRIBUTE_TAG_INFO)); +} + +/** + * Convert Windows attr to the Unix stat format. + */ +static void windows_attr2stat(DWORD FileAttributes, DWORD ReparseTag, struct windows_stat* st) +{ + /* Convert special attributes */ + if ((FileAttributes & FILE_ATTRIBUTE_DEVICE) != 0) { + st->st_mode = S_IFBLK; + st->st_desc = "device"; + } else if ((FileAttributes & FILE_ATTRIBUTE_OFFLINE) != 0) { /* Offline */ + st->st_mode = S_IFCHR; + st->st_desc = "offline"; + } else if ((FileAttributes & FILE_ATTRIBUTE_TEMPORARY) != 0) { /* Temporary */ + st->st_mode = S_IFCHR; + st->st_desc = "temporary"; + } else if ((FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) { /* Reparse point */ + switch (ReparseTag) { + /* if we don't have the ReparseTag information */ + case 0 : + /* don't set the st_mode, to set it later calling lstat_sync() */ + st->st_mode = 0; + st->st_desc = "unknown"; + break; + /* for deduplicated files, assume that they are regular ones */ + case IO_REPARSE_TAG_DEDUP : + if ((FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { + st->st_mode = S_IFDIR; + st->st_desc = "directory-dedup"; + } else { + st->st_mode = S_IFREG; + st->st_desc = "regular-dedup"; + } + break; + case IO_REPARSE_TAG_SYMLINK : + if ((FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { + st->st_mode = S_IFLNKDIR; + st->st_desc = "reparse-point-symlink-dir"; + } else { + st->st_mode = S_IFLNK; + st->st_desc = "reparse-point-symlink-file"; + } + break; + /* all the other are skipped as reparse-point */ + case IO_REPARSE_TAG_MOUNT_POINT : + st->st_mode = S_IFCHR; + st->st_desc = "reparse-point-mount"; + break; + case IO_REPARSE_TAG_NFS : + st->st_mode = S_IFCHR; + st->st_desc = "reparse-point-nfs"; + break; + default : + st->st_mode = S_IFCHR; + st->st_desc = "reparse-point"; + break; + } + } else if ((FileAttributes & FILE_ATTRIBUTE_SYSTEM) != 0) { /* System */ + if ((FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { + st->st_mode = S_IFCHR; + st->st_desc = "system-directory"; + } else { + st->st_mode = S_IFREG; + st->st_desc = "system-file"; + } + } else { + if ((FileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { + st->st_mode = S_IFDIR; + st->st_desc = "directory"; + } else { + st->st_mode = S_IFREG; + st->st_desc = "regular"; + } + } + + /* store the HIDDEN attribute in a separate field */ + st->st_hidden = (FileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0; +} + +/** + * Convert Windows info to the Unix stat format. + */ +static int windows_info2stat(const BY_HANDLE_FILE_INFORMATION* info, const FILE_ATTRIBUTE_TAG_INFO* tag, struct windows_stat* st) +{ + uint64_t mtime; + + windows_attr2stat(info->dwFileAttributes, tag->ReparseTag, st); + + st->st_size = info->nFileSizeHigh; + st->st_size <<= 32; + st->st_size |= info->nFileSizeLow; + + mtime = info->ftLastWriteTime.dwHighDateTime; + mtime <<= 32; + mtime |= info->ftLastWriteTime.dwLowDateTime; + + /* + * Convert to unix time + * + * How To Convert a UNIX time_t to a Win32 FILETIME or SYSTEMTIME + * http://support.microsoft.com/kb/167296 + */ + mtime -= 116444736000000000LL; + st->st_mtime = mtime / 10000000; + st->st_mtimensec = (mtime % 10000000) * 100; + + st->st_ino = info->nFileIndexHigh; + st->st_ino <<= 32; + st->st_ino |= info->nFileIndexLow; + + st->st_nlink = info->nNumberOfLinks; + + st->st_dev = info->dwVolumeSerialNumber; + + /* GetFileInformationByHandle() ensures to return synced information */ + st->st_sync = 1; + + /** + * In ReFS the IDs are 128 bit, and the 64 bit interface may fail. + * + * From Microsoft "Application Compatibility with ReFS" + * http://download.microsoft.com/download/C/B/3/CB3561DC-6BF6-443D-B5B9-9676ACDF7F75/Application%20Compatibility%20with%20ReFS.docx + * "64-bit file identifier can be obtained from GetFileInformationByHandle in" + * "the nFileIndexHigh and nFileIndexLow members. This API is an extended version" + * "that includes 128-bit file identifiers. If GetFileInformationByHandle returns" + * "FILE_INVALID_FILE_ID, the identifier may only be described in 128 bit form." + */ + if (st->st_ino == FILE_INVALID_FILE_ID) { + log_fatal("Invalid inode number! Is this ReFS?\n"); + errno = EINVAL; + return -1; + } + + return 0; +} + +/** + * Convert Windows info to the Unix stat format. + */ +static int windows_stream2stat(const BY_HANDLE_FILE_INFORMATION* info, const FILE_ID_BOTH_DIR_INFO* stream, struct windows_stat* st) +{ + uint64_t mtime; + + /* The FILE_ID_BOTH_DIR_INFO doesn't have the ReparseTag information */ + /* we could use instead FILE_ID_EXTD_DIR_INFO, but it's available only */ + /* from Windows Server 2012 */ + windows_attr2stat(stream->FileAttributes, 0, st); + + st->st_size = stream->EndOfFile.QuadPart; + + mtime = stream->LastWriteTime.QuadPart; + + /* + * Convert to unix time + * + * How To Convert a UNIX time_t to a Win32 FILETIME or SYSTEMTIME + * http://support.microsoft.com/kb/167296 + */ + mtime -= 116444736000000000LL; + st->st_mtime = mtime / 10000000; + st->st_mtimensec = (mtime % 10000000) * 100; + + st->st_ino = stream->FileId.QuadPart; + + st->st_nlink = info->nNumberOfLinks; + + st->st_dev = info->dwVolumeSerialNumber; + + /* directory listing doesn't ensure to return synced information */ + st->st_sync = 0; + + /* in ReFS the IDs are 128 bit, and the 64 bit interface may fail */ + if (st->st_ino == FILE_INVALID_FILE_ID) { + log_fatal("Invalid inode number! Is this ReFS?\n"); + errno = EINVAL; + return -1; + } + + return 0; +} + +/** + * Convert Windows findfirst info to the Unix stat format. + */ +static void windows_finddata2stat(const WIN32_FIND_DATAW* info, struct windows_stat* st) +{ + uint64_t mtime; + + windows_attr2stat(info->dwFileAttributes, info->dwReserved0, st); + + st->st_size = info->nFileSizeHigh; + st->st_size <<= 32; + st->st_size |= info->nFileSizeLow; + + mtime = info->ftLastWriteTime.dwHighDateTime; + mtime <<= 32; + mtime |= info->ftLastWriteTime.dwLowDateTime; + + /* + * Convert to unix time + * + * How To Convert a UNIX time_t to a Win32 FILETIME or SYSTEMTIME + * http://support.microsoft.com/kb/167296 + */ + mtime -= 116444736000000000LL; + st->st_mtime = mtime / 10000000; + st->st_mtimensec = (mtime % 10000000) * 100; + + /* No inode information available */ + st->st_ino = 0; + + /* No link information available */ + st->st_nlink = 0; + + /* No device information available */ + st->st_dev = 0; + + /* directory listing doesn't ensure to return synced information */ + st->st_sync = 0; +} + +static void windows_finddata2dirent(const WIN32_FIND_DATAW* info, struct windows_dirent* dirent) +{ + char conv_buf[CONV_MAX]; + const char* name; + size_t len; + + name = u16tou8ex(conv_buf, info->cFileName, wcslen(info->cFileName), &len); + + if (len + 1 >= sizeof(dirent->d_name)) { + log_fatal("Name too long\n"); + exit(EXIT_FAILURE); + } + + memcpy(dirent->d_name, name, len); + dirent->d_name[len] = 0; + + windows_finddata2stat(info, &dirent->d_stat); +} + +static int windows_stream2dirent(const BY_HANDLE_FILE_INFORMATION* info, const FILE_ID_BOTH_DIR_INFO* stream, struct windows_dirent* dirent) +{ + char conv_buf[CONV_MAX]; + const char* name; + size_t len; + + name = u16tou8ex(conv_buf, stream->FileName, stream->FileNameLength / 2, &len); + + if (len + 1 >= sizeof(dirent->d_name)) { + log_fatal("Name too long\n"); + exit(EXIT_FAILURE); + } + + memcpy(dirent->d_name, name, len); + dirent->d_name[len] = 0; + + return windows_stream2stat(info, stream, &dirent->d_stat); +} + +/** + * Convert Windows error to errno. + */ +static void windows_errno(DWORD error) +{ + switch (error) { + case ERROR_INVALID_HANDLE : + /* we check for a bad handle calling _get_osfhandle() */ + /* and in such case we return EBADF */ + /* Other cases are here identified with EINVAL */ + errno = EINVAL; + break; + case ERROR_HANDLE_EOF : /* in ReadFile() over the end of the file */ + errno = EINVAL; + break; + case ERROR_FILE_NOT_FOUND : + case ERROR_PATH_NOT_FOUND : /* in GetFileAttributeW() if internal path not found */ + errno = ENOENT; + break; + case ERROR_ACCESS_DENIED : /* in CreateDirectoryW() if dir is scheduled for deletion */ + case ERROR_CURRENT_DIRECTORY : /* in RemoveDirectoryW() if removing the current directory */ + case ERROR_SHARING_VIOLATION : /* in RemoveDirectoryW() if in use */ + case ERROR_WRITE_PROTECT : /* when dealing with read-only media/snapshot and trying to write to them */ + errno = EACCES; + break; + case ERROR_ALREADY_EXISTS : /* in CreateDirectoryW() if already exists */ + errno = EEXIST; + break; + case ERROR_DISK_FULL : + errno = ENOSPC; + break; + case ERROR_BUFFER_OVERFLOW : + errno = ENAMETOOLONG; + break; + case ERROR_NOT_ENOUGH_MEMORY : + errno = ENOMEM; + break; + case ERROR_NOT_SUPPORTED : /* in CreateSymlinkW() if not present in kernel32 */ + errno = ENOSYS; + break; + case ERROR_PRIVILEGE_NOT_HELD : /* in CreateSymlinkW() if no SeCreateSymbolicLinkPrivilige permission */ + errno = EPERM; + break; + case ERROR_IO_DEVICE : /* in ReadFile() and WriteFile() */ + errno = EIO; + break; + default : + log_fatal("Unexpected Windows error %d.\n", (int)error); + errno = EIO; + break; + } +} + +int windows_fstat(int fd, struct windows_stat* st) +{ + BY_HANDLE_FILE_INFORMATION info; + FILE_ATTRIBUTE_TAG_INFO tag; + HANDLE h; + + h = (HANDLE)_get_osfhandle(fd); + if (h == INVALID_HANDLE_VALUE) { + errno = EBADF; + return -1; + } + + if (!GetFileInformationByHandle(h, &info)) { + windows_errno(GetLastError()); + return -1; + } + + if (!GetReparseTagInfoByHandle(h, &tag, info.dwFileAttributes)) { + windows_errno(GetLastError()); + return -1; + } + + return windows_info2stat(&info, &tag, st); +} + +int windows_lstat(const char* file, struct windows_stat* st) +{ + wchar_t conv_buf[CONV_MAX]; + HANDLE h; + WIN32_FIND_DATAW data; + + /* FindFirstFileW by default gets information of symbolic links and not of their targets */ + h = FindFirstFileW(convert(conv_buf, file), &data); + if (h == INVALID_HANDLE_VALUE) { + windows_errno(GetLastError()); + return -1; + } + + if (!FindClose(h)) { + windows_errno(GetLastError()); + return -1; + } + + windows_finddata2stat(&data, st); + + return 0; +} + +void windows_dirent_lstat(const struct windows_dirent* dd, struct windows_stat* st) +{ + memcpy(st, &dd->d_stat, sizeof(struct windows_stat)); +} + +int windows_mkdir(const char* file) +{ + wchar_t conv_buf[CONV_MAX]; + + if (!CreateDirectoryW(convert(conv_buf, file), 0)) { + windows_errno(GetLastError()); + return -1; + } + + return 0; +} + +int windows_rmdir(const char* file) +{ + wchar_t conv_buf[CONV_MAX]; + + if (!RemoveDirectoryW(convert(conv_buf, file))) { + windows_errno(GetLastError()); + return -1; + } + + return 0; +} + +static BOOL GetFilePhysicalOffset(HANDLE h, uint64_t* physical) +{ + STARTING_VCN_INPUT_BUFFER svib; + unsigned char rpb_buffer[sizeof(RETRIEVAL_POINTERS_BUFFER)]; + RETRIEVAL_POINTERS_BUFFER* rpb = (RETRIEVAL_POINTERS_BUFFER*)&rpb_buffer; + BOOL ret; + DWORD n; + + /* in Wine FSCTL_GET_RETRIVIAL_POINTERS is not supported */ + if (is_wine) { + *physical = FILEPHY_UNREPORTED_OFFSET; + return TRUE; + } + + /* set the output variable, just to be safe */ + rpb->ExtentCount = 0; + + /* read the physical address */ + svib.StartingVcn.QuadPart = 0; + ret = DeviceIoControl(h, FSCTL_GET_RETRIEVAL_POINTERS, &svib, sizeof(svib), rpb_buffer, sizeof(rpb_buffer), &n, 0); + if (!ret) { + DWORD error = GetLastError(); + if (error == ERROR_MORE_DATA) { + /* we ignore ERROR_MODE_DATA because we are interested only at the first entry */ + /* and this is the expected error if the files has more entries */ + } else if (error == ERROR_HANDLE_EOF) { + /* if the file is small, it can be stored in the Master File Table (MFT) */ + /* and then it doesn't have a physical address */ + /* In such case we report a specific fake address, to report this special condition */ + /* that it's different from the 0 offset reported by the underline file system */ + *physical = FILEPHY_WITHOUT_OFFSET; + return TRUE; + } else if (error == ERROR_NOT_SUPPORTED) { + /* for disks shared on network this operation is not supported */ + *physical = FILEPHY_UNREPORTED_OFFSET; + return TRUE; + } else { + return FALSE; + } + } + + if (rpb->ExtentCount < 1) + *physical = FILEPHY_UNREPORTED_OFFSET; + else + *physical = rpb->Extents[0].Lcn.QuadPart + FILEPHY_REAL_OFFSET; + + return TRUE; +} + +int lstat_sync(const char* file, struct windows_stat* st, uint64_t* physical) +{ + wchar_t conv_buf[CONV_MAX]; + BY_HANDLE_FILE_INFORMATION info; + FILE_ATTRIBUTE_TAG_INFO tag; + HANDLE h; + + /* + * Open the handle of the file. + * + * Use FILE_FLAG_BACKUP_SEMANTICS to open directories (it's just ignored for files). + * Use FILE_FLAG_OPEN_REPARSE_POINT to open symbolic links and not the their target. + * + * Note that even with FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + * and FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT some paths + * cannot be opened like "C:\System Volume Information" resulting + * in error ERROR_ACCESS_DENIED. + */ + h = CreateFileW(convert(conv_buf, file), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0); + if (h == INVALID_HANDLE_VALUE) { + windows_errno(GetLastError()); + return -1; + } + + if (!GetFileInformationByHandle(h, &info)) { + DWORD error = GetLastError(); + CloseHandle(h); + windows_errno(error); + return -1; + } + + if (!GetReparseTagInfoByHandle(h, &tag, info.dwFileAttributes)) { + DWORD error = GetLastError(); + CloseHandle(h); + windows_errno(error); + return -1; + } + + /* read the physical offset, only if a pointer is provided */ + if (physical != 0) { + if (!GetFilePhysicalOffset(h, physical)) { + DWORD error = GetLastError(); + CloseHandle(h); + windows_errno(error); + return -1; + } + } + + if (!CloseHandle(h)) { + windows_errno(GetLastError()); + return -1; + } + + return windows_info2stat(&info, &tag, st); +} + +int windows_stat(const char* file, struct windows_stat* st) +{ + wchar_t conv_buf[CONV_MAX]; + BY_HANDLE_FILE_INFORMATION info; + FILE_ATTRIBUTE_TAG_INFO tag; + HANDLE h; + + /* + * Open the handle of the file. + * + * Use FILE_FLAG_BACKUP_SEMANTICS to open directories (it's just ignored for files). + */ + h = CreateFileW(convert(conv_buf, file), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); + if (h == INVALID_HANDLE_VALUE) { + windows_errno(GetLastError()); + return -1; + } + + if (!GetFileInformationByHandle(h, &info)) { + DWORD error = GetLastError(); + CloseHandle(h); + windows_errno(error); + return -1; + } + + if (!GetReparseTagInfoByHandle(h, &tag, info.dwFileAttributes)) { + DWORD error = GetLastError(); + CloseHandle(h); + windows_errno(error); + return -1; + } + + if (!CloseHandle(h)) { + windows_errno(GetLastError()); + return -1; + } + + return windows_info2stat(&info, &tag, st); +} + +int windows_ftruncate(int fd, off64_t off) +{ + HANDLE h; + LARGE_INTEGER pos; + + if (fd == -1) { + errno = EBADF; + return -1; + } + + h = (HANDLE)_get_osfhandle(fd); + if (h == INVALID_HANDLE_VALUE) { + errno = EBADF; + return -1; + } + + pos.QuadPart = off; + if (!SetFilePointerEx(h, pos, 0, FILE_BEGIN)) { + windows_errno(GetLastError()); + return -1; + } + + /* + * Windows effectively reserves space, but it doesn't initialize it. + * It's then important to write starting from the begin to the end, + * to avoid to have Windows to fill the holes writing zeros. + * + * See: + * "Why does my single-byte write take forever?" + * http://blogs.msdn.com/b/oldnewthing/archive/2011/09/22/10215053.aspx + */ + if (!SetEndOfFile(h)) { + windows_errno(GetLastError()); + return -1; + } + + return 0; +} + +int windows_fallocate(int fd, int mode, off64_t off, off64_t len) +{ + if (mode != 0) + return -1; + + /* no difference with ftruncate because Windows doesn't use sparse files */ + return windows_ftruncate(fd, off + len); +} + +int windows_fsync(int fd) +{ + HANDLE h; + + if (fd == -1) { + errno = EBADF; + return -1; + } + + h = (HANDLE)_get_osfhandle(fd); + if (h == INVALID_HANDLE_VALUE) { + errno = EBADF; + return -1; + } + + /* + * "The FlushFileBuffers API can be used to flush all the outstanding data + * and metadata on a single file or a whole volume. However, frequent use + * of this API can cause reduced throughput. Internally, Windows uses the + * SCSI Synchronize Cache or the IDE/ATAPI Flush cache commands." + * + * From: + * "Windows Write Caching - Part 2 An overview for Application Developers" + * http://winntfs.com/2012/11/29/windows-write-caching-part-2-an-overview-for-application-developers/ + */ + if (!FlushFileBuffers(h)) { + DWORD error = GetLastError(); + + switch (error) { + case ERROR_INVALID_HANDLE : + /* + * FlushFileBuffers returns this error if the handle + * doesn't support buffering, like the console output. + * + * We had a report that also ATA-over-Ethernet returns + * this error, but not enough sure to ignore it. + * So, we use now an extended error reporting. + */ + log_fatal("Unexpected Windows INVALID_HANDLE error in FlushFileBuffers().\n"); + log_fatal("Are you using ATA-over-Ethernet ? Please report it.\n"); + + /* normal error processing */ + windows_errno(error); + return -1; + + case ERROR_ACCESS_DENIED : + /* + * FlushFileBuffers returns this error for read-only + * data, that cannot have to be flushed. + */ + return 0; + + default : + windows_errno(error); + return -1; + } + } + + return 0; +} + +int windows_futimens(int fd, struct windows_timespec tv[2]) +{ + HANDLE h; + FILETIME ft; + uint64_t mtime; + + if (fd == -1) { + errno = EBADF; + return -1; + } + + h = (HANDLE)_get_osfhandle(fd); + if (h == INVALID_HANDLE_VALUE) { + errno = EBADF; + return -1; + } + + /* + * Convert to windows time + * + * How To Convert a UNIX time_t to a Win32 FILETIME or SYSTEMTIME + * http://support.microsoft.com/kb/167296 + */ + mtime = tv[0].tv_sec; + mtime *= 10000000; + mtime += tv[0].tv_nsec / 100; + mtime += 116444736000000000; + + ft.dwHighDateTime = mtime >> 32; + ft.dwLowDateTime = mtime; + + if (!SetFileTime(h, 0, 0, &ft)) { + windows_errno(GetLastError()); + return -1; + } + + return 0; +} + +int windows_utimensat(int fd, const char* file, struct windows_timespec tv[2], int flags) +{ + wchar_t conv_buf[CONV_MAX]; + HANDLE h; + FILETIME ft; + uint64_t mtime; + DWORD wflags; + + /* + * Support only the absolute paths + */ + if (fd != AT_FDCWD) { + errno = EBADF; + return -1; + } + + /* + * Open the handle of the file. + * + * Use FILE_FLAG_BACKUP_SEMANTICS to open directories (it's just ignored for files). + * Use FILE_FLAG_OPEN_REPARSE_POINT to open symbolic links and not the their target. + * + * Note that even with FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + * and FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT some paths + * cannot be opened like "C:\System Volume Information" resulting + * in error ERROR_ACCESS_DENIED. + */ + wflags = FILE_FLAG_BACKUP_SEMANTICS; + if ((flags & AT_SYMLINK_NOFOLLOW) != 0) + wflags |= FILE_FLAG_OPEN_REPARSE_POINT; + h = CreateFileW(convert(conv_buf, file), FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, wflags, 0); + if (h == INVALID_HANDLE_VALUE) { + windows_errno(GetLastError()); + return -1; + } + + /* + * Convert to windows time + * + * How To Convert a UNIX time_t to a Win32 FILETIME or SYSTEMTIME + * http://support.microsoft.com/kb/167296 + */ + mtime = tv[0].tv_sec; + mtime *= 10000000; + mtime += tv[0].tv_nsec / 100; + mtime += 116444736000000000; + + ft.dwHighDateTime = mtime >> 32; + ft.dwLowDateTime = mtime; + + if (!SetFileTime(h, 0, 0, &ft)) { + windows_errno(GetLastError()); + CloseHandle(h); + return -1; + } + + if (!CloseHandle(h)) { + windows_errno(GetLastError()); + return -1; + } + + return 0; +} + +int windows_rename(const char* from, const char* to) +{ + wchar_t conv_buf_from[CONV_MAX]; + wchar_t conv_buf_to[CONV_MAX]; + + /* + * Implements an atomic rename in Windows. + * Not really atomic at now to support XP. + * + * Is an atomic file rename (with overwrite) possible on Windows? + * http://stackoverflow.com/questions/167414/is-an-atomic-file-rename-with-overwrite-possible-on-windows + */ + if (!MoveFileExW(convert(conv_buf_from, from), convert(conv_buf_to, to), MOVEFILE_REPLACE_EXISTING)) { + windows_errno(GetLastError()); + return -1; + } + + return 0; +} + +int windows_remove(const char* file) +{ + wchar_t conv_buf[CONV_MAX]; + + if (!DeleteFileW(convert(conv_buf, file))) { + windows_errno(GetLastError()); + return -1; + } + + return 0; +} + +FILE* windows_fopen(const char* file, const char* mode) +{ + wchar_t conv_buf_file[CONV_MAX]; + wchar_t conv_buf_mode[CONV_MAX]; + + return _wfopen(convert(conv_buf_file, file), u8tou16(conv_buf_mode, mode)); +} + +int windows_open(const char* file, int flags, ...) +{ + wchar_t conv_buf[CONV_MAX]; + HANDLE h; + int f; + DWORD access; + DWORD share; + DWORD create; + DWORD attr; + + switch (flags & O_ACCMODE) { + case O_RDONLY : + access = GENERIC_READ; + break; + case O_WRONLY : + access = GENERIC_WRITE; + break; + case O_RDWR : + access = GENERIC_READ | GENERIC_WRITE; + break; + default: + errno = EINVAL; + return -1; + } + + share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; + + switch (flags & (O_CREAT | O_EXCL | O_TRUNC)) { + case 0 : + create = OPEN_EXISTING; + break; + case O_CREAT : + create = OPEN_ALWAYS; + break; + case O_CREAT | O_EXCL : + case O_CREAT | O_EXCL | O_TRUNC : + create = CREATE_NEW; + break; + case O_CREAT | O_TRUNC : + create = CREATE_ALWAYS; + break; + case O_TRUNC : + create = TRUNCATE_EXISTING; + break; + default: + errno = EINVAL; + return -1; + } + + attr = FILE_ATTRIBUTE_NORMAL; + if ((flags & O_DIRECT) != 0) + attr |= FILE_FLAG_NO_BUFFERING; + if ((flags & O_DSYNC) != 0) + attr |= FILE_FLAG_WRITE_THROUGH; + if ((flags & O_RANDOM) != 0) + attr |= FILE_FLAG_RANDOM_ACCESS; + if ((flags & O_SEQUENTIAL) != 0) + attr |= FILE_FLAG_SEQUENTIAL_SCAN; + if ((flags & _O_SHORT_LIVED) != 0) + attr |= FILE_ATTRIBUTE_TEMPORARY; + if ((flags & O_TEMPORARY) != 0) + attr |= FILE_FLAG_DELETE_ON_CLOSE; + + h = CreateFileW(convert(conv_buf, file), access, share, 0, create, attr, 0); + if (h == INVALID_HANDLE_VALUE) { + windows_errno(GetLastError()); + return -1; + } + + /* mask out flags unknown by Windows */ + flags &= ~(O_DIRECT | O_DSYNC); + + f = _open_osfhandle((intptr_t)h, flags); + if (f == -1) { + CloseHandle(h); + return -1; + } + + return f; +} + +struct windows_dir_struct { + BY_HANDLE_FILE_INFORMATION info; + WIN32_FIND_DATAW find; + HANDLE h; + struct windows_dirent entry; + unsigned char* buffer; + unsigned buffer_size; + unsigned buffer_pos; + int state; +}; + +#define DIR_STATE_EOF -1 /**< End of the dir stream */ +#define DIR_STATE_EMPTY 0 /**< The entry is empty. */ +#define DIR_STATE_FILLED 1 /**< The entry is valid. */ + +static windows_dir* windows_opendir_find(const char* dir) +{ + wchar_t conv_buf[CONV_MAX]; + wchar_t* wdir; + windows_dir* dirstream; + size_t len; + + dirstream = malloc(sizeof(windows_dir)); + if (!dirstream) { + log_fatal("Low memory\n"); + exit(EXIT_FAILURE); + } + + wdir = convert(conv_buf, dir); + + /* add final / and * */ + len = wcslen(wdir); + if (len != 0 && wdir[len - 1] != '\\') + wdir[len++] = L'\\'; + wdir[len++] = L'*'; + wdir[len++] = 0; + + dirstream->h = FindFirstFileW(wdir, &dirstream->find); + if (dirstream->h == INVALID_HANDLE_VALUE) { + DWORD error = GetLastError(); + + if (error == ERROR_FILE_NOT_FOUND) { + dirstream->state = DIR_STATE_EOF; + return dirstream; + } + + free(dirstream); + windows_errno(error); + return 0; + } + + windows_finddata2dirent(&dirstream->find, &dirstream->entry); + dirstream->state = DIR_STATE_FILLED; + + return dirstream; +} + +static struct windows_dirent* windows_readdir_find(windows_dir* dirstream) +{ + if (dirstream->state == DIR_STATE_EMPTY) { + if (!FindNextFileW(dirstream->h, &dirstream->find)) { + DWORD error = GetLastError(); + + if (error != ERROR_NO_MORE_FILES) { + windows_errno(error); + return 0; + } + + dirstream->state = DIR_STATE_EOF; + } else { + windows_finddata2dirent(&dirstream->find, &dirstream->entry); + dirstream->state = DIR_STATE_FILLED; + } + } + + if (dirstream->state == DIR_STATE_FILLED) { + dirstream->state = DIR_STATE_EMPTY; + return &dirstream->entry; + } + + /* otherwise it's the end of stream */ + assert(dirstream->state == DIR_STATE_EOF); + errno = 0; + + return 0; +} + +static int windows_closedir_find(windows_dir* dirstream) +{ + if (dirstream->h != INVALID_HANDLE_VALUE) { + if (!FindClose(dirstream->h)) { + DWORD error = GetLastError(); + + free(dirstream); + + windows_errno(error); + return -1; + } + } + + free(dirstream); + + return 0; +} + +static int windows_first_stream(windows_dir* dirstream) +{ + FILE_ID_BOTH_DIR_INFO* fd; + + if (!GetFileInformationByHandleEx(dirstream->h, FileIdBothDirectoryInfo, dirstream->buffer, dirstream->buffer_size)) { + DWORD error = GetLastError(); + + if (error == ERROR_NO_MORE_FILES) { + dirstream->state = DIR_STATE_EOF; + return 0; + } + + windows_errno(error); + return -1; + } + + /* get the first entry */ + dirstream->state = DIR_STATE_FILLED; + dirstream->buffer_pos = 0; + fd = (FILE_ID_BOTH_DIR_INFO*)dirstream->buffer; + return windows_stream2dirent(&dirstream->info, fd, &dirstream->entry); +} + +static int windows_next_stream(windows_dir* dirstream) +{ + FILE_ID_BOTH_DIR_INFO* fd; + + /* last entry read */ + fd = (FILE_ID_BOTH_DIR_INFO*)(dirstream->buffer + dirstream->buffer_pos); + + /* check if there is a next one */ + if (fd->NextEntryOffset == 0) { + /* if not, fill it up again */ + if (windows_first_stream(dirstream) != 0) + return -1; + return 0; + } + + /* go to the next one */ + dirstream->state = DIR_STATE_FILLED; + dirstream->buffer_pos += fd->NextEntryOffset; + fd = (FILE_ID_BOTH_DIR_INFO*)(dirstream->buffer + dirstream->buffer_pos); + return windows_stream2dirent(&dirstream->info, fd, &dirstream->entry); +} + +static windows_dir* windows_opendir_stream(const char* dir) +{ + wchar_t conv_buf[CONV_MAX]; + windows_dir* dirstream; + WCHAR* wdir; + + dirstream = malloc(sizeof(windows_dir)); + if (!dirstream) { + log_fatal("Low memory\n"); + exit(EXIT_FAILURE); + } + + wdir = convert(conv_buf, dir); + + /* uses a 64 kB buffer for reading directory */ + dirstream->buffer_size = 64 * 1024; + dirstream->buffer = malloc(dirstream->buffer_size); + if (!dirstream->buffer) { + log_fatal("Low memory\n"); + exit(EXIT_FAILURE); + } + + dirstream->h = CreateFileW(wdir, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); + if (dirstream->h == INVALID_HANDLE_VALUE) { + DWORD error = GetLastError(); + free(dirstream->buffer); + free(dirstream); + windows_errno(error); + return 0; + } + + /* get dir information for the VolumeSerialNumber */ + /* this value is used for all the files in the dir */ + if (!GetFileInformationByHandle(dirstream->h, &dirstream->info)) { + DWORD error = GetLastError(); + CloseHandle(dirstream->h); + free(dirstream->buffer); + free(dirstream); + windows_errno(error); + return 0; + } + + if (windows_first_stream(dirstream) != 0) { + CloseHandle(dirstream->h); + free(dirstream->buffer); + free(dirstream); + return 0; + } + + return dirstream; +} + +static struct windows_dirent* windows_readdir_stream(windows_dir* dirstream) +{ + if (dirstream->state == DIR_STATE_EMPTY) { + if (windows_next_stream(dirstream) != 0) { + free(dirstream->buffer); + free(dirstream); + return 0; + } + } + + if (dirstream->state == DIR_STATE_FILLED) { + dirstream->state = DIR_STATE_EMPTY; + return &dirstream->entry; + } + + /* otherwise it's the end of stream */ + assert(dirstream->state == DIR_STATE_EOF); + errno = 0; + + return 0; +} + +static int windows_closedir_stream(windows_dir* dirstream) +{ + if (dirstream->h != INVALID_HANDLE_VALUE) { + if (!CloseHandle(dirstream->h)) { + DWORD error = GetLastError(); + + free(dirstream->buffer); + free(dirstream); + + windows_errno(error); + return -1; + } + } + + free(dirstream->buffer); + free(dirstream); + + return 0; +} + +windows_dir* windows_opendir(const char* dir) +{ + if (!is_scan_winfind) + return windows_opendir_stream(dir); + else + return windows_opendir_find(dir); +} + +struct windows_dirent* windows_readdir(windows_dir* dirstream) +{ + if (!is_scan_winfind) + return windows_readdir_stream(dirstream); + else + return windows_readdir_find(dirstream); +} + +int windows_closedir(windows_dir* dirstream) +{ + if (!is_scan_winfind) + return windows_closedir_stream(dirstream); + else + return windows_closedir_find(dirstream); +} + +int windows_dirent_hidden(struct dirent* dd) +{ + return dd->d_stat.st_hidden; +} + +const char* windows_stat_desc(struct stat* st) +{ + return st->st_desc; +} + +void windows_sleep(unsigned seconds) +{ + Sleep(seconds * 1000); +} + +int windows_link(const char* existing, const char* file) +{ + wchar_t conv_buf_file[CONV_MAX]; + wchar_t conv_buf_existing[CONV_MAX]; + + if (!CreateHardLinkW(convert(conv_buf_file, file), convert(conv_buf_existing, existing), 0)) { + windows_errno(GetLastError()); + return -1; + } + + return 0; +} + +/** + * In Windows 10 allow creationg of symblink by not priviliged user. + * + * See: Symlinks in Windows 10! + * https://blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/#cQG7cx48oGH86lkI.97 + * "Specify this flag to allow creation of symbolic links when the process is not elevated" + */ +#ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE +#define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE 0x2 +#endif + +int windows_symlink(const char* existing, const char* file) +{ + wchar_t conv_buf_file[CONV_MAX]; + wchar_t conv_buf_existing[CONV_MAX]; + + /* We must convert to the extended-length \\?\ format if the path is too long */ + /* otherwise the link creation fails. */ + /* But we don't want to always convert it, to avoid to recreate */ + /* user symlinks different than they were before */ + if (!CreateSymbolicLinkW(convert(conv_buf_file, file), convert_if_required(conv_buf_existing, existing), + SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE) + ) { + DWORD error = GetLastError(); + if (GetLastError() != ERROR_INVALID_PARAMETER) { + windows_errno(error); + return -1; + } + + /* retry without the new flag SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE */ + if (!CreateSymbolicLinkW(convert(conv_buf_file, file), convert_if_required(conv_buf_existing, existing), 0)) { + windows_errno(GetLastError()); + return -1; + } + } + + return 0; +} + +/* Adds missing definitions in MingW winnt.h */ +#ifndef FSCTL_GET_REPARSE_POINT +#define FSCTL_GET_REPARSE_POINT 0x000900a8 +#endif +#ifndef REPARSE_DATA_BUFFER_HEADER_SIZE +typedef struct _REPARSE_DATA_BUFFER { + DWORD ReparseTag; + WORD ReparseDataLength; + WORD Reserved; + _ANONYMOUS_UNION union { + struct { + WORD SubstituteNameOffset; + WORD SubstituteNameLength; + WORD PrintNameOffset; + WORD PrintNameLength; + ULONG Flags; + WCHAR PathBuffer[1]; + } SymbolicLinkReparseBuffer; + struct { + WORD SubstituteNameOffset; + WORD SubstituteNameLength; + WORD PrintNameOffset; + WORD PrintNameLength; + WCHAR PathBuffer[1]; + } MountPointReparseBuffer; + struct { + BYTE DataBuffer[1]; + } GenericReparseBuffer; + } DUMMYUNIONNAME; +} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER; +#endif + +int windows_readlink(const char* file, char* buffer, size_t size) +{ + wchar_t conv_buf_file[CONV_MAX]; + char conv_buf_name[CONV_MAX]; + HANDLE h; + const char* name; + size_t len; + unsigned char rdb_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + REPARSE_DATA_BUFFER* rdb = (REPARSE_DATA_BUFFER*)rdb_buffer; + BOOL ret; + DWORD n; + + /* + * Open the handle of the file. + * + * Use FILE_FLAG_BACKUP_SEMANTICS to open directories (it's just ignored for files). + * Use FILE_FLAG_OPEN_REPARSE_POINT to open symbolic links and not the their target. + */ + h = CreateFileW(convert(conv_buf_file, file), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, 0); + if (h == INVALID_HANDLE_VALUE) { + windows_errno(GetLastError()); + return -1; + } + + /* read the reparse point */ + ret = DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, 0, 0, rdb_buffer, sizeof(rdb_buffer), &n, 0); + if (!ret) { + windows_errno(GetLastError()); + CloseHandle(h); + return -1; + } + + CloseHandle(h); + + /* check if it's really a symbolic link */ + if (rdb->ReparseTag != IO_REPARSE_TAG_SYMLINK) { + errno = EINVAL; + return -1; + } + + /* convert the name to UTF-8 */ + name = u16tou8ex(conv_buf_name, + rdb->SymbolicLinkReparseBuffer.PathBuffer + rdb->SymbolicLinkReparseBuffer.PrintNameOffset, + rdb->SymbolicLinkReparseBuffer.PrintNameLength / 2, &len); + + /* check for overflow */ + if (len > size) { + len = size; + } + + memcpy(buffer, name, len); + + return len; +} + +int devuuid(uint64_t device, char* uuid, size_t uuid_size) +{ + /* just use the volume serial number returned in the device parameter */ + snprintf(uuid, uuid_size, "%08x", (unsigned)device); + + log_tag("uuid:windows:%u:%s:\n", (unsigned)device, uuid); + + return 0; +} + +int filephy(const char* file, uint64_t size, uint64_t* physical) +{ + wchar_t conv_buf[CONV_MAX]; + HANDLE h; + + (void)size; + + /* open the handle of the file */ + h = CreateFileW(convert(conv_buf, file), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, 0); + if (h == INVALID_HANDLE_VALUE) { + windows_errno(GetLastError()); + return -1; + } + + if (!GetFilePhysicalOffset(h, physical)) { + DWORD error = GetLastError(); + CloseHandle(h); + windows_errno(error); + return -1; + } + + CloseHandle(h); + return 0; +} + +int fsinfo(const char* path, int* has_persistent_inode, int* has_syncronized_hardlinks, uint64_t* total_space, uint64_t* free_space) +{ + wchar_t conv_buf[CONV_MAX]; + + /* all FAT/exFAT/NTFS when managed from Windows have persistent inodes */ + if (has_persistent_inode) + *has_persistent_inode = 1; + + /* NTFS doesn't syncronize hardlinks metadata */ + if (has_syncronized_hardlinks) + *has_syncronized_hardlinks = 0; + + if (free_space || total_space) { + ULARGE_INTEGER total_bytes; + ULARGE_INTEGER total_free_bytes; + DWORD attr; + char dir[PATH_MAX]; + + if (strlen(path) + 1 > sizeof(dir)) { + windows_errno(ERROR_BUFFER_OVERFLOW); + return -1; + } + + strcpy(dir, path); + + /* get the file attributes */ + attr = GetFileAttributesW(convert(conv_buf, dir)); + if (attr == INVALID_FILE_ATTRIBUTES) { + DWORD error = GetLastError(); + + if (error != ERROR_FILE_NOT_FOUND) { + windows_errno(error); + return -1; + } + + /* if it doesn't exist, we assume a file */ + /* and we check for the containing dir */ + attr = 0; + } + + /* if it's not a directory, truncate the file name */ + if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) { + char* slash = strrchr(dir, '/'); + + /** + * Cut the file name, but leave the last slash. + * + * This is done because a MSDN comment about using of UNC paths. + * + * MSDN 'GetDiskFreeSpaceEx function' + * http://msdn.microsoft.com/en-us/library/windows/desktop/aa364937%28v=vs.85%29.aspx + * If this parameter is a UNC name, it must include a trailing backslash, + * for example, "\\MyServer\MyShare\". + */ + if (slash) + slash[1] = 0; + } + + /* get the free space of the directory */ + /* note that it must be a directory */ + if (!GetDiskFreeSpaceExW(convert(conv_buf, dir), 0, &total_bytes, &total_free_bytes)) { + windows_errno(GetLastError()); + return -1; + } + + if (total_space) + *total_space = total_bytes.QuadPart; + if (free_space) + *free_space = total_free_bytes.QuadPart; + } + + return 0; +} + +/* ensure to call the real C strerror() */ +#undef strerror + +const char* windows_strerror(int err) +{ + /* get the normal C error from the specified err */ + char* error; + char* previous; + const char* str = strerror(err); + size_t len = strlen(str); + + /* adds space for GetLastError() */ + len += 32; + + /* allocate a new one */ + error = malloc(len); + if (!error) + return str; + snprintf(error, len, "%s [%d/%u]", str, err, (unsigned)GetLastError()); + + /* get previous one, if any */ + previous = pthread_getspecific(last_error); + + /* store in the thread local storage */ + if (pthread_setspecific(last_error, error) != 0) { + free(error); + return str; + } + + free(previous); + return error; +} + +ssize_t windows_read(int fd, void* buffer, size_t size) +{ + HANDLE h; + DWORD count; + + if (fd == -1) { + errno = EBADF; + return -1; + } + + h = (HANDLE)_get_osfhandle(fd); + if (h == INVALID_HANDLE_VALUE) { + errno = EBADF; + return -1; + } + + if (!ReadFile(h, buffer, size, &count, 0)) { + windows_errno(GetLastError()); + return -1; + } + + return count; +} + +ssize_t windows_write(int fd, const void* buffer, size_t size) +{ + HANDLE h; + DWORD count; + + if (fd == -1) { + errno = EBADF; + return -1; + } + + h = (HANDLE)_get_osfhandle(fd); + if (h == INVALID_HANDLE_VALUE) { + errno = EBADF; + return -1; + } + + if (!WriteFile(h, buffer, size, &count, 0)) { + windows_errno(GetLastError()); + return -1; + } + + return count; +} + +off_t windows_lseek(int fd, off_t offset, int whence) +{ + HANDLE h; + LARGE_INTEGER pos; + LARGE_INTEGER ret; + + if (fd == -1) { + errno = EBADF; + return -1; + } + + /* we support only SEEK_SET */ + if (whence != SEEK_SET) { + errno = EINVAL; + return -1; + } + + h = (HANDLE)_get_osfhandle(fd); + if (h == INVALID_HANDLE_VALUE) { + errno = EBADF; + return -1; + } + + pos.QuadPart = offset; + if (!SetFilePointerEx(h, pos, &ret, FILE_BEGIN)) { + windows_errno(GetLastError()); + return -1; + } + + return ret.QuadPart; +} + +ssize_t windows_pread(int fd, void* buffer, size_t size, off_t offset) +{ + HANDLE h; + OVERLAPPED overlapped; + DWORD count; + + if (fd == -1) { + errno = EBADF; + return -1; + } + + h = (HANDLE)_get_osfhandle(fd); + if (h == INVALID_HANDLE_VALUE) { + errno = EBADF; + return -1; + } + +retry: + memset(&overlapped, 0, sizeof(overlapped)); + overlapped.Offset = offset & 0xFFFFFFFF; + overlapped.OffsetHigh = offset >> 32; + + if (!ReadFile(h, buffer, size, &count, &overlapped)) { + DWORD err = GetLastError(); + /* + * If Windows is not able to allocate memory from the PagedPool for the disk cache + * it could return the ERROR_NO_SYSTEM_RESOURCES error. + * In this case, the only possibility is to retry after a wait of few milliseconds. + * + * SQL Server reports operating system error 1450 or 1452 or 665 (retries) + * http://blogs.msdn.com/b/psssql/archive/2008/07/10/sql-server-reports-operating-system-error-1450-or-1452-or-665-retries.aspx + * + * 03-12-09 - ERROR_NO_SYSTEM_RESOURCES + * http://cbloomrants.blogspot.it/2009/03/03-12-09-errornosystemresources.html + * + * From SnapRAID Discussion Forum: + * + * Error reading file + * https://sourceforge.net/p/snapraid/discussion/1677233/thread/6657fdbf/ + * + * Unexpected Windows ERROR_NO_SYSTEM_RESOURCES in pwrite(), retrying... + * https://sourceforge.net/p/snapraid/discussion/1677233/thread/a7c25ba9/ + */ + if (err == ERROR_NO_SYSTEM_RESOURCES) { + log_fatal("Unexpected Windows ERROR_NO_SYSTEM_RESOURCES in pread(), retrying...\n"); + Sleep(50); + goto retry; + } + + windows_errno(err); + return -1; + } + + return count; +} + +ssize_t windows_pwrite(int fd, const void* buffer, size_t size, off_t offset) +{ + HANDLE h; + OVERLAPPED overlapped; + DWORD count; + + if (fd == -1) { + errno = EBADF; + return -1; + } + + h = (HANDLE)_get_osfhandle(fd); + if (h == INVALID_HANDLE_VALUE) { + errno = EBADF; + return -1; + } + +retry: + memset(&overlapped, 0, sizeof(overlapped)); + overlapped.Offset = offset & 0xFFFFFFFF; + overlapped.OffsetHigh = offset >> 32; + + if (!WriteFile(h, buffer, size, &count, &overlapped)) { + DWORD err = GetLastError(); + /* See windows_pread() for comments on this error management */ + if (err == ERROR_NO_SYSTEM_RESOURCES) { + log_fatal("Unexpected Windows ERROR_NO_SYSTEM_RESOURCES in pwrite(), retrying...\n"); + Sleep(50); + goto retry; + } + + windows_errno(err); + return -1; + } + + return count; +} + +size_t windows_direct_size(void) +{ + SYSTEM_INFO si; + + GetSystemInfo(&si); + + /* + * MSDN 'File Buffering' + * https://msdn.microsoft.com/en-us/library/windows/desktop/cc644950%28v=vs.85%29.aspx + * + * "Therefore, in most situations, page-aligned memory will also be sector-aligned," + * "because the case where the sector size is larger than the page size is rare." + */ + return si.dwPageSize; +} + +uint64_t tick(void) +{ + LARGE_INTEGER t; + uint64_t r; + + /* + * Ensure to return a strict monotone tick counter. + * + * We had reports of invalid stats due faulty High Precision Event Timer. + * See: https://sourceforge.net/p/snapraid/discussion/1677233/thread/a2122fd6/ + */ + pthread_mutex_lock(&tick_lock); + + /* + * MSDN 'QueryPerformanceCounter' + * "On systems that run Windows XP or later, the function" + * "will always succeed and will thus never return zero." + */ + r = 0; + if (QueryPerformanceCounter(&t)) + r = t.QuadPart; + + if (r < tick_last) + r = tick_last; + tick_last = r; + + pthread_mutex_unlock(&tick_lock); + + return r; +} + +uint64_t tick_ms(void) +{ + /* GetTickCount64() isn't supported in Windows XP */ + if (ptr_GetTickCount64 != 0) + return ptr_GetTickCount64(); + + return GetTickCount(); +} + +int randomize(void* void_ptr, size_t size) +{ + size_t i; + unsigned char* ptr = void_ptr; + + /* try RtlGenRandom */ + if (ptr_RtlGenRandom != 0 && ptr_RtlGenRandom(ptr, size) != 0) + return 0; + + /* try rand_s */ + for (i = 0; i < size; ++i) { + unsigned v = 0; + + if (rand_s(&v) != 0) + break; + + ptr[i] = v; + } + if (i == size) + return 0; + + /* fallback to standard rand */ + for (i = 0; i < size; ++i) + ptr[i] = rand(); + + return 0; +} + +/** + * Get the device file from a path inside the device. + */ +static int devresolve(const char* mount, char* file, size_t file_size, char* wfile, size_t wfile_size) +{ + wchar_t conv_buf_mount[CONV_MAX]; + char conv_buf_volume_guid[CONV_MAX]; + WCHAR volume_mount[MAX_PATH]; + WCHAR volume_guid[MAX_PATH]; + DWORD i; + char* p; + + /* get the volume mount point from the disk path */ + if (!GetVolumePathNameW(convert(conv_buf_mount, mount), volume_mount, sizeof(volume_mount) / sizeof(WCHAR))) { + windows_errno(GetLastError()); + return -1; + } + + /* get the volume GUID path from the mount point */ + if (!GetVolumeNameForVolumeMountPointW(volume_mount, volume_guid, sizeof(volume_guid) / sizeof(WCHAR))) { + windows_errno(GetLastError()); + return -1; + } + + /* remove the final slash, otherwise CreateFile() opens the file-system */ + /* and not the volume */ + i = 0; + while (volume_guid[i] != 0) + ++i; + if (i != 0 && volume_guid[i - 1] == '\\') + volume_guid[i - 1] = 0; + + pathcpy(wfile, wfile_size, u16tou8(conv_buf_volume_guid, volume_guid)); + + /* get the GUID start { */ + p = strchr(wfile, '{'); + if (!p) + p = wfile; + else + ++p; + + pathprint(file, file_size, "/dev/vol%s", p); + + /* cut GUID end } */ + p = strrchr(file, '}'); + if (p) + *p = 0; + + return 0; +} + +/** + * Read a device tree filling the specified list of disk_t entries. + */ +static int devtree(const char* name, const char* custom, const char* wfile, devinfo_t* parent, tommy_list* list) +{ + wchar_t conv_buf[CONV_MAX]; + HANDLE h; + unsigned char vde_buffer[sizeof(VOLUME_DISK_EXTENTS)]; + VOLUME_DISK_EXTENTS* vde = (VOLUME_DISK_EXTENTS*)&vde_buffer; + unsigned vde_size = sizeof(vde_buffer); + void* vde_alloc = 0; + BOOL ret; + DWORD n; + DWORD i; + + /* open the volume */ + h = CreateFileW(convert(conv_buf, wfile), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); + if (h == INVALID_HANDLE_VALUE) { + windows_errno(GetLastError()); + return -1; + } + + /* get the physical extents of the volume */ + ret = DeviceIoControl(h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, 0, 0, vde, vde_size, &n, 0); + if (!ret) { + DWORD error = GetLastError(); + if (error != ERROR_MORE_DATA) { + CloseHandle(h); + windows_errno(error); + } + + /* more than one extends, allocate more space */ + vde_size = sizeof(VOLUME_DISK_EXTENTS) + vde->NumberOfDiskExtents * sizeof(DISK_EXTENT); + vde_alloc = malloc_nofail(vde_size); + vde = vde_alloc; + + /* retry with more space */ + ret = DeviceIoControl(h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, 0, 0, vde, vde_size, &n, 0); + } + if (!ret) { + DWORD error = GetLastError(); + CloseHandle(h); + windows_errno(error); + return -1; + } + + for (i = 0; i < vde->NumberOfDiskExtents; ++i) { + devinfo_t* devinfo; + + devinfo = calloc_nofail(1, sizeof(devinfo_t)); + + pathcpy(devinfo->name, sizeof(devinfo->name), name); + pathcpy(devinfo->smartctl, sizeof(devinfo->smartctl), custom); + devinfo->device = vde->Extents[i].DiskNumber; + pathprint(devinfo->file, sizeof(devinfo->file), "/dev/pd%" PRIu64, devinfo->device); + pathprint(devinfo->wfile, sizeof(devinfo->wfile), "\\\\.\\PhysicalDrive%" PRIu64, devinfo->device); + devinfo->parent = parent; + + /* insert in the list */ + tommy_list_insert_tail(list, &devinfo->node, devinfo); + } + + if (!CloseHandle(h)) { + windows_errno(GetLastError()); + return -1; + } + + free(vde_alloc); + + return 0; +} + +/** + * Read smartctl --scan from a stream. + * Return 0 on success. + */ +static int smartctl_scan(FILE* f, tommy_list* list) +{ + while (1) { + char buf[256]; + char* s; + + s = fgets(buf, sizeof(buf), f); + if (s == 0) + break; + + /* remove extraneous chars */ + s = strpolish(buf); + + log_tag("smartctl:scan::text: %s\n", s); + + if (*s == '/') { + char* sep = strchr(s, ' '); + if (sep) { + tommy_node* i; + const char* number; + uint64_t device; + + /* clear everything after the first space */ + *sep = 0; + + /* get the device number from the device file */ + /* note that this is Windows specific */ + /* for the format /dev/pdX of smartmontools */ + number = s; + while (*number != 0 && !isdigit(*number)) + ++number; + device = atoi(number); + + /* check if already present */ + /* comparing the device file */ + for (i = tommy_list_head(list); i != 0; i = i->next) { + devinfo_t* devinfo = i->data; + if (devinfo->device == device) + break; + } + + /* if not found */ + if (i == 0) { + devinfo_t* devinfo; + + devinfo = calloc_nofail(1, sizeof(devinfo_t)); + devinfo->device = device; + pathprint(devinfo->file, sizeof(devinfo->file), "/dev/pd%" PRIu64, devinfo->device); + pathprint(devinfo->wfile, sizeof(devinfo->wfile), "\\\\.\\PhysicalDrive%" PRIu64, devinfo->device); + + /* insert in the list */ + tommy_list_insert_tail(list, &devinfo->node, devinfo); + } + } + } + } + + return 0; +} + +/** + * Scan all the devices. + */ +static int devscan(tommy_list* list) +{ + char conv_buf[CONV_MAX]; + WCHAR cmd[MAX_PATH + 128]; + FILE* f; + int ret; + + snwprintf(cmd, sizeof(cmd), L"\"%lssmartctl.exe\" --scan-open -d pd", exedir); + + log_tag("smartctl:scan::run: %s\n", u16tou8(conv_buf, cmd)); + + f = _wpopen(cmd, L"rt"); + if (!f) { + /* LCOV_EXCL_START */ + log_fatal("Failed to run '%s' (from popen).\n", u16tou8(conv_buf, cmd)); + return -1; + /* LCOV_EXCL_STOP */ + } + + if (smartctl_scan(f, list) != 0) { + /* LCOV_EXCL_START */ + pclose(f); + return -1; + /* LCOV_EXCL_STOP */ + } + + ret = pclose(f); + + log_tag("smartctl:scan::ret: %x\n", ret); + + if (ret == -1) { + /* LCOV_EXCL_START */ + log_fatal("Failed to run '%s' (from pclose).\n", u16tou8(conv_buf, cmd)); + return -1; + /* LCOV_EXCL_STOP */ + } + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to run '%s' with return code %xh.\n", u16tou8(conv_buf, cmd), ret); + return -1; + /* LCOV_EXCL_STOP */ + } + + return 0; +} + +/** + * Get SMART attributes. + */ +static int devsmart(uint64_t device, const char* name, const char* custom, uint64_t* smart, char* serial, char* vendor, char* model) +{ + char conv_buf[CONV_MAX]; + WCHAR cmd[MAX_PATH + 128]; + char file[128]; + FILE* f; + int ret; + int count; + + snprintf(file, sizeof(file), "/dev/pd%" PRIu64, device); + + /* if there is a custom command */ + if (custom[0]) { + char option[128]; + snprintf(option, sizeof(option), custom, file); + snwprintf(cmd, sizeof(cmd), L"\"%lssmartctl.exe\" -a %s", exedir, option); + } else { + snwprintf(cmd, sizeof(cmd), L"\"%lssmartctl.exe\" -a %s", exedir, file); + } + + count = 0; + +retry: + log_tag("smartctl:%s:%s:run: %s\n", file, name, u16tou8(conv_buf, cmd)); + + f = _wpopen(cmd, L"rt"); + if (!f) { + /* LCOV_EXCL_START */ + log_fatal("Failed to run '%s' (from popen).\n", u16tou8(conv_buf, cmd)); + return -1; + /* LCOV_EXCL_STOP */ + } + + if (smartctl_attribute(f, file, name, smart, serial, vendor, model) != 0) { + /* LCOV_EXCL_START */ + pclose(f); + return -1; + /* LCOV_EXCL_STOP */ + } + + ret = pclose(f); + + log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret); + + if (ret == -1) { + /* LCOV_EXCL_START */ + log_fatal("Failed to run '%s' (from pclose).\n", u16tou8(conv_buf, cmd)); + return -1; + /* LCOV_EXCL_STOP */ + } + + /* if first try without custom command */ + if (count == 0 && custom[0] == 0) { + /* + * Handle some common cases in Windows. + * + * Sometimes the "type" autodetection is wrong, and the command fails at identification + * stage, returning with error 2, or even with error 0, and with no info at all. + * We detect this condition checking the PowerOnHours, Size and RotationRate attributes. + * + * In such conditions we retry using the "sat" type, that often allows to proceed. + * + * Note that getting error 4 is instead very common, even with full info gathering. + */ + if ((ret == 0 || ret == 2) + && smart[9] == SMART_UNASSIGNED + && smart[SMART_SIZE] == SMART_UNASSIGNED + && smart[SMART_ROTATION_RATE] == SMART_UNASSIGNED + ) { + /* retry using the "sat" type */ + snwprintf(cmd, sizeof(cmd), L"\"%lssmartctl.exe\" -a -d sat %s", exedir, file); + + ++count; + goto retry; + } + } + + /* store the smartctl return value */ + smart[SMART_FLAGS] = ret; + + return 0; +} + +/** + * Spin down a specific device. + */ +static int devdown(uint64_t device, const char* name, const char* custom) +{ + char conv_buf[CONV_MAX]; + WCHAR cmd[MAX_PATH + 128]; + char file[128]; + FILE* f; + int ret; + int count; + + snprintf(file, sizeof(file), "/dev/pd%" PRIu64, device); + + /* if there is a custom command */ + if (custom[0]) { + char option[128]; + snprintf(option, sizeof(option), custom, file); + snwprintf(cmd, sizeof(cmd), L"\"%lssmartctl.exe\" -s standby,now %s", exedir, option); + } else { + snwprintf(cmd, sizeof(cmd), L"\"%lssmartctl.exe\" -s standby,now %s", exedir, file); + } + + count = 0; + +retry: + log_tag("smartctl:%s:%s:run: %s\n", file, name, u16tou8(conv_buf, cmd)); + + f = _wpopen(cmd, L"rt"); + if (!f) { + /* LCOV_EXCL_START */ + log_fatal("Failed to run '%s' (from popen).\n", u16tou8(conv_buf, cmd)); + return -1; + /* LCOV_EXCL_STOP */ + } + + if (smartctl_flush(f, file, name) != 0) { + /* LCOV_EXCL_START */ + pclose(f); + return -1; + /* LCOV_EXCL_STOP */ + } + + ret = pclose(f); + + log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret); + + if (ret == -1) { + /* LCOV_EXCL_START */ + log_fatal("Failed to run '%s' (from pclose).\n", u16tou8(conv_buf, cmd)); + return -1; + /* LCOV_EXCL_STOP */ + } + + /* if first try without custom command */ + if (count == 0 && custom[0] == 0) { + /* + * Handle some common cases in Windows. + * + * Sometimes the "type" autodetection is wrong, and the command fails at identification + * stage, returning with error 2. + * + * In such conditions we retry using the "sat" type, that often allows to proceed. + */ + if (ret == 2) { + /* retry using the "sat" type */ + snwprintf(cmd, sizeof(cmd), L"\"%lssmartctl.exe\" -s standby,now -d sat %s", exedir, file); + + ++count; + goto retry; + } + } + + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to run '%s' with return code %xh.\n", u16tou8(conv_buf, cmd), ret); + return -1; + /* LCOV_EXCL_STOP */ + } + + return 0; +} + +/** + * Spin up a device. + * + * There isn't a defined way to spin up a device, + * so we just do a generic write. + */ +static int devup(const char* mount) +{ + wchar_t conv_buf[CONV_MAX]; + int f; + char path[PATH_MAX]; + + /* add a temporary name used for writing */ + pathprint(path, sizeof(path), "%s.snapraid-spinup.tmp", mount); + + /* create a temporary file, automatically deleted on close */ + f = _wopen(convert(conv_buf, path), _O_CREAT | _O_TEMPORARY | _O_RDWR, _S_IREAD | _S_IWRITE); + if (f != -1) + close(f); + + return 0; +} + +/** + * Thread for spinning up. + * + * Note that filling up the devinfo object is done inside this thread, + * to avoid to block the main thread if the device need to be spin up + * to handle stat/resolve requests. + */ +static void* thread_spinup(void* arg) +{ + devinfo_t* devinfo = arg; + struct stat st; + uint64_t start; + + start = tick_ms(); + + /* uses lstat_sync() that maps to CreateFile */ + /* we cannot use FindFirstFile because it doesn't allow to open the root dir */ + if (lstat_sync(devinfo->mount, &st, 0) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to stat path '%s'. %s.\n", devinfo->mount, strerror(errno)); + return (void*)-1; + /* LCOV_EXCL_STOP */ + } + + /* set the device number */ + devinfo->device = st.st_dev; + + if (devresolve(devinfo->mount, devinfo->file, sizeof(devinfo->file), devinfo->wfile, sizeof(devinfo->wfile)) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to resolve path '%s'.\n", devinfo->mount); + return (void*)-1; + /* LCOV_EXCL_STOP */ + } + + if (devup(devinfo->mount) != 0) { + /* LCOV_EXCL_START */ + return (void*)-1; + /* LCOV_EXCL_STOP */ + } + + msg_status("Spunup device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start); + + return 0; +} + +/** + * Thread for spinning down. + */ +static void* thread_spindown(void* arg) +{ + devinfo_t* devinfo = arg; + uint64_t start; + + start = tick_ms(); + + if (devdown(devinfo->device, devinfo->name, devinfo->smartctl) != 0) { + /* LCOV_EXCL_START */ + return (void*)-1; + /* LCOV_EXCL_STOP */ + } + + msg_status("Spundown device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start); + + return 0; +} + +/** + * Thread for getting smart info. + */ +static void* thread_smart(void* arg) +{ + devinfo_t* devinfo = arg; + + if (devsmart(devinfo->device, devinfo->name, devinfo->smartctl, devinfo->smart, devinfo->smart_serial, devinfo->smart_vendor, devinfo->smart_model) != 0) { + /* LCOV_EXCL_START */ + return (void*)-1; + /* LCOV_EXCL_STOP */ + } + + return 0; +} + +static int device_thread(tommy_list* list, void* (*func)(void* arg)) +{ + int fail = 0; + tommy_node* i; + + /* starts all threads */ + for (i = tommy_list_head(list); i != 0; i = i->next) { + devinfo_t* devinfo = i->data; + + thread_create(&devinfo->thread, 0, func, devinfo); + } + + /* joins all threads */ + for (i = tommy_list_head(list); i != 0; i = i->next) { + devinfo_t* devinfo = i->data; + void* retval; + + thread_join(devinfo->thread, &retval); + + if (retval != 0) + ++fail; + } + + if (fail != 0) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + + return 0; +} + +int devquery(tommy_list* high, tommy_list* low, int operation, int others) +{ + tommy_node* i; + void* (*func)(void* arg) = 0; + + if (operation != DEVICE_UP) { + /* for each device */ + for (i = tommy_list_head(high); i != 0; i = i->next) { + devinfo_t* devinfo = i->data; + + if (devresolve(devinfo->mount, devinfo->file, sizeof(devinfo->file), devinfo->wfile, sizeof(devinfo->wfile)) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to resolve path '%s'.\n", devinfo->mount); + return -1; + /* LCOV_EXCL_STOP */ + } + + /* expand the tree of devices */ + if (devtree(devinfo->name, devinfo->smartctl, devinfo->wfile, devinfo, low) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to expand device '%s'.\n", devinfo->file); + return -1; + /* LCOV_EXCL_STOP */ + } + } + } + + if (operation == DEVICE_UP) { + /* duplicate the high */ + for (i = tommy_list_head(high); i != 0; i = i->next) { + devinfo_t* devinfo = i->data; + devinfo_t* entry; + + entry = calloc_nofail(1, sizeof(devinfo_t)); + + entry->device = devinfo->device; + pathcpy(entry->name, sizeof(entry->name), devinfo->name); + pathcpy(entry->mount, sizeof(entry->mount), devinfo->mount); + + /* insert in the high */ + tommy_list_insert_tail(low, &entry->node, entry); + } + } + + /* add other devices */ + if (others) { + if (devscan(low) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to list other devices.\n"); + return -1; + /* LCOV_EXCL_STOP */ + } + } + + switch (operation) { + case DEVICE_UP : func = thread_spinup; break; + case DEVICE_DOWN : func = thread_spindown; break; + case DEVICE_SMART : func = thread_smart; break; + } + + if (!func) + return 0; + + return device_thread(low, func); +} + +/****************************************************************************/ +/* thread */ + +int windows_mutex_init(windows_mutex_t* mutex, void* attr) +{ + CRITICAL_SECTION* cs; + + (void)attr; + + cs = malloc(sizeof(CRITICAL_SECTION)); + if (!cs) + return -1; + + InitializeCriticalSection(cs); + + *mutex = cs; + + return 0; +} + +int windows_mutex_destroy(windows_mutex_t* mutex) +{ + CRITICAL_SECTION* cs = *mutex; + + DeleteCriticalSection(cs); + + free(cs); + + return 0; +} + +int windows_mutex_lock(windows_mutex_t* mutex) +{ + CRITICAL_SECTION* cs = *mutex; + + EnterCriticalSection(cs); + + return 0; +} + +int windows_mutex_unlock(windows_mutex_t* mutex) +{ + CRITICAL_SECTION* cs = *mutex; + + LeaveCriticalSection(cs); + + return 0; +} + +int windows_cond_init(windows_cond_t* cond, void* attr) +{ + CONDITION_VARIABLE* cv; + + (void)attr; + + cv = malloc(sizeof(CONDITION_VARIABLE)); + if (!cv) + return -1; + + InitializeConditionVariable(cv); + + *cond = cv; + + return 0; +} + +int windows_cond_destroy(windows_cond_t* cond) +{ + CONDITION_VARIABLE* cv = *cond; + + /* note that in Windows there is no DeleteConditionVariable() to call */ + free(cv); + + return 0; +} + +int windows_cond_signal(windows_cond_t* cond) +{ + CONDITION_VARIABLE* cv = *cond; + + WakeConditionVariable(cv); + + return 0; +} + +int windows_cond_broadcast(windows_cond_t* cond) +{ + CONDITION_VARIABLE* cv = *cond; + + WakeAllConditionVariable(cv); + + return 0; +} + +int windows_cond_wait(windows_cond_t* cond, windows_mutex_t* mutex) +{ + CONDITION_VARIABLE* cv = *cond; + CRITICAL_SECTION* cs = *mutex; + + if (!SleepConditionVariableCS(cv, cs, INFINITE)) + return -1; + + return 0; +} + +#endif + diff --git a/cmdline/mingw.h b/cmdline/mingw.h new file mode 100644 index 0000000..7ac80e1 --- /dev/null +++ b/cmdline/mingw.h @@ -0,0 +1,418 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#ifndef __PORTABLE_MINGW_H +#define __PORTABLE_MINGW_H + +#ifdef __MINGW32__ /* Only for MingW */ + +#include + +/** + * Always assume that the assembler supports SSE2, SSSE3, SSE42 and AVX2 instructions in x86 + */ +#ifdef CONFIG_X86 +#define HAVE_SSE2 1 +#define HAVE_SSSE3 1 +#define HAVE_SSE42 1 +#define HAVE_AVX2 1 +#endif + +/****************************************************************************/ +/* file */ + +/** + * Redefines PATH_MAX to allow very long paths. + */ +#undef PATH_MAX +#define PATH_MAX 1024 + +/* Remap functions and types */ +#undef fopen +#define fopen windows_fopen +#undef open +#define open windows_open +#define open_noatime windows_open +#undef stat +#define stat windows_stat +#undef lstat +#define lstat windows_lstat +#undef off_t +#define off_t off64_t +#undef fstat +#define fstat windows_fstat +#define HAVE_FTRUNCATE 1 +#undef ftruncate +#define ftruncate windows_ftruncate +#define HAVE_FALLOCATE 1 +#undef fallocate +#define fallocate windows_fallocate +#define HAVE_FSYNC 1 +#undef fsync +#define fsync windows_fsync +#undef rename +#define rename windows_rename +#undef remove +#define remove windows_remove +#undef mkdir +#define mkdir(a, b) windows_mkdir(a) +#undef rmdir +#define rmdir windows_rmdir +#undef dirent +#define dirent windows_dirent +#undef DIR +#define DIR windows_dir +#undef opendir +#define opendir windows_opendir +#undef readdir +#define readdir windows_readdir +#undef closedir +#define closedir windows_closedir +#define HAVE_FUTIMENS 1 +#undef futimens +#define futimens windows_futimens +#define HAVE_UTIMENSAT 1 +#define AT_FDCWD -1 +#define AT_SYMLINK_NOFOLLOW 1 +#undef utimensat +#define utimensat windows_utimensat +#define O_NOFOLLOW 0 +#define dirent_hidden windows_dirent_hidden +#define HAVE_STRUCT_DIRENT_D_STAT 1 +#undef HAVE_STRUCT_DIRENT_D_INO +#define HAVE_STRUCT_STAT_ST_NLINK 1 +#define dirent_lstat windows_dirent_lstat +#define stat_desc windows_stat_desc +#undef sleep +#define sleep windows_sleep +/* 4==DIR, 5,6,7=free, 8==REG */ +#define S_IFLNK 0x5000 /* Symbolic link to file */ +#define S_ISLNK(m) (((m) & _S_IFMT) == S_IFLNK) +#define S_IFLNKDIR 0x6000 /* Symbolic link to directory */ +#define S_ISLNKDIR(m) (((m) & _S_IFMT) == S_IFLNKDIR) +#define S_IFJUN 0x7000 /* Junction */ +#define S_ISJUN(m) (((m) & _S_IFMT) == S_IFJUN) +#undef readlink +#define readlink windows_readlink +#undef symlink +#define symlink windows_symlink +#undef link +#define link windows_link +#undef strerror +#define strerror windows_strerror +#undef read +#define read windows_read +#undef write +#define write windows_write +#undef lseek +#define lseek windows_lseek +#undef pread +#define pread windows_pread +#undef pwrite +#define pwrite windows_pwrite +#define direct_size windows_direct_size +#define HAVE_DIRECT_IO 1 +#define O_DIRECT 0x10000000 +#define O_DSYNC 0x20000000 + +/** + * If nanoseconds are not supported, we report the special STAT_NSEC_INVALID value, + * to mark that it's undefined. + */ +#define STAT_NSEC_INVALID -1 + +/* We have nano second support */ +#define STAT_NSEC(st) ((int)(st)->st_mtimensec) + +/** + * Generic stat information. + */ +struct windows_stat { + uint64_t st_ino; + int64_t st_size; + int64_t st_mtime; + int32_t st_mtimensec; + uint32_t st_mode; + uint32_t st_dev; + uint32_t st_nlink; + int st_hidden; + const char* st_desc; + int st_sync; /**< If the information are in sync with the file-system. */ +}; + +/** + * Like the C fstat(). + */ +int windows_fstat(int fd, struct windows_stat* st); + +/** + * Like the C lstat(), but with some limitations. + * + * The st_ino field may be 0 if it's not possible to read it in a fast way. + * Specifically this always happens. + * + * In case of hardlinks, the size and the attributes of the file can + * be completely bogus, because changes made by other hardlinks are reported + * in the directory entry only when the file is opened. + * + * MSDN CreateHardLinks + * http://msdn.microsoft.com/en-us/library/windows/desktop/aa363860%28v=vs.85%29.aspx + * 'When you create a hard link on the NTFS file system, the file attribute information' + * 'in the directory entry is refreshed only when the file is opened, or when' + * 'GetFileInformationByHandle is called with the handle of a specific file.' + * + * MSDN HardLinks and Junctions + * http://msdn.microsoft.com/en-us/library/windows/desktop/aa365006%28v=vs.85%29.aspx + * 'However, the directory entry size and attribute information is updated only' + * 'for the link through which the change was made.' + * + * Use lstat_sync() to override these limitations. + */ +int windows_lstat(const char* file, struct windows_stat* st); + +/** + * Like the C stat(). + */ +int windows_stat(const char* file, struct windows_stat* st); + +/** + * Like the C mkdir(). + */ +int windows_mkdir(const char* file); + +/** + * Like rmdir(). + */ +int windows_rmdir(const char* file); + +/** + * Like the C lstat(), but with some limitations. + * + * This call fills all the st_* fields of the stat struct, + * and if provided the pointer, also the physical offset. + * + * It doesn't work for all kinds of files and directories. + * You must call it only for regular files. + * For example, "C:\System Volume Information" cannot be accessed + * with error ERROR_ACCESS_DENIED. + * + * Note that instead lstat() works for all the files. + */ +#define HAVE_LSTAT_SYNC 1 +int lstat_sync(const char* file, struct windows_stat* st, uint64_t* physical); + +/** + * Like the C ftruncate(). + */ +int windows_ftruncate(int fd, off64_t off); + +/** + * Like the C fallocate(). + */ +int windows_fallocate(int fd, int mode, off64_t off, off64_t len); + +/** + * Like the C fsync(). + */ +int windows_fsync(int fd); + +/** + * Like the C futimes(). + */ +int windows_futimes(int fd, struct timeval tv[2]); + +struct windows_timespec { + int64_t tv_sec; + int tv_nsec; +}; + +#define timespec windows_timespec + +/** + * Like the C futimens(). + */ +int windows_futimens(int fd, struct windows_timespec tv[2]); + +/** + * Like the C utimensat(). + */ +int windows_utimensat(int fd, const char* file, struct windows_timespec tv[2], int flags); + +/** + * Like the C rename(). + */ +int windows_rename(const char* a, const char* b); + +/** + * Like the C remove(). + */ +int windows_remove(const char* a); + +/** + * Like the C fopen(). + */ +FILE* windows_fopen(const char* file, const char* mode); + +/** + * Like the C open(). + */ +int windows_open(const char* file, int flags, ...); + +/** + * Like the C dirent. + */ +struct windows_dirent { + char d_name[PATH_MAX]; + struct windows_stat d_stat; +}; + +/** + * Like the C DIR. + */ +struct windows_dir_struct; +typedef struct windows_dir_struct windows_dir; + +/** + * Like the C opendir(). + */ +windows_dir* windows_opendir(const char* dir); + +/** + * Like the C readdir(). + */ +struct windows_dirent* windows_readdir(windows_dir* dirstream); + +/** + * Like the C closedir(). + */ +int windows_closedir(windows_dir* dirstream); + +/** + * Convert a dirent record to a lstat record, but with some limitations. + * + * The st_mode field may be 0 if the file is a reparse point. + * Specifically this happens if we are using GetFileInformationByHandleEx() + * to read the directory stream. + * + * The st_ino field may be 0 if it's not possible to read it in a fast way. + * Specifically this happens if we are using FindFirst/FindNext to enumerate + * the directory. + * + * In such cases, call lstat_sync() to fill the missing fields. + */ +void windows_dirent_lstat(const struct windows_dirent* dd, struct windows_stat* st); + +/** + * Like dirent_hidden(). + */ +int windows_dirent_hidden(struct dirent* dd); + +/** + * Like stat_desc(). + */ +const char* windows_stat_desc(struct stat* st); + +/** + * Like sleep(). + */ +void windows_sleep(unsigned seconds); + +/** + * Like readlink(). + */ +int windows_readlink(const char* file, char* buffer, size_t size); + +/** + * Like symlink(). + * Return ENOSYS if symlinks are not supported. + */ +int windows_symlink(const char* existing, const char* file); + +/** + * Like link(). + */ +int windows_link(const char* existing, const char* file); + +/** + * Like strerror(). + */ +const char* windows_strerror(int err); + +/** + * Like read(). + */ +ssize_t windows_read(int f, void* buffer, size_t size); + +/** + * Like write(). + */ +ssize_t windows_write(int f, const void* buffer, size_t size); + +/** + * Like lseek(). + */ +off_t windows_lseek(int f, off_t offset, int whence); + +/** + * Like pread(). + */ +ssize_t windows_pread(int f, void* buffer, size_t size, off_t offset); + +/** + * Like pwrite(). + */ +ssize_t windows_pwrite(int f, const void* buffer, size_t size, off_t offset); + +/** + * List direct_size(). + */ +size_t windows_direct_size(void); + +/****************************************************************************/ +/* thread */ + +#define pthread_mutex_t windows_mutex_t +#define pthread_cond_t windows_cond_t +#define pthread_mutex_init windows_mutex_init +#define pthread_mutex_destroy windows_mutex_destroy +#define pthread_mutex_lock windows_mutex_lock +#define pthread_mutex_unlock windows_mutex_unlock +#define pthread_cond_init windows_cond_init +#define pthread_cond_destroy windows_cond_destroy +#define pthread_cond_signal windows_cond_signal +#define pthread_cond_broadcast windows_cond_broadcast +#define pthread_cond_wait windows_cond_wait + +typedef void* windows_mutex_t; +typedef void* windows_cond_t; + +/** + * Like pthread_* equivalent. + */ +int windows_mutex_init(windows_mutex_t* mutex, void* attr); +int windows_mutex_destroy(windows_mutex_t* mutex); +int windows_mutex_lock(windows_mutex_t* mutex); +int windows_mutex_unlock(windows_mutex_t* mutex); +int windows_cond_init(windows_cond_t* cond, void* attr); +int windows_cond_destroy(windows_cond_t* cond); +int windows_cond_signal(windows_cond_t* cond); +int windows_cond_broadcast(windows_cond_t* cond); +int windows_cond_wait(windows_cond_t* cond, windows_mutex_t* mutex); + +#endif +#endif + diff --git a/cmdline/mkstream.c b/cmdline/mkstream.c new file mode 100644 index 0000000..8f852bd --- /dev/null +++ b/cmdline/mkstream.c @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2015 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "stream.h" +#include "support.h" + +#define STREAM_MAX 8 +#define BUFFER_MAX 64 +#define STR_MAX 128 + +void test(void) +{ + struct stream* s; + char file[32]; + unsigned char buffer[BUFFER_MAX]; + char str[STR_MAX]; + unsigned i, j; + uint32_t u32 = -1L; + uint64_t u64 = -1LL; + uint32_t put_crc_stored; + uint32_t put_crc_computed; + + crc32c_init(); + + s = sopen_multi_write(STREAM_MAX); + for (i = 0; i < STREAM_MAX; ++i) { + snprintf(file, sizeof(file), "stream%u.bin", i); + if (sopen_multi_file(s, i, file) != 0) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + for (j = 0; j < 256; ++j) { + if (sputc(j, s) != 0) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + for (j = 0; j < 32; ++j) { + if (sputb32(u32 >> j, s) != 0) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + for (j = 0; j < 64; ++j) { + if (sputb64(u64 >> j, s) != 0) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + for (j = 0; j < BUFFER_MAX; ++j) { + memset(buffer, j, j); + if (swrite(buffer, j, s) != 0) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + for (j = 1; j < STR_MAX; ++j) { + memset(str, ' ' + j, j - 1); + str[j - 1] = 0; + if (sputbs(str, s) != 0) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + put_crc_stored = scrc(s); + put_crc_computed = scrc_stream(s); + + if (put_crc_stored != put_crc_computed) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (sputble32(put_crc_stored, s) != 0) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (sclose(s) != 0) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + for (i = 0; i < STREAM_MAX; ++i) { + uint32_t get_crc_stored; + uint32_t get_crc_computed; + snprintf(file, sizeof(file), "stream%u.bin", i); + + s = sopen_read(file); + if (s == 0) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + for (j = 0; j < 256; ++j) { + int c = sgetc(s); + if (c == EOF || (unsigned char)c != j) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + for (j = 0; j < 32; ++j) { + uint32_t v32; + if (sgetb32(s, &v32) != 0 || v32 != (u32 >> j)) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + for (j = 0; j < 64; ++j) { + uint64_t v64; + if (sgetb64(s, &v64) != 0 || v64 != (u64 >> j)) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + for (j = 1; j < BUFFER_MAX; ++j) { + char copy[BUFFER_MAX]; + memset(buffer, j, j); + if (sread(s, copy, j) != 0 || memcmp(copy, buffer, j) != 0) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + for (j = 1; j < STR_MAX; ++j) { + char copy[STR_MAX]; + memset(str, ' ' + j, j - 1); + str[j - 1] = 0; + if (sgetbs(s, copy, sizeof(copy)) != 0 || strcmp(copy, str) != 0) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + /* get the computed CRC *before* reading the stored one */ + get_crc_computed = scrc(s); + + if (sgetble32(s, &get_crc_stored) != 0) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (get_crc_stored != put_crc_stored) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (get_crc_stored != get_crc_computed) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (sclose(s) != 0) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + for (i = 0; i < STREAM_MAX; ++i) { + uint32_t get_crc_stored; + uint32_t get_crc_computed; + unsigned char buf[4]; + snprintf(file, sizeof(file), "stream%u.bin", i); + + s = sopen_read(file); + if (s == 0) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (sdeplete(s, buf) != 0) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* get the stored crc from the last four bytes */ + get_crc_stored = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24; + + if (get_crc_stored != put_crc_stored) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* get the computed CRC *after* reading the stored one */ + get_crc_computed = scrc(s); + + /* adjust the stored crc to include itself */ + get_crc_stored = crc32c(get_crc_stored, buf, 4); + + if (get_crc_stored != get_crc_computed) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (sclose(s) != 0) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } +} + +int main(void) +{ + unsigned i; + + lock_init(); + + for (i = 1; i <= 16; ++i) { + + /* test with different stream buffer size */ + STREAM_SIZE = i; + + printf("Test stream buffer size %u\n", i); + + test(); + } + + return 0; +} + diff --git a/cmdline/mktest.c b/cmdline/mktest.c new file mode 100644 index 0000000..1df95cc --- /dev/null +++ b/cmdline/mktest.c @@ -0,0 +1,794 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "support.h" + +/****************************************************************************/ +/* random */ + +/** + * Pseudo random number generator. + */ +unsigned long long seed = 0; + +unsigned rnd(unsigned max) +{ + seed = seed * 6364136223846793005LL + 1442695040888963407LL; + + return (seed >> 32) % max; +} + +unsigned rndnz(unsigned max) +{ + if (max <= 1) + return 1; + else + return rnd(max - 1) + 1; +} + +void rndnz_range(unsigned char* data, int size) +{ + int i; + + for (i = 0; i < size; ++i) + data[i] = rndnz(256); +} + +void rndnz_damage(unsigned char* data, int size) +{ + int i; + + /* corrupt ensuring always different data */ + for (i = 0; i < size; ++i) { + unsigned char c; + + do { + c = rndnz(256); + } while (c == data[i]); + + data[i] = c; + } +} + +char CHARSET[] = "qwertyuiopasdfghjklzxcvbnm1234567890 .-+"; +#define CHARSET_LEN (sizeof(CHARSET) - 1) + +void rnd_name(char* file) +{ + int l = 1 + rnd(20); + + while (l) { + *file++ = CHARSET[rnd(CHARSET_LEN)]; + --l; + } + *file = 0; +} + +/****************************************************************************/ +/* file */ + +int file_cmp(const void* a, const void* b) +{ + return strcmp(a, b); +} + +int fallback(int f, struct stat* st) +{ +#if HAVE_FUTIMENS + struct timespec tv[2]; +#else + struct timeval tv[2]; +#endif + int ret; + +#if HAVE_FUTIMENS /* futimens() is preferred because it gives nanosecond precision */ + tv[0].tv_sec = st->st_mtime; + if (STAT_NSEC(st) != STAT_NSEC_INVALID) + tv[0].tv_nsec = STAT_NSEC(st); + else + tv[0].tv_nsec = 0; + tv[1].tv_sec = tv[0].tv_sec; + tv[1].tv_nsec = tv[0].tv_nsec; + + ret = futimens(f, tv); +#elif HAVE_FUTIMES /* fallback to futimes() if nanosecond precision is not available */ + tv[0].tv_sec = st->st_mtime; + if (STAT_NSEC(st) != STAT_NSEC_INVALID) + tv[0].tv_usec = STAT_NSEC(st) / 1000; + else + tv[0].tv_usec = 0; + tv[1].tv_sec = tv[0].tv_sec; + tv[1].tv_usec = tv[0].tv_usec; + + ret = futimes(f, tv); +#elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */ + tv[0].tv_sec = st->st_mtime; + if (STAT_NSEC(st) != STAT_NSEC_INVALID) + tv[0].tv_usec = STAT_NSEC(st) / 1000; + else + tv[0].tv_usec = 0; + tv[1].tv_sec = tv[0].tv_sec; + tv[1].tv_usec = tv[0].tv_usec; + + ret = futimesat(f, 0, tv); +#else +#error No function available to set file timestamps +#endif + return ret; +} + +/****************************************************************************/ +/* cmd */ + +/** + * Create a file with random content. + * - If the file exists it's rewritten, but avoiding to truncating it to 0. + */ +void cmd_generate_file(const char* path, int size) +{ + unsigned char* data; + int f; + + /* remove the existing file/symlink if any */ + if (remove(path) != 0) { + if (errno != ENOENT) { + /* LCOV_EXCL_START */ + log_fatal("Error removing file %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } else { + /* don't truncate files to 0 size to avoid ZERO file size protection */ + ++size; + } + + data = malloc(size); + + /* We don't write zero bytes because we want to test */ + /* the recovering of new files, after an aborted sync */ + /* If the files contains full blocks at zero */ + /* this is an impossible condition to recover */ + /* because we cannot differentiate between an unused block */ + /* and a file filled with 0 */ + rndnz_range(data, size); + + f = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_NOFOLLOW, 0600); + if (f < 0) { + /* LCOV_EXCL_START */ + log_fatal("Error creating file %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (write(f, data, size) != size) { + /* LCOV_EXCL_START */ + log_fatal("Error writing file %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (close(f) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error closing file %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + free(data); +} + +/** + * Create a symlink. + * - If the file already exists, it's removed. + */ +void cmd_generate_symlink(const char* path, const char* linkto) +{ + /* remove the existing file/symlink if any */ + if (remove(path) != 0) { + if (errno != ENOENT) { + /* LCOV_EXCL_START */ + log_fatal("Error removing file %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + if (symlink(linkto, path) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error writing symlink %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } +} + +/** + * Create a file or a symlink with a random name. + */ +void cmd_generate(int disk, int size) +{ + char path[PATH_MAX]; + char* file; + + snprintf(path, sizeof(path), "bench/disk%d/", disk); + file = path + strlen(path); + + /* add a directory */ + *file++ = 'a' + rnd(2); + *file = 0; + + /* create it */ + if (mkdir(path, 0777) != 0) { + if (errno != EEXIST) { + /* LCOV_EXCL_START */ + log_fatal("Error creating directory %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + *file++ = '/'; + + while (1) { + /* add a random file */ + rnd_name(file); + + /* skip some invalid file name, see http://en.wikipedia.org/wiki/Filename */ + if (strcmp(file, ".") == 0 + || strcmp(file, "..") == 0 + || strcmp(file, "prn") == 0 + || strcmp(file, "con") == 0 + || strcmp(file, "nul") == 0 + || strcmp(file, "aux") == 0 + || file[0] == ' ' + || file[strlen(file) - 1] == ' ' + || file[strlen(file) - 1] == '.' + ) { + continue; + } + + break; + } + +#ifndef WIN32 /* Windows XP doesn't support symlinks */ + if (rnd(32) == 0) { + /* symlink */ + char linkto[PATH_MAX]; + + rnd_name(linkto); + + cmd_generate_symlink(path, linkto); + } else +#endif + { + /* file */ + cmd_generate_file(path, size); + } +} + +/** + * Write a partially a file. + * - The file must exist. + * - The file size is not changed. + * - The written data may be equal or not at the already existing one. + * - If it's a symlink nothing is done. + */ +void cmd_write(const char* path, int size) +{ + struct stat st; + + if (lstat(path, &st) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error accessing %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (S_ISREG(st.st_mode)) { + unsigned char* data; + off_t off; + int f; + + /* not over the end */ + if (size > st.st_size) + size = st.st_size; + + /* start at random position inside the file */ + if (size < st.st_size) + off = rnd(st.st_size - size); + else + off = 0; + + data = malloc(size); + + rndnz_range(data, size); + + f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW); + if (f < 0) { + /* LCOV_EXCL_START */ + log_fatal("Error creating file %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (lseek(f, off, SEEK_SET) != off) { + /* LCOV_EXCL_START */ + log_fatal("Error seeking file %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (write(f, data, size) != size) { + /* LCOV_EXCL_START */ + log_fatal("Error writing file %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (close(f) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error closing file %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + free(data); + } +} + +/** + * Damage a file. + * - The file must exist. + * - The file size is not changed. + * - The written data is SURELY different than the already existing one. + * - The file timestamp is NOT modified. + * - If it's a symlink nothing is done. + */ +void cmd_damage(const char* path, int size) +{ + struct stat st; + + /* here a 0 size means to change nothing */ + /* as also the timestamp should not be changed */ + if (!size) + return; + + if (lstat(path, &st) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error accessing %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (st.st_size == 0) + return; + + if (S_ISREG(st.st_mode)) { + off_t off; + unsigned char* data; + int f; + + /* not over the end */ + if (size > st.st_size) + size = st.st_size; + + /* start at random position inside the file */ + if (size < st.st_size) + off = rnd(st.st_size - size); + else + off = 0; + + data = malloc(size); + + f = open(path, O_RDWR | O_BINARY | O_NOFOLLOW); + if (f < 0) { + /* LCOV_EXCL_START */ + log_fatal("Error creating file %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (lseek(f, off, SEEK_SET) != off) { + /* LCOV_EXCL_START */ + log_fatal("Error seeking file %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (read(f, data, size) != size) { + /* LCOV_EXCL_START */ + log_fatal("Error writing file %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + rndnz_damage(data, size); + + if (lseek(f, off, SEEK_SET) != off) { + /* LCOV_EXCL_START */ + log_fatal("Error seeking file %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (write(f, data, size) != size) { + /* LCOV_EXCL_START */ + log_fatal("Error writing file %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (fallback(f, &st) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error setting time for file %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (close(f) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error closing file %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + free(data); + } +} + +/** + * Append to a file. + * - The file must exist. + * - If it's a symlink nothing is done. + */ +void cmd_append(const char* path, int size) +{ + struct stat st; + + if (lstat(path, &st) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error accessing %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (S_ISREG(st.st_mode)) { + unsigned char* data; + int f; + + data = malloc(size); + + rndnz_range(data, size); + + f = open(path, O_WRONLY | O_APPEND | O_BINARY | O_NOFOLLOW); + if (f < 0) { + /* LCOV_EXCL_START */ + log_fatal("Error opening file %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (write(f, data, size) != size) { + /* LCOV_EXCL_START */ + log_fatal("Error writing file %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (close(f) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error closing file %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + free(data); + } +} + +/** + * Truncate a file. + * - The file must exist. + * - The file is NEVER truncated to 0. + * - If it's a symlink nothing is done. + */ +void cmd_truncate(const char* path, int size) +{ + struct stat st; + + if (lstat(path, &st) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error accessing %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (S_ISREG(st.st_mode)) { + off_t off; + int f; + + /* if file is empty, just rewrite it */ + if (st.st_size == 0) { + size = 0; + } else { + /* don't truncate files to 0 size to avoid ZERO file size protection */ + if (size >= st.st_size) + size = st.st_size - 1; + } + + off = st.st_size - size; + + f = open(path, O_WRONLY | O_BINARY | O_NOFOLLOW); + if (f < 0) { + /* LCOV_EXCL_START */ + log_fatal("Error opening file %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (ftruncate(f, off) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error truncating file %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (close(f) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error closing file %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } +} + +/** + * Delete a file. + * - The file must exist. + */ +void cmd_delete(const char* path) +{ + if (remove(path) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error removing %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } +} + +/** + * Change a file. Or deleted/truncated/append/created. + * - The file must exist. + */ +void cmd_change(const char* path, int size) +{ + struct stat st; + + if (!size) + return; + + if (lstat(path, &st) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error accessing %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (S_ISLNK(st.st_mode)) { + /* symlink */ + if (rnd(2) == 0) { + /* delete */ + if (remove(path) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error removing %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } else { + /* recreate */ + char linkto[PATH_MAX]; + + if (remove(path) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error removing %s\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + rnd_name(linkto); + + cmd_generate_symlink(path, linkto); + } + } else if (S_ISREG(st.st_mode)) { + int r; + + r = rnd(4); + + if (r == 0) { + cmd_write(path, size); + } else if (r == 1) { + cmd_append(path, size); + } else if (r == 2) { + cmd_truncate(path, size); + } else { + cmd_delete(path); + } + } +} + +void help(void) +{ + printf("Test for " PACKAGE " v" VERSION " by Andrea Mazzoleni, " PACKAGE_URL "\n"); + printf("Usage:\n"); + printf("\tmktest generate SEED DISK_NUM FILE_NUM FILE_SIZE\n"); + printf("\tmktest damage SEED NUM SIZE FILE\n"); + printf("\tmktest write SEED NUM SIZE FILE\n"); + printf("\tmktest change SEED SIZE FILE\n"); + printf("\tmktest append SEED SIZE FILE\n"); + printf("\tmktest truncate SEED SIZE FILE\n"); +} + +int main(int argc, char* argv[]) +{ + int i, j, b; + + lock_init(); + + if (argc < 2) { + help(); + exit(EXIT_SUCCESS); + } + + if (strcmp(argv[1], "generate") == 0) { + int disk, file, size; + + if (argc != 6) { + /* LCOV_EXCL_START */ + help(); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + seed = atoi(argv[2]); + disk = atoi(argv[3]); + file = atoi(argv[4]); + size = atoi(argv[5]); + + for (i = 0; i < disk; ++i) { + for (j = 0; j < file; ++j) { + if (j == 0) + /* create at least a big one */ + cmd_generate(i + 1, size); + else if (j == 1) + /* create at least an empty one */ + cmd_generate(i + 1, 0); + else + cmd_generate(i + 1, rnd(size)); + } + } + } else if (strcmp(argv[1], "write") == 0) { + int fail, size; + + if (argc < 6) { + /* LCOV_EXCL_START */ + help(); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + seed = atoi(argv[2]); + fail = atoi(argv[3]); + size = atoi(argv[4]); + b = 5; + + /* sort the file names */ + qsort(&argv[b], argc - b, sizeof(argv[b]), file_cmp); + + for (i = b; i < argc; ++i) + for (j = 0; j < fail; ++j) + cmd_write(argv[i], rndnz(size)); + } else if (strcmp(argv[1], "damage") == 0) { + int fail, size; + + if (argc < 6) { + /* LCOV_EXCL_START */ + help(); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + seed = atoi(argv[2]); + fail = atoi(argv[3]); + size = atoi(argv[4]); + b = 5; + + /* sort the file names */ + qsort(&argv[b], argc - b, sizeof(argv[b]), file_cmp); + + for (i = b; i < argc; ++i) + for (j = 0; j < fail; ++j) + cmd_damage(argv[i], rndnz(size)); /* at least one byte */ + } else if (strcmp(argv[1], "append") == 0) { + int size; + + if (argc < 5) { + /* LCOV_EXCL_START */ + help(); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + seed = atoi(argv[2]); + size = atoi(argv[3]); + b = 4; + + /* sort the file names */ + qsort(&argv[b], argc - b, sizeof(argv[b]), file_cmp); + + for (i = b; i < argc; ++i) + cmd_append(argv[i], rndnz(size)); /* at least one byte */ + } else if (strcmp(argv[1], "truncate") == 0) { + int size; + + if (argc < 5) { + /* LCOV_EXCL_START */ + help(); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + seed = atoi(argv[2]); + size = atoi(argv[3]); + b = 4; + + /* sort the file names */ + qsort(&argv[b], argc - b, sizeof(argv[b]), file_cmp); + + for (i = b; i < argc; ++i) + cmd_truncate(argv[i], rnd(size)); + } else if (strcmp(argv[1], "change") == 0) { + int size; + + if (argc < 5) { + /* LCOV_EXCL_START */ + help(); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + seed = atoi(argv[2]); + size = atoi(argv[3]); + b = 4; + + /* sort the file names */ + qsort(&argv[b], argc - b, sizeof(argv[b]), file_cmp); + + for (i = b; i < argc; ++i) + cmd_change(argv[i], rnd(size)); + } else { + /* LCOV_EXCL_START */ + help(); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + lock_done(); + + return 0; +} + diff --git a/cmdline/murmur3.c b/cmdline/murmur3.c new file mode 100644 index 0000000..2731cd9 --- /dev/null +++ b/cmdline/murmur3.c @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +/* + * Derivative work from MurmorHash3.cpp revision r136 + * + * SMHasher & MurmurHash + * http://code.google.com/p/smhasher/ + * + * Exact source used as reference: + * http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp?spec=svn136&r=136 + */ + +// MurmurHash3 was written by Austin Appleby, and is placed in the public +// domain. The author hereby disclaims copyright to this source code. + +/* Finalization mix - force all bits of a hash block to avalanche */ +static inline uint32_t fmix32(uint32_t h) +{ + h ^= h >> 16; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + h ^= h >> 16; + return h; +} + +/* + * Warning! + * Don't declare these variables static, otherwise the gcc optimizer + * may generate very slow code for multiplication with these constants, + * like: + + -> .cpp + k1 *= c1; + -> .asm + 152: 8d 14 80 lea (%eax,%eax,4),%edx + 155: 8d 14 90 lea (%eax,%edx,4),%edx + 158: c1 e2 03 shl $0x3,%edx + 15b: 29 c2 sub %eax,%edx + 15d: 8d 14 d2 lea (%edx,%edx,8),%edx + 160: 8d 14 90 lea (%eax,%edx,4),%edx + 163: 8d 14 d0 lea (%eax,%edx,8),%edx + 166: 8d 14 90 lea (%eax,%edx,4),%edx + 169: 8d 14 50 lea (%eax,%edx,2),%edx + 16c: 8d 14 90 lea (%eax,%edx,4),%edx + 16f: 8d 14 92 lea (%edx,%edx,4),%edx + 172: 8d 14 50 lea (%eax,%edx,2),%edx + 175: 8d 04 d0 lea (%eax,%edx,8),%eax + 178: 8d 14 c5 00 00 00 00 lea 0x0(,%eax,8),%edx + 17f: 29 d0 sub %edx,%eax + + * resulting in speeds of 500 MB/s instead of 3000 MB/s. + * + * Verified with gcc 4.4.4 compiling with : + * + * g++ -g -c -O2 MurmurHash3.cpp -o MurmurHash3.o + */ +uint32_t c1 = 0x239b961b; +uint32_t c2 = 0xab0e9789; +uint32_t c3 = 0x38b34ae5; +uint32_t c4 = 0xa1e38b93; + +void MurmurHash3_x86_128(const void* data, size_t size, const uint8_t* seed, void* digest) +{ + size_t nblocks; + const uint32_t* blocks; + const uint32_t* end; + size_t size_remainder; + uint32_t h1, h2, h3, h4; + + h1 = util_read32(seed + 0); + h2 = util_read32(seed + 4); + h3 = util_read32(seed + 8); + h4 = util_read32(seed + 12); + + nblocks = size / 16; + blocks = data; + end = blocks + nblocks * 4; + + /* body */ + while (blocks < end) { + uint32_t k1 = blocks[0]; + uint32_t k2 = blocks[1]; + uint32_t k3 = blocks[2]; + uint32_t k4 = blocks[3]; + +#if WORDS_BIGENDIAN + k1 = util_swap32(k1); + k2 = util_swap32(k2); + k3 = util_swap32(k3); + k4 = util_swap32(k4); +#endif + + k1 *= c1; k1 = util_rotl32(k1, 15); k1 *= c2; h1 ^= k1; + + h1 = util_rotl32(h1, 19); h1 += h2; h1 = h1 * 5 + 0x561ccd1b; + + k2 *= c2; k2 = util_rotl32(k2, 16); k2 *= c3; h2 ^= k2; + + h2 = util_rotl32(h2, 17); h2 += h3; h2 = h2 * 5 + 0x0bcaa747; + + k3 *= c3; k3 = util_rotl32(k3, 17); k3 *= c4; h3 ^= k3; + + h3 = util_rotl32(h3, 15); h3 += h4; h3 = h3 * 5 + 0x96cd1c35; + + k4 *= c4; k4 = util_rotl32(k4, 18); k4 *= c1; h4 ^= k4; + + h4 = util_rotl32(h4, 13); h4 += h1; h4 = h4 * 5 + 0x32ac3b17; + + blocks += 4; + } + + /* tail */ + size_remainder = size & 15; + if (size_remainder != 0) { + const uint8_t* tail = (const uint8_t*)blocks; + + uint32_t k1 = 0; + uint32_t k2 = 0; + uint32_t k3 = 0; + uint32_t k4 = 0; + + switch (size_remainder) { + case 15 : k4 ^= (uint32_t)tail[14] << 16; + case 14 : k4 ^= (uint32_t)tail[13] << 8; + case 13 : k4 ^= (uint32_t)tail[12] << 0; + k4 *= c4; k4 = util_rotl32(k4, 18); k4 *= c1; h4 ^= k4; + case 12 : k3 ^= (uint32_t)tail[11] << 24; + case 11 : k3 ^= (uint32_t)tail[10] << 16; + case 10 : k3 ^= (uint32_t)tail[ 9] << 8; + case 9 : k3 ^= (uint32_t)tail[ 8] << 0; + k3 *= c3; k3 = util_rotl32(k3, 17); k3 *= c4; h3 ^= k3; + case 8 : k2 ^= (uint32_t)tail[ 7] << 24; + case 7 : k2 ^= (uint32_t)tail[ 6] << 16; + case 6 : k2 ^= (uint32_t)tail[ 5] << 8; + case 5 : k2 ^= (uint32_t)tail[ 4] << 0; + k2 *= c2; k2 = util_rotl32(k2, 16); k2 *= c3; h2 ^= k2; + case 4 : k1 ^= (uint32_t)tail[ 3] << 24; + case 3 : k1 ^= (uint32_t)tail[ 2] << 16; + case 2 : k1 ^= (uint32_t)tail[ 1] << 8; + case 1 : k1 ^= (uint32_t)tail[ 0] << 0; + k1 *= c1; k1 = util_rotl32(k1, 15); k1 *= c2; h1 ^= k1; + } + } + + /* finalization */ + h1 ^= size; h2 ^= size; h3 ^= size; h4 ^= size; + + h1 += h2; h1 += h3; h1 += h4; + h2 += h1; h3 += h1; h4 += h1; + + h1 = fmix32(h1); + h2 = fmix32(h2); + h3 = fmix32(h3); + h4 = fmix32(h4); + + h1 += h2; h1 += h3; h1 += h4; + h2 += h1; h3 += h1; h4 += h1; + + util_write32(digest + 0, h1); + util_write32(digest + 4, h2); + util_write32(digest + 8, h3); + util_write32(digest + 12, h4); +} + diff --git a/cmdline/murmur3test.c b/cmdline/murmur3test.c new file mode 100644 index 0000000..2d21fdc --- /dev/null +++ b/cmdline/murmur3test.c @@ -0,0 +1,264 @@ +{ "", 0, { 0x6d, 0xc8, 0xcf, 0x99, 0x79, 0xda, 0x82, 0x0b, 0x9d, 0xd0, 0x02, 0x56, 0x0e, 0x6a, 0x28, 0x0a } }, +{ "a", 1, { 0x83, 0xa4, 0xc1, 0x6e, 0x1f, 0xcb, 0x8b, 0x30, 0x26, 0x59, 0x53, 0x64, 0x3b, 0x3f, 0xc1, 0xda } }, +{ "abc", 3, { 0xb3, 0xfc, 0x85, 0x98, 0x5b, 0xe6, 0x5a, 0xa2, 0x4b, 0xe9, 0x91, 0xee, 0x71, 0x9f, 0x9f, 0x8d } }, +{ "message digest", 14, { 0x20, 0xa2, 0x19, 0x39, 0xec, 0x22, 0x47, 0x6d, 0xe2, 0xec, 0x49, 0x9d, 0xc0, 0xd9, 0x9a, 0x3e } }, +{ "abcdefghijklmnopqrstuvwxyz", 26, { 0xde, 0x14, 0xd1, 0x23, 0x69, 0xa3, 0x51, 0x40, 0xc2, 0x05, 0x6c, 0x02, 0xb1, 0xa5, 0x57, 0xf7 } }, +{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62, { 0xc9, 0x76, 0x9b, 0xc1, 0xaf, 0x21, 0x57, 0xbc, 0x1a, 0x37, 0xa3, 0xd0, 0xc5, 0x3e, 0x0c, 0xa7 } }, +{ "The quick brown fox jumps over the lazy dog", 43, { 0x50, 0x2a, 0xbe, 0xaf, 0x34, 0xa9, 0x5a, 0x3d, 0x23, 0x32, 0x5f, 0x35, 0xf4, 0xbb, 0xae, 0xb6 } }, +{ "\x00", 1, { 0xe6, 0x32, 0x4f, 0xfc, 0x34, 0xec, 0x2e, 0xa6, 0xd2, 0x78, 0x69, 0x5d, 0x02, 0x5a, 0x13, 0xf2 } }, +{ "\x16\x27", 2, { 0x6f, 0xa3, 0xa2, 0x16, 0xbf, 0x09, 0x0c, 0x4c, 0xc7, 0xca, 0xc2, 0xbc, 0xd7, 0xb4, 0xed, 0xd4 } }, +{ "\xe2\x56\xb4", 3, { 0xc1, 0x5f, 0x9c, 0x8d, 0x8b, 0xeb, 0x7a, 0x1e, 0xc3, 0xd2, 0x30, 0xb6, 0xc1, 0x45, 0x4b, 0xee } }, +{ "\xc9\x4d\x9c\xda", 4, { 0x00, 0x7b, 0x90, 0x9a, 0x99, 0xbd, 0xc8, 0x6b, 0x70, 0x54, 0x3b, 0x17, 0xfa, 0xae, 0x7c, 0xca } }, +{ "\x79\xf1\x29\x69\x5d", 5, { 0xb3, 0x8c, 0x03, 0x90, 0x92, 0x18, 0x1d, 0x76, 0xfe, 0x37, 0xb2, 0xb2, 0x49, 0x8f, 0x84, 0x5e } }, +{ "\x00\x7e\xdf\x1e\x31\x1c", 6, { 0x0b, 0x4f, 0x0a, 0xa5, 0x2b, 0xaf, 0x0c, 0x3b, 0x6f, 0x80, 0xaa, 0xd8, 0xfb, 0x25, 0x09, 0xbf } }, +{ "\x2a\x4c\xe1\xff\x9e\x6f\x53", 7, { 0xb6, 0xf1, 0x94, 0x8a, 0x57, 0x87, 0xfa, 0xe4, 0x18, 0x79, 0xab, 0x38, 0x5c, 0x4b, 0xc8, 0x5d } }, +{ "\xba\x02\xab\x18\x30\xc5\x0e\x8a", 8, { 0x9a, 0x13, 0x04, 0x08, 0x73, 0xb3, 0xe7, 0xd8, 0x22, 0xcb, 0x09, 0x11, 0xda, 0xce, 0xc2, 0x8b } }, +{ "\xec\x4e\x7a\x72\x1e\x71\x2a\xc9\x33", 9, { 0x01, 0xd2, 0x9a, 0x1a, 0x6f, 0x81, 0x70, 0x76, 0xac, 0x74, 0xe9, 0xbc, 0x5e, 0x70, 0x76, 0xcb } }, +{ "\xfd\xe2\x9c\x0f\x72\xb7\x08\xea\xd0\x78", 10, { 0x06, 0xd3, 0x6f, 0x5a, 0x8f, 0x86, 0x3b, 0xdd, 0x46, 0xa1, 0xa1, 0x5f, 0x75, 0xf0, 0x8f, 0xa3 } }, +{ "\x65\xc4\x8a\xb8\x80\x86\x9a\x79\x00\xb7\xae", 11, { 0x16, 0x2f, 0xc0, 0x17, 0x48, 0x37, 0xdc, 0xe0, 0x06, 0xa1, 0x78, 0xd5, 0xa8, 0xb7, 0xae, 0x2f } }, +{ "\x77\xe9\xd7\x80\x0e\x3f\x5c\x43\xc8\xc2\x46\x39", 12, { 0xc0, 0xa5, 0x2e, 0xda, 0x4e, 0x6c, 0xed, 0x9f, 0x3e, 0x36, 0x79, 0xac, 0x5d, 0x65, 0xb6, 0x88 } }, +{ "\x87\xd8\x61\x61\x4c\x89\x17\x4e\xa1\xa4\xef\x13\xa9", 13, { 0xda, 0xa3, 0x53, 0xaa, 0x70, 0xb5, 0xa2, 0xcc, 0x01, 0x60, 0xbf, 0x90, 0x60, 0x76, 0x42, 0x15 } }, +{ "\xfe\xa6\x5b\xc2\xda\xe8\x95\xd4\x64\xab\x4c\x39\x58\x29", 14, { 0xa9, 0x13, 0x46, 0x19, 0xc6, 0x8f, 0xed, 0x22, 0xde, 0xbf, 0x77, 0xbd, 0xfb, 0x61, 0xa4, 0x0d } }, +{ "\x94\x49\xc0\x78\xa0\x80\xda\xc7\x71\x4e\x17\x37\xa9\x7c\x40", 15, { 0xe3, 0x99, 0xd9, 0x33, 0xc9, 0xc6, 0xf5, 0x16, 0xdf, 0x60, 0x39, 0x1a, 0xe7, 0x56, 0x3e, 0x30 } }, +{ "\x53\x7e\x36\xb4\x2e\xc9\xb9\xcc\x18\x3e\x9a\x5f\xfc\xb7\xb0\x61", 16, { 0x92, 0x65, 0x17, 0x2d, 0xa5, 0xfb, 0x6d, 0x60, 0xdc, 0xd0, 0xce, 0x45, 0x52, 0x63, 0xad, 0x13 } }, +{ "\x59\xa9\x9f\xa6\xdb\xb7\x02\xc5\x95\x65\x34\x17\xde\xe5\xbb\xdf\xc5", 17, { 0x6d, 0xae, 0x56, 0xbf, 0xa2, 0x8b, 0x0a, 0x62, 0x3c, 0xf7, 0x12, 0x95, 0xe0, 0x3d, 0x9e, 0xa4 } }, +{ "\x0d\x52\x83\x32\x6a\x92\xf9\x9a\x6e\x3c\x3d\x5e\xc4\x25\xfe\xc1\xc4\xbe", 18, { 0xf2, 0x00, 0xea, 0x7b, 0x07, 0xe8, 0xf4, 0xf7, 0xbc, 0x36, 0xd5, 0x3b, 0x4a, 0x35, 0x01, 0x66 } }, +{ "\x59\x84\x02\x3f\xbc\x20\x01\x70\xed\xa0\x05\x14\x23\x18\x06\xf2\x52\xc5\xc1", 19, { 0xfc, 0x1c, 0x08, 0x2b, 0x38, 0x0b, 0x86, 0xf9, 0x62, 0x01, 0x50, 0x17, 0x13, 0x70, 0x86, 0xe8 } }, +{ "\x81\x84\xc3\xe8\x2f\x63\x65\x79\x4e\xd3\x34\x2c\x9c\xbc\x87\x05\x6d\xe5\xbc\x0a", 20, { 0xfb, 0xb8, 0x1e, 0xc4, 0x33, 0x0c, 0x81, 0x8b, 0x9f, 0x93, 0xf7, 0x33, 0xe4, 0xdf, 0x12, 0x0c } }, +{ "\x77\xfc\x10\x0f\x3a\xb2\x20\xad\x0a\x03\xfd\x51\xba\x93\xe6\x70\xe7\x34\xa4\xd8\xde", 21, { 0x09, 0x77, 0x2c, 0xd4, 0xc8, 0x21, 0xce, 0xf3, 0x15, 0xee, 0x0a, 0xef, 0x1b, 0xdf, 0x79, 0x31 } }, +{ "\x84\x87\x22\x2b\xb3\xf8\x44\xbf\x63\xbb\x43\xbd\xa8\xc4\x05\xe1\x2f\xb2\x44\x8d\x7a\xec", 22, { 0xc7, 0xb8, 0x65, 0x7e, 0xbc, 0x87, 0x1f, 0xbb, 0x56, 0x47, 0xde, 0x82, 0x6d, 0x23, 0xdc, 0x23 } }, +{ "\x9f\x72\x49\x57\xca\xd7\x15\xb1\xe6\x89\xb5\x8d\xec\x5f\x24\xeb\x42\x69\x5a\x73\x70\xb5\x56", 23, { 0xc0, 0x92, 0x04, 0xcb, 0x56, 0x1c, 0x82, 0x54, 0x66, 0xff, 0x4d, 0x02, 0xa4, 0x75, 0xfb, 0xab } }, +{ "\x4e\xec\xbd\x3d\xa2\x11\x70\x9c\xa8\x2e\xdb\xca\x6b\xbb\x74\x69\x1e\xa7\x03\x0b\x1b\xcd\x2e\xf0", 24, { 0x96, 0x49, 0x0a, 0x9c, 0xef, 0x7d, 0xe0, 0x15, 0x4d, 0x76, 0x7a, 0x39, 0x7e, 0x2d, 0xe8, 0x58 } }, +{ "\x74\x84\x9f\xed\x38\x55\xd4\x69\x44\xc8\x82\x82\xc2\x57\xa7\x4d\x43\x84\x2b\x3a\x75\x06\x32\x95\x81", 25, { 0x7f, 0xaa, 0x9d, 0xbf, 0xa5, 0xb8, 0xad, 0xe4, 0xaa, 0x1e, 0x11, 0xb3, 0x83, 0x59, 0xec, 0x8f } }, +{ "\x1e\x01\x28\x03\x09\x8a\xfe\xa7\x8e\x95\x42\x5d\xb7\x8d\x46\x38\x9c\xe5\xa1\xe8\x5a\x25\x70\xd2\x23\x95", 26, { 0xb2, 0x19, 0xf5, 0x35, 0xe2, 0x17, 0x94, 0xd8, 0x0c, 0x5c, 0x03, 0x78, 0x66, 0xd3, 0xe8, 0x94 } }, +{ "\xbc\xc9\x70\x84\xfc\x6c\x51\x35\xb1\x1c\xe4\x67\x2f\x97\xe4\x80\x7c\x36\x59\x55\x51\xbf\x6d\x98\x3d\xe8\x5f", 27, { 0x79, 0xca, 0xd3, 0xb3, 0x5d, 0xee, 0x4d, 0xa4, 0x00, 0xa9, 0x5c, 0x20, 0x3b, 0x19, 0x7d, 0x16 } }, +{ "\xdf\xe9\x69\x90\x4d\x76\xbc\xbb\xdf\x03\x74\x42\x55\x4a\x37\xa3\xba\x6a\x5a\x09\x92\xbf\x17\xff\xa0\xed\x6d\x3f", 28, { 0x7c, 0xca, 0x53, 0x89, 0xcd, 0x37, 0x11, 0x06, 0xf9, 0xd0, 0x8e, 0x41, 0x17, 0xd7, 0x42, 0xe4 } }, +{ "\x51\xfc\x95\xa9\xc8\x9d\x1c\x4f\x87\x8b\xa2\xad\xb7\x0d\x2d\xf6\x14\x98\x2b\x89\x77\x91\x02\x83\x01\x2f\x56\x6e\xe1", 29, { 0xdb, 0x92, 0x9e, 0xe8, 0x1e, 0xf7, 0x3a, 0xc6, 0xfc, 0x66, 0x8b, 0x7f, 0x3b, 0x77, 0x56, 0x64 } }, +{ "\x7f\xd6\x16\xc3\x81\xc3\x7c\xd6\x70\xff\xe4\x77\x1f\xcd\x09\x7f\x7f\x2b\x71\x26\x3d\xc9\xdb\x92\x88\xa5\xd4\x00\xf0\x44", 30, { 0x6d, 0x2e, 0x0a, 0x81, 0xbc, 0x6a, 0xd7, 0x2d, 0x04, 0xba, 0x4a, 0xcc, 0x0b, 0x3b, 0xc9, 0xf8 } }, +{ "\x68\x8e\x6a\x8e\xf6\xa2\x70\x47\x1d\xfb\x45\x26\xd2\x52\x56\x94\x94\xac\xbc\x02\xb6\x3f\xde\xe7\xdb\xfe\x34\x55\x81\xc3\x26", 31, { 0xe3, 0xc8, 0xa6, 0x56, 0x3f, 0x8c, 0x6e, 0x64, 0x11, 0xb3, 0x8a, 0x09, 0x95, 0xcf, 0xa0, 0xe1 } }, +{ "\x37\xb3\x18\x13\x29\xe2\xa2\x6d\xf4\xce\x2b\x01\xa5\x9f\x4b\x54\x48\x10\xb1\x29\x46\xcb\x13\x20\x58\xcf\xb0\x78\x27\x0d\x7e\xf5", 32, { 0xe0, 0x0a, 0x19, 0xff, 0x6e, 0xee, 0x06, 0x88, 0xea, 0x38, 0x6b, 0xc8, 0x68, 0x6a, 0x94, 0xa2 } }, +{ "\x82\x13\xf6\xdd\x3b\xdf\x78\x1c\x9e\xd6\x5b\x87\x8f\xcd\x95\x3d\x3f\x43\x04\x2a\x8b\xb2\x57\xa5\xf1\xfa\x9c\x39\x2f\xfe\x66\x81\x7a", 33, { 0x2b, 0xba, 0x42, 0x8d, 0xb0, 0x96, 0xcd, 0x0c, 0xc3, 0x6a, 0x05, 0x7c, 0x81, 0x42, 0x6f, 0x4c } }, +{ "\x4a\x9a\x2c\x58\xf1\xd6\x21\x1a\x76\x7f\xbc\xfa\xe0\x66\x35\xcd\xf1\x17\x22\x64\x6f\xbd\x13\x85\xa1\xb5\x5b\x81\xd6\xad\xee\x72\x1e\x79", 34, { 0x20, 0xdf, 0x47, 0x95, 0xc3, 0x0d, 0x81, 0x29, 0xdc, 0xd2, 0xf7, 0x28, 0x7c, 0xf8, 0xef, 0xa9 } }, +{ "\x66\x13\x1c\x72\x20\x3c\xf3\x8b\x83\xf8\x5e\xf2\x60\x44\xdc\x5e\x75\x67\x08\xfb\x0c\xe9\x07\xf0\xc1\x31\x1a\x89\x60\xbf\x53\x06\xed\x02\x64", 35, { 0xe9, 0x2a, 0x0c, 0x85, 0xe6, 0xaa, 0x86, 0x00, 0xdd, 0xb1, 0x3e, 0x0f, 0xa4, 0xd2, 0x5d, 0xa1 } }, +{ "\xff\xbd\xd6\x92\x72\xc1\x9e\xc9\x6b\xe3\xfb\xca\x4e\x88\x26\x7f\xc4\x36\xf0\x70\x40\x4f\x53\x4d\x2d\xfc\xb3\xab\xb6\x25\xb7\xcc\x31\x9c\xbf\x97", 36, { 0x90, 0x40, 0x16, 0xeb, 0xb9, 0x97, 0x22, 0xd2, 0x28, 0x99, 0xd8, 0x87, 0x57, 0x71, 0x58, 0x9c } }, +{ "\x29\x59\x01\xa6\x06\xe0\x43\x7e\x5b\xbf\x37\xda\xcc\x33\x6e\x20\x9a\xeb\xfa\xf5\xcd\xe4\xa5\xec\xfd\x73\xc7\x59\xbc\x61\xc8\x44\xa3\x30\x33\x79\xf8", 37, { 0xf4, 0x09, 0x5a, 0x82, 0x2b, 0x32, 0x80, 0x9a, 0x0a, 0x71, 0x32, 0x74, 0x57, 0x18, 0xc5, 0x40 } }, +{ "\x7c\x72\xbd\xf9\x7d\x2c\x1b\xc8\xa9\x38\x5c\xf2\x76\x3c\x94\x9d\x3d\xe7\xd9\x4e\x3a\xc7\x0f\x55\xb0\xc7\xdf\xd5\x29\x49\xc6\x74\xdb\xdc\x49\x9b\x27\x9a", 38, { 0x12, 0x88, 0x65, 0xe1, 0x77, 0x1a, 0x72, 0xd0, 0x39, 0xc4, 0xcd, 0xc6, 0x21, 0x0e, 0xa5, 0x13 } }, +{ "\x46\x6a\x3b\x21\x66\x3c\xd6\x2c\xaf\xd2\x2b\xcd\x36\x1e\xdf\x49\xf2\xae\x2d\x8f\xab\xb3\x29\x57\x10\xae\x22\xd4\xe8\xb6\x20\x15\x61\x68\x8c\xfd\x85\x6b\xef", 39, { 0x31, 0xe0, 0x8f, 0xd8, 0xfd, 0x6b, 0x31, 0xa2, 0xc4, 0x03, 0x70, 0xb9, 0xe1, 0x0d, 0x95, 0x16 } }, +{ "\xdd\xca\x9e\xd3\xab\xc8\xe1\xc5\xe2\x05\x7d\x7c\xf5\xec\x31\x14\x71\xdd\xda\x73\xae\x5e\xbd\xcd\x31\x6e\x74\x42\xa1\xfa\x74\xa4\x64\x69\x37\x57\xd6\x52\x0a\x51", 40, { 0x44, 0xa4, 0x8b, 0x8f, 0x05, 0x9d, 0x67, 0xeb, 0x05, 0xac, 0xed, 0x43, 0x92, 0x50, 0x91, 0xf9 } }, +{ "\x26\x4d\x75\x42\xcc\xe7\x42\xcd\xaa\xaf\x2c\xf3\xbf\x6d\x26\x91\x82\x72\x44\x00\xe1\x0b\x4a\xda\xd5\x0f\xd0\xdc\xa2\x98\x0e\xe7\xa8\xce\x4a\x21\xe9\xdf\xdb\x38\x18", 41, { 0xae, 0x76, 0x17, 0x96, 0x45, 0x61, 0xbb, 0x31, 0xbb, 0xf5, 0xc4, 0x6e, 0xe9, 0xc6, 0x22, 0xf8 } }, +{ "\x0b\xd8\xc7\x5a\xdb\x62\xd1\x9c\x71\x8b\x69\x90\xfb\xe2\x74\x45\x41\x9d\x87\x61\x5e\x61\xea\xfe\x8c\xb0\xbe\x1f\x18\xef\x3a\xce\x74\x13\x11\xd3\x6b\xe8\xf0\x12\x6f\xfe", 42, { 0x07, 0xd5, 0xac, 0x77, 0x53, 0xc4, 0x8c, 0xd9, 0xb4, 0xec, 0x2b, 0xa5, 0xa5, 0x57, 0x45, 0xaf } }, +{ "\x23\x82\x0e\x30\x57\xc6\x83\xd2\x7a\x69\x69\x76\xbf\xbb\x8b\x5b\xbd\x42\xd6\x73\xb7\xdf\x70\x10\xf6\x7f\xe1\x2a\x53\x7a\x6f\x4f\xd1\x8b\x89\x27\x66\x6d\x59\xa3\xdb\x0e\x7c", 43, { 0x52, 0x80, 0xcc, 0x28, 0xb7, 0x1b, 0x2d, 0x6f, 0xcd, 0x73, 0xe1, 0xd7, 0xa9, 0xd0, 0xe6, 0xb4 } }, +{ "\xc2\xc9\x72\xce\xff\xc3\x27\x5e\x5b\x92\x60\x81\x02\x9b\xb1\x02\x9d\x5d\x66\x77\x33\x17\x80\xaf\xbc\x86\x4d\x47\x44\xcc\xa3\x5b\xb9\x6c\xb9\x5a\x51\x72\xa1\xf3\x9a\xb0\x66\x2c", 44, { 0xe3, 0x96, 0x4f, 0xe1, 0x37, 0xb0, 0x7a, 0xc6, 0xeb, 0xbe, 0x59, 0x4f, 0xfa, 0xaa, 0x95, 0xf1 } }, +{ "\x1f\x22\xbe\x91\xb4\x73\x6c\x89\x5f\x99\x35\xc4\xe3\x9b\x7c\xd0\xea\x73\x7c\xcb\xce\x0e\x22\x33\x04\x6f\x85\xd9\x25\xf4\x03\xf4\x9b\xb1\xf9\x52\xe4\xf8\x1e\xa9\x86\xfb\x7d\x0c\x8f", 45, { 0x6f, 0xb0, 0xa2, 0x69, 0x84, 0x9d, 0x97, 0x2b, 0x05, 0x8d, 0x15, 0x87, 0x7b, 0x2b, 0xa3, 0xc0 } }, +{ "\x88\x0d\x79\xc8\xf2\xee\x8f\x76\x10\x42\x5d\xcc\x5f\xa6\x55\xf0\x43\x4c\x5f\xa8\x6b\xb7\x0a\xa1\x51\x11\xdd\x5c\xe1\x2c\xcc\xb6\x31\x13\xc6\x12\x6f\x4c\x6b\x24\xd9\xae\xdb\x5d\xe4\xd9", 46, { 0x8c, 0x08, 0x81, 0x71, 0xd6, 0xf1, 0x21, 0x47, 0xe1, 0xac, 0x8a, 0xed, 0x99, 0xa2, 0x4c, 0x1f } }, +{ "\xaa\xee\x80\x55\xef\x7b\x73\x4a\x7c\x5e\xe2\xd9\x27\x95\xef\x17\x47\x49\x7b\xa4\x3b\xfc\x0c\xeb\x24\x4e\xca\xf8\xb2\x6b\xa4\xf0\x1c\x14\x90\x32\x29\x49\xef\x09\x6c\x91\x0e\x0a\x8d\xe5\xc9", 47, { 0xca, 0x4d, 0x13, 0x4c, 0xb6, 0xdf, 0xee, 0x5b, 0x9f, 0xb9, 0x05, 0x0d, 0xb6, 0x91, 0x7d, 0xd7 } }, +{ "\x11\xc1\x3f\x4a\xd2\x5b\xba\xef\x1e\x7c\x66\x4a\xb5\xe6\xaa\x41\xc2\xef\x56\x56\xf7\x91\x45\x01\x45\x9e\xab\x3a\x38\x10\x01\x13\xee\x7f\x8a\x81\xb2\xab\x80\x3b\x39\x39\xe0\xba\x78\x7b\xcf\x61", 48, { 0xf5, 0x57, 0x8d, 0x27, 0xa0, 0xa1, 0xcb, 0xc7, 0xe8, 0x2f, 0x77, 0xec, 0xdd, 0xa3, 0x84, 0xf7 } }, +{ "\x20\x68\xa7\xb7\xb8\xab\xa3\xcf\x55\xd7\x23\xc9\xf7\xb7\x9b\x71\x83\xc3\x1e\x04\x59\xaf\x83\x13\x91\x1e\x31\x81\xd7\x75\x8d\xa6\xe0\xca\xfc\x96\x88\xfa\x97\x7c\x8a\xd9\x6b\x1f\xdb\x85\x69\x87\xa3", 49, { 0x94, 0x10, 0x45, 0x76, 0xe9, 0xd7, 0x75, 0xce, 0x30, 0xcb, 0x28, 0xb7, 0xbc, 0xc0, 0x98, 0x94 } }, +{ "\xd4\xf1\xb9\xd9\xeb\xf5\x9d\x7a\xf0\xcd\x01\x65\xd7\x98\xb6\xd6\x59\x49\xd8\x7d\x03\x55\x2c\x3a\x6b\xf7\xa1\x78\x7d\x1e\xf9\x23\xf3\xf5\x81\x47\xe3\x0c\xfc\x46\x72\x28\x9e\xb6\xa6\xa4\x34\xd5\x5a\x81", 50, { 0x8f, 0x3d, 0x45, 0x4f, 0x31, 0xdc, 0xf9, 0xdc, 0x48, 0xbe, 0x95, 0x53, 0x80, 0xf1, 0xc0, 0x74 } }, +{ "\x61\xa9\x4a\x12\x02\xb8\x4e\x3d\xb3\x61\xa4\x6e\x6b\xd6\x66\x1e\x42\xb7\x1a\xfb\x54\x4b\x68\xb5\xbd\x5d\xe6\x65\xc3\xb1\x0f\x99\x13\x22\x53\x00\x24\x59\x48\xaf\xb8\x2c\xfe\x0d\x81\x90\x70\x62\xe0\x3c\x15", 51, { 0x5d, 0xe7, 0x06, 0x6a, 0xbc, 0x01, 0xd0, 0x64, 0x94, 0x29, 0xae, 0x04, 0xf1, 0xcc, 0xb5, 0xd6 } }, +{ "\xf6\xc8\xdd\x96\xe9\xc2\xef\x9b\x8f\x09\x3f\xbf\x85\xd5\xfa\xa2\x55\xb5\x70\x1c\xc1\x15\x6b\x8e\xb0\xdf\x26\x55\xb2\x3e\xec\x58\x32\x7e\x4f\xc1\x37\x10\x01\xc8\xd6\xa9\x52\xab\x38\x89\x46\xba\x44\xd9\x52\x8e", 52, { 0x84, 0xae, 0x25, 0xbc, 0x36, 0x9c, 0x91, 0x9b, 0x44, 0x2e, 0xd6, 0xef, 0x9e, 0x1f, 0xe2, 0x8f } }, +{ "\xe9\x2d\xb3\x5a\x09\x2a\x6c\x59\x05\x41\xda\x67\xe1\x99\xf5\xac\x14\x0b\x25\x73\xef\x47\xbe\x19\xa7\x14\x1a\x20\x01\xb4\x52\x63\x99\x65\x98\x64\xce\x04\x34\xc1\x4d\xcd\x19\xc5\x39\x3d\x24\x1b\xf4\x18\xf0\x9e\x8d", 53, { 0x1e, 0xa3, 0x3b, 0xad, 0x84, 0x80, 0xa6, 0x3e, 0x7a, 0xbe, 0xe1, 0xc2, 0xf6, 0x07, 0x6c, 0x8f } }, +{ "\x86\x58\x4b\xc6\x59\x8a\x58\xc0\x6a\xc4\x5e\x45\x21\xaf\xb1\xb2\x12\x54\xd0\x7f\xc4\xbf\xf8\x6d\x8e\x2f\xd3\x4b\x9b\xf6\x4e\x64\x0c\xf3\x88\x88\x3c\xaa\xe6\xb5\x1f\xfd\x43\x63\xc3\x89\x45\x69\xf9\xa0\xcb\x8f\x0d\xde", 54, { 0x18, 0x55, 0xdc, 0x67, 0x81, 0x98, 0xdf, 0x9d, 0x59, 0x3d, 0xed, 0xb3, 0xf2, 0x14, 0x22, 0x43 } }, +{ "\x82\xb1\xb0\x6a\x97\x8c\xf7\xcb\x86\x28\x7c\x64\x11\xe2\xa2\x8e\x4d\x15\xf7\x50\xd6\x64\xb2\xbd\x23\xa7\x5b\xeb\xf4\x70\x8a\x8b\xe8\x39\xc7\x2a\x2b\x2b\x91\x03\x4c\x8d\x7a\x7e\x2c\xc8\x6f\x49\x12\x13\x16\x12\xdc\xbf\x50", 55, { 0x7c, 0xd8, 0x1e, 0x1e, 0xfb, 0x01, 0xad, 0x5a, 0x4c, 0x0e, 0x83, 0xbd, 0x9d, 0x2e, 0xe1, 0xff } }, +{ "\xde\x50\x21\xdd\x09\x91\x17\x1f\xda\xad\x39\xf7\xc2\x53\x9e\xcc\x32\xa2\x48\xaa\x16\x1c\x2d\x86\xf1\xb9\xe2\xa0\x96\x18\xe6\x01\x80\xd0\x89\x24\xcf\xe5\x77\xb1\xe0\x57\xe5\x64\x87\xd4\x57\x0d\xeb\x8d\x0b\xb0\xff\x25\x06\xcc", 56, { 0xb5, 0x25, 0x80, 0x30, 0x10, 0x74, 0x47, 0xb8, 0xac, 0x64, 0xa9, 0x31, 0x47, 0xd4, 0x6a, 0x69 } }, +{ "\x99\xc6\xb8\xb9\x30\x4e\x4e\x2a\x37\xa7\x95\xd2\x10\x35\x86\x24\xaf\x68\x72\x32\xcc\x71\xcb\xb7\xc4\x11\x8c\x30\x0d\x8c\x46\x24\x54\xbd\xc8\x85\x35\x43\x6b\x2f\x96\xd9\xf7\x8d\xa0\xc4\x36\x5b\x5b\x65\x13\x85\xe6\xee\x6d\x2f\x4f", 57, { 0xf2, 0xeb, 0xbc, 0x0f, 0x7b, 0x22, 0x29, 0x53, 0xd2, 0xcb, 0x16, 0x52, 0x41, 0x8f, 0xf5, 0x27 } }, +{ "\x31\x7e\xce\x15\x94\xe2\x73\x37\x21\x47\x28\xf8\xba\xb0\x73\x32\x69\x65\xf7\x54\xd6\x7b\x3a\xfa\xd2\xfc\x82\x28\x0f\xb2\xd8\x22\xf2\x95\x2e\xea\x81\xce\x9c\x57\x77\x67\xc6\xce\x77\x92\x5a\xa0\x5d\x93\xb6\x00\xaf\x4a\xa6\x9f\x32\x61", 58, { 0xb7, 0x47, 0x82, 0x40, 0x69, 0x9d, 0x2d, 0x25, 0xd5, 0xce, 0x1b, 0xd5, 0xeb, 0x8c, 0xbf, 0x71 } }, +{ "\x4b\xe6\x99\x0e\x17\xcf\x58\x85\xf4\x60\x98\xfe\x84\xc6\x43\x5e\x84\x0a\x3e\x84\x4a\x72\xb7\x33\x6d\x77\x94\x97\x83\x5d\x0a\x76\x05\x75\x4f\xf4\x4f\xeb\x67\x02\xc4\x4c\x1b\x65\x0f\x99\x09\x5f\x84\x00\xd4\xfc\xa4\x3d\x7b\xfa\xbf\x8d\xc7", 59, { 0x82, 0x36, 0x57, 0xa2, 0xc1, 0xad, 0x78, 0x3f, 0xb9, 0xfb, 0xa2, 0xc6, 0x79, 0x7e, 0xca, 0x7a } }, +{ "\x55\xb4\x4a\xde\x6f\xd4\x28\xf6\xd9\xe5\x0a\x23\xc1\x42\x82\x50\xf8\x20\xe4\x4c\x9e\xeb\x05\xfc\x6b\xce\x95\xaf\x9d\x52\x16\x8f\x7a\x1e\x78\x32\x81\xdd\x53\x50\x31\x3d\xc0\x8f\x75\x13\xd5\x7b\xaa\x9b\xbb\x91\x4f\xdd\x6c\x7a\x48\x2c\x0e\x55", 60, { 0x7a, 0x3f, 0x5c, 0x60, 0x63, 0x7e, 0x72, 0xdf, 0xcc, 0x23, 0x8a, 0xa3, 0x84, 0x14, 0x20, 0xe2 } }, +{ "\xcf\xc9\xe7\x2d\xf7\xa4\xfd\x8a\xde\x42\x4b\x23\x6f\xba\xa1\xb1\xd1\xd9\x19\xde\x70\x65\x31\x5c\xa6\x7f\x8a\x13\x05\x21\x3c\x72\x43\xc7\xd4\xe7\xc3\x2b\xeb\x69\xbc\x28\x64\x32\x08\xc0\x41\x8b\x8b\x39\x22\xbf\x3e\x62\x5c\x31\xd7\xf3\xb2\x8a\x17", 61, { 0xe3, 0x74, 0x31, 0xe3, 0xd2, 0x5e, 0x01, 0x00, 0x51, 0xde, 0x8c, 0x48, 0x58, 0x76, 0xaa, 0xca } }, +{ "\x12\xb3\x0a\xb0\xf2\xaf\x00\xd0\x96\x57\x55\x4e\xb4\xf0\x42\x70\xb4\x34\x21\x56\xd7\xc5\x61\x07\x75\x4f\x94\x17\x5e\x39\xa3\xf1\x62\x07\x21\xc7\xed\x4f\xbc\x13\xca\x55\xd0\xc8\x08\x46\x15\x1a\xfa\x0d\x79\xe7\x58\xd6\x09\xc0\x82\x1d\x08\x98\xe5\x72", 62, { 0x14, 0x7a, 0x4d, 0x78, 0xbe, 0xcf, 0x03, 0xf0, 0xa6, 0x57, 0x16, 0x8d, 0x7e, 0x07, 0xa8, 0x36 } }, +{ "\x22\x09\x76\xcb\xba\x3d\x5c\x85\x60\x7f\xaa\xf9\x5e\x5e\x4a\xb7\x71\x7b\xf5\x62\x95\xf0\x5e\x28\xf9\x5d\x6e\xdb\x12\x90\xaa\xb1\xcc\xd0\xb2\x95\xdb\xc7\xe3\x27\x2f\x09\x1b\x57\x85\x45\x9c\x99\x1a\x07\x09\xc5\x7a\x27\x8e\x8f\x77\xd2\x1d\x9e\x36\x32\xd3", 63, { 0x8d, 0x97, 0x7a, 0xb1, 0x6f, 0x7a, 0x54, 0x80, 0x88, 0x10, 0x07, 0x3b, 0xb4, 0x6a, 0x19, 0xb9 } }, +{ "\x4a\x64\xbd\x79\xf7\x86\x17\x25\x09\x6d\xa5\x01\x83\xc7\xaf\x23\x3f\xd2\x31\x9c\xcc\x2c\x3f\x8d\xdf\xc7\x12\x72\x78\xf8\xb3\x82\x93\xae\x42\x2f\x86\xbf\xe3\xc8\xfd\x5e\x46\x3f\x90\xa9\xd2\x04\xfe\x5f\x6e\x0f\x09\xaf\xeb\xfd\xed\x2b\x11\x52\x7e\xdc\x45\xdd", 64, { 0x15, 0xf4, 0x8b, 0xb9, 0x10, 0x92, 0xcd, 0x68, 0x96, 0xc1, 0x4c, 0x7d, 0x00, 0x47, 0x36, 0x34 } }, +{ "\xdd\x6e\xd4\x39\xd6\x8c\xde\x6f\xda\x47\xe1\xb9\x94\xaf\xe1\x62\x29\x84\x32\xc9\x11\x06\xe2\x84\x8d\xe9\xc5\xa0\xc4\x65\x1d\x07\x7e\x69\xe6\xfb\x7c\xef\xbc\xbe\x71\x6b\x6a\x54\xa1\x5d\x10\x60\x15\x06\xf0\x2b\x78\x37\xd5\xc4\x92\x44\x20\x41\x5e\x18\x70\x23\xc9", 65, { 0x8e, 0x53, 0x6f, 0xfb, 0xda, 0xda, 0x44, 0x77, 0xb3, 0x44, 0x3e, 0x65, 0xec, 0xbc, 0x40, 0x2a } }, +{ "\x62\xed\xd8\x0a\xed\x32\x59\x98\x0e\xd4\xf4\xcd\x36\x93\x24\x15\xa7\x1d\x9c\xd2\x44\x79\x63\xd0\x81\x16\x18\x60\x79\x71\x57\x13\x1e\x5d\x34\x15\x8a\xf2\xe4\x23\x75\x14\x7c\x2a\xc0\x9f\xd1\x7e\x2d\x2c\x7d\xb3\x32\x83\x03\x1c\xe2\x9d\x0a\xdd\x0b\x54\xc6\xaf\x5f\xa9", 66, { 0x3b, 0xd1, 0xd1, 0xc0, 0xfa, 0xcb, 0x9c, 0xdb, 0x86, 0x97, 0x8f, 0x09, 0x31, 0xa6, 0x10, 0xca } }, +{ "\x74\x30\xca\xb2\x03\xe5\xe2\x1e\xd0\xcd\x7d\x66\x8a\xa2\x5c\x92\x35\xaf\x04\xa5\x4a\x49\xad\xa7\xfb\xeb\x54\x4d\x93\xf2\xeb\x46\xfc\xf1\xb1\x24\x5a\xb2\x9c\xe5\xd5\xca\xf1\x1e\x75\xd8\xf6\xc3\x26\x5a\xc0\x95\xda\x2b\x26\x28\xcd\x9d\xd6\x90\xe4\x2f\x85\xa8\x2f\xeb\x42", 67, { 0xfe, 0x03, 0x68, 0xe3, 0xc5, 0xf8, 0xb8, 0x4d, 0x9b, 0x29, 0x4b, 0x26, 0x36, 0x39, 0x34, 0xe6 } }, +{ "\xfe\x8e\x5f\xe4\x5e\x6f\x35\xa2\xfa\xb5\x71\xc1\x33\xb4\x47\x68\x06\x59\x97\x8f\x16\x67\x06\x16\x52\xdc\xba\xf2\x42\x72\xb1\x82\xf3\x41\xbf\x00\x7d\x81\x22\x12\x2e\x6e\xc3\x80\x55\x44\x0c\x01\xac\x6a\x60\x2e\x63\xab\x3b\x98\xc5\x9f\xe8\xf5\x89\x28\xd9\x75\xb8\x18\xa6\x33", 68, { 0xb7, 0x0e, 0x24, 0x63, 0x59, 0x66, 0x0c, 0xa2, 0xfb, 0x46, 0xc6, 0xa1, 0x72, 0xd1, 0xd9, 0x3f } }, +{ "\x35\xf0\xa5\xc6\xee\xc3\x22\xf8\x9e\x3a\x3b\x8e\x3c\xb0\x5b\x46\x03\x7d\x51\xdf\x1f\x50\x0c\x52\xf1\xb6\xf5\x1e\xff\xb7\xe9\xc1\x7b\x9f\xd2\x42\x6e\xda\xe1\xeb\x81\xf9\x69\x15\x68\xd1\x5b\x1b\xec\xc2\x5a\x71\x93\x15\x7a\xcd\xed\x7f\x9a\x83\x7e\xc2\x5b\xee\x43\x73\xbc\x0a\xe3", 69, { 0xd4, 0x3f, 0xb8, 0xeb, 0x1a, 0xb1, 0xed, 0xed, 0x3a, 0x26, 0x8f, 0x0b, 0x7d, 0x06, 0x0a, 0x64 } }, +{ "\xd6\x54\x1f\x73\xe5\x2b\x98\xe6\x70\x34\xf2\x10\x5e\x6b\xd0\x55\x11\x87\x2b\xf2\xe8\x5d\xa6\xe7\xde\xd1\xff\x80\x4f\x79\xa2\x7f\xdb\xd0\x58\xe8\x63\x13\x1c\x69\x31\xbb\x0e\x63\x34\x98\x81\x99\x68\x87\x2f\x74\x54\xd0\x8c\xf0\xad\x1e\x37\x27\x18\x1b\x8d\x78\x0d\xa8\x58\x54\xd7\xb6", 70, { 0xbd, 0x93, 0x38, 0x13, 0x7b, 0x70, 0x0d, 0xa8, 0x1b, 0x1a, 0x7a, 0x2d, 0xbe, 0x11, 0x15, 0x38 } }, +{ "\xa5\xa5\xb7\xc4\xb3\xda\x29\xf5\x07\x93\x3e\xcd\x9d\xe6\x28\x88\x38\x4c\xd4\x17\xdb\x2c\xb2\xb8\x50\x01\x90\x30\xe5\x2a\xa4\xa8\x37\x4e\xa8\x21\x26\x69\x20\x96\xe8\x78\xb7\xad\x39\xbd\xc7\x19\xb0\xaf\xf8\x8f\x2d\x82\x00\x62\x6f\x4e\x88\xbd\xc2\xdf\x2f\x7d\xd5\x18\xa7\xa9\xa9\x04\xfd", 71, { 0x7a, 0x7d, 0xc9, 0x94, 0x96, 0xaf, 0x51, 0x90, 0xc5, 0x48, 0x51, 0x9b, 0xeb, 0xd2, 0x6d, 0x3c } }, +{ "\x8e\xa6\x7b\xf7\x7b\xc8\x6d\x96\x16\xf6\xce\xbb\x5a\x73\x1e\xe6\x2e\x6d\x93\x19\xa2\xb3\xe6\xdb\xc8\x84\xb7\x58\x2d\x83\x9e\xa6\xf3\xc6\xcf\x22\x8c\x0d\x69\xf9\x15\x0f\x5b\xc3\x4d\xf0\xf3\x49\x30\xd0\x05\x67\x34\x7d\xb4\x0d\x1f\x48\xe0\x5f\x83\xf5\x2c\xfc\xd7\xcc\xaa\x5c\x34\xcc\x26\x53", 72, { 0x82, 0x13, 0x1c, 0x29, 0xf6, 0x16, 0x5a, 0x23, 0xba, 0xc4, 0x25, 0x2c, 0x5a, 0x9e, 0x9b, 0xde } }, +{ "\xa9\xff\x0c\xb2\x3b\xe9\xf7\x0c\x7c\x1a\xd6\x96\xc6\xe3\xbd\x28\x15\x25\x46\x60\x7e\x45\xa1\xe6\x50\x3b\x3f\xc9\xc6\xca\x17\x08\x65\xca\x94\x2e\xf8\xa1\x1b\x14\x26\xd0\x3c\xca\xad\xa9\x74\x91\x3d\x1e\x9d\xff\xf3\xb5\xf3\x45\x70\x99\xc3\x8e\x96\xca\xb2\x7d\xdf\x73\xa7\xd9\x59\x5c\x56\x45\x42", 73, { 0x92, 0x2d, 0x15, 0x76, 0x2c, 0xb6, 0xf5, 0x81, 0x60, 0xcc, 0x0e, 0xd5, 0x09, 0xff, 0x39, 0xb8 } }, +{ "\x76\x6a\x28\x3c\x94\x4e\xab\x2c\x39\x99\xe0\xb5\x8c\x14\x00\x4c\x68\x68\xcd\xf8\x90\x69\x16\xa9\xff\xf9\x59\x32\x5e\x9a\x82\xe3\x8f\x94\xd2\xc7\x66\xbf\xdb\x77\x78\xee\xa7\x99\x0b\xf8\xf9\xf9\x2d\x64\xab\x41\xe0\xb0\x36\x58\x72\x3e\x50\x55\xec\xdc\xb0\x1f\xa0\xee\xed\xa3\xe5\x3a\x84\xb0\xe0\x50", 74, { 0xa5, 0x43, 0x80, 0x60, 0x02, 0x56, 0x20, 0x34, 0xdf, 0x73, 0x76, 0xbf, 0xe5, 0x73, 0xcb, 0xbc } }, +{ "\xf8\x72\x78\x94\x14\x89\x6b\xea\x4c\xc5\x7f\xfc\x42\x80\xd0\x2a\x64\x98\x48\x0f\xb2\x08\x2e\xad\x9d\x23\xd5\x34\x0b\x6c\x74\x74\x78\x14\x16\xdc\x36\x11\xa8\x2e\xd4\xd7\x30\xc1\x9d\xb5\x1d\x72\x38\xcf\xb9\x28\x6d\xb4\xba\x03\x07\x9b\xf8\x21\xd4\x3f\x3a\x0c\xc9\x54\x29\xc3\x42\xa4\x66\x64\x68\xcb\xb7", 75, { 0xf9, 0x8f, 0xcc, 0xd8, 0x9b, 0xcd, 0x41, 0x55, 0x5b, 0xb0, 0xb5, 0xa2, 0xf4, 0x53, 0x3a, 0x88 } }, +{ "\x73\xac\x8b\x5c\xc9\x6f\xcd\x80\x1b\xc4\x35\xcb\x26\x4d\x60\x14\x74\x42\xbd\x34\xce\x90\x05\xf6\x3f\x1d\x58\x2a\xc0\x2a\xf6\xd9\x85\xd2\x96\x92\xe3\xaf\x66\xe3\xdc\x9c\xa0\xe3\x49\x94\xc6\xec\xa2\xb9\x7a\x67\x6d\x71\xfc\xc0\x41\xab\x40\x78\x76\x40\xab\x58\x6c\x74\x6a\xc3\x74\x9b\x6f\x25\x5e\xd8\x09\x88", 76, { 0xaa, 0x3b, 0xd6, 0x8d, 0x86, 0x26, 0x1f, 0x65, 0xe7, 0x23, 0x96, 0x84, 0xda, 0x55, 0xa7, 0x8d } }, +{ "\x9f\x01\x1f\x45\x1f\x9e\x09\xd7\x9d\x10\x0c\xcb\xc0\xcf\x6f\xd3\xbb\xcc\x3e\xfb\x9b\xf5\x9b\xf3\x30\xd7\xbb\x8a\x96\x5d\x84\x3c\x5f\xb6\xc2\xe2\x5e\x55\x00\x87\x12\x12\x09\x5b\xae\x6e\xfb\xc1\xc1\xf3\x04\x83\x87\xba\xbc\x25\xcb\x06\x1f\x57\x77\x0e\x25\x83\xba\xd8\x00\x87\xd4\x41\xf2\x7d\x81\x19\xc8\xb5\x00", 77, { 0xe5, 0xee, 0xc1, 0x56, 0xbb, 0x5a, 0x4f, 0xa7, 0x4c, 0x76, 0x0d, 0x17, 0x27, 0xfb, 0xc2, 0x3e } }, +{ "\x6b\xf6\xc4\xbe\xda\x50\xb6\xa4\x26\x63\x5e\xfa\xce\x6e\xcf\xf6\xd0\x00\xe3\xe5\x8c\x2f\xf8\xf5\xc7\x72\xbb\x9d\xca\x1c\x1c\xa9\xaa\x76\x61\xe5\xa3\x77\x56\x65\x9e\x22\xa2\x70\xd2\x7c\x36\x07\x86\x29\xde\x15\xf4\xa3\xfa\x34\x4a\x15\x46\x19\xca\xda\xd4\x9e\x11\x8d\x1c\x6b\x74\xcc\x2a\x3f\x86\x8e\xf5\xe0\xb6\x1e", 78, { 0x78, 0xa5, 0x61, 0x3a, 0x59, 0x4a, 0x02, 0xa5, 0xa3, 0xa6, 0x94, 0x54, 0x0b, 0xe8, 0x94, 0x0f } }, +{ "\xd0\x9d\x15\xb4\xf9\x7d\x36\xae\x4f\x06\x2e\x70\x21\xab\xbb\xd5\x22\xd3\x81\x50\x78\x82\x6f\xa4\xf3\xa6\x41\x3c\x5b\x00\x1e\x27\xe2\xad\x61\xb4\xb8\x51\x75\xa7\xbe\xdf\xd9\x15\x52\x06\x43\xe1\x49\x3b\xe1\xd3\xfa\x5f\xba\x52\x77\x0e\x33\xbe\xd7\x84\xae\x6c\xaf\x2b\x4d\x3f\x9f\xc5\xd4\xdf\x08\x32\xac\x99\xdb\xdf\x04", 79, { 0x23, 0x58, 0xdd, 0x9f, 0x9e, 0xdd, 0x10, 0xda, 0xc2, 0x01, 0x1b, 0xaa, 0xb3, 0xec, 0x5e, 0x13 } }, +{ "\xd3\x8d\xcb\x12\x2a\x27\x37\x78\x2a\x79\xea\xc1\xa9\x6e\x1e\x0a\xc0\x7b\x0a\xbd\x67\x31\x0d\x79\xac\xf3\x74\x0e\x90\xc1\xe8\xa4\x7e\x32\x77\xfb\x69\x80\x3d\xcc\x81\xbd\xae\x4f\x91\x24\x83\xd6\xf8\x8b\x3f\x96\x41\xf4\x5d\x86\x62\x42\x18\x61\x8e\x08\xd6\xc5\xb7\x7d\x32\x7d\xa3\x8c\xa5\xdc\xaa\x08\xd0\x40\x0a\xfd\x68\xb6", 80, { 0xe2, 0xa8, 0x37, 0xb5, 0xf7, 0x9d, 0x34, 0x76, 0x8c, 0x62, 0x65, 0xbe, 0x61, 0xb3, 0x81, 0xfb } }, +{ "\xe6\x21\xbe\xbc\xe1\x6a\xea\x21\x53\xb9\x93\x09\x27\xb4\x5e\x0d\x51\xb1\xf1\x7f\xee\xcd\xa3\xcb\xf9\x1d\xc2\xf8\xa7\xfc\x80\x4e\x61\x84\x7a\x12\x5c\x18\xe6\x6d\xd6\x1d\x59\x6b\xee\xc8\x33\x1e\x20\x12\xa8\xe3\x5d\xc9\x6b\xbc\xc3\xc0\xf9\xdd\xfe\x27\x7f\x42\x3a\xf5\x68\x7d\xc4\x81\x87\x8e\x3c\x30\xde\xea\x79\x49\x09\x9e\xf9", 81, { 0x56, 0x9a, 0x78, 0x23, 0xde, 0x2b, 0xe3, 0xea, 0x51, 0x96, 0xff, 0x8d, 0xac, 0x0f, 0x6e, 0x95 } }, +{ "\xe5\x4a\x8d\x03\x02\x32\xd5\x5c\xb6\xe8\x50\xa1\x80\x19\x36\x47\xba\x7c\xe0\x2d\x2a\x00\xa7\xdb\xb9\x95\xeb\x5a\x3b\x94\x30\xaf\x6c\xcc\x62\xf5\xfc\x2a\x39\x16\xc1\x04\xb7\x26\x0c\x02\xcf\x5c\x16\xa9\x20\xad\x98\x85\xde\x07\x79\xf3\xd2\x27\xa2\x88\x78\x17\xee\x22\x46\x48\x3d\x89\x0c\x47\xa7\xc1\x76\x1f\xce\xee\xaf\x4c\x4d\xe4", 82, { 0x2e, 0x98, 0xba, 0x76, 0xed, 0xff, 0xf1, 0x24, 0x93, 0x11, 0x1d, 0xae, 0xa9, 0x3c, 0x2c, 0x19 } }, +{ "\x20\x57\x4d\x4b\x56\x13\x36\x6b\x02\x72\x81\x9a\x19\x04\xac\x3f\x1c\x0e\x47\x82\x72\x43\x2c\x92\xf1\x22\xcc\x92\x7b\xeb\xa3\x21\xc5\x3f\xcd\x84\x33\x53\xb3\x73\xdf\xd0\xdd\x7d\xb9\x4b\xec\x18\xc8\x5c\x9f\x49\x8f\x5d\x12\xec\x8a\xc1\x08\xa1\xd7\x0e\x5d\x53\xf2\x78\x9e\x66\x99\x1c\xb4\x7c\xce\xd5\xbb\xe4\xfb\xbf\xf0\xa1\x2f\x46\xc9", 83, { 0xc1, 0x06, 0x74, 0x68, 0xa6, 0x97, 0x98, 0x95, 0xee, 0x75, 0x92, 0x71, 0xe1, 0xe8, 0x5a, 0x0a } }, +{ "\x12\x87\xe9\x1f\x42\xa8\x91\x87\xce\x68\x88\xbe\x6f\x8c\x18\x42\x24\xac\xc1\xfd\xfd\x33\x15\x1c\x85\x83\x34\xff\xcd\x35\xe0\x49\x11\x7e\x3c\x16\x0a\xad\x26\x4c\xcf\xd0\x2d\x0b\x69\x76\x31\x3e\xf2\x90\x96\x53\x68\x71\x24\x07\x13\xf5\x7f\x5a\x91\xbd\x3e\xa2\x7b\x98\xa9\xbc\xb6\xfd\x14\x5d\x58\xb4\xd2\x86\x34\x95\xd8\x16\x04\x69\xf0\x79", 84, { 0x0b, 0x29, 0x0b, 0x0f, 0xff, 0xe0, 0x89, 0x9c, 0xea, 0x43, 0x82, 0xda, 0xea, 0x48, 0x69, 0x79 } }, +{ "\x32\xed\x96\x7e\x43\xf4\x73\x47\xe0\xac\x73\x59\x83\xf9\x85\xd4\xba\xfd\xef\xbc\x1b\xb9\x4b\x75\xc5\xcd\x21\x4e\x8e\x5b\x22\x34\xce\x0a\xff\x87\xc7\x26\xe4\x09\xaf\xe5\x95\xf2\x5c\xc5\x23\x22\x8c\x10\x4a\x6e\xcd\x81\x6a\x1b\x0f\x01\x20\x69\xc4\x8a\x81\x46\xb1\x2d\xf3\x24\x55\x2e\xa7\xe4\xf2\x4d\xb6\xf1\x3c\x20\xd7\x6a\x9d\x9b\xbb\x77\x23", 85, { 0xd1, 0xd8, 0x5e, 0xa5, 0x95, 0xa7, 0x49, 0xac, 0x47, 0x06, 0x57, 0x0d, 0x28, 0x00, 0xf4, 0xa0 } }, +{ "\xb2\x05\xbd\x07\x15\xe9\xec\xdb\x1a\x60\x75\x4f\xb9\x05\x59\x9f\xb0\x90\x1d\x9d\xc7\xec\xda\x56\x2e\xf6\x70\x64\x02\xd4\xdb\xd0\xee\xf0\x9e\xa1\xee\x90\x5b\x06\x2f\x14\x84\x1b\x13\xcb\x2c\x5b\x50\x71\xf7\xa3\x38\x49\x30\xdf\x13\xd3\xf9\x53\xa8\x2b\x9d\x88\xdb\xfe\x02\xd1\x70\x29\x3a\x78\xed\xf0\x38\x8a\x9e\xd7\x9f\x3c\xb2\x20\xb6\xf9\x83\xe2", 86, { 0xf1, 0x5f, 0x79, 0x80, 0x57, 0x2d, 0x9a, 0xb6, 0xc1, 0x7f, 0x79, 0xf3, 0xc9, 0x37, 0x04, 0x63 } }, +{ "\x78\x09\xf3\xc3\xc8\xdf\xf2\x52\xc2\xff\x1b\x03\x2d\x8a\x7e\xc8\x0c\x67\x79\x48\x54\x10\xbf\xbe\xb7\xf6\x7a\x71\x9f\x92\x8d\xcb\x36\x0a\xf2\x19\xa2\x7c\x43\xde\x4e\xe9\x54\xd4\x64\xc1\xfd\x80\x57\x07\xf5\x71\x9c\x20\xd9\x15\x78\x3e\x4d\x37\xf4\x64\x39\x19\xee\x15\x35\x29\x4a\x9d\xff\x64\x45\xfb\x29\x44\xe9\x69\xd0\x67\x9d\x8a\x86\xbe\xd4\x2f\x51", 87, { 0x1b, 0xd6, 0xd5, 0xe4, 0x5a, 0xec, 0x0f, 0xb0, 0x32, 0x9f, 0x48, 0xd3, 0x30, 0xa0, 0x5c, 0xc7 } }, +{ "\x6e\xe6\xc6\xcd\x46\xfb\x60\x6c\xdd\x23\x5d\xde\x48\x84\xb7\x8c\x76\xab\xe7\x3d\x28\x03\x77\xdb\x8f\x63\x26\x50\x83\xc1\xb1\x8b\x5e\x04\x44\x9f\x73\xf8\x7d\x0a\x2e\x5b\x19\x12\xca\x14\x3d\x4b\xa9\x83\x63\x36\x53\xf3\xdf\x04\x0d\x2c\x0d\x78\x15\x26\x19\xea\x79\xd7\x6b\x67\x91\x2d\xad\xf6\x1f\x18\x7a\xf6\x01\xbe\xa4\xa3\x90\xd2\x22\xb7\x99\xff\x95\x2c", 88, { 0x10, 0x9b, 0xe4, 0xa6, 0xe5, 0x6b, 0x8b, 0xa9, 0x93, 0x3d, 0x1f, 0x2b, 0x86, 0xee, 0x43, 0x6f } }, +{ "\xf6\x7e\x75\x20\xc8\xc7\xdc\xd2\x52\x63\xef\xc9\x75\xe0\xe5\x14\xc4\xde\xb5\xac\x43\x47\x60\xf5\xc1\x9c\xd8\x63\xcf\x6a\x8c\x3a\x5c\xdb\x91\x6e\xee\x68\x6e\xa8\x7f\xac\x84\x6a\xf2\x54\x18\x49\x30\x33\xff\x59\xe4\x72\xe5\xa8\xcf\xe5\x39\xe0\xc8\x78\xb8\x10\x54\xc8\x95\x84\xde\xce\x42\xd0\x93\xb6\xde\xec\xdc\xce\x3b\x79\x79\x99\x8a\x22\x37\x04\xa6\x1d\x4d", 89, { 0xc5, 0x4b, 0x08, 0x71, 0x93, 0xf9, 0x29, 0x50, 0xdf, 0x2e, 0xf2, 0xdb, 0xd3, 0xc0, 0x45, 0x8e } }, +{ "\xb0\xfa\xd1\x59\x6e\x0f\x92\xf2\xc9\xb5\x87\xe9\xbc\xcd\xad\x21\x84\xb2\xf4\x08\x90\x42\x87\xb1\x96\x8c\x29\x90\xbf\x18\xbb\xd1\x02\xcd\xda\x55\x8f\x83\xa5\x4a\x61\x26\x9c\x65\xf6\x83\xa4\xbf\x1b\xb2\x27\x49\xe0\x20\x58\xee\xac\x38\x94\x44\x69\xae\xe4\xed\xdf\x68\x9f\x90\x1f\x09\x2c\x6f\x15\x1a\xe5\xa6\x41\xd7\x18\xff\x7f\x94\x27\x74\x02\xca\xcf\x42\x5f\xc2", 90, { 0x87, 0x4d, 0x37, 0x7f, 0xf8, 0xc5, 0xf8, 0xbc, 0xa4, 0x91, 0x41, 0xf0, 0xcb, 0xc4, 0x24, 0xfc } }, +{ "\x85\xa6\xc5\xdd\xfc\x37\x4b\x7e\xc4\xdf\x62\x94\x0c\x77\x6a\xc7\x88\xfe\x60\x3e\x6d\x76\xb4\x0b\x99\x5c\x38\x34\xd1\xc2\x35\x5f\x22\x0a\x98\x19\x68\x41\x4a\xc3\xed\x15\x9d\x19\x29\x75\xe1\x60\xa8\xc4\x17\x2c\x09\xb9\xbd\xcb\x22\xd5\xc8\x51\x41\x82\xb0\x41\x8d\xc5\xa5\xd5\x8c\xa0\xdf\xeb\xbe\x07\x13\x8c\x66\x7c\x01\x19\x68\x49\x2a\x14\x4d\x5a\xa0\x88\x64\xb4\xf5", 91, { 0x9a, 0x75, 0xb0, 0x83, 0xa7, 0xef, 0xdc, 0xd1, 0xec, 0x55, 0x02, 0xe0, 0xc3, 0x21, 0x11, 0xcb } }, +{ "\x17\x04\x96\x55\x9e\xec\x2a\xb0\x86\xcb\xe8\x0f\xaa\xdb\x88\x08\xe0\xa7\xa1\x4d\x26\xee\xe3\x5e\x6b\xa0\xee\x5f\xf7\x05\xcc\x04\x77\xfd\x12\xa8\xa9\x62\x8e\x7d\xa0\x89\xad\xde\xb4\xe8\x6c\xc1\x0a\xd1\xf9\x48\xbc\x5c\xe6\x76\xa4\x64\x08\xfe\xca\xa7\xf2\x37\x68\x11\x09\x2d\x96\x12\x44\xd1\x96\x2b\x83\x50\xbe\x89\x88\x80\xfe\xc8\x96\x77\x0d\xd8\xa4\x36\x35\xfd\x3e\x83", 92, { 0x76, 0x5a, 0x38, 0x22, 0x4b, 0x74, 0x03, 0xca, 0xef, 0x81, 0xf9, 0x95, 0x2f, 0x9a, 0x61, 0x09 } }, +{ "\xb7\xf0\xf9\xd4\xdc\x23\x91\x67\x99\x22\xa1\x6f\xdd\x15\xfd\x68\x7b\x62\xaf\x8c\xaf\x6f\x8d\x5e\x4f\x85\x74\x63\x8f\xd0\x23\xf0\x71\x83\xb6\x1f\xc7\x18\xbc\xdb\xe6\xb5\xf8\x1b\xe9\xaa\xb1\x2c\x9f\x17\xb6\x26\x12\xab\xf2\x80\xb5\x87\xa7\xc0\x29\x40\x4b\x4a\xac\x03\xfc\x5a\x1e\xd3\xa0\x0d\xb1\xef\x9d\x99\x2d\x4f\x32\x9e\xde\x4c\x70\x94\x1b\x5f\xd9\x63\x73\x01\x93\x11\x75", 93, { 0xd5, 0x80, 0x2e, 0xe7, 0x75, 0x2b, 0x14, 0x45, 0xe7, 0x79, 0xbb, 0x8a, 0x9e, 0x25, 0xbe, 0x59 } }, +{ "\xb2\x49\x95\x1c\x16\x9f\xcb\xd5\x39\x4f\x81\x2f\xf3\xe5\xae\x1e\x67\x13\xc2\xec\xa5\xb2\x19\xbd\x70\x56\x89\xbd\x19\x8c\x1a\xe8\x8a\xb2\xd5\x75\x5f\x73\xb5\xe0\x2e\xdf\xba\x93\xe7\x23\x1d\x30\x57\xe9\x9e\x7e\xc7\x4f\xf9\xed\xc1\x7c\x77\xc7\xf2\xe5\xa0\xf5\x2b\x1b\x0e\x6c\x81\x4e\x5c\x32\x95\x62\x3e\x11\xee\xac\xab\xd6\x82\x49\x34\x46\x54\x1b\x78\x9f\x37\x61\xb0\xc6\xb0\xf2", 94, { 0xe7, 0x95, 0xef, 0x83, 0xc5, 0xa8, 0xfd, 0x49, 0x2c, 0xea, 0xcc, 0xb6, 0x5a, 0xd5, 0xfa, 0xf8 } }, +{ "\x66\x12\xf9\x16\x43\xb3\x22\x01\x05\xc0\x53\xed\x8f\xdd\x2c\xd2\x1a\x85\x4d\xc5\x8a\xfa\xf1\xeb\xdb\xc6\xb5\x18\xba\xec\x77\x08\x30\xb0\x59\x38\x79\x00\xe5\x62\xf3\x7e\x4b\x94\x32\x2b\xc5\xec\x30\xb1\x1b\xf2\xa2\x4d\x42\x92\x65\x57\x20\xb4\x17\x6f\x6b\x7a\xc3\x46\xaf\x15\xb4\x06\x6e\x44\x6a\x5f\x61\x6b\xaa\x2f\xdd\x4c\xb0\xcd\x51\x64\x80\xf3\xec\xe4\x5b\x45\x5b\x4a\x4c\x82\xb0", 95, { 0x78, 0xba, 0x8a, 0x34, 0xdc, 0x24, 0xb8, 0xf7, 0x78, 0xb9, 0x19, 0xfa, 0x5e, 0x19, 0xcd, 0x1d } }, +{ "\x9c\xe1\x46\x5e\x41\xf7\x79\x61\x7c\xaf\x58\x7a\x85\x7d\x1e\x98\x46\x5f\x4e\x53\xaf\x2a\xa0\x91\xb6\xff\x86\x4b\xef\xdd\x59\x6a\xc3\x50\x25\xcb\x50\x48\x0d\x62\xdd\x04\x5d\x7a\xf8\x2d\x2a\x1a\x2e\xff\xa8\x83\x67\xa2\x08\xd7\xdb\x97\x0b\xd4\xb5\x4e\x28\xbd\x42\xd4\x56\x59\xd6\xa9\x77\x15\x3c\xb0\x61\x44\xd7\x3f\x89\x87\x59\x56\x4e\x48\x1f\xed\xe0\x60\x28\x66\xcb\xd9\xb1\x22\x24\xcd", 96, { 0x4c, 0x22, 0xab, 0x04, 0x6c, 0xee, 0xab, 0xc7, 0x2b, 0x36, 0x9d, 0x34, 0x1e, 0x33, 0x3e, 0x9d } }, +{ "\x6e\x2f\x4e\x6d\x66\x1f\x69\x1e\x6c\xf4\x59\xbd\x35\x37\x6e\x03\x1b\x28\xb5\x04\x6d\x0f\xda\xd1\x70\xb1\xb8\x3e\xf7\xde\x7f\xbe\x9a\x27\x81\x6a\x96\xae\x99\x20\x41\x16\x38\xc8\x28\x98\x0d\xb2\xc7\x37\x51\x1b\xe4\x0c\xac\xcf\x88\xbb\xc7\xe8\x9b\x06\x6f\xb4\x1b\x80\x62\xb5\xf8\x59\xba\xc2\x90\x58\xf3\x4a\xc2\xe8\x9b\xb8\xb1\x49\x95\xf3\x17\xe7\x09\xfd\x43\xc8\xec\xbb\xb0\x1e\x27\xd3\x44", 97, { 0xf5, 0xdd, 0x03, 0x8a, 0xea, 0x22, 0xdd, 0xfb, 0x84, 0x4d, 0xe1, 0x47, 0x01, 0x83, 0x5f, 0xfa } }, +{ "\xfc\x66\xb1\x22\x26\x80\xa5\x2c\x01\x7e\x26\x18\xa9\x4a\x3a\x2d\x21\xf6\xed\x9b\xa5\xa5\xfe\x75\x1c\x1a\x9a\x4c\xa9\xdb\x40\x69\x61\x01\xc3\xa6\x17\x9f\x6e\xe9\x52\xcd\x41\x3e\x60\x50\x5a\x91\x84\xe7\x6f\x05\x4a\x34\x78\xf3\xfc\x46\x69\x82\x2d\xbf\x1d\xdf\x72\xa7\x4e\x19\x30\xcc\xc1\x9c\x91\xd3\x7f\x48\x91\xe0\x3d\x2e\x34\xdd\xdd\xe7\xda\x6b\x0d\x90\xaa\x63\x0e\x65\x2c\x07\x8f\xf9\xf3\xcb", 98, { 0x3d, 0x89, 0x3a, 0x16, 0x78, 0x2f, 0xa7, 0x44, 0x52, 0x47, 0x8e, 0x03, 0xaf, 0x55, 0xc5, 0x4e } }, +{ "\xb7\x0f\x77\xb9\x42\x19\x01\x85\xc3\x4a\xbf\x2d\x07\x5a\xf7\x4c\x9a\xd6\x59\xfd\x63\x21\x6d\x66\x6a\x0b\x2b\xe8\xba\x0b\xa9\xe1\x62\x1c\xef\x1c\x95\x32\xe6\xd6\xf1\x58\x6f\x6e\xdd\x68\x91\xa8\x0b\x66\xca\x9d\x1d\x79\x86\x43\x64\x86\xad\x95\xc3\x6a\x57\x5f\xb2\xd4\x9b\xa8\x5e\xbe\x85\xbb\xee\x86\x25\xd4\xe1\xad\xc4\x64\x93\x2b\x32\x01\xde\x6c\x3b\xed\xdd\xeb\x38\x41\xcc\x6a\xc1\xb7\x0b\xcb\x80", 99, { 0x19, 0x77, 0x92, 0x3c, 0x8c, 0xe5, 0xc6, 0xcc, 0x04, 0xed, 0xe0, 0x02, 0x69, 0xa4, 0xb0, 0x14 } }, +{ "\x11\x42\x8e\x21\x28\x9e\xe8\x65\x94\x38\x7c\x56\xf5\x97\xb8\x95\xdc\x4c\xcf\xcf\x5a\xbc\x4e\x4e\x22\xfa\x5d\xab\x5d\xd2\x95\xa2\x0b\xe3\x78\xfe\x10\xe4\x91\xb3\xe3\x07\x29\x0a\xce\x7a\xa3\xf7\xe2\x0a\x75\x86\x7b\xe2\xc3\x74\x6c\x72\x9a\xda\xc6\x6b\xc5\x04\x4a\xe6\x50\x60\x69\xa4\x97\x92\xf3\x70\x09\xa4\x64\xa1\x7f\x5b\xc8\xbc\x33\xa5\x47\x36\x5e\x2e\x51\x56\x72\x11\x66\x39\xf1\xab\x82\xef\xe8\x8c", 100, { 0x55, 0x0f, 0x1a, 0x5e, 0x93, 0x15, 0x75, 0xf2, 0xb7, 0x6b, 0x67, 0x79, 0x45, 0x36, 0x12, 0xe1 } }, +{ "\x24\xc3\x0c\x87\xfa\x99\x6f\xe9\x2b\x6f\xdf\xc6\x40\x06\xdc\x6f\xb0\x9a\x33\xff\x06\xcc\x3b\x15\xb1\xa1\xab\x9c\x68\xa3\x17\xc5\x38\x25\x05\x16\x2b\xa4\xb0\x9c\x97\x49\x58\x3c\x00\x8c\x44\x28\xab\xf2\x56\x6d\xc0\xf6\x49\xa8\x1a\x06\x89\xd8\xaf\xa4\xae\x4f\x97\xad\x97\xc3\xba\xb7\x1f\x81\x1b\x93\x7f\xc1\xbb\xf1\x40\x14\x2b\x23\xda\xfa\xb2\xfa\xee\x90\x16\xcd\x1d\x66\x0b\x98\x83\x6f\x35\x40\xd4\x11\xdc", 101, { 0x7e, 0x9b, 0xb1, 0xbf, 0xc2, 0xf0, 0xd6, 0xa9, 0xd1, 0xa3, 0x5d, 0x1f, 0x74, 0xae, 0xd6, 0xc5 } }, +{ "\xf4\x11\x5d\x2b\xb0\xe6\x59\x25\xdb\xa3\x78\x25\x10\xd5\x2b\x10\xfa\x81\x90\x19\x59\xfc\x49\x30\x21\x6a\x68\x08\xc1\xd1\x86\xc3\x81\xd9\xf3\x3d\x04\x22\x07\xf2\xed\x42\x97\x8d\x9e\x59\x83\x0e\x1c\x53\x6d\x96\x0f\xba\x84\xd2\xe5\x36\x7e\x02\x15\xa2\xa4\xa5\x81\xcb\x07\xc3\xf4\xc7\xd0\xd6\xcb\xf0\xb5\x56\xb1\x7c\x88\xe0\x83\xba\xe9\x02\x52\xeb\x1c\xa5\x86\xbb\xf5\x18\x1f\x5a\xf0\xb5\x17\x3c\x5d\x32\xe4\x69", 102, { 0x0a, 0x37, 0xdb, 0x00, 0x9a, 0x07, 0x39, 0xfd, 0xd4, 0x36, 0x02, 0x15, 0x7e, 0xce, 0x60, 0x3c } }, +{ "\xb8\x86\x19\x81\x17\x75\x2c\x50\xbc\xba\x52\x0a\xca\xd0\x87\x23\x15\x5e\xaa\xcd\x12\x3d\xc4\x0f\xed\x27\x69\x7f\xba\xfd\x37\x9c\xc3\xb4\x7b\xca\xff\xde\xf4\xea\xa4\xd1\xaf\x95\xd4\x76\x11\xf6\x72\xb0\xf3\x41\x18\x66\xe7\xd4\x21\x2f\x9a\xe8\xe1\x99\x52\xf4\xf4\x16\x96\x9e\xb4\x84\xec\x5e\xc4\x57\xbd\xb2\xc9\x66\x55\xf8\x39\x4e\x07\xeb\x4b\x87\x6d\xbc\x0e\x01\xcd\xcc\x96\x7a\x98\x04\x50\x5f\x0c\xd2\x77\x5c\xf9", 103, { 0x5f, 0x1c, 0x52, 0x55, 0xd4, 0xde, 0x34, 0x35, 0x0d, 0xbb, 0xf3, 0x57, 0xa6, 0x15, 0x3f, 0x6f } }, +{ "\xc0\x9f\x82\xa0\xb2\x6f\x14\xb6\xbc\x6c\xee\x89\x9e\xf0\x93\x3a\xdd\x39\xd1\x28\x7f\x9d\x13\x6d\x62\xdb\x43\x82\x39\x8e\x5a\xfe\x24\xbb\x85\x7b\xeb\x89\xf5\x99\xd8\x10\x44\x1c\x2e\x49\x7f\x31\x49\x26\xd4\xce\x53\xbb\xd9\x37\xa0\x99\x76\x9c\xa7\x3c\x71\xdf\x9e\x9a\x94\x74\xb1\xdb\x7d\x62\xde\x28\x02\x66\x70\x9d\x3e\x36\x15\x58\x3d\xe3\x9e\xb3\x40\x57\x54\x8e\xad\xfe\xf1\xc5\x96\x82\x42\xc1\xe4\xae\x57\x2a\x20\x74", 104, { 0x3c, 0xd5, 0x22, 0xa8, 0x37, 0xc4, 0xe8, 0xad, 0x2a, 0xf4, 0xf6, 0x6d, 0x03, 0x38, 0x4e, 0xa9 } }, +{ "\x63\xba\xdd\x0a\x37\x2d\xc6\x2e\x56\x54\x40\x8b\xb4\x49\xbb\x34\x10\xbd\x9a\x4d\xeb\x6d\xbc\xc8\x23\xb4\xa7\x4d\x31\x39\x51\x33\xfc\xc8\x8a\xab\x57\x3f\x09\xfd\x1e\x9f\x11\xea\xe8\x42\xbf\x2f\x69\x2b\xf3\x2b\x67\x79\xd9\x98\x57\xf6\x13\x75\x94\xcc\x85\x04\x3b\x57\xbc\xef\xa5\x16\xfb\x86\x82\xba\xe4\x23\x8e\x61\xc0\xaf\xf3\xdc\x6b\x3d\x3b\x2c\xdf\xd4\xf0\x0c\x5b\x4a\xd3\xa8\x2f\x4b\xb5\x6b\x27\x79\xf5\xf6\x91\xae\x96", 105, { 0x34, 0x7e, 0x78, 0x3a, 0xaa, 0xd6, 0xde, 0xb7, 0xf4, 0x1f, 0xf8, 0x13, 0x4d, 0xe7, 0xba, 0x0f } }, +{ "\x2c\xed\x5c\xfb\x6a\x31\x16\x42\xd4\xb6\x27\x3b\xcb\xc2\x60\x04\x7a\xb3\xf0\x42\x90\xc4\x6b\xfe\x08\x7f\xed\x19\x23\xbf\x58\x6d\x78\x61\xb8\x82\x21\x87\xc8\xea\x17\x88\x8e\x3a\x98\x77\x21\xa5\xc4\x4f\x8b\x36\x48\xb8\xc9\xaa\x31\x78\xef\xe7\xe2\x79\x68\x1d\x21\x72\x5b\x78\x4b\x35\x2a\x7f\xa8\x95\x14\x0c\xd9\xf2\xfa\xe8\x6e\x63\x3f\x02\x94\x7e\xc8\x4c\xeb\xc7\x23\x33\x76\xb2\xc4\xb9\xac\x56\x6a\x30\xab\xb1\xa0\x95\x8c\x92", 106, { 0x56, 0x75, 0xe1, 0xc5, 0x9d, 0xa4, 0xf9, 0xec, 0x3b, 0xf3, 0x7d, 0x8f, 0xb3, 0x9a, 0xef, 0xb5 } }, +{ "\x5f\x86\xd1\x27\xd0\xe1\xfb\x23\x30\xfb\x39\x8b\xcd\x7a\x3a\x1e\x2d\xd0\x23\x5f\x4d\x54\x9d\x40\x07\xfe\x05\x6d\x8d\xbf\xc7\x32\x11\x7b\xc5\x09\x87\xa4\xf0\xc4\x82\x74\xfa\x53\x3b\xc7\x22\x33\xb1\x92\x2e\x74\xea\x04\x77\x64\x57\x37\x1e\xdd\x55\x93\x5c\x28\xd0\xc0\xf8\x8d\x02\x45\xd1\x79\x59\xc2\x9b\x49\x77\xc6\xa7\xb9\x53\x4e\xda\xe4\x7c\xdb\xbf\xf7\x7e\x2e\xb9\x76\x5d\xa3\x51\x2a\x3e\x28\xae\xa6\x26\xd8\x22\x75\xd9\x38\xe0", 107, { 0x4e, 0xe1, 0xda, 0x97, 0xf7, 0x4d, 0xce, 0x3c, 0xae, 0xd0, 0x5a, 0x17, 0xa8, 0x9d, 0xea, 0x3f } }, +{ "\xe3\xe4\x0c\xcc\x64\xb7\xd7\x6b\xa4\xea\xee\xfa\x2b\xa0\x38\x9a\xac\x09\x84\xa8\xeb\x01\x87\x2b\x4a\xd6\x71\x67\xee\x27\x2a\x8e\x92\xe7\x2e\x96\xe8\x81\x02\x26\xa7\x16\x51\xa9\x36\xe1\xa8\x85\xf3\xbc\xcb\x66\x20\xbb\xb2\xb4\x6a\xf6\x23\x23\x18\x65\xed\x68\xcd\xe3\xbe\x09\xf9\x55\xa2\x4d\xe2\xe4\x18\x53\x4b\x66\xd3\x3f\xbe\xda\x0a\x8f\x7b\x12\x7c\x8b\xfd\x6b\x04\xdb\x25\xb8\xd4\x33\x06\x3d\x51\x29\x4c\xd7\x8b\x26\x49\x39\x57\x7b", 108, { 0x56, 0x6e, 0x56, 0xba, 0xee, 0x28, 0x17, 0xeb, 0x10, 0xc1, 0x9b, 0xf4, 0x7b, 0xbe, 0xf1, 0x99 } }, +{ "\x9d\x51\x0b\x8b\x82\xc9\xd6\x26\xb2\xa9\xb9\xf7\xf5\x19\x26\x13\x4a\x44\x33\xb1\xb1\x59\x7b\xf9\x93\xab\x92\xf5\xcf\xf8\x22\xa4\x63\xc7\xa7\x2d\xb2\xea\xc3\x31\x77\x23\x3e\x39\x47\xe3\x9e\x4e\xbc\x2e\x5f\xa8\x44\x9a\xd0\x7e\x84\x75\x8a\xfc\x6a\x06\x8d\x53\xce\xec\xf8\xea\xc4\xa4\x65\xb2\x80\x26\xdf\x97\xe6\xae\x81\x12\xae\x98\xac\xdb\x31\x64\xe4\xbc\xd2\xda\x47\x81\x0b\x47\xac\x0c\x13\xe5\x54\x85\x29\x58\x4f\xae\x80\x55\x6f\x54\xc7", 109, { 0xca, 0x20, 0x60, 0x9f, 0x8f, 0x6d, 0x8f, 0x91, 0x97, 0x72, 0x2c, 0xe3, 0xfd, 0x2a, 0x05, 0xa5 } }, +{ "\x5d\xe1\xe1\x54\xa7\x6d\x0f\xec\x1c\x4a\xb7\x31\x7c\x9e\xc7\xa9\x9e\x92\x52\x67\xd4\x0f\xc2\x58\x6d\x17\x28\x2c\x54\xc2\xb4\xde\xd5\xd3\x40\xe2\x80\xf6\x06\xeb\x26\x98\x73\x56\x00\x63\x13\x36\xf0\x55\xab\xfc\xdf\x7c\x65\xc3\x45\x50\x26\x36\xc6\xac\xfc\x1f\xfa\x6b\xb3\x8c\x45\x9b\x86\xa0\xe5\x61\xf3\xf3\x0b\x69\xa7\xa7\x20\x07\x99\x08\x28\xef\x33\xdf\x44\x8d\xaa\x54\x51\x02\x6f\x7d\xae\xbc\xbd\x87\x1c\xb1\x53\x7f\xbe\x38\x3c\xbe\x3f\x84", 110, { 0x51, 0x82, 0x43, 0x6a, 0x40, 0xa6, 0x76, 0xb1, 0x58, 0xa4, 0x3d, 0xb1, 0xd3, 0xcd, 0xde, 0x96 } }, +{ "\xc9\xef\x12\xbd\xa1\xbe\xd5\xbd\xef\x1f\xcf\x64\xb9\x38\x98\x98\x51\xec\xd8\xdc\xe4\x05\x27\x8c\x2f\xfd\x14\xb2\x52\x69\x41\x89\xbd\x03\xac\x8c\x47\x52\x08\x39\x5d\xf8\x49\x67\x57\x98\x3f\x41\xe6\x62\x5a\xde\xaa\x3c\x8c\x7e\xe0\x8e\x4c\x64\x39\xaa\xb6\x4b\xc5\xd7\xcf\x86\x0e\xf9\xe7\xb7\x42\xde\x17\x2b\x87\x27\xea\xd1\x73\xd1\x18\xd5\x94\x5f\x6d\xde\x29\xa6\xc9\xe0\xf4\x34\x40\x9e\x27\x5e\x61\xc0\x7b\xe5\x94\x8c\x60\x44\x9d\x44\x4f\x99\x3d", 111, { 0xbc, 0x5f, 0x18, 0x15, 0x64, 0x22, 0x74, 0x18, 0xa4, 0xa0, 0x96, 0xdb, 0x00, 0x70, 0x9d, 0xb4 } }, +{ "\x1c\x3b\x2d\xf7\xd7\x25\xa2\xf0\xfd\xcf\xb8\xf0\xbb\x88\xbc\x85\x57\x26\x8d\x46\x4e\x12\x4c\x35\x0b\x7d\xa0\x3e\x46\xb1\xa2\xdc\xf8\x82\x6c\xdb\xf6\xe3\x39\x38\x31\x95\x39\x24\x89\xf9\xf4\x27\x49\x07\x58\x62\x43\x57\x61\xed\x89\x5d\x63\x5e\xc5\xb2\xf7\x6b\x36\x8d\x80\xa7\x48\x50\x59\x68\xce\x3e\x9d\xca\xde\x4b\x92\xcc\x49\x0c\xb2\x97\xb5\xce\x58\xdf\x59\xc2\x04\x62\x55\x56\x4b\x8e\xac\x9e\x5e\x40\xdf\xf1\x34\xa6\x27\x91\x57\x45\x4e\x82\x48\x16", 112, { 0x3e, 0x3d, 0x87, 0x58, 0x0e, 0x01, 0x69, 0x78, 0x5c, 0x50, 0xd4, 0xb4, 0xf2, 0x87, 0x15, 0xf9 } }, +{ "\x2a\x7b\x90\xcc\xb7\xfa\x65\x31\xd0\x72\xf5\xae\x8a\xa0\x51\xe9\x2d\xfc\xf9\x89\xd0\x4a\x00\x15\x90\x4f\xdc\xfa\x6c\xa1\xcc\xab\xc0\x98\xe6\xe3\x5c\x61\xbc\x06\x41\x30\xaa\xa5\xf7\x95\xbf\x20\x8e\xe8\x46\x66\x2f\xdf\xf0\xd9\x5d\x3e\x9f\x4c\xce\xad\xd1\x2e\xe0\xa5\xa7\xc0\xba\x84\x91\x82\x00\xc1\x99\xac\x32\x39\x48\xd8\xa2\xa8\x38\xbd\x10\x33\x38\x15\xe3\x21\x15\xa0\x06\xaa\x0b\x42\x5d\xe8\xc8\x48\xe3\xea\x19\xc8\x62\xe8\x34\x26\xcd\x90\xa1\xb3\x3d", 113, { 0x19, 0x09, 0x55, 0xc0, 0xf8, 0xda, 0x05, 0x7f, 0xa9, 0x81, 0xbc, 0xa1, 0xcc, 0x3f, 0xe1, 0x11 } }, +{ "\x7f\xc5\x6f\x87\xcb\x0c\xef\x76\xbd\xb2\x5a\xaa\x9c\x2f\x8d\x0c\xa4\x3d\x5f\xec\x16\x87\xfe\xba\x69\xef\x78\x5e\x9e\x7c\x56\x34\xb1\xdf\x63\xa7\x2b\xa0\x8a\x69\xd4\xea\xdd\x4c\x86\xef\xb2\xc0\x1d\xf9\xe8\xea\x8b\x0f\x47\x5d\x08\x40\x05\x77\x66\x8f\x65\x5a\x82\x7a\x7a\x86\xd7\x29\x0a\x10\x2c\x30\x8d\x81\x6e\x01\x55\x4e\x98\xf1\xc7\xef\xce\xe5\xc7\x9e\x8a\x99\x32\xad\xed\x8c\x85\x84\x37\x8c\x9b\x36\x52\xd9\x93\xc0\x89\xf9\xd0\xdd\x56\x18\x19\x89\x58\x19", 114, { 0x4e, 0x98, 0x6a, 0xa5, 0x5f, 0x57, 0xb4, 0x40, 0xd2, 0xf5, 0xf2, 0x3b, 0x19, 0xa7, 0x14, 0xa0 } }, +{ "\xe1\x10\x63\x3d\xa2\xd1\xb2\x6e\x62\x94\x37\x29\x58\x85\x13\x06\xa7\xcd\x21\xe6\x49\xcc\xad\xb8\x07\xf4\x43\xe7\xa4\x45\xa1\x64\x1a\x61\xce\x4b\xfc\x4b\x44\x35\xfa\xc0\x48\x19\x83\x32\x5b\xdf\x85\x5d\xc8\x83\x50\x88\x5e\xe2\x98\x5a\x38\x25\x99\x57\xb8\xc7\x55\xf5\x92\x44\xf9\x5f\x04\x5f\x5e\xc5\x24\x10\xab\x5e\x51\x09\x17\xfb\xcb\xe4\xcc\x49\x5f\xeb\xe7\xa3\x3b\x83\x9c\x92\xe0\x35\x77\xe2\x34\x5a\xbd\x62\xb7\x63\xf1\x37\xce\xc3\x72\xdd\x3b\x79\x41\xbc\xae", 115, { 0x73, 0x08, 0xff, 0x52, 0x04, 0x9f, 0x74, 0x4f, 0x24, 0x7d, 0x90, 0x31, 0xe7, 0xa5, 0x0d, 0x41 } }, +{ "\x3d\xe1\x62\x74\x46\x57\x63\x4e\xb6\x51\xca\x5d\xa3\x63\x3b\x38\xc3\x6c\xa7\x20\xb3\x17\xaa\x4b\xe4\x7d\x84\x5c\x23\xe8\xb2\xf4\xc3\xb3\x28\x62\x68\x4d\x2e\x76\x73\x5c\xd4\x73\x05\xfe\x13\x22\xb2\x2a\x82\x03\xc4\x35\xb1\x9f\x29\x71\x26\xf9\xfa\xf0\xf2\x22\xa8\x66\xee\xec\xc5\x2c\x97\xb6\x6d\x61\x83\x67\x4f\x2b\x80\x76\x5b\x1b\x48\x25\x0a\xaf\xe2\xcd\x45\xf0\x97\x55\xf3\x3c\x8f\xbc\x22\x1e\x09\xd6\xd1\x59\x34\x14\x57\x04\xac\x7b\x74\xcf\x94\xb7\xf3\x63\x4c\x49", 116, { 0x57, 0xd9, 0xf8, 0x21, 0x2c, 0xc8, 0x6d, 0xe5, 0xdc, 0xbf, 0x77, 0x8f, 0x8b, 0x15, 0x62, 0xfd } }, +{ "\xf8\xe8\xcf\xdb\xec\xa0\xac\xb4\x01\xb0\x9f\x46\x64\xff\xcc\xe5\xff\x37\x97\x92\xe7\xe9\x22\xf6\x69\xcd\x64\x6a\xac\x27\xe3\x33\x03\x44\x0e\xcb\xd2\x23\x39\x5a\x19\x31\x35\x44\xa2\x2d\x8b\xdb\xc3\x2b\x55\x35\xd1\xb4\xba\x19\x21\x0a\x04\x13\xbc\x89\x60\xa7\x9e\x28\x31\xa2\xab\x1f\x10\x8c\x2f\xa3\x65\x39\x10\xcd\x9b\x7e\x93\x99\x03\x01\xc7\x09\x47\x2a\x92\x69\x88\x36\x56\xae\x17\x6a\x3f\xf8\xcd\x64\x2b\x37\x08\x8c\x37\xe9\x42\xaa\xe2\x01\x4f\x92\xe1\xe3\x33\xfa\x7f", 117, { 0x88, 0x12, 0x61, 0x94, 0x21, 0xa3, 0xcb, 0x31, 0xa8, 0x60, 0x2d, 0xff, 0x13, 0x02, 0x40, 0xa5 } }, +{ "\x8c\x9d\x6c\xad\xcf\x04\x56\xad\xba\x5d\x3f\x57\x17\x76\x14\x07\x0e\xf2\xa1\x24\xe8\xe1\x1b\x4d\xee\xfb\xd9\x21\x70\x7a\x23\xab\xe1\x91\x23\x69\x20\x8c\xf9\xf8\xd2\x85\xea\x5d\xea\xc0\xb8\xf2\x4a\xa4\x0c\xeb\x83\x57\x10\x84\xb9\xf4\x19\xc9\xa2\x6c\x82\x01\xad\xf6\x94\xb8\x3f\x34\xa1\x68\x18\xe4\x30\xc3\xd4\x3f\x52\xa0\x8e\xf2\x13\x7f\x9f\xb6\x0c\xba\x84\x8e\x15\x4b\xdd\x9c\x19\x34\x92\xa1\x02\x8f\x10\x10\xd2\x32\xb1\xcd\xd3\xfe\x3a\x87\xe7\xc5\x7e\xae\xf9\xd5\x1f\x13", 118, { 0x1f, 0x41, 0x60, 0x14, 0x09, 0xd9, 0xff, 0x1c, 0x0b, 0x49, 0x8c, 0xd7, 0xbe, 0xa9, 0x80, 0x08 } }, +{ "\x94\x25\x74\x1c\x92\x1b\x86\xa0\xec\xf8\x35\x65\xb1\xe1\x78\x33\x12\x8b\xc2\x94\x9a\x81\x7f\x2b\x7a\x15\xbd\xaf\x02\xe1\xe8\x82\x2c\xf9\xae\xf2\x53\xaf\x01\x0b\x01\x01\x3b\x16\xe5\xa3\x5b\xb3\xe3\xa5\x6d\x8e\x46\xc2\x08\xc1\x11\x44\xf1\xc6\x73\x96\xdd\x17\x58\x68\x54\x64\x1c\x79\xb1\x70\x5a\x04\x46\x89\xe3\xc9\x9c\xa2\xcb\xb6\xd8\x0e\x9d\x32\x39\xdb\xae\x07\xbd\xc9\x8f\xe9\xe3\xe6\x9c\xa7\x8c\xc7\xb1\xed\xfb\x65\xfc\xb3\xfb\x91\xee\x46\x20\x15\x4b\xf1\x25\x69\x62\x48\x74", 119, { 0x58, 0x70, 0xa6, 0x06, 0xac, 0xb1, 0xee, 0x1f, 0x53, 0xe8, 0x72, 0x20, 0x3c, 0x05, 0x3b, 0x77 } }, +{ "\x0f\x56\x10\xc5\x8c\x9a\xce\xde\x03\x7b\xeb\x78\x6f\xd7\x81\x42\x7c\xeb\xc4\xff\x03\x4a\x0f\xca\x20\xea\x8a\x7a\xf2\x59\x76\x20\xef\x0d\x15\xad\xe1\xd8\x39\xb1\x81\x7a\x67\x3e\xae\x50\xa6\xeb\x4a\x2b\xea\xf4\xb2\x3c\x18\x7f\xd8\x2b\xb6\xf9\xfe\x46\x31\x9f\x10\xd6\xc9\x19\x9f\x8e\x1d\x40\x76\x1d\x4e\x00\xdb\xe3\xd3\x59\x63\xbf\xd9\x7f\x72\x07\x55\x22\x4f\x91\xa7\xc8\xe0\xee\xec\x55\x06\xb7\xe0\xad\x97\xff\x6e\x70\xf4\xe8\xd7\xe4\x47\x51\x7a\xf1\x5c\xad\x45\x45\x18\xef\xb9\x98", 120, { 0x26, 0x76, 0x51, 0x74, 0x00, 0x2d, 0x40, 0xe3, 0x3e, 0x70, 0x71, 0xc5, 0xf9, 0x19, 0xf1, 0x8b } }, +{ "\x9a\xa1\x93\x09\xec\x14\x1c\xa7\x65\xb2\x0f\x0d\x9f\x6f\x22\x25\x11\x5e\x33\x0d\x48\x60\x10\x16\xc7\xf7\xe3\xe9\x77\x38\x38\xc4\xcc\xdf\xad\xe2\x77\x7c\x35\xf9\xc1\xcc\x08\xdd\x8b\x23\x2b\x42\xdf\x04\x97\x9e\x32\xd3\x09\x2d\x38\xa1\x65\x0e\x64\x27\xc8\x8b\xfb\xcf\x29\x76\xd4\xeb\xaa\xae\xae\x08\x81\xc1\x2e\x5d\x7d\xab\x73\x5e\x38\xbd\x58\x6e\xd8\x99\x45\xb1\x81\x5a\xb2\xff\x5b\xd0\x3a\xf4\x3b\xe8\x57\x24\xf0\x2b\xc0\x6c\x2d\x5d\x5c\x64\x0e\x45\xe1\xf0\x48\x8d\x0e\xf6\xf2\xbf\x81", 121, { 0x3a, 0xfd, 0x49, 0x99, 0x51, 0xab, 0x70, 0xe1, 0xaf, 0x2e, 0xa2, 0x10, 0x8f, 0x52, 0x9c, 0x6e } }, +{ "\x29\xea\x6f\x36\x04\xe5\x78\x9c\xd3\x17\x5e\x55\xeb\x7b\xd3\x8b\xfa\xbf\x55\xea\x79\xd0\xf4\x3d\x3e\xfd\x31\xa8\x2d\xca\x02\x7f\x0f\x54\xf3\xc2\x7b\x5c\x66\x37\xf0\xf1\xfb\x22\x05\xbe\x0b\xa2\xb7\xee\x4d\xab\xe2\xb7\x9b\x9b\xcb\x8a\xcf\x7b\xda\xd5\xc7\xd5\x65\x73\x89\x2d\xa6\xb2\x7f\x1d\xcf\xfe\xe3\x10\x34\x2e\x36\x9b\xa7\x6b\xe9\x73\xe2\xb9\x1f\x0f\x1c\x23\x8a\xdb\xbe\x87\x72\x15\x2f\xfb\xd4\x48\xcc\xdb\xa7\x63\xf3\x71\x3a\x76\x3e\x3f\xb9\x08\xce\xeb\xce\x17\xbd\xc8\x63\xad\xb5\xfd", 122, { 0x1a, 0xfc, 0xd7, 0x74, 0xe1, 0x55, 0x51, 0x67, 0x6b, 0xe7, 0x1b, 0xc8, 0xd4, 0xab, 0x39, 0x47 } }, +{ "\x86\x1b\x9f\x54\x66\xd5\x73\xa1\x7a\xe9\x2e\xcc\xc1\x1d\xe2\x7e\x24\xa5\xe7\x64\xf7\x7e\x2f\x23\x9e\x6a\xb7\xd8\x4c\x88\x1a\x4a\xe7\x8f\x40\xaf\x08\xa7\x33\x17\x1e\xe4\x12\x79\xb1\x60\x1e\x59\xc4\xf3\xf1\x12\x55\x91\xcf\xc5\xfe\x41\x15\xde\xbd\xb6\xce\x40\xd1\x8c\x65\x0d\xbb\x20\x74\x13\x64\x0c\xbb\xd6\x5d\x3e\x2c\x36\x40\xb3\x22\xbd\x36\xd5\xb2\x87\x93\x6f\x1a\xce\x9b\x49\x57\x12\x68\x65\xd2\xe1\xe3\xd4\x3a\x48\xef\x35\x6d\xd6\xa6\xcb\x8f\x49\xbb\x3a\x3d\xd8\xff\xde\xdc\x1c\xff\xc9\x0b", 123, { 0x31, 0x66, 0x6a, 0xcb, 0x7f, 0xb2, 0x21, 0x3b, 0x4c, 0xb3, 0xbc, 0x28, 0xe1, 0x8b, 0x32, 0x58 } }, +{ "\x9c\xca\x57\x37\xf3\xd0\x6e\x4c\xa0\xe5\x57\x89\x6a\x65\x34\x6c\x6e\x72\x1d\xcd\xc7\x59\xdb\x07\xd8\x13\x40\x50\x39\xe7\x21\x2a\x3b\x2d\xf2\xf2\x1a\x2d\xfc\x96\xbe\x25\x3d\x64\x2e\x69\xdc\xfd\x92\xa5\x47\x68\xe2\x3e\xeb\x43\x31\xd7\x8f\x14\x90\xf0\x4e\xbd\xa0\xa8\x2f\x0e\xb8\xa3\x62\x75\xae\x06\x1a\xd0\x46\x9f\x01\x63\x35\x22\x5d\xe5\xd0\x8e\xbd\xb5\x56\xaf\x5f\x2a\xd6\xbc\x22\x07\xbf\x20\x22\x0d\x02\x56\xf5\xab\xe6\xed\x81\xd1\x68\xab\x78\xe2\x4c\xce\x72\xc8\xc4\x6d\xa5\x21\xbc\xfe\x43\x97", 124, { 0x69, 0x78, 0xc0, 0x8c, 0x6b, 0x92, 0x3d, 0x79, 0x26, 0x06, 0x37, 0x64, 0x96, 0x5e, 0x9a, 0x6b } }, +{ "\xc0\xf1\x71\x4d\x8b\x79\xdf\x75\x2d\x6a\x08\xfe\xd7\x3d\x08\x6b\x46\x31\x15\xbf\xca\x8c\x9b\x94\xf2\x00\xf8\x4c\xd6\x28\xd1\x5e\x01\x31\x0f\xd2\xf9\x96\x7a\xc8\x6b\x03\xf0\x31\xf8\x5b\x41\xa1\x96\xd5\xaa\x3d\xa4\x41\xed\xcf\x8f\x69\x09\xf8\x1a\x92\x9b\x85\x4d\x22\xd1\xda\xfc\x5b\x07\x8a\xf2\x45\x00\x09\xbb\xaa\xc2\x79\x0b\x3b\x0e\xa0\xce\xd0\x7a\xfb\xcd\xcd\x2d\xeb\xfa\xa0\x37\x0e\x58\x66\x8a\xa9\x89\xad\x99\x41\xf5\x54\x8c\x49\x94\x8f\x1d\xf5\x59\x07\x12\x2d\x3c\x1e\x57\x9d\xe2\x50\xb7\xe9\xea", 125, { 0x5a, 0x5a, 0xd4, 0x98, 0xee, 0x0c, 0xa8, 0xdd, 0xef, 0x60, 0xed, 0xc3, 0xf6, 0xd3, 0x95, 0x0f } }, +{ "\xb5\x37\xfe\xd6\xa3\x0f\x84\x94\x70\x46\x6f\xa9\x55\xe9\xb5\xf9\x6e\xe7\x1a\x35\xdd\x8c\x26\xe1\x0f\x98\x38\x00\x16\xfc\xb5\x5f\x36\x30\x59\x7c\x7b\x33\xad\x11\x87\x20\x99\x40\x6a\x6a\x11\x5c\xaa\xb4\xeb\x51\x62\x50\xd1\xb2\x86\x51\x52\x5d\x44\x4e\x13\xcd\x86\xb6\x22\xfc\x94\xcb\x6b\xf3\xd7\x3d\x43\xef\xb8\x64\x22\x32\xa7\x18\x6e\x63\x38\x30\x72\xa2\x67\x96\x6d\x2c\xfc\x04\xc7\xa8\x0a\x5d\x5e\x0c\x91\xaa\xff\x2f\x43\xaf\xf1\xeb\x64\x29\xab\xee\xca\xa7\xa5\x1e\x04\x02\x4b\xa6\x97\x7b\x0e\xa2\x63\x6f", 126, { 0x17, 0xca, 0x2b, 0xf4, 0x91, 0x4e, 0x34, 0x11, 0xb0, 0x08, 0x52, 0xdc, 0x95, 0x8c, 0xfb, 0x2c } }, +{ "\x95\x63\x25\xb9\x12\x5f\x16\xa4\xaf\xb8\xb0\x8b\x26\x67\x90\x10\x70\x05\x76\xf5\x95\x36\x6a\x9a\xa2\xb2\xfa\x13\xb9\xf1\x9e\xe5\x42\x73\x3c\x5e\x3f\xa9\xc6\x8e\xbe\x83\x01\xe5\x67\x97\x61\x6b\x35\xea\x11\x96\x42\x5f\x0e\xcb\xba\xba\x73\x74\xf2\x4f\xcf\xba\x91\x4b\xb2\xdf\xec\x9e\x47\x3b\x70\x84\x1b\xd2\x38\xaf\xfc\x8e\xbf\x13\xfc\x1d\xaf\x4d\x95\x69\xd8\xb1\xe6\xb0\x3c\xee\x1c\x41\x47\x60\xec\xd2\x1c\xf2\x3c\x80\x0a\xae\xe1\x63\x1d\xe3\x83\xcd\xd1\xf2\x9d\x20\xe2\xb5\xa1\x49\x3e\x8b\x38\xdd\x1c\x04\xa7", 127, { 0x75, 0x90, 0x2f, 0x4a, 0xfb, 0x9d, 0x91, 0xb1, 0x0e, 0x74, 0xd7, 0x1c, 0xb6, 0xb0, 0x98, 0x06 } }, +{ "\xce\x26\x26\x4d\xca\xd2\x5a\x49\x30\xcf\xf6\x38\xaf\x9a\x68\x1c\x7d\x2f\xfb\x58\x31\xdd\x49\xd7\x3e\x32\x3e\x4d\x0d\x16\xc4\x96\xb6\xf4\x10\x3a\x5a\x13\x89\x12\x1f\x03\x50\x04\xc9\x32\x70\xe9\xf2\x9e\xa4\x90\xe6\xa5\xbf\xdc\x1d\xf8\xbc\x08\x55\xae\x62\x0b\x4c\x75\x93\x16\x17\xe3\x32\x3b\x22\xea\xaf\x27\xc5\x6a\x31\x10\x7f\xe1\x5f\xaa\xd1\x3d\xca\x52\xb9\xd2\xfa\x4e\xc9\x67\x13\x2c\xe4\x6b\x23\x46\x95\x45\x0b\x67\x0c\xc9\x08\x88\xb6\xc6\xde\xb3\x78\xbc\xa0\x09\x87\xab\x1e\xdf\xe7\x06\xeb\x02\x7d\xc7\x09\x1b", 128, { 0xdd, 0x13, 0xdd, 0xd7, 0xfd, 0x85, 0xb9, 0xfe, 0xcf, 0x5f, 0x63, 0xd8, 0x30, 0x7f, 0x81, 0x37 } }, +{ "\xd3\x9c\x34\x2e\x69\x3f\xc8\x3c\xb2\xe3\x4f\x09\xb2\xca\xab\xf8\x31\xf3\xdc\x12\x9c\xf1\x6f\x25\x79\xd7\x84\x09\x85\x50\x7a\xfe\x6d\xcb\x39\x31\x25\xd3\x1b\x5d\xe7\x7c\x78\x8e\xcb\xf9\xcc\x02\xff\x4b\x87\x28\xa4\x14\x72\xca\x46\x8a\xb9\x46\xf5\x87\x99\xf7\x04\xbc\xa6\xb4\x5e\x06\xb9\x6e\x80\xd9\x76\xfd\x16\xd8\x76\xf4\x36\x87\x15\xb0\x33\x18\xd9\x70\x1f\x61\x7d\x9e\xe1\xef\x9a\x2c\xee\x34\xf1\x1a\xa7\xdb\x57\x14\x4f\x3c\x3d\x37\xa8\xeb\xdb\xf4\x29\x6b\xf9\x0d\xdd\x00\x5a\xbd\xda\xa2\xc5\xf4\x5d\x0e\xb1\xc0\x7f", 129, { 0x85, 0x9f, 0x82, 0x66, 0xc3, 0xf3, 0xd5, 0xcf, 0xc6, 0x98, 0x4e, 0xcb, 0x74, 0xa6, 0x30, 0xe5 } }, +{ "\xf6\x8c\xc7\x96\x58\xa8\xf1\x2b\xec\xc3\x22\x93\xb6\x31\x25\x2c\xbc\xa8\xa4\x36\xd2\xa8\x53\x4b\x91\x85\x2d\x7c\x66\x12\xd7\x0a\xc6\xec\x20\xbe\x7f\x60\xaa\xe5\x2a\xfa\xa2\xec\xbd\xab\xaa\x93\x3d\x95\xd9\xd1\x90\x77\xd8\x45\x70\xb0\x2d\x54\x7c\xf1\x94\xe3\x68\x84\x89\xb2\x55\x33\xe3\x53\x3c\xd6\x9a\xc7\x83\x7d\xa9\xb4\xb2\x36\x0f\x44\x3f\x7b\xef\x9c\x85\x3b\xd7\xf7\xd3\x83\x1d\x5f\xa1\xc9\x65\x08\xde\xd5\x40\x49\x65\x4c\xef\x37\x8d\xdb\x45\xe0\xdf\xfc\xaa\x21\xe3\x68\x3b\x25\x13\x19\x0f\x7a\xf1\xfb\x95\xd1\x34\x2f", 130, { 0x09, 0x1a, 0xd5, 0xec, 0xd3, 0xed, 0x5a, 0x2d, 0xf5, 0x61, 0xe8, 0x95, 0x69, 0xe8, 0xda, 0x04 } }, +{ "\x19\x52\x1e\xfa\x65\x9a\xe9\x50\x84\x52\x5f\xf9\xa2\x6d\x89\x5e\x0f\xfd\x7f\xf3\x62\xb3\x5e\x40\xba\xf1\x58\x8d\x20\x8e\xe6\x29\x08\x25\x18\x57\xf7\x1a\x0c\xd6\x3e\x2b\x7d\x0c\xe4\xae\x73\xce\xa2\x6d\x18\xce\x07\x1a\xab\xa2\xbc\x70\x8d\x6d\xe2\xe9\x79\x2c\x97\x16\xd1\x9f\x98\x9e\x13\xd1\x00\xd5\x6a\x46\x2f\xf8\x61\xc1\xc6\x03\xb2\xaf\xce\x2f\x3d\x33\xf8\x0b\x14\xcf\xff\x36\xb3\xab\x2a\xb7\x4d\x86\xed\xf9\x41\x36\xaf\x66\xac\xdd\xa7\x9e\x18\xaa\xdf\x54\x51\x49\x5b\xc5\x58\xe9\x53\xd6\x71\xe7\x9b\xca\x57\x1c\x23\x9d\x90", 131, { 0x76, 0x56, 0x7f, 0xe3, 0x54, 0xbe, 0xa3, 0x1f, 0xff, 0x3a, 0xb0, 0xfb, 0x98, 0xfd, 0x35, 0x13 } }, +{ "\xc0\x9b\xff\xdb\xf9\x2f\xf0\xc5\x04\x70\xf4\x5a\xfe\x52\xf4\xf9\x50\x52\xb1\x41\xb5\xb0\xe5\x27\xea\xda\xf8\x2a\xf1\xe9\x5c\x9d\x01\x44\x85\x23\x0d\x62\x88\x3a\xef\xae\x4f\xed\x31\x83\x77\xad\x78\x56\xc6\x3b\x8e\xf3\x4c\xbc\x0a\xe0\x15\xee\x9e\xde\x87\x7a\xfd\x8d\x5f\x5f\x67\x2f\x42\x8e\xd2\x85\x03\x95\xb7\xd5\x70\x73\x76\x0d\xd9\x8a\x66\x02\x1e\xb2\x7d\xd1\x74\x69\x99\x66\xb4\x29\x69\x1b\x5f\xd2\xfa\x78\x32\x47\xe2\x19\x62\x15\x03\xad\x75\x4c\xfc\x1a\xbd\x72\x32\xbe\x71\x8d\x76\xd1\x69\x5f\x53\xe6\x76\xaf\xf7\x90\x5b\xc1", 132, { 0x0f, 0x4a, 0xeb, 0xeb, 0xe2, 0xf4, 0xfd, 0x1a, 0xa8, 0x5e, 0xe3, 0x62, 0x7d, 0xe0, 0xdf, 0x1e } }, +{ "\xbc\x21\x6c\xe7\x51\x8e\xc2\x30\x89\x6e\x19\x3f\xc0\x21\x46\x38\xe6\x0e\x57\xd3\x29\x04\x49\x92\x43\xc2\x60\x0f\x5d\x92\x27\x6f\x9e\x0f\x04\xf3\x55\x08\x77\xad\xbf\x7d\xef\x4f\x75\xc6\x49\x1e\x75\xd3\xe6\x06\xcb\x8e\x67\xc8\xdb\x5d\x08\x4f\x4e\xc3\x96\x20\x97\x26\x0e\xee\x21\xab\xd4\x4d\x17\x3d\x8c\x7f\xcf\xad\x99\x6b\xd4\xf4\x30\xab\x8e\x93\x18\xc4\x90\x1b\x00\x71\x7e\xc9\x7c\x18\x99\x49\x9e\x5e\xe9\x9b\x2d\xd6\x06\x13\x85\xd4\x82\x7a\x0a\x60\xf6\x53\x4a\x46\xa8\x38\xaf\x4b\xd6\x62\xdd\x7a\xa1\x46\xae\x9c\x99\x5d\xc7\xc5\xe1", 133, { 0xee, 0x0d, 0xd8, 0x9d, 0x25, 0x60, 0xda, 0x7a, 0x2c, 0x60, 0x14, 0xc7, 0x3f, 0x1d, 0x3b, 0x3d } }, +{ "\xfd\xd7\x0b\xff\x63\x6c\x52\x42\xd2\x71\x43\xd0\xd4\x48\x5b\x4b\x9f\x80\x1f\x20\x93\x33\x6e\x6c\xe0\xff\xee\x8a\x45\x9f\xa8\x3d\xf3\x25\xb0\x77\x90\xd6\xfd\xc4\x57\xa2\x57\x56\x5c\x3e\x6e\xad\xed\xe0\x06\xe3\x14\x96\x50\x91\x3a\x44\x55\x62\xe6\x38\x8b\x32\xa2\x6c\x8a\xe2\xfe\x57\xd8\xbb\xae\x70\xe0\x7c\xce\x40\x02\x01\x46\x22\xc4\x92\x49\x9a\x25\xc6\xf7\x50\x12\x12\x23\xa8\xf2\xf3\x2e\xfe\x5c\xb3\x12\x83\xe8\xda\x7b\xaf\x23\x35\x0f\x62\x9c\x7c\xcf\x9b\x1b\xa2\x95\xd3\xf1\xbe\xbd\xf7\x6b\x91\xe1\x01\x60\xb3\xbc\x32\xea\x5f\x30\xee", 134, { 0x8b, 0x7c, 0xff, 0x2f, 0x5f, 0xb8, 0xe4, 0xec, 0x5f, 0x22, 0xc5, 0x45, 0x5e, 0xb0, 0x62, 0x87 } }, +{ "\x31\xd7\x62\x33\x63\x75\x03\xb7\xc0\x50\xaa\x9e\xd1\x87\x5d\xd5\xb8\x2d\x2f\x0e\xa3\xd1\x03\x58\x5a\xa8\x6e\x5a\xf8\x5a\xbb\x2b\xb7\x66\x08\xd1\xe4\x32\x8d\x55\xf1\xb3\xfd\x7f\xa9\xb5\x04\x34\x7e\xc7\xf1\x68\xfe\xc7\x6e\xc1\x64\x05\x6a\xca\x4b\x17\x17\xd0\x7e\x39\x0f\x5d\xea\x5e\x92\x4e\xb5\xd7\xea\x93\x67\x9f\xef\x83\x46\x41\xa7\xda\xc1\x66\x05\x50\x02\xff\xd2\xd6\xa6\x0b\xa9\x70\x89\x05\x1c\xaa\xba\xee\xf5\xb8\x8e\xf2\x96\x2e\xd0\xba\x82\x58\x16\x4d\xf4\x37\x2f\xa3\xad\x19\xb8\xc8\xcc\xd3\xce\xa9\xd5\x9e\xdd\x7f\xd4\x8c\x97\xd5\x9a", 135, { 0x8a, 0xa7, 0x2b, 0xac, 0xd5, 0x8c, 0x7a, 0xae, 0xe0, 0x26, 0xa8, 0xd7, 0xc0, 0xa2, 0x20, 0xb4 } }, +{ "\xa5\x01\x37\x26\xa2\xa7\x79\x20\x45\xf0\xa1\x7e\x53\x8c\x72\x49\x2f\x09\x96\x7a\x15\x85\x67\xfe\xef\x7e\x5a\xd9\xd7\xc5\x08\x66\x2a\x91\xda\xbd\x45\xb0\x51\x2d\xdf\xd9\xf0\xe8\x03\x1c\xc6\xbe\xa8\x7a\x9c\x02\xef\x91\xb7\x89\xf8\x70\x4a\xd0\x60\x89\x7b\x3d\x5b\xc4\x10\x7e\x6b\xb0\xb6\x0e\xbb\xd4\xee\xd6\x1a\x24\x94\xf0\x97\x8f\x0d\x86\xb5\xb5\x0d\xd9\x4b\xb6\x03\x5e\xfb\x26\x21\x02\x4c\x1c\x0b\x8f\x67\x6a\x1b\x27\x6b\xe6\x4f\xec\x6d\xe7\xd0\xc2\x0f\xcc\x1f\x2c\xbb\xb6\xde\x53\x7d\x55\x39\x25\x7b\xe0\xef\x9a\x11\x1e\x01\x12\x8d\xa2\xf5\xdb", 136, { 0xcb, 0x2c, 0x7e, 0xc1, 0x58, 0xd4, 0xea, 0xf8, 0xb3, 0xc1, 0x82, 0x69, 0xcc, 0x3c, 0xaf, 0xa0 } }, +{ "\x84\x14\xc7\xce\xcf\xa9\x6d\x18\x26\xb4\x06\x16\x56\x56\x9e\x5a\x22\x51\xa0\xcb\xb4\xfb\xd9\xe9\xbe\x4e\x25\x2d\x32\x1c\xb8\x8e\x9a\x60\x0b\x20\x14\xaf\x60\xd7\xee\xcd\xf4\x6a\xda\x5b\xc1\x53\xce\xae\xed\xf2\x7b\xbc\xd2\xd1\x67\x30\xab\x03\xa9\x9d\xd7\xa5\x41\xce\xcd\x86\x11\x3b\x9d\xe3\x7c\x99\x1f\x4b\x9a\x89\xba\xa1\x15\x70\xd2\x40\xa3\x66\xcf\x39\x20\x47\xc7\xb7\x46\xe8\xc7\x84\x0c\x64\xc3\xa4\x99\x94\x17\x1f\xe4\x9c\xb9\xdd\xea\xa2\xfe\xa9\x8a\x9a\x05\x58\x00\x3d\xc4\x03\xfc\x18\xad\x6f\x5e\xc1\xfc\x8e\x91\x24\xa0\x1e\x81\xfb\xc3\x70\x3a", 137, { 0xa3, 0xac, 0x47, 0xc4, 0x7f, 0xf0, 0xfa, 0xcf, 0x5a, 0x75, 0x87, 0xd1, 0x31, 0x8d, 0x68, 0xe1 } }, +{ "\x5c\xf8\x43\x1f\x6c\x00\xcf\xc3\x31\x39\xdd\x67\x86\xa4\x13\x11\x27\x91\x4e\x45\xec\xe9\x28\x62\x13\x18\x99\x9c\xb6\x95\xb9\x92\x5b\x0f\xa3\x8c\xaa\x36\x76\x52\x39\x23\x75\xab\x83\x64\x4e\x71\xf8\xa8\x78\x4d\x2e\x03\xb5\x15\x35\xdf\xb7\xbf\x08\x80\xdf\x00\x1e\x32\x20\x85\x20\x11\x02\xcd\xb6\x75\xc3\xa1\x7b\xf8\x98\x31\x0f\x25\x11\xcd\x4a\xbe\x9a\x3c\x8d\xaa\x1d\xbd\x35\x79\xc5\x97\x29\x96\xde\x5f\x93\x08\xd8\xc6\xac\xe4\x6a\x1c\xaf\x53\xd4\x65\xef\x3c\x3c\x16\x04\x8d\x3a\x6d\x21\x2b\x6f\x6a\x81\x74\x50\x6d\x00\x6d\x01\x6d\xc6\x8d\x5c\xd2\x1e\x25", 138, { 0x4a, 0xa7, 0x74, 0xe4, 0x2d, 0x30, 0x28, 0x86, 0xda, 0x3f, 0x18, 0x0c, 0xef, 0x15, 0xa0, 0xb2 } }, +{ "\x10\xf0\x65\x6a\xe6\x21\x1d\x21\x1f\x7e\x21\xe5\xfa\x3a\xf3\x18\x52\x9b\x31\x64\x63\x95\x27\xed\xad\x04\x7d\x15\xf1\x85\x11\xeb\x58\xf2\xe0\x31\xb3\x79\x1d\x08\xdd\x59\x64\x3a\x3d\x38\x08\x24\x68\x23\x88\x3e\xe3\x22\x21\x48\x06\x77\x7d\x13\xfb\x73\x89\xea\xe6\xf6\x64\x9b\x1f\x81\x73\x25\x9a\xf9\x91\xff\x68\xfb\x64\x03\x56\xd6\xcb\xf6\xb3\x29\x73\xb4\x30\x1a\x89\xfc\xdf\x30\x89\xd6\x5e\xce\x35\x9d\x0d\x4d\xa2\xad\x7a\xb5\x6c\xa9\xde\x17\x0a\x69\xc1\x89\x3c\x7f\xb8\xbf\xa1\x65\x4f\x42\x65\x44\x01\x50\x17\x63\x64\x51\x98\x2a\x62\xf1\x2f\xd2\xa1\xde\xba", 139, { 0xa0, 0x86, 0x6f, 0x0d, 0x37, 0x2f, 0x7e, 0xf8, 0x9a, 0x82, 0x03, 0x51, 0x49, 0x80, 0x26, 0x4c } }, +{ "\xac\x04\x20\xff\x0a\x4b\x0f\x21\xce\xd6\xf6\x2e\x8d\x87\x43\xd5\x5f\xc4\x67\x35\x45\x9c\x50\xd0\x38\x01\x80\x9e\xca\x33\xca\x3e\x7b\x3e\xa9\x48\x9b\x99\x3d\xbd\xd6\xf0\xe3\xa0\x61\xfc\x6f\x9e\xc0\x8d\x09\xe8\x31\xa9\xa1\x21\xb8\xcf\x10\x73\xc8\x54\xcd\xbc\x8b\xef\x48\xe6\xce\x50\xe6\x55\x8c\xea\x9a\x79\x16\xd2\x1c\x83\xdc\xbf\xc9\x34\xda\x31\x17\xd0\xa1\xaf\xb3\x32\x00\x29\x39\xf9\x50\x7b\x8f\xe0\x59\x12\xdf\x2c\xe4\xa9\x2f\x3e\xde\x2d\x9e\x48\x26\xbf\x3d\x1c\xf4\xd7\x87\x20\xe5\x86\x7f\x5e\xa7\xd4\x65\xb8\x3d\x47\x14\x38\xef\x85\xfb\x86\xd2\x11\xb5\x73", 140, { 0x0f, 0x04, 0x8f, 0x85, 0xdf, 0x16, 0x04, 0x94, 0x33, 0x86, 0x13, 0xb6, 0x66, 0xea, 0xc7, 0x9c } }, +{ "\xef\x31\x48\xb1\x13\xf0\xf7\xa5\x33\x40\xc4\x55\x79\x37\x86\x7c\xef\x7a\xa2\xbd\xc7\xb7\x69\xf4\x44\x4c\x0e\xa7\x49\x05\x42\x9b\x7c\x02\x6e\x83\x17\xb7\x8c\xd4\x4b\x0e\xa3\xb4\x50\xa7\xdd\x10\x0e\x3f\x46\xcc\x61\x2e\x23\x16\x0d\x0a\xed\xd4\x3e\x6a\xe9\x3b\xba\xc5\x65\x81\xa5\x78\x91\xaa\xf0\xe6\xf7\x7f\x60\xb9\x98\x9e\x36\x47\xa5\xaa\x80\x11\xd6\xa2\xfc\x65\x6b\x4f\xa4\x23\xbd\xd7\xdb\x9c\x80\x70\x32\x96\x98\x2e\xd7\x6c\x94\xfc\x9a\x52\xcb\xa9\x9d\xb7\x12\x1a\x98\xc3\x17\x9e\xc7\xff\x5d\x5f\x70\x14\xd4\xf3\x14\xac\x14\x12\x32\x75\x36\x62\xb2\x44\x4f\x6f\xf5", 141, { 0x4c, 0xac, 0xbf, 0x73, 0xc7, 0x06, 0x64, 0x46, 0xda, 0x86, 0x95, 0xdf, 0xb9, 0xb8, 0xb5, 0xd6 } }, +{ "\x56\x8a\xb6\x76\xb1\xe1\xe0\x1d\xa9\x78\x0c\x20\x7e\x96\x45\x96\x23\x40\x13\x9a\x19\x74\x2d\x18\x7a\xff\x4c\x37\x12\xfb\x1a\x63\xa8\xe9\x49\xf6\x5a\x66\xc1\x82\x26\x8d\xf1\xbd\x85\xea\x47\x0a\x31\x16\xba\xa0\x08\xf4\x84\x59\x09\x86\xee\x19\x7b\x6d\x43\xd9\x2c\xfb\xe6\x4f\xd7\xf6\x80\x3c\x9f\xec\x51\x51\xb8\x2e\xa8\xbf\x25\x6a\x6e\x5a\x9b\xe9\xdc\x69\x85\x61\x4c\x0c\x21\x78\x2d\x4a\xc7\xd6\x11\xb7\x4a\xe5\xe1\xbe\x77\x28\x30\x91\xba\x35\xac\xaa\xe1\x50\xb1\xfc\xf8\xa6\xf7\xbb\x52\x23\x6c\xc5\xa9\xf0\x1d\xab\x5d\x8c\x4d\x60\xd8\x86\xa8\x7d\x13\xd4\x91\x2f\x31\xd4", 142, { 0x63, 0x7e, 0x3a, 0xe0, 0x18, 0xd6, 0xf3, 0xb6, 0x8a, 0x93, 0xae, 0x2c, 0x75, 0x4d, 0x53, 0x73 } }, +{ "\x98\xbe\x49\xdc\x07\xba\x41\x7f\x9b\xc4\xd5\x5f\x50\xf6\xb7\xaa\x56\xf0\xd1\x33\x1f\x80\xa6\x2d\x9a\xed\xd6\x86\x7a\xe0\xc0\xde\xaf\xf0\x42\x22\xf6\xc9\x9c\xc9\x8c\xf8\x72\xab\xfe\x55\xf0\x79\x1c\x0c\x08\xdd\x0b\x4a\xd6\x2f\x7a\x82\x25\xd0\xed\x59\x0b\x27\x35\x34\xaf\x36\x00\x5b\x2b\xd8\x8c\xca\x8c\x99\x77\x94\xf6\x32\xb3\xf5\xe5\x9f\x95\xf2\x8e\xdf\x0c\xaf\x64\x48\xee\x4d\xb6\x84\x6e\x7d\x75\x2c\xaa\xa6\x14\xff\x61\xaf\x88\xbe\xc2\x69\x6f\xa8\x5f\x9c\x4d\x8d\x41\xad\xf1\x91\x15\xe8\xf6\x80\x83\x70\x65\xc8\x9f\xc0\x78\x17\x78\xdd\x79\x92\xce\x1a\xc9\xae\xe2\x87\xfd", 143, { 0xa5, 0xdb, 0x01, 0x1b, 0x71, 0xec, 0xf0, 0x5c, 0x2f, 0xaf, 0x35, 0x2c, 0xf6, 0x74, 0xfd, 0x3e } }, +{ "\xaf\x65\xf8\x23\xbb\x92\xad\x22\x9a\x57\xa3\x3f\x0d\xae\x76\xbc\xc8\x0b\xf1\x9b\x0d\xee\x34\x80\xe5\x98\x81\xb4\xfe\xda\xa3\x46\x1c\x08\xfb\x4c\x3d\x0d\x28\x47\x4e\x98\x52\xa4\x83\x74\x13\x5f\x57\xf6\x03\xc2\x20\x8f\xdf\x4b\x4d\x82\x55\xac\x40\xaf\x6f\xec\xc2\x8d\x99\xab\x27\x36\x51\x82\xff\x9c\x6a\x89\x76\xd9\xfc\xf2\x49\xa5\xeb\xd2\x65\xe1\x13\x00\x1e\x50\x0d\x16\x08\x65\xa1\x95\x76\x36\xc8\x25\x8d\x90\x5c\xf9\x03\x25\x5e\x51\x7a\xe1\xe3\x19\x73\x5a\x9d\xaf\xf0\x66\x02\xc2\xab\xc6\x1b\x55\xec\xff\xeb\xe3\x0b\x49\x7a\x9d\x82\xa1\x7d\xcf\xae\xf9\xa3\x60\x22\x90\x7e\x78", 144, { 0x70, 0xcb, 0x37, 0x7b, 0x48, 0x29, 0xcd, 0x1c, 0x9e, 0xe6, 0x27, 0x97, 0xf6, 0x5f, 0xb5, 0xdd } }, +{ "\xa8\x5c\x0c\x3c\xd5\xa2\xe2\xb5\x48\xa8\xf4\xce\x7f\x83\x03\x7c\x55\x0a\xa3\xf8\x1c\xeb\xe8\x28\x53\xdb\xad\x1c\x04\xe9\x80\xb3\xbd\xec\x2d\x5e\x28\x1b\xe6\xfc\x4a\xbb\x0c\xe5\x54\xf3\x9c\x02\x29\xbb\x39\x19\x6d\xf3\xd1\x27\x46\x90\xef\xe6\xb3\xf1\x9d\x6e\x85\x50\xf4\xf8\xfd\x53\x42\xbd\x04\xc2\xd6\xfd\x01\x54\x6a\x1b\x5b\xa2\x2e\xe5\x8b\x3d\x6d\xf2\xdc\xdb\xde\x24\xc2\xac\x89\x4e\xd4\xcb\x54\xef\x68\xd0\x2a\x1b\xca\x82\xc7\x7a\x18\xa9\x22\x6a\xbd\x02\x76\x40\x88\x4c\xef\xac\x68\x80\xee\x3a\xc6\x1d\xf9\xf5\x7f\xa1\x42\x26\x7d\x13\xd2\x3a\xf1\xbd\x52\xc1\x2f\xf8\x76\x93\x25", 145, { 0xaa, 0x81, 0x41, 0xd2, 0xf2, 0x8b, 0x40, 0x43, 0x3f, 0xcb, 0x21, 0x01, 0x79, 0xcd, 0xe5, 0xf0 } }, +{ "\x1f\x06\x0d\x79\xa6\x8b\x79\x3f\x43\x92\x8c\x54\x4a\x9f\x08\x5a\x16\xb2\x82\x50\xa3\x6f\x3e\xcc\x39\xec\x36\xd8\x43\x1c\x39\x67\x3e\xd2\x30\x72\xcd\x75\x7d\xb4\xe9\x3f\x7c\xfe\x35\x31\x2b\x37\x6f\x97\xe6\xf4\x03\x33\x4b\xb0\xba\x09\x3c\xa8\x8f\xc6\x02\x56\xa2\xce\x8f\x87\x46\xe1\xdc\x1b\x35\x69\x71\x59\xe3\x62\x03\xec\xef\xe6\x37\x7e\xb6\x54\x85\xf0\x02\x1c\x37\x33\xe0\x2a\x91\xc6\x8f\xed\x0b\xcc\x94\x03\xba\xc9\xeb\x83\xcd\xf9\x58\xe6\x32\x4d\xdb\x92\x58\x03\x41\x05\x10\xe0\xd7\x9b\x8d\x0d\x3a\xfb\x8a\x8c\x4a\x24\x8a\x55\x3d\x10\x3b\x11\xcf\x02\xf4\x72\x97\x71\x5d\x2d\x75\x91", 146, { 0x08, 0xbc, 0x75, 0x2b, 0x6e, 0x0a, 0xe8, 0xd2, 0x25, 0x7e, 0x6c, 0x2b, 0x47, 0xf3, 0x79, 0x7f } }, +{ "\x2e\x95\x28\x7a\x10\xd5\xfc\xf7\x9f\xca\xa0\xee\x91\x7b\x16\x67\xf0\x36\xc3\x3a\x83\x48\xa6\x59\x4b\x58\xa5\xb8\x29\x60\x03\xd5\x9d\x49\xee\xe7\xa9\x23\x35\xa7\xd3\xfe\x17\xb5\x4a\x67\x37\xa9\x20\x82\xab\xb7\xb6\xc1\x33\xfe\x35\x3e\x86\x6d\x38\xbb\xc8\x52\x87\x33\x19\x81\xff\x1c\x47\x1d\x8d\x3c\xa3\x06\x59\x25\xf1\xdf\xff\x4f\x79\xba\xf8\xd0\x3a\x63\x17\xba\x3e\x46\x30\x11\x09\xfd\xd3\x67\x2b\x7a\x36\x16\xf5\xce\x30\x1a\x48\x93\x62\x89\x89\xfc\x70\xaf\xb0\x77\x6d\xca\x80\xfc\x55\x5f\xd1\xf6\xb3\x37\x09\xca\x63\xf9\xa9\x08\x72\x65\x03\x2d\x21\x2a\x0a\x12\x09\x65\x41\xf5\x58\xb8\xd6", 147, { 0x43, 0x95, 0x30, 0xa4, 0x0d, 0xbc, 0x2d, 0x03, 0x2c, 0x61, 0xc3, 0x95, 0x63, 0xd2, 0x7d, 0x95 } }, +{ "\x23\x39\x02\xc8\x3e\x52\xc0\x42\x30\x67\x00\x0c\xad\x1c\xfd\x17\x5e\xd7\x5c\x36\xaf\xc4\x02\xec\x36\xf2\x90\x60\xbe\x9a\x7c\x6d\xf0\x80\xcd\xd6\x9d\x73\x72\x97\xab\xee\x40\x56\x99\xe1\x87\xf8\xb0\x89\x4f\x50\xc8\x7b\x34\xf3\xb4\xc1\xdb\x27\x4b\x1b\x10\xfa\x14\x67\x7e\x6e\x8d\x1b\x0a\xd2\x18\xee\xcc\x2c\x83\x96\xaa\xd2\x32\xad\x93\x17\xeb\xad\x55\x23\x3e\x1a\x1c\xdc\x8f\xbf\x88\x00\xc1\x10\x69\x55\x81\xae\x1a\xf7\x2c\x0a\x77\xd0\x5e\x21\x7c\x27\x18\x65\x7b\x4f\x8d\xbc\xf9\x7f\x89\xa1\x26\xc2\x7f\x69\xf8\x05\x2d\xa0\xe3\x4e\xee\x92\x37\x0c\x9c\xe5\x15\x89\x1f\x63\x0f\x7b\x97\xd6\x5c\xba", 148, { 0x7a, 0x61, 0x56, 0xe4, 0xc4, 0xdf, 0xf9, 0x6d, 0xc2, 0x11, 0x35, 0x16, 0xf1, 0x9a, 0x6e, 0x89 } }, +{ "\x22\x0c\xb4\x0d\x4a\xfa\xce\x1d\x0e\xfd\x74\x8b\x8b\x3b\x3f\x1d\x47\x28\xf5\x13\x1b\x25\x7b\x98\xba\x42\x78\x54\xe2\x24\x89\x1e\x1d\x02\x1a\xcf\x34\xc9\xe7\x32\x31\x60\x10\x17\x10\x06\xd2\x87\x02\xd7\xe8\x11\x5d\x6d\x7d\x43\x23\xa2\xcc\x35\x2c\x74\x56\x3f\xf3\x02\xbf\xca\xfb\xb3\x46\x44\xdc\x76\xdf\x2d\xee\x23\xef\x4e\x90\x00\xa3\x0a\x16\x60\xee\xcd\x4d\x67\x1d\xa1\xab\xe8\x18\xdf\x18\x6f\x37\x02\x53\x5a\xbe\x97\x03\x22\xf7\x51\x5b\xb7\xea\x39\x68\x0a\xbc\x02\xfa\xa4\xa2\x7a\x2c\x73\x80\x1d\x92\xa6\x22\xc4\xff\xad\x15\x7a\xf0\x63\x23\x6f\x99\x48\x6a\x06\x89\xe7\x18\x09\xfc\x56\xc6\xfc\xbd", 149, { 0x69, 0x0d, 0x82, 0x75, 0x0b, 0x92, 0x08, 0xa6, 0xae, 0xc8, 0x57, 0xe3, 0x5e, 0x0f, 0x9f, 0x3e } }, +{ "\xdc\x6d\x8f\xb6\xad\x09\x2d\x16\xd0\xc8\xb1\x1d\x21\xef\x38\x87\x73\x4a\x11\x92\xcd\x4e\xd1\xae\xd5\xcd\x84\xc1\x4b\x54\xfd\x14\xac\x24\x4f\xdd\xf7\xcc\x54\x69\x8b\x5f\x6a\xe6\x2f\x57\x3e\xca\x2c\x06\xc0\xe4\x95\xb5\x36\xfd\xa7\x5b\x6d\x2a\x4b\xfb\x09\xb1\xb8\x9b\xfe\x96\x35\xdc\x17\xc1\xfc\x3b\xb4\xcd\x3a\xe3\x91\x6f\x33\x2c\xc0\x81\x83\xb4\xb9\xaa\x7f\x18\x88\xac\xba\x50\x24\x4a\xa4\xa5\xe0\xd4\x4c\x4f\xfb\x50\x46\xaf\x52\x47\xa7\x25\x34\x29\x2d\x8f\x56\x5e\x7c\x5f\xdd\xea\x83\x58\x99\xbb\xfd\xe5\x52\x92\x14\x16\x3a\x8c\x1f\x37\x81\x4c\x8c\x0f\x08\xc7\xd9\xb2\x2d\xac\xbc\x03\xc5\x6e\x63\xca", 150, { 0x7f, 0x92, 0xfb, 0x9d, 0x68, 0x56, 0xeb, 0x53, 0xe8, 0xab, 0x26, 0x4d, 0xd0, 0x3f, 0xf8, 0xe6 } }, +{ "\x28\xef\xd6\x6e\x65\xca\x78\x4f\x96\x3d\xac\xc2\x4f\xb2\x93\xaa\x30\xe8\xf4\xaf\x9a\xc3\x35\x1e\x7e\xac\x86\x5d\x51\xa6\x1d\x09\x1c\xef\x9b\xae\xaf\x4f\x8e\x22\xf5\x00\x10\x7e\x63\x39\x8c\xba\x8b\x59\xa0\xe4\xcd\xad\x1e\xfd\x2c\xde\x2d\x70\x3e\xfa\x8d\x30\x3d\x1d\xf8\x6d\x3c\xbb\xa3\xf2\x73\x8d\xe4\x1e\xbb\x16\xed\x7d\x15\xd1\xb6\x02\x64\xf9\xf9\xe3\x3b\xf4\x57\x11\xd1\x5d\x98\x53\x11\xad\x10\xfe\xce\x85\x1c\x53\x14\x9a\xcc\x75\x99\x3d\x9b\x05\x53\x86\x59\x5c\x23\x1c\x29\x64\xaf\xa4\xa6\x13\x4d\xc4\x21\x85\x1a\xd3\x06\xb6\x2b\x1f\x5d\xd9\xdb\xd9\x6c\x57\x44\xa1\x79\x67\xc9\xaa\xac\x46\xcf\x8a\x13", 151, { 0xf3, 0x88, 0x0d, 0xa8, 0x7a, 0x3e, 0xd7, 0x9e, 0x5d, 0x42, 0x7d, 0x7a, 0xaa, 0xbc, 0x6e, 0xd4 } }, +{ "\x14\x8b\xa1\xc0\x4b\xf6\x23\x0d\xdc\xde\xc3\x00\xe7\x16\xfd\xc9\x17\xce\x00\x68\x99\xfd\x37\x6b\xb7\xfa\x73\xd5\x15\x2a\xb7\x1b\x86\xd4\x9f\x48\x8c\x11\x6d\x40\x6a\xdf\xb1\x21\xe8\x54\x95\xc5\xa3\xef\xc2\x64\x0e\x0a\xf3\x57\x09\x6c\x14\xf7\x1c\xfb\x16\xa4\x50\x8e\x52\xe1\xaa\xe0\x97\x9d\x45\xa1\xd2\x8d\x0b\xa7\x59\xb4\x0f\x43\xd4\x04\x8a\xae\xc8\x1e\x71\xa1\xc1\x36\xaf\x03\x1c\x12\x04\xbd\x6e\x31\x79\xaa\x95\x08\x7f\xaa\x59\x67\xa4\xd6\xbd\xfb\xf1\xcd\xe8\xec\xe2\x2d\xab\xa7\x02\x1e\xaf\xb6\x23\x08\x3c\xca\x37\x64\xa8\xdb\xcf\xb0\x5a\x66\x2d\x7c\x7a\xd5\x07\xa2\x37\xfd\xdb\x93\xb4\xc1\xe9\xcb\x90\xd3", 152, { 0x60, 0x2b, 0xfd, 0x08, 0x46, 0xc2, 0x5c, 0x0d, 0x1d, 0x63, 0x05, 0xd8, 0x59, 0x14, 0x44, 0xd1 } }, +{ "\xd2\x66\x10\x9b\xcb\xcd\xeb\x30\x7e\x89\xb2\x83\x7d\x38\xdb\x9b\x63\x9c\x69\xfa\x89\xd0\x39\x1f\x62\x97\xea\x25\x74\xcd\x6a\x89\xf3\xff\x1a\x09\xfc\x16\x9d\xa7\x6b\x2e\x42\xcc\x59\x85\x0b\x8a\x35\x8e\x5a\xfa\x7e\x25\x37\xc4\x1a\xde\x40\xbd\x56\x76\x2e\xab\x7b\x6b\xff\x23\x09\xa7\xc6\x93\x93\x57\x0b\x5c\x36\xdb\xe0\x17\xb7\xd6\x81\xf9\x38\x64\xa7\x51\x97\x6b\x69\x2e\x64\x0b\xcf\x1d\x7c\x2f\xf5\x0f\x46\x45\xd9\x5a\x8a\x0a\xc1\xd6\xe9\x7e\x4b\x28\xfd\xf7\x13\x1b\x0e\x52\xfa\x2a\x6d\x44\x19\x1a\x71\xce\x43\xc4\x0b\xcf\x2f\xf0\x08\xb3\x4a\x5d\xe4\x49\x18\xde\x45\xb3\x43\x9e\x1b\x77\x42\x84\x51\xb2\xa7\xb1\x30", 153, { 0xa7, 0xb7, 0x03, 0xe9, 0xa9, 0xbe, 0x15, 0x1f, 0xd7, 0x1d, 0x12, 0xad, 0xa6, 0x66, 0x1e, 0x57 } }, +{ "\x6b\x05\x26\x51\x05\x7b\x83\x3d\xcf\xe2\xeb\xa3\xb6\x8f\x03\x34\x1a\xc5\x18\x1f\xbd\xba\x60\x24\xd8\x44\x58\x57\x48\x20\x4d\x74\xe5\xdf\xf7\xd9\xf3\x6e\x3f\x24\xb2\x40\x22\x69\x10\x1a\xad\x10\x7f\x7a\x28\x4a\xe0\xa5\x4f\x2e\x9e\x4c\xbb\x74\xd8\xda\x60\xcc\xb6\x5d\x2f\xdc\xdd\x0e\xdc\xd5\xfd\x7f\xba\xb0\x87\x60\xc2\x0b\x7c\xed\xb2\x9a\x61\xf8\x52\x4b\x4f\x8e\xd1\xfa\x27\x49\x4e\xce\xe2\x32\x74\x2e\x06\x50\x3d\x64\x34\xd1\xd7\xcc\xde\xd4\xa3\xb8\x17\xd1\x5a\xe4\x83\xa6\x4a\x90\x6d\x3f\xbf\x40\xf7\xe0\x7d\x0c\x6c\x12\x68\xa4\xb2\x28\x46\xe4\xdb\x6c\x9d\x10\xda\xeb\xb7\xac\x52\xda\xc4\xfb\x8a\xa4\x1e\x12\x7d\x91", 154, { 0x83, 0xe9, 0x8a, 0x97, 0xe1, 0xf0, 0xd6, 0x1c, 0x85, 0xf4, 0xed, 0x7e, 0x3a, 0x05, 0x3d, 0x25 } }, +{ "\xa7\x97\x0f\x14\x4e\x1b\x59\xb1\xb1\x12\x25\x89\xdd\x6b\x75\x83\x30\xd0\x3e\x19\x5f\x7c\x32\xbc\x94\xb3\xbb\xe5\xb0\xe3\x03\xba\xae\x55\x30\x58\x27\x90\xad\xc3\xf2\x4a\xa4\x68\xe3\x0c\x88\x4a\xb4\x61\xce\xd1\x02\xba\xbb\x2c\x6e\xe1\x58\x5e\xe4\x18\x83\xec\xf8\xce\x20\x22\x6c\xfd\x6c\xfd\xce\x23\x72\xb8\x3e\xda\x96\xf6\x4e\x16\x4e\x88\x02\xfb\xf1\xdc\xf6\x59\xa7\x03\x9f\xc5\x80\x5d\xa9\x55\xa2\xe3\x80\xf7\x9a\x11\xeb\x6e\xd3\x6e\xd2\xea\x24\xb9\x20\x44\x83\xb2\xc3\xd3\xd7\x82\xd0\xed\xec\xc8\xc4\xfe\x80\x40\xe6\x3e\x7a\x12\xc8\x12\x3a\xb5\xec\x01\x0b\x7e\x82\x51\xb5\xc9\x4f\x3e\x30\xc2\xaa\xd6\x72\xd1\xa1\x74\x69", 155, { 0xad, 0x2e, 0x8c, 0x9f, 0xe8, 0x7f, 0x9d, 0xba, 0x71, 0xc8, 0x41, 0x50, 0x33, 0x22, 0x2e, 0xaa } }, +{ "\xa0\x38\xd6\x05\xca\xd1\xdd\x6c\x21\xa7\xe2\x51\x9c\x74\xb0\x5f\xdb\x33\x21\xcf\x59\x00\x58\x19\x2d\x1b\x98\xc6\x7d\x0b\xbf\x64\x7f\xdf\x63\x94\x2d\x90\x88\x3d\x85\x82\xfa\xe3\x7a\x29\x4d\x12\x7a\xc8\x6f\xf4\x9d\x55\xe7\x02\x67\x79\xac\xd7\x3a\xb3\xa4\x20\x5b\x9c\xb8\xb0\x9f\x45\x90\xb0\xb1\xbc\xf0\xf4\x03\xae\xae\x68\x4f\x26\x4f\xa9\xc9\x74\x3e\xb0\xe3\x28\xa8\xa9\xbc\x3d\xf7\xe2\x26\x54\xe8\xdf\x52\x15\x4b\x8a\x1b\xba\x57\x87\xeb\xa7\xa7\xa6\x4e\x31\xd5\x72\x11\x7f\xb1\xe6\x16\x8e\x1f\x3f\xb7\x4e\x8a\xed\xd5\xea\x09\xa3\x7c\x25\x0c\x8d\x34\xdf\xc2\xa1\xe7\xb8\x0b\x0f\x6a\xcb\x15\xd2\xaa\x9b\x95\x68\x74\x0c\xa4\x9e", 156, { 0x0d, 0x7b, 0x57, 0x4b, 0x26, 0x26, 0xcd, 0x87, 0x41, 0x4e, 0x6a, 0xff, 0x3b, 0x56, 0x58, 0x20 } }, +{ "\xe0\x88\x34\x85\x5b\x42\x2d\x81\x50\x97\x28\x7f\x73\x90\xc7\x46\xaa\x84\xaf\xe7\x97\xdb\x23\x4f\xc6\xed\x3e\xfb\x70\x08\xcc\xca\xea\x91\xc6\xee\xad\x41\x69\xfc\x02\x91\xf2\x24\x4a\x31\xf8\x7a\xe7\xb1\x65\x72\xcb\x43\x12\x6b\x9b\x97\xff\x62\x7f\xe6\x2c\xc7\x89\x0b\x16\x6c\xbf\xcb\xd1\x9a\xc7\x35\xbe\x3e\x2e\x25\xea\x41\x54\xe2\x04\xf5\xf8\xe7\xf8\xab\x5c\xbf\x2c\x61\x15\x09\x56\x98\x71\x9b\xf8\x44\x84\xc3\x79\xdd\xd1\xa9\xe1\x93\x92\xd0\x31\x9e\xa5\xbb\x5d\xb3\x13\xac\xe7\x92\x3d\x88\x19\xbc\xa5\xd6\xdf\x43\x56\xe6\x3f\xb9\xf1\x0e\x75\x4a\x56\x10\xaf\xe6\xeb\x97\x61\x96\x8c\xe0\x46\xf0\x0f\x76\xf5\xa6\x72\x15\x1c\x38\xa4", 157, { 0x73, 0xb6, 0x03, 0x35, 0xf6, 0xda, 0xb2, 0x8b, 0x69, 0xf1, 0x80, 0xf7, 0x40, 0x0b, 0x06, 0xc0 } }, +{ "\xb0\x5b\xca\xec\x8e\xbf\x10\xfa\x8f\xd9\x65\x89\x8d\x7a\xfb\xad\xde\x0e\x2d\xbe\xf5\x93\xf1\xe1\x28\x34\x69\x30\x8c\x86\x98\x85\xfc\x5e\x31\xe8\x39\x4c\x8b\x92\x2b\xb9\xb2\x9e\x46\x99\x97\x4b\x08\xcc\x67\xf0\x9e\x17\xf9\x7d\xa6\xb9\x60\xa9\x10\xad\xa0\xbd\x1e\x7c\x7e\xfd\x8a\xbb\x70\xae\xc6\x28\xb4\xc9\x5e\x5d\x7d\x3a\x7a\x2f\x47\xd5\x7f\xa6\x4c\xd6\xd6\x98\x0f\x13\xc4\xe4\x15\xc0\x78\x48\xb3\xdf\x24\xe0\x03\x42\x43\x3c\xf0\x3e\xf8\x1c\x71\xee\x97\xca\xd3\x21\x3d\x14\x2e\xe1\x99\xe5\xf9\xa1\xce\x80\xba\x02\x71\x58\xd6\x42\xad\x8e\x86\x41\x86\x07\xea\x31\x3a\x29\x37\xda\xc3\x33\x0d\x88\x7a\x37\xe4\x92\xd5\xb4\xa4\x87\x51\xd4", 158, { 0x26, 0x34, 0xea, 0x0f, 0xa7, 0x52, 0x4b, 0x9a, 0xb2, 0xdf, 0xcc, 0x1f, 0xf1, 0xd3, 0xd0, 0x78 } }, +{ "\x53\xf6\x6b\x3e\xe8\xda\xc8\x99\x3f\xa0\x74\x9f\x26\xd7\x47\xd9\x94\x73\x64\xfc\xf9\xbe\xdb\xe0\xb1\xdc\x6e\x19\x92\xf9\x71\x34\xa4\x11\xca\x90\xf0\x5b\x18\xd6\x71\x53\xf0\x16\x28\x63\x43\x7f\x4b\x2d\xdb\xbb\x9d\x77\x04\xe5\xd9\xb4\x47\x28\x48\x2b\x52\xf5\x72\xc6\xf3\xe0\xf1\x79\x43\x18\x60\x4d\xe0\x81\x73\x08\x52\x70\x21\x7b\x8f\x02\xfb\x68\x99\x19\xa0\x0d\x45\xf4\x49\x52\x18\x6a\x80\x8a\x4a\xc3\xee\xe9\xec\x33\x51\x83\x25\xf4\x8c\xfd\x98\xff\xd8\xd2\xe1\x66\x19\x44\x3f\x51\x4b\xdd\x4c\x93\x1b\xa0\xe6\xe8\x92\xd1\x32\xcd\xec\x5e\xb7\xfc\x87\xe9\xa5\x83\xf7\x73\x39\x80\x36\xa6\x38\x7b\xf9\xbe\x98\x60\x1d\x16\x3e\x17\x40\x4b\xe2", 159, { 0xe6, 0xaf, 0x93, 0x2f, 0xba, 0x00, 0x41, 0x8d, 0x2c, 0x9f, 0xc7, 0x71, 0x81, 0x48, 0x2c, 0xfe } }, +{ "\xc2\x6d\x0f\x10\x92\xef\x8c\x47\x47\x46\x72\x44\x42\x38\x9f\x59\x48\xfe\x6a\xf6\xd5\x9f\x8c\x49\x1a\x5b\xac\x02\x96\x3d\x86\x2f\x4c\xd3\xb7\x47\xa6\xfa\x27\x42\xe6\xd3\x13\xe5\x45\xd2\xb6\x1c\xaa\xf5\x93\x7f\x08\x11\x62\xf7\x54\x47\x94\x7a\x22\x96\x85\xf1\xdb\x8b\x3e\x3b\x9d\x13\xe3\x4b\xaf\x71\xbf\x6d\x9f\x4a\xea\xa6\xfb\xdd\x95\x38\xa8\x51\xf2\x44\xe2\x27\xc2\x8a\xd0\xcf\x7c\x4c\xc3\x56\x17\x52\x0b\x3c\x75\x06\x76\x64\x6c\xbf\x66\x24\x71\x1b\x8e\x7c\xe3\x85\x49\x64\xf2\xd6\x96\x3e\x2a\x17\xb4\x6b\xa0\x65\x56\xfa\xb7\xed\x84\x7a\x8f\x17\x0e\xf0\x0b\xc0\xad\xe4\x7e\x9f\xb7\x96\xf2\xc9\x7e\x4e\x14\x4f\x47\xd1\xbf\x05\xe2\xef\x23\x5e", 160, { 0xc1, 0xf7, 0x9a, 0xa7, 0xb1, 0x56, 0xdd, 0x85, 0x09, 0x0d, 0x4f, 0xc0, 0xd1, 0x25, 0xb0, 0x3c } }, +{ "\xeb\x39\x92\x73\x9b\xd1\xe7\x22\x4b\x5a\x93\x53\x87\x0e\x45\x56\xcb\xed\x35\x68\xdd\x13\x0e\x55\xc6\x23\x76\x37\x6e\xdf\x3b\x5c\xd3\xda\x1b\x45\xe6\x44\x30\xcb\x02\xe4\xf6\x5d\x09\x25\xfb\x64\x1d\x47\x22\xc7\xf8\xb6\x93\x8a\xe9\x78\x42\x91\x6c\xbf\x1b\x83\x64\x9e\xc7\xca\xf7\xd9\x1e\xb6\x06\xd5\x29\xc1\x48\xae\xd2\xed\x02\x67\x2b\x4a\x65\x3c\x57\x94\x83\x14\x19\xf8\xef\x12\xf7\xf7\xf1\x4b\x0a\x64\x63\x92\x65\x87\x2c\x6e\x20\x64\x56\x2d\x00\x15\xcd\x12\xc4\x54\xb6\xa9\x0e\x15\x69\x3c\xec\x50\x0d\x5e\x03\xdc\xcf\xa4\x57\x77\xbf\x74\xb9\xe2\x47\xf5\xce\x29\x48\x26\xb7\x01\xd2\x0a\x62\x49\x80\x01\x6d\xb3\x6e\x33\xb2\x7c\xd9\x25\x73\x57\x51", 161, { 0x25, 0x9e, 0x60, 0x07, 0xc6, 0x99, 0x48, 0xe3, 0x91, 0x92, 0x4e, 0x39, 0xd7, 0x44, 0x7f, 0x63 } }, +{ "\x6d\x23\x68\x9d\x82\xcf\x6b\x2b\xad\x27\xf5\x32\x1c\x2d\xd3\x66\x15\x79\x8f\x57\x48\x26\x11\x67\x3d\x5d\x61\x66\xec\x7c\x8a\xcc\x6b\xe2\x9a\x92\xc2\x5a\xc7\xad\xda\x21\xac\x28\x94\x95\xb0\xdc\xf7\x7d\x87\xcf\x81\xef\xd2\x27\x9e\xe2\xe2\xc9\x36\x50\x9a\x93\x61\x07\x72\x32\x36\x0d\x98\xa0\xc1\xae\x31\x3d\x12\x24\xbd\x89\x72\xe1\x98\x7c\xb1\x7b\x9c\x82\x9b\x34\xe4\x16\x89\x25\xac\xfa\x13\x07\x54\x10\xe3\x9e\x83\xd9\xa5\xc3\x68\x87\x1a\x0c\x1c\xc0\x4c\x1a\x23\xf2\xdc\x7e\x12\x4d\x77\x48\x4a\x62\x67\x2e\xe2\x56\x45\x56\xa3\xc2\xcd\xc0\x2c\x2b\xca\x53\x36\x19\x30\x83\xf2\xd6\x48\x9b\x8f\xc4\x06\xac\xd8\x5b\x76\x12\xf9\xbf\x55\x9f\x61\xfa\xbc\x67", 162, { 0x02, 0xa5, 0xc5, 0x80, 0xb9, 0x42, 0x65, 0x02, 0xa8, 0x7b, 0x20, 0x32, 0x10, 0x65, 0xad, 0x6c } }, +{ "\xc3\xdb\xf7\x28\x38\x6a\x74\x53\x7f\x06\xd7\xbb\x64\x1d\x2a\xd9\x3e\x88\x32\xba\x91\x81\xdd\x86\xd4\x42\xd7\xad\x4e\x3b\x3b\xaf\x1a\xee\x67\x88\x49\x6b\xe8\xb7\x26\x63\x94\xea\x94\xec\xb7\x48\x94\xd0\x65\x5a\xe3\x92\xef\x97\xc0\xfe\x70\x8a\xcb\x6c\x87\xa2\x09\x91\x1f\x96\x04\x01\x69\x73\x10\x45\xeb\x43\xa8\x94\xb2\x5b\xf6\x32\xa3\x42\x71\x62\xf0\x39\xa1\x09\xa6\x6c\xfe\xe1\x62\xb3\xf6\x56\x24\x05\x0e\x01\x3b\x7a\x20\xbe\x60\xfa\xc2\x6c\xdf\x87\xc7\x40\xf0\x25\xdf\xc6\x24\x62\x5a\x76\xfb\x85\x09\xef\x92\x57\x45\xd2\x79\x88\x09\x3e\xa3\xc0\x3a\xe3\x77\x44\x08\xc5\x03\x40\x6c\x8f\x50\xb7\xd1\x91\xd0\x04\xcf\x58\xf4\x0b\x12\xe9\xda\x02\x59\x99\x24", 163, { 0xbf, 0x90, 0x55, 0xe1, 0xda, 0x81, 0x3d, 0x69, 0x5c, 0x5d, 0x2c, 0x5d, 0x96, 0xe9, 0x51, 0x54 } }, +{ "\xd6\x9b\x8c\xe4\x3b\x44\xc8\xb3\x53\x9c\xf5\xe1\xfa\x49\xb3\xc6\xac\xeb\x98\x37\x13\xe5\xc5\x14\x31\x3c\x24\xff\x27\x97\x40\x27\xa0\x66\xc0\x42\xdd\x20\x81\x99\x5d\xa4\x4f\x3d\x28\xc1\x40\x57\xb8\xd1\xae\x9d\x85\x80\xcf\xe1\x2c\xaa\xf3\xc3\x3b\x62\x59\x87\x9b\x10\xad\x01\x9a\xb2\x22\xad\x95\x43\x28\xdb\x3e\x38\xca\x07\x90\x27\xa7\x47\x4c\x83\x8b\xdd\x2e\x82\xaa\xec\xb1\x1f\x78\x48\x7c\x3b\x28\x66\x68\xdf\xbf\x72\x2e\x9c\xd3\x80\xb2\x13\xe5\xda\xe6\x91\x58\x78\x5c\xd2\x0e\x8d\x6d\xe7\x9e\x3e\xff\x32\x33\x6d\xf5\x8d\x04\xb4\x39\x8a\x6b\x6e\x5f\xd5\xa5\xef\xf6\xb6\x25\xd3\x70\xb3\x95\x74\xab\x52\x6a\x75\x1b\xfc\x22\x7b\x96\xfd\x1d\xfc\xbc\xa8\x15\x2f", 164, { 0x9c, 0x17, 0x1d, 0x5e, 0x84, 0xcb, 0x1e, 0x60, 0x48, 0xd1, 0x73, 0x61, 0xee, 0xa5, 0xbb, 0x78 } }, +{ "\x01\x98\x3c\x23\x59\x11\xf1\xec\x7f\x84\x1e\xf7\xe1\x31\x30\x7f\x2b\xe7\xb4\x18\x6e\xe7\x8b\x69\xed\xe7\xc9\xf7\x84\x32\x30\x1c\xb6\xec\x44\x16\x51\x74\x0b\x3b\xc0\xe2\x63\x4b\xed\xaf\xff\xde\xd0\x74\x00\xfc\x99\xcb\x2c\xcb\x76\x52\xcd\x63\x01\xce\x28\xbe\x4a\x6b\x99\xcb\x7c\x21\x48\xa1\x2e\x33\x8a\xd0\x48\xd2\xd6\xd4\x90\xde\x61\xa3\xd0\xcc\x59\x65\xa6\xa2\xbb\x44\xe8\x1f\xd2\x59\xb1\xf9\x4d\xc5\x0d\x3e\xfb\xe1\x3d\xdc\x25\x8d\xa7\x3c\x88\xa5\x5d\x08\xed\x92\x48\x0e\x67\xfc\xf0\x3c\x29\x9d\xeb\xcb\x01\x31\xe1\x79\x75\x8a\x37\xee\x78\xbf\x60\x40\xc9\x84\xbc\x92\xe9\x95\x2b\xd7\xb7\x4d\x33\xb4\xa9\x53\xca\x84\xa9\x73\xc0\x75\x8a\x8b\xcb\xcf\x25\x9c\x31", 165, { 0x17, 0x89, 0x0e, 0x3e, 0xab, 0xcb, 0x90, 0x4d, 0xe0, 0xf3, 0x5b, 0x5b, 0xfe, 0x31, 0x6d, 0x40 } }, +{ "\x55\x14\x00\x0c\xc4\x0a\xbb\x3d\x78\xce\xe9\xf0\x2e\xd2\x57\xc7\xe4\x74\x2e\xa5\xdd\xd0\xca\x1a\xc1\x40\xaa\x66\xe0\x71\x7f\x2c\x97\x23\x67\xb4\xcb\x7c\x33\xdd\x93\x0a\xe4\x9d\xf2\x54\x35\x36\xc1\x1b\x52\xf8\xac\x32\xa6\xad\x53\xf7\xd2\xa4\x90\x6d\xb9\x5d\xd8\xf7\xb8\xce\xba\xb3\xf3\x50\x85\x71\xcb\x29\x07\x4f\x6b\xb6\x6f\xf3\x82\x35\x54\x63\x0b\x2d\xce\x84\x47\x7a\xc2\x2d\xcd\xf9\x3c\xe7\xb7\xcc\xf5\x43\xfe\x4a\xf3\xd8\xe0\x86\x50\xd8\x7d\x7a\x12\x4e\x82\xd1\x39\xf7\xfc\x4e\xd8\xba\x4e\xdc\x5b\xc4\x3e\x32\xe7\x44\x29\x22\xdf\xc0\x57\x7f\x82\x13\x69\xa9\xb1\x03\xef\xb7\xce\x83\x16\x3f\xc1\x82\x7e\xc4\x14\x6d\x2a\xbd\x3e\x48\x91\x3e\xfd\x64\xd1\x46\xdc\xbe", 166, { 0xf1, 0x4c, 0xc8, 0x4a, 0x3c, 0x5d, 0xf7, 0xd0, 0x16, 0x5d, 0x8d, 0xf6, 0xf1, 0x0e, 0x52, 0xec } }, +{ "\x03\xa4\xd4\xf4\xa9\x86\x0f\xe5\x44\x9f\xc7\xe3\x03\xf4\x4d\x97\x95\x44\x26\x72\x1f\x12\x50\xcc\x4a\x50\xa2\x9b\x73\xa9\x51\xd0\x06\x6b\x8f\x51\xe5\x10\x4d\x8f\x01\x68\x22\xc5\x0c\x64\x44\xcc\x45\x81\xb2\x9c\x72\xce\x74\x63\xec\x9c\xfa\x3b\xd4\xc2\xa2\x8c\x64\x8a\x55\xfe\x60\x3c\x51\x18\xaa\x44\x01\x7a\xf5\x02\x07\xb3\x92\x2f\x5c\xc0\x66\xe7\x8f\x22\xfd\x57\x29\x9b\xb7\x03\x32\x84\x20\xb4\xcc\xce\x5e\xfd\xfc\x93\xc3\x69\x89\x58\x82\x43\xfd\xe2\x7f\x02\xc8\xb1\x3f\x4e\x84\x1d\xff\xb3\x54\x0c\xe0\xe1\x65\x4e\x3f\x9d\x96\x95\x23\x48\x34\x14\xd0\x0a\xde\xb2\x78\x9b\x88\xeb\x11\xae\x9a\x44\x42\xfa\x38\x69\x77\xe6\x9d\xe4\x13\xd0\xa0\x7c\xc5\xfa\x59\x28\xf4\x11\xdd", 167, { 0xa0, 0x91, 0xf8, 0x02, 0x18, 0x02, 0x02, 0x74, 0x19, 0xaf, 0xbf, 0x2f, 0xe5, 0xd5, 0x0a, 0x96 } }, +{ "\xae\x54\x5b\x24\xdd\x9a\x7d\x0c\x63\x4c\xe7\x77\x4c\xb1\xdd\x8f\x18\xe8\x22\x29\x77\x15\x43\x47\xa3\xb6\x7d\xb8\x5a\x14\x4c\xda\x77\xd4\x91\x80\x2c\xad\x5e\xee\xde\x34\x62\x01\x9d\xd2\xec\x6c\x3f\xd8\x9d\x1c\x18\xa9\xaf\xbd\x57\x15\xdc\x56\x00\xc7\xec\x10\x81\xd4\xde\x14\xf4\x73\xb2\x91\xf0\xcc\xd1\xdd\x0c\xe9\x1a\xb3\xf1\xc9\x8a\x9b\x1b\x93\x87\x67\x2c\xe8\xc9\xd9\xed\x51\xe6\x62\xe2\xd8\x78\x05\x88\xb2\xec\x5a\x2d\x19\xea\xaf\x6c\x38\x5c\x49\x44\x40\x1e\xc8\xd5\x98\x40\xa8\xb6\x31\xfa\xe4\xf5\xf7\x2d\xb5\xac\x63\x92\x78\x3c\x2d\x81\xad\x29\x1f\x60\x1b\x92\x05\xa6\x12\x4b\xc1\x8b\xc8\x99\x7b\x4e\xe5\x89\xf5\x22\x1a\xed\xfc\xb6\xec\xf4\xfa\x60\x8f\x65\xa9\xe5\xed", 168, { 0xac, 0x8b, 0xae, 0x88, 0xd7, 0x6a, 0x35, 0x60, 0x7d, 0x02, 0x43, 0x98, 0x20, 0x2a, 0xd6, 0xec } }, +{ "\x78\xe2\xe7\xc6\x51\x93\xec\xf1\x19\xcf\x07\xc0\xbb\x00\x25\x81\x38\x37\xf5\x21\xa8\xa4\x75\xec\xce\x21\x16\x6f\x56\xe8\x8b\x7f\xad\x66\x33\x52\x7d\x27\x21\xca\xc4\xf0\xc4\xd2\x90\xeb\x38\xe1\x59\xfd\x28\x9c\xfb\x34\x5d\x98\x4e\x5c\xe8\x3d\x64\xb1\xe8\xc6\x5e\xae\xf9\x64\xeb\x04\x39\x82\x5e\xa6\xf8\x24\x6b\x01\xfc\x69\x7f\x49\x6d\x2f\xb9\xef\x63\xd5\x88\x2e\x0b\x1b\xe2\xc5\x70\x26\x1d\xbf\xec\xa1\x6e\x6e\x2a\xfd\xfd\x76\xd6\xd8\xa1\x05\xe4\x7b\x3d\x20\x7a\x7e\xb6\x19\x7b\x86\x90\x1d\xb1\x2f\x24\xe9\x96\x04\x80\x9d\xbf\xab\xdb\xa9\xe6\x1e\xb3\xe4\x92\x14\x85\xbb\x65\x7e\x28\x86\x02\x2d\xc7\xf6\x99\x90\x79\xab\x10\x9b\x7f\xe2\xcf\xc4\x19\x4c\x28\x27\x05\xf9\x62\xca\x95", 169, { 0xc4, 0xf0, 0x9b, 0x16, 0xea, 0x1a, 0x1a, 0x5a, 0x54, 0x70, 0x0c, 0xa8, 0xb4, 0xe3, 0x92, 0xd2 } }, +{ "\x73\x61\xfa\x6c\xe8\xf3\xd4\xd4\x7f\xb9\xe0\xbf\xcb\xb0\xd7\x59\x5d\x5b\x85\x46\x73\x8f\xc9\x7d\xcf\xda\xba\xc0\xa3\x91\xe4\xb7\xa8\x75\xb0\xa8\x4e\x01\xe1\xd6\x0e\x53\x3b\x73\xdb\xb4\x3e\x42\xb6\xc6\x10\xce\x61\x49\x78\x40\x2b\x8a\x06\xe1\xea\x68\x51\x2d\x07\x04\x59\x90\xb3\x04\x0a\xc0\x38\x84\xe2\xb6\x6a\x9b\xa9\x4a\x3c\x85\x5f\x6a\x6f\x72\x34\xf6\x64\xea\xb1\x3b\x13\xdb\xf4\x0b\x14\x41\x18\x75\xdb\x70\xb3\x27\x01\x01\x79\x5c\xbd\x57\xfd\x83\x71\xcc\x98\x6e\x61\x7d\x62\x33\x7e\xaf\x5d\xa3\x60\xdd\xb2\x64\x53\x5f\x13\xae\x88\xb8\x3f\x9e\x6d\x7c\xa4\x3a\x17\xdc\x1e\x02\xda\xd0\xde\x2f\xfb\xe0\x66\x8b\x7d\x8e\xb0\xec\x17\x63\x6e\x4e\x47\x95\x6d\x8c\x80\x51\x13\xbb\x7f\xab", 170, { 0x69, 0x9d, 0x5b, 0x85, 0x72, 0xec, 0xe6, 0xbf, 0x17, 0x47, 0xff, 0x53, 0xb3, 0xf0, 0xd5, 0x34 } }, +{ "\x07\x23\xbc\x20\xef\xdb\xfb\xc4\x54\x00\x01\x0c\xa3\x92\x64\x3a\x4d\xeb\x7c\x61\x0d\xdc\x76\x14\x49\x65\x87\xaf\x92\x11\x3c\x41\x46\xec\xf0\x15\x55\x22\x58\xdc\x20\x36\x38\x78\x7d\xdb\x38\x67\xd7\x72\xd1\xca\x73\x21\x62\x11\xcd\x8c\x5f\x45\x21\x33\xa8\xf2\x05\x68\xf8\xaf\x33\xeb\x74\x4c\x65\x24\x63\x96\x59\xfc\xfd\xc9\xf4\x58\x5c\x93\x83\x32\x8f\xc1\x1c\x56\xce\x88\x23\xb7\xc7\x72\xe8\x6c\x17\xe4\x6e\x4a\xd4\x48\x47\x1e\x47\xdb\x9a\x87\xb7\x14\x47\x6e\x60\xb0\x21\x24\x83\x57\x5a\x16\x97\xec\xfd\x2f\x9d\x76\x94\xca\x91\xa6\xe9\x53\xfc\x04\xea\x79\xa6\xba\xa5\x11\x69\xfd\x73\x8a\x21\x14\x32\x09\xc0\x06\xab\x21\x7e\xe4\x12\x30\x2d\xb0\xab\x59\xaa\xe9\x89\x19\x70\xb4\x71\x88\x46", 171, { 0x24, 0x02, 0xdb, 0x04, 0xc8, 0xa1, 0xc2, 0x6a, 0xaa, 0x95, 0x63, 0x35, 0x92, 0x4e, 0x35, 0x1b } }, +{ "\xa9\xde\x2f\x19\x37\x1e\x80\xe4\xb4\x9a\xf6\xcb\x04\x33\xca\x48\xe5\xc7\x4f\x7c\xd6\xd2\xea\xa7\xa2\x31\xb2\xb3\x8d\x02\xa0\xeb\x19\xa8\x73\xc9\x75\xeb\x23\xec\x83\x3c\xff\x28\x85\x15\x65\xb8\x63\x7f\x1e\x8e\x9b\xad\x54\xcb\xc5\xc6\x30\x4a\xc2\xc0\x14\x57\x81\x68\x72\x7e\x6d\x7e\x47\x7d\x77\xfc\x38\x5b\xbb\x77\x47\x92\xd1\x9f\x32\x67\xb3\xe1\x68\x5b\x46\x2b\xa8\xba\x87\xcf\x39\x50\x53\x81\xc0\x3b\xd2\x7b\xc1\xdc\x82\xc0\xb5\xe7\xdc\x7c\xc3\x9a\xa4\x8a\x1f\x0b\xd2\x10\xfc\x99\x18\x45\x2f\x84\x10\x53\x61\x99\x04\x58\xf1\x06\x59\x86\x64\x4c\x98\x69\x89\x51\x1a\x48\x2e\x95\x50\xa5\x78\x7d\xac\xe0\xe3\xcb\x30\xf8\xd7\x2f\x91\x70\xe3\xf6\x07\x50\x98\xe1\xb4\x42\x04\x11\xae\xdd\xca\x1d", 172, { 0x95, 0x82, 0xd6, 0xd6, 0x0d, 0x72, 0x51, 0x58, 0xba, 0xbc, 0x56, 0xa9, 0xf6, 0x07, 0x54, 0xa6 } }, +{ "\xab\x00\xdb\x46\x48\x54\xd3\xc2\xf6\xf3\xf2\x34\x82\x27\xb5\x3d\x3f\x4a\x10\x2c\xd1\xcd\x4b\xd1\x99\x55\x76\x6f\xb8\x00\x8a\xcf\xc2\xc6\x1e\x71\x01\xfa\xc3\xde\x63\xee\xfc\x19\x01\xb6\xdd\x34\x4c\x06\x3f\xfe\xd6\x35\x9d\xda\xba\x62\x8e\xab\xaa\xb5\xdf\xeb\x93\xbf\x4c\xdb\xef\xfb\xdb\xd4\xa6\x76\xd6\xbd\xa2\x8a\x63\x96\xee\xc6\xc1\x30\x89\xea\x21\xff\xcd\x0d\x1f\x08\x77\xe1\xdb\xf4\x52\x0f\xb8\x47\x85\xbc\xb1\xaa\x75\x2d\x53\x64\x58\x87\x5b\xe7\x58\xaf\xec\x87\x5f\x50\x6c\x45\x85\xfb\xfd\xca\x14\x68\x93\x6f\x34\xda\xb7\x79\x38\xa1\xd7\x62\x83\xb9\x47\x52\x18\x90\xd8\xad\xbe\xe5\x13\xc5\xcc\xcc\x13\xb0\x96\xce\xfc\x35\x74\x2d\x1c\xe0\x6c\x44\x9c\x35\x7b\x0d\xe2\x01\x85\xbd\x87\xcc\xd6", 173, { 0xd7, 0x83, 0x37, 0xf7, 0xb8, 0xcb, 0x87, 0x54, 0xc4, 0x01, 0x9d, 0xcf, 0x3b, 0x57, 0xf5, 0x8b } }, +{ "\x8a\xf0\x6a\x54\x8c\x8b\xb1\x44\xc1\xa8\x44\xb5\x2b\xf1\x8e\x8c\x14\x88\xcb\x2d\x72\xbb\x40\xc3\x65\x66\x8b\x2d\xdc\xe6\x15\x86\x58\xb5\xa3\x4e\xc9\xa7\x0c\x3a\x94\xc0\x05\x94\xb6\xb0\x18\x50\x02\xec\xb3\xad\x86\x69\x5d\x84\x0c\xf7\x03\x31\xbc\x39\x71\x1b\xdf\x3d\xdc\xe1\xbe\xbc\x9b\x22\xa8\xef\xf6\xe9\x13\x0b\x17\xb4\xda\x5b\x1e\x1f\xa5\xf9\x50\x32\x67\x29\x6f\x44\x00\x52\x24\x89\x02\x9a\x99\x3f\x90\x1d\x23\x72\x62\xc9\x1d\x67\xe6\xd9\xd0\xab\x81\xeb\x8e\xb8\xf3\xc0\xde\x40\xd9\x90\xd1\x19\x4b\x08\x73\xc6\xa5\xe1\x5d\x9e\x64\x1e\x68\x9c\x26\xe2\x7c\xc2\xd3\xeb\x86\x2a\xdb\xaf\x87\xaa\x95\x11\xc9\x23\xc7\xc0\x2e\x66\x43\x2d\xa1\xc4\xae\x26\xad\x31\x5c\x14\x2c\x14\x57\xcd\x17\xae\x7f\x17", 174, { 0x8b, 0xaa, 0x35, 0x9d, 0xe0, 0x56, 0x8f, 0x69, 0xc8, 0x17, 0x5c, 0x10, 0x2d, 0x43, 0x12, 0xe3 } }, +{ "\x7d\x24\xcb\xba\x8f\x2a\xad\x41\xd8\x4e\x94\x4d\x89\xdf\x8b\x95\xf2\x78\xff\x7d\x0d\x2c\x9d\x52\x35\x4f\x5a\x20\xf4\xdf\x8c\x30\xf9\x8e\x35\x22\x28\x6d\x61\xa3\xcc\x36\xa5\xca\xe8\x36\xc7\x14\xab\xd5\x7c\xfa\x01\xc4\x4c\x2d\x46\xc1\x92\x6e\x15\x0a\x9f\x0b\x3f\x5c\xff\xf9\xd8\xa6\xd3\x8b\x6b\x4f\x5d\xcd\x4d\x21\x9b\x7f\x0f\xd0\x0a\xb1\x0d\x2b\x8b\xf8\x23\xde\x63\x4a\x7f\xe1\x5d\x7b\x92\x81\x0a\x55\x21\x09\x29\x4d\x78\x0d\x21\xe8\xbd\x52\xaa\xaa\x62\x5d\x8c\xb6\xb4\x97\x80\x07\x91\x19\x33\x49\x36\x1a\x68\x55\x36\xf2\x3c\x48\x87\xca\x85\x3f\xb7\xe3\x54\xb0\x3c\x7f\x9a\x68\xe8\x6f\xe7\x1d\x7b\x3a\x4d\xaf\x53\xe7\x63\x00\x3e\x68\x66\x6c\x70\xa3\x79\xe7\x90\x1e\x0d\xb2\xec\x45\x5b\xba\xcd\x5b\x0e", 175, { 0x1e, 0x96, 0xa5, 0x23, 0xc0, 0x9c, 0x30, 0x9c, 0x2a, 0x99, 0x58, 0x95, 0xf2, 0x54, 0x8e, 0xed } }, +{ "\x8d\xe6\xfb\xff\xf9\xe6\x4a\x18\x43\x2d\xbc\x59\x01\x9a\x7f\xf9\x95\x83\x87\xa4\x46\xbe\x37\xe3\xfc\xdc\xa9\x9a\x98\x76\x9a\xaa\xee\x9f\xf5\xb7\x60\x79\xfa\x04\x18\xe3\x0b\x79\xe1\x50\x13\xc7\xa2\xb3\x93\xa2\x79\x96\x4b\x2d\x70\x4a\x81\x74\xdf\x39\xf1\x12\x5e\x57\x51\xf3\x64\xb7\x7f\x34\x81\x3a\x49\x27\x34\x62\xd9\x72\x6a\x44\xbb\x56\x94\x9c\x8c\x0e\x63\xfb\x42\x4e\x23\x1b\x12\xea\xb1\x53\x02\x98\x1a\x25\x0b\xce\xd2\xf5\xea\xc5\x8e\xd5\x83\xa0\xbe\x7b\xf2\xa5\xaa\x54\x30\xa9\x28\xb1\x5f\x8b\xf8\x1f\xb3\xd6\xbc\xd6\xfc\x8a\x96\x47\xd3\xf5\x60\xd8\x61\xba\x83\xac\xc7\xf3\x74\x9b\x2d\x73\xd1\x41\x6b\x24\x14\x32\x4d\x8f\xf1\x4b\x86\x7b\x52\x24\x35\xac\xed\xa1\x0c\xcc\x7e\xa8\x23\x68\xa6\xed\x58\x11", 176, { 0xbe, 0xf1, 0xe8, 0x50, 0x33, 0xbf, 0xf7, 0xbe, 0x13, 0x51, 0x2e, 0x59, 0x3c, 0x64, 0x15, 0xd8 } }, +{ "\x60\xe8\x60\xa3\x1c\xe8\x6f\xa2\x7a\x41\x80\xbf\xa4\xa1\x41\x7b\x48\x81\x9e\xe3\x31\xb7\xe9\x79\x81\x27\xa3\x33\x8d\x9a\xea\x9c\x55\xa7\x7e\x19\x9e\xcd\x71\x47\xae\xa3\x6b\x7f\xa3\x26\x97\x7b\x71\x32\x2e\x12\x76\x0c\x9e\x1f\xbc\x1c\x56\x80\xca\xb8\x31\x3a\x27\x1b\x7c\xba\x6c\x74\xa6\x36\x05\x1b\x83\x32\x84\xde\x3d\x1f\xa1\x7a\xd7\x1e\xd2\x25\x5f\xe2\x83\x48\xb0\xb3\xf3\x4a\xe1\x8e\xab\x88\x4e\x69\x9b\x60\x41\x95\xd2\x6d\x3c\x3d\xd9\xcd\xe5\x0b\xad\x9d\x8e\xea\x58\x86\x60\xe6\x2b\x71\x25\x2f\x9a\x56\xaf\x3c\xb4\x32\xe7\x0b\x3d\x17\x75\x87\x69\x5d\x09\x03\x38\xf6\x45\xe3\x69\xdf\x47\x5b\x1c\xb3\xd6\x4e\x07\x5a\x28\x58\x54\xde\x4d\xe7\x16\x5e\x3c\x84\x67\x1b\x78\x30\x1f\xaf\x5f\xe9\x33\x5e\x0f\x4c\xa7", 177, { 0x21, 0xa8, 0xb9, 0x73, 0x01, 0x98, 0x8c, 0x9f, 0x67, 0xfb, 0xb8, 0xdb, 0xc4, 0xde, 0x97, 0x6a } }, +{ "\x85\xf5\x54\x31\x2f\xf4\x40\x6c\xc7\x2e\x93\xb5\xe7\x71\x35\xa6\x4f\x41\xb7\x2d\xf1\x7e\xb4\x48\x28\xb2\x53\x5f\x09\xf9\xe8\x3d\xd2\x8d\xba\xad\x80\xed\xdf\xad\x7c\xaa\x44\x51\x75\xce\xc9\x37\x49\xe9\x89\xa3\x1c\xb9\x37\x37\x8c\x75\xa3\x50\xfb\xb6\x5c\xff\x0b\x03\x70\xa2\x28\xf7\x4f\x1f\x3e\x11\xce\xbc\x8c\x18\x47\x9e\x90\x29\xdd\xdd\x22\x5f\xdd\x40\x9d\x1d\x40\x9a\x37\xfa\x4d\xc0\x72\x4a\x5b\x25\xab\x45\xb4\x15\xd0\xd7\x96\x8a\x2f\x03\x53\xae\x69\xf4\x98\xee\x85\xa2\xca\xb7\x21\x1d\x8c\xd0\xc3\x7a\x5d\x54\x4d\x57\x5f\x4a\x8f\x0c\x32\xe3\xf7\x6f\xff\x4f\x63\x44\x91\x3c\x17\x40\x9d\xec\xca\xb8\x22\xf1\xdb\xeb\xeb\x88\xa1\xe8\x32\x90\xdf\x1d\x5f\x25\x57\x7e\xed\xde\x75\x4e\x6e\x9f\x2c\x8d\xa5\x1b\xde\xff", 178, { 0x51, 0x6b, 0x97, 0x49, 0x9d, 0x54, 0x92, 0x2b, 0x34, 0xc3, 0x79, 0x77, 0x7f, 0x03, 0x8d, 0x1a } }, +{ "\xd1\xe9\x75\xd4\x09\x42\x8f\xf9\xc2\x55\xd6\xfa\x6e\x47\x6d\x92\x3f\xca\x86\xd1\x09\x59\x10\xe8\x46\x0d\x8e\x94\x33\x1f\x03\x25\x17\xfb\x09\x2a\xa3\xfd\x02\xbb\x75\xca\x65\x63\xb7\x4e\x3a\xa7\xe4\x4d\xa1\x37\xab\xa8\x8b\xb1\xec\x2f\x8c\x0c\xdf\x1d\xc9\xa7\x54\x34\x0c\xee\x14\x76\xf6\xa6\x67\x7d\x54\xd7\xaf\x77\x8a\x53\x32\xc2\x2b\xe6\xf5\x20\xab\x1c\xc3\x97\x2c\xa9\x4d\xe8\x74\x79\x6b\xa9\x00\x55\x81\x01\x32\x2e\xfc\x00\xa5\x0a\xfc\x99\xa1\x88\x0c\x3d\xaa\x11\x0c\x14\x33\x9d\x30\xda\x70\x1f\x21\x55\x49\x8f\x41\x6e\x6a\x92\x0c\xf3\x77\xc7\x9a\xe8\x5d\xb0\x40\x86\xc4\x3b\x56\xd1\xa0\xec\x14\xd9\xe7\xaa\x96\x8d\x5d\x23\xff\x36\x8a\xdc\xb9\x98\xce\xd8\xda\xa0\x8b\xe4\xa2\xc9\x80\x7d\x21\x12\x36\x5f\xf6\x94\x92", 179, { 0x6b, 0xc1, 0x3c, 0x44, 0x56, 0x28, 0x48, 0xa5, 0xc9, 0x18, 0x9c, 0x37, 0xa8, 0x8e, 0xce, 0xf2 } }, +{ "\xac\x31\xc2\x8b\xb5\x5a\x42\xf6\x67\x8b\x62\x7d\x55\xb8\x38\xaf\x5d\x0f\x5b\x31\xfa\x7a\x38\x11\x26\x42\x11\x3b\xea\xcd\x98\x04\x83\x88\x24\xe4\x32\xe0\x8e\x41\xa1\x69\xab\x66\xed\x22\x65\x92\x54\xd0\x78\x2d\x7c\x86\xc6\x16\x5e\x46\x58\x17\xcd\xc2\xf2\x7a\xa7\x3b\x52\xb5\x97\x8b\x05\x40\x84\x3d\xe5\x87\x99\xda\x32\xfb\xf2\x3f\x4c\x43\xe0\x29\x0a\x91\xd9\xd3\xbb\x0f\xff\xb6\xb7\x77\x4b\x6f\xa0\xc2\x56\xbf\x3a\xf8\xc4\xac\xe4\x26\x4d\xc4\xb3\x6e\x69\x81\x2a\x38\x97\xc8\x97\x87\x4b\x8c\x0c\x66\x72\x90\xf9\x80\xa3\x49\x63\xcf\xe3\xe1\xc3\x6d\x15\x58\x7d\x86\xfc\xc5\xfb\x6f\xee\xbb\x66\xcf\x18\xc6\x01\xfb\x68\x15\x22\x60\x1b\x31\xcd\x19\xe3\xeb\xee\xa1\xb4\x55\x33\xa2\x2b\xe6\x84\xec\x9b\xc1\x20\x81\xb6\x0f\x55\xcd", 180, { 0x38, 0xf4, 0xa7, 0xc3, 0x5e, 0x5a, 0xf4, 0x32, 0xf2, 0x12, 0x4c, 0xf5, 0x99, 0xb6, 0x90, 0xe8 } }, +{ "\xd5\x88\xdb\xf3\xe4\x11\xce\x42\xed\x80\x47\xc6\x3f\x7b\x96\xfb\x3b\x7e\x1d\x9d\xba\xfb\xcc\x9b\x1e\x9b\x34\x29\xf4\xa3\x4a\xf4\x43\x72\xbb\x71\x74\x26\xe6\x4f\xdd\x5f\x7b\x0b\xec\x1b\xae\xa1\xec\xc0\x17\x60\x77\x39\x29\xd7\x79\x38\x4c\xeb\xdc\x99\x9a\x0a\xd5\xe7\x33\x7a\xca\xf7\x3e\xcb\xdf\xb2\x7c\x6b\x1c\xf1\x8a\x58\x3c\x81\xb3\xf0\x15\x45\x6f\xe4\x9f\x7b\x7d\x4b\xa2\x17\x98\xd3\x00\x4b\xd9\x12\x9c\x28\xa8\xfa\xe6\x5e\x60\x6b\x05\x1f\x7f\xe3\x9f\x22\x86\x50\x48\xc4\x73\x06\x84\x48\xd9\xcc\x7b\x3f\x99\x11\x38\x03\x3f\x3c\x9d\x5d\xfb\x21\xe7\x47\x3a\x8f\xda\xcb\xe0\x06\x89\x0a\x24\x86\xc4\x58\x09\x82\x1e\x85\x75\xf4\x99\x37\xf0\x8a\xf0\x72\xfa\xfe\x81\x3a\x08\x83\xd6\x50\x1d\x5b\xcf\x17\x02\x85\x6d\x9a\x22\x94\x3d", 181, { 0x0a, 0x5b, 0x96, 0x06, 0x98, 0x96, 0x99, 0xa6, 0xdc, 0x6a, 0xa5, 0xbf, 0xc4, 0xfa, 0x83, 0x48 } }, +{ "\xa7\x04\x9b\x5f\x13\x65\x45\x32\x21\xf1\x01\x9e\xfe\x9e\x5a\xfd\x63\xa5\x64\xa6\x5d\x1e\x52\x18\x29\x38\x25\xc0\x39\x12\x7f\x67\x53\x38\x96\x3b\xd9\xbd\x44\x78\x23\xf1\x3a\xb3\x08\xbf\x55\xc3\x7c\xa6\x09\x4c\x53\x52\xf9\xe9\x24\xd6\xa9\xf6\x48\x88\x4b\xf7\x02\x7a\xb5\xa8\xb9\x90\x74\xa1\x60\x43\xfa\xa6\xf6\xf1\xf2\x89\x29\xde\xb5\xbc\x16\xcb\xd4\x77\x2b\x31\xd5\x82\x2e\x1a\xfc\xa0\x56\x9d\x3e\x98\x97\xf4\x5b\xe1\xfb\x3b\x04\xe9\x2c\xc7\x37\x02\x0e\x21\xac\xe9\x89\x9e\x67\xf5\x64\x9c\x6e\xd9\x4d\x5b\x95\x15\xf5\x75\x75\xff\x58\xfb\x7b\x6a\x1a\x2e\x1c\xf0\x0d\xd7\x26\xe2\xcf\x44\x32\xc8\x91\xdf\x36\x96\xf2\x6c\x37\x6e\x09\xde\x1b\x0c\x82\xd7\x9c\xd3\xdf\xbb\x59\x71\xe0\x70\x07\x31\xfe\xb4\xc4\xdd\x10\x1a\x8c\x4d\x11\xa2", 182, { 0x34, 0xf3, 0xea, 0x31, 0xf3, 0x44, 0x99, 0x87, 0x3c, 0x5f, 0x60, 0xbc, 0xe5, 0xb0, 0x5a, 0xdd } }, +{ "\xc4\x90\xf9\xf4\xf4\xb6\xc7\x39\x92\x39\xa0\x96\xf9\x06\x11\x46\x79\x2b\x71\x53\x87\x1e\x62\xf1\x15\xa7\x76\x77\xfd\x6b\xed\xfb\x96\x17\x9d\x88\x69\x25\xeb\xfe\xfe\x4e\xf5\x87\xcf\x8c\xd2\xb2\x5e\xcb\xf1\x2d\x62\x2b\x9e\x23\x1d\xf4\xa3\x30\xc9\x17\x0b\xfd\x30\x5d\x01\x7d\x5b\x2f\xd8\xc3\x62\x00\x24\x7d\x62\x5b\x05\x11\x8d\x84\x84\x52\x5c\xce\x15\xdf\xdf\x79\x3c\x18\x34\x45\x4d\xbe\x16\x97\x4b\x26\x8d\x47\xf2\x1a\xc3\x04\xd1\x4d\xf7\x65\x8e\x78\x8b\x8c\x4d\x15\x37\x79\x2c\xb7\x60\xe9\xe5\x04\x83\xe8\x97\x51\xcb\xfa\x9e\xd8\xc3\xe2\x9e\x98\x26\x0d\x9f\xc9\xd1\x9e\x52\xfb\xd9\x17\x72\xca\xb9\xa0\x46\x40\xa4\xf7\x43\xc7\xf9\xf5\xce\xc9\xd5\xb9\x1e\xe6\xc2\x73\x40\xd1\x8c\xcf\x34\xc8\x34\xfb\x35\xae\xfe\x57\x16\xc6\xa5\xb9\xc8", 183, { 0xe0, 0x50, 0xf4, 0x13, 0x5b, 0x9f, 0x3d, 0x6c, 0xf8, 0xc9, 0x95, 0x5e, 0x68, 0x81, 0xb2, 0x0a } }, +{ "\x0e\xaf\x59\xf8\x36\xdb\x60\xd5\x3b\xb6\x08\xef\xa5\x4c\x6f\x3b\x59\xfc\xfe\x33\x1b\x65\x70\x1a\xa4\x7c\x82\x5d\x5c\xc0\x36\x15\xb5\x84\xc3\xaa\x24\x6b\x1c\x91\xbc\xf3\x1b\x35\x68\x28\x4a\xf4\xc4\x78\x4e\x40\x99\xa7\xf1\xe6\xf3\xd9\xca\x6b\xe1\xcc\x8b\x92\xc9\x29\xe7\xfb\x65\xef\x1e\xe5\x5e\x0f\x26\x14\x83\x17\x77\xce\xa6\x06\x74\xff\x13\x3e\x71\x7c\xae\x97\x65\x64\xa8\x8f\x2d\xa3\xdd\xa0\x7a\x90\xce\xaa\x59\xb6\x36\x90\x5d\xb0\x4b\xdf\x6b\x2e\x92\xa8\x22\x14\x5f\x6e\xe5\xc1\xe8\x3b\x86\x6d\x05\xcd\x90\xab\x87\xee\x31\x0e\x32\xe1\xc2\xe8\x58\xf8\xf5\x2d\x13\x43\x9a\x77\x1e\x62\x0e\x23\x50\x7c\x40\x98\xb7\x48\x61\xa8\x4d\x48\x28\x0e\x59\x16\xbf\x17\x65\xd7\x4d\x5e\xd8\xcc\x21\xb0\x2f\x07\x78\x0e\xdc\x3a\xeb\xd0\xbb\xab\x78\xe6", 184, { 0xf1, 0x8e, 0x78, 0x9a, 0x46, 0xe0, 0x68, 0x70, 0x90, 0x49, 0x85, 0x8e, 0x6b, 0x49, 0x0b, 0x61 } }, +{ "\x2d\x43\x2a\x3a\xd3\xc6\x68\x31\xe9\x1e\xd8\x51\x3c\xd0\xee\xfd\xc9\x90\x15\x5b\xf4\xef\x78\x56\x62\x32\x6d\xbf\x73\x3f\x7e\x8e\x5f\xb1\x16\x47\xec\x0a\xc5\x78\xc9\x08\x30\x5e\x8b\x10\x98\xa8\x41\xc7\x05\x53\xb5\xc0\x0e\xb4\x42\x4f\x48\x94\x4d\x7c\x49\x75\x61\x13\x58\xf3\xeb\xd9\xb2\x46\x8e\xd9\x7b\xe4\x24\xdc\x40\x43\x53\xf6\x25\xbc\xc7\x3d\xb0\x8b\x11\x95\x30\xf3\x1c\xa7\xcb\x7f\x47\xf0\x23\x62\x24\xf5\xa5\x00\xcd\x95\x6e\x86\xde\x77\xd9\xb3\x12\xa1\xa9\xba\x7d\x2a\xd0\x40\x63\x08\xda\x80\xb4\x03\xf9\x8e\x25\xcb\xad\xb9\xec\x24\x10\x09\x18\x3f\xbb\xe7\x8a\x25\x58\xdc\x94\x4c\xc6\x72\x2c\x4c\xe2\x37\xcc\xab\xf8\xdf\xea\xd4\xc6\x89\x0f\x27\x29\x1a\x97\x2a\x67\xc6\x04\xdc\x18\xad\xfe\x2a\xb1\xa1\xeb\x7b\xae\x06\x27\x66\x5c\xd3\xe0", 185, { 0x75, 0x72, 0xbf, 0x88, 0x25, 0xbe, 0x77, 0x6b, 0x6f, 0x97, 0x84, 0xf0, 0x11, 0xa5, 0xc8, 0x22 } }, +{ "\x83\x40\xb5\x91\x5f\x27\x52\x19\x89\xcc\xaa\x77\xc9\x1f\x9a\x25\x71\x38\x7b\x0d\xcb\xd8\xe7\x2c\xb1\x97\x9b\xc2\x3c\xb0\x78\x33\x94\x65\xa4\x7e\xe7\x10\xcd\x57\x75\xc8\x8e\xe2\xc7\xac\xea\x0e\xff\xcf\xf5\x8c\x4b\xc0\x91\x6b\x74\xb4\x56\x52\x93\x52\x8b\x59\xe2\x1b\x51\x84\xb0\x75\xe0\xdc\x6e\x52\xe8\x2c\xe7\x81\x19\x55\x8d\x91\xbe\x4e\xee\x5e\x84\xbc\x46\x39\x59\x2a\x2d\xb8\x70\xe5\x71\x17\x60\x77\xfe\x49\x6c\xbe\xfa\x9f\xde\xa8\xed\x14\x8c\x8d\x1e\x32\x7c\x28\xf9\xa5\xa4\x33\xab\x5b\xca\x9f\xd0\x54\x8a\x6d\x44\x0b\x76\x2c\x16\x81\x57\x0f\x9b\xe2\x92\xaa\x9e\xd6\xa6\x49\xb5\x67\xd2\xed\xaf\x8a\xd3\xe4\x29\x4c\xcb\x04\x40\x9a\x3e\x83\x60\xad\x35\x76\x3b\x10\x85\xe4\xd6\x4f\x2a\x87\xbd\x3e\xcc\x1e\x57\xe3\x64\x71\x54\x01\xf8\xe3\x42\x42", 186, { 0xbb, 0x9a, 0xed, 0xe2, 0x33, 0x52, 0xb1, 0x0f, 0xad, 0xa6, 0x08, 0x76, 0x99, 0x43, 0xe4, 0x6e } }, +{ "\x82\xad\x3f\x00\xef\xbd\xc9\xaf\x43\x2a\xb1\xeb\xd9\x52\x2f\x1a\xc8\x92\x0e\xbe\x62\xa1\x08\x5a\xd6\x89\x2c\xfd\xf5\x43\x7b\x6f\x11\xef\x93\xf7\x01\xad\x83\xc7\x42\x1b\xbd\x06\x38\x6b\x29\x78\x92\x1f\x56\xcb\xcb\x64\xcb\x80\xcc\x09\x7c\x73\xae\x1a\x58\x09\x9e\x1d\xff\xf6\xda\xe8\x91\xa8\xd7\x1d\xa2\x54\x85\x44\x49\x9b\xaa\x83\x58\xd8\x6b\xfc\xa6\x09\xea\xc3\x87\x57\x08\x7a\x5d\x43\x4b\x8c\x48\x6f\xdb\x02\xf8\x07\xa7\x05\xa4\xca\xa5\xf1\x13\xb9\x36\x11\xd8\x5a\xa7\xfd\x9b\xa9\xd4\x8d\x91\x9c\xe7\x79\x0d\x52\x3e\x8f\x30\xd7\x6b\x8f\xbd\x96\x54\xa6\x07\x5c\x7b\x85\x0b\x04\x59\x1e\x9a\xc5\xe3\xfb\xaf\x14\x2e\x3b\xdf\x37\x2e\x29\xee\x68\x9a\x7a\x7d\xa2\xec\x23\xe1\x0b\x84\xd5\x10\xfd\xec\x16\xb5\xb2\x36\xfd\x63\x8c\x82\x8a\xe5\xff\x9c\x9f\xb4", 187, { 0xf7, 0xcb, 0x61, 0x06, 0xde, 0xbd, 0x8d, 0xcb, 0xa7, 0x96, 0x12, 0x6e, 0x8e, 0x63, 0x04, 0x6a } }, +{ "\x1c\xc2\x9f\x82\xba\x82\xa2\xf3\x43\xc2\x52\x6b\x18\xda\x65\x02\xa2\xdb\xb7\x94\xf6\xf3\x03\xf6\x24\xe8\x3e\x43\x1d\xc2\x90\x54\x3e\x86\xef\x4d\x7d\x1c\x5a\x54\x2f\x52\xb0\x5d\x73\xf9\x2a\x21\x3f\x2d\x7b\x2d\x05\xb3\x83\x17\x01\x7b\xaa\xcb\x22\x44\xdf\x03\x92\x5e\x2d\xd5\xe4\x8b\xf7\x66\xd9\xff\xd0\xbc\xcf\x87\xf9\xb2\xc7\xc6\x78\x04\x11\x99\xd1\x8a\x96\x9c\x64\x82\xc2\xc6\x62\x06\x0c\x30\x6d\x9c\x23\xf3\xcc\xec\xb6\x2e\x48\x8c\xe0\x27\xa6\xf8\x2f\x89\xc0\x9d\x50\xcb\x42\x14\x58\xb1\xfe\x6c\xb1\xec\xed\xa0\x9f\xdd\xc3\x27\x6e\x78\x2d\xab\x3a\x43\xaa\xd1\x5b\x7c\x03\x37\x6b\x5a\x68\x7c\xf4\x6c\x29\x78\xbb\x1e\x0e\x8c\xa3\x5b\x53\x15\x40\x4c\x43\xfa\xf9\x3d\x6f\x65\xd9\xa1\x8b\x8f\xf2\x2c\xe6\xb3\x6e\x1e\x85\x24\x33\xa0\xdb\x7a\x32\x46\x26\xe8", 188, { 0x32, 0x70, 0x9f, 0xcf, 0xca, 0x08, 0x40, 0x64, 0x9c, 0x92, 0xf1, 0x9d, 0xf0, 0x45, 0xa3, 0xf3 } }, +{ "\x4d\xb5\x68\xa9\xe3\x5e\x00\x99\xf9\x68\xe5\xe0\x06\xac\x80\xc9\x5b\xda\x23\xb1\x2d\xb9\x29\x1a\x40\x8b\xaa\xdf\x32\x8e\xdb\x82\x62\x9f\x01\xa1\x7b\xfa\x10\x88\xa1\x1c\xe4\xdf\x36\xc9\x1b\x84\x49\x2a\x8d\x74\x9b\x0e\x69\xe2\x50\x51\xed\x6a\x2f\x5a\xc1\x5f\x96\xbd\xf1\x40\xfd\x02\x85\x4a\x24\x7d\xbf\x27\xdc\x5c\xf1\xc4\x6f\xbf\xf8\x40\xae\x01\x59\x00\x95\x16\xf6\xdf\x9c\x0d\x6c\x83\x9d\xb4\x0c\xcb\x5c\x5a\x75\x64\xb8\xaf\xcb\x7b\x6d\xc8\x96\x8c\x84\x3f\x39\x59\x58\x78\x0c\xf7\x45\xfe\x19\x02\xee\x0b\x70\xf1\x2b\x26\x27\x84\x8e\xe7\xf2\x5a\x90\xd6\x5b\x9f\x5d\x72\x9e\xe2\x39\x4d\x23\x04\x8d\x54\x98\x4c\x92\x2d\xaa\x98\x99\xb9\x61\xaf\xf4\xb9\x16\xb1\x85\x8c\x11\xaf\xe1\x16\xc3\x57\x1f\xbd\x9c\xc8\x43\x8d\x8a\x84\x42\x7b\x10\x83\xb2\xc7\xfe\x64\x10", 189, { 0xcd, 0x2f, 0x08, 0x67, 0xde, 0x29, 0xd6, 0xbf, 0xf2, 0x95, 0x3e, 0xe6, 0x88, 0x73, 0x70, 0x43 } }, +{ "\x7a\xd3\xbf\xad\x0f\xab\x95\x35\x2e\xe6\xe9\xdd\x93\x58\x68\x29\x0e\x26\x43\x57\xa3\x43\x1e\x6b\xd1\x87\x20\xd8\xf0\x69\x2b\xc8\xb3\x59\x25\x08\xce\xbd\x75\x93\xb1\x85\x8a\xba\x71\x6d\x95\xec\xc8\xcf\x57\x28\x33\x22\x14\xfc\x39\x13\xa7\x38\xcc\x3e\xaf\x34\xc8\x89\xe7\xbb\x98\x1d\x94\x93\xf8\x02\x17\xaa\xd5\x56\xa2\xdf\x50\x2a\x07\x69\xe1\xf9\xac\xe8\x98\xc6\x9b\x06\x7f\xd1\xb6\xca\x1c\xf5\x08\x79\x13\xa1\x36\x29\xe7\x71\x14\xe3\xe1\x68\x53\x74\x09\xcc\x59\xd0\x51\x9f\x29\x24\xd2\xb5\x81\x77\x2d\x77\x03\xfc\x14\x32\x8b\xf6\xe1\x1c\x9f\x48\x63\xe5\x04\x98\xba\xf6\x6d\x1f\x58\x4a\x4f\x11\x27\xe5\xd0\xa3\xc9\xf4\xdd\xbd\xfb\x83\x5a\x3e\x13\xd5\x75\xe6\xa8\x63\x14\xe5\x50\x74\x6c\xfd\x84\x55\xb3\x56\xa0\x36\xed\xde\x07\xa1\xe3\x5a\x64\x97\x33\x0e\x0b\x49", 190, { 0x41, 0x35, 0xb4, 0x71, 0x1c, 0xe2, 0x04, 0x6c, 0x09, 0x30, 0x9e, 0x23, 0xaa, 0x6f, 0x9c, 0xed } }, +{ "\x80\x05\x7d\x70\xc9\xfe\x0a\x49\xd8\xf3\x91\x31\xd1\x47\x63\xd8\xea\x8b\x46\x25\x39\xed\x95\xa6\xa8\x3d\x85\xb2\x06\x9d\x82\x1e\x38\xc5\xb8\x98\x8d\xf0\xad\xa3\x2f\x67\x0b\x2f\xb4\xa8\x7c\xd4\xd4\x33\xae\xab\x36\xf0\x76\xc9\x63\x40\x10\x59\xdc\x9e\x84\x55\x46\xf2\x25\xe1\xc3\x72\x34\x44\x5d\x35\xa1\x83\x9c\x56\xf1\x9c\x37\xc1\x3b\x5c\xe7\x9d\x4c\xdd\x56\x56\xea\xa0\x37\x45\x36\x43\x6f\xff\x2a\xdf\x70\x37\x42\x00\xa7\x51\x38\x42\x0b\x84\xe7\x84\xd6\xaa\x51\xcc\x51\xa7\xbc\xb7\xc7\x74\xf7\x9b\x9b\xc7\xba\x3b\x76\x61\x2b\x25\x98\xf3\x7d\xac\x50\xae\xb3\x7e\x87\x66\x83\xe1\x76\x61\x55\x8e\x78\xc2\x6a\x2a\xf9\x8d\x1a\x5d\x8e\x56\x36\x91\x1f\x8b\x8c\x49\x3f\x5a\x88\x1b\x9c\x40\xf7\x4c\x92\x30\xe7\x06\xda\x5c\xab\x38\x5f\xa2\xfb\x0a\x31\x96\x37\xfc\x92\x28\xcc", 191, { 0xb0, 0x0c, 0x4f, 0x1c, 0x01, 0xbc, 0x03, 0x95, 0xe7, 0x9b, 0x96, 0x28, 0xa3, 0x74, 0xc6, 0x15 } }, +{ "\x9a\x2e\xf2\xaf\xde\x68\x21\x07\x22\xd0\xfd\xe7\xc0\xb0\x16\x39\x48\xc6\x0d\xb6\x5d\x0b\xfc\x11\x2c\xb2\x83\x34\x8a\x2c\x70\xa1\xa9\x68\x0a\xfb\x77\x19\xfa\x9e\x94\x2f\xd7\x68\xed\x67\x4c\x9b\xfa\xfe\xe8\xdb\x90\x81\x82\x51\x63\xc0\x47\xf2\x1c\xe0\x62\xda\x13\x90\x46\xd2\xaa\x54\x9b\xf1\x45\xfd\xc3\x5e\xe9\x39\x07\x33\x70\x46\x63\x7d\x66\xc2\xea\x60\x84\x9f\xd7\x57\xc7\x32\x32\x9a\x2b\x6a\x1c\x98\x09\x1d\xb7\xa3\x0a\x7e\xb4\xac\xc7\xab\x7a\x23\xff\x63\xf0\x00\x74\xd5\xe7\xe0\x62\x93\x27\x47\x9d\xa6\x14\x04\x46\xbb\xfd\xb2\x29\x7a\x02\x5a\xb6\xf7\x9f\x36\x9a\x41\xd9\x91\xfa\x18\x03\xca\x4c\xbd\x2d\x77\xd1\xe1\x2a\xa5\xb3\xbf\x3d\x3e\xb7\x45\x60\x84\x9e\x6d\x30\xb9\x1e\xab\x78\xe1\x78\x7f\x58\x9f\xb6\x2a\x11\x3c\x83\x7d\x70\xc7\xa6\xcc\xd5\x56\x1d\x02\xe0\x6a", 192, { 0xfd, 0xf1, 0x42, 0x20, 0xf2, 0xc8, 0x59, 0xfc, 0x92, 0xf4, 0x19, 0x99, 0x56, 0x5e, 0x8c, 0xc3 } }, +{ "\xd2\xce\xb7\x71\xfc\xfc\xf5\x64\x15\xde\x32\x91\x73\xe8\x2b\x73\x86\x5c\x8e\xbd\xad\x1a\x65\x76\xb5\x99\x1c\x3d\xee\xf3\x30\xae\xec\x1a\x76\xdd\xd7\x28\x06\xff\x6f\xd5\xc2\x29\xa1\x02\x86\x30\xbe\x72\xee\xaf\x5e\x98\xbe\x26\xd0\x8a\xf2\x3f\x3c\x15\x63\x2d\x58\xeb\x13\x2d\xc3\xf8\x15\x2e\x01\xd3\x1c\x8d\x14\x4f\x9e\xf9\xb3\x30\xa4\x76\x2a\xfa\x31\x7d\xcd\xe5\x4c\x40\x1a\xee\xac\x0a\x6a\x07\x00\xc5\x54\x6f\xd8\x96\x9f\x1c\x33\xa3\xe1\x54\xa6\xf4\xb8\x5a\x25\x77\xa4\x46\x71\x1d\x80\xee\x1e\x23\x9b\x00\x40\x6b\x77\x32\xb2\x08\x1d\x90\x02\xd9\x1b\xf4\xfc\x4c\x1c\x94\xd1\x44\x22\xb5\xe4\x15\x62\x7e\x32\xac\xbc\xe7\x5b\xcc\xd5\xd0\x51\x73\xd3\x2e\x9c\x5b\xb4\x60\x47\x9c\x4b\xa0\x6b\x6e\xd9\x94\x55\x0d\x44\x04\x57\xb5\xf6\xa7\x28\xcd\x55\x16\xf8\x20\xda\xe2\x15\x46\xd0", 193, { 0x88, 0x74, 0xaf, 0x07, 0x77, 0x96, 0x60, 0x6a, 0xa4, 0xf8, 0xd3, 0xfe, 0x51, 0x45, 0xb1, 0x39 } }, +{ "\xc1\x33\x21\xab\xe3\x5b\x83\x03\x63\x73\xed\x2b\xd9\x66\x72\x72\x0c\xef\xbb\xf6\xc4\x07\x23\x20\xbe\xe9\x02\xbf\xb9\xbe\x08\xc4\xae\xeb\xbf\x98\x1c\xf3\x32\x16\x81\x09\xac\x28\xe5\x36\x99\x01\x8f\x23\x8a\xf4\xdb\x84\x54\xf0\x24\x21\x57\x99\xdb\x82\xdc\x03\xb9\x37\x98\x0d\x11\xc1\x4e\x58\x3e\x21\x90\xe3\x3c\xfa\xa5\x44\x53\x65\x86\x85\xee\x51\x03\x99\x8a\x95\x03\x7a\xca\x94\xe8\xe0\xa7\x8c\x11\x9f\xc4\x7b\x79\x9e\xdf\xae\x7c\x6f\x64\xe7\xba\x90\x1c\x2a\x14\x3d\x02\x24\xd4\xf0\x36\x39\xe9\x77\x0b\x29\x4f\xaf\x3b\x5d\x8d\xe2\x3a\xd4\x58\xbb\xa7\xa5\x55\xe2\xdf\x30\xfc\x38\xac\xe5\x98\xb0\x1b\xb0\x6b\xc8\x6b\x00\xee\xa3\x21\x73\x35\xc5\x39\x20\x71\x6a\x77\x80\x90\x83\xdb\xf9\xff\x4e\x32\x09\x8f\x91\xc9\x0b\x75\x72\x3d\xa9\x6b\xf6\x6e\xdf\xf5\x14\x92\xa7\xbe\x75\x65\x47", 194, { 0x4a, 0x49, 0xa4, 0xc0, 0x34, 0x27, 0x8d, 0x1e, 0x19, 0x41, 0x7c, 0x92, 0xdc, 0x85, 0x81, 0xc3 } }, +{ "\x21\xcb\x7e\x33\xc3\xcb\xbd\xa0\x5d\xc8\xe1\xa6\x97\xee\x36\x10\x10\x17\x6b\xc4\x7a\x4d\x82\xc9\xe3\xdd\xe0\xfa\x0e\x14\x84\x46\xff\x99\x54\xa1\x96\x66\x93\x8b\x53\x65\x70\x3b\x38\xa3\xb7\x68\xcc\x33\xaa\xb3\x3b\xa2\xeb\xb4\x9b\x12\x90\x9f\x49\xf5\x59\x93\x72\x68\xfd\x7f\xae\x29\xa0\xb1\xc6\x37\x62\xfc\x96\x05\x11\x86\x0e\x5a\xfe\x2c\x52\xc8\xed\x92\x01\xc6\x26\xca\x93\x6c\xa8\x9f\xdc\xcb\x7d\x80\xad\xe7\x29\x04\x9a\x53\x3c\x1e\xd5\x67\x07\xde\x39\x1f\x6b\xe1\x63\x93\xcd\x57\xfb\x0f\x25\xaf\x11\xce\x36\xe1\xa1\x58\xd8\x57\x39\x75\x71\x79\xb2\xcc\x82\xd4\x19\x1d\x5d\xe6\xb2\x18\xf5\x88\x12\xd8\xce\xf8\x6b\xff\x13\x82\xe5\x6e\xc6\xcb\x27\xa1\x11\xba\xf4\xa6\xbc\x04\xf2\xb8\xb8\x52\x87\x7c\xd8\x10\xdc\xd7\x9f\xd4\x03\x6a\x34\x69\x35\xab\x72\x78\x34\xa1\x1c\xd2\xcf\x3c\x2e", 195, { 0x9c, 0x25, 0x37, 0x70, 0xb4, 0xce, 0x2c, 0x7d, 0xff, 0xd2, 0xda, 0x7d, 0x85, 0x7e, 0x25, 0xe8 } }, +{ "\x5c\x84\x4e\x4e\x98\x3f\x2a\x61\xcc\x41\xd8\x3a\xd1\x1c\xf1\x6e\x79\xda\x1d\x43\x9e\x3e\x27\xc7\xc3\x22\xba\xfc\x6a\xff\xbb\x31\xf2\x8b\x42\x6c\x29\x7d\x35\x03\x76\x6c\x83\x4a\x9c\xd5\xfb\x66\x2c\x3c\xc6\x40\x8a\x69\x87\x95\x99\xd3\x0e\x2b\x06\x1b\xb3\x1e\x2e\xaf\x55\x59\xad\x8f\xef\x20\x84\x2c\xd3\xc9\xe6\x6c\x87\x8b\x9f\xcb\x39\x6e\x22\x9b\xdf\x62\x2d\x6c\xef\x6c\x1b\x86\xb8\xfb\xc6\x93\x5c\x59\x16\x5a\x6a\x3d\x2b\xa6\x1c\x7d\x23\x45\x2a\xe0\x88\x2c\x48\x11\x59\xb8\x43\xb0\xb3\x0f\xb4\x83\x1c\xa5\x5e\xca\x6c\xda\x2a\xb0\x59\xc1\xbc\xdd\x9d\xfc\xb1\x28\xc6\xc3\x78\x6a\x9a\x03\xca\x6e\x24\xa3\xc7\x04\x5f\xe1\xae\x35\x7e\xdb\x39\x90\xd6\x2a\x93\xa3\x69\xa9\xf7\x86\x10\x53\xe6\x91\x44\x4a\x04\x2d\x89\xf4\x90\xc8\x77\x40\x7e\xe2\x66\x07\x33\x45\xb5\x8d\xdd\x51\xb7\x26\x6c\x75", 196, { 0xf4, 0x1a, 0xd3, 0x01, 0xe5, 0x69, 0x44, 0x94, 0x9b, 0x60, 0x1d, 0x3d, 0xbc, 0xc8, 0x4a, 0x94 } }, +{ "\x3b\xf5\x30\xba\xb7\xd0\x10\x79\x11\x3f\x64\x2d\x09\xa4\x70\x63\x45\x74\x7e\xce\xfa\xa3\x97\x77\x35\x1e\xdd\x11\xc4\x72\x88\x6a\xc3\x8a\x7b\xfe\xc6\x95\x82\xa6\xa0\x06\x2b\x6d\xce\xb5\x3e\x83\x83\x23\xda\x4b\x51\xda\x2d\x8f\x71\xf3\xcf\xd3\xaf\xb2\xbc\xc7\xf5\x4b\xec\xd6\x72\xc8\x91\xdb\x66\x02\xec\xf3\x8d\xcc\xcc\x6d\x25\x30\xa5\xde\x9e\xd1\x49\x52\xde\x6f\x45\x9d\x2d\x89\xdb\xcf\xc4\x1d\x97\xc5\xed\x8b\x90\xdc\xd6\x98\x3d\xc1\xf8\x8e\xf1\x64\x1f\x80\xf4\x0b\x15\xaa\x40\x83\xef\xf7\xd5\x71\xf3\x9d\xb9\xc6\x24\xe4\x90\x50\x6d\x04\xd3\x6e\x66\x2b\xb0\xdc\xc5\x9d\x7e\xac\x64\xf6\xdb\x56\xea\x8b\x65\xe6\x19\xef\x11\x53\xb4\x91\x2b\xf0\x0b\x82\xea\xfc\x24\x55\xaf\x54\x88\x20\xda\x48\xa7\x9e\x49\x8a\xe8\x76\x6f\x42\x51\x97\x0c\x3f\xd0\xba\x8e\x49\x24\x09\x04\x92\x6b\xde\xbb\x4a\x48", 197, { 0xe0, 0x17, 0x3a, 0x13, 0x7d, 0xcc, 0xf3, 0x56, 0x2a, 0xf8, 0x56, 0x04, 0xdb, 0xcf, 0x6b, 0x4a } }, +{ "\xa4\x77\x52\xb0\xda\x4f\x08\x52\x36\x26\x41\xa1\xe6\xc2\x55\x7f\xf1\x8a\x53\x87\xbc\xe0\x55\xf7\xa9\x19\xef\x39\xda\x15\xc1\x0c\x13\x80\x2c\x53\xbe\xa4\x21\x7a\x07\xe8\x15\x81\x27\xe8\x11\xa7\xbf\x32\xe5\xb3\x5a\x9b\x7c\xe1\x15\x3d\x4b\x68\x5b\x0e\xe4\xa4\xc8\x1d\xa7\xe5\x2f\x6b\x97\xd4\xb7\x63\x4a\x7c\x20\xf7\xfa\xfc\x23\x59\xba\xc8\xf8\x53\xc2\x97\xf1\x44\xeb\xed\x44\xb8\x36\x45\xe6\xa2\x86\xda\x92\x38\x6e\x12\xe8\x6b\x25\x88\xb3\x02\x96\xb4\x43\x52\x94\x39\xf9\x9c\x2b\xcc\xe1\x03\x12\xbc\x79\x28\x3c\x21\x90\x64\x8d\xa5\x4a\xa1\xaa\xea\x40\xd6\xe9\x97\xc4\x1d\x68\x02\x42\x72\x39\x7b\xc2\x0a\xbb\x33\x89\x4d\x04\xc8\xdf\x72\x7a\x6e\xec\xb6\x81\xbb\xbc\x39\x4e\x0f\x62\x75\xda\x9d\x38\x5b\xf3\x1b\x44\x0c\x6c\x02\xb6\x31\x75\x82\x8d\xf7\x05\x06\x5a\xaa\x73\x5f\x1d\xed\x25\x8f\x4b\x93", 198, { 0x1b, 0xae, 0x3b, 0x86, 0xbc, 0x4d, 0x77, 0x02, 0x5a, 0x90, 0x72, 0xf2, 0x23, 0x18, 0x3b, 0x53 } }, +{ "\x5f\x35\xf1\x1e\x3d\x90\xf2\xd2\xbc\x31\x6c\x74\xf2\x42\x39\xa4\x5e\x6c\x92\xd4\x5a\x6a\xcd\xe4\xad\x28\x47\x5c\x3d\x97\x5c\x45\xe1\x10\x93\xa4\x55\x62\xd7\x94\x46\x7a\xe0\xff\x8e\xae\xb1\xf9\x7a\xa6\x3a\xb9\x46\xe7\x1d\x34\xaa\xfd\x8d\x57\x8d\x45\x53\xe1\xd8\x54\xeb\xdc\x66\x07\xcb\xb6\x17\x28\xc3\x00\x04\xba\x7f\xc2\xcc\xe2\x2a\x78\x0d\x72\x2d\xae\xef\x12\x15\x33\xda\x0d\x93\xfd\x47\xb6\x9c\x99\xb4\x75\xb1\x4c\xb1\x71\x39\xcc\x18\xdb\x0a\x94\x5a\xd5\x06\xe8\xf3\xfe\xe2\x65\xff\x9c\x02\x44\xe7\x64\x80\x2b\x34\xe8\x4c\xaf\x84\x9e\x6d\x6b\x99\x88\x66\xb6\x8f\x85\xb3\x03\x26\x34\x73\xda\x3d\x81\x1f\x6f\x60\xcd\x78\xdc\x78\xbe\x7f\x00\xa1\xa0\x9e\xf3\x19\x76\xe4\x25\x53\xa2\x6e\x12\x2b\x2c\xe1\xa3\x35\xb2\x13\x25\x2e\xed\xc9\xde\x94\xdb\x9b\x51\x51\x8e\xf4\x10\x93\x91\x36\x39\xb7\xf2\xfa", 199, { 0xa3, 0xff, 0x9e, 0xb2, 0xc4, 0x17, 0xce, 0xca, 0xb4, 0xda, 0x08, 0x92, 0xb0, 0x6b, 0xf7, 0x47 } }, +{ "\x8e\x63\xf1\x75\x35\xb3\x43\xf6\x08\x8a\x03\x8b\x9a\x0b\x36\xc4\xc8\x20\xf9\x8f\xf7\x37\x4a\x42\xef\x0d\x6f\xb8\x53\xa2\x06\x92\xbc\x4c\xaa\x9f\x72\xe8\x3f\x56\xc6\x2b\xdb\x80\x0f\x16\x51\xf2\x3f\x88\x5b\x78\x21\xed\x63\xce\x31\x15\xee\xc8\x17\x1f\xa6\x91\xc2\x94\x02\x10\x1e\x90\x94\x66\x71\x1a\xef\x94\x57\x95\x32\x3a\x58\x50\x36\x7a\x23\x38\x50\xfb\x6a\xad\xc3\x09\x59\x71\xc5\xda\xb3\xbd\x2c\xec\x8c\x6e\xb5\x89\x9d\x5c\xf1\x6c\x47\xcb\xcd\x7e\x27\xfb\xbc\xb9\x52\xda\x83\x2e\x2d\xda\xa0\x21\xec\xdd\x58\x52\xa5\x4b\x5c\x57\x10\x46\x17\x24\xdd\xf5\x97\xad\xb2\xfd\x15\xa2\xc0\x0e\x22\x59\x01\x99\x71\xca\x10\x9f\x3b\xb3\xa4\xa5\x52\xdc\xaa\xc4\xc6\x75\xff\xdd\x2e\x9b\xc7\xe9\x94\xf9\x6d\x6e\xff\x8b\x37\x0d\x9d\x7e\x84\x38\x8d\x34\xa5\x02\x47\x63\x56\x0f\xa9\x5d\xd8\xaa\x9e\x6a\xac\xf5\x6d\x51", 200, { 0x6c, 0x74, 0x72, 0x4a, 0xa1, 0xeb, 0x2f, 0xe2, 0x8e, 0x27, 0xa4, 0xd0, 0xba, 0xf2, 0xf5, 0x30 } }, +{ "\xed\x3b\x9c\xf6\x4b\x62\x7e\x1d\xa0\x7c\x60\x4d\x30\x7c\x4c\xcf\x82\x05\x78\xd6\xd5\x5e\x4e\xb8\x41\x82\x19\x5a\x6c\x55\x49\xab\xe5\xf0\x63\x47\x20\x1d\x88\x3b\x0e\xde\x9f\xe8\x59\x28\x22\x00\x39\xad\x82\xae\xf6\xd7\x38\xd2\xfa\xd0\x69\x6a\x92\xbe\x35\x0c\x41\x0c\x9d\x8f\xc1\xe4\x0e\xca\x97\xb9\x8e\x74\x51\x00\x82\x2a\x5f\xfe\x19\x90\x8c\xbc\x59\x8f\x17\x18\xc4\xbc\x72\xf6\xa6\xd8\x96\x93\xfe\x74\x01\xfa\x07\xad\x4d\x8f\x62\x15\x6e\xc8\xe1\xb2\x88\xfc\xf2\x20\x6b\x53\xa6\xd1\xac\xde\x5d\x75\x61\xc0\x10\x75\x78\x89\x3b\x98\xb4\xa3\x65\xc9\x46\xe5\x4d\xf0\x04\x45\xb3\xfc\x48\xaa\xc0\x02\x68\xe0\x12\x7f\xcd\xa5\x68\xb9\xb2\xe0\xe7\x44\x7b\xf1\x07\xa1\xaf\x23\x1d\x01\x94\x3e\x85\x27\x66\x3a\x6b\x6b\x33\x0e\x36\xda\x56\xa5\x93\x7b\x8e\xf2\x19\xad\xba\x1a\x9e\xac\x33\xd0\x16\x32\xc6\xbf\x22\x3a\x4c", 201, { 0xfc, 0xfb, 0x80, 0xef, 0x32, 0xd8, 0x1e, 0x33, 0xb0, 0x18, 0xbb, 0xfe, 0x11, 0x1f, 0x3a, 0x1f } }, +{ "\x20\x3d\xdf\xe8\x6b\x7e\x63\xdd\x2a\x0a\x4c\x0a\xe8\x1a\xa9\x02\x49\xa5\x73\xcc\x33\xaa\x0e\x34\x2a\x1c\xef\xcc\xba\x69\x57\x82\x0d\xa9\x3d\xdf\x9c\x60\x49\xda\x02\xf0\xfd\x57\xec\x9e\xee\x3f\x2d\x3e\x30\x3c\xee\x7e\xd1\x11\x03\xcd\x7b\x95\x58\xe6\x3d\x4a\x8a\xfd\x63\x9e\x92\x84\x81\xbd\x9c\x9a\x8f\x11\xf6\x11\x2e\x57\x24\x1a\x09\x5f\x10\x8f\x57\x60\x5e\xdd\x7c\xf5\xde\x8c\xcf\xb8\x1b\x6d\x77\x7a\x10\x5f\x6e\x1c\xfa\xbd\xa7\x0d\x49\x68\x4c\x60\xb0\x6c\x20\x88\x5b\x51\x04\xb4\x40\x01\x95\xc1\x8f\x51\xf2\xe0\x43\x2d\x9b\xc6\xda\x65\x75\x89\x21\x0e\xea\x1e\x29\x96\x2d\x6c\x56\x68\x9b\x0c\x95\x38\x3d\xa0\xad\xeb\x6a\xcd\xaf\x26\x89\xd6\x88\x72\xf5\xd6\xb5\x09\xf9\x9a\x15\x40\xfa\x19\xda\x90\xb4\x90\x99\x42\x9c\x3e\x82\xb7\x65\xb9\xa9\x51\x9f\xec\x82\x02\x79\xae\x6c\x6f\xa7\xff\x64\xc0\x5f\xe1\xda\x07", 202, { 0xc3, 0xe1, 0xb0, 0x79, 0x72, 0x94, 0x8c, 0x0f, 0xa0, 0xfa, 0xa3, 0x43, 0x20, 0xc6, 0x93, 0x87 } }, +{ "\x7d\xd1\xa0\x4a\xc6\xe0\xff\x2e\x49\x73\xe4\x42\xe1\x93\x38\xe6\xd8\xf2\x4d\xd7\xa6\x7b\x74\x58\xd7\x94\xab\xfd\x0a\xf3\x73\x17\x15\x1a\xc0\xb7\x46\x70\x0a\x61\xc5\xfe\x81\x4f\x15\xc3\x5d\x5e\xb9\xb4\x53\x99\xf3\x53\x23\x61\xa7\xea\x4e\x36\x5f\x64\xe6\x24\x68\xc9\x7d\xcc\x19\x54\x3f\x0e\x33\x33\x1c\x50\x64\xdb\x1d\x6e\xe6\x05\xd8\x3e\x44\x48\xff\xbe\x3d\x54\x12\xdc\xc1\xc8\x35\xe2\x18\xb1\x1c\x7d\x22\xa0\x22\x68\xb9\x67\x79\xba\x32\x6f\x7c\xc8\x03\xb9\x21\xb8\x7e\x6f\x8a\xa3\xbc\x26\xba\x66\x95\xb3\x64\x06\xcb\xa7\xdf\xbd\x46\x68\x37\xa5\x7a\xed\x5d\x00\xe4\x15\x7e\x22\xb4\xa5\x71\xfb\x85\xdd\x49\x45\x47\xb5\x0a\x46\x3e\xb9\x79\x42\x23\x7e\x0c\x81\x68\xc0\x01\xf8\x99\x19\x8b\x97\xde\x60\x26\x2f\x9d\x9c\x0c\xfd\x3c\xa4\xc0\xd7\x04\x54\xc7\xf1\x21\x6e\x76\x4c\xc6\x0a\xe7\xbd\x6d\xbb\x05\x96\x3c\x40\xc7", 203, { 0x8d, 0x91, 0xba, 0x03, 0xb1, 0xc8, 0xaa, 0x70, 0xf9, 0x6c, 0x1c, 0x25, 0xa2, 0x93, 0xa9, 0x8d } }, +{ "\xf3\x83\xe4\x7a\xa2\x62\x73\x36\xb0\x88\xd9\x72\x8c\x16\x58\xb4\xdb\xa1\x65\x61\xd7\x56\x20\xb2\x64\x39\x6f\xc7\xb1\x86\xb6\xd6\x87\x38\x34\x7c\x32\xa7\xfd\x34\x08\x4c\x90\xe5\x9a\xa1\x14\x95\x77\x23\x34\x3c\x97\x79\x93\xb3\x6b\xaf\xee\xcb\x7f\x9b\xcd\x7a\xc8\x60\xe6\x31\x90\x10\x0e\x49\xfb\x6d\xdc\x9b\x35\xc8\xdc\x2e\x3a\x0b\x6d\x0b\x41\xd2\x38\x2d\xc6\xb3\x4d\x95\x32\x9e\xdc\x79\x2a\x60\x8c\x9c\x71\x42\x7b\xb9\x7b\xce\xd3\x19\x8f\xb1\x05\x44\x97\xbc\xa5\xd4\x87\x05\xe2\x65\x68\x2a\xa0\xa8\x00\xb5\x34\x97\x20\x9b\xbb\xc3\x8a\xdf\x17\xc8\x7c\x54\x88\xe3\xdd\x7f\xe3\x9a\x03\x9a\x71\x99\x1f\xb5\x66\x9d\x46\xf8\xfb\x89\x1c\x03\x2b\x96\x1f\x76\x08\xa8\x8d\x8c\xb7\xbb\xf3\xe2\x0e\x7c\x54\x56\xc8\xf4\xf2\x0b\x63\x5f\xbc\x88\x97\x1b\x53\x00\x72\xbc\xbb\xac\x14\x3c\x9b\x54\x05\x50\x30\xee\x2e\xd5\xd4\x5d\x7b\x69", 204, { 0xf3, 0x73, 0x23, 0x57, 0xe5, 0x6b, 0xc8, 0xaa, 0x91, 0xf1, 0x46, 0x79, 0x25, 0xaa, 0x4f, 0x9f } }, +{ "\x27\x5a\x0a\x17\xd7\x70\x10\x2a\x12\x21\x49\x22\x85\x26\x19\xc5\x0f\xd4\x44\x4c\x07\x9a\x47\xbe\x26\xa7\x51\x5b\x13\xa8\xe1\x2e\x8a\xaf\xfd\xc6\x28\x2f\x0c\xfe\xd5\x24\x51\xf7\xce\x50\x04\x27\x4d\x9f\x0e\x8b\xd8\xac\x62\xf8\x23\x5c\xf3\x8f\xa3\xa8\x55\x4f\xb1\x79\xf4\xc5\x56\xac\xeb\xde\xb9\x35\x82\xdd\x22\x5f\x47\x67\xaa\x31\xc7\xbb\x82\xed\xe9\x00\xdc\xb2\xe8\xb7\x79\x41\xeb\x50\xd0\xdc\x43\xd8\xd8\x4a\x40\xcf\x72\xf8\xb0\x18\x76\x39\xf5\x09\x59\xae\xc2\xa2\x78\xc1\x72\xdb\x03\x4b\x05\x16\x89\x56\xb7\xb4\x1b\xfc\x3f\xc4\x20\x6e\xa1\xd5\xb5\x11\xb0\xec\xbe\xc2\x24\x91\x8e\x3a\x53\x04\x2f\x8d\x90\x8d\x4e\xcd\x1d\xf1\xc6\xcb\xcd\x00\xc7\xfd\x3b\x4c\xa3\x7b\xa1\xf4\x35\x24\x56\x9e\xee\xdd\xe6\x83\x7d\xf9\xcf\xa3\x1a\xb5\xd6\x1a\x70\xda\x04\x8b\x25\x85\x41\xb8\x07\x03\x8b\x34\xd4\xd6\xd3\x2f\xa6\xd5\x74\x71\xf9", 205, { 0x12, 0xe3, 0xc8, 0xd7, 0x9f, 0xe5, 0x62, 0x5e, 0xc1, 0x04, 0xed, 0xd2, 0x54, 0xf5, 0x06, 0xd8 } }, +{ "\x6f\x51\x62\x5a\x10\x89\x45\xae\x9c\xda\x85\x1d\x18\x8f\x28\x99\x68\x27\x60\x0f\x33\x84\x40\x28\xe2\xcc\x8c\xbc\xc8\xe0\xa9\xd4\x5c\x77\xb3\x5a\xa1\xd6\xad\x5f\xa6\x2e\xd3\x09\x29\x92\x0c\x17\x57\x93\x7c\x13\xaf\x7a\x35\x13\x04\x21\x0d\x2b\xa1\x6e\x8a\x72\x86\x6d\xfa\xaf\xd1\x09\xa0\xa1\x38\x67\x08\xe8\xb3\xe0\x7c\x93\x37\x98\x8f\x47\x9c\xbf\xd6\x08\xa0\x64\xb7\xa7\x04\xf1\x59\xc8\xd4\x47\xbb\x8f\xc4\x77\xe0\xe7\xb6\x19\x28\x6f\x58\x4d\xbb\x01\xeb\x4c\x1e\xdf\x1e\xa9\xe7\x7c\x18\x2a\x8d\xe5\x95\x3d\x59\xca\x28\x19\x79\x2d\x9e\x72\x33\xa6\x83\xd8\x37\x50\xbe\xad\x0d\x54\x57\xc1\xad\x10\x5a\x8c\x2d\xe3\xd3\x07\x95\x97\xf8\x27\xce\x6c\x66\xf7\xb9\xbd\x84\x51\x5d\x51\x04\x38\x38\x41\x88\xd5\xb6\x81\x61\x0d\xbf\x0c\x72\xbb\x6b\xb0\x33\x8f\xd1\x73\xd1\x82\xfd\xa1\x73\xf5\xff\x73\x98\x65\x20\x5e\x9c\xcd\x30\xf5\x5a\x99", 206, { 0xa3, 0xaf, 0xd7, 0xe6, 0xa2, 0xce, 0x1a, 0x98, 0x7a, 0x71, 0xe1, 0xab, 0xf9, 0xce, 0x37, 0xb6 } }, +{ "\xfb\x7b\xea\x42\xda\x09\x8b\x8a\x65\x58\x9c\x56\x46\x2c\xc5\x23\x29\x5e\x33\x26\xcf\x84\x00\x04\x42\x3e\xb0\x2b\x23\x20\xd7\xcb\x1f\x37\xd9\x75\x80\x3a\xca\x4e\xe0\x4f\x73\xef\xf8\x76\x76\xdd\x96\x96\x89\xa0\xad\x22\xde\x82\x86\x68\xa3\xe6\x15\x76\xa5\x42\x66\xa9\x10\xba\x36\xd3\x51\x5a\x9e\x08\x1c\xf0\xea\x06\x89\x84\x88\x3e\x59\x75\x1c\x83\x57\x32\xb1\x4e\xda\x91\x09\xab\x67\xcf\x15\xc4\x73\x25\x80\x08\x45\x03\x65\xf8\xfa\xec\x22\x8e\xa3\xed\x44\x4a\x89\xbb\xa1\xda\x90\x68\x85\x65\xb9\xc2\x04\x74\xc1\x48\x6f\x7d\xe7\xca\xe1\x0e\xcb\x9c\xf9\x93\x72\x76\xa2\xc4\x66\xeb\x0d\xad\xfa\x84\xc0\x5b\xab\x79\xc8\x20\xa2\x0b\x0a\x84\x57\x81\xb8\xc8\x4f\xbc\xdf\x17\x05\x79\x1c\x4c\xe7\x23\x6f\x5a\x77\x53\x27\x5c\x92\xe5\xfd\x3a\xce\xb8\x3d\xf4\xfc\x01\x1f\x8e\xcd\x4c\x34\x99\x90\x11\xfc\x59\x19\xef\x94\x98\xbe\x88\x8c\x06\x7b", 207, { 0x35, 0xc8, 0x5d, 0xea, 0xdd, 0x9b, 0x4e, 0xe1, 0x1d, 0x35, 0x19, 0x7e, 0x3c, 0xe6, 0xb8, 0x29 } }, +{ "\xf8\xd7\x4b\x35\xf2\xdc\xab\x1b\x79\xa9\x55\x29\x39\x47\x48\xc6\x80\x28\xe3\x8e\xdc\xbd\x07\x2a\x51\x24\xea\x5a\x37\xff\x7b\x14\xae\x60\x6d\xc6\xbf\xe0\xe3\xb8\x11\xcf\xb6\x8d\x45\x85\x66\xe8\xee\xd7\x9a\x2c\x30\xa5\x55\x5b\xf4\x91\xb8\x20\xc5\xca\x6e\xe8\x4a\x06\xb7\x2a\x60\x8e\x15\xc8\xd4\x73\x8d\x8d\xba\xde\x9a\xd6\x6c\x85\xb4\x4e\x22\x3a\x77\xd2\x2b\x9d\x74\x73\xc6\xf2\x91\x99\x9f\x0d\x1d\x44\xe9\x6a\x74\x6e\x14\x59\x4b\x8d\x2c\x56\x99\x35\xce\x77\x23\xd9\xc7\xfe\xa2\xb1\x4a\x0e\x92\xb8\xce\x7b\x9a\xcd\x82\xba\x93\xf9\x6e\xf7\x36\xd0\x27\x46\x67\xf0\x2e\xf1\x18\xa7\xe7\xf0\xdb\xb1\x31\x76\x08\x1e\xa6\xa8\x87\x52\x70\x68\x3b\x26\xc6\x50\x0c\x2d\x02\xbb\x8e\x11\x61\xfd\x53\x1b\x56\xb2\xca\xd1\x8b\x34\xd2\xb9\x75\x26\xdf\x3c\x92\x2d\xc7\xa6\x42\xbf\x2a\x4a\x40\x13\x7c\xc2\xbb\x38\xb1\x54\x15\x42\x83\x71\x37\x9f\x63\x57", 208, { 0xdf, 0xbc, 0x18, 0xbe, 0xc2, 0x94, 0xd5, 0x70, 0x1c, 0xe7, 0x30, 0xe9, 0x86, 0xc7, 0x7f, 0x08 } }, +{ "\x8f\x87\xfa\xd6\xa7\x92\x5a\x2f\x63\x63\xc6\x17\xd7\x82\x1a\xdc\xc2\x48\xd8\x9f\xab\xf3\xd1\xbf\x97\xd9\x6d\x57\x64\xba\x97\xdd\xc6\x2e\x47\xeb\xdb\x3d\xad\x1a\x6c\x0d\xf7\x0a\xc2\xb6\xbf\x7f\x23\x32\x14\xa6\xe8\x70\x24\x75\x3c\x87\x83\x30\x73\x07\x1a\x07\x04\x6c\xaf\xdd\x25\xac\x0c\x23\x01\xf0\xcf\xe3\x99\x5f\xce\xd9\x34\x15\x24\xbb\x84\x32\xdc\x9a\x57\x0f\x39\x60\xf6\x8c\xa0\x79\x1e\x85\x23\x8f\x98\x63\xab\x6d\x77\xce\xc1\x05\xee\x80\xf9\x8d\xcb\x35\xfb\xc3\x94\xbf\x2f\x52\x3d\x35\x05\x4d\x83\x4b\xde\xd8\xe7\xbd\x9a\xe6\x4a\xe6\xbf\x1c\x22\x6d\x42\xd4\x56\x1e\xf6\x3f\xbc\xd7\x8e\xa2\x2c\x99\x50\xc1\x41\xbe\x59\x59\xac\x4a\x87\xc6\x34\x59\x06\xc5\x4e\xb8\x7a\x54\x54\x90\xc6\xb6\x65\x3d\x77\x92\xda\x3e\xd1\x3b\x60\x45\x74\x0b\xb7\x6d\xa9\xe8\x06\x8b\x4f\xe8\xd8\x9c\x5c\x11\xb7\x5e\x12\x39\x63\xfc\xc1\x0c\xaf\xe1\x32\x2c\xf9", 209, { 0xb0, 0xbf, 0x87, 0x74, 0x91, 0x48, 0xb8, 0x57, 0xf4, 0xbb, 0xfa, 0x00, 0xec, 0x90, 0x0a, 0x39 } }, +{ "\xae\xb7\x73\x44\x46\xcd\x54\xf4\x06\x6b\x5f\x25\x12\xea\xe3\xa8\xcb\x90\xad\x9a\x5c\xba\xef\xa3\x74\xa6\x3c\xc8\x0e\xda\xb0\xee\x6b\x35\x2d\xec\x22\x90\xc0\x4b\x4e\x11\x21\x9d\xe5\x0c\x59\x77\x28\x95\x7e\x0c\x36\xa6\x9a\x67\xbc\xe9\xaa\x44\xc7\x24\xc2\x8c\xba\x3f\x4e\x6c\x5b\xf2\x73\x11\x07\x0f\x93\x01\x06\x69\xef\x19\xf9\x60\x68\x1f\x70\x0a\x5e\x03\x98\x00\xb9\xb7\x11\xc2\x06\xa8\xde\xc8\xb9\xd7\x76\x26\x91\x99\xf7\xda\x19\xe7\x7a\xb6\x4a\x63\x81\xe4\x4e\xe8\x8d\x1b\x5f\xcc\xcd\x5d\xce\xb5\xf0\x6a\x20\x14\x1c\xc5\x52\x43\xf7\x60\x3e\x37\xe2\xe6\x16\xe2\x45\xa5\x0c\x28\x05\x17\x14\x7b\x12\x0b\xc1\x15\x1e\x75\x4c\xd1\x68\xce\xb4\xa7\xb6\x29\xff\xc2\x61\xd4\x9e\x40\x8a\xa7\xee\x85\x6b\xec\xdb\x3c\xc8\xeb\x9f\xec\x83\x10\xa8\x32\x4f\xbb\x98\xa1\x7d\xa4\x66\x33\xf2\xe9\xa2\x6a\x3a\xb6\xd5\x07\xb5\x90\x06\x66\xef\x3e\x59\x74\x0e\x54", 210, { 0x3f, 0x07, 0x92, 0x47, 0x77, 0x40, 0x22, 0x89, 0xaf, 0x63, 0xa4, 0x03, 0x20, 0xa2, 0x2a, 0x9e } }, +{ "\xd3\x4e\x64\x5d\x38\x78\x24\xa4\x15\xb7\x32\x9f\xda\x8c\x13\xf9\x1f\x4d\x04\x3b\x07\xe1\x26\x16\xc2\x17\xd6\x4f\x2c\xa4\x1b\x47\x93\xb7\x39\x26\x96\x3b\x62\xa4\x28\xa8\x8c\x74\xb4\x86\x5e\x4d\x5b\x80\x44\x95\x58\x21\xa2\xac\x85\x2d\x24\xd3\xf7\x9e\x34\xb8\xc3\x3a\x85\x9f\xe4\xcd\xcc\x2e\x35\x09\x8f\xd5\x98\xf6\x15\xd8\x39\x17\x7d\xfa\xed\x1b\xeb\xc8\xb4\x3c\xdd\x7f\x5d\x38\x9c\x9b\x49\xea\xcd\xfd\x47\x85\x27\xb7\x9f\x6c\x3f\x77\x2a\xb0\x7f\x8f\x9e\x26\x35\x9d\xe8\x24\xc7\xdc\xb2\xd9\x05\x05\x04\x46\x97\xe3\x06\xdd\x95\x72\xe3\xb4\x35\xb3\xca\x66\x9f\x0f\x0e\x86\xdd\x65\x6e\xc1\xee\xb2\x6e\x8f\xf9\x5c\xe4\x95\x9f\x1b\x8f\x9b\x69\x84\xe0\x25\x61\x34\xdd\xb0\xbc\x95\x1b\x8b\xb4\x50\xe9\x4f\x74\x4f\x8c\xfc\x2d\x6d\xa4\xb1\x46\xbd\xad\x07\xb0\x74\xa1\x0b\x57\x74\xbb\xd7\xb4\x76\x57\xcc\x7f\xd2\xf5\x6e\x82\xee\x5d\xdc\x89\x41\xdc\xea\x76", 211, { 0xb4, 0xe4, 0x99, 0x88, 0x69, 0xa4, 0xd3, 0x42, 0x48, 0xfd, 0x35, 0x33, 0xd4, 0xa3, 0x66, 0x48 } }, +{ "\x03\xac\xdd\x71\x73\x72\xc2\x3c\xc4\xe0\x6b\xa4\xa5\x7b\x07\x13\x6c\x77\x5d\x43\xde\xbe\xa5\x0d\x9d\x0f\x03\x5f\x2e\x43\xa1\x4c\xa6\xab\x67\x3e\xf1\x96\x5a\x47\xbf\xef\x8e\x94\x0c\x02\xc9\x02\x4a\x5f\xb6\xcb\x2c\xd7\xc3\x59\x11\xa3\x98\x3b\x0c\xa5\x33\x35\x8c\xc6\xa4\x71\xad\x7e\x62\xd4\x1a\x72\x49\x6c\x9c\x37\x31\x05\x44\x34\x2c\xdb\x31\xa6\x5b\x69\xff\xbe\x6d\x60\xcc\xe5\xb6\xb3\xe8\x1f\xe8\xcf\x18\x8d\x70\xe8\x87\x0c\x6f\x6f\x4a\xfc\x53\xa0\x8e\x1b\x12\x37\x61\x8f\x03\x42\x19\x02\x59\x12\x65\xe7\x3c\x4b\xee\xdc\x85\x1b\xa9\x28\x16\x87\xbc\x63\xd4\xe1\x0a\x35\x43\x56\x5d\x36\xbc\xa3\x2f\xf5\x4d\xe8\x15\x15\x2d\x95\xc9\x91\xda\x81\xd2\x1f\xd1\x19\xd2\xb2\xea\xb5\x6c\x1a\x4d\x06\xcf\xc7\x14\xac\xe4\xab\x7f\xe4\x10\x3d\xce\x5f\xa6\x99\xbf\x2d\xec\xc4\xa4\xd8\xc8\x0e\x20\x8e\x08\x90\x7e\x76\x4b\xd5\xad\x23\x8e\x95\xdc\x26\x57\x9d\xae\xbd", 212, { 0xba, 0xe8, 0x47, 0x79, 0xba, 0x43, 0xe2, 0x04, 0xf1, 0x5a, 0x99, 0xb4, 0x4d, 0xf6, 0x3b, 0x7c } }, +{ "\x78\xca\x1a\xaa\x80\x33\xe3\x1f\xc4\x67\xae\xd5\x05\xcb\xc5\x3c\xbe\x26\x67\xcd\x0d\x38\xc9\x7b\x3b\x84\xae\x48\xea\x2f\x9e\xf3\xda\x01\xc6\xce\x57\x88\x6b\xae\x43\x5b\x0c\xfd\xbc\x7c\x14\xe9\x69\xd7\x39\xbf\x66\xe7\x74\x52\xc9\x78\x9d\x95\xd1\x87\xa2\x49\xab\x45\x63\xcf\xe0\x3a\x2e\x1f\x5e\x87\xd2\xd1\x20\x44\x62\x59\x7d\x08\x88\x50\x0b\x86\x83\xed\x2d\x54\xbe\x92\x40\xc7\x0e\x83\x5e\xfb\x88\xb1\xcd\xef\xfd\xb5\x08\xcd\x14\xd8\x67\x46\x02\x4e\x6d\x1c\xe8\x84\xae\xb9\xc8\x8f\x5b\xfd\x25\xc3\x6c\x15\x37\x65\x68\x86\xc8\x78\xd4\x4a\xae\xb3\x36\x11\xe5\x94\xc4\xa8\x48\x8e\xae\x77\xec\x5e\x05\x24\x1a\x7c\x46\x56\xe6\xac\x87\x94\x70\xb3\x3d\x4b\xb7\x27\xa8\xee\x15\x60\xdc\x38\x5b\x8b\x6c\x8d\x89\xdd\xb4\x7e\x2a\xe3\xc3\x6c\x4a\xf8\xe3\x43\x15\xd1\xc7\x68\x0e\x32\x51\xae\xe8\xc3\xfd\x81\x05\xfd\xed\x25\x88\x3f\x91\x19\x19\xfd\xf2\x95\x35\x17\x9c", 213, { 0x36, 0x5a, 0x4c, 0xec, 0xc3, 0x99, 0x8e, 0x50, 0xdb, 0xee, 0x2e, 0xc0, 0x07, 0x66, 0x78, 0x82 } }, +{ "\x33\x2e\x48\x26\xaa\xc6\xb5\x5f\xb4\x64\xa5\x17\x12\xf1\x50\x87\xa6\x52\xd0\x5e\xbd\x82\x34\x69\x6f\x4a\xb4\xdd\x1f\xa0\xfe\x44\x1e\x9a\xaf\x02\x6c\x0d\xdd\x83\x9e\xc7\xd1\x04\xdb\x64\xd2\xfa\x00\xd1\x1c\x22\xe4\x5b\xf0\x26\xb5\x73\xc5\xe9\x81\x00\x9c\x70\xd1\x61\x71\x6c\x70\xfe\xcd\x68\x49\x89\x78\x8b\x6e\xd7\x4c\x0b\x35\x55\x26\x2f\x7d\x28\xf5\xfe\x0e\xe5\xf4\x89\x1e\xea\xf4\xd2\xf0\x57\xd2\x58\x97\xac\x09\x40\xd9\x01\x60\x21\x2f\xdc\xc4\x6c\xe8\xb2\x30\x77\x6c\xfd\xc8\x24\x9e\xf6\x06\x32\x5b\xf0\x0b\x20\x20\x51\x17\xb9\xc8\x2d\x14\x41\x72\x80\x4d\x3a\x81\x08\x3c\xd3\xbd\xbd\x80\xee\x96\xee\xed\xcd\x89\xfa\xbe\x58\x9c\xa7\xe5\x0d\x03\x22\x83\x84\xe5\x93\x74\x9e\x38\x5c\x01\x4a\xc8\xef\xb9\xf3\x57\x49\x59\x89\xdf\x0f\xe8\x2b\xf3\x43\xe0\x6e\x43\xa3\x86\x4d\x3e\x9e\x5b\xad\xd2\xf4\xab\x8b\x4f\xe9\x42\xc4\x69\x25\x3e\x80\x5c\x2b\x00\x3c\x2a\x74", 214, { 0x94, 0xb3, 0x23, 0x0b, 0x78, 0xb0, 0xe5, 0x34, 0x86, 0x5b, 0x43, 0xce, 0xc8, 0x6b, 0xc9, 0x2e } }, +{ "\x3c\x73\x00\x28\x30\xe9\xb7\x78\xf2\x94\x76\x9a\xe1\x27\x74\x62\x3d\x3c\xdb\x7a\xd3\x1d\xc8\x3e\xd1\x2e\x6f\x36\xb8\xfb\x5c\x31\x6f\xda\xd4\xfa\x73\x3d\x5a\xba\x2c\x96\x4d\xea\x5b\xe7\xae\xf2\xb0\xe5\x00\x63\x78\xc8\x48\xce\x74\xb2\x34\x3f\xc5\xb9\x58\x59\x03\x93\x93\x0f\x6c\xdd\x90\xfc\x39\x08\x69\x60\x0c\xe0\x65\xb8\x86\xba\xe2\xf9\xf6\x3a\x4e\x68\x2c\xbe\x4f\x19\x6b\x6b\x03\x02\x7c\xd2\x61\xbb\xdf\x3e\xbe\xd4\x1d\x9c\x6c\xd2\x39\x08\x7d\xc8\x45\xf0\xa5\x8f\x10\xe7\x3d\xa2\xfd\x08\x64\x98\xef\x05\x40\x3e\x60\xcb\x62\x50\x91\xd3\x48\xd4\xdc\x08\xfc\x14\x25\x50\xd9\x36\x6f\xba\x6d\x79\x8a\x42\x7a\x0e\xea\x43\x17\x91\x94\x7a\xf4\x22\x31\xb2\xba\x25\x45\x12\x91\x92\x79\xff\xbb\xf9\x14\xaf\x5d\x16\x88\x4c\x5e\x0c\x29\xc0\x68\x42\xf8\x23\x0c\xd7\x9e\xbf\x02\xc3\x74\xbc\x8e\x8b\xbf\x6d\xfd\xa0\xf9\x35\x4f\x55\x4a\x17\xef\x7c\x16\xda\x9d\x9c\xb0\xd5\x6c", 215, { 0xa5, 0xbf, 0x5d, 0x7b, 0xd6, 0x14, 0xfe, 0x55, 0x13, 0xa2, 0x41, 0x76, 0x5d, 0xa5, 0x45, 0x8d } }, +{ "\xd0\x2c\x5c\xe7\x3f\x51\xc7\x4f\x33\xad\x1b\x00\xd8\xc3\x58\xf2\x93\x60\x5f\x5a\xfd\x0c\x7d\x70\x7b\x9b\x98\x4c\x7b\xe3\xf4\xea\x4d\x87\xa3\x4c\x9b\xf2\x87\xbe\x87\x60\x05\x35\x60\x16\x48\xd1\x00\xb2\x2f\x82\xc4\x9d\xd4\xc6\x29\x9c\xba\x90\x00\x86\x92\x45\x4d\x10\xaa\xdf\xc2\xc4\xf3\x34\xd3\x10\xad\x51\x76\x7b\xb1\x00\x79\xf2\x5b\x6a\x7f\x41\x12\xd5\x98\x9d\x75\x8d\x7c\x5e\x23\xe1\x64\xc9\x27\x45\x86\x0b\xfe\x95\x2b\x43\x47\x79\x6e\xb6\x07\xe3\x93\x26\x95\xb5\x01\x3c\x28\x80\xdd\x22\xfb\x68\x45\x2d\x1a\x23\x26\xb8\xcd\x20\xbb\x0c\x9e\xc4\xa2\x7b\x07\xcf\x9c\x8c\xbd\xdd\xe1\x50\x93\x09\x1e\xd3\x0d\xac\x0d\xae\x82\x43\xae\xba\xec\x6f\x27\xdf\x50\x15\x35\x0a\xc4\xa5\x4e\x3d\x22\x78\x55\xc0\x48\x53\xf9\x75\x08\x09\xab\x49\xb3\x3c\x3a\xc6\x3d\x43\x0c\xc6\x0d\x28\xfb\x42\x64\xc8\xc9\x49\x67\x1d\x42\x0c\xca\x99\xed\x16\x1b\xa8\x6e\x98\xa8\x58\x7b\xe2\x0f\x15", 216, { 0x59, 0xfe, 0x50, 0x4c, 0xbb, 0x58, 0x09, 0xb1, 0x1b, 0xce, 0xbc, 0x3c, 0x1d, 0x12, 0xfc, 0x29 } }, +{ "\x79\xee\x60\x8d\xb2\x17\xf0\xb2\x35\xe7\xbd\xde\x4b\x0d\x79\x10\x91\x6d\x35\x54\xb7\x52\xab\x41\xd4\xbf\x28\x9c\x63\xe3\x14\x1b\xde\xaa\x1f\x43\xf5\x70\x0a\x72\x6b\xd0\x0f\xf9\x8e\x9b\xef\x61\x51\xe5\x96\xcf\x07\x39\x6c\x82\xbe\xec\x3a\x78\x36\x8f\xb7\x30\x7d\x7e\xaf\x8b\x28\x95\xcf\xcc\x2f\x02\x0f\xbe\x66\x36\xbc\xf5\x94\xf6\x21\x2c\x32\x8e\xd1\xce\xc1\x24\x94\x90\xc8\x2a\xec\x3b\x69\xed\x42\x87\x9f\x4b\xb2\x23\x17\x81\x70\xd2\xa7\x22\xd5\xaf\x6f\x24\x0a\x91\x8b\x15\x50\x89\x72\x6b\xe9\x88\xee\xf8\xa6\x1e\xb8\x7c\x0e\x5d\xaf\x55\x28\xdc\xb5\x51\xe6\xd7\x26\xa4\x2e\x74\xf6\xf5\x85\x20\x66\x92\x5a\x18\x63\xc4\xed\x04\x7b\x3e\xda\xbd\x7c\xaf\x46\x2f\xab\x77\xa5\x5a\x9e\x76\x25\x73\xb7\xff\xba\x27\x3d\xeb\xc7\xff\x18\xca\x66\xde\x29\x35\x54\xa8\x44\x3f\x7c\xfd\xcb\x0a\x1e\x23\xe8\x75\x9c\x02\x66\xf3\xe1\x48\x2d\x77\x6e\xad\x58\x8b\x02\x51\xf5\x80\xe6\x41\x58", 217, { 0x46, 0x60, 0x93, 0x1b, 0x8d, 0xd0, 0x21, 0x38, 0x27, 0xd0, 0x23, 0xfe, 0x9a, 0x06, 0xe0, 0x3f } }, +{ "\xc0\xd2\x18\x1c\x3f\x7f\xc2\xb7\x10\xca\x5c\xb9\x14\x82\x37\xa1\xcd\xce\xfc\x5c\x50\x3e\xe9\x5b\x59\x6c\x39\x4f\x79\x4e\xa2\x84\x6a\x1c\xf8\xd7\x83\xd8\xef\x56\x46\x7f\xfd\x72\x17\xca\x5e\xe3\x08\xa1\x31\x19\xcf\x1d\xc0\x5a\xd9\x38\xdd\x7c\x77\x14\x67\x41\x37\xe4\xec\x4a\x4e\x7b\x68\xba\x30\x6f\x2c\x68\x42\xea\xda\xc0\xa7\x0d\x8d\x37\x37\x00\x15\x68\x8e\x9a\x60\xd0\x40\xaa\xf4\x23\x2a\xe0\x98\x48\xe4\x5b\x13\xf8\x52\xd0\x0c\xee\x5a\x53\x10\xcc\xb0\xc6\xb2\x8a\xcc\xdb\xcd\x9b\xfd\xc7\xe5\x9e\x97\x85\xac\xbd\x48\xc3\xa0\xa6\x89\x6d\xd1\x24\x30\xd5\xc1\x59\x22\x7c\x64\x9a\x25\x80\x46\xe7\xd3\xa1\xcc\x05\xaa\xf1\x92\x3a\x41\x18\xf4\xa5\x95\x41\xa8\x37\x82\xa5\x88\x52\x4d\xb2\x6e\xfc\x5e\xd7\x39\xc0\x0b\xef\xec\x21\x8f\x47\xf5\xbc\x19\x4e\x8a\xf9\x01\xd8\x2f\x6d\x15\x0e\x55\xd0\x12\xf6\x1c\x96\x2e\x9b\x39\x2c\xd2\xd9\xf3\xd0\x65\xc7\x47\x0d\x44\xc1\x2c\xd2\xce\x10", 218, { 0xf3, 0xa4, 0xbf, 0xef, 0x5b, 0x96, 0x17, 0xce, 0x45, 0x37, 0xa1, 0x87, 0x6e, 0x17, 0x10, 0x65 } }, +{ "\xf1\x2e\x9b\x39\xc2\xab\xcc\xdf\x49\x44\x7d\x55\x70\x03\x57\xc4\x45\x3b\x43\xf5\xf7\x5f\x39\xbc\xfd\x7e\x36\x02\x56\x5c\x4c\x6d\xeb\x2e\xd3\xae\x10\xf1\xbd\x66\x29\x67\x07\xb6\x69\xaf\x4c\x62\xb6\x80\x74\xa1\xa9\x02\x89\x83\xb1\x49\xaa\xff\x57\x6e\x18\x98\x9c\x4c\x6e\xac\x7e\xd4\xed\x59\x99\x0e\xf5\x0c\xeb\xac\x90\xa7\xb0\x4c\x29\x4e\x6c\x4b\x5a\xcf\x07\x40\xe3\xac\x12\x1c\xb6\xc5\x27\xdc\x2e\xa6\x6f\xe8\x60\x6b\x3e\x0c\x8a\x4c\xd8\x10\xa9\xc9\x57\xf5\x26\x73\xa4\xcf\xb0\x54\xa3\x3a\x25\xfc\x6b\x7a\xa9\x29\xb2\x33\xda\x12\x48\xc1\x1a\x50\xba\x35\x0b\x6a\x17\xed\x19\xfb\xcf\xcf\x30\x82\xb6\x22\x8f\xc6\x28\x08\xb4\xe4\x47\x9c\x77\xf6\x60\xa4\x33\x62\x6c\xf3\x1f\xbc\xb2\x5e\xba\x59\x8a\x58\x65\x71\x3c\x2d\x0a\xf0\x06\xd8\xfa\xd9\x3c\x81\xd5\x57\x8a\x96\xa2\x62\x55\x84\xff\x0a\x40\x12\x72\x64\xcb\x5a\xdd\x0e\x15\x66\x10\x5f\xc2\x63\x79\x30\xf7\x84\xf6\x42\x82\x76\xcb", 219, { 0xcd, 0x28, 0x77, 0xaa, 0xac, 0x2a, 0xed, 0x44, 0x22, 0x6b, 0x47, 0x34, 0xb0, 0x26, 0xb4, 0xb3 } }, +{ "\x4a\x17\x7b\xaf\xa0\xb6\x26\x01\x80\x28\xb2\x18\xfa\xa7\xfe\xb7\x7c\x9d\x29\xa0\xfa\x85\xc6\x3f\xb7\xee\xbc\x87\xb3\x9e\xbd\xdb\xb1\xd3\x61\x22\xe4\xa5\xde\xfd\x35\x87\x66\x15\x34\xec\x1d\x8d\x98\x06\xb6\x97\x74\xa9\xa9\x22\xf9\x4e\x13\xb1\xe2\x34\x29\x47\x80\xa1\x5a\x7e\x62\x47\x01\xb8\xa0\xc1\xc4\x6c\xc4\x3c\x8c\xa2\x56\x33\x21\x7a\x03\x52\x60\xe6\x69\x7c\x1c\x77\x82\xe8\x8f\x55\xaa\x66\x7b\x49\x4e\xc0\xe2\xf4\x33\x3b\x5e\x23\x60\x3d\x1e\x3a\xaa\x08\x7d\xcc\xda\xa4\x40\x4d\x7c\xdb\x6c\xdf\x47\x5e\xc2\x48\x24\x06\xd9\x05\xdd\x34\xd6\x78\x63\x59\xc9\x3c\xbc\x91\xa7\x99\x87\x6a\xe0\x13\x2d\xc4\x9d\x1d\xa6\xd0\x98\xeb\xe5\x3a\x97\x65\xe1\x63\x86\x37\x41\xc7\x30\x05\xa4\x7e\x9a\xbc\x8a\xde\xfc\x04\xe2\x3d\x5d\xd1\x30\xd4\xc9\x19\x5a\xbf\x32\xa0\x10\x20\xe1\xee\xd7\x64\x97\x63\xb0\x9e\x44\x61\x69\x0f\x63\xa7\x7f\xc7\xf0\xbe\xae\x64\x07\x8b\x18\xf9\x1b\x05\x0d\x0b\xcf\x01", 220, { 0x95, 0x6d, 0xe2, 0x53, 0x57, 0x08, 0xe7, 0x97, 0x5e, 0xe4, 0x9d, 0xac, 0x5c, 0x77, 0xf2, 0xd4 } }, +{ "\x7d\xb5\x74\x2a\xf7\xeb\x20\x0c\x5d\xdb\x67\x4f\x27\x6f\xb9\x00\x50\xef\x58\x0b\xe0\xc4\xf3\xc5\x17\x57\xe4\xa6\x33\x18\x03\x14\xdf\x9b\x25\x5a\x38\xdc\x35\xb7\x7c\xa3\xec\x93\x51\x03\x30\xcd\xb0\xfc\x07\x2f\x6c\x40\x36\x03\x63\x13\x7a\xbf\x3f\x4b\x62\xdb\xe9\x77\xc7\xc3\x8c\x1c\xe9\xe8\x41\x1a\x28\xf1\x5c\x2e\x5c\x10\x52\x91\xd1\x6f\x46\xbd\xe2\xc8\x2f\x4f\x30\x14\xa6\x08\x80\x5b\x51\xed\x2f\xaa\xe8\x8f\x52\x23\xe1\x65\x6e\x2e\xbc\x55\xd0\xce\xed\x51\x8b\x0e\x61\x1e\x0c\x99\xae\x30\x5b\x69\xdc\xb2\xf0\x98\xca\xa2\x30\x52\x3f\x18\x83\xec\x8e\xa6\x12\x0d\xe5\xdb\x22\x0a\x32\xe2\x08\x50\xb1\x48\xc8\xfa\x17\xdb\x4e\x83\x54\xad\x48\x95\x09\x38\x9e\x00\x86\x9b\x8f\xc6\x7e\x03\x69\x53\x4a\x25\xe5\xca\xd6\xe7\x1d\x7a\x2c\x1e\x2a\x6f\x9b\x72\x5e\x25\x83\x5e\x1b\x58\xc0\x54\x4e\xf7\xb1\xfd\x8c\x36\xe4\x9e\xc7\xc2\x60\x96\xac\x10\x8e\x04\x9d\xcf\xc4\x85\x46\x7c\x6f\x1b\xde\x13\xdd", 221, { 0x6d, 0xbe, 0xd8, 0x8e, 0x62, 0x40, 0x88, 0xb8, 0xf7, 0x63, 0xda, 0xce, 0x3a, 0x5f, 0x47, 0x0f } }, +{ "\x29\xfc\xe3\xa5\x9b\x13\x7b\xb3\x22\x8c\xc0\xf4\x9d\x7e\x20\x9a\x93\x0d\xe1\x0c\xdd\x5c\x93\x6e\x61\x30\xa4\xc8\xf8\x22\x12\xd5\x71\x80\x3b\x6b\xaf\xc2\xd0\x81\xed\xa4\xe8\xe2\x22\xe4\x31\x6d\x80\x9a\x41\x06\x16\x2f\x0a\x1d\x95\xfb\x6c\xd9\x2f\x7f\xe5\xe0\x9b\x3c\x63\xc5\x35\x2e\x3a\x0f\x43\xe8\x31\xe2\x53\x4d\xb7\x4d\xc0\xe8\x33\x2f\x53\xe9\x79\xc6\x05\xbd\x58\xd6\xe2\x48\x50\x72\x0a\xc2\x61\x6a\xd2\x2b\xfe\x51\x07\x6c\x21\x29\x52\x0c\x78\xad\xb7\x8b\xbd\x3b\x38\x5f\x23\x5d\x96\x88\xec\xf3\x37\xd2\x17\xfe\x23\xa7\x37\x0b\x28\x8e\x5f\x3a\x1e\x44\x3a\xe9\x45\x75\x37\x02\xca\x17\xe1\xdf\x69\x64\x4c\xd5\x2c\x72\xab\x64\x51\x70\xff\xf9\x49\x7f\xea\x5d\xdd\x2a\xa2\xbe\x6b\x84\x01\x58\x4f\xdd\xb8\xc0\x5d\x20\xa4\xcd\x8a\xcc\x39\x23\xaa\x8d\x1b\x5d\x53\x76\xcb\xd6\xe1\xde\x7e\x15\x93\xd4\x0a\xd3\xd3\x40\xf9\xa9\x93\x97\xc0\x5a\xd3\x3a\x09\xbb\x3f\x6c\x2d\x3b\xf4\xee\xbe\x13\x63\x39", 222, { 0x19, 0x9e, 0x3f, 0xa3, 0xf4, 0x23, 0x12, 0xaa, 0x16, 0x04, 0xf8, 0xc9, 0x22, 0xd4, 0x39, 0x69 } }, +{ "\x3f\x0b\x4e\x57\xf7\xe5\xf0\x5f\xda\x6b\x3a\x8b\xa8\x10\x37\xf8\x12\x45\x90\xf9\x16\x5b\x2c\x17\x6c\x10\xef\xa9\x18\xb8\xa4\x0c\x20\x09\xf5\x80\x58\x83\x97\x9f\x59\x7a\x82\x7b\x90\xc2\x5e\x52\x72\xf5\xfa\xf0\xcd\x63\xf5\xa2\x3a\x97\x7f\xd2\xaf\x82\x3a\x44\x31\x47\x3a\xec\xa6\xa2\x2b\x69\xc8\xf6\x92\x22\x36\xf1\x2c\xfc\xa5\xde\x72\xb5\x33\x86\x3e\xe0\xdc\xc4\x87\x7d\x05\xa4\x48\x34\x36\x37\x80\x2e\xe5\xf6\x52\x91\x6d\xd0\x4c\x96\x1e\xd3\xc4\x48\x6d\x73\x5e\xda\x4c\x79\xab\xa5\x95\x8a\xec\xbe\x9f\x52\xf4\x31\xf3\x4e\x2b\xdc\x19\x34\xaf\xe9\x8b\xff\x94\xe9\xcb\x9a\x4c\x8a\x90\x28\x22\xf5\x1c\xee\xe0\xc6\xa9\xde\x91\xa9\x01\xc1\x61\x8d\x2d\x00\xa0\x88\x45\x0e\xe5\x47\x67\x75\x4f\x30\xc2\x7c\xe7\x16\xd2\x72\x21\x98\xa6\x9b\x82\x17\x5c\xb4\x5b\x51\xaf\x23\xb3\x9f\xa7\xc0\x43\xc7\x6f\x3a\x9a\x7f\x43\x27\x61\x7f\x88\xac\xb9\x41\xf5\xc5\xc0\x58\xef\x32\x33\x6a\xf3\xff\x2d\xcc\x2d\xae\x0e", 223, { 0xbc, 0xe6, 0x12, 0x5a, 0xda, 0xbc, 0x5a, 0x1b, 0x21, 0xa2, 0x7a, 0x18, 0x4b, 0x6a, 0x4b, 0xd2 } }, +{ "\xb8\x25\x02\x77\x2d\x99\x6b\x71\x64\x65\x09\xad\xea\x9e\x5e\xe6\x5f\xbf\x95\x63\xc9\xfb\x69\x98\x95\xb1\xb4\xec\x2c\xfe\x95\x96\x2e\x6c\x3c\xa0\x4e\xc7\x55\x0e\xca\x10\x0e\x18\x85\x8b\xc7\x92\xc2\xf3\x55\x6d\x7f\xce\xf3\x56\x6c\xdb\xc6\x7c\x87\xa7\x0c\x6f\x55\x3f\xe0\x24\xbe\xff\xac\x15\x86\x89\x2b\x85\x64\xd2\x19\xe1\xc1\x56\x7a\x42\x0e\x6b\x84\x0f\xc2\xb3\x2b\xc0\xef\xac\x47\xbd\x80\x62\x63\x64\x11\x43\x24\x2a\x6b\x13\x54\xd8\x9a\xf6\x8a\xf7\xad\xab\x78\x47\x0a\xd8\xd1\x68\x6b\x7f\xd5\x9c\x79\x90\x7a\xa4\x03\x99\x38\xc6\xdb\x99\x71\xf0\x4d\xf2\x7c\xf7\x3d\x7c\x4d\xf8\xdc\xb6\xc2\xdf\x07\x17\x8c\x06\x3c\x82\xb8\xf5\x39\xd9\xd9\x48\x33\xa9\xd4\xae\xb0\x03\x48\x0d\x01\x6a\x98\xc3\x60\xe8\x96\x08\xa2\x3b\xcd\x6f\x98\x2d\x6b\x8b\x08\x01\xc9\xae\x43\x09\x99\xcd\x63\x55\xab\x7f\x23\x85\x5c\x24\x5b\xc0\x9b\x23\x16\xbd\x99\x4b\x51\xfe\x0d\x5b\x53\x1d\x21\x9d\xa4\x3f\xfc\xad\xab\xa5\xed\x57", 224, { 0xcf, 0x7a, 0x97, 0xcb, 0x19, 0xd8, 0x74, 0x61, 0x6c, 0x4b, 0xe9, 0xa4, 0xa7, 0x52, 0x11, 0x02 } }, +{ "\xe7\x61\x30\x9e\xca\x25\x61\xd9\x2d\x37\x7a\xf9\x74\x80\x8a\xe5\x40\xc4\xf5\x06\xca\xed\x62\xde\xe3\x80\x45\xd3\x85\x31\x08\x0a\x14\x91\xd8\x6f\x37\xe5\x0b\xd0\x4e\x13\x29\x29\x8f\xb6\x9e\xfb\xc0\x50\xfa\xd5\x93\x9f\xe2\xf4\x99\x08\x97\x06\xe4\x30\x20\x0b\x3e\xaa\x17\x54\xff\xca\x0e\xae\x8f\x98\x9c\x98\x79\xe1\x07\xaf\x27\x67\x8f\x2b\x40\x38\x55\x82\x9b\x1c\xe7\x2a\xde\x27\x69\x7c\xb7\x6f\x61\xb4\xb7\xd8\x1e\x15\xc6\x0b\xc6\x29\x47\x85\xfb\x26\xc9\xcb\x29\x6c\x66\xbc\x6f\x2b\xbc\xff\x28\x22\x85\x9a\x15\x82\xd6\xa4\x29\xf1\xf1\x13\xf0\xaa\xc6\xaf\x9c\xc1\x0d\x28\xad\x84\xf9\x42\x3c\xfe\x99\x2e\xe5\x95\xd0\xf5\x4f\xd3\xef\x0d\x5a\x41\xec\x0e\xe3\x6f\x42\x7e\x36\x11\x64\xc8\x11\x44\xdf\x4c\x51\xee\x0b\x90\x3c\x42\x6d\x93\x6a\x63\xac\x42\x50\x20\x2e\x04\x6a\xde\x4f\x70\x05\x93\x3e\x1e\xa6\xee\x73\x9b\x1a\x95\xd0\x76\x1b\x86\x54\x77\x9c\x9e\x76\xf0\xb2\x38\x24\x2b\x1e\xee\x57\x02\x7b\x7b\x52", 225, { 0x73, 0x28, 0x7e, 0x73, 0x4a, 0x07, 0x8f, 0xf9, 0x54, 0x98, 0x66, 0x8b, 0xe6, 0x28, 0x69, 0x5a } }, +{ "\x8e\x01\xc1\x78\xf7\xf3\xe5\xc8\x6b\xab\x98\xf6\x2a\x40\x71\x27\xbd\xd1\x76\x48\x46\x71\xba\x0b\xf3\xaf\x20\x7f\x8d\xc0\x3d\x4a\x2d\x4b\x5c\x86\x0d\xd1\x9b\x36\x7c\xb7\x32\x64\xeb\xf2\xd4\xd8\x25\x4e\x2e\x76\x9c\x5b\x8c\x35\xde\xf4\x9b\xb8\x27\x6d\x49\x8a\x0f\x58\xc8\xfb\x64\xf4\xb2\x91\x12\x34\x47\x2d\x3f\x67\xd1\xbc\x74\x88\x28\x96\xf5\x24\x52\x76\x31\xe4\x42\x16\x54\xb6\xc1\x67\xfa\x9c\x6a\x6a\xff\x11\xcf\xae\x72\x13\xba\x66\xa8\xd2\x8e\x26\x6c\xf3\xcb\x3a\x54\x81\xb0\xa3\x2f\x71\xfa\xaf\x9a\xd0\xcb\x34\xb2\x8b\xa6\x69\xe3\xdb\x97\x60\xdf\x4b\x6f\x24\xab\x67\x2d\x6b\xd3\x03\x79\xf8\xbe\x25\x49\x90\x1c\x90\xa6\x96\x7b\xed\x89\x45\xf9\x98\xdf\x8a\x14\x05\xac\x7c\x9d\xce\x4c\x79\xcc\x5a\xd4\xde\x6c\x2b\x96\x62\x37\xc3\xc3\x10\x3c\x34\x2b\xdf\x7c\x43\x21\xef\x95\x38\x7a\x62\x96\x45\xb4\xd5\xf1\x90\x32\x7a\x8e\xdf\xa5\xd3\xfc\xdf\x87\x0d\xc2\x11\xc1\xf7\xd4\x52\x6d\x9d\x21\x05\xb5\x85\x49\xdf", 226, { 0xd2, 0x88, 0x52, 0x3d, 0x56, 0x8c, 0x3e, 0x43, 0xc1, 0x91, 0x26, 0x52, 0x1f, 0x00, 0x34, 0x9b } }, +{ "\xda\x85\x6c\x4e\x51\x3f\x1e\x87\x08\x3b\x76\x2b\xc6\x9f\x46\x95\xb0\x8d\x65\xc2\xe7\x19\x27\xde\x4f\xe6\xee\x67\x6b\x5c\xda\x00\x64\x88\x9c\xd4\x29\x8f\x68\xa5\xaf\xd0\x08\x70\x59\x96\x0e\xbf\x74\x76\x22\x8b\xd9\x4b\x79\xcb\xb5\xcc\x66\x9d\x66\xc7\x0a\x10\x7b\xfc\x28\x8c\xde\x99\x13\xdf\x0e\x4d\xc8\xe4\x84\x0a\x18\xd2\x37\x5c\xfe\x1e\x3b\x61\x0f\x0e\x85\x64\x0f\xdc\xc9\x1a\x9f\x83\x84\x78\x14\x28\x16\x2f\x64\x28\x07\xc6\x3a\xba\x6a\x52\x29\x41\x5e\xd3\xfc\x31\xb1\x2e\x2c\x9b\xa0\xc3\x6b\x56\xba\xaa\x5d\xcc\xe2\x8f\x66\x5e\x73\x27\x9e\x75\x7e\x4e\xe1\x26\x2e\xbf\x04\x81\x4d\x6f\x22\x77\xdf\x86\x14\x65\xec\xfb\xfe\x41\x5c\xca\x06\x60\xfa\xd5\x20\xe1\x9b\x55\x05\xba\x58\xfb\x43\x5d\xf6\xa7\x6d\x06\x67\xc4\x72\xa4\x6a\x3e\x0b\x61\x4d\x21\x4e\xd0\xd2\xcf\x60\xb2\x30\xdd\x47\x65\x30\x8c\xde\xea\x78\xdf\xe1\x91\xe5\x5d\x28\x43\x11\x65\xf1\x6c\xf4\x29\x56\x83\xa6\x49\xdd\x37\x42\x0c\x2e\x37\xe7\x3d\xdf", 227, { 0xcd, 0x4e, 0x87, 0xb7, 0x10, 0x56, 0x56, 0xa0, 0x13, 0xe5, 0xbd, 0x06, 0xe2, 0x8d, 0x82, 0xf9 } }, +{ "\x9e\xd8\xa0\x6c\xfa\xc3\x10\x42\xf8\x1f\x36\xfa\xad\xae\xe8\xa3\x83\x22\x1b\x38\xbe\xdc\x86\x31\xaa\xcf\xd6\x35\x63\x83\x87\xec\x40\x36\x66\xf3\xdd\x1d\xa0\xe9\xc4\xc8\x85\xa6\xb8\xa3\xdf\x8c\x9d\x98\xe9\xf5\x07\xd2\xee\xcb\x5d\x9d\x80\x37\xaa\x69\x51\x72\x00\xee\xb1\xb7\x89\x69\xa4\x59\x2b\x04\x9f\xf0\xd7\x53\xdf\xaf\x6f\xfa\x66\xd1\x51\x6d\x94\x32\x85\xd0\x5e\xfa\x7f\xfd\x2d\x74\x91\xa3\x55\xfd\xf0\x8b\x30\x17\x60\xf6\xd7\x9d\x7f\x23\x7c\x11\xac\xed\x67\x11\x92\x90\x8b\xe9\x54\x8c\xc4\x41\x57\xa2\xb0\xf7\xa6\xfb\x27\x08\x06\x68\x58\xa7\x97\xc4\x81\x70\x24\x76\x4a\xb6\x07\x13\xbf\xf8\xbc\x20\xe9\x73\x00\xf5\x08\xd1\xa5\xbc\x6e\xff\xf5\x99\xfa\x1c\xc1\xe4\x30\x8d\x05\x91\xf2\x2d\x39\xb1\xdd\xa2\x36\x11\x43\xcb\xc3\x00\xc0\x55\xbc\x2f\x7b\x6d\xde\xb1\xfb\x8f\x31\x21\xa3\x7d\x12\xe2\xcc\x4c\xdc\x81\x7d\x99\x33\x38\xc9\xd8\xed\x8c\xc6\xcc\x9c\x15\x25\x13\xbc\x5e\x73\xd9\x76\xe2\xeb\xad\x0f\x37\xf5\x70", 228, { 0x19, 0xfd, 0x74, 0x3f, 0xff, 0x64, 0x2f, 0xff, 0xfa, 0x16, 0xbb, 0xd2, 0x16, 0x92, 0x6c, 0x7b } }, +{ "\xf0\x47\x3f\x69\x52\xb8\x77\x76\x86\x6d\xa2\x5e\xde\x26\x1c\x41\x3b\x43\x2c\x30\x34\xa6\x43\xd9\xe0\xb5\xd2\x5b\x41\x7f\xc5\x38\x4d\xf6\x9f\x68\x9a\x5a\x33\x8a\xa5\xb7\xfc\x36\xbe\x85\x1a\x6d\x94\x6d\xe9\x32\x59\x2b\x40\x32\x91\x8e\x43\x9e\x7d\x9d\xe6\x1a\x1e\xd4\xfe\xcd\xe8\x8c\x05\x99\x05\x78\x6a\x65\x42\x4b\x93\x95\x9a\x77\x70\x9b\x5d\x11\xbd\xa7\xfd\xd0\xd4\x7a\x75\x35\x2c\x58\x57\xc4\x72\x1c\x70\x70\x42\x65\x19\x14\x82\xee\x1d\x1e\x5b\xfc\x42\x46\xd5\xf0\x76\x7c\x0f\xfc\x98\xe0\x17\xf2\xdf\xeb\x6c\x38\xeb\xab\x0d\xd8\x66\x2b\x3d\xb4\x56\xf1\xd6\xd7\x03\xa0\x47\xe6\x7f\xbe\x2c\xb5\xd7\x90\x88\xf6\xd5\x22\xa2\x0c\x6e\x63\x79\xfd\xcf\x6c\xe4\x86\xff\xe1\x4b\x49\x30\x70\xfc\x22\xa8\x77\x2b\x97\x47\xc2\x89\x6d\xb4\x71\x7f\x57\x28\xf8\x07\xca\xd6\x41\x27\xec\xf6\xec\x0c\xaa\x6d\xb6\xbf\xe9\x1b\xf7\x86\xd4\xc0\x45\xd9\x54\x8b\x37\xff\x9e\x41\x44\x46\xe5\x07\xc9\xdb\x31\xcc\x29\x4b\x48\x55\x0e\x97\xc8\xe6", 229, { 0x8d, 0xe4, 0xe9, 0x8c, 0x60, 0x20, 0x2e, 0x6e, 0x67, 0x30, 0xe5, 0x90, 0xee, 0x49, 0x57, 0x5d } }, +{ "\xce\xed\x56\x8a\xea\x09\xf1\x00\xb0\x28\x60\x42\x00\xa4\xca\xb2\x2b\x31\x64\xe4\xf7\xb2\x44\x02\xbf\xb9\x55\xe0\xb7\x9a\x63\x9d\x4e\x2a\x56\xf2\xac\x19\x7c\x1a\x5b\xe9\xff\x5e\x02\x8a\x75\x3c\x4b\x94\x96\x33\xe6\x20\x09\x2e\xa7\x44\x57\x8b\xcb\x28\x01\xc6\x58\xc9\xac\xc6\xa2\x4a\x7a\xc4\xe9\xf2\x75\xd4\x20\xc7\x25\x12\xc9\xc4\x41\x6a\xfb\xb9\x82\x03\x85\xc0\x92\x49\x2d\x57\x24\x95\x11\x1f\x1d\x7c\x2f\x30\xef\xb1\x00\x17\x07\x97\x3f\x6d\x5d\x67\xc7\x15\x28\xfb\x9a\x11\xb4\x35\xfe\x01\x4b\x0e\xc1\x3a\x50\x3f\x9e\x7f\x6c\x85\xb8\x5f\xdf\x95\x43\x2a\xf8\x9c\x42\x91\xa0\x71\x6a\xd9\x10\x5a\x26\xbc\xa3\x78\xb4\xdc\xc5\xd0\x6c\xe4\x0b\xf6\x21\x3e\x5d\x58\xa0\x6a\x4e\x24\x56\x02\x8c\xd7\x0e\x47\x73\x64\xd7\x66\xbc\xfd\x03\x4d\x52\x80\x4c\x25\x45\x81\x12\x6b\xd7\xf0\xc0\xae\xb4\x67\x4c\xe7\x3f\x13\xdc\x70\x08\x3c\x86\xa3\x5a\x72\x30\x10\xf0\x56\x97\x5a\xc7\x02\x6b\xae\x0e\x16\x96\xe1\x3a\x60\x9d\x26\x36\x27\x1f\x69", 230, { 0xe1, 0x2d, 0x4d, 0x4e, 0x25, 0xde, 0x0e, 0xf5, 0xcb, 0x99, 0x33, 0xe3, 0x45, 0x90, 0xf0, 0x1f } }, +{ "\xb8\x14\x7b\x4a\xaf\xbe\x8f\xb9\xd8\xd0\x9b\x2a\x70\xd9\x43\x75\x04\xb0\xb3\x4e\x64\x82\xdd\x5c\xb6\x7a\xde\xf7\xa6\x0b\x7e\x83\xbb\xdd\xd6\x64\xc5\x51\x0c\x9c\x72\xb3\x3a\x08\x01\xfb\x6d\x34\x0e\x40\xc9\xd6\x8b\xba\xca\xee\xcf\x72\xa5\x78\xc8\x88\xcd\xca\x4d\x21\x91\x90\x8e\xeb\xe2\x62\xad\x4e\x33\xff\x65\x30\x79\x29\xe8\x65\x52\x1c\xc7\xb2\x42\xac\x0b\x7c\x18\xfa\x61\x12\x6f\xd2\x71\x94\x50\xa5\x4f\x7e\xf5\x1e\x0a\xd5\xa8\x62\x63\xec\xca\xe9\x98\xd3\xf0\xf4\x5d\x5d\x28\xaa\xec\xcd\x59\xd3\x33\x1c\xc8\x30\x2c\xea\xb7\x74\x4b\xff\x28\xe3\x10\x7c\xbf\x86\xbc\xa2\xc5\x08\x20\x3e\x49\x31\x90\xb0\x61\xfc\xf7\x97\x8e\x56\x05\x1c\x3d\x76\x83\xd7\x6a\xd3\xc6\x61\x5f\xc7\x42\x77\x9b\xbe\x36\xc7\xcd\x1a\x85\x5b\xff\xa7\xa5\x9f\xd0\xb6\xb0\x10\xda\xd8\x98\x83\x32\x38\x78\x0f\x0d\x96\x05\x99\x7f\xdc\x23\xfa\x5f\x5e\x94\xcf\x47\xb3\xcb\xdc\xb8\x2a\xdf\x1d\x5a\xeb\x9b\x6b\x60\xac\xb2\xc8\x0a\x0c\x0f\x47\x44\x90\x4b\x9b\x6c", 231, { 0xfc, 0xbf, 0x92, 0xda, 0xc4, 0x1d, 0xb9, 0x19, 0x4f, 0x37, 0xa0, 0xbf, 0x95, 0xd0, 0x48, 0x08 } }, +{ "\x37\x38\x3a\x31\xbb\x9a\x2d\x97\x67\xf5\x77\x16\x90\x82\x1f\xe2\xb1\x3b\xdc\x46\x27\x15\x5d\x2a\x85\x4e\x32\xb3\x95\xdc\x5a\x09\xec\x05\x69\x34\x29\x0c\x56\x1f\xca\x09\xdf\xbf\xaa\xd2\x99\x4d\x1b\x15\x98\xaf\x9c\x88\xb6\xf5\x37\x37\x84\xfe\x7a\xfc\xcb\x3b\x0f\x0d\xbd\x8b\xfa\xaf\xbd\x46\x6f\x09\xc8\x56\x4e\x13\x7e\x7f\x3c\xad\xd1\xbe\x5f\xcc\x49\xcf\xb5\xcf\xf1\xc9\x12\xf0\xe1\xe5\xb4\xd6\x69\x5c\x84\x46\xd7\x6e\xec\xfa\xe6\x7e\x4f\x8a\xc3\x5a\x29\x87\xbd\x99\xc5\xa7\x88\x1e\x95\x1a\x2d\xb9\x31\xfb\x92\xec\xef\xe2\xa1\xca\x1b\x96\x18\xfb\xd3\xe0\xed\xdd\x82\x7a\x5c\xc5\xf7\x26\x8e\x63\x21\xdc\xe7\x43\x69\x1b\xed\x70\xac\x61\xd0\x33\xd4\xb6\x9a\xf9\x12\x62\xf4\x52\xb9\xbe\x92\x16\xba\x28\x3c\xa2\xb8\x10\x7a\x40\xc7\x2f\xdc\xa5\xc6\xd8\xe3\x93\x56\x66\x8f\x9f\x76\xd5\x86\x0d\xbd\x6d\xde\xd7\x33\x99\x87\xcd\xcb\xd6\x58\xd6\x81\xc7\xb4\x54\x0c\x65\xd9\xa5\x41\x53\xc5\xc6\x04\x4f\xc5\x13\xeb\xc5\x9b\x2a\x70\x7e\x4b\xed", 232, { 0xfb, 0xcb, 0x4a, 0x19, 0x4e, 0xcd, 0x8d, 0x1e, 0x33, 0xad, 0xf0, 0x88, 0x02, 0xf2, 0x49, 0xb6 } }, +{ "\xd3\x75\x82\xa5\x8a\xca\xa4\x44\x66\xd0\x70\xc3\x44\x41\x52\xaa\x6c\x91\x46\xae\x89\x5f\x64\x74\x45\x08\x0c\x74\x81\x56\xae\xf9\x2e\x56\x36\x44\xcb\x47\x13\xd0\x7b\xae\xe3\xb1\xc2\x87\xbd\x16\xdc\x96\x1a\xed\xba\xdb\x60\xa5\x99\x23\x0d\x0f\x41\xbb\x7c\x5e\xd8\x40\x57\x4d\x60\x92\x9a\x5f\xd4\xe7\x3f\x42\xda\xfb\x8c\x4d\x24\x65\xf5\x28\x69\x05\xae\x8b\xfc\x9a\xd2\x1f\x06\x70\x29\x80\x65\x36\x99\x64\x1f\xee\x2c\xd5\x84\xfd\xba\x9a\xe0\x62\x33\xb4\xda\x03\x8b\x04\x6d\x23\x42\x0a\x80\xf1\x8f\xc8\x23\x3a\x28\xc5\x68\x3d\xb1\x2d\xdc\x9f\xbf\x15\xa1\x75\x87\xdd\x29\x7f\x27\xae\x91\x75\x91\x23\x98\x78\x10\x05\x3a\xab\x78\x2e\xed\xdb\xee\x8e\x77\x59\x51\x4c\x6a\xe9\x44\x04\x3d\xd3\xda\x2f\x09\x16\xdc\xa0\xdd\xbc\xb9\x2b\xbe\x49\x0b\x60\x3e\x4d\xc2\x75\xb7\x19\xef\x42\x25\x8e\x2f\x65\x9d\x11\xb2\x85\x6e\x9a\xe7\xb4\xd3\xec\xc6\xee\x51\xdf\xb9\xbe\xb3\xd9\x28\x00\xa0\x5b\xa0\xc1\xd6\xb7\x9f\x42\x05\xe0\xfe\x1c\x4a\x5a\xfb\x7d\x46", 233, { 0x6f, 0xa3, 0x9b, 0x06, 0x9a, 0x45, 0xa7, 0x4c, 0x93, 0x2a, 0xae, 0x07, 0x2f, 0x79, 0x54, 0x7f } }, +{ "\x50\xe2\x90\xdb\xc4\x58\xfb\x83\xe0\x44\x82\x4c\x6c\x5a\xc9\x74\x59\x45\x36\x9c\x7a\x71\xf5\xac\x52\x72\x15\x44\x08\x14\xcf\xda\x77\x00\xe7\x75\x62\x07\x2c\x05\xc5\x0e\x19\x5c\x46\x96\x9e\xcd\xca\xe7\xf8\x60\x25\xd9\xbd\xaf\xe9\x3f\xf4\x60\x5f\xf0\x60\x3f\x94\x73\xde\xf6\x8a\x46\xe4\x6c\x90\xcb\x29\xb8\xac\xd0\x63\xc1\x34\xba\x2c\x74\x7c\x4d\xfe\xa0\xa9\x1a\x5d\x71\xa4\x85\x14\x87\x2a\x71\x97\xb2\x01\x8b\x87\x4c\x45\x30\x55\x33\xe1\xfc\xfe\x62\x19\xf0\xf4\x2c\x43\x3f\x1d\x14\x96\xb5\xf4\x4b\x1a\xc4\xce\xc7\xbf\x2d\x37\xfc\x8a\x48\x7b\x39\xea\xef\x40\xa2\x29\x0d\x50\xc6\xfe\xbe\x75\xdc\x3f\x23\x7d\x9f\xb3\xc6\x5d\xc3\x05\xa4\x72\x12\xd5\xdb\xe2\x28\xe9\xf1\x21\xc7\x81\xbe\x90\xd8\xc8\xf8\x40\xff\x66\x59\xd4\xd9\x32\x6f\x83\xd5\x05\x00\x3d\xac\xaa\x17\xe5\x7e\xf1\xaf\xbd\x8b\xe3\xfb\xe0\x8a\x0f\x50\xe8\xa9\x03\xb0\xaf\x22\xd7\xf4\x33\x77\xe3\x95\x93\x4a\x90\x17\x36\xdb\x4c\x12\x0b\x1e\x97\xde\xea\x78\x3b\xda\x19\x16\x98\x59", 234, { 0x10, 0x62, 0x10, 0x20, 0x9a, 0x5a, 0x01, 0xcb, 0x7e, 0x58, 0x93, 0xef, 0x8a, 0x77, 0xe5, 0xb3 } }, +{ "\xeb\xea\x1d\x2a\x84\x43\xd3\xc3\xb7\x08\x13\x09\x10\x91\x58\xbf\xed\x23\x2f\x88\xc7\x05\x4b\x9a\x8f\x43\xb5\x01\x33\xff\x20\x8d\x3f\x6e\x5a\x5a\xa0\x76\xdf\xfa\x85\xe2\x88\x41\x5e\x40\x61\xac\x06\x58\x97\x6e\xfd\x49\x90\x19\xce\x41\x15\xe6\x90\xd8\xaa\xa1\x87\x0a\xff\x33\xea\xcf\x7f\xcd\xbf\x59\x05\xaf\xe3\xea\xae\x92\x26\x4f\xc9\xb8\x92\xfc\xeb\x8e\xcc\xc5\x20\xfa\x94\x37\x3c\x47\x67\x91\x4f\xab\x44\x62\x36\x71\x8b\xc0\x4e\xc7\x00\x22\x44\x26\xef\xdb\x08\x59\x6a\x34\xe0\x2d\xae\x24\x99\xb4\xa4\xae\xd8\x35\x83\xd7\x8e\xb3\x92\x43\x8a\x18\x0b\x6b\x28\xff\x1b\x7d\x27\x1b\x07\xd1\x98\x46\x68\x03\xf3\x2a\x97\xb1\x44\x86\x23\xd2\x82\x1e\x7f\xb1\x00\x42\xb9\x86\xfd\xf8\x65\xaf\x56\xc8\x98\x90\x5b\x25\x10\x04\xbe\x73\x71\x7e\xa7\xb9\xaa\xc1\xe5\xe5\x76\x38\x40\xb6\xff\xf2\xea\x4a\x9d\x3e\x14\x44\xbb\xdf\x9c\x99\xda\xed\xe3\xf8\xaf\x48\xbd\xd4\x68\xb9\x82\x0f\x0d\xa6\x41\x44\x01\x72\x14\xb1\xa7\x6f\x8f\xbf\x21\x81\x52\x30\x33\x50\xbe", 235, { 0x58, 0xde, 0x89, 0x88, 0x29, 0xd3, 0x62, 0xe9, 0xc9, 0x41, 0x78, 0xc1, 0x0e, 0x4c, 0x32, 0xc6 } }, +{ "\xe4\x46\x29\xc4\x48\x89\x72\xd9\x5c\x32\xc8\x06\x5e\xe2\xb7\x1b\x18\x27\x15\x03\xc3\x1b\xfb\x33\x97\x29\x61\x3d\xf0\xef\x55\x81\x1e\x3f\xd8\x02\xc9\x40\x55\x56\xff\xb2\xbf\xb8\xdc\x4f\x45\x38\xd5\x4c\xb5\x11\xa1\xff\x6b\x1b\xc4\x9a\xf3\x57\xb9\x15\x43\xa8\xbb\x2a\x8e\xa1\x30\x7a\xc6\x79\xb3\xcd\xb1\x1b\xbc\x77\xa7\x5a\xee\xd5\xe5\x42\xfd\xf7\x91\x8a\x3a\x58\x4b\x25\xbd\xc8\x6c\xf7\x2e\x6b\xde\xa5\x30\xda\x98\x85\x6a\x67\xb4\xb5\x32\x7d\x2e\x47\xd8\x26\x3b\x9a\x8d\xa7\x44\xc4\xef\x46\x7e\x2b\x32\x2c\x27\x33\xec\x64\x5e\x11\x7c\x03\x9f\xbe\x18\x62\xdb\x08\x73\x87\x30\xc2\x07\xa2\x4a\x1c\x04\xb3\x55\x0d\xd5\x49\x9e\xec\x4b\x64\xc5\x1f\x68\x7c\xa1\xea\xca\x9b\xb0\x69\xb3\xa5\x39\x99\xb1\xb8\x00\x90\xee\xae\xa5\xcd\x16\xbf\x9a\xaa\xe0\x44\xbf\xee\x3c\x96\x9c\x7f\x17\x15\x3a\x34\xce\x44\x9e\xc9\x2d\x12\xe3\xec\x22\x34\xf3\x74\x02\xad\xe2\xb1\x77\x6f\xe7\xde\x06\x1b\xf7\xb3\x39\xe5\x00\x17\x6d\x93\xbf\xf3\x3a\xa4\x3e\x22\x7a\x8d\xee\x84", 236, { 0x74, 0xb2, 0x77, 0xc9, 0x12, 0x1c, 0x72, 0xf0, 0xb8, 0x7a, 0x7e, 0xee, 0xce, 0x93, 0x97, 0xe0 } }, +{ "\xf8\x1f\x5c\x32\xb7\x04\x93\xcb\xdc\x68\x0f\xed\x39\xb4\x59\xc0\x76\x75\x44\xac\xde\x5b\xc2\x2a\xc3\x5e\x63\xb8\x8f\xfb\x6c\xe6\x69\x9c\x90\x8e\x80\x16\x4e\x21\xf7\x4c\xe6\x1b\x6d\xf1\xf9\x98\x28\x6a\xbc\x01\xdd\xd1\xd8\xdf\x1e\x16\xe2\xd0\x60\x40\x72\x96\xa8\xd1\xe2\x4d\xd2\x48\xa5\xb5\x7e\xc0\x41\xad\x97\xb6\xea\xc1\x81\xe8\xbd\xda\xdf\x58\x95\x14\xfe\x70\x8e\xad\xe1\x3f\x14\x18\xe9\xe1\xa6\x31\x21\xfd\x2d\x8c\x24\x68\xf3\xe6\xab\xe8\x42\xbd\xb7\x13\x9a\xfc\x57\x55\x8d\xce\x17\x0f\x3b\x93\x05\xdd\x66\xf0\x61\xf0\x31\x01\xe0\x9a\x7a\xaa\x9d\xe9\xd0\x0b\x9d\x6a\x13\x11\xfd\x0f\xa7\x29\xba\x2b\x54\x10\x1d\x99\xbe\xc6\xc1\xfd\x7b\xa1\x42\x22\xd6\x7e\x84\x83\x20\x12\x9d\xe5\xad\x5e\x60\x21\x72\x41\x87\x00\x39\x27\x7c\x3e\x7e\xe0\xc4\xb1\xea\x8b\x09\x83\x69\xb1\xc2\x9b\xea\x6e\x81\x1b\xb2\xc9\xd8\x02\x5e\x25\xe9\xf0\x73\xd1\x89\x0a\xa3\xba\x11\xf4\x9f\x40\xc1\xfb\x93\x25\xd0\x55\x43\xa2\x14\x7f\xc0\x94\x4a\xc6\xc6\xd3\x03\xe2\xb5\xa4\x2c", 237, { 0x3d, 0xd8, 0x41, 0x6f, 0xd4, 0x1f, 0x87, 0xc7, 0x02, 0x20, 0x21, 0xd6, 0xeb, 0x2d, 0xd3, 0xc7 } }, +{ "\xbc\x2a\x44\x38\x51\x3a\xa4\xec\xae\x4b\x35\xc6\x1b\x8e\xd9\x0b\x54\x1c\xf8\x6c\xf2\xac\xb4\x54\xe9\xef\x34\xd1\x2a\x88\x1d\x1c\x69\xab\x1f\xc6\xf9\x51\xab\x81\xd3\x15\xc3\x89\xb5\xaf\xe9\xad\x67\x0a\x39\xfe\x19\x03\x93\x12\xe8\xc0\xf0\xf5\x7f\xab\xd6\xae\xda\x0a\xe6\x69\x26\x3d\x93\x46\xc4\x93\xed\xbd\x6d\xc8\x9b\xab\x6f\x1f\xe7\xfe\x16\x18\xf4\xfa\x26\xcf\x0a\x25\x84\xf1\x12\xd5\xf4\x5b\x1d\x54\xfc\x51\x1e\xad\xe8\x57\xb8\x16\xe7\xaf\x32\xf9\x53\x70\x88\xa1\x0e\x40\x9b\x7e\x07\xae\x88\x14\xdc\x2e\x15\x86\x9a\xb2\x47\xbb\x9f\xe1\x12\x2a\xa1\xf6\x28\x48\xc7\x38\xf3\x8b\xf5\x11\x9d\x19\x25\xce\x4c\x12\xf0\xf2\x6c\x77\x2d\x37\x24\xb5\xb0\x22\xea\xd2\x34\x42\x32\x33\x53\x05\x41\x07\xb1\x36\x21\x54\x39\x16\xad\x9c\x7f\x16\xcc\x2b\x45\x2f\xba\x00\x19\xdf\x82\x56\x1b\xc1\x88\xcd\xdd\xc7\x42\x3a\x63\x16\x07\x08\x49\x7d\x00\x49\x04\x93\x3b\x5d\x41\x6d\xde\x3d\x69\xf9\x78\x65\x46\xfb\x73\x5c\xbf\xa1\xa6\xe1\xbf\xc4\x07\xb4\x34\xbe\x7d\xfd\x34\xe2", 238, { 0xe4, 0xf0, 0xa4, 0xab, 0x6f, 0x2a, 0xdd, 0x87, 0x83, 0xbb, 0xc7, 0x5c, 0x71, 0x24, 0x8f, 0x1b } }, +{ "\xd4\x5d\x39\x9c\xca\x90\x8d\x26\x46\xbc\xc1\xe4\xa8\x58\x57\x5e\x3b\xbc\x7f\xd7\xc7\x41\xfe\x8e\x44\x14\x2b\x91\xa9\x9c\x14\x38\xe1\x85\xbd\x45\xdf\x69\x88\x96\xc9\x1b\xb0\x84\x4f\x8f\xef\xdc\x1f\x69\x40\x78\x71\x20\xbf\x79\xbd\xcf\xac\x22\x8d\x98\x8e\x54\x6c\xb5\x74\xa2\xfe\x1d\x57\x10\x29\xcf\x9b\x6d\x71\xbd\xb4\x4a\x62\x58\xe5\x96\x26\xb4\x24\xd7\x36\x58\x1a\x07\x2d\xa5\x46\x09\xb8\xe1\x41\xc6\xaa\xde\x1c\xe9\x2c\x4b\xe5\x33\x12\x97\x49\x7b\x48\x7d\x53\x46\x6b\x31\x53\xff\x74\x25\xda\xd3\x8f\x78\xe1\x2b\x0a\xfc\x09\xc7\x69\xe2\xfc\x74\x96\x04\xf3\x69\x35\xcf\x52\x44\x16\xcb\x6e\x9c\xc4\xc9\x6e\x42\x3a\xa8\x4f\x19\xb5\xc3\x01\x8f\xa5\xfa\xaf\xb7\xbd\x5c\x1c\x05\x29\x6e\x29\xa5\xdf\x1b\x73\x78\x0f\x37\x19\xac\xb4\xb1\x9b\xf6\x4c\x55\xdd\x6f\xa4\x3c\x4b\x08\xcd\xd1\x17\xab\x2b\x80\x9e\xf0\xab\xfc\xe9\x79\x14\x2d\x50\xeb\x77\xb5\x38\x89\xc1\x1e\xfc\x6e\x6f\xa2\xe9\x67\x60\x95\x64\x6b\xc6\x73\x27\xb8\x36\x82\xa8\x8b\xe0\x24\x9a\x7b\xd8\xbb\x8c", 239, { 0x70, 0xdd, 0xb0, 0x46, 0x25, 0x38, 0xe4, 0xdd, 0x2a, 0x78, 0x64, 0xf0, 0x7b, 0xdc, 0x71, 0xa8 } }, +{ "\x72\x92\x38\xb0\x49\x6d\x43\xb7\xff\x66\x01\xd7\x96\xed\x84\xee\x8b\xd4\xd5\xc0\xf0\x64\x96\x5d\x27\x8a\x57\x9e\x3d\x2f\x78\xcd\xe0\xa5\xb6\x64\xff\x3d\x53\xee\xfc\xf5\xe6\x0a\x90\x4e\xbc\x8f\x3c\x3c\xea\xc9\x68\x37\xf1\xe0\x1a\x6f\x0c\x59\x54\x1c\x18\xb6\x0a\xf3\x20\x39\xbe\xb4\x85\xc7\xba\xe0\xc6\xe7\xea\x89\xf2\xe9\x53\x41\xa7\x23\x34\x34\xc5\x57\xb7\x52\xb5\x30\x54\xa4\x4f\xeb\xc3\xc0\x6d\x13\x9b\x58\x0a\x64\x8c\xec\x15\xd1\x35\xa0\xd8\xa2\xa3\x28\x00\xb5\x68\xdf\x48\xe4\x53\xf7\xc6\x87\xd1\xcb\xd2\x10\xdf\x51\x8f\xd5\xab\xab\x17\xeb\xc7\xdc\x47\x2d\x08\x98\x24\x5c\x01\x34\xe8\x60\x17\xbc\xad\xad\x41\x23\xb5\xc1\x5f\x95\x54\xc9\x33\xe9\x7a\x64\x00\x32\xe1\x7f\xbd\x74\xcf\x5f\xf6\x74\x88\xbd\x40\xa9\x54\x0b\x57\x4e\x28\xd5\xd6\x99\xf4\x43\x91\x05\x88\xbb\x92\xcc\x24\xa3\xaf\x71\x9a\x44\xc5\x79\x22\xca\x93\x39\xba\x67\x35\xcb\x38\x98\x3a\x1a\xee\x80\x65\x1d\xf8\x70\xfd\x21\x24\x88\xd1\x3e\x7f\x76\xcc\xeb\x78\x5d\x30\xae\xb3\xd2\x72\xec\x6d\x00", 240, { 0x77, 0xeb, 0x85, 0x90, 0xee, 0xde, 0x0a, 0x48, 0x59, 0x1f, 0xe2, 0xa5, 0xa9, 0x24, 0xea, 0x47 } }, +{ "\xb2\xde\x87\xeb\xd6\xa4\x31\xd1\x42\x74\x34\xad\x36\xeb\xdb\xd5\xc3\x84\x7f\xc3\x6b\x26\xae\xf0\x54\xd7\xf8\xdc\x29\x8f\x55\x2b\x8e\x27\x36\xe9\x3d\x70\x26\xee\xc2\x60\x1d\x5d\xcf\x68\x62\x46\x3d\xe1\x19\x6b\xa0\xa4\x70\x20\x85\xb8\x62\x4b\x4a\x26\x27\x8b\x9a\xe9\x39\x76\x85\x02\x02\xfa\x38\xa7\x27\xe4\x5d\x9b\x6b\x7f\x12\x99\x41\x55\x7e\xea\xf3\x11\x16\x16\x68\x84\x6b\xb7\x95\xc6\xac\x69\x83\x75\xc0\xdd\xf8\x19\xf8\x0d\xc5\xa8\x75\x8a\xac\x25\x16\xf1\xeb\x62\x1b\x7c\x69\xe7\x5b\xb4\x7c\xeb\x1e\x44\x55\x7f\x98\xe9\x09\xca\x03\x86\x3c\x6f\x57\x54\x6c\x0b\xa9\x37\xd7\xda\x1e\x2b\x0a\x79\x8a\xdd\x08\xc6\xa9\x56\x13\xe3\xf8\xd2\x1a\x5a\x31\xaf\xbe\x5a\x62\x81\x02\x20\xa9\x42\x8f\x71\x8e\xa7\xa2\x43\xfd\x8d\x93\x7c\xde\x92\x03\xd2\x53\xc1\xa0\xd1\x8d\x65\x97\xfb\x4b\xfe\x98\x09\xf1\x52\x7f\x50\x41\x9a\xa4\x3f\xb8\xdd\xc0\x04\x87\x5b\x7a\x4f\x2c\x1f\x8d\x2f\xad\xb8\x98\x18\x71\x01\x83\x05\xbb\x1b\x88\xba\xc3\x7c\xe5\x23\x73\x21\x1d\xd8\xbb\xdf\xe5\xc2\x91", 241, { 0x54, 0x10, 0x15, 0x52, 0x9c, 0x0e, 0x89, 0x84, 0xd4, 0x90, 0xfc, 0x2a, 0x5b, 0x5e, 0xf2, 0xed } }, +{ "\xd7\xb2\xd7\x89\x08\xdd\x01\x0c\xff\x6f\x1c\x38\xa9\x8f\x1e\x54\x49\x85\x52\xee\x84\x6a\xbd\x93\x9a\x6e\xa1\x2b\xaf\xc6\x1f\xee\x47\x30\xf7\x07\xd1\x24\x6c\xc3\x5a\x99\x43\x76\x62\x70\xe9\xeb\xcc\x81\xb4\x85\xee\x41\x42\xf6\xc9\x0d\xfe\x9b\x52\x15\xc1\x73\xef\xe7\x94\xbb\xfd\x97\x94\x27\x8e\x89\xee\xbe\x30\xdb\x0a\x52\xe8\x71\xc5\x9b\x3e\x9e\xd6\xf0\x72\x6b\x52\xa1\xcc\x88\x4a\xf3\x11\xcd\x92\xb9\x11\x6b\x9d\x8b\x5e\xb3\x84\xa6\x17\x83\x25\x60\xe2\x49\x68\x46\xf8\xb5\x9d\xd4\x59\xff\x01\xcf\x21\xd2\x60\x43\xf3\xd4\xd4\x15\x91\xd2\xab\x44\x8e\x8d\x67\xc0\x1a\x1b\xde\xe7\xfd\xfc\x82\x98\x9f\xba\xbb\xf6\x43\x3b\x70\xbb\x54\xa7\xa5\x36\xd8\xf0\x3e\xe2\x01\x02\xe2\xa5\xe2\x89\xfb\xa2\x3f\x59\xd9\xbb\x7d\x7f\xf6\xa6\xb8\xe2\x54\xaa\xf3\x94\x03\xf7\x6a\xbb\xbf\xa0\x04\x16\xb5\x36\xe5\x2e\x66\x02\x1f\x1c\xa5\xde\x88\xf1\xba\xb0\xa6\xc5\xa9\x84\xc7\x5f\x8d\x45\x2e\x7e\x1d\x18\x67\xc2\x50\x56\xbc\x3a\x1d\x24\xc0\x8b\x5c\xb0\x08\xb9\xc8\x09\xfa\x95\x25\x9b\xbd\xc3", 242, { 0x58, 0x95, 0xff, 0xfc, 0x90, 0xfc, 0xfe, 0x6c, 0x68, 0xf7, 0x0c, 0x90, 0x74, 0x06, 0x60, 0xaa } }, +{ "\x7e\x46\x50\x67\x88\x1b\xb7\x6c\x23\xb3\x4f\x70\xfe\x2b\x43\x4f\x59\xbf\x17\x4b\xe6\x02\x61\xd5\xc9\xb7\x98\xfb\xbf\x50\x05\x6d\x5a\x00\xd6\x2d\x6a\x7f\x51\xd3\x78\x5a\x26\x7a\x6c\xf4\xdd\x4b\x4e\x1d\x6e\xa3\x29\x4c\xef\xe4\x0b\x7c\x68\xd5\x2a\xa1\xc2\xb7\x21\xc6\xde\xe5\x57\xc5\xc3\x26\x81\xa2\xef\x93\x3d\x84\xce\x1f\xdf\x50\x49\xc8\x49\xe3\x75\x59\xf3\xec\x6c\xd9\x0b\x65\x39\x94\xb6\xac\xed\xc3\x74\x42\xce\xda\xa1\x1e\xaf\x6f\x17\xaf\x5b\xc2\xf1\x6d\x2b\xed\x6b\x1b\xb7\xa9\xe5\x9b\xa9\xba\x06\x6d\xad\xf8\xfd\xc6\x84\xfc\xe3\x49\x38\x63\x3d\x64\x6a\xc2\x9d\x4a\xc7\x26\x67\x88\x99\x46\xb1\x46\x7a\x48\x44\x1d\x23\x2c\xc0\x8f\x62\xd9\xdb\x27\x2a\xc2\xc9\x2e\xc4\x35\xb8\x07\x24\x40\x73\x28\x56\x40\x26\xb5\x17\x07\x41\xbb\x80\xa9\x75\x05\xdd\xe3\xdb\x9f\x9c\x29\x34\xe5\x61\x4b\x4b\x46\x37\xc3\x77\x9b\xe0\x9d\x3c\x1e\x4d\x03\x11\x08\x29\x64\x3d\xcb\x8f\x41\xdb\xe9\xdd\x94\xfc\x6f\xa0\xdd\xeb\x12\xae\xca\x8b\xe4\x53\x82\xdd\xb3\xa3\x8e\x9e\xff\xef\x64\x0d\x95\x52", 243, { 0x55, 0x8a, 0xc2, 0x51, 0x47, 0xe1, 0xcc, 0x16, 0x28, 0xb4, 0x10, 0x71, 0x27, 0x29, 0xa8, 0xba } }, +{ "\x92\xcb\xcc\x6b\x83\xda\x5b\x25\xf1\xc8\xd6\xb1\xe8\xe5\xc3\x95\x73\xaf\x5d\xde\xe5\x4f\xe4\x71\xc5\x3c\x9f\x80\x57\xfe\x70\x18\xc3\x0d\x12\xd6\xe5\xd8\xf1\xba\xb0\xe1\xa5\x13\x3f\x05\x0d\x9a\x7a\xd9\x04\x9b\x61\x30\xc3\x4e\xf8\xba\xd3\x44\xcf\xc7\xac\xfd\x2d\x29\xef\x96\xd9\x36\x3d\x9f\x84\xec\xb2\x0b\xd6\x30\x02\x41\x13\x2f\x2e\x4f\x6a\xe5\xe2\x3e\xda\xbc\x6e\x80\xc1\x4c\x5f\x86\x03\x41\xba\x6e\xd3\x5a\xd4\xda\x21\x8e\xd1\xdc\xa0\x49\xb7\x0d\x73\xd4\x2e\xbd\x73\xd2\xd6\x44\x1f\xe6\x45\x77\x21\x72\x9b\x36\x79\x7b\xc4\x23\x48\xa8\x4a\x6d\x3b\x69\xd4\xca\x92\x35\x40\x83\xcc\xeb\x58\xa9\xf1\x5a\x33\x65\x7c\xdc\x2b\x6d\xe2\x1d\x76\x93\xc3\xf9\x63\x77\xac\x84\x33\x5d\x87\x23\x92\x19\xa0\xd7\xb0\x27\x54\x9a\x01\xd7\x58\xe2\x8d\xa5\xa3\x42\xf4\xa7\xf9\x30\x02\x1f\x16\xe1\xeb\x30\x73\x50\x23\xae\xb7\x5e\xdc\x0e\xbd\x14\x1d\x7c\x3e\x04\x7c\x0c\x1b\xcd\x78\x08\x4a\xbc\x75\x68\x5a\x8f\x54\x5f\xa4\x56\xae\x12\x10\x73\xae\x64\x81\xc0\x88\xec\xde\xcf\x9a\x08\xbe\x4c\x1d\x0b", 244, { 0x25, 0x5e, 0xd3, 0x6f, 0x90, 0x16, 0x46, 0xa9, 0xa0, 0x75, 0x89, 0xa0, 0xd2, 0x74, 0x1b, 0x84 } }, +{ "\xaf\x7f\x88\x91\x24\xee\x81\xf4\xf8\x20\x80\xd7\xa3\x7b\x03\xdf\xf8\x4f\x68\x82\x98\xec\x6a\xf7\xf7\xed\x3a\x4d\x08\x98\x39\x98\x88\x5d\x50\x46\xe4\x7c\xed\x8f\xc8\xc4\x9a\x0b\x46\x76\x3b\x5d\x9f\x48\xe4\x0d\xb0\x85\x55\x74\xfb\x51\x13\xd0\x51\x0b\x24\x77\x1a\xcb\x66\x29\x41\x0b\x8c\x7e\xbe\x61\xb6\x7e\xc1\x6a\xac\x4f\x78\xc3\xb8\x09\x7d\x31\x1d\xa6\xdf\xe0\x37\x15\xcb\xc9\x30\x6d\xd8\x2c\x5c\x3e\xec\x3d\x32\x04\xcd\xdb\xe8\xb5\x48\x7b\xaa\x7a\xf8\x23\x76\x7a\xb3\x93\x97\xd1\x97\x7e\xbb\x9f\xac\xf5\xb3\x3d\x36\xe5\xc8\x8b\x9a\xb7\xb4\x65\xea\x15\x44\x34\x0f\xcd\x88\xa0\x92\xce\xb3\x63\x07\x4e\x96\x39\x16\x0e\xb4\xf4\x27\xb5\x01\xab\xa9\x59\x3c\x12\x00\x1d\xe6\xe6\x09\xf4\xdd\x7f\x4b\x84\x9a\x87\xbb\x25\x04\xc9\x2b\x08\xee\x23\x51\x75\x34\x96\x70\x2c\x6d\x7c\xa5\xed\x4d\xd9\xd0\x13\x9a\xc9\x1d\x5c\xc9\x19\x2e\xc4\x35\xf2\xe7\x8e\xfb\xb1\xd5\x64\x74\xd2\x3c\x96\x50\x0a\xbb\x7e\x4b\x73\x9e\x04\x8f\xe2\xc0\x3e\xa6\x54\x1b\x2f\x1a\x87\xee\xb0\xac\xa6\x89\x6d\x2d\x1c\xb8", 245, { 0x5e, 0xd5, 0xdf, 0xa5, 0xd4, 0xe1, 0xeb, 0x5b, 0x7e, 0x24, 0x12, 0xa1, 0xd3, 0x55, 0xba, 0x11 } }, +{ "\x06\xfb\x8a\xca\x55\x1c\xd3\x3d\xcf\xf0\x54\x07\x03\x96\x31\x83\x40\xde\xcb\xf7\x54\xe6\x4e\xbe\x6e\x53\x66\x17\x25\x2e\x11\x88\x92\x58\x8f\xf0\x97\xab\x77\x28\x43\xaf\xe4\x55\x4e\xf6\xcc\xce\xbf\x15\x70\xa4\xad\x3f\xef\xd2\x21\x7f\xf6\x02\x1b\x92\x92\xfa\xac\x5e\x26\xa1\x40\x13\x78\xb2\xfe\xdd\xe5\xfc\x48\x43\xb5\x53\x5d\x1f\x89\x17\x1e\x3a\xf1\x5e\xee\x83\x1a\xc1\xb2\xec\xa5\xc0\xf7\xe2\x92\xd3\x33\x67\x5b\x0e\x24\xcd\x1d\x6f\x55\x10\xf1\xc7\xbf\xd1\x5a\x43\x8c\xeb\xd6\x97\xf7\xb4\x97\xc6\x4f\xd2\x4c\x90\x19\xb7\x18\x77\x55\xba\xa4\x70\xd9\xd3\x50\x23\xda\xf3\x84\xdf\x8a\xfe\x25\x1e\xdb\x66\x24\xaf\x61\x65\x30\x86\x55\xd7\x8b\x1c\xb5\xb1\xfa\x84\x89\x22\xd6\x0c\x41\x44\x40\x8c\x3b\x7f\x72\x4e\x60\x7b\x30\x99\xee\xbf\x5c\xdc\x50\xeb\xa9\x74\x29\x8e\x68\x1a\x6f\xa5\x7e\xec\xb4\xb1\x77\x16\x81\x73\xb3\x1d\xdb\x47\xbe\xc8\xe7\x1a\xbe\xab\xa9\x0a\x05\x51\xe8\x99\xc7\x05\x2e\x8c\xe5\x3d\xeb\x66\xe7\xa4\xb9\x7c\x09\xc3\xbb\xb5\x6c\x4b\x1e\xe0\x6d\x01\xc1\xb2\x13\x46\xf1\x5a", 246, { 0xf1, 0x29, 0xb7, 0xfb, 0x81, 0x56, 0xef, 0x46, 0xb7, 0x0b, 0xc5, 0xc2, 0xbe, 0xbe, 0xb5, 0x5b } }, +{ "\xa2\x42\x4d\xc3\x4c\xad\xc9\x66\x07\x39\xce\xc9\x7a\x9f\x7d\x97\x11\x45\x14\x5d\x30\x89\x6a\xdf\x83\xad\x94\x15\x74\x5f\xaa\xc5\xb6\xe3\xa3\xbe\xfe\xdf\x5d\xae\xd2\xc3\xba\xa1\x7a\xd3\xe4\x16\x12\xd2\xb0\xbf\xc1\x4c\x20\xd6\x04\x81\x03\x17\x24\xe9\xb7\x5e\xc6\x68\x0f\xdd\xa1\x10\x4f\xf9\x4a\x8d\x54\xc2\x2b\x31\xd1\x0d\x92\x9d\xb3\x30\xe5\x08\xa6\x5a\xf4\x2f\xb1\x8c\x67\xd9\xfd\x38\x56\x06\xb3\x74\xf7\xb4\x03\xdb\x72\x4d\x40\x01\xd1\xb0\x28\x90\x13\xda\x42\x04\x60\x31\x60\xff\x56\x6d\x44\x49\x81\x23\x5f\x68\xea\xf0\xb4\xd8\xc6\x3e\xdc\xe8\x4f\xb6\x22\x31\xb0\x42\xce\xb3\x1a\xbd\x7f\x8d\xf4\x3a\xb1\x59\x2f\xee\x5f\x22\xb7\xbb\xc2\x02\x05\x59\x37\x5d\xd1\x23\x3e\xb4\xe5\x7c\x9e\x26\x0d\xdc\xa7\x8a\x2b\x7b\x90\x21\x67\x98\xfe\xfb\x83\x66\xa6\xe9\x4c\x94\x09\x1b\x2c\x77\x5e\x55\xdd\xd7\x8e\xd2\x38\x53\x59\xb5\x2c\x71\x96\x28\xca\x46\x97\x14\x7c\xbe\xaa\x7b\x56\x89\xbc\x75\x84\xa3\x19\xc5\xe3\x7d\x4f\x17\xad\xcd\x30\xd8\x4c\xef\xf5\xb2\x4f\xf6\x7f\xa3\x7a\x54\xb9\xb9\xf7\x21\x1a", 247, { 0xca, 0x55, 0x81, 0x7c, 0x31, 0x59, 0x07, 0x16, 0xf7, 0xce, 0x7f, 0x9d, 0xf9, 0xbc, 0x6d, 0xb1 } }, +{ "\x6c\xab\x0b\x47\x97\xa4\xdb\xd5\x15\xae\xa0\x2c\xf4\x05\x7a\x87\x59\x24\x05\x17\xf0\xbc\x5f\x47\x0d\xc0\xd8\x1b\x64\x9d\x35\xb2\x61\x87\xa1\xea\x25\xef\x31\x22\x1e\x11\x12\x1a\x42\xa9\x52\xf7\xe8\xc5\x47\x64\x43\xb6\x9f\xd2\x7b\x20\x06\xdf\x6a\x31\x6e\xd5\xf0\xee\xfe\x49\xf3\xa9\x99\xe4\xf6\x8f\x09\x3e\x55\x5e\xc8\xe6\x1a\x33\x6b\x7e\x7f\x81\xac\x03\x01\x1e\x12\x2b\x1e\x77\x3f\xe7\xab\xe4\xd5\x08\xd4\x16\x06\xfe\xb0\xad\xb8\xbb\x7f\xe6\x51\xb5\x84\x72\x24\x0b\x79\x62\x77\xbf\xb4\x3d\x30\x21\xd4\x34\x1c\x4d\x27\x6d\xdc\xcb\x9c\x7b\x6d\x54\x5f\xef\x52\xb4\x17\x08\x60\xcb\xb8\x85\x26\xad\x05\x9b\xf7\xe9\xa6\x03\x95\xe7\xe1\x2a\x7b\x6a\xf8\x8c\xc7\x36\x1f\x1b\xc2\xcb\x19\xd9\x0d\x4f\x6e\x85\x6b\x89\x4b\x71\x25\x09\xf6\x72\x1e\x66\xec\xf2\x73\xa0\x98\x20\xce\xa4\xb2\x46\x48\xed\x32\x3a\xf8\x47\xf0\xee\x1d\xae\xda\x23\xe3\x56\xd1\x3a\xd6\xc4\x20\x2b\xe0\x19\x99\x8e\x00\x6f\x4e\xd7\x8a\x5c\xe9\x9f\x14\x94\xa9\x1d\x04\xab\xf9\xb3\xb4\xf7\xaf\xa5\x3f\x93\xde\xe4\xeb\x81\x58\x09\x33\xe7", 248, { 0x1c, 0x9e, 0x80, 0x30, 0x66, 0x3c, 0xf5, 0x9d, 0x8e, 0x03, 0x83, 0xcf, 0x5c, 0x89, 0x97, 0x74 } }, +{ "\xc3\x5d\x6f\x7a\x56\x15\x22\xf8\x31\x9b\xe0\xcf\x57\x07\xda\xdb\x49\xac\x08\x4d\x3f\xcf\xf1\xa7\x05\x73\x1a\xe3\x71\x50\x09\xb3\x7d\xe1\xf4\xe4\x05\x9c\x0b\xdc\x1e\x3d\x5f\x42\x10\x3c\x6d\xbc\xf2\x5d\x4b\xd3\xe1\x66\x6e\xf4\xdc\xea\x16\x90\x3f\x44\x56\x62\xda\xa0\xc3\xd0\xae\x33\xb9\x6b\x43\x8a\x45\x91\xa9\x00\xb2\x32\x09\x4a\xb3\xaf\xe6\x2c\x2a\xde\xf6\x4e\x93\x2a\x97\x29\x10\xd8\xf0\x1c\x11\x64\xa5\x9b\x9f\x0a\x36\x87\x46\x60\xf5\x98\x9d\x20\xa2\xf6\x73\x04\xa4\xe7\x98\xca\xe6\xa3\x45\x57\x4c\x44\x29\xf8\xd1\xd9\x10\xc3\x3f\x9a\x32\x1c\x89\x35\x16\x53\xc8\x47\x21\x6b\xd0\xe6\xbf\xf6\x6f\x5b\x2d\x1c\x42\xed\xe0\xba\x33\xd8\x95\xa6\x92\x5d\xf6\x11\xcf\xf3\xe6\x06\xd2\x9b\x69\x0f\xf7\x51\x33\xf6\xa9\x9e\xcc\xa9\x9a\x4b\x5c\x37\x9c\x30\x19\xf7\x1f\x2a\x49\xc7\x48\x2a\xf6\x72\xaa\x6a\x2e\x2b\xa3\xbb\xf4\x36\x55\xfb\xc7\xa6\x40\xa2\xcc\x41\x79\x7b\x9a\x7f\x89\x6f\xa2\xb1\xe5\x7c\x39\x3f\x05\xc5\x44\x0a\x22\xc4\x7f\xf0\x91\x9b\x6a\x6d\xb7\x87\xd0\x5e\xa8\x75\xf5\xe1\x61\xaf\x5b\x59\x9d", 249, { 0x41, 0x95, 0xad, 0xac, 0x33, 0xb1, 0xf3, 0x9e, 0xa2, 0x05, 0x82, 0x08, 0xb3, 0xc7, 0x1d, 0xbc } }, +{ "\xaf\x31\x8e\x57\x14\x59\xf1\xde\xb2\x14\xfd\x8e\xc4\x4d\xb8\x30\x3c\x7f\x59\xf0\x3b\x43\x03\xf7\x9d\x79\xaf\xa5\xab\x13\x29\x6c\xf4\x79\x31\x4c\x35\x9c\xc2\xe6\x75\x9b\x6f\x40\x2e\x0b\xe8\x14\xa5\xe7\x9c\xd5\x5b\x14\x79\x3f\x9c\x8e\xce\x99\x34\x35\x52\x8a\x41\x2e\x3e\x95\x24\xf7\x95\x33\x91\x0b\x84\x8c\xc6\x2e\xe3\xd1\xd9\x56\xdb\x39\x29\x36\xa2\x95\xf6\x68\x62\x92\x0d\x35\x39\x8b\x9c\x04\x59\x09\x24\x5e\x4e\xd8\x8c\x9a\x60\xc6\x51\x2a\x0e\xfb\xdb\x80\xbb\xf0\xeb\x9e\x65\x0e\x31\x39\x8f\xe3\xfb\x89\x41\x03\x07\xb0\x26\x79\x79\xc4\xd3\xe9\xe8\x7b\x27\x43\x92\x72\xcd\x26\xb0\x1a\xde\xcf\xe5\x3f\xa4\xbc\xcf\x36\x7a\xe1\xc0\xa3\xcf\x86\x87\xe4\x49\xbb\x67\x1e\x05\x79\x29\xe2\xfd\x57\x4d\x7b\x83\xe5\x5c\xd6\xea\xa9\x59\x0e\x43\xb4\x56\x94\x45\xdf\x22\xf8\x46\xa7\x20\x56\x66\xa2\x33\x5f\xcb\x9d\xd5\x03\x06\x55\x47\xb8\x94\xce\xe3\x6a\x81\x52\x8d\xff\x27\x09\x48\x85\x15\x32\xe4\xfb\x0b\xfc\xd5\xb9\x21\x03\x20\x7d\x06\x6a\x6e\x12\x66\x91\x43\x9e\x65\x73\x48\x89\x49\x9f\xc4\x06\x34\xd1\x29\x3f", 250, { 0xc2, 0x69, 0xc7, 0x4f, 0x4c, 0x81, 0x48, 0x5e, 0x87, 0x0f, 0xfb, 0xfe, 0xda, 0xfa, 0xa7, 0x72 } }, +{ "\x0e\x2d\xcb\x21\x81\x17\xab\xc1\x1e\xb1\x72\x69\x9d\xf2\x79\x44\x41\x60\x05\xa1\x5a\x6a\x90\xe7\xe4\x64\x42\x16\x4d\x1f\x7f\xf5\x54\x24\x9a\xde\x0d\x8d\xa7\x22\x01\x81\x6d\x1a\x72\x4a\x7a\xcb\xbb\x15\x51\x35\xd6\x45\xbf\x38\xf8\x73\x4c\x24\x57\x06\xcc\xdc\x0b\x6c\x15\xa5\x12\xf2\xca\x90\x6e\x46\x56\x82\x69\x86\xf5\xdd\xf9\x04\xec\xcd\x3e\x99\xd9\x31\x27\xa3\x25\x23\x35\x9c\x95\x26\x58\x58\x00\xeb\xf5\xdb\x1b\xc0\x09\xd4\x70\x96\x67\xba\x6d\xad\x1d\x82\x99\xde\xf5\xfa\xe1\x84\x17\xc5\x11\x08\xcc\xf3\x5e\x08\x5d\x3c\x20\x24\x1a\xda\x9d\x65\x76\x00\xff\x49\x4f\xfa\x68\x6f\x4c\xe2\x1c\xdb\x60\xfc\xdd\xe7\x6b\xaf\x54\xc7\xff\x21\xab\xb7\x3f\x6d\x37\xc3\xe4\x84\x53\x32\x59\x9d\x48\x90\x06\x5a\x68\x57\xab\x79\x3a\x3a\xe2\x33\xcf\x0d\xc6\x34\x33\x54\xb3\x38\xff\x66\x23\x3f\x0c\x3d\xb7\x6c\x42\xdd\x57\x80\x8e\x5f\x70\xed\xf2\x9a\x5c\x9a\xb6\x6c\xe0\x33\xbc\xaa\xce\x29\xf1\xa2\xcb\x4d\xdf\x49\x2b\x04\x60\x06\xf8\x28\x6e\x1a\x12\x7c\x15\xaa\x70\xc9\x89\x6a\x84\x99\x54\xe8\xbd\x8f\xa7\x72\x26\x61\xd2", 251, { 0xdd, 0x00, 0x50, 0x61, 0xae, 0x25, 0x19, 0xe0, 0x00, 0x24, 0x84, 0x43, 0x02, 0x6f, 0x1c, 0xd4 } }, +{ "\xa5\x2c\x74\xcf\x94\x7c\x13\xf9\x91\x0b\x4b\xda\x9b\x2f\x65\x21\x64\xeb\x01\xb3\xfd\x48\xcb\xd8\x20\xde\xdd\x96\x1a\x72\xb1\x1b\x53\xb9\xc1\x53\x7b\x3b\xbd\x9a\x53\x53\x68\x8b\x15\x53\x10\xf7\x81\xc4\xa8\xf2\x86\xca\x83\x07\x89\xa6\xaf\x8b\x54\x56\xec\x0f\x9e\x57\x48\xef\x33\x8a\x58\x07\xc0\x34\x15\x86\x3d\x20\x50\xda\xf7\xdf\xd3\xcb\x39\x30\x16\xa4\x96\x7a\x9b\x8b\xd6\x76\xe7\xf2\x7b\xe9\x1d\x26\xee\x8f\x38\x05\x4b\x14\xe4\xcc\xc6\x3b\xfa\x0e\xb8\x22\x96\xc1\x4a\x9c\xd7\x73\xbc\xbe\x33\x9a\x53\x76\x74\x08\xdd\x54\x53\x7d\xe2\x6c\xaf\x57\x69\x54\x6a\x64\x64\x49\xe1\xd8\xb9\x6e\x06\x5a\xed\x34\x1b\x38\x6f\xd5\x0c\xbc\x7f\xf9\x6a\x96\xb9\x7c\x00\x78\x42\x47\x14\xc1\x8d\x5b\x3b\x51\xcb\xec\xd9\x7b\xed\xaa\x35\x18\x57\x1a\x35\xb8\x22\x23\xba\xf4\x0e\xa5\x9a\xdf\x03\x44\x36\x9b\x42\x43\xb8\x07\x2d\x8a\xeb\x96\xaf\xca\xb7\x3b\x49\xb7\x37\x80\xba\x74\x79\xb6\x4b\x0d\xd1\x47\xb4\x1d\xda\x27\xae\x90\x0b\x69\x16\x83\xf1\xee\xbb\x48\x0e\x38\xc4\x85\x4e\x5c\xc1\x7c\x22\x16\x4c\x65\x3c\xf7\x5b\xf7\xe5\xb9", 252, { 0x93, 0x1d, 0xc4, 0x3f, 0x9e, 0x01, 0xe4, 0xa0, 0xba, 0x31, 0x17, 0x62, 0xb1, 0x71, 0x07, 0x29 } }, +{ "\x26\x05\xfe\xb3\xaf\x45\x91\x67\xf3\x2d\x13\x39\xab\xf7\x38\x3b\xbf\xc3\x73\x23\x48\xda\x09\x5e\x40\x10\xd1\x3d\xc9\x44\x8a\x4e\x16\x02\xd9\xc6\xfa\x47\xdd\x19\x0b\x64\x70\xac\x72\xfb\xfd\xa2\x52\x26\xf9\xd3\xd3\xb8\x00\xdb\xca\x9b\x8c\x4e\x07\x58\x54\x09\x3a\xb6\x3f\xa4\x82\x79\x03\x03\x94\x4b\x5f\x0c\x84\xb9\xf1\x73\x33\x54\xb4\xb0\x56\xf8\x1a\x12\x1e\x29\xc2\xed\x89\x99\xd7\xef\x45\xc6\x04\x91\x3c\xc0\x17\xa9\xc1\x08\x31\x1c\x55\x94\xa7\xb0\x15\xf0\x79\xff\xc4\x7e\x6d\x87\x71\xde\xc7\xdf\xc5\x68\xa6\x04\xeb\xd6\xfe\xd2\x1c\xff\x2d\x8e\xc6\xbe\x3c\xa0\x58\xf1\xb5\x5e\xac\x9d\x1c\x03\x12\x2f\x0b\xbe\xf5\xdd\xed\xe7\x2d\x2b\x57\x4c\xe0\x8a\xfe\xaa\x15\x1b\x59\x37\xd7\x91\xd4\x5c\x02\x34\xad\x80\xad\x01\x6f\x00\x34\xef\x09\x3b\xe0\x4c\x8b\xc9\x35\x46\x7c\xcb\xd9\x86\xda\x5d\x1c\xf7\xaf\x28\x28\xa5\x4c\x15\xc6\xc0\x25\x1c\xca\xbf\x48\x3a\x1d\xa1\x7b\x81\x65\x4e\xf2\x49\x53\x1c\xaa\x84\x88\x6f\x65\x30\x25\x78\x42\xe5\xee\x1e\xf8\x8e\x19\xf9\xaf\x34\xb9\x7a\x7b\xf6\xc2\x29\x75\x15\xb8\x07\x78\x2c\xf9", 253, { 0x52, 0x78, 0x7c, 0x98, 0x49, 0x6b, 0xa5, 0xff, 0x30, 0xbc, 0xb9, 0x58, 0x43, 0x67, 0x74, 0xff } }, +{ "\x12\x75\x7c\xa3\xe7\x74\x65\x23\x81\x28\xf1\x5b\x1f\x2d\x8b\x6f\x44\xe0\xcd\x2d\xd8\xdb\x77\x16\x6c\x0b\x7b\x0d\x9b\x70\x34\x9b\x8c\x71\xb7\xdd\x93\xda\x42\x0b\xf7\x73\xd2\xa5\xce\x3e\xd1\x3c\x05\x4c\xeb\xda\x7c\x3c\x01\x0f\x4e\x51\x37\x99\x2e\x2f\x28\xaf\xed\x32\x39\xea\x18\x6b\x0b\xd0\xbd\x39\x0a\xff\x4e\x7f\x22\xf3\x9f\x87\x92\x74\x0a\x73\xd8\x9f\xb2\x5b\xcc\x8e\xe4\x08\xc9\xa7\x99\x4c\x06\x7e\x18\xfc\x02\x68\xb8\x8c\x1e\x9d\xc3\x45\x44\x08\x77\x25\xc5\xaf\x26\x53\x41\xba\x7d\x3d\xbf\x22\xe1\x50\xdd\xf7\xf5\x53\x21\x4d\x38\x61\x6d\xc4\xcc\x81\x91\xb3\x51\xe3\xfb\xf1\xf0\xba\x89\x3f\x74\xb0\x7f\x55\x92\x0a\x94\x88\x49\x5a\x27\x14\x64\xdb\x8f\x0c\x1d\x6c\x90\xdb\xdc\x2c\xe9\x76\x1d\xae\x09\x20\x6f\xd9\xe2\xd9\x98\x5f\xd7\x64\xd6\xd8\xcf\xf4\x40\x7a\x6b\x72\x4b\x77\x54\x6d\x69\xf4\xad\x9f\xcc\xa1\xa8\x18\x49\xf9\x34\x0a\x57\x18\xd4\x30\x36\x34\x8b\xdb\x2c\xb9\xf4\x9a\xea\x05\x6e\x85\x0e\xbd\x73\x26\xc2\xca\x0a\x05\x81\xf4\x53\xcf\xfa\x19\x40\x22\x0d\x09\x63\xf8\xf2\x01\xe1\xad\x79\xc3\x86\xae\x6b\x4e", 254, { 0xce, 0x3c, 0x1c, 0xb0, 0xc1, 0xd5, 0x9a, 0x1f, 0xad, 0x95, 0x57, 0x98, 0xc6, 0x74, 0x61, 0x10 } }, +{ "\xf3\xc0\x10\x3f\xf2\xea\xca\xc4\xea\x01\xdf\x39\x6d\xce\x54\x61\xef\xdd\xf4\x42\x92\xe5\x70\x9d\x1c\xcf\xa0\x08\x0a\x65\xe8\xaa\xbe\x98\xb6\x93\xd3\x6d\x27\xb5\x91\x86\xc9\x83\x7c\x49\x7b\x25\x07\xaf\x71\x55\x66\xab\x54\xd9\x81\x34\x86\x9d\x04\xf1\x83\x6c\x93\x80\x63\x4b\x1b\x64\x7b\x72\x44\x89\x24\xe8\x02\x74\x93\xba\x4b\x0b\xe7\xd7\xe3\xfe\x42\x8b\x53\xd1\x0e\x96\xf8\x88\x61\xe9\x37\xee\x7b\xfc\xce\x81\x6c\xce\x46\xfd\xd3\x7a\x84\x83\xc1\x73\x7f\x66\xbb\x5c\x0c\x93\xde\x86\xd6\x9a\x1d\x07\x69\x5d\xa6\x73\x6d\x54\x64\x3a\xef\x7a\x9d\x9e\xdb\xd7\xba\x4f\x86\xab\x27\xa4\x68\x34\x51\x78\xe7\x1c\xcc\x9f\x4e\x83\x97\x04\xdc\xa4\x77\x61\xf9\x26\x7f\x99\x84\x01\xb1\xb5\x47\x0b\xbf\x79\x8c\x1f\xea\xa2\xc9\xe8\x0c\xbf\x76\x4f\xb1\xa9\xff\x7f\x5f\xa1\xd5\x91\xf6\x04\xa0\xd9\x32\xad\x8f\xcc\x4e\xe7\xcf\x8c\xc3\x0d\x19\x12\x2f\xc1\x66\xf7\x50\xc5\xbe\xdf\x2f\x79\x2e\x83\x59\xf1\xd8\x59\x48\xb2\x24\xe1\xe1\x0a\x15\x8e\x17\x09\xb6\x50\xad\x1f\xb3\xba\x18\x54\x03\xd5\x82\x1e\xc3\x80\xeb\xe2\x1f\x82\x6a\x0a\x69\x2e\x92", 255, { 0xbb, 0x05, 0x2f, 0x98, 0xc3, 0x43, 0x0a, 0x44, 0x7d, 0xae, 0x93, 0xea, 0x0a, 0x81, 0x4e, 0x3a } }, +{ "\xbf\x4b\xb1\xf0\x43\x19\xfc\xb0\xee\x40\x48\x5f\xc3\xdc\x4a\xca\xaf\x65\xf5\x06\x5d\x88\xe7\x89\xb8\x14\x71\x76\xfe\x0b\x46\xf6\x7e\xd9\xbf\xc1\xee\xa1\xc8\xbd\x6b\xb2\x6b\xbd\x0d\x18\xf7\x6a\x26\x4f\xcc\x3f\x18\x13\xc6\xae\xd0\x53\x44\x60\xe3\x43\xd4\x9a\x43\x91\x7c\xbb\x9d\xaf\xa7\xe1\x53\x4f\xab\xac\x11\xed\xf3\x1a\x0e\x85\xce\x92\xe1\x66\xd3\xfc\xfd\x1f\xee\x0d\xcb\x95\x0c\xa0\x63\x36\x5f\x40\xe6\x48\x4e\xc2\x7a\x5b\xfd\x0f\xe3\xdd\x74\x00\xbb\xcc\x6e\x62\x4e\x86\xc0\x18\x14\xbc\x64\x60\xcb\x85\x22\x2e\x31\x8f\xda\xb4\x5b\x70\x70\x03\xb5\x1a\x54\xcb\x97\x6d\xac\x3e\x7f\xe7\x21\x13\xf1\x77\x43\xa7\xe8\x6f\x9a\x3e\xf7\x97\x4a\x66\x01\x5d\x62\x7c\x91\x2a\xc1\x48\xd7\xd1\xa5\xc4\x40\x21\xd1\xfa\xb1\x9a\x5b\x0b\x5f\x3c\x0f\x4b\x4d\x7a\x83\x8a\x63\x4e\xb9\x6e\x28\x66\x6a\xfc\x1d\x7c\xf5\x35\xb5\xc3\xe4\xdd\xf4\x7d\x16\x57\xa2\xa9\x8f\xab\x2c\xda\xd9\xaa\x18\x23\x14\x29\x23\x2f\xa1\x69\xf9\x6d\x67\x97\x91\x68\xc0\x6e\x22\x34\x04\xfa\xc5\x04\xb0\x78\xa8\xd9\x32\x5a\xec\x55\x53\x66\x1d\xae\x41\xfe\x4b\xbe\x38\x7a", 256, { 0x64, 0xe1, 0xfd, 0x82, 0x3c, 0xe4, 0x10, 0x8b, 0x41, 0xca, 0x5d, 0xff, 0xed, 0x9f, 0x47, 0x22 } }, + diff --git a/cmdline/parity.c b/cmdline/parity.c new file mode 100644 index 0000000..6bfdbcd --- /dev/null +++ b/cmdline/parity.c @@ -0,0 +1,899 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "support.h" +#include "elem.h" +#include "state.h" +#include "parity.h" +#include "handle.h" + +/** + * Pseudo random limits for parity + */ +#define PARITY_LIMIT(size, split, level) \ + size ? size + (123562341 + split * 634542351 + level * 983491341) % size : 0 + +/****************************************************************************/ +/* parity */ + +block_off_t parity_allocated_size(struct snapraid_state* state) +{ + block_off_t parity_block; + tommy_node* i; + + /* compute the size of the parity file */ + parity_block = 0; + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* disk = i->data; + + /* start from the declared size */ + block_off_t block = fs_size(disk); + + /* decrease the block until an allocated one, but part of a file */ + /* we don't stop at deleted blocks, because we want to have them cleared */ + /* if they are at the end of the parity */ + while (block > parity_block && !block_has_file(fs_par2block_find(disk, block - 1))) + --block; + + /* get the highest value */ + if (block > parity_block) + parity_block = block; + } + + return parity_block; +} + +block_off_t parity_used_size(struct snapraid_state* state) +{ + block_off_t parity_block; + tommy_node* i; + + /* compute the size of the parity file */ + parity_block = 0; + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* disk = i->data; + + /* start from the declared size */ + block_off_t block = fs_size(disk); + + /* decrease the block until an used one */ + while (block > parity_block && !block_has_file_and_valid_parity(fs_par2block_find(disk, block - 1))) + --block; + + /* get the highest value */ + if (block > parity_block) + parity_block = block; + } + + return parity_block; +} + +int parity_is_invalid(struct snapraid_state* state) +{ + block_off_t blockmax; + block_off_t i; + + blockmax = parity_allocated_size(state); + + for (i = 0; i < blockmax; ++i) { + tommy_node* node_disk; + int one_invalid; + int one_valid; + + /* for each disk */ + one_invalid = 0; + one_valid = 0; + for (node_disk = state->disklist; node_disk != 0; node_disk = node_disk->next) { + struct snapraid_disk* disk = node_disk->data; + struct snapraid_block* block = fs_par2block_find(disk, i); + + if (block_has_file(block)) + one_valid = 1; + if (block_has_invalid_parity(block)) + one_invalid = 1; + } + + /* if both valid and invalid, we need to update */ + if (one_invalid && one_valid) + return 1; + } + + return 0; +} + +void parity_overflow(struct snapraid_state* state, data_off_t size) +{ + tommy_node* i; + block_off_t blockalloc; + int found = 0; + char esc_buffer[ESC_MAX]; + + /* don't report if everything is outside or if the file is not accessible */ + if (size == 0) { + return; + } + + blockalloc = size / state->block_size; + + /* for all disks */ + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* disk = i->data; + tommy_node* j; + + /* for all files */ + for (j = disk->filelist; j != 0; j = j->next) { + struct snapraid_file* file = j->data; + + if (file->blockmax > 0) { + block_off_t parity_pos = fs_file2par_get(disk, file, file->blockmax - 1); + if (parity_pos >= blockalloc) { + found = 1; + log_tag("outofparity:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + log_fatal("outofparity %s%s\n", disk->dir, file->sub); + } + } + } + } + + if (found) { + log_fatal("\nYour data requires more parity than the available space.\n"); + log_fatal("Please move the files 'outofparity' to another data disk.\n"); + } +} + +void parity_size(struct snapraid_parity_handle* handle, data_off_t* out_size) +{ + unsigned s; + data_off_t size; + + /* now compute the size summing all the parity splits */ + size = 0; + + for (s = 0; s < handle->split_mac; ++s) { + struct snapraid_split_handle* split = &handle->split_map[s]; + + size += split->size; + } + + *out_size = size; +} + +int parity_create(struct snapraid_parity_handle* handle, const struct snapraid_parity* parity, unsigned level, int mode, uint32_t block_size, data_off_t limit_size) +{ + unsigned s; + data_off_t block_mask; + + /* mask of bits used by the block size */ + block_mask = ((data_off_t)block_size) - 1; + + handle->level = level; + handle->split_mac = 0; + + for (s = 0; s < parity->split_mac; ++s) { + struct snapraid_split_handle* split = &handle->split_map[s]; + int ret; + int flags; + + advise_init(&split->advise, mode); + pathcpy(split->path, sizeof(split->path), parity->split_map[s].path); + split->size = parity->split_map[s].size; + split->limit_size = PARITY_LIMIT(limit_size, s, level); + + /* opening in sequential mode in Windows */ + flags = O_RDWR | O_CREAT | O_BINARY | advise_flags(&split->advise); + split->f = open(split->path, flags, 0600); + if (split->f == -1) { + /* LCOV_EXCL_START */ + log_fatal("Error opening parity file '%s'. %s.\n", split->path, strerror(errno)); + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* we have a valid file handle */ + ++handle->split_mac; + + /* get the stat info */ + ret = fstat(split->f, &split->st); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error accessing parity file '%s'. %s.\n", split->path, strerror(errno)); + goto bail; + /* LCOV_EXCL_STOP */ + } + + /** + * If the parity size is not yet set, set it now. + * This happens when expanding the number of parities, + * or when upgrading from a content file that has not split->size data. + */ + if (split->size == PARITY_SIZE_INVALID) { + split->size = split->st.st_size; + + /* ensure that the resulting size if block aligned */ + if ((split->size & block_mask) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error in preallocated size of parity file '%s' with size %" PRIu64 " and block %u .\n", split->path, split->size, block_size); + goto bail; + /* LCOV_EXCL_STOP */ + } + } + + ret = advise_open(&split->advise, split->f); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error advising parity file '%s'. %s.\n", split->path, strerror(errno)); + goto bail; + /* LCOV_EXCL_STOP */ + } + } + + return 0; + +bail: + /* LCOV_EXCL_START */ + for (s = 0; s < handle->split_mac; ++s) { + struct snapraid_split_handle* split = &handle->split_map[s]; + close(split->f); + split->f = -1; + } + return -1; + /* LCOV_EXCL_STOP */ +} + +static int parity_handle_grow(struct snapraid_split_handle* split, data_off_t previous_size, data_off_t size, int skip_fallocate) +{ + int ret; + + (void)previous_size; + + /* simulate a failure for testing limits */ + if (split->limit_size != 0 && size > (data_off_t)split->limit_size) + return -1; + +#if HAVE_FALLOCATE + if (!skip_fallocate) { + /* + * Allocate real space using the specific Linux fallocate() operation. + * If the underline file-system doesn't support it, this operation fails. + * + * Instead posix_fallocate() fallbacks to write the whole file, + * and we cannot use it as we may need to initialize a multi terabyte + * file. + * + * See: fallocate vs posix_fallocate + * http://stackoverflow.com/questions/14063046/fallocate-vs-posix-fallocate + * + * To work better with Btrfs, use as offset the previous allocated size. + * Otherwise Btrfs will count as space needed even the already allocated one. + * + * See: Massive loss of disk space + * https://www.mail-archive.com/linux-btrfs@vger.kernel.org/msg66454.html + */ + ret = fallocate(split->f, 0, previous_size, size - previous_size); + + /* + * In some legacy system fallocate() may return the error number + * as positive integer, and in this case it doesn't set errno. + * + * Detect and handle this case. + * + * See: Fix fallocate error return on i386 + * https://sourceware.org/ml/libc-hacker/2010-04/msg00000.html + * + * See: [PATCH XFS] Fix error return for fallocate() on XFS + * http://oss.sgi.com/archives/xfs/2009-11/msg00201.html + */ + if (ret > 0) { + /* LCOV_EXCL_START */ + errno = ret; + ret = -1; + /* LCOV_EXCL_STOP */ + } + } else { + errno = EOPNOTSUPP; + ret = -1; + } + + /* + * Fallback to ftruncate() if the operation is not supported. + * + * We get EOPNOTSUPP if the operation is not supported, like in ext3/ext2 + * or ENOSYS with kernel before 2.6.23, because fallocate is not supported + * at all. + * + * See: man fallocate + * ENOSYS - This kernel does not implement fallocate(). + * EOPNOTSUPP - The file system containing the file referred to by fd does not support this operation + */ + if (ret != 0 && (errno == EOPNOTSUPP || errno == ENOSYS)) { + /* fallback using ftruncate() */ + ret = ftruncate(split->f, size); + } +#else + (void)skip_fallocate; /* avoid the warning */ + + /* allocate using a sparse file */ + ret = ftruncate(split->f, size); +#endif + + if (ret != 0) + log_tag("split:grow:%s:%" PRIu64 ": failed with error %s\n", split->path, size, strerror(errno)); + else + log_tag("split:grow:%s:%" PRIu64 ": ok\n", split->path, size); + + return ret; +} + +static int parity_handle_shrink(struct snapraid_split_handle* split, data_off_t size) +{ + int ret; + + ret = ftruncate(split->f, size); + + if (ret != 0) + log_tag("split:shrink:%s:%" PRIu64 ": failed with error %s\n", split->path, size, strerror(errno)); + else + log_tag("split:shrink:%s:%" PRIu64 ": ok\n", split->path, size); + + return ret; +} + +/** + * Get the highest bit set. + */ +uint64_t hbit_u64(uint64_t v) +{ + unsigned ilog; + + ilog = 0; + while ((v /= 2) != 0) + ++ilog; + + return 1ULL << ilog; +} + +static int parity_handle_fill(struct snapraid_split_handle* split, data_off_t size, uint32_t block_size, int skip_fallocate, int skip_space_holder) +{ + data_off_t base; + data_off_t delta; + data_off_t block_mask; + +#ifdef _WIN32 + /* + * In Windows we want to avoid the annoying warning + * message of disk full. + * + * To ensure to leave some space available, we first create + * a spaceholder file >200 MB, to ensure to not fill completely + * the disk. + */ + char spaceholder_path[PATH_MAX]; + + pathprint(spaceholder_path, sizeof(spaceholder_path), "%s%s", split->path, ".spaceholder"); + + if (!skip_space_holder) { + data_off_t spaceholder_size = 256 * 1024 * 1024; + int spaceholder_f; + + spaceholder_f = open(spaceholder_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0600); + if (spaceholder_f == -1) { + log_fatal("Failed to create space holder file '%s'.\n", spaceholder_path); + return -1; + } + + /* note that in Windows ftruncate is really allocating space */ + if (ftruncate(spaceholder_f, spaceholder_size) != 0) { + log_fatal("WARNING Failed to resize the space holder file '%s' to %" PRIu64 " bytes.\n", spaceholder_path, spaceholder_size); + log_fatal("Assuming that no more space is available.\n"); + close(spaceholder_f); + remove(spaceholder_path); + return 0; + } + + if (fsync(spaceholder_f) != 0) { + log_fatal("Failed to sync the space holder file '%s'.\n", spaceholder_path); + close(spaceholder_f); + remove(spaceholder_path); + return -1; + } + + if (close(spaceholder_f) != 0) { + log_fatal("Failed to close the space holder file '%s'.\n", spaceholder_path); + remove(spaceholder_path); + return -1; + } + } +#else + (void)skip_space_holder; +#endif + + /* mask of bits used by the block size */ + block_mask = ((data_off_t)block_size) - 1; + + /* present size */ + base = split->st.st_size; + + /* truncate it to block size multiplier */ + /* in case of damage the size may get wrong */ + base &= ~block_mask; + + /* size we have to increase */ + delta = size - base; + + log_tag("split:fill:%s:%" PRIu64 ":%" PRIu64 ":\n", split->path, base, size); + + /* grow the size one bit at time, like a kind of binary search */ + while (delta != 0) { + int ret; + data_off_t run = hbit_u64(delta); + + /* mask out the bit we process */ + delta &= ~run; + + log_tag("split:delta:%s:%" PRIu64 ":%" PRIu64 ":\n", split->path, base, run); + + ret = parity_handle_grow(split, base, base + run, skip_fallocate); + if (ret != 0) { + /* we cannot grow, fallback enabling all the smaller bits */ + delta = run - 1; + + /* mask out the block size */ + delta &= ~block_mask; + } else { + /* increase the effective size */ + base += run; + } + } + + /* ensure that the resulting size if block aligned */ + if ((base & block_mask) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in requested parity size %" PRIu64 " with block %u\n", base, block_size); + os_abort(); + /* LCOV_EXCL_STOP */ + } + +#ifdef _WIN32 + /* now delete the spaceholder file */ + if (remove(spaceholder_path) != 0) { + log_fatal("WARNING Failed to remove the space holder file '%s'.\n", spaceholder_path); + log_fatal("Continuing anyway.\n"); + } +#endif + + /* shrink to the expected size to ensure to throw away any extra */ + /* data allocated when the grow operation fails */ + return parity_handle_shrink(split, base); +} + +static int parity_handle_chsize(struct snapraid_split_handle* split, data_off_t size, uint32_t block_size, int skip_fallocate, int skip_space_holder) +{ + int ret; + int f_ret; + int f_errno; + int f_dir; + + if (split->st.st_size < size) { + f_ret = parity_handle_fill(split, size, block_size, skip_fallocate, skip_space_holder); + f_errno = errno; + f_dir = 1; + } else if (split->st.st_size > size) { + f_ret = parity_handle_shrink(split, size); + f_errno = errno; + f_dir = -1; + } else { + f_ret = 0; + f_errno = 0; + f_dir = 0; + } + + /* get the stat info */ + ret = fstat(split->f, &split->st); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error accessing parity file '%s'. %s.\n", split->path, strerror(errno)); + return -1; + /* LCOV_EXCL_STOP */ + } + + /* now check the error */ + if (f_ret != 0) { + /* LCOV_EXCL_START */ + if (f_dir > 0) { + if (f_errno == ENOSPC) { + log_fatal("Failed to grow parity file '%s' to size %" PRIu64 " due lack of space.\n", split->path, size); + } else { + log_fatal("Error growing parity file '%s' to size %" PRIu64 ". Do you have enough space? %s.\n", split->path, size, strerror(f_errno)); + } + } else { + log_fatal("Error truncating parity file '%s' to size %" PRIu64 ". %s.\n", split->path, size, strerror(f_errno)); + } + return -1; + /* LCOV_EXCL_STOP */ + } + + return 0; +} + +static int parity_split_is_fixed(struct snapraid_parity_handle* handle, unsigned s) +{ + /* next one */ + ++s; + + /* the latest one is always growing */ + if (s >= handle->split_mac) + return 0; + + /* if the next it's 0, this one is growing */ + if (handle->split_map[s].size == 0) + return 0; + + return 1; +} + +int parity_chsize(struct snapraid_parity_handle* handle, struct snapraid_parity* parity, int* is_modified, data_off_t size, uint32_t block_size, int skip_fallocate, int skip_space_holder) +{ + int ret; + unsigned s; + data_off_t block_mask; + + /* mask of bits used by the block size */ + block_mask = ((data_off_t)block_size) - 1; + + if (size < 0) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + + for (s = 0; s < handle->split_mac; ++s) { + struct snapraid_split_handle* split = &handle->split_map[s]; + int is_fixed = parity_split_is_fixed(handle, s); + data_off_t run; + + if (is_fixed) { + /* if the required size is smaller, we have to reduce also the file */ + /* ignoring the previous size */ + if (size <= split->size) { + /* mark it as not fixed anymore for the later check */ + is_fixed = 0; + + run = size; /* allocate only the needed size */ + } else { + /* if the size cannot be changed, use the fixed one */ + run = split->size; + + if ((run & block_mask) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in split '%s' size with extra '%" PRIu64 "' bytes.\n", split->path, run & block_mask); + return -1; + /* LCOV_EXCL_STOP */ + } + } + } else { + /* otherwise tries to allocate all the needed remaining size */ + run = size; + } + + ret = parity_handle_chsize(split, run, block_size, skip_fallocate, skip_space_holder); + if (ret != 0) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + + if (split->st.st_size > run) { + /* LCOV_EXCL_START */ + log_fatal("Unexpected over resizing parity file '%s' to size %" PRIu64 " resulting in size %" PRIu64 ".\n", split->path, run, (uint64_t)split->st.st_size); + return -1; + /* LCOV_EXCL_STOP */ + } else if (is_fixed && split->st.st_size < run) { + /* LCOV_EXCL_START */ + log_fatal("Failed restoring parity file '%s' to size %" PRIu64 " resulting in size %" PRIu64 ".\n", split->path, run, (uint64_t)split->st.st_size); + return -1; + /* LCOV_EXCL_STOP */ + } else { + /* here it's possible to get less than the requested size */ + run = split->st.st_size; + + if ((run & block_mask) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in final parity size %" PRIu64 " with block size %u\n", run, block_size); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* store what we have allocated */ + split->size = run; + + /* decrease the remaining size */ + size -= run; + } + } + + /* if we cannot allocate all the space */ + if (size != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to allocate all the required parity space. You miss %" PRIu64 " bytes.\n", size); + return -1; + /* LCOV_EXCL_STOP */ + } + + /* now copy the new size in the parity data */ + if (is_modified) + *is_modified = 0; + + for (s = 0; s < handle->split_mac; ++s) { + struct snapraid_split_handle* split = &handle->split_map[s]; + + if (parity->split_map[s].size != split->size) { + parity->split_map[s].size = split->size; + if (is_modified) + *is_modified = 1; + } + } + + return 0; +} + +int parity_open(struct snapraid_parity_handle* handle, const struct snapraid_parity* parity, unsigned level, int mode, uint32_t block_size, data_off_t limit_size) +{ + unsigned s; + data_off_t block_mask; + + handle->level = level; + handle->split_mac = 0; + + /* mask of bits used by the block size */ + block_mask = ((data_off_t)block_size) - 1; + + for (s = 0; s < parity->split_mac; ++s) { + struct snapraid_split_handle* split = &handle->split_map[s]; + int ret; + int flags; + + advise_init(&split->advise, mode); + pathcpy(split->path, sizeof(split->path), parity->split_map[s].path); + split->size = parity->split_map[s].size; + split->limit_size = PARITY_LIMIT(limit_size, s, level); + + /* open for read */ + /* O_NOATIME: do not change access time */ + flags = O_RDONLY | O_BINARY | advise_flags(&split->advise); + + split->f = open_noatime(split->path, flags); + if (split->f == -1) { + /* LCOV_EXCL_START */ + log_fatal("Error opening parity file '%s'. %s.\n", split->path, strerror(errno)); + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* we have a valid file handle */ + ++handle->split_mac; + + /* get the stat info */ + ret = fstat(split->f, &split->st); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error accessing parity file '%s'. %s.\n", split->path, strerror(errno)); + goto bail; + /* LCOV_EXCL_STOP */ + } + + /** + * If the parity size is not yet set, set it now. + * This happens when expanding the number of parities, + * or when upgrading from a content file that has not split->size data. + */ + if (split->size == PARITY_SIZE_INVALID) { + split->size = split->st.st_size; + + /* ensure that the resulting size if block aligned */ + if ((split->size & block_mask) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error in preallocated size of parity file '%s' with size %" PRIu64 " and block %u .\n", split->path, split->size, block_size); + goto bail; + /* LCOV_EXCL_STOP */ + } + } + + ret = advise_open(&split->advise, split->f); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error advising parity file '%s'. %s.\n", split->path, strerror(errno)); + goto bail; + /* LCOV_EXCL_STOP */ + } + } + + return 0; + +bail: + /* LCOV_EXCL_START */ + for (s = 0; s < handle->split_mac; ++s) { + struct snapraid_split_handle* split = &handle->split_map[s]; + close(split->f); + split->f = -1; + } + return -1; + /* LCOV_EXCL_STOP */ +} + +int parity_sync(struct snapraid_parity_handle* handle) +{ +#if HAVE_FSYNC + unsigned s; + + for (s = 0; s < handle->split_mac; ++s) { + struct snapraid_split_handle* split = &handle->split_map[s]; + int ret; + + /* Ensure that data changes are written to disk. */ + /* This is required to ensure that parity is more updated than content */ + /* in case of a system crash. */ + ret = fsync(split->f); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error synching parity file '%s'. %s.\n", split->path, strerror(errno)); + return -1; + /* LCOV_EXCL_STOP */ + } + } +#endif + + return 0; +} + +int parity_close(struct snapraid_parity_handle* handle) +{ + unsigned s; + int f_ret = 0; + + for (s = 0; s < handle->split_mac; ++s) { + struct snapraid_split_handle* split = &handle->split_map[s]; + int ret; + + ret = close(split->f); + if (ret != 0) { + /* LCOV_EXCL_START */ + /* This is a serious error, as it may be the result of a failed write */ + /* identified at later time. */ + /* In a normal file-system (not NFS) it should never happen */ + log_fatal("Error closing parity file '%s'. %s.\n", split->path, strerror(errno)); + f_ret = -1; + /* LCOV_EXCL_STOP */ + + /* continue to close the others */ + } + + /* reset the descriptor */ + split->f = -1; + } + + return f_ret; +} + +struct snapraid_split_handle* parity_split_find(struct snapraid_parity_handle* handle, data_off_t* offset) +{ + unsigned s; + + if (*offset < 0) + return 0; + + for (s = 0; s < handle->split_mac; ++s) { + struct snapraid_split_handle* split = &handle->split_map[s]; + + if (*offset < split->size) + return split; + + *offset -= split->size; + } + + return 0; +} + +int parity_write(struct snapraid_parity_handle* handle, block_off_t pos, unsigned char* block_buffer, unsigned block_size) +{ + ssize_t write_ret; + data_off_t offset; + struct snapraid_split_handle* split; + int ret; + + offset = pos * (data_off_t)block_size; + + split = parity_split_find(handle, &offset); + if (!split) { + /* LCOV_EXCL_START */ + log_fatal("Writing parity data outside range at extra offset %" PRIu64 ".\n", offset); + return -1; + /* LCOV_EXCL_STOP */ + } + + write_ret = pwrite(split->f, block_buffer, block_size, offset); + if (write_ret != (ssize_t)block_size) { /* conversion is safe because block_size is always small */ + /* LCOV_EXCL_START */ + if (errno == ENOSPC) { + log_fatal("Failed to grow parity file '%s' using write due lack of space.\n", split->path); + } else { + log_fatal("Error writing file '%s'. %s.\n", split->path, strerror(errno)); + } + return -1; + /* LCOV_EXCL_STOP */ + } + + ret = advise_write(&split->advise, split->f, offset, block_size); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error advising parity file '%s'. %s.\n", split->path, strerror(errno)); + return -1; + /* LCOV_EXCL_STOP */ + } + + return 0; +} + +int parity_read(struct snapraid_parity_handle* handle, block_off_t pos, unsigned char* block_buffer, unsigned block_size, fptr* out) +{ + ssize_t read_ret; + data_off_t offset; + unsigned count; + struct snapraid_split_handle* split; + int ret; + + offset = pos * (data_off_t)block_size; + + split = parity_split_find(handle, &offset); + if (!split) { + /* LCOV_EXCL_START */ + out("Reading parity data outside range at extra offset %" PRIu64 ".\n", offset); + return -1; + /* LCOV_EXCL_STOP */ + } + + count = 0; + do { + read_ret = pread(split->f, block_buffer + count, block_size - count, offset + count); + if (read_ret < 0) { + /* LCOV_EXCL_START */ + out("Error reading file '%s' at offset %" PRIu64 " for size %u. %s.\n", split->path, offset + count, block_size - count, strerror(errno)); + return -1; + /* LCOV_EXCL_STOP */ + } + if (read_ret == 0) { + /* LCOV_EXCL_START */ + out("Unexpected end of file '%s' at offset %" PRIu64 ". %s.\n", split->path, offset, strerror(errno)); + return -1; + /* LCOV_EXCL_STOP */ + } + + count += read_ret; + } while (count < block_size); + + ret = advise_read(&split->advise, split->f, offset, block_size); + if (ret != 0) { + /* LCOV_EXCL_START */ + out("Error advising parity file '%s'. %s.\n", split->path, strerror(errno)); + return -1; + /* LCOV_EXCL_STOP */ + } + + return block_size; +} + diff --git a/cmdline/parity.h b/cmdline/parity.h new file mode 100644 index 0000000..056362e --- /dev/null +++ b/cmdline/parity.h @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#ifndef __PARITY_H +#define __PARITY_H + +#include "support.h" + +/****************************************************************************/ +/* parity */ + +struct snapraid_split_handle { + char path[PATH_MAX]; /**< Path of the file. */ + int f; /**< Handle of the files. */ + struct stat st; /**< Stat info of the opened file. */ + struct advise_struct advise; /**< Advise information. */ + + /** + * Size of the parity split. + * Only the latest not zero size is allowed to grow. + * Note that this value CANNOT be PARITY_SIZE_INVALID. + */ + data_off_t size; + + /** + * Artificial size limit for testing. + * 0 means unlimited. + */ + data_off_t limit_size; +}; + +struct snapraid_parity_handle { + struct snapraid_split_handle split_map[SPLIT_MAX]; + unsigned split_mac; /**< Number of parity splits. */ + unsigned level; /**< Level of the parity. */ +}; + +/** + * Compute the size of the allocated parity data in number of blocks. + * + * This includes parity blocks not yet written and still invalid. + */ +block_off_t parity_allocated_size(struct snapraid_state* state); + +/** + * Compute the size of the used parity data in number of blocks. + * + * This includes only parity blocks used for files, not counting + * potential invalid parity at the end. + * + * If the array is fully synced there is no difference between + * parity_allocate_size() and parity_used_size(). + * But if the sync is interrupted, the parity_used_size() returns + * the position of the latest BLK block, ignoring CHG, REL and DELETED ones, + * because their parity may be still not even written in the parity file. + */ +block_off_t parity_used_size(struct snapraid_state* state); + +/** + * Check if the parity needs to be updated with a "sync". + * + * This is the same logic used in "status" to detect an incomplete "sync", + * that ignores invalid block, if they are not used by a file in any disk. + * This means that DELETED blocks won't necessarily imply an invalid parity. + */ +int parity_is_invalid(struct snapraid_state* state); + +/** + * Report all the files outside the specified parity size. + */ +void parity_overflow(struct snapraid_state* state, data_off_t size); + +/** + * Create the parity file. + * \param out_size Return the size of the parity file. + */ +int parity_create(struct snapraid_parity_handle* handle, const struct snapraid_parity* parity, unsigned level, int mode, uint32_t block_size, data_off_t limit_size); + +/** + * Change the parity size. + * \param out_size Return the size of the parity file. The out_size is set also on error to reflect a partial resize. + */ +int parity_chsize(struct snapraid_parity_handle* handle, struct snapraid_parity* parity, int* is_modified, data_off_t size, uint32_t block_size, int skip_fallocate, int skip_space_holder); + +/** + * Get the size of the parity. + * + * This returns the cached/expected version of the split sizes, and not the real file size. + */ +void parity_size(struct snapraid_parity_handle* handle, data_off_t* out_size); + +/** + * Open an already existing parity file. + */ +int parity_open(struct snapraid_parity_handle* handle, const struct snapraid_parity* parity, unsigned level, int mode, uint32_t block_size, data_off_t limit_size); + +/** + * Flush the parity file in the disk. + */ +int parity_sync(struct snapraid_parity_handle* handle); + +/** + * Close the parity file. + */ +int parity_close(struct snapraid_parity_handle* handle); + +/** + * Read a block from the parity file. + */ +int parity_read(struct snapraid_parity_handle* handle, block_off_t pos, unsigned char* block_buffer, unsigned block_size, fptr* out); + +/** + * Write a block in the parity file. + */ +int parity_write(struct snapraid_parity_handle* handle, block_off_t pos, unsigned char* block_buffer, unsigned block_size); + +#endif + diff --git a/cmdline/pool.c b/cmdline/pool.c new file mode 100644 index 0000000..44e3510 --- /dev/null +++ b/cmdline/pool.c @@ -0,0 +1,470 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "support.h" +#include "elem.h" +#include "state.h" + +struct snapraid_pool { + char file[PATH_MAX]; + char linkto[PATH_MAX]; + int64_t mtime_sec; + int mtime_nsec; + + /* nodes for data structures */ + tommy_hashdyn_node node; +}; + +struct snapraid_pool* pool_alloc(const char* dir, const char* name, const char* linkto, const struct stat* st) +{ + struct snapraid_pool* pool; + + pool = malloc_nofail(sizeof(struct snapraid_pool)); + pathprint(pool->file, sizeof(pool->file), "%s%s", dir, name); + pathcpy(pool->linkto, sizeof(pool->linkto), linkto); + pool->mtime_sec = st->st_mtime; + pool->mtime_nsec = STAT_NSEC(st); + + return pool; +} + +static inline tommy_uint32_t pool_hash(const char* file) +{ + return tommy_hash_u32(0, file, strlen(file)); +} + +void pool_free(struct snapraid_pool* pool) +{ + free(pool); +} + +int pool_compare(const void* void_arg, const void* void_data) +{ + const char* arg = void_arg; + const struct snapraid_pool* pool = void_data; + + return strcmp(arg, pool->file); +} + +/** + * Remove empty dir. + * Return == 0 if the directory is empty, and it can be removed + */ +static int clean_dir(const char* dir) +{ + DIR* d; + int full = 0; + + d = opendir(dir); + if (!d) { + /* LCOV_EXCL_START */ + log_fatal("Error opening pool directory '%s'. %s.\n", dir, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + while (1) { + char path_next[PATH_MAX]; + struct stat st; + const char* name; + struct dirent* dd; + + /* clear errno to detect erroneous conditions */ + errno = 0; + dd = readdir(d); + if (dd == 0 && errno != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error reading pool directory '%s'. %s.\n", dir, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (dd == 0 && errno == 0) { + break; /* finished */ + } + + /* skip "." and ".." files */ + name = dd->d_name; + if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) + continue; + + pathprint(path_next, sizeof(path_next), "%s%s", dir, name); + +#if HAVE_STRUCT_DIRENT_D_STAT + /* convert dirent to lstat result */ + dirent_lstat(dd, &st); + + /* if the st_mode field is missing, takes care to fill it using normal lstat() */ + /* at now this can happen only in Windows */ + if (st.st_mode == 0) { + if (lstat(path_next, &st) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } +#else + /* get lstat info about the file */ + if (lstat(path_next, &st) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } +#endif + + if (S_ISDIR(st.st_mode)) { + /* recurse */ + pathslash(path_next, sizeof(path_next)); + if (clean_dir(path_next) == 0) { + int ret; + + /* directory is empty, try to remove it */ + ret = rmdir(path_next); + if (ret < 0) { +#ifdef _WIN32 + if (errno == EACCES) { + /* in Windows just ignore EACCES errors removing directories */ + /* because it could happen that the directory is in use */ + /* and it cannot be removed */ + log_fatal("Directory '%s' not removed because it's in use.\n", path_next); + full = 1; + } else +#endif + { + /* LCOV_EXCL_START */ + log_fatal("Error removing pool directory '%s'. %s.\n", path_next, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + } else { + /* something is present */ + full = 1; + } + } else { + /* something is present */ + full = 1; + } + } + + if (closedir(d) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error closing pool directory '%s'. %s.\n", dir, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + return full; +} + +/** + * Read all the links in a directory tree. + */ +static void read_dir(tommy_hashdyn* poolset, const char* base_dir, const char* sub_dir) +{ + char dir[PATH_MAX]; + DIR* d; + + pathprint(dir, sizeof(dir), "%s%s", base_dir, sub_dir); + d = opendir(dir); + if (!d) { + /* LCOV_EXCL_START */ + log_fatal("Error opening pool directory '%s'. %s.\n", dir, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + while (1) { + char path_next[PATH_MAX]; + struct stat st; + const char* name; + struct dirent* dd; + + /* clear errno to detect erroneous conditions */ + errno = 0; + dd = readdir(d); + if (dd == 0 && errno != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error reading pool directory '%s'. %s.\n", dir, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (dd == 0 && errno == 0) { + break; /* finished */ + } + + /* skip "." and ".." files */ + name = dd->d_name; + if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) + continue; + + pathprint(path_next, sizeof(path_next), "%s%s", dir, name); + +#if HAVE_STRUCT_DIRENT_D_STAT + /* convert dirent to lstat result */ + dirent_lstat(dd, &st); + + /* if the st_mode field is missing, takes care to fill it using normal lstat() */ + /* at now this can happen only in Windows */ + if (st.st_mode == 0) { + if (lstat(path_next, &st) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } +#else + /* get lstat info about the file */ + if (lstat(path_next, &st) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } +#endif + + if (S_ISLNK(st.st_mode)) { + struct snapraid_pool* pool; + char linkto[PATH_MAX]; + int ret; + + ret = readlink(path_next, linkto, sizeof(linkto)); + if (ret < 0 || ret >= PATH_MAX) { + /* LCOV_EXCL_START */ + log_fatal("Error in readlink symlink '%s'. %s.\n", path_next, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + linkto[ret] = 0; + + /* store the link info */ + pool = pool_alloc(sub_dir, name, linkto, &st); + + tommy_hashdyn_insert(poolset, &pool->node, pool, pool_hash(pool->file)); + + } else if (S_ISDIR(st.st_mode)) { + pathprint(path_next, sizeof(path_next), "%s%s/", sub_dir, name); + + read_dir(poolset, base_dir, path_next); + } else { + msg_verbose("Ignoring pool file '%s'\n", path_next); + } + } + + if (closedir(d) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error closing pool directory '%s'. %s.\n", dir, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } +} + +/** + * Remove the link + */ +static void remove_link(void* void_arg, void* void_pool) +{ + char path[PATH_MAX]; + const char* arg = void_arg; + struct snapraid_pool* pool = void_pool; + int ret; + + pathprint(path, sizeof(path), "%s%s", arg, pool->file); + + /* delete the link */ + ret = remove(path); + if (ret < 0) { + /* LCOV_EXCL_START */ + log_fatal("Error removing symlink '%s'. %s.\n", path, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } +} + +/** + * Create a link to the specified disk link. + */ +static void make_link(tommy_hashdyn* poolset, const char* pool_dir, const char* share_dir, struct snapraid_disk* disk, const char* sub, int64_t mtime_sec, int mtime_nsec) +{ + char path[PATH_MAX]; + char linkto[PATH_MAX]; + char linkto_exported[PATH_MAX]; + struct snapraid_pool* found; + int ret; + + /* make the source path */ + pathprint(path, sizeof(path), "%s%s", pool_dir, sub); + + /* make the linkto path */ + if (share_dir[0] != 0) { + /* with a shared directory, use it */ + pathprint(linkto, sizeof(linkto), "%s%s/%s", share_dir, disk->name, sub); + } else { + /* without a share directory, use the local disk paths */ + pathprint(linkto, sizeof(linkto), "%s%s", disk->dir, sub); + } + + /* search for the sub path */ + found = tommy_hashdyn_search(poolset, pool_compare, sub, pool_hash(sub)); + if (found) { + /* remove from the set */ + tommy_hashdyn_remove_existing(poolset, &found->node); + + /* check if the info match */ + if (found->mtime_sec == mtime_sec + && found->mtime_nsec == mtime_nsec + && strcmp(found->linkto, linkto) == 0 + ) { + /* nothing to do */ + pool_free(found); + return; + } + + /* delete the link */ + ret = remove(path); + if (ret < 0) { + /* LCOV_EXCL_START */ + log_fatal("Error removing symlink '%s'. %s.\n", path, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + pool_free(found); + } + + /* create the ancestor directories */ + ret = mkancestor(path); + if (ret != 0) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* convert back slashes */ + pathexport(linkto_exported, sizeof(linkto_exported), linkto); + + /* create the symlink */ + ret = symlink(linkto_exported, path); + if (ret != 0) { + if (errno == EEXIST) { + log_fatal("WARNING! Duplicate pooling for '%s'\n", path); +#ifdef _WIN32 + } else if (errno == EPERM) { + /* LCOV_EXCL_START */ + log_fatal("You must run as Adminstrator to be able to create symlinks.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ +#endif + } else { + /* LCOV_EXCL_START */ + log_fatal("Error writing symlink '%s'. %s.\n", path, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + if (mtime_sec) { + ret = lmtime(path, mtime_sec, mtime_nsec); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error setting time to symlink '%s'. %s.\n", path, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } +} + +void state_pool(struct snapraid_state* state) +{ + tommy_hashdyn poolset; + tommy_node* i; + char pool_dir[PATH_MAX]; + char share_dir[PATH_MAX]; + unsigned count; + + tommy_hashdyn_init(&poolset); + + if (state->pool[0] == 0) { + /* LCOV_EXCL_START */ + log_fatal("To use the 'pool' command you must set the pool directory in the configuration file\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + msg_progress("Reading...\n"); + + /* pool directory with final slash */ + pathprint(pool_dir, sizeof(pool_dir), "%s", state->pool); + pathslash(pool_dir, sizeof(pool_dir)); + + /* share directory with final slash */ + pathprint(share_dir, sizeof(share_dir), "%s", state->share); + pathslash(share_dir, sizeof(share_dir)); + + /* first read the previous pool tree */ + read_dir(&poolset, pool_dir, ""); + + msg_progress("Writing...\n"); + + /* for each disk */ + count = 0; + for (i = state->disklist; i != 0; i = i->next) { + tommy_node* j; + struct snapraid_disk* disk = i->data; + + /* for each file */ + for (j = disk->filelist; j != 0; j = j->next) { + struct snapraid_file* file = j->data; + make_link(&poolset, pool_dir, share_dir, disk, file->sub, file->mtime_sec, file->mtime_nsec); + ++count; + } + + /* for each link */ + for (j = disk->linklist; j != 0; j = j->next) { + struct snapraid_link* slink = j->data; + make_link(&poolset, pool_dir, share_dir, disk, slink->sub, 0, 0); + ++count; + } + + /* we ignore empty dirs in disk->dir */ + } + + msg_progress("Cleaning...\n"); + + /* delete all the remaining links */ + tommy_hashdyn_foreach_arg(&poolset, (tommy_foreach_arg_func*)remove_link, pool_dir); + + /* delete empty dirs */ + clean_dir(pool_dir); + + tommy_hashdyn_foreach(&poolset, (tommy_foreach_func*)pool_free); + tommy_hashdyn_done(&poolset); + + if (count) + msg_status("%u links\n", count); + else + msg_status("No link\n"); + + log_tag("summary:link_count::%u\n", count); + log_tag("summary:exit:ok\n"); + log_flush(); +} + diff --git a/cmdline/portable.h b/cmdline/portable.h new file mode 100644 index 0000000..053ad85 --- /dev/null +++ b/cmdline/portable.h @@ -0,0 +1,492 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#ifndef __PORTABLE_H +#define __PORTABLE_H + +#if HAVE_CONFIG_H +#include "config.h" /* Use " to include first in the same directory of this file */ +#endif + +/***************************************************************************/ +/* Config */ + +#ifdef __MINGW32__ +/** + * Enable the GNU printf functions instead of using the MSVCRT ones. + * + * Note that this is the default if _POSIX is also defined. + * To disable it you have to set it to 0. + */ +#define __USE_MINGW_ANSI_STDIO 1 + +/** + * Define the MSVCRT version targetting Windows Vista. + */ +#define __MSVCRT_VERSION__ 0x0600 + +/** + * Include Windows Vista headers. + * + * Like for InitializeCriticalSection(). + */ +#define _WIN32_WINNT 0x600 + +/** + * Enable the rand_s() function.l + */ +#define _CRT_RAND_S + +#include +#endif + +/** + * Specify the format attribute for printf. + */ +#ifdef __MINGW32__ +#if defined(__USE_MINGW_ANSI_STDIO) && __USE_MINGW_ANSI_STDIO == 1 +#define attribute_printf gnu_printf /* GNU format */ +#else +#define attribute_printf ms_printf /* MSVCRT format */ +#endif +#else +#define attribute_printf printf /* GNU format is the default one */ +#endif + +/** + * Compiler extension + */ +#ifndef __always_inline +#define __always_inline inline __attribute__((always_inline)) +#endif + +#ifndef __noreturn +#define __noreturn __attribute__((noreturn)) +#endif + + +/** + * Architecture for inline assembly. + */ +#if HAVE_ASSEMBLY +#if defined(__i386__) +#define CONFIG_X86 1 +#define CONFIG_X86_32 1 +#endif + +#if defined(__x86_64__) +#define CONFIG_X86 1 +#define CONFIG_X86_64 1 +#endif +#endif + +/** + * Includes some platform specific headers. + */ +#if HAVE_SYS_PARAM_H +#include +#endif + +#if HAVE_SYS_MOUNT_H +#include +#endif + +#if HAVE_SYS_VFS_H +#include +#endif + +#if HAVE_SYS_STATFS_H +#include +#endif + +#if HAVE_SYS_FILE_H +#include +#endif + +#if HAVE_SYS_IOCTL_H +#include +#endif + +#if HAVE_LINUX_FS_H +#include +#endif + +#if HAVE_LINUX_FIEMAP_H +#include +#endif + +#if HAVE_BLKID_BLKID_H +#include +#if HAVE_BLKID_DEVNO_TO_DEVNAME && HAVE_BLKID_GET_TAG_VALUE +#define HAVE_BLKID 1 +#endif +#endif + +/** + * Includes some standard headers. + */ +#include +#include /* On many systems (e.g., Darwin), `stdio.h' is a prerequisite. */ +#include +#include +#include +#include +#include +#include +#include +#include + +#if HAVE_STDINT_H +#include +#endif + +#if HAVE_INTTYPES_H +#include +#endif + +#if HAVE_UNISTD_H +#include +#endif + +#if TIME_WITH_SYS_TIME +#include +#include +#else +#if HAVE_SYS_TIME_H +#include +#else +#include +#endif +#endif + +#if HAVE_MACH_MACH_TIME_H +#include +#endif + +#if HAVE_DIRENT_H +#include +#define NAMLEN(dirent) strlen((dirent)->d_name) +#else +#define dirent direct +#define NAMLEN(dirent) (dirent)->d_namlen +#if HAVE_SYS_NDIR_H +#include +#endif +#if HAVE_SYS_DIR_H +#include +#endif +#if HAVE_NDIR_H +#include +#endif +#endif + +#if HAVE_SYS_TYPES_H +#include +#endif + +#if MAJOR_IN_MKDEV +#include +#elif MAJOR_IN_SYSMACROS +#include +#endif + +#if HAVE_SYS_STAT_H +#include +#endif + +#if HAVE_SYS_WAIT_H +#include +#endif +#ifndef WEXITSTATUS +#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#endif +#ifndef WIFEXITED +#define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif + +#if HAVE_GETOPT_H +#include +#endif + +#if HAVE_FNMATCH_H +#include +#else +#include "fnmatch.h" +#endif + +#if HAVE_PTHREAD_H +#include +#endif + +#if HAVE_MATH_H +#include +#endif + +#if HAVE_EXECINFO_H +#include +#endif + +/** + * Enable thread use. + */ +#if HAVE_PTHREAD_CREATE +#define HAVE_PTHREAD 1 +#endif + +/** + * Disable case check in Windows. + */ +#ifdef _WIN32 +#define FNM_CASEINSENSITIVE_FOR_WIN FNM_CASEFOLD +#else +#define FNM_CASEINSENSITIVE_FOR_WIN 0 +#endif + +#if HAVE_IO_H +#include +#endif + +#if HAVE_GETOPT_LONG +#define SWITCH_GETOPT_LONG(a, b) a +#else +#define SWITCH_GETOPT_LONG(a, b) b +#endif + +/** + * Enables lock file support. + */ +#if HAVE_FLOCK && HAVE_FTRUNCATE +#define HAVE_LOCKFILE 1 +#endif + +/** + * Basic block position type. + * With 32 bits and 128k blocks you can address 256 TB. + */ +typedef uint32_t block_off_t; + +/** + * Basic data position type. + * It's signed as file size and offset are usually signed. + */ +typedef int64_t data_off_t; + +/** + * Includes specific support for Windows or Linux. + */ +#ifdef __MINGW32__ +#include "mingw.h" +#else +#include "unix.h" +#endif + +/** + * Include list support to have tommy_node. + */ +#include "tommyds/tommylist.h" + +/** + * Another name for link() to avoid confusion with local variables called "link". + */ +static inline int hardlink(const char* a, const char* b) +{ + return link(a, b); +} + +/** + * Get the device UUID. + * Return 0 on success. + */ +int devuuid(uint64_t device, char* uuid, size_t size); + +/** + * Physical offset not yet read. + */ +#define FILEPHY_UNREAD_OFFSET 0 + +/** + * Special value returned when the file-system doesn't report any offset for unknown reason. + */ +#define FILEPHY_UNREPORTED_OFFSET 1 + +/** + * Special value returned when the file doesn't have a real offset. + * For example, because it's stored in the NTFS MFT. + */ +#define FILEPHY_WITHOUT_OFFSET 2 + +/** + * Value indicating real offsets. All offsets greater or equal at this one are real. + */ +#define FILEPHY_REAL_OFFSET 3 + +/** + * Get the physcal address of the specified file. + * This is expected to be just a hint and not necessarily correct or unique. + * Return 0 on success. + */ +int filephy(const char* path, uint64_t size, uint64_t* physical); + +/** + * Check if the underline file-system support persistent inodes. + * Return -1 on error, 0 on success. + */ +int fsinfo(const char* path, int* has_persistent_inode, int* has_syncronized_hardlinks, uint64_t* total_space, uint64_t* free_space); + +/** + * Get the tick counter value. + * + * Note that the frequency is unspecified, because the time measure + * is meant to be used to compare the ratio between usage times. + */ +uint64_t tick(void); + +/** + * Get the tick counter value in millisecond. + */ +uint64_t tick_ms(void); + +/** + * Initializes the system. + */ +void os_init(int opt); + +/** + * Deinitialize the system. + */ +void os_done(void); + +/** + * Abort the process with a stacktrace. + */ +void os_abort(void) __noreturn; + +/** + * Clear the screen. + */ +void os_clear(void); + +/** + * Log file. + * + * This stream if fully buffered. + * + * If no log file is selected, it's 0. + */ +FILE* stdlog; + +/** + * Exit codes for testing. + */ +int exit_success; +int exit_failure; +int exit_sync_needed; +#undef EXIT_SUCCESS +#undef EXIT_FAILURE +#define EXIT_SUCCESS exit_success +#define EXIT_FAILURE exit_failure +#define EXIT_SYNC_NEEDED exit_sync_needed + +/** + * Fill memory with pseudo-random values. + */ +int randomize(void* ptr, size_t size); + +/** + * Standard SMART attributes. + */ +#define SMART_START_STOP_COUNT 4 +#define SMART_REALLOCATED_SECTOR_COUNT 5 +#define SMART_POWER_ON_HOURS 9 +#define SMART_AIRFLOW_TEMPERATURE_CELSIUS 190 +#define SMART_LOAD_CYCLE_COUNT 193 +#define SMART_TEMPERATURE_CELSIUS 194 + +/** + * Additional SMART attributes. + */ +#define SMART_ERROR 256 /**< ATA Error count. */ +#define SMART_SIZE 257 /**< Size in bytes. */ +#define SMART_ROTATION_RATE 258 /**< Rotation speed. 0 for SSD. */ +#define SMART_FLAGS 259 /**< Flags returned by smartctl. */ + +/** + * SMART attributes count. + */ +#define SMART_COUNT 260 + +/** + * Flags returned by smartctl. + */ +#define SMARTCTL_FLAG_UNSUPPORTED (1 << 0) /**< Device not recognized, requiring the -d option. */ +#define SMARTCTL_FLAG_OPEN (1 << 1) /**< Device open or identification failed. */ +#define SMARTCTL_FLAG_COMMAND (1 << 2) /**< Some SMART or ATA commands failed. This is a common error, also happening with full info gathering. */ +#define SMARTCTL_FLAG_FAIL (1 << 3) /**< SMART status check returned "DISK FAILING". */ +#define SMARTCTL_FLAG_PREFAIL (1 << 4) /**< We found prefail Attributes <= threshold. */ +#define SMARTCTL_FLAG_PREFAIL_LOGGED (1 << 5) /**< SMART status check returned "DISK OK" but we found that some (usage or prefail) Attributes have been <= threshold at some time in the past. */ +#define SMARTCTL_FLAG_ERROR (1 << 6) /**< The device error log contains records of errors. */ +#define SMARTCTL_FLAG_ERROR_LOGGED (1 << 7) /**< The device self-test log contains records of errors. */ + +/** + * SMART max attribute length. + */ +#define SMART_MAX 64 + +/** + * Value for unassigned SMART attribute. + */ +#define SMART_UNASSIGNED 0xFFFFFFFFFFFFFFFFULL + +/** + * Device info entry. + */ +struct devinfo_struct { + uint64_t device; /**< Device ID. */ + char name[PATH_MAX]; /**< Name of the disk. */ + char mount[PATH_MAX]; /**< Mount point or other contained directory. */ + char smartctl[PATH_MAX]; /**< Options for smartctl. */ + char file[PATH_MAX]; /**< File device. */ +#ifdef _WIN32 + char wfile[PATH_MAX]; /**< File device in Windows format. Like \\.\PhysicalDriveX, or \\?\Volume{X}. */ +#endif + struct devinfo_struct* parent; /**< Pointer at the parent if any. */ + uint64_t smart[SMART_COUNT]; /**< SMART raw attributes. */ + char smart_serial[SMART_MAX]; /**< SMART serial number. */ + char smart_vendor[SMART_MAX]; /**< SMART vendor. */ + char smart_model[SMART_MAX]; /**< SMART model. */ +#if HAVE_PTHREAD + pthread_t thread; +#endif + tommy_node node; +}; +typedef struct devinfo_struct devinfo_t; + +#define DEVICE_LIST 0 +#define DEVICE_DOWN 1 +#define DEVICE_UP 2 +#define DEVICE_SMART 3 + +/** + * Query all the "high" level devices with the specified operation, + * and produces a list of "low" level devices to operate on. + * + * The passed "low" device list must be already initialized. + */ +int devquery(tommy_list* high, tommy_list* low, int operation, int others); + +#endif + diff --git a/cmdline/rehash.c b/cmdline/rehash.c new file mode 100644 index 0000000..6b5376b --- /dev/null +++ b/cmdline/rehash.c @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "util.h" +#include "elem.h" +#include "import.h" +#include "state.h" +#include "parity.h" +#include "handle.h" +#include "raid/raid.h" + +/****************************************************************************/ +/* rehash */ + +void state_rehash(struct snapraid_state* state) +{ + block_off_t blockmax; + block_off_t i; + + blockmax = parity_allocated_size(state); + + /* check if a rehash is already in progress */ + if (state->prevhash != HASH_UNDEFINED) { + /* LCOV_EXCL_START */ + log_fatal("You already have a rehash in progress.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (state->hash == state->besthash) { + /* LCOV_EXCL_START */ + log_fatal("You are already using the best hash for your platform.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* copy the present hash as previous one */ + state->prevhash = state->hash; + memcpy(state->prevhashseed, state->hashseed, HASH_MAX); + + /* set the new hash and seed */ + state->hash = state->besthash; + if (randomize(state->hashseed, HASH_MAX) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to get random values.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* mark all the block for rehashing */ + for (i = 0; i < blockmax; ++i) { + snapraid_info info; + + /* if it's unused */ + info = info_get(&state->infoarr, i); + if (info == 0) { + /* skip it */ + continue; + } + + if (info_get_rehash(info)) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency for a rehash already in progress\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* enable the rehash */ + info = info_set_rehash(info); + + /* save it */ + info_set(&state->infoarr, i, info); + } + + /* save the new content file */ + state->need_write = 1; + + msg_status("A rehash is now scheduled. It will take place progressively in the next\n"); + msg_status("'sync' and 'scrub' commands. You can check the rehash progress using the\n"); + msg_status("'status' command.\n"); +} + diff --git a/cmdline/scan.c b/cmdline/scan.c new file mode 100644 index 0000000..8e70ff3 --- /dev/null +++ b/cmdline/scan.c @@ -0,0 +1,1926 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "support.h" +#include "elem.h" +#include "state.h" +#include "parity.h" + +struct snapraid_scan { + struct snapraid_state* state; /**< State used. */ + struct snapraid_disk* disk; /**< Disk used. */ + + /** + * Counters of changes. + */ + unsigned count_equal; /**< Files equal. */ + unsigned count_move; /**< Files with a different name, but equal inode, size and timestamp in the same disk. */ + unsigned count_restore; /**< Files with equal name, size and timestamp, but different inode. */ + unsigned count_change; /**< Files with same name, but different size and/or timestamp. */ + unsigned count_copy; /**< Files new, with same name size and timestamp of a file in a different disk. */ + unsigned count_insert; /**< Files new. */ + unsigned count_remove; /**< Files removed. */ + + tommy_list file_insert_list; /**< Files to insert. */ + tommy_list link_insert_list; /**< Links to insert. */ + tommy_list dir_insert_list; /**< Dirs to insert. */ + + /* nodes for data structures */ + tommy_node node; +}; + +/** + * Remove the specified link from the data set. + */ +static void scan_link_remove(struct snapraid_scan* scan, struct snapraid_link* slink) +{ + struct snapraid_state* state = scan->state; + struct snapraid_disk* disk = scan->disk; + + /* state changed */ + state->need_write = 1; + + /* remove the file from the link containers */ + tommy_hashdyn_remove_existing(&disk->linkset, &slink->nodeset); + tommy_list_remove_existing(&disk->linklist, &slink->nodelist); + + /* deallocate */ + link_free(slink); +} + +/** + * Insert the specified link in the data set. + */ +static void scan_link_insert(struct snapraid_scan* scan, struct snapraid_link* slink) +{ + struct snapraid_state* state = scan->state; + struct snapraid_disk* disk = scan->disk; + + /* state changed */ + state->need_write = 1; + + /* insert the link in the link containers */ + tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub)); + tommy_list_insert_tail(&disk->linklist, &slink->nodelist, slink); +} + +/** + * Process a symbolic link. + */ +static void scan_link(struct snapraid_scan* scan, int is_diff, const char* sub, const char* linkto, unsigned link_flag) +{ + struct snapraid_state* state = scan->state; + struct snapraid_disk* disk = scan->disk; + struct snapraid_link* slink; + char esc_buffer[ESC_MAX]; + + /* check if the link already exists */ + slink = tommy_hashdyn_search(&disk->linkset, link_name_compare_to_arg, sub, link_name_hash(sub)); + if (slink) { + /* check if multiple files have the same name */ + if (link_flag_has(slink, FILE_IS_PRESENT)) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency for link '%s%s'\n", disk->dir, sub); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* mark as present */ + link_flag_set(slink, FILE_IS_PRESENT); + + /* check if the link is not changed and it's of the same kind */ + if (strcmp(slink->linkto, linkto) == 0 && link_flag == link_flag_get(slink, FILE_IS_LINK_MASK)) { + /* it's equal */ + ++scan->count_equal; + + if (state->opt.gui) { + log_tag("scan:equal:%s:%s\n", disk->name, esc_tag(slink->sub, esc_buffer)); + } + } else { + /* it's an update */ + + /* we have to save the linkto/type */ + state->need_write = 1; + + ++scan->count_change; + + log_tag("scan:update:%s:%s\n", disk->name, esc_tag(slink->sub, esc_buffer)); + if (is_diff) { + printf("update %s\n", fmt_term(disk, slink->sub, esc_buffer)); + } + + /* update it */ + free(slink->linkto); + slink->linkto = strdup_nofail(linkto); + link_flag_let(slink, link_flag, FILE_IS_LINK_MASK); + } + + /* nothing more to do */ + return; + } else { + /* create the new link */ + ++scan->count_insert; + + log_tag("scan:add:%s:%s\n", disk->name, esc_tag(sub, esc_buffer)); + if (is_diff) { + printf("add %s\n", fmt_term(disk, sub, esc_buffer)); + } + + /* and continue to insert it */ + } + + /* insert it */ + slink = link_alloc(sub, linkto, link_flag); + + /* mark it as present */ + link_flag_set(slink, FILE_IS_PRESENT); + + /* insert it in the delayed insert list */ + tommy_list_insert_tail(&scan->link_insert_list, &slink->nodelist, slink); +} + +/** + * Insert the specified file in the parity. + */ +static void scan_file_allocate(struct snapraid_scan* scan, struct snapraid_file* file) +{ + struct snapraid_state* state = scan->state; + struct snapraid_disk* disk = scan->disk; + block_off_t i; + block_off_t parity_pos; + + /* state changed */ + state->need_write = 1; + + /* allocate the blocks of the file */ + parity_pos = disk->first_free_block; + for (i = 0; i < file->blockmax; ++i) { + struct snapraid_block* block; + struct snapraid_block* over_block; + snapraid_info info; + + /* increment the position until the first really free block */ + while (block_has_file(fs_par2block_find(disk, parity_pos))) + ++parity_pos; + + /* get block we are going to overwrite, if any */ + over_block = fs_par2block_find(disk, parity_pos); + + /* deallocate it */ + if (over_block != BLOCK_NULL) + fs_deallocate(disk, parity_pos); + + /* get block specific info */ + info = info_get(&state->infoarr, parity_pos); + + /* get the new block we are going to write */ + block = fs_file2block_get(file, i); + + /* if the file block already has an updated hash without rehash */ + if (block_has_updated_hash(block) && !info_get_rehash(info)) { + /* the only possible case is for REP blocks */ + assert(block_state_get(block) == BLOCK_STATE_REP); + + /* convert to a REP block */ + block_state_set(block, BLOCK_STATE_REP); + + /* and keep the hash as it's */ + } else { + unsigned over_state; + + /* convert to a CHG block */ + block_state_set(block, BLOCK_STATE_CHG); + + /* state of the block we are going to overwrite */ + over_state = block_state_get(over_block); + + /* if the block is an empty one */ + if (over_state == BLOCK_STATE_EMPTY) { + /* the block was empty and filled with zeros */ + /* set the hash to the special ZERO value */ + hash_zero_set(block->hash); + } else { + /* otherwise it's a DELETED one */ + assert(over_state == BLOCK_STATE_DELETED); + + /* copy the past hash of the block */ + memcpy(block->hash, over_block->hash, BLOCK_HASH_SIZE); + + /* if we have not already cleared the past hash */ + if (!state->clear_past_hash) { + /* in this case we don't know if the old state is still the one */ + /* stored inside the parity, because after an aborted sync, the parity */ + /* may be or may be not have been updated with the new data */ + /* Then we reset the hash to a bogus value */ + /* For example: */ + /* - One file is deleted */ + /* - Sync aborted after, updating the parity to the new state, */ + /* but without saving the content file representing this new state. */ + /* - Another file is added again (exactly here) */ + /* with the hash of DELETED block not representing the real parity state */ + hash_invalid_set(block->hash); + } + } + } + + /* store in the disk map, after invalidating all the other blocks */ + fs_allocate(disk, parity_pos, file, i); + + /* set the new free position */ + disk->first_free_block = parity_pos + 1; + } + + /* insert in the list of contained files */ + tommy_list_insert_tail(&disk->filelist, &file->nodelist, file); +} + +/** + * Delete the specified file from the parity. + * + * Note that the parity remains allocated, but the blocks and the file are marked as DELETED. + * The file is then inserted in the deleted set, and it should not be deallocated, + * as the parity still references it. + */ +static void scan_file_deallocate(struct snapraid_scan* scan, struct snapraid_file* file) +{ + struct snapraid_state* state = scan->state; + struct snapraid_disk* disk = scan->disk; + block_off_t i; + + /* remove from the list of contained files */ + tommy_list_remove_existing(&disk->filelist, &file->nodelist); + + /* state changed */ + state->need_write = 1; + + /* here we are supposed to adjust the ::first_free_block position */ + /* with the parity position we are deleting */ + /* but we also know that we do only delayed insert, after all the deletion, */ + /* so at this point ::first_free_block is always at 0, and we don't need to update it */ + if (disk->first_free_block != 0) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency for first free position at '%u' deallocating file '%s'\n", disk->first_free_block, file->sub); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* free all the blocks of the file */ + for (i = 0; i < file->blockmax; ++i) { + struct snapraid_block* block = fs_file2block_get(file, i); + unsigned block_state; + + /* in case we scan after an aborted sync, */ + /* we could get also intermediate states */ + block_state = block_state_get(block); + switch (block_state) { + case BLOCK_STATE_BLK : + /* we keep the hash making it an "old" hash, because the parity is still containing data for it */ + break; + case BLOCK_STATE_CHG : + /* if we have not already cleared the past hash */ + if (!state->clear_past_hash) { + /* in these cases we don't know if the old state is still the one */ + /* stored inside the parity, because after an aborted sync, the parity */ + /* may be or may be not have been updated with the data that it's now */ + /* deleted. Then we reset the hash to a bogus value. */ + /* For example: */ + /* - One file is added */ + /* - Sync aborted after updating the parity to the new state, */ + /* but without saving the content file representing this new state. */ + /* - File is now deleted after the aborted sync */ + /* - Sync again, deleting the blocks (exactly here) */ + /* with the hash of CHG block not representing the real parity state */ + hash_invalid_set(block->hash); + } + break; + case BLOCK_STATE_REP : + /* we just don't know the old hash, and then we set it to invalid */ + hash_invalid_set(block->hash); + break; + default : + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in file '%s' deallocating block '%u:%u' state %u\n", file->sub, i, file->blockmax, block_state); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* set the block as deleted */ + block_state_set(block, BLOCK_STATE_DELETED); + } + + /* mark the file as deleted */ + file_flag_set(file, FILE_IS_DELETED); + + /* insert it in the list of deleted blocks */ + tommy_list_insert_tail(&disk->deletedlist, &file->nodelist, file); +} + +static void scan_file_delayed_allocate(struct snapraid_scan* scan, struct snapraid_file* file) +{ + struct snapraid_state* state = scan->state; + struct snapraid_disk* disk = scan->disk; + + /* if we sort for physical offsets we have to read them for new files */ + if (state->opt.force_order == SORT_PHYSICAL + && file->physical == FILEPHY_UNREAD_OFFSET + ) { + char path_next[PATH_MAX]; + + pathprint(path_next, sizeof(path_next), "%s%s", disk->dir, file->sub); + + if (filephy(path_next, file->size, &file->physical) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error in getting the physical offset of file '%s'. %s.\n", path_next, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + /* insert in the delayed list */ + tommy_list_insert_tail(&scan->file_insert_list, &file->nodelist, file); +} + +/** + * Check if a file is completely formed of blocks with invalid parity, + * and no rehash is tagged, and if it has at least one block. + */ +static int file_is_full_invalid_parity_and_stable(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file) +{ + block_off_t i; + + /* with no block, it never has an invalid parity */ + if (file->blockmax == 0) + return 0; + + /* check all blocks */ + for (i = 0; i < file->blockmax; ++i) { + snapraid_info info; + struct snapraid_block* block = fs_file2block_get(file, i); + block_off_t parity_pos; + + /* exclude blocks with parity */ + if (!block_has_invalid_parity(block)) + return 0; + + /* + * Get the parity position. + * + * Note that here we expect to always have mapped + * parity, because kept files always have it. + * + * Anyway, checking for POS_NULL doesn't hurt. + */ + parity_pos = fs_file2par_find(disk, file, i); + + /* if it's not mapped, it cannot have rehash */ + if (parity_pos != POS_NULL) { + /* get block specific info */ + info = info_get(&state->infoarr, parity_pos); + + /* if rehash fails */ + if (info_get_rehash(info)) + return 0; + } + } + + return 1; +} + +/** + * Check if a file is completely formed of blocks with an updated hash, + * and no rehash is tagged, and if it has at least one block. + */ +static int file_is_full_hashed_and_stable(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file) +{ + block_off_t i; + + /* with no block, it never has a hash */ + if (file->blockmax == 0) + return 0; + + /* check all blocks */ + for (i = 0; i < file->blockmax; ++i) { + snapraid_info info; + struct snapraid_block* block = fs_file2block_get(file, i); + block_off_t parity_pos; + + /* exclude blocks without hash */ + if (!block_has_updated_hash(block)) + return 0; + + /* + * Get the parity position. + * + * Note that it's possible to have files + * not mapped into the parity, even if they + * have a valid hash. + * + * This happens for example, for 'copied' files + * that have REP blocks, but not yet mapped. + * + * If there are multiple copies, it's also possible + * that such files are used as 'source' to copy + * hashes, and then to get them inside this function. + */ + parity_pos = fs_file2par_find(disk, file, i); + + /* if it's not mapped, it cannot have rehash */ + if (parity_pos != POS_NULL) { + /* get block specific info */ + info = info_get(&state->infoarr, parity_pos); + + /* exclude blocks needing a rehash */ + if (info_get_rehash(info)) + return 0; + } + } + + return 1; +} + +/** + * Refresh the file info. + * + * This is needed by Windows as the normal way to list directories may report not + * updated info. Only the GetFileInformationByHandle() func, called file-by-file, + * really ensures to return synced info. + * + * If this happens, we read also the physical offset, to avoid to read it later. + */ +static void scan_file_refresh(struct snapraid_scan* scan, const char* sub, struct stat* st, uint64_t* physical) +{ +#if HAVE_LSTAT_SYNC + struct snapraid_state* state = scan->state; + struct snapraid_disk* disk = scan->disk; + + /* if the st_sync is not set, ensure to get synced info */ + if (st->st_sync == 0) { + char path_next[PATH_MAX]; + struct stat synced_st; + + pathprint(path_next, sizeof(path_next), "%s%s", disk->dir, sub); + + /* if we sort for physical offsets we have to read them for new files */ + if (state->opt.force_order == SORT_PHYSICAL + && *physical == FILEPHY_UNREAD_OFFSET + ) { + /* do nothing, leave the pointer to read the physical offset */ + } else { + physical = 0; /* set the pointer to 0 to read nothing */ + } + + if (lstat_sync(path_next, &synced_st, physical) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error in stat file '%s'. %s.\n", path_next, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (st->st_mtime != synced_st.st_mtime + || st->st_mtimensec != synced_st.st_mtimensec + ) { +#ifndef _WIN32 + /* + * In Windows having different metadata is expected with open files + * because the metadata in the directory is updated only when the file + * is closed. + * + * The same happens for hardlinks that duplicate metatada. + * The link metadata is updated only when the link is opened. + * This extends also to st_size and st_nlink. + * + * See also: + * Why is the file size reported incorrectly for files that are still being written to? + * http://blogs.msdn.com/b/oldnewthing/archive/2011/12/26/10251026.aspx + */ + log_fatal("WARNING! Detected uncached time change from %" PRIu64 ".%09u to %" PRIu64 ".%09u for file '%s'\n", + (uint64_t)st->st_mtime, (uint32_t)st->st_mtimensec, (uint64_t)synced_st.st_mtime, (uint32_t)synced_st.st_mtimensec, sub); + log_fatal("It's better if you run SnapRAID without other processes running.\n"); +#endif + st->st_mtime = synced_st.st_mtime; + st->st_mtimensec = synced_st.st_mtimensec; + } + + if (st->st_size != synced_st.st_size) { +#ifndef _WIN32 + log_fatal("WARNING! Detected uncached size change from %" PRIu64 " to %" PRIu64 " for file '%s'\n", + (uint64_t)st->st_size, (uint64_t)synced_st.st_size, sub); + log_fatal("It's better if you run SnapRAID without other processes running.\n"); +#endif + st->st_size = synced_st.st_size; + } + + if (st->st_nlink != synced_st.st_nlink) { +#ifndef _WIN32 + log_fatal("WARNING! Detected uncached nlink change from %u to %u for file '%s'\n", + (uint32_t)st->st_nlink, (uint32_t)synced_st.st_nlink, sub); + log_fatal("It's better if you run SnapRAID without other processes running.\n"); +#endif + st->st_nlink = synced_st.st_nlink; + } + + if (st->st_ino != synced_st.st_ino) { + log_fatal("DANGER! Detected uncached inode change from %" PRIu64 " to %" PRIu64 " for file '%s'\n", + (uint64_t)st->st_ino, (uint64_t)synced_st.st_ino, sub); + log_fatal("It's better if you run SnapRAID without other processes running.\n"); + /* at this point, it's too late to change inode */ + /* and having inconsistent inodes may result to internal failures */ + /* so, it's better to abort */ + exit(EXIT_FAILURE); + } + } +#else + (void)scan; + (void)sub; + (void)st; + (void)physical; +#endif +} + +/** + * Insert the file in the data set. + */ +static void scan_file_insert(struct snapraid_scan* scan, struct snapraid_file* file) +{ + struct snapraid_disk* disk = scan->disk; + + /* insert the file in the containers */ + if (!file_flag_has(file, FILE_IS_WITHOUT_INODE)) + tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); + tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub)); + tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec)); + + /* delayed allocation of the parity */ + scan_file_delayed_allocate(scan, file); +} + +/** + * Remove the file from the data set. + * + * File is then deleted. + */ +static void scan_file_remove(struct snapraid_scan* scan, struct snapraid_file* file) +{ + struct snapraid_disk* disk = scan->disk; + + /* remove the file from the containers */ + if (!file_flag_has(file, FILE_IS_WITHOUT_INODE)) + tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); + tommy_hashdyn_remove_existing(&disk->pathset, &file->pathset); + tommy_hashdyn_remove_existing(&disk->stampset, &file->stampset); + + /* deallocate the file from the parity */ + scan_file_deallocate(scan, file); +} + +/** + * Keep the file as it's (or with only a name/inode modification). + * + * If the file is kept, nothing has to be done. + * + * But if a file contains only blocks with invalid parity, it's reallocated to ensure + * to always minimize the space used in the parity. + * + * This could happen after a failed sync, when some other files are deleted, + * and then new ones can be moved backward to fill the hole created. + */ +static void scan_file_keep(struct snapraid_scan* scan, struct snapraid_file* file) +{ + struct snapraid_disk* disk = scan->disk; + + /* if the file is full invalid, schedule a reinsert at later stage */ + if (file_is_full_invalid_parity_and_stable(scan->state, disk, file)) { + struct snapraid_file* copy = file_dup(file); + + /* remove the file */ + scan_file_remove(scan, file); + + /* reinsert the copy in the delayed list */ + scan_file_insert(scan, copy); + } +} + +/** + * Process a file. + */ +static void scan_file(struct snapraid_scan* scan, int is_diff, const char* sub, struct stat* st, uint64_t physical) +{ + struct snapraid_state* state = scan->state; + struct snapraid_disk* disk = scan->disk; + struct snapraid_file* file; + tommy_node* i; + int is_original_file_size_different_than_zero; + int is_file_already_present; + data_off_t file_already_present_size; + int64_t file_already_present_mtime_sec; + int file_already_present_mtime_nsec; + int is_file_reported; + char esc_buffer[ESC_MAX]; + char esc_buffer_alt[ESC_MAX]; + + /* + * If the disk has persistent inodes and UUID, try a search on the past inodes, + * to detect moved files. + * + * For persistent inodes we mean inodes that keep their values when the file-system + * is unmounted and remounted. This don't always happen. + * + * Cases found are: + * - Linux FUSE with exFAT driver from https://code.google.com/p/exfat/. + * Inodes are reassigned at every mount restarting from 1 and incrementing. + * As worse, the exFAT support in FUSE doesn't use sub-second precision in timestamps + * making inode collision more easy (exFAT by design supports 10ms precision). + * - Linux VFAT kernel (3.2) driver. Inodes are fully reassigned at every mount. + * + * In such cases, to avoid possible random collisions, it's better to disable the moved + * file recognition. + * + * For persistent UUID we mean that it has the same UUID as before. + * Otherwise, if the UUID is changed, likely it's a new recreated file-system, + * and then the inode have no meaning. + * + * Note that to disable the search by past inode, we do this implicitly + * removing all the past inode before searching for files. + * This ensures that no file is found with a past inode, but at the same time, + * it allows to find new files with the same inode, to identify them as hardlinks. + */ + int has_past_inodes = !disk->has_volatile_inodes && !disk->has_different_uuid && !disk->has_unsupported_uuid; + + /* always search with the new inode, in the all new inodes found until now, */ + /* with the eventual presence of also the past inodes */ + uint64_t inode = st->st_ino; + + file = tommy_hashdyn_search(&disk->inodeset, file_inode_compare_to_arg, &inode, file_inode_hash(inode)); + + /* identify moved files with past inodes and hardlinks with the new inodes */ + if (file) { + /* check if the file is not changed */ + if (file->size == st->st_size + && file->mtime_sec == st->st_mtime + && (file->mtime_nsec == STAT_NSEC(st) + /* always accept the stored value if it's STAT_NSEC_INVALID */ + /* it happens when upgrading from an old version of SnapRAID */ + /* not yet supporting the nanosecond field */ + || file->mtime_nsec == STAT_NSEC_INVALID + ) + ) { + /* check if multiple files have the same inode */ + if (file_flag_has(file, FILE_IS_PRESENT)) { + /* if has_volatile_hardlinks is true, the nlink value is not reliable */ + if (!disk->has_volatile_hardlinks && st->st_nlink == 1) { + /* LCOV_EXCL_START */ + log_fatal("Internal inode '%" PRIu64 "' inconsistency for file '%s%s' already present\n", (uint64_t)st->st_ino, disk->dir, sub); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* it's a hardlink */ + scan_link(scan, is_diff, sub, file->sub, FILE_IS_HARDLINK); + return; + } + + /* mark as present */ + file_flag_set(file, FILE_IS_PRESENT); + + /* update the nanoseconds mtime only if different */ + /* to avoid unneeded updates */ + if (file->mtime_nsec == STAT_NSEC_INVALID + && STAT_NSEC(st) != file->mtime_nsec + ) { + file->mtime_nsec = STAT_NSEC(st); + + /* we have to save the new mtime */ + state->need_write = 1; + } + + if (strcmp(file->sub, sub) != 0) { + /* if the path is different, it means a moved file with the same inode */ + ++scan->count_move; + + log_tag("scan:move:%s:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer), esc_tag(sub, esc_buffer_alt)); + if (is_diff) { + printf("move %s -> %s\n", fmt_term(disk, file->sub, esc_buffer), fmt_term(disk, sub, esc_buffer_alt)); + } + + /* remove from the name set */ + tommy_hashdyn_remove_existing(&disk->pathset, &file->pathset); + + /* save the new name */ + file_rename(file, sub); + + /* reinsert in the name set */ + tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub)); + + /* we have to save the new name */ + state->need_write = 1; + } else { + /* otherwise it's equal */ + ++scan->count_equal; + + if (state->opt.gui) { + log_tag("scan:equal:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + } + } + + /* mark the file as kept */ + scan_file_keep(scan, file); + + /* nothing more to do */ + return; + } + + /* + * Here the file matches the inode, but not the other info + * + * It could be a modified file with the same name, + * or a restored/copied file that get assigned a previously used inode, + * or a file-system with not persistent inodes. + * + * In NTFS it could be also a hardlink, because in NTFS + * hardlink don't share the same directory information, + * like attribute and time. + * + * For example: + * C:> echo A > A + * C:> mklink /H B A + * ...wait one minute + * C:> echo AAAAAAAAAAAAAA > A + * C:> dir + * ...both time and size of A and B don't match! + */ + if (file_flag_has(file, FILE_IS_PRESENT)) { + /* if has_volatile_hardlinks is true, the nlink value is not reliable */ + if (!disk->has_volatile_hardlinks && st->st_nlink == 1) { + /* LCOV_EXCL_START */ + log_fatal("Internal inode '%" PRIu64 "' inconsistency for files '%s%s' and '%s%s' with same inode but different attributes: size %" PRIu64 "?%" PRIu64 ", sec %" PRIu64 "?%" PRIu64 ", nsec %d?%d\n", + file->inode, disk->dir, sub, disk->dir, file->sub, + file->size, (uint64_t)st->st_size, + file->mtime_sec, (uint64_t)st->st_mtime, + file->mtime_nsec, STAT_NSEC(st)); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* LCOV_EXCL_START */ + /* suppose it's hardlink with not synced metadata */ + scan_link(scan, is_diff, sub, file->sub, FILE_IS_HARDLINK); + return; + /* LCOV_EXCL_STOP */ + } + + /* assume a previously used inode, it's the worst case */ + /* and we handle it removing the duplicate stored inode. */ + /* If the file is found by name later, it will have the inode restored, */ + /* otherwise, it will get removed */ + + /* remove from the inode set */ + tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); + + /* clear the inode */ + /* this is not really needed for correct functionality */ + /* because we are going to set FILE_IS_WITHOUT_INODE */ + /* but it's easier for debugging to have invalid inodes set to 0 */ + file->inode = 0; + + /* mark as missing inode */ + file_flag_set(file, FILE_IS_WITHOUT_INODE); + + /* go further to find it by name */ + } + + /* initialize for later overwrite */ + is_file_reported = 0; + is_original_file_size_different_than_zero = 0; + + /* then try finding it by name */ + file = tommy_hashdyn_search(&disk->pathset, file_path_compare_to_arg, sub, file_path_hash(sub)); + + /* keep track if the file already exists */ + is_file_already_present = file != 0; + + if (is_file_already_present) { + /* if the file is without an inode */ + if (file_flag_has(file, FILE_IS_WITHOUT_INODE)) { + /* set it now */ + file->inode = st->st_ino; + + /* insert in the set */ + tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); + + /* unmark as missing inode */ + file_flag_clear(file, FILE_IS_WITHOUT_INODE); + } else { + /* here the inode has to be different, otherwise we would have found it before */ + if (file->inode == st->st_ino) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in inode '%" PRIu64 "' for files '%s%s' as unexpected matching\n", file->inode, disk->dir, sub); + os_abort(); + /* LCOV_EXCL_STOP */ + } + } + + /* for sure it cannot be already present */ + if (file_flag_has(file, FILE_IS_PRESENT)) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in path for file '%s%s' matching and already present\n", disk->dir, sub); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* check if the file is not changed */ + if (file->size == st->st_size + && file->mtime_sec == st->st_mtime + && (file->mtime_nsec == STAT_NSEC(st) + /* always accept the stored value if it's STAT_NSEC_INVALID */ + /* it happens when upgrading from an old version of SnapRAID */ + /* not yet supporting the nanosecond field */ + || file->mtime_nsec == STAT_NSEC_INVALID + ) + ) { + /* mark as present */ + file_flag_set(file, FILE_IS_PRESENT); + + /* update the nano seconds mtime only if different */ + /* to avoid unneeded updates */ + if (file->mtime_nsec == STAT_NSEC_INVALID + && STAT_NSEC(st) != STAT_NSEC_INVALID + ) { + file->mtime_nsec = STAT_NSEC(st); + + /* we have to save the new mtime */ + state->need_write = 1; + } + + /* if when processing the disk we used the past inodes values */ + if (has_past_inodes) { + /* if persistent inodes are supported, we are sure that the inode number */ + /* is now different, because otherwise the file would have been found */ + /* when searching by inode. */ + /* if the inode is different, it means a rewritten file with the same path */ + /* like when restoring a backup that restores also the timestamp */ + ++scan->count_restore; + + log_tag("scan:restore:%s:%s\n", disk->name, esc_tag(sub, esc_buffer)); + if (is_diff) { + printf("restore %s\n", fmt_term(disk, sub, esc_buffer)); + } + + /* remove from the inode set */ + tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); + + /* save the new inode */ + file->inode = st->st_ino; + + /* reinsert in the inode set */ + tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); + + /* we have to save the new inode */ + state->need_write = 1; + } else { + /* otherwise it's the case of not persistent inode, where doesn't */ + /* matter if the inode is different or equal, because they have no */ + /* meaning, and then we don't even save them */ + ++scan->count_equal; + + if (state->opt.gui) { + log_tag("scan:equal:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + } + } + + /* mark the file as kept */ + scan_file_keep(scan, file); + + /* nothing more to do */ + return; + } + + /* here if the file is changed but with the correct name */ + + /* save the info for later printout */ + file_already_present_size = file->size; + file_already_present_mtime_sec = file->mtime_sec; + file_already_present_mtime_nsec = file->mtime_nsec; + + /* keep track if the original file was not of zero size */ + is_original_file_size_different_than_zero = file->size != 0; + + /* remove it, and continue to insert it again */ + scan_file_remove(scan, file); + + /* and continue to insert it again */ + } else { + file_already_present_size = 0; + file_already_present_mtime_sec = 0; + file_already_present_mtime_nsec = 0; + } + + /* refresh the info, to ensure that they are synced, */ + /* note that we refresh only the info of the new or modified files */ + /* because this is slow operation */ + scan_file_refresh(scan, sub, st, &physical); + +#ifndef _WIN32 + /* do a safety check to ensure that the common ext4 case of zeroing */ + /* the size of a file after a crash doesn't propagate to the backup */ + /* this check is specific for Linux, so we disable it on Windows */ + if (is_original_file_size_different_than_zero && st->st_size == 0) { + if (!state->opt.force_zero) { + /* LCOV_EXCL_START */ + log_fatal("The file '%s%s' has unexpected zero size!\n", disk->dir, sub); + log_fatal("It's possible that after a kernel crash this file was lost,\n"); + log_fatal("and you can use 'snapraid fix -f /%s' to recover it.\n", fmt_poll(disk, sub, esc_buffer)); + if (!is_diff) { + log_fatal("If this an expected condition you can '%s' anyway using 'snapraid --force-zero %s'\n", state->command, state->command); + exit(EXIT_FAILURE); + } + /* LCOV_EXCL_STOP */ + } + } +#else + /* avoid the unused warning in Windows */ + (void)is_original_file_size_different_than_zero; +#endif + + /* insert it */ + file = file_alloc(state->block_size, sub, st->st_size, st->st_mtime, STAT_NSEC(st), st->st_ino, physical); + + /* mark it as present */ + file_flag_set(file, FILE_IS_PRESENT); + + /* if copy detection is enabled */ + /* note that the copy detection is tried also for updated files */ + /* this makes sense because it may happen to have two different copies */ + /* of the same file, and we move the right one over the wrong one */ + /* in such case we have a "copy" over an "update" */ + if (!state->opt.force_nocopy) { + tommy_uint32_t hash = file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec); + + /* search for a file with the same name and stamp in all the disks */ + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* other_disk = i->data; + struct snapraid_file* other_file; + + /* if the nanosecond part of the time stamp is valid, search */ + /* for name and stamp, otherwise for path and stamp */ + if (file->mtime_nsec != 0 && file->mtime_nsec != STAT_NSEC_INVALID) + other_file = tommy_hashdyn_search(&other_disk->stampset, file_namestamp_compare, file, hash); + else + other_file = tommy_hashdyn_search(&other_disk->stampset, file_pathstamp_compare, file, hash); + + /* if found, and it's a fully hashed file */ + if (other_file && file_is_full_hashed_and_stable(scan->state, other_disk, other_file)) { + /* assume that the file is a copy, and reuse the hash */ + file_copy(other_file, file); + + /* revert old counter and use the copy one */ + ++scan->count_copy; + + log_tag("scan:copy:%s:%s:%s:%s\n", other_disk->name, esc_tag(other_file->sub, esc_buffer), disk->name, esc_tag(file->sub, esc_buffer_alt)); + if (is_diff) { + printf("copy %s -> %s\n", fmt_term(other_disk, other_file->sub, esc_buffer), fmt_term(disk, file->sub, esc_buffer_alt)); + } + + /* mark it as reported */ + is_file_reported = 1; + + /* no need to continue the search */ + break; + } + } + } + + /* if not yet reported, do it now */ + /* we postpone this to avoid to print two times the copied files */ + if (!is_file_reported) { + if (is_file_already_present) { + ++scan->count_change; + + log_tag("scan:update:%s:%s: %" PRIu64 " %" PRIu64 ".%d -> %" PRIu64 " %" PRIu64 ".%d\n", disk->name, esc_tag(sub, esc_buffer), + file_already_present_size, file_already_present_mtime_sec, file_already_present_mtime_nsec, + file->size, file->mtime_sec, file->mtime_nsec + ); + + if (is_diff) { + printf("update %s\n", fmt_term(disk, sub, esc_buffer)); + } + } else { + ++scan->count_insert; + + log_tag("scan:add:%s:%s\n", disk->name, esc_tag(sub, esc_buffer)); + if (is_diff) { + printf("add %s\n", fmt_term(disk, sub, esc_buffer)); + } + } + } + + /* insert the file in the delayed list */ + scan_file_insert(scan, file); +} + +/** + * Remove the specified dir from the data set. + */ +static void scan_emptydir_remove(struct snapraid_scan* scan, struct snapraid_dir* dir) +{ + struct snapraid_state* state = scan->state; + struct snapraid_disk* disk = scan->disk; + + /* state changed */ + state->need_write = 1; + + /* remove the file from the dir containers */ + tommy_hashdyn_remove_existing(&disk->dirset, &dir->nodeset); + tommy_list_remove_existing(&disk->dirlist, &dir->nodelist); + + /* deallocate */ + dir_free(dir); +} + +/** + * Insert the specified dir in the data set. + */ +static void scan_emptydir_insert(struct snapraid_scan* scan, struct snapraid_dir* dir) +{ + struct snapraid_state* state = scan->state; + struct snapraid_disk* disk = scan->disk; + + /* state changed */ + state->need_write = 1; + + /* insert the dir in the dir containers */ + tommy_hashdyn_insert(&disk->dirset, &dir->nodeset, dir, dir_name_hash(dir->sub)); + tommy_list_insert_tail(&disk->dirlist, &dir->nodelist, dir); +} + +/** + * Process a dir. + */ +static void scan_emptydir(struct snapraid_scan* scan, const char* sub) +{ + struct snapraid_disk* disk = scan->disk; + struct snapraid_dir* dir; + + /* check if the dir already exists */ + dir = tommy_hashdyn_search(&disk->dirset, dir_name_compare, sub, dir_name_hash(sub)); + if (dir) { + /* check if multiple files have the same name */ + if (dir_flag_has(dir, FILE_IS_PRESENT)) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency for dir '%s%s'\n", disk->dir, sub); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* mark as present */ + dir_flag_set(dir, FILE_IS_PRESENT); + + /* nothing more to do */ + return; + } else { + /* and continue to insert it */ + } + + /* insert it */ + dir = dir_alloc(sub); + + /* mark it as present */ + dir_flag_set(dir, FILE_IS_PRESENT); + + /* insert it in the delayed insert list */ + tommy_list_insert_tail(&scan->dir_insert_list, &dir->nodelist, dir); +} + +struct dirent_sorted { + /* node for data structures */ + tommy_node node; + +#if HAVE_STRUCT_DIRENT_D_INO + uint64_t d_ino; /**< Inode number. */ +#endif +#if HAVE_STRUCT_DIRENT_D_TYPE + uint32_t d_type; /**< File type. */ +#endif +#if HAVE_STRUCT_DIRENT_D_STAT + struct stat d_stat; /**< Stat result. */ +#endif + char d_name[]; /**< Variable length name. It must be the last field. */ +}; + +#if HAVE_STRUCT_DIRENT_D_INO +static int dd_ino_compare(const void* void_a, const void* void_b) +{ + const struct dirent_sorted* a = void_a; + const struct dirent_sorted* b = void_b; + + if (a->d_ino < b->d_ino) + return -1; + if (a->d_ino > b->d_ino) + return 1; + + return 0; +} +#endif + +static int dd_name_compare(const void* void_a, const void* void_b) +{ + const struct dirent_sorted* a = void_a; + const struct dirent_sorted* b = void_b; + + return strcmp(a->d_name, b->d_name); +} + +/** + * Return the stat info of a dir entry. + */ +#if HAVE_STRUCT_DIRENT_D_STAT +#define DSTAT(file, dd, buf) dstat(dd) +struct stat* dstat(struct dirent_sorted* dd) +{ + return &dd->d_stat; +} +#else +#define DSTAT(file, dd, buf) dstat(file, buf) +struct stat* dstat(const char* file, struct stat* st) +{ + if (lstat(file, st) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error in stat file/directory '%s'. %s.\n", file, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + return st; +} +#endif + +/** + * Process a directory. + * Return != 0 if at least one file or link is processed. + */ +static int scan_dir(struct snapraid_scan* scan, int level, int is_diff, const char* dir, const char* sub) +{ + struct snapraid_state* state = scan->state; + struct snapraid_disk* disk = scan->disk; + int processed = 0; + DIR* d; + tommy_list list; + tommy_node* node; + + tommy_list_init(&list); + + d = opendir(dir); + if (!d) { + /* LCOV_EXCL_START */ + log_fatal("Error opening directory '%s'. %s.\n", dir, strerror(errno)); + if (level == 0) + log_fatal("If this is the disk mount point, remember to create it manually\n"); + else + log_fatal("If it's a permission problem, you can exclude it in the config file with:\n\texclude /%s\n", sub); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* read the full directory */ + while (1) { + char path_next[PATH_MAX]; + char sub_next[PATH_MAX]; + struct dirent_sorted* entry; + const char* name; + struct dirent* dd; + size_t name_len; + + /* + * Clear errno to differentiate the end of the stream and an error condition + * + * From the Linux readdir() manpage: + * "If the end of the directory stream is reached, NULL is returned and errno is not changed. + * If an error occurs, NULL is returned and errno is set appropriately." + */ + errno = 0; + dd = readdir(d); + if (dd == 0 && errno != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error reading directory '%s'. %s.\n", dir, strerror(errno)); + log_fatal("You can exclude it in the config file with:\n\texclude /%s\n", sub); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (dd == 0) { + break; /* finished */ + } + + /* skip "." and ".." files */ + name = dd->d_name; + if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) + continue; + + pathprint(path_next, sizeof(path_next), "%s%s", dir, name); + pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name); + + /* check for not supported file names */ + if (name[0] == 0) { + /* LCOV_EXCL_START */ + log_fatal("Unsupported name '%s' in file '%s'.\n", name, path_next); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* exclude hidden files even before calling lstat() */ + if (filter_hidden(state->filter_hidden, dd) != 0) { + msg_verbose("Excluding hidden '%s'\n", path_next); + continue; + } + + /* exclude content files even before calling lstat() */ + if (filter_content(&state->contentlist, path_next) != 0) { + msg_verbose("Excluding content '%s'\n", path_next); + continue; + } + + name_len = strlen(dd->d_name); + entry = malloc_nofail(sizeof(struct dirent_sorted) + name_len + 1); + + /* copy the dir entry */ +#if HAVE_STRUCT_DIRENT_D_INO + entry->d_ino = dd->d_ino; +#endif +#if HAVE_STRUCT_DIRENT_D_TYPE + entry->d_type = dd->d_type; +#endif +#if HAVE_STRUCT_DIRENT_D_STAT + /* convert dirent to lstat result */ + dirent_lstat(dd, &entry->d_stat); + + /* note that at this point the st_mode may be 0 */ +#endif + memcpy(entry->d_name, dd->d_name, name_len + 1); + + /* insert in the list */ + tommy_list_insert_tail(&list, &entry->node, entry); + } + + if (closedir(d) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error closing directory '%s'. %s.\n", dir, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (state->opt.force_order == SORT_ALPHA) { + /* if requested sort alphabetically */ + /* this is mainly done for testing to ensure to always */ + /* process in the same way in different platforms */ + tommy_list_sort(&list, dd_name_compare); + } +#if HAVE_STRUCT_DIRENT_D_INO + else if (!disk->has_volatile_inodes) { + /* if inodes are persistent */ + /* sort the list of dir entries by inodes */ + tommy_list_sort(&list, dd_ino_compare); + } + /* otherwise just keep the insertion order */ +#endif + + /* process the sorted dir entries */ + node = list; + while (node != 0) { + char path_next[PATH_MAX]; + char sub_next[PATH_MAX]; + char out[PATH_MAX]; + struct snapraid_filter* reason = 0; + struct dirent_sorted* dd = node->data; + const char* name = dd->d_name; + struct stat* st; + int type; +#if !HAVE_STRUCT_DIRENT_D_STAT + struct stat st_buf; +#endif + + pathprint(path_next, sizeof(path_next), "%s%s", dir, name); + pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name); + + /* start with an unknown type */ + type = -1; + st = 0; + + /* if dirent has the type, use it */ +#if HAVE_STRUCT_DIRENT_D_TYPE + switch (dd->d_type) { + case DT_UNKNOWN : break; + case DT_REG : type = 0; break; + case DT_LNK : type = 1; break; + case DT_DIR : type = 2; break; + default : type = 3; break; + } +#endif + + /* if type is still unknown */ + if (type < 0) { + /* get the type from stat */ + st = DSTAT(path_next, dd, &st_buf); + +#if HAVE_STRUCT_DIRENT_D_STAT + /* if the st_mode field is missing, takes care to fill it using normal lstat() */ + /* at now this can happen only in Windows (with HAVE_STRUCT_DIRENT_D_STAT defined), */ + /* because we use a directory reading method that doesn't read info about ReparsePoint. */ + /* Note that here we cannot call here lstat_sync(), because we don't know what kind */ + /* of file is it, and lstat_sync() doesn't always work */ + if (st->st_mode == 0) { + if (lstat(path_next, st) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } +#endif + + if (S_ISREG(st->st_mode)) + type = 0; + else if (S_ISLNK(st->st_mode)) + type = 1; + else if (S_ISDIR(st->st_mode)) + type = 2; + else + type = 3; + } + + if (type == 0) { /* REG */ + if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) { + + /* late stat, if not yet called */ + if (!st) + st = DSTAT(path_next, dd, &st_buf); + +#if HAVE_LSTAT_SYNC + /* if the st_ino field is missing, takes care to fill it using the extended lstat() */ + /* this can happen only in Windows */ + if (st->st_ino == 0 || st->st_nlink == 0) { + if (lstat_sync(path_next, st, 0) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error in stat file '%s'. %s.\n", path_next, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } +#endif + + scan_file(scan, is_diff, sub_next, st, FILEPHY_UNREAD_OFFSET); + processed = 1; + } else { + msg_verbose("Excluding file '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); + } + } else if (type == 1) { /* LNK */ + if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) { + char subnew[PATH_MAX]; + int ret; + + ret = readlink(path_next, subnew, sizeof(subnew)); + if (ret >= PATH_MAX) { + /* LCOV_EXCL_START */ + log_fatal("Error in readlink file '%s'. Symlink too long.\n", path_next); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (ret < 0) { + /* LCOV_EXCL_START */ + log_fatal("Error in readlink file '%s'. %s.\n", path_next, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (ret == 0) + log_fatal("WARNING! Empty symbolic link '%s'.\n", path_next); + + /* readlink doesn't put the final 0 */ + subnew[ret] = 0; + + /* process as a symbolic link */ + scan_link(scan, is_diff, sub_next, subnew, FILE_IS_SYMLINK); + processed = 1; + } else { + msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); + } + } else if (type == 2) { /* DIR */ + if (filter_subdir(&state->filterlist, &reason, disk->name, sub_next) == 0) { +#ifndef _WIN32 + /* late stat, if not yet called */ + if (!st) + st = DSTAT(path_next, dd, &st_buf); + + /* in Unix don't follow mount points in different devices */ + /* in Windows we are already skipping them reporting them as special files */ + if ((uint64_t)st->st_dev != disk->device) { + log_fatal("WARNING! Ignoring mount point '%s' because it appears to be in a different device\n", path_next); + } else +#endif + { + char sub_dir[PATH_MAX]; + + /* recurse */ + pathslash(path_next, sizeof(path_next)); + pathcpy(sub_dir, sizeof(sub_dir), sub_next); + pathslash(sub_dir, sizeof(sub_dir)); + if (scan_dir(scan, level + 1, is_diff, path_next, sub_dir) == 0) { + /* scan the directory as empty dir */ + scan_emptydir(scan, sub_next); + } + /* or we processed something internally, or we have added the empty dir */ + processed = 1; + } + } else { + msg_verbose("Excluding directory '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); + } + } else { + if (filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) { + /* late stat, if not yet called */ + if (!st) + st = DSTAT(path_next, dd, &st_buf); + + log_fatal("WARNING! Ignoring special '%s' file '%s'\n", stat_desc(st), path_next); + } else { + msg_verbose("Excluding special file '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); + } + } + + /* next entry */ + node = node->next; + + /* free the present one */ + free(dd); + } + + return processed; +} + +static int state_diffscan(struct snapraid_state* state, int is_diff) +{ + tommy_node* i; + tommy_node* j; + tommy_list scanlist; + int done; + fptr* msg; + struct snapraid_scan total; + int no_difference; + char esc_buffer[ESC_MAX]; + + tommy_list_init(&scanlist); + + if (is_diff) + msg_progress("Comparing...\n"); + + /* first scan all the directory and find new and deleted files */ + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* disk = i->data; + struct snapraid_scan* scan; + tommy_node* node; + int ret; + int has_persistent_inodes; + int has_syncronized_hardlinks; + + scan = malloc_nofail(sizeof(struct snapraid_scan)); + scan->state = state; + scan->disk = disk; + scan->count_equal = 0; + scan->count_move = 0; + scan->count_copy = 0; + scan->count_restore = 0; + scan->count_change = 0; + scan->count_remove = 0; + scan->count_insert = 0; + tommy_list_init(&scan->file_insert_list); + tommy_list_init(&scan->link_insert_list); + tommy_list_init(&scan->dir_insert_list); + + tommy_list_insert_tail(&scanlist, &scan->node, scan); + + if (!is_diff) + msg_progress("Scanning disk %s...\n", disk->name); + + /* check if the disk supports persistent inodes */ + ret = fsinfo(disk->dir, &has_persistent_inodes, &has_syncronized_hardlinks, 0, 0); + if (ret < 0) { + /* LCOV_EXCL_START */ + log_fatal("Error accessing disk '%s' to get file-system info. %s.\n", disk->dir, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (!has_persistent_inodes) { + disk->has_volatile_inodes = 1; + } + if (!has_syncronized_hardlinks) { + disk->has_volatile_hardlinks = 1; + } + + /* if inodes or UUID are not persistent/changed/unsupported */ + if (disk->has_volatile_inodes || disk->has_different_uuid || disk->has_unsupported_uuid) { + /* remove all the inodes from the inode collection */ + /* if they are not persistent, all of them could be changed now */ + /* and we don't want to find false matching ones */ + /* see scan_file() for more details */ + node = disk->filelist; + while (node) { + struct snapraid_file* file = node->data; + + node = node->next; + + /* remove from the inode set */ + tommy_hashdyn_remove_existing(&disk->inodeset, &file->nodeset); + + /* clear the inode */ + file->inode = 0; + + /* mark as missing inode */ + file_flag_set(file, FILE_IS_WITHOUT_INODE); + } + } + + scan_dir(scan, 0, is_diff, disk->dir, ""); + } + + /* we split the search in two phases because to detect files */ + /* moved from one disk to another we have to start deletion */ + /* only when all disks have all the new files found */ + + /* now process all the new and deleted files */ + for (i = scanlist; i != 0; i = i->next) { + struct snapraid_scan* scan = i->data; + struct snapraid_disk* disk = scan->disk; + tommy_node* node; + unsigned phy_count; + unsigned phy_dup; + uint64_t phy_last; + struct snapraid_file* phy_file_last; + + /* check for removed files */ + node = disk->filelist; + while (node) { + struct snapraid_file* file = node->data; + + /* next node */ + node = node->next; + + /* remove if not present */ + if (!file_flag_has(file, FILE_IS_PRESENT)) { + ++scan->count_remove; + + log_tag("scan:remove:%s:%s\n", disk->name, esc_tag(file->sub, esc_buffer)); + if (is_diff) { + printf("remove %s\n", fmt_term(disk, file->sub, esc_buffer)); + } + + scan_file_remove(scan, file); + } + } + + /* check for removed links */ + node = disk->linklist; + while (node) { + struct snapraid_link* slink = node->data; + + /* next node */ + node = node->next; + + /* remove if not present */ + if (!link_flag_has(slink, FILE_IS_PRESENT)) { + ++scan->count_remove; + + log_tag("scan:remove:%s:%s\n", disk->name, esc_tag(slink->sub, esc_buffer)); + if (is_diff) { + printf("remove %s\n", fmt_term(disk, slink->sub, esc_buffer)); + } + + scan_link_remove(scan, slink); + } + } + + /* check for removed dirs */ + node = disk->dirlist; + while (node) { + struct snapraid_dir* dir = node->data; + + /* next node */ + node = node->next; + + /* remove if not present */ + if (!dir_flag_has(dir, FILE_IS_PRESENT)) { + scan_emptydir_remove(scan, dir); + } + } + + /* sort the files before inserting them */ + /* we use a stable sort to ensure that if the reported physical offset/inode */ + /* are always 0, we keep at least the directory order */ + switch (state->opt.force_order) { + case SORT_PHYSICAL : + tommy_list_sort(&scan->file_insert_list, file_physical_compare); + break; + case SORT_INODE : + tommy_list_sort(&scan->file_insert_list, file_inode_compare); + break; + case SORT_ALPHA : + tommy_list_sort(&scan->file_insert_list, file_path_compare); + break; + case SORT_DIR : + /* already in order */ + break; + } + + /* insert all the new files, we insert them only after the deletion */ + /* to reuse the just freed space */ + /* also check if the physical offset reported are fakes or not */ + node = scan->file_insert_list; + phy_count = 0; + phy_dup = 0; + phy_last = FILEPHY_UNREAD_OFFSET; + phy_file_last = 0; + while (node) { + struct snapraid_file* file = node->data; + + /* if the file is not empty, count duplicate physical offsets */ + if (state->opt.force_order == SORT_PHYSICAL && file->size != 0) { + if (phy_file_last != 0 && file->physical == phy_last + /* files without offset are expected to have duplicates */ + && phy_last != FILEPHY_WITHOUT_OFFSET + ) { + /* if verbose, print the list of duplicates real offsets */ + /* other cases are for offsets not supported, so we don't need to report them file by file */ + if (phy_last >= FILEPHY_REAL_OFFSET) { + log_fatal("WARNING! Files '%s%s' and '%s%s' have the same physical offset %" PRId64 ".\n", disk->dir, phy_file_last->sub, disk->dir, file->sub, phy_last); + } + ++phy_dup; + } + phy_file_last = file; + phy_last = file->physical; + ++phy_count; + } + + /* next node */ + node = node->next; + + /* insert in the parity */ + scan_file_allocate(scan, file); + } + + /* mark the disk without reliable physical offset if it has duplicates */ + /* here it should never happen because we already sorted out hardlinks */ + if (state->opt.force_order == SORT_PHYSICAL && phy_dup > 0) { + disk->has_unreliable_physical = 1; + } + + /* insert all the new links */ + node = scan->link_insert_list; + while (node) { + struct snapraid_link* slink = node->data; + + /* next node */ + node = node->next; + + /* insert it */ + scan_link_insert(scan, slink); + } + + /* insert all the new dirs */ + node = scan->dir_insert_list; + while (node) { + struct snapraid_dir* dir = node->data; + + /* next node */ + node = node->next; + + /* insert it */ + scan_emptydir_insert(scan, dir); + } + } + + /* check for disks where all the previously existing files where removed */ + if (!state->opt.force_empty) { + int all_missing = 0; + int all_rewritten = 0; + done = 0; + for (i = state->disklist, j = scanlist; i != 0; i = i->next, j = j->next) { + struct snapraid_disk* disk = i->data; + struct snapraid_scan* scan = j->data; + + if (scan->count_equal == 0 + && scan->count_move == 0 + && scan->count_restore == 0 + && (scan->count_remove != 0 || scan->count_change != 0) + ) { + if (!done) { + done = 1; + log_fatal("WARNING! All the files previously present in disk '%s' at dir '%s'", disk->name, disk->dir); + } else { + log_fatal(", disk '%s' at dir '%s'", disk->name, disk->dir); + } + + /* detect the special condition of all files missing */ + if (scan->count_change == 0) + all_missing = 1; + + /* detect the special condition of all files rewritten */ + if (scan->count_remove == 0) + all_rewritten = 1; + } + } + if (done) { + log_fatal("\nare now missing or rewritten!\n"); + if (all_rewritten) { + log_fatal("This could happen when restoring a disk with a backup\n"); + log_fatal("program that is not setting correctly the timestamps.\n"); + } + if (all_missing) { + log_fatal("This could happen when some disks are not mounted\n"); + log_fatal("in the expected directory.\n"); + } + if (!is_diff) { + log_fatal("If you want to '%s' anyway, use 'snapraid --force-empty %s'.\n", state->command, state->command); + exit(EXIT_FAILURE); + } + } + } + + /* check for disks without the physical offset support */ + if (state->opt.force_order == SORT_PHYSICAL) { + done = 0; + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* disk = i->data; + + if (disk->has_unreliable_physical) { + if (!done) { + done = 1; + log_fatal("WARNING! Physical offsets not supported for disk '%s'", disk->name); + } else { + log_fatal(", '%s'", disk->name); + } + } + } + if (done) { + log_fatal(". Files order won't be optimal.\n"); + } + } + + /* check for disks without persistent inodes */ + done = 0; + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* disk = i->data; + + if (disk->has_volatile_inodes) { + if (!done) { + done = 1; + log_fatal("WARNING! Inodes are not persistent for disks: '%s'", disk->name); + } else { + log_fatal(", '%s'", disk->name); + } + } + } + if (done) { + log_fatal(". Not using inodes to detect move operations.\n"); + } + + /* check for disks with changed UUID */ + done = 0; + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* disk = i->data; + + /* don't print the message if the UUID changed because before */ + /* it was no set. */ + /* this is the normal condition for an empty disk because it */ + /* isn't stored */ + if (disk->has_different_uuid && !disk->had_empty_uuid) { + if (!done) { + done = 1; + log_fatal("WARNING! UUID is changed for disks: '%s'", disk->name); + } else { + log_fatal(", '%s'", disk->name); + } + } + } + if (done) { + log_fatal(". Not using inodes to detect move operations.\n"); + } + + /* check for disks with unsupported UUID */ + done = 0; + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* disk = i->data; + + if (disk->has_unsupported_uuid) { + if (!done) { + done = 1; + log_fatal("WARNING! UUID is unsupported for disks: '%s'", disk->name); + } else { + log_fatal(", '%s'", disk->name); + } + } + } + if (done) { + log_fatal(". Not using inodes to detect move operations.\n"); +#if defined(_linux) && !HAVE_BLKID + log_fatal("The 'blkid' library is not linked in SnapRAID!\n"); + log_fatal("Try rebuilding it after installing the libblkid-dev or libblkid-devel package.\n"); +#endif + } + + total.count_equal = 0; + total.count_move = 0; + total.count_copy = 0; + total.count_restore = 0; + total.count_change = 0; + total.count_remove = 0; + total.count_insert = 0; + + for (i = scanlist; i != 0; i = i->next) { + struct snapraid_scan* scan = i->data; + total.count_equal += scan->count_equal; + total.count_move += scan->count_move; + total.count_copy += scan->count_copy; + total.count_restore += scan->count_restore; + total.count_change += scan->count_change; + total.count_remove += scan->count_remove; + total.count_insert += scan->count_insert; + } + + if (is_diff) { + msg_status("\n"); + msg = msg_status; + } else { + msg = msg_verbose; + } + + msg("%8u equal\n", total.count_equal); + msg("%8u added\n", total.count_insert); + msg("%8u removed\n", total.count_remove); + msg("%8u updated\n", total.count_change); + msg("%8u moved\n", total.count_move); + msg("%8u copied\n", total.count_copy); + msg("%8u restored\n", total.count_restore); + + log_tag("summary:equal:%u\n", total.count_equal); + log_tag("summary:added:%u\n", total.count_insert); + log_tag("summary:removed:%u\n", total.count_remove); + log_tag("summary:updated:%u\n", total.count_change); + log_tag("summary:moved:%u\n", total.count_move); + log_tag("summary:copied:%u\n", total.count_copy); + log_tag("summary:restored:%u\n", total.count_restore); + + no_difference = !total.count_move && !total.count_copy && !total.count_restore + && !total.count_change && !total.count_remove && !total.count_insert; + + if (is_diff) { + if (no_difference) { + msg_status("No differences\n"); + } else { + msg_status("There are differences!\n"); + } + } + + if (no_difference) { + log_tag("summary:exit:equal\n"); + } else { + log_tag("summary:exit:diff\n"); + } + log_flush(); + + tommy_list_foreach(&scanlist, (tommy_foreach_func*)free); + + /* check the file-system on all disks */ + state_fscheck(state, "after scan"); + + if (is_diff) { + /* check for file difference */ + if (!no_difference) + return 1; + + /* check also for incomplete "sync" */ + if (parity_is_invalid(state)) + return 1; + } + + return 0; +} + +int state_diff(struct snapraid_state* state) +{ + return state_diffscan(state, 1); +} + +void state_scan(struct snapraid_state* state) +{ + (void)state_diffscan(state, 0); /* ignore return value */ +} + diff --git a/cmdline/scrub.c b/cmdline/scrub.c new file mode 100644 index 0000000..20a7ead --- /dev/null +++ b/cmdline/scrub.c @@ -0,0 +1,902 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "support.h" +#include "elem.h" +#include "state.h" +#include "parity.h" +#include "handle.h" +#include "io.h" +#include "raid/raid.h" + +/****************************************************************************/ +/* scrub */ + +/** + * Buffer for storing the new hashes. + */ +struct snapraid_rehash { + unsigned char hash[HASH_MAX]; + struct snapraid_block* block; +}; + +/** + * Scrub plan to use. + */ +struct snapraid_plan { + struct snapraid_state* state; + int plan; /**< One of the SCRUB_*. */ + time_t timelimit; /**< Time limit. Valid only with SCRUB_AUTO. */ + block_off_t lastlimit; /**< Number of blocks allowed with time exactly at ::timelimit. */ + block_off_t countlast; /**< Counter of blocks with time exactly at ::timelimit. */ +}; + +/** + * Check if we have to process the specified block index ::i. + */ +static int block_is_enabled(void* void_plan, block_off_t i) +{ + struct snapraid_plan* plan = void_plan; + time_t blocktime; + snapraid_info info; + + /* don't scrub unused blocks in all plans */ + info = info_get(&plan->state->infoarr, i); + if (info == 0) + return 0; + + /* bad blocks are always scrubbed in all plans */ + if (info_get_bad(info)) + return 1; + + switch (plan->plan) { + case SCRUB_FULL : + /* in 'full' plan everything is scrubbed */ + return 1; + case SCRUB_EVEN : + /* in 'even' plan, scrub only even blocks */ + return i % 2 == 0; + case SCRUB_NEW : + /* in 'sync' plan, only blocks never scrubbed */ + return info_get_justsynced(info); + case SCRUB_BAD : + /* in 'bad' plan, only bad blocks (already reported) */ + return 0; + } + + /* if it's too new */ + blocktime = info_get_time(info); + if (blocktime > plan->timelimit) { + /* skip it */ + return 0; + } + + /* if the time is less than the limit, always include */ + /* otherwise, check if we reached the last limit count */ + if (blocktime == plan->timelimit) { + /* if we reached the count limit */ + if (plan->countlast >= plan->lastlimit) { + /* skip it */ + return 0; + } + + ++plan->countlast; + } + + return 1; +} + +static void scrub_data_reader(struct snapraid_worker* worker, struct snapraid_task* task) +{ + struct snapraid_io* io = worker->io; + struct snapraid_state* state = io->state; + struct snapraid_handle* handle = worker->handle; + struct snapraid_disk* disk = handle->disk; + block_off_t blockcur = task->position; + unsigned char* buffer = task->buffer; + int ret; + char esc_buffer[ESC_MAX]; + + /* if the disk position is not used */ + if (!disk) { + /* use an empty block */ + memset(buffer, 0, state->block_size); + task->state = TASK_STATE_DONE; + return; + } + + /* get the block */ + task->block = fs_par2block_find(disk, blockcur); + + /* if the block is not used */ + if (!block_has_file(task->block)) { + /* use an empty block */ + memset(buffer, 0, state->block_size); + task->state = TASK_STATE_DONE; + return; + } + + /* get the file of this block */ + task->file = fs_par2file_get(disk, blockcur, &task->file_pos); + + /* if the file is different than the current one, close it */ + if (handle->file != 0 && handle->file != task->file) { + /* keep a pointer at the file we are going to close for error reporting */ + struct snapraid_file* report = handle->file; + ret = handle_close(handle); + if (ret == -1) { + /* LCOV_EXCL_START */ + /* This one is really an unexpected error, because we are only reading */ + /* and closing a descriptor should never fail */ + if (errno == EIO) { + log_tag("error:%u:%s:%s: Close EIO error. %s\n", blockcur, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno)); + log_fatal("DANGER! Unexpected input/output close error in a data disk, it isn't possible to scrub.\n"); + log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle->path); + log_fatal("Stopping at block %u\n", blockcur); + task->state = TASK_STATE_IOERROR; + return; + } + + log_tag("error:%u:%s:%s: Close error. %s\n", blockcur, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno)); + log_fatal("WARNING! Unexpected close error in a data disk, it isn't possible to scrub.\n"); + log_fatal("Ensure that file '%s' can be accessed.\n", handle->path); + log_fatal("Stopping at block %u\n", blockcur); + task->state = TASK_STATE_ERROR; + return; + /* LCOV_EXCL_STOP */ + } + } + + ret = handle_open(handle, task->file, state->file_mode, log_error, 0); + if (ret == -1) { + if (errno == EIO) { + /* LCOV_EXCL_START */ + log_tag("error:%u:%s:%s: Open EIO error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno)); + log_fatal("DANGER! Unexpected input/output open error in a data disk, it isn't possible to scrub.\n"); + log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle->path); + log_fatal("Stopping at block %u\n", blockcur); + task->state = TASK_STATE_IOERROR; + return; + /* LCOV_EXCL_STOP */ + } + + log_tag("error:%u:%s:%s: Open error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno)); + task->state = TASK_STATE_ERROR_CONTINUE; + return; + } + + /* check if the file is changed */ + if (handle->st.st_size != task->file->size + || handle->st.st_mtime != task->file->mtime_sec + || STAT_NSEC(&handle->st) != task->file->mtime_nsec + /* don't check the inode to support filesystem without persistent inodes */ + ) { + /* report that the block and the file are not synced */ + task->is_timestamp_different = 1; + /* follow */ + } + + /* note that we intentionally don't abort if the file has different attributes */ + /* from the last sync, as we are expected to return errors if running */ + /* in an unsynced array. This is just like the check command. */ + + task->read_size = handle_read(handle, task->file_pos, buffer, state->block_size, log_error, 0); + if (task->read_size == -1) { + if (errno == EIO) { + log_tag("error:%u:%s:%s: Read EIO error at position %u. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), task->file_pos, strerror(errno)); + log_error("Input/Output error in file '%s' at position '%u'\n", handle->path, task->file_pos); + task->state = TASK_STATE_IOERROR_CONTINUE; + return; + } + + log_tag("error:%u:%s:%s: Read error at position %u. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), task->file_pos, strerror(errno)); + task->state = TASK_STATE_ERROR_CONTINUE; + return; + } + + /* store the path of the opened file */ + pathcpy(task->path, sizeof(task->path), handle->path); + + task->state = TASK_STATE_DONE; +} + +static void scrub_parity_reader(struct snapraid_worker* worker, struct snapraid_task* task) +{ + struct snapraid_io* io = worker->io; + struct snapraid_state* state = io->state; + struct snapraid_parity_handle* parity_handle = worker->parity_handle; + unsigned level = parity_handle->level; + block_off_t blockcur = task->position; + unsigned char* buffer = task->buffer; + int ret; + + /* read the parity */ + ret = parity_read(parity_handle, blockcur, buffer, state->block_size, log_error); + if (ret == -1) { + if (errno == EIO) { + log_tag("parity_error:%u:%s: Read EIO error. %s\n", blockcur, lev_config_name(level), strerror(errno)); + log_error("Input/Output error in parity '%s' at position '%u'\n", lev_config_name(level), blockcur); + task->state = TASK_STATE_IOERROR_CONTINUE; + return; + } + + log_tag("parity_error:%u:%s: Read error. %s\n", blockcur, lev_config_name(level), strerror(errno)); + task->state = TASK_STATE_ERROR_CONTINUE; + return; + } + + task->state = TASK_STATE_DONE; +} + +static int state_scrub_process(struct snapraid_state* state, struct snapraid_parity_handle* parity_handle, block_off_t blockstart, block_off_t blockmax, struct snapraid_plan* plan, time_t now) +{ + struct snapraid_io io; + struct snapraid_handle* handle; + void* rehandle_alloc; + struct snapraid_rehash* rehandle; + unsigned diskmax; + block_off_t blockcur; + unsigned j; + unsigned buffermax; + data_off_t countsize; + block_off_t countpos; + block_off_t countmax; + block_off_t autosavedone; + block_off_t autosavelimit; + block_off_t autosavemissing; + int ret; + unsigned error; + unsigned silent_error; + unsigned io_error; + unsigned l; + unsigned* waiting_map; + unsigned waiting_mac; + char esc_buffer[ESC_MAX]; + + /* maps the disks to handles */ + handle = handle_mapping(state, &diskmax); + + /* rehash buffers */ + rehandle = malloc_nofail_align(diskmax * sizeof(struct snapraid_rehash), &rehandle_alloc); + + /* we need 1 * data + 2 * parity */ + buffermax = diskmax + 2 * state->level; + + /* initialize the io threads */ + io_init(&io, state, state->opt.io_cache, buffermax, scrub_data_reader, handle, diskmax, scrub_parity_reader, 0, parity_handle, state->level); + + /* possibly waiting disks */ + waiting_mac = diskmax > RAID_PARITY_MAX ? diskmax : RAID_PARITY_MAX; + waiting_map = malloc_nofail(waiting_mac * sizeof(unsigned)); + + error = 0; + silent_error = 0; + io_error = 0; + + /* first count the number of blocks to process */ + countmax = 0; + plan->countlast = 0; + for (blockcur = blockstart; blockcur < blockmax; ++blockcur) { + if (!block_is_enabled(plan, blockcur)) + continue; + ++countmax; + } + + /* compute the autosave size for all disk, even if not read */ + /* this makes sense because the speed should be almost the same */ + /* if the disks are read in parallel */ + autosavelimit = state->autosave / (diskmax * state->block_size); + autosavemissing = countmax; /* blocks to do */ + autosavedone = 0; /* blocks done */ + + /* drop until now */ + state_usage_waste(state); + + countsize = 0; + countpos = 0; + plan->countlast = 0; + + /* start all the worker threads */ + io_start(&io, blockstart, blockmax, &block_is_enabled, plan); + + state_progress_begin(state, blockstart, blockmax, countmax); + while (1) { + unsigned char* buffer_recov[LEV_MAX]; + snapraid_info info; + int error_on_this_block; + int silent_error_on_this_block; + int io_error_on_this_block; + int block_is_unsynced; + int rehash; + void** buffer; + + /* go to the next block */ + blockcur = io_read_next(&io, &buffer); + if (blockcur >= blockmax) + break; + + /* until now is scheduling */ + state_usage_sched(state); + + /* one more block processed for autosave */ + ++autosavedone; + --autosavemissing; + + /* by default process the block, and skip it if something goes wrong */ + error_on_this_block = 0; + silent_error_on_this_block = 0; + io_error_on_this_block = 0; + + /* if all the blocks at this address are synced */ + /* if not, parity is not even checked */ + block_is_unsynced = 0; + + /* get block specific info */ + info = info_get(&state->infoarr, blockcur); + + /* if we have to use the old hash */ + rehash = info_get_rehash(info); + + /* for each disk, process the block */ + for (j = 0; j < diskmax; ++j) { + struct snapraid_task* task; + int read_size; + unsigned char hash[HASH_MAX]; + struct snapraid_block* block; + int file_is_unsynced; + struct snapraid_disk* disk; + struct snapraid_file* file; + block_off_t file_pos; + unsigned diskcur; + + /* if the file on this disk is synced */ + /* if not, silent errors are assumed as expected error */ + file_is_unsynced = 0; + + /* until now is misc */ + state_usage_misc(state); + + /* get the next task */ + task = io_data_read(&io, &diskcur, waiting_map, &waiting_mac); + + /* until now is disk */ + state_usage_disk(state, handle, waiting_map, waiting_mac); + + /* get the task results */ + disk = task->disk; + block = task->block; + file = task->file; + file_pos = task->file_pos; + read_size = task->read_size; + + /* by default no rehash in case of "continue" */ + rehandle[diskcur].block = 0; + + /* if the disk position is not used */ + if (!disk) + continue; + + state_usage_file(state, disk, file); + + /* if the block is unsynced, errors are expected */ + if (block_has_invalid_parity(block)) { + /* report that the block and the file are not synced */ + block_is_unsynced = 1; + file_is_unsynced = 1; + /* follow */ + } + + /* if the block is not used */ + if (!block_has_file(block)) + continue; + + /* if the block is unsynced, errors are expected */ + if (task->is_timestamp_different) { + /* report that the block and the file are not synced */ + block_is_unsynced = 1; + file_is_unsynced = 1; + /* follow */ + } + + /* handle error conditions */ + if (task->state == TASK_STATE_IOERROR) { + /* LCOV_EXCL_START */ + ++io_error; + goto bail; + /* LCOV_EXCL_STOP */ + } + if (task->state == TASK_STATE_ERROR) { + /* LCOV_EXCL_START */ + ++error; + goto bail; + /* LCOV_EXCL_STOP */ + } + if (task->state == TASK_STATE_ERROR_CONTINUE) { + ++error; + error_on_this_block = 1; + continue; + } + if (task->state == TASK_STATE_IOERROR_CONTINUE) { + ++io_error; + if (io_error >= state->opt.io_error_limit) { + /* LCOV_EXCL_START */ + log_fatal("DANGER! Too many input/output read error in a data disk, it isn't possible to scrub.\n"); + log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, task->path); + log_fatal("Stopping at block %u\n", blockcur); + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* otherwise continue */ + io_error_on_this_block = 1; + continue; + } + if (task->state != TASK_STATE_DONE) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in task state\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + countsize += read_size; + + /* now compute the hash */ + if (rehash) { + memhash(state->prevhash, state->prevhashseed, hash, buffer[diskcur], read_size); + + /* compute the new hash, and store it */ + rehandle[diskcur].block = block; + memhash(state->hash, state->hashseed, rehandle[diskcur].hash, buffer[diskcur], read_size); + } else { + memhash(state->hash, state->hashseed, hash, buffer[diskcur], read_size); + } + + /* until now is hash */ + state_usage_hash(state); + + if (block_has_updated_hash(block)) { + /* compare the hash */ + if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { + unsigned diff = memdiff(hash, block->hash, BLOCK_HASH_SIZE); + + log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u/%u\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff, BLOCK_HASH_SIZE * 8); + + /* it's a silent error only if we are dealing with synced files */ + if (file_is_unsynced) { + ++error; + error_on_this_block = 1; + } else { + log_error("Data error in file '%s' at position '%u', diff bits %u/%u\n", task->path, file_pos, diff, BLOCK_HASH_SIZE * 8); + ++silent_error; + silent_error_on_this_block = 1; + } + continue; + } + } + } + + /* buffers for parity read and not computed */ + for (l = 0; l < state->level; ++l) + buffer_recov[l] = buffer[diskmax + state->level + l]; + for (; l < LEV_MAX; ++l) + buffer_recov[l] = 0; + + /* until now is misc */ + state_usage_misc(state); + + /* read the parity */ + for (l = 0; l < state->level; ++l) { + struct snapraid_task* task; + unsigned levcur; + + task = io_parity_read(&io, &levcur, waiting_map, &waiting_mac); + + /* until now is parity */ + state_usage_parity(state, waiting_map, waiting_mac); + + /* handle error conditions */ + if (task->state == TASK_STATE_IOERROR) { + /* LCOV_EXCL_START */ + ++io_error; + goto bail; + /* LCOV_EXCL_STOP */ + } + if (task->state == TASK_STATE_ERROR) { + /* LCOV_EXCL_START */ + ++error; + goto bail; + /* LCOV_EXCL_STOP */ + } + if (task->state == TASK_STATE_ERROR_CONTINUE) { + ++error; + error_on_this_block = 1; + + /* if continuing on error, clear the missing buffer */ + buffer_recov[levcur] = 0; + continue; + } + if (task->state == TASK_STATE_IOERROR_CONTINUE) { + ++io_error; + if (io_error >= state->opt.io_error_limit) { + /* LCOV_EXCL_START */ + log_fatal("DANGER! Too many input/output read error in the %s disk, it isn't possible to scrub.\n", lev_name(levcur)); + log_fatal("Ensure that disk '%s' is sane and can be read.\n", lev_config_name(levcur)); + log_fatal("Stopping at block %u\n", blockcur); + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* otherwise continue */ + io_error_on_this_block = 1; + + /* if continuing on error, clear the missing buffer */ + buffer_recov[levcur] = 0; + continue; + } + if (task->state != TASK_STATE_DONE) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in task state\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + } + + /* if we have read all the data required and it's correct, proceed with the parity check */ + if (!error_on_this_block && !silent_error_on_this_block && !io_error_on_this_block) { + + /* compute the parity */ + raid_gen(diskmax, state->level, state->block_size, buffer); + + /* compare the parity */ + for (l = 0; l < state->level; ++l) { + if (buffer_recov[l] && memcmp(buffer[diskmax + l], buffer_recov[l], state->block_size) != 0) { + unsigned diff = memdiff(buffer[diskmax + l], buffer_recov[l], state->block_size); + + log_tag("parity_error:%u:%s: Data error, diff bits %u/%u\n", blockcur, lev_config_name(l), diff, state->block_size * 8); + + /* it's a silent error only if we are dealing with synced blocks */ + if (block_is_unsynced) { + ++error; + error_on_this_block = 1; + } else { + log_fatal("Data error in parity '%s' at position '%u', diff bits %u/%u\n", lev_config_name(l), blockcur, diff, state->block_size * 8); + ++silent_error; + silent_error_on_this_block = 1; + } + } + } + + /* until now is raid */ + state_usage_raid(state); + } + + if (silent_error_on_this_block || io_error_on_this_block) { + /* set the error status keeping other info */ + info_set(&state->infoarr, blockcur, info_set_bad(info)); + } else if (error_on_this_block) { + /* do nothing, as this is a generic error */ + /* likely caused by a not synced array */ + } else { + /* if rehash is needed */ + if (rehash) { + /* store all the new hash already computed */ + for (j = 0; j < diskmax; ++j) { + if (rehandle[j].block) + memcpy(rehandle[j].block->hash, rehandle[j].hash, BLOCK_HASH_SIZE); + } + } + + /* update the time info of the block */ + /* and clear any other flag */ + info_set(&state->infoarr, blockcur, info_make(now, 0, 0, 0)); + } + + /* mark the state as needing write */ + state->need_write = 1; + + /* count the number of processed block */ + ++countpos; + + /* progress */ + if (state_progress(state, &io, blockcur, countpos, countmax, countsize)) { + /* LCOV_EXCL_START */ + break; + /* LCOV_EXCL_STOP */ + } + + /* autosave */ + if (state->autosave != 0 + && autosavedone >= autosavelimit /* if we have reached the limit */ + && autosavemissing >= autosavelimit /* if we have at least a full step to do */ + ) { + autosavedone = 0; /* restart the counter */ + + /* until now is misc */ + state_usage_misc(state); + + state_progress_stop(state); + + msg_progress("Autosaving...\n"); + state_write(state); + + state_progress_restart(state); + + /* drop until now */ + state_usage_waste(state); + } + } + + state_progress_end(state, countpos, countmax, countsize); + + state_usage_print(state); + + if (error || silent_error || io_error) { + msg_status("\n"); + msg_status("%8u file errors\n", error); + msg_status("%8u io errors\n", io_error); + msg_status("%8u data errors\n", silent_error); + } else { + /* print the result only if processed something */ + if (countpos != 0) + msg_status("Everything OK\n"); + } + + if (error) + log_fatal("WARNING! Unexpected file errors!\n"); + if (io_error) + log_fatal("DANGER! Unexpected input/output errors! The failing blocks are now marked as bad!\n"); + if (silent_error) + log_fatal("DANGER! Unexpected data errors! The failing blocks are now marked as bad!\n"); + if (io_error || silent_error) { + log_fatal("Use 'snapraid status' to list the bad blocks.\n"); + log_fatal("Use 'snapraid -e fix' to recover.\n"); + } + + log_tag("summary:error_file:%u\n", error); + log_tag("summary:error_io:%u\n", io_error); + log_tag("summary:error_data:%u\n", silent_error); + if (error + silent_error + io_error == 0) + log_tag("summary:exit:ok\n"); + else + log_tag("summary:exit:error\n"); + log_flush(); + +bail: + /* stop all the worker threads */ + io_stop(&io); + + for (j = 0; j < diskmax; ++j) { + struct snapraid_file* file = handle[j].file; + struct snapraid_disk* disk = handle[j].disk; + ret = handle_close(&handle[j]); + if (ret == -1) { + /* LCOV_EXCL_START */ + log_tag("error:%u:%s:%s: Close error. %s\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); + log_fatal("DANGER! Unexpected close error in a data disk.\n"); + ++error; + /* continue, as we are already exiting */ + /* LCOV_EXCL_STOP */ + } + } + + free(handle); + free(rehandle_alloc); + free(waiting_map); + io_done(&io); + + if (state->opt.expect_recoverable) { + if (error + silent_error + io_error == 0) + return -1; + } else { + if (error + silent_error + io_error != 0) + return -1; + } + return 0; +} + +/** + * Return a * b / c approximated to the upper value. + */ +static uint32_t md(uint32_t a, uint32_t b, uint32_t c) +{ + uint64_t v = a; + + v *= b; + v += c - 1; + v /= c; + + return v; +} + +int state_scrub(struct snapraid_state* state, int plan, int olderthan) +{ + block_off_t blockmax; + block_off_t countlimit; + block_off_t i; + block_off_t count; + time_t recentlimit; + int ret; + struct snapraid_parity_handle parity_handle[LEV_MAX]; + struct snapraid_plan ps; + time_t* timemap; + unsigned error; + time_t now; + unsigned l; + + /* get the present time */ + now = time(0); + + msg_progress("Initializing...\n"); + + if ((plan == SCRUB_BAD || plan == SCRUB_NEW || plan == SCRUB_FULL) + && olderthan >= 0) { + /* LCOV_EXCL_START */ + log_fatal("You can specify -o, --older-than only with a numeric percentage.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + blockmax = parity_allocated_size(state); + + /* preinitialize to avoid warnings */ + countlimit = 0; + recentlimit = 0; + + ps.state = state; + if (state->opt.force_scrub_even) { + ps.plan = SCRUB_EVEN; + } else if (plan == SCRUB_FULL) { + ps.plan = SCRUB_FULL; + } else if (plan == SCRUB_NEW) { + ps.plan = SCRUB_NEW; + } else if (plan == SCRUB_BAD) { + ps.plan = SCRUB_BAD; + } else if (state->opt.force_scrub_at) { + /* scrub the specified amount of blocks */ + ps.plan = SCRUB_AUTO; + countlimit = state->opt.force_scrub_at; + recentlimit = now; + } else { + ps.plan = SCRUB_AUTO; + if (plan >= 0) { + countlimit = md(blockmax, plan, 100); + } else { + /* by default scrub 8.33% of the array (100/12=8.(3)) */ + countlimit = md(blockmax, 1, 12); + } + + if (olderthan >= 0) { + recentlimit = now - olderthan * 24 * 3600; + } else { + /* by default use a 10 day time limit */ + recentlimit = now - 10 * 24 * 3600; + } + } + + /* identify the time limit */ + /* we sort all the block times, and we identify the time limit for which we reach the quota */ + /* this allow to process first the oldest blocks */ + timemap = malloc_nofail(blockmax * sizeof(time_t)); + + /* copy the info in the temp vector */ + count = 0; + log_tag("block_count:%u\n", blockmax); + for (i = 0; i < blockmax; ++i) { + snapraid_info info = info_get(&state->infoarr, i); + + /* skip unused blocks */ + if (info == 0) + continue; + + timemap[count++] = info_get_time(info); + } + + if (!count) { + /* LCOV_EXCL_START */ + log_fatal("The array appears to be empty.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* sort it */ + qsort(timemap, count, sizeof(time_t), time_compare); + + /* output the info map */ + i = 0; + log_tag("info_count:%u\n", count); + while (i < count) { + unsigned j = i + 1; + while (j < count && timemap[i] == timemap[j]) + ++j; + log_tag("info_time:%" PRIu64 ":%u\n", (uint64_t)timemap[i], j - i); + i = j; + } + + /* compute the limits from count/recentlimit */ + if (ps.plan == SCRUB_AUTO) { + /* no more than the full count */ + if (countlimit > count) + countlimit = count; + + /* decrease until we reach the specific recentlimit */ + while (countlimit > 0 && timemap[countlimit - 1] > recentlimit) + --countlimit; + + /* if there is something to scrub */ + if (countlimit > 0) { + /* get the most recent time we want to scrub */ + ps.timelimit = timemap[countlimit - 1]; + + /* count how many entries for this exact time we have to scrub */ + /* if the blocks have all the same time, we end with countlimit == lastlimit */ + ps.lastlimit = 1; + while (countlimit > ps.lastlimit && timemap[countlimit - ps.lastlimit - 1] == ps.timelimit) + ++ps.lastlimit; + } else { + /* if nothing to scrub, disable also other limits */ + ps.timelimit = 0; + ps.lastlimit = 0; + } + + log_tag("count_limit:%u\n", countlimit); + log_tag("time_limit:%" PRIu64 "\n", (uint64_t)ps.timelimit); + log_tag("last_limit:%u\n", ps.lastlimit); + } + + /* free the temp vector */ + free(timemap); + + /* open the file for reading */ + for (l = 0; l < state->level; ++l) { + ret = parity_open(&parity_handle[l], &state->parity[l], l, state->file_mode, state->block_size, state->opt.parity_limit_size); + if (ret == -1) { + /* LCOV_EXCL_START */ + log_fatal("WARNING! Without an accessible %s file, it isn't possible to scrub.\n", lev_name(l)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + msg_progress("Scrubbing...\n"); + + error = 0; + + ret = state_scrub_process(state, parity_handle, 0, blockmax, &ps, now); + if (ret == -1) { + ++error; + /* continue, as we are already exiting */ + } + + for (l = 0; l < state->level; ++l) { + ret = parity_close(&parity_handle[l]); + if (ret == -1) { + /* LCOV_EXCL_START */ + log_fatal("DANGER! Unexpected close error in %s disk.\n", lev_name(l)); + ++error; + /* continue, as we are already exiting */ + /* LCOV_EXCL_STOP */ + } + } + + /* abort if required */ + if (error != 0) + return -1; + return 0; +} + diff --git a/cmdline/search.c b/cmdline/search.c new file mode 100644 index 0000000..3d543fa --- /dev/null +++ b/cmdline/search.c @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2014 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "support.h" +#include "search.h" + +/****************************************************************************/ +/* search */ + +static void search_file(struct snapraid_state* state, const char* path, data_off_t size, int64_t mtime_sec, int mtime_nsec) +{ + struct snapraid_search_file* file; + tommy_uint32_t file_hash; + + file = malloc_nofail(sizeof(struct snapraid_search_file)); + file->path = strdup_nofail(path); + file->size = size; + file->mtime_sec = mtime_sec; + file->mtime_nsec = mtime_nsec; + + file_hash = file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec); + + tommy_hashdyn_insert(&state->searchset, &file->node, file, file_hash); +} + +void search_file_free(struct snapraid_search_file* file) +{ + free(file->path); + free(file); +} + +struct search_file_compare_arg { + const struct snapraid_state* state; + const struct snapraid_block* block; + const struct snapraid_file* file; + unsigned char* buffer; + data_off_t offset; + unsigned read_size; + int prevhash; +}; + +int search_file_compare(const void* void_arg, const void* void_data) +{ + const struct search_file_compare_arg* arg = void_arg; + const struct snapraid_search_file* file = void_data; + const struct snapraid_state* state = arg->state; + unsigned char buffer_hash[HASH_MAX]; + const char* path = file->path; + int f; + ssize_t ret; + + /* compare file info */ + if (arg->file->size != file->size) + return -1; + + if (arg->file->mtime_sec != file->mtime_sec) + return -1; + + if (arg->file->mtime_nsec != file->mtime_nsec) + return -1; + + /* read the block and compare the hash */ + f = open(path, O_RDONLY | O_BINARY); + if (f == -1) { + /* LCOV_EXCL_START */ + if (errno == ENOENT) { + log_fatal("DANGER! file '%s' disappeared.\n", path); + log_fatal("If you moved it, please rerun the same command.\n"); + } else { + log_fatal("Error opening file '%s'. %s.\n", path, strerror(errno)); + } + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + ret = pread(f, arg->buffer, arg->read_size, arg->offset); + if (ret < 0 || (unsigned)ret != arg->read_size) { + /* LCOV_EXCL_START */ + log_fatal("Error reading file '%s'. %s.\n", path, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + ret = close(f); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error closing file '%s'. %s.\n", path, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* compute the hash */ + if (arg->prevhash) + memhash(state->prevhash, state->prevhashseed, buffer_hash, arg->buffer, arg->read_size); + else + memhash(state->hash, state->hashseed, buffer_hash, arg->buffer, arg->read_size); + + /* check if the hash is matching */ + if (memcmp(buffer_hash, arg->block->hash, BLOCK_HASH_SIZE) != 0) + return -1; + + if (arg->read_size != state->block_size) { + /* fill the remaining with 0 */ + memset(arg->buffer + arg->read_size, 0, state->block_size - arg->read_size); + } + + return 0; +} + +int state_search_fetch(struct snapraid_state* state, int prevhash, struct snapraid_file* missing_file, block_off_t missing_file_pos, struct snapraid_block* missing_block, unsigned char* buffer) +{ + struct snapraid_search_file* file; + tommy_uint32_t file_hash; + struct search_file_compare_arg arg; + + arg.state = state; + arg.block = missing_block; + arg.file = missing_file; + arg.buffer = buffer; + arg.offset = state->block_size * (data_off_t)missing_file_pos; + arg.read_size = file_block_size(missing_file, missing_file_pos, state->block_size); + arg.prevhash = prevhash; + + file_hash = file_stamp_hash(arg.file->size, arg.file->mtime_sec, arg.file->mtime_nsec); + + /* search in the hashtable, and also check if the data matches the hash */ + file = tommy_hashdyn_search(&state->searchset, search_file_compare, &arg, file_hash); + if (!file) + return -1; + + /* if found, buffer is already set with data */ + return 0; +} + +static void search_dir(struct snapraid_state* state, struct snapraid_disk* disk, const char* dir, const char* sub) +{ + DIR* d; + + d = opendir(dir); + if (!d) { + /* LCOV_EXCL_START */ + log_fatal("Error opening directory '%s'. %s.\n", dir, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + while (1) { + char path_next[PATH_MAX]; + char sub_next[PATH_MAX]; + char out[PATH_MAX]; + struct snapraid_filter* reason = 0; + struct stat st; + const char* name; + struct dirent* dd; + + /* clear errno to detect erroneous conditions */ + errno = 0; + dd = readdir(d); + if (dd == 0 && errno != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error reading directory '%s'. %s.\n", dir, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (dd == 0) { + break; /* finished */ + } + + /* skip "." and ".." files */ + name = dd->d_name; + if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) + continue; + + pathprint(path_next, sizeof(path_next), "%s%s", dir, name); + pathprint(sub_next, sizeof(sub_next), "%s%s", sub, name); + + /* exclude hidden files even before calling lstat() */ + if (disk != 0 && filter_hidden(state->filter_hidden, dd) != 0) { + msg_verbose("Excluding hidden '%s'\n", path_next); + continue; + } + + /* exclude content files even before calling lstat() */ + if (disk != 0 && filter_content(&state->contentlist, path_next) != 0) { + msg_verbose("Excluding content '%s'\n", path_next); + continue; + } + +#if HAVE_STRUCT_DIRENT_D_STAT + /* convert dirent to lstat result */ + dirent_lstat(dd, &st); + + /* if the st_mode field is missing, takes care to fill it using normal lstat() */ + /* at now this can happen only in Windows (with HAVE_STRUCT_DIRENT_D_STAT defined), */ + /* because we use a directory reading method that doesn't read info about ReparsePoint. */ + /* Note that here we cannot call here lstat_sync(), because we don't know what kind */ + /* of file is it, and lstat_sync() doesn't always work */ + if (st.st_mode == 0) { + if (lstat(path_next, &st) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } +#else + /* get lstat info about the file */ + if (lstat(path_next, &st) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error in stat file/directory '%s'. %s.\n", path_next, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } +#endif + + if (S_ISREG(st.st_mode)) { + if (disk == 0 || filter_path(&state->filterlist, &reason, disk->name, sub_next) == 0) { + search_file(state, path_next, st.st_size, st.st_mtime, STAT_NSEC(&st)); + } else { + msg_verbose("Excluding link '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); + } + } else if (S_ISDIR(st.st_mode)) { + if (disk == 0 || filter_subdir(&state->filterlist, &reason, disk->name, sub_next) == 0) { + pathslash(path_next, sizeof(path_next)); + pathslash(sub_next, sizeof(sub_next)); + search_dir(state, disk, path_next, sub_next); + } else { + msg_verbose("Excluding directory '%s' for rule '%s'\n", path_next, filter_type(reason, out, sizeof(out))); + } + } + } + + if (closedir(d) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error closing directory '%s'. %s.\n", dir, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } +} + +void state_search(struct snapraid_state* state, const char* dir) +{ + char path[PATH_MAX]; + + msg_progress("Importing...\n"); + + /* add the final slash */ + pathimport(path, sizeof(path), dir); + pathslash(path, sizeof(path)); + + search_dir(state, 0, path, ""); +} + +void state_search_array(struct snapraid_state* state) +{ + tommy_node* i; + + /* import from all the disks */ + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* disk = i->data; + + /* skip data disks that are not accessible */ + if (disk->skip_access) + continue; + + msg_progress("Searching disk %s...\n", disk->name); + + search_dir(state, disk, disk->dir, ""); + } +} + diff --git a/cmdline/search.h b/cmdline/search.h new file mode 100644 index 0000000..a0697a9 --- /dev/null +++ b/cmdline/search.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2014 Andrea Mazzoleni + * + * 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 . + */ + +#ifndef __SEARCH_H +#define __SEARCH_H + +#include "elem.h" +#include "state.h" + +/****************************************************************************/ +/* search */ + +/** + * Search file. + * File used to search for moved data. + */ +struct snapraid_search_file { + char* path; /**< Full path of the file. */ + char* name; /**< Pointer of the name inside the path. */ + data_off_t size; + int64_t mtime_sec; + int mtime_nsec; + + /* nodes for data structures */ + tommy_node node; +}; + +/** + * Deallocate a search file. + */ +void search_file_free(struct snapraid_search_file* file); + +/** + * Fetch a file from the size, timestamp and name. + * Return ==0 if the block is found, and copied into buffer. + */ +int state_search_fetch(struct snapraid_state* state, int prevhash, struct snapraid_file* missing_file, block_off_t missing_file_pos, struct snapraid_block* missing_block, unsigned char* buffer); + +/** + * Import files from the specified directory. + */ +void state_search(struct snapraid_state* state, const char* dir); + +/** + * Import files from all the data disks. + */ +void state_search_array(struct snapraid_state* state); + +#endif + diff --git a/cmdline/selftest.c b/cmdline/selftest.c new file mode 100644 index 0000000..b1e355a --- /dev/null +++ b/cmdline/selftest.c @@ -0,0 +1,640 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "snapraid.h" +#include "util.h" +#include "raid/raid.h" +#include "raid/cpu.h" +#include "raid/combo.h" +#include "raid/internal.h" +#include "raid/test.h" +#include "elem.h" +#include "state.h" +#include "support.h" +#include "tommyds/tommyhash.h" +#include "tommyds/tommyarray.h" +#include "tommyds/tommyarrayblkof.h" +#include "tommyds/tommyhashdyn.h" + +struct hash32_test_vector { + const char* data; + int len; + uint32_t digest; +}; + +struct strhash32_test_vector { + char* data; + uint32_t digest; +}; + +struct hash64_test_vector { + const char* data; + int len; + uint64_t digest; +}; + +struct hash_test_vector { + const char* data; + int len; + unsigned char digest[HASH_MAX]; +}; + +/** + * Test vectors for tommy_hash32 + */ +static struct hash32_test_vector TEST_HASH32[] = { + { "", 0, 0x8614384c }, + { "a", 1, 0x12c16c36 }, + { "abc", 3, 0xc58e8af5 }, + { "message digest", 14, 0x006b32f1 }, + { "abcdefghijklmnopqrstuvwxyz", 26, 0x7e6fcfe0 }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62, 0x8604adf8 }, + { "The quick brown fox jumps over the lazy dog", 43, 0xdeba3d3a }, + { "\x00", 1, 0x4a7d1c33 }, + { "\x16\x27", 2, 0x8b50899b }, + { "\xe2\x56\xb4", 3, 0x60406493 }, + { "\xc9\x4d\x9c\xda", 4, 0xa049144a }, + { "\x79\xf1\x29\x69\x5d", 5, 0x4da2c2f1 }, + { "\x00\x7e\xdf\x1e\x31\x1c", 6, 0x59de30cf }, + { "\x2a\x4c\xe1\xff\x9e\x6f\x53", 7, 0x219e149c }, + { "\xba\x02\xab\x18\x30\xc5\x0e\x8a", 8, 0x25067520 }, + { "\xec\x4e\x7a\x72\x1e\x71\x2a\xc9\x33", 9, 0xa1f368d8 }, + { "\xfd\xe2\x9c\x0f\x72\xb7\x08\xea\xd0\x78", 10, 0x805fc63d }, + { "\x65\xc4\x8a\xb8\x80\x86\x9a\x79\x00\xb7\xae", 11, 0x7f75dd0f }, + { "\x77\xe9\xd7\x80\x0e\x3f\x5c\x43\xc8\xc2\x46\x39", 12, 0xb9154382 }, + { 0, 0, 0 } +}; + +/** + * Test vectors for tommy_strhash32 + */ +struct strhash32_test_vector TEST_STRHASH32[] = { + { "", 0x0af1416d }, + { "a", 0x68fa0f3f }, + { "abc", 0xfc68ffc5 }, + { "message digest", 0x08477b63 }, + { "abcdefghijklmnopqrstuvwxyz", 0x5b9c25e5 }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 0x1e530ce7 }, + { "The quick brown fox jumps over the lazy dog", 0xaf93eefe }, + { "\xff", 0xfc88801b }, + { "\x16\x27", 0xcd7216db }, + { "\xe2\x56\xb4", 0x05f98d02 }, + { "\xc9\x4d\x9c\xda", 0xf65206f8 }, + { "\x79\xf1\x29\x69\x5d", 0x72bd6bda }, + { "\xff\x7e\xdf\x1e\x31\x1c", 0x57dfb9b4 }, + { "\x2a\x4c\xe1\xff\x9e\x6f\x53", 0x499ff634 }, + { "\xba\x02\xab\x18\x30\xc5\x0e\x8a", 0xe896b7ce }, + { "\xec\x4e\x7a\x72\x1e\x71\x2a\xc9\x33", 0xfe3939f0 }, + { "\xfd\xe2\x9c\x0f\x72\xb7\x08\xea\xd0\x78", 0x4351d482 }, + { "\x65\xc4\x8a\xb8\x80\x86\x9a\x79\xff\xb7\xae", 0x88e92135 }, + { "\x77\xe9\xd7\x80\x0e\x3f\x5c\x43\xc8\xc2\x46\x39", 0x01109c16 }, + { "\x87\xd8\x61\x61\x4c\x89\x17\x4e\xa1\xa4\xef\x13\xa9", 0xbcb050dc }, + { "\xfe\xa6\x5b\xc2\xda\xe8\x95\xd4\x64\xab\x4c\x39\x58\x29", 0xbe5e1fd5 }, + { "\x94\x49\xc0\x78\xa0\x80\xda\xc7\x71\x4e\x17\x37\xa9\x7c\x40", 0x70d8c97f }, + { "\x53\x7e\x36\xb4\x2e\xc9\xb9\xcc\x18\x3e\x9a\x5f\xfc\xb7\xb0\x61", 0x957440a9 }, + { 0, 0 } +}; + +/** + * Test vectors for tommy_hash64 + */ +static struct hash64_test_vector TEST_HASH64[] = { + { "", 0, 0x8614384cb5165fbfULL }, + { "a", 1, 0x1a2e0298a8e94a3dULL }, + { "abc", 3, 0x7555796b7a7d21ebULL }, + { "message digest", 14, 0x9411a57d04b92fb4ULL }, + { "abcdefghijklmnopqrstuvwxyz", 26, 0x3ca3f8d2b4e69832ULL }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62, 0x6dae542ba0015a4dULL }, + { "The quick brown fox jumps over the lazy dog", 43, 0xe06d8cbb3d2ea1a6ULL }, + { "\x00", 1, 0x201e664fb5f2c021ULL }, + { "\x16\x27", 2, 0xef42fa8032c4b775ULL }, + { "\xe2\x56\xb4", 3, 0x6e6c498a6688466cULL }, + { "\xc9\x4d\x9c\xda", 4, 0x5195005419905423ULL }, + { "\x79\xf1\x29\x69\x5d", 5, 0x221235b48afee7c1ULL }, + { "\x00\x7e\xdf\x1e\x31\x1c", 6, 0x1b1f18b9266f095bULL }, + { "\x2a\x4c\xe1\xff\x9e\x6f\x53", 7, 0x2cbafa8e741d49caULL }, + { "\xba\x02\xab\x18\x30\xc5\x0e\x8a", 8, 0x4677f04c06e0758dULL }, + { "\xec\x4e\x7a\x72\x1e\x71\x2a\xc9\x33", 9, 0x5afe09e8214e2163ULL }, + { "\xfd\xe2\x9c\x0f\x72\xb7\x08\xea\xd0\x78", 10, 0x115b6276d209fab6ULL }, + { "\x65\xc4\x8a\xb8\x80\x86\x9a\x79\x00\xb7\xae", 11, 0xd0636d2f01cf3a3eULL }, + { "\x77\xe9\xd7\x80\x0e\x3f\x5c\x43\xc8\xc2\x46\x39", 12, 0x6d259f5fef74f93eULL }, + { 0, 0, 0 } +}; + +/** + * Test vectors for MurmorHash3_x86_128 + */ +static struct hash_test_vector TEST_MURMUR3[] = { +#include "murmur3test.c" + { 0, 0, { 0 } } +}; + +/** + * Test vectors for SpookyHash_128 + */ +static struct hash_test_vector TEST_SPOOKY2[] = { +#include "spooky2test.c" + { 0, 0, { 0 } } +}; + +#define HASH_TEST_MAX 512 /* tests are never longer than 512 bytes */ + +static void test_hash(void) +{ + unsigned i; + unsigned char* seed_aligned; + void* seed_alloc; + unsigned char* buffer_aligned; + void* buffer_alloc; + uint32_t seed32; + uint64_t seed64; + + seed_aligned = malloc_nofail_align(HASH_MAX, &seed_alloc); + buffer_aligned = malloc_nofail_align(HASH_TEST_MAX, &buffer_alloc); + + seed32 = 0xa766795d; + seed64 = 0x2f022773a766795dULL; + + seed_aligned[0] = 0x5d; + seed_aligned[1] = 0x79; + seed_aligned[2] = 0x66; + seed_aligned[3] = 0xa7; + seed_aligned[4] = 0x73; + seed_aligned[5] = 0x27; + seed_aligned[6] = 0x02; + seed_aligned[7] = 0x2f; + seed_aligned[8] = 0x6a; + seed_aligned[9] = 0xa1; + seed_aligned[10] = 0x9e; + seed_aligned[11] = 0xc1; + seed_aligned[12] = 0x14; + seed_aligned[13] = 0x8c; + seed_aligned[14] = 0x9e; + seed_aligned[15] = 0x43; + + for (i = 0; TEST_HASH32[i].data; ++i) { + uint32_t digest; + memcpy(buffer_aligned, TEST_HASH32[i].data, TEST_HASH32[i].len); + digest = tommy_hash_u32(seed32, buffer_aligned, TEST_HASH32[i].len); + if (digest != TEST_HASH32[i].digest) { + /* LCOV_EXCL_START */ + log_fatal("Failed hash32 test\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + for (i = 0; TEST_STRHASH32[i].data; ++i) { + uint32_t digest; + memcpy(buffer_aligned, TEST_STRHASH32[i].data, strlen(TEST_STRHASH32[i].data) + 1); + digest = tommy_strhash_u32(seed32, buffer_aligned); + if (digest != TEST_STRHASH32[i].digest) { + /* LCOV_EXCL_START */ + log_fatal("Failed strhash32 test\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + for (i = 0; TEST_HASH64[i].data; ++i) { + uint64_t digest; + memcpy(buffer_aligned, TEST_HASH64[i].data, TEST_HASH64[i].len); + digest = tommy_hash_u64(seed64, buffer_aligned, TEST_HASH64[i].len); + if (digest != TEST_HASH64[i].digest) { + /* LCOV_EXCL_START */ + log_fatal("Failed hash64 test\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + + for (i = 0; TEST_MURMUR3[i].data; ++i) { + unsigned char digest[HASH_MAX]; + memcpy(buffer_aligned, TEST_MURMUR3[i].data, TEST_MURMUR3[i].len); + memhash(HASH_MURMUR3, seed_aligned, digest, buffer_aligned, TEST_MURMUR3[i].len); + if (memcmp(digest, TEST_MURMUR3[i].digest, HASH_MAX) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed Murmur3 test\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + for (i = 0; TEST_SPOOKY2[i].data; ++i) { + unsigned char digest[HASH_MAX]; + memcpy(buffer_aligned, TEST_SPOOKY2[i].data, TEST_SPOOKY2[i].len); + memhash(HASH_SPOOKY2, seed_aligned, digest, buffer_aligned, TEST_SPOOKY2[i].len); + if (memcmp(digest, TEST_SPOOKY2[i].digest, HASH_MAX) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed Spooky2 test\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + free(buffer_alloc); + free(seed_alloc); +} + +struct crc_test_vector { + const char* data; + int len; + uint32_t digest; +}; + +/** + * Test vectors for CRC32C (Castagnoli) + */ +static struct crc_test_vector TEST_CRC32C[] = { + { "", 0, 0 }, + { "\x61", 1, 0xc1d04330 }, + { "\x66\x6f\x6f", 3, 0xcfc4ae1d }, + { "\x68\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64", 11, 0xc99465aa }, + { "\x68\x65\x6c\x6c\x6f\x20", 6, 0x7e627e58 }, + { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 32, 0x8a9136aa }, + { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", 32, 0x62a8ab43 }, + { "\x1f\x1e\x1d\x1c\x1b\x1a\x19\x18\x17\x16\x15\x14\x13\x12\x11\x10\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00", 32, 0x113fdb5c }, + { "\x01\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x14\x00\x00\x00\x18\x28\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00", 48, 0xd9963a56 }, + { "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", 32, 0x46dd794e }, + { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28", 40, 0x0e2c157f }, + { "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50", 40, 0xe980ebf6 }, + { "\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78", 40, 0xde74bded }, + { "\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0", 40, 0xd579c862 }, + { "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8", 40, 0xba979ad0 }, + { "\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0", 40, 0x2b29d913 }, + { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0", 240, 0x24c5d375 }, + { 0, 0, 0 } +}; + +static void test_crc32c(void) +{ + unsigned i; + + for (i = 0; TEST_CRC32C[i].data; ++i) { + uint32_t digest; + uint32_t digest_gen; + + digest = crc32c(0, (const unsigned char*)TEST_CRC32C[i].data, TEST_CRC32C[i].len); + digest_gen = crc32c_gen(0, (const unsigned char*)TEST_CRC32C[i].data, TEST_CRC32C[i].len); + + if (digest != TEST_CRC32C[i].digest || digest_gen != TEST_CRC32C[i].digest) { + /* LCOV_EXCL_START */ + log_fatal("Failed CRC32C test\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } +} + +/** + * Size of tommy data structures. + */ +#define TOMMY_SIZE 256 + +static int tommy_test_search(const void* arg, const void* obj) +{ + return arg != obj; +} + +static int tommy_test_compare(const void* void_arg_a, const void* void_arg_b) +{ + if (void_arg_a < void_arg_b) + return -1; + if (void_arg_a > void_arg_b) + return 1; + return 0; +} + +static unsigned tommy_test_foreach_count; + +static void tommy_test_foreach(void* obj) +{ + (void)obj; + + ++tommy_test_foreach_count; +} + +static void tommy_test_foreach_arg(void* void_arg, void* obj) +{ + unsigned* arg = void_arg; + + (void)obj; + + ++*arg; +} + +static void test_tommy(void) +{ + tommy_array array; + tommy_arrayblkof arrayblkof; + tommy_list list; + tommy_hashdyn hashdyn; + tommy_tree tree; + tommy_node node[TOMMY_SIZE + 1]; + unsigned i; + + tommy_array_init(&array); + tommy_arrayblkof_init(&arrayblkof, sizeof(unsigned)); + + for (i = 0; i < TOMMY_SIZE; ++i) { + tommy_array_insert(&array, &node[i]); + tommy_arrayblkof_grow(&arrayblkof, i + 1); + *(unsigned*)tommy_arrayblkof_ref(&arrayblkof, i) = i; + } + + tommy_array_grow(&array, TOMMY_SIZE); + tommy_arrayblkof_grow(&arrayblkof, TOMMY_SIZE); + + if (tommy_array_memory_usage(&array) < TOMMY_SIZE * sizeof(void*)) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + if (tommy_arrayblkof_memory_usage(&arrayblkof) < TOMMY_SIZE * sizeof(unsigned)) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + for (i = 0; i < TOMMY_SIZE; ++i) { + if (tommy_array_get(&array, i) != &node[i]) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + if (*(unsigned*)tommy_arrayblkof_ref(&arrayblkof, i) != i) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + } + + tommy_arrayblkof_done(&arrayblkof); + tommy_array_done(&array); + + tommy_list_init(&list); + + if (!tommy_list_empty(&list)) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + if (tommy_list_tail(&list)) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + if (tommy_list_head(&list)) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + tommy_list_insert_tail(&list, &node[0], &node[0]); + + if (tommy_list_tail(&list) != tommy_list_head(&list)) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + tommy_hashdyn_init(&hashdyn); + + for (i = 0; i < TOMMY_SIZE; ++i) + tommy_hashdyn_insert(&hashdyn, &node[i], &node[i], i % 64); + + if (tommy_hashdyn_count(&hashdyn) != TOMMY_SIZE) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + if (tommy_hashdyn_memory_usage(&hashdyn) < TOMMY_SIZE * sizeof(tommy_node)) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + tommy_test_foreach_count = 0; + tommy_hashdyn_foreach(&hashdyn, tommy_test_foreach); + if (tommy_test_foreach_count != TOMMY_SIZE) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + tommy_test_foreach_count = 0; + tommy_hashdyn_foreach_arg(&hashdyn, tommy_test_foreach_arg, &tommy_test_foreach_count); + if (tommy_test_foreach_count != TOMMY_SIZE) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + for (i = 0; i < TOMMY_SIZE / 2; ++i) + tommy_hashdyn_remove_existing(&hashdyn, &node[i]); + + for (i = 0; i < TOMMY_SIZE / 2; ++i) { + if (tommy_hashdyn_remove(&hashdyn, tommy_test_search, &node[i], i % 64) != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + } + for (i = TOMMY_SIZE / 2; i < TOMMY_SIZE; ++i) { + if (tommy_hashdyn_remove(&hashdyn, tommy_test_search, &node[i], i % 64) == 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + } + + if (tommy_hashdyn_count(&hashdyn) != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + tommy_hashdyn_done(&hashdyn); + + tommy_tree_init(&tree, tommy_test_compare); + + for (i = 0; i < TOMMY_SIZE; ++i) + tommy_tree_insert(&tree, &node[i], (void*)(uintptr_t)(i + 1)); + + /* try to insert a duplicate, count should not change */ + tommy_tree_insert(&tree, &node[TOMMY_SIZE], (void*)(uintptr_t)1); + + if (tommy_tree_count(&tree) != TOMMY_SIZE) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + if (tommy_tree_memory_usage(&tree) < TOMMY_SIZE * sizeof(tommy_node)) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + if (tommy_tree_search(&tree, (void*)1) != (void*)1) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + if (tommy_tree_search(&tree, (void*)-1) != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + if (tommy_tree_search_compare(&tree, tommy_test_compare, (void*)1) != (void*)1) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + if (tommy_tree_search_compare(&tree, tommy_test_compare, (void*)-1) != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + tommy_test_foreach_count = 0; + tommy_tree_foreach(&tree, tommy_test_foreach); + if (tommy_test_foreach_count != TOMMY_SIZE) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + tommy_test_foreach_count = 0; + tommy_tree_foreach_arg(&tree, tommy_test_foreach_arg, &tommy_test_foreach_count); + if (tommy_test_foreach_count != TOMMY_SIZE) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + for (i = 0; i < TOMMY_SIZE / 2; ++i) + tommy_tree_remove_existing(&tree, &node[i]); + + for (i = 0; i < TOMMY_SIZE / 2; ++i) { + if (tommy_tree_remove(&tree, (void*)(uintptr_t)(i + 1)) != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + } + + for (i = TOMMY_SIZE / 2; i < TOMMY_SIZE; ++i) { + if (tommy_tree_remove(&tree, (void*)(uintptr_t)(i + 1)) == 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + } + + if (tommy_tree_count(&tree) != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + return; +bail: + /* LCOV_EXCL_START */ + log_fatal("Failed tommy test\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ +} + +void selftest(void) +{ + log_tag("selftest:\n"); + log_flush(); + + msg_progress("Self test...\n"); + + /* large file check */ + if (sizeof(off_t) < sizeof(uint64_t)) { + /* LCOV_EXCL_START */ + log_fatal("Missing support for large files\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + test_hash(); + test_crc32c(); + test_tommy(); + if (raid_selftest() != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed SELF test\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (raid_test_sort() != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed SORT test\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (raid_test_insert() != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed INSERT test\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (raid_test_combo() != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed COMBO test\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (raid_test_par(RAID_MODE_VANDERMONDE, 32, 256) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed GEN Vandermonde test\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (raid_test_rec(RAID_MODE_VANDERMONDE, 12, 256) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed REC Vandermonde test\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (raid_test_par(RAID_MODE_CAUCHY, 32, 256) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed GEN Cauchy test\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (raid_test_rec(RAID_MODE_CAUCHY, 12, 256) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed REC Cauchy test\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (raid_test_par(RAID_MODE_CAUCHY, 1, 256) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed GEN Cauchy test sigle data disk\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } +} + diff --git a/cmdline/snapraid.c b/cmdline/snapraid.c new file mode 100644 index 0000000..1221872 --- /dev/null +++ b/cmdline/snapraid.c @@ -0,0 +1,1511 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "snapraid.h" +#include "support.h" +#include "elem.h" +#include "import.h" +#include "search.h" +#include "state.h" +#include "io.h" +#include "raid/raid.h" + +/****************************************************************************/ +/* main */ + +void version(void) +{ + msg_status(PACKAGE " v" VERSION " by Andrea Mazzoleni, " PACKAGE_URL "\n"); +} + +void usage(void) +{ + version(); + + printf("Usage: " PACKAGE " status|diff|sync|scrub|list|dup|up|down|smart|pool|check|fix [options]\n"); + printf("\n"); + printf("Commands:\n"); + printf(" status Print the status of the array\n"); + printf(" diff Show the changes that needs to be synchronized\n"); + printf(" sync Synchronize the state of the array\n"); + printf(" scrub Scrub the array\n"); + printf(" list List the array content\n"); + printf(" dup Find duplicate files\n"); + printf(" up Spin-up the array\n"); + printf(" down Spin-down the array\n"); + printf(" smart SMART attributes of the array\n"); + printf(" pool Create or update the virtual view of the array\n"); + printf(" check Check the array\n"); + printf(" fix Fix the array\n"); + printf("\n"); + printf("Options:\n"); + printf(" " SWITCH_GETOPT_LONG("-c, --conf FILE ", "-c") " Configuration file\n"); + printf(" " SWITCH_GETOPT_LONG("-f, --filter PATTERN ", "-f") " Process only files matching the pattern\n"); + printf(" " SWITCH_GETOPT_LONG("-d, --filter-disk NAME", "-f") " Process only files in the specified disk\n"); + printf(" " SWITCH_GETOPT_LONG("-m, --filter-missing ", "-m") " Process only missing/deleted files\n"); + printf(" " SWITCH_GETOPT_LONG("-e, --filter-error ", "-e") " Process only files with errors\n"); + printf(" " SWITCH_GETOPT_LONG("-p, --plan PLAN ", "-p") " Define a scrub plan or percentage\n"); + printf(" " SWITCH_GETOPT_LONG("-o, --older-than DAYS ", "-o") " Process only the older part of the array\n"); + printf(" " SWITCH_GETOPT_LONG("-i, --import DIR ", "-i") " Import deleted files\n"); + printf(" " SWITCH_GETOPT_LONG("-l, --log FILE ", "-l") " Log file. Default none\n"); + printf(" " SWITCH_GETOPT_LONG("-a, --audit-only ", "-a") " Check only file data and not parity\n"); + printf(" " SWITCH_GETOPT_LONG("-h, --pre-hash ", "-h") " Pre-hash all the new data\n"); + printf(" " SWITCH_GETOPT_LONG("-Z, --force-zero ", "-Z") " Force syncing of files that get zero size\n"); + printf(" " SWITCH_GETOPT_LONG("-E, --force-empty ", "-E") " Force syncing of disks that get empty\n"); + printf(" " SWITCH_GETOPT_LONG("-U, --force-uuid ", "-U") " Force commands on disks with uuid changed\n"); + printf(" " SWITCH_GETOPT_LONG("-D, --force-device ", "-D") " Force commands with inaccessible/shared disks\n"); + printf(" " SWITCH_GETOPT_LONG("-N, --force-nocopy ", "-N") " Force commands disabling the copy detection\n"); + printf(" " SWITCH_GETOPT_LONG("-F, --force-full ", "-F") " Force a full parity computation in sync\n"); + printf(" " SWITCH_GETOPT_LONG("-R, --force-realloc ", "-R") " Force a full parity reallocation in sync\n"); + printf(" " SWITCH_GETOPT_LONG("-v, --verbose ", "-v") " Verbose\n"); +} + +void memory(void) +{ + log_tag("memory:used:%" PRIu64 "\n", (uint64_t)malloc_counter_get()); + + /* size of the block */ + log_tag("memory:block:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_block))); + log_tag("memory:extent:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_extent))); + log_tag("memory:file:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_file))); + log_tag("memory:link:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_link))); + log_tag("memory:dir:%" PRIu64 "\n", (uint64_t)(sizeof(struct snapraid_dir))); + + msg_progress("Using %u MiB of memory for the FileSystem.\n", (unsigned)(malloc_counter_get() / MEBI)); +} + +void test(int argc, char* argv[]) +{ + int i; + char buffer[ESC_MAX]; + + /* special testing code for quoting */ + if (argc < 2 || strcmp(argv[1], "test") != 0) + return; + + for (i = 2; i < argc; ++i) { + printf("argv[%d]\n", i); + printf("\t#%s#\n", argv[i]); + printf("\t#%s#\n", esc_shell(argv[i], buffer)); + } + +#ifdef _WIN32 + assert(strcmp(esc_shell(" ", buffer), "\" \"") == 0); + assert(strcmp(esc_shell(" \" ", buffer), "\" \"\\\"\" \"") == 0); + assert(strcmp(esc_shell("&|()<>^", buffer), "^&^|^(^)^<^>^^") == 0); + assert(strcmp(esc_shell("&|()<>^ ", buffer), "\"&|()<>^ \"") == 0); +#else + assert(strcmp(esc_shell(",._+:@%%/-", buffer), ",._+:@%%/-") == 0); + assert(strcmp(esc_shell(" ", buffer), "\\ ") == 0); +#endif + + printf("Everything OK\n"); + + exit(EXIT_SUCCESS); +} + +/****************************************************************************/ +/* log */ + +void log_open(const char* file) +{ + char path[PATH_MAX]; + const char* mode; + char text_T[32]; + char text_D[32]; + time_t t; + struct tm* tm; + + /* leave stdlog at 0 if not specified */ + if (file == 0) + return; + + t = time(0); + tm = localtime(&t); + if (tm) { + strftime(text_T, sizeof(text_T), "%H%M%S", tm); + strftime(text_D, sizeof(text_T), "%Y%m%d", tm); + } else { + /* LCOV_EXCL_START */ + strcpy(text_T, "invalid"); + strcpy(text_D, "invalid"); + /* LCOV_EXCL_STOP */ + } + + /* file mode */ + mode = "wt"; + if (*file == '>') { + ++file; + + if (*file == '>') { + mode = "at"; + ++file; + } + + if (file[0] == '&' && file[1] == '1') { + stdlog = stdout; + return; + } + + if (file[0] == '&' && file[1] == '2') { + stdlog = stderr; + return; + } + } + + /* process the path */ + for (*path = 0; *file != 0; ) { + switch (*file) { + case '%' : + ++file; + switch (*file) { + case '%' : + pathcatc(path, sizeof(path), '%'); + break; + case 'T' : + pathcat(path, sizeof(path), text_T); + break; + case 'D' : + pathcat(path, sizeof(path), text_D); + break; + default : + /* LCOV_EXCL_START */ + log_fatal("Invalid type specifier '%c' in the log file.\n", *file); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + break; + default : + pathcatc(path, sizeof(path), *file); + break; + } + ++file; + } + + stdlog = fopen(path, mode); + if (!stdlog) { + /* LCOV_EXCL_START */ + log_fatal("Error opening the log file '%s'. %s.\n", path, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } +} + +void log_close(const char* file) +{ + if (stdlog != stdout && stdlog != stderr && stdlog != 0) { + if (fclose(stdlog) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error closing the log file '%s'. %s.\n", file, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + stdlog = 0; +} + +/****************************************************************************/ +/* config */ + +void config(char* conf, size_t conf_size, const char* argv0) +{ +#ifdef _WIN32 + char* slash; + + pathimport(conf, conf_size, argv0); + + slash = strrchr(conf, '/'); + if (slash) { + slash[1] = 0; + pathcat(conf, conf_size, PACKAGE ".conf"); + } else { + pathcpy(conf, conf_size, PACKAGE ".conf"); + } +#else + (void)argv0; + +#ifdef SYSCONFDIR + /* if it exists, give precedence at sysconfdir, usually /usr/local/etc */ + if (access(SYSCONFDIR "/" PACKAGE ".conf", F_OK) == 0) + pathcpy(conf, conf_size, SYSCONFDIR "/" PACKAGE ".conf"); + else /* otherwise fallback to plain /etc */ +#endif + pathcpy(conf, conf_size, "/etc/" PACKAGE ".conf"); +#endif +} + +/****************************************************************************/ +/* main */ + +#define OPT_TEST_SKIP_SELF 256 +#define OPT_TEST_KILL_AFTER_SYNC 257 +#define OPT_TEST_EXPECT_UNRECOVERABLE 258 +#define OPT_TEST_EXPECT_RECOVERABLE 259 +#define OPT_TEST_SKIP_SIGN 260 +#define OPT_TEST_SKIP_FALLOCATE 261 +#define OPT_TEST_SKIP_DEVICE 262 +#define OPT_TEST_FORCE_MURMUR3 264 +#define OPT_TEST_FORCE_SPOOKY2 265 +#define OPT_TEST_SKIP_LOCK 266 +#define OPT_TEST_FORCE_ORDER_PHYSICAL 267 +#define OPT_TEST_FORCE_ORDER_INODE 268 +#define OPT_TEST_FORCE_ORDER_ALPHA 269 +#define OPT_TEST_FORCE_ORDER_DIR 270 +#define OPT_TEST_FORCE_SCRUB_AT 271 +#define OPT_TEST_FORCE_SCRUB_EVEN 272 +#define OPT_TEST_FORCE_CONTENT_WRITE 273 +#define OPT_TEST_SKIP_CONTENT_CHECK 275 +#define OPT_TEST_SKIP_PARITY_ACCESS 276 +#define OPT_TEST_EXPECT_FAILURE 277 +#define OPT_TEST_RUN 278 +#define OPT_TEST_FORCE_SCAN_WINFIND 279 +#define OPT_TEST_IMPORT_CONTENT 280 +#define OPT_TEST_FORCE_PROGRESS 281 +#define OPT_TEST_SKIP_DISK_ACCESS 282 +#define OPT_TEST_FORCE_AUTOSAVE_AT 283 +#define OPT_TEST_FAKE_DEVICE 284 +#define OPT_TEST_EXPECT_NEED_SYNC 285 +#define OPT_NO_WARNINGS 286 +#define OPT_TEST_FAKE_UUID 287 +#define OPT_TEST_MATCH_FIRST_UUID 288 +#define OPT_TEST_FORCE_PARITY_UPDATE 289 +#define OPT_TEST_IO_CACHE 290 +#define OPT_TEST_IO_STATS 291 +#define OPT_TEST_COND_SIGNAL_OUTSIDE 292 +#define OPT_TEST_IO_ADVISE_NONE 293 +#define OPT_TEST_IO_ADVISE_SEQUENTIAL 294 +#define OPT_TEST_IO_ADVISE_FLUSH 295 +#define OPT_TEST_IO_ADVISE_FLUSH_WINDOW 296 +#define OPT_TEST_IO_ADVISE_DISCARD 297 +#define OPT_TEST_IO_ADVISE_DISCARD_WINDOW 298 +#define OPT_TEST_IO_ADVISE_DIRECT 299 +#define OPT_TEST_PARITY_LIMIT 301 +#define OPT_TEST_SKIP_CONTENT_WRITE 302 +#define OPT_TEST_SKIP_SPACE_HOLDER 303 +#define OPT_TEST_FORMAT 304 + +#if HAVE_GETOPT_LONG +struct option long_options[] = { + { "conf", 1, 0, 'c' }, + { "filter", 1, 0, 'f' }, + { "filter-disk", 1, 0, 'd' }, + { "filter-missing", 0, 0, 'm' }, + { "filter-error", 0, 0, 'e' }, + { "percentage", 1, 0, 'p' }, /* legacy name for --plan */ + { "plan", 1, 0, 'p' }, + { "older-than", 1, 0, 'o' }, + { "start", 1, 0, 'S' }, + { "count", 1, 0, 'B' }, + { "error-limit", 1, 0, 'L' }, + { "import", 1, 0, 'i' }, + { "log", 1, 0, 'l' }, + { "force-zero", 0, 0, 'Z' }, + { "force-empty", 0, 0, 'E' }, + { "force-uuid", 0, 0, 'U' }, + { "force-device", 0, 0, 'D' }, + { "force-nocopy", 0, 0, 'N' }, + { "force-full", 0, 0, 'F' }, + { "force-realloc", 0, 0, 'R' }, + { "audit-only", 0, 0, 'a' }, + { "pre-hash", 0, 0, 'h' }, + { "speed-test", 0, 0, 'T' }, /* undocumented speed test command */ + { "gen-conf", 1, 0, 'C' }, + { "verbose", 0, 0, 'v' }, + { "quiet", 0, 0, 'q' }, /* undocumented quiet option */ + { "gui", 0, 0, 'G' }, /* undocumented GUI interface option */ + { "help", 0, 0, 'H' }, + { "version", 0, 0, 'V' }, + + /* The following are test specific options, DO NOT USE! */ + + /* After syncing, do not write the new content file */ + { "test-kill-after-sync", 0, 0, OPT_TEST_KILL_AFTER_SYNC }, + + /* Exit with failure if after check/fix there ARE NOT unrecoverable errors. */ + { "test-expect-unrecoverable", 0, 0, OPT_TEST_EXPECT_UNRECOVERABLE }, + + /* Exit with failure if after check/fix there ARE NOT recoverable errors. */ + { "test-expect-recoverable", 0, 0, OPT_TEST_EXPECT_RECOVERABLE }, + + /* Skip the initial self test */ + { "test-skip-self", 0, 0, OPT_TEST_SKIP_SELF }, + + /* Skip the initial sign check when reading the content file */ + { "test-skip-sign", 0, 0, OPT_TEST_SKIP_SIGN }, + + /* Skip the fallocate() when growing the parity files */ + { "test-skip-fallocate", 0, 0, OPT_TEST_SKIP_FALLOCATE }, + + /* Skip the device check */ + { "test-skip-device", 0, 0, OPT_TEST_SKIP_DEVICE }, + + /* Force Murmur3 hash */ + { "test-force-murmur3", 0, 0, OPT_TEST_FORCE_MURMUR3 }, + + /* Force Spooky2 hash */ + { "test-force-spooky2", 0, 0, OPT_TEST_FORCE_SPOOKY2 }, + + /* Skip the use of lock file */ + { "test-skip-lock", 0, 0, OPT_TEST_SKIP_LOCK }, + + /* Force a sort order for files */ + { "test-force-order-physical", 0, 0, OPT_TEST_FORCE_ORDER_PHYSICAL }, + { "test-force-order-inode", 0, 0, OPT_TEST_FORCE_ORDER_INODE }, + { "test-force-order-alpha", 0, 0, OPT_TEST_FORCE_ORDER_ALPHA }, + { "test-force-order-dir", 0, 0, OPT_TEST_FORCE_ORDER_DIR }, + + /* Force scrub of the specified number of blocks */ + { "test-force-scrub-at", 1, 0, OPT_TEST_FORCE_SCRUB_AT }, + + /* Force scrub of all the even blocks. This is really for testing, don't try it */ + { "test-force-scrub-even", 0, 0, OPT_TEST_FORCE_SCRUB_EVEN }, + + /* Force write of the content file even if no modification is done */ + { "test-force-content-write", 0, 0, OPT_TEST_FORCE_CONTENT_WRITE }, + + /* Relax the checks done at the content file */ + { "test-skip-content-check", 0, 0, OPT_TEST_SKIP_CONTENT_CHECK }, + + /* Skip the parity access */ + { "test-skip-parity-access", 0, 0, OPT_TEST_SKIP_PARITY_ACCESS }, + + /* Exit generic failure */ + { "test-expect-failure", 0, 0, OPT_TEST_EXPECT_FAILURE }, + + /* Exit generic need sync */ + { "test-expect-need-sync", 0, 0, OPT_TEST_EXPECT_NEED_SYNC }, + + /* Run some command after loading the state and before the command */ + { "test-run", 1, 0, OPT_TEST_RUN }, + + /* Use the FindFirst/Next approach in Windows to list files */ + { "test-force-scan-winfind", 0, 0, OPT_TEST_FORCE_SCAN_WINFIND }, + + /* Alternative import working by data */ + { "test-import-content", 1, 0, OPT_TEST_IMPORT_CONTENT }, + + /* Force immediate progress state update */ + { "test-force-progress", 0, 0, OPT_TEST_FORCE_PROGRESS }, + + /* Skip the disk access */ + { "test-skip-disk-access", 0, 0, OPT_TEST_SKIP_DISK_ACCESS }, + + /* Force autosave at the specified block */ + { "test-force-autosave-at", 1, 0, OPT_TEST_FORCE_AUTOSAVE_AT }, + + /* Fake device data */ + { "test-fake-device", 0, 0, OPT_TEST_FAKE_DEVICE }, + + /* Disable annoying warnings */ + { "no-warnings", 0, 0, OPT_NO_WARNINGS }, + + /* Fake UUID */ + { "test-fake-uuid", 0, 0, OPT_TEST_FAKE_UUID }, + + /* Match first UUID */ + { "test-match-first-uuid", 0, 0, OPT_TEST_MATCH_FIRST_UUID }, + + /* Force parity update even if all the data hash is already matching */ + { "test-force-parity-update", 0, 0, OPT_TEST_FORCE_PARITY_UPDATE }, + + /* Number of IO buffers */ + { "test-io-cache", 1, 0, OPT_TEST_IO_CACHE }, + + /* Print IO stats */ + { "test-io-stats", 0, 0, OPT_TEST_IO_STATS }, + + /* Signal condition variable outside the mutex */ + { "test-cond-signal-outside", 0, 0, OPT_TEST_COND_SIGNAL_OUTSIDE }, + + /* Set the io advise to none */ + { "test-io-advise-none", 0, 0, OPT_TEST_IO_ADVISE_NONE }, + + /* Set the io advise to sequential */ + { "test-io-advise-sequential", 0, 0, OPT_TEST_IO_ADVISE_SEQUENTIAL }, + + /* Set the io advise to flush */ + { "test-io-advise-flush", 0, 0, OPT_TEST_IO_ADVISE_FLUSH }, + + /* Set the io advise to flush window */ + { "test-io-advise-flush-window", 0, 0, OPT_TEST_IO_ADVISE_FLUSH_WINDOW }, + + /* Set the io advise to discard */ + { "test-io-advise-discard", 0, 0, OPT_TEST_IO_ADVISE_DISCARD }, + + /* Set the io advise to discard window */ + { "test-io-advise-discard-window", 0, 0, OPT_TEST_IO_ADVISE_DISCARD_WINDOW }, + + /* Set the io advise to direct */ + { "test-io-advise-direct", 0, 0, OPT_TEST_IO_ADVISE_DIRECT }, + + /* Set an artificial parity limit */ + { "test-parity-limit", 1, 0, OPT_TEST_PARITY_LIMIT }, + + /* Skip content write */ + { "test-skip-content-write", 0, 0, OPT_TEST_SKIP_CONTENT_WRITE }, + + /* Skip space holder file in parity disks */ + { "test-skip-space-holder", 0, 0, OPT_TEST_SKIP_SPACE_HOLDER }, + + /* Set the output format */ + { "test-fmt", 1, 0, OPT_TEST_FORMAT }, + + { 0, 0, 0, 0 } +}; +#endif + +#define OPTIONS "c:f:d:mep:o:S:B:L:i:l:ZEUDNFRahTC:vqHVG" + +volatile int global_interrupt = 0; + +/* LCOV_EXCL_START */ +void signal_handler(int signum) +{ + (void)signum; + + /* report the request of interruption */ + global_interrupt = 1; +} +/* LCOV_EXCL_STOP */ + +void signal_init(void) +{ +#if HAVE_SIGACTION + struct sigaction sa; + + sa.sa_handler = signal_handler; + sigemptyset(&sa.sa_mask); + + /* use the SA_RESTART to automatically restart interrupted system calls */ + sa.sa_flags = SA_RESTART; + + sigaction(SIGHUP, &sa, 0); + sigaction(SIGTERM, &sa, 0); + sigaction(SIGINT, &sa, 0); + sigaction(SIGQUIT, &sa, 0); +#else + signal(SIGINT, signal_handler); +#endif +} + +#define OPERATION_DIFF 0 +#define OPERATION_SYNC 1 +#define OPERATION_CHECK 2 +#define OPERATION_FIX 3 +#define OPERATION_DRY 4 +#define OPERATION_DUP 5 +#define OPERATION_LIST 6 +#define OPERATION_POOL 7 +#define OPERATION_REHASH 8 +#define OPERATION_SCRUB 9 +#define OPERATION_STATUS 10 +#define OPERATION_REWRITE 11 +#define OPERATION_READ 12 +#define OPERATION_TOUCH 13 +#define OPERATION_SPINUP 14 +#define OPERATION_SPINDOWN 15 +#define OPERATION_DEVICES 16 +#define OPERATION_SMART 17 + +int main(int argc, char* argv[]) +{ + int c; + struct snapraid_option opt; + char conf[PATH_MAX]; + struct snapraid_state state; + int operation; + block_off_t blockstart; + block_off_t blockcount; + int ret; + tommy_list filterlist_file; + tommy_list filterlist_disk; + int filter_missing; + int filter_error; + int plan; + int olderthan; + char* e; + const char* command; + const char* import_timestamp; + const char* import_content; + const char* log_file; + int lock; + const char* gen_conf; + const char* run; + int speedtest; + int period; + time_t t; + struct tm* tm; + int i; + + test(argc, argv); + + lock_init(); + + /* defaults */ + config(conf, sizeof(conf), argv[0]); + memset(&opt, 0, sizeof(opt)); + opt.io_error_limit = 100; + blockstart = 0; + blockcount = 0; + tommy_list_init(&filterlist_file); + tommy_list_init(&filterlist_disk); + period = 1000; + filter_missing = 0; + filter_error = 0; + plan = SCRUB_AUTO; + olderthan = SCRUB_AUTO; + import_timestamp = 0; + import_content = 0; + log_file = 0; + lock = 0; + gen_conf = 0; + speedtest = 0; + run = 0; + + opterr = 0; + while ((c = +#if HAVE_GETOPT_LONG + getopt_long(argc, argv, OPTIONS, long_options, 0)) +#else + getopt(argc, argv, OPTIONS)) +#endif + != EOF) { + switch (c) { + case 'c' : + pathimport(conf, sizeof(conf), optarg); + break; + case 'f' : { + struct snapraid_filter* filter = filter_alloc_file(1, optarg); + if (!filter) { + /* LCOV_EXCL_START */ + log_fatal("Invalid filter specification '%s'\n", optarg); + log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + tommy_list_insert_tail(&filterlist_file, &filter->node, filter); + } break; + case 'd' : { + struct snapraid_filter* filter = filter_alloc_disk(1, optarg); + if (!filter) { + /* LCOV_EXCL_START */ + log_fatal("Invalid filter specification '%s'\n", optarg); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + tommy_list_insert_tail(&filterlist_disk, &filter->node, filter); + } break; + case 'm' : + filter_missing = 1; + opt.expected_missing = 1; + break; + case 'e' : + /* when processing only error, we filter both files and blocks */ + /* and we apply fixes only to synced ones */ + filter_error = 1; + opt.badonly = 1; + opt.syncedonly = 1; + break; + case 'p' : + if (strcmp(optarg, "bad") == 0) { + plan = SCRUB_BAD; + } else if (strcmp(optarg, "new") == 0) { + plan = SCRUB_NEW; + } else if (strcmp(optarg, "full") == 0) { + plan = SCRUB_FULL; + } else { + plan = strtoul(optarg, &e, 10); + if (!e || *e || plan > 100) { + /* LCOV_EXCL_START */ + log_fatal("Invalid plan/percentage '%s'\n", optarg); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + break; + case 'o' : + olderthan = strtoul(optarg, &e, 10); + if (!e || *e || olderthan > 1000) { + /* LCOV_EXCL_START */ + log_fatal("Invalid number of days '%s'\n", optarg); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + break; + case 'S' : + blockstart = strtoul(optarg, &e, 0); + if (!e || *e) { + /* LCOV_EXCL_START */ + log_fatal("Invalid start position '%s'\n", optarg); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + break; + case 'B' : + blockcount = strtoul(optarg, &e, 0); + if (!e || *e) { + /* LCOV_EXCL_START */ + log_fatal("Invalid count number '%s'\n", optarg); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + break; + case 'L' : + opt.io_error_limit = strtoul(optarg, &e, 0); + if (!e || *e) { + /* LCOV_EXCL_START */ + log_fatal("Invalid error limit number '%s'\n", optarg); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + break; + case 'i' : + if (import_timestamp) { + /* LCOV_EXCL_START */ + log_fatal("Import directory '%s' already specified as '%s'\n", optarg, import_timestamp); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + import_timestamp = optarg; + break; + case OPT_TEST_IMPORT_CONTENT : + if (import_content) { + /* LCOV_EXCL_START */ + log_fatal("Import directory '%s' already specified as '%s'\n", optarg, import_content); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + import_content = optarg; + break; + case 'l' : + if (log_file) { + /* LCOV_EXCL_START */ + log_fatal("Log file '%s' already specified as '%s'\n", optarg, log_file); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + log_file = optarg; + break; + case 'Z' : + opt.force_zero = 1; + break; + case 'E' : + opt.force_empty = 1; + break; + case 'U' : + opt.force_uuid = 1; + break; + case 'D' : + opt.force_device = 1; + break; + case 'N' : + opt.force_nocopy = 1; + break; + case 'F' : + opt.force_full = 1; + break; + case 'R' : + opt.force_realloc = 1; + break; + case 'a' : + opt.auditonly = 1; + break; + case 'h' : + opt.prehash = 1; + break; + case 'v' : + ++msg_level; + break; + case 'q' : + --msg_level; + break; + case 'G' : + opt.gui = 1; + break; + case 'H' : + usage(); + exit(EXIT_SUCCESS); + case 'V' : + version(); + exit(EXIT_SUCCESS); + case 'T' : + speedtest = 1; + break; + case 'C' : + gen_conf = optarg; + break; + case OPT_TEST_KILL_AFTER_SYNC : + opt.kill_after_sync = 1; + break; + case OPT_TEST_EXPECT_UNRECOVERABLE : + opt.expect_unrecoverable = 1; + break; + case OPT_TEST_EXPECT_RECOVERABLE : + opt.expect_recoverable = 1; + break; + case OPT_TEST_SKIP_SELF : + opt.skip_self = 1; + break; + case OPT_TEST_SKIP_SIGN : + opt.skip_sign = 1; + break; + case OPT_TEST_SKIP_FALLOCATE : + opt.skip_fallocate = 1; + break; + case OPT_TEST_SKIP_DEVICE : + opt.skip_device = 1; + period = 50; /* reduce period of the speed test */ + break; + case OPT_TEST_SKIP_CONTENT_CHECK : + opt.skip_content_check = 1; + break; + case OPT_TEST_SKIP_PARITY_ACCESS : + opt.skip_parity_access = 1; + break; + case OPT_TEST_SKIP_DISK_ACCESS : + opt.skip_disk_access = 1; + break; + case OPT_TEST_FORCE_MURMUR3 : + opt.force_murmur3 = 1; + break; + case OPT_TEST_FORCE_SPOOKY2 : + opt.force_spooky2 = 1; + break; + case OPT_TEST_SKIP_LOCK : + opt.skip_lock = 1; + break; + case OPT_TEST_FORCE_ORDER_PHYSICAL : + opt.force_order = SORT_PHYSICAL; + break; + case OPT_TEST_FORCE_ORDER_INODE : + opt.force_order = SORT_INODE; + break; + case OPT_TEST_FORCE_ORDER_ALPHA : + opt.force_order = SORT_ALPHA; + break; + case OPT_TEST_FORCE_ORDER_DIR : + opt.force_order = SORT_DIR; + break; + case OPT_TEST_FORCE_SCRUB_AT : + opt.force_scrub_at = atoi(optarg); + break; + case OPT_TEST_FORCE_SCRUB_EVEN : + opt.force_scrub_even = 1; + break; + case OPT_TEST_FORCE_CONTENT_WRITE : + opt.force_content_write = 1; + break; + case OPT_TEST_EXPECT_FAILURE : + /* invert the exit codes */ + exit_success = 1; + exit_failure = 0; + break; + case OPT_TEST_EXPECT_NEED_SYNC : + /* invert the exit codes */ + exit_success = 1; + exit_sync_needed = 0; + break; + case OPT_TEST_RUN : + run = optarg; + break; + case OPT_TEST_FORCE_SCAN_WINFIND : + opt.force_scan_winfind = 1; + break; + case OPT_TEST_FORCE_PROGRESS : + opt.force_progress = 1; + break; + case OPT_TEST_FORCE_AUTOSAVE_AT : + opt.force_autosave_at = atoi(optarg); + break; + case OPT_TEST_FAKE_DEVICE : + opt.fake_device = 1; + break; + case OPT_NO_WARNINGS : + opt.no_warnings = 1; + break; + case OPT_TEST_FAKE_UUID : + opt.fake_uuid = 2; + break; + case OPT_TEST_MATCH_FIRST_UUID : + opt.match_first_uuid = 1; + break; + case OPT_TEST_FORCE_PARITY_UPDATE : + opt.force_parity_update = 1; + break; + case OPT_TEST_IO_CACHE : + opt.io_cache = atoi(optarg); + if (opt.io_cache != 1 && (opt.io_cache < IO_MIN || opt.io_cache > IO_MAX)) { + /* LCOV_EXCL_START */ + log_fatal("The IO cache should be between %u and %u.\n", IO_MIN, IO_MAX); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + break; + case OPT_TEST_IO_STATS : + opt.force_stats = 1; + break; + case OPT_TEST_COND_SIGNAL_OUTSIDE : +#if HAVE_PTHREAD + thread_cond_signal_outside = 1; +#endif + break; + case OPT_TEST_IO_ADVISE_NONE : + opt.file_mode = ADVISE_NONE; + break; + case OPT_TEST_IO_ADVISE_SEQUENTIAL : + opt.file_mode = ADVISE_SEQUENTIAL; + break; + case OPT_TEST_IO_ADVISE_FLUSH : + opt.file_mode = ADVISE_FLUSH; + break; + case OPT_TEST_IO_ADVISE_FLUSH_WINDOW : + opt.file_mode = ADVISE_FLUSH_WINDOW; + break; + case OPT_TEST_IO_ADVISE_DISCARD : + opt.file_mode = ADVISE_DISCARD; + break; + case OPT_TEST_IO_ADVISE_DISCARD_WINDOW : + opt.file_mode = ADVISE_DISCARD_WINDOW; + break; + case OPT_TEST_IO_ADVISE_DIRECT : + opt.file_mode = ADVISE_DIRECT; + break; + case OPT_TEST_PARITY_LIMIT : + opt.parity_limit_size = atoll(optarg); + break; + case OPT_TEST_SKIP_CONTENT_WRITE : + opt.skip_content_write = 1; + break; + case OPT_TEST_SKIP_SPACE_HOLDER : + opt.skip_space_holder = 1; + break; + case OPT_TEST_FORMAT : + if (strcmp(optarg, "file") == 0) + FMT_MODE = FMT_FILE; + else if (strcmp(optarg, "disk") == 0) + FMT_MODE = FMT_DISK; + else if (strcmp(optarg, "path") == 0) + FMT_MODE = FMT_PATH; + else { + /* LCOV_EXCL_START */ + log_fatal("Unknown format '%s'\n", optarg); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + break; + default : + /* LCOV_EXCL_START */ + log_fatal("Unknown option '%c'\n", (char)c); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + os_init(opt.force_scan_winfind); + raid_init(); + crc32c_init(); + + if (speedtest != 0) { + speed(period); + os_done(); + exit(EXIT_SUCCESS); + } + + if (gen_conf != 0) { + generate_configuration(gen_conf); + os_done(); + exit(EXIT_SUCCESS); + } + + if (optind + 1 != argc) { + /* LCOV_EXCL_START */ + usage(); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + command = argv[optind]; + if (strcmp(command, "diff") == 0) { + operation = OPERATION_DIFF; + } else if (strcmp(argv[optind], "sync") == 0) { + operation = OPERATION_SYNC; + } else if (strcmp(argv[optind], "check") == 0) { + operation = OPERATION_CHECK; + } else if (strcmp(argv[optind], "fix") == 0) { + operation = OPERATION_FIX; + } else if (strcmp(argv[optind], "test-dry") == 0) { + operation = OPERATION_DRY; + } else if (strcmp(argv[optind], "dup") == 0) { + operation = OPERATION_DUP; + } else if (strcmp(argv[optind], "list") == 0) { + operation = OPERATION_LIST; + } else if (strcmp(argv[optind], "pool") == 0) { + operation = OPERATION_POOL; + } else if (strcmp(argv[optind], "rehash") == 0) { + operation = OPERATION_REHASH; + } else if (strcmp(argv[optind], "scrub") == 0) { + operation = OPERATION_SCRUB; + } else if (strcmp(argv[optind], "status") == 0) { + operation = OPERATION_STATUS; + } else if (strcmp(argv[optind], "test-rewrite") == 0) { + operation = OPERATION_REWRITE; + } else if (strcmp(argv[optind], "test-read") == 0) { + operation = OPERATION_READ; + } else if (strcmp(argv[optind], "touch") == 0) { + operation = OPERATION_TOUCH; + } else if (strcmp(argv[optind], "up") == 0) { + operation = OPERATION_SPINUP; + } else if (strcmp(argv[optind], "down") == 0) { + operation = OPERATION_SPINDOWN; + } else if (strcmp(argv[optind], "devices") == 0) { + operation = OPERATION_DEVICES; + } else if (strcmp(argv[optind], "smart") == 0) { + operation = OPERATION_SMART; + } else { + /* LCOV_EXCL_START */ + log_fatal("Unknown command '%s'\n", argv[optind]); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* check options compatibility */ + switch (operation) { + case OPERATION_CHECK : + break; + default : + if (opt.auditonly) { + /* LCOV_EXCL_START */ + log_fatal("You cannot use -a, --audit-only with the '%s' command\n", command); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + switch (operation) { + case OPERATION_FIX : + case OPERATION_CHECK : + break; + default : + if (opt.force_device) { + /* LCOV_EXCL_START */ + log_fatal("You cannot use -D, --force-device with the '%s' command\n", command); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + switch (operation) { + case OPERATION_SYNC : + case OPERATION_CHECK : + case OPERATION_FIX : + break; + default : + if (opt.force_nocopy) { + /* LCOV_EXCL_START */ + log_fatal("You cannot use -N, --force-nocopy with the '%s' command\n", command); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + switch (operation) { + case OPERATION_SYNC : + break; + default : + if (opt.prehash) { + /* LCOV_EXCL_START */ + log_fatal("You cannot use -h, --pre-hash with the '%s' command\n", command); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (opt.force_full) { + /* LCOV_EXCL_START */ + log_fatal("You cannot use -F, --force-full with the '%s' command\n", command); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (opt.force_realloc) { + /* LCOV_EXCL_START */ + log_fatal("You cannot use -R, --force-realloc with the '%s' command\n", command); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + if (opt.force_full && opt.force_nocopy) { + /* LCOV_EXCL_START */ + log_fatal("You cannot use the -F, --force-full and -N, --force-nocopy options at the same time\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (opt.force_realloc && opt.force_nocopy) { + /* LCOV_EXCL_START */ + log_fatal("You cannot use the -R, --force-realloc and -N, --force-nocopy options at the same time\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (opt.force_realloc && opt.force_full) { + /* LCOV_EXCL_START */ + log_fatal("You cannot use the -R, --force-realloc and -F, --force-full options at the same time\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (opt.prehash && opt.force_nocopy) { + /* LCOV_EXCL_START */ + log_fatal("You cannot use the -h, --pre-hash and -N, --force-nocopy options at the same time\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + switch (operation) { + case OPERATION_CHECK : + case OPERATION_FIX : + case OPERATION_DRY : + break; + default : + if (!tommy_list_empty(&filterlist_disk)) { + /* LCOV_EXCL_START */ + log_fatal("You cannot use -d, --filter-disk with the '%s' command\n", command); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + /* follow */ + case OPERATION_SPINUP : + case OPERATION_SPINDOWN : + if (!tommy_list_empty(&filterlist_file)) { + /* LCOV_EXCL_START */ + log_fatal("You cannot use -f, --filter with the '%s' command\n", command); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (filter_missing != 0) { + /* LCOV_EXCL_START */ + log_fatal("You cannot use -m, --filter-missing with the '%s' command\n", command); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (filter_error != 0) { + /* LCOV_EXCL_START */ + log_fatal("You cannot use -e, --filter-error with the '%s' command\n", command); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + /* errors must be always fixed on all disks */ + /* because we don't keep the information on what disk is the error */ + if (filter_error != 0 && !tommy_list_empty(&filterlist_disk)) { + /* LCOV_EXCL_START */ + log_fatal("You cannot use -e, --filter-error and -d, --filter-disk at the same time\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + switch (operation) { + case OPERATION_CHECK : + case OPERATION_FIX : + break; + default : + if (import_timestamp != 0 || import_content != 0) { + /* LCOV_EXCL_START */ + log_fatal("You cannot import with the '%s' command\n", command); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + switch (operation) { + case OPERATION_LIST : + case OPERATION_DUP : + case OPERATION_STATUS : + case OPERATION_REWRITE : + case OPERATION_READ : + case OPERATION_REHASH : + case OPERATION_SPINUP : /* we want to do it in different threads to avoid blocking */ + /* avoid to check and access data disks if not needed */ + opt.skip_disk_access = 1; + break; + } + + switch (operation) { + case OPERATION_DIFF : + case OPERATION_LIST : + case OPERATION_DUP : + case OPERATION_POOL : + case OPERATION_STATUS : + case OPERATION_REWRITE : + case OPERATION_READ : + case OPERATION_REHASH : + case OPERATION_TOUCH : + case OPERATION_SPINUP : /* we want to do it in different threads to avoid blocking */ + /* avoid to check and access parity disks if not needed */ + opt.skip_parity_access = 1; + break; + } + + switch (operation) { + case OPERATION_FIX : + case OPERATION_CHECK : + /* avoid to stop processing if a content file is not accessible */ + opt.skip_content_access = 1; + break; + } + + switch (operation) { + case OPERATION_DIFF : + case OPERATION_LIST : + case OPERATION_DUP : + case OPERATION_POOL : + case OPERATION_TOUCH : + case OPERATION_SPINUP : + case OPERATION_SPINDOWN : + case OPERATION_DEVICES : + case OPERATION_SMART : + opt.skip_self = 1; + break; + } + + switch (operation) { +#if HAVE_DIRECT_IO + case OPERATION_SYNC : + case OPERATION_SCRUB : + case OPERATION_DRY : + break; +#endif + default: + /* we allow direct IO only on some commands */ + if (opt.file_mode == ADVISE_DIRECT) + opt.file_mode = ADVISE_SEQUENTIAL; + break; + } + + switch (operation) { + case OPERATION_DEVICES : + case OPERATION_SMART : + /* we may need to use these commands during operations */ + opt.skip_lock = 1; + break; + } + + switch (operation) { + case OPERATION_SMART : + /* allow to run without configuration file */ + opt.auto_conf = 1; + break; + } + + /* open the log file */ + log_open(log_file); + + /* print generic info into the log */ + t = time(0); + tm = localtime(&t); + log_tag("version:%s\n", PACKAGE_VERSION); + log_tag("unixtime:%" PRIi64 "\n", (int64_t)t); + if (tm) { + char datetime[64]; + strftime(datetime, sizeof(datetime), "%Y-%m-%d %H:%M:%S", tm); + log_tag("time:%s\n", datetime); + } + log_tag("command:%s\n", command); + for (i = 0; i < argc; ++i) + log_tag("argv:%u:%s\n", i, argv[i]); + log_flush(); + + if (!opt.skip_self) + selftest(); + + state_init(&state); + + /* read the configuration file */ + state_config(&state, conf, command, &opt, &filterlist_disk); + + /* set the raid mode */ + raid_mode(state.raid_mode); + +#if HAVE_LOCKFILE + /* create the lock file */ + if (!opt.skip_lock && state.lockfile[0]) { + lock = lock_lock(state.lockfile); + if (lock == -1) { + /* LCOV_EXCL_START */ + if (errno != EWOULDBLOCK) { + log_fatal("Error creating the lock file '%s'. %s.\n", state.lockfile, strerror(errno)); + } else { + log_fatal("The lock file '%s' is already locked!\n", state.lockfile); + log_fatal("SnapRAID is already in use!\n"); + } + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } +#else + (void)lock; +#endif + + if (operation == OPERATION_DIFF) { + state_read(&state); + + ret = state_diff(&state); + + /* abort if sync needed */ + if (ret > 0) + exit(EXIT_SYNC_NEEDED); + } else if (operation == OPERATION_SYNC) { + + /* in the next state read ensures to clear all the past hashes in case */ + /* we are reading from an incomplete sync */ + /* The indeterminate hash are only for CHG/DELETED blocks for which we don't */ + /* know if the previous interrupted sync was able to update or not the parity. */ + /* The sync process instead needs to trust this information because it's used */ + /* to avoid to recompute the parity if all the input are equals as before. */ + + /* In these cases we don't know if the old state is still the one */ + /* stored inside the parity, because after an aborted sync, the parity */ + /* may be or may be not have been updated with the data that may be now */ + /* deleted. Then we reset the hash to a bogus value. */ + + /* An example for CHG blocks is: */ + /* - One file is added creating a CHG block with ZERO state */ + /* - Sync aborted after updating the parity to the new state, */ + /* but without saving the content file representing this new BLK state. */ + /* - File is now deleted after the aborted sync */ + /* - Sync again, deleting the blocks over the CHG ones */ + /* with the hash of CHG blocks not representing the real parity state */ + + /* An example for DELETED blocks is: */ + /* - One file is deleted creating DELETED blocks */ + /* - Sync aborted after, updating the parity to the new state, */ + /* but without saving the content file representing this new EMPTY state. */ + /* - Another file is added again over the DELETE ones */ + /* with the hash of DELETED blocks not representing the real parity state */ + state.clear_past_hash = 1; + + state_read(&state); + + state_scan(&state); + + /* refresh the size info before the content write */ + state_refresh(&state); + + memory(); + + /* intercept signals while operating */ + signal_init(); + + /* run a test command if required */ + if (run != 0) { + ret = system(run); /* ignore error */ + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error in running command '%s'.\n", run); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + /* waits some time to ensure that any concurrent modification done at the files, */ + /* using the same mtime read by the scan process, will be read by sync. */ + /* Note that any later modification done, potentially not read by sync, will have */ + /* a different mtime, and it will be synchronized at the next sync. */ + /* The worst case is the FAT file-system with a two seconds resolution for mtime. */ + /* If you don't use FAT, the wait is not needed, because most file-systems have now */ + /* at least microseconds resolution, but better to be safe. */ + if (!opt.skip_self) + sleep(2); + + ret = state_sync(&state, blockstart, blockcount); + + /* save the new state if required */ + if (!opt.kill_after_sync) { + if ((state.need_write || state.opt.force_content_write)) + state_write(&state); + } else { + log_fatal("WARNING! Skipped state write for --test-kill-after-sync option.\n"); + } + + /* abort if required */ + if (ret != 0) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } else if (operation == OPERATION_DRY) { + state_read(&state); + + /* filter */ + state_skip(&state); + state_filter(&state, &filterlist_file, &filterlist_disk, filter_missing, filter_error); + + memory(); + + /* intercept signals while operating */ + signal_init(); + + state_dry(&state, blockstart, blockcount); + } else if (operation == OPERATION_REHASH) { + state_read(&state); + + /* intercept signals while operating */ + signal_init(); + + state_rehash(&state); + + /* save the new state if required */ + if (state.need_write) + state_write(&state); + } else if (operation == OPERATION_SCRUB) { + state_read(&state); + + memory(); + + /* intercept signals while operating */ + signal_init(); + + ret = state_scrub(&state, plan, olderthan); + + /* save the new state if required */ + if (state.need_write || state.opt.force_content_write) + state_write(&state); + + /* abort if required */ + if (ret != 0) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } else if (operation == OPERATION_REWRITE) { + state_read(&state); + + /* intercept signals while operating */ + signal_init(); + + state_write(&state); + + memory(); + } else if (operation == OPERATION_READ) { + state_read(&state); + + memory(); + } else if (operation == OPERATION_TOUCH) { + state_read(&state); + + state_touch(&state); + + /* intercept signals while operating */ + signal_init(); + + state_write(&state); + + memory(); + } else if (operation == OPERATION_SPINUP) { + state_device(&state, DEVICE_UP, &filterlist_disk); + } else if (operation == OPERATION_SPINDOWN) { + state_device(&state, DEVICE_DOWN, &filterlist_disk); + } else if (operation == OPERATION_DEVICES) { + state_device(&state, DEVICE_LIST, 0); + } else if (operation == OPERATION_SMART) { + state_device(&state, DEVICE_SMART, 0); + } else if (operation == OPERATION_STATUS) { + state_read(&state); + + memory(); + + state_status(&state); + } else if (operation == OPERATION_DUP) { + state_read(&state); + + state_dup(&state); + } else if (operation == OPERATION_LIST) { + state_read(&state); + + state_list(&state); + } else if (operation == OPERATION_POOL) { + state_read(&state); + + state_pool(&state); + } else { + state_read(&state); + + /* if we are also trying to recover */ + if (!state.opt.auditonly) { + /* import the user specified dirs */ + if (import_timestamp != 0) + state_search(&state, import_timestamp); + if (import_content != 0) + state_import(&state, import_content); + + /* import from all the array */ + if (!state.opt.force_nocopy) + state_search_array(&state); + } + + /* filter */ + state_skip(&state); + state_filter(&state, &filterlist_file, &filterlist_disk, filter_missing, filter_error); + + memory(); + + /* intercept signals while operating */ + signal_init(); + + if (operation == OPERATION_CHECK) { + ret = state_check(&state, 0, blockstart, blockcount); + } else { /* it's fix */ + ret = state_check(&state, 1, blockstart, blockcount); + } + + /* abort if required */ + if (ret != 0) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + /* close log file */ + log_close(log_file); + +#if HAVE_LOCKFILE + if (!opt.skip_lock && state.lockfile[0]) { + if (lock_unlock(lock) == -1) { + /* LCOV_EXCL_START */ + log_fatal("Error closing the lock file '%s'. %s.\n", state.lockfile, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } +#endif + + state_done(&state); + tommy_list_foreach(&filterlist_file, (tommy_foreach_func*)filter_free); + tommy_list_foreach(&filterlist_disk, (tommy_foreach_func*)filter_free); + + os_done(); + lock_done(); + + return EXIT_SUCCESS; +} + diff --git a/cmdline/snapraid.h b/cmdline/snapraid.h new file mode 100644 index 0000000..e12cbcb --- /dev/null +++ b/cmdline/snapraid.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#ifndef __SNAPRAID_H +#define __SNAPRAID_H + +/****************************************************************************/ +/* snapraid */ + +void speed(int period); +void selftest(void); + +#endif + diff --git a/cmdline/speed.c b/cmdline/speed.c new file mode 100644 index 0000000..f3ecdf8 --- /dev/null +++ b/cmdline/speed.c @@ -0,0 +1,948 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "snapraid.h" +#include "util.h" +#include "raid/raid.h" +#include "raid/cpu.h" +#include "raid/internal.h" +#include "raid/memory.h" +#include "state.h" + +/* + * Size of the blocks to test. + */ +#define TEST_SIZE (256 * KIBI) + +/* + * Number of data blocks to test. + */ +#define TEST_COUNT (8) + +/** + * Differential us of two timeval. + */ +static int64_t diffgettimeofday(struct timeval *start, struct timeval *stop) +{ + int64_t d; + + d = 1000000LL * (stop->tv_sec - start->tv_sec); + d += stop->tv_usec - start->tv_usec; + + return d; +} + +/** + * Start time measurement. + */ +#define SPEED_START \ + count = 0; \ + gettimeofday(&start, 0); \ + do { \ + for (i = 0; i < delta; ++i) + +/** + * Stop time measurement. + */ +#define SPEED_STOP \ + count += delta; \ + gettimeofday(&stop, 0); \ + } while (diffgettimeofday(&start, &stop) < period * 1000LL) ; \ + ds = size * (int64_t)count * nd; \ + dt = diffgettimeofday(&start, &stop); + +/** + * Global variable used to propagate side effects. + * + * This is required to avoid optimizing compilers + * to remove code without side effects. + */ +static unsigned side_effect; + +void speed(int period) +{ + struct timeval start; + struct timeval stop; + int64_t ds; + int64_t dt; + int i, j; + unsigned char digest[HASH_MAX]; + unsigned char seed[HASH_MAX]; + int id[RAID_PARITY_MAX]; + int ip[RAID_PARITY_MAX]; + int count; + int delta = period >= 1000 ? 10 : 1; + int size = TEST_SIZE; + int nd = TEST_COUNT; + int nv; + void *v_alloc; + void **v; + + nv = nd + RAID_PARITY_MAX + 1; + + v = malloc_nofail_vector_align(nd, nv, size, &v_alloc); + + /* initialize disks with fixed data */ + for (i = 0; i < nd; ++i) + memset(v[i], i, size); + + /* zero buffer */ + memset(v[nd + RAID_PARITY_MAX], 0, size); + raid_zero(v[nd + RAID_PARITY_MAX]); + + /* hash seed */ + for (i = 0; i < HASH_MAX; ++i) + seed[i] = i; + + /* basic disks and parity mapping */ + for (i = 0; i < RAID_PARITY_MAX; ++i) { + id[i] = i; + ip[i] = i; + } + + printf(PACKAGE " v" VERSION " by Andrea Mazzoleni, " PACKAGE_URL "\n"); + +#ifdef __GNUC__ + printf("Compiler gcc " __VERSION__ "\n"); +#endif + +#ifdef CONFIG_X86 + { + char vendor[CPU_VENDOR_MAX]; + unsigned family; + unsigned model; + + raid_cpu_info(vendor, &family, &model); + + printf("CPU %s, family %u, model %u, flags%s%s%s%s%s%s\n", vendor, family, model, + raid_cpu_has_sse2() ? " sse2" : "", + raid_cpu_has_ssse3() ? " ssse3" : "", + raid_cpu_has_crc32() ? " crc32" : "", + raid_cpu_has_avx2() ? " avx2" : "", + raid_cpu_has_slowmult() ? " slowmult" : "", + raid_cpu_has_slowextendedreg() ? " slowext" : "" + ); + } +#else + printf("CPU is not a x86/x64\n"); +#endif +#if WORDS_BIGENDIAN + printf("Memory is big-endian %d-bit\n", (int)sizeof(void *) * 8); +#else + printf("Memory is little-endian %d-bit\n", (int)sizeof(void *) * 8); +#endif + +#if HAVE_FUTIMENS + printf("Support nanosecond timestamps with futimens()\n"); +#elif HAVE_FUTIMES + printf("Support nanosecond timestamps with futimes()\n"); +#elif HAVE_FUTIMESAT + printf("Support nanosecond timestamps with futimesat()\n"); +#else + printf("Does not support nanosecond timestamps\n"); +#endif + + printf("\n"); + + printf("Speed test using %u data buffers of %u bytes, for a total of %u KiB.\n", nd, size, nd * size / KIBI); + printf("Memory blocks have a displacement of %u bytes to improve cache performance.\n", RAID_MALLOC_DISPLACEMENT); + printf("The reported values are the aggregate bandwidth of all data blocks in MB/s,\n"); + printf("not counting parity blocks.\n"); + printf("\n"); + + printf("Memory write speed using the C memset() function:\n"); + printf("%8s", "memset"); + fflush(stdout); + + SPEED_START { + for (j = 0; j < nd; ++j) + memset(v[j], j, size); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + printf("\n"); + printf("\n"); + + /* crc table */ + printf("CRC used to check the content file integrity:\n"); + + printf("%8s", "table"); + fflush(stdout); + + SPEED_START { + for (j = 0; j < nd; ++j) + side_effect += crc32c_gen(0, v[j], size); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + printf("\n"); + + printf("%8s", "intel"); + fflush(stdout); + +#if HAVE_SSE42 + if (raid_cpu_has_crc32()) { + SPEED_START { + for (j = 0; j < nd; ++j) + side_effect += crc32c_x86(0, v[j], size); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif + printf("\n"); + printf("\n"); + + /* hash table */ + printf("Hash used to check the data blocks integrity:\n"); + + printf("%8s", ""); + printf("%8s", "best"); + printf("%8s", "murmur3"); + printf("%8s", "spooky2"); + printf("\n"); + + printf("%8s", "hash"); +#ifdef CONFIG_X86 + if (sizeof(void *) == 4 && !raid_cpu_has_slowmult()) + printf("%8s", "murmur3"); + else + printf("%8s", "spooky2"); +#else + if (sizeof(void *) == 4) + printf("%8s", "murmur3"); + else + printf("%8s", "spooky2"); +#endif + fflush(stdout); + + SPEED_START { + for (j = 0; j < nd; ++j) + memhash(HASH_MURMUR3, seed, digest, v[j], size); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + + SPEED_START { + for (j = 0; j < nd; ++j) + memhash(HASH_SPOOKY2, seed, digest, v[j], size); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + printf("\n"); + printf("\n"); + + /* RAID table */ + printf("RAID functions used for computing the parity with 'sync':\n"); + printf("%8s", ""); + printf("%8s", "best"); + printf("%8s", "int8"); + printf("%8s", "int32"); + printf("%8s", "int64"); +#ifdef CONFIG_X86 + printf("%8s", "sse2"); +#ifdef CONFIG_X86_64 + printf("%8s", "sse2e"); +#endif + printf("%8s", "ssse3"); +#ifdef CONFIG_X86_64 + printf("%8s", "ssse3e"); +#endif + printf("%8s", "avx2"); +#ifdef CONFIG_X86_64 + printf("%8s", "avx2e"); +#endif +#endif + printf("\n"); + + /* GEN1 */ + printf("%8s", "gen1"); + printf("%8s", raid_gen1_tag()); + fflush(stdout); + + printf("%8s", ""); + + SPEED_START { + raid_gen1_int32(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + + SPEED_START { + raid_gen1_int64(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSE2 + if (raid_cpu_has_sse2()) { + SPEED_START { + raid_gen1_sse2(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + } +#endif + +#ifdef CONFIG_X86_64 + printf("%8s", ""); +#endif + printf("%8s", ""); +#ifdef CONFIG_X86_64 + printf("%8s", ""); +#endif +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + raid_gen1_avx2(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + } +#endif +#endif + printf("\n"); + + /* GEN2 */ + printf("%8s", "gen2"); + printf("%8s", raid_gen2_tag()); + fflush(stdout); + + printf("%8s", ""); + + SPEED_START { + raid_gen2_int32(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + + SPEED_START { + raid_gen2_int64(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSE2 + if (raid_cpu_has_sse2()) { + SPEED_START { + raid_gen2_sse2(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86_64 + SPEED_START { + raid_gen2_sse2ext(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); +#endif + } +#endif + + printf("%8s", ""); +#ifdef CONFIG_X86_64 + printf("%8s", ""); +#endif +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + raid_gen2_avx2(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + } +#endif +#endif + printf("\n"); + + /* GENz */ + printf("%8s", "genz"); + printf("%8s", raid_genz_tag()); + fflush(stdout); + + printf("%8s", ""); + + SPEED_START { + raid_genz_int32(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + + SPEED_START { + raid_genz_int64(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSE2 + if (raid_cpu_has_sse2()) { + SPEED_START { + raid_genz_sse2(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86_64 + SPEED_START { + raid_genz_sse2ext(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); +#endif + } +#endif + + printf("%8s", ""); +#ifdef CONFIG_X86_64 + printf("%8s", ""); +#endif + printf("%8s", ""); + +#ifdef CONFIG_X86_64 +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + raid_genz_avx2ext(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + } +#endif +#endif +#endif + printf("\n"); + + /* GEN3 */ + printf("%8s", "gen3"); + printf("%8s", raid_gen3_tag()); + fflush(stdout); + + SPEED_START { + raid_gen3_int8(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + + printf("%8s", ""); + printf("%8s", ""); + +#ifdef CONFIG_X86 + if (raid_cpu_has_sse2()) { + printf("%8s", ""); + +#ifdef CONFIG_X86_64 + printf("%8s", ""); +#endif + } +#endif + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) { + SPEED_START { + raid_gen3_ssse3(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86_64 + SPEED_START { + raid_gen3_ssse3ext(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); +#endif + } +#endif + + printf("%8s", ""); + +#ifdef CONFIG_X86_64 +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + raid_gen3_avx2ext(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + } +#endif +#endif +#endif + printf("\n"); + + /* GEN4 */ + printf("%8s", "gen4"); + printf("%8s", raid_gen4_tag()); + fflush(stdout); + + SPEED_START { + raid_gen4_int8(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + + printf("%8s", ""); + printf("%8s", ""); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSE2 + if (raid_cpu_has_sse2()) { + printf("%8s", ""); + +#ifdef CONFIG_X86_64 + printf("%8s", ""); +#endif + } +#endif +#endif + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) { + SPEED_START { + raid_gen4_ssse3(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86_64 + SPEED_START { + raid_gen4_ssse3ext(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); +#endif + } +#endif + + printf("%8s", ""); + +#ifdef CONFIG_X86_64 +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + raid_gen4_avx2ext(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + } +#endif +#endif +#endif + printf("\n"); + + /* GEN5 */ + printf("%8s", "gen5"); + printf("%8s", raid_gen5_tag()); + fflush(stdout); + + SPEED_START { + raid_gen5_int8(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + + printf("%8s", ""); + printf("%8s", ""); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSE2 + if (raid_cpu_has_sse2()) { + printf("%8s", ""); + +#ifdef CONFIG_X86_64 + printf("%8s", ""); +#endif + } +#endif +#endif + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) { + SPEED_START { + raid_gen5_ssse3(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86_64 + SPEED_START { + raid_gen5_ssse3ext(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); +#endif + } +#endif + + printf("%8s", ""); + +#ifdef CONFIG_X86_64 +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + raid_gen5_avx2ext(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + } +#endif +#endif +#endif + printf("\n"); + + /* GEN6 */ + printf("%8s", "gen6"); + printf("%8s", raid_gen6_tag()); + fflush(stdout); + + SPEED_START { + raid_gen6_int8(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + + printf("%8s", ""); + printf("%8s", ""); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSE2 + if (raid_cpu_has_sse2()) { + printf("%8s", ""); + +#ifdef CONFIG_X86_64 + printf("%8s", ""); +#endif + } +#endif +#endif + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) { + SPEED_START { + raid_gen6_ssse3(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86_64 + SPEED_START { + raid_gen6_ssse3ext(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); +#endif + } +#endif + + printf("%8s", ""); + +#ifdef CONFIG_X86_64 +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + raid_gen6_avx2ext(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + } +#endif +#endif +#endif + printf("\n"); + printf("\n"); + + /* recover table */ + printf("RAID functions used for recovering with 'fix':\n"); + printf("%8s", ""); + printf("%8s", "best"); + printf("%8s", "int8"); +#ifdef CONFIG_X86 + printf("%8s", "ssse3"); + printf("%8s", "avx2"); +#endif + printf("\n"); + + printf("%8s", "rec1"); + printf("%8s", raid_rec1_tag()); + fflush(stdout); + + SPEED_START { + for (j = 0; j < nd; ++j) + /* +1 to avoid GEN1 optimized case */ + raid_rec1_int8(1, id, ip + 1, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) { + SPEED_START { + for (j = 0; j < nd; ++j) + /* +1 to avoid GEN1 optimized case */ + raid_rec1_ssse3(1, id, ip + 1, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + for (j = 0; j < nd; ++j) + /* +1 to avoid GEN1 optimized case */ + raid_rec1_avx2(1, id, ip + 1, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#endif + printf("\n"); + + printf("%8s", "rec2"); + printf("%8s", raid_rec2_tag()); + fflush(stdout); + + SPEED_START { + for (j = 0; j < nd; ++j) + /* +1 to avoid GEN2 optimized case */ + raid_rec2_int8(2, id, ip + 1, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) { + SPEED_START { + for (j = 0; j < nd; ++j) + /* +1 to avoid GEN2 optimized case */ + raid_rec2_ssse3(2, id, ip + 1, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + for (j = 0; j < nd; ++j) + /* +1 to avoid GEN1 optimized case */ + raid_rec2_avx2(2, id, ip + 1, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#endif + printf("\n"); + + printf("%8s", "rec3"); + printf("%8s", raid_recX_tag()); + fflush(stdout); + + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_int8(3, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) { + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_ssse3(3, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_avx2(3, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#endif + printf("\n"); + + printf("%8s", "rec4"); + printf("%8s", raid_recX_tag()); + fflush(stdout); + + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_int8(4, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) { + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_ssse3(4, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_avx2(4, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#endif + printf("\n"); + + printf("%8s", "rec5"); + printf("%8s", raid_recX_tag()); + fflush(stdout); + + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_int8(5, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) { + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_ssse3(5, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_avx2(5, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#endif + printf("\n"); + + printf("%8s", "rec6"); + printf("%8s", raid_recX_tag()); + fflush(stdout); + + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_int8(6, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) { + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_ssse3(6, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_avx2(6, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#endif + printf("\n"); + printf("\n"); + + printf("If the 'best' expectations are wrong, please report it in the SnapRAID forum\n\n"); + + free(v_alloc); + free(v); +} + diff --git a/cmdline/spooky2.c b/cmdline/spooky2.c new file mode 100644 index 0000000..c2a5c5e --- /dev/null +++ b/cmdline/spooky2.c @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 . + */ + +/* + * Derivative work from SpookyV2.cpp/h + * + * WARNING!!!! Note that this implementation doesn't use the short hash optimization + * resulting in different hashes for any length shorter than 192 bytes + * + * SpookyHash + * http://burtleburtle.net/bob/hash/spooky.html + * + * Exact source used as reference: + * http://burtleburtle.net/bob/c/SpookyV2.h + * http://burtleburtle.net/bob/c/SpookyV2.cpp + */ + +// Spooky Hash +// A 128-bit noncryptographic hash, for checksums and table lookup +// By Bob Jenkins. Public domain. +// Oct 31 2010: published framework, disclaimer ShortHash isn't right +// Nov 7 2010: disabled ShortHash +// Oct 31 2011: replace End, ShortMix, ShortEnd, enable ShortHash again +// April 10 2012: buffer overflow on platforms without unaligned reads +// July 12 2012: was passing out variables in final to in/out in short +// July 30 2012: I reintroduced the buffer overflow +// August 5 2012: SpookyV2: d = should be d += in short hash, and remove extra mix from long hash +// +// Up to 3 bytes/cycle for long messages. Reasonably fast for short messages. +// All 1 or 2 bit deltas achieve avalanche within 1% bias per output bit. +// +// This was developed for and tested on 64-bit x86-compatible processors. +// It assumes the processor is little-endian. There is a macro +// controlling whether unaligned reads are allowed (by default they are). +// This should be an equally good hash on big-endian machines, but it will +// compute different results on them than on little-endian machines. +// +// Google's CityHash has similar specs to SpookyHash, and CityHash is faster +// on new Intel boxes. MD4 and MD5 also have similar specs, but they are orders +// of magnitude slower. CRCs are two or more times slower, but unlike +// SpookyHash, they have nice math for combining the CRCs of pieces to form +// the CRCs of wholes. There are also cryptographic hashes, but those are even +// slower than MD5. +// + +#define Mix(data, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11) \ + s0 += data[0]; s2 ^= s10; s11 ^= s0; s0 = util_rotl64(s0, 11); s11 += s1; \ + s1 += data[1]; s3 ^= s11; s0 ^= s1; s1 = util_rotl64(s1, 32); s0 += s2; \ + s2 += data[2]; s4 ^= s0; s1 ^= s2; s2 = util_rotl64(s2, 43); s1 += s3; \ + s3 += data[3]; s5 ^= s1; s2 ^= s3; s3 = util_rotl64(s3, 31); s2 += s4; \ + s4 += data[4]; s6 ^= s2; s3 ^= s4; s4 = util_rotl64(s4, 17); s3 += s5; \ + s5 += data[5]; s7 ^= s3; s4 ^= s5; s5 = util_rotl64(s5, 28); s4 += s6; \ + s6 += data[6]; s8 ^= s4; s5 ^= s6; s6 = util_rotl64(s6, 39); s5 += s7; \ + s7 += data[7]; s9 ^= s5; s6 ^= s7; s7 = util_rotl64(s7, 57); s6 += s8; \ + s8 += data[8]; s10 ^= s6; s7 ^= s8; s8 = util_rotl64(s8, 55); s7 += s9; \ + s9 += data[9]; s11 ^= s7; s8 ^= s9; s9 = util_rotl64(s9, 54); s8 += s10; \ + s10 += data[10]; s0 ^= s8; s9 ^= s10; s10 = util_rotl64(s10, 22); s9 += s11; \ + s11 += data[11]; s1 ^= s9; s10 ^= s11; s11 = util_rotl64(s11, 46); s10 += s0; + +#define EndPartial(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11) \ + h11 += h1; h2 ^= h11; h1 = util_rotl64(h1, 44); \ + h0 += h2; h3 ^= h0; h2 = util_rotl64(h2, 15); \ + h1 += h3; h4 ^= h1; h3 = util_rotl64(h3, 34); \ + h2 += h4; h5 ^= h2; h4 = util_rotl64(h4, 21); \ + h3 += h5; h6 ^= h3; h5 = util_rotl64(h5, 38); \ + h4 += h6; h7 ^= h4; h6 = util_rotl64(h6, 33); \ + h5 += h7; h8 ^= h5; h7 = util_rotl64(h7, 10); \ + h6 += h8; h9 ^= h6; h8 = util_rotl64(h8, 13); \ + h7 += h9; h10 ^= h7; h9 = util_rotl64(h9, 38); \ + h8 += h10; h11 ^= h8; h10 = util_rotl64(h10, 53); \ + h9 += h11; h0 ^= h9; h11 = util_rotl64(h11, 42); \ + h10 += h0; h1 ^= h10; h0 = util_rotl64(h0, 54); + +#define End(data, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11) \ + h0 += data[0]; h1 += data[1]; h2 += data[2]; h3 += data[3]; \ + h4 += data[4]; h5 += data[5]; h6 += data[6]; h7 += data[7]; \ + h8 += data[8]; h9 += data[9]; h10 += data[10]; h11 += data[11]; \ + EndPartial(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); \ + EndPartial(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); \ + EndPartial(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); + +// number of uint64_t's in internal state +#define sc_numVars 12 + +// size of the internal state +#define sc_blockSize (sc_numVars * 8) + +// +// sc_const: a constant which: +// * is not zero +// * is odd +// * is a not-very-regular mix of 1's and 0's +// * does not need any other special mathematical properties +// +#define sc_const 0xdeadbeefdeadbeefLL + +void SpookyHash128(const void* data, size_t size, const uint8_t* seed, uint8_t* digest) +{ + uint64_t h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11; + uint64_t buf[sc_numVars]; + size_t nblocks; + const uint64_t* blocks; + const uint64_t* end; + size_t size_remainder; +#if WORDS_BIGENDIAN + unsigned i; +#endif + + h9 = util_read64(seed + 0); + h10 = util_read64(seed + 8); + + h0 = h3 = h6 = h9; + h1 = h4 = h7 = h10; + h2 = h5 = h8 = h11 = sc_const; + + nblocks = size / sc_blockSize; + blocks = data; + end = blocks + nblocks * sc_numVars; + + /* body */ + while (blocks < end) { +#if WORDS_BIGENDIAN + for (i = 0; i < sc_numVars; ++i) + buf[i] = util_swap64(blocks[i]); + Mix(buf, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); +#else + Mix(blocks, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); +#endif + blocks += sc_numVars; + } + + /* tail */ + size_remainder = (size - ((const uint8_t*)end - (const uint8_t*)data)); + memcpy(buf, end, size_remainder); + memset(((uint8_t*)buf) + size_remainder, 0, sc_blockSize - size_remainder); + ((uint8_t*)buf)[sc_blockSize - 1] = size_remainder; + + /* finalization */ +#if WORDS_BIGENDIAN + for (i = 0; i < sc_numVars; ++i) + buf[i] = util_swap64(buf[i]); +#endif + End(buf, h0, h1, h2, h3, h4, h5, h6, h7, h8, h9, h10, h11); + + util_write64(digest + 0, h0); + util_write64(digest + 8, h1); +} + diff --git a/cmdline/spooky2test.c b/cmdline/spooky2test.c new file mode 100644 index 0000000..84d6f78 --- /dev/null +++ b/cmdline/spooky2test.c @@ -0,0 +1,264 @@ +{ "", 0, { 0xc7, 0xd7, 0x7b, 0x13, 0xfc, 0xa2, 0x7b, 0x21, 0x00, 0x95, 0xf6, 0xa9, 0x6f, 0x84, 0xaa, 0xc9 } }, +{ "a", 1, { 0x85, 0x34, 0x3d, 0x36, 0xf4, 0x56, 0x79, 0x60, 0xa7, 0x96, 0x5f, 0x16, 0x44, 0x1e, 0x8c, 0xea } }, +{ "abc", 3, { 0xb0, 0x41, 0x6b, 0xce, 0xba, 0xdf, 0x5d, 0xe3, 0x09, 0x38, 0xcb, 0x1f, 0x25, 0xdc, 0x44, 0xa2 } }, +{ "message digest", 14, { 0xdf, 0xe5, 0xcb, 0x3f, 0x51, 0xa8, 0xa2, 0xd4, 0x8d, 0xa0, 0xd5, 0x48, 0x26, 0x1c, 0x17, 0x74 } }, +{ "abcdefghijklmnopqrstuvwxyz", 26, { 0x95, 0xe3, 0x9c, 0x85, 0xb8, 0x70, 0x3d, 0x24, 0x51, 0x1c, 0x3c, 0x85, 0x8c, 0xd7, 0x57, 0x2c } }, +{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62, { 0x7d, 0x0d, 0xb7, 0xae, 0x85, 0xce, 0xa1, 0x13, 0xf8, 0xfc, 0xb4, 0xf4, 0x05, 0xab, 0x68, 0xb0 } }, +{ "The quick brown fox jumps over the lazy dog", 43, { 0xda, 0xfa, 0x43, 0x97, 0xaf, 0x0b, 0xdc, 0x06, 0x1e, 0xc2, 0x77, 0x12, 0xeb, 0x36, 0xd4, 0x4d } }, +{ "\x00", 1, { 0x51, 0xe3, 0xc3, 0x5c, 0x6d, 0x8f, 0xb3, 0xc8, 0x01, 0x19, 0x29, 0xcb, 0x9d, 0x98, 0xa3, 0xa0 } }, +{ "\x16\x27", 2, { 0xbb, 0x96, 0x86, 0x56, 0xcc, 0x62, 0x37, 0xe0, 0xe8, 0xf0, 0x5b, 0x63, 0x3b, 0xd1, 0x6c, 0x42 } }, +{ "\xe2\x56\xb4", 3, { 0xf6, 0xb2, 0x17, 0x1a, 0x27, 0x85, 0x2b, 0x8a, 0x45, 0x4e, 0x26, 0xf1, 0xeb, 0xb9, 0x60, 0x64 } }, +{ "\xc9\x4d\x9c\xda", 4, { 0x94, 0xdb, 0x3e, 0x5b, 0x3a, 0x4c, 0x0e, 0xf9, 0x4a, 0xe6, 0x42, 0xfa, 0xc6, 0xb5, 0xa6, 0x1d } }, +{ "\x79\xf1\x29\x69\x5d", 5, { 0x0c, 0x5e, 0x36, 0x05, 0x04, 0xd5, 0xf2, 0x53, 0x7b, 0x56, 0x03, 0xc7, 0x6f, 0x08, 0x45, 0x07 } }, +{ "\x00\x7e\xdf\x1e\x31\x1c", 6, { 0xd5, 0x65, 0x58, 0x3d, 0xa3, 0x96, 0x8a, 0xa2, 0x6e, 0xe5, 0x8d, 0x84, 0xa5, 0x3f, 0xd7, 0x6c } }, +{ "\x2a\x4c\xe1\xff\x9e\x6f\x53", 7, { 0x19, 0x00, 0x13, 0x2a, 0xd9, 0x50, 0x80, 0x5e, 0xb9, 0x19, 0x36, 0x5a, 0xb6, 0x36, 0x2a, 0x0f } }, +{ "\xba\x02\xab\x18\x30\xc5\x0e\x8a", 8, { 0x13, 0xc7, 0xac, 0xcb, 0x7a, 0x5d, 0xe5, 0x14, 0x4b, 0xf6, 0xee, 0xfd, 0x52, 0x86, 0xb7, 0x5f } }, +{ "\xec\x4e\x7a\x72\x1e\x71\x2a\xc9\x33", 9, { 0xe4, 0x12, 0x97, 0x2c, 0xe2, 0xca, 0x21, 0x67, 0xec, 0xe8, 0x63, 0xf7, 0x20, 0x7d, 0xae, 0xad } }, +{ "\xfd\xe2\x9c\x0f\x72\xb7\x08\xea\xd0\x78", 10, { 0x11, 0x14, 0x7d, 0xd2, 0x79, 0xd5, 0x32, 0x30, 0x43, 0x83, 0x26, 0x60, 0x47, 0xed, 0x63, 0x2b } }, +{ "\x65\xc4\x8a\xb8\x80\x86\x9a\x79\x00\xb7\xae", 11, { 0x59, 0xa5, 0x00, 0x96, 0x3f, 0x01, 0xd8, 0x90, 0x00, 0x46, 0x2f, 0x11, 0xf1, 0xf9, 0xb8, 0x7d } }, +{ "\x77\xe9\xd7\x80\x0e\x3f\x5c\x43\xc8\xc2\x46\x39", 12, { 0x21, 0x3e, 0x1d, 0x1b, 0x44, 0xb7, 0x71, 0xc0, 0xde, 0x2b, 0xb4, 0x6d, 0x82, 0x6d, 0x8c, 0x1e } }, +{ "\x87\xd8\x61\x61\x4c\x89\x17\x4e\xa1\xa4\xef\x13\xa9", 13, { 0xe3, 0xa9, 0x25, 0xc9, 0x53, 0x3c, 0xa2, 0xa5, 0x69, 0x62, 0x31, 0xde, 0x10, 0xbb, 0x54, 0xd3 } }, +{ "\xfe\xa6\x5b\xc2\xda\xe8\x95\xd4\x64\xab\x4c\x39\x58\x29", 14, { 0x91, 0x14, 0xf0, 0x97, 0x98, 0x3b, 0x8e, 0x97, 0x33, 0x33, 0x8e, 0xb9, 0xca, 0x3a, 0x1d, 0x82 } }, +{ "\x94\x49\xc0\x78\xa0\x80\xda\xc7\x71\x4e\x17\x37\xa9\x7c\x40", 15, { 0x06, 0x33, 0x47, 0x61, 0xe7, 0xc9, 0xc1, 0x0e, 0x23, 0x36, 0x86, 0x2b, 0x2d, 0x21, 0x89, 0x57 } }, +{ "\x53\x7e\x36\xb4\x2e\xc9\xb9\xcc\x18\x3e\x9a\x5f\xfc\xb7\xb0\x61", 16, { 0x66, 0x36, 0x7d, 0xee, 0x47, 0x92, 0xa4, 0x4f, 0x62, 0xf8, 0xd9, 0x36, 0x8e, 0xe7, 0x69, 0x53 } }, +{ "\x59\xa9\x9f\xa6\xdb\xb7\x02\xc5\x95\x65\x34\x17\xde\xe5\xbb\xdf\xc5", 17, { 0xd7, 0x7b, 0x00, 0x79, 0xae, 0x0f, 0xc9, 0x16, 0x02, 0x28, 0xab, 0x6a, 0xdf, 0x3e, 0x30, 0x03 } }, +{ "\x0d\x52\x83\x32\x6a\x92\xf9\x9a\x6e\x3c\x3d\x5e\xc4\x25\xfe\xc1\xc4\xbe", 18, { 0x46, 0x32, 0xb2, 0xa0, 0x1b, 0xa8, 0xea, 0xce, 0x66, 0x9f, 0xc1, 0x58, 0xc9, 0x94, 0xba, 0x3b } }, +{ "\x59\x84\x02\x3f\xbc\x20\x01\x70\xed\xa0\x05\x14\x23\x18\x06\xf2\x52\xc5\xc1", 19, { 0x98, 0xfc, 0x24, 0x88, 0x92, 0xbd, 0xad, 0x17, 0xcc, 0x07, 0x11, 0x2b, 0x37, 0x4e, 0xb1, 0x47 } }, +{ "\x81\x84\xc3\xe8\x2f\x63\x65\x79\x4e\xd3\x34\x2c\x9c\xbc\x87\x05\x6d\xe5\xbc\x0a", 20, { 0x9f, 0x9d, 0x76, 0xcf, 0x19, 0x6b, 0xae, 0x90, 0x61, 0x27, 0x76, 0x9d, 0xe4, 0x7b, 0x29, 0x4c } }, +{ "\x77\xfc\x10\x0f\x3a\xb2\x20\xad\x0a\x03\xfd\x51\xba\x93\xe6\x70\xe7\x34\xa4\xd8\xde", 21, { 0xb2, 0xfe, 0xf1, 0xb3, 0x6c, 0x1d, 0x2a, 0x88, 0x2a, 0x02, 0x4e, 0x25, 0x12, 0xa8, 0x6a, 0x6d } }, +{ "\x84\x87\x22\x2b\xb3\xf8\x44\xbf\x63\xbb\x43\xbd\xa8\xc4\x05\xe1\x2f\xb2\x44\x8d\x7a\xec", 22, { 0x2e, 0x1f, 0xd3, 0x56, 0xce, 0x43, 0x56, 0x70, 0xb8, 0x84, 0x6d, 0xd9, 0x24, 0x49, 0x36, 0x4d } }, +{ "\x9f\x72\x49\x57\xca\xd7\x15\xb1\xe6\x89\xb5\x8d\xec\x5f\x24\xeb\x42\x69\x5a\x73\x70\xb5\x56", 23, { 0xf2, 0xbf, 0x7a, 0x59, 0x6e, 0x6c, 0x2f, 0xcf, 0x5b, 0xaa, 0x02, 0x31, 0xac, 0x48, 0x5d, 0xe9 } }, +{ "\x4e\xec\xbd\x3d\xa2\x11\x70\x9c\xa8\x2e\xdb\xca\x6b\xbb\x74\x69\x1e\xa7\x03\x0b\x1b\xcd\x2e\xf0", 24, { 0x68, 0x75, 0x89, 0x8f, 0xaf, 0xdb, 0x8e, 0x21, 0x92, 0xab, 0x3a, 0xd2, 0x25, 0xad, 0xc1, 0x26 } }, +{ "\x74\x84\x9f\xed\x38\x55\xd4\x69\x44\xc8\x82\x82\xc2\x57\xa7\x4d\x43\x84\x2b\x3a\x75\x06\x32\x95\x81", 25, { 0x03, 0x4c, 0x88, 0xfc, 0x08, 0x2e, 0x21, 0x1e, 0x9f, 0xac, 0x56, 0x0c, 0xfc, 0x96, 0xbf, 0xec } }, +{ "\x1e\x01\x28\x03\x09\x8a\xfe\xa7\x8e\x95\x42\x5d\xb7\x8d\x46\x38\x9c\xe5\xa1\xe8\x5a\x25\x70\xd2\x23\x95", 26, { 0x0d, 0xb4, 0xe1, 0xa3, 0x6a, 0xed, 0xb5, 0x0b, 0x0f, 0xa1, 0x90, 0xf1, 0x48, 0xb7, 0x47, 0xd8 } }, +{ "\xbc\xc9\x70\x84\xfc\x6c\x51\x35\xb1\x1c\xe4\x67\x2f\x97\xe4\x80\x7c\x36\x59\x55\x51\xbf\x6d\x98\x3d\xe8\x5f", 27, { 0x6b, 0x15, 0x3d, 0x7d, 0xe7, 0x46, 0x1f, 0xe1, 0xb8, 0x15, 0xe7, 0xc8, 0x75, 0x66, 0x19, 0xf5 } }, +{ "\xdf\xe9\x69\x90\x4d\x76\xbc\xbb\xdf\x03\x74\x42\x55\x4a\x37\xa3\xba\x6a\x5a\x09\x92\xbf\x17\xff\xa0\xed\x6d\x3f", 28, { 0x6d, 0x27, 0xc4, 0x1a, 0xa8, 0xa4, 0x76, 0x37, 0x72, 0x9d, 0x84, 0xbe, 0x00, 0x7b, 0x7b, 0xf6 } }, +{ "\x51\xfc\x95\xa9\xc8\x9d\x1c\x4f\x87\x8b\xa2\xad\xb7\x0d\x2d\xf6\x14\x98\x2b\x89\x77\x91\x02\x83\x01\x2f\x56\x6e\xe1", 29, { 0x65, 0xa5, 0xce, 0x1b, 0x75, 0x9d, 0x8f, 0xd3, 0x5f, 0x84, 0x26, 0x59, 0x32, 0x0d, 0x9c, 0x5f } }, +{ "\x7f\xd6\x16\xc3\x81\xc3\x7c\xd6\x70\xff\xe4\x77\x1f\xcd\x09\x7f\x7f\x2b\x71\x26\x3d\xc9\xdb\x92\x88\xa5\xd4\x00\xf0\x44", 30, { 0x99, 0xfa, 0xec, 0x52, 0x11, 0x1b, 0xfc, 0x3a, 0xba, 0xe5, 0x96, 0xbc, 0xa7, 0xb4, 0xa8, 0x3c } }, +{ "\x68\x8e\x6a\x8e\xf6\xa2\x70\x47\x1d\xfb\x45\x26\xd2\x52\x56\x94\x94\xac\xbc\x02\xb6\x3f\xde\xe7\xdb\xfe\x34\x55\x81\xc3\x26", 31, { 0x14, 0x6f, 0xe7, 0x1d, 0x1c, 0xa6, 0x6d, 0xc6, 0xd5, 0x33, 0xbb, 0xf5, 0xdc, 0x90, 0x83, 0xf7 } }, +{ "\x37\xb3\x18\x13\x29\xe2\xa2\x6d\xf4\xce\x2b\x01\xa5\x9f\x4b\x54\x48\x10\xb1\x29\x46\xcb\x13\x20\x58\xcf\xb0\x78\x27\x0d\x7e\xf5", 32, { 0x41, 0x97, 0x27, 0x98, 0x5b, 0x0a, 0x50, 0x29, 0x3f, 0x71, 0xa0, 0x20, 0xfa, 0x18, 0x13, 0x9b } }, +{ "\x82\x13\xf6\xdd\x3b\xdf\x78\x1c\x9e\xd6\x5b\x87\x8f\xcd\x95\x3d\x3f\x43\x04\x2a\x8b\xb2\x57\xa5\xf1\xfa\x9c\x39\x2f\xfe\x66\x81\x7a", 33, { 0x96, 0xda, 0xe6, 0x6e, 0xda, 0xaf, 0x1c, 0x5c, 0xb6, 0x68, 0x6c, 0xb5, 0x2a, 0x53, 0x52, 0x21 } }, +{ "\x4a\x9a\x2c\x58\xf1\xd6\x21\x1a\x76\x7f\xbc\xfa\xe0\x66\x35\xcd\xf1\x17\x22\x64\x6f\xbd\x13\x85\xa1\xb5\x5b\x81\xd6\xad\xee\x72\x1e\x79", 34, { 0x2c, 0x13, 0x32, 0xbe, 0x4b, 0xee, 0x1e, 0x36, 0x8a, 0xcd, 0x5c, 0x1c, 0x5f, 0x5a, 0x7e, 0xce } }, +{ "\x66\x13\x1c\x72\x20\x3c\xf3\x8b\x83\xf8\x5e\xf2\x60\x44\xdc\x5e\x75\x67\x08\xfb\x0c\xe9\x07\xf0\xc1\x31\x1a\x89\x60\xbf\x53\x06\xed\x02\x64", 35, { 0x8a, 0x9e, 0x07, 0x96, 0x6b, 0xeb, 0x7e, 0xc2, 0x3f, 0xca, 0xe4, 0x74, 0x0f, 0x8a, 0xd0, 0xb1 } }, +{ "\xff\xbd\xd6\x92\x72\xc1\x9e\xc9\x6b\xe3\xfb\xca\x4e\x88\x26\x7f\xc4\x36\xf0\x70\x40\x4f\x53\x4d\x2d\xfc\xb3\xab\xb6\x25\xb7\xcc\x31\x9c\xbf\x97", 36, { 0x6d, 0x72, 0xeb, 0xd3, 0xf4, 0x77, 0x52, 0x8b, 0xb9, 0x10, 0x42, 0x47, 0x1d, 0xcc, 0xa3, 0xa4 } }, +{ "\x29\x59\x01\xa6\x06\xe0\x43\x7e\x5b\xbf\x37\xda\xcc\x33\x6e\x20\x9a\xeb\xfa\xf5\xcd\xe4\xa5\xec\xfd\x73\xc7\x59\xbc\x61\xc8\x44\xa3\x30\x33\x79\xf8", 37, { 0xd1, 0x39, 0xc1, 0x5b, 0x60, 0xb6, 0x53, 0x6e, 0xda, 0x86, 0xc6, 0x34, 0xa7, 0x8f, 0xe9, 0x66 } }, +{ "\x7c\x72\xbd\xf9\x7d\x2c\x1b\xc8\xa9\x38\x5c\xf2\x76\x3c\x94\x9d\x3d\xe7\xd9\x4e\x3a\xc7\x0f\x55\xb0\xc7\xdf\xd5\x29\x49\xc6\x74\xdb\xdc\x49\x9b\x27\x9a", 38, { 0x8e, 0x6e, 0x12, 0xe2, 0x8f, 0xd3, 0x0d, 0x34, 0xac, 0x81, 0xc6, 0xe6, 0xe8, 0xf2, 0x84, 0x03 } }, +{ "\x46\x6a\x3b\x21\x66\x3c\xd6\x2c\xaf\xd2\x2b\xcd\x36\x1e\xdf\x49\xf2\xae\x2d\x8f\xab\xb3\x29\x57\x10\xae\x22\xd4\xe8\xb6\x20\x15\x61\x68\x8c\xfd\x85\x6b\xef", 39, { 0x73, 0x15, 0x7b, 0xcb, 0xa7, 0x03, 0x3b, 0xb0, 0xac, 0x14, 0x75, 0x41, 0xe5, 0x83, 0xb4, 0x66 } }, +{ "\xdd\xca\x9e\xd3\xab\xc8\xe1\xc5\xe2\x05\x7d\x7c\xf5\xec\x31\x14\x71\xdd\xda\x73\xae\x5e\xbd\xcd\x31\x6e\x74\x42\xa1\xfa\x74\xa4\x64\x69\x37\x57\xd6\x52\x0a\x51", 40, { 0x41, 0x74, 0x00, 0x0d, 0xee, 0x8b, 0x3e, 0x10, 0xac, 0x8e, 0x4e, 0x41, 0x25, 0x38, 0xa6, 0xf0 } }, +{ "\x26\x4d\x75\x42\xcc\xe7\x42\xcd\xaa\xaf\x2c\xf3\xbf\x6d\x26\x91\x82\x72\x44\x00\xe1\x0b\x4a\xda\xd5\x0f\xd0\xdc\xa2\x98\x0e\xe7\xa8\xce\x4a\x21\xe9\xdf\xdb\x38\x18", 41, { 0x46, 0x5e, 0x28, 0x3e, 0x2d, 0x14, 0x30, 0xbf, 0x07, 0x39, 0x12, 0x33, 0x8e, 0x1b, 0xcd, 0x05 } }, +{ "\x0b\xd8\xc7\x5a\xdb\x62\xd1\x9c\x71\x8b\x69\x90\xfb\xe2\x74\x45\x41\x9d\x87\x61\x5e\x61\xea\xfe\x8c\xb0\xbe\x1f\x18\xef\x3a\xce\x74\x13\x11\xd3\x6b\xe8\xf0\x12\x6f\xfe", 42, { 0x19, 0xae, 0x68, 0x51, 0xdb, 0xf7, 0xfa, 0xe7, 0x3c, 0xdc, 0x83, 0x35, 0x95, 0xb7, 0x9e, 0xd8 } }, +{ "\x23\x82\x0e\x30\x57\xc6\x83\xd2\x7a\x69\x69\x76\xbf\xbb\x8b\x5b\xbd\x42\xd6\x73\xb7\xdf\x70\x10\xf6\x7f\xe1\x2a\x53\x7a\x6f\x4f\xd1\x8b\x89\x27\x66\x6d\x59\xa3\xdb\x0e\x7c", 43, { 0xfc, 0xe5, 0x55, 0x88, 0x24, 0xff, 0x12, 0x50, 0x72, 0x7d, 0xbb, 0x96, 0xda, 0xfa, 0x2a, 0xd0 } }, +{ "\xc2\xc9\x72\xce\xff\xc3\x27\x5e\x5b\x92\x60\x81\x02\x9b\xb1\x02\x9d\x5d\x66\x77\x33\x17\x80\xaf\xbc\x86\x4d\x47\x44\xcc\xa3\x5b\xb9\x6c\xb9\x5a\x51\x72\xa1\xf3\x9a\xb0\x66\x2c", 44, { 0x4e, 0x95, 0x9e, 0x13, 0xba, 0x8e, 0x68, 0xa8, 0xd2, 0xcb, 0x9c, 0xd6, 0xb0, 0x91, 0x48, 0xc9 } }, +{ "\x1f\x22\xbe\x91\xb4\x73\x6c\x89\x5f\x99\x35\xc4\xe3\x9b\x7c\xd0\xea\x73\x7c\xcb\xce\x0e\x22\x33\x04\x6f\x85\xd9\x25\xf4\x03\xf4\x9b\xb1\xf9\x52\xe4\xf8\x1e\xa9\x86\xfb\x7d\x0c\x8f", 45, { 0x32, 0x7d, 0xcc, 0x9a, 0x8b, 0x86, 0x41, 0xe3, 0x94, 0x5d, 0xb2, 0xa1, 0xc4, 0xf2, 0xb9, 0x9a } }, +{ "\x88\x0d\x79\xc8\xf2\xee\x8f\x76\x10\x42\x5d\xcc\x5f\xa6\x55\xf0\x43\x4c\x5f\xa8\x6b\xb7\x0a\xa1\x51\x11\xdd\x5c\xe1\x2c\xcc\xb6\x31\x13\xc6\x12\x6f\x4c\x6b\x24\xd9\xae\xdb\x5d\xe4\xd9", 46, { 0x9d, 0x7d, 0x73, 0xcf, 0x4b, 0x16, 0x28, 0xd1, 0x06, 0x3a, 0xde, 0xde, 0xf5, 0xdd, 0x8a, 0xda } }, +{ "\xaa\xee\x80\x55\xef\x7b\x73\x4a\x7c\x5e\xe2\xd9\x27\x95\xef\x17\x47\x49\x7b\xa4\x3b\xfc\x0c\xeb\x24\x4e\xca\xf8\xb2\x6b\xa4\xf0\x1c\x14\x90\x32\x29\x49\xef\x09\x6c\x91\x0e\x0a\x8d\xe5\xc9", 47, { 0x00, 0xf1, 0x9c, 0x62, 0x0b, 0xe5, 0x13, 0xde, 0x01, 0x5e, 0x1c, 0xe9, 0xf5, 0x8d, 0x5e, 0x54 } }, +{ "\x11\xc1\x3f\x4a\xd2\x5b\xba\xef\x1e\x7c\x66\x4a\xb5\xe6\xaa\x41\xc2\xef\x56\x56\xf7\x91\x45\x01\x45\x9e\xab\x3a\x38\x10\x01\x13\xee\x7f\x8a\x81\xb2\xab\x80\x3b\x39\x39\xe0\xba\x78\x7b\xcf\x61", 48, { 0xa9, 0x50, 0x1d, 0x59, 0x8d, 0x20, 0x34, 0xca, 0x14, 0xc3, 0xfe, 0xc6, 0xd2, 0x01, 0xcb, 0xc6 } }, +{ "\x20\x68\xa7\xb7\xb8\xab\xa3\xcf\x55\xd7\x23\xc9\xf7\xb7\x9b\x71\x83\xc3\x1e\x04\x59\xaf\x83\x13\x91\x1e\x31\x81\xd7\x75\x8d\xa6\xe0\xca\xfc\x96\x88\xfa\x97\x7c\x8a\xd9\x6b\x1f\xdb\x85\x69\x87\xa3", 49, { 0xc3, 0xf7, 0x89, 0x76, 0x95, 0xe3, 0xbd, 0x8c, 0xca, 0x78, 0xfd, 0x14, 0x43, 0xd5, 0x3b, 0xc0 } }, +{ "\xd4\xf1\xb9\xd9\xeb\xf5\x9d\x7a\xf0\xcd\x01\x65\xd7\x98\xb6\xd6\x59\x49\xd8\x7d\x03\x55\x2c\x3a\x6b\xf7\xa1\x78\x7d\x1e\xf9\x23\xf3\xf5\x81\x47\xe3\x0c\xfc\x46\x72\x28\x9e\xb6\xa6\xa4\x34\xd5\x5a\x81", 50, { 0x1c, 0x9d, 0x43, 0x52, 0xba, 0x7f, 0xc6, 0x30, 0x6b, 0x72, 0xd7, 0x96, 0x5b, 0xd1, 0x2d, 0xbf } }, +{ "\x61\xa9\x4a\x12\x02\xb8\x4e\x3d\xb3\x61\xa4\x6e\x6b\xd6\x66\x1e\x42\xb7\x1a\xfb\x54\x4b\x68\xb5\xbd\x5d\xe6\x65\xc3\xb1\x0f\x99\x13\x22\x53\x00\x24\x59\x48\xaf\xb8\x2c\xfe\x0d\x81\x90\x70\x62\xe0\x3c\x15", 51, { 0x7e, 0x5a, 0xb7, 0x6b, 0xb6, 0x54, 0xdf, 0x9e, 0x2f, 0xb5, 0x77, 0xf1, 0x9a, 0x6a, 0x59, 0x79 } }, +{ "\xf6\xc8\xdd\x96\xe9\xc2\xef\x9b\x8f\x09\x3f\xbf\x85\xd5\xfa\xa2\x55\xb5\x70\x1c\xc1\x15\x6b\x8e\xb0\xdf\x26\x55\xb2\x3e\xec\x58\x32\x7e\x4f\xc1\x37\x10\x01\xc8\xd6\xa9\x52\xab\x38\x89\x46\xba\x44\xd9\x52\x8e", 52, { 0xb9, 0x98, 0x85, 0xa3, 0x53, 0x84, 0x15, 0xf4, 0x7d, 0xbe, 0x68, 0xff, 0x96, 0x56, 0x6a, 0xc5 } }, +{ "\xe9\x2d\xb3\x5a\x09\x2a\x6c\x59\x05\x41\xda\x67\xe1\x99\xf5\xac\x14\x0b\x25\x73\xef\x47\xbe\x19\xa7\x14\x1a\x20\x01\xb4\x52\x63\x99\x65\x98\x64\xce\x04\x34\xc1\x4d\xcd\x19\xc5\x39\x3d\x24\x1b\xf4\x18\xf0\x9e\x8d", 53, { 0x78, 0x0a, 0x2e, 0xce, 0x91, 0xb5, 0xd9, 0xa2, 0xc1, 0x7f, 0xab, 0xd3, 0x93, 0x73, 0xc5, 0xf2 } }, +{ "\x86\x58\x4b\xc6\x59\x8a\x58\xc0\x6a\xc4\x5e\x45\x21\xaf\xb1\xb2\x12\x54\xd0\x7f\xc4\xbf\xf8\x6d\x8e\x2f\xd3\x4b\x9b\xf6\x4e\x64\x0c\xf3\x88\x88\x3c\xaa\xe6\xb5\x1f\xfd\x43\x63\xc3\x89\x45\x69\xf9\xa0\xcb\x8f\x0d\xde", 54, { 0x20, 0x66, 0xd7, 0xd2, 0x54, 0xf6, 0x4a, 0x99, 0xbd, 0x73, 0xde, 0x75, 0x3b, 0x07, 0xaa, 0x2a } }, +{ "\x82\xb1\xb0\x6a\x97\x8c\xf7\xcb\x86\x28\x7c\x64\x11\xe2\xa2\x8e\x4d\x15\xf7\x50\xd6\x64\xb2\xbd\x23\xa7\x5b\xeb\xf4\x70\x8a\x8b\xe8\x39\xc7\x2a\x2b\x2b\x91\x03\x4c\x8d\x7a\x7e\x2c\xc8\x6f\x49\x12\x13\x16\x12\xdc\xbf\x50", 55, { 0x0b, 0x6a, 0x58, 0xcd, 0x5c, 0x4b, 0xa5, 0xbe, 0xff, 0xdb, 0xff, 0x98, 0x89, 0x58, 0xe4, 0xe9 } }, +{ "\xde\x50\x21\xdd\x09\x91\x17\x1f\xda\xad\x39\xf7\xc2\x53\x9e\xcc\x32\xa2\x48\xaa\x16\x1c\x2d\x86\xf1\xb9\xe2\xa0\x96\x18\xe6\x01\x80\xd0\x89\x24\xcf\xe5\x77\xb1\xe0\x57\xe5\x64\x87\xd4\x57\x0d\xeb\x8d\x0b\xb0\xff\x25\x06\xcc", 56, { 0xcb, 0x43, 0x10, 0xa9, 0x26, 0xff, 0xaf, 0x74, 0xd9, 0xde, 0xc4, 0xab, 0xa2, 0x97, 0x12, 0x12 } }, +{ "\x99\xc6\xb8\xb9\x30\x4e\x4e\x2a\x37\xa7\x95\xd2\x10\x35\x86\x24\xaf\x68\x72\x32\xcc\x71\xcb\xb7\xc4\x11\x8c\x30\x0d\x8c\x46\x24\x54\xbd\xc8\x85\x35\x43\x6b\x2f\x96\xd9\xf7\x8d\xa0\xc4\x36\x5b\x5b\x65\x13\x85\xe6\xee\x6d\x2f\x4f", 57, { 0x69, 0x64, 0x39, 0x12, 0xc7, 0x7b, 0x98, 0x65, 0xf1, 0x8b, 0xc8, 0x61, 0xad, 0x18, 0x5e, 0x44 } }, +{ "\x31\x7e\xce\x15\x94\xe2\x73\x37\x21\x47\x28\xf8\xba\xb0\x73\x32\x69\x65\xf7\x54\xd6\x7b\x3a\xfa\xd2\xfc\x82\x28\x0f\xb2\xd8\x22\xf2\x95\x2e\xea\x81\xce\x9c\x57\x77\x67\xc6\xce\x77\x92\x5a\xa0\x5d\x93\xb6\x00\xaf\x4a\xa6\x9f\x32\x61", 58, { 0xc3, 0xc8, 0x1d, 0xfd, 0x52, 0x98, 0x05, 0x1b, 0xe1, 0x01, 0x1e, 0xbf, 0x18, 0xbd, 0x55, 0x5d } }, +{ "\x4b\xe6\x99\x0e\x17\xcf\x58\x85\xf4\x60\x98\xfe\x84\xc6\x43\x5e\x84\x0a\x3e\x84\x4a\x72\xb7\x33\x6d\x77\x94\x97\x83\x5d\x0a\x76\x05\x75\x4f\xf4\x4f\xeb\x67\x02\xc4\x4c\x1b\x65\x0f\x99\x09\x5f\x84\x00\xd4\xfc\xa4\x3d\x7b\xfa\xbf\x8d\xc7", 59, { 0x81, 0x50, 0x46, 0x50, 0xc1, 0x0e, 0x9f, 0xb5, 0x07, 0xaf, 0xde, 0xd3, 0x59, 0xfe, 0xcc, 0x22 } }, +{ "\x55\xb4\x4a\xde\x6f\xd4\x28\xf6\xd9\xe5\x0a\x23\xc1\x42\x82\x50\xf8\x20\xe4\x4c\x9e\xeb\x05\xfc\x6b\xce\x95\xaf\x9d\x52\x16\x8f\x7a\x1e\x78\x32\x81\xdd\x53\x50\x31\x3d\xc0\x8f\x75\x13\xd5\x7b\xaa\x9b\xbb\x91\x4f\xdd\x6c\x7a\x48\x2c\x0e\x55", 60, { 0xb4, 0xc3, 0xbe, 0x48, 0x13, 0x1d, 0x4c, 0xa6, 0x77, 0x96, 0xfb, 0x46, 0x00, 0xaa, 0xe0, 0x23 } }, +{ "\xcf\xc9\xe7\x2d\xf7\xa4\xfd\x8a\xde\x42\x4b\x23\x6f\xba\xa1\xb1\xd1\xd9\x19\xde\x70\x65\x31\x5c\xa6\x7f\x8a\x13\x05\x21\x3c\x72\x43\xc7\xd4\xe7\xc3\x2b\xeb\x69\xbc\x28\x64\x32\x08\xc0\x41\x8b\x8b\x39\x22\xbf\x3e\x62\x5c\x31\xd7\xf3\xb2\x8a\x17", 61, { 0xae, 0x50, 0xbd, 0x11, 0xb4, 0x2e, 0x1b, 0x32, 0xbc, 0x0a, 0x61, 0xb0, 0x07, 0x0c, 0xb7, 0x6e } }, +{ "\x12\xb3\x0a\xb0\xf2\xaf\x00\xd0\x96\x57\x55\x4e\xb4\xf0\x42\x70\xb4\x34\x21\x56\xd7\xc5\x61\x07\x75\x4f\x94\x17\x5e\x39\xa3\xf1\x62\x07\x21\xc7\xed\x4f\xbc\x13\xca\x55\xd0\xc8\x08\x46\x15\x1a\xfa\x0d\x79\xe7\x58\xd6\x09\xc0\x82\x1d\x08\x98\xe5\x72", 62, { 0xb6, 0x1f, 0xc7, 0x47, 0x6f, 0x2c, 0x1a, 0x33, 0xcd, 0x50, 0x40, 0xd0, 0x30, 0xd4, 0x96, 0x9f } }, +{ "\x22\x09\x76\xcb\xba\x3d\x5c\x85\x60\x7f\xaa\xf9\x5e\x5e\x4a\xb7\x71\x7b\xf5\x62\x95\xf0\x5e\x28\xf9\x5d\x6e\xdb\x12\x90\xaa\xb1\xcc\xd0\xb2\x95\xdb\xc7\xe3\x27\x2f\x09\x1b\x57\x85\x45\x9c\x99\x1a\x07\x09\xc5\x7a\x27\x8e\x8f\x77\xd2\x1d\x9e\x36\x32\xd3", 63, { 0x54, 0xbb, 0x99, 0xe2, 0xff, 0x14, 0xe1, 0xce, 0xa6, 0xb9, 0x6b, 0x77, 0xf9, 0x1f, 0x52, 0xd7 } }, +{ "\x4a\x64\xbd\x79\xf7\x86\x17\x25\x09\x6d\xa5\x01\x83\xc7\xaf\x23\x3f\xd2\x31\x9c\xcc\x2c\x3f\x8d\xdf\xc7\x12\x72\x78\xf8\xb3\x82\x93\xae\x42\x2f\x86\xbf\xe3\xc8\xfd\x5e\x46\x3f\x90\xa9\xd2\x04\xfe\x5f\x6e\x0f\x09\xaf\xeb\xfd\xed\x2b\x11\x52\x7e\xdc\x45\xdd", 64, { 0xa7, 0x71, 0x25, 0x07, 0x06, 0x4e, 0x0a, 0x46, 0xbb, 0x2f, 0xd6, 0x8a, 0x0b, 0x19, 0xda, 0x2f } }, +{ "\xdd\x6e\xd4\x39\xd6\x8c\xde\x6f\xda\x47\xe1\xb9\x94\xaf\xe1\x62\x29\x84\x32\xc9\x11\x06\xe2\x84\x8d\xe9\xc5\xa0\xc4\x65\x1d\x07\x7e\x69\xe6\xfb\x7c\xef\xbc\xbe\x71\x6b\x6a\x54\xa1\x5d\x10\x60\x15\x06\xf0\x2b\x78\x37\xd5\xc4\x92\x44\x20\x41\x5e\x18\x70\x23\xc9", 65, { 0x7e, 0x44, 0xc6, 0xdd, 0x7f, 0x97, 0x6b, 0x87, 0x68, 0x0a, 0xd6, 0x98, 0xec, 0x78, 0x88, 0x0b } }, +{ "\x62\xed\xd8\x0a\xed\x32\x59\x98\x0e\xd4\xf4\xcd\x36\x93\x24\x15\xa7\x1d\x9c\xd2\x44\x79\x63\xd0\x81\x16\x18\x60\x79\x71\x57\x13\x1e\x5d\x34\x15\x8a\xf2\xe4\x23\x75\x14\x7c\x2a\xc0\x9f\xd1\x7e\x2d\x2c\x7d\xb3\x32\x83\x03\x1c\xe2\x9d\x0a\xdd\x0b\x54\xc6\xaf\x5f\xa9", 66, { 0x1e, 0x1d, 0x15, 0x6e, 0x61, 0xaf, 0x88, 0x11, 0x0d, 0x63, 0xfc, 0x25, 0x8a, 0x13, 0x66, 0xb9 } }, +{ "\x74\x30\xca\xb2\x03\xe5\xe2\x1e\xd0\xcd\x7d\x66\x8a\xa2\x5c\x92\x35\xaf\x04\xa5\x4a\x49\xad\xa7\xfb\xeb\x54\x4d\x93\xf2\xeb\x46\xfc\xf1\xb1\x24\x5a\xb2\x9c\xe5\xd5\xca\xf1\x1e\x75\xd8\xf6\xc3\x26\x5a\xc0\x95\xda\x2b\x26\x28\xcd\x9d\xd6\x90\xe4\x2f\x85\xa8\x2f\xeb\x42", 67, { 0x8a, 0x89, 0xe2, 0xa9, 0xd2, 0xbb, 0xeb, 0x0c, 0xd6, 0x6c, 0xe7, 0x6b, 0xbd, 0xe1, 0xd3, 0xa7 } }, +{ "\xfe\x8e\x5f\xe4\x5e\x6f\x35\xa2\xfa\xb5\x71\xc1\x33\xb4\x47\x68\x06\x59\x97\x8f\x16\x67\x06\x16\x52\xdc\xba\xf2\x42\x72\xb1\x82\xf3\x41\xbf\x00\x7d\x81\x22\x12\x2e\x6e\xc3\x80\x55\x44\x0c\x01\xac\x6a\x60\x2e\x63\xab\x3b\x98\xc5\x9f\xe8\xf5\x89\x28\xd9\x75\xb8\x18\xa6\x33", 68, { 0x27, 0x2d, 0x93, 0x98, 0x27, 0x31, 0xa7, 0x1c, 0x09, 0x80, 0xd8, 0x3b, 0xcf, 0xde, 0x6f, 0x7a } }, +{ "\x35\xf0\xa5\xc6\xee\xc3\x22\xf8\x9e\x3a\x3b\x8e\x3c\xb0\x5b\x46\x03\x7d\x51\xdf\x1f\x50\x0c\x52\xf1\xb6\xf5\x1e\xff\xb7\xe9\xc1\x7b\x9f\xd2\x42\x6e\xda\xe1\xeb\x81\xf9\x69\x15\x68\xd1\x5b\x1b\xec\xc2\x5a\x71\x93\x15\x7a\xcd\xed\x7f\x9a\x83\x7e\xc2\x5b\xee\x43\x73\xbc\x0a\xe3", 69, { 0x00, 0x4e, 0xc2, 0xb8, 0x3e, 0xdf, 0x71, 0x7c, 0xc0, 0x9c, 0xd3, 0x98, 0x85, 0x4d, 0xc7, 0x95 } }, +{ "\xd6\x54\x1f\x73\xe5\x2b\x98\xe6\x70\x34\xf2\x10\x5e\x6b\xd0\x55\x11\x87\x2b\xf2\xe8\x5d\xa6\xe7\xde\xd1\xff\x80\x4f\x79\xa2\x7f\xdb\xd0\x58\xe8\x63\x13\x1c\x69\x31\xbb\x0e\x63\x34\x98\x81\x99\x68\x87\x2f\x74\x54\xd0\x8c\xf0\xad\x1e\x37\x27\x18\x1b\x8d\x78\x0d\xa8\x58\x54\xd7\xb6", 70, { 0x81, 0x58, 0x80, 0xad, 0x21, 0x1f, 0x75, 0x90, 0x18, 0x1c, 0x0a, 0xb5, 0xf2, 0xa3, 0x72, 0x34 } }, +{ "\xa5\xa5\xb7\xc4\xb3\xda\x29\xf5\x07\x93\x3e\xcd\x9d\xe6\x28\x88\x38\x4c\xd4\x17\xdb\x2c\xb2\xb8\x50\x01\x90\x30\xe5\x2a\xa4\xa8\x37\x4e\xa8\x21\x26\x69\x20\x96\xe8\x78\xb7\xad\x39\xbd\xc7\x19\xb0\xaf\xf8\x8f\x2d\x82\x00\x62\x6f\x4e\x88\xbd\xc2\xdf\x2f\x7d\xd5\x18\xa7\xa9\xa9\x04\xfd", 71, { 0xfb, 0x0d, 0x18, 0xc6, 0xe4, 0x89, 0x48, 0xb1, 0xf6, 0xfd, 0xeb, 0xe2, 0xc1, 0xf1, 0xf3, 0x23 } }, +{ "\x8e\xa6\x7b\xf7\x7b\xc8\x6d\x96\x16\xf6\xce\xbb\x5a\x73\x1e\xe6\x2e\x6d\x93\x19\xa2\xb3\xe6\xdb\xc8\x84\xb7\x58\x2d\x83\x9e\xa6\xf3\xc6\xcf\x22\x8c\x0d\x69\xf9\x15\x0f\x5b\xc3\x4d\xf0\xf3\x49\x30\xd0\x05\x67\x34\x7d\xb4\x0d\x1f\x48\xe0\x5f\x83\xf5\x2c\xfc\xd7\xcc\xaa\x5c\x34\xcc\x26\x53", 72, { 0x36, 0x75, 0xbc, 0x48, 0xda, 0x88, 0x50, 0x72, 0x0e, 0xf7, 0x29, 0x63, 0x24, 0x34, 0xe3, 0x39 } }, +{ "\xa9\xff\x0c\xb2\x3b\xe9\xf7\x0c\x7c\x1a\xd6\x96\xc6\xe3\xbd\x28\x15\x25\x46\x60\x7e\x45\xa1\xe6\x50\x3b\x3f\xc9\xc6\xca\x17\x08\x65\xca\x94\x2e\xf8\xa1\x1b\x14\x26\xd0\x3c\xca\xad\xa9\x74\x91\x3d\x1e\x9d\xff\xf3\xb5\xf3\x45\x70\x99\xc3\x8e\x96\xca\xb2\x7d\xdf\x73\xa7\xd9\x59\x5c\x56\x45\x42", 73, { 0x2e, 0x33, 0xf2, 0x55, 0x54, 0x86, 0xb7, 0xa7, 0x53, 0x25, 0xf2, 0xe5, 0x8a, 0x28, 0xf6, 0x82 } }, +{ "\x76\x6a\x28\x3c\x94\x4e\xab\x2c\x39\x99\xe0\xb5\x8c\x14\x00\x4c\x68\x68\xcd\xf8\x90\x69\x16\xa9\xff\xf9\x59\x32\x5e\x9a\x82\xe3\x8f\x94\xd2\xc7\x66\xbf\xdb\x77\x78\xee\xa7\x99\x0b\xf8\xf9\xf9\x2d\x64\xab\x41\xe0\xb0\x36\x58\x72\x3e\x50\x55\xec\xdc\xb0\x1f\xa0\xee\xed\xa3\xe5\x3a\x84\xb0\xe0\x50", 74, { 0xfd, 0xff, 0x52, 0x9f, 0xba, 0xe5, 0xe2, 0x49, 0xa8, 0xfa, 0x24, 0xec, 0xa0, 0xc7, 0x0b, 0x65 } }, +{ "\xf8\x72\x78\x94\x14\x89\x6b\xea\x4c\xc5\x7f\xfc\x42\x80\xd0\x2a\x64\x98\x48\x0f\xb2\x08\x2e\xad\x9d\x23\xd5\x34\x0b\x6c\x74\x74\x78\x14\x16\xdc\x36\x11\xa8\x2e\xd4\xd7\x30\xc1\x9d\xb5\x1d\x72\x38\xcf\xb9\x28\x6d\xb4\xba\x03\x07\x9b\xf8\x21\xd4\x3f\x3a\x0c\xc9\x54\x29\xc3\x42\xa4\x66\x64\x68\xcb\xb7", 75, { 0x17, 0x43, 0xcd, 0x6e, 0xf2, 0xfb, 0x65, 0xa6, 0x27, 0x7f, 0x7b, 0x30, 0xa9, 0x73, 0xb9, 0xe3 } }, +{ "\x73\xac\x8b\x5c\xc9\x6f\xcd\x80\x1b\xc4\x35\xcb\x26\x4d\x60\x14\x74\x42\xbd\x34\xce\x90\x05\xf6\x3f\x1d\x58\x2a\xc0\x2a\xf6\xd9\x85\xd2\x96\x92\xe3\xaf\x66\xe3\xdc\x9c\xa0\xe3\x49\x94\xc6\xec\xa2\xb9\x7a\x67\x6d\x71\xfc\xc0\x41\xab\x40\x78\x76\x40\xab\x58\x6c\x74\x6a\xc3\x74\x9b\x6f\x25\x5e\xd8\x09\x88", 76, { 0x1d, 0xc9, 0xfa, 0xc0, 0x76, 0x7a, 0xd0, 0x00, 0x3b, 0xec, 0xae, 0x60, 0x8f, 0xb8, 0x72, 0xb3 } }, +{ "\x9f\x01\x1f\x45\x1f\x9e\x09\xd7\x9d\x10\x0c\xcb\xc0\xcf\x6f\xd3\xbb\xcc\x3e\xfb\x9b\xf5\x9b\xf3\x30\xd7\xbb\x8a\x96\x5d\x84\x3c\x5f\xb6\xc2\xe2\x5e\x55\x00\x87\x12\x12\x09\x5b\xae\x6e\xfb\xc1\xc1\xf3\x04\x83\x87\xba\xbc\x25\xcb\x06\x1f\x57\x77\x0e\x25\x83\xba\xd8\x00\x87\xd4\x41\xf2\x7d\x81\x19\xc8\xb5\x00", 77, { 0x7e, 0x0a, 0x91, 0xef, 0x91, 0x65, 0x79, 0x1f, 0x66, 0x8b, 0x7e, 0xb7, 0xb3, 0xe1, 0x02, 0x61 } }, +{ "\x6b\xf6\xc4\xbe\xda\x50\xb6\xa4\x26\x63\x5e\xfa\xce\x6e\xcf\xf6\xd0\x00\xe3\xe5\x8c\x2f\xf8\xf5\xc7\x72\xbb\x9d\xca\x1c\x1c\xa9\xaa\x76\x61\xe5\xa3\x77\x56\x65\x9e\x22\xa2\x70\xd2\x7c\x36\x07\x86\x29\xde\x15\xf4\xa3\xfa\x34\x4a\x15\x46\x19\xca\xda\xd4\x9e\x11\x8d\x1c\x6b\x74\xcc\x2a\x3f\x86\x8e\xf5\xe0\xb6\x1e", 78, { 0xd2, 0x81, 0xce, 0x6f, 0x24, 0x4b, 0x96, 0x1b, 0x08, 0x0c, 0x6e, 0x2e, 0x55, 0xd5, 0x40, 0x8b } }, +{ "\xd0\x9d\x15\xb4\xf9\x7d\x36\xae\x4f\x06\x2e\x70\x21\xab\xbb\xd5\x22\xd3\x81\x50\x78\x82\x6f\xa4\xf3\xa6\x41\x3c\x5b\x00\x1e\x27\xe2\xad\x61\xb4\xb8\x51\x75\xa7\xbe\xdf\xd9\x15\x52\x06\x43\xe1\x49\x3b\xe1\xd3\xfa\x5f\xba\x52\x77\x0e\x33\xbe\xd7\x84\xae\x6c\xaf\x2b\x4d\x3f\x9f\xc5\xd4\xdf\x08\x32\xac\x99\xdb\xdf\x04", 79, { 0xb0, 0xc7, 0xe4, 0x19, 0x13, 0x5d, 0x32, 0x5b, 0x90, 0x39, 0x3c, 0x85, 0x8c, 0xd8, 0x61, 0xfd } }, +{ "\xd3\x8d\xcb\x12\x2a\x27\x37\x78\x2a\x79\xea\xc1\xa9\x6e\x1e\x0a\xc0\x7b\x0a\xbd\x67\x31\x0d\x79\xac\xf3\x74\x0e\x90\xc1\xe8\xa4\x7e\x32\x77\xfb\x69\x80\x3d\xcc\x81\xbd\xae\x4f\x91\x24\x83\xd6\xf8\x8b\x3f\x96\x41\xf4\x5d\x86\x62\x42\x18\x61\x8e\x08\xd6\xc5\xb7\x7d\x32\x7d\xa3\x8c\xa5\xdc\xaa\x08\xd0\x40\x0a\xfd\x68\xb6", 80, { 0x6a, 0xa7, 0xac, 0x63, 0x95, 0x32, 0x9d, 0xb9, 0x93, 0x8b, 0x41, 0xfe, 0xd5, 0x77, 0x03, 0x84 } }, +{ "\xe6\x21\xbe\xbc\xe1\x6a\xea\x21\x53\xb9\x93\x09\x27\xb4\x5e\x0d\x51\xb1\xf1\x7f\xee\xcd\xa3\xcb\xf9\x1d\xc2\xf8\xa7\xfc\x80\x4e\x61\x84\x7a\x12\x5c\x18\xe6\x6d\xd6\x1d\x59\x6b\xee\xc8\x33\x1e\x20\x12\xa8\xe3\x5d\xc9\x6b\xbc\xc3\xc0\xf9\xdd\xfe\x27\x7f\x42\x3a\xf5\x68\x7d\xc4\x81\x87\x8e\x3c\x30\xde\xea\x79\x49\x09\x9e\xf9", 81, { 0xa4, 0x46, 0x74, 0x55, 0xda, 0x5c, 0x22, 0x46, 0xf2, 0xb8, 0xd1, 0x7a, 0x5e, 0xa9, 0x22, 0x09 } }, +{ "\xe5\x4a\x8d\x03\x02\x32\xd5\x5c\xb6\xe8\x50\xa1\x80\x19\x36\x47\xba\x7c\xe0\x2d\x2a\x00\xa7\xdb\xb9\x95\xeb\x5a\x3b\x94\x30\xaf\x6c\xcc\x62\xf5\xfc\x2a\x39\x16\xc1\x04\xb7\x26\x0c\x02\xcf\x5c\x16\xa9\x20\xad\x98\x85\xde\x07\x79\xf3\xd2\x27\xa2\x88\x78\x17\xee\x22\x46\x48\x3d\x89\x0c\x47\xa7\xc1\x76\x1f\xce\xee\xaf\x4c\x4d\xe4", 82, { 0x67, 0x67, 0xb5, 0x70, 0xa1, 0xd2, 0x3b, 0x5c, 0xb5, 0xea, 0xb7, 0xf3, 0x39, 0xa9, 0xef, 0xf7 } }, +{ "\x20\x57\x4d\x4b\x56\x13\x36\x6b\x02\x72\x81\x9a\x19\x04\xac\x3f\x1c\x0e\x47\x82\x72\x43\x2c\x92\xf1\x22\xcc\x92\x7b\xeb\xa3\x21\xc5\x3f\xcd\x84\x33\x53\xb3\x73\xdf\xd0\xdd\x7d\xb9\x4b\xec\x18\xc8\x5c\x9f\x49\x8f\x5d\x12\xec\x8a\xc1\x08\xa1\xd7\x0e\x5d\x53\xf2\x78\x9e\x66\x99\x1c\xb4\x7c\xce\xd5\xbb\xe4\xfb\xbf\xf0\xa1\x2f\x46\xc9", 83, { 0xb9, 0x7f, 0x77, 0xa3, 0xd3, 0x37, 0x5f, 0x32, 0xbd, 0x36, 0x3b, 0x21, 0xb8, 0xd0, 0x42, 0xef } }, +{ "\x12\x87\xe9\x1f\x42\xa8\x91\x87\xce\x68\x88\xbe\x6f\x8c\x18\x42\x24\xac\xc1\xfd\xfd\x33\x15\x1c\x85\x83\x34\xff\xcd\x35\xe0\x49\x11\x7e\x3c\x16\x0a\xad\x26\x4c\xcf\xd0\x2d\x0b\x69\x76\x31\x3e\xf2\x90\x96\x53\x68\x71\x24\x07\x13\xf5\x7f\x5a\x91\xbd\x3e\xa2\x7b\x98\xa9\xbc\xb6\xfd\x14\x5d\x58\xb4\xd2\x86\x34\x95\xd8\x16\x04\x69\xf0\x79", 84, { 0x1d, 0x33, 0x53, 0x15, 0xa2, 0x3a, 0x5b, 0x3d, 0x37, 0x92, 0x65, 0xc7, 0x04, 0xb6, 0x7a, 0xd8 } }, +{ "\x32\xed\x96\x7e\x43\xf4\x73\x47\xe0\xac\x73\x59\x83\xf9\x85\xd4\xba\xfd\xef\xbc\x1b\xb9\x4b\x75\xc5\xcd\x21\x4e\x8e\x5b\x22\x34\xce\x0a\xff\x87\xc7\x26\xe4\x09\xaf\xe5\x95\xf2\x5c\xc5\x23\x22\x8c\x10\x4a\x6e\xcd\x81\x6a\x1b\x0f\x01\x20\x69\xc4\x8a\x81\x46\xb1\x2d\xf3\x24\x55\x2e\xa7\xe4\xf2\x4d\xb6\xf1\x3c\x20\xd7\x6a\x9d\x9b\xbb\x77\x23", 85, { 0x2d, 0x58, 0x23, 0x43, 0xe5, 0xa1, 0xc3, 0x4b, 0x28, 0x16, 0x9e, 0x76, 0xb5, 0x07, 0xd4, 0x3a } }, +{ "\xb2\x05\xbd\x07\x15\xe9\xec\xdb\x1a\x60\x75\x4f\xb9\x05\x59\x9f\xb0\x90\x1d\x9d\xc7\xec\xda\x56\x2e\xf6\x70\x64\x02\xd4\xdb\xd0\xee\xf0\x9e\xa1\xee\x90\x5b\x06\x2f\x14\x84\x1b\x13\xcb\x2c\x5b\x50\x71\xf7\xa3\x38\x49\x30\xdf\x13\xd3\xf9\x53\xa8\x2b\x9d\x88\xdb\xfe\x02\xd1\x70\x29\x3a\x78\xed\xf0\x38\x8a\x9e\xd7\x9f\x3c\xb2\x20\xb6\xf9\x83\xe2", 86, { 0x88, 0xef, 0x98, 0xec, 0xda, 0x19, 0xbe, 0xbe, 0x17, 0xb8, 0xe4, 0x4d, 0xea, 0x79, 0xc2, 0x82 } }, +{ "\x78\x09\xf3\xc3\xc8\xdf\xf2\x52\xc2\xff\x1b\x03\x2d\x8a\x7e\xc8\x0c\x67\x79\x48\x54\x10\xbf\xbe\xb7\xf6\x7a\x71\x9f\x92\x8d\xcb\x36\x0a\xf2\x19\xa2\x7c\x43\xde\x4e\xe9\x54\xd4\x64\xc1\xfd\x80\x57\x07\xf5\x71\x9c\x20\xd9\x15\x78\x3e\x4d\x37\xf4\x64\x39\x19\xee\x15\x35\x29\x4a\x9d\xff\x64\x45\xfb\x29\x44\xe9\x69\xd0\x67\x9d\x8a\x86\xbe\xd4\x2f\x51", 87, { 0x5a, 0x35, 0x4a, 0x9b, 0x4a, 0x1f, 0x23, 0x3b, 0x70, 0x42, 0xbb, 0x52, 0x31, 0x27, 0xee, 0xee } }, +{ "\x6e\xe6\xc6\xcd\x46\xfb\x60\x6c\xdd\x23\x5d\xde\x48\x84\xb7\x8c\x76\xab\xe7\x3d\x28\x03\x77\xdb\x8f\x63\x26\x50\x83\xc1\xb1\x8b\x5e\x04\x44\x9f\x73\xf8\x7d\x0a\x2e\x5b\x19\x12\xca\x14\x3d\x4b\xa9\x83\x63\x36\x53\xf3\xdf\x04\x0d\x2c\x0d\x78\x15\x26\x19\xea\x79\xd7\x6b\x67\x91\x2d\xad\xf6\x1f\x18\x7a\xf6\x01\xbe\xa4\xa3\x90\xd2\x22\xb7\x99\xff\x95\x2c", 88, { 0xdd, 0x18, 0xb1, 0x72, 0xbb, 0x74, 0x5b, 0xfc, 0x9b, 0x3f, 0x66, 0xec, 0xc2, 0x0a, 0x43, 0xcc } }, +{ "\xf6\x7e\x75\x20\xc8\xc7\xdc\xd2\x52\x63\xef\xc9\x75\xe0\xe5\x14\xc4\xde\xb5\xac\x43\x47\x60\xf5\xc1\x9c\xd8\x63\xcf\x6a\x8c\x3a\x5c\xdb\x91\x6e\xee\x68\x6e\xa8\x7f\xac\x84\x6a\xf2\x54\x18\x49\x30\x33\xff\x59\xe4\x72\xe5\xa8\xcf\xe5\x39\xe0\xc8\x78\xb8\x10\x54\xc8\x95\x84\xde\xce\x42\xd0\x93\xb6\xde\xec\xdc\xce\x3b\x79\x79\x99\x8a\x22\x37\x04\xa6\x1d\x4d", 89, { 0x95, 0xd2, 0xf3, 0xfa, 0x24, 0xcf, 0xd0, 0x6d, 0xca, 0x74, 0x7b, 0x13, 0x05, 0x68, 0xcd, 0x51 } }, +{ "\xb0\xfa\xd1\x59\x6e\x0f\x92\xf2\xc9\xb5\x87\xe9\xbc\xcd\xad\x21\x84\xb2\xf4\x08\x90\x42\x87\xb1\x96\x8c\x29\x90\xbf\x18\xbb\xd1\x02\xcd\xda\x55\x8f\x83\xa5\x4a\x61\x26\x9c\x65\xf6\x83\xa4\xbf\x1b\xb2\x27\x49\xe0\x20\x58\xee\xac\x38\x94\x44\x69\xae\xe4\xed\xdf\x68\x9f\x90\x1f\x09\x2c\x6f\x15\x1a\xe5\xa6\x41\xd7\x18\xff\x7f\x94\x27\x74\x02\xca\xcf\x42\x5f\xc2", 90, { 0x1c, 0x07, 0x39, 0x77, 0xf3, 0x7e, 0xb5, 0x17, 0xb5, 0x1c, 0x09, 0x97, 0xbb, 0x47, 0x34, 0xe3 } }, +{ "\x85\xa6\xc5\xdd\xfc\x37\x4b\x7e\xc4\xdf\x62\x94\x0c\x77\x6a\xc7\x88\xfe\x60\x3e\x6d\x76\xb4\x0b\x99\x5c\x38\x34\xd1\xc2\x35\x5f\x22\x0a\x98\x19\x68\x41\x4a\xc3\xed\x15\x9d\x19\x29\x75\xe1\x60\xa8\xc4\x17\x2c\x09\xb9\xbd\xcb\x22\xd5\xc8\x51\x41\x82\xb0\x41\x8d\xc5\xa5\xd5\x8c\xa0\xdf\xeb\xbe\x07\x13\x8c\x66\x7c\x01\x19\x68\x49\x2a\x14\x4d\x5a\xa0\x88\x64\xb4\xf5", 91, { 0x6b, 0xcf, 0x3d, 0x4f, 0x7a, 0x79, 0xf2, 0x5e, 0xe8, 0xd1, 0xda, 0xe9, 0x5e, 0xb1, 0x9c, 0xc5 } }, +{ "\x17\x04\x96\x55\x9e\xec\x2a\xb0\x86\xcb\xe8\x0f\xaa\xdb\x88\x08\xe0\xa7\xa1\x4d\x26\xee\xe3\x5e\x6b\xa0\xee\x5f\xf7\x05\xcc\x04\x77\xfd\x12\xa8\xa9\x62\x8e\x7d\xa0\x89\xad\xde\xb4\xe8\x6c\xc1\x0a\xd1\xf9\x48\xbc\x5c\xe6\x76\xa4\x64\x08\xfe\xca\xa7\xf2\x37\x68\x11\x09\x2d\x96\x12\x44\xd1\x96\x2b\x83\x50\xbe\x89\x88\x80\xfe\xc8\x96\x77\x0d\xd8\xa4\x36\x35\xfd\x3e\x83", 92, { 0x0a, 0x40, 0xa5, 0x22, 0x7b, 0xe3, 0x34, 0x40, 0xb1, 0x02, 0xa4, 0xf4, 0x4a, 0x1d, 0x26, 0xcb } }, +{ "\xb7\xf0\xf9\xd4\xdc\x23\x91\x67\x99\x22\xa1\x6f\xdd\x15\xfd\x68\x7b\x62\xaf\x8c\xaf\x6f\x8d\x5e\x4f\x85\x74\x63\x8f\xd0\x23\xf0\x71\x83\xb6\x1f\xc7\x18\xbc\xdb\xe6\xb5\xf8\x1b\xe9\xaa\xb1\x2c\x9f\x17\xb6\x26\x12\xab\xf2\x80\xb5\x87\xa7\xc0\x29\x40\x4b\x4a\xac\x03\xfc\x5a\x1e\xd3\xa0\x0d\xb1\xef\x9d\x99\x2d\x4f\x32\x9e\xde\x4c\x70\x94\x1b\x5f\xd9\x63\x73\x01\x93\x11\x75", 93, { 0x83, 0x24, 0x5e, 0x67, 0xff, 0x3f, 0xf3, 0xac, 0x7f, 0x5d, 0x83, 0xda, 0x0f, 0x0f, 0x3b, 0x66 } }, +{ "\xb2\x49\x95\x1c\x16\x9f\xcb\xd5\x39\x4f\x81\x2f\xf3\xe5\xae\x1e\x67\x13\xc2\xec\xa5\xb2\x19\xbd\x70\x56\x89\xbd\x19\x8c\x1a\xe8\x8a\xb2\xd5\x75\x5f\x73\xb5\xe0\x2e\xdf\xba\x93\xe7\x23\x1d\x30\x57\xe9\x9e\x7e\xc7\x4f\xf9\xed\xc1\x7c\x77\xc7\xf2\xe5\xa0\xf5\x2b\x1b\x0e\x6c\x81\x4e\x5c\x32\x95\x62\x3e\x11\xee\xac\xab\xd6\x82\x49\x34\x46\x54\x1b\x78\x9f\x37\x61\xb0\xc6\xb0\xf2", 94, { 0xc1, 0xa1, 0x23, 0x7f, 0xf0, 0x11, 0x23, 0xcf, 0x64, 0xb1, 0x96, 0x5d, 0xb6, 0xb5, 0x34, 0xe0 } }, +{ "\x66\x12\xf9\x16\x43\xb3\x22\x01\x05\xc0\x53\xed\x8f\xdd\x2c\xd2\x1a\x85\x4d\xc5\x8a\xfa\xf1\xeb\xdb\xc6\xb5\x18\xba\xec\x77\x08\x30\xb0\x59\x38\x79\x00\xe5\x62\xf3\x7e\x4b\x94\x32\x2b\xc5\xec\x30\xb1\x1b\xf2\xa2\x4d\x42\x92\x65\x57\x20\xb4\x17\x6f\x6b\x7a\xc3\x46\xaf\x15\xb4\x06\x6e\x44\x6a\x5f\x61\x6b\xaa\x2f\xdd\x4c\xb0\xcd\x51\x64\x80\xf3\xec\xe4\x5b\x45\x5b\x4a\x4c\x82\xb0", 95, { 0x5c, 0xe8, 0x8d, 0x8c, 0xb0, 0x07, 0x9f, 0xc3, 0x82, 0x01, 0x92, 0x4f, 0x7d, 0xb2, 0x46, 0x76 } }, +{ "\x9c\xe1\x46\x5e\x41\xf7\x79\x61\x7c\xaf\x58\x7a\x85\x7d\x1e\x98\x46\x5f\x4e\x53\xaf\x2a\xa0\x91\xb6\xff\x86\x4b\xef\xdd\x59\x6a\xc3\x50\x25\xcb\x50\x48\x0d\x62\xdd\x04\x5d\x7a\xf8\x2d\x2a\x1a\x2e\xff\xa8\x83\x67\xa2\x08\xd7\xdb\x97\x0b\xd4\xb5\x4e\x28\xbd\x42\xd4\x56\x59\xd6\xa9\x77\x15\x3c\xb0\x61\x44\xd7\x3f\x89\x87\x59\x56\x4e\x48\x1f\xed\xe0\x60\x28\x66\xcb\xd9\xb1\x22\x24\xcd", 96, { 0x13, 0x2f, 0xc8, 0x0f, 0xaf, 0x52, 0x90, 0x3f, 0x45, 0x2f, 0x80, 0x39, 0xa5, 0x04, 0x8c, 0xd4 } }, +{ "\x6e\x2f\x4e\x6d\x66\x1f\x69\x1e\x6c\xf4\x59\xbd\x35\x37\x6e\x03\x1b\x28\xb5\x04\x6d\x0f\xda\xd1\x70\xb1\xb8\x3e\xf7\xde\x7f\xbe\x9a\x27\x81\x6a\x96\xae\x99\x20\x41\x16\x38\xc8\x28\x98\x0d\xb2\xc7\x37\x51\x1b\xe4\x0c\xac\xcf\x88\xbb\xc7\xe8\x9b\x06\x6f\xb4\x1b\x80\x62\xb5\xf8\x59\xba\xc2\x90\x58\xf3\x4a\xc2\xe8\x9b\xb8\xb1\x49\x95\xf3\x17\xe7\x09\xfd\x43\xc8\xec\xbb\xb0\x1e\x27\xd3\x44", 97, { 0xe5, 0x04, 0x88, 0xc9, 0xa8, 0x97, 0xde, 0x0f, 0xc3, 0x2b, 0xee, 0x13, 0xc6, 0x06, 0x7c, 0x2d } }, +{ "\xfc\x66\xb1\x22\x26\x80\xa5\x2c\x01\x7e\x26\x18\xa9\x4a\x3a\x2d\x21\xf6\xed\x9b\xa5\xa5\xfe\x75\x1c\x1a\x9a\x4c\xa9\xdb\x40\x69\x61\x01\xc3\xa6\x17\x9f\x6e\xe9\x52\xcd\x41\x3e\x60\x50\x5a\x91\x84\xe7\x6f\x05\x4a\x34\x78\xf3\xfc\x46\x69\x82\x2d\xbf\x1d\xdf\x72\xa7\x4e\x19\x30\xcc\xc1\x9c\x91\xd3\x7f\x48\x91\xe0\x3d\x2e\x34\xdd\xdd\xe7\xda\x6b\x0d\x90\xaa\x63\x0e\x65\x2c\x07\x8f\xf9\xf3\xcb", 98, { 0xf8, 0x09, 0xb6, 0x5e, 0xb8, 0xfb, 0xde, 0x39, 0xd6, 0xfe, 0x1c, 0xd8, 0x44, 0x48, 0x7f, 0x01 } }, +{ "\xb7\x0f\x77\xb9\x42\x19\x01\x85\xc3\x4a\xbf\x2d\x07\x5a\xf7\x4c\x9a\xd6\x59\xfd\x63\x21\x6d\x66\x6a\x0b\x2b\xe8\xba\x0b\xa9\xe1\x62\x1c\xef\x1c\x95\x32\xe6\xd6\xf1\x58\x6f\x6e\xdd\x68\x91\xa8\x0b\x66\xca\x9d\x1d\x79\x86\x43\x64\x86\xad\x95\xc3\x6a\x57\x5f\xb2\xd4\x9b\xa8\x5e\xbe\x85\xbb\xee\x86\x25\xd4\xe1\xad\xc4\x64\x93\x2b\x32\x01\xde\x6c\x3b\xed\xdd\xeb\x38\x41\xcc\x6a\xc1\xb7\x0b\xcb\x80", 99, { 0x4e, 0x3f, 0xa9, 0x33, 0xaf, 0x6e, 0x3a, 0xac, 0xc0, 0x29, 0x88, 0x8f, 0x91, 0x86, 0xc9, 0x7c } }, +{ "\x11\x42\x8e\x21\x28\x9e\xe8\x65\x94\x38\x7c\x56\xf5\x97\xb8\x95\xdc\x4c\xcf\xcf\x5a\xbc\x4e\x4e\x22\xfa\x5d\xab\x5d\xd2\x95\xa2\x0b\xe3\x78\xfe\x10\xe4\x91\xb3\xe3\x07\x29\x0a\xce\x7a\xa3\xf7\xe2\x0a\x75\x86\x7b\xe2\xc3\x74\x6c\x72\x9a\xda\xc6\x6b\xc5\x04\x4a\xe6\x50\x60\x69\xa4\x97\x92\xf3\x70\x09\xa4\x64\xa1\x7f\x5b\xc8\xbc\x33\xa5\x47\x36\x5e\x2e\x51\x56\x72\x11\x66\x39\xf1\xab\x82\xef\xe8\x8c", 100, { 0xbe, 0x63, 0xc5, 0x40, 0x5e, 0x75, 0x2c, 0x1d, 0x52, 0xb3, 0x28, 0x39, 0x09, 0x05, 0x7b, 0x4d } }, +{ "\x24\xc3\x0c\x87\xfa\x99\x6f\xe9\x2b\x6f\xdf\xc6\x40\x06\xdc\x6f\xb0\x9a\x33\xff\x06\xcc\x3b\x15\xb1\xa1\xab\x9c\x68\xa3\x17\xc5\x38\x25\x05\x16\x2b\xa4\xb0\x9c\x97\x49\x58\x3c\x00\x8c\x44\x28\xab\xf2\x56\x6d\xc0\xf6\x49\xa8\x1a\x06\x89\xd8\xaf\xa4\xae\x4f\x97\xad\x97\xc3\xba\xb7\x1f\x81\x1b\x93\x7f\xc1\xbb\xf1\x40\x14\x2b\x23\xda\xfa\xb2\xfa\xee\x90\x16\xcd\x1d\x66\x0b\x98\x83\x6f\x35\x40\xd4\x11\xdc", 101, { 0xd6, 0x38, 0x85, 0xcf, 0x1e, 0xaf, 0x84, 0xf1, 0x6a, 0x8f, 0x77, 0xc8, 0xab, 0x9e, 0x1a, 0x64 } }, +{ "\xf4\x11\x5d\x2b\xb0\xe6\x59\x25\xdb\xa3\x78\x25\x10\xd5\x2b\x10\xfa\x81\x90\x19\x59\xfc\x49\x30\x21\x6a\x68\x08\xc1\xd1\x86\xc3\x81\xd9\xf3\x3d\x04\x22\x07\xf2\xed\x42\x97\x8d\x9e\x59\x83\x0e\x1c\x53\x6d\x96\x0f\xba\x84\xd2\xe5\x36\x7e\x02\x15\xa2\xa4\xa5\x81\xcb\x07\xc3\xf4\xc7\xd0\xd6\xcb\xf0\xb5\x56\xb1\x7c\x88\xe0\x83\xba\xe9\x02\x52\xeb\x1c\xa5\x86\xbb\xf5\x18\x1f\x5a\xf0\xb5\x17\x3c\x5d\x32\xe4\x69", 102, { 0x7b, 0xe8, 0xa1, 0x02, 0xa6, 0x52, 0xe9, 0x3b, 0x9d, 0xb4, 0xbc, 0x95, 0xba, 0x9e, 0xd1, 0x07 } }, +{ "\xb8\x86\x19\x81\x17\x75\x2c\x50\xbc\xba\x52\x0a\xca\xd0\x87\x23\x15\x5e\xaa\xcd\x12\x3d\xc4\x0f\xed\x27\x69\x7f\xba\xfd\x37\x9c\xc3\xb4\x7b\xca\xff\xde\xf4\xea\xa4\xd1\xaf\x95\xd4\x76\x11\xf6\x72\xb0\xf3\x41\x18\x66\xe7\xd4\x21\x2f\x9a\xe8\xe1\x99\x52\xf4\xf4\x16\x96\x9e\xb4\x84\xec\x5e\xc4\x57\xbd\xb2\xc9\x66\x55\xf8\x39\x4e\x07\xeb\x4b\x87\x6d\xbc\x0e\x01\xcd\xcc\x96\x7a\x98\x04\x50\x5f\x0c\xd2\x77\x5c\xf9", 103, { 0x60, 0xd0, 0x9d, 0x98, 0xae, 0xef, 0x2b, 0x51, 0xa0, 0x3c, 0x5d, 0x3c, 0x71, 0xa6, 0x4a, 0x5b } }, +{ "\xc0\x9f\x82\xa0\xb2\x6f\x14\xb6\xbc\x6c\xee\x89\x9e\xf0\x93\x3a\xdd\x39\xd1\x28\x7f\x9d\x13\x6d\x62\xdb\x43\x82\x39\x8e\x5a\xfe\x24\xbb\x85\x7b\xeb\x89\xf5\x99\xd8\x10\x44\x1c\x2e\x49\x7f\x31\x49\x26\xd4\xce\x53\xbb\xd9\x37\xa0\x99\x76\x9c\xa7\x3c\x71\xdf\x9e\x9a\x94\x74\xb1\xdb\x7d\x62\xde\x28\x02\x66\x70\x9d\x3e\x36\x15\x58\x3d\xe3\x9e\xb3\x40\x57\x54\x8e\xad\xfe\xf1\xc5\x96\x82\x42\xc1\xe4\xae\x57\x2a\x20\x74", 104, { 0x1a, 0xe2, 0xe9, 0xa9, 0xb1, 0xf0, 0x27, 0x90, 0x7d, 0xf3, 0x66, 0x14, 0x07, 0xe0, 0xe9, 0xdc } }, +{ "\x63\xba\xdd\x0a\x37\x2d\xc6\x2e\x56\x54\x40\x8b\xb4\x49\xbb\x34\x10\xbd\x9a\x4d\xeb\x6d\xbc\xc8\x23\xb4\xa7\x4d\x31\x39\x51\x33\xfc\xc8\x8a\xab\x57\x3f\x09\xfd\x1e\x9f\x11\xea\xe8\x42\xbf\x2f\x69\x2b\xf3\x2b\x67\x79\xd9\x98\x57\xf6\x13\x75\x94\xcc\x85\x04\x3b\x57\xbc\xef\xa5\x16\xfb\x86\x82\xba\xe4\x23\x8e\x61\xc0\xaf\xf3\xdc\x6b\x3d\x3b\x2c\xdf\xd4\xf0\x0c\x5b\x4a\xd3\xa8\x2f\x4b\xb5\x6b\x27\x79\xf5\xf6\x91\xae\x96", 105, { 0x0c, 0x2a, 0x47, 0x52, 0xba, 0xb6, 0xca, 0x3e, 0xb2, 0x6e, 0x64, 0x53, 0x9f, 0x3d, 0x3f, 0xf2 } }, +{ "\x2c\xed\x5c\xfb\x6a\x31\x16\x42\xd4\xb6\x27\x3b\xcb\xc2\x60\x04\x7a\xb3\xf0\x42\x90\xc4\x6b\xfe\x08\x7f\xed\x19\x23\xbf\x58\x6d\x78\x61\xb8\x82\x21\x87\xc8\xea\x17\x88\x8e\x3a\x98\x77\x21\xa5\xc4\x4f\x8b\x36\x48\xb8\xc9\xaa\x31\x78\xef\xe7\xe2\x79\x68\x1d\x21\x72\x5b\x78\x4b\x35\x2a\x7f\xa8\x95\x14\x0c\xd9\xf2\xfa\xe8\x6e\x63\x3f\x02\x94\x7e\xc8\x4c\xeb\xc7\x23\x33\x76\xb2\xc4\xb9\xac\x56\x6a\x30\xab\xb1\xa0\x95\x8c\x92", 106, { 0x73, 0x8a, 0xe1, 0x0f, 0xcf, 0x84, 0x6e, 0xf5, 0x84, 0xab, 0x8b, 0x58, 0xd5, 0x1b, 0xc8, 0x95 } }, +{ "\x5f\x86\xd1\x27\xd0\xe1\xfb\x23\x30\xfb\x39\x8b\xcd\x7a\x3a\x1e\x2d\xd0\x23\x5f\x4d\x54\x9d\x40\x07\xfe\x05\x6d\x8d\xbf\xc7\x32\x11\x7b\xc5\x09\x87\xa4\xf0\xc4\x82\x74\xfa\x53\x3b\xc7\x22\x33\xb1\x92\x2e\x74\xea\x04\x77\x64\x57\x37\x1e\xdd\x55\x93\x5c\x28\xd0\xc0\xf8\x8d\x02\x45\xd1\x79\x59\xc2\x9b\x49\x77\xc6\xa7\xb9\x53\x4e\xda\xe4\x7c\xdb\xbf\xf7\x7e\x2e\xb9\x76\x5d\xa3\x51\x2a\x3e\x28\xae\xa6\x26\xd8\x22\x75\xd9\x38\xe0", 107, { 0x4e, 0x61, 0xed, 0x55, 0xbd, 0x31, 0x31, 0x6f, 0xa6, 0xa6, 0x8f, 0xde, 0x2b, 0x8f, 0x51, 0x60 } }, +{ "\xe3\xe4\x0c\xcc\x64\xb7\xd7\x6b\xa4\xea\xee\xfa\x2b\xa0\x38\x9a\xac\x09\x84\xa8\xeb\x01\x87\x2b\x4a\xd6\x71\x67\xee\x27\x2a\x8e\x92\xe7\x2e\x96\xe8\x81\x02\x26\xa7\x16\x51\xa9\x36\xe1\xa8\x85\xf3\xbc\xcb\x66\x20\xbb\xb2\xb4\x6a\xf6\x23\x23\x18\x65\xed\x68\xcd\xe3\xbe\x09\xf9\x55\xa2\x4d\xe2\xe4\x18\x53\x4b\x66\xd3\x3f\xbe\xda\x0a\x8f\x7b\x12\x7c\x8b\xfd\x6b\x04\xdb\x25\xb8\xd4\x33\x06\x3d\x51\x29\x4c\xd7\x8b\x26\x49\x39\x57\x7b", 108, { 0x35, 0x50, 0xf9, 0xfe, 0xb2, 0x42, 0x8e, 0x9b, 0x20, 0x2d, 0x1f, 0xd7, 0x1b, 0x32, 0x8a, 0x93 } }, +{ "\x9d\x51\x0b\x8b\x82\xc9\xd6\x26\xb2\xa9\xb9\xf7\xf5\x19\x26\x13\x4a\x44\x33\xb1\xb1\x59\x7b\xf9\x93\xab\x92\xf5\xcf\xf8\x22\xa4\x63\xc7\xa7\x2d\xb2\xea\xc3\x31\x77\x23\x3e\x39\x47\xe3\x9e\x4e\xbc\x2e\x5f\xa8\x44\x9a\xd0\x7e\x84\x75\x8a\xfc\x6a\x06\x8d\x53\xce\xec\xf8\xea\xc4\xa4\x65\xb2\x80\x26\xdf\x97\xe6\xae\x81\x12\xae\x98\xac\xdb\x31\x64\xe4\xbc\xd2\xda\x47\x81\x0b\x47\xac\x0c\x13\xe5\x54\x85\x29\x58\x4f\xae\x80\x55\x6f\x54\xc7", 109, { 0x3a, 0xf8, 0x64, 0x70, 0xe9, 0x73, 0x58, 0x6b, 0x98, 0xb5, 0xdd, 0xbd, 0xfc, 0x56, 0x38, 0xc1 } }, +{ "\x5d\xe1\xe1\x54\xa7\x6d\x0f\xec\x1c\x4a\xb7\x31\x7c\x9e\xc7\xa9\x9e\x92\x52\x67\xd4\x0f\xc2\x58\x6d\x17\x28\x2c\x54\xc2\xb4\xde\xd5\xd3\x40\xe2\x80\xf6\x06\xeb\x26\x98\x73\x56\x00\x63\x13\x36\xf0\x55\xab\xfc\xdf\x7c\x65\xc3\x45\x50\x26\x36\xc6\xac\xfc\x1f\xfa\x6b\xb3\x8c\x45\x9b\x86\xa0\xe5\x61\xf3\xf3\x0b\x69\xa7\xa7\x20\x07\x99\x08\x28\xef\x33\xdf\x44\x8d\xaa\x54\x51\x02\x6f\x7d\xae\xbc\xbd\x87\x1c\xb1\x53\x7f\xbe\x38\x3c\xbe\x3f\x84", 110, { 0x96, 0x3d, 0x85, 0x1f, 0xc8, 0xcf, 0x7e, 0x10, 0xe1, 0x2c, 0x33, 0xe0, 0x8a, 0x3b, 0x50, 0x98 } }, +{ "\xc9\xef\x12\xbd\xa1\xbe\xd5\xbd\xef\x1f\xcf\x64\xb9\x38\x98\x98\x51\xec\xd8\xdc\xe4\x05\x27\x8c\x2f\xfd\x14\xb2\x52\x69\x41\x89\xbd\x03\xac\x8c\x47\x52\x08\x39\x5d\xf8\x49\x67\x57\x98\x3f\x41\xe6\x62\x5a\xde\xaa\x3c\x8c\x7e\xe0\x8e\x4c\x64\x39\xaa\xb6\x4b\xc5\xd7\xcf\x86\x0e\xf9\xe7\xb7\x42\xde\x17\x2b\x87\x27\xea\xd1\x73\xd1\x18\xd5\x94\x5f\x6d\xde\x29\xa6\xc9\xe0\xf4\x34\x40\x9e\x27\x5e\x61\xc0\x7b\xe5\x94\x8c\x60\x44\x9d\x44\x4f\x99\x3d", 111, { 0x50, 0x81, 0x50, 0xba, 0x15, 0x74, 0xa5, 0xf8, 0x00, 0x23, 0x1f, 0xe5, 0xf0, 0x1a, 0xef, 0x6f } }, +{ "\x1c\x3b\x2d\xf7\xd7\x25\xa2\xf0\xfd\xcf\xb8\xf0\xbb\x88\xbc\x85\x57\x26\x8d\x46\x4e\x12\x4c\x35\x0b\x7d\xa0\x3e\x46\xb1\xa2\xdc\xf8\x82\x6c\xdb\xf6\xe3\x39\x38\x31\x95\x39\x24\x89\xf9\xf4\x27\x49\x07\x58\x62\x43\x57\x61\xed\x89\x5d\x63\x5e\xc5\xb2\xf7\x6b\x36\x8d\x80\xa7\x48\x50\x59\x68\xce\x3e\x9d\xca\xde\x4b\x92\xcc\x49\x0c\xb2\x97\xb5\xce\x58\xdf\x59\xc2\x04\x62\x55\x56\x4b\x8e\xac\x9e\x5e\x40\xdf\xf1\x34\xa6\x27\x91\x57\x45\x4e\x82\x48\x16", 112, { 0x24, 0xfa, 0x3a, 0xa0, 0x34, 0xeb, 0x16, 0x59, 0xd6, 0x98, 0xf1, 0x66, 0xad, 0xfb, 0xf7, 0x93 } }, +{ "\x2a\x7b\x90\xcc\xb7\xfa\x65\x31\xd0\x72\xf5\xae\x8a\xa0\x51\xe9\x2d\xfc\xf9\x89\xd0\x4a\x00\x15\x90\x4f\xdc\xfa\x6c\xa1\xcc\xab\xc0\x98\xe6\xe3\x5c\x61\xbc\x06\x41\x30\xaa\xa5\xf7\x95\xbf\x20\x8e\xe8\x46\x66\x2f\xdf\xf0\xd9\x5d\x3e\x9f\x4c\xce\xad\xd1\x2e\xe0\xa5\xa7\xc0\xba\x84\x91\x82\x00\xc1\x99\xac\x32\x39\x48\xd8\xa2\xa8\x38\xbd\x10\x33\x38\x15\xe3\x21\x15\xa0\x06\xaa\x0b\x42\x5d\xe8\xc8\x48\xe3\xea\x19\xc8\x62\xe8\x34\x26\xcd\x90\xa1\xb3\x3d", 113, { 0xa1, 0xc5, 0xd1, 0x2c, 0x14, 0xcf, 0xb3, 0xd5, 0x90, 0xa0, 0xe8, 0x8d, 0xef, 0x19, 0xa2, 0xdc } }, +{ "\x7f\xc5\x6f\x87\xcb\x0c\xef\x76\xbd\xb2\x5a\xaa\x9c\x2f\x8d\x0c\xa4\x3d\x5f\xec\x16\x87\xfe\xba\x69\xef\x78\x5e\x9e\x7c\x56\x34\xb1\xdf\x63\xa7\x2b\xa0\x8a\x69\xd4\xea\xdd\x4c\x86\xef\xb2\xc0\x1d\xf9\xe8\xea\x8b\x0f\x47\x5d\x08\x40\x05\x77\x66\x8f\x65\x5a\x82\x7a\x7a\x86\xd7\x29\x0a\x10\x2c\x30\x8d\x81\x6e\x01\x55\x4e\x98\xf1\xc7\xef\xce\xe5\xc7\x9e\x8a\x99\x32\xad\xed\x8c\x85\x84\x37\x8c\x9b\x36\x52\xd9\x93\xc0\x89\xf9\xd0\xdd\x56\x18\x19\x89\x58\x19", 114, { 0x65, 0x16, 0xd9, 0xfd, 0x97, 0x36, 0x97, 0x2c, 0x1d, 0x90, 0xe6, 0xb9, 0x11, 0x75, 0x7e, 0xd1 } }, +{ "\xe1\x10\x63\x3d\xa2\xd1\xb2\x6e\x62\x94\x37\x29\x58\x85\x13\x06\xa7\xcd\x21\xe6\x49\xcc\xad\xb8\x07\xf4\x43\xe7\xa4\x45\xa1\x64\x1a\x61\xce\x4b\xfc\x4b\x44\x35\xfa\xc0\x48\x19\x83\x32\x5b\xdf\x85\x5d\xc8\x83\x50\x88\x5e\xe2\x98\x5a\x38\x25\x99\x57\xb8\xc7\x55\xf5\x92\x44\xf9\x5f\x04\x5f\x5e\xc5\x24\x10\xab\x5e\x51\x09\x17\xfb\xcb\xe4\xcc\x49\x5f\xeb\xe7\xa3\x3b\x83\x9c\x92\xe0\x35\x77\xe2\x34\x5a\xbd\x62\xb7\x63\xf1\x37\xce\xc3\x72\xdd\x3b\x79\x41\xbc\xae", 115, { 0xdd, 0xa6, 0xd8, 0x85, 0x1a, 0x69, 0x15, 0x50, 0xbb, 0x0b, 0x98, 0x6a, 0x04, 0x95, 0x94, 0x7b } }, +{ "\x3d\xe1\x62\x74\x46\x57\x63\x4e\xb6\x51\xca\x5d\xa3\x63\x3b\x38\xc3\x6c\xa7\x20\xb3\x17\xaa\x4b\xe4\x7d\x84\x5c\x23\xe8\xb2\xf4\xc3\xb3\x28\x62\x68\x4d\x2e\x76\x73\x5c\xd4\x73\x05\xfe\x13\x22\xb2\x2a\x82\x03\xc4\x35\xb1\x9f\x29\x71\x26\xf9\xfa\xf0\xf2\x22\xa8\x66\xee\xec\xc5\x2c\x97\xb6\x6d\x61\x83\x67\x4f\x2b\x80\x76\x5b\x1b\x48\x25\x0a\xaf\xe2\xcd\x45\xf0\x97\x55\xf3\x3c\x8f\xbc\x22\x1e\x09\xd6\xd1\x59\x34\x14\x57\x04\xac\x7b\x74\xcf\x94\xb7\xf3\x63\x4c\x49", 116, { 0xc8, 0x45, 0x92, 0xb3, 0xa3, 0xee, 0xed, 0x4c, 0x7d, 0xad, 0x54, 0x75, 0xbd, 0x5e, 0xc8, 0x88 } }, +{ "\xf8\xe8\xcf\xdb\xec\xa0\xac\xb4\x01\xb0\x9f\x46\x64\xff\xcc\xe5\xff\x37\x97\x92\xe7\xe9\x22\xf6\x69\xcd\x64\x6a\xac\x27\xe3\x33\x03\x44\x0e\xcb\xd2\x23\x39\x5a\x19\x31\x35\x44\xa2\x2d\x8b\xdb\xc3\x2b\x55\x35\xd1\xb4\xba\x19\x21\x0a\x04\x13\xbc\x89\x60\xa7\x9e\x28\x31\xa2\xab\x1f\x10\x8c\x2f\xa3\x65\x39\x10\xcd\x9b\x7e\x93\x99\x03\x01\xc7\x09\x47\x2a\x92\x69\x88\x36\x56\xae\x17\x6a\x3f\xf8\xcd\x64\x2b\x37\x08\x8c\x37\xe9\x42\xaa\xe2\x01\x4f\x92\xe1\xe3\x33\xfa\x7f", 117, { 0xce, 0x59, 0x2a, 0x66, 0xbd, 0x8e, 0xcc, 0x02, 0x56, 0xa9, 0xb2, 0x02, 0x08, 0x00, 0x60, 0xf2 } }, +{ "\x8c\x9d\x6c\xad\xcf\x04\x56\xad\xba\x5d\x3f\x57\x17\x76\x14\x07\x0e\xf2\xa1\x24\xe8\xe1\x1b\x4d\xee\xfb\xd9\x21\x70\x7a\x23\xab\xe1\x91\x23\x69\x20\x8c\xf9\xf8\xd2\x85\xea\x5d\xea\xc0\xb8\xf2\x4a\xa4\x0c\xeb\x83\x57\x10\x84\xb9\xf4\x19\xc9\xa2\x6c\x82\x01\xad\xf6\x94\xb8\x3f\x34\xa1\x68\x18\xe4\x30\xc3\xd4\x3f\x52\xa0\x8e\xf2\x13\x7f\x9f\xb6\x0c\xba\x84\x8e\x15\x4b\xdd\x9c\x19\x34\x92\xa1\x02\x8f\x10\x10\xd2\x32\xb1\xcd\xd3\xfe\x3a\x87\xe7\xc5\x7e\xae\xf9\xd5\x1f\x13", 118, { 0x21, 0xc8, 0x1d, 0xc6, 0x45, 0xbe, 0xfc, 0x87, 0x21, 0x04, 0xc5, 0xc2, 0x14, 0x3b, 0x40, 0x91 } }, +{ "\x94\x25\x74\x1c\x92\x1b\x86\xa0\xec\xf8\x35\x65\xb1\xe1\x78\x33\x12\x8b\xc2\x94\x9a\x81\x7f\x2b\x7a\x15\xbd\xaf\x02\xe1\xe8\x82\x2c\xf9\xae\xf2\x53\xaf\x01\x0b\x01\x01\x3b\x16\xe5\xa3\x5b\xb3\xe3\xa5\x6d\x8e\x46\xc2\x08\xc1\x11\x44\xf1\xc6\x73\x96\xdd\x17\x58\x68\x54\x64\x1c\x79\xb1\x70\x5a\x04\x46\x89\xe3\xc9\x9c\xa2\xcb\xb6\xd8\x0e\x9d\x32\x39\xdb\xae\x07\xbd\xc9\x8f\xe9\xe3\xe6\x9c\xa7\x8c\xc7\xb1\xed\xfb\x65\xfc\xb3\xfb\x91\xee\x46\x20\x15\x4b\xf1\x25\x69\x62\x48\x74", 119, { 0xc1, 0x1f, 0x44, 0xbf, 0x5d, 0x95, 0xee, 0x5f, 0x2e, 0x4f, 0xef, 0x28, 0x62, 0xf6, 0xe7, 0x5c } }, +{ "\x0f\x56\x10\xc5\x8c\x9a\xce\xde\x03\x7b\xeb\x78\x6f\xd7\x81\x42\x7c\xeb\xc4\xff\x03\x4a\x0f\xca\x20\xea\x8a\x7a\xf2\x59\x76\x20\xef\x0d\x15\xad\xe1\xd8\x39\xb1\x81\x7a\x67\x3e\xae\x50\xa6\xeb\x4a\x2b\xea\xf4\xb2\x3c\x18\x7f\xd8\x2b\xb6\xf9\xfe\x46\x31\x9f\x10\xd6\xc9\x19\x9f\x8e\x1d\x40\x76\x1d\x4e\x00\xdb\xe3\xd3\x59\x63\xbf\xd9\x7f\x72\x07\x55\x22\x4f\x91\xa7\xc8\xe0\xee\xec\x55\x06\xb7\xe0\xad\x97\xff\x6e\x70\xf4\xe8\xd7\xe4\x47\x51\x7a\xf1\x5c\xad\x45\x45\x18\xef\xb9\x98", 120, { 0xf6, 0x28, 0x50, 0x22, 0xdd, 0x55, 0xfc, 0xba, 0xb4, 0x4c, 0xc4, 0x1f, 0xa7, 0x92, 0x8a, 0x03 } }, +{ "\x9a\xa1\x93\x09\xec\x14\x1c\xa7\x65\xb2\x0f\x0d\x9f\x6f\x22\x25\x11\x5e\x33\x0d\x48\x60\x10\x16\xc7\xf7\xe3\xe9\x77\x38\x38\xc4\xcc\xdf\xad\xe2\x77\x7c\x35\xf9\xc1\xcc\x08\xdd\x8b\x23\x2b\x42\xdf\x04\x97\x9e\x32\xd3\x09\x2d\x38\xa1\x65\x0e\x64\x27\xc8\x8b\xfb\xcf\x29\x76\xd4\xeb\xaa\xae\xae\x08\x81\xc1\x2e\x5d\x7d\xab\x73\x5e\x38\xbd\x58\x6e\xd8\x99\x45\xb1\x81\x5a\xb2\xff\x5b\xd0\x3a\xf4\x3b\xe8\x57\x24\xf0\x2b\xc0\x6c\x2d\x5d\x5c\x64\x0e\x45\xe1\xf0\x48\x8d\x0e\xf6\xf2\xbf\x81", 121, { 0xec, 0x78, 0x08, 0x73, 0x5a, 0xc1, 0xb9, 0x65, 0xd2, 0xa0, 0x7c, 0x7c, 0xfb, 0x45, 0x7b, 0xb2 } }, +{ "\x29\xea\x6f\x36\x04\xe5\x78\x9c\xd3\x17\x5e\x55\xeb\x7b\xd3\x8b\xfa\xbf\x55\xea\x79\xd0\xf4\x3d\x3e\xfd\x31\xa8\x2d\xca\x02\x7f\x0f\x54\xf3\xc2\x7b\x5c\x66\x37\xf0\xf1\xfb\x22\x05\xbe\x0b\xa2\xb7\xee\x4d\xab\xe2\xb7\x9b\x9b\xcb\x8a\xcf\x7b\xda\xd5\xc7\xd5\x65\x73\x89\x2d\xa6\xb2\x7f\x1d\xcf\xfe\xe3\x10\x34\x2e\x36\x9b\xa7\x6b\xe9\x73\xe2\xb9\x1f\x0f\x1c\x23\x8a\xdb\xbe\x87\x72\x15\x2f\xfb\xd4\x48\xcc\xdb\xa7\x63\xf3\x71\x3a\x76\x3e\x3f\xb9\x08\xce\xeb\xce\x17\xbd\xc8\x63\xad\xb5\xfd", 122, { 0x41, 0x22, 0x16, 0xa5, 0xec, 0x77, 0xcc, 0x6c, 0x26, 0x63, 0x46, 0xa1, 0xf4, 0xe3, 0x94, 0x6e } }, +{ "\x86\x1b\x9f\x54\x66\xd5\x73\xa1\x7a\xe9\x2e\xcc\xc1\x1d\xe2\x7e\x24\xa5\xe7\x64\xf7\x7e\x2f\x23\x9e\x6a\xb7\xd8\x4c\x88\x1a\x4a\xe7\x8f\x40\xaf\x08\xa7\x33\x17\x1e\xe4\x12\x79\xb1\x60\x1e\x59\xc4\xf3\xf1\x12\x55\x91\xcf\xc5\xfe\x41\x15\xde\xbd\xb6\xce\x40\xd1\x8c\x65\x0d\xbb\x20\x74\x13\x64\x0c\xbb\xd6\x5d\x3e\x2c\x36\x40\xb3\x22\xbd\x36\xd5\xb2\x87\x93\x6f\x1a\xce\x9b\x49\x57\x12\x68\x65\xd2\xe1\xe3\xd4\x3a\x48\xef\x35\x6d\xd6\xa6\xcb\x8f\x49\xbb\x3a\x3d\xd8\xff\xde\xdc\x1c\xff\xc9\x0b", 123, { 0x09, 0xff, 0x3e, 0x2d, 0x99, 0x55, 0xc5, 0x1e, 0x17, 0xcc, 0xc1, 0xdd, 0x07, 0x11, 0x8a, 0x62 } }, +{ "\x9c\xca\x57\x37\xf3\xd0\x6e\x4c\xa0\xe5\x57\x89\x6a\x65\x34\x6c\x6e\x72\x1d\xcd\xc7\x59\xdb\x07\xd8\x13\x40\x50\x39\xe7\x21\x2a\x3b\x2d\xf2\xf2\x1a\x2d\xfc\x96\xbe\x25\x3d\x64\x2e\x69\xdc\xfd\x92\xa5\x47\x68\xe2\x3e\xeb\x43\x31\xd7\x8f\x14\x90\xf0\x4e\xbd\xa0\xa8\x2f\x0e\xb8\xa3\x62\x75\xae\x06\x1a\xd0\x46\x9f\x01\x63\x35\x22\x5d\xe5\xd0\x8e\xbd\xb5\x56\xaf\x5f\x2a\xd6\xbc\x22\x07\xbf\x20\x22\x0d\x02\x56\xf5\xab\xe6\xed\x81\xd1\x68\xab\x78\xe2\x4c\xce\x72\xc8\xc4\x6d\xa5\x21\xbc\xfe\x43\x97", 124, { 0xe3, 0xc6, 0x50, 0x53, 0x82, 0x8e, 0xf8, 0xd1, 0x42, 0x08, 0xdc, 0xf3, 0x3b, 0x60, 0x8d, 0xc7 } }, +{ "\xc0\xf1\x71\x4d\x8b\x79\xdf\x75\x2d\x6a\x08\xfe\xd7\x3d\x08\x6b\x46\x31\x15\xbf\xca\x8c\x9b\x94\xf2\x00\xf8\x4c\xd6\x28\xd1\x5e\x01\x31\x0f\xd2\xf9\x96\x7a\xc8\x6b\x03\xf0\x31\xf8\x5b\x41\xa1\x96\xd5\xaa\x3d\xa4\x41\xed\xcf\x8f\x69\x09\xf8\x1a\x92\x9b\x85\x4d\x22\xd1\xda\xfc\x5b\x07\x8a\xf2\x45\x00\x09\xbb\xaa\xc2\x79\x0b\x3b\x0e\xa0\xce\xd0\x7a\xfb\xcd\xcd\x2d\xeb\xfa\xa0\x37\x0e\x58\x66\x8a\xa9\x89\xad\x99\x41\xf5\x54\x8c\x49\x94\x8f\x1d\xf5\x59\x07\x12\x2d\x3c\x1e\x57\x9d\xe2\x50\xb7\xe9\xea", 125, { 0x8e, 0xb8, 0x75, 0x22, 0x66, 0x98, 0xd0, 0x80, 0x2d, 0xcc, 0x7a, 0x6e, 0x92, 0x96, 0x2e, 0xe8 } }, +{ "\xb5\x37\xfe\xd6\xa3\x0f\x84\x94\x70\x46\x6f\xa9\x55\xe9\xb5\xf9\x6e\xe7\x1a\x35\xdd\x8c\x26\xe1\x0f\x98\x38\x00\x16\xfc\xb5\x5f\x36\x30\x59\x7c\x7b\x33\xad\x11\x87\x20\x99\x40\x6a\x6a\x11\x5c\xaa\xb4\xeb\x51\x62\x50\xd1\xb2\x86\x51\x52\x5d\x44\x4e\x13\xcd\x86\xb6\x22\xfc\x94\xcb\x6b\xf3\xd7\x3d\x43\xef\xb8\x64\x22\x32\xa7\x18\x6e\x63\x38\x30\x72\xa2\x67\x96\x6d\x2c\xfc\x04\xc7\xa8\x0a\x5d\x5e\x0c\x91\xaa\xff\x2f\x43\xaf\xf1\xeb\x64\x29\xab\xee\xca\xa7\xa5\x1e\x04\x02\x4b\xa6\x97\x7b\x0e\xa2\x63\x6f", 126, { 0x97, 0xa7, 0x1a, 0x12, 0xd4, 0x55, 0xc2, 0x52, 0x09, 0xa9, 0x14, 0xbd, 0x78, 0x17, 0xf5, 0xd7 } }, +{ "\x95\x63\x25\xb9\x12\x5f\x16\xa4\xaf\xb8\xb0\x8b\x26\x67\x90\x10\x70\x05\x76\xf5\x95\x36\x6a\x9a\xa2\xb2\xfa\x13\xb9\xf1\x9e\xe5\x42\x73\x3c\x5e\x3f\xa9\xc6\x8e\xbe\x83\x01\xe5\x67\x97\x61\x6b\x35\xea\x11\x96\x42\x5f\x0e\xcb\xba\xba\x73\x74\xf2\x4f\xcf\xba\x91\x4b\xb2\xdf\xec\x9e\x47\x3b\x70\x84\x1b\xd2\x38\xaf\xfc\x8e\xbf\x13\xfc\x1d\xaf\x4d\x95\x69\xd8\xb1\xe6\xb0\x3c\xee\x1c\x41\x47\x60\xec\xd2\x1c\xf2\x3c\x80\x0a\xae\xe1\x63\x1d\xe3\x83\xcd\xd1\xf2\x9d\x20\xe2\xb5\xa1\x49\x3e\x8b\x38\xdd\x1c\x04\xa7", 127, { 0x94, 0x7d, 0x6b, 0x70, 0x52, 0xe6, 0x4a, 0xbd, 0xc1, 0x5b, 0xbc, 0x11, 0x26, 0x8c, 0x48, 0xb3 } }, +{ "\xce\x26\x26\x4d\xca\xd2\x5a\x49\x30\xcf\xf6\x38\xaf\x9a\x68\x1c\x7d\x2f\xfb\x58\x31\xdd\x49\xd7\x3e\x32\x3e\x4d\x0d\x16\xc4\x96\xb6\xf4\x10\x3a\x5a\x13\x89\x12\x1f\x03\x50\x04\xc9\x32\x70\xe9\xf2\x9e\xa4\x90\xe6\xa5\xbf\xdc\x1d\xf8\xbc\x08\x55\xae\x62\x0b\x4c\x75\x93\x16\x17\xe3\x32\x3b\x22\xea\xaf\x27\xc5\x6a\x31\x10\x7f\xe1\x5f\xaa\xd1\x3d\xca\x52\xb9\xd2\xfa\x4e\xc9\x67\x13\x2c\xe4\x6b\x23\x46\x95\x45\x0b\x67\x0c\xc9\x08\x88\xb6\xc6\xde\xb3\x78\xbc\xa0\x09\x87\xab\x1e\xdf\xe7\x06\xeb\x02\x7d\xc7\x09\x1b", 128, { 0x14, 0x39, 0x8a, 0x7a, 0x34, 0x95, 0xeb, 0x11, 0x5f, 0xf6, 0x04, 0x23, 0x14, 0xa9, 0xb1, 0x51 } }, +{ "\xd3\x9c\x34\x2e\x69\x3f\xc8\x3c\xb2\xe3\x4f\x09\xb2\xca\xab\xf8\x31\xf3\xdc\x12\x9c\xf1\x6f\x25\x79\xd7\x84\x09\x85\x50\x7a\xfe\x6d\xcb\x39\x31\x25\xd3\x1b\x5d\xe7\x7c\x78\x8e\xcb\xf9\xcc\x02\xff\x4b\x87\x28\xa4\x14\x72\xca\x46\x8a\xb9\x46\xf5\x87\x99\xf7\x04\xbc\xa6\xb4\x5e\x06\xb9\x6e\x80\xd9\x76\xfd\x16\xd8\x76\xf4\x36\x87\x15\xb0\x33\x18\xd9\x70\x1f\x61\x7d\x9e\xe1\xef\x9a\x2c\xee\x34\xf1\x1a\xa7\xdb\x57\x14\x4f\x3c\x3d\x37\xa8\xeb\xdb\xf4\x29\x6b\xf9\x0d\xdd\x00\x5a\xbd\xda\xa2\xc5\xf4\x5d\x0e\xb1\xc0\x7f", 129, { 0xa6, 0x03, 0x6e, 0x71, 0xb9, 0x65, 0xc3, 0x1c, 0xaa, 0x8e, 0x3b, 0xc0, 0xab, 0x74, 0x07, 0xf0 } }, +{ "\xf6\x8c\xc7\x96\x58\xa8\xf1\x2b\xec\xc3\x22\x93\xb6\x31\x25\x2c\xbc\xa8\xa4\x36\xd2\xa8\x53\x4b\x91\x85\x2d\x7c\x66\x12\xd7\x0a\xc6\xec\x20\xbe\x7f\x60\xaa\xe5\x2a\xfa\xa2\xec\xbd\xab\xaa\x93\x3d\x95\xd9\xd1\x90\x77\xd8\x45\x70\xb0\x2d\x54\x7c\xf1\x94\xe3\x68\x84\x89\xb2\x55\x33\xe3\x53\x3c\xd6\x9a\xc7\x83\x7d\xa9\xb4\xb2\x36\x0f\x44\x3f\x7b\xef\x9c\x85\x3b\xd7\xf7\xd3\x83\x1d\x5f\xa1\xc9\x65\x08\xde\xd5\x40\x49\x65\x4c\xef\x37\x8d\xdb\x45\xe0\xdf\xfc\xaa\x21\xe3\x68\x3b\x25\x13\x19\x0f\x7a\xf1\xfb\x95\xd1\x34\x2f", 130, { 0x93, 0xfb, 0xf2, 0x73, 0x89, 0x24, 0x2e, 0x2d, 0xf7, 0xf6, 0x94, 0x0b, 0xfe, 0x0f, 0xfc, 0x89 } }, +{ "\x19\x52\x1e\xfa\x65\x9a\xe9\x50\x84\x52\x5f\xf9\xa2\x6d\x89\x5e\x0f\xfd\x7f\xf3\x62\xb3\x5e\x40\xba\xf1\x58\x8d\x20\x8e\xe6\x29\x08\x25\x18\x57\xf7\x1a\x0c\xd6\x3e\x2b\x7d\x0c\xe4\xae\x73\xce\xa2\x6d\x18\xce\x07\x1a\xab\xa2\xbc\x70\x8d\x6d\xe2\xe9\x79\x2c\x97\x16\xd1\x9f\x98\x9e\x13\xd1\x00\xd5\x6a\x46\x2f\xf8\x61\xc1\xc6\x03\xb2\xaf\xce\x2f\x3d\x33\xf8\x0b\x14\xcf\xff\x36\xb3\xab\x2a\xb7\x4d\x86\xed\xf9\x41\x36\xaf\x66\xac\xdd\xa7\x9e\x18\xaa\xdf\x54\x51\x49\x5b\xc5\x58\xe9\x53\xd6\x71\xe7\x9b\xca\x57\x1c\x23\x9d\x90", 131, { 0xf0, 0x21, 0xdf, 0x96, 0x22, 0x89, 0xf7, 0xca, 0x7b, 0x3d, 0x32, 0xbe, 0xc3, 0x70, 0x87, 0x87 } }, +{ "\xc0\x9b\xff\xdb\xf9\x2f\xf0\xc5\x04\x70\xf4\x5a\xfe\x52\xf4\xf9\x50\x52\xb1\x41\xb5\xb0\xe5\x27\xea\xda\xf8\x2a\xf1\xe9\x5c\x9d\x01\x44\x85\x23\x0d\x62\x88\x3a\xef\xae\x4f\xed\x31\x83\x77\xad\x78\x56\xc6\x3b\x8e\xf3\x4c\xbc\x0a\xe0\x15\xee\x9e\xde\x87\x7a\xfd\x8d\x5f\x5f\x67\x2f\x42\x8e\xd2\x85\x03\x95\xb7\xd5\x70\x73\x76\x0d\xd9\x8a\x66\x02\x1e\xb2\x7d\xd1\x74\x69\x99\x66\xb4\x29\x69\x1b\x5f\xd2\xfa\x78\x32\x47\xe2\x19\x62\x15\x03\xad\x75\x4c\xfc\x1a\xbd\x72\x32\xbe\x71\x8d\x76\xd1\x69\x5f\x53\xe6\x76\xaf\xf7\x90\x5b\xc1", 132, { 0x6e, 0x38, 0x9a, 0xae, 0x82, 0xdf, 0x52, 0xff, 0xe8, 0xed, 0xfc, 0x75, 0xe6, 0x9a, 0xdc, 0x14 } }, +{ "\xbc\x21\x6c\xe7\x51\x8e\xc2\x30\x89\x6e\x19\x3f\xc0\x21\x46\x38\xe6\x0e\x57\xd3\x29\x04\x49\x92\x43\xc2\x60\x0f\x5d\x92\x27\x6f\x9e\x0f\x04\xf3\x55\x08\x77\xad\xbf\x7d\xef\x4f\x75\xc6\x49\x1e\x75\xd3\xe6\x06\xcb\x8e\x67\xc8\xdb\x5d\x08\x4f\x4e\xc3\x96\x20\x97\x26\x0e\xee\x21\xab\xd4\x4d\x17\x3d\x8c\x7f\xcf\xad\x99\x6b\xd4\xf4\x30\xab\x8e\x93\x18\xc4\x90\x1b\x00\x71\x7e\xc9\x7c\x18\x99\x49\x9e\x5e\xe9\x9b\x2d\xd6\x06\x13\x85\xd4\x82\x7a\x0a\x60\xf6\x53\x4a\x46\xa8\x38\xaf\x4b\xd6\x62\xdd\x7a\xa1\x46\xae\x9c\x99\x5d\xc7\xc5\xe1", 133, { 0xc4, 0xd1, 0x37, 0xe5, 0xf5, 0x29, 0xa4, 0xa2, 0xf0, 0xf2, 0x27, 0x54, 0x17, 0x1f, 0x12, 0x2c } }, +{ "\xfd\xd7\x0b\xff\x63\x6c\x52\x42\xd2\x71\x43\xd0\xd4\x48\x5b\x4b\x9f\x80\x1f\x20\x93\x33\x6e\x6c\xe0\xff\xee\x8a\x45\x9f\xa8\x3d\xf3\x25\xb0\x77\x90\xd6\xfd\xc4\x57\xa2\x57\x56\x5c\x3e\x6e\xad\xed\xe0\x06\xe3\x14\x96\x50\x91\x3a\x44\x55\x62\xe6\x38\x8b\x32\xa2\x6c\x8a\xe2\xfe\x57\xd8\xbb\xae\x70\xe0\x7c\xce\x40\x02\x01\x46\x22\xc4\x92\x49\x9a\x25\xc6\xf7\x50\x12\x12\x23\xa8\xf2\xf3\x2e\xfe\x5c\xb3\x12\x83\xe8\xda\x7b\xaf\x23\x35\x0f\x62\x9c\x7c\xcf\x9b\x1b\xa2\x95\xd3\xf1\xbe\xbd\xf7\x6b\x91\xe1\x01\x60\xb3\xbc\x32\xea\x5f\x30\xee", 134, { 0xec, 0x22, 0x50, 0xb3, 0x22, 0x24, 0x26, 0x6d, 0x36, 0xda, 0xd2, 0xa4, 0xc6, 0xc7, 0xd1, 0x20 } }, +{ "\x31\xd7\x62\x33\x63\x75\x03\xb7\xc0\x50\xaa\x9e\xd1\x87\x5d\xd5\xb8\x2d\x2f\x0e\xa3\xd1\x03\x58\x5a\xa8\x6e\x5a\xf8\x5a\xbb\x2b\xb7\x66\x08\xd1\xe4\x32\x8d\x55\xf1\xb3\xfd\x7f\xa9\xb5\x04\x34\x7e\xc7\xf1\x68\xfe\xc7\x6e\xc1\x64\x05\x6a\xca\x4b\x17\x17\xd0\x7e\x39\x0f\x5d\xea\x5e\x92\x4e\xb5\xd7\xea\x93\x67\x9f\xef\x83\x46\x41\xa7\xda\xc1\x66\x05\x50\x02\xff\xd2\xd6\xa6\x0b\xa9\x70\x89\x05\x1c\xaa\xba\xee\xf5\xb8\x8e\xf2\x96\x2e\xd0\xba\x82\x58\x16\x4d\xf4\x37\x2f\xa3\xad\x19\xb8\xc8\xcc\xd3\xce\xa9\xd5\x9e\xdd\x7f\xd4\x8c\x97\xd5\x9a", 135, { 0x24, 0x9d, 0xa1, 0xd8, 0x65, 0x77, 0x2f, 0x84, 0x7f, 0x6b, 0x6a, 0xc7, 0xec, 0x38, 0x7c, 0x68 } }, +{ "\xa5\x01\x37\x26\xa2\xa7\x79\x20\x45\xf0\xa1\x7e\x53\x8c\x72\x49\x2f\x09\x96\x7a\x15\x85\x67\xfe\xef\x7e\x5a\xd9\xd7\xc5\x08\x66\x2a\x91\xda\xbd\x45\xb0\x51\x2d\xdf\xd9\xf0\xe8\x03\x1c\xc6\xbe\xa8\x7a\x9c\x02\xef\x91\xb7\x89\xf8\x70\x4a\xd0\x60\x89\x7b\x3d\x5b\xc4\x10\x7e\x6b\xb0\xb6\x0e\xbb\xd4\xee\xd6\x1a\x24\x94\xf0\x97\x8f\x0d\x86\xb5\xb5\x0d\xd9\x4b\xb6\x03\x5e\xfb\x26\x21\x02\x4c\x1c\x0b\x8f\x67\x6a\x1b\x27\x6b\xe6\x4f\xec\x6d\xe7\xd0\xc2\x0f\xcc\x1f\x2c\xbb\xb6\xde\x53\x7d\x55\x39\x25\x7b\xe0\xef\x9a\x11\x1e\x01\x12\x8d\xa2\xf5\xdb", 136, { 0x77, 0xfc, 0x95, 0x17, 0xdd, 0xeb, 0xc5, 0xa5, 0x2f, 0x8d, 0x90, 0xd8, 0xd1, 0x38, 0x80, 0x09 } }, +{ "\x84\x14\xc7\xce\xcf\xa9\x6d\x18\x26\xb4\x06\x16\x56\x56\x9e\x5a\x22\x51\xa0\xcb\xb4\xfb\xd9\xe9\xbe\x4e\x25\x2d\x32\x1c\xb8\x8e\x9a\x60\x0b\x20\x14\xaf\x60\xd7\xee\xcd\xf4\x6a\xda\x5b\xc1\x53\xce\xae\xed\xf2\x7b\xbc\xd2\xd1\x67\x30\xab\x03\xa9\x9d\xd7\xa5\x41\xce\xcd\x86\x11\x3b\x9d\xe3\x7c\x99\x1f\x4b\x9a\x89\xba\xa1\x15\x70\xd2\x40\xa3\x66\xcf\x39\x20\x47\xc7\xb7\x46\xe8\xc7\x84\x0c\x64\xc3\xa4\x99\x94\x17\x1f\xe4\x9c\xb9\xdd\xea\xa2\xfe\xa9\x8a\x9a\x05\x58\x00\x3d\xc4\x03\xfc\x18\xad\x6f\x5e\xc1\xfc\x8e\x91\x24\xa0\x1e\x81\xfb\xc3\x70\x3a", 137, { 0xd2, 0x39, 0x29, 0x3a, 0xe7, 0x3c, 0xc8, 0x48, 0x93, 0x9d, 0x84, 0x3d, 0x11, 0x7c, 0xd9, 0x72 } }, +{ "\x5c\xf8\x43\x1f\x6c\x00\xcf\xc3\x31\x39\xdd\x67\x86\xa4\x13\x11\x27\x91\x4e\x45\xec\xe9\x28\x62\x13\x18\x99\x9c\xb6\x95\xb9\x92\x5b\x0f\xa3\x8c\xaa\x36\x76\x52\x39\x23\x75\xab\x83\x64\x4e\x71\xf8\xa8\x78\x4d\x2e\x03\xb5\x15\x35\xdf\xb7\xbf\x08\x80\xdf\x00\x1e\x32\x20\x85\x20\x11\x02\xcd\xb6\x75\xc3\xa1\x7b\xf8\x98\x31\x0f\x25\x11\xcd\x4a\xbe\x9a\x3c\x8d\xaa\x1d\xbd\x35\x79\xc5\x97\x29\x96\xde\x5f\x93\x08\xd8\xc6\xac\xe4\x6a\x1c\xaf\x53\xd4\x65\xef\x3c\x3c\x16\x04\x8d\x3a\x6d\x21\x2b\x6f\x6a\x81\x74\x50\x6d\x00\x6d\x01\x6d\xc6\x8d\x5c\xd2\x1e\x25", 138, { 0x0e, 0xfb, 0x6c, 0xcd, 0xb4, 0x7f, 0xb9, 0xa7, 0x2b, 0xcc, 0x94, 0x5f, 0x1f, 0x1c, 0x9b, 0x52 } }, +{ "\x10\xf0\x65\x6a\xe6\x21\x1d\x21\x1f\x7e\x21\xe5\xfa\x3a\xf3\x18\x52\x9b\x31\x64\x63\x95\x27\xed\xad\x04\x7d\x15\xf1\x85\x11\xeb\x58\xf2\xe0\x31\xb3\x79\x1d\x08\xdd\x59\x64\x3a\x3d\x38\x08\x24\x68\x23\x88\x3e\xe3\x22\x21\x48\x06\x77\x7d\x13\xfb\x73\x89\xea\xe6\xf6\x64\x9b\x1f\x81\x73\x25\x9a\xf9\x91\xff\x68\xfb\x64\x03\x56\xd6\xcb\xf6\xb3\x29\x73\xb4\x30\x1a\x89\xfc\xdf\x30\x89\xd6\x5e\xce\x35\x9d\x0d\x4d\xa2\xad\x7a\xb5\x6c\xa9\xde\x17\x0a\x69\xc1\x89\x3c\x7f\xb8\xbf\xa1\x65\x4f\x42\x65\x44\x01\x50\x17\x63\x64\x51\x98\x2a\x62\xf1\x2f\xd2\xa1\xde\xba", 139, { 0x7c, 0xea, 0xd6, 0xf2, 0x79, 0xc5, 0xbc, 0xa4, 0x89, 0x86, 0xfc, 0x29, 0x94, 0x1c, 0x8b, 0xee } }, +{ "\xac\x04\x20\xff\x0a\x4b\x0f\x21\xce\xd6\xf6\x2e\x8d\x87\x43\xd5\x5f\xc4\x67\x35\x45\x9c\x50\xd0\x38\x01\x80\x9e\xca\x33\xca\x3e\x7b\x3e\xa9\x48\x9b\x99\x3d\xbd\xd6\xf0\xe3\xa0\x61\xfc\x6f\x9e\xc0\x8d\x09\xe8\x31\xa9\xa1\x21\xb8\xcf\x10\x73\xc8\x54\xcd\xbc\x8b\xef\x48\xe6\xce\x50\xe6\x55\x8c\xea\x9a\x79\x16\xd2\x1c\x83\xdc\xbf\xc9\x34\xda\x31\x17\xd0\xa1\xaf\xb3\x32\x00\x29\x39\xf9\x50\x7b\x8f\xe0\x59\x12\xdf\x2c\xe4\xa9\x2f\x3e\xde\x2d\x9e\x48\x26\xbf\x3d\x1c\xf4\xd7\x87\x20\xe5\x86\x7f\x5e\xa7\xd4\x65\xb8\x3d\x47\x14\x38\xef\x85\xfb\x86\xd2\x11\xb5\x73", 140, { 0x2d, 0xe4, 0xcd, 0x76, 0x59, 0x59, 0x50, 0x08, 0xc3, 0xaf, 0xda, 0xd6, 0x68, 0x92, 0x96, 0xd3 } }, +{ "\xef\x31\x48\xb1\x13\xf0\xf7\xa5\x33\x40\xc4\x55\x79\x37\x86\x7c\xef\x7a\xa2\xbd\xc7\xb7\x69\xf4\x44\x4c\x0e\xa7\x49\x05\x42\x9b\x7c\x02\x6e\x83\x17\xb7\x8c\xd4\x4b\x0e\xa3\xb4\x50\xa7\xdd\x10\x0e\x3f\x46\xcc\x61\x2e\x23\x16\x0d\x0a\xed\xd4\x3e\x6a\xe9\x3b\xba\xc5\x65\x81\xa5\x78\x91\xaa\xf0\xe6\xf7\x7f\x60\xb9\x98\x9e\x36\x47\xa5\xaa\x80\x11\xd6\xa2\xfc\x65\x6b\x4f\xa4\x23\xbd\xd7\xdb\x9c\x80\x70\x32\x96\x98\x2e\xd7\x6c\x94\xfc\x9a\x52\xcb\xa9\x9d\xb7\x12\x1a\x98\xc3\x17\x9e\xc7\xff\x5d\x5f\x70\x14\xd4\xf3\x14\xac\x14\x12\x32\x75\x36\x62\xb2\x44\x4f\x6f\xf5", 141, { 0x5c, 0xf1, 0xaa, 0x0f, 0x1a, 0x4b, 0xef, 0x0b, 0x9d, 0x3e, 0xba, 0x20, 0x09, 0xb6, 0xbe, 0x59 } }, +{ "\x56\x8a\xb6\x76\xb1\xe1\xe0\x1d\xa9\x78\x0c\x20\x7e\x96\x45\x96\x23\x40\x13\x9a\x19\x74\x2d\x18\x7a\xff\x4c\x37\x12\xfb\x1a\x63\xa8\xe9\x49\xf6\x5a\x66\xc1\x82\x26\x8d\xf1\xbd\x85\xea\x47\x0a\x31\x16\xba\xa0\x08\xf4\x84\x59\x09\x86\xee\x19\x7b\x6d\x43\xd9\x2c\xfb\xe6\x4f\xd7\xf6\x80\x3c\x9f\xec\x51\x51\xb8\x2e\xa8\xbf\x25\x6a\x6e\x5a\x9b\xe9\xdc\x69\x85\x61\x4c\x0c\x21\x78\x2d\x4a\xc7\xd6\x11\xb7\x4a\xe5\xe1\xbe\x77\x28\x30\x91\xba\x35\xac\xaa\xe1\x50\xb1\xfc\xf8\xa6\xf7\xbb\x52\x23\x6c\xc5\xa9\xf0\x1d\xab\x5d\x8c\x4d\x60\xd8\x86\xa8\x7d\x13\xd4\x91\x2f\x31\xd4", 142, { 0xcb, 0x47, 0xda, 0xb2, 0x8e, 0x25, 0x2b, 0x75, 0xc9, 0x37, 0x45, 0x95, 0x31, 0x20, 0x1f, 0x6c } }, +{ "\x98\xbe\x49\xdc\x07\xba\x41\x7f\x9b\xc4\xd5\x5f\x50\xf6\xb7\xaa\x56\xf0\xd1\x33\x1f\x80\xa6\x2d\x9a\xed\xd6\x86\x7a\xe0\xc0\xde\xaf\xf0\x42\x22\xf6\xc9\x9c\xc9\x8c\xf8\x72\xab\xfe\x55\xf0\x79\x1c\x0c\x08\xdd\x0b\x4a\xd6\x2f\x7a\x82\x25\xd0\xed\x59\x0b\x27\x35\x34\xaf\x36\x00\x5b\x2b\xd8\x8c\xca\x8c\x99\x77\x94\xf6\x32\xb3\xf5\xe5\x9f\x95\xf2\x8e\xdf\x0c\xaf\x64\x48\xee\x4d\xb6\x84\x6e\x7d\x75\x2c\xaa\xa6\x14\xff\x61\xaf\x88\xbe\xc2\x69\x6f\xa8\x5f\x9c\x4d\x8d\x41\xad\xf1\x91\x15\xe8\xf6\x80\x83\x70\x65\xc8\x9f\xc0\x78\x17\x78\xdd\x79\x92\xce\x1a\xc9\xae\xe2\x87\xfd", 143, { 0x25, 0x55, 0x2f, 0xfb, 0x95, 0x22, 0x2a, 0xea, 0xac, 0x33, 0xb7, 0x28, 0x61, 0xa0, 0x65, 0x9b } }, +{ "\xaf\x65\xf8\x23\xbb\x92\xad\x22\x9a\x57\xa3\x3f\x0d\xae\x76\xbc\xc8\x0b\xf1\x9b\x0d\xee\x34\x80\xe5\x98\x81\xb4\xfe\xda\xa3\x46\x1c\x08\xfb\x4c\x3d\x0d\x28\x47\x4e\x98\x52\xa4\x83\x74\x13\x5f\x57\xf6\x03\xc2\x20\x8f\xdf\x4b\x4d\x82\x55\xac\x40\xaf\x6f\xec\xc2\x8d\x99\xab\x27\x36\x51\x82\xff\x9c\x6a\x89\x76\xd9\xfc\xf2\x49\xa5\xeb\xd2\x65\xe1\x13\x00\x1e\x50\x0d\x16\x08\x65\xa1\x95\x76\x36\xc8\x25\x8d\x90\x5c\xf9\x03\x25\x5e\x51\x7a\xe1\xe3\x19\x73\x5a\x9d\xaf\xf0\x66\x02\xc2\xab\xc6\x1b\x55\xec\xff\xeb\xe3\x0b\x49\x7a\x9d\x82\xa1\x7d\xcf\xae\xf9\xa3\x60\x22\x90\x7e\x78", 144, { 0x6d, 0xea, 0x3a, 0xd4, 0x25, 0x47, 0x84, 0x4e, 0x6a, 0x6c, 0x75, 0xcd, 0x94, 0xd4, 0x93, 0xef } }, +{ "\xa8\x5c\x0c\x3c\xd5\xa2\xe2\xb5\x48\xa8\xf4\xce\x7f\x83\x03\x7c\x55\x0a\xa3\xf8\x1c\xeb\xe8\x28\x53\xdb\xad\x1c\x04\xe9\x80\xb3\xbd\xec\x2d\x5e\x28\x1b\xe6\xfc\x4a\xbb\x0c\xe5\x54\xf3\x9c\x02\x29\xbb\x39\x19\x6d\xf3\xd1\x27\x46\x90\xef\xe6\xb3\xf1\x9d\x6e\x85\x50\xf4\xf8\xfd\x53\x42\xbd\x04\xc2\xd6\xfd\x01\x54\x6a\x1b\x5b\xa2\x2e\xe5\x8b\x3d\x6d\xf2\xdc\xdb\xde\x24\xc2\xac\x89\x4e\xd4\xcb\x54\xef\x68\xd0\x2a\x1b\xca\x82\xc7\x7a\x18\xa9\x22\x6a\xbd\x02\x76\x40\x88\x4c\xef\xac\x68\x80\xee\x3a\xc6\x1d\xf9\xf5\x7f\xa1\x42\x26\x7d\x13\xd2\x3a\xf1\xbd\x52\xc1\x2f\xf8\x76\x93\x25", 145, { 0xdb, 0x35, 0x6a, 0x9a, 0x9f, 0x39, 0xbc, 0x4e, 0xdc, 0xf9, 0x16, 0x44, 0xc7, 0xfb, 0x4d, 0xb9 } }, +{ "\x1f\x06\x0d\x79\xa6\x8b\x79\x3f\x43\x92\x8c\x54\x4a\x9f\x08\x5a\x16\xb2\x82\x50\xa3\x6f\x3e\xcc\x39\xec\x36\xd8\x43\x1c\x39\x67\x3e\xd2\x30\x72\xcd\x75\x7d\xb4\xe9\x3f\x7c\xfe\x35\x31\x2b\x37\x6f\x97\xe6\xf4\x03\x33\x4b\xb0\xba\x09\x3c\xa8\x8f\xc6\x02\x56\xa2\xce\x8f\x87\x46\xe1\xdc\x1b\x35\x69\x71\x59\xe3\x62\x03\xec\xef\xe6\x37\x7e\xb6\x54\x85\xf0\x02\x1c\x37\x33\xe0\x2a\x91\xc6\x8f\xed\x0b\xcc\x94\x03\xba\xc9\xeb\x83\xcd\xf9\x58\xe6\x32\x4d\xdb\x92\x58\x03\x41\x05\x10\xe0\xd7\x9b\x8d\x0d\x3a\xfb\x8a\x8c\x4a\x24\x8a\x55\x3d\x10\x3b\x11\xcf\x02\xf4\x72\x97\x71\x5d\x2d\x75\x91", 146, { 0x31, 0x6e, 0xe6, 0x46, 0x65, 0xc8, 0x63, 0x25, 0x2b, 0x8f, 0x01, 0xbd, 0x64, 0x08, 0x2c, 0x6e } }, +{ "\x2e\x95\x28\x7a\x10\xd5\xfc\xf7\x9f\xca\xa0\xee\x91\x7b\x16\x67\xf0\x36\xc3\x3a\x83\x48\xa6\x59\x4b\x58\xa5\xb8\x29\x60\x03\xd5\x9d\x49\xee\xe7\xa9\x23\x35\xa7\xd3\xfe\x17\xb5\x4a\x67\x37\xa9\x20\x82\xab\xb7\xb6\xc1\x33\xfe\x35\x3e\x86\x6d\x38\xbb\xc8\x52\x87\x33\x19\x81\xff\x1c\x47\x1d\x8d\x3c\xa3\x06\x59\x25\xf1\xdf\xff\x4f\x79\xba\xf8\xd0\x3a\x63\x17\xba\x3e\x46\x30\x11\x09\xfd\xd3\x67\x2b\x7a\x36\x16\xf5\xce\x30\x1a\x48\x93\x62\x89\x89\xfc\x70\xaf\xb0\x77\x6d\xca\x80\xfc\x55\x5f\xd1\xf6\xb3\x37\x09\xca\x63\xf9\xa9\x08\x72\x65\x03\x2d\x21\x2a\x0a\x12\x09\x65\x41\xf5\x58\xb8\xd6", 147, { 0xea, 0x55, 0x9c, 0xa7, 0x61, 0xf9, 0x9e, 0xc7, 0x2a, 0x9a, 0x54, 0xba, 0xa7, 0x5b, 0x37, 0xfd } }, +{ "\x23\x39\x02\xc8\x3e\x52\xc0\x42\x30\x67\x00\x0c\xad\x1c\xfd\x17\x5e\xd7\x5c\x36\xaf\xc4\x02\xec\x36\xf2\x90\x60\xbe\x9a\x7c\x6d\xf0\x80\xcd\xd6\x9d\x73\x72\x97\xab\xee\x40\x56\x99\xe1\x87\xf8\xb0\x89\x4f\x50\xc8\x7b\x34\xf3\xb4\xc1\xdb\x27\x4b\x1b\x10\xfa\x14\x67\x7e\x6e\x8d\x1b\x0a\xd2\x18\xee\xcc\x2c\x83\x96\xaa\xd2\x32\xad\x93\x17\xeb\xad\x55\x23\x3e\x1a\x1c\xdc\x8f\xbf\x88\x00\xc1\x10\x69\x55\x81\xae\x1a\xf7\x2c\x0a\x77\xd0\x5e\x21\x7c\x27\x18\x65\x7b\x4f\x8d\xbc\xf9\x7f\x89\xa1\x26\xc2\x7f\x69\xf8\x05\x2d\xa0\xe3\x4e\xee\x92\x37\x0c\x9c\xe5\x15\x89\x1f\x63\x0f\x7b\x97\xd6\x5c\xba", 148, { 0x0f, 0x9d, 0xb8, 0x04, 0x8a, 0x9f, 0x75, 0x74, 0x4a, 0xcd, 0xdd, 0x47, 0xcf, 0x76, 0x81, 0xfa } }, +{ "\x22\x0c\xb4\x0d\x4a\xfa\xce\x1d\x0e\xfd\x74\x8b\x8b\x3b\x3f\x1d\x47\x28\xf5\x13\x1b\x25\x7b\x98\xba\x42\x78\x54\xe2\x24\x89\x1e\x1d\x02\x1a\xcf\x34\xc9\xe7\x32\x31\x60\x10\x17\x10\x06\xd2\x87\x02\xd7\xe8\x11\x5d\x6d\x7d\x43\x23\xa2\xcc\x35\x2c\x74\x56\x3f\xf3\x02\xbf\xca\xfb\xb3\x46\x44\xdc\x76\xdf\x2d\xee\x23\xef\x4e\x90\x00\xa3\x0a\x16\x60\xee\xcd\x4d\x67\x1d\xa1\xab\xe8\x18\xdf\x18\x6f\x37\x02\x53\x5a\xbe\x97\x03\x22\xf7\x51\x5b\xb7\xea\x39\x68\x0a\xbc\x02\xfa\xa4\xa2\x7a\x2c\x73\x80\x1d\x92\xa6\x22\xc4\xff\xad\x15\x7a\xf0\x63\x23\x6f\x99\x48\x6a\x06\x89\xe7\x18\x09\xfc\x56\xc6\xfc\xbd", 149, { 0x76, 0x46, 0xa2, 0x5b, 0x70, 0xce, 0xd9, 0x5e, 0xe2, 0x86, 0xf5, 0xb1, 0xc2, 0x39, 0xd9, 0x4d } }, +{ "\xdc\x6d\x8f\xb6\xad\x09\x2d\x16\xd0\xc8\xb1\x1d\x21\xef\x38\x87\x73\x4a\x11\x92\xcd\x4e\xd1\xae\xd5\xcd\x84\xc1\x4b\x54\xfd\x14\xac\x24\x4f\xdd\xf7\xcc\x54\x69\x8b\x5f\x6a\xe6\x2f\x57\x3e\xca\x2c\x06\xc0\xe4\x95\xb5\x36\xfd\xa7\x5b\x6d\x2a\x4b\xfb\x09\xb1\xb8\x9b\xfe\x96\x35\xdc\x17\xc1\xfc\x3b\xb4\xcd\x3a\xe3\x91\x6f\x33\x2c\xc0\x81\x83\xb4\xb9\xaa\x7f\x18\x88\xac\xba\x50\x24\x4a\xa4\xa5\xe0\xd4\x4c\x4f\xfb\x50\x46\xaf\x52\x47\xa7\x25\x34\x29\x2d\x8f\x56\x5e\x7c\x5f\xdd\xea\x83\x58\x99\xbb\xfd\xe5\x52\x92\x14\x16\x3a\x8c\x1f\x37\x81\x4c\x8c\x0f\x08\xc7\xd9\xb2\x2d\xac\xbc\x03\xc5\x6e\x63\xca", 150, { 0x63, 0xf7, 0x3c, 0x3f, 0x15, 0xc6, 0x1c, 0x37, 0x20, 0x84, 0x1a, 0x45, 0x07, 0x6f, 0x04, 0x5b } }, +{ "\x28\xef\xd6\x6e\x65\xca\x78\x4f\x96\x3d\xac\xc2\x4f\xb2\x93\xaa\x30\xe8\xf4\xaf\x9a\xc3\x35\x1e\x7e\xac\x86\x5d\x51\xa6\x1d\x09\x1c\xef\x9b\xae\xaf\x4f\x8e\x22\xf5\x00\x10\x7e\x63\x39\x8c\xba\x8b\x59\xa0\xe4\xcd\xad\x1e\xfd\x2c\xde\x2d\x70\x3e\xfa\x8d\x30\x3d\x1d\xf8\x6d\x3c\xbb\xa3\xf2\x73\x8d\xe4\x1e\xbb\x16\xed\x7d\x15\xd1\xb6\x02\x64\xf9\xf9\xe3\x3b\xf4\x57\x11\xd1\x5d\x98\x53\x11\xad\x10\xfe\xce\x85\x1c\x53\x14\x9a\xcc\x75\x99\x3d\x9b\x05\x53\x86\x59\x5c\x23\x1c\x29\x64\xaf\xa4\xa6\x13\x4d\xc4\x21\x85\x1a\xd3\x06\xb6\x2b\x1f\x5d\xd9\xdb\xd9\x6c\x57\x44\xa1\x79\x67\xc9\xaa\xac\x46\xcf\x8a\x13", 151, { 0x62, 0xc8, 0xb6, 0x40, 0xbc, 0xc6, 0xa0, 0x0a, 0xa7, 0xd0, 0x3e, 0x39, 0xf2, 0xb0, 0xea, 0x37 } }, +{ "\x14\x8b\xa1\xc0\x4b\xf6\x23\x0d\xdc\xde\xc3\x00\xe7\x16\xfd\xc9\x17\xce\x00\x68\x99\xfd\x37\x6b\xb7\xfa\x73\xd5\x15\x2a\xb7\x1b\x86\xd4\x9f\x48\x8c\x11\x6d\x40\x6a\xdf\xb1\x21\xe8\x54\x95\xc5\xa3\xef\xc2\x64\x0e\x0a\xf3\x57\x09\x6c\x14\xf7\x1c\xfb\x16\xa4\x50\x8e\x52\xe1\xaa\xe0\x97\x9d\x45\xa1\xd2\x8d\x0b\xa7\x59\xb4\x0f\x43\xd4\x04\x8a\xae\xc8\x1e\x71\xa1\xc1\x36\xaf\x03\x1c\x12\x04\xbd\x6e\x31\x79\xaa\x95\x08\x7f\xaa\x59\x67\xa4\xd6\xbd\xfb\xf1\xcd\xe8\xec\xe2\x2d\xab\xa7\x02\x1e\xaf\xb6\x23\x08\x3c\xca\x37\x64\xa8\xdb\xcf\xb0\x5a\x66\x2d\x7c\x7a\xd5\x07\xa2\x37\xfd\xdb\x93\xb4\xc1\xe9\xcb\x90\xd3", 152, { 0x37, 0x36, 0xc5, 0xe7, 0x36, 0x49, 0xee, 0x57, 0x1d, 0x40, 0xa0, 0x4c, 0x9e, 0xde, 0x94, 0x3a } }, +{ "\xd2\x66\x10\x9b\xcb\xcd\xeb\x30\x7e\x89\xb2\x83\x7d\x38\xdb\x9b\x63\x9c\x69\xfa\x89\xd0\x39\x1f\x62\x97\xea\x25\x74\xcd\x6a\x89\xf3\xff\x1a\x09\xfc\x16\x9d\xa7\x6b\x2e\x42\xcc\x59\x85\x0b\x8a\x35\x8e\x5a\xfa\x7e\x25\x37\xc4\x1a\xde\x40\xbd\x56\x76\x2e\xab\x7b\x6b\xff\x23\x09\xa7\xc6\x93\x93\x57\x0b\x5c\x36\xdb\xe0\x17\xb7\xd6\x81\xf9\x38\x64\xa7\x51\x97\x6b\x69\x2e\x64\x0b\xcf\x1d\x7c\x2f\xf5\x0f\x46\x45\xd9\x5a\x8a\x0a\xc1\xd6\xe9\x7e\x4b\x28\xfd\xf7\x13\x1b\x0e\x52\xfa\x2a\x6d\x44\x19\x1a\x71\xce\x43\xc4\x0b\xcf\x2f\xf0\x08\xb3\x4a\x5d\xe4\x49\x18\xde\x45\xb3\x43\x9e\x1b\x77\x42\x84\x51\xb2\xa7\xb1\x30", 153, { 0x1b, 0xaf, 0xb0, 0x43, 0x8c, 0x29, 0x50, 0xc6, 0x5f, 0x88, 0x3c, 0x47, 0xe5, 0x59, 0x28, 0xf0 } }, +{ "\x6b\x05\x26\x51\x05\x7b\x83\x3d\xcf\xe2\xeb\xa3\xb6\x8f\x03\x34\x1a\xc5\x18\x1f\xbd\xba\x60\x24\xd8\x44\x58\x57\x48\x20\x4d\x74\xe5\xdf\xf7\xd9\xf3\x6e\x3f\x24\xb2\x40\x22\x69\x10\x1a\xad\x10\x7f\x7a\x28\x4a\xe0\xa5\x4f\x2e\x9e\x4c\xbb\x74\xd8\xda\x60\xcc\xb6\x5d\x2f\xdc\xdd\x0e\xdc\xd5\xfd\x7f\xba\xb0\x87\x60\xc2\x0b\x7c\xed\xb2\x9a\x61\xf8\x52\x4b\x4f\x8e\xd1\xfa\x27\x49\x4e\xce\xe2\x32\x74\x2e\x06\x50\x3d\x64\x34\xd1\xd7\xcc\xde\xd4\xa3\xb8\x17\xd1\x5a\xe4\x83\xa6\x4a\x90\x6d\x3f\xbf\x40\xf7\xe0\x7d\x0c\x6c\x12\x68\xa4\xb2\x28\x46\xe4\xdb\x6c\x9d\x10\xda\xeb\xb7\xac\x52\xda\xc4\xfb\x8a\xa4\x1e\x12\x7d\x91", 154, { 0xee, 0xd2, 0x3f, 0xfe, 0x5e, 0xf6, 0x9b, 0x93, 0x25, 0x36, 0x5e, 0xa2, 0x89, 0x96, 0x1b, 0xe0 } }, +{ "\xa7\x97\x0f\x14\x4e\x1b\x59\xb1\xb1\x12\x25\x89\xdd\x6b\x75\x83\x30\xd0\x3e\x19\x5f\x7c\x32\xbc\x94\xb3\xbb\xe5\xb0\xe3\x03\xba\xae\x55\x30\x58\x27\x90\xad\xc3\xf2\x4a\xa4\x68\xe3\x0c\x88\x4a\xb4\x61\xce\xd1\x02\xba\xbb\x2c\x6e\xe1\x58\x5e\xe4\x18\x83\xec\xf8\xce\x20\x22\x6c\xfd\x6c\xfd\xce\x23\x72\xb8\x3e\xda\x96\xf6\x4e\x16\x4e\x88\x02\xfb\xf1\xdc\xf6\x59\xa7\x03\x9f\xc5\x80\x5d\xa9\x55\xa2\xe3\x80\xf7\x9a\x11\xeb\x6e\xd3\x6e\xd2\xea\x24\xb9\x20\x44\x83\xb2\xc3\xd3\xd7\x82\xd0\xed\xec\xc8\xc4\xfe\x80\x40\xe6\x3e\x7a\x12\xc8\x12\x3a\xb5\xec\x01\x0b\x7e\x82\x51\xb5\xc9\x4f\x3e\x30\xc2\xaa\xd6\x72\xd1\xa1\x74\x69", 155, { 0x71, 0x8e, 0xdb, 0xc9, 0x57, 0x5f, 0x0d, 0x0c, 0xec, 0xbe, 0xde, 0xdc, 0xa1, 0x2e, 0x69, 0xb9 } }, +{ "\xa0\x38\xd6\x05\xca\xd1\xdd\x6c\x21\xa7\xe2\x51\x9c\x74\xb0\x5f\xdb\x33\x21\xcf\x59\x00\x58\x19\x2d\x1b\x98\xc6\x7d\x0b\xbf\x64\x7f\xdf\x63\x94\x2d\x90\x88\x3d\x85\x82\xfa\xe3\x7a\x29\x4d\x12\x7a\xc8\x6f\xf4\x9d\x55\xe7\x02\x67\x79\xac\xd7\x3a\xb3\xa4\x20\x5b\x9c\xb8\xb0\x9f\x45\x90\xb0\xb1\xbc\xf0\xf4\x03\xae\xae\x68\x4f\x26\x4f\xa9\xc9\x74\x3e\xb0\xe3\x28\xa8\xa9\xbc\x3d\xf7\xe2\x26\x54\xe8\xdf\x52\x15\x4b\x8a\x1b\xba\x57\x87\xeb\xa7\xa7\xa6\x4e\x31\xd5\x72\x11\x7f\xb1\xe6\x16\x8e\x1f\x3f\xb7\x4e\x8a\xed\xd5\xea\x09\xa3\x7c\x25\x0c\x8d\x34\xdf\xc2\xa1\xe7\xb8\x0b\x0f\x6a\xcb\x15\xd2\xaa\x9b\x95\x68\x74\x0c\xa4\x9e", 156, { 0x28, 0x35, 0xde, 0xdd, 0xce, 0x7d, 0xf6, 0x36, 0x34, 0x58, 0x67, 0x85, 0xef, 0xd3, 0xd0, 0x4b } }, +{ "\xe0\x88\x34\x85\x5b\x42\x2d\x81\x50\x97\x28\x7f\x73\x90\xc7\x46\xaa\x84\xaf\xe7\x97\xdb\x23\x4f\xc6\xed\x3e\xfb\x70\x08\xcc\xca\xea\x91\xc6\xee\xad\x41\x69\xfc\x02\x91\xf2\x24\x4a\x31\xf8\x7a\xe7\xb1\x65\x72\xcb\x43\x12\x6b\x9b\x97\xff\x62\x7f\xe6\x2c\xc7\x89\x0b\x16\x6c\xbf\xcb\xd1\x9a\xc7\x35\xbe\x3e\x2e\x25\xea\x41\x54\xe2\x04\xf5\xf8\xe7\xf8\xab\x5c\xbf\x2c\x61\x15\x09\x56\x98\x71\x9b\xf8\x44\x84\xc3\x79\xdd\xd1\xa9\xe1\x93\x92\xd0\x31\x9e\xa5\xbb\x5d\xb3\x13\xac\xe7\x92\x3d\x88\x19\xbc\xa5\xd6\xdf\x43\x56\xe6\x3f\xb9\xf1\x0e\x75\x4a\x56\x10\xaf\xe6\xeb\x97\x61\x96\x8c\xe0\x46\xf0\x0f\x76\xf5\xa6\x72\x15\x1c\x38\xa4", 157, { 0x11, 0xb8, 0xb0, 0x6e, 0xcf, 0xbf, 0xc1, 0x00, 0x35, 0x81, 0x35, 0x3d, 0x73, 0x40, 0x71, 0xab } }, +{ "\xb0\x5b\xca\xec\x8e\xbf\x10\xfa\x8f\xd9\x65\x89\x8d\x7a\xfb\xad\xde\x0e\x2d\xbe\xf5\x93\xf1\xe1\x28\x34\x69\x30\x8c\x86\x98\x85\xfc\x5e\x31\xe8\x39\x4c\x8b\x92\x2b\xb9\xb2\x9e\x46\x99\x97\x4b\x08\xcc\x67\xf0\x9e\x17\xf9\x7d\xa6\xb9\x60\xa9\x10\xad\xa0\xbd\x1e\x7c\x7e\xfd\x8a\xbb\x70\xae\xc6\x28\xb4\xc9\x5e\x5d\x7d\x3a\x7a\x2f\x47\xd5\x7f\xa6\x4c\xd6\xd6\x98\x0f\x13\xc4\xe4\x15\xc0\x78\x48\xb3\xdf\x24\xe0\x03\x42\x43\x3c\xf0\x3e\xf8\x1c\x71\xee\x97\xca\xd3\x21\x3d\x14\x2e\xe1\x99\xe5\xf9\xa1\xce\x80\xba\x02\x71\x58\xd6\x42\xad\x8e\x86\x41\x86\x07\xea\x31\x3a\x29\x37\xda\xc3\x33\x0d\x88\x7a\x37\xe4\x92\xd5\xb4\xa4\x87\x51\xd4", 158, { 0x88, 0xe5, 0x0c, 0x22, 0xb2, 0x63, 0x28, 0xbd, 0x76, 0x62, 0x67, 0x97, 0x24, 0xc6, 0x2a, 0x19 } }, +{ "\x53\xf6\x6b\x3e\xe8\xda\xc8\x99\x3f\xa0\x74\x9f\x26\xd7\x47\xd9\x94\x73\x64\xfc\xf9\xbe\xdb\xe0\xb1\xdc\x6e\x19\x92\xf9\x71\x34\xa4\x11\xca\x90\xf0\x5b\x18\xd6\x71\x53\xf0\x16\x28\x63\x43\x7f\x4b\x2d\xdb\xbb\x9d\x77\x04\xe5\xd9\xb4\x47\x28\x48\x2b\x52\xf5\x72\xc6\xf3\xe0\xf1\x79\x43\x18\x60\x4d\xe0\x81\x73\x08\x52\x70\x21\x7b\x8f\x02\xfb\x68\x99\x19\xa0\x0d\x45\xf4\x49\x52\x18\x6a\x80\x8a\x4a\xc3\xee\xe9\xec\x33\x51\x83\x25\xf4\x8c\xfd\x98\xff\xd8\xd2\xe1\x66\x19\x44\x3f\x51\x4b\xdd\x4c\x93\x1b\xa0\xe6\xe8\x92\xd1\x32\xcd\xec\x5e\xb7\xfc\x87\xe9\xa5\x83\xf7\x73\x39\x80\x36\xa6\x38\x7b\xf9\xbe\x98\x60\x1d\x16\x3e\x17\x40\x4b\xe2", 159, { 0x5a, 0xc3, 0xb5, 0xfd, 0x87, 0xbf, 0x56, 0xbf, 0x6f, 0x69, 0xe7, 0xac, 0xf6, 0xb7, 0x50, 0x26 } }, +{ "\xc2\x6d\x0f\x10\x92\xef\x8c\x47\x47\x46\x72\x44\x42\x38\x9f\x59\x48\xfe\x6a\xf6\xd5\x9f\x8c\x49\x1a\x5b\xac\x02\x96\x3d\x86\x2f\x4c\xd3\xb7\x47\xa6\xfa\x27\x42\xe6\xd3\x13\xe5\x45\xd2\xb6\x1c\xaa\xf5\x93\x7f\x08\x11\x62\xf7\x54\x47\x94\x7a\x22\x96\x85\xf1\xdb\x8b\x3e\x3b\x9d\x13\xe3\x4b\xaf\x71\xbf\x6d\x9f\x4a\xea\xa6\xfb\xdd\x95\x38\xa8\x51\xf2\x44\xe2\x27\xc2\x8a\xd0\xcf\x7c\x4c\xc3\x56\x17\x52\x0b\x3c\x75\x06\x76\x64\x6c\xbf\x66\x24\x71\x1b\x8e\x7c\xe3\x85\x49\x64\xf2\xd6\x96\x3e\x2a\x17\xb4\x6b\xa0\x65\x56\xfa\xb7\xed\x84\x7a\x8f\x17\x0e\xf0\x0b\xc0\xad\xe4\x7e\x9f\xb7\x96\xf2\xc9\x7e\x4e\x14\x4f\x47\xd1\xbf\x05\xe2\xef\x23\x5e", 160, { 0x59, 0x21, 0x8f, 0x6b, 0x10, 0x2a, 0x92, 0x6c, 0x6c, 0xbd, 0x52, 0x03, 0x5c, 0x47, 0xa6, 0xc0 } }, +{ "\xeb\x39\x92\x73\x9b\xd1\xe7\x22\x4b\x5a\x93\x53\x87\x0e\x45\x56\xcb\xed\x35\x68\xdd\x13\x0e\x55\xc6\x23\x76\x37\x6e\xdf\x3b\x5c\xd3\xda\x1b\x45\xe6\x44\x30\xcb\x02\xe4\xf6\x5d\x09\x25\xfb\x64\x1d\x47\x22\xc7\xf8\xb6\x93\x8a\xe9\x78\x42\x91\x6c\xbf\x1b\x83\x64\x9e\xc7\xca\xf7\xd9\x1e\xb6\x06\xd5\x29\xc1\x48\xae\xd2\xed\x02\x67\x2b\x4a\x65\x3c\x57\x94\x83\x14\x19\xf8\xef\x12\xf7\xf7\xf1\x4b\x0a\x64\x63\x92\x65\x87\x2c\x6e\x20\x64\x56\x2d\x00\x15\xcd\x12\xc4\x54\xb6\xa9\x0e\x15\x69\x3c\xec\x50\x0d\x5e\x03\xdc\xcf\xa4\x57\x77\xbf\x74\xb9\xe2\x47\xf5\xce\x29\x48\x26\xb7\x01\xd2\x0a\x62\x49\x80\x01\x6d\xb3\x6e\x33\xb2\x7c\xd9\x25\x73\x57\x51", 161, { 0xfd, 0x5f, 0x53, 0x55, 0x7c, 0xa6, 0xcc, 0x9a, 0x93, 0x96, 0x50, 0x2d, 0xe3, 0xbc, 0xde, 0x90 } }, +{ "\x6d\x23\x68\x9d\x82\xcf\x6b\x2b\xad\x27\xf5\x32\x1c\x2d\xd3\x66\x15\x79\x8f\x57\x48\x26\x11\x67\x3d\x5d\x61\x66\xec\x7c\x8a\xcc\x6b\xe2\x9a\x92\xc2\x5a\xc7\xad\xda\x21\xac\x28\x94\x95\xb0\xdc\xf7\x7d\x87\xcf\x81\xef\xd2\x27\x9e\xe2\xe2\xc9\x36\x50\x9a\x93\x61\x07\x72\x32\x36\x0d\x98\xa0\xc1\xae\x31\x3d\x12\x24\xbd\x89\x72\xe1\x98\x7c\xb1\x7b\x9c\x82\x9b\x34\xe4\x16\x89\x25\xac\xfa\x13\x07\x54\x10\xe3\x9e\x83\xd9\xa5\xc3\x68\x87\x1a\x0c\x1c\xc0\x4c\x1a\x23\xf2\xdc\x7e\x12\x4d\x77\x48\x4a\x62\x67\x2e\xe2\x56\x45\x56\xa3\xc2\xcd\xc0\x2c\x2b\xca\x53\x36\x19\x30\x83\xf2\xd6\x48\x9b\x8f\xc4\x06\xac\xd8\x5b\x76\x12\xf9\xbf\x55\x9f\x61\xfa\xbc\x67", 162, { 0xb5, 0xc0, 0xce, 0xe9, 0x9a, 0x70, 0x42, 0x5b, 0xc4, 0x6d, 0xf4, 0x0e, 0x8c, 0x2a, 0xf1, 0x63 } }, +{ "\xc3\xdb\xf7\x28\x38\x6a\x74\x53\x7f\x06\xd7\xbb\x64\x1d\x2a\xd9\x3e\x88\x32\xba\x91\x81\xdd\x86\xd4\x42\xd7\xad\x4e\x3b\x3b\xaf\x1a\xee\x67\x88\x49\x6b\xe8\xb7\x26\x63\x94\xea\x94\xec\xb7\x48\x94\xd0\x65\x5a\xe3\x92\xef\x97\xc0\xfe\x70\x8a\xcb\x6c\x87\xa2\x09\x91\x1f\x96\x04\x01\x69\x73\x10\x45\xeb\x43\xa8\x94\xb2\x5b\xf6\x32\xa3\x42\x71\x62\xf0\x39\xa1\x09\xa6\x6c\xfe\xe1\x62\xb3\xf6\x56\x24\x05\x0e\x01\x3b\x7a\x20\xbe\x60\xfa\xc2\x6c\xdf\x87\xc7\x40\xf0\x25\xdf\xc6\x24\x62\x5a\x76\xfb\x85\x09\xef\x92\x57\x45\xd2\x79\x88\x09\x3e\xa3\xc0\x3a\xe3\x77\x44\x08\xc5\x03\x40\x6c\x8f\x50\xb7\xd1\x91\xd0\x04\xcf\x58\xf4\x0b\x12\xe9\xda\x02\x59\x99\x24", 163, { 0x62, 0xcf, 0x51, 0xd0, 0xdd, 0x5e, 0xaa, 0x1d, 0x2e, 0xbc, 0x45, 0xe8, 0xbe, 0x1e, 0x27, 0xc5 } }, +{ "\xd6\x9b\x8c\xe4\x3b\x44\xc8\xb3\x53\x9c\xf5\xe1\xfa\x49\xb3\xc6\xac\xeb\x98\x37\x13\xe5\xc5\x14\x31\x3c\x24\xff\x27\x97\x40\x27\xa0\x66\xc0\x42\xdd\x20\x81\x99\x5d\xa4\x4f\x3d\x28\xc1\x40\x57\xb8\xd1\xae\x9d\x85\x80\xcf\xe1\x2c\xaa\xf3\xc3\x3b\x62\x59\x87\x9b\x10\xad\x01\x9a\xb2\x22\xad\x95\x43\x28\xdb\x3e\x38\xca\x07\x90\x27\xa7\x47\x4c\x83\x8b\xdd\x2e\x82\xaa\xec\xb1\x1f\x78\x48\x7c\x3b\x28\x66\x68\xdf\xbf\x72\x2e\x9c\xd3\x80\xb2\x13\xe5\xda\xe6\x91\x58\x78\x5c\xd2\x0e\x8d\x6d\xe7\x9e\x3e\xff\x32\x33\x6d\xf5\x8d\x04\xb4\x39\x8a\x6b\x6e\x5f\xd5\xa5\xef\xf6\xb6\x25\xd3\x70\xb3\x95\x74\xab\x52\x6a\x75\x1b\xfc\x22\x7b\x96\xfd\x1d\xfc\xbc\xa8\x15\x2f", 164, { 0xd4, 0x4e, 0xcd, 0x21, 0xa5, 0x2f, 0xe7, 0xf0, 0xee, 0x4c, 0x55, 0xcd, 0x8a, 0xa7, 0xdc, 0x4c } }, +{ "\x01\x98\x3c\x23\x59\x11\xf1\xec\x7f\x84\x1e\xf7\xe1\x31\x30\x7f\x2b\xe7\xb4\x18\x6e\xe7\x8b\x69\xed\xe7\xc9\xf7\x84\x32\x30\x1c\xb6\xec\x44\x16\x51\x74\x0b\x3b\xc0\xe2\x63\x4b\xed\xaf\xff\xde\xd0\x74\x00\xfc\x99\xcb\x2c\xcb\x76\x52\xcd\x63\x01\xce\x28\xbe\x4a\x6b\x99\xcb\x7c\x21\x48\xa1\x2e\x33\x8a\xd0\x48\xd2\xd6\xd4\x90\xde\x61\xa3\xd0\xcc\x59\x65\xa6\xa2\xbb\x44\xe8\x1f\xd2\x59\xb1\xf9\x4d\xc5\x0d\x3e\xfb\xe1\x3d\xdc\x25\x8d\xa7\x3c\x88\xa5\x5d\x08\xed\x92\x48\x0e\x67\xfc\xf0\x3c\x29\x9d\xeb\xcb\x01\x31\xe1\x79\x75\x8a\x37\xee\x78\xbf\x60\x40\xc9\x84\xbc\x92\xe9\x95\x2b\xd7\xb7\x4d\x33\xb4\xa9\x53\xca\x84\xa9\x73\xc0\x75\x8a\x8b\xcb\xcf\x25\x9c\x31", 165, { 0x92, 0x9b, 0xb5, 0xb5, 0x6a, 0x86, 0x10, 0xb0, 0xb7, 0xe5, 0x9a, 0xc2, 0x89, 0x26, 0x9a, 0x48 } }, +{ "\x55\x14\x00\x0c\xc4\x0a\xbb\x3d\x78\xce\xe9\xf0\x2e\xd2\x57\xc7\xe4\x74\x2e\xa5\xdd\xd0\xca\x1a\xc1\x40\xaa\x66\xe0\x71\x7f\x2c\x97\x23\x67\xb4\xcb\x7c\x33\xdd\x93\x0a\xe4\x9d\xf2\x54\x35\x36\xc1\x1b\x52\xf8\xac\x32\xa6\xad\x53\xf7\xd2\xa4\x90\x6d\xb9\x5d\xd8\xf7\xb8\xce\xba\xb3\xf3\x50\x85\x71\xcb\x29\x07\x4f\x6b\xb6\x6f\xf3\x82\x35\x54\x63\x0b\x2d\xce\x84\x47\x7a\xc2\x2d\xcd\xf9\x3c\xe7\xb7\xcc\xf5\x43\xfe\x4a\xf3\xd8\xe0\x86\x50\xd8\x7d\x7a\x12\x4e\x82\xd1\x39\xf7\xfc\x4e\xd8\xba\x4e\xdc\x5b\xc4\x3e\x32\xe7\x44\x29\x22\xdf\xc0\x57\x7f\x82\x13\x69\xa9\xb1\x03\xef\xb7\xce\x83\x16\x3f\xc1\x82\x7e\xc4\x14\x6d\x2a\xbd\x3e\x48\x91\x3e\xfd\x64\xd1\x46\xdc\xbe", 166, { 0x34, 0x76, 0xd8, 0x8f, 0x60, 0x2b, 0x1e, 0x31, 0x24, 0x84, 0xf7, 0xc0, 0x6c, 0xe6, 0x88, 0x4d } }, +{ "\x03\xa4\xd4\xf4\xa9\x86\x0f\xe5\x44\x9f\xc7\xe3\x03\xf4\x4d\x97\x95\x44\x26\x72\x1f\x12\x50\xcc\x4a\x50\xa2\x9b\x73\xa9\x51\xd0\x06\x6b\x8f\x51\xe5\x10\x4d\x8f\x01\x68\x22\xc5\x0c\x64\x44\xcc\x45\x81\xb2\x9c\x72\xce\x74\x63\xec\x9c\xfa\x3b\xd4\xc2\xa2\x8c\x64\x8a\x55\xfe\x60\x3c\x51\x18\xaa\x44\x01\x7a\xf5\x02\x07\xb3\x92\x2f\x5c\xc0\x66\xe7\x8f\x22\xfd\x57\x29\x9b\xb7\x03\x32\x84\x20\xb4\xcc\xce\x5e\xfd\xfc\x93\xc3\x69\x89\x58\x82\x43\xfd\xe2\x7f\x02\xc8\xb1\x3f\x4e\x84\x1d\xff\xb3\x54\x0c\xe0\xe1\x65\x4e\x3f\x9d\x96\x95\x23\x48\x34\x14\xd0\x0a\xde\xb2\x78\x9b\x88\xeb\x11\xae\x9a\x44\x42\xfa\x38\x69\x77\xe6\x9d\xe4\x13\xd0\xa0\x7c\xc5\xfa\x59\x28\xf4\x11\xdd", 167, { 0x8e, 0x0a, 0xc8, 0xfc, 0x3e, 0xdd, 0xb3, 0xf5, 0x3b, 0x8d, 0x4d, 0xfd, 0xac, 0xbe, 0x7e, 0x2e } }, +{ "\xae\x54\x5b\x24\xdd\x9a\x7d\x0c\x63\x4c\xe7\x77\x4c\xb1\xdd\x8f\x18\xe8\x22\x29\x77\x15\x43\x47\xa3\xb6\x7d\xb8\x5a\x14\x4c\xda\x77\xd4\x91\x80\x2c\xad\x5e\xee\xde\x34\x62\x01\x9d\xd2\xec\x6c\x3f\xd8\x9d\x1c\x18\xa9\xaf\xbd\x57\x15\xdc\x56\x00\xc7\xec\x10\x81\xd4\xde\x14\xf4\x73\xb2\x91\xf0\xcc\xd1\xdd\x0c\xe9\x1a\xb3\xf1\xc9\x8a\x9b\x1b\x93\x87\x67\x2c\xe8\xc9\xd9\xed\x51\xe6\x62\xe2\xd8\x78\x05\x88\xb2\xec\x5a\x2d\x19\xea\xaf\x6c\x38\x5c\x49\x44\x40\x1e\xc8\xd5\x98\x40\xa8\xb6\x31\xfa\xe4\xf5\xf7\x2d\xb5\xac\x63\x92\x78\x3c\x2d\x81\xad\x29\x1f\x60\x1b\x92\x05\xa6\x12\x4b\xc1\x8b\xc8\x99\x7b\x4e\xe5\x89\xf5\x22\x1a\xed\xfc\xb6\xec\xf4\xfa\x60\x8f\x65\xa9\xe5\xed", 168, { 0x77, 0x8c, 0x9e, 0x7c, 0x8c, 0x2b, 0x00, 0xa3, 0x26, 0x62, 0x11, 0x70, 0x3a, 0xe1, 0x62, 0x5b } }, +{ "\x78\xe2\xe7\xc6\x51\x93\xec\xf1\x19\xcf\x07\xc0\xbb\x00\x25\x81\x38\x37\xf5\x21\xa8\xa4\x75\xec\xce\x21\x16\x6f\x56\xe8\x8b\x7f\xad\x66\x33\x52\x7d\x27\x21\xca\xc4\xf0\xc4\xd2\x90\xeb\x38\xe1\x59\xfd\x28\x9c\xfb\x34\x5d\x98\x4e\x5c\xe8\x3d\x64\xb1\xe8\xc6\x5e\xae\xf9\x64\xeb\x04\x39\x82\x5e\xa6\xf8\x24\x6b\x01\xfc\x69\x7f\x49\x6d\x2f\xb9\xef\x63\xd5\x88\x2e\x0b\x1b\xe2\xc5\x70\x26\x1d\xbf\xec\xa1\x6e\x6e\x2a\xfd\xfd\x76\xd6\xd8\xa1\x05\xe4\x7b\x3d\x20\x7a\x7e\xb6\x19\x7b\x86\x90\x1d\xb1\x2f\x24\xe9\x96\x04\x80\x9d\xbf\xab\xdb\xa9\xe6\x1e\xb3\xe4\x92\x14\x85\xbb\x65\x7e\x28\x86\x02\x2d\xc7\xf6\x99\x90\x79\xab\x10\x9b\x7f\xe2\xcf\xc4\x19\x4c\x28\x27\x05\xf9\x62\xca\x95", 169, { 0x0c, 0xf1, 0xe5, 0x46, 0x88, 0x85, 0xe9, 0x7a, 0x00, 0x08, 0xbf, 0xe5, 0x0b, 0x81, 0x55, 0xec } }, +{ "\x73\x61\xfa\x6c\xe8\xf3\xd4\xd4\x7f\xb9\xe0\xbf\xcb\xb0\xd7\x59\x5d\x5b\x85\x46\x73\x8f\xc9\x7d\xcf\xda\xba\xc0\xa3\x91\xe4\xb7\xa8\x75\xb0\xa8\x4e\x01\xe1\xd6\x0e\x53\x3b\x73\xdb\xb4\x3e\x42\xb6\xc6\x10\xce\x61\x49\x78\x40\x2b\x8a\x06\xe1\xea\x68\x51\x2d\x07\x04\x59\x90\xb3\x04\x0a\xc0\x38\x84\xe2\xb6\x6a\x9b\xa9\x4a\x3c\x85\x5f\x6a\x6f\x72\x34\xf6\x64\xea\xb1\x3b\x13\xdb\xf4\x0b\x14\x41\x18\x75\xdb\x70\xb3\x27\x01\x01\x79\x5c\xbd\x57\xfd\x83\x71\xcc\x98\x6e\x61\x7d\x62\x33\x7e\xaf\x5d\xa3\x60\xdd\xb2\x64\x53\x5f\x13\xae\x88\xb8\x3f\x9e\x6d\x7c\xa4\x3a\x17\xdc\x1e\x02\xda\xd0\xde\x2f\xfb\xe0\x66\x8b\x7d\x8e\xb0\xec\x17\x63\x6e\x4e\x47\x95\x6d\x8c\x80\x51\x13\xbb\x7f\xab", 170, { 0x46, 0x56, 0xb9, 0xc5, 0xa9, 0x38, 0x86, 0xec, 0xb8, 0x20, 0x03, 0xdb, 0xb1, 0xc2, 0x84, 0xd8 } }, +{ "\x07\x23\xbc\x20\xef\xdb\xfb\xc4\x54\x00\x01\x0c\xa3\x92\x64\x3a\x4d\xeb\x7c\x61\x0d\xdc\x76\x14\x49\x65\x87\xaf\x92\x11\x3c\x41\x46\xec\xf0\x15\x55\x22\x58\xdc\x20\x36\x38\x78\x7d\xdb\x38\x67\xd7\x72\xd1\xca\x73\x21\x62\x11\xcd\x8c\x5f\x45\x21\x33\xa8\xf2\x05\x68\xf8\xaf\x33\xeb\x74\x4c\x65\x24\x63\x96\x59\xfc\xfd\xc9\xf4\x58\x5c\x93\x83\x32\x8f\xc1\x1c\x56\xce\x88\x23\xb7\xc7\x72\xe8\x6c\x17\xe4\x6e\x4a\xd4\x48\x47\x1e\x47\xdb\x9a\x87\xb7\x14\x47\x6e\x60\xb0\x21\x24\x83\x57\x5a\x16\x97\xec\xfd\x2f\x9d\x76\x94\xca\x91\xa6\xe9\x53\xfc\x04\xea\x79\xa6\xba\xa5\x11\x69\xfd\x73\x8a\x21\x14\x32\x09\xc0\x06\xab\x21\x7e\xe4\x12\x30\x2d\xb0\xab\x59\xaa\xe9\x89\x19\x70\xb4\x71\x88\x46", 171, { 0xea, 0xdb, 0xc3, 0x9a, 0xf7, 0x45, 0x25, 0xa6, 0xbb, 0x14, 0x02, 0x97, 0x30, 0xae, 0x75, 0xc7 } }, +{ "\xa9\xde\x2f\x19\x37\x1e\x80\xe4\xb4\x9a\xf6\xcb\x04\x33\xca\x48\xe5\xc7\x4f\x7c\xd6\xd2\xea\xa7\xa2\x31\xb2\xb3\x8d\x02\xa0\xeb\x19\xa8\x73\xc9\x75\xeb\x23\xec\x83\x3c\xff\x28\x85\x15\x65\xb8\x63\x7f\x1e\x8e\x9b\xad\x54\xcb\xc5\xc6\x30\x4a\xc2\xc0\x14\x57\x81\x68\x72\x7e\x6d\x7e\x47\x7d\x77\xfc\x38\x5b\xbb\x77\x47\x92\xd1\x9f\x32\x67\xb3\xe1\x68\x5b\x46\x2b\xa8\xba\x87\xcf\x39\x50\x53\x81\xc0\x3b\xd2\x7b\xc1\xdc\x82\xc0\xb5\xe7\xdc\x7c\xc3\x9a\xa4\x8a\x1f\x0b\xd2\x10\xfc\x99\x18\x45\x2f\x84\x10\x53\x61\x99\x04\x58\xf1\x06\x59\x86\x64\x4c\x98\x69\x89\x51\x1a\x48\x2e\x95\x50\xa5\x78\x7d\xac\xe0\xe3\xcb\x30\xf8\xd7\x2f\x91\x70\xe3\xf6\x07\x50\x98\xe1\xb4\x42\x04\x11\xae\xdd\xca\x1d", 172, { 0x6d, 0xb0, 0x2c, 0x2a, 0xe2, 0xf9, 0xc9, 0xa2, 0x0a, 0x36, 0xf9, 0x94, 0x5f, 0x28, 0x33, 0xf3 } }, +{ "\xab\x00\xdb\x46\x48\x54\xd3\xc2\xf6\xf3\xf2\x34\x82\x27\xb5\x3d\x3f\x4a\x10\x2c\xd1\xcd\x4b\xd1\x99\x55\x76\x6f\xb8\x00\x8a\xcf\xc2\xc6\x1e\x71\x01\xfa\xc3\xde\x63\xee\xfc\x19\x01\xb6\xdd\x34\x4c\x06\x3f\xfe\xd6\x35\x9d\xda\xba\x62\x8e\xab\xaa\xb5\xdf\xeb\x93\xbf\x4c\xdb\xef\xfb\xdb\xd4\xa6\x76\xd6\xbd\xa2\x8a\x63\x96\xee\xc6\xc1\x30\x89\xea\x21\xff\xcd\x0d\x1f\x08\x77\xe1\xdb\xf4\x52\x0f\xb8\x47\x85\xbc\xb1\xaa\x75\x2d\x53\x64\x58\x87\x5b\xe7\x58\xaf\xec\x87\x5f\x50\x6c\x45\x85\xfb\xfd\xca\x14\x68\x93\x6f\x34\xda\xb7\x79\x38\xa1\xd7\x62\x83\xb9\x47\x52\x18\x90\xd8\xad\xbe\xe5\x13\xc5\xcc\xcc\x13\xb0\x96\xce\xfc\x35\x74\x2d\x1c\xe0\x6c\x44\x9c\x35\x7b\x0d\xe2\x01\x85\xbd\x87\xcc\xd6", 173, { 0xfb, 0x6c, 0x0f, 0xbd, 0xe3, 0x87, 0x1b, 0x0a, 0xb2, 0x35, 0xf1, 0xb1, 0x53, 0x60, 0xd6, 0xd2 } }, +{ "\x8a\xf0\x6a\x54\x8c\x8b\xb1\x44\xc1\xa8\x44\xb5\x2b\xf1\x8e\x8c\x14\x88\xcb\x2d\x72\xbb\x40\xc3\x65\x66\x8b\x2d\xdc\xe6\x15\x86\x58\xb5\xa3\x4e\xc9\xa7\x0c\x3a\x94\xc0\x05\x94\xb6\xb0\x18\x50\x02\xec\xb3\xad\x86\x69\x5d\x84\x0c\xf7\x03\x31\xbc\x39\x71\x1b\xdf\x3d\xdc\xe1\xbe\xbc\x9b\x22\xa8\xef\xf6\xe9\x13\x0b\x17\xb4\xda\x5b\x1e\x1f\xa5\xf9\x50\x32\x67\x29\x6f\x44\x00\x52\x24\x89\x02\x9a\x99\x3f\x90\x1d\x23\x72\x62\xc9\x1d\x67\xe6\xd9\xd0\xab\x81\xeb\x8e\xb8\xf3\xc0\xde\x40\xd9\x90\xd1\x19\x4b\x08\x73\xc6\xa5\xe1\x5d\x9e\x64\x1e\x68\x9c\x26\xe2\x7c\xc2\xd3\xeb\x86\x2a\xdb\xaf\x87\xaa\x95\x11\xc9\x23\xc7\xc0\x2e\x66\x43\x2d\xa1\xc4\xae\x26\xad\x31\x5c\x14\x2c\x14\x57\xcd\x17\xae\x7f\x17", 174, { 0xf9, 0x28, 0x28, 0x66, 0x7b, 0xe7, 0x4e, 0x18, 0xda, 0xce, 0xe9, 0x8d, 0xff, 0xab, 0x12, 0x98 } }, +{ "\x7d\x24\xcb\xba\x8f\x2a\xad\x41\xd8\x4e\x94\x4d\x89\xdf\x8b\x95\xf2\x78\xff\x7d\x0d\x2c\x9d\x52\x35\x4f\x5a\x20\xf4\xdf\x8c\x30\xf9\x8e\x35\x22\x28\x6d\x61\xa3\xcc\x36\xa5\xca\xe8\x36\xc7\x14\xab\xd5\x7c\xfa\x01\xc4\x4c\x2d\x46\xc1\x92\x6e\x15\x0a\x9f\x0b\x3f\x5c\xff\xf9\xd8\xa6\xd3\x8b\x6b\x4f\x5d\xcd\x4d\x21\x9b\x7f\x0f\xd0\x0a\xb1\x0d\x2b\x8b\xf8\x23\xde\x63\x4a\x7f\xe1\x5d\x7b\x92\x81\x0a\x55\x21\x09\x29\x4d\x78\x0d\x21\xe8\xbd\x52\xaa\xaa\x62\x5d\x8c\xb6\xb4\x97\x80\x07\x91\x19\x33\x49\x36\x1a\x68\x55\x36\xf2\x3c\x48\x87\xca\x85\x3f\xb7\xe3\x54\xb0\x3c\x7f\x9a\x68\xe8\x6f\xe7\x1d\x7b\x3a\x4d\xaf\x53\xe7\x63\x00\x3e\x68\x66\x6c\x70\xa3\x79\xe7\x90\x1e\x0d\xb2\xec\x45\x5b\xba\xcd\x5b\x0e", 175, { 0xeb, 0xa1, 0xc8, 0x38, 0xbc, 0x82, 0x3d, 0x39, 0xc0, 0x92, 0xec, 0xdb, 0xa3, 0xa7, 0xc6, 0x56 } }, +{ "\x8d\xe6\xfb\xff\xf9\xe6\x4a\x18\x43\x2d\xbc\x59\x01\x9a\x7f\xf9\x95\x83\x87\xa4\x46\xbe\x37\xe3\xfc\xdc\xa9\x9a\x98\x76\x9a\xaa\xee\x9f\xf5\xb7\x60\x79\xfa\x04\x18\xe3\x0b\x79\xe1\x50\x13\xc7\xa2\xb3\x93\xa2\x79\x96\x4b\x2d\x70\x4a\x81\x74\xdf\x39\xf1\x12\x5e\x57\x51\xf3\x64\xb7\x7f\x34\x81\x3a\x49\x27\x34\x62\xd9\x72\x6a\x44\xbb\x56\x94\x9c\x8c\x0e\x63\xfb\x42\x4e\x23\x1b\x12\xea\xb1\x53\x02\x98\x1a\x25\x0b\xce\xd2\xf5\xea\xc5\x8e\xd5\x83\xa0\xbe\x7b\xf2\xa5\xaa\x54\x30\xa9\x28\xb1\x5f\x8b\xf8\x1f\xb3\xd6\xbc\xd6\xfc\x8a\x96\x47\xd3\xf5\x60\xd8\x61\xba\x83\xac\xc7\xf3\x74\x9b\x2d\x73\xd1\x41\x6b\x24\x14\x32\x4d\x8f\xf1\x4b\x86\x7b\x52\x24\x35\xac\xed\xa1\x0c\xcc\x7e\xa8\x23\x68\xa6\xed\x58\x11", 176, { 0x48, 0xe5, 0x26, 0x3b, 0x57, 0x15, 0x53, 0xb3, 0x89, 0x25, 0x12, 0x09, 0x49, 0xd9, 0xd6, 0xd2 } }, +{ "\x60\xe8\x60\xa3\x1c\xe8\x6f\xa2\x7a\x41\x80\xbf\xa4\xa1\x41\x7b\x48\x81\x9e\xe3\x31\xb7\xe9\x79\x81\x27\xa3\x33\x8d\x9a\xea\x9c\x55\xa7\x7e\x19\x9e\xcd\x71\x47\xae\xa3\x6b\x7f\xa3\x26\x97\x7b\x71\x32\x2e\x12\x76\x0c\x9e\x1f\xbc\x1c\x56\x80\xca\xb8\x31\x3a\x27\x1b\x7c\xba\x6c\x74\xa6\x36\x05\x1b\x83\x32\x84\xde\x3d\x1f\xa1\x7a\xd7\x1e\xd2\x25\x5f\xe2\x83\x48\xb0\xb3\xf3\x4a\xe1\x8e\xab\x88\x4e\x69\x9b\x60\x41\x95\xd2\x6d\x3c\x3d\xd9\xcd\xe5\x0b\xad\x9d\x8e\xea\x58\x86\x60\xe6\x2b\x71\x25\x2f\x9a\x56\xaf\x3c\xb4\x32\xe7\x0b\x3d\x17\x75\x87\x69\x5d\x09\x03\x38\xf6\x45\xe3\x69\xdf\x47\x5b\x1c\xb3\xd6\x4e\x07\x5a\x28\x58\x54\xde\x4d\xe7\x16\x5e\x3c\x84\x67\x1b\x78\x30\x1f\xaf\x5f\xe9\x33\x5e\x0f\x4c\xa7", 177, { 0x3d, 0x14, 0xce, 0xb4, 0x3a, 0x69, 0xc6, 0xb9, 0x35, 0x2a, 0x07, 0x20, 0x11, 0x8a, 0x7d, 0x87 } }, +{ "\x85\xf5\x54\x31\x2f\xf4\x40\x6c\xc7\x2e\x93\xb5\xe7\x71\x35\xa6\x4f\x41\xb7\x2d\xf1\x7e\xb4\x48\x28\xb2\x53\x5f\x09\xf9\xe8\x3d\xd2\x8d\xba\xad\x80\xed\xdf\xad\x7c\xaa\x44\x51\x75\xce\xc9\x37\x49\xe9\x89\xa3\x1c\xb9\x37\x37\x8c\x75\xa3\x50\xfb\xb6\x5c\xff\x0b\x03\x70\xa2\x28\xf7\x4f\x1f\x3e\x11\xce\xbc\x8c\x18\x47\x9e\x90\x29\xdd\xdd\x22\x5f\xdd\x40\x9d\x1d\x40\x9a\x37\xfa\x4d\xc0\x72\x4a\x5b\x25\xab\x45\xb4\x15\xd0\xd7\x96\x8a\x2f\x03\x53\xae\x69\xf4\x98\xee\x85\xa2\xca\xb7\x21\x1d\x8c\xd0\xc3\x7a\x5d\x54\x4d\x57\x5f\x4a\x8f\x0c\x32\xe3\xf7\x6f\xff\x4f\x63\x44\x91\x3c\x17\x40\x9d\xec\xca\xb8\x22\xf1\xdb\xeb\xeb\x88\xa1\xe8\x32\x90\xdf\x1d\x5f\x25\x57\x7e\xed\xde\x75\x4e\x6e\x9f\x2c\x8d\xa5\x1b\xde\xff", 178, { 0xaa, 0x31, 0x4b, 0xfa, 0x31, 0x2f, 0x20, 0xf7, 0x63, 0xcf, 0x19, 0xbd, 0x14, 0xf2, 0xac, 0xda } }, +{ "\xd1\xe9\x75\xd4\x09\x42\x8f\xf9\xc2\x55\xd6\xfa\x6e\x47\x6d\x92\x3f\xca\x86\xd1\x09\x59\x10\xe8\x46\x0d\x8e\x94\x33\x1f\x03\x25\x17\xfb\x09\x2a\xa3\xfd\x02\xbb\x75\xca\x65\x63\xb7\x4e\x3a\xa7\xe4\x4d\xa1\x37\xab\xa8\x8b\xb1\xec\x2f\x8c\x0c\xdf\x1d\xc9\xa7\x54\x34\x0c\xee\x14\x76\xf6\xa6\x67\x7d\x54\xd7\xaf\x77\x8a\x53\x32\xc2\x2b\xe6\xf5\x20\xab\x1c\xc3\x97\x2c\xa9\x4d\xe8\x74\x79\x6b\xa9\x00\x55\x81\x01\x32\x2e\xfc\x00\xa5\x0a\xfc\x99\xa1\x88\x0c\x3d\xaa\x11\x0c\x14\x33\x9d\x30\xda\x70\x1f\x21\x55\x49\x8f\x41\x6e\x6a\x92\x0c\xf3\x77\xc7\x9a\xe8\x5d\xb0\x40\x86\xc4\x3b\x56\xd1\xa0\xec\x14\xd9\xe7\xaa\x96\x8d\x5d\x23\xff\x36\x8a\xdc\xb9\x98\xce\xd8\xda\xa0\x8b\xe4\xa2\xc9\x80\x7d\x21\x12\x36\x5f\xf6\x94\x92", 179, { 0x24, 0x4a, 0x76, 0x30, 0xfe, 0x50, 0x3c, 0xd3, 0x96, 0x8d, 0xed, 0x72, 0xd2, 0xd1, 0x92, 0x63 } }, +{ "\xac\x31\xc2\x8b\xb5\x5a\x42\xf6\x67\x8b\x62\x7d\x55\xb8\x38\xaf\x5d\x0f\x5b\x31\xfa\x7a\x38\x11\x26\x42\x11\x3b\xea\xcd\x98\x04\x83\x88\x24\xe4\x32\xe0\x8e\x41\xa1\x69\xab\x66\xed\x22\x65\x92\x54\xd0\x78\x2d\x7c\x86\xc6\x16\x5e\x46\x58\x17\xcd\xc2\xf2\x7a\xa7\x3b\x52\xb5\x97\x8b\x05\x40\x84\x3d\xe5\x87\x99\xda\x32\xfb\xf2\x3f\x4c\x43\xe0\x29\x0a\x91\xd9\xd3\xbb\x0f\xff\xb6\xb7\x77\x4b\x6f\xa0\xc2\x56\xbf\x3a\xf8\xc4\xac\xe4\x26\x4d\xc4\xb3\x6e\x69\x81\x2a\x38\x97\xc8\x97\x87\x4b\x8c\x0c\x66\x72\x90\xf9\x80\xa3\x49\x63\xcf\xe3\xe1\xc3\x6d\x15\x58\x7d\x86\xfc\xc5\xfb\x6f\xee\xbb\x66\xcf\x18\xc6\x01\xfb\x68\x15\x22\x60\x1b\x31\xcd\x19\xe3\xeb\xee\xa1\xb4\x55\x33\xa2\x2b\xe6\x84\xec\x9b\xc1\x20\x81\xb6\x0f\x55\xcd", 180, { 0x74, 0x83, 0x94, 0xea, 0x7a, 0x82, 0x27, 0x87, 0x79, 0x88, 0xa8, 0x23, 0x8f, 0xc2, 0x4e, 0xaa } }, +{ "\xd5\x88\xdb\xf3\xe4\x11\xce\x42\xed\x80\x47\xc6\x3f\x7b\x96\xfb\x3b\x7e\x1d\x9d\xba\xfb\xcc\x9b\x1e\x9b\x34\x29\xf4\xa3\x4a\xf4\x43\x72\xbb\x71\x74\x26\xe6\x4f\xdd\x5f\x7b\x0b\xec\x1b\xae\xa1\xec\xc0\x17\x60\x77\x39\x29\xd7\x79\x38\x4c\xeb\xdc\x99\x9a\x0a\xd5\xe7\x33\x7a\xca\xf7\x3e\xcb\xdf\xb2\x7c\x6b\x1c\xf1\x8a\x58\x3c\x81\xb3\xf0\x15\x45\x6f\xe4\x9f\x7b\x7d\x4b\xa2\x17\x98\xd3\x00\x4b\xd9\x12\x9c\x28\xa8\xfa\xe6\x5e\x60\x6b\x05\x1f\x7f\xe3\x9f\x22\x86\x50\x48\xc4\x73\x06\x84\x48\xd9\xcc\x7b\x3f\x99\x11\x38\x03\x3f\x3c\x9d\x5d\xfb\x21\xe7\x47\x3a\x8f\xda\xcb\xe0\x06\x89\x0a\x24\x86\xc4\x58\x09\x82\x1e\x85\x75\xf4\x99\x37\xf0\x8a\xf0\x72\xfa\xfe\x81\x3a\x08\x83\xd6\x50\x1d\x5b\xcf\x17\x02\x85\x6d\x9a\x22\x94\x3d", 181, { 0x15, 0xb7, 0x30, 0xcc, 0x2e, 0x0b, 0x5f, 0x0f, 0x3f, 0x7d, 0x9a, 0x52, 0x62, 0x75, 0x4d, 0x08 } }, +{ "\xa7\x04\x9b\x5f\x13\x65\x45\x32\x21\xf1\x01\x9e\xfe\x9e\x5a\xfd\x63\xa5\x64\xa6\x5d\x1e\x52\x18\x29\x38\x25\xc0\x39\x12\x7f\x67\x53\x38\x96\x3b\xd9\xbd\x44\x78\x23\xf1\x3a\xb3\x08\xbf\x55\xc3\x7c\xa6\x09\x4c\x53\x52\xf9\xe9\x24\xd6\xa9\xf6\x48\x88\x4b\xf7\x02\x7a\xb5\xa8\xb9\x90\x74\xa1\x60\x43\xfa\xa6\xf6\xf1\xf2\x89\x29\xde\xb5\xbc\x16\xcb\xd4\x77\x2b\x31\xd5\x82\x2e\x1a\xfc\xa0\x56\x9d\x3e\x98\x97\xf4\x5b\xe1\xfb\x3b\x04\xe9\x2c\xc7\x37\x02\x0e\x21\xac\xe9\x89\x9e\x67\xf5\x64\x9c\x6e\xd9\x4d\x5b\x95\x15\xf5\x75\x75\xff\x58\xfb\x7b\x6a\x1a\x2e\x1c\xf0\x0d\xd7\x26\xe2\xcf\x44\x32\xc8\x91\xdf\x36\x96\xf2\x6c\x37\x6e\x09\xde\x1b\x0c\x82\xd7\x9c\xd3\xdf\xbb\x59\x71\xe0\x70\x07\x31\xfe\xb4\xc4\xdd\x10\x1a\x8c\x4d\x11\xa2", 182, { 0x96, 0x00, 0xc5, 0x60, 0xaa, 0xdd, 0xfd, 0x65, 0xc4, 0x77, 0x58, 0x7b, 0x27, 0x5e, 0xcd, 0xef } }, +{ "\xc4\x90\xf9\xf4\xf4\xb6\xc7\x39\x92\x39\xa0\x96\xf9\x06\x11\x46\x79\x2b\x71\x53\x87\x1e\x62\xf1\x15\xa7\x76\x77\xfd\x6b\xed\xfb\x96\x17\x9d\x88\x69\x25\xeb\xfe\xfe\x4e\xf5\x87\xcf\x8c\xd2\xb2\x5e\xcb\xf1\x2d\x62\x2b\x9e\x23\x1d\xf4\xa3\x30\xc9\x17\x0b\xfd\x30\x5d\x01\x7d\x5b\x2f\xd8\xc3\x62\x00\x24\x7d\x62\x5b\x05\x11\x8d\x84\x84\x52\x5c\xce\x15\xdf\xdf\x79\x3c\x18\x34\x45\x4d\xbe\x16\x97\x4b\x26\x8d\x47\xf2\x1a\xc3\x04\xd1\x4d\xf7\x65\x8e\x78\x8b\x8c\x4d\x15\x37\x79\x2c\xb7\x60\xe9\xe5\x04\x83\xe8\x97\x51\xcb\xfa\x9e\xd8\xc3\xe2\x9e\x98\x26\x0d\x9f\xc9\xd1\x9e\x52\xfb\xd9\x17\x72\xca\xb9\xa0\x46\x40\xa4\xf7\x43\xc7\xf9\xf5\xce\xc9\xd5\xb9\x1e\xe6\xc2\x73\x40\xd1\x8c\xcf\x34\xc8\x34\xfb\x35\xae\xfe\x57\x16\xc6\xa5\xb9\xc8", 183, { 0xef, 0xfd, 0x81, 0xc1, 0x6c, 0x60, 0x89, 0x07, 0x98, 0xf3, 0x9c, 0xe6, 0x82, 0x4e, 0x17, 0xaa } }, +{ "\x0e\xaf\x59\xf8\x36\xdb\x60\xd5\x3b\xb6\x08\xef\xa5\x4c\x6f\x3b\x59\xfc\xfe\x33\x1b\x65\x70\x1a\xa4\x7c\x82\x5d\x5c\xc0\x36\x15\xb5\x84\xc3\xaa\x24\x6b\x1c\x91\xbc\xf3\x1b\x35\x68\x28\x4a\xf4\xc4\x78\x4e\x40\x99\xa7\xf1\xe6\xf3\xd9\xca\x6b\xe1\xcc\x8b\x92\xc9\x29\xe7\xfb\x65\xef\x1e\xe5\x5e\x0f\x26\x14\x83\x17\x77\xce\xa6\x06\x74\xff\x13\x3e\x71\x7c\xae\x97\x65\x64\xa8\x8f\x2d\xa3\xdd\xa0\x7a\x90\xce\xaa\x59\xb6\x36\x90\x5d\xb0\x4b\xdf\x6b\x2e\x92\xa8\x22\x14\x5f\x6e\xe5\xc1\xe8\x3b\x86\x6d\x05\xcd\x90\xab\x87\xee\x31\x0e\x32\xe1\xc2\xe8\x58\xf8\xf5\x2d\x13\x43\x9a\x77\x1e\x62\x0e\x23\x50\x7c\x40\x98\xb7\x48\x61\xa8\x4d\x48\x28\x0e\x59\x16\xbf\x17\x65\xd7\x4d\x5e\xd8\xcc\x21\xb0\x2f\x07\x78\x0e\xdc\x3a\xeb\xd0\xbb\xab\x78\xe6", 184, { 0xe5, 0xf6, 0xa3, 0x02, 0x8d, 0x9c, 0x95, 0x97, 0xf0, 0x29, 0x88, 0x10, 0x26, 0xed, 0xac, 0x58 } }, +{ "\x2d\x43\x2a\x3a\xd3\xc6\x68\x31\xe9\x1e\xd8\x51\x3c\xd0\xee\xfd\xc9\x90\x15\x5b\xf4\xef\x78\x56\x62\x32\x6d\xbf\x73\x3f\x7e\x8e\x5f\xb1\x16\x47\xec\x0a\xc5\x78\xc9\x08\x30\x5e\x8b\x10\x98\xa8\x41\xc7\x05\x53\xb5\xc0\x0e\xb4\x42\x4f\x48\x94\x4d\x7c\x49\x75\x61\x13\x58\xf3\xeb\xd9\xb2\x46\x8e\xd9\x7b\xe4\x24\xdc\x40\x43\x53\xf6\x25\xbc\xc7\x3d\xb0\x8b\x11\x95\x30\xf3\x1c\xa7\xcb\x7f\x47\xf0\x23\x62\x24\xf5\xa5\x00\xcd\x95\x6e\x86\xde\x77\xd9\xb3\x12\xa1\xa9\xba\x7d\x2a\xd0\x40\x63\x08\xda\x80\xb4\x03\xf9\x8e\x25\xcb\xad\xb9\xec\x24\x10\x09\x18\x3f\xbb\xe7\x8a\x25\x58\xdc\x94\x4c\xc6\x72\x2c\x4c\xe2\x37\xcc\xab\xf8\xdf\xea\xd4\xc6\x89\x0f\x27\x29\x1a\x97\x2a\x67\xc6\x04\xdc\x18\xad\xfe\x2a\xb1\xa1\xeb\x7b\xae\x06\x27\x66\x5c\xd3\xe0", 185, { 0x57, 0xa9, 0xed, 0x9a, 0xe3, 0x2c, 0x62, 0x78, 0x43, 0x4c, 0x1b, 0x41, 0xd3, 0x3c, 0x09, 0xe6 } }, +{ "\x83\x40\xb5\x91\x5f\x27\x52\x19\x89\xcc\xaa\x77\xc9\x1f\x9a\x25\x71\x38\x7b\x0d\xcb\xd8\xe7\x2c\xb1\x97\x9b\xc2\x3c\xb0\x78\x33\x94\x65\xa4\x7e\xe7\x10\xcd\x57\x75\xc8\x8e\xe2\xc7\xac\xea\x0e\xff\xcf\xf5\x8c\x4b\xc0\x91\x6b\x74\xb4\x56\x52\x93\x52\x8b\x59\xe2\x1b\x51\x84\xb0\x75\xe0\xdc\x6e\x52\xe8\x2c\xe7\x81\x19\x55\x8d\x91\xbe\x4e\xee\x5e\x84\xbc\x46\x39\x59\x2a\x2d\xb8\x70\xe5\x71\x17\x60\x77\xfe\x49\x6c\xbe\xfa\x9f\xde\xa8\xed\x14\x8c\x8d\x1e\x32\x7c\x28\xf9\xa5\xa4\x33\xab\x5b\xca\x9f\xd0\x54\x8a\x6d\x44\x0b\x76\x2c\x16\x81\x57\x0f\x9b\xe2\x92\xaa\x9e\xd6\xa6\x49\xb5\x67\xd2\xed\xaf\x8a\xd3\xe4\x29\x4c\xcb\x04\x40\x9a\x3e\x83\x60\xad\x35\x76\x3b\x10\x85\xe4\xd6\x4f\x2a\x87\xbd\x3e\xcc\x1e\x57\xe3\x64\x71\x54\x01\xf8\xe3\x42\x42", 186, { 0xcb, 0x49, 0xbe, 0x32, 0xa6, 0x87, 0x50, 0x00, 0x6b, 0x95, 0x12, 0xf2, 0x40, 0x2b, 0x3e, 0x10 } }, +{ "\x82\xad\x3f\x00\xef\xbd\xc9\xaf\x43\x2a\xb1\xeb\xd9\x52\x2f\x1a\xc8\x92\x0e\xbe\x62\xa1\x08\x5a\xd6\x89\x2c\xfd\xf5\x43\x7b\x6f\x11\xef\x93\xf7\x01\xad\x83\xc7\x42\x1b\xbd\x06\x38\x6b\x29\x78\x92\x1f\x56\xcb\xcb\x64\xcb\x80\xcc\x09\x7c\x73\xae\x1a\x58\x09\x9e\x1d\xff\xf6\xda\xe8\x91\xa8\xd7\x1d\xa2\x54\x85\x44\x49\x9b\xaa\x83\x58\xd8\x6b\xfc\xa6\x09\xea\xc3\x87\x57\x08\x7a\x5d\x43\x4b\x8c\x48\x6f\xdb\x02\xf8\x07\xa7\x05\xa4\xca\xa5\xf1\x13\xb9\x36\x11\xd8\x5a\xa7\xfd\x9b\xa9\xd4\x8d\x91\x9c\xe7\x79\x0d\x52\x3e\x8f\x30\xd7\x6b\x8f\xbd\x96\x54\xa6\x07\x5c\x7b\x85\x0b\x04\x59\x1e\x9a\xc5\xe3\xfb\xaf\x14\x2e\x3b\xdf\x37\x2e\x29\xee\x68\x9a\x7a\x7d\xa2\xec\x23\xe1\x0b\x84\xd5\x10\xfd\xec\x16\xb5\xb2\x36\xfd\x63\x8c\x82\x8a\xe5\xff\x9c\x9f\xb4", 187, { 0x19, 0x6a, 0xcb, 0x09, 0x35, 0x27, 0xb3, 0x8d, 0xd4, 0xcb, 0x04, 0x0f, 0x85, 0xa6, 0x19, 0x58 } }, +{ "\x1c\xc2\x9f\x82\xba\x82\xa2\xf3\x43\xc2\x52\x6b\x18\xda\x65\x02\xa2\xdb\xb7\x94\xf6\xf3\x03\xf6\x24\xe8\x3e\x43\x1d\xc2\x90\x54\x3e\x86\xef\x4d\x7d\x1c\x5a\x54\x2f\x52\xb0\x5d\x73\xf9\x2a\x21\x3f\x2d\x7b\x2d\x05\xb3\x83\x17\x01\x7b\xaa\xcb\x22\x44\xdf\x03\x92\x5e\x2d\xd5\xe4\x8b\xf7\x66\xd9\xff\xd0\xbc\xcf\x87\xf9\xb2\xc7\xc6\x78\x04\x11\x99\xd1\x8a\x96\x9c\x64\x82\xc2\xc6\x62\x06\x0c\x30\x6d\x9c\x23\xf3\xcc\xec\xb6\x2e\x48\x8c\xe0\x27\xa6\xf8\x2f\x89\xc0\x9d\x50\xcb\x42\x14\x58\xb1\xfe\x6c\xb1\xec\xed\xa0\x9f\xdd\xc3\x27\x6e\x78\x2d\xab\x3a\x43\xaa\xd1\x5b\x7c\x03\x37\x6b\x5a\x68\x7c\xf4\x6c\x29\x78\xbb\x1e\x0e\x8c\xa3\x5b\x53\x15\x40\x4c\x43\xfa\xf9\x3d\x6f\x65\xd9\xa1\x8b\x8f\xf2\x2c\xe6\xb3\x6e\x1e\x85\x24\x33\xa0\xdb\x7a\x32\x46\x26\xe8", 188, { 0x6e, 0xa3, 0x09, 0xda, 0xde, 0xad, 0x44, 0xc1, 0x7b, 0x3f, 0xcd, 0x70, 0x94, 0x3c, 0x2a, 0x39 } }, +{ "\x4d\xb5\x68\xa9\xe3\x5e\x00\x99\xf9\x68\xe5\xe0\x06\xac\x80\xc9\x5b\xda\x23\xb1\x2d\xb9\x29\x1a\x40\x8b\xaa\xdf\x32\x8e\xdb\x82\x62\x9f\x01\xa1\x7b\xfa\x10\x88\xa1\x1c\xe4\xdf\x36\xc9\x1b\x84\x49\x2a\x8d\x74\x9b\x0e\x69\xe2\x50\x51\xed\x6a\x2f\x5a\xc1\x5f\x96\xbd\xf1\x40\xfd\x02\x85\x4a\x24\x7d\xbf\x27\xdc\x5c\xf1\xc4\x6f\xbf\xf8\x40\xae\x01\x59\x00\x95\x16\xf6\xdf\x9c\x0d\x6c\x83\x9d\xb4\x0c\xcb\x5c\x5a\x75\x64\xb8\xaf\xcb\x7b\x6d\xc8\x96\x8c\x84\x3f\x39\x59\x58\x78\x0c\xf7\x45\xfe\x19\x02\xee\x0b\x70\xf1\x2b\x26\x27\x84\x8e\xe7\xf2\x5a\x90\xd6\x5b\x9f\x5d\x72\x9e\xe2\x39\x4d\x23\x04\x8d\x54\x98\x4c\x92\x2d\xaa\x98\x99\xb9\x61\xaf\xf4\xb9\x16\xb1\x85\x8c\x11\xaf\xe1\x16\xc3\x57\x1f\xbd\x9c\xc8\x43\x8d\x8a\x84\x42\x7b\x10\x83\xb2\xc7\xfe\x64\x10", 189, { 0x84, 0x35, 0x9a, 0xad, 0x8c, 0xa1, 0x8d, 0xfc, 0x2a, 0xaf, 0xbc, 0xa9, 0x59, 0x79, 0xf1, 0xae } }, +{ "\x7a\xd3\xbf\xad\x0f\xab\x95\x35\x2e\xe6\xe9\xdd\x93\x58\x68\x29\x0e\x26\x43\x57\xa3\x43\x1e\x6b\xd1\x87\x20\xd8\xf0\x69\x2b\xc8\xb3\x59\x25\x08\xce\xbd\x75\x93\xb1\x85\x8a\xba\x71\x6d\x95\xec\xc8\xcf\x57\x28\x33\x22\x14\xfc\x39\x13\xa7\x38\xcc\x3e\xaf\x34\xc8\x89\xe7\xbb\x98\x1d\x94\x93\xf8\x02\x17\xaa\xd5\x56\xa2\xdf\x50\x2a\x07\x69\xe1\xf9\xac\xe8\x98\xc6\x9b\x06\x7f\xd1\xb6\xca\x1c\xf5\x08\x79\x13\xa1\x36\x29\xe7\x71\x14\xe3\xe1\x68\x53\x74\x09\xcc\x59\xd0\x51\x9f\x29\x24\xd2\xb5\x81\x77\x2d\x77\x03\xfc\x14\x32\x8b\xf6\xe1\x1c\x9f\x48\x63\xe5\x04\x98\xba\xf6\x6d\x1f\x58\x4a\x4f\x11\x27\xe5\xd0\xa3\xc9\xf4\xdd\xbd\xfb\x83\x5a\x3e\x13\xd5\x75\xe6\xa8\x63\x14\xe5\x50\x74\x6c\xfd\x84\x55\xb3\x56\xa0\x36\xed\xde\x07\xa1\xe3\x5a\x64\x97\x33\x0e\x0b\x49", 190, { 0x15, 0x6b, 0xec, 0xbe, 0xf4, 0xb1, 0x19, 0x29, 0x9b, 0x9c, 0x5a, 0x59, 0xd9, 0x1c, 0x8f, 0x68 } }, +{ "\x80\x05\x7d\x70\xc9\xfe\x0a\x49\xd8\xf3\x91\x31\xd1\x47\x63\xd8\xea\x8b\x46\x25\x39\xed\x95\xa6\xa8\x3d\x85\xb2\x06\x9d\x82\x1e\x38\xc5\xb8\x98\x8d\xf0\xad\xa3\x2f\x67\x0b\x2f\xb4\xa8\x7c\xd4\xd4\x33\xae\xab\x36\xf0\x76\xc9\x63\x40\x10\x59\xdc\x9e\x84\x55\x46\xf2\x25\xe1\xc3\x72\x34\x44\x5d\x35\xa1\x83\x9c\x56\xf1\x9c\x37\xc1\x3b\x5c\xe7\x9d\x4c\xdd\x56\x56\xea\xa0\x37\x45\x36\x43\x6f\xff\x2a\xdf\x70\x37\x42\x00\xa7\x51\x38\x42\x0b\x84\xe7\x84\xd6\xaa\x51\xcc\x51\xa7\xbc\xb7\xc7\x74\xf7\x9b\x9b\xc7\xba\x3b\x76\x61\x2b\x25\x98\xf3\x7d\xac\x50\xae\xb3\x7e\x87\x66\x83\xe1\x76\x61\x55\x8e\x78\xc2\x6a\x2a\xf9\x8d\x1a\x5d\x8e\x56\x36\x91\x1f\x8b\x8c\x49\x3f\x5a\x88\x1b\x9c\x40\xf7\x4c\x92\x30\xe7\x06\xda\x5c\xab\x38\x5f\xa2\xfb\x0a\x31\x96\x37\xfc\x92\x28\xcc", 191, { 0xaf, 0x3e, 0x62, 0xef, 0x2b, 0x45, 0x27, 0x17, 0x20, 0x4f, 0x50, 0xb2, 0xb9, 0xa7, 0x9b, 0x48 } }, +{ "\x9a\x2e\xf2\xaf\xde\x68\x21\x07\x22\xd0\xfd\xe7\xc0\xb0\x16\x39\x48\xc6\x0d\xb6\x5d\x0b\xfc\x11\x2c\xb2\x83\x34\x8a\x2c\x70\xa1\xa9\x68\x0a\xfb\x77\x19\xfa\x9e\x94\x2f\xd7\x68\xed\x67\x4c\x9b\xfa\xfe\xe8\xdb\x90\x81\x82\x51\x63\xc0\x47\xf2\x1c\xe0\x62\xda\x13\x90\x46\xd2\xaa\x54\x9b\xf1\x45\xfd\xc3\x5e\xe9\x39\x07\x33\x70\x46\x63\x7d\x66\xc2\xea\x60\x84\x9f\xd7\x57\xc7\x32\x32\x9a\x2b\x6a\x1c\x98\x09\x1d\xb7\xa3\x0a\x7e\xb4\xac\xc7\xab\x7a\x23\xff\x63\xf0\x00\x74\xd5\xe7\xe0\x62\x93\x27\x47\x9d\xa6\x14\x04\x46\xbb\xfd\xb2\x29\x7a\x02\x5a\xb6\xf7\x9f\x36\x9a\x41\xd9\x91\xfa\x18\x03\xca\x4c\xbd\x2d\x77\xd1\xe1\x2a\xa5\xb3\xbf\x3d\x3e\xb7\x45\x60\x84\x9e\x6d\x30\xb9\x1e\xab\x78\xe1\x78\x7f\x58\x9f\xb6\x2a\x11\x3c\x83\x7d\x70\xc7\xa6\xcc\xd5\x56\x1d\x02\xe0\x6a", 192, { 0xc8, 0x67, 0xcd, 0x31, 0xf4, 0xb8, 0x95, 0x60, 0x67, 0xc3, 0xcd, 0x10, 0xe4, 0x31, 0xe5, 0x8e } }, +{ "\xd2\xce\xb7\x71\xfc\xfc\xf5\x64\x15\xde\x32\x91\x73\xe8\x2b\x73\x86\x5c\x8e\xbd\xad\x1a\x65\x76\xb5\x99\x1c\x3d\xee\xf3\x30\xae\xec\x1a\x76\xdd\xd7\x28\x06\xff\x6f\xd5\xc2\x29\xa1\x02\x86\x30\xbe\x72\xee\xaf\x5e\x98\xbe\x26\xd0\x8a\xf2\x3f\x3c\x15\x63\x2d\x58\xeb\x13\x2d\xc3\xf8\x15\x2e\x01\xd3\x1c\x8d\x14\x4f\x9e\xf9\xb3\x30\xa4\x76\x2a\xfa\x31\x7d\xcd\xe5\x4c\x40\x1a\xee\xac\x0a\x6a\x07\x00\xc5\x54\x6f\xd8\x96\x9f\x1c\x33\xa3\xe1\x54\xa6\xf4\xb8\x5a\x25\x77\xa4\x46\x71\x1d\x80\xee\x1e\x23\x9b\x00\x40\x6b\x77\x32\xb2\x08\x1d\x90\x02\xd9\x1b\xf4\xfc\x4c\x1c\x94\xd1\x44\x22\xb5\xe4\x15\x62\x7e\x32\xac\xbc\xe7\x5b\xcc\xd5\xd0\x51\x73\xd3\x2e\x9c\x5b\xb4\x60\x47\x9c\x4b\xa0\x6b\x6e\xd9\x94\x55\x0d\x44\x04\x57\xb5\xf6\xa7\x28\xcd\x55\x16\xf8\x20\xda\xe2\x15\x46\xd0", 193, { 0x0e, 0x63, 0xa1, 0x87, 0xec, 0x2a, 0x99, 0xd9, 0x1d, 0xec, 0x28, 0x37, 0x05, 0xb3, 0xe9, 0x44 } }, +{ "\xc1\x33\x21\xab\xe3\x5b\x83\x03\x63\x73\xed\x2b\xd9\x66\x72\x72\x0c\xef\xbb\xf6\xc4\x07\x23\x20\xbe\xe9\x02\xbf\xb9\xbe\x08\xc4\xae\xeb\xbf\x98\x1c\xf3\x32\x16\x81\x09\xac\x28\xe5\x36\x99\x01\x8f\x23\x8a\xf4\xdb\x84\x54\xf0\x24\x21\x57\x99\xdb\x82\xdc\x03\xb9\x37\x98\x0d\x11\xc1\x4e\x58\x3e\x21\x90\xe3\x3c\xfa\xa5\x44\x53\x65\x86\x85\xee\x51\x03\x99\x8a\x95\x03\x7a\xca\x94\xe8\xe0\xa7\x8c\x11\x9f\xc4\x7b\x79\x9e\xdf\xae\x7c\x6f\x64\xe7\xba\x90\x1c\x2a\x14\x3d\x02\x24\xd4\xf0\x36\x39\xe9\x77\x0b\x29\x4f\xaf\x3b\x5d\x8d\xe2\x3a\xd4\x58\xbb\xa7\xa5\x55\xe2\xdf\x30\xfc\x38\xac\xe5\x98\xb0\x1b\xb0\x6b\xc8\x6b\x00\xee\xa3\x21\x73\x35\xc5\x39\x20\x71\x6a\x77\x80\x90\x83\xdb\xf9\xff\x4e\x32\x09\x8f\x91\xc9\x0b\x75\x72\x3d\xa9\x6b\xf6\x6e\xdf\xf5\x14\x92\xa7\xbe\x75\x65\x47", 194, { 0xa3, 0x61, 0x94, 0x86, 0x67, 0x56, 0xab, 0x69, 0x85, 0x9b, 0xbc, 0xa2, 0x1c, 0x09, 0x1e, 0x31 } }, +{ "\x21\xcb\x7e\x33\xc3\xcb\xbd\xa0\x5d\xc8\xe1\xa6\x97\xee\x36\x10\x10\x17\x6b\xc4\x7a\x4d\x82\xc9\xe3\xdd\xe0\xfa\x0e\x14\x84\x46\xff\x99\x54\xa1\x96\x66\x93\x8b\x53\x65\x70\x3b\x38\xa3\xb7\x68\xcc\x33\xaa\xb3\x3b\xa2\xeb\xb4\x9b\x12\x90\x9f\x49\xf5\x59\x93\x72\x68\xfd\x7f\xae\x29\xa0\xb1\xc6\x37\x62\xfc\x96\x05\x11\x86\x0e\x5a\xfe\x2c\x52\xc8\xed\x92\x01\xc6\x26\xca\x93\x6c\xa8\x9f\xdc\xcb\x7d\x80\xad\xe7\x29\x04\x9a\x53\x3c\x1e\xd5\x67\x07\xde\x39\x1f\x6b\xe1\x63\x93\xcd\x57\xfb\x0f\x25\xaf\x11\xce\x36\xe1\xa1\x58\xd8\x57\x39\x75\x71\x79\xb2\xcc\x82\xd4\x19\x1d\x5d\xe6\xb2\x18\xf5\x88\x12\xd8\xce\xf8\x6b\xff\x13\x82\xe5\x6e\xc6\xcb\x27\xa1\x11\xba\xf4\xa6\xbc\x04\xf2\xb8\xb8\x52\x87\x7c\xd8\x10\xdc\xd7\x9f\xd4\x03\x6a\x34\x69\x35\xab\x72\x78\x34\xa1\x1c\xd2\xcf\x3c\x2e", 195, { 0x6f, 0x1c, 0xed, 0x06, 0x68, 0x7c, 0x13, 0x93, 0x1d, 0x84, 0xbc, 0xd5, 0x40, 0xbb, 0x5a, 0x78 } }, +{ "\x5c\x84\x4e\x4e\x98\x3f\x2a\x61\xcc\x41\xd8\x3a\xd1\x1c\xf1\x6e\x79\xda\x1d\x43\x9e\x3e\x27\xc7\xc3\x22\xba\xfc\x6a\xff\xbb\x31\xf2\x8b\x42\x6c\x29\x7d\x35\x03\x76\x6c\x83\x4a\x9c\xd5\xfb\x66\x2c\x3c\xc6\x40\x8a\x69\x87\x95\x99\xd3\x0e\x2b\x06\x1b\xb3\x1e\x2e\xaf\x55\x59\xad\x8f\xef\x20\x84\x2c\xd3\xc9\xe6\x6c\x87\x8b\x9f\xcb\x39\x6e\x22\x9b\xdf\x62\x2d\x6c\xef\x6c\x1b\x86\xb8\xfb\xc6\x93\x5c\x59\x16\x5a\x6a\x3d\x2b\xa6\x1c\x7d\x23\x45\x2a\xe0\x88\x2c\x48\x11\x59\xb8\x43\xb0\xb3\x0f\xb4\x83\x1c\xa5\x5e\xca\x6c\xda\x2a\xb0\x59\xc1\xbc\xdd\x9d\xfc\xb1\x28\xc6\xc3\x78\x6a\x9a\x03\xca\x6e\x24\xa3\xc7\x04\x5f\xe1\xae\x35\x7e\xdb\x39\x90\xd6\x2a\x93\xa3\x69\xa9\xf7\x86\x10\x53\xe6\x91\x44\x4a\x04\x2d\x89\xf4\x90\xc8\x77\x40\x7e\xe2\x66\x07\x33\x45\xb5\x8d\xdd\x51\xb7\x26\x6c\x75", 196, { 0x26, 0xa3, 0xf1, 0x62, 0xb9, 0x04, 0xc2, 0x92, 0x0c, 0x08, 0x6f, 0x8a, 0x4a, 0x9e, 0x80, 0xaf } }, +{ "\x3b\xf5\x30\xba\xb7\xd0\x10\x79\x11\x3f\x64\x2d\x09\xa4\x70\x63\x45\x74\x7e\xce\xfa\xa3\x97\x77\x35\x1e\xdd\x11\xc4\x72\x88\x6a\xc3\x8a\x7b\xfe\xc6\x95\x82\xa6\xa0\x06\x2b\x6d\xce\xb5\x3e\x83\x83\x23\xda\x4b\x51\xda\x2d\x8f\x71\xf3\xcf\xd3\xaf\xb2\xbc\xc7\xf5\x4b\xec\xd6\x72\xc8\x91\xdb\x66\x02\xec\xf3\x8d\xcc\xcc\x6d\x25\x30\xa5\xde\x9e\xd1\x49\x52\xde\x6f\x45\x9d\x2d\x89\xdb\xcf\xc4\x1d\x97\xc5\xed\x8b\x90\xdc\xd6\x98\x3d\xc1\xf8\x8e\xf1\x64\x1f\x80\xf4\x0b\x15\xaa\x40\x83\xef\xf7\xd5\x71\xf3\x9d\xb9\xc6\x24\xe4\x90\x50\x6d\x04\xd3\x6e\x66\x2b\xb0\xdc\xc5\x9d\x7e\xac\x64\xf6\xdb\x56\xea\x8b\x65\xe6\x19\xef\x11\x53\xb4\x91\x2b\xf0\x0b\x82\xea\xfc\x24\x55\xaf\x54\x88\x20\xda\x48\xa7\x9e\x49\x8a\xe8\x76\x6f\x42\x51\x97\x0c\x3f\xd0\xba\x8e\x49\x24\x09\x04\x92\x6b\xde\xbb\x4a\x48", 197, { 0x8e, 0x2a, 0x66, 0x4b, 0x0e, 0xe7, 0x3f, 0xaa, 0x95, 0xa8, 0x6c, 0x1d, 0xeb, 0x22, 0xdb, 0xd8 } }, +{ "\xa4\x77\x52\xb0\xda\x4f\x08\x52\x36\x26\x41\xa1\xe6\xc2\x55\x7f\xf1\x8a\x53\x87\xbc\xe0\x55\xf7\xa9\x19\xef\x39\xda\x15\xc1\x0c\x13\x80\x2c\x53\xbe\xa4\x21\x7a\x07\xe8\x15\x81\x27\xe8\x11\xa7\xbf\x32\xe5\xb3\x5a\x9b\x7c\xe1\x15\x3d\x4b\x68\x5b\x0e\xe4\xa4\xc8\x1d\xa7\xe5\x2f\x6b\x97\xd4\xb7\x63\x4a\x7c\x20\xf7\xfa\xfc\x23\x59\xba\xc8\xf8\x53\xc2\x97\xf1\x44\xeb\xed\x44\xb8\x36\x45\xe6\xa2\x86\xda\x92\x38\x6e\x12\xe8\x6b\x25\x88\xb3\x02\x96\xb4\x43\x52\x94\x39\xf9\x9c\x2b\xcc\xe1\x03\x12\xbc\x79\x28\x3c\x21\x90\x64\x8d\xa5\x4a\xa1\xaa\xea\x40\xd6\xe9\x97\xc4\x1d\x68\x02\x42\x72\x39\x7b\xc2\x0a\xbb\x33\x89\x4d\x04\xc8\xdf\x72\x7a\x6e\xec\xb6\x81\xbb\xbc\x39\x4e\x0f\x62\x75\xda\x9d\x38\x5b\xf3\x1b\x44\x0c\x6c\x02\xb6\x31\x75\x82\x8d\xf7\x05\x06\x5a\xaa\x73\x5f\x1d\xed\x25\x8f\x4b\x93", 198, { 0xfd, 0x93, 0x65, 0x5a, 0xe8, 0xb0, 0xde, 0x62, 0x06, 0x84, 0x76, 0x4f, 0x5b, 0x47, 0xf7, 0xd4 } }, +{ "\x5f\x35\xf1\x1e\x3d\x90\xf2\xd2\xbc\x31\x6c\x74\xf2\x42\x39\xa4\x5e\x6c\x92\xd4\x5a\x6a\xcd\xe4\xad\x28\x47\x5c\x3d\x97\x5c\x45\xe1\x10\x93\xa4\x55\x62\xd7\x94\x46\x7a\xe0\xff\x8e\xae\xb1\xf9\x7a\xa6\x3a\xb9\x46\xe7\x1d\x34\xaa\xfd\x8d\x57\x8d\x45\x53\xe1\xd8\x54\xeb\xdc\x66\x07\xcb\xb6\x17\x28\xc3\x00\x04\xba\x7f\xc2\xcc\xe2\x2a\x78\x0d\x72\x2d\xae\xef\x12\x15\x33\xda\x0d\x93\xfd\x47\xb6\x9c\x99\xb4\x75\xb1\x4c\xb1\x71\x39\xcc\x18\xdb\x0a\x94\x5a\xd5\x06\xe8\xf3\xfe\xe2\x65\xff\x9c\x02\x44\xe7\x64\x80\x2b\x34\xe8\x4c\xaf\x84\x9e\x6d\x6b\x99\x88\x66\xb6\x8f\x85\xb3\x03\x26\x34\x73\xda\x3d\x81\x1f\x6f\x60\xcd\x78\xdc\x78\xbe\x7f\x00\xa1\xa0\x9e\xf3\x19\x76\xe4\x25\x53\xa2\x6e\x12\x2b\x2c\xe1\xa3\x35\xb2\x13\x25\x2e\xed\xc9\xde\x94\xdb\x9b\x51\x51\x8e\xf4\x10\x93\x91\x36\x39\xb7\xf2\xfa", 199, { 0x05, 0x5a, 0x5c, 0xa0, 0xac, 0x17, 0x39, 0x3b, 0x11, 0x90, 0x08, 0xf7, 0x91, 0x12, 0x33, 0xbd } }, +{ "\x8e\x63\xf1\x75\x35\xb3\x43\xf6\x08\x8a\x03\x8b\x9a\x0b\x36\xc4\xc8\x20\xf9\x8f\xf7\x37\x4a\x42\xef\x0d\x6f\xb8\x53\xa2\x06\x92\xbc\x4c\xaa\x9f\x72\xe8\x3f\x56\xc6\x2b\xdb\x80\x0f\x16\x51\xf2\x3f\x88\x5b\x78\x21\xed\x63\xce\x31\x15\xee\xc8\x17\x1f\xa6\x91\xc2\x94\x02\x10\x1e\x90\x94\x66\x71\x1a\xef\x94\x57\x95\x32\x3a\x58\x50\x36\x7a\x23\x38\x50\xfb\x6a\xad\xc3\x09\x59\x71\xc5\xda\xb3\xbd\x2c\xec\x8c\x6e\xb5\x89\x9d\x5c\xf1\x6c\x47\xcb\xcd\x7e\x27\xfb\xbc\xb9\x52\xda\x83\x2e\x2d\xda\xa0\x21\xec\xdd\x58\x52\xa5\x4b\x5c\x57\x10\x46\x17\x24\xdd\xf5\x97\xad\xb2\xfd\x15\xa2\xc0\x0e\x22\x59\x01\x99\x71\xca\x10\x9f\x3b\xb3\xa4\xa5\x52\xdc\xaa\xc4\xc6\x75\xff\xdd\x2e\x9b\xc7\xe9\x94\xf9\x6d\x6e\xff\x8b\x37\x0d\x9d\x7e\x84\x38\x8d\x34\xa5\x02\x47\x63\x56\x0f\xa9\x5d\xd8\xaa\x9e\x6a\xac\xf5\x6d\x51", 200, { 0x09, 0x82, 0x5e, 0x9d, 0x4d, 0x7d, 0x4f, 0xf4, 0xcb, 0xc6, 0x86, 0xe7, 0xc4, 0xdb, 0x1a, 0xb4 } }, +{ "\xed\x3b\x9c\xf6\x4b\x62\x7e\x1d\xa0\x7c\x60\x4d\x30\x7c\x4c\xcf\x82\x05\x78\xd6\xd5\x5e\x4e\xb8\x41\x82\x19\x5a\x6c\x55\x49\xab\xe5\xf0\x63\x47\x20\x1d\x88\x3b\x0e\xde\x9f\xe8\x59\x28\x22\x00\x39\xad\x82\xae\xf6\xd7\x38\xd2\xfa\xd0\x69\x6a\x92\xbe\x35\x0c\x41\x0c\x9d\x8f\xc1\xe4\x0e\xca\x97\xb9\x8e\x74\x51\x00\x82\x2a\x5f\xfe\x19\x90\x8c\xbc\x59\x8f\x17\x18\xc4\xbc\x72\xf6\xa6\xd8\x96\x93\xfe\x74\x01\xfa\x07\xad\x4d\x8f\x62\x15\x6e\xc8\xe1\xb2\x88\xfc\xf2\x20\x6b\x53\xa6\xd1\xac\xde\x5d\x75\x61\xc0\x10\x75\x78\x89\x3b\x98\xb4\xa3\x65\xc9\x46\xe5\x4d\xf0\x04\x45\xb3\xfc\x48\xaa\xc0\x02\x68\xe0\x12\x7f\xcd\xa5\x68\xb9\xb2\xe0\xe7\x44\x7b\xf1\x07\xa1\xaf\x23\x1d\x01\x94\x3e\x85\x27\x66\x3a\x6b\x6b\x33\x0e\x36\xda\x56\xa5\x93\x7b\x8e\xf2\x19\xad\xba\x1a\x9e\xac\x33\xd0\x16\x32\xc6\xbf\x22\x3a\x4c", 201, { 0x67, 0xe6, 0x8a, 0xc1, 0xa4, 0x4c, 0x07, 0xb7, 0xd2, 0x7e, 0x82, 0x85, 0x0f, 0x8c, 0x27, 0xed } }, +{ "\x20\x3d\xdf\xe8\x6b\x7e\x63\xdd\x2a\x0a\x4c\x0a\xe8\x1a\xa9\x02\x49\xa5\x73\xcc\x33\xaa\x0e\x34\x2a\x1c\xef\xcc\xba\x69\x57\x82\x0d\xa9\x3d\xdf\x9c\x60\x49\xda\x02\xf0\xfd\x57\xec\x9e\xee\x3f\x2d\x3e\x30\x3c\xee\x7e\xd1\x11\x03\xcd\x7b\x95\x58\xe6\x3d\x4a\x8a\xfd\x63\x9e\x92\x84\x81\xbd\x9c\x9a\x8f\x11\xf6\x11\x2e\x57\x24\x1a\x09\x5f\x10\x8f\x57\x60\x5e\xdd\x7c\xf5\xde\x8c\xcf\xb8\x1b\x6d\x77\x7a\x10\x5f\x6e\x1c\xfa\xbd\xa7\x0d\x49\x68\x4c\x60\xb0\x6c\x20\x88\x5b\x51\x04\xb4\x40\x01\x95\xc1\x8f\x51\xf2\xe0\x43\x2d\x9b\xc6\xda\x65\x75\x89\x21\x0e\xea\x1e\x29\x96\x2d\x6c\x56\x68\x9b\x0c\x95\x38\x3d\xa0\xad\xeb\x6a\xcd\xaf\x26\x89\xd6\x88\x72\xf5\xd6\xb5\x09\xf9\x9a\x15\x40\xfa\x19\xda\x90\xb4\x90\x99\x42\x9c\x3e\x82\xb7\x65\xb9\xa9\x51\x9f\xec\x82\x02\x79\xae\x6c\x6f\xa7\xff\x64\xc0\x5f\xe1\xda\x07", 202, { 0xee, 0x3e, 0xeb, 0xd8, 0x7a, 0x38, 0xa2, 0x68, 0xcc, 0xf5, 0x88, 0x6a, 0xe0, 0x3a, 0xba, 0xac } }, +{ "\x7d\xd1\xa0\x4a\xc6\xe0\xff\x2e\x49\x73\xe4\x42\xe1\x93\x38\xe6\xd8\xf2\x4d\xd7\xa6\x7b\x74\x58\xd7\x94\xab\xfd\x0a\xf3\x73\x17\x15\x1a\xc0\xb7\x46\x70\x0a\x61\xc5\xfe\x81\x4f\x15\xc3\x5d\x5e\xb9\xb4\x53\x99\xf3\x53\x23\x61\xa7\xea\x4e\x36\x5f\x64\xe6\x24\x68\xc9\x7d\xcc\x19\x54\x3f\x0e\x33\x33\x1c\x50\x64\xdb\x1d\x6e\xe6\x05\xd8\x3e\x44\x48\xff\xbe\x3d\x54\x12\xdc\xc1\xc8\x35\xe2\x18\xb1\x1c\x7d\x22\xa0\x22\x68\xb9\x67\x79\xba\x32\x6f\x7c\xc8\x03\xb9\x21\xb8\x7e\x6f\x8a\xa3\xbc\x26\xba\x66\x95\xb3\x64\x06\xcb\xa7\xdf\xbd\x46\x68\x37\xa5\x7a\xed\x5d\x00\xe4\x15\x7e\x22\xb4\xa5\x71\xfb\x85\xdd\x49\x45\x47\xb5\x0a\x46\x3e\xb9\x79\x42\x23\x7e\x0c\x81\x68\xc0\x01\xf8\x99\x19\x8b\x97\xde\x60\x26\x2f\x9d\x9c\x0c\xfd\x3c\xa4\xc0\xd7\x04\x54\xc7\xf1\x21\x6e\x76\x4c\xc6\x0a\xe7\xbd\x6d\xbb\x05\x96\x3c\x40\xc7", 203, { 0x5d, 0x3b, 0xc3, 0x5e, 0xdc, 0x45, 0x22, 0x74, 0x96, 0x59, 0x61, 0x19, 0xb7, 0x97, 0x5f, 0x60 } }, +{ "\xf3\x83\xe4\x7a\xa2\x62\x73\x36\xb0\x88\xd9\x72\x8c\x16\x58\xb4\xdb\xa1\x65\x61\xd7\x56\x20\xb2\x64\x39\x6f\xc7\xb1\x86\xb6\xd6\x87\x38\x34\x7c\x32\xa7\xfd\x34\x08\x4c\x90\xe5\x9a\xa1\x14\x95\x77\x23\x34\x3c\x97\x79\x93\xb3\x6b\xaf\xee\xcb\x7f\x9b\xcd\x7a\xc8\x60\xe6\x31\x90\x10\x0e\x49\xfb\x6d\xdc\x9b\x35\xc8\xdc\x2e\x3a\x0b\x6d\x0b\x41\xd2\x38\x2d\xc6\xb3\x4d\x95\x32\x9e\xdc\x79\x2a\x60\x8c\x9c\x71\x42\x7b\xb9\x7b\xce\xd3\x19\x8f\xb1\x05\x44\x97\xbc\xa5\xd4\x87\x05\xe2\x65\x68\x2a\xa0\xa8\x00\xb5\x34\x97\x20\x9b\xbb\xc3\x8a\xdf\x17\xc8\x7c\x54\x88\xe3\xdd\x7f\xe3\x9a\x03\x9a\x71\x99\x1f\xb5\x66\x9d\x46\xf8\xfb\x89\x1c\x03\x2b\x96\x1f\x76\x08\xa8\x8d\x8c\xb7\xbb\xf3\xe2\x0e\x7c\x54\x56\xc8\xf4\xf2\x0b\x63\x5f\xbc\x88\x97\x1b\x53\x00\x72\xbc\xbb\xac\x14\x3c\x9b\x54\x05\x50\x30\xee\x2e\xd5\xd4\x5d\x7b\x69", 204, { 0x91, 0x24, 0x52, 0x7f, 0x19, 0x7f, 0xae, 0x81, 0x27, 0xa6, 0x98, 0xe8, 0xa1, 0xc3, 0x1d, 0xf4 } }, +{ "\x27\x5a\x0a\x17\xd7\x70\x10\x2a\x12\x21\x49\x22\x85\x26\x19\xc5\x0f\xd4\x44\x4c\x07\x9a\x47\xbe\x26\xa7\x51\x5b\x13\xa8\xe1\x2e\x8a\xaf\xfd\xc6\x28\x2f\x0c\xfe\xd5\x24\x51\xf7\xce\x50\x04\x27\x4d\x9f\x0e\x8b\xd8\xac\x62\xf8\x23\x5c\xf3\x8f\xa3\xa8\x55\x4f\xb1\x79\xf4\xc5\x56\xac\xeb\xde\xb9\x35\x82\xdd\x22\x5f\x47\x67\xaa\x31\xc7\xbb\x82\xed\xe9\x00\xdc\xb2\xe8\xb7\x79\x41\xeb\x50\xd0\xdc\x43\xd8\xd8\x4a\x40\xcf\x72\xf8\xb0\x18\x76\x39\xf5\x09\x59\xae\xc2\xa2\x78\xc1\x72\xdb\x03\x4b\x05\x16\x89\x56\xb7\xb4\x1b\xfc\x3f\xc4\x20\x6e\xa1\xd5\xb5\x11\xb0\xec\xbe\xc2\x24\x91\x8e\x3a\x53\x04\x2f\x8d\x90\x8d\x4e\xcd\x1d\xf1\xc6\xcb\xcd\x00\xc7\xfd\x3b\x4c\xa3\x7b\xa1\xf4\x35\x24\x56\x9e\xee\xdd\xe6\x83\x7d\xf9\xcf\xa3\x1a\xb5\xd6\x1a\x70\xda\x04\x8b\x25\x85\x41\xb8\x07\x03\x8b\x34\xd4\xd6\xd3\x2f\xa6\xd5\x74\x71\xf9", 205, { 0xaf, 0x74, 0x5b, 0xa6, 0xbe, 0xb5, 0x95, 0xdd, 0x3a, 0xa9, 0x3e, 0x1c, 0x12, 0x8f, 0x4a, 0x81 } }, +{ "\x6f\x51\x62\x5a\x10\x89\x45\xae\x9c\xda\x85\x1d\x18\x8f\x28\x99\x68\x27\x60\x0f\x33\x84\x40\x28\xe2\xcc\x8c\xbc\xc8\xe0\xa9\xd4\x5c\x77\xb3\x5a\xa1\xd6\xad\x5f\xa6\x2e\xd3\x09\x29\x92\x0c\x17\x57\x93\x7c\x13\xaf\x7a\x35\x13\x04\x21\x0d\x2b\xa1\x6e\x8a\x72\x86\x6d\xfa\xaf\xd1\x09\xa0\xa1\x38\x67\x08\xe8\xb3\xe0\x7c\x93\x37\x98\x8f\x47\x9c\xbf\xd6\x08\xa0\x64\xb7\xa7\x04\xf1\x59\xc8\xd4\x47\xbb\x8f\xc4\x77\xe0\xe7\xb6\x19\x28\x6f\x58\x4d\xbb\x01\xeb\x4c\x1e\xdf\x1e\xa9\xe7\x7c\x18\x2a\x8d\xe5\x95\x3d\x59\xca\x28\x19\x79\x2d\x9e\x72\x33\xa6\x83\xd8\x37\x50\xbe\xad\x0d\x54\x57\xc1\xad\x10\x5a\x8c\x2d\xe3\xd3\x07\x95\x97\xf8\x27\xce\x6c\x66\xf7\xb9\xbd\x84\x51\x5d\x51\x04\x38\x38\x41\x88\xd5\xb6\x81\x61\x0d\xbf\x0c\x72\xbb\x6b\xb0\x33\x8f\xd1\x73\xd1\x82\xfd\xa1\x73\xf5\xff\x73\x98\x65\x20\x5e\x9c\xcd\x30\xf5\x5a\x99", 206, { 0x69, 0x2b, 0x76, 0x76, 0x70, 0x75, 0xc8, 0x00, 0xd0, 0x62, 0xd9, 0xc8, 0xd8, 0x37, 0xe6, 0xe6 } }, +{ "\xfb\x7b\xea\x42\xda\x09\x8b\x8a\x65\x58\x9c\x56\x46\x2c\xc5\x23\x29\x5e\x33\x26\xcf\x84\x00\x04\x42\x3e\xb0\x2b\x23\x20\xd7\xcb\x1f\x37\xd9\x75\x80\x3a\xca\x4e\xe0\x4f\x73\xef\xf8\x76\x76\xdd\x96\x96\x89\xa0\xad\x22\xde\x82\x86\x68\xa3\xe6\x15\x76\xa5\x42\x66\xa9\x10\xba\x36\xd3\x51\x5a\x9e\x08\x1c\xf0\xea\x06\x89\x84\x88\x3e\x59\x75\x1c\x83\x57\x32\xb1\x4e\xda\x91\x09\xab\x67\xcf\x15\xc4\x73\x25\x80\x08\x45\x03\x65\xf8\xfa\xec\x22\x8e\xa3\xed\x44\x4a\x89\xbb\xa1\xda\x90\x68\x85\x65\xb9\xc2\x04\x74\xc1\x48\x6f\x7d\xe7\xca\xe1\x0e\xcb\x9c\xf9\x93\x72\x76\xa2\xc4\x66\xeb\x0d\xad\xfa\x84\xc0\x5b\xab\x79\xc8\x20\xa2\x0b\x0a\x84\x57\x81\xb8\xc8\x4f\xbc\xdf\x17\x05\x79\x1c\x4c\xe7\x23\x6f\x5a\x77\x53\x27\x5c\x92\xe5\xfd\x3a\xce\xb8\x3d\xf4\xfc\x01\x1f\x8e\xcd\x4c\x34\x99\x90\x11\xfc\x59\x19\xef\x94\x98\xbe\x88\x8c\x06\x7b", 207, { 0xdc, 0x06, 0x1a, 0x7c, 0xe0, 0x3b, 0x42, 0x40, 0xac, 0xe3, 0xdd, 0xf7, 0x63, 0xae, 0xaa, 0x36 } }, +{ "\xf8\xd7\x4b\x35\xf2\xdc\xab\x1b\x79\xa9\x55\x29\x39\x47\x48\xc6\x80\x28\xe3\x8e\xdc\xbd\x07\x2a\x51\x24\xea\x5a\x37\xff\x7b\x14\xae\x60\x6d\xc6\xbf\xe0\xe3\xb8\x11\xcf\xb6\x8d\x45\x85\x66\xe8\xee\xd7\x9a\x2c\x30\xa5\x55\x5b\xf4\x91\xb8\x20\xc5\xca\x6e\xe8\x4a\x06\xb7\x2a\x60\x8e\x15\xc8\xd4\x73\x8d\x8d\xba\xde\x9a\xd6\x6c\x85\xb4\x4e\x22\x3a\x77\xd2\x2b\x9d\x74\x73\xc6\xf2\x91\x99\x9f\x0d\x1d\x44\xe9\x6a\x74\x6e\x14\x59\x4b\x8d\x2c\x56\x99\x35\xce\x77\x23\xd9\xc7\xfe\xa2\xb1\x4a\x0e\x92\xb8\xce\x7b\x9a\xcd\x82\xba\x93\xf9\x6e\xf7\x36\xd0\x27\x46\x67\xf0\x2e\xf1\x18\xa7\xe7\xf0\xdb\xb1\x31\x76\x08\x1e\xa6\xa8\x87\x52\x70\x68\x3b\x26\xc6\x50\x0c\x2d\x02\xbb\x8e\x11\x61\xfd\x53\x1b\x56\xb2\xca\xd1\x8b\x34\xd2\xb9\x75\x26\xdf\x3c\x92\x2d\xc7\xa6\x42\xbf\x2a\x4a\x40\x13\x7c\xc2\xbb\x38\xb1\x54\x15\x42\x83\x71\x37\x9f\x63\x57", 208, { 0x90, 0x71, 0x3e, 0x92, 0x18, 0x0b, 0x7f, 0xec, 0xf7, 0x44, 0x3a, 0xd3, 0x5c, 0x05, 0xb4, 0xfe } }, +{ "\x8f\x87\xfa\xd6\xa7\x92\x5a\x2f\x63\x63\xc6\x17\xd7\x82\x1a\xdc\xc2\x48\xd8\x9f\xab\xf3\xd1\xbf\x97\xd9\x6d\x57\x64\xba\x97\xdd\xc6\x2e\x47\xeb\xdb\x3d\xad\x1a\x6c\x0d\xf7\x0a\xc2\xb6\xbf\x7f\x23\x32\x14\xa6\xe8\x70\x24\x75\x3c\x87\x83\x30\x73\x07\x1a\x07\x04\x6c\xaf\xdd\x25\xac\x0c\x23\x01\xf0\xcf\xe3\x99\x5f\xce\xd9\x34\x15\x24\xbb\x84\x32\xdc\x9a\x57\x0f\x39\x60\xf6\x8c\xa0\x79\x1e\x85\x23\x8f\x98\x63\xab\x6d\x77\xce\xc1\x05\xee\x80\xf9\x8d\xcb\x35\xfb\xc3\x94\xbf\x2f\x52\x3d\x35\x05\x4d\x83\x4b\xde\xd8\xe7\xbd\x9a\xe6\x4a\xe6\xbf\x1c\x22\x6d\x42\xd4\x56\x1e\xf6\x3f\xbc\xd7\x8e\xa2\x2c\x99\x50\xc1\x41\xbe\x59\x59\xac\x4a\x87\xc6\x34\x59\x06\xc5\x4e\xb8\x7a\x54\x54\x90\xc6\xb6\x65\x3d\x77\x92\xda\x3e\xd1\x3b\x60\x45\x74\x0b\xb7\x6d\xa9\xe8\x06\x8b\x4f\xe8\xd8\x9c\x5c\x11\xb7\x5e\x12\x39\x63\xfc\xc1\x0c\xaf\xe1\x32\x2c\xf9", 209, { 0x72, 0x27, 0x02, 0xd5, 0x86, 0x5b, 0x0b, 0x2b, 0x77, 0x13, 0x3a, 0x71, 0x39, 0x5b, 0x88, 0x5d } }, +{ "\xae\xb7\x73\x44\x46\xcd\x54\xf4\x06\x6b\x5f\x25\x12\xea\xe3\xa8\xcb\x90\xad\x9a\x5c\xba\xef\xa3\x74\xa6\x3c\xc8\x0e\xda\xb0\xee\x6b\x35\x2d\xec\x22\x90\xc0\x4b\x4e\x11\x21\x9d\xe5\x0c\x59\x77\x28\x95\x7e\x0c\x36\xa6\x9a\x67\xbc\xe9\xaa\x44\xc7\x24\xc2\x8c\xba\x3f\x4e\x6c\x5b\xf2\x73\x11\x07\x0f\x93\x01\x06\x69\xef\x19\xf9\x60\x68\x1f\x70\x0a\x5e\x03\x98\x00\xb9\xb7\x11\xc2\x06\xa8\xde\xc8\xb9\xd7\x76\x26\x91\x99\xf7\xda\x19\xe7\x7a\xb6\x4a\x63\x81\xe4\x4e\xe8\x8d\x1b\x5f\xcc\xcd\x5d\xce\xb5\xf0\x6a\x20\x14\x1c\xc5\x52\x43\xf7\x60\x3e\x37\xe2\xe6\x16\xe2\x45\xa5\x0c\x28\x05\x17\x14\x7b\x12\x0b\xc1\x15\x1e\x75\x4c\xd1\x68\xce\xb4\xa7\xb6\x29\xff\xc2\x61\xd4\x9e\x40\x8a\xa7\xee\x85\x6b\xec\xdb\x3c\xc8\xeb\x9f\xec\x83\x10\xa8\x32\x4f\xbb\x98\xa1\x7d\xa4\x66\x33\xf2\xe9\xa2\x6a\x3a\xb6\xd5\x07\xb5\x90\x06\x66\xef\x3e\x59\x74\x0e\x54", 210, { 0x00, 0xbf, 0x87, 0x36, 0xd5, 0xe8, 0x54, 0x2f, 0x00, 0xca, 0x28, 0x9c, 0xe1, 0x28, 0xe5, 0x7e } }, +{ "\xd3\x4e\x64\x5d\x38\x78\x24\xa4\x15\xb7\x32\x9f\xda\x8c\x13\xf9\x1f\x4d\x04\x3b\x07\xe1\x26\x16\xc2\x17\xd6\x4f\x2c\xa4\x1b\x47\x93\xb7\x39\x26\x96\x3b\x62\xa4\x28\xa8\x8c\x74\xb4\x86\x5e\x4d\x5b\x80\x44\x95\x58\x21\xa2\xac\x85\x2d\x24\xd3\xf7\x9e\x34\xb8\xc3\x3a\x85\x9f\xe4\xcd\xcc\x2e\x35\x09\x8f\xd5\x98\xf6\x15\xd8\x39\x17\x7d\xfa\xed\x1b\xeb\xc8\xb4\x3c\xdd\x7f\x5d\x38\x9c\x9b\x49\xea\xcd\xfd\x47\x85\x27\xb7\x9f\x6c\x3f\x77\x2a\xb0\x7f\x8f\x9e\x26\x35\x9d\xe8\x24\xc7\xdc\xb2\xd9\x05\x05\x04\x46\x97\xe3\x06\xdd\x95\x72\xe3\xb4\x35\xb3\xca\x66\x9f\x0f\x0e\x86\xdd\x65\x6e\xc1\xee\xb2\x6e\x8f\xf9\x5c\xe4\x95\x9f\x1b\x8f\x9b\x69\x84\xe0\x25\x61\x34\xdd\xb0\xbc\x95\x1b\x8b\xb4\x50\xe9\x4f\x74\x4f\x8c\xfc\x2d\x6d\xa4\xb1\x46\xbd\xad\x07\xb0\x74\xa1\x0b\x57\x74\xbb\xd7\xb4\x76\x57\xcc\x7f\xd2\xf5\x6e\x82\xee\x5d\xdc\x89\x41\xdc\xea\x76", 211, { 0xfa, 0xb4, 0x08, 0xeb, 0xfa, 0x54, 0xe3, 0x20, 0xe9, 0x99, 0x17, 0x29, 0x29, 0xf5, 0xeb, 0xb1 } }, +{ "\x03\xac\xdd\x71\x73\x72\xc2\x3c\xc4\xe0\x6b\xa4\xa5\x7b\x07\x13\x6c\x77\x5d\x43\xde\xbe\xa5\x0d\x9d\x0f\x03\x5f\x2e\x43\xa1\x4c\xa6\xab\x67\x3e\xf1\x96\x5a\x47\xbf\xef\x8e\x94\x0c\x02\xc9\x02\x4a\x5f\xb6\xcb\x2c\xd7\xc3\x59\x11\xa3\x98\x3b\x0c\xa5\x33\x35\x8c\xc6\xa4\x71\xad\x7e\x62\xd4\x1a\x72\x49\x6c\x9c\x37\x31\x05\x44\x34\x2c\xdb\x31\xa6\x5b\x69\xff\xbe\x6d\x60\xcc\xe5\xb6\xb3\xe8\x1f\xe8\xcf\x18\x8d\x70\xe8\x87\x0c\x6f\x6f\x4a\xfc\x53\xa0\x8e\x1b\x12\x37\x61\x8f\x03\x42\x19\x02\x59\x12\x65\xe7\x3c\x4b\xee\xdc\x85\x1b\xa9\x28\x16\x87\xbc\x63\xd4\xe1\x0a\x35\x43\x56\x5d\x36\xbc\xa3\x2f\xf5\x4d\xe8\x15\x15\x2d\x95\xc9\x91\xda\x81\xd2\x1f\xd1\x19\xd2\xb2\xea\xb5\x6c\x1a\x4d\x06\xcf\xc7\x14\xac\xe4\xab\x7f\xe4\x10\x3d\xce\x5f\xa6\x99\xbf\x2d\xec\xc4\xa4\xd8\xc8\x0e\x20\x8e\x08\x90\x7e\x76\x4b\xd5\xad\x23\x8e\x95\xdc\x26\x57\x9d\xae\xbd", 212, { 0xe8, 0x18, 0xd0, 0x40, 0x9b, 0xb0, 0x23, 0xd1, 0x12, 0xb7, 0xa8, 0xcc, 0xdb, 0xb8, 0x5e, 0xb0 } }, +{ "\x78\xca\x1a\xaa\x80\x33\xe3\x1f\xc4\x67\xae\xd5\x05\xcb\xc5\x3c\xbe\x26\x67\xcd\x0d\x38\xc9\x7b\x3b\x84\xae\x48\xea\x2f\x9e\xf3\xda\x01\xc6\xce\x57\x88\x6b\xae\x43\x5b\x0c\xfd\xbc\x7c\x14\xe9\x69\xd7\x39\xbf\x66\xe7\x74\x52\xc9\x78\x9d\x95\xd1\x87\xa2\x49\xab\x45\x63\xcf\xe0\x3a\x2e\x1f\x5e\x87\xd2\xd1\x20\x44\x62\x59\x7d\x08\x88\x50\x0b\x86\x83\xed\x2d\x54\xbe\x92\x40\xc7\x0e\x83\x5e\xfb\x88\xb1\xcd\xef\xfd\xb5\x08\xcd\x14\xd8\x67\x46\x02\x4e\x6d\x1c\xe8\x84\xae\xb9\xc8\x8f\x5b\xfd\x25\xc3\x6c\x15\x37\x65\x68\x86\xc8\x78\xd4\x4a\xae\xb3\x36\x11\xe5\x94\xc4\xa8\x48\x8e\xae\x77\xec\x5e\x05\x24\x1a\x7c\x46\x56\xe6\xac\x87\x94\x70\xb3\x3d\x4b\xb7\x27\xa8\xee\x15\x60\xdc\x38\x5b\x8b\x6c\x8d\x89\xdd\xb4\x7e\x2a\xe3\xc3\x6c\x4a\xf8\xe3\x43\x15\xd1\xc7\x68\x0e\x32\x51\xae\xe8\xc3\xfd\x81\x05\xfd\xed\x25\x88\x3f\x91\x19\x19\xfd\xf2\x95\x35\x17\x9c", 213, { 0xc0, 0xa9, 0x36, 0x91, 0xae, 0x59, 0x54, 0xe1, 0x90, 0xbf, 0x8f, 0x65, 0xc7, 0x08, 0x89, 0x62 } }, +{ "\x33\x2e\x48\x26\xaa\xc6\xb5\x5f\xb4\x64\xa5\x17\x12\xf1\x50\x87\xa6\x52\xd0\x5e\xbd\x82\x34\x69\x6f\x4a\xb4\xdd\x1f\xa0\xfe\x44\x1e\x9a\xaf\x02\x6c\x0d\xdd\x83\x9e\xc7\xd1\x04\xdb\x64\xd2\xfa\x00\xd1\x1c\x22\xe4\x5b\xf0\x26\xb5\x73\xc5\xe9\x81\x00\x9c\x70\xd1\x61\x71\x6c\x70\xfe\xcd\x68\x49\x89\x78\x8b\x6e\xd7\x4c\x0b\x35\x55\x26\x2f\x7d\x28\xf5\xfe\x0e\xe5\xf4\x89\x1e\xea\xf4\xd2\xf0\x57\xd2\x58\x97\xac\x09\x40\xd9\x01\x60\x21\x2f\xdc\xc4\x6c\xe8\xb2\x30\x77\x6c\xfd\xc8\x24\x9e\xf6\x06\x32\x5b\xf0\x0b\x20\x20\x51\x17\xb9\xc8\x2d\x14\x41\x72\x80\x4d\x3a\x81\x08\x3c\xd3\xbd\xbd\x80\xee\x96\xee\xed\xcd\x89\xfa\xbe\x58\x9c\xa7\xe5\x0d\x03\x22\x83\x84\xe5\x93\x74\x9e\x38\x5c\x01\x4a\xc8\xef\xb9\xf3\x57\x49\x59\x89\xdf\x0f\xe8\x2b\xf3\x43\xe0\x6e\x43\xa3\x86\x4d\x3e\x9e\x5b\xad\xd2\xf4\xab\x8b\x4f\xe9\x42\xc4\x69\x25\x3e\x80\x5c\x2b\x00\x3c\x2a\x74", 214, { 0x60, 0x47, 0x87, 0xbd, 0xbc, 0x4a, 0x9d, 0xcc, 0x51, 0x19, 0xbe, 0xfd, 0x54, 0x82, 0x87, 0x82 } }, +{ "\x3c\x73\x00\x28\x30\xe9\xb7\x78\xf2\x94\x76\x9a\xe1\x27\x74\x62\x3d\x3c\xdb\x7a\xd3\x1d\xc8\x3e\xd1\x2e\x6f\x36\xb8\xfb\x5c\x31\x6f\xda\xd4\xfa\x73\x3d\x5a\xba\x2c\x96\x4d\xea\x5b\xe7\xae\xf2\xb0\xe5\x00\x63\x78\xc8\x48\xce\x74\xb2\x34\x3f\xc5\xb9\x58\x59\x03\x93\x93\x0f\x6c\xdd\x90\xfc\x39\x08\x69\x60\x0c\xe0\x65\xb8\x86\xba\xe2\xf9\xf6\x3a\x4e\x68\x2c\xbe\x4f\x19\x6b\x6b\x03\x02\x7c\xd2\x61\xbb\xdf\x3e\xbe\xd4\x1d\x9c\x6c\xd2\x39\x08\x7d\xc8\x45\xf0\xa5\x8f\x10\xe7\x3d\xa2\xfd\x08\x64\x98\xef\x05\x40\x3e\x60\xcb\x62\x50\x91\xd3\x48\xd4\xdc\x08\xfc\x14\x25\x50\xd9\x36\x6f\xba\x6d\x79\x8a\x42\x7a\x0e\xea\x43\x17\x91\x94\x7a\xf4\x22\x31\xb2\xba\x25\x45\x12\x91\x92\x79\xff\xbb\xf9\x14\xaf\x5d\x16\x88\x4c\x5e\x0c\x29\xc0\x68\x42\xf8\x23\x0c\xd7\x9e\xbf\x02\xc3\x74\xbc\x8e\x8b\xbf\x6d\xfd\xa0\xf9\x35\x4f\x55\x4a\x17\xef\x7c\x16\xda\x9d\x9c\xb0\xd5\x6c", 215, { 0x9f, 0x07, 0x30, 0xc6, 0x81, 0xe5, 0xb3, 0x2c, 0x28, 0x8e, 0x78, 0x51, 0x93, 0xde, 0x42, 0x5f } }, +{ "\xd0\x2c\x5c\xe7\x3f\x51\xc7\x4f\x33\xad\x1b\x00\xd8\xc3\x58\xf2\x93\x60\x5f\x5a\xfd\x0c\x7d\x70\x7b\x9b\x98\x4c\x7b\xe3\xf4\xea\x4d\x87\xa3\x4c\x9b\xf2\x87\xbe\x87\x60\x05\x35\x60\x16\x48\xd1\x00\xb2\x2f\x82\xc4\x9d\xd4\xc6\x29\x9c\xba\x90\x00\x86\x92\x45\x4d\x10\xaa\xdf\xc2\xc4\xf3\x34\xd3\x10\xad\x51\x76\x7b\xb1\x00\x79\xf2\x5b\x6a\x7f\x41\x12\xd5\x98\x9d\x75\x8d\x7c\x5e\x23\xe1\x64\xc9\x27\x45\x86\x0b\xfe\x95\x2b\x43\x47\x79\x6e\xb6\x07\xe3\x93\x26\x95\xb5\x01\x3c\x28\x80\xdd\x22\xfb\x68\x45\x2d\x1a\x23\x26\xb8\xcd\x20\xbb\x0c\x9e\xc4\xa2\x7b\x07\xcf\x9c\x8c\xbd\xdd\xe1\x50\x93\x09\x1e\xd3\x0d\xac\x0d\xae\x82\x43\xae\xba\xec\x6f\x27\xdf\x50\x15\x35\x0a\xc4\xa5\x4e\x3d\x22\x78\x55\xc0\x48\x53\xf9\x75\x08\x09\xab\x49\xb3\x3c\x3a\xc6\x3d\x43\x0c\xc6\x0d\x28\xfb\x42\x64\xc8\xc9\x49\x67\x1d\x42\x0c\xca\x99\xed\x16\x1b\xa8\x6e\x98\xa8\x58\x7b\xe2\x0f\x15", 216, { 0xa6, 0xa5, 0x85, 0xaa, 0x5a, 0xae, 0x5b, 0xdc, 0xc7, 0x29, 0x53, 0x55, 0x13, 0x71, 0x93, 0xef } }, +{ "\x79\xee\x60\x8d\xb2\x17\xf0\xb2\x35\xe7\xbd\xde\x4b\x0d\x79\x10\x91\x6d\x35\x54\xb7\x52\xab\x41\xd4\xbf\x28\x9c\x63\xe3\x14\x1b\xde\xaa\x1f\x43\xf5\x70\x0a\x72\x6b\xd0\x0f\xf9\x8e\x9b\xef\x61\x51\xe5\x96\xcf\x07\x39\x6c\x82\xbe\xec\x3a\x78\x36\x8f\xb7\x30\x7d\x7e\xaf\x8b\x28\x95\xcf\xcc\x2f\x02\x0f\xbe\x66\x36\xbc\xf5\x94\xf6\x21\x2c\x32\x8e\xd1\xce\xc1\x24\x94\x90\xc8\x2a\xec\x3b\x69\xed\x42\x87\x9f\x4b\xb2\x23\x17\x81\x70\xd2\xa7\x22\xd5\xaf\x6f\x24\x0a\x91\x8b\x15\x50\x89\x72\x6b\xe9\x88\xee\xf8\xa6\x1e\xb8\x7c\x0e\x5d\xaf\x55\x28\xdc\xb5\x51\xe6\xd7\x26\xa4\x2e\x74\xf6\xf5\x85\x20\x66\x92\x5a\x18\x63\xc4\xed\x04\x7b\x3e\xda\xbd\x7c\xaf\x46\x2f\xab\x77\xa5\x5a\x9e\x76\x25\x73\xb7\xff\xba\x27\x3d\xeb\xc7\xff\x18\xca\x66\xde\x29\x35\x54\xa8\x44\x3f\x7c\xfd\xcb\x0a\x1e\x23\xe8\x75\x9c\x02\x66\xf3\xe1\x48\x2d\x77\x6e\xad\x58\x8b\x02\x51\xf5\x80\xe6\x41\x58", 217, { 0xf2, 0xd7, 0x83, 0x16, 0xed, 0x22, 0x8c, 0xde, 0xa0, 0xe8, 0x95, 0x2a, 0x6c, 0x79, 0xc1, 0x12 } }, +{ "\xc0\xd2\x18\x1c\x3f\x7f\xc2\xb7\x10\xca\x5c\xb9\x14\x82\x37\xa1\xcd\xce\xfc\x5c\x50\x3e\xe9\x5b\x59\x6c\x39\x4f\x79\x4e\xa2\x84\x6a\x1c\xf8\xd7\x83\xd8\xef\x56\x46\x7f\xfd\x72\x17\xca\x5e\xe3\x08\xa1\x31\x19\xcf\x1d\xc0\x5a\xd9\x38\xdd\x7c\x77\x14\x67\x41\x37\xe4\xec\x4a\x4e\x7b\x68\xba\x30\x6f\x2c\x68\x42\xea\xda\xc0\xa7\x0d\x8d\x37\x37\x00\x15\x68\x8e\x9a\x60\xd0\x40\xaa\xf4\x23\x2a\xe0\x98\x48\xe4\x5b\x13\xf8\x52\xd0\x0c\xee\x5a\x53\x10\xcc\xb0\xc6\xb2\x8a\xcc\xdb\xcd\x9b\xfd\xc7\xe5\x9e\x97\x85\xac\xbd\x48\xc3\xa0\xa6\x89\x6d\xd1\x24\x30\xd5\xc1\x59\x22\x7c\x64\x9a\x25\x80\x46\xe7\xd3\xa1\xcc\x05\xaa\xf1\x92\x3a\x41\x18\xf4\xa5\x95\x41\xa8\x37\x82\xa5\x88\x52\x4d\xb2\x6e\xfc\x5e\xd7\x39\xc0\x0b\xef\xec\x21\x8f\x47\xf5\xbc\x19\x4e\x8a\xf9\x01\xd8\x2f\x6d\x15\x0e\x55\xd0\x12\xf6\x1c\x96\x2e\x9b\x39\x2c\xd2\xd9\xf3\xd0\x65\xc7\x47\x0d\x44\xc1\x2c\xd2\xce\x10", 218, { 0xdf, 0x39, 0x06, 0xcc, 0xa4, 0x24, 0x46, 0xc5, 0xa8, 0xd7, 0xba, 0x98, 0x18, 0xc2, 0xff, 0x44 } }, +{ "\xf1\x2e\x9b\x39\xc2\xab\xcc\xdf\x49\x44\x7d\x55\x70\x03\x57\xc4\x45\x3b\x43\xf5\xf7\x5f\x39\xbc\xfd\x7e\x36\x02\x56\x5c\x4c\x6d\xeb\x2e\xd3\xae\x10\xf1\xbd\x66\x29\x67\x07\xb6\x69\xaf\x4c\x62\xb6\x80\x74\xa1\xa9\x02\x89\x83\xb1\x49\xaa\xff\x57\x6e\x18\x98\x9c\x4c\x6e\xac\x7e\xd4\xed\x59\x99\x0e\xf5\x0c\xeb\xac\x90\xa7\xb0\x4c\x29\x4e\x6c\x4b\x5a\xcf\x07\x40\xe3\xac\x12\x1c\xb6\xc5\x27\xdc\x2e\xa6\x6f\xe8\x60\x6b\x3e\x0c\x8a\x4c\xd8\x10\xa9\xc9\x57\xf5\x26\x73\xa4\xcf\xb0\x54\xa3\x3a\x25\xfc\x6b\x7a\xa9\x29\xb2\x33\xda\x12\x48\xc1\x1a\x50\xba\x35\x0b\x6a\x17\xed\x19\xfb\xcf\xcf\x30\x82\xb6\x22\x8f\xc6\x28\x08\xb4\xe4\x47\x9c\x77\xf6\x60\xa4\x33\x62\x6c\xf3\x1f\xbc\xb2\x5e\xba\x59\x8a\x58\x65\x71\x3c\x2d\x0a\xf0\x06\xd8\xfa\xd9\x3c\x81\xd5\x57\x8a\x96\xa2\x62\x55\x84\xff\x0a\x40\x12\x72\x64\xcb\x5a\xdd\x0e\x15\x66\x10\x5f\xc2\x63\x79\x30\xf7\x84\xf6\x42\x82\x76\xcb", 219, { 0x9a, 0x70, 0x70, 0xa9, 0xb4, 0x61, 0xe5, 0x09, 0x0c, 0xb2, 0x96, 0x1f, 0xf2, 0x98, 0x95, 0xe3 } }, +{ "\x4a\x17\x7b\xaf\xa0\xb6\x26\x01\x80\x28\xb2\x18\xfa\xa7\xfe\xb7\x7c\x9d\x29\xa0\xfa\x85\xc6\x3f\xb7\xee\xbc\x87\xb3\x9e\xbd\xdb\xb1\xd3\x61\x22\xe4\xa5\xde\xfd\x35\x87\x66\x15\x34\xec\x1d\x8d\x98\x06\xb6\x97\x74\xa9\xa9\x22\xf9\x4e\x13\xb1\xe2\x34\x29\x47\x80\xa1\x5a\x7e\x62\x47\x01\xb8\xa0\xc1\xc4\x6c\xc4\x3c\x8c\xa2\x56\x33\x21\x7a\x03\x52\x60\xe6\x69\x7c\x1c\x77\x82\xe8\x8f\x55\xaa\x66\x7b\x49\x4e\xc0\xe2\xf4\x33\x3b\x5e\x23\x60\x3d\x1e\x3a\xaa\x08\x7d\xcc\xda\xa4\x40\x4d\x7c\xdb\x6c\xdf\x47\x5e\xc2\x48\x24\x06\xd9\x05\xdd\x34\xd6\x78\x63\x59\xc9\x3c\xbc\x91\xa7\x99\x87\x6a\xe0\x13\x2d\xc4\x9d\x1d\xa6\xd0\x98\xeb\xe5\x3a\x97\x65\xe1\x63\x86\x37\x41\xc7\x30\x05\xa4\x7e\x9a\xbc\x8a\xde\xfc\x04\xe2\x3d\x5d\xd1\x30\xd4\xc9\x19\x5a\xbf\x32\xa0\x10\x20\xe1\xee\xd7\x64\x97\x63\xb0\x9e\x44\x61\x69\x0f\x63\xa7\x7f\xc7\xf0\xbe\xae\x64\x07\x8b\x18\xf9\x1b\x05\x0d\x0b\xcf\x01", 220, { 0x8a, 0xd2, 0x4d, 0x87, 0x81, 0x67, 0x56, 0xc3, 0xa6, 0x51, 0x29, 0xe9, 0xa8, 0x9f, 0x1d, 0xc2 } }, +{ "\x7d\xb5\x74\x2a\xf7\xeb\x20\x0c\x5d\xdb\x67\x4f\x27\x6f\xb9\x00\x50\xef\x58\x0b\xe0\xc4\xf3\xc5\x17\x57\xe4\xa6\x33\x18\x03\x14\xdf\x9b\x25\x5a\x38\xdc\x35\xb7\x7c\xa3\xec\x93\x51\x03\x30\xcd\xb0\xfc\x07\x2f\x6c\x40\x36\x03\x63\x13\x7a\xbf\x3f\x4b\x62\xdb\xe9\x77\xc7\xc3\x8c\x1c\xe9\xe8\x41\x1a\x28\xf1\x5c\x2e\x5c\x10\x52\x91\xd1\x6f\x46\xbd\xe2\xc8\x2f\x4f\x30\x14\xa6\x08\x80\x5b\x51\xed\x2f\xaa\xe8\x8f\x52\x23\xe1\x65\x6e\x2e\xbc\x55\xd0\xce\xed\x51\x8b\x0e\x61\x1e\x0c\x99\xae\x30\x5b\x69\xdc\xb2\xf0\x98\xca\xa2\x30\x52\x3f\x18\x83\xec\x8e\xa6\x12\x0d\xe5\xdb\x22\x0a\x32\xe2\x08\x50\xb1\x48\xc8\xfa\x17\xdb\x4e\x83\x54\xad\x48\x95\x09\x38\x9e\x00\x86\x9b\x8f\xc6\x7e\x03\x69\x53\x4a\x25\xe5\xca\xd6\xe7\x1d\x7a\x2c\x1e\x2a\x6f\x9b\x72\x5e\x25\x83\x5e\x1b\x58\xc0\x54\x4e\xf7\xb1\xfd\x8c\x36\xe4\x9e\xc7\xc2\x60\x96\xac\x10\x8e\x04\x9d\xcf\xc4\x85\x46\x7c\x6f\x1b\xde\x13\xdd", 221, { 0x11, 0xa3, 0xea, 0x6a, 0x2d, 0xee, 0x6c, 0xd5, 0xd4, 0xd9, 0xde, 0x9e, 0x00, 0x76, 0x0c, 0xd3 } }, +{ "\x29\xfc\xe3\xa5\x9b\x13\x7b\xb3\x22\x8c\xc0\xf4\x9d\x7e\x20\x9a\x93\x0d\xe1\x0c\xdd\x5c\x93\x6e\x61\x30\xa4\xc8\xf8\x22\x12\xd5\x71\x80\x3b\x6b\xaf\xc2\xd0\x81\xed\xa4\xe8\xe2\x22\xe4\x31\x6d\x80\x9a\x41\x06\x16\x2f\x0a\x1d\x95\xfb\x6c\xd9\x2f\x7f\xe5\xe0\x9b\x3c\x63\xc5\x35\x2e\x3a\x0f\x43\xe8\x31\xe2\x53\x4d\xb7\x4d\xc0\xe8\x33\x2f\x53\xe9\x79\xc6\x05\xbd\x58\xd6\xe2\x48\x50\x72\x0a\xc2\x61\x6a\xd2\x2b\xfe\x51\x07\x6c\x21\x29\x52\x0c\x78\xad\xb7\x8b\xbd\x3b\x38\x5f\x23\x5d\x96\x88\xec\xf3\x37\xd2\x17\xfe\x23\xa7\x37\x0b\x28\x8e\x5f\x3a\x1e\x44\x3a\xe9\x45\x75\x37\x02\xca\x17\xe1\xdf\x69\x64\x4c\xd5\x2c\x72\xab\x64\x51\x70\xff\xf9\x49\x7f\xea\x5d\xdd\x2a\xa2\xbe\x6b\x84\x01\x58\x4f\xdd\xb8\xc0\x5d\x20\xa4\xcd\x8a\xcc\x39\x23\xaa\x8d\x1b\x5d\x53\x76\xcb\xd6\xe1\xde\x7e\x15\x93\xd4\x0a\xd3\xd3\x40\xf9\xa9\x93\x97\xc0\x5a\xd3\x3a\x09\xbb\x3f\x6c\x2d\x3b\xf4\xee\xbe\x13\x63\x39", 222, { 0x88, 0x92, 0xcd, 0x7f, 0x51, 0x5f, 0xd0, 0x0d, 0x4e, 0x0f, 0x7b, 0x98, 0x75, 0xa3, 0xbc, 0x7e } }, +{ "\x3f\x0b\x4e\x57\xf7\xe5\xf0\x5f\xda\x6b\x3a\x8b\xa8\x10\x37\xf8\x12\x45\x90\xf9\x16\x5b\x2c\x17\x6c\x10\xef\xa9\x18\xb8\xa4\x0c\x20\x09\xf5\x80\x58\x83\x97\x9f\x59\x7a\x82\x7b\x90\xc2\x5e\x52\x72\xf5\xfa\xf0\xcd\x63\xf5\xa2\x3a\x97\x7f\xd2\xaf\x82\x3a\x44\x31\x47\x3a\xec\xa6\xa2\x2b\x69\xc8\xf6\x92\x22\x36\xf1\x2c\xfc\xa5\xde\x72\xb5\x33\x86\x3e\xe0\xdc\xc4\x87\x7d\x05\xa4\x48\x34\x36\x37\x80\x2e\xe5\xf6\x52\x91\x6d\xd0\x4c\x96\x1e\xd3\xc4\x48\x6d\x73\x5e\xda\x4c\x79\xab\xa5\x95\x8a\xec\xbe\x9f\x52\xf4\x31\xf3\x4e\x2b\xdc\x19\x34\xaf\xe9\x8b\xff\x94\xe9\xcb\x9a\x4c\x8a\x90\x28\x22\xf5\x1c\xee\xe0\xc6\xa9\xde\x91\xa9\x01\xc1\x61\x8d\x2d\x00\xa0\x88\x45\x0e\xe5\x47\x67\x75\x4f\x30\xc2\x7c\xe7\x16\xd2\x72\x21\x98\xa6\x9b\x82\x17\x5c\xb4\x5b\x51\xaf\x23\xb3\x9f\xa7\xc0\x43\xc7\x6f\x3a\x9a\x7f\x43\x27\x61\x7f\x88\xac\xb9\x41\xf5\xc5\xc0\x58\xef\x32\x33\x6a\xf3\xff\x2d\xcc\x2d\xae\x0e", 223, { 0x01, 0xee, 0xfc, 0xcf, 0xf4, 0x83, 0xfd, 0x73, 0xc0, 0x07, 0x8d, 0x6d, 0xe4, 0x05, 0xae, 0xc8 } }, +{ "\xb8\x25\x02\x77\x2d\x99\x6b\x71\x64\x65\x09\xad\xea\x9e\x5e\xe6\x5f\xbf\x95\x63\xc9\xfb\x69\x98\x95\xb1\xb4\xec\x2c\xfe\x95\x96\x2e\x6c\x3c\xa0\x4e\xc7\x55\x0e\xca\x10\x0e\x18\x85\x8b\xc7\x92\xc2\xf3\x55\x6d\x7f\xce\xf3\x56\x6c\xdb\xc6\x7c\x87\xa7\x0c\x6f\x55\x3f\xe0\x24\xbe\xff\xac\x15\x86\x89\x2b\x85\x64\xd2\x19\xe1\xc1\x56\x7a\x42\x0e\x6b\x84\x0f\xc2\xb3\x2b\xc0\xef\xac\x47\xbd\x80\x62\x63\x64\x11\x43\x24\x2a\x6b\x13\x54\xd8\x9a\xf6\x8a\xf7\xad\xab\x78\x47\x0a\xd8\xd1\x68\x6b\x7f\xd5\x9c\x79\x90\x7a\xa4\x03\x99\x38\xc6\xdb\x99\x71\xf0\x4d\xf2\x7c\xf7\x3d\x7c\x4d\xf8\xdc\xb6\xc2\xdf\x07\x17\x8c\x06\x3c\x82\xb8\xf5\x39\xd9\xd9\x48\x33\xa9\xd4\xae\xb0\x03\x48\x0d\x01\x6a\x98\xc3\x60\xe8\x96\x08\xa2\x3b\xcd\x6f\x98\x2d\x6b\x8b\x08\x01\xc9\xae\x43\x09\x99\xcd\x63\x55\xab\x7f\x23\x85\x5c\x24\x5b\xc0\x9b\x23\x16\xbd\x99\x4b\x51\xfe\x0d\x5b\x53\x1d\x21\x9d\xa4\x3f\xfc\xad\xab\xa5\xed\x57", 224, { 0x03, 0xe5, 0xd1, 0xd0, 0xaf, 0x2a, 0x72, 0xab, 0x3c, 0xa0, 0xdc, 0x8e, 0x46, 0xe4, 0x33, 0x69 } }, +{ "\xe7\x61\x30\x9e\xca\x25\x61\xd9\x2d\x37\x7a\xf9\x74\x80\x8a\xe5\x40\xc4\xf5\x06\xca\xed\x62\xde\xe3\x80\x45\xd3\x85\x31\x08\x0a\x14\x91\xd8\x6f\x37\xe5\x0b\xd0\x4e\x13\x29\x29\x8f\xb6\x9e\xfb\xc0\x50\xfa\xd5\x93\x9f\xe2\xf4\x99\x08\x97\x06\xe4\x30\x20\x0b\x3e\xaa\x17\x54\xff\xca\x0e\xae\x8f\x98\x9c\x98\x79\xe1\x07\xaf\x27\x67\x8f\x2b\x40\x38\x55\x82\x9b\x1c\xe7\x2a\xde\x27\x69\x7c\xb7\x6f\x61\xb4\xb7\xd8\x1e\x15\xc6\x0b\xc6\x29\x47\x85\xfb\x26\xc9\xcb\x29\x6c\x66\xbc\x6f\x2b\xbc\xff\x28\x22\x85\x9a\x15\x82\xd6\xa4\x29\xf1\xf1\x13\xf0\xaa\xc6\xaf\x9c\xc1\x0d\x28\xad\x84\xf9\x42\x3c\xfe\x99\x2e\xe5\x95\xd0\xf5\x4f\xd3\xef\x0d\x5a\x41\xec\x0e\xe3\x6f\x42\x7e\x36\x11\x64\xc8\x11\x44\xdf\x4c\x51\xee\x0b\x90\x3c\x42\x6d\x93\x6a\x63\xac\x42\x50\x20\x2e\x04\x6a\xde\x4f\x70\x05\x93\x3e\x1e\xa6\xee\x73\x9b\x1a\x95\xd0\x76\x1b\x86\x54\x77\x9c\x9e\x76\xf0\xb2\x38\x24\x2b\x1e\xee\x57\x02\x7b\x7b\x52", 225, { 0x1e, 0x37, 0x6b, 0x9f, 0xa2, 0xf6, 0xbd, 0xe8, 0x1e, 0x4e, 0xdc, 0xe4, 0x20, 0xaf, 0x0b, 0x93 } }, +{ "\x8e\x01\xc1\x78\xf7\xf3\xe5\xc8\x6b\xab\x98\xf6\x2a\x40\x71\x27\xbd\xd1\x76\x48\x46\x71\xba\x0b\xf3\xaf\x20\x7f\x8d\xc0\x3d\x4a\x2d\x4b\x5c\x86\x0d\xd1\x9b\x36\x7c\xb7\x32\x64\xeb\xf2\xd4\xd8\x25\x4e\x2e\x76\x9c\x5b\x8c\x35\xde\xf4\x9b\xb8\x27\x6d\x49\x8a\x0f\x58\xc8\xfb\x64\xf4\xb2\x91\x12\x34\x47\x2d\x3f\x67\xd1\xbc\x74\x88\x28\x96\xf5\x24\x52\x76\x31\xe4\x42\x16\x54\xb6\xc1\x67\xfa\x9c\x6a\x6a\xff\x11\xcf\xae\x72\x13\xba\x66\xa8\xd2\x8e\x26\x6c\xf3\xcb\x3a\x54\x81\xb0\xa3\x2f\x71\xfa\xaf\x9a\xd0\xcb\x34\xb2\x8b\xa6\x69\xe3\xdb\x97\x60\xdf\x4b\x6f\x24\xab\x67\x2d\x6b\xd3\x03\x79\xf8\xbe\x25\x49\x90\x1c\x90\xa6\x96\x7b\xed\x89\x45\xf9\x98\xdf\x8a\x14\x05\xac\x7c\x9d\xce\x4c\x79\xcc\x5a\xd4\xde\x6c\x2b\x96\x62\x37\xc3\xc3\x10\x3c\x34\x2b\xdf\x7c\x43\x21\xef\x95\x38\x7a\x62\x96\x45\xb4\xd5\xf1\x90\x32\x7a\x8e\xdf\xa5\xd3\xfc\xdf\x87\x0d\xc2\x11\xc1\xf7\xd4\x52\x6d\x9d\x21\x05\xb5\x85\x49\xdf", 226, { 0xfc, 0xeb, 0xea, 0x4e, 0x08, 0xfa, 0x14, 0xd6, 0xcc, 0x61, 0x90, 0xfa, 0x48, 0x06, 0x9e, 0x7a } }, +{ "\xda\x85\x6c\x4e\x51\x3f\x1e\x87\x08\x3b\x76\x2b\xc6\x9f\x46\x95\xb0\x8d\x65\xc2\xe7\x19\x27\xde\x4f\xe6\xee\x67\x6b\x5c\xda\x00\x64\x88\x9c\xd4\x29\x8f\x68\xa5\xaf\xd0\x08\x70\x59\x96\x0e\xbf\x74\x76\x22\x8b\xd9\x4b\x79\xcb\xb5\xcc\x66\x9d\x66\xc7\x0a\x10\x7b\xfc\x28\x8c\xde\x99\x13\xdf\x0e\x4d\xc8\xe4\x84\x0a\x18\xd2\x37\x5c\xfe\x1e\x3b\x61\x0f\x0e\x85\x64\x0f\xdc\xc9\x1a\x9f\x83\x84\x78\x14\x28\x16\x2f\x64\x28\x07\xc6\x3a\xba\x6a\x52\x29\x41\x5e\xd3\xfc\x31\xb1\x2e\x2c\x9b\xa0\xc3\x6b\x56\xba\xaa\x5d\xcc\xe2\x8f\x66\x5e\x73\x27\x9e\x75\x7e\x4e\xe1\x26\x2e\xbf\x04\x81\x4d\x6f\x22\x77\xdf\x86\x14\x65\xec\xfb\xfe\x41\x5c\xca\x06\x60\xfa\xd5\x20\xe1\x9b\x55\x05\xba\x58\xfb\x43\x5d\xf6\xa7\x6d\x06\x67\xc4\x72\xa4\x6a\x3e\x0b\x61\x4d\x21\x4e\xd0\xd2\xcf\x60\xb2\x30\xdd\x47\x65\x30\x8c\xde\xea\x78\xdf\xe1\x91\xe5\x5d\x28\x43\x11\x65\xf1\x6c\xf4\x29\x56\x83\xa6\x49\xdd\x37\x42\x0c\x2e\x37\xe7\x3d\xdf", 227, { 0xe2, 0x2e, 0xd4, 0x1d, 0xb5, 0x4e, 0xf8, 0x9c, 0x90, 0x06, 0xb3, 0xdc, 0x67, 0x84, 0x36, 0xff } }, +{ "\x9e\xd8\xa0\x6c\xfa\xc3\x10\x42\xf8\x1f\x36\xfa\xad\xae\xe8\xa3\x83\x22\x1b\x38\xbe\xdc\x86\x31\xaa\xcf\xd6\x35\x63\x83\x87\xec\x40\x36\x66\xf3\xdd\x1d\xa0\xe9\xc4\xc8\x85\xa6\xb8\xa3\xdf\x8c\x9d\x98\xe9\xf5\x07\xd2\xee\xcb\x5d\x9d\x80\x37\xaa\x69\x51\x72\x00\xee\xb1\xb7\x89\x69\xa4\x59\x2b\x04\x9f\xf0\xd7\x53\xdf\xaf\x6f\xfa\x66\xd1\x51\x6d\x94\x32\x85\xd0\x5e\xfa\x7f\xfd\x2d\x74\x91\xa3\x55\xfd\xf0\x8b\x30\x17\x60\xf6\xd7\x9d\x7f\x23\x7c\x11\xac\xed\x67\x11\x92\x90\x8b\xe9\x54\x8c\xc4\x41\x57\xa2\xb0\xf7\xa6\xfb\x27\x08\x06\x68\x58\xa7\x97\xc4\x81\x70\x24\x76\x4a\xb6\x07\x13\xbf\xf8\xbc\x20\xe9\x73\x00\xf5\x08\xd1\xa5\xbc\x6e\xff\xf5\x99\xfa\x1c\xc1\xe4\x30\x8d\x05\x91\xf2\x2d\x39\xb1\xdd\xa2\x36\x11\x43\xcb\xc3\x00\xc0\x55\xbc\x2f\x7b\x6d\xde\xb1\xfb\x8f\x31\x21\xa3\x7d\x12\xe2\xcc\x4c\xdc\x81\x7d\x99\x33\x38\xc9\xd8\xed\x8c\xc6\xcc\x9c\x15\x25\x13\xbc\x5e\x73\xd9\x76\xe2\xeb\xad\x0f\x37\xf5\x70", 228, { 0x55, 0xd9, 0x74, 0x7a, 0xdd, 0xdb, 0x7e, 0x9a, 0x38, 0xc0, 0x19, 0xe1, 0xa7, 0xca, 0x59, 0x91 } }, +{ "\xf0\x47\x3f\x69\x52\xb8\x77\x76\x86\x6d\xa2\x5e\xde\x26\x1c\x41\x3b\x43\x2c\x30\x34\xa6\x43\xd9\xe0\xb5\xd2\x5b\x41\x7f\xc5\x38\x4d\xf6\x9f\x68\x9a\x5a\x33\x8a\xa5\xb7\xfc\x36\xbe\x85\x1a\x6d\x94\x6d\xe9\x32\x59\x2b\x40\x32\x91\x8e\x43\x9e\x7d\x9d\xe6\x1a\x1e\xd4\xfe\xcd\xe8\x8c\x05\x99\x05\x78\x6a\x65\x42\x4b\x93\x95\x9a\x77\x70\x9b\x5d\x11\xbd\xa7\xfd\xd0\xd4\x7a\x75\x35\x2c\x58\x57\xc4\x72\x1c\x70\x70\x42\x65\x19\x14\x82\xee\x1d\x1e\x5b\xfc\x42\x46\xd5\xf0\x76\x7c\x0f\xfc\x98\xe0\x17\xf2\xdf\xeb\x6c\x38\xeb\xab\x0d\xd8\x66\x2b\x3d\xb4\x56\xf1\xd6\xd7\x03\xa0\x47\xe6\x7f\xbe\x2c\xb5\xd7\x90\x88\xf6\xd5\x22\xa2\x0c\x6e\x63\x79\xfd\xcf\x6c\xe4\x86\xff\xe1\x4b\x49\x30\x70\xfc\x22\xa8\x77\x2b\x97\x47\xc2\x89\x6d\xb4\x71\x7f\x57\x28\xf8\x07\xca\xd6\x41\x27\xec\xf6\xec\x0c\xaa\x6d\xb6\xbf\xe9\x1b\xf7\x86\xd4\xc0\x45\xd9\x54\x8b\x37\xff\x9e\x41\x44\x46\xe5\x07\xc9\xdb\x31\xcc\x29\x4b\x48\x55\x0e\x97\xc8\xe6", 229, { 0xd9, 0xf5, 0xd6, 0x7b, 0x77, 0x59, 0xa0, 0xb5, 0x8b, 0xaf, 0xaa, 0xc9, 0xea, 0x60, 0xdf, 0xe2 } }, +{ "\xce\xed\x56\x8a\xea\x09\xf1\x00\xb0\x28\x60\x42\x00\xa4\xca\xb2\x2b\x31\x64\xe4\xf7\xb2\x44\x02\xbf\xb9\x55\xe0\xb7\x9a\x63\x9d\x4e\x2a\x56\xf2\xac\x19\x7c\x1a\x5b\xe9\xff\x5e\x02\x8a\x75\x3c\x4b\x94\x96\x33\xe6\x20\x09\x2e\xa7\x44\x57\x8b\xcb\x28\x01\xc6\x58\xc9\xac\xc6\xa2\x4a\x7a\xc4\xe9\xf2\x75\xd4\x20\xc7\x25\x12\xc9\xc4\x41\x6a\xfb\xb9\x82\x03\x85\xc0\x92\x49\x2d\x57\x24\x95\x11\x1f\x1d\x7c\x2f\x30\xef\xb1\x00\x17\x07\x97\x3f\x6d\x5d\x67\xc7\x15\x28\xfb\x9a\x11\xb4\x35\xfe\x01\x4b\x0e\xc1\x3a\x50\x3f\x9e\x7f\x6c\x85\xb8\x5f\xdf\x95\x43\x2a\xf8\x9c\x42\x91\xa0\x71\x6a\xd9\x10\x5a\x26\xbc\xa3\x78\xb4\xdc\xc5\xd0\x6c\xe4\x0b\xf6\x21\x3e\x5d\x58\xa0\x6a\x4e\x24\x56\x02\x8c\xd7\x0e\x47\x73\x64\xd7\x66\xbc\xfd\x03\x4d\x52\x80\x4c\x25\x45\x81\x12\x6b\xd7\xf0\xc0\xae\xb4\x67\x4c\xe7\x3f\x13\xdc\x70\x08\x3c\x86\xa3\x5a\x72\x30\x10\xf0\x56\x97\x5a\xc7\x02\x6b\xae\x0e\x16\x96\xe1\x3a\x60\x9d\x26\x36\x27\x1f\x69", 230, { 0xc7, 0xb4, 0xa5, 0x2d, 0xd4, 0x3e, 0xbe, 0xcb, 0x90, 0xc5, 0x10, 0x56, 0x22, 0x68, 0xc4, 0x02 } }, +{ "\xb8\x14\x7b\x4a\xaf\xbe\x8f\xb9\xd8\xd0\x9b\x2a\x70\xd9\x43\x75\x04\xb0\xb3\x4e\x64\x82\xdd\x5c\xb6\x7a\xde\xf7\xa6\x0b\x7e\x83\xbb\xdd\xd6\x64\xc5\x51\x0c\x9c\x72\xb3\x3a\x08\x01\xfb\x6d\x34\x0e\x40\xc9\xd6\x8b\xba\xca\xee\xcf\x72\xa5\x78\xc8\x88\xcd\xca\x4d\x21\x91\x90\x8e\xeb\xe2\x62\xad\x4e\x33\xff\x65\x30\x79\x29\xe8\x65\x52\x1c\xc7\xb2\x42\xac\x0b\x7c\x18\xfa\x61\x12\x6f\xd2\x71\x94\x50\xa5\x4f\x7e\xf5\x1e\x0a\xd5\xa8\x62\x63\xec\xca\xe9\x98\xd3\xf0\xf4\x5d\x5d\x28\xaa\xec\xcd\x59\xd3\x33\x1c\xc8\x30\x2c\xea\xb7\x74\x4b\xff\x28\xe3\x10\x7c\xbf\x86\xbc\xa2\xc5\x08\x20\x3e\x49\x31\x90\xb0\x61\xfc\xf7\x97\x8e\x56\x05\x1c\x3d\x76\x83\xd7\x6a\xd3\xc6\x61\x5f\xc7\x42\x77\x9b\xbe\x36\xc7\xcd\x1a\x85\x5b\xff\xa7\xa5\x9f\xd0\xb6\xb0\x10\xda\xd8\x98\x83\x32\x38\x78\x0f\x0d\x96\x05\x99\x7f\xdc\x23\xfa\x5f\x5e\x94\xcf\x47\xb3\xcb\xdc\xb8\x2a\xdf\x1d\x5a\xeb\x9b\x6b\x60\xac\xb2\xc8\x0a\x0c\x0f\x47\x44\x90\x4b\x9b\x6c", 231, { 0x40, 0xc0, 0x57, 0x95, 0x6a, 0x81, 0x82, 0x29, 0x3b, 0xd0, 0x98, 0x14, 0x84, 0xa7, 0xa4, 0xd1 } }, +{ "\x37\x38\x3a\x31\xbb\x9a\x2d\x97\x67\xf5\x77\x16\x90\x82\x1f\xe2\xb1\x3b\xdc\x46\x27\x15\x5d\x2a\x85\x4e\x32\xb3\x95\xdc\x5a\x09\xec\x05\x69\x34\x29\x0c\x56\x1f\xca\x09\xdf\xbf\xaa\xd2\x99\x4d\x1b\x15\x98\xaf\x9c\x88\xb6\xf5\x37\x37\x84\xfe\x7a\xfc\xcb\x3b\x0f\x0d\xbd\x8b\xfa\xaf\xbd\x46\x6f\x09\xc8\x56\x4e\x13\x7e\x7f\x3c\xad\xd1\xbe\x5f\xcc\x49\xcf\xb5\xcf\xf1\xc9\x12\xf0\xe1\xe5\xb4\xd6\x69\x5c\x84\x46\xd7\x6e\xec\xfa\xe6\x7e\x4f\x8a\xc3\x5a\x29\x87\xbd\x99\xc5\xa7\x88\x1e\x95\x1a\x2d\xb9\x31\xfb\x92\xec\xef\xe2\xa1\xca\x1b\x96\x18\xfb\xd3\xe0\xed\xdd\x82\x7a\x5c\xc5\xf7\x26\x8e\x63\x21\xdc\xe7\x43\x69\x1b\xed\x70\xac\x61\xd0\x33\xd4\xb6\x9a\xf9\x12\x62\xf4\x52\xb9\xbe\x92\x16\xba\x28\x3c\xa2\xb8\x10\x7a\x40\xc7\x2f\xdc\xa5\xc6\xd8\xe3\x93\x56\x66\x8f\x9f\x76\xd5\x86\x0d\xbd\x6d\xde\xd7\x33\x99\x87\xcd\xcb\xd6\x58\xd6\x81\xc7\xb4\x54\x0c\x65\xd9\xa5\x41\x53\xc5\xc6\x04\x4f\xc5\x13\xeb\xc5\x9b\x2a\x70\x7e\x4b\xed", 232, { 0x0f, 0x8c, 0xf7, 0x8f, 0xe2, 0x33, 0xb8, 0xdb, 0x7b, 0x4b, 0x15, 0x6c, 0x88, 0x92, 0xce, 0x22 } }, +{ "\xd3\x75\x82\xa5\x8a\xca\xa4\x44\x66\xd0\x70\xc3\x44\x41\x52\xaa\x6c\x91\x46\xae\x89\x5f\x64\x74\x45\x08\x0c\x74\x81\x56\xae\xf9\x2e\x56\x36\x44\xcb\x47\x13\xd0\x7b\xae\xe3\xb1\xc2\x87\xbd\x16\xdc\x96\x1a\xed\xba\xdb\x60\xa5\x99\x23\x0d\x0f\x41\xbb\x7c\x5e\xd8\x40\x57\x4d\x60\x92\x9a\x5f\xd4\xe7\x3f\x42\xda\xfb\x8c\x4d\x24\x65\xf5\x28\x69\x05\xae\x8b\xfc\x9a\xd2\x1f\x06\x70\x29\x80\x65\x36\x99\x64\x1f\xee\x2c\xd5\x84\xfd\xba\x9a\xe0\x62\x33\xb4\xda\x03\x8b\x04\x6d\x23\x42\x0a\x80\xf1\x8f\xc8\x23\x3a\x28\xc5\x68\x3d\xb1\x2d\xdc\x9f\xbf\x15\xa1\x75\x87\xdd\x29\x7f\x27\xae\x91\x75\x91\x23\x98\x78\x10\x05\x3a\xab\x78\x2e\xed\xdb\xee\x8e\x77\x59\x51\x4c\x6a\xe9\x44\x04\x3d\xd3\xda\x2f\x09\x16\xdc\xa0\xdd\xbc\xb9\x2b\xbe\x49\x0b\x60\x3e\x4d\xc2\x75\xb7\x19\xef\x42\x25\x8e\x2f\x65\x9d\x11\xb2\x85\x6e\x9a\xe7\xb4\xd3\xec\xc6\xee\x51\xdf\xb9\xbe\xb3\xd9\x28\x00\xa0\x5b\xa0\xc1\xd6\xb7\x9f\x42\x05\xe0\xfe\x1c\x4a\x5a\xfb\x7d\x46", 233, { 0xe5, 0x61, 0x01, 0x70, 0x0e, 0x76, 0x73, 0x8d, 0xa8, 0x90, 0x1c, 0xda, 0x14, 0x27, 0xde, 0xf4 } }, +{ "\x50\xe2\x90\xdb\xc4\x58\xfb\x83\xe0\x44\x82\x4c\x6c\x5a\xc9\x74\x59\x45\x36\x9c\x7a\x71\xf5\xac\x52\x72\x15\x44\x08\x14\xcf\xda\x77\x00\xe7\x75\x62\x07\x2c\x05\xc5\x0e\x19\x5c\x46\x96\x9e\xcd\xca\xe7\xf8\x60\x25\xd9\xbd\xaf\xe9\x3f\xf4\x60\x5f\xf0\x60\x3f\x94\x73\xde\xf6\x8a\x46\xe4\x6c\x90\xcb\x29\xb8\xac\xd0\x63\xc1\x34\xba\x2c\x74\x7c\x4d\xfe\xa0\xa9\x1a\x5d\x71\xa4\x85\x14\x87\x2a\x71\x97\xb2\x01\x8b\x87\x4c\x45\x30\x55\x33\xe1\xfc\xfe\x62\x19\xf0\xf4\x2c\x43\x3f\x1d\x14\x96\xb5\xf4\x4b\x1a\xc4\xce\xc7\xbf\x2d\x37\xfc\x8a\x48\x7b\x39\xea\xef\x40\xa2\x29\x0d\x50\xc6\xfe\xbe\x75\xdc\x3f\x23\x7d\x9f\xb3\xc6\x5d\xc3\x05\xa4\x72\x12\xd5\xdb\xe2\x28\xe9\xf1\x21\xc7\x81\xbe\x90\xd8\xc8\xf8\x40\xff\x66\x59\xd4\xd9\x32\x6f\x83\xd5\x05\x00\x3d\xac\xaa\x17\xe5\x7e\xf1\xaf\xbd\x8b\xe3\xfb\xe0\x8a\x0f\x50\xe8\xa9\x03\xb0\xaf\x22\xd7\xf4\x33\x77\xe3\x95\x93\x4a\x90\x17\x36\xdb\x4c\x12\x0b\x1e\x97\xde\xea\x78\x3b\xda\x19\x16\x98\x59", 234, { 0x2d, 0x01, 0x5b, 0x45, 0xca, 0x44, 0x57, 0xf8, 0xea, 0xbb, 0x14, 0x25, 0xd1, 0x7b, 0x62, 0xec } }, +{ "\xeb\xea\x1d\x2a\x84\x43\xd3\xc3\xb7\x08\x13\x09\x10\x91\x58\xbf\xed\x23\x2f\x88\xc7\x05\x4b\x9a\x8f\x43\xb5\x01\x33\xff\x20\x8d\x3f\x6e\x5a\x5a\xa0\x76\xdf\xfa\x85\xe2\x88\x41\x5e\x40\x61\xac\x06\x58\x97\x6e\xfd\x49\x90\x19\xce\x41\x15\xe6\x90\xd8\xaa\xa1\x87\x0a\xff\x33\xea\xcf\x7f\xcd\xbf\x59\x05\xaf\xe3\xea\xae\x92\x26\x4f\xc9\xb8\x92\xfc\xeb\x8e\xcc\xc5\x20\xfa\x94\x37\x3c\x47\x67\x91\x4f\xab\x44\x62\x36\x71\x8b\xc0\x4e\xc7\x00\x22\x44\x26\xef\xdb\x08\x59\x6a\x34\xe0\x2d\xae\x24\x99\xb4\xa4\xae\xd8\x35\x83\xd7\x8e\xb3\x92\x43\x8a\x18\x0b\x6b\x28\xff\x1b\x7d\x27\x1b\x07\xd1\x98\x46\x68\x03\xf3\x2a\x97\xb1\x44\x86\x23\xd2\x82\x1e\x7f\xb1\x00\x42\xb9\x86\xfd\xf8\x65\xaf\x56\xc8\x98\x90\x5b\x25\x10\x04\xbe\x73\x71\x7e\xa7\xb9\xaa\xc1\xe5\xe5\x76\x38\x40\xb6\xff\xf2\xea\x4a\x9d\x3e\x14\x44\xbb\xdf\x9c\x99\xda\xed\xe3\xf8\xaf\x48\xbd\xd4\x68\xb9\x82\x0f\x0d\xa6\x41\x44\x01\x72\x14\xb1\xa7\x6f\x8f\xbf\x21\x81\x52\x30\x33\x50\xbe", 235, { 0x92, 0x09, 0x96, 0x7f, 0x5b, 0x1d, 0x4f, 0x40, 0xe8, 0xc7, 0x0d, 0x8f, 0x7e, 0xd7, 0x63, 0x43 } }, +{ "\xe4\x46\x29\xc4\x48\x89\x72\xd9\x5c\x32\xc8\x06\x5e\xe2\xb7\x1b\x18\x27\x15\x03\xc3\x1b\xfb\x33\x97\x29\x61\x3d\xf0\xef\x55\x81\x1e\x3f\xd8\x02\xc9\x40\x55\x56\xff\xb2\xbf\xb8\xdc\x4f\x45\x38\xd5\x4c\xb5\x11\xa1\xff\x6b\x1b\xc4\x9a\xf3\x57\xb9\x15\x43\xa8\xbb\x2a\x8e\xa1\x30\x7a\xc6\x79\xb3\xcd\xb1\x1b\xbc\x77\xa7\x5a\xee\xd5\xe5\x42\xfd\xf7\x91\x8a\x3a\x58\x4b\x25\xbd\xc8\x6c\xf7\x2e\x6b\xde\xa5\x30\xda\x98\x85\x6a\x67\xb4\xb5\x32\x7d\x2e\x47\xd8\x26\x3b\x9a\x8d\xa7\x44\xc4\xef\x46\x7e\x2b\x32\x2c\x27\x33\xec\x64\x5e\x11\x7c\x03\x9f\xbe\x18\x62\xdb\x08\x73\x87\x30\xc2\x07\xa2\x4a\x1c\x04\xb3\x55\x0d\xd5\x49\x9e\xec\x4b\x64\xc5\x1f\x68\x7c\xa1\xea\xca\x9b\xb0\x69\xb3\xa5\x39\x99\xb1\xb8\x00\x90\xee\xae\xa5\xcd\x16\xbf\x9a\xaa\xe0\x44\xbf\xee\x3c\x96\x9c\x7f\x17\x15\x3a\x34\xce\x44\x9e\xc9\x2d\x12\xe3\xec\x22\x34\xf3\x74\x02\xad\xe2\xb1\x77\x6f\xe7\xde\x06\x1b\xf7\xb3\x39\xe5\x00\x17\x6d\x93\xbf\xf3\x3a\xa4\x3e\x22\x7a\x8d\xee\x84", 236, { 0x53, 0x0e, 0x63, 0xd7, 0x2d, 0xd0, 0xbc, 0x79, 0xa2, 0x08, 0xa2, 0x58, 0x61, 0x64, 0x23, 0x51 } }, +{ "\xf8\x1f\x5c\x32\xb7\x04\x93\xcb\xdc\x68\x0f\xed\x39\xb4\x59\xc0\x76\x75\x44\xac\xde\x5b\xc2\x2a\xc3\x5e\x63\xb8\x8f\xfb\x6c\xe6\x69\x9c\x90\x8e\x80\x16\x4e\x21\xf7\x4c\xe6\x1b\x6d\xf1\xf9\x98\x28\x6a\xbc\x01\xdd\xd1\xd8\xdf\x1e\x16\xe2\xd0\x60\x40\x72\x96\xa8\xd1\xe2\x4d\xd2\x48\xa5\xb5\x7e\xc0\x41\xad\x97\xb6\xea\xc1\x81\xe8\xbd\xda\xdf\x58\x95\x14\xfe\x70\x8e\xad\xe1\x3f\x14\x18\xe9\xe1\xa6\x31\x21\xfd\x2d\x8c\x24\x68\xf3\xe6\xab\xe8\x42\xbd\xb7\x13\x9a\xfc\x57\x55\x8d\xce\x17\x0f\x3b\x93\x05\xdd\x66\xf0\x61\xf0\x31\x01\xe0\x9a\x7a\xaa\x9d\xe9\xd0\x0b\x9d\x6a\x13\x11\xfd\x0f\xa7\x29\xba\x2b\x54\x10\x1d\x99\xbe\xc6\xc1\xfd\x7b\xa1\x42\x22\xd6\x7e\x84\x83\x20\x12\x9d\xe5\xad\x5e\x60\x21\x72\x41\x87\x00\x39\x27\x7c\x3e\x7e\xe0\xc4\xb1\xea\x8b\x09\x83\x69\xb1\xc2\x9b\xea\x6e\x81\x1b\xb2\xc9\xd8\x02\x5e\x25\xe9\xf0\x73\xd1\x89\x0a\xa3\xba\x11\xf4\x9f\x40\xc1\xfb\x93\x25\xd0\x55\x43\xa2\x14\x7f\xc0\x94\x4a\xc6\xc6\xd3\x03\xe2\xb5\xa4\x2c", 237, { 0x78, 0xa2, 0x83, 0x25, 0x5d, 0x8e, 0x55, 0xc1, 0x14, 0xb5, 0xee, 0x4c, 0xc1, 0x74, 0x53, 0x04 } }, +{ "\xbc\x2a\x44\x38\x51\x3a\xa4\xec\xae\x4b\x35\xc6\x1b\x8e\xd9\x0b\x54\x1c\xf8\x6c\xf2\xac\xb4\x54\xe9\xef\x34\xd1\x2a\x88\x1d\x1c\x69\xab\x1f\xc6\xf9\x51\xab\x81\xd3\x15\xc3\x89\xb5\xaf\xe9\xad\x67\x0a\x39\xfe\x19\x03\x93\x12\xe8\xc0\xf0\xf5\x7f\xab\xd6\xae\xda\x0a\xe6\x69\x26\x3d\x93\x46\xc4\x93\xed\xbd\x6d\xc8\x9b\xab\x6f\x1f\xe7\xfe\x16\x18\xf4\xfa\x26\xcf\x0a\x25\x84\xf1\x12\xd5\xf4\x5b\x1d\x54\xfc\x51\x1e\xad\xe8\x57\xb8\x16\xe7\xaf\x32\xf9\x53\x70\x88\xa1\x0e\x40\x9b\x7e\x07\xae\x88\x14\xdc\x2e\x15\x86\x9a\xb2\x47\xbb\x9f\xe1\x12\x2a\xa1\xf6\x28\x48\xc7\x38\xf3\x8b\xf5\x11\x9d\x19\x25\xce\x4c\x12\xf0\xf2\x6c\x77\x2d\x37\x24\xb5\xb0\x22\xea\xd2\x34\x42\x32\x33\x53\x05\x41\x07\xb1\x36\x21\x54\x39\x16\xad\x9c\x7f\x16\xcc\x2b\x45\x2f\xba\x00\x19\xdf\x82\x56\x1b\xc1\x88\xcd\xdd\xc7\x42\x3a\x63\x16\x07\x08\x49\x7d\x00\x49\x04\x93\x3b\x5d\x41\x6d\xde\x3d\x69\xf9\x78\x65\x46\xfb\x73\x5c\xbf\xa1\xa6\xe1\xbf\xc4\x07\xb4\x34\xbe\x7d\xfd\x34\xe2", 238, { 0xb6, 0xbc, 0xec, 0x14, 0x2d, 0x49, 0xb6, 0x90, 0x18, 0xf9, 0x7b, 0xa5, 0x1b, 0xe9, 0x0c, 0x12 } }, +{ "\xd4\x5d\x39\x9c\xca\x90\x8d\x26\x46\xbc\xc1\xe4\xa8\x58\x57\x5e\x3b\xbc\x7f\xd7\xc7\x41\xfe\x8e\x44\x14\x2b\x91\xa9\x9c\x14\x38\xe1\x85\xbd\x45\xdf\x69\x88\x96\xc9\x1b\xb0\x84\x4f\x8f\xef\xdc\x1f\x69\x40\x78\x71\x20\xbf\x79\xbd\xcf\xac\x22\x8d\x98\x8e\x54\x6c\xb5\x74\xa2\xfe\x1d\x57\x10\x29\xcf\x9b\x6d\x71\xbd\xb4\x4a\x62\x58\xe5\x96\x26\xb4\x24\xd7\x36\x58\x1a\x07\x2d\xa5\x46\x09\xb8\xe1\x41\xc6\xaa\xde\x1c\xe9\x2c\x4b\xe5\x33\x12\x97\x49\x7b\x48\x7d\x53\x46\x6b\x31\x53\xff\x74\x25\xda\xd3\x8f\x78\xe1\x2b\x0a\xfc\x09\xc7\x69\xe2\xfc\x74\x96\x04\xf3\x69\x35\xcf\x52\x44\x16\xcb\x6e\x9c\xc4\xc9\x6e\x42\x3a\xa8\x4f\x19\xb5\xc3\x01\x8f\xa5\xfa\xaf\xb7\xbd\x5c\x1c\x05\x29\x6e\x29\xa5\xdf\x1b\x73\x78\x0f\x37\x19\xac\xb4\xb1\x9b\xf6\x4c\x55\xdd\x6f\xa4\x3c\x4b\x08\xcd\xd1\x17\xab\x2b\x80\x9e\xf0\xab\xfc\xe9\x79\x14\x2d\x50\xeb\x77\xb5\x38\x89\xc1\x1e\xfc\x6e\x6f\xa2\xe9\x67\x60\x95\x64\x6b\xc6\x73\x27\xb8\x36\x82\xa8\x8b\xe0\x24\x9a\x7b\xd8\xbb\x8c", 239, { 0x9e, 0x1e, 0x8a, 0x93, 0x65, 0x23, 0xbe, 0x28, 0x19, 0x89, 0x4c, 0xa5, 0x58, 0xc6, 0x31, 0x08 } }, +{ "\x72\x92\x38\xb0\x49\x6d\x43\xb7\xff\x66\x01\xd7\x96\xed\x84\xee\x8b\xd4\xd5\xc0\xf0\x64\x96\x5d\x27\x8a\x57\x9e\x3d\x2f\x78\xcd\xe0\xa5\xb6\x64\xff\x3d\x53\xee\xfc\xf5\xe6\x0a\x90\x4e\xbc\x8f\x3c\x3c\xea\xc9\x68\x37\xf1\xe0\x1a\x6f\x0c\x59\x54\x1c\x18\xb6\x0a\xf3\x20\x39\xbe\xb4\x85\xc7\xba\xe0\xc6\xe7\xea\x89\xf2\xe9\x53\x41\xa7\x23\x34\x34\xc5\x57\xb7\x52\xb5\x30\x54\xa4\x4f\xeb\xc3\xc0\x6d\x13\x9b\x58\x0a\x64\x8c\xec\x15\xd1\x35\xa0\xd8\xa2\xa3\x28\x00\xb5\x68\xdf\x48\xe4\x53\xf7\xc6\x87\xd1\xcb\xd2\x10\xdf\x51\x8f\xd5\xab\xab\x17\xeb\xc7\xdc\x47\x2d\x08\x98\x24\x5c\x01\x34\xe8\x60\x17\xbc\xad\xad\x41\x23\xb5\xc1\x5f\x95\x54\xc9\x33\xe9\x7a\x64\x00\x32\xe1\x7f\xbd\x74\xcf\x5f\xf6\x74\x88\xbd\x40\xa9\x54\x0b\x57\x4e\x28\xd5\xd6\x99\xf4\x43\x91\x05\x88\xbb\x92\xcc\x24\xa3\xaf\x71\x9a\x44\xc5\x79\x22\xca\x93\x39\xba\x67\x35\xcb\x38\x98\x3a\x1a\xee\x80\x65\x1d\xf8\x70\xfd\x21\x24\x88\xd1\x3e\x7f\x76\xcc\xeb\x78\x5d\x30\xae\xb3\xd2\x72\xec\x6d\x00", 240, { 0x32, 0x30, 0x23, 0x6a, 0x09, 0x78, 0x4b, 0x95, 0x15, 0x31, 0x10, 0x58, 0xba, 0xcc, 0x32, 0x4e } }, +{ "\xb2\xde\x87\xeb\xd6\xa4\x31\xd1\x42\x74\x34\xad\x36\xeb\xdb\xd5\xc3\x84\x7f\xc3\x6b\x26\xae\xf0\x54\xd7\xf8\xdc\x29\x8f\x55\x2b\x8e\x27\x36\xe9\x3d\x70\x26\xee\xc2\x60\x1d\x5d\xcf\x68\x62\x46\x3d\xe1\x19\x6b\xa0\xa4\x70\x20\x85\xb8\x62\x4b\x4a\x26\x27\x8b\x9a\xe9\x39\x76\x85\x02\x02\xfa\x38\xa7\x27\xe4\x5d\x9b\x6b\x7f\x12\x99\x41\x55\x7e\xea\xf3\x11\x16\x16\x68\x84\x6b\xb7\x95\xc6\xac\x69\x83\x75\xc0\xdd\xf8\x19\xf8\x0d\xc5\xa8\x75\x8a\xac\x25\x16\xf1\xeb\x62\x1b\x7c\x69\xe7\x5b\xb4\x7c\xeb\x1e\x44\x55\x7f\x98\xe9\x09\xca\x03\x86\x3c\x6f\x57\x54\x6c\x0b\xa9\x37\xd7\xda\x1e\x2b\x0a\x79\x8a\xdd\x08\xc6\xa9\x56\x13\xe3\xf8\xd2\x1a\x5a\x31\xaf\xbe\x5a\x62\x81\x02\x20\xa9\x42\x8f\x71\x8e\xa7\xa2\x43\xfd\x8d\x93\x7c\xde\x92\x03\xd2\x53\xc1\xa0\xd1\x8d\x65\x97\xfb\x4b\xfe\x98\x09\xf1\x52\x7f\x50\x41\x9a\xa4\x3f\xb8\xdd\xc0\x04\x87\x5b\x7a\x4f\x2c\x1f\x8d\x2f\xad\xb8\x98\x18\x71\x01\x83\x05\xbb\x1b\x88\xba\xc3\x7c\xe5\x23\x73\x21\x1d\xd8\xbb\xdf\xe5\xc2\x91", 241, { 0x93, 0x4c, 0xcc, 0x99, 0x4e, 0xac, 0x76, 0x01, 0xbd, 0x95, 0x4b, 0x71, 0x97, 0xc2, 0xb6, 0x4b } }, +{ "\xd7\xb2\xd7\x89\x08\xdd\x01\x0c\xff\x6f\x1c\x38\xa9\x8f\x1e\x54\x49\x85\x52\xee\x84\x6a\xbd\x93\x9a\x6e\xa1\x2b\xaf\xc6\x1f\xee\x47\x30\xf7\x07\xd1\x24\x6c\xc3\x5a\x99\x43\x76\x62\x70\xe9\xeb\xcc\x81\xb4\x85\xee\x41\x42\xf6\xc9\x0d\xfe\x9b\x52\x15\xc1\x73\xef\xe7\x94\xbb\xfd\x97\x94\x27\x8e\x89\xee\xbe\x30\xdb\x0a\x52\xe8\x71\xc5\x9b\x3e\x9e\xd6\xf0\x72\x6b\x52\xa1\xcc\x88\x4a\xf3\x11\xcd\x92\xb9\x11\x6b\x9d\x8b\x5e\xb3\x84\xa6\x17\x83\x25\x60\xe2\x49\x68\x46\xf8\xb5\x9d\xd4\x59\xff\x01\xcf\x21\xd2\x60\x43\xf3\xd4\xd4\x15\x91\xd2\xab\x44\x8e\x8d\x67\xc0\x1a\x1b\xde\xe7\xfd\xfc\x82\x98\x9f\xba\xbb\xf6\x43\x3b\x70\xbb\x54\xa7\xa5\x36\xd8\xf0\x3e\xe2\x01\x02\xe2\xa5\xe2\x89\xfb\xa2\x3f\x59\xd9\xbb\x7d\x7f\xf6\xa6\xb8\xe2\x54\xaa\xf3\x94\x03\xf7\x6a\xbb\xbf\xa0\x04\x16\xb5\x36\xe5\x2e\x66\x02\x1f\x1c\xa5\xde\x88\xf1\xba\xb0\xa6\xc5\xa9\x84\xc7\x5f\x8d\x45\x2e\x7e\x1d\x18\x67\xc2\x50\x56\xbc\x3a\x1d\x24\xc0\x8b\x5c\xb0\x08\xb9\xc8\x09\xfa\x95\x25\x9b\xbd\xc3", 242, { 0x02, 0x2b, 0x4e, 0xda, 0x1a, 0x44, 0x77, 0x00, 0x7e, 0xbc, 0x69, 0xdc, 0x8d, 0x36, 0x54, 0xec } }, +{ "\x7e\x46\x50\x67\x88\x1b\xb7\x6c\x23\xb3\x4f\x70\xfe\x2b\x43\x4f\x59\xbf\x17\x4b\xe6\x02\x61\xd5\xc9\xb7\x98\xfb\xbf\x50\x05\x6d\x5a\x00\xd6\x2d\x6a\x7f\x51\xd3\x78\x5a\x26\x7a\x6c\xf4\xdd\x4b\x4e\x1d\x6e\xa3\x29\x4c\xef\xe4\x0b\x7c\x68\xd5\x2a\xa1\xc2\xb7\x21\xc6\xde\xe5\x57\xc5\xc3\x26\x81\xa2\xef\x93\x3d\x84\xce\x1f\xdf\x50\x49\xc8\x49\xe3\x75\x59\xf3\xec\x6c\xd9\x0b\x65\x39\x94\xb6\xac\xed\xc3\x74\x42\xce\xda\xa1\x1e\xaf\x6f\x17\xaf\x5b\xc2\xf1\x6d\x2b\xed\x6b\x1b\xb7\xa9\xe5\x9b\xa9\xba\x06\x6d\xad\xf8\xfd\xc6\x84\xfc\xe3\x49\x38\x63\x3d\x64\x6a\xc2\x9d\x4a\xc7\x26\x67\x88\x99\x46\xb1\x46\x7a\x48\x44\x1d\x23\x2c\xc0\x8f\x62\xd9\xdb\x27\x2a\xc2\xc9\x2e\xc4\x35\xb8\x07\x24\x40\x73\x28\x56\x40\x26\xb5\x17\x07\x41\xbb\x80\xa9\x75\x05\xdd\xe3\xdb\x9f\x9c\x29\x34\xe5\x61\x4b\x4b\x46\x37\xc3\x77\x9b\xe0\x9d\x3c\x1e\x4d\x03\x11\x08\x29\x64\x3d\xcb\x8f\x41\xdb\xe9\xdd\x94\xfc\x6f\xa0\xdd\xeb\x12\xae\xca\x8b\xe4\x53\x82\xdd\xb3\xa3\x8e\x9e\xff\xef\x64\x0d\x95\x52", 243, { 0x9b, 0x3c, 0x03, 0x49, 0xe3, 0x82, 0x8c, 0x8e, 0xfb, 0x2f, 0xc9, 0x7b, 0xee, 0x4c, 0x16, 0x17 } }, +{ "\x92\xcb\xcc\x6b\x83\xda\x5b\x25\xf1\xc8\xd6\xb1\xe8\xe5\xc3\x95\x73\xaf\x5d\xde\xe5\x4f\xe4\x71\xc5\x3c\x9f\x80\x57\xfe\x70\x18\xc3\x0d\x12\xd6\xe5\xd8\xf1\xba\xb0\xe1\xa5\x13\x3f\x05\x0d\x9a\x7a\xd9\x04\x9b\x61\x30\xc3\x4e\xf8\xba\xd3\x44\xcf\xc7\xac\xfd\x2d\x29\xef\x96\xd9\x36\x3d\x9f\x84\xec\xb2\x0b\xd6\x30\x02\x41\x13\x2f\x2e\x4f\x6a\xe5\xe2\x3e\xda\xbc\x6e\x80\xc1\x4c\x5f\x86\x03\x41\xba\x6e\xd3\x5a\xd4\xda\x21\x8e\xd1\xdc\xa0\x49\xb7\x0d\x73\xd4\x2e\xbd\x73\xd2\xd6\x44\x1f\xe6\x45\x77\x21\x72\x9b\x36\x79\x7b\xc4\x23\x48\xa8\x4a\x6d\x3b\x69\xd4\xca\x92\x35\x40\x83\xcc\xeb\x58\xa9\xf1\x5a\x33\x65\x7c\xdc\x2b\x6d\xe2\x1d\x76\x93\xc3\xf9\x63\x77\xac\x84\x33\x5d\x87\x23\x92\x19\xa0\xd7\xb0\x27\x54\x9a\x01\xd7\x58\xe2\x8d\xa5\xa3\x42\xf4\xa7\xf9\x30\x02\x1f\x16\xe1\xeb\x30\x73\x50\x23\xae\xb7\x5e\xdc\x0e\xbd\x14\x1d\x7c\x3e\x04\x7c\x0c\x1b\xcd\x78\x08\x4a\xbc\x75\x68\x5a\x8f\x54\x5f\xa4\x56\xae\x12\x10\x73\xae\x64\x81\xc0\x88\xec\xde\xcf\x9a\x08\xbe\x4c\x1d\x0b", 244, { 0x74, 0x8d, 0xdc, 0x08, 0x81, 0xb7, 0x48, 0x31, 0x0b, 0xac, 0x8b, 0x95, 0x9a, 0xee, 0x5a, 0xfc } }, +{ "\xaf\x7f\x88\x91\x24\xee\x81\xf4\xf8\x20\x80\xd7\xa3\x7b\x03\xdf\xf8\x4f\x68\x82\x98\xec\x6a\xf7\xf7\xed\x3a\x4d\x08\x98\x39\x98\x88\x5d\x50\x46\xe4\x7c\xed\x8f\xc8\xc4\x9a\x0b\x46\x76\x3b\x5d\x9f\x48\xe4\x0d\xb0\x85\x55\x74\xfb\x51\x13\xd0\x51\x0b\x24\x77\x1a\xcb\x66\x29\x41\x0b\x8c\x7e\xbe\x61\xb6\x7e\xc1\x6a\xac\x4f\x78\xc3\xb8\x09\x7d\x31\x1d\xa6\xdf\xe0\x37\x15\xcb\xc9\x30\x6d\xd8\x2c\x5c\x3e\xec\x3d\x32\x04\xcd\xdb\xe8\xb5\x48\x7b\xaa\x7a\xf8\x23\x76\x7a\xb3\x93\x97\xd1\x97\x7e\xbb\x9f\xac\xf5\xb3\x3d\x36\xe5\xc8\x8b\x9a\xb7\xb4\x65\xea\x15\x44\x34\x0f\xcd\x88\xa0\x92\xce\xb3\x63\x07\x4e\x96\x39\x16\x0e\xb4\xf4\x27\xb5\x01\xab\xa9\x59\x3c\x12\x00\x1d\xe6\xe6\x09\xf4\xdd\x7f\x4b\x84\x9a\x87\xbb\x25\x04\xc9\x2b\x08\xee\x23\x51\x75\x34\x96\x70\x2c\x6d\x7c\xa5\xed\x4d\xd9\xd0\x13\x9a\xc9\x1d\x5c\xc9\x19\x2e\xc4\x35\xf2\xe7\x8e\xfb\xb1\xd5\x64\x74\xd2\x3c\x96\x50\x0a\xbb\x7e\x4b\x73\x9e\x04\x8f\xe2\xc0\x3e\xa6\x54\x1b\x2f\x1a\x87\xee\xb0\xac\xa6\x89\x6d\x2d\x1c\xb8", 245, { 0x64, 0x0a, 0x21, 0xd7, 0x1f, 0x9e, 0xd7, 0xcd, 0x82, 0xd1, 0xb8, 0xb3, 0x7e, 0xb4, 0xa8, 0x66 } }, +{ "\x06\xfb\x8a\xca\x55\x1c\xd3\x3d\xcf\xf0\x54\x07\x03\x96\x31\x83\x40\xde\xcb\xf7\x54\xe6\x4e\xbe\x6e\x53\x66\x17\x25\x2e\x11\x88\x92\x58\x8f\xf0\x97\xab\x77\x28\x43\xaf\xe4\x55\x4e\xf6\xcc\xce\xbf\x15\x70\xa4\xad\x3f\xef\xd2\x21\x7f\xf6\x02\x1b\x92\x92\xfa\xac\x5e\x26\xa1\x40\x13\x78\xb2\xfe\xdd\xe5\xfc\x48\x43\xb5\x53\x5d\x1f\x89\x17\x1e\x3a\xf1\x5e\xee\x83\x1a\xc1\xb2\xec\xa5\xc0\xf7\xe2\x92\xd3\x33\x67\x5b\x0e\x24\xcd\x1d\x6f\x55\x10\xf1\xc7\xbf\xd1\x5a\x43\x8c\xeb\xd6\x97\xf7\xb4\x97\xc6\x4f\xd2\x4c\x90\x19\xb7\x18\x77\x55\xba\xa4\x70\xd9\xd3\x50\x23\xda\xf3\x84\xdf\x8a\xfe\x25\x1e\xdb\x66\x24\xaf\x61\x65\x30\x86\x55\xd7\x8b\x1c\xb5\xb1\xfa\x84\x89\x22\xd6\x0c\x41\x44\x40\x8c\x3b\x7f\x72\x4e\x60\x7b\x30\x99\xee\xbf\x5c\xdc\x50\xeb\xa9\x74\x29\x8e\x68\x1a\x6f\xa5\x7e\xec\xb4\xb1\x77\x16\x81\x73\xb3\x1d\xdb\x47\xbe\xc8\xe7\x1a\xbe\xab\xa9\x0a\x05\x51\xe8\x99\xc7\x05\x2e\x8c\xe5\x3d\xeb\x66\xe7\xa4\xb9\x7c\x09\xc3\xbb\xb5\x6c\x4b\x1e\xe0\x6d\x01\xc1\xb2\x13\x46\xf1\x5a", 246, { 0xb9, 0x5e, 0x62, 0x77, 0x29, 0xc0, 0xa2, 0xbd, 0x30, 0xef, 0x76, 0xa4, 0x2d, 0x67, 0xa4, 0xb2 } }, +{ "\xa2\x42\x4d\xc3\x4c\xad\xc9\x66\x07\x39\xce\xc9\x7a\x9f\x7d\x97\x11\x45\x14\x5d\x30\x89\x6a\xdf\x83\xad\x94\x15\x74\x5f\xaa\xc5\xb6\xe3\xa3\xbe\xfe\xdf\x5d\xae\xd2\xc3\xba\xa1\x7a\xd3\xe4\x16\x12\xd2\xb0\xbf\xc1\x4c\x20\xd6\x04\x81\x03\x17\x24\xe9\xb7\x5e\xc6\x68\x0f\xdd\xa1\x10\x4f\xf9\x4a\x8d\x54\xc2\x2b\x31\xd1\x0d\x92\x9d\xb3\x30\xe5\x08\xa6\x5a\xf4\x2f\xb1\x8c\x67\xd9\xfd\x38\x56\x06\xb3\x74\xf7\xb4\x03\xdb\x72\x4d\x40\x01\xd1\xb0\x28\x90\x13\xda\x42\x04\x60\x31\x60\xff\x56\x6d\x44\x49\x81\x23\x5f\x68\xea\xf0\xb4\xd8\xc6\x3e\xdc\xe8\x4f\xb6\x22\x31\xb0\x42\xce\xb3\x1a\xbd\x7f\x8d\xf4\x3a\xb1\x59\x2f\xee\x5f\x22\xb7\xbb\xc2\x02\x05\x59\x37\x5d\xd1\x23\x3e\xb4\xe5\x7c\x9e\x26\x0d\xdc\xa7\x8a\x2b\x7b\x90\x21\x67\x98\xfe\xfb\x83\x66\xa6\xe9\x4c\x94\x09\x1b\x2c\x77\x5e\x55\xdd\xd7\x8e\xd2\x38\x53\x59\xb5\x2c\x71\x96\x28\xca\x46\x97\x14\x7c\xbe\xaa\x7b\x56\x89\xbc\x75\x84\xa3\x19\xc5\xe3\x7d\x4f\x17\xad\xcd\x30\xd8\x4c\xef\xf5\xb2\x4f\xf6\x7f\xa3\x7a\x54\xb9\xb9\xf7\x21\x1a", 247, { 0x98, 0x8d, 0x87, 0xaa, 0xc7, 0xf9, 0xad, 0x6e, 0x99, 0x00, 0xf9, 0x61, 0x74, 0x29, 0xad, 0xca } }, +{ "\x6c\xab\x0b\x47\x97\xa4\xdb\xd5\x15\xae\xa0\x2c\xf4\x05\x7a\x87\x59\x24\x05\x17\xf0\xbc\x5f\x47\x0d\xc0\xd8\x1b\x64\x9d\x35\xb2\x61\x87\xa1\xea\x25\xef\x31\x22\x1e\x11\x12\x1a\x42\xa9\x52\xf7\xe8\xc5\x47\x64\x43\xb6\x9f\xd2\x7b\x20\x06\xdf\x6a\x31\x6e\xd5\xf0\xee\xfe\x49\xf3\xa9\x99\xe4\xf6\x8f\x09\x3e\x55\x5e\xc8\xe6\x1a\x33\x6b\x7e\x7f\x81\xac\x03\x01\x1e\x12\x2b\x1e\x77\x3f\xe7\xab\xe4\xd5\x08\xd4\x16\x06\xfe\xb0\xad\xb8\xbb\x7f\xe6\x51\xb5\x84\x72\x24\x0b\x79\x62\x77\xbf\xb4\x3d\x30\x21\xd4\x34\x1c\x4d\x27\x6d\xdc\xcb\x9c\x7b\x6d\x54\x5f\xef\x52\xb4\x17\x08\x60\xcb\xb8\x85\x26\xad\x05\x9b\xf7\xe9\xa6\x03\x95\xe7\xe1\x2a\x7b\x6a\xf8\x8c\xc7\x36\x1f\x1b\xc2\xcb\x19\xd9\x0d\x4f\x6e\x85\x6b\x89\x4b\x71\x25\x09\xf6\x72\x1e\x66\xec\xf2\x73\xa0\x98\x20\xce\xa4\xb2\x46\x48\xed\x32\x3a\xf8\x47\xf0\xee\x1d\xae\xda\x23\xe3\x56\xd1\x3a\xd6\xc4\x20\x2b\xe0\x19\x99\x8e\x00\x6f\x4e\xd7\x8a\x5c\xe9\x9f\x14\x94\xa9\x1d\x04\xab\xf9\xb3\xb4\xf7\xaf\xa5\x3f\x93\xde\xe4\xeb\x81\x58\x09\x33\xe7", 248, { 0xaf, 0x11, 0x9d, 0x89, 0x3d, 0x36, 0x81, 0xb4, 0x1a, 0x91, 0x0b, 0x44, 0x0c, 0xe4, 0x73, 0xf2 } }, +{ "\xc3\x5d\x6f\x7a\x56\x15\x22\xf8\x31\x9b\xe0\xcf\x57\x07\xda\xdb\x49\xac\x08\x4d\x3f\xcf\xf1\xa7\x05\x73\x1a\xe3\x71\x50\x09\xb3\x7d\xe1\xf4\xe4\x05\x9c\x0b\xdc\x1e\x3d\x5f\x42\x10\x3c\x6d\xbc\xf2\x5d\x4b\xd3\xe1\x66\x6e\xf4\xdc\xea\x16\x90\x3f\x44\x56\x62\xda\xa0\xc3\xd0\xae\x33\xb9\x6b\x43\x8a\x45\x91\xa9\x00\xb2\x32\x09\x4a\xb3\xaf\xe6\x2c\x2a\xde\xf6\x4e\x93\x2a\x97\x29\x10\xd8\xf0\x1c\x11\x64\xa5\x9b\x9f\x0a\x36\x87\x46\x60\xf5\x98\x9d\x20\xa2\xf6\x73\x04\xa4\xe7\x98\xca\xe6\xa3\x45\x57\x4c\x44\x29\xf8\xd1\xd9\x10\xc3\x3f\x9a\x32\x1c\x89\x35\x16\x53\xc8\x47\x21\x6b\xd0\xe6\xbf\xf6\x6f\x5b\x2d\x1c\x42\xed\xe0\xba\x33\xd8\x95\xa6\x92\x5d\xf6\x11\xcf\xf3\xe6\x06\xd2\x9b\x69\x0f\xf7\x51\x33\xf6\xa9\x9e\xcc\xa9\x9a\x4b\x5c\x37\x9c\x30\x19\xf7\x1f\x2a\x49\xc7\x48\x2a\xf6\x72\xaa\x6a\x2e\x2b\xa3\xbb\xf4\x36\x55\xfb\xc7\xa6\x40\xa2\xcc\x41\x79\x7b\x9a\x7f\x89\x6f\xa2\xb1\xe5\x7c\x39\x3f\x05\xc5\x44\x0a\x22\xc4\x7f\xf0\x91\x9b\x6a\x6d\xb7\x87\xd0\x5e\xa8\x75\xf5\xe1\x61\xaf\x5b\x59\x9d", 249, { 0x49, 0x19, 0x39, 0x2e, 0xe6, 0x98, 0xbd, 0xe8, 0x33, 0xe7, 0x7f, 0x85, 0xcb, 0x16, 0x46, 0xeb } }, +{ "\xaf\x31\x8e\x57\x14\x59\xf1\xde\xb2\x14\xfd\x8e\xc4\x4d\xb8\x30\x3c\x7f\x59\xf0\x3b\x43\x03\xf7\x9d\x79\xaf\xa5\xab\x13\x29\x6c\xf4\x79\x31\x4c\x35\x9c\xc2\xe6\x75\x9b\x6f\x40\x2e\x0b\xe8\x14\xa5\xe7\x9c\xd5\x5b\x14\x79\x3f\x9c\x8e\xce\x99\x34\x35\x52\x8a\x41\x2e\x3e\x95\x24\xf7\x95\x33\x91\x0b\x84\x8c\xc6\x2e\xe3\xd1\xd9\x56\xdb\x39\x29\x36\xa2\x95\xf6\x68\x62\x92\x0d\x35\x39\x8b\x9c\x04\x59\x09\x24\x5e\x4e\xd8\x8c\x9a\x60\xc6\x51\x2a\x0e\xfb\xdb\x80\xbb\xf0\xeb\x9e\x65\x0e\x31\x39\x8f\xe3\xfb\x89\x41\x03\x07\xb0\x26\x79\x79\xc4\xd3\xe9\xe8\x7b\x27\x43\x92\x72\xcd\x26\xb0\x1a\xde\xcf\xe5\x3f\xa4\xbc\xcf\x36\x7a\xe1\xc0\xa3\xcf\x86\x87\xe4\x49\xbb\x67\x1e\x05\x79\x29\xe2\xfd\x57\x4d\x7b\x83\xe5\x5c\xd6\xea\xa9\x59\x0e\x43\xb4\x56\x94\x45\xdf\x22\xf8\x46\xa7\x20\x56\x66\xa2\x33\x5f\xcb\x9d\xd5\x03\x06\x55\x47\xb8\x94\xce\xe3\x6a\x81\x52\x8d\xff\x27\x09\x48\x85\x15\x32\xe4\xfb\x0b\xfc\xd5\xb9\x21\x03\x20\x7d\x06\x6a\x6e\x12\x66\x91\x43\x9e\x65\x73\x48\x89\x49\x9f\xc4\x06\x34\xd1\x29\x3f", 250, { 0x7c, 0x09, 0xc7, 0x86, 0x67, 0x7f, 0xd7, 0x70, 0x09, 0x34, 0xc4, 0x7d, 0xa5, 0x07, 0x09, 0x7f } }, +{ "\x0e\x2d\xcb\x21\x81\x17\xab\xc1\x1e\xb1\x72\x69\x9d\xf2\x79\x44\x41\x60\x05\xa1\x5a\x6a\x90\xe7\xe4\x64\x42\x16\x4d\x1f\x7f\xf5\x54\x24\x9a\xde\x0d\x8d\xa7\x22\x01\x81\x6d\x1a\x72\x4a\x7a\xcb\xbb\x15\x51\x35\xd6\x45\xbf\x38\xf8\x73\x4c\x24\x57\x06\xcc\xdc\x0b\x6c\x15\xa5\x12\xf2\xca\x90\x6e\x46\x56\x82\x69\x86\xf5\xdd\xf9\x04\xec\xcd\x3e\x99\xd9\x31\x27\xa3\x25\x23\x35\x9c\x95\x26\x58\x58\x00\xeb\xf5\xdb\x1b\xc0\x09\xd4\x70\x96\x67\xba\x6d\xad\x1d\x82\x99\xde\xf5\xfa\xe1\x84\x17\xc5\x11\x08\xcc\xf3\x5e\x08\x5d\x3c\x20\x24\x1a\xda\x9d\x65\x76\x00\xff\x49\x4f\xfa\x68\x6f\x4c\xe2\x1c\xdb\x60\xfc\xdd\xe7\x6b\xaf\x54\xc7\xff\x21\xab\xb7\x3f\x6d\x37\xc3\xe4\x84\x53\x32\x59\x9d\x48\x90\x06\x5a\x68\x57\xab\x79\x3a\x3a\xe2\x33\xcf\x0d\xc6\x34\x33\x54\xb3\x38\xff\x66\x23\x3f\x0c\x3d\xb7\x6c\x42\xdd\x57\x80\x8e\x5f\x70\xed\xf2\x9a\x5c\x9a\xb6\x6c\xe0\x33\xbc\xaa\xce\x29\xf1\xa2\xcb\x4d\xdf\x49\x2b\x04\x60\x06\xf8\x28\x6e\x1a\x12\x7c\x15\xaa\x70\xc9\x89\x6a\x84\x99\x54\xe8\xbd\x8f\xa7\x72\x26\x61\xd2", 251, { 0xb3, 0x4a, 0x6d, 0xad, 0x44, 0xc4, 0x04, 0xa4, 0x65, 0x17, 0xe7, 0x33, 0x5a, 0xd6, 0x98, 0x59 } }, +{ "\xa5\x2c\x74\xcf\x94\x7c\x13\xf9\x91\x0b\x4b\xda\x9b\x2f\x65\x21\x64\xeb\x01\xb3\xfd\x48\xcb\xd8\x20\xde\xdd\x96\x1a\x72\xb1\x1b\x53\xb9\xc1\x53\x7b\x3b\xbd\x9a\x53\x53\x68\x8b\x15\x53\x10\xf7\x81\xc4\xa8\xf2\x86\xca\x83\x07\x89\xa6\xaf\x8b\x54\x56\xec\x0f\x9e\x57\x48\xef\x33\x8a\x58\x07\xc0\x34\x15\x86\x3d\x20\x50\xda\xf7\xdf\xd3\xcb\x39\x30\x16\xa4\x96\x7a\x9b\x8b\xd6\x76\xe7\xf2\x7b\xe9\x1d\x26\xee\x8f\x38\x05\x4b\x14\xe4\xcc\xc6\x3b\xfa\x0e\xb8\x22\x96\xc1\x4a\x9c\xd7\x73\xbc\xbe\x33\x9a\x53\x76\x74\x08\xdd\x54\x53\x7d\xe2\x6c\xaf\x57\x69\x54\x6a\x64\x64\x49\xe1\xd8\xb9\x6e\x06\x5a\xed\x34\x1b\x38\x6f\xd5\x0c\xbc\x7f\xf9\x6a\x96\xb9\x7c\x00\x78\x42\x47\x14\xc1\x8d\x5b\x3b\x51\xcb\xec\xd9\x7b\xed\xaa\x35\x18\x57\x1a\x35\xb8\x22\x23\xba\xf4\x0e\xa5\x9a\xdf\x03\x44\x36\x9b\x42\x43\xb8\x07\x2d\x8a\xeb\x96\xaf\xca\xb7\x3b\x49\xb7\x37\x80\xba\x74\x79\xb6\x4b\x0d\xd1\x47\xb4\x1d\xda\x27\xae\x90\x0b\x69\x16\x83\xf1\xee\xbb\x48\x0e\x38\xc4\x85\x4e\x5c\xc1\x7c\x22\x16\x4c\x65\x3c\xf7\x5b\xf7\xe5\xb9", 252, { 0xdc, 0x2a, 0xf1, 0x01, 0x65, 0x86, 0xb7, 0x25, 0x94, 0xcb, 0x82, 0x3e, 0x4d, 0x4f, 0xbe, 0x81 } }, +{ "\x26\x05\xfe\xb3\xaf\x45\x91\x67\xf3\x2d\x13\x39\xab\xf7\x38\x3b\xbf\xc3\x73\x23\x48\xda\x09\x5e\x40\x10\xd1\x3d\xc9\x44\x8a\x4e\x16\x02\xd9\xc6\xfa\x47\xdd\x19\x0b\x64\x70\xac\x72\xfb\xfd\xa2\x52\x26\xf9\xd3\xd3\xb8\x00\xdb\xca\x9b\x8c\x4e\x07\x58\x54\x09\x3a\xb6\x3f\xa4\x82\x79\x03\x03\x94\x4b\x5f\x0c\x84\xb9\xf1\x73\x33\x54\xb4\xb0\x56\xf8\x1a\x12\x1e\x29\xc2\xed\x89\x99\xd7\xef\x45\xc6\x04\x91\x3c\xc0\x17\xa9\xc1\x08\x31\x1c\x55\x94\xa7\xb0\x15\xf0\x79\xff\xc4\x7e\x6d\x87\x71\xde\xc7\xdf\xc5\x68\xa6\x04\xeb\xd6\xfe\xd2\x1c\xff\x2d\x8e\xc6\xbe\x3c\xa0\x58\xf1\xb5\x5e\xac\x9d\x1c\x03\x12\x2f\x0b\xbe\xf5\xdd\xed\xe7\x2d\x2b\x57\x4c\xe0\x8a\xfe\xaa\x15\x1b\x59\x37\xd7\x91\xd4\x5c\x02\x34\xad\x80\xad\x01\x6f\x00\x34\xef\x09\x3b\xe0\x4c\x8b\xc9\x35\x46\x7c\xcb\xd9\x86\xda\x5d\x1c\xf7\xaf\x28\x28\xa5\x4c\x15\xc6\xc0\x25\x1c\xca\xbf\x48\x3a\x1d\xa1\x7b\x81\x65\x4e\xf2\x49\x53\x1c\xaa\x84\x88\x6f\x65\x30\x25\x78\x42\xe5\xee\x1e\xf8\x8e\x19\xf9\xaf\x34\xb9\x7a\x7b\xf6\xc2\x29\x75\x15\xb8\x07\x78\x2c\xf9", 253, { 0x84, 0x6b, 0xe9, 0x6b, 0xfc, 0xff, 0x73, 0x49, 0xce, 0xf5, 0x59, 0xf8, 0x85, 0x75, 0x4b, 0x6d } }, +{ "\x12\x75\x7c\xa3\xe7\x74\x65\x23\x81\x28\xf1\x5b\x1f\x2d\x8b\x6f\x44\xe0\xcd\x2d\xd8\xdb\x77\x16\x6c\x0b\x7b\x0d\x9b\x70\x34\x9b\x8c\x71\xb7\xdd\x93\xda\x42\x0b\xf7\x73\xd2\xa5\xce\x3e\xd1\x3c\x05\x4c\xeb\xda\x7c\x3c\x01\x0f\x4e\x51\x37\x99\x2e\x2f\x28\xaf\xed\x32\x39\xea\x18\x6b\x0b\xd0\xbd\x39\x0a\xff\x4e\x7f\x22\xf3\x9f\x87\x92\x74\x0a\x73\xd8\x9f\xb2\x5b\xcc\x8e\xe4\x08\xc9\xa7\x99\x4c\x06\x7e\x18\xfc\x02\x68\xb8\x8c\x1e\x9d\xc3\x45\x44\x08\x77\x25\xc5\xaf\x26\x53\x41\xba\x7d\x3d\xbf\x22\xe1\x50\xdd\xf7\xf5\x53\x21\x4d\x38\x61\x6d\xc4\xcc\x81\x91\xb3\x51\xe3\xfb\xf1\xf0\xba\x89\x3f\x74\xb0\x7f\x55\x92\x0a\x94\x88\x49\x5a\x27\x14\x64\xdb\x8f\x0c\x1d\x6c\x90\xdb\xdc\x2c\xe9\x76\x1d\xae\x09\x20\x6f\xd9\xe2\xd9\x98\x5f\xd7\x64\xd6\xd8\xcf\xf4\x40\x7a\x6b\x72\x4b\x77\x54\x6d\x69\xf4\xad\x9f\xcc\xa1\xa8\x18\x49\xf9\x34\x0a\x57\x18\xd4\x30\x36\x34\x8b\xdb\x2c\xb9\xf4\x9a\xea\x05\x6e\x85\x0e\xbd\x73\x26\xc2\xca\x0a\x05\x81\xf4\x53\xcf\xfa\x19\x40\x22\x0d\x09\x63\xf8\xf2\x01\xe1\xad\x79\xc3\x86\xae\x6b\x4e", 254, { 0x23, 0xe9, 0x88, 0x6a, 0xc2, 0x8c, 0x64, 0x59, 0xdb, 0xa2, 0xe7, 0x84, 0x10, 0x37, 0x53, 0xd0 } }, +{ "\xf3\xc0\x10\x3f\xf2\xea\xca\xc4\xea\x01\xdf\x39\x6d\xce\x54\x61\xef\xdd\xf4\x42\x92\xe5\x70\x9d\x1c\xcf\xa0\x08\x0a\x65\xe8\xaa\xbe\x98\xb6\x93\xd3\x6d\x27\xb5\x91\x86\xc9\x83\x7c\x49\x7b\x25\x07\xaf\x71\x55\x66\xab\x54\xd9\x81\x34\x86\x9d\x04\xf1\x83\x6c\x93\x80\x63\x4b\x1b\x64\x7b\x72\x44\x89\x24\xe8\x02\x74\x93\xba\x4b\x0b\xe7\xd7\xe3\xfe\x42\x8b\x53\xd1\x0e\x96\xf8\x88\x61\xe9\x37\xee\x7b\xfc\xce\x81\x6c\xce\x46\xfd\xd3\x7a\x84\x83\xc1\x73\x7f\x66\xbb\x5c\x0c\x93\xde\x86\xd6\x9a\x1d\x07\x69\x5d\xa6\x73\x6d\x54\x64\x3a\xef\x7a\x9d\x9e\xdb\xd7\xba\x4f\x86\xab\x27\xa4\x68\x34\x51\x78\xe7\x1c\xcc\x9f\x4e\x83\x97\x04\xdc\xa4\x77\x61\xf9\x26\x7f\x99\x84\x01\xb1\xb5\x47\x0b\xbf\x79\x8c\x1f\xea\xa2\xc9\xe8\x0c\xbf\x76\x4f\xb1\xa9\xff\x7f\x5f\xa1\xd5\x91\xf6\x04\xa0\xd9\x32\xad\x8f\xcc\x4e\xe7\xcf\x8c\xc3\x0d\x19\x12\x2f\xc1\x66\xf7\x50\xc5\xbe\xdf\x2f\x79\x2e\x83\x59\xf1\xd8\x59\x48\xb2\x24\xe1\xe1\x0a\x15\x8e\x17\x09\xb6\x50\xad\x1f\xb3\xba\x18\x54\x03\xd5\x82\x1e\xc3\x80\xeb\xe2\x1f\x82\x6a\x0a\x69\x2e\x92", 255, { 0xe8, 0x99, 0x39, 0xbb, 0x59, 0x6c, 0x74, 0x74, 0x67, 0x04, 0x26, 0x4c, 0xd3, 0xaf, 0x38, 0x31 } }, +{ "\xbf\x4b\xb1\xf0\x43\x19\xfc\xb0\xee\x40\x48\x5f\xc3\xdc\x4a\xca\xaf\x65\xf5\x06\x5d\x88\xe7\x89\xb8\x14\x71\x76\xfe\x0b\x46\xf6\x7e\xd9\xbf\xc1\xee\xa1\xc8\xbd\x6b\xb2\x6b\xbd\x0d\x18\xf7\x6a\x26\x4f\xcc\x3f\x18\x13\xc6\xae\xd0\x53\x44\x60\xe3\x43\xd4\x9a\x43\x91\x7c\xbb\x9d\xaf\xa7\xe1\x53\x4f\xab\xac\x11\xed\xf3\x1a\x0e\x85\xce\x92\xe1\x66\xd3\xfc\xfd\x1f\xee\x0d\xcb\x95\x0c\xa0\x63\x36\x5f\x40\xe6\x48\x4e\xc2\x7a\x5b\xfd\x0f\xe3\xdd\x74\x00\xbb\xcc\x6e\x62\x4e\x86\xc0\x18\x14\xbc\x64\x60\xcb\x85\x22\x2e\x31\x8f\xda\xb4\x5b\x70\x70\x03\xb5\x1a\x54\xcb\x97\x6d\xac\x3e\x7f\xe7\x21\x13\xf1\x77\x43\xa7\xe8\x6f\x9a\x3e\xf7\x97\x4a\x66\x01\x5d\x62\x7c\x91\x2a\xc1\x48\xd7\xd1\xa5\xc4\x40\x21\xd1\xfa\xb1\x9a\x5b\x0b\x5f\x3c\x0f\x4b\x4d\x7a\x83\x8a\x63\x4e\xb9\x6e\x28\x66\x6a\xfc\x1d\x7c\xf5\x35\xb5\xc3\xe4\xdd\xf4\x7d\x16\x57\xa2\xa9\x8f\xab\x2c\xda\xd9\xaa\x18\x23\x14\x29\x23\x2f\xa1\x69\xf9\x6d\x67\x97\x91\x68\xc0\x6e\x22\x34\x04\xfa\xc5\x04\xb0\x78\xa8\xd9\x32\x5a\xec\x55\x53\x66\x1d\xae\x41\xfe\x4b\xbe\x38\x7a", 256, { 0xf9, 0xd0, 0x4d, 0xbb, 0xc9, 0x3f, 0xc3, 0xa4, 0x73, 0xd0, 0xd2, 0x2a, 0xb4, 0x79, 0x0a, 0xcb } }, + diff --git a/cmdline/state.c b/cmdline/state.c new file mode 100644 index 0000000..cff523e --- /dev/null +++ b/cmdline/state.c @@ -0,0 +1,4706 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "elem.h" +#include "import.h" +#include "search.h" +#include "state.h" +#include "support.h" +#include "parity.h" +#include "stream.h" +#include "handle.h" +#include "io.h" +#include "raid/raid.h" +#include "raid/cpu.h" + +/** + * Configure the multithread support. + * + * Multi thread for write could be either faster or slower, depending + * on the specific conditions. With multithreads it's likely faster + * writing to disk, but you'll need to access multiple times the same data, + * being potentially slower. + * + * For upcoming SnapRAID version it's planned to add a mutex protection + * at the file-system structure, slowing down multiple data access, + * so we disable it. + * + * Multi thread for verify is instead always generally faster, + * so we enable it if possible. + */ +#if HAVE_PTHREAD +/* #define HAVE_MT_WRITE 1 */ +#define HAVE_MT_VERIFY 1 +#endif + +const char* lev_name(unsigned l) +{ + switch (l) { + case 0 : return "Parity"; + case 1 : return "2-Parity"; + case 2 : return "3-Parity"; + case 3 : return "4-Parity"; + case 4 : return "5-Parity"; + case 5 : return "6-Parity"; + } + + return 0; +} + +const char* lev_config_name(unsigned l) +{ + switch (l) { + case 0 : return "parity"; + case 1 : return "2-parity"; + case 2 : return "3-parity"; + case 3 : return "4-parity"; + case 4 : return "5-parity"; + case 5 : return "6-parity"; + } + + return 0; +} + +static int lev_config_scan(const char* s, unsigned* level, unsigned* mode) +{ + if (strcmp(s, "parity") == 0 || strcmp(s, "1-parity") == 0) { + *level = 0; + return 0; + } + + if (strcmp(s, "q-parity") == 0 || strcmp(s, "2-parity") == 0) { + *level = 1; + return 0; + } + + if (strcmp(s, "r-parity") == 0 || strcmp(s, "3-parity") == 0) { + *level = 2; + return 0; + } + + if (strcmp(s, "4-parity") == 0) { + *level = 3; + return 0; + } + + if (strcmp(s, "5-parity") == 0) { + *level = 4; + return 0; + } + + if (strcmp(s, "6-parity") == 0) { + *level = 5; + return 0; + } + + if (strcmp(s, "z-parity") == 0) { + *level = 2; + if (mode) + *mode = RAID_MODE_VANDERMONDE; + return 0; + } + + return -1; +} + +const char* lev_raid_name(unsigned mode, unsigned n) +{ + switch (n) { + case 1 : return "par1"; + case 2 : return "par2"; + case 3 : if (mode == RAID_MODE_CAUCHY) + return "par3"; + else + return "parz"; + case 4 : return "par4"; + case 5 : return "par5"; + case 6 : return "par6"; + } + + return 0; +} + +void state_init(struct snapraid_state* state) +{ + unsigned l, s; + + memset(&state->opt, 0, sizeof(state->opt)); + state->filter_hidden = 0; + state->autosave = 0; + state->need_write = 0; + state->checked_read = 0; + state->block_size = 256 * KIBI; /* default 256 KiB */ + state->raid_mode = RAID_MODE_CAUCHY; + state->file_mode = ADVISE_DEFAULT; + for (l = 0; l < LEV_MAX; ++l) { + state->parity[l].split_mac = 0; + for (s = 0; s < SPLIT_MAX; ++s) { + state->parity[l].split_map[s].path[0] = 0; + state->parity[l].split_map[s].uuid[0] = 0; + state->parity[l].split_map[s].size = PARITY_SIZE_INVALID; + state->parity[l].split_map[s].device = 0; + } + state->parity[l].smartctl[0] = 0; + state->parity[l].total_blocks = 0; + state->parity[l].free_blocks = 0; + state->parity[l].skip_access = 0; + state->parity[l].tick = 0; + state->parity[l].cached_blocks = 0; + state->parity[l].is_excluded_by_filter = 0; + } + state->tick_io = 0; + state->tick_misc = 0; + state->tick_sched = 0; + state->tick_raid = 0; + state->tick_hash = 0; + state->tick_last = tick(); + state->share[0] = 0; + state->pool[0] = 0; + state->pool_device = 0; + state->lockfile[0] = 0; + state->level = 1; /* default is the lowest protection */ + state->clear_past_hash = 0; + state->no_conf = 0; + + tommy_list_init(&state->disklist); + tommy_list_init(&state->maplist); + tommy_list_init(&state->contentlist); + tommy_list_init(&state->filterlist); + tommy_list_init(&state->importlist); + tommy_hashdyn_init(&state->importset); + tommy_hashdyn_init(&state->previmportset); + tommy_hashdyn_init(&state->searchset); + tommy_arrayblkof_init(&state->infoarr, sizeof(snapraid_info)); +} + +void state_done(struct snapraid_state* state) +{ + tommy_list_foreach(&state->disklist, (tommy_foreach_func*)disk_free); + tommy_list_foreach(&state->maplist, (tommy_foreach_func*)map_free); + tommy_list_foreach(&state->contentlist, (tommy_foreach_func*)content_free); + tommy_list_foreach(&state->filterlist, (tommy_foreach_func*)filter_free); + tommy_list_foreach(&state->importlist, (tommy_foreach_func*)import_file_free); + tommy_hashdyn_foreach(&state->searchset, (tommy_foreach_func*)search_file_free); + tommy_hashdyn_done(&state->importset); + tommy_hashdyn_done(&state->previmportset); + tommy_hashdyn_done(&state->searchset); + tommy_arrayblkof_done(&state->infoarr); +} + +/** + * Check the configuration. + */ +static void state_config_check(struct snapraid_state* state, const char* path, tommy_list* filterlist_disk) +{ + tommy_node* i; + unsigned l, s; + + /* check for parity level */ + if (state->raid_mode == RAID_MODE_VANDERMONDE) { + if (state->level > 3) { + /* LCOV_EXCL_START */ + log_fatal("If you use the z-parity you cannot have more than 3 parities.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STIO */ + } + } + + for (l = 0; l < state->level; ++l) { + if (state->parity[l].split_mac == 0) { + /* LCOV_EXCL_START */ + log_fatal("No '%s' specification in '%s'\n", lev_config_name(l), path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + if (tommy_list_empty(&state->contentlist)) { + /* LCOV_EXCL_START */ + log_fatal("No 'content' specification in '%s'\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* check for equal paths */ + for (i = state->contentlist; i != 0; i = i->next) { + struct snapraid_content* content = i->data; + + for (l = 0; l < state->level; ++l) { + for (s = 0; s < state->parity[l].split_mac; ++s) { + if (pathcmp(state->parity[l].split_map[s].path, content->content) == 0) { + /* LCOV_EXCL_START */ + log_fatal("Same path used for '%s' and 'content' as '%s'\n", lev_config_name(l), content->content); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + } + } + + /* check device of data disks */ + if (!state->opt.skip_device && !state->opt.skip_disk_access) { + for (i = state->disklist; i != 0; i = i->next) { + tommy_node* j; + struct snapraid_disk* disk = i->data; + + /* skip data disks that are not accessible */ + if (disk->skip_access) + continue; + +#ifdef _WIN32 + if (disk->device == 0) { + /* LCOV_EXCL_START */ + log_fatal("Disk '%s' has a zero serial number.\n", disk->dir); + log_fatal("This is not necessarily wrong, but for using SnapRAID\n"); + log_fatal("it's better to change the serial number of the disk.\n"); + log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } +#endif + + for (j = i->next; j != 0; j = j->next) { + struct snapraid_disk* other = j->data; + if (disk->device == other->device) { + if (state->opt.force_device) { + /* note tha we just ignore the issue */ + /* and we DON'T mark the disk to be skipped */ + /* because we want to use these disks */ + if (!state->opt.no_warnings) + log_fatal("DANGER! Ignoring that disks '%s' and '%s' are on the same device\n", disk->name, other->name); + } else { + /* LCOV_EXCL_START */ + log_fatal("Disks '%s' and '%s' are on the same device.\n", disk->dir, other->dir); +#ifdef _WIN32 + log_fatal("Both have the serial number '%" PRIx64 "'.\n", disk->device); + log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n"); + log_fatal("to change one of the disk serial.\n"); +#endif + /* in "fix" we allow to continue anyway */ + if (strcmp(state->command, "fix") == 0) { + log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command); + } + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + } + + /* skip data disks that are not accessible */ + if (disk->skip_access) + continue; + + if (!state->opt.skip_parity_access) { + for (l = 0; l < state->level; ++l) { + for (s = 0; s < state->parity[l].split_mac; ++s) { + if (disk->device == state->parity[l].split_map[s].device) { + /* LCOV_EXCL_START */ + log_fatal("Disk '%s' and %s '%s' are on the same device.\n", disk->dir, lev_name(l), state->parity[l].split_map[s].path); +#ifdef _WIN32 + log_fatal("Both have the serial number '%" PRIx64 "'.\n", disk->device); + log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n"); + log_fatal("to change one of the disk serial.\n"); +#endif + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + } + } + + if (state->pool[0] != 0 && disk->device == state->pool_device) { + /* LCOV_EXCL_START */ + log_fatal("Disk '%s' and pool '%s' are on the same device.\n", disk->dir, state->pool); +#ifdef _WIN32 + log_fatal("Both have the serial number '%" PRIx64 "'.\n", disk->device); + log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n"); + log_fatal("to change one of the disk serial.\n"); +#endif + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + } + + /* check device of parity disks */ + if (!state->opt.skip_device && !state->opt.skip_parity_access) { + for (l = 0; l < state->level; ++l) { + for (s = 0; s < state->parity[l].split_mac; ++s) { + unsigned j, t; + + /* skip parity disks that are not accessible */ + if (state->parity[l].skip_access) + continue; + +#ifdef _WIN32 + if (state->parity[l].split_map[s].device == 0) { + /* LCOV_EXCL_START */ + log_fatal("Disk '%s' has a zero serial number.\n", state->parity[l].split_map[s].path); + log_fatal("This is not necessarily wrong, but for using SnapRAID\n"); + log_fatal("it's better to change the serial number of the disk.\n"); + log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } +#endif + + for (j = l + 1; j < state->level; ++j) { + for (t = 0; t < state->parity[j].split_mac; ++t) { + if (state->parity[l].split_map[s].device == state->parity[j].split_map[t].device) { + if (state->opt.force_device) { + /* note tha we just ignore the issue */ + /* and we DON'T mark the disk to be skipped */ + /* because we want to use these disks */ + if (!state->opt.no_warnings) + log_fatal("DANGER! Skipping parities '%s' and '%s' on the same device\n", lev_config_name(l), lev_config_name(j)); + } else { + /* LCOV_EXCL_START */ + log_fatal("Parity '%s' and '%s' are on the same device.\n", state->parity[l].split_map[s].path, state->parity[j].split_map[t].path); +#ifdef _WIN32 + log_fatal("Both have the serial number '%" PRIx64 "'.\n", state->parity[l].split_map[s].device); + log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n"); + log_fatal("to change one of the disk serial.\n"); +#endif + /* in "fix" we allow to continue anyway */ + if (strcmp(state->command, "fix") == 0) { + log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command); + } + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + } + } + + if (state->pool[0] != 0 && state->pool_device == state->parity[l].split_map[s].device) { + /* LCOV_EXCL_START */ + log_fatal("Pool '%s' and parity '%s' are on the same device.\n", state->pool, state->parity[l].split_map[s].path); +#ifdef _WIN32 + log_fatal("Both have the serial number '%" PRIx64 "'.\n", state->pool_device); + log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'\n"); + log_fatal("to change one of the disk serial.\n"); +#endif + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + } + } + + /* check device of pool disk */ +#ifdef _WIN32 + if (!state->opt.skip_device) { + if (state->pool[0] != 0 && state->pool_device == 0) { + /* LCOV_EXCL_START */ + log_fatal("Disk '%s' has a zero serial number.\n", state->pool); + log_fatal("This is not necessarily wrong, but for using SnapRAID\n"); + log_fatal("it's better to change the serial number of the disk.\n"); + log_fatal("Try using the 'VolumeID' tool by 'Mark Russinovich'.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } +#endif + + /* count the content files */ + if (!state->opt.skip_device && !state->opt.skip_content_access) { + unsigned content_count; + + content_count = 0; + for (i = state->contentlist; i != 0; i = i->next) { + tommy_node* j; + struct snapraid_content* content = i->data; + + /* check if there are others in the same disk */ + for (j = i->next; j != 0; j = j->next) { + struct snapraid_content* other = j->data; + if (content->device == other->device) { + log_fatal("WARNING! Content files on the same disk: '%s' and '%s'.\n", content->content, other->content); + break; + } + } + if (j != 0) { + /* skip it */ + continue; + } + + ++content_count; + } + + if (content_count < state->level + 1) { + /* LCOV_EXCL_START */ + log_fatal("You must have at least %d 'content' files in different disks.\n", state->level + 1); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + /* check for speed */ +#ifdef CONFIG_X86 + if (!raid_cpu_has_ssse3()) +#endif + if (state->raid_mode == RAID_MODE_CAUCHY && !state->opt.no_warnings) { + if (state->level == 3) { + log_fatal("WARNING! Your CPU doesn't have a fast implementation for triple parity.\n"); + log_fatal("WARNING! It's recommended to switch to 'z-parity' instead than '3-parity'.\n"); + } else if (state->level > 3) { + log_fatal("WARNING! Your CPU doesn't have a fast implementation beyond triple parity.\n"); + log_fatal("WARNING! It's recommended to reduce the parity levels to triple parity.\n"); + } + } + + /* ensure that specified filter disks are valid ones */ + for (i = tommy_list_head(filterlist_disk); i != 0; i = i->next) { + tommy_node* j; + struct snapraid_filter* filter = i->data; + for (j = state->disklist; j != 0; j = j->next) { + struct snapraid_disk* disk = j->data; + if (fnmatch(filter->pattern, disk->name, FNM_CASEINSENSITIVE_FOR_WIN) == 0) + break; + } + if (j == 0) { + /* check matching with parity disks */ + for (l = 0; l < state->level; ++l) + if (fnmatch(filter->pattern, lev_config_name(l), FNM_CASEINSENSITIVE_FOR_WIN) == 0) + break; + if (l == state->level) { + /* LCOV_EXCL_START */ + log_fatal("Option -d, --filter-disk %s doesn't match any data or parity disk.\n", filter->pattern); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + } +} + +/** + * Validate the smartctl command. + * + * It must contains only one %s string, and not other % chars. + */ +static int validate_smartctl(const char* custom) +{ + const char* s = custom; + int arg = 0; + + while (*s) { + if (s[0] == '%' && s[1] == 's') { + if (arg) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + arg = 1; + } else if (s[0] == '%') { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + + ++s; + } + + return 0; +} + +void state_config(struct snapraid_state* state, const char* path, const char* command, struct snapraid_option* opt, tommy_list* filterlist_disk) +{ + STREAM* f; + unsigned line; + tommy_node* i; + unsigned l, s; + + /* copy the options */ + state->opt = *opt; + + /* if unset, sort by physical order */ + if (!state->opt.force_order) + state->opt.force_order = SORT_PHYSICAL; + + /* adjust file mode */ + if (state->opt.file_mode != ADVISE_DEFAULT) { + state->file_mode = state->opt.file_mode; + } else { + /* default mode, if nothing is specified */ + state->file_mode = ADVISE_DISCARD; + } + + /* store current command */ + state->command = command; + + log_tag("conf:file:%s\n", path); + + f = sopen_read(path); + if (!f) { + /* LCOV_EXCL_START */ + if (errno == ENOENT) { + if (state->opt.auto_conf) { + log_tag("conf:missing:\n"); + /* mark that we are without a configuration file */ + state->no_conf = 1; + state->level = 0; + return; + } + + log_fatal("No configuration file found at '%s'\n", path); + } else if (errno == EACCES) { + log_fatal("You do not have rights to access the configuration file '%s'\n", path); + } else { + log_fatal("Error opening the configuration file '%s'. %s.\n", path, strerror(errno)); + } + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + line = 1; + while (1) { + char tag[PATH_MAX]; + char buffer[PATH_MAX]; + int ret; + int c; + unsigned level; + + /* skip initial spaces */ + sgetspace(f); + + /* read the command */ + ret = sgettok(f, tag, sizeof(tag)); + if (ret < 0) { + /* LCOV_EXCL_START */ + log_fatal("Error reading the configuration file '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* skip spaces after the command */ + sgetspace(f); + + if (strcmp(tag, "blocksize") == 0 + /* block_size is the old format of the option */ + || strcmp(tag, "block_size") == 0) { + + ret = sgetu32(f, &state->block_size); + if (ret < 0) { + /* LCOV_EXCL_START */ + log_fatal("Invalid 'blocksize' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (state->block_size < 1) { + /* LCOV_EXCL_START */ + log_fatal("Too small 'blocksize' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (state->block_size > 16 * KIBI) { + /* LCOV_EXCL_START */ + log_fatal("Too big 'blocksize' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + /* check if it's a power of 2 */ + if ((state->block_size & (state->block_size - 1)) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Not power of 2 'blocksize' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + state->block_size *= KIBI; + } else if (strcmp(tag, "hashsize") == 0 + || strcmp(tag, "hash_size") == 0 /* v11.0 used incorretly this one, kept now for backward compatibility */ + ) { + uint32_t hash_size; + + ret = sgetu32(f, &hash_size); + if (ret < 0) { + /* LCOV_EXCL_START */ + log_fatal("Invalid 'hashsize' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (hash_size < 2) { + /* LCOV_EXCL_START */ + log_fatal("Too small 'hashsize' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (hash_size > HASH_MAX) { + /* LCOV_EXCL_START */ + log_fatal("Too big 'hashsize' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + /* check if it's a power of 2 */ + if ((hash_size & (hash_size - 1)) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Not power of 2 'hashsize' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + BLOCK_HASH_SIZE = hash_size; + } else if (lev_config_scan(tag, &level, &state->raid_mode) == 0) { + char device[PATH_MAX]; + char* split_map[SPLIT_MAX + 1]; + unsigned split_mac; + char* slash; + uint64_t dev; + int skip_access; + + if (state->parity[level].split_mac != 0) { + /* LCOV_EXCL_START */ + log_fatal("Multiple '%s' specification in '%s' at line %u\n", tag, path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + ret = sgetlasttok(f, buffer, sizeof(buffer)); + if (ret < 0) { + /* LCOV_EXCL_START */ + log_fatal("Invalid '%s' specification in '%s' at line %u\n", tag, path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (!*buffer) { + /* LCOV_EXCL_START */ + log_fatal("Empty '%s' specification in '%s' at line %u\n", tag, path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + split_mac = strsplit(split_map, SPLIT_MAX + 1, buffer, ","); + + if (split_mac > SPLIT_MAX) { + /* LCOV_EXCL_START */ + log_fatal("Too many files in '%s' specification in '%s' at line %u\n", tag, path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + skip_access = 0; + state->parity[level].split_mac = split_mac; + for (s = 0; s < split_mac; ++s) { + pathimport(state->parity[level].split_map[s].path, sizeof(state->parity[level].split_map[s].path), split_map[s]); + + if (!state->opt.skip_parity_access) { + struct stat st; + + /* get the device of the directory containing the parity file */ + pathimport(device, sizeof(device), split_map[s]); + slash = strrchr(device, '/'); + if (slash) + *slash = 0; + else + pathcpy(device, sizeof(device), "."); + + if (stat(device, &st) == 0) { + dev = st.st_dev; + } else { + /* if the disk can be skipped */ + if (state->opt.force_device) { + /* use a fake device, and mark the disk to be skipped */ + dev = 0; + skip_access = 1; + log_fatal("DANGER! Skipping inaccessible parity disk '%s'...\n", tag); + } else { + /* LCOV_EXCL_START */ + log_fatal("Error accessing 'parity' dir '%s' specification in '%s' at line %u\n", device, path, line); + + /* in "fix" we allow to continue anyway */ + if (strcmp(state->command, "fix") == 0) { + log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command); + } + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + } else { + /* use a fake device */ + dev = 0; + } + + state->parity[level].split_map[s].device = dev; + } + + /* store the global parity skip_access */ + state->parity[level].skip_access = skip_access; + + /* adjust the level */ + if (state->level < level + 1) + state->level = level + 1; + } else if (strcmp(tag, "share") == 0) { + if (*state->share) { + /* LCOV_EXCL_START */ + log_fatal("Multiple 'share' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + ret = sgetlasttok(f, buffer, sizeof(buffer)); + if (ret < 0) { + /* LCOV_EXCL_START */ + log_fatal("Invalid 'share' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (!*buffer) { + /* LCOV_EXCL_START */ + log_fatal("Empty 'share' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + pathimport(state->share, sizeof(state->share), buffer); + } else if (strcmp(tag, "pool") == 0) { + struct stat st; + + if (*state->pool) { + /* LCOV_EXCL_START */ + log_fatal("Multiple 'pool' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + ret = sgetlasttok(f, buffer, sizeof(buffer)); + if (ret < 0) { + /* LCOV_EXCL_START */ + log_fatal("Invalid 'pool' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (!*buffer) { + /* LCOV_EXCL_START */ + log_fatal("Empty 'pool' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + pathimport(state->pool, sizeof(state->pool), buffer); + + /* get the device of the directory containing the pool tree */ + if (stat(buffer, &st) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error accessing 'pool' dir '%s' specification in '%s' at line %u\n", buffer, path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + state->pool_device = st.st_dev; + } else if (strcmp(tag, "content") == 0) { + struct snapraid_content* content; + char device[PATH_MAX]; + char* slash; + struct stat st; + uint64_t dev; + + ret = sgetlasttok(f, buffer, sizeof(buffer)); + if (ret < 0) { + /* LCOV_EXCL_START */ + log_fatal("Invalid 'content' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (pathcmp(buffer, "/dev/null") == 0 || pathcmp(buffer, "NUL") == 0) { + /* LCOV_EXCL_START */ + log_fatal("You cannot use the null device as 'content' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (!*buffer) { + /* LCOV_EXCL_START */ + log_fatal("Empty 'content' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* check if the content file is already specified */ + for (i = state->contentlist; i != 0; i = i->next) { + content = i->data; + if (pathcmp(content->content, buffer) == 0) + break; + } + if (i) { + /* LCOV_EXCL_START */ + log_fatal("Duplicate 'content' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* get the device of the directory containing the content file */ + pathimport(device, sizeof(device), buffer); + slash = strrchr(device, '/'); + if (slash) + *slash = 0; + else + pathcpy(device, sizeof(device), "."); + if (stat(device, &st) == 0) { + dev = st.st_dev; + } else { + if (state->opt.skip_content_access) { + /* use a fake device */ + dev = 0; + log_fatal("WARNING! Skipping inaccessible content file '%s'...\n", buffer); + } else { + /* LCOV_EXCL_START */ + log_fatal("Error accessing 'content' dir '%s' specification in '%s' at line %u\n", device, path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + /* set the lock file at the first accessible content file */ + if (state->lockfile[0] == 0 && dev != 0) { + pathcpy(state->lockfile, sizeof(state->lockfile), buffer); + pathcat(state->lockfile, sizeof(state->lockfile), ".lock"); + } + + content = content_alloc(buffer, dev); + + tommy_list_insert_tail(&state->contentlist, &content->node, content); + } else if (strcmp(tag, "data") == 0 || strcmp(tag, "disk") == 0) { + /* "disk" is the deprecated name up to SnapRAID 9.x */ + char dir[PATH_MAX]; + char device[PATH_MAX]; + char uuid[UUID_MAX]; + struct snapraid_disk* disk; + uint64_t dev; + int skip_access; + + ret = sgettok(f, buffer, sizeof(buffer)); + if (ret < 0) { + /* LCOV_EXCL_START */ + log_fatal("Invalid 'data' name specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (!*buffer) { + /* LCOV_EXCL_START */ + log_fatal("Empty 'data' name specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + sgetspace(f); + + ret = sgetlasttok(f, dir, sizeof(dir)); + if (ret < 0) { + /* LCOV_EXCL_START */ + log_fatal("Invalid 'data' dir specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (!*dir) { + /* LCOV_EXCL_START */ + log_fatal("Empty 'data' dir specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* get the device of the dir */ + pathimport(device, sizeof(device), dir); + + /* check if the disk name already exists */ + for (i = state->disklist; i != 0; i = i->next) { + disk = i->data; + if (strcmp(disk->name, buffer) == 0) + break; + } + if (i) { + /* LCOV_EXCL_START */ + log_fatal("Duplicate 'data' name '%s' at line %u\n", buffer, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* if the disk has to be present */ + skip_access = 0; + if (!state->opt.skip_disk_access) { + struct stat st; + + if (stat(device, &st) == 0) { + dev = st.st_dev; + + /* read the uuid, if unsupported use an empty one */ + if (devuuid(dev, uuid, sizeof(uuid)) != 0) { + *uuid = 0; + } + + /* fake a different UUID when testing */ + if (state->opt.fake_uuid) { + snprintf(uuid, sizeof(uuid), "fake-uuid-%d", state->opt.fake_uuid); + --state->opt.fake_uuid; + } + } else { + /* if the disk can be skipped */ + if (state->opt.force_device) { + /* use a fake device, and mark the disk to be skipped */ + dev = 0; + *uuid = 0; + skip_access = 1; + log_fatal("DANGER! Skipping inaccessible data disk '%s'...\n", buffer); + } else { + /* LCOV_EXCL_START */ + log_fatal("Error accessing 'disk' '%s' specification in '%s' at line %u\n", dir, device, line); + + /* in "fix" we allow to continue anyway */ + if (strcmp(state->command, "fix") == 0) { + log_fatal("You can '%s' anyway, using 'snapraid --force-device %s'.\n", state->command, state->command); + } + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + } else { + /* use a fake device */ + dev = 0; + *uuid = 0; + } + + disk = disk_alloc(buffer, dir, dev, uuid, skip_access); + + tommy_list_insert_tail(&state->disklist, &disk->node, disk); + } else if (strcmp(tag, "smartctl") == 0) { + char custom[PATH_MAX]; + + ret = sgettok(f, buffer, sizeof(buffer)); + if (ret < 0) { + /* LCOV_EXCL_START */ + log_fatal("Invalid 'smartctl' name specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (!*buffer) { + /* LCOV_EXCL_START */ + log_fatal("Empty 'smartctl' name specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + sgetspace(f); + + ret = sgetlasttok(f, custom, sizeof(custom)); + if (ret < 0) { + /* LCOV_EXCL_START */ + log_fatal("Invalid 'smartctl' option specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (!*custom) { + /* LCOV_EXCL_START */ + log_fatal("Empty 'smartctl' option specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (validate_smartctl(custom) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Invalid 'smartctl' option specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* search for parity */ + if (lev_config_scan(buffer, &level, 0) == 0) { + if (state->parity[level].smartctl[0] != 0) { + /* LCOV_EXCL_START */ + log_fatal("Duplicate parity smartctl '%s' at line %u\n", buffer, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + pathcpy(state->parity[level].smartctl, sizeof(state->parity[level].smartctl), custom); + } else { + struct snapraid_disk* disk; + + /* search the disk */ + disk = 0; + for (i = state->disklist; i != 0; i = i->next) { + disk = i->data; + if (strcmp(disk->name, buffer) == 0) + break; + } + if (!disk) { + /* LCOV_EXCL_START */ + log_fatal("Missing disk smartctl '%s' at line %u\n", buffer, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (disk->smartctl[0] != 0) { + /* LCOV_EXCL_START */ + log_fatal("Duplicate disk name '%s' at line %u\n", buffer, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + pathcpy(disk->smartctl, sizeof(disk->smartctl), custom); + } + } else if (strcmp(tag, "nohidden") == 0) { + state->filter_hidden = 1; + } else if (strcmp(tag, "exclude") == 0) { + struct snapraid_filter* filter; + + ret = sgetlasttok(f, buffer, sizeof(buffer)); + if (ret < 0) { + /* LCOV_EXCL_START */ + log_fatal("Invalid 'exclude' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (!*buffer) { + /* LCOV_EXCL_START */ + log_fatal("Empty 'exclude' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + filter = filter_alloc_file(-1, buffer); + if (!filter) { + /* LCOV_EXCL_START */ + log_fatal("Invalid 'exclude' specification '%s' in '%s' at line %u\n", buffer, path, line); + log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + tommy_list_insert_tail(&state->filterlist, &filter->node, filter); + } else if (strcmp(tag, "include") == 0) { + struct snapraid_filter* filter; + + ret = sgetlasttok(f, buffer, sizeof(buffer)); + if (ret < 0) { + /* LCOV_EXCL_START */ + log_fatal("Invalid 'include' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (!*buffer) { + /* LCOV_EXCL_START */ + log_fatal("Empty 'include' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + filter = filter_alloc_file(1, buffer); + if (!filter) { + /* LCOV_EXCL_START */ + log_fatal("Invalid 'include' specification '%s' in '%s' at line %u\n", buffer, path, line); + log_fatal("Filters using relative paths are not supported. Ensure to add an initial slash\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + tommy_list_insert_tail(&state->filterlist, &filter->node, filter); + } else if (strcmp(tag, "autosave") == 0) { + char* e; + + ret = sgetlasttok(f, buffer, sizeof(buffer)); + if (ret < 0) { + /* LCOV_EXCL_START */ + log_fatal("Invalid 'autosave' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (!*buffer) { + /* LCOV_EXCL_START */ + log_fatal("Empty 'autosave' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + state->autosave = strtoul(buffer, &e, 0); + + if (!e || *e) { + /* LCOV_EXCL_START */ + log_fatal("Invalid 'autosave' specification in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* convert to GB */ + state->autosave *= GIGA; + } else if (tag[0] == 0) { + /* allow empty lines */ + } else if (tag[0] == '#') { + ret = sgetline(f, buffer, sizeof(buffer)); + if (ret < 0) { + /* LCOV_EXCL_START */ + log_fatal("Invalid comment in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } else { + /* LCOV_EXCL_START */ + log_fatal("Invalid command '%s' in '%s' at line %u\n", tag, path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* skip final spaces */ + sgetspace(f); + + /* next line */ + c = sgeteol(f); + if (c == EOF) { + break; + } + if (c != '\n') { + /* LCOV_EXCL_START */ + log_fatal("Extra data in '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + ++line; + } + + if (serror(f)) { + /* LCOV_EXCL_START */ + log_fatal("Error reading the configuration file '%s' at line %u\n", path, line); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + sclose(f); + + state_config_check(state, path, filterlist_disk); + + /* select the default hash */ + if (state->opt.force_murmur3) { + state->besthash = HASH_MURMUR3; + } else if (state->opt.force_spooky2) { + state->besthash = HASH_SPOOKY2; + } else { +#ifdef CONFIG_X86 + if (sizeof(void*) == 4 && !raid_cpu_has_slowmult()) + state->besthash = HASH_MURMUR3; + else + state->besthash = HASH_SPOOKY2; +#else + if (sizeof(void*) == 4) + state->besthash = HASH_MURMUR3; + else + state->besthash = HASH_SPOOKY2; +#endif + } + + /* by default use the best hash */ + state->hash = state->besthash; + + /* by default use a random hash seed */ + if (randomize(state->hashseed, HASH_MAX) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to get random values.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* no previous hash by default */ + state->prevhash = HASH_UNDEFINED; + + /* intentionally not set the prevhashseed, if used valgrind will warn about it */ + + log_tag("blocksize:%u\n", state->block_size); + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* disk = i->data; + log_tag("data:%s:%s\n", disk->name, disk->dir); + } + + log_tag("mode:%s\n", lev_raid_name(state->raid_mode, state->level)); + for (l = 0; l < state->level; ++l) + for (s = 0; s < state->parity[l].split_mac; ++s) + log_tag("%s:%u:%s\n", lev_config_name(l), s, state->parity[l].split_map[s].path); + if (state->pool[0] != 0) + log_tag("pool:%s\n", state->pool); + if (state->share[0] != 0) + log_tag("share:%s\n", state->share); + if (state->autosave != 0) + log_tag("autosave:%" PRIu64 "\n", state->autosave); + for (i = tommy_list_head(&state->filterlist); i != 0; i = i->next) { + char out[PATH_MAX]; + struct snapraid_filter* filter = i->data; + log_tag("filter:%s\n", filter_type(filter, out, sizeof(out))); + } + if (state->filter_hidden) + log_tag("filter:nohidden:\n"); + log_flush(); +} + +/** + * Find a disk by name. + */ +static struct snapraid_disk* find_disk_by_name(struct snapraid_state* state, const char* name) +{ + tommy_node* i; + + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* disk = i->data; + if (strcmp(disk->name, name) == 0) + return disk; + } + + if (state->no_conf) { + /* without a configuration file, add disks automatically */ + struct snapraid_disk* disk; + + disk = disk_alloc(name, "DUMMY/", -1, "", 0); + + tommy_list_insert_tail(&state->disklist, &disk->node, disk); + + return disk; + } + + return 0; +} + +/** + * Find a disk by UUID. + */ +static struct snapraid_disk* find_disk_by_uuid(struct snapraid_state* state, const char* uuid) +{ + tommy_node* i; + struct snapraid_disk* found = 0; + + /* special test case to find the first matching UUID */ + /* when testing UUID are all equal or not supported */ + /* and we should handle this case specifically */ + if (state->opt.match_first_uuid) + return state->disklist->data; + + /* LCOV_EXCL_START */ + /* never find an empty uuid */ + if (!*uuid) + return 0; + + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* disk = i->data; + if (strcmp(disk->uuid, uuid) == 0) { + /* never match duplicate UUID */ + if (found) + return 0; + found = disk; + } + } + + return found; + /* LCOV_EXCL_STOP */ +} + +/** + * Update the disk mapping if required. + */ +static void state_map(struct snapraid_state* state) +{ + unsigned hole; + tommy_node* i; + unsigned uuid_mismatch; + unsigned diskcount; + unsigned l, s; + + /* remove all the mapping without a disk */ + /* this happens when a disk is removed from the configuration file */ + /* From SnapRAID 4.0 mappings are automatically removed if a disk is not used */ + /* when saving the content file, but we keep this code to import older content files. */ + for (i = state->maplist; i != 0; ) { + struct snapraid_map* map = i->data; + struct snapraid_disk* disk; + + disk = find_disk_by_name(state, map->name); + + /* go to the next mapping before removing */ + i = i->next; + + if (disk == 0) { + /* disk not found, remove the mapping */ + tommy_list_remove_existing(&state->maplist, &map->node); + map_free(map); + } + } + + /* maps each unmapped disk present in the configuration file in the first available hole */ + /* this happens when you add disks for the first time in the configuration file */ + hole = 0; /* first position to try */ + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* disk = i->data; + struct snapraid_map* map; + tommy_node* j; + + /* check if the disk is already mapped */ + for (j = state->maplist; j != 0; j = j->next) { + map = j->data; + if (strcmp(disk->name, map->name) == 0) { + /* mapping found */ + break; + } + } + if (j != 0) { + /* mapping is present, then copy the free blocks into to disk */ + disk->total_blocks = map->total_blocks; + disk->free_blocks = map->free_blocks; + continue; + } + + /* mapping not found, search for an hole */ + while (1) { + for (j = state->maplist; j != 0; j = j->next) { + map = j->data; + if (map->position == hole) { + /* position already used */ + break; + } + } + if (j == 0) { + /* hole found */ + break; + } + + /* try with the next one */ + ++hole; + } + + /* insert the new mapping */ + map = map_alloc(disk->name, hole, 0, 0, ""); + + tommy_list_insert_tail(&state->maplist, &map->node, map); + } + + /* without configuration don't check for number of data disks or uuid changes */ + if (state->no_conf) + return; + + /* counter for the number of UUID mismatches */ + uuid_mismatch = 0; + + /* check if mapping match the disk uuid */ + if (!state->opt.skip_disk_access) { + for (i = state->maplist; i != 0; i = i->next) { + struct snapraid_map* map = i->data; + struct snapraid_disk* disk; + + disk = find_disk_by_name(state, map->name); + if (disk == 0) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency for mapping '%s'\n", map->name); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + if (disk->has_unsupported_uuid) { + /* if uuid is not available, skip this one */ + continue; + } + + /* if the uuid is changed */ + if (strcmp(disk->uuid, map->uuid) != 0) { + /* mark the disk as with an UUID change */ + disk->has_different_uuid = 1; + + /* if the previous uuid is available */ + if (map->uuid[0] != 0) { + /* count the number of uuid change */ + ++uuid_mismatch; + log_fatal("UUID change for disk '%s' from '%s' to '%s'\n", disk->name, map->uuid, disk->uuid); + } else { + /* no message here, because having a disk without */ + /* UUID is the normal state of an empty disk */ + disk->had_empty_uuid = 1; + } + + /* update the uuid in the mapping, */ + pathcpy(map->uuid, sizeof(map->uuid), disk->uuid); + + /* write the new state with the new uuid */ + state->need_write = 1; + } + } + } + + /* check the parity uuid */ + if (!state->opt.skip_parity_access) { + for (l = 0; l < state->level; ++l) { + for (s = 0; s < state->parity[l].split_mac; ++s) { + char uuid[UUID_MAX]; + int ret; + + ret = devuuid(state->parity[l].split_map[s].device, uuid, sizeof(uuid)); + if (ret != 0) { + /* uuid not available, just ignore */ + continue; + } + + /* if the uuid is changed */ + if (strcmp(uuid, state->parity[l].split_map[s].uuid) != 0) { + /* if the previous uuid is available */ + if (state->parity[l].split_map[s].uuid[0] != 0) { + /* count the number of uuid change */ + ++uuid_mismatch; + log_fatal("UUID change for parity '%s[%u]' from '%s' to '%s'\n", lev_config_name(l), s, state->parity[l].split_map[s].uuid, uuid); + } + + /* update the uuid */ + pathcpy(state->parity[l].split_map[s].uuid, sizeof(state->parity[l].split_map[s].uuid), uuid); + + /* write the new state with the new uuid */ + state->need_write = 1; + } + } + } + } + + if (!state->opt.force_uuid && uuid_mismatch > state->level) { + /* LCOV_EXCL_START */ + log_fatal("Too many disks have UUID changed from the latest 'sync'.\n"); + log_fatal("If this happens because you really replaced them,\n"); + log_fatal("you can '%s' anyway, using 'snapraid --force-uuid %s'.\n", state->command, state->command); + log_fatal("Instead, it's possible that you messed up the disk mount points,\n"); + log_fatal("and you have to restore the mount points at the state of the latest sync.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* count the number of data disks, including holes left after removing some */ + diskcount = 0; + for (i = state->maplist; i != 0; i = i->next) { + struct snapraid_map* map = i->data; + + if (map->position + 1 > diskcount) + diskcount = map->position + 1; + } + + /* ensure to don't go over the limit of the RAID engine */ + if (diskcount > RAID_DATA_MAX) { + /* LCOV_EXCL_START */ + log_fatal("Too many data disks. No more than %u.\n", RAID_DATA_MAX); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* now count the real number of data disks, excluding holes left after removing some */ + diskcount = tommy_list_count(&state->maplist); + + /* recommend number of parities */ + if (!state->opt.no_warnings) { + /* intentionally use log_fatal() instead of log_error() to give more visibility at the warning */ + if (diskcount >= 36 && state->level < 6) { + log_fatal("WARNING! With %u disks it's recommended to use six parity levels.\n", diskcount); + } else if (diskcount >= 29 && state->level < 5) { + log_fatal("WARNING! With %u disks it's recommended to use five parity levels.\n", diskcount); + } else if (diskcount >= 22 && state->level < 4) { + log_fatal("WARNING! With %u disks it's recommended to use four parity levels.\n", diskcount); + } else if (diskcount >= 15 && state->level < 3) { + log_fatal("WARNING! With %u disks it's recommended to use three parity levels.\n", diskcount); + } else if (diskcount >= 5 && state->level < 2) { + log_fatal("WARNING! With %u disks it's recommended to use two parity levels.\n", diskcount); + } + } +} + +void state_refresh(struct snapraid_state* state) +{ + tommy_node* i; + unsigned l, s; + + /* for all disks */ + for (i = state->maplist; i != 0; i = i->next) { + struct snapraid_map* map = i->data; + struct snapraid_disk* disk; + uint64_t total_space; + uint64_t free_space; + int ret; + + disk = find_disk_by_name(state, map->name); + if (disk == 0) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency for mapping '%s'\n", map->name); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + ret = fsinfo(disk->dir, 0, 0, &total_space, &free_space); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error accessing disk '%s' to get file-system info. %s.\n", disk->dir, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* set the new free blocks */ + map->total_blocks = total_space / state->block_size; + map->free_blocks = free_space / state->block_size; + + /* also update the disk info */ + disk->total_blocks = map->total_blocks; + disk->free_blocks = map->free_blocks; + } + + /* for all parities */ + for (l = 0; l < state->level; ++l) { + /* set the new free blocks */ + state->parity[l].total_blocks = 0; + state->parity[l].free_blocks = 0; + + for (s = 0; s < state->parity[l].split_mac; ++s) { + uint64_t total_space; + uint64_t free_space; + int ret; + + ret = fsinfo(state->parity[l].split_map[s].path, 0, 0, &total_space, &free_space); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error accessing file '%s' to get file-system info. %s.\n", state->parity[l].split_map[s].path, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* add the new free blocks */ + state->parity[l].total_blocks += total_space / state->block_size; + state->parity[l].free_blocks += free_space / state->block_size; + } + } + + /* note what we don't set need_write = 1, because we don't want */ + /* to update the content file only for the free space info. */ +} + +/** + * Check the content. + */ +static void state_content_check(struct snapraid_state* state, const char* path) +{ + tommy_node* i; + + /* check that any map has different name and position */ + for (i = state->maplist; i != 0; i = i->next) { + struct snapraid_map* map = i->data; + tommy_node* j; + for (j = i->next; j != 0; j = j->next) { + struct snapraid_map* other = j->data; + if (strcmp(map->name, other->name) == 0) { + /* LCOV_EXCL_START */ + log_fatal("Colliding 'map' disk specification in '%s'\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + if (map->position == other->position) { + /* LCOV_EXCL_START */ + log_fatal("Colliding 'map' index specification in '%s'\n", path); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + } +} + +/** + * Check if the position is REQUIRED, or we can completely clear it from the state. + * + * Note that position with only DELETED blocks are discarged. + */ +static int fs_position_is_required(struct snapraid_state* state, block_off_t pos) +{ + tommy_node* i; + + /* check for each disk */ + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* disk = i->data; + struct snapraid_block* block = fs_par2block_find(disk, pos); + + /* if we have at least one file, the position is needed */ + if (block_has_file(block)) + return 1; + } + + return 0; +} + +/** + * Check if the info block is REQUIREQ. + * + * This is used to ensure that we keep the last check used for scrubbing. + * and that we add it when importing old context files. + * + * Note that you can have position without info blocks, for example + * if all the blocks are not synced. + * + * Note also that not requiring an info block, doesn't mean that if present it + * can be discarded. + */ +static int fs_info_is_required(struct snapraid_state* state, block_off_t pos) +{ + tommy_node* i; + + /* check for each disk */ + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* disk = i->data; + struct snapraid_block* block = fs_par2block_find(disk, pos); + + /* if we have at least one synced file, the info is required */ + if (block_state_get(block) == BLOCK_STATE_BLK) + return 1; + } + + return 0; +} + +static void fs_position_clear_deleted(struct snapraid_state* state, block_off_t pos) +{ + tommy_node* i; + + /* check for each disk if block is really used */ + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* disk = i->data; + struct snapraid_block* block = fs_par2block_find(disk, pos); + + /* if the block is deleted */ + if (block_state_get(block) == BLOCK_STATE_DELETED) { + /* set it to empty */ + fs_deallocate(disk, pos); + } + } +} + +/** + * Check if a block position in a disk is deleted. + */ +static int fs_is_block_deleted(struct snapraid_disk* disk, block_off_t pos) +{ + struct snapraid_block* block = fs_par2block_find(disk, pos); + + return block_state_get(block) == BLOCK_STATE_DELETED; +} + +/** + * Flush the file checking the final CRC. + * We exploit the fact that the CRC is always stored in the last 4 bytes. + */ +static void decoding_error(const char* path, STREAM* f) +{ + unsigned char buf[4]; + uint32_t crc_stored; + uint32_t crc_computed; + + if (seof(f)) { + /* LCOV_EXCL_START */ + log_fatal("Unexpected end of content file '%s' at offset %" PRIi64 "\n", path, stell(f)); + log_fatal("This content file is truncated. Use an alternate copy.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (serror(f)) { + /* LCOV_EXCL_START */ + log_fatal("Error reading the content file '%s' at offset %" PRIi64 "\n", path, stell(f)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + log_fatal("Decoding error in '%s' at offset %" PRIi64 "\n", path, stell(f)); + + if (sdeplete(f, buf) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error flushing the content file '%s' at offset %" PRIi64 "\n", path, stell(f)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* get the stored crc from the last four bytes */ + crc_stored = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24; + + /* get the computed crc */ + crc_computed = scrc(f); + + /* adjust the stored crc to include itself */ + crc_stored = crc32c(crc_stored, buf, 4); + + if (crc_computed != crc_stored) { + log_fatal("Mismatching CRC in '%s'\n", path); + log_fatal("This content file is damaged! Use an alternate copy.\n"); + exit(EXIT_FAILURE); + } else { + log_fatal("The file CRC is correct!\n"); + } +} + +static void state_read_content(struct snapraid_state* state, const char* path, STREAM* f) +{ + block_off_t blockmax; + unsigned count_file; + unsigned count_hardlink; + unsigned count_symlink; + unsigned count_dir; + int crc_checked; + char buffer[PATH_MAX]; + int ret; + tommy_array disk_mapping; + uint32_t mapping_max; + + blockmax = 0; + count_file = 0; + count_hardlink = 0; + count_symlink = 0; + count_dir = 0; + crc_checked = 0; + mapping_max = 0; + tommy_array_init(&disk_mapping); + + ret = sread(f, buffer, 12); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Invalid header!\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* + * File format versions: + * - SNAPCNT1/SnapRAID 4.0 First version. + * - SNAPCNT2/SnapRAID 7.0 Adds entries 'M' and 'P', to add free_blocks support. + * The previous 'm' entry is now deprecated, but supported for importing. + * Similarly for text file, we add 'mapping' and 'parity' deprecating 'map'. + * - SNAPCNT3/SnapRAID 11.0 Adds entry 'y' for hash size. + * - SNAPCNT3/SnapRAID 11.0 Adds entry 'Q' for multi parity file. + * The previous 'P' entry is now deprecated, but supported for importing. + */ + if (memcmp(buffer, "SNAPCNT1\n\3\0\0", 12) != 0 + && memcmp(buffer, "SNAPCNT2\n\3\0\0", 12) != 0 + && memcmp(buffer, "SNAPCNT3\n\3\0\0", 12) != 0 + ) { + /* LCOV_EXCL_START */ + if (memcmp(buffer, "SNAPCNT", 7) != 0) { + decoding_error(path, f); + log_fatal("Invalid header!\n"); + os_abort(); + } else { + log_fatal("The content file '%s' was generated with a newer version of SnapRAID!\n", path); + exit(EXIT_FAILURE); + } + /* LCOV_EXCL_STOP */ + } + + while (1) { + int c; + + /* read the command */ + c = sgetc(f); + if (c == EOF) { + break; + } + + if (c == 'f') { + /* file */ + char sub[PATH_MAX]; + uint64_t v_size; + uint64_t v_mtime_sec; + uint32_t v_mtime_nsec; + uint64_t v_inode; + uint32_t v_idx; + struct snapraid_file* file; + struct snapraid_disk* disk; + uint32_t mapping; + + ret = sgetb32(f, &mapping); + if (ret < 0 || mapping >= mapping_max) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Internal inconsistency in mapping index!\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + disk = tommy_array_get(&disk_mapping, mapping); + + ret = sgetb64(f, &v_size); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + if (state->block_size == 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Internal incosistency due zero blocksize!\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* check for impossible file size to avoid to crash for a too big allocation */ + if (v_size / state->block_size > blockmax) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Internal inconsistency in file size too big!\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + ret = sgetb64(f, &v_mtime_sec); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + ret = sgetb32(f, &v_mtime_nsec); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* STAT_NSEC_INVALID is encoded as 0 */ + if (v_mtime_nsec == 0) + v_mtime_nsec = STAT_NSEC_INVALID; + else + --v_mtime_nsec; + + ret = sgetb64(f, &v_inode); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + ret = sgetbs(f, sub, sizeof(sub)); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + if (!*sub) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Internal inconsistency for null file!\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* allocate the file */ + file = file_alloc(state->block_size, sub, v_size, v_mtime_sec, v_mtime_nsec, v_inode, 0); + + /* insert the file in the file containers */ + tommy_hashdyn_insert(&disk->inodeset, &file->nodeset, file, file_inode_hash(file->inode)); + tommy_hashdyn_insert(&disk->pathset, &file->pathset, file, file_path_hash(file->sub)); + tommy_hashdyn_insert(&disk->stampset, &file->stampset, file, file_stamp_hash(file->size, file->mtime_sec, file->mtime_nsec)); + tommy_list_insert_tail(&disk->filelist, &file->nodelist, file); + + /* read all the blocks */ + v_idx = 0; + while (v_idx < file->blockmax) { + block_off_t v_pos; + uint32_t v_count; + + /* get the "subcommand */ + c = sgetc(f); + + ret = sgetb32(f, &v_pos); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + ret = sgetb32(f, &v_count); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + if (v_idx + v_count > file->blockmax) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Internal inconsistency in block number!\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + if (v_pos + v_count > blockmax) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Internal inconsistency in block size %u/%u!\n", blockmax, v_pos + v_count); + os_abort(); + /* LCOV_EXCL_START */ + } + + /* fill the blocks in the run */ + while (v_count) { + struct snapraid_block* block = fs_file2block_get(file, v_idx); + + switch (c) { + case 'b' : + block_state_set(block, BLOCK_STATE_BLK); + break; + case 'n' : + /* deprecated NEW blocks are converted to CHG ones */ + block_state_set(block, BLOCK_STATE_CHG); + break; + case 'g' : + block_state_set(block, BLOCK_STATE_CHG); + break; + case 'p' : + block_state_set(block, BLOCK_STATE_REP); + break; + default : + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Invalid block type!\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* read the hash only for 'blk/chg/rep', and not for 'new' */ + if (c != 'n') { + ret = sread(f, block->hash, BLOCK_HASH_SIZE); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + } else { + /* set the ZERO hash for deprecated NEW blocks */ + hash_zero_set(block->hash); + } + + /* if the block contains a hash of past data */ + /* and we are clearing such indeterminate hashes */ + if (state->clear_past_hash + && block_has_past_hash(block) + ) { + /* set the hash value to INVALID */ + hash_invalid_set(block->hash); + } + + /* if we are disabling the copy optimization */ + /* we want also to clear any already previously stored information */ + /* in other sync commands */ + /* note that this is required only in sync, and we detect */ + /* this using the clear_past_hash flag */ + if (state->clear_past_hash + && state->opt.force_nocopy + && block_state_get(block) == BLOCK_STATE_REP + ) { + /* set the hash value to INVALID */ + hash_invalid_set(block->hash); + /* convert from REP to CHG block */ + block_state_set(block, BLOCK_STATE_CHG); + } + + /* if we want a full reallocation, marks block as invalid parity */ + /* note that we do this after the force_nocopy option */ + /* to avoid to mixup the two things */ + if (state->opt.force_realloc + && block_state_get(block) == BLOCK_STATE_BLK) { + /* convert from BLK to REP */ + block_state_set(block, BLOCK_STATE_REP); + } + + /* set the parity association */ + fs_allocate(disk, v_pos, file, v_idx); + + /* go to the next block */ + ++v_idx; + ++v_pos; + --v_count; + } + } + + /* stat */ + ++count_file; + } else if (c == 'i') { + /* "inf" command */ + snapraid_info info; + uint32_t v_pos; + uint32_t v_oldest; + + ret = sgetb32(f, &v_oldest); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + v_pos = 0; + while (v_pos < blockmax) { + int bad; + int rehash; + int justsynced; + uint32_t t; + uint32_t flag; + uint32_t v_count; + + ret = sgetb32(f, &v_count); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + if (v_pos + v_count > blockmax) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Internal inconsistency in info size %u/%u!\n", blockmax, v_pos + v_count); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + ret = sgetb32(f, &flag); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* if there is an info */ + if ((flag & 1) != 0) { + /* read the time */ + ret = sgetb32(f, &t); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* analyze the flags */ + bad = (flag & 2) != 0; + rehash = (flag & 4) != 0; + justsynced = (flag & 8) != 0; + + if (rehash && state->prevhash == HASH_UNDEFINED) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Internal inconsistency for missing previous checksum!\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + info = info_make(t + v_oldest, bad, rehash, justsynced); + } else { + info = 0; + } + + while (v_count) { + /* insert the info in the array */ + info_set(&state->infoarr, v_pos, info); + + /* ensure that an info is present only for used positions */ + if (fs_info_is_required(state, v_pos)) { + if (!info) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Internal inconsistency for missing info!\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + } else { + /* extra info are accepted for backward compatibility */ + /* they are discarded at the first write */ + } + + /* go to next block */ + ++v_pos; + --v_count; + } + } + } else if (c == 'h') { + /* hole */ + uint32_t v_pos; + struct snapraid_disk* disk; + uint32_t mapping; + + ret = sgetb32(f, &mapping); + if (ret < 0 || mapping >= mapping_max) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Internal inconsistency in mapping index!\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + disk = tommy_array_get(&disk_mapping, mapping); + + v_pos = 0; + while (v_pos < blockmax) { + uint32_t v_idx; + uint32_t v_count; + struct snapraid_file* deleted; + + ret = sgetb32(f, &v_count); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + if (v_pos + v_count > blockmax) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Internal inconsistency in hole size %u/%u!\n", blockmax, v_pos + v_count); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* get the sub-command */ + c = sgetc(f); + + switch (c) { + case 'o' : + /* if it's a run of deleted blocks */ + + /* allocate a fake deleted file */ + deleted = file_alloc(state->block_size, "", v_count * (data_off_t)state->block_size, 0, 0, 0, 0); + + /* mark the file as deleted */ + file_flag_set(deleted, FILE_IS_DELETED); + + /* insert it in the list of deleted files */ + tommy_list_insert_tail(&disk->deletedlist, &deleted->nodelist, deleted); + + /* process all blocks */ + v_idx = 0; + while (v_count) { + struct snapraid_block* block = fs_file2block_get(deleted, v_idx); + + /* set the block as deleted */ + block_state_set(block, BLOCK_STATE_DELETED); + + /* read the hash */ + ret = sread(f, block->hash, BLOCK_HASH_SIZE); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* if we are clearing indeterminate hashes */ + if (state->clear_past_hash) { + /* set the hash value to INVALID */ + hash_invalid_set(block->hash); + } + + /* insert the block in the block array */ + fs_allocate(disk, v_pos, deleted, v_idx); + + /* go to next block */ + ++v_pos; + ++v_idx; + --v_count; + } + break; + case 'O' : + /* go to the next run */ + v_pos += v_count; + break; + default : + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Invalid hole type!\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + } + } else if (c == 's') { + /* symlink */ + char sub[PATH_MAX]; + char linkto[PATH_MAX]; + struct snapraid_link* slink; + struct snapraid_disk* disk; + uint32_t mapping; + + ret = sgetb32(f, &mapping); + if (ret < 0 || mapping >= mapping_max) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Internal inconsistency in mapping index!\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + disk = tommy_array_get(&disk_mapping, mapping); + + ret = sgetbs(f, sub, sizeof(sub)); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + if (!*sub) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Internal inconsistency for null symlink!\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + ret = sgetbs(f, linkto, sizeof(linkto)); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* allocate the link as symbolic link */ + slink = link_alloc(sub, linkto, FILE_IS_SYMLINK); + + /* insert the link in the link containers */ + tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub)); + tommy_list_insert_tail(&disk->linklist, &slink->nodelist, slink); + + /* stat */ + ++count_symlink; + } else if (c == 'a') { + /* hardlink */ + char sub[PATH_MAX]; + char linkto[PATH_MAX]; + struct snapraid_link* slink; + struct snapraid_disk* disk; + uint32_t mapping; + + ret = sgetb32(f, &mapping); + if (ret < 0 || mapping >= mapping_max) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Internal inconsistency in mapping index!\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + disk = tommy_array_get(&disk_mapping, mapping); + + ret = sgetbs(f, sub, sizeof(sub)); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + if (!*sub) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Internal inconsistency for null hardlink!\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + ret = sgetbs(f, linkto, sizeof(linkto)); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + if (!*linkto) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Internal inconsistency for empty hardlink '%s'!\n", sub); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* allocate the link as hard link */ + slink = link_alloc(sub, linkto, FILE_IS_HARDLINK); + + /* insert the link in the link containers */ + tommy_hashdyn_insert(&disk->linkset, &slink->nodeset, slink, link_name_hash(slink->sub)); + tommy_list_insert_tail(&disk->linklist, &slink->nodelist, slink); + + /* stat */ + ++count_hardlink; + } else if (c == 'r') { + /* dir */ + char sub[PATH_MAX]; + struct snapraid_dir* dir; + struct snapraid_disk* disk; + uint32_t mapping; + + ret = sgetb32(f, &mapping); + if (ret < 0 || mapping >= mapping_max) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Internal inconsistency in mapping index!\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + disk = tommy_array_get(&disk_mapping, mapping); + + ret = sgetbs(f, sub, sizeof(sub)); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + if (!*sub) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Internal inconsistency for null dir!\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* allocate the dir */ + dir = dir_alloc(sub); + + /* insert the dir in the dir containers */ + tommy_hashdyn_insert(&disk->dirset, &dir->nodeset, dir, dir_name_hash(dir->sub)); + tommy_list_insert_tail(&disk->dirlist, &dir->nodelist, dir); + + /* stat */ + ++count_dir; + } else if (c == 'c') { + /* get the subcommand */ + c = sgetc(f); + + switch (c) { + case 'u' : + state->hash = HASH_MURMUR3; + break; + case 'k' : + state->hash = HASH_SPOOKY2; + break; + default : + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Invalid checksum!\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* read the seed */ + ret = sread(f, state->hashseed, HASH_MAX); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + } else if (c == 'C') { + /* get the sub-command */ + c = sgetc(f); + + switch (c) { + case 'u' : + state->prevhash = HASH_MURMUR3; + break; + case 'k' : + state->prevhash = HASH_SPOOKY2; + break; + default : + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Invalid checksum!\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* read the seed */ + ret = sread(f, state->prevhashseed, HASH_MAX); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + } else if (c == 'z') { + uint32_t block_size; + + ret = sgetb32(f, &block_size); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + if (block_size == 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Zero 'blocksize' specification in the content file!\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* without configuration, auto assign the block size */ + if (state->no_conf) { + state->block_size = block_size; + } + + if (block_size != state->block_size) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Mismatching 'blocksize' specification in the content file!\n"); + log_fatal("Please restore the 'blocksize' value in the configuration file to '%u'\n", block_size / KIBI); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } else if (c == 'y') { + uint32_t hash_size; + + ret = sgetb32(f, &hash_size); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + if (hash_size < 2 || hash_size > HASH_MAX) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Invalid 'hashsize' specification in the content file!\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* without configuration, auto assign the block size */ + if (state->no_conf) { + BLOCK_HASH_SIZE = hash_size; + } + + if ((int)hash_size != BLOCK_HASH_SIZE) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Mismatching 'hashsize' specification in the content file!\n"); + log_fatal("Please restore the 'hashsize' value in the configuration file to '%u'\n", hash_size); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } else if (c == 'x') { + ret = sgetb32(f, &blockmax); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + } else if (c == 'm' || c == 'M') { + struct snapraid_map* map; + char uuid[UUID_MAX]; + uint32_t v_pos; + uint32_t v_total_blocks; + uint32_t v_free_blocks; + struct snapraid_disk* disk; + + ret = sgetbs(f, buffer, sizeof(buffer)); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + ret = sgetb32(f, &v_pos); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* from SnapRAID 7.0 the 'M' command includes the free space */ + if (c == 'M') { + ret = sgetb32(f, &v_total_blocks); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + ret = sgetb32(f, &v_free_blocks); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + } else { + v_total_blocks = 0; + v_free_blocks = 0; + } + + /* read the uuid */ + ret = sgetbs(f, uuid, sizeof(uuid)); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* find the disk */ + disk = find_disk_by_name(state, buffer); + if (!disk) { + /* search by UUID if renamed */ + disk = find_disk_by_uuid(state, uuid); + if (disk) { + log_fatal("WARNING! Renaming disk '%s' to '%s'\n", buffer, disk->name); + + /* write the new state with the new name */ + state->need_write = 1; + } + } + if (!disk) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Disk '%s' with uuid '%s' not present in the configuration file!\n", buffer, uuid); + log_fatal("If you have removed it from the configuration file, please restore it\n"); + /* if it's a command without UUID, it cannot autorename using UUID */ + if (state->opt.skip_disk_access) + log_fatal("If you have renamed it, run 'sync' to update the new name\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + map = map_alloc(disk->name, v_pos, v_total_blocks, v_free_blocks, uuid); + + tommy_list_insert_tail(&state->maplist, &map->node, map); + + /* insert in the mapping vector */ + tommy_array_grow(&disk_mapping, mapping_max + 1); + tommy_array_set(&disk_mapping, mapping_max, disk); + ++mapping_max; + } else if (c == 'P') { + /* from SnapRAID 7.0 the 'P' command includes the free space */ + /* from SnapRAID 11.0 the 'P' command is deprecated by 'Q' */ + char v_uuid[UUID_MAX]; + uint32_t v_level; + uint32_t v_total_blocks; + uint32_t v_free_blocks; + + ret = sgetb32(f, &v_level); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + ret = sgetb32(f, &v_total_blocks); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + ret = sgetb32(f, &v_free_blocks); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + ret = sgetbs(f, v_uuid, sizeof(v_uuid)); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + if (v_level >= LEV_MAX) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Invalid parity level '%u' in the configuration file!\n", v_level); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* auto configure if configuration is missing */ + if (state->no_conf) { + if (v_level >= state->level) + state->level = v_level + 1; + } + + /* if we use this parity entry */ + if (v_level < state->level) { + /* if the configuration has more splits, keep them */ + if (state->parity[v_level].split_mac < 1) + state->parity[v_level].split_mac = 1; + /* set the parity info */ + pathcpy(state->parity[v_level].split_map[0].uuid, sizeof(state->parity[v_level].split_map[0].uuid), v_uuid); + state->parity[v_level].total_blocks = v_total_blocks; + state->parity[v_level].free_blocks = v_free_blocks; + } + } else if (c == 'Q') { + /* from SnapRAID 11.0 the 'Q' command include size info and multi file support */ + uint32_t v_level; + uint32_t v_total_blocks; + uint32_t v_free_blocks; + uint32_t v_split_mac; + unsigned s; + + ret = sgetb32(f, &v_level); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + ret = sgetb32(f, &v_total_blocks); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + ret = sgetb32(f, &v_free_blocks); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + ret = sgetb32(f, &v_split_mac); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + if (v_level >= LEV_MAX) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Invalid parity level '%u' in the configuration file!\n", v_level); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* auto configure if configuration is missing */ + if (state->no_conf) { + if (v_level >= state->level) + state->level = v_level + 1; + if (state->parity[v_level].split_mac < v_split_mac) + state->parity[v_level].split_mac = v_split_mac; + } + + /* if we use this parity entry */ + if (v_level < state->level) { + /* set the parity info */ + state->parity[v_level].total_blocks = v_total_blocks; + state->parity[v_level].free_blocks = v_free_blocks; + } + + for (s = 0; s < v_split_mac; ++s) { + char v_path[PATH_MAX]; + char v_uuid[UUID_MAX]; + uint64_t v_size; + + ret = sgetbs(f, v_path, sizeof(v_path)); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + ret = sgetbs(f, v_uuid, sizeof(v_uuid)); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + ret = sgetb64(f, &v_size); + if (ret < 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* if we use this parity entry */ + if (v_level < state->level) { + /* if this split was removed from the configuration */ + if (s >= state->parity[v_level].split_mac) { + /* if the file is used, we really need it */ + if (v_size != 0) { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Parity '%s' misses used file '%u'!\n", lev_config_name(v_level), s); + log_fatal("If you have removed it from the configuration file, please restore it\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* otherwise we can drop it */ + log_fatal("WARNING! Dropping from '%s' unused split '%u'\n", lev_config_name(v_level), s); + } else { + /* we copy the path only if without configuration file */ + if (state->no_conf) + pathcpy(state->parity[v_level].split_map[s].path, sizeof(state->parity[v_level].split_map[s].path), v_path); + + /* set the split info */ + pathcpy(state->parity[v_level].split_map[s].uuid, sizeof(state->parity[v_level].split_map[s].uuid), v_uuid); + state->parity[v_level].split_map[s].size = v_size; + + /* log the info read from the content file */ + log_tag("content:%s:%u:%s:%s:%" PRIi64 "\n", lev_config_name(v_level), s, + state->parity[v_level].split_map[s].path, + state->parity[v_level].split_map[s].uuid, + state->parity[v_level].split_map[s].size); + } + } + } + } else if (c == 'N') { + uint32_t crc_stored; + uint32_t crc_computed; + + /* get the crc before reading it from the file */ + crc_computed = scrc(f); + + ret = sgetble32(f, &crc_stored); + if (ret < 0) { + /* LCOV_EXCL_START */ + /* here don't call decoding_error() because it's too late to get the crc */ + log_fatal("Error reading the CRC in '%s' at offset %" PRIi64 "\n", path, stell(f)); + log_fatal("This content file is damaged! Use an alternate copy.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (crc_stored != crc_computed) { + /* LCOV_EXCL_START */ + /* here don't call decoding_error() because it's too late to get the crc */ + log_fatal("Mismatching CRC in '%s'\n", path); + log_fatal("This content file is damaged! Use an alternate copy.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + crc_checked = 1; + } else { + /* LCOV_EXCL_START */ + decoding_error(path, f); + log_fatal("Invalid command '%c'!\n", (char)c); + os_abort(); + /* LCOV_EXCL_STOP */ + } + } + + tommy_array_done(&disk_mapping); + + if (serror(f)) { + /* LCOV_EXCL_START */ + log_fatal("Error reading the content file '%s' at offset %" PRIi64 "\n", path, stell(f)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (!crc_checked) { + /* LCOV_EXCL_START */ + log_fatal("Finished reading '%s' without finding the CRC\n", path); + log_fatal("This content file is truncated or damaged! Use an alternate copy.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* check the file-system on all disks */ + state_fscheck(state, "after read"); + + /* check that the stored parity size matches the loaded state */ + if (blockmax != parity_allocated_size(state)) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in parity size %u/%u in '%s' at offset %" PRIi64 "\n", blockmax, parity_allocated_size(state), path, stell(f)); + if (state->opt.skip_content_check) { + log_fatal("Overriding.\n"); + blockmax = parity_allocated_size(state); + } else { + exit(EXIT_FAILURE); + } + /* LCOV_EXCL_STOP */ + } + + msg_verbose("%8u files\n", count_file); + msg_verbose("%8u hardlinks\n", count_hardlink); + msg_verbose("%8u symlinks\n", count_symlink); + msg_verbose("%8u empty dirs\n", count_dir); +} + +struct state_write_thread_context { + struct snapraid_state* state; +#if HAVE_MT_WRITE + pthread_t thread; +#endif + /* input */ + block_off_t blockmax; + time_t info_oldest; + int info_has_rehash; + STREAM* f; + /* output */ + uint32_t crc; + unsigned count_file; + unsigned count_hardlink; + unsigned count_symlink; + unsigned count_dir; +}; + +static void* state_write_thread(void* arg) +{ + struct state_write_thread_context* context = arg; + struct snapraid_state* state = context->state; + block_off_t blockmax = context->blockmax; + time_t info_oldest = context->info_oldest; + int info_has_rehash = context->info_has_rehash; + STREAM* f = context->f; + uint32_t crc; + unsigned count_file; + unsigned count_hardlink; + unsigned count_symlink; + unsigned count_dir; + tommy_node* i; + block_off_t idx; + block_off_t begin; + unsigned l, s; + int version; + + count_file = 0; + count_hardlink = 0; + count_symlink = 0; + count_dir = 0; + + /* check what version to use */ + version = 2; + for (l = 0; l < state->level; ++l) { + if (state->parity[l].split_mac > 1) + version = 3; + } + if (BLOCK_HASH_SIZE != 16) + version = 3; + + /* write header */ + if (version == 3) + swrite("SNAPCNT3\n\3\0\0", 12, f); + else + swrite("SNAPCNT2\n\3\0\0", 12, f); + + /* write block size and block max */ + sputc('z', f); + sputb32(state->block_size, f); + sputc('x', f); + sputb32(blockmax, f); + + /* hash size */ + if (version == 3) { + sputc('y', f); + sputb32(BLOCK_HASH_SIZE, f); + } + + if (serror(f)) { + /* LCOV_EXCL_START */ + log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + return context; + /* LCOV_EXCL_STOP */ + } + + sputc('c', f); + if (state->hash == HASH_MURMUR3) { + sputc('u', f); + } else if (state->hash == HASH_SPOOKY2) { + sputc('k', f); + } else { + /* LCOV_EXCL_START */ + log_fatal("Unexpected hash when writing the content file '%s'.\n", serrorfile(f)); + return context; + /* LCOV_EXCL_STOP */ + } + swrite(state->hashseed, HASH_MAX, f); + if (serror(f)) { + /* LCOV_EXCL_START */ + log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + return context; + /* LCOV_EXCL_STOP */ + } + + /* previous hash only present */ + if (state->prevhash != HASH_UNDEFINED) { + /* if at least one rehash tag found, we have to save the previous hash */ + if (info_has_rehash) { + sputc('C', f); + if (state->prevhash == HASH_MURMUR3) { + sputc('u', f); + } else if (state->prevhash == HASH_SPOOKY2) { + sputc('k', f); + } else { + /* LCOV_EXCL_START */ + log_fatal("Unexpected prevhash when writing the content file '%s'.\n", serrorfile(f)); + return context; + /* LCOV_EXCL_STOP */ + } + swrite(state->prevhashseed, HASH_MAX, f); + if (serror(f)) { + /* LCOV_EXCL_START */ + log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + return context; + /* LCOV_EXCL_STOP */ + } + } + } + + /* for each map */ + for (i = state->maplist; i != 0; i = i->next) { + struct snapraid_map* map = i->data; + struct snapraid_disk* disk; + + /* find the disk for this mapping */ + disk = find_disk_by_name(state, map->name); + if (!disk) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name); + return context; + /* LCOV_EXCL_STOP */ + } + + /* save the mapping only if disk is mapped */ + if (disk->mapping_idx != -1) { + sputc('M', f); + sputbs(map->name, f); + sputb32(map->position, f); + sputb32(map->total_blocks, f); + sputb32(map->free_blocks, f); + sputbs(map->uuid, f); + if (serror(f)) { + /* LCOV_EXCL_START */ + log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + return context; + /* LCOV_EXCL_STOP */ + } + } + } + + /* for each parity */ + for (l = 0; l < state->level; ++l) { + if (version == 3) { + sputc('Q', f); + sputb32(l, f); + sputb32(state->parity[l].total_blocks, f); + sputb32(state->parity[l].free_blocks, f); + sputb32(state->parity[l].split_mac, f); + for (s = 0; s < state->parity[l].split_mac; ++s) { + sputbs(state->parity[l].split_map[s].path, f); + sputbs(state->parity[l].split_map[s].uuid, f); + sputb64(state->parity[l].split_map[s].size, f); + } + } else { + sputc('P', f); + sputb32(l, f); + sputb32(state->parity[l].total_blocks, f); + sputb32(state->parity[l].free_blocks, f); + sputbs(state->parity[l].split_map[0].uuid, f); + } + if (serror(f)) { + /* LCOV_EXCL_START */ + log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + return context; + /* LCOV_EXCL_STOP */ + } + } + + /* for each disk */ + for (i = state->disklist; i != 0; i = i->next) { + tommy_node* j; + struct snapraid_disk* disk = i->data; + + /* if the disk is not mapped, skip it */ + if (disk->mapping_idx < 0) + continue; + + /* for each file */ + for (j = disk->filelist; j != 0; j = j->next) { + struct snapraid_file* file = j->data; + uint64_t size; + uint64_t mtime_sec; + int32_t mtime_nsec; + uint64_t inode; + + size = file->size; + mtime_sec = file->mtime_sec; + mtime_nsec = file->mtime_nsec; + inode = file->inode; + + sputc('f', f); + sputb32(disk->mapping_idx, f); + sputb64(size, f); + sputb64(mtime_sec, f); + /* encode STAT_NSEC_INVALID as 0 */ + if (mtime_nsec == STAT_NSEC_INVALID) + sputb32(0, f); + else + sputb32(mtime_nsec + 1, f); + sputb64(inode, f); + sputbs(file->sub, f); + if (serror(f)) { + /* LCOV_EXCL_START */ + log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + return context; + /* LCOV_EXCL_STOP */ + } + + /* for all the blocks of the file */ + begin = 0; + while (begin < file->blockmax) { + unsigned v_state = block_state_get(fs_file2block_get(file, begin)); + block_off_t v_pos = fs_file2par_get(disk, file, begin); + uint32_t v_count; + + block_off_t end; + + /* find the end of run of blocks */ + end = begin + 1; + while (end < file->blockmax) { + if (v_state != block_state_get(fs_file2block_get(file, end))) + break; + if (v_pos + (end - begin) != fs_file2par_get(disk, file, end)) + break; + ++end; + } + + switch (v_state) { + case BLOCK_STATE_BLK : + sputc('b', f); + break; + case BLOCK_STATE_CHG : + sputc('g', f); + break; + case BLOCK_STATE_REP : + sputc('p', f); + break; + default : + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in state for block %u state %u\n", v_pos, v_state); + return context; + /* LCOV_EXCL_STOP */ + } + + sputb32(v_pos, f); + + v_count = end - begin; + sputb32(v_count, f); + + /* write hashes */ + for (idx = begin; idx < end; ++idx) { + struct snapraid_block* block = fs_file2block_get(file, idx); + + swrite(block->hash, BLOCK_HASH_SIZE, f); + } + + if (serror(f)) { + /* LCOV_EXCL_START */ + log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + return context; + /* LCOV_EXCL_STOP */ + } + + /* next begin position */ + begin = end; + } + + ++count_file; + } + + /* for each link */ + for (j = disk->linklist; j != 0; j = j->next) { + struct snapraid_link* slink = j->data; + + switch (link_flag_get(slink, FILE_IS_LINK_MASK)) { + case FILE_IS_HARDLINK : + sputc('a', f); + ++count_hardlink; + break; + case FILE_IS_SYMLINK : + sputc('s', f); + ++count_symlink; + break; + } + + sputb32(disk->mapping_idx, f); + sputbs(slink->sub, f); + sputbs(slink->linkto, f); + if (serror(f)) { + /* LCOV_EXCL_START */ + log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + return context; + /* LCOV_EXCL_STOP */ + } + } + + /* for each dir */ + for (j = disk->dirlist; j != 0; j = j->next) { + struct snapraid_dir* dir = j->data; + + sputc('r', f); + sputb32(disk->mapping_idx, f); + sputbs(dir->sub, f); + if (serror(f)) { + /* LCOV_EXCL_START */ + log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + return context; + /* LCOV_EXCL_STOP */ + } + + ++count_dir; + } + + /* deleted blocks of the disk */ + sputc('h', f); + sputb32(disk->mapping_idx, f); + if (serror(f)) { + /* LCOV_EXCL_START */ + log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + return context; + /* LCOV_EXCL_STOP */ + } + begin = 0; + while (begin < blockmax) { + int is_deleted; + block_off_t end; + + is_deleted = fs_is_block_deleted(disk, begin); + + /* find the end of run of blocks */ + end = begin + 1; + while (end < blockmax + && is_deleted == fs_is_block_deleted(disk, end) + ) { + ++end; + } + + sputb32(end - begin, f); + + if (is_deleted) { + /* write the run of deleted blocks with hash */ + sputc('o', f); + + /* write all the hash */ + while (begin < end) { + struct snapraid_block* block = fs_par2block_get(disk, begin); + + swrite(block->hash, BLOCK_HASH_SIZE, f); + + ++begin; + } + } else { + /* write the run of blocks without hash */ + /* they can be either used or empty blocks */ + sputc('O', f); + + /* next begin position */ + begin = end; + } + + if (serror(f)) { + /* LCOV_EXCL_START */ + log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + return context; + /* LCOV_EXCL_STOP */ + } + } + } + + /* write the info for each block */ + sputc('i', f); + sputb32(info_oldest, f); + begin = 0; + while (begin < blockmax) { + snapraid_info info; + block_off_t end; + time_t t; + unsigned flag; + + info = info_get(&state->infoarr, begin); + + /* find the end of run of blocks */ + end = begin + 1; + while (end < blockmax + && info == info_get(&state->infoarr, end) + ) { + ++end; + } + + sputb32(end - begin, f); + + /* if there is info */ + if (info) { + /* other flags */ + flag = 1; /* info is present */ + if (info_get_bad(info)) + flag |= 2; + if (info_get_rehash(info)) + flag |= 4; + if (info_get_justsynced(info)) + flag |= 8; + sputb32(flag, f); + + t = info_get_time(info) - info_oldest; + sputb32(t, f); + } else { + /* write a special 0 flag to mark missing info */ + sputb32(0, f); + } + + if (serror(f)) { + /* LCOV_EXCL_START */ + log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + return context; + /* LCOV_EXCL_STOP */ + } + + /* next begin position */ + begin = end; + } + + sputc('N', f); + + /* flush data written to the disk */ + if (sflush(f)) { + /* LCOV_EXCL_START */ + log_fatal("Error writing the content file '%s' (in flush before crc). %s.\n", serrorfile(f), strerror(errno)); + return context; + /* LCOV_EXCL_STOP */ + } + + /* get the file crc */ + crc = scrc(f); + + /* compare the crc of the data written to file */ + /* with the one of the data written to the stream */ + if (crc != scrc_stream(f)) { + /* LCOV_EXCL_START */ + log_fatal("CRC mismatch writing the content stream.\n"); + log_fatal("DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n"); + log_fatal("Try running a memory test like http://www.memtest86.com/\n"); + return context; + /* LCOV_EXCL_STOP */ + } + + sputble32(crc, f); + if (serror(f)) { + /* LCOV_EXCL_START */ + log_fatal("Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + return context; + /* LCOV_EXCL_STOP */ + } + + /* set output variables */ + context->crc = crc; + context->count_file = count_file; + context->count_hardlink = count_hardlink; + context->count_symlink = count_symlink; + context->count_dir = count_dir; + + return 0; +} + +static void state_write_content(struct snapraid_state* state, uint32_t* out_crc) +{ +#if HAVE_MT_WRITE + int fail; + int first; +#else + STREAM* f; + unsigned count_content; + unsigned k; + struct state_write_thread_context* context; + void* retval; +#endif + tommy_node* i; + block_off_t blockmax; + time_t info_oldest; + int info_has_rehash; + int mapping_idx; + block_off_t idx; + uint32_t crc; + unsigned count_file; + unsigned count_hardlink; + unsigned count_symlink; + unsigned count_dir; + + /* blocks of all array */ + blockmax = parity_allocated_size(state); + + /* check the file-system on all disks */ + state_fscheck(state, "before write"); + + /* clear the info for unused blocks */ + /* and get some other info */ + info_oldest = 0; /* oldest time in info */ + info_has_rehash = 0; /* if there is a rehash info */ + for (idx = 0; idx < blockmax; ++idx) { + /* if the position is used */ + if (fs_position_is_required(state, idx)) { + snapraid_info info = info_get(&state->infoarr, idx); + + /* only if there is some info to store */ + if (info) { + time_t info_time = info_get_time(info); + + if (!info_oldest || info_time < info_oldest) + info_oldest = info_time; + + if (info_get_rehash(info)) + info_has_rehash = 1; + } + } else { + /* clear any previous info */ + info_set(&state->infoarr, idx, 0); + + /* and clear any deleted blocks */ + fs_position_clear_deleted(state, idx); + } + } + + /* map disks */ + mapping_idx = 0; + for (i = state->maplist; i != 0; i = i->next) { + struct snapraid_map* map = i->data; + struct snapraid_disk* disk; + + /* find the disk for this mapping */ + disk = find_disk_by_name(state, map->name); + if (!disk) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency for unmapped disk '%s'\n", map->name); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + /* save the mapping only for not empty disks */ + if (!fs_is_empty(disk, blockmax)) { + /* assign the mapping index used to identify disks */ + disk->mapping_idx = mapping_idx; + ++mapping_idx; + } else { + /* mark the disk as without mapping */ + disk->mapping_idx = -1; + } + } + +#if HAVE_MT_WRITE + /* start all writing threads */ + i = tommy_list_head(&state->contentlist); + while (i) { + struct snapraid_content* content = i->data; + struct state_write_thread_context* context; + char tmp[PATH_MAX]; + STREAM* f; + + msg_progress("Saving state to %s...\n", content->content); + + pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); + f = sopen_write(tmp); + if (f == 0) { + /* LCOV_EXCL_START */ + log_fatal("Error opening the content file '%s'. %s.\n", tmp, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* allocate the thread context */ + context = malloc_nofail(sizeof(struct state_write_thread_context)); + content->context = context; + + /* initialize */ + context->state = state; + context->blockmax = blockmax; + context->info_oldest = info_oldest; + context->info_has_rehash = info_has_rehash; + context->f = f; + + thread_create(&context->thread, 0, state_write_thread, context); + + i = i->next; + } + + /* join all thread */ + fail = 0; + first = 1; + crc = 0; + count_file = 0; + count_hardlink = 0; + count_symlink = 0; + count_dir = 0; + i = tommy_list_head(&state->contentlist); + while (i) { + struct snapraid_content* content = i->data; + struct state_write_thread_context* context = content->context; + void* retval; + + thread_join(context->thread, &retval); + + if (retval) { + /* LCOV_EXCL_START */ + fail = 1; + /* LCOV_EXCL_STOP */ + } else { + STREAM* f = context->f; + + /* Use the sequence fflush() -> fsync() -> fclose() -> rename() to ensure */ + /* than even in a system crash event we have one valid copy of the file. */ + if (sflush(f) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error writing the content file '%s', in flush(). %s.\n", serrorfile(f), strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + +#if HAVE_FSYNC + if (ssync(f) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error writing the content file '%s' in sync(). %s.\n", serrorfile(f), strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } +#endif + + if (sclose(f) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error closing the content file. %s.\n", strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (first) { + first = 0; + crc = context->crc; + count_file = context->count_file; + count_hardlink = context->count_hardlink; + count_symlink = context->count_symlink; + count_dir = context->count_dir; + } else { + if (crc != context->crc) { + /* LCOV_EXCL_START */ + log_fatal("Different CRCs writing content streams.\n"); + log_fatal("DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n"); + log_fatal("Try running a memory test like http://www.memtest86.com/\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + } + + free(context); + + i = i->next; + } + + /* abort on failure */ + if (fail) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } +#else + /* count the content files */ + count_content = 0; + i = tommy_list_head(&state->contentlist); + while (i) { + struct snapraid_content* content = i->data; + msg_progress("Saving state to %s...\n", content->content); + ++count_content; + i = i->next; + } + + /* open all the content files */ + f = sopen_multi_write(count_content); + if (!f) { + /* LCOV_EXCL_START */ + log_fatal("Error opening the content files.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + k = 0; + i = tommy_list_head(&state->contentlist); + while (i) { + struct snapraid_content* content = i->data; + char tmp[PATH_MAX]; + pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); + if (sopen_multi_file(f, k, tmp) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error opening the content file '%s'. %s.\n", tmp, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + ++k; + i = i->next; + } + + /* allocate the thread context */ + context = malloc_nofail(sizeof(struct state_write_thread_context)); + + /* initialize */ + context->state = state; + context->blockmax = blockmax; + context->info_oldest = info_oldest; + context->info_has_rehash = info_has_rehash; + context->f = f; + + retval = state_write_thread(context); + + /* abort on failure */ + if (retval) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* Use the sequence fflush() -> fsync() -> fclose() -> rename() to ensure */ + /* than even in a system crash event we have one valid copy of the file. */ + if (sflush(f) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error writing the content file '%s', in flush(). %s.\n", serrorfile(f), strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + +#if HAVE_FSYNC + if (ssync(f) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error writing the content file '%s' in sync(). %s.\n", serrorfile(f), strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } +#endif + + if (sclose(f) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error closing the content file. %s.\n", strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + crc = context->crc; + count_file = context->count_file; + count_hardlink = context->count_hardlink; + count_symlink = context->count_symlink; + count_dir = context->count_dir; + + free(context); +#endif + + msg_verbose("%8u files\n", count_file); + msg_verbose("%8u hardlinks\n", count_hardlink); + msg_verbose("%8u symlinks\n", count_symlink); + msg_verbose("%8u empty dirs\n", count_dir); + + *out_crc = crc; +} + +void state_read(struct snapraid_state* state) +{ + STREAM* f; + char path[PATH_MAX]; + struct stat st; + tommy_node* node; + int ret; + int c; + + /* iterate over all the available content files and load the first one present */ + f = 0; + node = tommy_list_head(&state->contentlist); + while (node) { + struct snapraid_content* content = node->data; + pathcpy(path, sizeof(path), content->content); + + if (!state->no_conf) { + log_tag("content:%s\n", path); + log_flush(); + } + msg_progress("Loading state from %s...\n", path); + + f = sopen_read(path); + if (f != 0) { + /* if opened stop the search */ + break; + } else { + /* if it's real error of an existing file, abort */ + if (errno != ENOENT) { + /* LCOV_EXCL_START */ + log_fatal("Error opening the content file '%s'. %s.\n", path, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* otherwise continue */ + if (node->next) { + log_fatal("WARNING! Content file '%s' not found, trying with another copy...\n", path); + + /* ensure to rewrite all the content files */ + state->need_write = 1; + } + } + + /* next content file */ + node = node->next; + } + + /* if not found, assume empty */ + if (!f) { + log_fatal("No content file found. Assuming empty.\n"); + + /* create the initial mapping */ + state_map(state); + return; + } + + /* get the stat of the content file */ + ret = fstat(shandle(f), &st); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error stating the content file '%s'. %s.\n", path, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* go further to check other content files */ + while (node) { + char other_path[PATH_MAX]; + struct stat other_st; + struct snapraid_content* content = node->data; + pathcpy(other_path, sizeof(other_path), content->content); + + ret = stat(other_path, &other_st); + if (ret != 0) { + /* allow missing content files, but not any other kind of error */ + if (errno != ENOENT) { + /* LCOV_EXCL_START */ + log_fatal("Error stating the content file '%s'. %s.\n", other_path, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* ensure to rewrite all the content files */ + state->need_write = 1; + } else { + /* if the size is different */ + if (other_st.st_size != st.st_size) { + log_fatal("WARNING! Content files '%s' and '%s' have a different size!\n", path, other_path); + log_fatal("Likely one of the two is broken!\n"); + + /* ensure to rewrite all the content files */ + state->need_write = 1; + } + } + + /* next content file */ + node = node->next; + } + + /* start with a undefined default. */ + /* it's for compatibility with version 1.0 where MD5 was implicit. */ + state->hash = HASH_UNDEFINED; + + /* start with a zero seed, it was the default in old versions */ + memset(state->hashseed, 0, HASH_MAX); + + /* previous hash, start with an undefined value */ + state->prevhash = HASH_UNDEFINED; + + /* intentionally not set the prevhashseed, if used valgrind will warn about it */ + + /* get the first char to detect the file type */ + c = sgetc(f); + sungetc(c, f); + + /* guess the file type from the first char */ + if (c == 'S') { + state_read_content(state, path, f); + } else { + /* LCOV_EXCL_START */ + log_fatal("From SnapRAID v9.0 the text content file is not supported anymore.\n"); + log_fatal("You have first to upgrade to SnapRAID v8.1 to convert it to binary format.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + sclose(f); + + if (state->hash == HASH_UNDEFINED) { + /* LCOV_EXCL_START */ + log_fatal("The checksum to use is not specified.\n"); + log_fatal("This happens because you are likely upgrading from SnapRAID 1.0.\n"); + log_fatal("To use a new SnapRAID you must restart from scratch,\n"); + log_fatal("deleting all the content and parity files.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* update the mapping */ + state_map(state); + + state_content_check(state, path); + + /* mark that we read the content file, and it passed all the checks */ + state->checked_read = 1; +} + +struct state_verify_thread_context { + struct snapraid_state* state; + struct snapraid_content* content; +#if HAVE_MT_VERIFY + pthread_t thread; +#else + void* retval; +#endif + /* input */ + uint32_t crc; + STREAM* f; +}; + +static void* state_verify_thread(void* arg) +{ + struct state_verify_thread_context* context = arg; + STREAM* f = context->f; + unsigned char buf[4]; + uint32_t crc_stored; + uint32_t crc_computed; + + if (sdeplete(f, buf) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error flushing the content file '%s'. %s.\n", serrorfile(f), strerror(errno)); + return context; + /* LCOV_EXCL_STOP */ + } + + /* get the stored crc from the last four bytes */ + crc_stored = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24; + + if (crc_stored != context->crc) { + /* LCOV_EXCL_START */ + log_fatal("DANGER! Wrong stored CRC in '%s'\n", serrorfile(f)); + return context; + /* LCOV_EXCL_STOP */ + } + + /* get the computed crc */ + crc_computed = scrc(f); + + /* adjust the stored crc to include itself */ + crc_stored = crc32c(crc_stored, buf, 4); + + if (crc_computed != crc_stored) { + /* LCOV_EXCL_START */ + log_fatal("DANGER! Wrong file CRC in '%s'\n", serrorfile(f)); + return context; + /* LCOV_EXCL_STOP */ + } + + return 0; +} + +static void state_verify_content(struct snapraid_state* state, uint32_t crc) +{ + tommy_node* i; + int fail; + + /* start all reading threads */ + i = tommy_list_head(&state->contentlist); + while (i) { + struct snapraid_content* content = i->data; + struct state_verify_thread_context* context; + char tmp[PATH_MAX]; + STREAM* f; + + msg_progress("Verifying %s...\n", content->content); + + pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); + + f = sopen_read(tmp); + if (f == 0) { + /* LCOV_EXCL_START */ + log_fatal("Error reopening the content file '%s'. %s.\n", tmp, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* allocate the thread context */ + context = malloc_nofail(sizeof(struct state_verify_thread_context)); + content->context = context; + + /* initialize */ + context->state = state; + context->content = content; + context->crc = crc; + context->f = f; + +#if HAVE_MT_VERIFY + thread_create(&context->thread, 0, state_verify_thread, context); +#else + context->retval = state_verify_thread(context); +#endif + + i = i->next; + } + + /* join all thread */ + fail = 0; + i = tommy_list_head(&state->contentlist); + while (i) { + struct snapraid_content* content = i->data; + struct state_verify_thread_context* context = content->context; + void* retval; + +#if HAVE_MT_VERIFY + thread_join(context->thread, &retval); +#else + retval = context->retval; +#endif + if (retval) { + /* LCOV_EXCL_START */ + fail = 1; + /* LCOV_EXCL_STOP */ + } else { + STREAM* f = context->f; + + if (sclose(f) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error closing the content file. %s.\n", strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + free(context); + + i = i->next; + } + + /* abort on failure */ + if (fail) { + /* LCOV_EXCL_START */ + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } +} + +static void state_rename_content(struct snapraid_state* state) +{ + tommy_node* i; + + i = tommy_list_head(&state->contentlist); + while (i) { + struct snapraid_content* content = i->data; + char tmp[PATH_MAX]; + + /* now renames the just written copy with the correct name */ + pathprint(tmp, sizeof(tmp), "%s.tmp", content->content); + if (rename(tmp, content->content) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error renaming the content file '%s' to '%s' in rename(). %s.\n", tmp, content->content, strerror(errno)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + i = i->next; + } +} + +void state_write(struct snapraid_state* state) +{ + uint32_t crc; + + /* write all the content files */ + state_write_content(state, &crc); + + /* verify the just written files */ + state_verify_content(state, crc); + + /* rename the new files, over the old ones */ + state_rename_content(state); + + state->need_write = 0; /* no write needed anymore */ + state->checked_read = 0; /* what we wrote is not checked in read */ +} + +void state_skip(struct snapraid_state* state) +{ + tommy_node* i; + + /* for each disk */ + for (i = state->disklist; i != 0; i = i->next) { + tommy_node* j; + struct snapraid_disk* disk = i->data; + + if (!disk->skip_access) + continue; + + /* for each file */ + for (j = tommy_list_head(&disk->filelist); j != 0; j = j->next) { + struct snapraid_file* file = j->data; + file_flag_set(file, FILE_IS_EXCLUDED); + } + + /* for each link */ + for (j = tommy_list_head(&disk->linklist); j != 0; j = j->next) { + struct snapraid_link* slink = j->data; + link_flag_set(slink, FILE_IS_EXCLUDED); + } + + /* for each dir */ + for (j = tommy_list_head(&disk->dirlist); j != 0; j = j->next) { + struct snapraid_dir* dir = j->data; + dir_flag_set(dir, FILE_IS_EXCLUDED); + } + } +} + +void state_filter(struct snapraid_state* state, tommy_list* filterlist_file, tommy_list* filterlist_disk, int filter_missing, int filter_error) +{ + tommy_node* i; + unsigned l; + + /* if no filter, include all */ + if (!filter_missing && !filter_error && tommy_list_empty(filterlist_file) && tommy_list_empty(filterlist_disk)) + return; + + msg_progress("Filtering...\n"); + + for (i = tommy_list_head(filterlist_disk); i != 0; i = i->next) { + struct snapraid_filter* filter = i->data; + msg_verbose("\t%s%s\n", filter->pattern, filter->is_disk ? "//" : ""); + } + for (i = tommy_list_head(filterlist_file); i != 0; i = i->next) { + struct snapraid_filter* filter = i->data; + msg_verbose("\t%s%s\n", filter->pattern, filter->is_dir ? "/" : ""); + } + if (filter_missing) + msg_verbose("\t\n"); + if (filter_error) + msg_verbose("\t\n"); + + /* for each disk */ + for (i = state->disklist; i != 0; i = i->next) { + tommy_node* j; + struct snapraid_disk* disk = i->data; + + /* if we filter for presence, we have to access the disk, so better to print something */ + if (filter_missing) + msg_progress("Scanning disk %s...\n", disk->name); + + /* for each file */ + for (j = tommy_list_head(&disk->filelist); j != 0; j = j->next) { + struct snapraid_file* file = j->data; + + if (filter_path(filterlist_disk, 0, disk->name, file->sub) != 0 + || filter_path(filterlist_file, 0, disk->name, file->sub) != 0 + || filter_existence(filter_missing, disk->dir, file->sub) != 0 + || filter_correctness(filter_error, &state->infoarr, disk, file) != 0 + ) { + file_flag_set(file, FILE_IS_EXCLUDED); + } + } + + /* for each link */ + for (j = tommy_list_head(&disk->linklist); j != 0; j = j->next) { + struct snapraid_link* slink = j->data; + + if (filter_path(filterlist_disk, 0, disk->name, slink->sub) != 0 + || filter_path(filterlist_file, 0, disk->name, slink->sub) != 0 + || filter_existence(filter_missing, disk->dir, slink->sub) != 0 + ) { + link_flag_set(slink, FILE_IS_EXCLUDED); + } + } + + /* for each empty dir */ + for (j = tommy_list_head(&disk->dirlist); j != 0; j = j->next) { + struct snapraid_dir* dir = j->data; + + if (filter_emptydir(filterlist_disk, 0, disk->name, dir->sub) != 0 + || filter_emptydir(filterlist_file, 0, disk->name, dir->sub) != 0 + || filter_existence(filter_missing, disk->dir, dir->sub) != 0 + ) { + dir_flag_set(dir, FILE_IS_EXCLUDED); + } + } + } + + /* if we are filtering by disk, exclude any parity not explicitely included */ + if (!tommy_list_empty(filterlist_disk)) { + /* for each parity disk */ + for (l = 0; l < state->level; ++l) { + /* check if the parity is excluded by name */ + if (filter_path(filterlist_disk, 0, lev_config_name(l), 0) != 0) { + /* excluded the parity from further operation */ + state->parity[l].is_excluded_by_filter = 1; + } + } + } else { + /* if we are filtering by file, exclude all parity */ + if (filter_missing || !tommy_list_empty(filterlist_file)) { + /* for each parity disk */ + for (l = 0; l < state->level; ++l) { + state->parity[l].is_excluded_by_filter = 1; + } + } + } +} + +int state_progress_begin(struct snapraid_state* state, block_off_t blockstart, block_off_t blockmax, block_off_t countmax) +{ + time_t now; + + if (state->opt.gui) { + log_tag("run:begin:%u:%u:%u\n", blockstart, blockmax, countmax); + log_flush(); + } + + now = time(0); + + state->progress_whole_start = now; + + state->progress_tick = 0; + state->progress_ptr = 0; + state->progress_wasted = 0; + + /* stop if requested */ + if (global_interrupt) { + /* LCOV_EXCL_START */ + if (!state->opt.gui) { + msg_status("Not starting for interruption\n"); + } + log_tag("sigint:0: SIGINT received\n"); + log_flush(); + return 0; + /* LCOV_EXCL_STOP */ + } + + return 1; +} + +void state_progress_end(struct snapraid_state* state, block_off_t countpos, block_off_t countmax, data_off_t countsize) +{ + if (state->opt.gui) { + log_tag("run:end\n"); + log_flush(); + } else if (countmax == 0) { + msg_status("Nothing to do\n"); + } else { + time_t now; + time_t elapsed; + + unsigned countsize_MB = (countsize + MEGA - 1) / MEGA; + + now = time(0); + + elapsed = now - state->progress_whole_start - state->progress_wasted; + + msg_bar("%u%% completed, %u MB accessed", countpos * 100 / countmax, countsize_MB); + + msg_bar(" in %u:%02u", (unsigned)(elapsed / 3600), (unsigned)((elapsed % 3600) / 60)); + + /* some extra spaces to ensure to overwrite the latest status line */ + msg_bar(" "); + + msg_bar("\n"); + msg_flush(); + } +} + +void state_progress_stop(struct snapraid_state* state) +{ + time_t now; + + now = time(0); + + if (!state->opt.gui) { + msg_bar("\n"); + msg_flush(); + } + + state->progress_interruption = now; +} + +void state_progress_restart(struct snapraid_state* state) +{ + time_t now; + + now = time(0); + + /* reset the progress counter */ + state->progress_tick = 0; + state->progress_ptr = 0; + + if (now >= state->progress_interruption) /* avoid degenerated cases when the clock is manually adjusted */ + state->progress_wasted += now - state->progress_interruption; +} + +#define PROGRESS_CLEAR " " + +/** + * Set the latest tick data in the progress vector. + */ +static void state_progress_latest(struct snapraid_state* state) +{ + tommy_node* i; + unsigned l; + + state->progress_tick_misc[state->progress_ptr] = state->tick_misc; + state->progress_tick_sched[state->progress_ptr] = state->tick_sched; + state->progress_tick_raid[state->progress_ptr] = state->tick_raid; + state->progress_tick_hash[state->progress_ptr] = state->tick_hash; + state->progress_tick_io[state->progress_ptr] = state->tick_io; + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* disk = i->data; + disk->progress_tick[state->progress_ptr] = disk->tick; + } + for (l = 0; l < state->level; ++l) + state->parity[l].progress_tick[state->progress_ptr] = state->parity[l].tick; +} + +/** + * Number of columns + */ +#define GRAPH_COLUMN 68 + +/** + * Get the reference value, 0 if index is PROGRESS_MAX + */ +#define ref(map, index) (index < PROGRESS_MAX ? map[index] : 0) + +static void state_progress_graph(struct snapraid_state* state, struct snapraid_io* io, unsigned current, unsigned oldest) +{ + uint64_t v; + uint64_t tick_total; + unsigned bar; + tommy_node* i; + unsigned l; + size_t pad; + + tick_total = 0; + + tick_total += state->progress_tick_misc[current] - ref(state->progress_tick_misc, oldest); + tick_total += state->progress_tick_sched[current] - ref(state->progress_tick_sched, oldest); + tick_total += state->progress_tick_raid[current] - ref(state->progress_tick_raid, oldest); + tick_total += state->progress_tick_hash[current] - ref(state->progress_tick_hash, oldest); + tick_total += state->progress_tick_io[current] - ref(state->progress_tick_io, oldest); + if (!tick_total) + return; + + pad = 4; + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* disk = i->data; + size_t len = strlen(disk->name); + if (pad < len) + pad = len; + } + for (l = 0; l < state->level; ++l) { + size_t len = strlen(lev_config_name(l)); + if (pad < len) + pad = len; + } + + /* extra space */ + pad += 1; + + if (pad + 30 < GRAPH_COLUMN) + bar = GRAPH_COLUMN - pad; + else + bar = 30; + + if (io) { + const char* legend = "cached blocks (instant, more is better)"; + + /* refresh the cached blocks info */ + io_refresh(io); + + printf("\n"); + + /* search for the slowest */ + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* disk = i->data; + v = disk->cached_blocks; + printr(disk->name, pad); + printf("%4" PRIu64 " | ", v); + + if (disk->progress_file && disk->progress_file->sub) + printf("%s", disk->progress_file->sub); + else + printf("-"); + + printf("\n"); + } + + for (l = 0; l < state->level; ++l) { + v = state->parity[l].cached_blocks; + printr(lev_config_name(l), pad); + printf("%4" PRIu64 " | ", v); + printc('o', v * bar / io->io_max); + printf("\n"); + } + + printc(' ', pad); + printf(" |_"); + printc('_', bar); + printf("\n"); + + printc(' ', 5 + pad + 1 + bar / 2 - strlen(legend) / 2); + printf("%s", legend); + printf("\n"); + } + + printf("\n"); + + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* disk = i->data; + v = disk->progress_tick[current] - ref(disk->progress_tick, oldest); + printr(disk->name, pad); + printf("%3" PRIu64 "%% | ", v * 100 / tick_total); + printc('*', v * bar / tick_total); + printf("\n"); + + /* clear the file in progress */ + disk->progress_file = 0; + } + + for (l = 0; l < state->level; ++l) { + v = state->parity[l].progress_tick[current] - ref(state->parity[l].progress_tick, oldest); + printr(lev_config_name(l), pad); + printf("%3" PRIu64 "%% | ", v * 100 / tick_total); + printc('*', v * bar / tick_total); + printf("\n"); + } + + v = state->progress_tick_raid[current] - ref(state->progress_tick_raid, oldest); + printr("raid", pad); + printf("%3" PRIu64 "%% | ", v * 100 / tick_total); + printc('*', v * bar / tick_total); + printf("\n"); + + v = state->progress_tick_hash[current] - ref(state->progress_tick_hash, oldest); + printr("hash", pad); + printf("%3" PRIu64 "%% | ", v * 100 / tick_total); + printc('*', v * bar / tick_total); + printf("\n"); + + v = state->progress_tick_sched[current] - ref(state->progress_tick_sched, oldest); + printr("sched", pad); + printf("%3" PRIu64 "%% | ", v * 100 / tick_total); + printc('*', v * bar / tick_total); + printf("\n"); + + v = state->progress_tick_misc[current] - ref(state->progress_tick_misc, oldest); + printr("misc", pad); + printf("%3" PRIu64 "%% | ", v * 100 / tick_total); + printc('*', v * bar / tick_total); + printf("\n"); + + printc(' ', pad); + printf(" |_"); + printc('_', bar); + printf("\n"); + + if (oldest == PROGRESS_MAX) { + const char* legend = "wait time (total, less is better)"; + printc(' ', 5 + pad + 1 + bar / 2 - strlen(legend) / 2); + printf("%s", legend); + printf("\n"); + } else { + const char* legend_d = "wait time (last %d secs, less is better)"; + printc(' ', 5 + pad + 1 + bar / 2 - strlen(legend_d) / 2); + printf(legend_d, PROGRESS_MAX); + printf("\n"); + } + + printf("\n"); +} + +int state_progress(struct snapraid_state* state, struct snapraid_io* io, block_off_t blockpos, block_off_t countpos, block_off_t countmax, data_off_t countsize) +{ + time_t now; + int pred; + + now = time(0); + + /* previous position */ + pred = state->progress_ptr + PROGRESS_MAX - 1; + if (pred >= PROGRESS_MAX) + pred -= PROGRESS_MAX; + + /* if the previous measure is different */ + if (state->progress_tick == 0 + || state->progress_time[pred] != now + ) { + time_t elapsed; + unsigned out_perc = 0; + unsigned out_speed = 0; + unsigned out_cpu = 0; + unsigned out_eta = 0; + int out_computed = 0; + + /* store the new measure */ + state->progress_time[state->progress_ptr] = now; + state->progress_pos[state->progress_ptr] = countpos; + state->progress_size[state->progress_ptr] = countsize; + state_progress_latest(state); + + elapsed = now - state->progress_whole_start - state->progress_wasted; + + /* completion percentage */ + if (countmax) + out_perc = countpos * 100 / countmax; + + /* if we have at least 5 measures */ + if (state->progress_tick >= 5 + /* or if we are running in test mode, with at least one measure */ + || (state->opt.force_progress && state->progress_tick >= 1) + ) { + int oldest; + int past; + time_t delta_time; + block_off_t delta_pos; + data_off_t delta_size; + uint64_t tick_cpu; + uint64_t tick_total; + uint64_t delta_tick_cpu; + uint64_t delta_tick_total; + uint64_t oldest_tick_cpu; + uint64_t oldest_tick_total; + + /* number of past measures */ + past = state->progress_tick; + + /* drop the oldest ones, to promptly */ + /* skip the startup phase */ + past -= past / 5; + + /* check how much we can go in the past */ + if (past >= PROGRESS_MAX - 1) { + /* the vector is filled, so we are already in position */ + /* to get the possible oldest one */ + oldest = state->progress_ptr + 1; + } else { + /* go backward the number of positions selected */ + oldest = state->progress_ptr + PROGRESS_MAX - past; + } + if (oldest >= PROGRESS_MAX) + oldest -= PROGRESS_MAX; + + tick_cpu = state->progress_tick_misc[state->progress_ptr] + + state->progress_tick_sched[state->progress_ptr] + + state->progress_tick_raid[state->progress_ptr] + + state->progress_tick_hash[state->progress_ptr]; + tick_total = tick_cpu + state->progress_tick_io[state->progress_ptr]; + + oldest_tick_cpu = state->progress_tick_misc[oldest] + + state->progress_tick_sched[oldest] + + state->progress_tick_raid[oldest] + + state->progress_tick_hash[oldest]; + oldest_tick_total = oldest_tick_cpu + state->progress_tick_io[oldest]; + + delta_time = now - state->progress_time[oldest]; + delta_pos = countpos - state->progress_pos[oldest]; + delta_size = countsize - state->progress_size[oldest]; + delta_tick_cpu = tick_cpu - oldest_tick_cpu; + delta_tick_total = tick_total - oldest_tick_total; + + /* estimate the speed in MB/s */ + if (delta_time != 0) + out_speed = (unsigned)(delta_size / MEGA / delta_time); + + /* estimate the cpu usage percentage */ + if (delta_tick_total != 0) + out_cpu = (unsigned)(delta_tick_cpu * 100U / delta_tick_total); + + /* estimate the remaining time in minutes */ + if (delta_pos != 0) + out_eta = (countmax - countpos) * delta_time / (60 * delta_pos); + + if (state->opt.force_stats) { + os_clear(); + state_progress_graph(state, io, state->progress_ptr, oldest); + } + + /* we have the output value */ + out_computed = 1; + } + + if (state->opt.gui) { + log_tag("run:pos:%u:%u:%" PRIu64 ":%u:%u:%u:%u:%" PRIu64 "\n", blockpos, countpos, countsize, out_perc, out_eta, out_speed, out_cpu, (uint64_t)elapsed); + log_flush(); + } else { + msg_bar("%u%%, %u MB", out_perc, (unsigned)(countsize / MEGA)); + if (out_computed) { + msg_bar(", %u MB/s", out_speed); + msg_bar(", CPU %u%%", out_cpu); + msg_bar(", %u:%02u ETA", out_eta / 60, out_eta % 60); + } + msg_bar("%s\r", PROGRESS_CLEAR); + msg_flush(); + } + + /* next position to fill */ + ++state->progress_ptr; + if (state->progress_ptr >= PROGRESS_MAX) + state->progress_ptr -= PROGRESS_MAX; + + /* one more measure */ + ++state->progress_tick; + } + + /* stop if requested */ + if (global_interrupt) { + /* LCOV_EXCL_START */ + if (!state->opt.gui) { + log_fatal("\n"); + log_fatal("Stopping for interruption at block %u\n", blockpos); + } + log_tag("sigint:%u: SIGINT received\n", blockpos); + log_flush(); + return 1; + /* LCOV_EXCL_STOP */ + } + + return 0; +} + +void state_usage_waste(struct snapraid_state* state) +{ + uint64_t now = tick(); + + state->tick_last = now; +} + +void state_usage_misc(struct snapraid_state* state) +{ + uint64_t now = tick(); + uint64_t delta = now - state->tick_last; + + /* increment the time spent in computations */ + state->tick_misc += delta; + + state->tick_last = now; +} + +void state_usage_sched(struct snapraid_state* state) +{ + uint64_t now = tick(); + uint64_t delta = now - state->tick_last; + + /* increment the time spent in computations */ + state->tick_sched += delta; + + state->tick_last = now; +} + +void state_usage_raid(struct snapraid_state* state) +{ + uint64_t now = tick(); + uint64_t delta = now - state->tick_last; + + /* increment the time spent in computations */ + state->tick_raid += delta; + + state->tick_last = now; +} + +void state_usage_hash(struct snapraid_state* state) +{ + uint64_t now = tick(); + uint64_t delta = now - state->tick_last; + + /* increment the time spent in computations */ + state->tick_hash += delta; + + state->tick_last = now; +} + +void state_usage_file(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file) +{ + (void)state; + + disk->progress_file = file; +} + +void state_usage_disk(struct snapraid_state* state, struct snapraid_handle* handle_map, unsigned* waiting_map, unsigned waiting_mac) +{ + uint64_t now = tick(); + uint64_t delta = now - state->tick_last; + unsigned i; + + /* increment the time spent in the data disks */ + for (i = 0; i < waiting_mac; ++i) { + struct snapraid_disk* disk = handle_map[waiting_map[i]].disk; + + if (!disk) + continue; + + disk->tick += delta; + } + state->tick_io += delta; + + state->tick_last = now; +} + +void state_usage_parity(struct snapraid_state* state, unsigned* waiting_map, unsigned waiting_mac) +{ + uint64_t now = tick(); + uint64_t delta = now - state->tick_last; + unsigned i; + + /* increment the time spent in the parity disk */ + for (i = 0; i < waiting_mac; ++i) + state->parity[waiting_map[i]].tick += delta; + state->tick_io += delta; + + state->tick_last = now; +} + +void state_usage_print(struct snapraid_state* state) +{ + /* set the latest data */ + state_progress_latest(state); + + if (msg_level < MSG_PROGRESS) + return; + + /* print a graph for it */ + state_progress_graph(state, 0, state->progress_ptr, PROGRESS_MAX); +} + +void state_fscheck(struct snapraid_state* state, const char* ope) +{ + tommy_node* i; + + /* check the file-system on all disks */ + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* disk = i->data; + + if (fs_check(disk) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in file-system for disk '%s' %s\n", disk->name, ope); + os_abort(); + /* LCOV_EXCL_STOP */ + } + } +} + +void generate_configuration(const char* path) +{ + struct snapraid_state state; + struct snapraid_content* content; + char esc_buffer[ESC_MAX]; + unsigned l, s; + tommy_node* j; + + state_init(&state); + + /* mark that we are without a configuration file */ + state.no_conf = 1; + + /* create the dummy content entry */ + content = content_alloc(path, -1); + + /* adds the content entry */ + tommy_list_insert_tail(&state.contentlist, &content->node, content); + + /* read the content file */ + state_read(&state); + + /* output a dummy configuration file */ + printf("# Configuration file generated from %s\n", path); + printf("\n"); + printf("# Use this blocksize\n"); + printf("blocksize %u\n", state.block_size / KIBI); + printf("\n"); + printf("# Use this hashsize\n"); + printf("hashsize %u\n", BLOCK_HASH_SIZE); + printf("\n"); + for (l = 0; l < state.level; ++l) { + printf("# Set the correct path for the %s files\n", lev_name(l)); + printf("# You had %u of them:\n", state.parity[l].split_mac); + for (s = 0; s < state.parity[l].split_mac; ++s) { + printf("# %u:\n", s); + printf("# PATH:"); + if (state.parity[l].split_map[s].path[0]) + printf("%s", state.parity[l].split_map[s].path); + else + printf("?"); + printf("\n"); + printf("# SIZE:"); + if (state.parity[l].split_map[s].size != PARITY_SIZE_INVALID) + printf("%" PRIu64, state.parity[l].split_map[s].size); + else + printf("?"); + printf("\n"); + printf("# UUID:"); + if (state.parity[l].split_map[s].uuid[0]) + printf("%s", state.parity[l].split_map[s].uuid); + else + printf("?"); + printf("\n"); + printf("#\n"); + } + printf("%s ENTER_HERE_THE_PARITY_FILES_COMMA_SEPARATED\n", lev_config_name(l)); + printf("\n"); + } + printf("# Add any other content file\n"); + printf("content %s\n", path); + printf("\n"); + for (j = state.maplist; j; j = j->next) { + struct snapraid_map* map = j->data; + struct snapraid_disk* disk; + printf("# Set the correct dir for disk '%s'\n", map->name); + if (map->uuid[0]) + printf("# Disk '%s' is the one with id '%s'\n", map->name, map->uuid); + disk = find_disk_by_name(&state, map->name); + if (disk && disk->filelist) { + struct snapraid_file* file = disk->filelist->data; + if (file) { + printf("# and containing: %s\n", fmt_poll(disk, file->sub, esc_buffer)); + } + } + printf("data %s ENTER_HERE_THE_DIR\n", map->name); + printf("\n"); + } + + state_done(&state); +} + diff --git a/cmdline/state.h b/cmdline/state.h new file mode 100644 index 0000000..cbc1a55 --- /dev/null +++ b/cmdline/state.h @@ -0,0 +1,385 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#ifndef __STATE_H +#define __STATE_H + +#include "elem.h" + +struct snapraid_handle; +struct snapraid_io; + +/****************************************************************************/ +/* parity level */ + +/** + * Max level of parity supported. + */ +#define LEV_MAX 6 + +/** + * Return the parity name: Parity, 2-Parity, 3-Parity, 4-Parity, 5-Parity, 6-Parity. + */ +const char* lev_name(unsigned level); + +/** + * Return the parity name used in the config file: parity, 2-parity, 3-parity, 4-parity, 5-parity, 6-parity. + */ +const char* lev_config_name(unsigned level); + +/****************************************************************************/ +/* state */ + +/** + * Units for disk space. + */ +#define KILO (1000) +#define MEGA (1000 * 1000) +#define GIGA (1000 * 1000 * 1000) +#define TERA (1000 * 1000 * 1000 * 1000LL) +#define KIBI (1024) +#define MEBI (1024 * 1024) +#define GIBI (1024 * 1024 * 1024) +#define TEBI (1024 * 1024 * 1024 * 1024LL) + +/** + * Global variable to identify if Ctrl+C is pressed. + */ +extern volatile int global_interrupt; + +#define SORT_PHYSICAL 1 /**< Sort by physical order. */ +#define SORT_INODE 2 /**< Sort by inode. */ +#define SORT_ALPHA 3 /**< Sort by alphabetic order. */ +#define SORT_DIR 4 /**< Sort by directory order. */ + +/** + * Options set only at startup. + * For all these options a value of 0 means nothing set, and to use the default. + */ +struct snapraid_option { + int gui; /**< Gui output. */ + int auditonly; /**< In check, checks only the hash and not the parity. */ + int badonly; /**< In fix, fixes only the blocks marked as bad. */ + int syncedonly; /**< In fix, fixes only files that are synced. */ + int prehash; /**< Enables the prehash mode for sync. */ + unsigned io_error_limit; /**< Max number of input/output errors before aborting. */ + int force_zero; /**< Forced dangerous operations of syncing files now with zero size. */ + int force_empty; /**< Forced dangerous operations of syncing disks now empty. */ + int force_uuid; /**< Forced dangerous operations of syncing disks with uuid changed. */ + int force_device; /**< Forced dangerous operations of using disks with save device id. */ + int force_nocopy; /**< Force dangerous operations of syncing files without using copy detection. */ + int force_full; /**< Force a full parity update. */ + int force_realloc; /**< Force a full reallocation and parity update. */ + int expect_unrecoverable; /**< Expect presence of unrecoverable error in checking or fixing. */ + int expect_recoverable; /**< Expect presence of recoverable error in checking. */ + int skip_device; /**< Skip devices matching checks. */ + int skip_sign; /**< Skip the sign check for content files. */ + int skip_fallocate; /**< Skip the use of fallocate(). */ + int skip_space_holder; /**< Skip the use of spaceholder file. */ + int file_mode; /**< File mode. Mask of ADVISE_* flags. */ + int skip_lock; /**< Skip the lock file protection. */ + int skip_self; /**< Skip the self-test. */ + int skip_content_check; /**< Relax some content file checks. */ + int skip_parity_access; /**< Skip the parity access for commands that don't need it. */ + int skip_disk_access; /**< Skip the data disk access for commands that don't need it. */ + int skip_content_access; /**< Skip the content access for commands that don't need it. */ + int kill_after_sync; /**< Kill the process after sync without saving the final state. */ + int force_murmur3; /**< Force Murmur3 choice. */ + int force_spooky2; /**< Force Spooky2 choice. */ + int force_order; /**< Force sorting order. One of the SORT_* defines. */ + unsigned force_scrub_at; /**< Force scrub for the specified number of blocks. */ + int force_scrub_even; /**< Force scrub of all the even blocks. */ + int force_content_write; /**< Force the update of the content file. */ + int skip_content_write; /**< Skip the update of the content file. */ + int force_scan_winfind; /**< Force the use of FindFirst/Next in Windows to list directories. */ + int force_progress; /**< Force the use of the progress status. */ + unsigned force_autosave_at; /**< Force autosave at the specified block. */ + int fake_device; /**< Fake device data. */ + int no_warnings; /**< Remove some warning messages. */ + int expected_missing; /**< If missing files are expected and should not be reported. */ + int fake_uuid; /**< Set fakes UUID for testing. */ + int match_first_uuid; /**< Force the matching of the first UUID. */ + int force_parity_update; /**< Force parity update even if data is not changed. */ + unsigned io_cache; /**< Number of IO buffers to use. 0 for default. */ + int auto_conf; /**< Allow to run without configuration file. */ + int force_stats; /**< Force stats print during process. */ + uint64_t parity_limit_size; /**< Test limit for parity files. */ +}; + +struct snapraid_state { + struct snapraid_option opt; /**< Setup options. */ + int filter_hidden; /**< Filter out hidden files. */ + uint64_t autosave; /**< Autosave after the specified amount of data. 0 to disable. */ + int need_write; /**< If the state is changed. */ + int checked_read; /**< If the state was read and checked. */ + uint32_t block_size; /**< Block size in bytes. */ + unsigned raid_mode; /**< Raid mode to use. RAID_MODE_DEFAULT or RAID_MODE_ALTERNATE. */ + int file_mode; /**< File access mode. Combination of ADVISE_* flags. */ + struct snapraid_parity parity[LEV_MAX]; /**< Parity vector. */ + char share[PATH_MAX]; /**< Path of the share tree. If !=0 pool links are created in a different way. */ + char pool[PATH_MAX]; /**< Path of the pool tree. */ + uint64_t pool_device; /**< Device identifier of the pool. */ + unsigned char hashseed[HASH_MAX]; /**< Hash seed. Just after a uint64 to provide a minimal alignment. */ + unsigned char prevhashseed[HASH_MAX]; /**< Previous hash seed. In case of rehash. */ + char lockfile[PATH_MAX]; /**< Path of the lock file to use. */ + unsigned level; /**< Number of parity levels. 1 for PAR1, 2 for PAR2. */ + unsigned hash; /**< Hash kind used. */ + unsigned prevhash; /**< Previous hash kind used. In case of rehash. */ + unsigned besthash; /**< Best hash suggested. */ + const char* command; /**< Command running. */ + tommy_list contentlist; /**< List of content files. */ + tommy_list disklist; /**< List of all the disks. */ + tommy_list maplist; /**< List of all the disk mappings. */ + tommy_list filterlist; /**< List of inclusion/exclusion. */ + tommy_list importlist; /**< List of import file. */ + tommy_hashdyn importset; /**< Hashtable by hash of all the import blocks. */ + tommy_hashdyn previmportset; /**< Hashtable by prevhash of all the import blocks. Valid only if we are in a rehash state. */ + tommy_hashdyn searchset; /**< Hashtable by timestamp of all the search files. */ + tommy_arrayblkof infoarr; /**< Block information array. */ + + /** + * Cumulative time used for computations. + */ + uint64_t tick_misc; + uint64_t tick_sched; + uint64_t tick_raid; + uint64_t tick_hash; + + /** + * Cumulative time used for all io operations of disks. + */ + uint64_t tick_io; + + /** + * Last time used for time measure. + */ + uint64_t tick_last; + + int clear_past_hash; /**< Clear all the hash from CHG and DELETED blocks when reading the state from an incomplete sync. */ + + time_t progress_whole_start; /**< Initial start of the whole process. */ + time_t progress_interruption; /**< Time of the start of the progress interruption. */ + time_t progress_wasted; /**< Time wasted in interruptions. */ + + time_t progress_time[PROGRESS_MAX]; /**< Last times of progress. */ + block_off_t progress_pos[PROGRESS_MAX]; /**< Last positions of progress. */ + data_off_t progress_size[PROGRESS_MAX]; /**< Last sizes of progress. */ + uint64_t progress_tick_misc[PROGRESS_MAX]; /**< Last cpu ticks of progress. */ + uint64_t progress_tick_sched[PROGRESS_MAX]; /**< Last scheduling ticks of progress. */ + uint64_t progress_tick_raid[PROGRESS_MAX]; /**< Last raid ticks of progress. */ + uint64_t progress_tick_hash[PROGRESS_MAX]; /**< Last hash ticks of progress. */ + uint64_t progress_tick_io[PROGRESS_MAX]; /**< Last io ticks of progress. */ + + int progress_ptr; /**< Pointer to the next position to fill. Rolling over. */ + int progress_tick; /**< Number of measures done. */ + + int no_conf; /**< Automatically add missing info. Used to load content without a configuration file. */ +}; + +/** + * Initialize the state. + */ +void state_init(struct snapraid_state* state); + +/** + * Deinitialize the state. + */ +void state_done(struct snapraid_state* state); + +/** + * Read the configuration file. + */ +void state_config(struct snapraid_state* state, const char* path, const char* command, struct snapraid_option* opt, tommy_list* filterlist_disk); + +/** + * Read the state. + */ +void state_read(struct snapraid_state* state); + +/** + * Write the new state. + */ +void state_write(struct snapraid_state* state); + +/** + * Diff all the disks. + */ +int state_diff(struct snapraid_state* state); + +/** + * Scan all the disks to update the state. + */ +void state_scan(struct snapraid_state* state); + +/** + * Set the nanosecond timestamp of all files that have a zero value. + */ +void state_touch(struct snapraid_state* state); + +/** + * Devices operations. + */ +void state_device(struct snapraid_state* state, int operation, tommy_list* filterlist_disk); + +/** + * Sync the parity data. + */ +int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t blockcount); + +/** + * Check (and fixes) all the files and parity data. + * \param fix If we have to fix, after checking. + */ +int state_check(struct snapraid_state* state, int fix, block_off_t blockstart, block_off_t blockcount); + +/** + * Dry the files. + */ +void state_dry(struct snapraid_state* state, block_off_t blockstart, block_off_t blockcount); + +/** + * Rehash the files. + */ +void state_rehash(struct snapraid_state* state); + +/** + * Scrub levels. + */ +#define SCRUB_AUTO -1 /**< Automatic selection. */ +#define SCRUB_BAD -2 /**< Scrub only the bad blocks. */ +#define SCRUB_NEW -3 /**< Scub the new blocks. */ +#define SCRUB_FULL -4 /**< Scrub everything. */ +#define SCRUB_EVEN -5 /**< Even blocks. */ + +/** + * Scrub the files. + */ +int state_scrub(struct snapraid_state* state, int plan, int olderthan); + +/** + * Print the status. + */ +int state_status(struct snapraid_state* state); + +/** + * Find duplicates. + */ +void state_dup(struct snapraid_state* state); + +/** + * List content. + */ +void state_list(struct snapraid_state* state); + +/** + * Create pool tree. + */ +void state_pool(struct snapraid_state* state); + +/** + * Refresh the free space info. + * + * Note that it requires disks access. + */ +void state_refresh(struct snapraid_state* state); + +/** + * Skip files, symlinks and dirs. + * Apply any skip access disk. + */ +void state_skip(struct snapraid_state* state); + +/** + * Filter files, symlinks and dirs. + * Apply an additional filter to the list currently loaded. + */ +void state_filter(struct snapraid_state* state, tommy_list* filterlist_file, tommy_list* filterlist_disk, int filter_missing, int filter_error); + +/** + * Begin the progress visualization. + */ +int state_progress_begin(struct snapraid_state* state, block_off_t blockstart, block_off_t blockmax, block_off_t countmax); + +/** + * End the progress visualization. + */ +void state_progress_end(struct snapraid_state* state, block_off_t countpos, block_off_t countmax, data_off_t countsize); + +/** + * Write the progress. + */ +int state_progress(struct snapraid_state* state, struct snapraid_io* io, block_off_t blockpos, block_off_t countpos, block_off_t countmax, data_off_t countsize); + +/** + * Stop temporarily the progress. + */ +void state_progress_stop(struct snapraid_state* state); + +/** + * Restart the progress. + */ +void state_progress_restart(struct snapraid_state* state); + +/** + * Set the usage time as wasted one not counted. + */ +void state_usage_waste(struct snapraid_state* state); + +/** + * Set the usage time for CPU. + */ +void state_usage_misc(struct snapraid_state* state); +void state_usage_sched(struct snapraid_state* state); +void state_usage_raid(struct snapraid_state* state); +void state_usage_hash(struct snapraid_state* state); + +/** + * Set the last file used + */ +void state_usage_file(struct snapraid_state* state, struct snapraid_disk* disk, struct snapraid_file* file); + +/** + * Set the usage time for a set of data disks. + */ +void state_usage_disk(struct snapraid_state* state, struct snapraid_handle* handle_map, unsigned* waiting_map, unsigned waiting_mac); + +/** + * Set the usage time for a set of parity disk. + */ +void state_usage_parity(struct snapraid_state* state, unsigned* waiting_map, unsigned waiting_mac); + +/** + * Print the stats of the usage time. + */ +void state_usage_print(struct snapraid_state* state); + +/** + * Check the file-system on all disks. + * On error it aborts. + */ +void state_fscheck(struct snapraid_state* state, const char* ope); + +/****************************************************************************/ +/* misc */ + +/** + * Generate a dummy configuration file from a content file. + */ +void generate_configuration(const char* content); + +#endif + diff --git a/cmdline/status.c b/cmdline/status.c new file mode 100644 index 0000000..a6d769c --- /dev/null +++ b/cmdline/status.c @@ -0,0 +1,531 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "support.h" +#include "elem.h" +#include "state.h" +#include "parity.h" +#include "handle.h" +#include "raid/raid.h" + +/****************************************************************************/ +/* status */ + +unsigned day_ago(time_t ref, time_t now) +{ + return (now - ref) / (24 * 3600); +} + +#define GRAPH_COLUMN 70 +#define GRAPH_ROW 15 + +static unsigned perc(uint64_t part, uint64_t total) +{ + if (!total) + return 0; + + return (unsigned)(part * 100 / total); +} + +/** + * Bit used to mark unscrubbed time info. + */ +#define TIME_NEW 1 + +int state_status(struct snapraid_state* state) +{ + block_off_t blockmax; + block_off_t i; + time_t* timemap; + time_t now; + block_off_t bad; + block_off_t bad_first; + block_off_t bad_last; + block_off_t rehash; + block_off_t count; + unsigned l; + unsigned dayoldest, daymedian, daynewest; + unsigned bar_scrubbed[GRAPH_COLUMN]; + unsigned bar_new[GRAPH_COLUMN]; + unsigned barpos; + unsigned barmax; + time_t oldest, newest, median; + unsigned x, y; + tommy_node* node_disk; + unsigned file_count; + unsigned file_fragmented; + unsigned extra_fragment; + unsigned file_zerosubsecond; + uint64_t file_size; + uint64_t file_block_count; + uint64_t file_block_free; + block_off_t parity_block_free; + unsigned unsynced_blocks; + unsigned unscrubbed_blocks; + uint64_t all_wasted; + int free_not_zero; + + /* get the present time */ + now = time(0); + + /* keep track if at least a free info is available */ + free_not_zero = 0; + + blockmax = parity_allocated_size(state); + + log_tag("summary:block_size:%u\n", state->block_size); + log_tag("summary:parity_block_count:%u\n", blockmax); + + /* get the minimum parity free space */ + parity_block_free = state->parity[0].free_blocks; + for (l = 0; l < state->level; ++l) { + log_tag("summary:parity_block_total:%s:%u\n", lev_config_name(l), state->parity[l].total_blocks); + log_tag("summary:parity_block_free:%s:%u\n", lev_config_name(l), state->parity[l].free_blocks); + if (state->parity[l].free_blocks < parity_block_free) + parity_block_free = state->parity[l].free_blocks; + if (state->parity[l].free_blocks != 0) + free_not_zero = 1; + } + log_tag("summary:parity_block_free_min:%u\n", parity_block_free); + + printf("SnapRAID status report:\n"); + printf("\n"); + printf(" Files Fragmented Excess Wasted Used Free Use Name\n"); + printf(" Files Fragments GB GB GB\n"); + + /* count fragments */ + file_count = 0; + file_size = 0; + file_block_count = 0; + file_block_free = 0; + file_fragmented = 0; + extra_fragment = 0; + file_zerosubsecond = 0; + all_wasted = 0; + for (node_disk = state->disklist; node_disk != 0; node_disk = node_disk->next) { + struct snapraid_disk* disk = node_disk->data; + tommy_node* node; + block_off_t j; + unsigned disk_file_count = 0; + unsigned disk_file_fragmented = 0; + unsigned disk_extra_fragment = 0; + unsigned disk_file_zerosubsecond = 0; + block_off_t disk_block_count = 0; + uint64_t disk_file_size = 0; + block_off_t disk_block_latest_used = 0; + block_off_t disk_block_max_by_space; + block_off_t disk_block_max_by_parity; + block_off_t disk_block_max; + int64_t wasted; + + /* for each file in the disk */ + node = disk->filelist; + while (node) { + struct snapraid_file* file; + + file = node->data; + node = node->next; /* next node */ + + if (file->mtime_nsec == STAT_NSEC_INVALID + || file->mtime_nsec == 0 + ) { + ++file_zerosubsecond; + ++disk_file_zerosubsecond; + if (disk_file_zerosubsecond < 50) + log_tag("zerosubsecond:%s:%s: \n", disk->name, file->sub); + if (disk_file_zerosubsecond == 50) + log_tag("zerosubsecond:%s:%s: (more follow)\n", disk->name, file->sub); + } + + /* check fragmentation */ + if (file->blockmax != 0) { + block_off_t prev_pos; + block_off_t last_pos; + int fragmented; + + fragmented = 0; + prev_pos = fs_file2par_get(disk, file, 0); + for (j = 1; j < file->blockmax; ++j) { + block_off_t parity_pos = fs_file2par_get(disk, file, j); + if (prev_pos + 1 != parity_pos) { + fragmented = 1; + ++extra_fragment; + ++disk_extra_fragment; + } + prev_pos = parity_pos; + } + + /* keep track of latest block used */ + last_pos = fs_file2par_get(disk, file, file->blockmax - 1); + if (last_pos > disk_block_latest_used) { + disk_block_latest_used = last_pos; + } + + if (fragmented) { + ++file_fragmented; + ++disk_file_fragmented; + } + + disk_block_count += file->blockmax; + } + + /* count files */ + ++file_count; + ++disk_file_count; + file_size += file->size; + file_block_count += file->blockmax; + disk_file_size += file->size; + } + + if (disk->free_blocks != 0) + free_not_zero = 1; + + /* get the free block info */ + disk_block_max_by_space = disk_block_count + disk->free_blocks; + disk_block_max_by_parity = blockmax + parity_block_free; + + /* the maximum usable space in a disk is limited by the smallest */ + /* of the disk size and the parity size */ + /* the wasted space is the space that we have to leave */ + /* free on the data disk, when the parity is filled up */ + if (disk_block_max_by_space < disk_block_max_by_parity) { + disk_block_max = disk_block_max_by_space; + } else { + disk_block_max = disk_block_max_by_parity; + } + + /* wasted space is the difference of the two maximum size */ + /* if negative, it's extra space available in parity */ + wasted = (int64_t)disk_block_max_by_space - (int64_t)disk_block_max_by_parity; + wasted *= state->block_size; + + if (wasted > 0) + all_wasted += wasted; + file_block_free += disk_block_max - disk_block_count; + + printf("%8u", disk_file_count); + printf("%8u", disk_file_fragmented); + printf("%8u", disk_extra_fragment); + if (wasted < -100LL * GIGA) { + printf(" -"); + } else { + printf("%8.1f", (double)wasted / GIGA); + } + printf("%8" PRIu64, disk_file_size / GIGA); + + if (disk_block_max == 0 && disk_block_count == 0) { + /* if the disk is empty and we don't have the free space info */ + printf(" -"); + printf(" - "); + } else { + printf("%8" PRIu64, (disk_block_max - disk_block_count) * (uint64_t)state->block_size / GIGA); + printf(" %3u%%", perc(disk_block_count, disk_block_max)); + } + printf(" %s\n", disk->name); + + log_tag("summary:disk_file_count:%s:%u\n", disk->name, disk_file_count); + log_tag("summary:disk_block_count:%s:%u\n", disk->name, disk_block_count); + log_tag("summary:disk_fragmented_file_count:%s:%u\n", disk->name, disk_file_fragmented); + log_tag("summary:disk_excess_fragment_count:%s:%u\n", disk->name, disk_extra_fragment); + log_tag("summary:disk_zerosubsecond_file_count:%s:%u\n", disk->name, disk_file_zerosubsecond); + log_tag("summary:disk_file_size:%s:%" PRIu64 "\n", disk->name, disk_file_size); + log_tag("summary:disk_block_allocated:%s:%u\n", disk->name, disk_block_latest_used + 1); + log_tag("summary:disk_block_total:%s:%u\n", disk->name, disk->total_blocks); + log_tag("summary:disk_block_free:%s:%u\n", disk->name, disk->free_blocks); + log_tag("summary:disk_block_max_by_space:%s:%u\n", disk->name, disk_block_max_by_space); + log_tag("summary:disk_block_max_by_parity:%s:%u\n", disk->name, disk_block_max_by_parity); + log_tag("summary:disk_block_max:%s:%u\n", disk->name, disk_block_max); + log_tag("summary:disk_space_wasted:%s:%" PRId64 "\n", disk->name, wasted); + } + + /* totals */ + printf(" --------------------------------------------------------------------------\n"); + printf("%8u", file_count); + printf("%8u", file_fragmented); + printf("%8u", extra_fragment); + printf("%8.1f", (double)all_wasted / GIGA); + printf("%8" PRIu64, file_size / GIGA); + printf("%8" PRIu64, file_block_free * state->block_size / GIGA); + printf(" %3u%%", perc(file_block_count, file_block_count + file_block_free)); + printf("\n"); + + /* warn about invalid data free info */ + if (!free_not_zero) + printf("\nWARNING! Free space info will be valid after the first sync.\n"); + + log_tag("summary:file_count:%u\n", file_count); + log_tag("summary:file_block_count:%" PRIu64 "\n", file_block_count); + log_tag("summary:fragmented_file_count:%u\n", file_fragmented); + log_tag("summary:excess_fragment_count:%u\n", extra_fragment); + log_tag("summary:zerosubsecond_file_count:%u\n", file_zerosubsecond); + log_tag("summary:file_size:%" PRIu64 "\n", file_size); + log_tag("summary:parity_size:%" PRIu64 "\n", blockmax * (uint64_t)state->block_size); + log_tag("summary:parity_size_max:%" PRIu64 "\n", (blockmax + parity_block_free) * (uint64_t)state->block_size); + log_tag("summary:hash:%s\n", hash_config_name(state->hash)); + log_tag("summary:prev_hash:%s\n", hash_config_name(state->prevhash)); + log_tag("summary:best_hash:%s\n", hash_config_name(state->besthash)); + log_flush(); + + /* copy the info a temp vector, and count bad/rehash/unsynced blocks */ + timemap = malloc_nofail(blockmax * sizeof(time_t)); + bad = 0; + bad_first = 0; + bad_last = 0; + count = 0; + rehash = 0; + unsynced_blocks = 0; + unscrubbed_blocks = 0; + log_tag("block_count:%u\n", blockmax); + for (i = 0; i < blockmax; ++i) { + int one_invalid; + int one_valid; + + snapraid_info info = info_get(&state->infoarr, i); + + /* for each disk */ + one_invalid = 0; + one_valid = 0; + for (node_disk = state->disklist; node_disk != 0; node_disk = node_disk->next) { + struct snapraid_disk* disk = node_disk->data; + struct snapraid_block* block = fs_par2block_find(disk, i); + + if (block_has_file(block)) + one_valid = 1; + if (block_has_invalid_parity(block)) + one_invalid = 1; + } + + /* if both valid and invalid, we need to update */ + if (one_invalid && one_valid) { + ++unsynced_blocks; + } + + /* skip unused blocks */ + if (info != 0) { + time_t scrub_time; + + if (info_get_bad(info)) { + if (bad == 0) + bad_first = i; + bad_last = i; + ++bad; + } + + if (info_get_rehash(info)) + ++rehash; + + scrub_time = info_get_time(info); + + if (info_get_justsynced(info)) { + ++unscrubbed_blocks; + + /* mark the time as not scrubbed */ + scrub_time |= TIME_NEW; + } + + timemap[count++] = scrub_time; + } + + if (state->opt.gui) { + if (info != 0) + log_tag("block:%u:%" PRIu64 ":%s:%s:%s:%s\n", i, (uint64_t)info_get_time(info), one_valid ? "used" : "", one_invalid ? "unsynced" : "", info_get_bad(info) ? "bad" : "", info_get_rehash(info) ? "rehash" : ""); + else + log_tag("block_noinfo:%u:%s:%s\n", i, one_valid ? "used" : "", one_invalid ? "unsynced" : ""); + } + } + + log_tag("summary:has_unsynced:%u\n", unsynced_blocks); + log_tag("summary:has_unscrubbed:%u\n", unscrubbed_blocks); + log_tag("summary:has_rehash:%u\n", rehash); + log_tag("summary:has_bad:%u:%u:%u\n", bad, bad_first, bad_last); + log_flush(); + + if (!count) { + log_fatal("The array is empty.\n"); + free(timemap); + return 0; + } + + /* sort the info to get the time info */ + qsort(timemap, count, sizeof(time_t), time_compare); + + /* output the info map */ + i = 0; + log_tag("info_count:%u\n", count); + while (i < count) { + unsigned j = i + 1; + while (j < count && timemap[i] == timemap[j]) + ++j; + if ((timemap[i] & TIME_NEW) == 0) { + log_tag("info_time:%" PRIu64 ":%u:scrubbed\n", (uint64_t)timemap[i], j - i); + } else { + log_tag("info_time:%" PRIu64 ":%u:new\n", (uint64_t)(timemap[i] & ~TIME_NEW), j - i); + } + i = j; + } + + oldest = timemap[0]; + median = timemap[count / 2]; + newest = timemap[count - 1]; + dayoldest = day_ago(oldest, now); + daymedian = day_ago(median, now); + daynewest = day_ago(newest, now); + + /* compute graph limits */ + barpos = 0; + barmax = 0; + for (i = 0; i < GRAPH_COLUMN; ++i) { + time_t limit; + unsigned step_scrubbed, step_new; + + limit = oldest + (newest - oldest) * (i + 1) / GRAPH_COLUMN; + + step_scrubbed = 0; + step_new = 0; + while (barpos < count && timemap[barpos] <= limit) { + if ((timemap[barpos] & TIME_NEW) != 0) + ++step_new; + else + ++step_scrubbed; + ++barpos; + } + + if (step_new + step_scrubbed > barmax) + barmax = step_new + step_scrubbed; + + bar_scrubbed[i] = step_scrubbed; + bar_new[i] = step_new; + } + + printf("\n\n"); + + /* print the graph */ + for (y = 0; y < GRAPH_ROW; ++y) { + if (y == 0) + printf("%3u%%|", barmax * 100 / count); + else if (y == GRAPH_ROW - 1) + printf(" 0%%|"); + else if (y == GRAPH_ROW / 2) + printf("%3u%%|", barmax * 50 / count); + else + printf(" |"); + for (x = 0; x < GRAPH_COLUMN; ++x) { + unsigned pivot_upper = barmax * (GRAPH_ROW - y) / GRAPH_ROW; + unsigned pivot_lower = barmax * (GRAPH_ROW - 1 - y) / GRAPH_ROW; + unsigned both = bar_scrubbed[x] + bar_new[x]; + unsigned scrubbed = bar_scrubbed[x]; + + if (both > pivot_upper) { + if (scrubbed > pivot_lower) + printf("*"); + else + printf("o"); + } else if (both > pivot_lower) { + if (scrubbed == both) + printf("*"); + else + printf("o"); + } else { + if (y == GRAPH_ROW - 1) + printf("_"); + else + printf(" "); + } + } + printf("\n"); + } + printf(" %3u days ago of the last scrub/sync %3u\n", dayoldest, daynewest); + + printf("\n"); + + printf("The oldest block was scrubbed %u days ago, the median %u, the newest %u.\n", dayoldest, daymedian, daynewest); + + printf("\n"); + + if (unsynced_blocks) { + printf("WARNING! The array is NOT fully synced.\n"); + printf("You have a sync in progress at %u%%.\n", (blockmax - unsynced_blocks) * 100 / blockmax); + } else { + printf("No sync is in progress.\n"); + } + + if (unscrubbed_blocks) { + printf("The %u%% of the array is not scrubbed.\n", (unscrubbed_blocks * 100 + blockmax - 1) / blockmax); + } else { + printf("The full array was scrubbed at least one time.\n"); + } + + if (file_zerosubsecond) { + printf("You have %u files with zero sub-second timestamp.\n", file_zerosubsecond); + printf("Run the 'touch' command to set it to a not zero value.\n"); + } else { + printf("No file has a zero sub-second timestamp.\n"); + } + + if (rehash) { + printf("You have a rehash in progress at %u%%.\n", (count - rehash) * 100 / count); + } else { + if (state->besthash != state->hash) { + printf("No rehash is in progress, but for optimal performance one is recommended.\n"); + } else { + printf("No rehash is in progress or needed.\n"); + } + } + + if (bad) { + block_off_t bad_print; + + printf("DANGER! In the array there are %u errors!\n\n", bad); + + printf("They are from block %u to %u, specifically at blocks:", bad_first, bad_last); + + /* print some of the errors */ + bad_print = 0; + for (i = 0; i < blockmax; ++i) { + snapraid_info info = info_get(&state->infoarr, i); + + /* skip unused blocks */ + if (info == 0) + continue; + + if (info_get_bad(info)) { + printf(" %u", i); + ++bad_print; + } + + if (bad_print > 100) { + printf(" and %u more...", bad - bad_print); + break; + } + } + + printf("\n\n"); + + printf("To fix them use the command 'snapraid -e fix'.\n"); + printf("The errors will disappear from the 'status' at the next 'scrub' command.\n"); + } else { + printf("No error detected.\n"); + } + + /* free the temp vector */ + free(timemap); + + return 0; +} + diff --git a/cmdline/stream.c b/cmdline/stream.c new file mode 100644 index 0000000..eeac131 --- /dev/null +++ b/cmdline/stream.c @@ -0,0 +1,757 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "support.h" +#include "util.h" +#include "stream.h" + +/****************************************************************************/ +/* stream */ + +unsigned STREAM_SIZE = 64 * 1024; + +STREAM* sopen_read(const char* file) +{ +#if HAVE_POSIX_FADVISE + int ret; +#endif + STREAM* s = malloc_nofail(sizeof(STREAM)); + + s->handle_size = 1; + s->handle = malloc_nofail(sizeof(struct stream_handle)); + + pathcpy(s->handle[0].path, sizeof(s->handle[0].path), file); + s->handle[0].f = open(file, O_RDONLY | O_BINARY | O_SEQUENTIAL); + if (s->handle[0].f == -1) { + free(s->handle); + free(s); + return 0; + } + +#if HAVE_POSIX_FADVISE + /* advise sequential access */ + ret = posix_fadvise(s->handle[0].f, 0, 0, POSIX_FADV_SEQUENTIAL); + if (ret == ENOSYS) { + log_fatal("WARNING! fadvise() is not supported in this platform. Performance may not be optimal!\n"); + /* call is not supported, like in armhf, see posix_fadvise manpage */ + ret = 0; + } + if (ret != 0) { + /* LCOV_EXCL_START */ + close(s->handle[0].f); + free(s->handle); + free(s); + errno = ret; /* posix_fadvise return the error code */ + return 0; + /* LCOV_EXCL_STOP */ + } +#endif + + s->buffer = malloc_nofail_test(STREAM_SIZE); + s->pos = s->buffer; + s->end = s->buffer; + s->state = STREAM_STATE_READ; + s->state_index = 0; + s->offset = 0; + s->offset_uncached = 0; + s->crc = 0; + s->crc_uncached = 0; + s->crc_stream = CRC_IV; + + return s; +} + +STREAM* sopen_multi_write(unsigned count) +{ + unsigned i; + + STREAM* s = malloc_nofail(sizeof(STREAM)); + + s->handle_size = count; + s->handle = malloc_nofail(count * sizeof(struct stream_handle)); + + for (i = 0; i < count; ++i) + s->handle[i].f = -1; + + s->buffer = malloc_nofail_test(STREAM_SIZE); + s->pos = s->buffer; + s->end = s->buffer + STREAM_SIZE; + s->state = STREAM_STATE_WRITE; + s->state_index = 0; + s->offset = 0; + s->offset_uncached = 0; + s->crc = 0; + s->crc_uncached = 0; + s->crc_stream = CRC_IV; + + return s; +} + +int sopen_multi_file(STREAM* s, unsigned i, const char* file) +{ +#if HAVE_POSIX_FADVISE + int ret; +#endif + int f; + + pathcpy(s->handle[i].path, sizeof(s->handle[i].path), file); + + f = open(file, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_SEQUENTIAL, 0600); + if (f == -1) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + +#if HAVE_POSIX_FADVISE + /* advise sequential access */ + ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL); + if (ret == ENOSYS) { + /* call is not supported, like in armhf, see posix_fadvise manpage */ + ret = 0; + } + if (ret != 0) { + /* LCOV_EXCL_START */ + close(f); + errno = ret; /* posix_fadvise return the error code */ + return -1; + /* LCOV_EXCL_STOP */ + } +#endif + + s->handle[i].f = f; + + return 0; +} + +STREAM* sopen_write(const char* file) +{ + STREAM* s = sopen_multi_write(1); + + if (sopen_multi_file(s, 0, file) != 0) { + sclose(s); + return 0; + } + + return s; +} + +int sclose(STREAM* s) +{ + int fail = 0; + unsigned i; + + if (s->state == STREAM_STATE_WRITE) { + if (sflush(s) != 0) { + /* LCOV_EXCL_START */ + fail = 1; + /* LCOV_EXCL_STOP */ + } + } + + for (i = 0; i < s->handle_size; ++i) { + if (close(s->handle[i].f) != 0) { + /* LCOV_EXCL_START */ + fail = 1; + /* LCOV_EXCL_STOP */ + } + } + + free(s->handle); + free(s->buffer); + free(s); + + if (fail) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + + return 0; +} + +int shandle(STREAM* s) +{ + if (!s->handle_size) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + + return s->handle[0].f; +} + +/** + * Fill the read stream buffer. + * \return 0 if at least on char is read, or EOF on error. + */ +static int sfill(STREAM* s) +{ + ssize_t ret; + + if (s->state != STREAM_STATE_READ) { + /* LCOV_EXCL_START */ + return EOF; + /* LCOV_EXCL_STOP */ + } + + ret = read(s->handle[0].f, s->buffer, STREAM_SIZE); + + if (ret < 0) { + /* LCOV_EXCL_START */ + s->state = STREAM_STATE_ERROR; + return EOF; + /* LCOV_EXCL_STOP */ + } + if (ret == 0) { + s->state = STREAM_STATE_EOF; + return EOF; + } + + /* update the crc */ + s->crc_uncached = s->crc; + s->crc = crc32c(s->crc, s->buffer, ret); + + /* update the offset */ + s->offset_uncached = s->offset; + s->offset += ret; + + s->pos = s->buffer; + s->end = s->buffer + ret; + + return 0; +} + +int sdeplete(STREAM* s, unsigned char* last) +{ + /* last four bytes */ + last[0] = 0; + last[1] = 0; + last[2] = 0; + last[3] = 0; + + while (1) { + /* increase the position up to 4 bytes before the end */ + if (s->pos + 4 <= s->end) + s->pos = s->end - 4; + + /* insert the last 4 bytes */ + while (s->pos < s->end) { + last[0] = last[1]; + last[1] = last[2]; + last[2] = last[3]; + last[3] = *s->pos++; + } + + /* fill again the buffer until the end of the file */ + if (sfill(s) != 0) { + /* on error fail */ + if (serror(s)) { + /* LCOV_EXCL_START */ + return EOF; + /* LCOV_EXCL_STOP */ + } + + /* on EOF terminate */ + break; + } + } + + return 0; +} + +int sflush(STREAM* s) +{ + ssize_t ret; + ssize_t size; + unsigned i; + + if (s->state != STREAM_STATE_WRITE) { + /* LCOV_EXCL_START */ + return EOF; + /* LCOV_EXCL_STOP */ + } + + size = s->pos - s->buffer; + if (!size) + return 0; + + for (i = 0; i < s->handle_size; ++i) { + ret = write(s->handle[i].f, s->buffer, size); + + if (ret != size) { + /* LCOV_EXCL_START */ + s->state = STREAM_STATE_ERROR; + s->state_index = i; + return EOF; + /* LCOV_EXCL_STOP */ + } + } + + /* + * Update the crc *after* writing the data. + * + * This must be done after the file write, + * to be able to detect memory errors on the buffer, + * happening during the write. + */ + s->crc = crc32c(s->crc, s->buffer, size); + s->crc_uncached = s->crc; + + /* update the offset */ + s->offset += size; + s->offset_uncached = s->offset; + + s->pos = s->buffer; + + return 0; +} + +int64_t stell(STREAM* s) +{ + return s->offset_uncached + (s->pos - s->buffer); +} + +uint32_t scrc(STREAM*s) +{ + return crc32c(s->crc_uncached, s->buffer, s->pos - s->buffer); +} + +uint32_t scrc_stream(STREAM*s) +{ + return s->crc_stream ^ CRC_IV; +} + +int sgetc_uncached(STREAM* s) +{ + /* if at the end of the buffer, fill it */ + if (s->pos == s->end && sfill(s) != 0) + return EOF; + return *s->pos++; +} + +int sgettok(STREAM* f, char* str, int size) +{ + char* i = str; + char* send = str + size; + int c; + + while (1) { + c = sgetc(f); + if (c == EOF) { + break; + } + if (c == ' ' || c == '\t') { + sungetc(c, f); + break; + } + if (c == '\n') { + /* remove ending carrige return to support the Windows CR+LF format */ + if (i != str && i[-1] == '\r') + --i; + sungetc(c, f); + break; + } + + *i++ = c; + + if (i == send) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + } + + *i = 0; + + return i - str; +} + +int sread(STREAM* f, void* void_data, unsigned size) +{ + unsigned char* data = void_data; + + /* if there is enough space in memory */ + if (sptrlookup(f, size)) { + /* optimized version with all the data in memory */ + unsigned char* pos = sptrget(f); + + /* copy it */ + while (size--) + *data++ = *pos++; + + sptrset(f, pos); + } else { + /* standard version using sgetc() */ + while (size--) { + int c = sgetc(f); + if (c == EOF) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + + *data++ = c; + } + } + + return 0; +} + +int sgetline(STREAM* f, char* str, int size) +{ + char* i = str; + char* send = str + size; + int c; + + /* if there is enough data in memory */ + if (sptrlookup(f, size)) { + /* optimized version with all the data in memory */ + unsigned char* pos = sptrget(f); + + while (1) { + c = *pos++; + if (c == '\n') { + /* remove ending carrige return to support the Windows CR+LF format */ + if (i != str && i[-1] == '\r') + --i; + --pos; + break; + } + + *i++ = c; + + if (i == send) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + } + + sptrset(f, pos); + } else { + while (1) { + c = sgetc(f); + if (c == EOF) { + /* LCOV_EXCL_START */ + break; + /* LCOV_EXCL_STOP */ + } + if (c == '\n') { + /* remove ending carrige return to support the Windows CR+LF format */ + if (i != str && i[-1] == '\r') + --i; + sungetc(c, f); + break; + } + + *i++ = c; + + if (i == send) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + } + } + + *i = 0; + + return i - str; +} + +int sgetlasttok(STREAM* f, char* str, int size) +{ + int ret; + + ret = sgetline(f, str, size); + if (ret < 0) { + /* LCOV_EXCL_START */ + return ret; + /* LCOV_EXCL_STOP */ + } + + while (ret > 0 && (str[ret - 1] == ' ' || str[ret - 1] == '\t')) + --ret; + + str[ret] = 0; + + return ret; +} + +int sgetu32(STREAM* f, uint32_t* value) +{ + int c; + + c = sgetc(f); + if (c >= '0' && c <= '9') { + uint32_t v; + + v = c - '0'; + + c = sgetc(f); + while (c >= '0' && c <= '9') { + v *= 10; + v += c - '0'; + c = sgetc(f); + } + + *value = v; + + sungetc(c, f); + return 0; + } else { + /* LCOV_EXCL_START */ + /* nothing read */ + return -1; + /* LCOV_EXCL_STOP */ + } +} + +int sgetb32(STREAM* f, uint32_t* value) +{ + uint32_t v; + unsigned char b; + unsigned char s; + int c; + + v = 0; + s = 0; +loop: + c = sgetc(f); + if (c == EOF) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + + b = (unsigned char)c; + if ((b & 0x80) == 0) { + v |= (uint32_t)b << s; + s += 7; + if (s >= 32) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + goto loop; + } + + v |= (uint32_t)(b & 0x7f) << s; + + *value = v; + + return 0; +} + +int sgetb64(STREAM* f, uint64_t* value) +{ + uint64_t v; + unsigned char b; + unsigned char s; + int c; + + v = 0; + s = 0; +loop: + c = sgetc(f); + if (c == EOF) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + + b = (unsigned char)c; + if ((b & 0x80) == 0) { + v |= (uint64_t)b << s; + s += 7; + if (s >= 64) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + goto loop; + } + + v |= (uint64_t)(b & 0x7f) << s; + + *value = v; + + return 0; +} + +int sgetble32(STREAM* f, uint32_t* value) +{ + unsigned char buf[4]; + + if (sread(f, buf, 4) != 0) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + + *value = buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24; + + return 0; +} + +int sgetbs(STREAM* f, char* str, int size) +{ + uint32_t len; + + if (sgetb32(f, &len) < 0) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + + if (len + 1 > (uint32_t)size) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + + str[len] = 0; + + return sread(f, str, (int)len); +} + +int swrite(const void* void_data, unsigned size, STREAM* f) +{ + const unsigned char* data = void_data; + + /* if there is enough space in memory */ + if (sptrlookup(f, size)) { + /* optimized version with all the data in memory */ + unsigned char* pos = sptrget(f); + + /** + * Update the crc *before* writing the data in the buffer + * + * This must be done before the memory write, + * to be able to detect memory errors on the buffer, + * happening before we write it on the file. + */ + f->crc_stream = crc32c_plain(f->crc_stream, data, size); + + /* copy it */ + while (size--) + *pos++ = *data++; + + sptrset(f, pos); + } else { + /* standard version using sputc() */ + while (size--) { + if (sputc(*data++, f) != 0) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + } + } + + return 0; +} + +int sputb32(uint32_t value, STREAM* s) +{ + unsigned char b; + unsigned char buf[16]; + unsigned i; + + i = 0; +loop: + b = value & 0x7f; + value >>= 7; + + if (value) { + buf[i++] = b; + goto loop; + } + + buf[i++] = b | 0x80; + + return swrite(buf, i, s); +} + +int sputb64(uint64_t value, STREAM* s) +{ + unsigned char b; + unsigned char buf[16]; + unsigned i; + + i = 0; +loop: + b = value & 0x7f; + value >>= 7; + + if (value) { + buf[i++] = b; + goto loop; + } + + buf[i++] = b | 0x80; + + return swrite(buf, i, s); +} + +int sputble32(uint32_t value, STREAM* s) +{ + unsigned char buf[4]; + + buf[0] = value & 0xFF; + buf[1] = (value >> 8) & 0xFF; + buf[2] = (value >> 16) & 0xFF; + buf[3] = (value >> 24) & 0xFF; + + return swrite(buf, 4, s); +} + +int sputbs(const char* str, STREAM* f) +{ + size_t len = strlen(str); + + if (sputb32(len, f) != 0) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + + return swrite(str, len, f); +} + +#if HAVE_FSYNC +int ssync(STREAM* s) +{ + unsigned i; + + for (i = 0; i < s->handle_size; ++i) { + if (fsync(s->handle[i].f) != 0) { + /* LCOV_EXCL_START */ + s->state = STREAM_STATE_ERROR; + s->state_index = i; + return -1; + /* LCOV_EXCL_STOP */ + } + } + + return 0; +} +#endif + diff --git a/cmdline/stream.h b/cmdline/stream.h new file mode 100644 index 0000000..35b941f --- /dev/null +++ b/cmdline/stream.h @@ -0,0 +1,416 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#ifndef __STREAM_H +#define __STREAM_H + +#include "util.h" + +/****************************************************************************/ +/* stream */ + +/** + * Size of the buffer of the stream. + * + * It's not a constant for testing purpose. + */ +unsigned STREAM_SIZE; + +#define STREAM_STATE_READ 0 /**< The stream is in a normal state of read. */ +#define STREAM_STATE_WRITE 1 /**< The stream is in a normal state of write. */ +#define STREAM_STATE_ERROR -1 /**< An error was encountered. */ +#define STREAM_STATE_EOF 2 /**< The end of file was encountered. */ + +struct stream_handle { + int f; /**< Handle of the file. */ + char path[PATH_MAX]; /**< Path of the file. */ +}; + +struct stream { + unsigned char* buffer; /**< Buffer of the stream. */ + unsigned char* pos; /**< Current position in the buffer. */ + unsigned char* end; /**< End position of the buffer. */ + int state; /**< State of the stream. One of STREAM_STATE. */ + int state_index; /**< Index of the handle causing a state change. */ + unsigned handle_size; /**< Number of handles. */ + struct stream_handle* handle; /**< Set of handles. */ + off_t offset; /**< Offset into the file. */ + off_t offset_uncached; /**< Offset into the file excluding the cached data. */ + + /** + * CRC of the data read or written in the file. + * + * If reading, it's the CRC of all data read from the file, + * including the one in the buffer. + * If writing it's all the data wrote to the file, + * excluding the one still in buffer yet to be written. + */ + uint32_t crc; + + /** + * CRC of the file excluding the cached data in the buffer. + * + * If reading, it's the CRC of the data read from the file, + * excluding the one in the buffer. + * If writing it's all the data wrote to the file, + * excluding the one still in buffer yet to be written. + */ + uint32_t crc_uncached; + + /** + * CRC of the data written to the stream. + * + * This is an extra check of the data that is written to + * file to ensure that it's consistent even in case + * of memory errors. + * + * This extra check takes about 2 seconds for each GB of + * content file with the Intel CRC instruction, + * and about 4 seconds without it. + * But usually this doesn't slow down the write process, + * as the disk is the bottle-neck. + * + * Note that this CRC doesn't have the IV processing. + * + * Not used in reading. + * In writing, it's all the data wrote calling sput() functions. + */ + uint32_t crc_stream; +}; + +/** + * Opaque STREAM type. Like ::FILE. + */ +typedef struct stream STREAM; + +/** + * Open a stream for reading. Like fopen("r"). + */ +STREAM* sopen_read(const char* file); + +/** + * Open a stream for writing. Like fopen("w"). + */ +STREAM* sopen_write(const char* file); + +/** + * Open a set of streams for writing. Like fopen("w"). + */ +STREAM* sopen_multi_write(unsigned count); + +/** + * Specify the file to open. + */ +int sopen_multi_file(STREAM* s, unsigned i, const char* file); + +/** + * Close a stream. Like fclose(). + */ +int sclose(STREAM* s); + +/** + * Return the handle of the file. + * In case of multi file, the first one is returned. + */ +int shandle(STREAM* s); + +/** + * Read the stream until the end, and return the latest 4 chars. + * The CRC of the file is also computed, and you can get it using scrc(). + * \return 0 on success, or EOF on error. + */ +int sdeplete(STREAM* s, unsigned char* last); + +/** + * Flush the write stream buffer. + * \return 0 on success, or EOF on error. + */ +int sflush(STREAM* s); + +/** + * Get the file pointer. + */ +int64_t stell(STREAM* s); + +/** + * Get the CRC of the processed data. + */ +uint32_t scrc(STREAM* s); + +/** + * Get the CRC of the processed data in put. + */ +uint32_t scrc_stream(STREAM* s); + +/** + * Check if the buffer has enough data loaded. + */ +static inline int sptrlookup(STREAM* s, int size) +{ + return s->pos + size <= s->end; +} + +/** + * Get the current stream ptr. + */ +static inline unsigned char* sptrget(STREAM* s) +{ + return s->pos; +} + +/** + * Set the current stream ptr. + */ +static inline void sptrset(STREAM* s, unsigned char* ptr) +{ + s->pos = ptr; +} + +/** + * Check the error status. Like ferror(). + */ +static inline int serror(STREAM* s) +{ + return s->state == STREAM_STATE_ERROR; +} + +/** + * Check the eof status. Like feof(). + */ +static inline int seof(STREAM* s) +{ + return s->state == STREAM_STATE_EOF; +} + +/** + * Get the index of the handle that caused the error. + */ +static inline int serrorindex(STREAM* s) +{ + return s->state_index; +} + +/** + * Get the path of the handle that caused the error. + */ +static inline const char* serrorfile(STREAM* s) +{ + return s->handle[s->state_index].path; +} + +/** + * Sync the stream. Like fsync(). + */ +int ssync(STREAM* s); + +/****************************************************************************/ +/* get */ + +/** + * \internal Used by sgetc(). + * \note Don't call this directly, but use sgetc(). + */ +int sgetc_uncached(STREAM* s); + +/** + * Read a char. Like fgetc(). + */ +static inline int sgetc(STREAM* s) +{ + if (tommy_unlikely(s->pos == s->end)) + return sgetc_uncached(s); + return *s->pos++; +} + +/** + * Unread a char. + * Like ungetc() but you have to unget the same char read. + */ +static inline void sungetc(int c, STREAM* s) +{ + if (c != EOF) + --s->pos; +} + +/** + * Read a fixed amount of chars. + * Return 0 on success, or -1 on error. + */ +int sread(STREAM* f, void* void_data, unsigned size); + +/** + * Get a char from a stream, ignoring one '\r'. + */ +static inline int sgeteol(STREAM* f) +{ + int c; + + c = sgetc(f); + if (c == '\r') + c = sgetc(f); + + return c; +} + +/** + * Read all the spaces and tabs. + * Return the number of spaces and tabs read. + */ +static inline int sgetspace(STREAM* f) +{ + int count = 0; + int c; + + c = sgetc(f); + while (c == ' ' || c == '\t') { + ++count; + c = sgetc(f); + } + + sungetc(c, f); + return count; +} + +/** + * Read until the first space or tab. + * Stop at the first ' ', '\t', '\n' or EOF. + * Return <0 if the buffer is too small, or the number of chars read. + */ +int sgettok(STREAM* f, char* str, int size); + +/** + * Read until the end of line. + * Stop at the first '\n' or EOF. Note that '\n' is left in the stream. + * Return <0 if the buffer is too small, or the number of chars read. + */ +int sgetline(STREAM* f, char* str, int size); + +/** + * Like sgetline() but remove ' ' and '\t' at the end. + */ +int sgetlasttok(STREAM* f, char* str, int size); + +/** + * Read a 32 bit number. + * Stop at the first not digit char or EOF. + * Return <0 if there isn't enough to read. + */ +int sgetu32(STREAM* f, uint32_t* value); + +/****************************************************************************/ +/* binary get */ + +/** + * Read a binary 32 bit number in packet format. + * Return <0 if there isn't enough to read. + */ +int sgetb32(STREAM* f, uint32_t* value); + +/** + * Read a binary 64 bit number in packet format. + * Return <0 if there isn't enough to read. + */ +int sgetb64(STREAM* f, uint64_t* value); + +/** + * Read a binary 32 bit number in little endian format. + * Return <0 if there isn't enough to read. + */ +int sgetble32(STREAM* f, uint32_t* value); + +/** + * Read a binary string. + * Return -1 on error or if the buffer is too small, or the number of chars read. + */ +int sgetbs(STREAM* f, char* str, int size); + +/****************************************************************************/ +/* put */ + +/** + * Write a char. Like fputc(). + * Return 0 on success or -1 on error. + */ +static inline int sputc(int c, STREAM* s) +{ + if (s->pos == s->end) { + if (sflush(s) != 0) + return -1; + } + + /** + * Update the crc *before* writing the data in the buffer + * + * This must be done before the memory write, + * to be able to detect memory errors on the buffer, + * happening before we write it on the file. + */ + s->crc_stream = crc32c_plain_char(s->crc_stream, c); + + *s->pos++ = c; + + return 0; +} + +/** + * Write a end of line. + * Return 0 on success or -1 on error. + */ +static inline int sputeol(STREAM* s) +{ +#ifdef _WIN32 + if (sputc('\r', s) != 0) + return -1; +#endif + return sputc('\n', s); +} + +/** + * Write a sized string. + * Return 0 on success or -1 on error. + */ +int swrite(const void* data, unsigned size, STREAM* f); + +/****************************************************************************/ +/* binary put */ + +/** + * Write a binary 32 bit number in packed format. + * Return 0 on success or -1 on error. + */ +int sputb32(uint32_t value, STREAM* s); + +/** + * Write a binary 64 bit number in packed format. + * Return 0 on success or -1 on error. + */ +int sputb64(uint64_t value, STREAM* s); + +/** + * Write a binary 32 bit number in little endian format. + * Return 0 on success or -1 on error. + */ +int sputble32(uint32_t value, STREAM* s); + +/** + * Write a binary string. + * Return 0 on success or -1 on error. + */ +int sputbs(const char* str, STREAM* s); + +#endif + diff --git a/cmdline/support.c b/cmdline/support.c new file mode 100644 index 0000000..80dfa5c --- /dev/null +++ b/cmdline/support.c @@ -0,0 +1,1716 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "support.h" + +/****************************************************************************/ +/* lock */ + +/** + * Locks used externally. + */ +#if HAVE_PTHREAD +static pthread_mutex_t msg_lock; +static pthread_mutex_t memory_lock; +#endif + +void lock_msg(void) +{ +#if HAVE_PTHREAD + thread_mutex_lock(&msg_lock); +#endif +} + +void unlock_msg(void) +{ +#if HAVE_PTHREAD + thread_mutex_unlock(&msg_lock); +#endif +} + +void lock_memory(void) +{ +#if HAVE_PTHREAD + thread_mutex_lock(&memory_lock); +#endif +} + +void unlock_memory(void) +{ +#if HAVE_PTHREAD + thread_mutex_unlock(&memory_lock); +#endif +} + +void lock_init(void) +{ +#if HAVE_PTHREAD + /* initialize the locks as first operation as log_fatal depends on them */ + thread_mutex_init(&msg_lock, 0); + thread_mutex_init(&memory_lock, 0); +#endif +} + +void lock_done(void) +{ +#if HAVE_PTHREAD + thread_mutex_destroy(&msg_lock); + thread_mutex_destroy(&memory_lock); +#endif +} + +/****************************************************************************/ +/* print */ + +int msg_level = 0; + +/* + * Note that in the following functions we always flush both + * stdout and stderr, because we want to ensure that they mixes + * well when redirected to files + * + * The buffering is similar at the "line buffered" one, that + * is not available on Windows, so we emulate it in this way. + * + * For stdlog flushing is limited. To ensure flushing the + * caller should use log_flush(). + */ + +void log_fatal(const char* format, ...) +{ + va_list ap; + + lock_msg(); + + if (stdlog) { + va_start(ap, format); + fprintf(stdlog, "msg:fatal: "); + vfprintf(stdlog, format, ap); + fflush(stdlog); + va_end(ap); + } + + va_start(ap, format); + vfprintf(stderr, format, ap); + fflush(stderr); + va_end(ap); + + unlock_msg(); +} + +void log_error(const char* format, ...) +{ + va_list ap; + + lock_msg(); + + if (stdlog) { + va_start(ap, format); + fprintf(stdlog, "msg:error: "); + vfprintf(stdlog, format, ap); + fflush(stdlog); + va_end(ap); + } else { + va_start(ap, format); + vfprintf(stderr, format, ap); + fflush(stderr); + va_end(ap); + } + + unlock_msg(); +} + +void log_expected(const char* format, ...) +{ + va_list ap; + + lock_msg(); + + if (stdlog) { + va_start(ap, format); + fprintf(stdlog, "msg:expected: "); + vfprintf(stdlog, format, ap); + fflush(stdlog); + va_end(ap); + } + + unlock_msg(); +} + +void log_tag(const char* format, ...) +{ + va_list ap; + + lock_msg(); + + if (stdlog) { + va_start(ap, format); + vfprintf(stdlog, format, ap); + /* here we intentionally don't flush */ + /* to make the output faster */ + va_end(ap); + } + + unlock_msg(); +} + +void log_flush(void) +{ + lock_msg(); + + if (stdlog) + fflush(stdlog); + fflush(stdout); + fflush(stderr); + + unlock_msg(); +} + +void msg_status(const char* format, ...) +{ + va_list ap; + + lock_msg(); + + if (stdlog) { + va_start(ap, format); + fprintf(stdlog, "msg:status: "); + vfprintf(stdlog, format, ap); + fflush(stdlog); + va_end(ap); + } + + if (msg_level >= MSG_STATUS) { + va_start(ap, format); + vfprintf(stdout, format, ap); + fflush(stdout); + va_end(ap); + } + + unlock_msg(); +} + +void msg_info(const char* format, ...) +{ + va_list ap; + + lock_msg(); + + /* don't output in stdlog as these messages */ + /* are always paired with a msg_tag() call */ + + if (msg_level >= MSG_INFO) { + va_start(ap, format); + vfprintf(stdout, format, ap); + fflush(stdout); + va_end(ap); + } + + unlock_msg(); +} + +void msg_progress(const char* format, ...) +{ + va_list ap; + + lock_msg(); + + if (stdlog) { + va_start(ap, format); + fprintf(stdlog, "msg:progress: "); + vfprintf(stdlog, format, ap); + fflush(stdlog); + va_end(ap); + } + + if (msg_level >= MSG_PROGRESS) { + va_start(ap, format); + vfprintf(stdout, format, ap); + fflush(stdout); + va_end(ap); + } + + unlock_msg(); +} + +void msg_bar(const char* format, ...) +{ + va_list ap; + + lock_msg(); + + /* don't output in stdlog as these messages */ + /* are intended for screen only */ + /* also don't flush stdout as they are intended to be partial messages */ + + if (msg_level >= MSG_BAR) { + va_start(ap, format); + vfprintf(stdout, format, ap); + va_end(ap); + } + + unlock_msg(); +} + +void msg_verbose(const char* format, ...) +{ + va_list ap; + + lock_msg(); + + if (stdlog) { + va_start(ap, format); + fprintf(stdlog, "msg:verbose: "); + vfprintf(stdlog, format, ap); + fflush(stdlog); + va_end(ap); + } + + if (msg_level >= MSG_VERBOSE) { + va_start(ap, format); + vfprintf(stdout, format, ap); + fflush(stdout); + va_end(ap); + } + + unlock_msg(); +} + +void msg_flush(void) +{ + lock_msg(); + + fflush(stdout); + fflush(stderr); + + unlock_msg(); +} + +void printc(char c, size_t pad) +{ + while (pad) { + /* group writes in long pieces */ + char buf[128]; + size_t len = pad; + + if (len >= sizeof(buf)) + len = sizeof(buf) - 1; + + memset(buf, c, len); + buf[len] = 0; + + fputs(buf, stdout); + + pad -= len; + } +} + +void printr(const char* str, size_t pad) +{ + size_t len; + + len = strlen(str); + + if (len < pad) + printc(' ', pad - len); + + fputs(str, stdout); +} + +void printl(const char* str, size_t pad) +{ + size_t len; + + fputs(str, stdout); + + len = strlen(str); + + if (len < pad) + printc(' ', pad - len); +} + +void printp(double v, size_t pad) +{ + char buf[64]; + const char* s = "%"; + + if (v > 0.1) + snprintf(buf, sizeof(buf), "%5.2f%s", v, s); + else if (v > 0.01) + snprintf(buf, sizeof(buf), "%6.3f%s", v, s); + else if (v > 0.001) + snprintf(buf, sizeof(buf), "%7.4f%s", v, s); + else if (v > 0.0001) + snprintf(buf, sizeof(buf), "%8.5f%s", v, s); + else if (v > 0.00001) + snprintf(buf, sizeof(buf), "%9.6f%s", v, s); + else if (v > 0.000001) + snprintf(buf, sizeof(buf), "%10.7f%s", v, s); + else if (v > 0.0000001) + snprintf(buf, sizeof(buf), "%11.8f%s", v, s); + else if (v > 0.00000001) + snprintf(buf, sizeof(buf), "%12.9f%s", v, s); + else if (v > 0.000000001) + snprintf(buf, sizeof(buf), "%13.10f%s", v, s); + else if (v > 0.0000000001) + snprintf(buf, sizeof(buf), "%14.11f%s", v, s); + else if (v > 0.00000000001) + snprintf(buf, sizeof(buf), "%15.12f%s", v, s); + else if (v > 0.000000000001) + snprintf(buf, sizeof(buf), "%16.13f%s", v, s); + else + snprintf(buf, sizeof(buf), "%17.14f%s", v, s); + printl(buf, pad); +} + +#define ESCAPE(from,escape,to) \ + case from : \ + if (p == end) \ + goto bail; \ + *p++ = escape; \ + if (p == end) \ + goto bail; \ + *p++ = to; \ + break + +const char* esc_tag(const char* str, char* buffer) +{ + char* begin = buffer; + char* end = begin + ESC_MAX; + char* p = begin; + + /* copy string with escaping */ + while (*str) { + char c = *str; + + switch (c) { + + ESCAPE('\n', '\\', 'n'); + ESCAPE('\r', '\\', 'r'); + ESCAPE(':', '\\', 'd'); + ESCAPE('\\', '\\', '\\'); + + default: + if (p == end) + goto bail; + *p++ = c; + break; + } + + ++str; + } + + /* put final 0 */ + if (p == end) + goto bail; + *p = 0; + + return begin; + +bail: + /* LCOV_EXCL_START */ + log_fatal("Escape for log too long\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ +} + +const char* esc_shell_multi(const char** str_map, unsigned str_max, char* buffer) +{ + char* begin = buffer; + char* end = begin + ESC_MAX; + char* p = begin; + unsigned str_mac; + const char* str; + +#ifdef _WIN32 + int has_quote = 0; + + for (str_mac = 0; str_mac < str_max; ++str_mac) { + str = str_map[str_mac]; + if (strchr(str, ' ') != 0) + has_quote = 1; + } + + if (has_quote) { + if (p == end) + goto bail; + *p++ = '"'; + } +#endif + + /* copy string with escaping */ + str_mac = 0; + str = str_map[str_mac]; + while (1) { + /* get the next char */ + char c = *str; + + /* if one string is finished, go to the next */ + while (c == 0 && str_mac + 1 < str_max) { + ++str_mac; + str = str_map[str_mac]; + c = *str; + } + + /* if we read all the strings, stop */ + if (!c) + break; + + switch (c) { +#ifdef _WIN32 + /* + * Windows shell escape + * + * The Windows NT Command Shell + * https://technet.microsoft.com/en-us/library/cc723564.aspx + */ + case '"' : + /* double quote, it needs to be quoted with \ */ + if (has_quote) { + /* " -> "\"" -> (close quote)(quoted with \ ")(reopen quote) */ + if (p == end) + goto bail; + *p++ = '"'; + if (p == end) + goto bail; + *p++ = '\\'; + if (p == end) + goto bail; + *p++ = '"'; + if (p == end) + goto bail; + *p++ = '"'; + } else { + /* " -> \" */ + if (p == end) + goto bail; + *p++ = '\\'; + if (p == end) + goto bail; + *p++ = '"'; + } + break; + case '&' : + case '|' : + case '(' : + case ')' : + case '<' : + case '>' : + case '^' : + /* reserved chars, they need to be quoted with ^ */ + if (has_quote) { + if (p == end) + goto bail; + *p++ = c; + } else { + if (p == end) + goto bail; + *p++ = '^'; + if (p == end) + goto bail; + *p++ = c; + } + break; +#else + /* special chars that need to be quoted */ + case ' ' : /* space */ + case '~' : /* home */ + case '`' : /* command */ + case '#' : /* comment */ + case '$' : /* variable */ + case '&' : /* background job */ + case '*' : /* wildcard */ + case '(' : /* shell */ + case ')' : /* shell */ + case '\\': /* quote */ + case '|' : /* pipe */ + case '[' : /* wildcard */ + case ']' : /* wildcard */ + case '{' : /* code */ + case '}' : /* code */ + case ';' : /* separator */ + case '\'': /* quote */ + case '"' : /* quote */ + case '<' : /* redirect */ + case '>' : /* redirect */ + case '?' : /* wildcard */ + if (p == end) + goto bail; + *p++ = '\\'; + if (p == end) + goto bail; + *p++ = c; + break; +#endif + default : + /* unquoted */ + if (p == end) + goto bail; + *p++ = c; + break; + } + + ++str; + } + +#ifdef _WIN32 + if (has_quote) { + if (p == end) + goto bail; + *p++ = '"'; + } +#endif + + /* put final 0 */ + if (p == end) + goto bail; + *p = 0; + + return begin; + +bail: + /* LCOV_EXCL_START */ + log_fatal("Escape for shell too long\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ +} + +char* strpolish(char* s) +{ + char* i = s; + + while (*i) { + if (isspace(*i) || !isprint(*i)) + *i = ' '; + ++i; + } + + return s; +} + +unsigned strsplit(char** split_map, unsigned split_max, char* str, const char* delimiters) +{ + unsigned mac = 0; + + /* skip initial delimiters */ + str += strspn(str, delimiters); + + while (*str != 0 || mac == split_max) { + /* start of the token */ + split_map[mac] = str; + ++mac; + + /* find the first delimiter or the end of the string */ + str += strcspn(str, delimiters); + + /* put the final terminator if missing */ + if (*str != 0) + *str++ = 0; + + /* skip trailing delimiters */ + str += strspn(str, delimiters); + } + + return mac; +} + +/****************************************************************************/ +/* path */ + +void pathcpy(char* dst, size_t size, const char* src) +{ + size_t len = strlen(src); + + if (len + 1 > size) { + /* LCOV_EXCL_START */ + log_fatal("Path too long '%s'\n", src); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + memcpy(dst, src, len + 1); +} + +void pathcat(char* dst, size_t size, const char* src) +{ + size_t dst_len = strlen(dst); + size_t src_len = strlen(src); + + if (dst_len + src_len + 1 > size) { + /* LCOV_EXCL_START */ + log_fatal("Path too long '%s%s'\n", dst, src); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + memcpy(dst + dst_len, src, src_len + 1); +} + +void pathcatc(char* dst, size_t size, char c) +{ + size_t dst_len = strlen(dst); + + if (dst_len + 2 > size) { + /* LCOV_EXCL_START */ + log_fatal("Path too long '%s%c'\n", dst, c); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + dst[dst_len] = c; + dst[dst_len + 1] = 0; +} + +void pathimport(char* dst, size_t size, const char* src) +{ + pathcpy(dst, size, src); + +#ifdef _WIN32 + /* convert the Windows dir separator '\' to C '/', */ + /* and the Windows escaping char '^' to the fnmatch '\' */ + while (*dst) { + switch (*dst) { + case '\\' : + *dst = '/'; + break; + case '^' : + *dst = '\\'; + break; + } + ++dst; + } +#endif +} + +void pathexport(char* dst, size_t size, const char* src) +{ + pathcpy(dst, size, src); + +#ifdef _WIN32 + /* invert the import */ + while (*dst) { + switch (*dst) { + case '/' : + *dst = '\\'; + break; + case '\\' : + *dst = '^'; + break; + } + ++dst; + } +#endif +} + +void pathprint(char* dst, size_t size, const char* format, ...) +{ + size_t len; + va_list ap; + + va_start(ap, format); + len = vsnprintf(dst, size, format, ap); + va_end(ap); + + if (len >= size) { + /* LCOV_EXCL_START */ + if (size > 0) { + dst[size - 1] = 0; + log_fatal("Path too long '%s...'\n", dst); + } else { + log_fatal("Path too long for empty size'\n"); + } + os_abort(); + /* LCOV_EXCL_STOP */ + } +} + +void pathslash(char* dst, size_t size) +{ + size_t len = strlen(dst); + + if (len > 0 && dst[len - 1] != '/') { + if (len + 2 >= size) { + /* LCOV_EXCL_START */ + log_fatal("Path too long '%s/'\n", dst); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + dst[len] = '/'; + dst[len + 1] = 0; + } +} + +void pathcut(char* dst) +{ + char* slash = strrchr(dst, '/'); + + if (slash) + slash[1] = 0; + else + dst[0] = 0; +} + +int pathcmp(const char* a, const char* b) +{ +#ifdef _WIN32 + char ai[PATH_MAX]; + char bi[PATH_MAX]; + + /* import to convert \ to / */ + pathimport(ai, sizeof(ai), a); + pathimport(bi, sizeof(bi), b); + + /* case insensitive compare in Windows */ + return stricmp(ai, bi); +#else + return strcmp(a, b); +#endif +} + +/****************************************************************************/ +/* file-system */ + +int mkancestor(const char* file) +{ + char dir[PATH_MAX]; + struct stat st; + char* c; + + pathcpy(dir, sizeof(dir), file); + + c = strrchr(dir, '/'); + if (!c) { + /* no ancestor */ + return 0; + } + + /* clear the file */ + *c = 0; + + /* if it's the root dir */ + if (*dir == 0) { + /* nothing more to do */ + return 0; + } + +#ifdef _WIN32 + /* if it's a drive specificaion like "C:" */ + if (isalpha(dir[0]) && dir[1] == ':' && dir[2] == 0) { + /* nothing more to do */ + return 0; + } +#endif + + /* + * Check if the dir already exists using lstat(). + * + * Note that in Windows when dealing with read-only media + * you cannot try to create the directory, and expecting + * the EEXIST error because the call will fail with ERROR_WRITE_PROTECTED. + * + * Also in Windows it's better to use lstat() than stat() because it + * doesn't need to open the dir with CreateFile(). + */ + if (lstat(dir, &st) == 0) { + /* it already exists */ + return 0; + } + + /* recursively create them all */ + if (mkancestor(dir) != 0) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + + /* create it */ + if (mkdir(dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error creating directory '%s'. %s.\n", dir, strerror(errno)); + return -1; + /* LCOV_EXCL_STOP */ + } + + return 0; +} + +int fmtime(int f, int64_t mtime_sec, int mtime_nsec) +{ +#if HAVE_FUTIMENS + struct timespec tv[2]; +#else + struct timeval tv[2]; +#endif + int ret; + +#if HAVE_FUTIMENS /* futimens() is preferred because it gives nanosecond precision */ + tv[0].tv_sec = mtime_sec; + if (mtime_nsec != STAT_NSEC_INVALID) + tv[0].tv_nsec = mtime_nsec; + else + tv[0].tv_nsec = 0; + tv[1].tv_sec = tv[0].tv_sec; + tv[1].tv_nsec = tv[0].tv_nsec; + + ret = futimens(f, tv); +#elif HAVE_FUTIMES /* fallback to futimes() if nanosecond precision is not available */ + tv[0].tv_sec = mtime_sec; + if (mtime_nsec != STAT_NSEC_INVALID) + tv[0].tv_usec = mtime_nsec / 1000; + else + tv[0].tv_usec = 0; + tv[1].tv_sec = tv[0].tv_sec; + tv[1].tv_usec = tv[0].tv_usec; + + ret = futimes(f, tv); +#elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */ + tv[0].tv_sec = mtime_sec; + if (mtime_nsec != STAT_NSEC_INVALID) + tv[0].tv_usec = mtime_nsec / 1000; + else + tv[0].tv_usec = 0; + tv[1].tv_sec = tv[0].tv_sec; + tv[1].tv_usec = tv[0].tv_usec; + + ret = futimesat(f, 0, tv); +#else +#error No function available to set file timestamps with sub-second precision +#endif + + return ret; +} + +int lmtime(const char* path, int64_t mtime_sec, int mtime_nsec) +{ +#if HAVE_UTIMENSAT + struct timespec tv[2]; +#else + struct timeval tv[2]; +#endif + int ret; + +#if HAVE_UTIMENSAT /* utimensat() is preferred because it gives nanosecond precision */ + tv[0].tv_sec = mtime_sec; + if (mtime_nsec != STAT_NSEC_INVALID) + tv[0].tv_nsec = mtime_nsec; + else + tv[0].tv_nsec = 0; + tv[1].tv_sec = tv[0].tv_sec; + tv[1].tv_nsec = tv[0].tv_nsec; + + ret = utimensat(AT_FDCWD, path, tv, AT_SYMLINK_NOFOLLOW); +#elif HAVE_LUTIMES /* fallback to lutimes() if nanosecond precision is not available */ + tv[0].tv_sec = mtime_sec; + if (mtime_nsec != STAT_NSEC_INVALID) + tv[0].tv_usec = mtime_nsec / 1000; + else + tv[0].tv_usec = 0; + tv[1].tv_sec = tv[0].tv_sec; + tv[1].tv_usec = tv[0].tv_usec; + + ret = lutimes(path, tv); +#elif HAVE_FUTIMESAT /* fallback to futimesat() for Solaris, it only has futimesat() */ + tv[0].tv_sec = mtime_sec; + if (mtime_nsec != STAT_NSEC_INVALID) + tv[0].tv_usec = mtime_nsec / 1000; + else + tv[0].tv_usec = 0; + tv[1].tv_sec = tv[0].tv_sec; + tv[1].tv_usec = tv[0].tv_usec; + + ret = futimesat(AT_FDCWD, path, tv); +#else +#error No function available to set file timestamps with sub-second precision +#endif + + return ret; +} + +/****************************************************************************/ +/* advise */ + +void advise_init(struct advise_struct* advise, int mode) +{ + advise->mode = mode; + advise->dirty_begin = 0; + advise->dirty_end = 0; +} + +int advise_flags(struct advise_struct* advise) +{ + int flags = 0; + + if (advise->mode == ADVISE_SEQUENTIAL + || advise->mode == ADVISE_FLUSH + || advise->mode == ADVISE_FLUSH_WINDOW + || advise->mode == ADVISE_DISCARD + || advise->mode == ADVISE_DISCARD_WINDOW + ) + flags |= O_SEQUENTIAL; + +#if HAVE_DIRECT_IO + if (advise->mode == ADVISE_DIRECT) + flags |= O_DIRECT; +#endif + + return flags; +} + +int advise_open(struct advise_struct* advise, int f) +{ + (void)advise; + (void)f; + +#if HAVE_POSIX_FADVISE + if (advise->mode == ADVISE_SEQUENTIAL + || advise->mode == ADVISE_FLUSH + || advise->mode == ADVISE_FLUSH_WINDOW + || advise->mode == ADVISE_DISCARD + || advise->mode == ADVISE_DISCARD_WINDOW + ) { + int ret; + + /* advise sequential access */ + ret = posix_fadvise(f, 0, 0, POSIX_FADV_SEQUENTIAL); + if (ret == ENOSYS) { + /* call is not supported, like in armhf, see posix_fadvise manpage */ + ret = 0; + } + if (ret != 0) { + /* LCOV_EXCL_START */ + errno = ret; /* posix_fadvise return the error code */ + return -1; + /* LCOV_EXCL_STOP */ + } + } +#endif + + return 0; +} + +int advise_write(struct advise_struct* advise, int f, data_off_t offset, data_off_t size) +{ + data_off_t flush_offset; + data_off_t flush_size; + data_off_t discard_offset; + data_off_t discard_size; + + (void)f; + (void)flush_offset; + (void)flush_size; + (void)discard_offset; + (void)discard_size; + + flush_offset = 0; + flush_size = 0; + discard_offset = 0; + discard_size = 0; + + /* + * Follow Linus recommendations about fast writes. + * + * Linus "Unexpected splice "always copy" behavior observed" + * http://thread.gmane.org/gmane.linux.kernel/987247/focus=988070 + * --- + * I have had _very_ good experiences with even a rather trivial + * file writer that basically used (iirc) 8MB windows, and the logic was very + * trivial: + * + * - before writing a new 8M window, do "start writeback" + * (SYNC_FILE_RANGE_WRITE) on the previous window, and do + * a wait (SYNC_FILE_RANGE_WAIT_AFTER) on the window before that. + * + * in fact, in its simplest form, you can do it like this (this is from my + * "overwrite disk images" program that I use on old disks): + * + * for (index = 0; index < max_index ;index++) { + * if (write(fd, buffer, BUFSIZE) != BUFSIZE) + * break; + * // This won't block, but will start writeout asynchronously + * sync_file_range(fd, index*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WRITE); + * // This does a blocking write-and-wait on any old ranges + * if (index) + * sync_file_range(fd, (index-1)*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER); + * } + * + * and even if you don't actually do a discard (maybe we should add a + * SYNC_FILE_RANGE_DISCARD bit, right now you'd need to do a separate + * fadvise(FADV_DONTNEED) to throw it out) the system behavior is pretty + * nice, because the heavy writer gets good IO performance _and_ leaves only + * easy-to-free pages around after itself. + * --- + * + * Linus "Unexpected splice "always copy" behavior observed" + * http://thread.gmane.org/gmane.linux.kernel/987247/focus=988176 + * --- + * The behavior for dirty page writeback is _not_ well defined, and + * if you do POSIX_FADV_DONTNEED, I would suggest you do it as part of that + * writeback logic, ie you do it only on ranges that you have just waited on. + * + * IOW, in my example, you'd couple the + * + * sync_file_range(fd, (index-1)*BUFSIZE, BUFSIZE, SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE|SYNC_FILE_RANGE_WAIT_AFTER); + * + * with a + * + * posix_fadvise(fd, (index-1)*BUFSIZE, BUFSIZE, POSIX_FADV_DONTNEED); + * + * afterwards to throw out the pages that you just waited for. + * --- + */ + + switch (advise->mode) { + case ADVISE_FLUSH : + flush_offset = offset; + flush_size = size; + break; + case ADVISE_DISCARD : + discard_offset = offset; + discard_size = size; + break; + case ADVISE_FLUSH_WINDOW : + /* if the dirty range can be extended */ + if (advise->dirty_end == offset) { + /* extent the dirty range */ + advise->dirty_end += size; + + /* if we reached the window size */ + if (advise->dirty_end - advise->dirty_begin >= ADVISE_WINDOW_SIZE) { + /* flush the window */ + flush_offset = advise->dirty_begin; + flush_size = ADVISE_WINDOW_SIZE; + + /* remove it from the dirty range */ + advise->dirty_begin += ADVISE_WINDOW_SIZE; + } + } else { + /* otherwise flush the existing dirty */ + flush_offset = advise->dirty_begin; + flush_size = advise->dirty_end - advise->dirty_begin; + + /* and set the new range as dirty */ + advise->dirty_begin = offset; + advise->dirty_end = offset + size; + } + break; + case ADVISE_DISCARD_WINDOW : + /* if the dirty range can be extended */ + if (advise->dirty_end == offset) { + /* extent the dirty range */ + advise->dirty_end += size; + + /* if we reached the double window size */ + if (advise->dirty_end - advise->dirty_begin >= 2 * ADVISE_WINDOW_SIZE) { + /* discard the first window */ + discard_offset = advise->dirty_begin; + discard_size = ADVISE_WINDOW_SIZE; + + /* remove it from the dirty range */ + advise->dirty_begin += ADVISE_WINDOW_SIZE; + + /* flush the second window */ + flush_offset = advise->dirty_begin; + flush_size = ADVISE_WINDOW_SIZE; + } + } else { + /* otherwise discard the existing dirty */ + discard_offset = advise->dirty_begin; + discard_size = advise->dirty_end - advise->dirty_begin; + + /* and set the new range as dirty */ + advise->dirty_begin = offset; + advise->dirty_end = offset + size; + } + break; + } + +#if HAVE_SYNC_FILE_RANGE + if (flush_size != 0) { + int ret; + + /* start writing immediately */ + ret = sync_file_range(f, flush_offset, flush_size, SYNC_FILE_RANGE_WRITE); + if (ret != 0) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + } +#endif + +#if HAVE_SYNC_FILE_RANGE && HAVE_POSIX_FADVISE + if (discard_size != 0) { + int ret; + + /* send the data to the disk and wait until it's written */ + ret = sync_file_range(f, discard_offset, discard_size, SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE | SYNC_FILE_RANGE_WAIT_AFTER); + if (ret != 0) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + + /* flush the data from the cache */ + ret = posix_fadvise(f, discard_offset, discard_size, POSIX_FADV_DONTNEED); + /* for POSIX_FADV_DONTNEED we don't allow failure with ENOSYS */ + if (ret != 0) { + /* LCOV_EXCL_START */ + errno = ret; /* posix_fadvise return the error code */ + return -1; + /* LCOV_EXCL_STOP */ + } + } +#endif + + return 0; +} + +int advise_read(struct advise_struct* advise, int f, data_off_t offset, data_off_t size) +{ + (void)advise; + (void)f; + (void)offset; + (void)size; + +#if HAVE_POSIX_FADVISE + if (advise->mode == ADVISE_DISCARD + || advise->mode == ADVISE_DISCARD_WINDOW + ) { + int ret; + + /* flush the data from the cache */ + ret = posix_fadvise(f, offset, size, POSIX_FADV_DONTNEED); + /* for POSIX_FADV_DONTNEED we don't allow failure with ENOSYS */ + if (ret != 0) { + /* LCOV_EXCL_START */ + errno = ret; /* posix_fadvise return the error code */ + return -1; + /* LCOV_EXCL_STOP */ + } + } +#endif + + /* + * Here we cannot call posix_fadvise(..., POSIX_FADV_WILLNEED) for the next block + * because it may be blocking. + * + * Ted Ts'o "posix_fadvise(POSIX_FADV_WILLNEED) waits before returning?" + * https://lkml.org/lkml/2010/12/6/122 + * --- + * readahead and posix_fadvise(POSIX_FADV_WILLNEED) work exactly the same + * way, and in fact share mostly the same code path (see + * force_page_cache_readahead() in mm/readahead.c). + * + * They are asynchronous in that there is no guarantee the pages will be + * in the page cache by the time they return. But at the same time, they + * are not guaranteed to be non-blocking. That is, the work of doing the + * readahead does not take place in a kernel thread. So if you try to + * request I/O than will fit in the request queue, the system call will + * block until some I/O is completed so that more I/O requested cam be + * loaded onto the request queue. + * + * The only way to fix this would be to either put the work on a kernel + * thread (i.e., some kind of workqueue) or in a userspace thread. For + * ion programmer wondering what to do today, I'd suggest the + * latter since it will be more portable across various kernel versions. + * + * This does leave the question about whether we should change the kernel + * to allow readahead() and posix_fadvise(POSIX_FADV_WILLNEED) to be + * non-blocking and do this work in a workqueue (or via some kind of + * callback/continuation scheme). My worry is just doing this if a user + * application does something crazy, like request gigabytes and gigabytes + * of readahead, and then repents of their craziness, there should be a + * way of cancelling the readahead request. Today, the user can just + * kill the application. But if we simply shove the work to a kernel + * thread, it becomes a lot harder to cancel the readahead request. We'd + * have to invent a new API, and then have a way to know whether the user + * has access to kill a particular readahead request, etc. + * --- + */ + + return 0; +} + +/****************************************************************************/ +/* memory */ + +/** + * Total amount of memory allocated. + */ +static size_t mcounter; + +size_t malloc_counter_get(void) +{ + size_t ret; + + lock_memory(); + + ret = mcounter; + + unlock_memory(); + + return ret; +} + +void malloc_counter_inc(size_t inc) +{ + lock_memory(); + + mcounter += inc; + + unlock_memory(); +} + +/* LCOV_EXCL_START */ +static ssize_t malloc_print(int f, const char* str) +{ + ssize_t len = 0; + + while (str[len]) + ++len; + return write(f, str, len); +} +/* LCOV_EXCL_STOP */ + +/* LCOV_EXCL_START */ +static ssize_t malloc_printn(int f, size_t value) +{ + char buf[32]; + int i; + + if (!value) + return write(f, "0", 1); + + i = sizeof(buf); + while (value) { + buf[--i] = (value % 10) + '0'; + value /= 10; + } + + return write(f, buf + i, sizeof(buf) - i); +} +/* LCOV_EXCL_STOP */ + +/* LCOV_EXCL_START */ +void malloc_fail(size_t size) +{ + /* don't use printf to avoid any possible extra allocation */ + int f = 2; /* stderr */ + + malloc_print(f, "Failed for Low Memory!\n"); + malloc_print(f, "Allocating "); + malloc_printn(f, size); + malloc_print(f, " bytes.\n"); + malloc_print(f, "Already allocated "); + malloc_printn(f, malloc_counter_get()); + malloc_print(f, " bytes.\n"); + if (sizeof(void*) == 4) { + malloc_print(f, "You are currently using a 32 bits executable.\n"); + malloc_print(f, "If you have more than 4GB of memory, please upgrade to a 64 bits one.\n"); + } +} +/* LCOV_EXCL_STOP */ + +void* malloc_nofail(size_t size) +{ + void* ptr = malloc(size); + + if (!ptr) { + /* LCOV_EXCL_START */ + malloc_fail(size); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + +#ifndef CHECKER /* Don't preinitialize when running for valgrind */ + /* Here we preinitialize the memory to ensure that the OS is really allocating it */ + /* and not only reserving the addressable space. */ + /* Otherwise we are risking that the OOM (Out Of Memory) killer in Linux will kill the process. */ + /* Filling the memory doesn't ensure to disable OOM, but it increase a lot the chances to */ + /* get a real error from malloc() instead than a process killed. */ + /* Note that calloc() doesn't have the same effect. */ + memset(ptr, 0xA5, size); +#endif + + malloc_counter_inc(size); + + return ptr; +} + +void* calloc_nofail(size_t count, size_t size) +{ + void* ptr; + + size *= count; + + /* see the note in malloc_nofail() of why we don't use calloc() */ + ptr = malloc(size); + + if (!ptr) { + /* LCOV_EXCL_START */ + malloc_fail(size); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + memset(ptr, 0, size); + + malloc_counter_inc(size); + + return ptr; +} + +char* strdup_nofail(const char* str) +{ + size_t size; + char* ptr; + + size = strlen(str) + 1; + + ptr = malloc(size); + + if (!ptr) { + /* LCOV_EXCL_START */ + malloc_fail(size); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + memcpy(ptr, str, size); + + malloc_counter_inc(size); + + return ptr; +} + +/****************************************************************************/ +/* smartctl */ + +/** + * Match a string with the specified pattern. + * Like sscanf() a space match any sequence of spaces. + * Return 0 if it matches. + */ +static int smatch(const char* str, const char* pattern) +{ + while (*pattern) { + if (isspace(*pattern)) { + ++pattern; + while (isspace(*str)) + ++str; + } else if (*pattern == *str) { + ++pattern; + ++str; + } else + return -1; + } + + return 0; +} + +int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* smart, char* serial, char* vendor, char* model) +{ + unsigned i; + int inside; + + /* preclear attribute */ + *serial = 0; + for (i = 0; i < SMART_COUNT; ++i) + smart[i] = SMART_UNASSIGNED; + + /* read the file */ + inside = 0; + while (1) { + char buf[256]; + unsigned id; + uint64_t raw; + char* s; + + s = fgets(buf, sizeof(buf), f); + if (s == 0) + break; + + /* remove extraneous chars */ + s = strpolish(buf); + + log_tag("smartctl:%s:%s:out: %s\n", file, name, s); + + /* skip initial spaces */ + while (isspace(*s)) + ++s; + + if (*s == 0) { + inside = 0; + /* common */ + } else if (smatch(s, "Rotation Rate: Solid State") == 0) { + smart[SMART_ROTATION_RATE] = 0; + } else if (sscanf(s, "Rotation Rate: %" SCNu64, &smart[SMART_ROTATION_RATE]) == 1) { + } else if (smatch(s, "User Capacity:") == 0) { + char* begin = strchr(s, ':'); + char* end = strstr(s, "bytes"); + if (begin != 0 && end != 0 && begin < end) { + char* p; + smart[SMART_SIZE] = 0; + for (p = begin; p != end; ++p) { + if (isdigit(*p)) { + smart[SMART_SIZE] *= 10; + smart[SMART_SIZE] += *p - '0'; + } + } + } + } else if (sscanf(s, "Device Model: %63s %63s", vendor, model) == 2) { + } else if (sscanf(s, "Device Model: %63s", model) == 1) { + /* SCSI */ + } else if (sscanf(s, "Serial number: %63s", serial) == 1) { /* note "n" of "number" lower case */ + } else if (sscanf(s, "Elements in grown defect list: %" SCNu64, &smart[SMART_REALLOCATED_SECTOR_COUNT]) == 1) { + } else if (sscanf(s, "Current Drive Temperature: %" SCNu64, &smart[SMART_TEMPERATURE_CELSIUS]) == 1) { + } else if (sscanf(s, "Drive Trip Temperature: %" SCNu64, &smart[SMART_AIRFLOW_TEMPERATURE_CELSIUS]) == 1) { + } else if (sscanf(s, "Accumulated start-stop cycles: %" SCNu64, &smart[SMART_START_STOP_COUNT]) == 1) { + } else if (sscanf(s, "Accumulated load-unload cycles: %" SCNu64, &smart[SMART_LOAD_CYCLE_COUNT]) == 1) { + } else if (sscanf(s, " number of hours powered up = %" SCNu64, &smart[SMART_POWER_ON_HOURS]) == 1) { + /* ATA */ + } else if (sscanf(s, "Serial Number: %63s", serial) == 1) { + } else if (smatch(s, "ID#") == 0) { + inside = 1; + } else if (smatch(s, "No Errors Logged") == 0) { + smart[SMART_ERROR] = 0; + } else if (sscanf(s, "ATA Error Count: %" SCNu64, &raw) == 1) { + smart[SMART_ERROR] = raw; + } else if (inside) { + if (sscanf(s, "%u %*s %*s %*s %*s %*s %*s %*s %*s %" SCNu64, &id, &raw) != 2) { + /* LCOV_EXCL_START */ + log_fatal("Invalid smartctl line '%s'.\n", s); + return -1; + /* LCOV_EXCL_STOP */ + } + + if (id >= 256) { + /* LCOV_EXCL_START */ + log_fatal("Invalid SMART id '%u'.\n", id); + return -1; + /* LCOV_EXCL_STOP */ + } + + smart[id] = raw; + } + } + + return 0; +} + +int smartctl_flush(FILE* f, const char* file, const char* name) +{ + /* read the file */ + while (1) { + char buf[256]; + char* s; + + s = fgets(buf, sizeof(buf), f); + if (s == 0) + break; + + /* remove extraneous chars */ + s = strpolish(buf); + + log_tag("smartctl:%s:%s:out: %s\n", file, name, s); + } + + return 0; +} + +/****************************************************************************/ +/* thread */ + +#if HAVE_PTHREAD +void thread_mutex_init(pthread_mutex_t* mutex, pthread_mutexattr_t* attr) +{ + if (pthread_mutex_init(mutex, attr) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed call to pthread_mutex_init().\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } +} + +void thread_mutex_destroy(pthread_mutex_t* mutex) +{ + if (pthread_mutex_destroy(mutex) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed call to pthread_mutex_destroy().\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } +} + +void thread_mutex_lock(pthread_mutex_t* mutex) +{ + if (pthread_mutex_lock(mutex) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed call to pthread_mutex_lock().\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } +} + +void thread_mutex_unlock(pthread_mutex_t* mutex) +{ + if (pthread_mutex_unlock(mutex) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed call to pthread_mutex_unlock().\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } +} + +void thread_cond_init(pthread_cond_t* cond, pthread_condattr_t* attr) +{ + if (pthread_cond_init(cond, attr) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed call to pthread_cond_init().\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } +} + +void thread_cond_destroy(pthread_cond_t* cond) +{ + if (pthread_cond_destroy(cond) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed call to pthread_cond_destroy().\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } +} + +void thread_cond_signal(pthread_cond_t* cond) +{ + if (pthread_cond_signal(cond) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed call to pthread_cond_signal().\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } +} + +void thread_cond_broadcast(pthread_cond_t* cond) +{ + if (pthread_cond_broadcast(cond) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed call to pthread_cond_broadcast().\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } +} + +void thread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex) +{ + if (pthread_cond_wait(cond, mutex) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed call to pthread_cond_wait().\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } +} + +/** + * Implementation note about conditional variables. + * + * The conditional variables can be signaled inside or ouside the mutex, + * what is better it's debatable but in general doing that ouside the mutex, + * reduces the number of context switches. + * + * But when when testing with helgrind and drd, this disallows such tools to + * to see the dependency between the signal and the wait. + * + * To avoid it we signal everything inside the mutex. And we do this in both + * test mode (with CHERCKER defined) and release mode (CHECKER not defined), + * to be on the safe side and avoid any difference in beaviour between test and + * release. + * + * Here some interesting discussion: + * + * Condvars: signal with mutex locked or not? + * http://www.domaigne.com/blog/computing/condvars-signal-with-mutex-locked-or-not/ + * + * Calling pthread_cond_signal without locking mutex + * http://stackoverflow.com/questions/4544234/calling-pthread-cond-signal-without-locking-mutex/4544494#4544494 + */ + +/** + * Control when to signal the condition variables. + */ +int thread_cond_signal_outside = 0; + +void thread_cond_signal_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex) +{ + if (thread_cond_signal_outside) { + /* without the thread checker unlock before signaling, */ + /* this reduces the number of context switches */ + thread_mutex_unlock(mutex); + } + + thread_cond_signal(cond); + + if (!thread_cond_signal_outside) { + /* with the thread checker unlock after signaling */ + /* to make explicit the condition and mutex relation */ + thread_mutex_unlock(mutex); + } +} + +void thread_cond_broadcast_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex) +{ + if (thread_cond_signal_outside) { + /* without the thread checker unlock before signaling, */ + /* this reduces the number of context switches */ + thread_mutex_unlock(mutex); + } + + thread_cond_broadcast(cond); + + if (!thread_cond_signal_outside) { + /* with the thread checker unlock after signaling */ + /* to make explicit the condition and mutex relation */ + thread_mutex_unlock(mutex); + } +} + +void thread_create(pthread_t* thread, pthread_attr_t* attr, void *(* func)(void *), void *arg) +{ + if (pthread_create(thread, attr, func, arg) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed call to pthread_create().\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } +} + +void thread_join(pthread_t thread, void** retval) +{ + if (pthread_join(thread, retval) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed call to pthread_join().\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } +} + +#endif + diff --git a/cmdline/support.h b/cmdline/support.h new file mode 100644 index 0000000..9cdf220 --- /dev/null +++ b/cmdline/support.h @@ -0,0 +1,437 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#ifndef __SUPPORT_H +#define __SUPPORT_H + +/****************************************************************************/ +/* lock */ + +/** + * Initialize and destroy the locks. + */ +void lock_init(void); +void lock_done(void); + +/** + * Lock used for printf. + * + * In Windows printf() is not atomic, and multiple threads + * will have output interleaved. + * + * Note that even defining __USE_MINGW_ANSI_STDIO the problem persists. + * + * See for example: + * + * Weird output when I use pthread and printf. + * http://stackoverflow.com/questions/13190254/weird-output-when-i-use-pthread-and-printf + * + * This is also required in other OS because we split output in stdlog in + * two fprintf calls. + */ +void lock_msg(void); +void unlock_msg(void); + +/** + * Lock used for memory counter. + */ +void lock_memory(void); +void unlock_memory(void); + +/****************************************************************************/ +/* log */ + +/** + * Fatal error messages. + * + * Messages printed before an early termination. + * + * These messages go in the log file and in stderr unconditionally. + */ +void log_fatal(const char* format, ...) __attribute__((format(attribute_printf, 1, 2))); + +/** + * Unexpected error messages. + * + * Messages reporting error conditions that don't prevent the program to run. + * + * Some of them could be also serious errors, like "silent errors". + * In such case, the summary result is always printed as error, + * and we are sure to notify the user in some way. + * + * These messages go in the log file if specified, otherwise they go in stderr. + */ +void log_error(const char* format, ...) __attribute__((format(attribute_printf, 1, 2))); + +/** + * Expected error messages, without fallback to stderr. + * + * These errors are "someway" expected, and then they never go to screen. + * For example, when undeleting missing files, the messages for missing files + * are not shown. + * + * These messages go in the log file if specified, otherwise they are lost. + */ +void log_expected(const char* format, ...) __attribute__((format(attribute_printf, 1, 2))); + +/** + * Tag messages. + * + * Messages are in tag format, like "tag:entry:...". + * + * These messages never go on the screen, but only in the log file if specified. + * + * Note that this function, allows not \n terminated strings. + * + * These messages are buffered. Use msg_flush() to flush them. + */ +void log_tag(const char* format, ...) __attribute__((format(attribute_printf, 1, 2))); + +/** + * Flush the log. + */ +void log_flush(void); + +/** + * Pointer to log function. + */ +typedef void fptr(const char* format, ...); + +/****************************************************************************/ +/* message */ + +/** + * Message levels. + * + * The levels control the amount of information printed on the screen. + * Note that log_fatal(), log_error(), log_expected() and log_tag() are not affected by this option. + * + * From the most quiet to the most verbose. + */ +#define MSG_STATUS -3 +#define MSG_INFO -2 +#define MSG_PROGRESS -1 +#define MSG_BAR 0 +#define MSG_VERBOSE 1 + +/** + * Selected message level. + */ +extern int msg_level; + +/** + * State messages. + * + * Messages that tell what the program is doing or did, but limited to few lines. + * They are status information, and summary results. + */ +void msg_status(const char* format, ...) __attribute__((format(attribute_printf, 1, 2))); + +/** + * Info messages. + * + * Messages that tell what was done. + * Potentially a lot of messages are possible. They can still be on the screen, + * as losing them we don't lose information. + * + * These messages never go in the log file, because there is always a corresponding log_tag(). + */ +void msg_info(const char* format, ...) __attribute__((format(attribute_printf, 1, 2))); + +/** + * Progress messages. + * + * Message that tell the progress of program. + * + * These messages also go in the log file. + */ +void msg_progress(const char* format, ...) __attribute__((format(attribute_printf, 1, 2))); + +/** + * Progress bar messages. + * + * Message that show the percentage of the progress. + * + * These messages never go in the log file. + * + * These messages are buffered. Use msg_flush() to flush them. + */ +void msg_bar(const char* format, ...) __attribute__((format(attribute_printf, 1, 2))); + +/** + * Verbose messages. + * + * Message that tell what is already expected. + * + * These messages also go in the log file. + */ +void msg_verbose(const char* format, ...) __attribute__((format(attribute_printf, 1, 2))); + +/** + * Flush the output. + */ +void msg_flush(void); + +/****************************************************************************/ +/* print */ + +/** + * Print a repeated char. + */ +void printc(char c, size_t pad); + +/** + * Print a string with right space padding. + */ +void printr(const char* str, size_t pad); + +/** + * Print a string with left space padding. + */ +void printl(const char* str, size_t pad); + +/** + * Print a probability with space padding. + */ +void printp(double v, size_t pad); + +/****************************************************************************/ +/* string */ + +#define ESC_MAX (PATH_MAX*2 + 1) + +/** + * Escape a string for the log. + * + * \param buffer Preallocated buffer of ESC_MAX size. + * + * Chars ':', '\n', '\r' and '\' are escaped to '\d', '\\n', '\\r' and '\\'. + */ +const char* esc_tag(const char* str, char* buffer); + +/** + * Escape a string for the shell. + * + * \param buffer Preallocated buffer of ESC_MAX size. + */ +const char* esc_shell_multi(const char** str_map, unsigned str_max, char* buffer); +static inline const char* esc_shell(const char* str, char* buffer) +{ + return esc_shell_multi(&str, 1, buffer); +} + +/** + * Polish a string. + * + * Not printable chars are replaced by spaces. + * + * Note that the passed string is modified. + */ +char* strpolish(char* s); + +/** + * Split a string in multiple tokens separated by delimiters. + * + * Multiple delimiters are grouped together. + */ +unsigned strsplit(char** split_map, unsigned split_max, char* line, const char* delimiters); + +/****************************************************************************/ +/* path */ + +/** + * Copy a path limiting the size. + * Abort if too long. + */ +void pathcpy(char* dst, size_t size, const char* src); + +/** + * Concatenate a path limiting the size. + * Abort if too long. + */ +void pathcat(char* dst, size_t size, const char* src); + +/** + * Concatenate a path limiting the size. + * Abort if too long. + */ +void pathcatc(char* dst, size_t size, char c); + +/** + * Import a path limiting the size. + * In Windows all the backslash are converted to the C standard of forward slash. + * Abort if too long. + */ +void pathimport(char* dst, size_t size, const char* src); + +/** + * Export a path limiting the size. + * In Windows all the C slashes are converted to the Windows backslash. + * Abort if too long. + */ +void pathexport(char* dst, size_t size, const char* src); + +/** + * Print a path. + * Abort if too long. + */ +void pathprint(char* dst, size_t size, const char* format, ...) __attribute__((format(attribute_printf, 3, 4))); + +/** + * Ensure the presence of a terminating slash, if it isn't empty. + * Abort if too long. + */ +void pathslash(char* dst, size_t size); + +/** + * Cut everything after the latest slash. + */ +void pathcut(char* dst); + +/** + * Compare two paths. + * In Windows it's case insensitive and assumes \ equal at /. + */ +int pathcmp(const char* a, const char* b); + +/****************************************************************************/ +/* file-system */ + +/** + * Create all the ancestor directories if missing. + * The file name, after the last /, is ignored. + */ +int mkancestor(const char* file); + +/** + * Change the modification time of an open file. + */ +int fmtime(int f, int64_t mtime_sec, int mtime_nsec); + +/** + * Change the modification time of a file or link. + * Note that links are NOT deferenced. + */ +int lmtime(const char* path, int64_t mtime_sec, int mtime_nsec); + +/****************************************************************************/ +/* advise */ + +/** + * Advise modes. + */ +#define ADVISE_DEFAULT 0 /**< Default mode. */ +#define ADVISE_NONE 1 /**< Bare read/write mode. */ +#define ADVISE_SEQUENTIAL 2 /**< Sequential mode. */ +#define ADVISE_FLUSH 3 /**< Flush mode. */ +#define ADVISE_FLUSH_WINDOW 4 /**< Flush mode with a window of 8MB. */ +#define ADVISE_DISCARD 5 /**< Discard the cache after every operation. */ +#define ADVISE_DISCARD_WINDOW 6 /**< Discard the cache with a window of 8MB. */ +#define ADVISE_DIRECT 7 /**< Direct mode. */ + +#define ADVISE_WINDOW_SIZE (8 * 1024 * 1024) /**< Window size. */ + +struct advise_struct { + int mode; + data_off_t dirty_begin; + data_off_t dirty_end; +}; + +void advise_init(struct advise_struct* advise, int mode); +int advise_flags(struct advise_struct* advise); +int advise_open(struct advise_struct* advise, int f); +int advise_write(struct advise_struct* advise, int f, data_off_t offset, data_off_t size); +int advise_read(struct advise_struct* advise, int f, data_off_t offset, data_off_t size); + +/****************************************************************************/ +/* memory */ + +/** + * Return the size of the allocated memory. + */ +size_t malloc_counter_get(void); + +/** + * Safe malloc. + * If no memory is available, it aborts. + */ +void* malloc_nofail(size_t size); + +/** + * Safe cmalloc. + * If no memory is available, it aborts. + */ +void* calloc_nofail(size_t count, size_t size); + +/** + * Safe strdup. + * If no memory is available, it aborts. + */ +char* strdup_nofail(const char* str); + +/** + * Helper for printing an error about a failed allocation. + */ +void malloc_fail(size_t size); + +/****************************************************************************/ +/* smartctl */ + +/** + * Read smartctl attributes from a stream. + * Return 0 on success. + */ +int smartctl_attribute(FILE* f, const char* file, const char* name, uint64_t* smart, char* serial, char* vendor, char* model); + +/** + * Flush smartctl output from a stream. + */ +int smartctl_flush(FILE* f, const char* file, const char* name); + +/****************************************************************************/ +/* thread */ + +#if HAVE_PTHREAD +/** + * Control when to signal the condition variables. + * + * Default is inside the mutex. + * + * Ensure to change that before starting any thread. + */ +int thread_cond_signal_outside; + +/** + * Thread wrappers to handle error conditions. + */ +void thread_mutex_init(pthread_mutex_t* mutex, pthread_mutexattr_t* attr); +void thread_mutex_destroy(pthread_mutex_t* mutex); +void thread_mutex_lock(pthread_mutex_t* mutex); +void thread_mutex_unlock(pthread_mutex_t* mutex); +void thread_cond_init(pthread_cond_t* cond, pthread_condattr_t* attr); +void thread_cond_destroy(pthread_cond_t* cond); +void thread_cond_signal(pthread_cond_t* cond); +void thread_cond_broadcast(pthread_cond_t* cond); +void thread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex); +void thread_cond_signal_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex); +void thread_cond_broadcast_and_unlock(pthread_cond_t* cond, pthread_mutex_t* mutex); +void thread_create(pthread_t* thread, pthread_attr_t* attr, void *(* func)(void *), void *arg); +void thread_join(pthread_t thread, void** retval); +#endif + +#endif + diff --git a/cmdline/sync.c b/cmdline/sync.c new file mode 100644 index 0000000..dbcce38 --- /dev/null +++ b/cmdline/sync.c @@ -0,0 +1,1610 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "support.h" +#include "elem.h" +#include "state.h" +#include "parity.h" +#include "handle.h" +#include "io.h" +#include "raid/raid.h" + +/****************************************************************************/ +/* hash */ + +static int state_hash_process(struct snapraid_state* state, block_off_t blockstart, block_off_t blockmax, int* skip_sync) +{ + struct snapraid_handle* handle; + unsigned diskmax; + block_off_t i; + unsigned j; + void* buffer; + void* buffer_alloc; + data_off_t countsize; + block_off_t countpos; + block_off_t countmax; + int ret; + unsigned error; + unsigned silent_error; + unsigned io_error; + char esc_buffer[ESC_MAX]; + + /* maps the disks to handles */ + handle = handle_mapping(state, &diskmax); + + /* buffer for reading */ + buffer = malloc_nofail_direct(state->block_size, &buffer_alloc); + if (!state->opt.skip_self) + mtest_vector(1, state->block_size, &buffer); + + error = 0; + silent_error = 0; + io_error = 0; + + /* first count the number of blocks to process */ + countmax = 0; + for (j = 0; j < diskmax; ++j) { + struct snapraid_disk* disk = handle[j].disk; + + /* if no disk, nothing to check */ + if (!disk) + continue; + + for (i = blockstart; i < blockmax; ++i) { + struct snapraid_block* block; + unsigned block_state; + + block = fs_par2block_find(disk, i); + + /* get the state of the block */ + block_state = block_state_get(block); + + /* process REP and CHG blocks */ + if (block_state != BLOCK_STATE_REP && block_state != BLOCK_STATE_CHG) + continue; + + ++countmax; + } + } + + /* drop until now */ + state_usage_waste(state); + + countsize = 0; + countpos = 0; + if (!state_progress_begin(state, blockstart, blockmax, countmax)) + goto end; + + for (j = 0; j < diskmax; ++j) { + struct snapraid_disk* disk = handle[j].disk; + + /* if no disk, nothing to check */ + if (!disk) + continue; + + for (i = blockstart; i < blockmax; ++i) { + snapraid_info info; + int rehash; + struct snapraid_block* block; + int read_size; + unsigned char hash[HASH_MAX]; + unsigned block_state; + struct snapraid_file* file; + block_off_t file_pos; + + block = fs_par2block_find(disk, i); + + /* get the state of the block */ + block_state = block_state_get(block); + + /* process REP and CHG blocks */ + if (block_state != BLOCK_STATE_REP && block_state != BLOCK_STATE_CHG) + continue; + + /* get the file of this block */ + file = fs_par2file_get(disk, i, &file_pos); + + /* get block specific info */ + info = info_get(&state->infoarr, i); + + /* if we have to use the old hash */ + rehash = info_get_rehash(info); + + /* until now is misc */ + state_usage_misc(state); + + /* if the file is different than the current one, close it */ + if (handle[j].file != 0 && handle[j].file != file) { + /* keep a pointer at the file we are going to close for error reporting */ + struct snapraid_file* report = handle[j].file; + ret = handle_close(&handle[j]); + if (ret == -1) { + /* LCOV_EXCL_START */ + /* This one is really an unexpected error, because we are only reading */ + /* and closing a descriptor should never fail */ + if (errno == EIO) { + log_tag("error:%u:%s:%s: Close EIO error. %s\n", i, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno)); + log_fatal("DANGER! Unexpected input/output close error in a data disk, it isn't possible to sync.\n"); + log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle[j].path); + log_fatal("Stopping at block %u\n", i); + ++io_error; + goto bail; + } + + log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno)); + log_fatal("WARNING! Unexpected close error in a data disk, it isn't possible to sync.\n"); + log_fatal("Ensure that file '%s' can be accessed.\n", handle[j].path); + log_fatal("Stopping at block %u\n", i); + ++error; + goto bail; + /* LCOV_EXCL_STOP */ + } + } + + ret = handle_open(&handle[j], file, state->file_mode, log_error, 0); + if (ret == -1) { + if (errno == EIO) { + /* LCOV_EXCL_START */ + log_tag("error:%u:%s:%s: Open EIO error. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); + log_fatal("DANGER! Unexpected input/output open error in a data disk, it isn't possible to sync.\n"); + log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle[j].path); + log_fatal("Stopping at block %u\n", i); + ++io_error; + goto bail; + /* LCOV_EXCL_STOP */ + } + + if (errno == ENOENT) { + log_tag("error:%u:%s:%s: Open ENOENT error. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); + log_error("Missing file '%s'.\n", handle[j].path); + log_error("WARNING! You cannot modify data disk during a sync.\n"); + log_error("Rerun the sync command when finished.\n"); + ++error; + /* if the file is missing, it means that it was removed during sync */ + /* this isn't a serious error, so we skip this block, and continue with others */ + continue; + } + + if (errno == EACCES) { + log_tag("error:%u:%s:%s: Open EACCES error. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); + log_error("No access at file '%s'.\n", handle[j].path); + log_error("WARNING! Please fix the access permission in the data disk.\n"); + log_error("Rerun the sync command when finished.\n"); + ++error; + /* this isn't a serious error, so we skip this block, and continue with others */ + continue; + } + + /* LCOV_EXCL_START */ + log_tag("error:%u:%s:%s: Open error. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); + log_fatal("WARNING! Unexpected open error in a data disk, it isn't possible to sync.\n"); + log_fatal("Ensure that file '%s' can be accessed.\n", handle[j].path); + log_fatal("Stopping to allow recovery. Try with 'snapraid check -f /%s'\n", fmt_poll(disk, file->sub, esc_buffer)); + ++error; + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* check if the file is changed */ + if (handle[j].st.st_size != file->size + || handle[j].st.st_mtime != file->mtime_sec + || STAT_NSEC(&handle[j].st) != file->mtime_nsec + || handle[j].st.st_ino != file->inode + ) { + log_tag("error:%u:%s:%s: Unexpected attribute change\n", i, disk->name, esc_tag(file->sub, esc_buffer)); + if (handle[j].st.st_size != file->size) { + log_error("Unexpected size change at file '%s' from %" PRIu64 " to %" PRIu64 ".\n", handle[j].path, file->size, (uint64_t)handle[j].st.st_size); + } else if (handle[j].st.st_mtime != file->mtime_sec + || STAT_NSEC(&handle[j].st) != file->mtime_nsec) { + log_error("Unexpected time change at file '%s' from %" PRIu64 ".%d to %" PRIu64 ".%d.\n", handle[j].path, file->mtime_sec, file->mtime_nsec, (uint64_t)handle[j].st.st_mtime, STAT_NSEC(&handle[j].st)); + } else { + log_error("Unexpected inode change from %" PRIu64 " to %" PRIu64 " at file '%s'.\n", file->inode, (uint64_t)handle[j].st.st_ino, handle[j].path); + } + log_error("WARNING! You cannot modify files during a sync.\n"); + log_error("Rerun the sync command when finished.\n"); + ++error; + /* if the file is changed, it means that it was modified during sync */ + /* this isn't a serious error, so we skip this block, and continue with others */ + continue; + } + + read_size = handle_read(&handle[j], file_pos, buffer, state->block_size, log_fatal, 0); + if (read_size == -1) { + /* LCOV_EXCL_START */ + if (errno == EIO) { + log_tag("error:%u:%s:%s: Read EIO error at position %u. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos, strerror(errno)); + log_fatal("DANGER! Unexpected input/output read error in a data disk, it isn't possible to sync.\n"); + log_fatal("Ensure that disk '%s' is sane and that file '%s' can be read.\n", disk->dir, handle[j].path); + log_fatal("Stopping at block %u\n", i); + ++io_error; + goto bail; + } + + log_tag("error:%u:%s:%s: Read error at position %u. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), file_pos, strerror(errno)); + log_fatal("WARNING! Unexpected read error in a data disk, it isn't possible to sync.\n"); + log_fatal("Ensure that file '%s' can be read.\n", handle[j].path); + log_fatal("Stopping to allow recovery. Try with 'snapraid check -f /%s'\n", fmt_poll(disk, file->sub, esc_buffer)); + ++error; + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* until now is disk */ + state_usage_disk(state, handle, &j, 1); + + state_usage_file(state, disk, file); + + countsize += read_size; + + /* now compute the hash */ + if (rehash) { + memhash(state->prevhash, state->prevhashseed, hash, buffer, read_size); + } else { + memhash(state->hash, state->hashseed, hash, buffer, read_size); + } + + /* until now is hash */ + state_usage_hash(state); + + if (block_state == BLOCK_STATE_REP) { + /* compare the hash */ + if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { + log_tag("error:%u:%s:%s: Unexpected data change\n", i, disk->name, esc_tag(file->sub, esc_buffer)); + log_error("Data change at file '%s' at position '%u'\n", handle[j].path, file_pos); + log_error("WARNING! Unexpected data modification of a file without parity!\n"); + + if (file_flag_has(file, FILE_IS_COPY)) { + log_error("This file was detected as a copy of another file with the same name, size,\n"); + log_error("and timestamp, but the file data isn't matching the assumed copy.\n"); + log_error("If this is a false positive, and the files are expected to be different,\n"); + log_error("you can 'sync' anyway using 'snapraid --force-nocopy sync'\n"); + } else { + log_error("Try removing the file from the array and rerun the 'sync' command!\n"); + } + + /* block sync to allow a recovery before overwriting */ + /* the parity needed to make such recovery */ + *skip_sync = 1; /* avoid to run the next sync */ + + ++silent_error; + continue; + } + } else { + /* the only other case is BLOCK_STATE_CHG */ + assert(block_state == BLOCK_STATE_CHG); + + /* copy the hash in the block */ + memcpy(block->hash, hash, BLOCK_HASH_SIZE); + + /* and mark the block as hashed */ + block_state_set(block, BLOCK_STATE_REP); + + /* mark the state as needing write */ + state->need_write = 1; + } + + /* count the number of processed block */ + ++countpos; + + /* progress */ + if (state_progress(state, 0, i, countpos, countmax, countsize)) { + /* LCOV_EXCL_START */ + *skip_sync = 1; /* avoid to run the next sync */ + break; + /* LCOV_EXCL_STOP */ + } + } + + /* close the last file in the disk */ + if (handle[j].file != 0) { + /* keep a pointer at the file we are going to close for error reporting */ + struct snapraid_file* report = handle[j].file; + ret = handle_close(&handle[j]); + if (ret == -1) { + /* LCOV_EXCL_START */ + /* This one is really an unexpected error, because we are only reading */ + /* and closing a descriptor should never fail */ + if (errno == EIO) { + log_tag("error:%u:%s:%s: Close EIO error. %s\n", blockmax, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno)); + log_fatal("DANGER! Unexpected input/output close error in a data disk, it isn't possible to sync.\n"); + log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle[j].path); + log_fatal("Stopping at block %u\n", blockmax); + ++io_error; + goto bail; + } + + log_tag("error:%u:%s:%s: Close error. %s\n", blockmax, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno)); + log_fatal("WARNING! Unexpected close error in a data disk, it isn't possible to sync.\n"); + log_fatal("Ensure that file '%s' can be accessed.\n", handle[j].path); + log_fatal("Stopping at block %u\n", blockmax); + ++error; + goto bail; + /* LCOV_EXCL_STOP */ + } + } + } + +end: + state_progress_end(state, countpos, countmax, countsize); + + /* note that at this point no io_error is possible */ + /* because at the first one we bail out */ + assert(io_error == 0); + + if (error || io_error || silent_error) { + msg_status("\n"); + msg_status("%8u file errors\n", error); + msg_status("%8u io errors\n", io_error); + msg_status("%8u data errors\n", silent_error); + } else { + /* print the result only if processed something */ + if (countpos != 0) + msg_status("Everything OK\n"); + } + + if (error) + log_fatal("WARNING! Unexpected file errors!\n"); + + log_tag("hash_summary:error_file:%u\n", error); + + /* proceed without bailing out */ + goto finish; + +bail: + /* on bail, don't run the next sync */ + *skip_sync = 1; + + /* close files left open */ + for (j = 0; j < diskmax; ++j) { + struct snapraid_file* file = handle[j].file; + struct snapraid_disk* disk = handle[j].disk; + ret = handle_close(&handle[j]); + if (ret == -1) { + log_tag("error:%u:%s:%s: Close error. %s\n", i, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); + log_fatal("DANGER! Unexpected close error in a data disk.\n"); + ++error; + /* continue, as we are already exiting */ + } + } + +finish: + free(handle); + free(buffer_alloc); + + if (error + io_error + silent_error != 0) + return -1; + return 0; +} + +/****************************************************************************/ +/* sync */ + +/** + * Sync plan to use. + */ +struct snapraid_plan { + unsigned handle_max; + struct snapraid_handle* handle_map; + int force_full; +}; + +/** + * A block that failed the hash check, or that was deleted. + */ +struct failed_struct { + unsigned index; /**< Index of the failed block. */ + unsigned size; /**< Size of the block. */ + + struct snapraid_block* block; /**< The failed block, or BLOCK_DELETED for a deleted block */ +}; + +/** + * Comparison function for sorting by index. + */ +int failed_compare_by_index(const void* void_a, const void* void_b) +{ + const struct failed_struct* a = void_a; + const struct failed_struct* b = void_b; + + if (a->index < b->index) + return -1; + if (a->index > b->index) + return 1; + return 0; +} + +/** + * Buffer for storing the new hashes. + */ +struct snapraid_rehash { + unsigned char hash[HASH_MAX]; + struct snapraid_block* block; +}; + +/** + * Check if we have to process the specified block index ::i. + */ +static int block_is_enabled(void* void_plan, block_off_t i) +{ + struct snapraid_plan* plan = void_plan; + unsigned j; + int one_invalid; + int one_valid; + + /* for each disk */ + one_invalid = 0; + one_valid = 0; + for (j = 0; j < plan->handle_max; ++j) { + struct snapraid_block* block; + struct snapraid_disk* disk = plan->handle_map[j].disk; + + /* if no disk, nothing to check */ + if (!disk) + continue; + + block = fs_par2block_find(disk, i); + + if (block_has_file(block)) + one_valid = 1; + + if (block_has_invalid_parity(block) || plan->force_full) + one_invalid = 1; + } + + /* if none valid or none invalid, we don't need to update */ + if (!one_invalid || !one_valid) + return 0; + + return 1; +} + +static void sync_data_reader(struct snapraid_worker* worker, struct snapraid_task* task) +{ + struct snapraid_io* io = worker->io; + struct snapraid_state* state = io->state; + struct snapraid_handle* handle = worker->handle; + struct snapraid_disk* disk = handle->disk; + block_off_t blockcur = task->position; + unsigned char* buffer = task->buffer; + int ret; + char esc_buffer[ESC_MAX]; + + /* if the disk position is not used */ + if (!disk) { + /* use an empty block */ + memset(buffer, 0, state->block_size); + task->state = TASK_STATE_DONE; + return; + } + + /* get the block */ + task->block = fs_par2block_find(disk, blockcur); + + /* if the block has no file, meaning that it's EMPTY or DELETED, */ + /* it doesn't participate in the new parity computation */ + if (!block_has_file(task->block)) { + /* use an empty block */ + memset(buffer, 0, state->block_size); + task->state = TASK_STATE_DONE; + return; + } + + /* get the file of this block */ + task->file = fs_par2file_get(disk, blockcur, &task->file_pos); + + /* if the file is different than the current one, close it */ + if (handle->file != 0 && handle->file != task->file) { + /* keep a pointer at the file we are going to close for error reporting */ + struct snapraid_file* report = handle->file; + ret = handle_close(handle); + if (ret == -1) { + /* LCOV_EXCL_START */ + /* This one is really an unexpected error, because we are only reading */ + /* and closing a descriptor should never fail */ + if (errno == EIO) { + log_tag("error:%u:%s:%s: Close EIO error. %s\n", blockcur, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno)); + log_fatal("DANGER! Unexpected input/output close error in a data disk, it isn't possible to sync.\n"); + log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle->path); + log_fatal("Stopping at block %u\n", blockcur); + task->state = TASK_STATE_IOERROR; + return; + } + + log_tag("error:%u:%s:%s: Close error. %s\n", blockcur, disk->name, esc_tag(report->sub, esc_buffer), strerror(errno)); + log_fatal("WARNING! Unexpected close error in a data disk, it isn't possible to sync.\n"); + log_fatal("Ensure that file '%s' can be accessed.\n", handle->path); + log_fatal("Stopping at block %u\n", blockcur); + task->state = TASK_STATE_ERROR; + return; + /* LCOV_EXCL_STOP */ + } + } + + ret = handle_open(handle, task->file, state->file_mode, log_error, 0); + if (ret == -1) { + if (errno == EIO) { + /* LCOV_EXCL_START */ + log_tag("error:%u:%s:%s: Open EIO error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno)); + log_fatal("DANGER! Unexpected input/output open error in a data disk, it isn't possible to sync.\n"); + log_fatal("Ensure that disk '%s' is sane and that file '%s' can be accessed.\n", disk->dir, handle->path); + log_fatal("Stopping at block %u\n", blockcur); + task->state = TASK_STATE_IOERROR; + return; + /* LCOV_EXCL_STOP */ + } + + if (errno == ENOENT) { + log_tag("error:%u:%s:%s: Open ENOENT error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno)); + log_error("Missing file '%s'.\n", handle->path); + log_error("WARNING! You cannot modify data disk during a sync.\n"); + log_error("Rerun the sync command when finished.\n"); + /* if the file is missing, it means that it was removed during sync */ + /* this isn't a serious error, so we skip this block, and continue with others */ + task->state = TASK_STATE_ERROR_CONTINUE; + return; + } + + if (errno == EACCES) { + log_tag("error:%u:%s:%s: Open EACCES error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno)); + log_error("No access at file '%s'.\n", handle->path); + log_error("WARNING! Please fix the access permission in the data disk.\n"); + log_error("Rerun the sync command when finished.\n"); + /* this isn't a serious error, so we skip this block, and continue with others */ + task->state = TASK_STATE_ERROR_CONTINUE; + return; + } + + /* LCOV_EXCL_START */ + log_tag("error:%u:%s:%s: Open error. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), strerror(errno)); + log_fatal("WARNING! Unexpected open error in a data disk, it isn't possible to sync.\n"); + log_fatal("Ensure that file '%s' can be accessed.\n", handle->path); + log_fatal("Stopping to allow recovery. Try with 'snapraid check -f /%s'\n", fmt_poll(disk, task->file->sub, esc_buffer)); + task->state = TASK_STATE_ERROR; + return; + /* LCOV_EXCL_STOP */ + } + + /* check if the file is changed */ + if (handle->st.st_size != task->file->size + || handle->st.st_mtime != task->file->mtime_sec + || STAT_NSEC(&handle->st) != task->file->mtime_nsec + || handle->st.st_ino != task->file->inode + ) { + log_tag("error:%u:%s:%s: Unexpected attribute change\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer)); + if (handle->st.st_size != task->file->size) { + log_error("Unexpected size change at file '%s' from %" PRIu64 " to %" PRIu64 ".\n", handle->path, task->file->size, (uint64_t)handle->st.st_size); + } else if (handle->st.st_mtime != task->file->mtime_sec + || STAT_NSEC(&handle->st) != task->file->mtime_nsec) { + log_error("Unexpected time change at file '%s' from %" PRIu64 ".%d to %" PRIu64 ".%d.\n", handle->path, task->file->mtime_sec, task->file->mtime_nsec, (uint64_t)handle->st.st_mtime, STAT_NSEC(&handle->st)); + } else { + log_error("Unexpected inode change from %" PRIu64 " to %" PRIu64 " at file '%s'.\n", task->file->inode, (uint64_t)handle->st.st_ino, handle->path); + } + log_error("WARNING! You cannot modify files during a sync.\n"); + log_error("Rerun the sync command when finished.\n"); + /* if the file is changed, it means that it was modified during sync */ + /* this isn't a serious error, so we skip this block, and continue with others */ + task->state = TASK_STATE_ERROR_CONTINUE; + return; + } + + task->read_size = handle_read(handle, task->file_pos, buffer, state->block_size, log_error, 0); + if (task->read_size == -1) { + /* LCOV_EXCL_START */ + if (errno == EIO) { + log_tag("error:%u:%s:%s: Read EIO error at position %u. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), task->file_pos, strerror(errno)); + log_error("Input/Output error in file '%s' at position '%u'\n", handle->path, task->file_pos); + task->state = TASK_STATE_IOERROR_CONTINUE; + return; + } + + log_tag("error:%u:%s:%s: Read error at position %u. %s\n", blockcur, disk->name, esc_tag(task->file->sub, esc_buffer), task->file_pos, strerror(errno)); + log_fatal("WARNING! Unexpected read error in a data disk, it isn't possible to sync.\n"); + log_fatal("Ensure that file '%s' can be read.\n", handle->path); + log_fatal("Stopping to allow recovery. Try with 'snapraid check -f /%s'\n", fmt_poll(disk, task->file->sub, esc_buffer)); + task->state = TASK_STATE_ERROR; + return; + /* LCOV_EXCL_STOP */ + } + + /* store the path of the opened file */ + pathcpy(task->path, sizeof(task->path), handle->path); + + task->state = TASK_STATE_DONE; +} + +static void sync_parity_writer(struct snapraid_worker* worker, struct snapraid_task* task) +{ + struct snapraid_io* io = worker->io; + struct snapraid_state* state = io->state; + struct snapraid_parity_handle* parity_handle = worker->parity_handle; + unsigned level = parity_handle->level; + block_off_t blockcur = task->position; + unsigned char* buffer = task->buffer; + int ret; + + /* write parity */ + ret = parity_write(parity_handle, blockcur, buffer, state->block_size); + if (ret == -1) { + /* LCOV_EXCL_START */ + if (errno == EIO) { + log_tag("parity_error:%u:%s: Write EIO error. %s\n", blockcur, lev_config_name(level), strerror(errno)); + log_error("Input/Output error in parity '%s' at position '%u'\n", lev_config_name(level), blockcur); + task->state = TASK_STATE_IOERROR_CONTINUE; + return; + } + + log_tag("parity_error:%u:%s: Write error. %s\n", blockcur, lev_config_name(level), strerror(errno)); + log_fatal("WARNING! Unexpected write error in the %s disk, it isn't possible to sync.\n", lev_name(level)); + log_fatal("Ensure that disk '%s' has some free space available.\n", lev_config_name(level)); + log_fatal("Stopping at block %u\n", blockcur); + task->state = TASK_STATE_ERROR; + return; + /* LCOV_EXCL_STOP */ + } + + task->state = TASK_STATE_DONE; +} + +static int state_sync_process(struct snapraid_state* state, struct snapraid_parity_handle* parity_handle, block_off_t blockstart, block_off_t blockmax) +{ + struct snapraid_io io; + struct snapraid_plan plan; + struct snapraid_handle* handle; + void* rehandle_alloc; + struct snapraid_rehash* rehandle; + unsigned diskmax; + block_off_t blockcur; + unsigned j; + void* zero_alloc; + void** zero; + void* copy_alloc; + void** copy; + unsigned buffermax; + data_off_t countsize; + block_off_t countpos; + block_off_t countmax; + block_off_t autosavedone; + block_off_t autosavelimit; + block_off_t autosavemissing; + int ret; + unsigned error; + unsigned silent_error; + unsigned io_error; + time_t now; + struct failed_struct* failed; + int* failed_map; + unsigned l; + unsigned* waiting_map; + unsigned waiting_mac; + char esc_buffer[ESC_MAX]; + + /* the sync process assumes that all the hashes are correct */ + /* including the ones from CHG and DELETED blocks */ + assert(state->clear_past_hash != 0); + + /* get the present time */ + now = time(0); + + /* maps the disks to handles */ + handle = handle_mapping(state, &diskmax); + + /* rehash buffers */ + rehandle = malloc_nofail_align(diskmax * sizeof(struct snapraid_rehash), &rehandle_alloc); + + /* we need 1 * data + 1 * parity */ + buffermax = diskmax + state->level; + + /* initialize the io threads */ + io_init(&io, state, state->opt.io_cache, buffermax, sync_data_reader, handle, diskmax, 0, sync_parity_writer, parity_handle, state->level); + + /* allocate the copy buffer */ + copy = malloc_nofail_vector_align(diskmax, diskmax, state->block_size, ©_alloc); + + /* allocate and fill the zero buffer */ + zero = malloc_nofail_align(state->block_size, &zero_alloc); + memset(zero, 0, state->block_size); + raid_zero(zero); + + failed = malloc_nofail(diskmax * sizeof(struct failed_struct)); + failed_map = malloc_nofail(diskmax * sizeof(unsigned)); + + /* possibly waiting disks */ + waiting_mac = diskmax > RAID_PARITY_MAX ? diskmax : RAID_PARITY_MAX; + waiting_map = malloc_nofail(waiting_mac * sizeof(unsigned)); + + error = 0; + silent_error = 0; + io_error = 0; + + /* first count the number of blocks to process */ + countmax = 0; + plan.handle_max = diskmax; + plan.handle_map = handle; + plan.force_full = state->opt.force_full; + for (blockcur = blockstart; blockcur < blockmax; ++blockcur) { + if (!block_is_enabled(&plan, blockcur)) + continue; + ++countmax; + } + + /* compute the autosave size for all disk, even if not read */ + /* this makes sense because the speed should be almost the same */ + /* if the disks are read in parallel */ + autosavelimit = state->autosave / (diskmax * state->block_size); + autosavemissing = countmax; /* blocks to do */ + autosavedone = 0; /* blocks done */ + + /* drop until now */ + state_usage_waste(state); + + countsize = 0; + countpos = 0; + + /* start all the worker threads */ + io_start(&io, blockstart, blockmax, &block_is_enabled, &plan); + + if (!state_progress_begin(state, blockstart, blockmax, countmax)) + goto end; + + while (1) { + unsigned failed_count; + int error_on_this_block; + int silent_error_on_this_block; + int io_error_on_this_block; + int fixed_error_on_this_block; + int parity_needs_to_be_updated; + int parity_going_to_be_updated; + snapraid_info info; + int rehash; + void** buffer; + int writer_error[IO_WRITER_ERROR_MAX]; + + /* go to the next block */ + blockcur = io_read_next(&io, &buffer); + if (blockcur >= blockmax) + break; + + /* until now is scheduling */ + state_usage_sched(state); + + /* one more block processed for autosave */ + ++autosavedone; + --autosavemissing; + + /* by default process the block, and skip it if something goes wrong */ + error_on_this_block = 0; + silent_error_on_this_block = 0; + io_error_on_this_block = 0; + fixed_error_on_this_block = 0; + + /* keep track of the number of failed blocks */ + failed_count = 0; + + /* get block specific info */ + info = info_get(&state->infoarr, blockcur); + + /* if we have to use the old hash */ + rehash = info_get_rehash(info); + + /* if the parity requires to be updated */ + /* It could happens that all the blocks are EMPTY/BLK and CHG but with the hash */ + /* still matching because the specific CHG block was not modified. */ + /* In such case, we can avoid to update parity, because it would be the same as before */ + /* Note that CHG/DELETED blocks already present in the content file loaded */ + /* have the hash cleared (::clear_past_hash flag), and then they won't never match the hash. */ + /* We are treating only CHG blocks created at runtime. */ + parity_needs_to_be_updated = state->opt.force_full || state->opt.force_parity_update; + + /* if the parity is going to be updated */ + parity_going_to_be_updated = 0; + + /* if the block is marked as bad, we force the parity update */ + /* because the bad block may be the result of a wrong parity */ + if (info_get_bad(info)) + parity_needs_to_be_updated = 1; + + /* for each disk, process the block */ + for (j = 0; j < diskmax; ++j) { + struct snapraid_task* task; + int read_size; + unsigned char hash[HASH_MAX]; + struct snapraid_block* block; + unsigned block_state; + struct snapraid_disk* disk; + struct snapraid_file* file; + block_off_t file_pos; + unsigned diskcur; + + /* until now is misc */ + state_usage_misc(state); + + task = io_data_read(&io, &diskcur, waiting_map, &waiting_mac); + + /* until now is disk */ + state_usage_disk(state, handle, waiting_map, waiting_mac); + + /* get the results */ + disk = task->disk; + block = task->block; + file = task->file; + file_pos = task->file_pos; + read_size = task->read_size; + + /* by default no rehash in case of "continue" */ + rehandle[diskcur].block = 0; + + /* if the disk position is not used */ + if (!disk) + continue; + + state_usage_file(state, disk, file); + + /* get the state of the block */ + block_state = block_state_get(block); + + /* if the block has invalid parity, */ + /* we have to take care of it in case of recover */ + if (block_has_invalid_parity(block)) { + /* store it in the failed set, because */ + /* the parity may be still computed with the previous content */ + failed[failed_count].index = diskcur; + failed[failed_count].size = state->block_size; + failed[failed_count].block = block; + ++failed_count; + + /* if the block has invalid parity, we have to update the parity */ + /* to include this block change */ + /* This also apply to CHG blocks, but we are going to handle */ + /* later this case to do the updates only if really needed */ + if (block_state != BLOCK_STATE_CHG) + parity_needs_to_be_updated = 1; + + /* note that DELETE blocks are skipped in the next check */ + /* and we have to store them in the failed blocks */ + /* before skipping */ + + /* follow */ + } + + /* if the block is not used */ + if (!block_has_file(block)) + continue; + + /* handle error conditions */ + if (task->state == TASK_STATE_IOERROR) { + /* LCOV_EXCL_START */ + ++io_error; + goto bail; + /* LCOV_EXCL_STOP */ + } + if (task->state == TASK_STATE_ERROR) { + /* LCOV_EXCL_START */ + ++error; + goto bail; + /* LCOV_EXCL_STOP */ + } + if (task->state == TASK_STATE_ERROR_CONTINUE) { + ++error; + error_on_this_block = 1; + continue; + } + if (task->state == TASK_STATE_IOERROR_CONTINUE) { + ++io_error; + if (io_error >= state->opt.io_error_limit) { + /* LCOV_EXCL_START */ + log_fatal("DANGER! Unexpected input/output read error in a data disk, it isn't possible to sync.\n"); + log_fatal("Ensure that disk '%s' is sane and that file '%s' can be read.\n", disk->dir, task->path); + log_fatal("Stopping at block %u\n", blockcur); + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* otherwise continue */ + io_error_on_this_block = 1; + continue; + } + if (task->state != TASK_STATE_DONE) { + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in task state\n"); + os_abort(); + /* LCOV_EXCL_STOP */ + } + + countsize += read_size; + + /* now compute the hash */ + if (rehash) { + memhash(state->prevhash, state->prevhashseed, hash, buffer[diskcur], read_size); + + /* compute the new hash, and store it */ + rehandle[diskcur].block = block; + memhash(state->hash, state->hashseed, rehandle[diskcur].hash, buffer[diskcur], read_size); + } else { + memhash(state->hash, state->hashseed, hash, buffer[diskcur], read_size); + } + + /* until now is hash */ + state_usage_hash(state); + + if (block_has_updated_hash(block)) { + /* compare the hash */ + if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { + /* if the file has invalid parity, it's a REP changed during the sync */ + if (block_has_invalid_parity(block)) { + log_tag("error:%u:%s:%s: Unexpected data change\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer)); + log_error("Data change at file '%s' at position '%u'\n", task->path, file_pos); + log_error("WARNING! Unexpected data modification of a file without parity!\n"); + + if (file_flag_has(file, FILE_IS_COPY)) { + log_error("This file was detected as a copy of another file with the same name, size,\n"); + log_error("and timestamp, but the file data isn't matching the assumed copy.\n"); + log_error("If this is a false positive, and the files are expected to be different,\n"); + log_error("you can 'sync' anyway using 'snapraid --force-nocopy sync'\n"); + } else { + log_error("Try removing the file from the array and rerun the 'sync' command!\n"); + } + + ++error; + + /* if the file is changed, it means that it was modified during sync */ + /* this isn't a serious error, so we skip this block, and continue with others */ + error_on_this_block = 1; + continue; + } else { /* otherwise it's a BLK with silent error */ + unsigned diff = memdiff(hash, block->hash, BLOCK_HASH_SIZE); + log_tag("error:%u:%s:%s: Data error at position %u, diff bits %u/%u\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), file_pos, diff, BLOCK_HASH_SIZE * 8); + log_error("Data error in file '%s' at position '%u', diff bits %u/%u\n", task->path, file_pos, diff, BLOCK_HASH_SIZE * 8); + + /* save the failed block for the fix */ + failed[failed_count].index = diskcur; + failed[failed_count].size = read_size; + failed[failed_count].block = block; + ++failed_count; + + /* silent errors are very rare, and are not a signal that a disk */ + /* is going to fail. So, we just continue marking the block as bad */ + /* just like in scrub */ + ++silent_error; + silent_error_on_this_block = 1; + continue; + } + } + } else { + /* if until now the parity doesn't need to be updated */ + if (!parity_needs_to_be_updated) { + /* for sure it's a CHG block, because EMPTY are processed before with "continue" */ + /* and BLK and REP have "block_has_updated_hash()" as 1, and all the others */ + /* have "parity_needs_to_be_updated" already at 1 */ + assert(block_state_get(block) == BLOCK_STATE_CHG); + + /* if the hash represents the data unequivocally */ + if (hash_is_unique(block->hash)) { + /* check if the hash is changed */ + if (memcmp(hash, block->hash, BLOCK_HASH_SIZE) != 0) { + /* the block is different, and we must update parity */ + parity_needs_to_be_updated = 1; + } + } else { + /* if the hash is already invalid, we update parity */ + parity_needs_to_be_updated = 1; + } + } + + /* copy the hash in the block, but doesn't mark the block as hashed */ + /* this allow in case of skipped block to do not save the failed computation */ + memcpy(block->hash, hash, BLOCK_HASH_SIZE); + + /* note that in case of rehash, this is the wrong hash, */ + /* but it will be overwritten later */ + } + } + + /* if we have only silent errors we can try to fix them on-the-fly */ + /* note the the fix is not written to disk, but used only to */ + /* compute the new parity */ + if (!error_on_this_block && !io_error_on_this_block && silent_error_on_this_block) { + unsigned failed_mac; + int something_to_recover = 0; + + /* sort the failed vector */ + /* because with threads it may be in any order */ + /* but RAID requires the indexes to be sorted */ + qsort(failed, failed_count, sizeof(failed[0]), failed_compare_by_index); + + /* setup the blocks to recover */ + failed_mac = 0; + for (j = 0; j < failed_count; ++j) { + unsigned char* block_buffer = buffer[failed[j].index]; + unsigned char* block_copy = copy[failed[j].index]; + unsigned block_state = block_state_get(failed[j].block); + + /* we try to recover only if at least one BLK is present */ + if (block_state == BLOCK_STATE_BLK) + something_to_recover = 1; + + /* save a copy of the content just read */ + /* that it's going to be overwritten by the recovering function */ + memcpy(block_copy, block_buffer, state->block_size); + + if (block_state == BLOCK_STATE_CHG + && hash_is_zero(failed[j].block->hash) + ) { + /* if the block was filled with 0, restore this state */ + /* and avoid to recover it */ + memset(block_buffer, 0, state->block_size); + } else { + /* if we have too many failures, we cannot recover */ + if (failed_mac >= state->level) + break; + + /* otherwise it has to be recovered */ + failed_map[failed_mac++] = failed[j].index; + } + } + + /* if we have something to recover and enough parity */ + if (something_to_recover && j == failed_count) { + /* until now is misc */ + state_usage_misc(state); + + /* read the parity */ + /* we are sure that parity exists because */ + /* we have at least one BLK block */ + for (l = 0; l < state->level; ++l) { + ret = parity_read(&parity_handle[l], blockcur, buffer[diskmax + l], state->block_size, log_error); + if (ret == -1) { + /* LCOV_EXCL_START */ + if (errno == EIO) { + log_tag("parity_error:%u:%s: Read EIO error. %s\n", blockcur, lev_config_name(l), strerror(errno)); + if (io_error >= state->opt.io_error_limit) { + log_fatal("DANGER! Unexpected input/output read error in the %s disk, it isn't possible to sync.\n", lev_name(l)); + log_fatal("Ensure that disk '%s' is sane and can be read.\n", lev_config_name(l)); + log_fatal("Stopping at block %u\n", blockcur); + ++io_error; + goto bail; + } + + log_error("Input/Output error in parity '%s' at position '%u'\n", lev_config_name(l), blockcur); + ++io_error; + io_error_on_this_block = 1; + continue; + } + + log_tag("parity_error:%u:%s: Read error. %s\n", blockcur, lev_config_name(l), strerror(errno)); + log_fatal("WARNING! Unexpected read error in the %s disk, it isn't possible to sync.\n", lev_name(l)); + log_fatal("Ensure that disk '%s' can be read.\n", lev_config_name(l)); + log_fatal("Stopping at block %u\n", blockcur); + ++error; + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* until now is parity */ + state_usage_parity(state, &l, 1); + } + + /* if no error in parity read */ + if (!io_error_on_this_block) { + /* try to fix the data */ + /* note that this is a simple fix algorithm, that doesn't take into */ + /* account the case of a wrong parity */ + /* only 'fix' supports the most advanced fixing */ + raid_rec(failed_mac, failed_map, diskmax, state->level, state->block_size, buffer); + + /* until now is raid */ + state_usage_raid(state); + + /* check the result and prepare the data */ + for (j = 0; j < failed_count; ++j) { + unsigned char hash[HASH_MAX]; + unsigned char* block_buffer = buffer[failed[j].index]; + unsigned char* block_copy = copy[failed[j].index]; + unsigned block_state = block_state_get(failed[j].block); + + if (block_state == BLOCK_STATE_BLK) { + unsigned size = failed[j].size; + + /* compute the hash of the recovered block */ + if (rehash) { + memhash(state->prevhash, state->prevhashseed, hash, block_buffer, size); + } else { + memhash(state->hash, state->hashseed, hash, block_buffer, size); + } + + /* until now is hash */ + state_usage_hash(state); + + /* if the hash doesn't match */ + if (memcmp(hash, failed[j].block->hash, BLOCK_HASH_SIZE) != 0) { + /* we have not recovered */ + break; + } + + /* pad with 0 if needed */ + if (size < state->block_size) + memset(block_buffer + size, 0, state->block_size - size); + } else { + /* otherwise restore the content */ + /* because we are not interested in the old state */ + /* that it's recovered for CHG, REP and DELETED blocks */ + memcpy(block_buffer, block_copy, state->block_size); + } + } + + /* if all is processed, we have fixed it */ + if (j == failed_count) + fixed_error_on_this_block = 1; + } + } + } + + /* if we have read all the data required and it's correct, proceed with the parity */ + if (!error_on_this_block && !io_error_on_this_block + && (!silent_error_on_this_block || fixed_error_on_this_block) + ) { + /* update the parity only if really needed */ + if (parity_needs_to_be_updated) { + /* compute the parity */ + raid_gen(diskmax, state->level, state->block_size, buffer); + + /* until now is raid */ + state_usage_raid(state); + + /* mark that the parity is going to be written */ + parity_going_to_be_updated = 1; + } + + /* for each disk, mark the blocks as processed */ + for (j = 0; j < diskmax; ++j) { + struct snapraid_block* block; + + if (!handle[j].disk) + continue; + + block = fs_par2block_find(handle[j].disk, blockcur); + + if (block == BLOCK_NULL) { + /* nothing to do */ + continue; + } + + /* if it's a deleted block */ + if (block_state_get(block) == BLOCK_STATE_DELETED) { + /* the parity is now updated without this block, so it's now empty */ + fs_deallocate(handle[j].disk, blockcur); + continue; + } + + /* now all the blocks have the hash and the parity computed */ + block_state_set(block, BLOCK_STATE_BLK); + } + + /* we update the info block only if we really have updated the parity */ + /* because otherwise the time/justsynced info would be misleading as we didn't */ + /* wrote the parity at this time */ + /* we also update the info block only if no silent error was found */ + /* because has no sense to refresh the time for data that we know bad */ + if (parity_needs_to_be_updated + && !silent_error_on_this_block + ) { + /* if rehash is needed */ + if (rehash) { + /* store all the new hash already computed */ + for (j = 0; j < diskmax; ++j) { + if (rehandle[j].block) + memcpy(rehandle[j].block->hash, rehandle[j].hash, BLOCK_HASH_SIZE); + } + } + + /* update the time info of the block */ + /* we are also clearing any previous bad and rehash flag */ + info_set(&state->infoarr, blockcur, info_make(now, 0, 0, 1)); + } + } + + /* if a silent (even if corrected) or input/output error was found */ + /* mark the block as bad to have check/fix to handle it */ + /* because our correction is in memory only and not yet written */ + if (silent_error_on_this_block || io_error_on_this_block) { + /* set the error status keeping the other info */ + info_set(&state->infoarr, blockcur, info_set_bad(info)); + } + + /* finally schedule parity write */ + /* Note that the calls to io_parity_write() are mandatory */ + /* even if the parity doesn't need to be updated */ + /* This because we want to keep track of the time usage */ + state_usage_misc(state); + + /* write start */ + io_write_preset(&io, blockcur, !parity_going_to_be_updated); + + /* write the parity */ + for (l = 0; l < state->level; ++l) { + unsigned levcur; + + io_parity_write(&io, &levcur, waiting_map, &waiting_mac); + + /* until now is parity */ + state_usage_parity(state, waiting_map, waiting_mac); + } + + /* write finished */ + io_write_next(&io, blockcur, !parity_going_to_be_updated, writer_error); + + /* handle errors reported */ + for (j = 0; j < IO_WRITER_ERROR_MAX; ++j) { + if (writer_error[j]) { + switch (j + IO_WRITER_ERROR_BASE) { + case TASK_STATE_IOERROR_CONTINUE : + ++io_error; + if (io_error >= state->opt.io_error_limit) { + /* LCOV_EXCL_START */ + log_fatal("DANGER! Unexpected input/output write error in a parity disk, it isn't possible to sync.\n"); + log_fatal("Stopping at block %u\n", blockcur); + goto bail; + /* LCOV_EXCL_STOP */ + } + break; + case TASK_STATE_ERROR_CONTINUE : + ++error; + break; + case TASK_STATE_IOERROR : + /* LCOV_EXCL_START */ + ++io_error; + goto bail; + /* LCOV_EXCL_STOP */ + case TASK_STATE_ERROR : + /* LCOV_EXCL_START */ + ++error; + goto bail; + /* LCOV_EXCL_STOP */ + } + } + } + + /* mark the state as needing write */ + state->need_write = 1; + + /* count the number of processed block */ + ++countpos; + + /* progress */ + if (state_progress(state, &io, blockcur, countpos, countmax, countsize)) { + /* LCOV_EXCL_START */ + break; + /* LCOV_EXCL_STOP */ + } + + /* autosave */ + if ((state->autosave != 0 + && autosavedone >= autosavelimit /* if we have reached the limit */ + && autosavemissing >= autosavelimit) /* if we have at least a full step to do */ + /* or if we have a forced autosave at the specified block */ + || (state->opt.force_autosave_at != 0 && state->opt.force_autosave_at == blockcur) + ) { + autosavedone = 0; /* restart the counter */ + + /* until now is misc */ + state_usage_misc(state); + + state_progress_stop(state); + + msg_progress("Autosaving...\n"); + + /* before writing the new content file we ensure that */ + /* the parity is really written flushing the disk cache */ + for (l = 0; l < state->level; ++l) { + ret = parity_sync(&parity_handle[l]); + if (ret == -1) { + /* LCOV_EXCL_START */ + log_tag("parity_error:%u:%s: Sync error\n", blockcur, lev_config_name(l)); + log_fatal("DANGER! Unexpected sync error in %s disk.\n", lev_name(l)); + log_fatal("Ensure that disk '%s' is sane.\n", lev_config_name(l)); + log_fatal("Stopping at block %u\n", blockcur); + ++error; + goto bail; + /* LCOV_EXCL_STOP */ + } + } + + /* now we can safely write the content file */ + state_write(state); + + state_progress_restart(state); + + /* drop until now */ + state_usage_waste(state); + } + } + +end: + state_progress_end(state, countpos, countmax, countsize); + + state_usage_print(state); + + /* before returning we ensure that */ + /* the parity is really written flushing the disk cache */ + for (l = 0; l < state->level; ++l) { + ret = parity_sync(&parity_handle[l]); + if (ret == -1) { + /* LCOV_EXCL_START */ + log_tag("parity_error:%u:%s: Sync error\n", blockcur, lev_config_name(l)); + log_fatal("DANGER! Unexpected sync error in %s disk.\n", lev_name(l)); + log_fatal("Ensure that disk '%s' is sane.\n", lev_config_name(l)); + log_fatal("Stopping at block %u\n", blockcur); + ++error; + goto bail; + /* LCOV_EXCL_STOP */ + } + } + + if (error || silent_error || io_error) { + msg_status("\n"); + msg_status("%8u file errors\n", error); + msg_status("%8u io errors\n", io_error); + msg_status("%8u data errors\n", silent_error); + } else { + /* print the result only if processed something */ + if (countpos != 0) + msg_status("Everything OK\n"); + } + + if (error) + log_fatal("WARNING! Unexpected file errors!\n"); + if (io_error) + log_fatal("DANGER! Unexpected input/output errors! The failing blocks are now marked as bad!\n"); + if (silent_error) + log_fatal("DANGER! Unexpected data errors! The failing blocks are now marked as bad!\n"); + if (io_error || silent_error) { + log_fatal("Use 'snapraid status' to list the bad blocks.\n"); + log_fatal("Use 'snapraid -e fix' to recover.\n"); + } + + log_tag("summary:error_file:%u\n", error); + log_tag("summary:error_io:%u\n", io_error); + log_tag("summary:error_data:%u\n", silent_error); + if (error + silent_error + io_error == 0) + log_tag("summary:exit:ok\n"); + else + log_tag("summary:exit:error\n"); + log_flush(); + +bail: + /* stop all the worker threads */ + io_stop(&io); + + for (j = 0; j < diskmax; ++j) { + struct snapraid_file* file = handle[j].file; + struct snapraid_disk* disk = handle[j].disk; + ret = handle_close(&handle[j]); + if (ret == -1) { + /* LCOV_EXCL_START */ + log_tag("error:%u:%s:%s: Close error. %s\n", blockcur, disk->name, esc_tag(file->sub, esc_buffer), strerror(errno)); + log_fatal("DANGER! Unexpected close error in a data disk.\n"); + ++error; + /* continue, as we are already exiting */ + /* LCOV_EXCL_STOP */ + } + } + + free(handle); + free(zero_alloc); + free(copy_alloc); + free(copy); + free(rehandle_alloc); + free(failed); + free(failed_map); + free(waiting_map); + io_done(&io); + + if (state->opt.expect_recoverable) { + if (error + silent_error + io_error == 0) + return -1; + } else { + if (error + silent_error + io_error != 0) + return -1; + } + return 0; +} + +int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t blockcount) +{ + block_off_t blockmax; + block_off_t used_paritymax; + block_off_t file_paritymax; + data_off_t size; + int ret; + struct snapraid_parity_handle parity_handle[LEV_MAX]; + unsigned unrecoverable_error; + unsigned l; + int skip_sync = 0; + + msg_progress("Initializing...\n"); + + blockmax = parity_allocated_size(state); + size = blockmax * (data_off_t)state->block_size; + + /* minimum size of the parity files we expect */ + used_paritymax = parity_used_size(state); + + /* effective size of the parity files */ + file_paritymax = 0; + + if (blockstart > blockmax) { + /* LCOV_EXCL_START */ + log_fatal("Error in the starting block %u. It's bigger than the parity size %u.\n", blockstart, blockmax); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* adjust the number of block to process */ + if (blockcount != 0 && blockstart + blockcount < blockmax) { + blockmax = blockstart + blockcount; + } + + for (l = 0; l < state->level; ++l) { + data_off_t out_size; + block_off_t parityblocks; + + /* create the file and open for writing */ + ret = parity_create(&parity_handle[l], &state->parity[l], l, state->file_mode, state->block_size, state->opt.parity_limit_size); + if (ret == -1) { + /* LCOV_EXCL_START */ + log_fatal("WARNING! Without an accessible %s file, it isn't possible to sync.\n", lev_name(l)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + /* number of block in the parity file */ + parity_size(&parity_handle[l], &out_size); + parityblocks = out_size / state->block_size; + + /* if the file is too small */ + if (parityblocks < used_paritymax) { + log_fatal("WARNING! The %s parity has data only %u blocks instead of %u.\n", lev_name(l), parityblocks, used_paritymax); + } + + /* keep the smallest parity number of blocks */ + if (l == 0 || file_paritymax > parityblocks) + file_paritymax = parityblocks; + } + + /* if we do a full parity realloc or computation, having a wrong parity size is expected */ + if (!state->opt.force_realloc && !state->opt.force_full) { + /* if the parities are too small */ + if (file_paritymax < used_paritymax) { + /* LCOV_EXCL_START */ + log_fatal("DANGER! One or more the parity files are smaller than expected!\n"); + if (file_paritymax != 0) { + log_fatal("If this happens because you are using an old content file,\n"); + log_fatal("you can 'sync' anyway using 'snapraid --force-full sync'\n"); + log_fatal("to force a full rebuild of the parity.\n"); + } else { + log_fatal("It's possible that the parity disks are not mounted.\n"); + log_fatal("If instead you are adding a new parity level, you can 'sync' using\n"); + log_fatal("'snapraid --force-full sync' to force a full rebuild of the parity.\n"); + } + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + } + + unrecoverable_error = 0; + + if (state->opt.prehash) { + msg_progress("Hashing...\n"); + + ret = state_hash_process(state, blockstart, blockmax, &skip_sync); + if (ret == -1) { + /* LCOV_EXCL_START */ + ++unrecoverable_error; + /* continue, in case also doing the sync if ::skip_sync is not set */ + /* LCOV_EXCL_STOP */ + } + } + + if (!skip_sync) { + msg_progress("Resizing...\n"); + + /* now change the size of all parities */ + for (l = 0; l < state->level; ++l) { + int is_modified; + + /* change the size of the parity file, truncating or extending it */ + /* from this point all the DELETED blocks after the end of the parity are invalid */ + /* and they are automatically removed when we save the new content file */ + ret = parity_chsize(&parity_handle[l], &state->parity[l], &is_modified, size, state->block_size, state->opt.skip_fallocate, state->opt.skip_space_holder); + if (ret == -1) { + /* LCOV_EXCL_START */ + data_off_t out_size; + parity_size(&parity_handle[l], &out_size); + parity_overflow(state, out_size); + log_fatal("WARNING! Without an unsable %s file, it isn't possible to sync.\n", lev_name(l)); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + if (is_modified) + state->need_write = 1; + } + + /* after resizing parity files, refresh again the free info */ + state_refresh(state); + + /** + * Save the new state before the sync but after the hashing phase + * + * This allows to recover after an aborted sync, and at the same time + * it allows to recover broken copied/moved files identified in the + * hashing phase. + * + * For example, think at this case: + * - Add some files at the array + * - Run a sync command, it will recompute the parity adding the new files + * - Abort the sync command before it stores the new content file + * - Delete the not yet synced files from the array + * - Run a new sync command + * + * The sync command has no way to know that the parity file was modified + * because the files triggering these changes are now deleted and they aren't + * listed in the content file. + * Instead, saving the new content file in advance, keeps track of all the parity + * that may be modified. + */ + if (!state->opt.skip_content_write) { + if (state->need_write) + state_write(state); + } else { + log_fatal("WARNING! Skipped state write for --test-skip-content-write option.\n"); + } + + msg_progress("Syncing...\n"); + + /* skip degenerated cases of empty parity, or skipping all */ + if (blockstart < blockmax) { + ret = state_sync_process(state, parity_handle, blockstart, blockmax); + if (ret == -1) { + /* LCOV_EXCL_START */ + ++unrecoverable_error; + /* continue, as we are already exiting */ + /* LCOV_EXCL_STOP */ + } + } else { + msg_status("Nothing to do\n"); + } + } + + for (l = 0; l < state->level; ++l) { + ret = parity_close(&parity_handle[l]); + if (ret == -1) { + /* LCOV_EXCL_START */ + log_fatal("DANGER! Unexpected close error in %s disk.\n", lev_name(l)); + ++unrecoverable_error; + /* continue, as we are already exiting */ + /* LCOV_EXCL_STOP */ + } + } + + /* abort if required */ + if (unrecoverable_error != 0) + return -1; + return 0; +} + diff --git a/cmdline/touch.c b/cmdline/touch.c new file mode 100644 index 0000000..c856847 --- /dev/null +++ b/cmdline/touch.c @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2014 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "support.h" +#include "elem.h" +#include "state.h" +#include "handle.h" + +void state_touch(struct snapraid_state* state) +{ + tommy_node* i; + char esc_buffer[ESC_MAX]; + + msg_progress("Setting sub-second timestamps...\n"); + + /* for all disks */ + for (i = state->disklist; i != 0; i = i->next) { + struct snapraid_disk* disk = i->data; + tommy_node* j; + + /* for all files */ + for (j = disk->filelist; j != 0; j = j->next) { + struct snapraid_file* file = j->data; + + /* if the file has a zero nanosecond timestamp */ + /* note that symbolic links are not in the file list */ + /* and then are not processed */ + if (file->mtime_nsec == 0) { + char path[PATH_MAX]; + struct stat st; + int f; + int ret; + int nsec; + int flags; + + pathprint(path, sizeof(path), "%s%s", disk->dir, file->sub); + + /* set a new nanosecond timestamp different than 0 */ + do { + uint32_t nano; + + /* get a random nanosecond value */ + if (randomize(&nano, sizeof(nano)) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to get random values.\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + nsec = nano % 1000000000; + } while (nsec == 0); + + /* O_BINARY: open as binary file (Windows only) */ + /* O_NOFOLLOW: do not follow links to ensure to open the real file */ + flags = O_BINARY | O_NOFOLLOW; +#ifdef _WIN32 + /* in Windows we must have write access at the file */ + flags |= O_RDWR; +#else + /* in all others platforms, read access is enough */ + flags |= O_RDONLY; +#endif + + /* open it */ + f = open(path, flags); + if (f == -1) { + /* LCOV_EXCL_START */ + log_fatal("Error opening file '%s'. %s.\n", path, strerror(errno)); + continue; + /* LCOV_EXCL_STOP */ + } + + /* get the present timestamp, that may be different than the one */ + /* in the content file */ + ret = fstat(f, &st); + if (ret == -1) { + /* LCOV_EXCL_START */ + close(f); + log_fatal("Error accessing file '%s'. %s.\n", path, strerror(errno)); + continue; + /* LCOV_EXCL_STOP */ + } + + /* set the tweaked modification time, with new nano seconds */ + ret = fmtime(f, st.st_mtime, nsec); + if (ret != 0) { + /* LCOV_EXCL_START */ + close(f); + log_fatal("Error timing file '%s'. %s.\n", path, strerror(errno)); + continue; + /* LCOV_EXCL_STOP */ + } + + /* uses fstat again to get the present timestamp */ + /* this is needed because the value read */ + /* may be different than the written one */ + ret = fstat(f, &st); + if (ret == -1) { + /* LCOV_EXCL_START */ + close(f); + log_fatal("Error accessing file '%s'. %s.\n", path, strerror(errno)); + continue; + /* LCOV_EXCL_STOP */ + } + + /* close it */ + ret = close(f); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Error closing file '%s'. %s.\n", path, strerror(errno)); + continue; + /* LCOV_EXCL_STOP */ + } + + /* set the same nanosecond value in the content file */ + /* note that if the seconds value is already matching */ + /* the file won't be synced because the content file will */ + /* contain the new updated timestamp */ + file->mtime_nsec = STAT_NSEC(&st); + + /* state changed, we need to update it */ + state->need_write = 1; + + log_tag("touch:%s:%s: %" PRIu64 ".%d\n", disk->name, esc_tag(file->sub, esc_buffer), (uint64_t)st.st_mtime, STAT_NSEC(&st)); + msg_info("touch %s\n", fmt_term(disk, file->sub, esc_buffer)); + } + } + } +} + diff --git a/cmdline/unix.c b/cmdline/unix.c new file mode 100644 index 0000000..cf3f162 --- /dev/null +++ b/cmdline/unix.c @@ -0,0 +1,1563 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#ifndef __MINGW32__ /* Only for Unix */ + +#include "support.h" + +/** + * Exit codes. + */ +int exit_success = 0; +int exit_failure = 1; +int exit_sync_needed = 2; + +int open_noatime(const char* file, int flags) +{ +#ifdef O_NOATIME + int f = open(file, flags | O_NOATIME); + + /* only root is allowed to use O_NOATIME, in case retry without it */ + if (f == -1 && errno == EPERM) + f = open(file, flags); + return f; +#else + return open(file, flags); +#endif +} + +int dirent_hidden(struct dirent* dd) +{ + return dd->d_name[0] == '.'; +} + +const char* stat_desc(struct stat* st) +{ + if (S_ISREG(st->st_mode)) + return "regular"; + if (S_ISDIR(st->st_mode)) + return "directory"; + if (S_ISCHR(st->st_mode)) + return "character"; + if (S_ISBLK(st->st_mode)) + return "block-device"; + if (S_ISFIFO(st->st_mode)) + return "fifo"; + if (S_ISLNK(st->st_mode)) + return "link"; + if (S_ISLNK(st->st_mode)) + return "symbolic-link"; + if (S_ISSOCK(st->st_mode)) + return "socket"; + return "unknown"; +} + +/** + * Get the device file from the device number. + * + * It uses /proc/self/mountinfo. + * + * Null devices (major==0) are resolved to the device indicated in mountinfo. + */ +#if HAVE_LINUX_DEVICE +static int devresolve_proc(uint64_t device, char* path, size_t path_size) +{ + FILE* f; + char match[32]; + + /* generate the matching string */ + snprintf(match, sizeof(match), "%u:%u", major(device), minor(device)); + + f = fopen("/proc/self/mountinfo", "r"); + if (!f) { + log_tag("resolve:proc:%u:%u: failed to open /proc/self/mountinfo\n", major(device), minor(device)); + return -1; + } + + /* + * mountinfo format + * 0 - mount ID + * 1 - parent ID + * 2 - major:minor + * 3 - root + * 4 - mount point + * 5 - options + * 6 - "-" (separator) + * 7 - fs + * 8 - mount source - /dev/device + */ + + while (1) { + char buf[256]; + char* first_map[8]; + unsigned first_mac; + char* second_map[8]; + unsigned second_mac; + char* s; + struct stat st; + char* separator; + char* majorminor; + char* mountpoint; + char* fs; + char* mountsource; + + s = fgets(buf, sizeof(buf), f); + if (s == 0) + break; + + /* find the separator position */ + separator = strstr(s, " - "); + if (!separator) + continue; + + /* skip the separator */ + *separator = 0; + separator += 3; + + /* split the line */ + first_mac = strsplit(first_map, 8, s, " \t\r\n"); + second_mac = strsplit(second_map, 8, separator, " \t\r\n"); + + /* if too short, it's the wrong line */ + if (first_mac < 5) + continue; + if (second_mac < 2) + continue; + + majorminor = first_map[2]; + mountpoint = first_map[4]; + fs = second_map[0]; + mountsource = second_map[1]; + + /* compare major:minor from mountinfo */ + if (strcmp(majorminor, match) == 0) { + /* + * Accept only /dev/... mountsource + * + * This excludes ZFS that uses a bare label for mountsource, like "tank". + * + * 410 408 0:193 / /XXX rw,relatime shared:217 - zfs tank/system/data/var/lib/docker/XXX rw,xattr,noacl + * + * Also excludes AUTOFS unmounted devices that point to a fake filesystem + * used to remount them at the first use. + * + * 97 25 0:42 / /XXX rw,relatime shared:76 - autofs /etc/auto.seed rw,fd=6,pgrp=952,timeout=30,minproto=5,maxproto=5,indirect + */ + if (strncmp(mountsource, "/dev/", 5) != 0) { + log_tag("resolve:proc:%u:%u: match skipped for not /dev/ mountsource for %s %s\n", major(device), minor(device), fs, mountsource); + continue; + } + + pathcpy(path, path_size, mountsource); + + log_tag("resolve:proc:%u:%u: found device %s matching device %s\n", major(device), minor(device), path, match); + + fclose(f); + return 0; + } + + /* get the device of the mount point */ + /* in Btrfs it could be different than the one in mountinfo */ + if (stat(mountpoint, &st) == 0 && st.st_dev == device) { + if (strncmp(mountsource, "/dev/", 5) != 0) { + log_tag("resolve:proc:%u:%u: match skipped for not /dev/ mountsource for %s %s\n", major(device), minor(device), fs, mountsource); + continue; + } + + pathcpy(path, path_size, mountsource); + + log_tag("resolve:proc:%u:%u: found device %s matching mountpoint %s\n", major(device), minor(device), path, mountpoint); + + fclose(f); + return 0; + } + } + + log_tag("resolve:proc:%u:%u: not found\n", major(device), minor(device)); + + fclose(f); + return -1; +} +#endif + +/** + * Get the device of a virtual superblock. + * + * This is intended to resolve the case of Btrfs filesystems that + * create a virtual superblock (major==0) not backed by any low + * level device. + * + * See: + * Bug 711881 - too funny btrfs st_dev numbers + * https://bugzilla.redhat.com/show_bug.cgi?id=711881 + */ +#if HAVE_LINUX_DEVICE +static int devdereference(uint64_t device, uint64_t* new_device) +{ + char path[PATH_MAX]; + struct stat st; + + /* use the proc interface to get the device containing the filesystem */ + if (devresolve_proc(device, path, sizeof(path)) != 0) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + + /* check the device */ + if (stat(path, &st) != 0) { + /* LCOV_EXCL_START */ + log_tag("dereference:%u:%u: failed to stat %s\n", major(device), minor(device), path); + return -1; + /* LCOV_EXCL_STOP */ + } + + if (major(st.st_rdev) == 0) { + /* LCOV_EXCL_START */ + log_tag("dereference:%u:%u: still null device %s -> %u:%u\n", major(device), minor(device), path, major(st.st_rdev), minor(st.st_rdev)); + return -1; + /* LCOV_EXCL_STOP */ + } + + *new_device = st.st_rdev; + log_tag("dereference:%u:%u: found %u:%u\n", major(device), minor(device), major(st.st_rdev), minor(st.st_rdev)); + return 0; +} +#endif + +/** + * Read a file extracting the specified tag TAG=VALUE format. + * Return !=0 on error. + */ +#if HAVE_LINUX_DEVICE +static int tagread(const char* path, const char* tag, char* value, size_t value_size) +{ + int f; + int ret; + int len; + char buf[512]; + size_t tag_len; + char* i; + char* e; + + f = open(path, O_RDONLY); + if (f == -1) { + /* LCOV_EXCL_START */ + log_fatal("Failed to open '%s'.\n", path); + return 0; + /* LCOV_EXCL_STOP */ + } + + len = read(f, buf, sizeof(buf)); + if (len < 0) { + /* LCOV_EXCL_START */ + close(f); + log_fatal("Failed to read '%s'.\n", path); + return -1; + /* LCOV_EXCL_STOP */ + } + if (len == sizeof(buf)) { + /* LCOV_EXCL_START */ + close(f); + log_fatal("Too long read '%s'.\n", path); + return -1; + /* LCOV_EXCL_STOP */ + } + + ret = close(f); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to close '%s'.\n", path); + return -1; + /* LCOV_EXCL_STOP */ + } + + buf[len] = 0; + tag_len = strlen(tag); + + for (i = buf; *i; ++i) { + char* p = i; + + /* start with a space */ + if (p != buf) { + if (!isspace(*p)) + continue; + ++p; + } + + if (strncmp(p, tag, tag_len) != 0) + continue; + p += tag_len; + + /* end with a = */ + if (*p != '=') + continue; + ++p; + + /* found */ + i = p; + break; + } + if (!*i) { + /* LCOV_EXCL_START */ + log_fatal("Missing tag '%s' for '%s'.\n", tag, path); + return -1; + /* LCOV_EXCL_STOP */ + } + + /* terminate at the first space */ + e = i; + while (*e != 0 && !isspace(*e)) + ++e; + *e = 0; + + if (!*i) { + /* LCOV_EXCL_START */ + log_fatal("Empty tag '%s' for '%s'.\n", tag, path); + return -1; + /* LCOV_EXCL_STOP */ + } + + pathprint(value, value_size, "%s", i); + + return 0; +} +#endif + +/** + * Get the device file from the device number. + * + * It uses /sys/dev/block/.../uevent. + * + * For null device (major==0) it fails. + */ +#if HAVE_LINUX_DEVICE +static int devresolve_sys(dev_t device, char* path, size_t path_size) +{ + struct stat st; + char buf[PATH_MAX]; + + /* default device path from device number */ + pathprint(path, path_size, "/sys/dev/block/%u:%u/uevent", major(device), minor(device)); + + if (tagread(path, "DEVNAME", buf, sizeof(buf)) != 0) { + /* LCOV_EXCL_START */ + log_tag("resolve:sys:%u:%u: failed to read DEVNAME tag '%s'\n", major(device), minor(device), path); + return -1; + /* LCOV_EXCL_STOP */ + } + + /* set the real device path */ + pathprint(path, path_size, "/dev/%s", buf); + + /* check the device */ + if (stat(path, &st) != 0) { + /* LCOV_EXCL_START */ + log_tag("resolve:sys:%u:%u: failed to stat '%s'\n", major(device), minor(device), path); + return -1; + /* LCOV_EXCL_STOP */ + } + if (st.st_rdev != device) { + /* LCOV_EXCL_START */ + log_tag("resolve:sys:%u:%u: unexpected device '%u:%u' for '%s'.\n", major(device), minor(device), major(st.st_rdev), minor(st.st_rdev), path); + return -1; + /* LCOV_EXCL_STOP */ + } + + log_tag("resolve:sys:%u:%u:%s: found\n", major(device), minor(device), path); + + return 0; +} +#endif + +/** + * Get the device file from the device number. + */ +#if HAVE_LINUX_DEVICE +static int devresolve(uint64_t device, char* path, size_t path_size) +{ + if (devresolve_sys(device, path, path_size) == 0) + return 0; + + return -1; +} +#endif + +/** + * Cache used by blkid. + */ +#if HAVE_BLKID +static blkid_cache cache = 0; +#endif + +/** + * Get the UUID using the /dev/disk/by-uuid/ links. + * It doesn't require root permission, and the uuid are always updated. + * It doesn't work with Btrfs file-systems that don't export the main UUID + * in /dev/disk/by-uuid/. + */ +#if HAVE_LINUX_DEVICE +static int devuuid_dev(uint64_t device, char* uuid, size_t uuid_size) +{ + int ret; + DIR* d; + struct dirent* dd; + struct stat st; + + /* scan the UUID directory searching for the device */ + d = opendir("/dev/disk/by-uuid"); + if (!d) { + log_tag("uuid:by-uuid:%u:%u: opendir(/dev/disk/by-uuid) failed, %s\n", major(device), minor(device), strerror(errno)); + /* directory missing?, likely we are not in Linux */ + return -1; + } + + while ((dd = readdir(d)) != 0) { + /* skip "." and ".." files, UUIDs never start with '.' */ + if (dd->d_name[0] == '.') + continue; + + ret = fstatat(dirfd(d), dd->d_name, &st, 0); + if (ret != 0) { + log_tag("uuid:by-uuid:%u:%u: fstatat(%s) failed, %s\n", major(device), minor(device), dd->d_name, strerror(errno)); + /* generic error, ignore and continue the search */ + continue; + } + + /* if it matches, we have the uuid */ + if (S_ISBLK(st.st_mode) && st.st_rdev == (dev_t)device) { + char buf[PATH_MAX]; + char path[PATH_MAX]; + + /* resolve the link */ + pathprint(path, sizeof(path), "/dev/disk/by-uuid/%s", dd->d_name); + ret = readlink(path, buf, sizeof(buf)); + if (ret < 0 || ret >= PATH_MAX) { + log_tag("uuid:by-uuid:%u:%u: readlink(/dev/disk/by-uuid/%s) failed, %s\n", major(device), minor(device), dd->d_name, strerror(errno)); + /* generic error, ignore and continue the search */ + continue; + } + buf[ret] = 0; + + /* found */ + pathcpy(uuid, uuid_size, dd->d_name); + + log_tag("uuid:by-uuid:%u:%u:%s: found %s\n", major(device), minor(device), uuid, buf); + + closedir(d); + return 0; + } + } + + log_tag("uuid:by-uuid:%u:%u: /dev/disk/by-uuid doesn't contain a matching block device\n", major(device), minor(device)); + + /* not found */ + closedir(d); + return -1; +} +#endif + +/** + * Get the UUID using liblkid. + * It uses a cache to work without root permission, resulting in UUID + * not necessarily recent. + * We could call blkid_probe_all() to refresh the UUID, but it would + * require root permission to read the superblocks, and resulting in + * all the disks spinning. + */ +#if HAVE_BLKID +static int devuuid_blkid(uint64_t device, char* uuid, size_t uuid_size) +{ + char* devname; + char* uuidname; + + devname = blkid_devno_to_devname(device); + if (!devname) { + log_tag("uuid:blkid:%u:%u: blkid_devno_to_devname() failed, %s\n", major(device), minor(device), strerror(errno)); + /* device mapping failed */ + return -1; + } + + uuidname = blkid_get_tag_value(cache, "UUID", devname); + if (!uuidname) { + log_tag("uuid:blkid:%u:%u: blkid_get_tag_value(UUID,%s) failed, %s\n", major(device), minor(device), devname, strerror(errno)); + /* uuid mapping failed */ + free(devname); + return -1; + } + + pathcpy(uuid, uuid_size, uuidname); + + log_tag("uuid:blkid:%u:%u:%s: found %s\n", major(device), minor(device), uuid, devname); + + free(devname); + free(uuidname); + return 0; +} +#endif + +int devuuid(uint64_t device, char* uuid, size_t uuid_size) +{ +#if HAVE_LINUX_DEVICE + /* if the major is the null device */ + if (major(device) == 0) { + /* obtain the real device */ + if (devdereference(device, &device) != 0) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + } +#endif + + /* first try with the /dev/disk/by-uuid version */ +#if HAVE_LINUX_DEVICE + if (devuuid_dev(device, uuid, uuid_size) == 0) + return 0; +#else + log_tag("uuid:by-uuid:%u:%u: by-uuid not supported\n", major(device), minor(device)); +#endif + + /* fall back to blkid for other cases */ +#if HAVE_BLKID + if (devuuid_blkid(device, uuid, uuid_size) == 0) + return 0; +#else + log_tag("uuid:blkid:%u:%u: blkid support not compiled in\n", major(device), minor(device)); +#endif + + log_tag("uuid:notfound:%u:%u:\n", major(device), minor(device)); + + /* not supported */ + (void)uuid; + (void)uuid_size; + return -1; +} + +int filephy(const char* path, uint64_t size, uint64_t* physical) +{ +#if HAVE_LINUX_FIEMAP_H + /* In Linux get the real physical address of the file */ + /* Note that FIEMAP doesn't require root permission */ + int f; + struct { + struct fiemap fiemap; + struct fiemap_extent extent; + } fm; + unsigned int blknum; + + f = open(path, O_RDONLY); + if (f == -1) { + return -1; + } + + /* first try with FIEMAP */ + /* if works for ext2, ext3, ext4, xfs, btrfs */ + memset(&fm, 0, sizeof(fm)); + fm.fiemap.fm_start = 0; + fm.fiemap.fm_length = ~0ULL; + fm.fiemap.fm_flags = FIEMAP_FLAG_SYNC; /* required to ensure that just created files report a valid address and not 0 */ + fm.fiemap.fm_extent_count = 1; /* we are interested only at the first block */ + + if (ioctl(f, FS_IOC_FIEMAP, &fm) != -1) { + uint32_t flags = fm.fiemap.fm_extents[0].fe_flags; + uint64_t offset = fm.fiemap.fm_extents[0].fe_physical; + + /* check some condition for validating the offset */ + if (flags & FIEMAP_EXTENT_DATA_INLINE) { + /* if the data is inline, we don't have an offset to report */ + *physical = FILEPHY_WITHOUT_OFFSET; + } else if (flags & FIEMAP_EXTENT_UNKNOWN) { + /* if the offset is unknown, we don't have an offset to report */ + *physical = FILEPHY_WITHOUT_OFFSET; + } else if (offset == 0) { + /* 0 is the general fallback for file-systems when */ + /* they don't have an offset to report */ + *physical = FILEPHY_WITHOUT_OFFSET; + } else { + /* finally report the real offset */ + *physical = offset + FILEPHY_REAL_OFFSET; + } + + if (close(f) == -1) + return -1; + return 0; + } + + /* if the file is empty, FIBMAP doesn't work, and we don't even try to use it */ + if (size == 0) { + *physical = FILEPHY_WITHOUT_OFFSET; + if (close(f) == -1) + return -1; + return 0; + } + + /* then try with FIBMAP */ + /* it works for jfs, reiserfs, ntfs-3g */ + /* in exfat it always returns 0, that it's anyway better than the fake inodes */ + blknum = 0; /* first block */ + if (ioctl(f, FIBMAP, &blknum) != -1) { + *physical = blknum + FILEPHY_REAL_OFFSET; + if (close(f) == -1) + return -1; + return 0; + } + + /* otherwise don't use anything, and keep the directory traversal order */ + /* at now this should happen only for vfat */ + /* and it's surely better than using fake inodes */ + *physical = FILEPHY_UNREPORTED_OFFSET; + if (close(f) == -1) + return -1; +#else + /* In a generic Unix use a dummy value for all the files */ + /* We don't want to risk to use the inode without knowing */ + /* if it really improves performance. */ + /* In this way we keep them in the directory traversal order */ + /* that at least keeps files in the same directory together. */ + /* Note also that in newer file-system with snapshot, like ZFS, */ + /* the inode doesn't represent evenmore the disk position, because files */ + /* are not overwritten in place, but rewritten in another location */ + /* of the disk. */ + *physical = FILEPHY_UNREPORTED_OFFSET; + + (void)path; /* not used here */ + (void)size; +#endif + + return 0; +} + +int fsinfo(const char* path, int* has_persistent_inode, int* has_syncronized_hardlinks, uint64_t* total_space, uint64_t* free_space) +{ + char type[64]; + const char* ptype; + +#if HAVE_STATFS + struct statfs st; + + if (statfs(path, &st) != 0) { + char dir[PATH_MAX]; + char* slash; + + if (errno != ENOENT) { + return -1; + } + + /* if it doesn't exist, we assume a file */ + /* and we check for the containing dir */ + if (strlen(path) + 1 > sizeof(dir)) { + errno = ENAMETOOLONG; + return -1; + } + + strcpy(dir, path); + + slash = strrchr(dir, '/'); + if (!slash) + return -1; + + *slash = 0; + if (statfs(dir, &st) != 0) + return -1; + } +#endif + + /* to get the fs type check "man stat" or "stat -f -t FILE" */ + if (has_persistent_inode) { +#if HAVE_STATFS && HAVE_STRUCT_STATFS_F_TYPE + switch (st.f_type) { + case 0x65735546 : /* FUSE, "fuseblk" in the stat command */ + case 0x4d44 : /* VFAT, "msdos" in the stat command */ + *has_persistent_inode = 0; + break; + default : + /* by default assume yes */ + *has_persistent_inode = 1; + break; + } +#else + /* in Unix inodes are persistent by default */ + *has_persistent_inode = 1; +#endif + } + + if (has_syncronized_hardlinks) { +#if HAVE_STATFS && HAVE_STRUCT_STATFS_F_TYPE + switch (st.f_type) { + case 0x5346544E : /* NTFS */ + case 0x4d44 : /* VFAT, "msdos" in the stat command */ + *has_syncronized_hardlinks = 0; + break; + default : + /* by default assume yes */ + *has_syncronized_hardlinks = 1; + break; + } +#else + /* in Unix hardlinks share the same metadata by default */ + *has_syncronized_hardlinks = 1; +#endif + } + + if (total_space) { +#if HAVE_STATFS + *total_space = st.f_bsize * (uint64_t)st.f_blocks; +#else + *total_space = 0; +#endif + } + + if (free_space) { +#if HAVE_STATFS + *free_space = st.f_bsize * (uint64_t)st.f_bfree; +#else + *free_space = 0; +#endif + } + +#if HAVE_STATFS && HAVE_STRUCT_STATFS_F_FSTYPENAME + /* get the filesystem type directly from the struct (Mac OS X) */ + (void)type; + ptype = st.f_fstypename; +#elif HAVE_STATFS && HAVE_STRUCT_STATFS_F_TYPE + /* get the filesystem type from f_type (Linux) */ + /* from: https://github.com/influxdata/gopsutil/blob/master/disk/disk_linux.go */ + switch (st.f_type) { + case 0x65735546 : ptype = "fuseblk"; break; + case 0x4D44 : ptype = "vfat/msdos"; break; + case 0xEF53 : ptype = "ext2/3/4"; break; + case 0x6969 : ptype = "nfs"; break; /* remote */ + case 0x6E667364 : ptype = "nfsd"; break; /* remote */ + case 0x517B : ptype = "smb"; break; /* remote */ + case 0x5346544E : ptype = "ntfs"; break; + case 0x52654973 : ptype = "reiserfs"; break; + case 0x3153464A : ptype = "jfs"; break; + case 0x58465342 : ptype = "xfs"; break; + case 0x9123683E : ptype = "btrfs"; break; + case 0x2FC12FC1 : ptype = "zfs"; break; + default : + snprintf(type, sizeof(type), "0x%X", (unsigned)st.f_type); + ptype = type; + } +#else + (void)type; + ptype = "unknown"; +#endif + + log_tag("statfs:%s: %s \n", ptype, path); + + return 0; +} + +uint64_t tick(void) +{ +#if HAVE_MACH_ABSOLUTE_TIME + /* for Mac OS X */ + return mach_absolute_time(); +#elif HAVE_CLOCK_GETTIME && (defined(CLOCK_MONOTONIC) || defined(CLOCK_MONOTONIC_RAW)) + /* for Linux */ + struct timespec tv; + + /* nanosecond precision with clock_gettime() */ +#if defined(CLOCK_MONOTONIC_RAW) + if (clock_gettime(CLOCK_MONOTONIC_RAW, &tv) != 0) { +#else + if (clock_gettime(CLOCK_MONOTONIC, &tv) != 0) { +#endif + return 0; + } + + return tv.tv_sec * 1000000000ULL + tv.tv_nsec; +#else + /* other platforms */ + struct timeval tv; + + /* microsecond precision with gettimeofday() */ + if (gettimeofday(&tv, 0) != 0) { + return 0; + } + + return tv.tv_sec * 1000000ULL + tv.tv_usec; +#endif +} + +uint64_t tick_ms(void) +{ + struct timeval tv; + + if (gettimeofday(&tv, 0) != 0) + return 0; + + return tv.tv_sec * 1000ULL + tv.tv_usec / 1000; +} + +int randomize(void* ptr, size_t size) +{ + int f; + ssize_t ret; + + f = open("/dev/urandom", O_RDONLY); + if (f == -1) + return -1; + + ret = read(f, ptr, size); + if (ret < 0 || (size_t)ret != size) { + close(f); + return -1; + } + + if (close(f) != 0) + return -1; + + return 0; +} + +/** + * Read a file extracting the contained device number in %u:%u format. + * Return 0 on error. + */ +#if HAVE_LINUX_DEVICE +static dev_t devread(const char* path) +{ + int f; + int ret; + int len; + char buf[64]; + char* e; + unsigned ma; + unsigned mi; + + f = open(path, O_RDONLY); + if (f == -1) { + /* LCOV_EXCL_START */ + log_fatal("Failed to open '%s'.\n", path); + return 0; + /* LCOV_EXCL_STOP */ + } + + len = read(f, buf, sizeof(buf)); + if (len < 0) { + /* LCOV_EXCL_START */ + close(f); + log_fatal("Failed to read '%s'.\n", path); + return 0; + /* LCOV_EXCL_STOP */ + } + if (len == sizeof(buf)) { + /* LCOV_EXCL_START */ + close(f); + log_fatal("Too long read '%s'.\n", path); + return 0; + /* LCOV_EXCL_STOP */ + } + + ret = close(f); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to close '%s'.\n", path); + return 0; + /* LCOV_EXCL_STOP */ + } + + buf[len] = 0; + + ma = strtoul(buf, &e, 10); + if (*e != ':') { + /* LCOV_EXCL_START */ + log_fatal("Invalid format in '%s' for '%s'.\n", path, buf); + return 0; + /* LCOV_EXCL_STOP */ + } + + mi = strtoul(e + 1, &e, 10); + if (*e != 0 && !isspace(*e)) { + /* LCOV_EXCL_START */ + log_fatal("Invalid format in '%s' for '%s'.\n", path, buf); + return 0; + /* LCOV_EXCL_STOP */ + } + + return makedev(ma, mi); +} +#endif + +/** + * Read a device tree filling the specified list of disk_t entries. + */ +#if HAVE_LINUX_DEVICE +static int devtree(const char* name, const char* custom, dev_t device, devinfo_t* parent, tommy_list* list) +{ + char path[PATH_MAX]; + DIR* d; + int slaves = 0; + + pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/slaves", major(device), minor(device)); + + /* check if there is a slaves list */ + d = opendir(path); + if (d != 0) { + struct dirent* dd; + + while ((dd = readdir(d)) != 0) { + if (dd->d_name[0] != '.') { + /* for each slave, expand the full potential tree */ + pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/slaves/%s/dev", major(device), minor(device), dd->d_name); + + device = devread(path); + if (!device) { + /* LCOV_EXCL_START */ + closedir(d); + return -1; + /* LCOV_EXCL_STOP */ + } + + if (devtree(name, custom, device, parent, list) != 0) { + /* LCOV_EXCL_START */ + closedir(d); + return -1; + /* LCOV_EXCL_STOP */ + } + + ++slaves; + } + } + + closedir(d); + } + + /* if no slaves found */ + if (!slaves) { + /* this is a raw device */ + devinfo_t* devinfo; + + /* check if it's a real device */ + pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/device", major(device), minor(device)); + if (access(path, F_OK) != 0) { + /* get the parent device */ + pathprint(path, sizeof(path), "/sys/dev/block/%u:%u/../dev", major(device), minor(device)); + + device = devread(path); + if (!device) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + } + + /* get the device file */ + if (devresolve(device, path, sizeof(path)) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to resolve device '%u:%u'.\n", major(device), minor(device)); + return -1; + /* LCOV_EXCL_STOP */ + } + + devinfo = calloc_nofail(1, sizeof(devinfo_t)); + + devinfo->device = device; + pathcpy(devinfo->name, sizeof(devinfo->name), name); + pathcpy(devinfo->smartctl, sizeof(devinfo->smartctl), custom); + pathcpy(devinfo->file, sizeof(devinfo->file), path); + devinfo->parent = parent; + + /* insert in the list */ + tommy_list_insert_tail(list, &devinfo->node, devinfo); + } + + return 0; +} +#endif + +/** + * Scan all the devices. + * + * If a device is already in, it's not added again. + */ +#if HAVE_LINUX_DEVICE +static int devscan(tommy_list* list) +{ + char dir[PATH_MAX]; + DIR* d; + struct dirent* dd; + + pathprint(dir, sizeof(dir), "/sys/dev/block/"); + + /* check if there is a slaves list */ + d = opendir(dir); + if (d == 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to open dir '%s'.\n", dir); + return -1; + /* LCOV_EXCL_STOP */ + } + + while ((dd = readdir(d)) != 0) { + char path[PATH_MAX]; + tommy_node* i; + dev_t device; + devinfo_t* devinfo; + + if (dd->d_name[0] == '.') + continue; + + pathprint(path, sizeof(path), "/sys/dev/block/%s/device", dd->d_name); + + /* check if it's a real device */ + if (access(path, F_OK) != 0) + continue; + + pathprint(path, sizeof(path), "/sys/dev/block/%s/dev", dd->d_name); + + device = devread(path); + if (!device) { + /* LCOV_EXCL_START */ + log_tag("scan:skip: Skipping device %s because failed to read its device number.\n", dd->d_name); + continue; + /* LCOV_EXCL_STOP */ + } + + /* check if already present */ + for (i = tommy_list_head(list); i != 0; i = i->next) { + devinfo = i->data; + if (devinfo->device == device) + break; + } + + /* if already present */ + if (i != 0) + continue; + + /* get the device file */ + if (devresolve(device, path, sizeof(path)) != 0) { + /* LCOV_EXCL_START */ + log_tag("scan:skip: Skipping device %u:%u because failed to resolve.\n", major(device), minor(device)); + continue; + /* LCOV_EXCL_STOP */ + } + + devinfo = calloc_nofail(1, sizeof(devinfo_t)); + + devinfo->device = device; + pathcpy(devinfo->file, sizeof(devinfo->file), path); + + /* insert in the list */ + tommy_list_insert_tail(list, &devinfo->node, devinfo); + } + + closedir(d); + return 0; +} +#endif + +/** + * Get SMART attributes. + */ +#if HAVE_LINUX_DEVICE +static int devsmart(dev_t device, const char* name, const char* custom, uint64_t* smart, char* serial, char* vendor, char* model) +{ + char cmd[128]; + char file[128]; + FILE* f; + int ret; + + if (devresolve(device, file, sizeof(file)) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to resolve device '%u:%u'.\n", major(device), minor(device)); + return -1; + /* LCOV_EXCL_STOP */ + } + + /* if there is a custom command */ + if (custom[0]) { + char option[128]; + snprintf(option, sizeof(option), custom, file); + snprintf(cmd, sizeof(cmd), "smartctl -a %s", option); + } else { + snprintf(cmd, sizeof(cmd), "smartctl -a %s", file); + } + + log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd); + + f = popen(cmd, "r"); + if (!f) { + /* LCOV_EXCL_START */ + log_fatal("Failed to run '%s' (from popen).\n", cmd); + return -1; + /* LCOV_EXCL_STOP */ + } + + if (smartctl_attribute(f, file, name, smart, serial, vendor, model) != 0) { + /* LCOV_EXCL_START */ + pclose(f); + return -1; + /* LCOV_EXCL_STOP */ + } + + ret = pclose(f); + + log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret); + + if (!WIFEXITED(ret)) { + /* LCOV_EXCL_START */ + log_fatal("Failed to run '%s' (not exited).\n", cmd); + return -1; + /* LCOV_EXCL_STOP */ + } + if (WEXITSTATUS(ret) == 127) { + /* LCOV_EXCL_START */ + log_fatal("Failed to run '%s' (from sh).\n", cmd); + return -1; + /* LCOV_EXCL_STOP */ + } + + /* store the return smartctl return value */ + smart[SMART_FLAGS] = WEXITSTATUS(ret); + + return 0; +} +#endif + +/** + * Spin down a specific device. + */ +#if HAVE_LINUX_DEVICE +static int devdown(dev_t device, const char* name, const char* custom) +{ + char cmd[128]; + char file[128]; + FILE* f; + int ret; + + if (devresolve(device, file, sizeof(file)) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to resolve device '%u:%u'.\n", major(device), minor(device)); + return -1; + /* LCOV_EXCL_STOP */ + } + + /* if there is a custom command */ + if (custom[0]) { + char option[128]; + snprintf(option, sizeof(option), custom, file); + snprintf(cmd, sizeof(cmd), "smartctl -s standby,now %s", option); + } else { + snprintf(cmd, sizeof(cmd), "smartctl -s standby,now %s", file); + } + + log_tag("smartctl:%s:%s:run: %s\n", file, name, cmd); + + f = popen(cmd, "r"); + if (!f) { + /* LCOV_EXCL_START */ + log_fatal("Failed to run '%s' (from popen).\n", cmd); + return -1; + /* LCOV_EXCL_STOP */ + } + + if (smartctl_flush(f, file, name) != 0) { + /* LCOV_EXCL_START */ + pclose(f); + return -1; + /* LCOV_EXCL_STOP */ + } + + ret = pclose(f); + + log_tag("smartctl:%s:%s:ret: %x\n", file, name, ret); + + if (!WIFEXITED(ret)) { + /* LCOV_EXCL_START */ + log_fatal("Failed to run '%s' (not exited).\n", cmd); + return -1; + /* LCOV_EXCL_STOP */ + } + if (WEXITSTATUS(ret) == 127) { + /* LCOV_EXCL_START */ + log_fatal("Failed to run '%s' (from sh).\n", cmd); + return -1; + /* LCOV_EXCL_STOP */ + } + if (WEXITSTATUS(ret) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to run '%s' with return code %xh.\n", cmd, WEXITSTATUS(ret)); + return -1; + /* LCOV_EXCL_STOP */ + } + + return 0; +} +#endif + +/** + * Spin up a device. + * + * There isn't a defined way to spin up a device, + * so we just do a generic write. + */ +static int devup(const char* mountpoint) +{ + int ret; + char path[PATH_MAX]; + + /* add a temporary name used for writing */ + pathprint(path, sizeof(path), "%s.snapraid-spinup", mountpoint); + + /* do a generic write, and immediately undo it */ + ret = mkdir(path, 0); + if (ret != 0 && errno != EEXIST) { + /* LCOV_EXCL_START */ + log_fatal("Failed to create dir '%s'.\n", path); + return -1; + /* LCOV_EXCL_STOP */ + } + + /* remove the just created dir */ + rmdir(path); + + return 0; +} + +/** + * Thread for spinning up. + * + * Note that filling up the devinfo object is done inside this thread, + * to avoid to block the main thread if the device need to be spin up + * to handle stat/resolve requests. + */ +static void* thread_spinup(void* arg) +{ + devinfo_t* devinfo = arg; + struct stat st; + uint64_t start; + + start = tick_ms(); + + /* first get the device number, this usually doesn't trigger a thread_spinup */ + if (stat(devinfo->mount, &st) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to stat device '%s'.\n", devinfo->mount); + return (void*)-1; + /* LCOV_EXCL_STOP */ + } + + /* set the device number for printing */ + devinfo->device = st.st_dev; + + if (devup(devinfo->mount) != 0) { + /* LCOV_EXCL_START */ + return (void*)-1; + /* LCOV_EXCL_STOP */ + } + + msg_status("Spunup device '%u:%u' for disk '%s' in %" PRIu64 " ms.\n", major(devinfo->device), minor(devinfo->device), devinfo->name, tick_ms() - start); + + return 0; +} + +/** + * Thread for spinning down. + */ +static void* thread_spindown(void* arg) +{ +#if HAVE_LINUX_DEVICE + devinfo_t* devinfo = arg; + uint64_t start; + + start = tick_ms(); + + if (devdown(devinfo->device, devinfo->name, devinfo->smartctl) != 0) { + /* LCOV_EXCL_START */ + return (void*)-1; + /* LCOV_EXCL_STOP */ + } + + msg_status("Spundown device '%s' for disk '%s' in %" PRIu64 " ms.\n", devinfo->file, devinfo->name, tick_ms() - start); + + return 0; +#else + (void)arg; + return (void*)-1; +#endif +} + +/** + * Thread for getting smart info. + */ +static void* thread_smart(void* arg) +{ +#if HAVE_LINUX_DEVICE + devinfo_t* devinfo = arg; + + if (devsmart(devinfo->device, devinfo->name, devinfo->smartctl, devinfo->smart, devinfo->smart_serial, devinfo->smart_vendor, devinfo->smart_model) != 0) { + /* LCOV_EXCL_START */ + return (void*)-1; + /* LCOV_EXCL_STOP */ + } + + return 0; +#else + (void)arg; + return (void*)-1; +#endif +} + +static int device_thread(tommy_list* list, void* (*func)(void* arg)) +{ + int fail = 0; + tommy_node* i; + +#if HAVE_PTHREAD + /* start all threads */ + for (i = tommy_list_head(list); i != 0; i = i->next) { + devinfo_t* devinfo = i->data; + + thread_create(&devinfo->thread, 0, func, devinfo); + } + + /* join all threads */ + for (i = tommy_list_head(list); i != 0; i = i->next) { + devinfo_t* devinfo = i->data; + void* retval; + + thread_join(devinfo->thread, &retval); + + if (retval != 0) + ++fail; + } +#else + for (i = tommy_list_head(list); i != 0; i = i->next) { + devinfo_t* devinfo = i->data; + + if (func(devinfo) != 0) + ++fail; + } +#endif + if (fail != 0) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + + return 0; +} + +int devquery(tommy_list* high, tommy_list* low, int operation, int others) +{ + tommy_node* i; + void* (*func)(void* arg) = 0; + +#if HAVE_LINUX_DEVICE + if (operation != DEVICE_UP) { + struct stat st; + /* sysfs interface is required */ + if (stat("/sys/dev/block", &st) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Missing interface /sys/dev/block.\n"); + return -1; + /* LCOV_EXCL_STOP */ + } + + /* for each device */ + for (i = tommy_list_head(high); i != 0; i = i->next) { + devinfo_t* devinfo = i->data; + uint64_t device = devinfo->device; + + /* if the major is the null device, find the real one */ + if (major(device) == 0) { + /* obtain the real device */ + if (devdereference(device, &device) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to dereference device '%u:%u'.\n", major(device), minor(device)); + return -1; + /* LCOV_EXCL_STOP */ + } + } + + /* get the device file */ + if (devresolve(device, devinfo->file, sizeof(devinfo->file)) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to resolve device '%u:%u'.\n", major(device), minor(device)); + return -1; + /* LCOV_EXCL_STOP */ + } + + /* expand the tree of devices */ + if (devtree(devinfo->name, devinfo->smartctl, device, devinfo, low) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to expand device '%u:%u'.\n", major(device), minor(device)); + return -1; + /* LCOV_EXCL_STOP */ + } + } + } +#endif + + if (operation == DEVICE_UP) { + /* duplicate the high */ + for (i = tommy_list_head(high); i != 0; i = i->next) { + devinfo_t* devinfo = i->data; + devinfo_t* entry; + + entry = calloc_nofail(1, sizeof(devinfo_t)); + + entry->device = devinfo->device; + pathcpy(entry->name, sizeof(entry->name), devinfo->name); + pathcpy(entry->mount, sizeof(entry->mount), devinfo->mount); + + /* insert in the high */ + tommy_list_insert_tail(low, &entry->node, entry); + } + } + +#if HAVE_LINUX_DEVICE + /* add other devices */ + if (others) { + if (devscan(low) != 0) { + /* LCOV_EXCL_START */ + log_fatal("Failed to list other devices.\n"); + return -1; + /* LCOV_EXCL_STOP */ + } + } +#else + (void)others; +#endif + + switch (operation) { + case DEVICE_UP : func = thread_spinup; break; + case DEVICE_DOWN : func = thread_spindown; break; + case DEVICE_SMART : func = thread_smart; break; + } + + if (!func) + return 0; + + return device_thread(low, func); +} + +void os_init(int opt) +{ +#if HAVE_BLKID + int ret; + ret = blkid_get_cache(&cache, NULL); + if (ret != 0) { + /* LCOV_EXCL_START */ + log_fatal("WARNING Failed to get blkid cache\n"); + /* LCOV_EXCL_STOP */ + } +#endif + + (void)opt; +} + +void os_done(void) +{ +#if HAVE_BLKID + if (cache != 0) + blkid_put_cache(cache); +#endif +} + +/* LCOV_EXCL_START */ +void os_abort(void) +{ +#if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS + void* stack[32]; + char** messages; + size_t size; + unsigned i; +#endif + + printf("Stacktrace of " PACKAGE " v" VERSION); +#ifdef _linux + printf(", linux"); +#endif +#ifdef __GNUC__ + printf(", gcc " __VERSION__); +#endif + printf(", %d-bit", (int)sizeof(void *) * 8); + printf(", PATH_MAX=%d", PATH_MAX); + printf("\n"); + +#if HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS + size = backtrace(stack, 32); + + messages = backtrace_symbols(stack, size); + + for (i = 1; i < size; ++i) { + const char* msg; + + if (messages) + msg = messages[i]; + else + msg = ""; + + printf("[bt] %02u: %s\n", i, msg); + + if (messages) { + int ret; + char addr2line[1024]; + size_t j = 0; + while (msg[j] != '(' && msg[j] != ' ' && msg[j] != 0) + ++j; + + snprintf(addr2line, sizeof(addr2line), "addr2line %p -e %.*s", stack[i], (unsigned)j, msg); + + ret = system(addr2line); + if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) + printf("exit:%d\n", WEXITSTATUS(ret)); + if (WIFSIGNALED(ret)) + printf("signal:%d\n", WTERMSIG(ret)); + } + } +#endif + + printf("Please report this error to the SnapRAID Forum:\n"); + printf("https://sourceforge.net/p/snapraid/discussion/1677233/\n"); + + abort(); +} +/* LCOV_EXCL_STOP */ + +void os_clear(void) +{ + /* ANSI codes */ + printf("\033[H"); /* cursor at topleft */ + printf("\033[2J"); /* clear screen */ +} + +size_t direct_size(void) +{ + long size; + + size = sysconf(_SC_PAGESIZE); + + if (size == -1) { + /* LCOV_EXCL_START */ + log_fatal("No page size\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + return size; +} + +#endif + diff --git a/cmdline/unix.h b/cmdline/unix.h new file mode 100644 index 0000000..8b190ce --- /dev/null +++ b/cmdline/unix.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#ifndef __UNIX_H +#define __UNIX_H + +#ifdef __linux__ +#define HAVE_LINUX_DEVICE 1 /**< In Linux enables special device support. */ +#define HAVE_DIRECT_IO 1 /**< Support O_DIRECT in open(). */ +#endif + +#define O_BINARY 0 /**< Not used in Unix. */ +#define O_SEQUENTIAL 0 /**< In Unix posix_fadvise() shall be used. */ + +/** + * If nanoseconds are not supported, we report the special STAT_NSEC_INVALID value, + * to mark that it's undefined. + */ +#define STAT_NSEC_INVALID -1 + +/* Check if we have nanoseconds support */ +#if HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC +#define STAT_NSEC(st) ((int)(st)->st_mtim.tv_nsec) /* Linux */ +#elif HAVE_STRUCT_STAT_ST_MTIMENSEC +#define STAT_NSEC(st) ((int)(st)->st_mtimensec) /* NetBSD */ +#elif HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC +#define STAT_NSEC(st) ((int)(st)->st_mtimespec.tv_nsec) /* FreeBSD, Mac OS X */ +#else +#define STAT_NSEC(st) STAT_NSEC_INVALID +#endif + +/** + * Open a file with the O_NOATIME flag to avoid to update the access time. + */ +int open_noatime(const char* file, int flags); + +/** + * Check if the specified file is hidden. + */ +int dirent_hidden(struct dirent* dd); + +/** + * Return a description of the file type. + */ +const char* stat_desc(struct stat* st); + +/** + * Return the aligment requirement for direct IO. + */ +size_t direct_size(void); + +#endif + diff --git a/cmdline/util.c b/cmdline/util.c new file mode 100644 index 0000000..1a35b85 --- /dev/null +++ b/cmdline/util.c @@ -0,0 +1,641 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#include "portable.h" + +#include "support.h" +#include "util.h" +#include "raid/cpu.h" +#include "raid/memory.h" + +/****************************************************************************/ +/* memory */ + +void* malloc_nofail_align(size_t size, void** freeptr) +{ + void* ptr; + + ptr = raid_malloc(size, freeptr); + + if (!ptr) { + /* LCOV_EXCL_START */ + malloc_fail(size); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + return ptr; +} + +void* malloc_nofail_direct(size_t size, void** freeptr) +{ + void* ptr; + + ptr = raid_malloc_align(size, direct_size(), freeptr); + + if (!ptr) { + /* LCOV_EXCL_START */ + malloc_fail(size); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + return ptr; +} + +void** malloc_nofail_vector_align(int nd, int n, size_t size, void** freeptr) +{ + void* ptr; + + ptr = raid_malloc_vector(nd, n, size, freeptr); + + if (!ptr) { + /* LCOV_EXCL_START */ + malloc_fail(n * size); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + return ptr; +} + +void** malloc_nofail_vector_direct(int nd, int n, size_t size, void** freeptr) +{ + void* ptr; + + ptr = raid_malloc_vector_align(nd, n, size, direct_size(), 0, freeptr); + + if (!ptr) { + /* LCOV_EXCL_START */ + malloc_fail(n * size); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + + return ptr; +} + +void* malloc_nofail_test(size_t size) +{ + void* ptr; + + ptr = malloc_nofail(size); + + mtest_vector(1, size, &ptr); + + return ptr; +} + +/** + * Fast memory test. + * + * It's similar at raid_mtest_vector() but faster because + * we have a lot of buffers to verify. + */ +static int fast_mtest_vector(int n, size_t size, void** vv) +{ + int i, j; + + /* test with all the bits */ + for (i = 0; i < 8; ++i) { + unsigned char value = 1 << i; + + /* fill first */ + memset(vv[0], value, size); + + /* copy to the next */ + for (j = 1; j < n; ++j) + memcpy(vv[j], vv[j - 1], size); + + /* compare with the previous */ + for (j = 1; j <= n; ++j) + if (memcmp(vv[j % n], vv[j - 1], size) != 0) + return -1; + } + + return 0; +} + +void mtest_vector(int n, size_t size, void** vv) +{ + if (fast_mtest_vector(n, size, vv) != 0) { + /* LCOV_EXCL_START */ + log_fatal("DANGER! Your RAM memory is broken! DO NOT PROCEED UNTIL FIXED!\n"); + log_fatal("Try running a memory test like http://www.memtest86.com/\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } +} + +/****************************************************************************/ +/* crc */ + +uint32_t CRC32C_0[256] = { + 0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4, + 0xc79a971f, 0x35f1141c, 0x26a1e7e8, 0xd4ca64eb, + 0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b, + 0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24, + 0x105ec76f, 0xe235446c, 0xf165b798, 0x030e349b, + 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384, + 0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54, + 0x5d1d08bf, 0xaf768bbc, 0xbc267848, 0x4e4dfb4b, + 0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a, + 0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35, + 0xaa64d611, 0x580f5512, 0x4b5fa6e6, 0xb93425e5, + 0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa, + 0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45, + 0xf779deae, 0x05125dad, 0x1642ae59, 0xe4292d5a, + 0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a, + 0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595, + 0x417b1dbc, 0xb3109ebf, 0xa0406d4b, 0x522bee48, + 0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957, + 0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687, + 0x0c38d26c, 0xfe53516f, 0xed03a29b, 0x1f682198, + 0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927, + 0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38, + 0xdbfc821c, 0x2997011f, 0x3ac7f2eb, 0xc8ac71e8, + 0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7, + 0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096, + 0xa65c047d, 0x5437877e, 0x4767748a, 0xb50cf789, + 0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859, + 0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46, + 0x7198540d, 0x83f3d70e, 0x90a324fa, 0x62c8a7f9, + 0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6, + 0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36, + 0x3cdb9bdd, 0xceb018de, 0xdde0eb2a, 0x2f8b6829, + 0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c, + 0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93, + 0x082f63b7, 0xfa44e0b4, 0xe9141340, 0x1b7f9043, + 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c, + 0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3, + 0x55326b08, 0xa759e80b, 0xb4091bff, 0x466298fc, + 0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c, + 0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033, + 0xa24bb5a6, 0x502036a5, 0x4370c551, 0xb11b4652, + 0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d, + 0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d, + 0xef087a76, 0x1d63f975, 0x0e330a81, 0xfc588982, + 0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d, + 0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622, + 0x38cc2a06, 0xcaa7a905, 0xd9f75af1, 0x2b9cd9f2, + 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed, + 0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530, + 0x0417b1db, 0xf67c32d8, 0xe52cc12c, 0x1747422f, + 0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff, + 0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0, + 0xd3d3e1ab, 0x21b862a8, 0x32e8915c, 0xc083125f, + 0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540, + 0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90, + 0x9e902e7b, 0x6cfbad78, 0x7fab5e8c, 0x8dc0dd8f, + 0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee, + 0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1, + 0x69e9f0d5, 0x9b8273d6, 0x88d28022, 0x7ab90321, + 0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e, + 0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81, + 0x34f4f86a, 0xc69f7b69, 0xd5cf889d, 0x27a40b9e, + 0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e, + 0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351 +}; + +uint32_t CRC32C_1[256] = { + 0x00000000, 0x13a29877, 0x274530ee, 0x34e7a899, + 0x4e8a61dc, 0x5d28f9ab, 0x69cf5132, 0x7a6dc945, + 0x9d14c3b8, 0x8eb65bcf, 0xba51f356, 0xa9f36b21, + 0xd39ea264, 0xc03c3a13, 0xf4db928a, 0xe7790afd, + 0x3fc5f181, 0x2c6769f6, 0x1880c16f, 0x0b225918, + 0x714f905d, 0x62ed082a, 0x560aa0b3, 0x45a838c4, + 0xa2d13239, 0xb173aa4e, 0x859402d7, 0x96369aa0, + 0xec5b53e5, 0xfff9cb92, 0xcb1e630b, 0xd8bcfb7c, + 0x7f8be302, 0x6c297b75, 0x58ced3ec, 0x4b6c4b9b, + 0x310182de, 0x22a31aa9, 0x1644b230, 0x05e62a47, + 0xe29f20ba, 0xf13db8cd, 0xc5da1054, 0xd6788823, + 0xac154166, 0xbfb7d911, 0x8b507188, 0x98f2e9ff, + 0x404e1283, 0x53ec8af4, 0x670b226d, 0x74a9ba1a, + 0x0ec4735f, 0x1d66eb28, 0x298143b1, 0x3a23dbc6, + 0xdd5ad13b, 0xcef8494c, 0xfa1fe1d5, 0xe9bd79a2, + 0x93d0b0e7, 0x80722890, 0xb4958009, 0xa737187e, + 0xff17c604, 0xecb55e73, 0xd852f6ea, 0xcbf06e9d, + 0xb19da7d8, 0xa23f3faf, 0x96d89736, 0x857a0f41, + 0x620305bc, 0x71a19dcb, 0x45463552, 0x56e4ad25, + 0x2c896460, 0x3f2bfc17, 0x0bcc548e, 0x186eccf9, + 0xc0d23785, 0xd370aff2, 0xe797076b, 0xf4359f1c, + 0x8e585659, 0x9dface2e, 0xa91d66b7, 0xbabffec0, + 0x5dc6f43d, 0x4e646c4a, 0x7a83c4d3, 0x69215ca4, + 0x134c95e1, 0x00ee0d96, 0x3409a50f, 0x27ab3d78, + 0x809c2506, 0x933ebd71, 0xa7d915e8, 0xb47b8d9f, + 0xce1644da, 0xddb4dcad, 0xe9537434, 0xfaf1ec43, + 0x1d88e6be, 0x0e2a7ec9, 0x3acdd650, 0x296f4e27, + 0x53028762, 0x40a01f15, 0x7447b78c, 0x67e52ffb, + 0xbf59d487, 0xacfb4cf0, 0x981ce469, 0x8bbe7c1e, + 0xf1d3b55b, 0xe2712d2c, 0xd69685b5, 0xc5341dc2, + 0x224d173f, 0x31ef8f48, 0x050827d1, 0x16aabfa6, + 0x6cc776e3, 0x7f65ee94, 0x4b82460d, 0x5820de7a, + 0xfbc3faf9, 0xe861628e, 0xdc86ca17, 0xcf245260, + 0xb5499b25, 0xa6eb0352, 0x920cabcb, 0x81ae33bc, + 0x66d73941, 0x7575a136, 0x419209af, 0x523091d8, + 0x285d589d, 0x3bffc0ea, 0x0f186873, 0x1cbaf004, + 0xc4060b78, 0xd7a4930f, 0xe3433b96, 0xf0e1a3e1, + 0x8a8c6aa4, 0x992ef2d3, 0xadc95a4a, 0xbe6bc23d, + 0x5912c8c0, 0x4ab050b7, 0x7e57f82e, 0x6df56059, + 0x1798a91c, 0x043a316b, 0x30dd99f2, 0x237f0185, + 0x844819fb, 0x97ea818c, 0xa30d2915, 0xb0afb162, + 0xcac27827, 0xd960e050, 0xed8748c9, 0xfe25d0be, + 0x195cda43, 0x0afe4234, 0x3e19eaad, 0x2dbb72da, + 0x57d6bb9f, 0x447423e8, 0x70938b71, 0x63311306, + 0xbb8de87a, 0xa82f700d, 0x9cc8d894, 0x8f6a40e3, + 0xf50789a6, 0xe6a511d1, 0xd242b948, 0xc1e0213f, + 0x26992bc2, 0x353bb3b5, 0x01dc1b2c, 0x127e835b, + 0x68134a1e, 0x7bb1d269, 0x4f567af0, 0x5cf4e287, + 0x04d43cfd, 0x1776a48a, 0x23910c13, 0x30339464, + 0x4a5e5d21, 0x59fcc556, 0x6d1b6dcf, 0x7eb9f5b8, + 0x99c0ff45, 0x8a626732, 0xbe85cfab, 0xad2757dc, + 0xd74a9e99, 0xc4e806ee, 0xf00fae77, 0xe3ad3600, + 0x3b11cd7c, 0x28b3550b, 0x1c54fd92, 0x0ff665e5, + 0x759baca0, 0x663934d7, 0x52de9c4e, 0x417c0439, + 0xa6050ec4, 0xb5a796b3, 0x81403e2a, 0x92e2a65d, + 0xe88f6f18, 0xfb2df76f, 0xcfca5ff6, 0xdc68c781, + 0x7b5fdfff, 0x68fd4788, 0x5c1aef11, 0x4fb87766, + 0x35d5be23, 0x26772654, 0x12908ecd, 0x013216ba, + 0xe64b1c47, 0xf5e98430, 0xc10e2ca9, 0xd2acb4de, + 0xa8c17d9b, 0xbb63e5ec, 0x8f844d75, 0x9c26d502, + 0x449a2e7e, 0x5738b609, 0x63df1e90, 0x707d86e7, + 0x0a104fa2, 0x19b2d7d5, 0x2d557f4c, 0x3ef7e73b, + 0xd98eedc6, 0xca2c75b1, 0xfecbdd28, 0xed69455f, + 0x97048c1a, 0x84a6146d, 0xb041bcf4, 0xa3e32483 +}; + +uint32_t CRC32C_2[256] = { + 0x00000000, 0xa541927e, 0x4f6f520d, 0xea2ec073, + 0x9edea41a, 0x3b9f3664, 0xd1b1f617, 0x74f06469, + 0x38513ec5, 0x9d10acbb, 0x773e6cc8, 0xd27ffeb6, + 0xa68f9adf, 0x03ce08a1, 0xe9e0c8d2, 0x4ca15aac, + 0x70a27d8a, 0xd5e3eff4, 0x3fcd2f87, 0x9a8cbdf9, + 0xee7cd990, 0x4b3d4bee, 0xa1138b9d, 0x045219e3, + 0x48f3434f, 0xedb2d131, 0x079c1142, 0xa2dd833c, + 0xd62de755, 0x736c752b, 0x9942b558, 0x3c032726, + 0xe144fb14, 0x4405696a, 0xae2ba919, 0x0b6a3b67, + 0x7f9a5f0e, 0xdadbcd70, 0x30f50d03, 0x95b49f7d, + 0xd915c5d1, 0x7c5457af, 0x967a97dc, 0x333b05a2, + 0x47cb61cb, 0xe28af3b5, 0x08a433c6, 0xade5a1b8, + 0x91e6869e, 0x34a714e0, 0xde89d493, 0x7bc846ed, + 0x0f382284, 0xaa79b0fa, 0x40577089, 0xe516e2f7, + 0xa9b7b85b, 0x0cf62a25, 0xe6d8ea56, 0x43997828, + 0x37691c41, 0x92288e3f, 0x78064e4c, 0xdd47dc32, + 0xc76580d9, 0x622412a7, 0x880ad2d4, 0x2d4b40aa, + 0x59bb24c3, 0xfcfab6bd, 0x16d476ce, 0xb395e4b0, + 0xff34be1c, 0x5a752c62, 0xb05bec11, 0x151a7e6f, + 0x61ea1a06, 0xc4ab8878, 0x2e85480b, 0x8bc4da75, + 0xb7c7fd53, 0x12866f2d, 0xf8a8af5e, 0x5de93d20, + 0x29195949, 0x8c58cb37, 0x66760b44, 0xc337993a, + 0x8f96c396, 0x2ad751e8, 0xc0f9919b, 0x65b803e5, + 0x1148678c, 0xb409f5f2, 0x5e273581, 0xfb66a7ff, + 0x26217bcd, 0x8360e9b3, 0x694e29c0, 0xcc0fbbbe, + 0xb8ffdfd7, 0x1dbe4da9, 0xf7908dda, 0x52d11fa4, + 0x1e704508, 0xbb31d776, 0x511f1705, 0xf45e857b, + 0x80aee112, 0x25ef736c, 0xcfc1b31f, 0x6a802161, + 0x56830647, 0xf3c29439, 0x19ec544a, 0xbcadc634, + 0xc85da25d, 0x6d1c3023, 0x8732f050, 0x2273622e, + 0x6ed23882, 0xcb93aafc, 0x21bd6a8f, 0x84fcf8f1, + 0xf00c9c98, 0x554d0ee6, 0xbf63ce95, 0x1a225ceb, + 0x8b277743, 0x2e66e53d, 0xc448254e, 0x6109b730, + 0x15f9d359, 0xb0b84127, 0x5a968154, 0xffd7132a, + 0xb3764986, 0x1637dbf8, 0xfc191b8b, 0x595889f5, + 0x2da8ed9c, 0x88e97fe2, 0x62c7bf91, 0xc7862def, + 0xfb850ac9, 0x5ec498b7, 0xb4ea58c4, 0x11abcaba, + 0x655baed3, 0xc01a3cad, 0x2a34fcde, 0x8f756ea0, + 0xc3d4340c, 0x6695a672, 0x8cbb6601, 0x29faf47f, + 0x5d0a9016, 0xf84b0268, 0x1265c21b, 0xb7245065, + 0x6a638c57, 0xcf221e29, 0x250cde5a, 0x804d4c24, + 0xf4bd284d, 0x51fcba33, 0xbbd27a40, 0x1e93e83e, + 0x5232b292, 0xf77320ec, 0x1d5de09f, 0xb81c72e1, + 0xccec1688, 0x69ad84f6, 0x83834485, 0x26c2d6fb, + 0x1ac1f1dd, 0xbf8063a3, 0x55aea3d0, 0xf0ef31ae, + 0x841f55c7, 0x215ec7b9, 0xcb7007ca, 0x6e3195b4, + 0x2290cf18, 0x87d15d66, 0x6dff9d15, 0xc8be0f6b, + 0xbc4e6b02, 0x190ff97c, 0xf321390f, 0x5660ab71, + 0x4c42f79a, 0xe90365e4, 0x032da597, 0xa66c37e9, + 0xd29c5380, 0x77ddc1fe, 0x9df3018d, 0x38b293f3, + 0x7413c95f, 0xd1525b21, 0x3b7c9b52, 0x9e3d092c, + 0xeacd6d45, 0x4f8cff3b, 0xa5a23f48, 0x00e3ad36, + 0x3ce08a10, 0x99a1186e, 0x738fd81d, 0xd6ce4a63, + 0xa23e2e0a, 0x077fbc74, 0xed517c07, 0x4810ee79, + 0x04b1b4d5, 0xa1f026ab, 0x4bdee6d8, 0xee9f74a6, + 0x9a6f10cf, 0x3f2e82b1, 0xd50042c2, 0x7041d0bc, + 0xad060c8e, 0x08479ef0, 0xe2695e83, 0x4728ccfd, + 0x33d8a894, 0x96993aea, 0x7cb7fa99, 0xd9f668e7, + 0x9557324b, 0x3016a035, 0xda386046, 0x7f79f238, + 0x0b899651, 0xaec8042f, 0x44e6c45c, 0xe1a75622, + 0xdda47104, 0x78e5e37a, 0x92cb2309, 0x378ab177, + 0x437ad51e, 0xe63b4760, 0x0c158713, 0xa954156d, + 0xe5f54fc1, 0x40b4ddbf, 0xaa9a1dcc, 0x0fdb8fb2, + 0x7b2bebdb, 0xde6a79a5, 0x3444b9d6, 0x91052ba8 +}; + +uint32_t CRC32C_3[256] = { + 0x00000000, 0xdd45aab8, 0xbf672381, 0x62228939, + 0x7b2231f3, 0xa6679b4b, 0xc4451272, 0x1900b8ca, + 0xf64463e6, 0x2b01c95e, 0x49234067, 0x9466eadf, + 0x8d665215, 0x5023f8ad, 0x32017194, 0xef44db2c, + 0xe964b13d, 0x34211b85, 0x560392bc, 0x8b463804, + 0x924680ce, 0x4f032a76, 0x2d21a34f, 0xf06409f7, + 0x1f20d2db, 0xc2657863, 0xa047f15a, 0x7d025be2, + 0x6402e328, 0xb9474990, 0xdb65c0a9, 0x06206a11, + 0xd725148b, 0x0a60be33, 0x6842370a, 0xb5079db2, + 0xac072578, 0x71428fc0, 0x136006f9, 0xce25ac41, + 0x2161776d, 0xfc24ddd5, 0x9e0654ec, 0x4343fe54, + 0x5a43469e, 0x8706ec26, 0xe524651f, 0x3861cfa7, + 0x3e41a5b6, 0xe3040f0e, 0x81268637, 0x5c632c8f, + 0x45639445, 0x98263efd, 0xfa04b7c4, 0x27411d7c, + 0xc805c650, 0x15406ce8, 0x7762e5d1, 0xaa274f69, + 0xb327f7a3, 0x6e625d1b, 0x0c40d422, 0xd1057e9a, + 0xaba65fe7, 0x76e3f55f, 0x14c17c66, 0xc984d6de, + 0xd0846e14, 0x0dc1c4ac, 0x6fe34d95, 0xb2a6e72d, + 0x5de23c01, 0x80a796b9, 0xe2851f80, 0x3fc0b538, + 0x26c00df2, 0xfb85a74a, 0x99a72e73, 0x44e284cb, + 0x42c2eeda, 0x9f874462, 0xfda5cd5b, 0x20e067e3, + 0x39e0df29, 0xe4a57591, 0x8687fca8, 0x5bc25610, + 0xb4868d3c, 0x69c32784, 0x0be1aebd, 0xd6a40405, + 0xcfa4bccf, 0x12e11677, 0x70c39f4e, 0xad8635f6, + 0x7c834b6c, 0xa1c6e1d4, 0xc3e468ed, 0x1ea1c255, + 0x07a17a9f, 0xdae4d027, 0xb8c6591e, 0x6583f3a6, + 0x8ac7288a, 0x57828232, 0x35a00b0b, 0xe8e5a1b3, + 0xf1e51979, 0x2ca0b3c1, 0x4e823af8, 0x93c79040, + 0x95e7fa51, 0x48a250e9, 0x2a80d9d0, 0xf7c57368, + 0xeec5cba2, 0x3380611a, 0x51a2e823, 0x8ce7429b, + 0x63a399b7, 0xbee6330f, 0xdcc4ba36, 0x0181108e, + 0x1881a844, 0xc5c402fc, 0xa7e68bc5, 0x7aa3217d, + 0x52a0c93f, 0x8fe56387, 0xedc7eabe, 0x30824006, + 0x2982f8cc, 0xf4c75274, 0x96e5db4d, 0x4ba071f5, + 0xa4e4aad9, 0x79a10061, 0x1b838958, 0xc6c623e0, + 0xdfc69b2a, 0x02833192, 0x60a1b8ab, 0xbde41213, + 0xbbc47802, 0x6681d2ba, 0x04a35b83, 0xd9e6f13b, + 0xc0e649f1, 0x1da3e349, 0x7f816a70, 0xa2c4c0c8, + 0x4d801be4, 0x90c5b15c, 0xf2e73865, 0x2fa292dd, + 0x36a22a17, 0xebe780af, 0x89c50996, 0x5480a32e, + 0x8585ddb4, 0x58c0770c, 0x3ae2fe35, 0xe7a7548d, + 0xfea7ec47, 0x23e246ff, 0x41c0cfc6, 0x9c85657e, + 0x73c1be52, 0xae8414ea, 0xcca69dd3, 0x11e3376b, + 0x08e38fa1, 0xd5a62519, 0xb784ac20, 0x6ac10698, + 0x6ce16c89, 0xb1a4c631, 0xd3864f08, 0x0ec3e5b0, + 0x17c35d7a, 0xca86f7c2, 0xa8a47efb, 0x75e1d443, + 0x9aa50f6f, 0x47e0a5d7, 0x25c22cee, 0xf8878656, + 0xe1873e9c, 0x3cc29424, 0x5ee01d1d, 0x83a5b7a5, + 0xf90696d8, 0x24433c60, 0x4661b559, 0x9b241fe1, + 0x8224a72b, 0x5f610d93, 0x3d4384aa, 0xe0062e12, + 0x0f42f53e, 0xd2075f86, 0xb025d6bf, 0x6d607c07, + 0x7460c4cd, 0xa9256e75, 0xcb07e74c, 0x16424df4, + 0x106227e5, 0xcd278d5d, 0xaf050464, 0x7240aedc, + 0x6b401616, 0xb605bcae, 0xd4273597, 0x09629f2f, + 0xe6264403, 0x3b63eebb, 0x59416782, 0x8404cd3a, + 0x9d0475f0, 0x4041df48, 0x22635671, 0xff26fcc9, + 0x2e238253, 0xf36628eb, 0x9144a1d2, 0x4c010b6a, + 0x5501b3a0, 0x88441918, 0xea669021, 0x37233a99, + 0xd867e1b5, 0x05224b0d, 0x6700c234, 0xba45688c, + 0xa345d046, 0x7e007afe, 0x1c22f3c7, 0xc167597f, + 0xc747336e, 0x1a0299d6, 0x782010ef, 0xa565ba57, + 0xbc65029d, 0x6120a825, 0x0302211c, 0xde478ba4, + 0x31035088, 0xec46fa30, 0x8e647309, 0x5321d9b1, + 0x4a21617b, 0x9764cbc3, 0xf54642fa, 0x2803e842 +}; + +#if HAVE_SSE42 +int crc_x86; +#endif + +uint32_t crc32c_gen(uint32_t crc, const unsigned char* ptr, unsigned size) +{ + crc ^= CRC_IV; + + crc = crc32c_gen_plain(crc, ptr, size); + + crc ^= CRC_IV; + + return crc; +} + +#if HAVE_SSE42 +uint32_t crc32c_x86(uint32_t crc, const unsigned char* ptr, unsigned size) +{ + crc ^= CRC_IV; + + crc = crc32c_x86_plain(crc, ptr, size); + + crc ^= CRC_IV; + + return crc; +} +#endif + +uint32_t (*crc32c)(uint32_t crc, const unsigned char* ptr, unsigned size); + +void crc32c_init(void) +{ + crc32c = crc32c_gen; +#if HAVE_SSE42 + if (raid_cpu_has_crc32()) { + crc_x86 = 1; + crc32c = crc32c_x86; + } +#endif +} + +/****************************************************************************/ +/* byte operations */ + +/* + * Rotate left. + * In x86/x64 they are optimized with a single assembler instruction. + */ +static inline uint32_t util_rotl32(uint32_t x, int8_t r) +{ + return (x << r) | (x >> (32 - r)); +} + +static inline uint64_t util_rotl64(uint64_t x, int8_t r) +{ + return (x << r) | (x >> (64 - r)); +} + +/** + * Swap endianess. + * They are needed only if BigEndian. + */ +#if defined(__GNUC__) + +#define util_swap32(x) __builtin_bswap32(x) +#define util_swap64(x) __builtin_bswap64(x) + +#elif HAVE_BYTESWAP_H + +#include + +#define util_swap32(x) bswap_32(x) +#define util_swap64(x) bswap_64(x) + +#else +static inline uint32_t util_swap32(uint32_t v) +{ + return (util_rotl32(v, 8) & 0x00ff00ff) + | (util_rotl32(v, 24) & 0xff00ff00); +} + +static inline uint64_t util_swap64(uint64_t v) +{ + return (util_rotl64(v, 8) & 0x000000ff000000ffULL) + | (util_rotl64(v, 24) & 0x0000ff000000ff00ULL) + | (util_rotl64(v, 40) & 0x00ff000000ff0000ULL) + | (util_rotl64(v, 56) & 0xff000000ff000000ULL); +} +#endif + +static inline uint32_t util_read32(const void* ptr) +{ + uint32_t v; + memcpy(&v, ptr, sizeof(v)); +#if WORDS_BIGENDIAN + v = util_swap32(v); +#endif + return v; +} + +static inline uint64_t util_read64(const void* ptr) +{ + uint64_t v; + memcpy(&v, ptr, sizeof(v)); +#if WORDS_BIGENDIAN + v = util_swap64(v); +#endif + return v; +} + +static inline void util_write32(void* ptr, uint32_t v) +{ +#if WORDS_BIGENDIAN + v = util_swap32(v); +#endif + memcpy(ptr, &v, sizeof(v)); +} + +static inline void util_write64(void* ptr, uint64_t v) +{ +#if WORDS_BIGENDIAN + v = util_swap64(v); +#endif + memcpy(ptr, &v, sizeof(v)); +} + +/****************************************************************************/ +/* hash */ + +#include "murmur3.c" +#include "spooky2.c" + +void memhash(unsigned kind, const unsigned char* seed, void* digest, const void* src, size_t size) +{ + switch (kind) { + case HASH_MURMUR3 : + MurmurHash3_x86_128(src, size, seed, digest); + break; + case HASH_SPOOKY2 : + SpookyHash128(src, size, seed, digest); + break; + default : + /* LCOV_EXCL_START */ + log_fatal("Internal inconsistency in hash function %u\n", kind); + exit(EXIT_FAILURE); + break; + /* LCOV_EXCL_STOP */ + } +} + +const char* hash_config_name(unsigned kind) +{ + switch (kind) { + case HASH_UNDEFINED : return "undefined"; + case HASH_MURMUR3 : return "murmur3"; + case HASH_SPOOKY2 : return "spooky2"; + default : + /* LCOV_EXCL_START */ + return "unknown"; + /* LCOV_EXCL_STOP */ + } +} + +unsigned memdiff(const unsigned char* data1, const unsigned char* data2, size_t size) +{ + size_t i; + unsigned count; + + count = 0; + for (i = 0; i < size; ++i) { + unsigned j; + unsigned char diff = data1[i] ^ data2[i]; + for (j = 0; j < 8; ++j) { + if ((diff & 1) != 0) + ++count; + diff >>= 1; + } + } + + return count; +} + +/****************************************************************************/ +/* lock */ + +#if HAVE_LOCKFILE +int lock_lock(const char* file) +{ + int f; + + f = open(file, O_CREAT | O_TRUNC | O_WRONLY, 0600); + if (f == -1) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + + /* exclusive lock, not blocking */ + if (flock(f, LOCK_EX | LOCK_NB) == -1) { + /* LCOV_EXCL_START */ + close(f); + return -1; + /* LCOV_EXCL_STOP */ + } + + return f; +} +#endif + +#if HAVE_LOCKFILE +int lock_unlock(int f) +{ + /* + * Intentionally don't remove the lock file. + * Removing it just introduces race course with other process + * that could have already opened it. + */ + if (close(f) == -1) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + + return 0; +} +#endif + diff --git a/cmdline/util.h b/cmdline/util.h new file mode 100644 index 0000000..1661a9d --- /dev/null +++ b/cmdline/util.h @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2011 Andrea Mazzoleni + * + * 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 . + */ + +#ifndef __UTIL_H +#define __UTIL_H + +/****************************************************************************/ +/* memory */ + +/** + * Safe aligned malloc. + * If no memory is available, it aborts. + */ +void* malloc_nofail_align(size_t size, void** freeptr); + +/** + * Safe aligned malloc. Usable for direct io. + */ +void* malloc_nofail_direct(size_t size, void** freeptr); + +/** + * Safe aligned vector allocation. + * If no memory is available, it aborts. + */ +void** malloc_nofail_vector_align(int nd, int n, size_t size, void** freeptr); + +/** + * Safe page vector allocation. Usable for direct io. + * If no memory is available, it aborts. + */ +void** malloc_nofail_vector_direct(int nd, int n, size_t size, void** freeptr); + +/** + * Safe allocation with memory test. + */ +void* malloc_nofail_test(size_t size); + +/** + * Test the memory vector for RAM problems. + * If a problem is found, it crashes. + */ +void mtest_vector(int n, size_t size, void** vv); + +/****************************************************************************/ +/* crc */ + +/** + * CRC initial value. + * Using a not zero value allows to detect a leading run of zeros. + */ +#define CRC_IV 0xffffffffU + +/** + * CRC-32 (Castagnoli) table. + */ +extern uint32_t CRC32C_0[256]; +extern uint32_t CRC32C_1[256]; +extern uint32_t CRC32C_2[256]; +extern uint32_t CRC32C_3[256]; + +/** + * If the CPU support the CRC instructions. + */ +#if HAVE_SSE42 +extern int crc_x86; +#endif + +/** + * Compute CRC-32 (Castagnoli) for a single byte without the IV. + */ +static inline uint32_t crc32c_plain_char(uint32_t crc, unsigned char c) +{ +#if HAVE_SSE42 + if (tommy_likely(crc_x86)) { + asm ("crc32b %1, %0\n" : "+r" (crc) : "m" (c)); + return crc; + } +#endif + return CRC32C_0[(crc ^ c) & 0xff] ^ (crc >> 8); +} + +/** + * Compute the CRC-32 (Castagnoli) without the IV. + */ +static inline uint32_t crc32c_gen_plain(uint32_t crc, const unsigned char* ptr, unsigned size) +{ + while (size >= 4) { + crc ^= ptr[0] | (uint32_t)ptr[1] << 8 | (uint32_t)ptr[2] << 16 | (uint32_t)ptr[3] << 24; + crc = CRC32C_3[crc & 0xff] ^ CRC32C_2[(crc >> 8) & 0xff] ^ CRC32C_1[(crc >> 16) & 0xff] ^ CRC32C_0[crc >> 24]; + ptr += 4; + size -= 4; + } + + while (size) { + crc = CRC32C_0[(crc ^ *ptr) & 0xff] ^ (crc >> 8); + ++ptr; + --size; + } + + return crc; +} + +/** + * Compute the CRC-32 (Castagnoli) without the IV. + */ +#if HAVE_SSE42 +static inline uint32_t crc32c_x86_plain(uint32_t crc, const unsigned char* ptr, unsigned size) +{ +#ifdef CONFIG_X86_64 + uint64_t crc64 = crc; + while (size >= 8) { + asm ("crc32q %1, %0\n" : "+r" (crc64) : "m" (*(const uint64_t*)ptr)); + ptr += 8; + size -= 8; + } + crc = crc64; +#else + while (size >= 4) { + asm ("crc32l %1, %0\n" : "+r" (crc) : "m" (*(const uint32_t*)ptr)); + ptr += 4; + size -= 4; + } +#endif + while (size) { + asm ("crc32b %1, %0\n" : "+r" (crc) : "m" (*ptr)); + ++ptr; + --size; + } + + return crc; +} +#endif + +/** + * Compute CRC-32 (Castagnoli) without the IV. + */ +static inline uint32_t crc32c_plain(uint32_t crc, const unsigned char* ptr, unsigned size) +{ +#if HAVE_SSE42 + if (tommy_likely(crc_x86)) { + return crc32c_x86_plain(crc, ptr, size); + } +#endif + return crc32c_gen_plain(crc, ptr, size); +} + +/** + * Compute the CRC-32 (Castagnoli) + */ +uint32_t (*crc32c)(uint32_t crc, const unsigned char* ptr, unsigned size); + +/** + * Internal entry points for testing. + */ +uint32_t crc32c_gen(uint32_t crc, const unsigned char* ptr, unsigned size); +uint32_t crc32c_x86(uint32_t crc, const unsigned char* ptr, unsigned size); + +/** + * Initialize the CRC-32 (Castagnoli) support. + */ +void crc32c_init(void); + +/****************************************************************************/ +/* hash */ + +/** + * Size of the hash. + */ +#define HASH_MAX 16 + +/** + * Hash kinds. + */ +#define HASH_UNDEFINED 0 +#define HASH_MURMUR3 1 +#define HASH_SPOOKY2 2 + +/** + * Compute the HASH of a memory block. + * Seed is a 128 bit vector. + */ +void memhash(unsigned kind, const unsigned char* seed, void* digest, const void* src, size_t size); + +/** + * Return the hash name. + */ +const char* hash_config_name(unsigned kind); + +/** + * Count the number of different bits in the two buffers. + */ +unsigned memdiff(const unsigned char* data1, const unsigned char* data2, size_t size); + +/****************************************************************************/ +/* lock */ + +/** + * Create and locks the lock file. + * Return -1 on error, otherwise it's the file handle to pass to lock_unlock(). + */ +int lock_lock(const char* file); + +/** + * Unlock the lock file. + * Return -1 on error. + */ +int lock_unlock(int f); + +#endif + diff --git a/compile b/compile new file mode 100755 index 0000000..a85b723 --- /dev/null +++ b/compile @@ -0,0 +1,347 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2012-10-14.11; # UTC + +# Copyright (C) 1999-2014 Free Software Foundation, Inc. +# Written by Tom Tromey . +# +# 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 2, 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 . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/config.guess b/config.guess new file mode 100755 index 0000000..6c32c86 --- /dev/null +++ b/config.guess @@ -0,0 +1,1421 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2014 Free Software Foundation, Inc. + +timestamp='2014-11-04' + +# This file 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 . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# +# Please send patches to . + + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2014 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case "${UNAME_SYSTEM}" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval $set_cc_for_build + cat <<-EOF > $dummy.c + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + *:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + aarch64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="gnulibc1" ; fi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi + else + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-${LIBC} + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:Linux:*:*) + echo ${UNAME_MACHINE}-pc-linux-${LIBC} + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } + ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-${LIBC} + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-${LIBC} + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-${LIBC} + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-${LIBC} + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-${LIBC} + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-${LIBC} + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux-${LIBC} + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-${LIBC} + exit ;; + x86_64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + eval $set_cc_for_build + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; +esac + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..2c06e18 --- /dev/null +++ b/config.h.in @@ -0,0 +1,422 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +#undef AC_APPLE_UNIVERSAL_BUILD + +/* Define to 1 if you have the `access' function. */ +#undef HAVE_ACCESS + +/* Define to 1 if inline assembly should be used. */ +#undef HAVE_ASSEMBLY + +/* Define to 1 if avx2 is supported by the assembler. */ +#undef HAVE_AVX2 + +/* Define to 1 if you have the `backtrace' function. */ +#undef HAVE_BACKTRACE + +/* Define to 1 if you have the `backtrace_symbols' function. */ +#undef HAVE_BACKTRACE_SYMBOLS + +/* Define to 1 if you have the header file. */ +#undef HAVE_BLKID_BLKID_H + +/* Define to 1 if you have the `blkid_devno_to_devname' function. */ +#undef HAVE_BLKID_DEVNO_TO_DEVNAME + +/* Define to 1 if you have the `blkid_get_tag_value' function. */ +#undef HAVE_BLKID_GET_TAG_VALUE + +/* Define to 1 if you have the header file. */ +#undef HAVE_BYTESWAP_H + +/* Define to 1 if you have the `clock_gettime' function. */ +#undef HAVE_CLOCK_GETTIME + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_DIRENT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_EXECINFO_H + +/* Define to 1 if you have the `fallocate' function. */ +#undef HAVE_FALLOCATE + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the `ferror_unlocked' function. */ +#undef HAVE_FERROR_UNLOCKED + +/* Define to 1 if you have the `flock' function. */ +#undef HAVE_FLOCK + +/* Define to 1 if you have the `fnmatch' function. */ +#undef HAVE_FNMATCH + +/* Define to 1 if you have the header file. */ +#undef HAVE_FNMATCH_H + +/* Define to 1 if you have the `fstatat' function. */ +#undef HAVE_FSTATAT + +/* Define to 1 if you have the `fsync' function. */ +#undef HAVE_FSYNC + +/* Define to 1 if you have the `ftruncate' function. */ +#undef HAVE_FTRUNCATE + +/* Define to 1 if you have the `futimens' function. */ +#undef HAVE_FUTIMENS + +/* Define to 1 if you have the `futimes' function. */ +#undef HAVE_FUTIMES + +/* Define to 1 if you have the `futimesat' function. */ +#undef HAVE_FUTIMESAT + +/* Define to 1 if you have the `getc_unlocked' function. */ +#undef HAVE_GETC_UNLOCKED + +/* Define to 1 if you have the `getopt' function. */ +#undef HAVE_GETOPT + +/* Define to 1 if you have the header file. */ +#undef HAVE_GETOPT_H + +/* Define to 1 if you have the `getopt_long' function. */ +#undef HAVE_GETOPT_LONG + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_IO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_FIEMAP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_FS_H + +/* Define to 1 if you have the `localtime_r' function. */ +#undef HAVE_LOCALTIME_R + +/* Define to 1 if you have the `lutimes' function. */ +#undef HAVE_LUTIMES + +/* Define to 1 if you have the `mach_absolute_time' function. */ +#undef HAVE_MACH_ABSOLUTE_TIME + +/* Define to 1 if you have the header file. */ +#undef HAVE_MACH_MACH_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MATH_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `memset' function. */ +#undef HAVE_MEMSET + +/* Define to 1 if you have the `mkdir' function. */ +#undef HAVE_MKDIR + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#undef HAVE_NDIR_H + +/* Define to 1 if you have the `posix_fadvise' function. */ +#undef HAVE_POSIX_FADVISE + +/* Define to 1 if you have the `pthread_create' function. */ +#undef HAVE_PTHREAD_CREATE + +/* Define to 1 if you have the header file. */ +#undef HAVE_PTHREAD_H + +/* Define to 1 if you have the `sigaction' function. */ +#undef HAVE_SIGACTION + +/* Define to 1 if you have the `snprintf' function. */ +#undef HAVE_SNPRINTF + +/* Define to 1 if sse2 is supported by the assembler. */ +#undef HAVE_SSE2 + +/* Define to 1 if sse4.2 is supported by the assembler. */ +#undef HAVE_SSE42 + +/* Define to 1 if ssse3 is supported by the assembler. */ +#undef HAVE_SSSE3 + +/* Define to 1 if you have the `statfs' function. */ +#undef HAVE_STATFS + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDDEF_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strchr' function. */ +#undef HAVE_STRCHR + +/* Define to 1 if you have the `strerror' function. */ +#undef HAVE_STRERROR + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strrchr' function. */ +#undef HAVE_STRRCHR + +/* Define to 1 if you have the `strtoul' function. */ +#undef HAVE_STRTOUL + +/* Define to 1 if `d_ino' is a member of `struct dirent'. */ +#undef HAVE_STRUCT_DIRENT_D_INO + +/* Define to 1 if `d_type' is a member of `struct dirent'. */ +#undef HAVE_STRUCT_DIRENT_D_TYPE + +/* Define to 1 if `f_fstypename' is a member of `struct statfs'. */ +#undef HAVE_STRUCT_STATFS_F_FSTYPENAME + +/* Define to 1 if `f_type' is a member of `struct statfs'. */ +#undef HAVE_STRUCT_STATFS_F_TYPE + +/* Define to 1 if `st_mtimensec' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_MTIMENSEC + +/* Define to 1 if `st_mtimespec.tv_nsec' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC + +/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC + +/* Define to 1 if `st_nlink' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_NLINK + +/* Define to 1 if you have the `sync_file_range' function. */ +#undef HAVE_SYNC_FILE_RANGE + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_DIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_FILE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MOUNT_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STATFS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_VFS_H + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#undef HAVE_SYS_WAIT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `utimensat' function. */ +#undef HAVE_UTIMENSAT + +/* Define to 1 if you have the `vsnprintf' function. */ +#undef HAVE_VSNPRINTF + +/* Define to 1 if `major', `minor', and `makedev' are declared in . + */ +#undef MAJOR_IN_MKDEV + +/* Define to 1 if `major', `minor', and `makedev' are declared in + . */ +#undef MAJOR_IN_SYSMACROS + +/* Define to 1 if assertions should be disabled. */ +#undef NDEBUG + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif + + +/* Version number of package */ +#undef VERSION + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +# undef WORDS_BIGENDIAN +# endif +#endif + +/* Enable large inode numbers on Mac OS X 10.5. */ +#ifndef _DARWIN_USE_64_BIT_INODE +# define _DARWIN_USE_64_BIT_INODE 1 +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Define for large files, on AIX-style hosts. */ +#undef _LARGE_FILES + +/* Define to 1 if on MINIX. */ +#undef _MINIX + +/* Define to 2 if the system does not provide POSIX.1 features except with + this defined. */ +#undef _POSIX_1_SOURCE + +/* Define to 1 if you need to in order for `stat' and other things to work. */ +#undef _POSIX_SOURCE + +/* Define for Solaris 2.5.1 so the uint32_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT32_T + +/* Define for Solaris 2.5.1 so the uint64_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT64_T + +/* Define for Solaris 2.5.1 so the uint8_t typedef from , + , or is not used. If the typedef were allowed, the + #define below would cause a syntax error. */ +#undef _UINT8_T + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to the type of a signed integer type of width exactly 8 bits if such + a type exists and the standard includes do not define it. */ +#undef int8_t + +/* Define to `long int' if does not define. */ +#undef off_t + +/* Define to the equivalent of the C99 'restrict' keyword, or to + nothing if this is not supported. Do not define if restrict is + supported directly. */ +#undef restrict +/* Work around a bug in Sun C++: it does not support _Restrict or + __restrict__, even though the corresponding Sun C compiler ends up with + "#define restrict _Restrict" or "#define restrict __restrict__" in the + previous line. Perhaps some future version of Sun C++ will work with + restrict; if so, hopefully it defines __RESTRICT like Sun C does. */ +#if defined __SUNPRO_CC && !defined __RESTRICT +# define _Restrict +# define __restrict__ +#endif + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* Define to `int' if does not define. */ +#undef ssize_t + +/* Define to the type of an unsigned integer type of width exactly 32 bits if + such a type exists and the standard includes do not define it. */ +#undef uint32_t + +/* Define to the type of an unsigned integer type of width exactly 64 bits if + such a type exists and the standard includes do not define it. */ +#undef uint64_t + +/* Define to the type of an unsigned integer type of width exactly 8 bits if + such a type exists and the standard includes do not define it. */ +#undef uint8_t + +/* Define to empty if the keyword `volatile' does not work. Warning: valid + code using `volatile' can become incorrect without. Disable with care. */ +#undef volatile diff --git a/config.sub b/config.sub new file mode 100755 index 0000000..7ffe373 --- /dev/null +++ b/config.sub @@ -0,0 +1,1807 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright 1992-2014 Free Software Foundation, Inc. + +timestamp='2014-12-03' + +# This file 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 . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to . +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2014 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze*) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | aarch64 | aarch64_be \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | c8051 | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | epiphany \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ + | ns16k | ns32k \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | riscv32 | riscv64 \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | aarch64-* | aarch64_be-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; + mingw32) + basic_machine=i686-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/configure b/configure new file mode 100755 index 0000000..8492d01 --- /dev/null +++ b/configure @@ -0,0 +1,8191 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for snapraid 11.2. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='snapraid' +PACKAGE_TARNAME='snapraid' +PACKAGE_VERSION='11.2' +PACKAGE_STRING='snapraid 11.2' +PACKAGE_BUGREPORT='' +PACKAGE_URL='http://www.snapraid.it' + +ac_unique_file="cmdline/snapraid.c" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +LIBOBJS +TESTENV_AVX2 +TESTENV_SSE42 +TESTENV_SSSE3 +TESTENV_SSE2 +FAILENV +TESTENV +HAVE_EMULATOR_FALSE +HAVE_EMULATOR_TRUE +HAVE_THREAD_CHECKER_FALSE +HAVE_THREAD_CHECKER_TRUE +HAVE_MEMORY_CHECKER_FALSE +HAVE_MEMORY_CHECKER_TRUE +HAVE_POSIX_FALSE +HAVE_POSIX_TRUE +HAVE_ADVD2_FALSE +HAVE_ADVD2_TRUE +ADVD2 +SDE +WINE +VALGRIND +EGREP +GREP +CPP +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_silent_rules +enable_largefile +enable_assert +with_blkid +enable_asm +enable_profiler +enable_coverage +enable_valgrind +enable_sgcheck +enable_helgrind +enable_drd +enable_asan +enable_msan +enable_ubsan +enable_tsan +enable_sde +enable_debug +enable_warning_as_error +enable_warning +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP +TESTENV +FAILENV +TESTENV_SSE2 +TESTENV_SSSE3 +TESTENV_SSE42 +TESTENV_AVX2' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures snapraid 11.2 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/snapraid] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of snapraid 11.2:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") + --disable-largefile omit support for large files + --disable-assert turn off assertions + --disable-asm Disable inline assembly + --enable-profiler enable the use of gprof for code coverage + --enable-coverage enable the use of gcov for code coverage + --enable-valgrind enable the use of valgrind in testing + --enable-sgcheck enable the use of sgcheck in testing + --enable-helgrind enable the use of helgrind in testing + --enable-drd enable the use of drd in testing + --enable-asan enable the use of AddressSanitizer in testing + --enable-msan enable the use of MemorySanitizer in testing + --enable-ubsan enable the use of UndefinedBehaviourSanitizer in + testing + --enable-tsan enable the use of ThreadSanitizer in testing + --enable-sde enable the use of SDE emulator in testing + --enable-debug enable debugging + --enable-warning-as-error + stop build on warnings + --enable-warning enable extra warning + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --without-blkid Ignore presence of blkid and disable it + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + TESTENV Test environment + FAILENV Test environment for failing tests + TESTENV_SSE2 + Test environment for SSE2 + TESTENV_SSSE3 + Test environment for SSSE3 + TESTENV_SSE42 + Test environment for SSE42 + TESTENV_AVX2 + Test environment for AVX2 + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +snapraid home page: . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +snapraid configure 11.2 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type + +# ac_fn_c_find_uintX_t LINENO BITS VAR +# ------------------------------------ +# Finds an unsigned integer type with width BITS, setting cache variable VAR +# accordingly. +ac_fn_c_find_uintX_t () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5 +$as_echo_n "checking for uint$2_t... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + # Order is important - never check a type that is potentially smaller + # than half of the expected target width. + for ac_type in uint$2_t 'unsigned int' 'unsigned long int' \ + 'unsigned long long int' 'unsigned short int' 'unsigned char'; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +static int test_array [1 - 2 * !((($ac_type) -1 >> ($2 / 2 - 1)) >> ($2 / 2 - 1) == 3)]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + case $ac_type in #( + uint$2_t) : + eval "$3=yes" ;; #( + *) : + eval "$3=\$ac_type" ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if eval test \"x\$"$3"\" = x"no"; then : + +else + break +fi + done +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_find_uintX_t + +# ac_fn_c_find_intX_t LINENO BITS VAR +# ----------------------------------- +# Finds a signed integer type with width BITS, setting cache variable VAR +# accordingly. +ac_fn_c_find_intX_t () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5 +$as_echo_n "checking for int$2_t... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + # Order is important - never check a type that is potentially smaller + # than half of the expected target width. + for ac_type in int$2_t 'int' 'long int' \ + 'long long int' 'short int' 'signed char'; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default + enum { N = $2 / 2 - 1 }; +int +main () +{ +static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default + enum { N = $2 / 2 - 1 }; +int +main () +{ +static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1) + < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))]; +test_array [0] = 0; +return test_array [0]; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + case $ac_type in #( + int$2_t) : + eval "$3=yes" ;; #( + *) : + eval "$3=\$ac_type" ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if eval test \"x\$"$3"\" = x"no"; then : + +else + break +fi + done +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_find_intX_t + +# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES +# ---------------------------------------------------- +# Tries to find if the field MEMBER exists in type AGGR, after including +# INCLUDES, setting cache variable VAR accordingly. +ac_fn_c_check_member () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 +$as_echo_n "checking for $2.$3... " >&6; } +if eval \${$4+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (sizeof ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + eval "$4=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$4 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_member + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by snapraid $as_me 11.2, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +am__api_version='1.15' + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; +esac + +# Do 'set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the 'STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=1;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='snapraid' + VERSION='11.2' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +mkdir_p='$(MKDIR_P)' + +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar pax cpio none' + +am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' + + + + + + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi +fi + + +ac_config_headers="$ac_config_headers config.h" + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" +if test "x$ac_cv_header_minix_config_h" = xyes; then : + MINIX=yes +else + MINIX= +fi + + + if test "$MINIX" = yes; then + +$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h + + +$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h + + +$as_echo "#define _MINIX 1" >>confdefs.h + + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 +$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } +if ${ac_cv_safe_to_define___extensions__+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +# define __EXTENSIONS__ 1 + $ac_includes_default +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_safe_to_define___extensions__=yes +else + ac_cv_safe_to_define___extensions__=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 +$as_echo "$ac_cv_safe_to_define___extensions__" >&6; } + test $ac_cv_safe_to_define___extensions__ = yes && + $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h + + $as_echo "#define _ALL_SOURCE 1" >>confdefs.h + + $as_echo "#define _GNU_SOURCE 1" >>confdefs.h + + $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h + + $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h + + +# Extract the first word of "valgrind", so it can be a program name with args. +set dummy valgrind; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_VALGRIND+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$VALGRIND"; then + ac_cv_prog_VALGRIND="$VALGRIND" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_VALGRIND="valgrind" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +VALGRIND=$ac_cv_prog_VALGRIND +if test -n "$VALGRIND"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $VALGRIND" >&5 +$as_echo "$VALGRIND" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "wine", so it can be a program name with args. +set dummy wine; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_WINE+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$WINE"; then + ac_cv_prog_WINE="$WINE" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_WINE="wine" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +WINE=$ac_cv_prog_WINE +if test -n "$WINE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WINE" >&5 +$as_echo "$WINE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "sde", so it can be a program name with args. +set dummy sde; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_SDE+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$SDE"; then + ac_cv_prog_SDE="$SDE" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_SDE="sde" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +SDE=$ac_cv_prog_SDE +if test -n "$SDE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SDE" >&5 +$as_echo "$SDE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "advd2", so it can be a program name with args. +set dummy advd2; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ADVD2+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ADVD2"; then + ac_cv_prog_ADVD2="$ADVD2" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ADVD2="advd2" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ADVD2=$ac_cv_prog_ADVD2 +if test -n "$ADVD2"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ADVD2" >&5 +$as_echo "$ADVD2" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test x"$ADVD2" != x; then + HAVE_ADVD2_TRUE= + HAVE_ADVD2_FALSE='#' +else + HAVE_ADVD2_TRUE='#' + HAVE_ADVD2_FALSE= +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -fno-omit-frame-pointer" >&5 +$as_echo_n "checking whether ${CC-cc} accepts -fno-omit-frame-pointer... " >&6; } +echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -c -fno-omit-frame-pointer conftest.c 2>&1`"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CFLAGS="$CFLAGS -fno-omit-frame-pointer" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f conftest* + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -fno-inline-functions-called-once" >&5 +$as_echo_n "checking whether ${CC-cc} accepts -fno-inline-functions-called-once... " >&6; } +echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -c -fno-inline-functions-called-once conftest.c 2>&1`"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CFLAGS="$CFLAGS -fno-inline-functions-called-once" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f conftest* + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -fno-inline-small-functions" >&5 +$as_echo_n "checking whether ${CC-cc} accepts -fno-inline-small-functions... " >&6; } +echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -c -fno-inline-small-functions conftest.c 2>&1`"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CFLAGS="$CFLAGS -fno-inline-small-functions" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f conftest* + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -rdynamic" >&5 +$as_echo_n "checking whether ${CC-cc} accepts -rdynamic... " >&6; } +echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -c -rdynamic conftest.c 2>&1`"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CFLAGS="$CFLAGS -rdynamic" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f conftest* + + +# Check whether --enable-largefile was given. +if test "${enable_largefile+set}" = set; then : + enableval=$enable_largefile; +fi + +if test "$enable_largefile" != no; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 +$as_echo_n "checking for special C compiler options needed for large files... " >&6; } +if ${ac_cv_sys_largefile_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_sys_largefile_CC=no + if test "$GCC" != yes; then + ac_save_CC=$CC + while :; do + # IRIX 6.2 and later do not support large files by default, + # so use the C compiler's -n32 option if that helps. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF + if ac_fn_c_try_compile "$LINENO"; then : + break +fi +rm -f core conftest.err conftest.$ac_objext + CC="$CC -n32" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_largefile_CC=' -n32'; break +fi +rm -f core conftest.err conftest.$ac_objext + break + done + CC=$ac_save_CC + rm -f conftest.$ac_ext + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 +$as_echo "$ac_cv_sys_largefile_CC" >&6; } + if test "$ac_cv_sys_largefile_CC" != no; then + CC=$CC$ac_cv_sys_largefile_CC + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 +$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } +if ${ac_cv_sys_file_offset_bits+:} false; then : + $as_echo_n "(cached) " >&6 +else + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_file_offset_bits=no; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _FILE_OFFSET_BITS 64 +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_file_offset_bits=64; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cv_sys_file_offset_bits=unknown + break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 +$as_echo "$ac_cv_sys_file_offset_bits" >&6; } +case $ac_cv_sys_file_offset_bits in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits +_ACEOF +;; +esac +rm -rf conftest* + if test $ac_cv_sys_file_offset_bits = unknown; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 +$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } +if ${ac_cv_sys_large_files+:} false; then : + $as_echo_n "(cached) " >&6 +else + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_large_files=no; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _LARGE_FILES 1 +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_large_files=1; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cv_sys_large_files=unknown + break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 +$as_echo "$ac_cv_sys_large_files" >&6; } +case $ac_cv_sys_large_files in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _LARGE_FILES $ac_cv_sys_large_files +_ACEOF +;; +esac +rm -rf conftest* + fi + + +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable assertions" >&5 +$as_echo_n "checking whether to enable assertions... " >&6; } + # Check whether --enable-assert was given. +if test "${enable_assert+set}" = set; then : + enableval=$enable_assert; ac_enable_assert=$enableval + if test "x$enableval" = xno; then : + +$as_echo "#define NDEBUG 1" >>confdefs.h + +elif test "x$enableval" != xyes; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: invalid argument supplied to --enable-assert" >&5 +$as_echo "$as_me: WARNING: invalid argument supplied to --enable-assert" >&2;} + ac_enable_assert=yes +fi +else + ac_enable_assert=yes +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_enable_assert" >&5 +$as_echo "$ac_enable_assert" >&6; } + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5 +$as_echo_n "checking for $ac_hdr that defines DIR... " >&6; } +if eval \${$as_ac_Header+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include <$ac_hdr> + +int +main () +{ +if ((DIR *) 0) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$as_ac_Header=yes" +else + eval "$as_ac_Header=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$as_ac_Header + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 +_ACEOF + +ac_header_dirent=$ac_hdr; break +fi + +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 +$as_echo_n "checking for library containing opendir... " >&6; } +if ${ac_cv_search_opendir+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dir; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_opendir=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_opendir+:} false; then : + break +fi +done +if ${ac_cv_search_opendir+:} false; then : + +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 +$as_echo "$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 +$as_echo_n "checking for library containing opendir... " >&6; } +if ${ac_cv_search_opendir+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' x; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_opendir=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_opendir+:} false; then : + break +fi +done +if ${ac_cv_search_opendir+:} false; then : + +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 +$as_echo "$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 +$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } +if ${ac_cv_header_time+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include + +int +main () +{ +if ((struct tm *) 0) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_time=yes +else + ac_cv_header_time=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 +$as_echo "$ac_cv_header_time" >&6; } +if test $ac_cv_header_time = yes; then + +$as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5 +$as_echo_n "checking for sys/wait.h that is POSIX.1 compatible... " >&6; } +if ${ac_cv_header_sys_wait_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#ifndef WEXITSTATUS +# define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) +#endif +#ifndef WIFEXITED +# define WIFEXITED(stat_val) (((stat_val) & 255) == 0) +#endif + +int +main () +{ + int s; + wait (&s); + s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_sys_wait_h=yes +else + ac_cv_header_sys_wait_h=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5 +$as_echo "$ac_cv_header_sys_wait_h" >&6; } +if test $ac_cv_header_sys_wait_h = yes; then + +$as_echo "#define HAVE_SYS_WAIT_H 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether sys/types.h defines makedev" >&5 +$as_echo_n "checking whether sys/types.h defines makedev... " >&6; } +if ${ac_cv_header_sys_types_h_makedev+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +return makedev(0, 0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_header_sys_types_h_makedev=yes +else + ac_cv_header_sys_types_h_makedev=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_types_h_makedev" >&5 +$as_echo "$ac_cv_header_sys_types_h_makedev" >&6; } + +if test $ac_cv_header_sys_types_h_makedev = no; then +ac_fn_c_check_header_mongrel "$LINENO" "sys/mkdev.h" "ac_cv_header_sys_mkdev_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_mkdev_h" = xyes; then : + +$as_echo "#define MAJOR_IN_MKDEV 1" >>confdefs.h + +fi + + + + if test $ac_cv_header_sys_mkdev_h = no; then + ac_fn_c_check_header_mongrel "$LINENO" "sys/sysmacros.h" "ac_cv_header_sys_sysmacros_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_sysmacros_h" = xyes; then : + +$as_echo "#define MAJOR_IN_SYSMACROS 1" >>confdefs.h + +fi + + + fi +fi + +for ac_header in fcntl.h stddef.h stdint.h stdlib.h string.h limits.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in unistd.h getopt.h fnmatch.h io.h inttypes.h byteswap.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in pthread.h math.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in sys/file.h sys/ioctl.h sys/vfs.h sys/statfs.h sys/param.h sys/mount.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in linux/fiemap.h linux/fs.h mach/mach_time.h execinfo.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 +$as_echo_n "checking for an ANSI C-conforming const... " >&6; } +if ${ac_cv_c_const+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#ifndef __cplusplus + /* Ultrix mips cc rejects this sort of thing. */ + typedef int charset[2]; + const charset cs = { 0, 0 }; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this sort of thing. */ + char tx; + char *t = &tx; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; } bx; + struct s *b = &bx; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_const=yes +else + ac_cv_c_const=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 +$as_echo "$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +$as_echo "#define const /**/" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 +$as_echo_n "checking for inline... " >&6; } +if ${ac_cv_c_inline+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __cplusplus +typedef int foo_t; +static $ac_kw foo_t static_foo () {return 0; } +$ac_kw foo_t foo () {return 0; } +#endif + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_inline=$ac_kw +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_inline" != no && break +done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 +$as_echo "$ac_cv_c_inline" >&6; } + +case $ac_cv_c_inline in + inline | yes) ;; + *) + case $ac_cv_c_inline in + no) ac_val=;; + *) ac_val=$ac_cv_c_inline;; + esac + cat >>confdefs.h <<_ACEOF +#ifndef __cplusplus +#define inline $ac_val +#endif +_ACEOF + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C/C++ restrict keyword" >&5 +$as_echo_n "checking for C/C++ restrict keyword... " >&6; } +if ${ac_cv_c_restrict+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_restrict=no + # The order here caters to the fact that C++ does not require restrict. + for ac_kw in __restrict __restrict__ _Restrict restrict; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +typedef int * int_ptr; + int foo (int_ptr $ac_kw ip) { + return ip[0]; + } +int +main () +{ +int s[1]; + int * $ac_kw t = s; + t[0] = 0; + return foo(t) + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_restrict=$ac_kw +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_restrict" != no && break + done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_restrict" >&5 +$as_echo "$ac_cv_c_restrict" >&6; } + + case $ac_cv_c_restrict in + restrict) ;; + no) $as_echo "#define restrict /**/" >>confdefs.h + ;; + *) cat >>confdefs.h <<_ACEOF +#define restrict $ac_cv_c_restrict +_ACEOF + ;; + esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working volatile" >&5 +$as_echo_n "checking for working volatile... " >&6; } +if ${ac_cv_c_volatile+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +volatile int x; +int * volatile y = (int *) 0; +return !x && !y; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_volatile=yes +else + ac_cv_c_volatile=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_volatile" >&5 +$as_echo "$ac_cv_c_volatile" >&6; } +if test $ac_cv_c_volatile = no; then + +$as_echo "#define volatile /**/" >>confdefs.h + +fi + +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "$ac_includes_default" +if test "x$ac_cv_type_off_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define off_t long int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + +ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default" +if test "x$ac_cv_type_ssize_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define ssize_t int +_ACEOF + +fi + +ac_fn_c_find_uintX_t "$LINENO" "32" "ac_cv_c_uint32_t" +case $ac_cv_c_uint32_t in #( + no|yes) ;; #( + *) + +$as_echo "#define _UINT32_T 1" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define uint32_t $ac_cv_c_uint32_t +_ACEOF +;; + esac + +ac_fn_c_find_uintX_t "$LINENO" "64" "ac_cv_c_uint64_t" +case $ac_cv_c_uint64_t in #( + no|yes) ;; #( + *) + +$as_echo "#define _UINT64_T 1" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define uint64_t $ac_cv_c_uint64_t +_ACEOF +;; + esac + +ac_fn_c_find_uintX_t "$LINENO" "8" "ac_cv_c_uint8_t" +case $ac_cv_c_uint8_t in #( + no|yes) ;; #( + *) + +$as_echo "#define _UINT8_T 1" >>confdefs.h + + +cat >>confdefs.h <<_ACEOF +#define uint8_t $ac_cv_c_uint8_t +_ACEOF +;; + esac + +ac_fn_c_find_intX_t "$LINENO" "8" "ac_cv_c_int8_t" +case $ac_cv_c_int8_t in #( + no|yes) ;; #( + *) + +cat >>confdefs.h <<_ACEOF +#define int8_t $ac_cv_c_int8_t +_ACEOF +;; +esac + + + + ac_fn_c_check_member "$LINENO" "struct dirent" "d_ino" "ac_cv_member_struct_dirent_d_ino" " +#include +#ifdef HAVE_DIRENT_H +# include +#else +# define dirent direct +# ifdef HAVE_SYS_NDIR_H +# include +# endif +# ifdef HAVE_SYS_DIR_H +# include +# endif +# ifdef HAVE_NDIR_H +# include +# endif +#endif + +" +if test "x$ac_cv_member_struct_dirent_d_ino" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_DIRENT_D_INO 1 +_ACEOF + + +fi + + + + + ac_fn_c_check_member "$LINENO" "struct dirent" "d_type" "ac_cv_member_struct_dirent_d_type" " +#include +#ifdef HAVE_DIRENT_H +# include +#else +# define dirent direct +# ifdef HAVE_SYS_NDIR_H +# include +# endif +# ifdef HAVE_SYS_DIR_H +# include +# endif +# ifdef HAVE_NDIR_H +# include +# endif +#endif + +" +if test "x$ac_cv_member_struct_dirent_d_type" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_DIRENT_D_TYPE 1 +_ACEOF + + +fi + + +ac_fn_c_check_member "$LINENO" "struct stat" "st_nlink" "ac_cv_member_struct_stat_st_nlink" " +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif + +" +if test "x$ac_cv_member_struct_stat_st_nlink" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_NLINK 1 +_ACEOF + + +fi +ac_fn_c_check_member "$LINENO" "struct stat" "st_mtim.tv_nsec" "ac_cv_member_struct_stat_st_mtim_tv_nsec" " +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif + +" +if test "x$ac_cv_member_struct_stat_st_mtim_tv_nsec" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC 1 +_ACEOF + + +fi +ac_fn_c_check_member "$LINENO" "struct stat" "st_mtimensec" "ac_cv_member_struct_stat_st_mtimensec" " +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif + +" +if test "x$ac_cv_member_struct_stat_st_mtimensec" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_MTIMENSEC 1 +_ACEOF + + +fi +ac_fn_c_check_member "$LINENO" "struct stat" "st_mtimespec.tv_nsec" "ac_cv_member_struct_stat_st_mtimespec_tv_nsec" " +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif + +" +if test "x$ac_cv_member_struct_stat_st_mtimespec_tv_nsec" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1 +_ACEOF + + +fi + +ac_fn_c_check_member "$LINENO" "struct statfs" "f_type" "ac_cv_member_struct_statfs_f_type" " +#if HAVE_SYS_PARAM_H +#include +#endif +#if HAVE_SYS_MOUNT_H +#include +#endif +#if HAVE_SYS_VFS_H +#include +#endif +#if HAVE_SYS_STATFS_H +#include +#endif + +" +if test "x$ac_cv_member_struct_statfs_f_type" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STATFS_F_TYPE 1 +_ACEOF + + +fi + +ac_fn_c_check_member "$LINENO" "struct statfs" "f_fstypename" "ac_cv_member_struct_statfs_f_fstypename" " +#if HAVE_SYS_PARAM_H +#include +#endif +#if HAVE_SYS_MOUNT_H +#include +#endif +#if HAVE_SYS_VFS_H +#include +#endif +#if HAVE_SYS_STATFS_H +#include +#endif + +" +if test "x$ac_cv_member_struct_statfs_f_fstypename" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STATFS_F_FSTYPENAME 1 +_ACEOF + + +fi + + +for ac_func in memset strchr strerror strrchr mkdir gettimeofday strtoul +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in getopt getopt_long snprintf vsnprintf sigaction +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in ftruncate fallocate access +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in fsync posix_fadvise sync_file_range +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in getc_unlocked ferror_unlocked fnmatch +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in futimes futimens futimesat localtime_r lutimes utimensat +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in fstatat flock statfs +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in mach_absolute_time +do : + ac_fn_c_check_func "$LINENO" "mach_absolute_time" "ac_cv_func_mach_absolute_time" +if test "x$ac_cv_func_mach_absolute_time" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_MACH_ABSOLUTE_TIME 1 +_ACEOF + +fi +done + +for ac_func in backtrace backtrace_symbols +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5 +$as_echo_n "checking for library containing clock_gettime... " >&6; } +if ${ac_cv_search_clock_gettime+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char clock_gettime (); +int +main () +{ +return clock_gettime (); + ; + return 0; +} +_ACEOF +for ac_lib in '' rt; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_clock_gettime=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_clock_gettime+:} false; then : + break +fi +done +if ${ac_cv_search_clock_gettime+:} false; then : + +else + ac_cv_search_clock_gettime=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5 +$as_echo "$ac_cv_search_clock_gettime" >&6; } +ac_res=$ac_cv_search_clock_gettime +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +for ac_func in clock_gettime +do : + ac_fn_c_check_func "$LINENO" "clock_gettime" "ac_cv_func_clock_gettime" +if test "x$ac_cv_func_clock_gettime" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_CLOCK_GETTIME 1 +_ACEOF + +fi +done + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -pthread" >&5 +$as_echo_n "checking whether ${CC-cc} accepts -pthread... " >&6; } +echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -c -pthread conftest.c 2>&1`"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CFLAGS="$CFLAGS -pthread" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + CFLAGS="$CFLAGS -D_REENTRANT" +fi +rm -f conftest* + +for ac_func in pthread_create +do : + ac_fn_c_check_func "$LINENO" "pthread_create" "ac_cv_func_pthread_create" +if test "x$ac_cv_func_pthread_create" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PTHREAD_CREATE 1 +_ACEOF + +fi +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing exp" >&5 +$as_echo_n "checking for library containing exp... " >&6; } +if ${ac_cv_search_exp+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char exp (); +int +main () +{ +return exp (); + ; + return 0; +} +_ACEOF +for ac_lib in '' m; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_exp=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_exp+:} false; then : + break +fi +done +if ${ac_cv_search_exp+:} false; then : + +else + ac_cv_search_exp=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_exp" >&5 +$as_echo "$ac_cv_search_exp" >&6; } +ac_res=$ac_cv_search_exp +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + + +# Check whether --with-blkid was given. +if test "${with_blkid+set}" = set; then : + withval=$with_blkid; +fi + +if test "x$with_blkid" != "xno"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing blkid_probe_all" >&5 +$as_echo_n "checking for library containing blkid_probe_all... " >&6; } +if ${ac_cv_search_blkid_probe_all+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char blkid_probe_all (); +int +main () +{ +return blkid_probe_all (); + ; + return 0; +} +_ACEOF +for ac_lib in '' blkid; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_blkid_probe_all=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_blkid_probe_all+:} false; then : + break +fi +done +if ${ac_cv_search_blkid_probe_all+:} false; then : + +else + ac_cv_search_blkid_probe_all=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_blkid_probe_all" >&5 +$as_echo "$ac_cv_search_blkid_probe_all" >&6; } +ac_res=$ac_cv_search_blkid_probe_all +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + have_blkid=yes +else + have_blkid=no +fi + +else + have_blkid=no +fi +if test "x$have_blkid" = "xyes"; then : + + for ac_header in blkid/blkid.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "blkid/blkid.h" "ac_cv_header_blkid_blkid_h" "$ac_includes_default" +if test "x$ac_cv_header_blkid_blkid_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_BLKID_BLKID_H 1 +_ACEOF + +fi + +done + + for ac_func in blkid_devno_to_devname blkid_get_tag_value +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +else + if test "x$with_blkid" = "xyes"; then : + as_fn_error $? "blkid requested but not found" "$LINENO" 5 + +fi + +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 +$as_echo_n "checking whether byte ordering is bigendian... " >&6; } +if ${ac_cv_c_bigendian+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_bigendian=unknown + # See if we're dealing with a universal compiler. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __APPLE_CC__ + not a universal capable compiler + #endif + typedef int dummy; + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + # Check for potential -arch flags. It is not universal unless + # there are at least two -arch flags with different values. + ac_arch= + ac_prev= + for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do + if test -n "$ac_prev"; then + case $ac_word in + i?86 | x86_64 | ppc | ppc64) + if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then + ac_arch=$ac_word + else + ac_cv_c_bigendian=universal + break + fi + ;; + esac + ac_prev= + elif test "x$ac_word" = "x-arch"; then + ac_prev=arch + fi + done +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + if test $ac_cv_c_bigendian = unknown; then + # See if sys/param.h defines the BYTE_ORDER macro. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ + && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ + && LITTLE_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +#if BYTE_ORDER != BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) + bogus endian macros + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + # It does; now see whether it defined to _BIG_ENDIAN or not. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +int +main () +{ +#ifndef _BIG_ENDIAN + not big endian + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_bigendian=yes +else + ac_cv_c_bigendian=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + if test $ac_cv_c_bigendian = unknown; then + # Compile a test program. + if test "$cross_compiling" = yes; then : + # Try to guess by grepping values from an object file. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +short int ascii_mm[] = + { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; + short int ascii_ii[] = + { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; + int use_ascii (int i) { + return ascii_mm[i] + ascii_ii[i]; + } + short int ebcdic_ii[] = + { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; + short int ebcdic_mm[] = + { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; + int use_ebcdic (int i) { + return ebcdic_mm[i] + ebcdic_ii[i]; + } + extern int foo; + +int +main () +{ +return use_ascii (foo) == use_ebcdic (foo); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then + ac_cv_c_bigendian=yes + fi + if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then + if test "$ac_cv_c_bigendian" = unknown; then + ac_cv_c_bigendian=no + else + # finding both strings is unlikely to happen, but who knows? + ac_cv_c_bigendian=unknown + fi + fi +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ + + /* Are we little or big endian? From Harbison&Steele. */ + union + { + long int l; + char c[sizeof (long int)]; + } u; + u.l = 1; + return u.c[sizeof (long int) - 1] == 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_c_bigendian=no +else + ac_cv_c_bigendian=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 +$as_echo "$ac_cv_c_bigendian" >&6; } + case $ac_cv_c_bigendian in #( + yes) + $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h +;; #( + no) + ;; #( + universal) + +$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h + + ;; #( + *) + as_fn_error $? "unknown endianness + presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; + esac + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -Wall" >&5 +$as_echo_n "checking whether ${CC-cc} accepts -Wall... " >&6; } +echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -c -Wall conftest.c 2>&1`"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CFLAGS="$CFLAGS -Wall" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f conftest* + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -Wextra" >&5 +$as_echo_n "checking whether ${CC-cc} accepts -Wextra... " >&6; } +echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -c -Wextra conftest.c 2>&1`"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CFLAGS="$CFLAGS -Wextra" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f conftest* + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -Wuninitialized" >&5 +$as_echo_n "checking whether ${CC-cc} accepts -Wuninitialized... " >&6; } +echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -c -Wuninitialized conftest.c 2>&1`"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CFLAGS="$CFLAGS -Wuninitialized" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f conftest* + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -Wshadow" >&5 +$as_echo_n "checking whether ${CC-cc} accepts -Wshadow... " >&6; } +echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -c -Wshadow conftest.c 2>&1`"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CFLAGS="$CFLAGS -Wshadow" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f conftest* + + +# Check whether --enable-asm was given. +if test "${enable_asm+set}" = set; then : + enableval=$enable_asm; +fi + +if test "x$enable_asm" != "xno"; then : + +$as_echo "#define HAVE_ASSEMBLY 1" >>confdefs.h + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sse2" >&5 +$as_echo_n "checking for sse2... " >&6; } +asmsse2=no +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#if defined(__i386__) || defined(__x86_64__) + void f(void) + { + asm volatile("pxor %xmm0,%xmm1"); + } +#else +#error not x86 +#endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_SSE2 1" >>confdefs.h + asmsse2=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $asmsse2" >&5 +$as_echo "$asmsse2" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ssse3" >&5 +$as_echo_n "checking for ssse3... " >&6; } +asmssse3=no +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#if defined(__i386__) || defined(__x86_64__) + void f(void) + { + asm volatile("pshufb %xmm0,%xmm1"); + } +#else +#error not x86 +#endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_SSSE3 1" >>confdefs.h + asmssse3=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $asmssse3" >&5 +$as_echo "$asmssse3" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sse42" >&5 +$as_echo_n "checking for sse42... " >&6; } +asmsse42=no +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#if defined(__i386__) || defined(__x86_64__) + unsigned f(unsigned crc, unsigned char b) + { + asm volatile("crc32b %1, %0" : "+r" (crc) : "rm" (b)); + return crc; + } +#else +#error not x86 +#endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_SSE42 1" >>confdefs.h + asmsse42=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $asmsse42" >&5 +$as_echo "$asmsse42" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for avx2" >&5 +$as_echo_n "checking for avx2... " >&6; } +asmavx2=no +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#if defined(__i386__) || defined(__x86_64__) + void f(void* ptr) + { + asm volatile("vbroadcasti128 %0, %%ymm0" : : "m" (ptr)); + } +#else +#error not x86 +#endif + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +$as_echo "#define HAVE_AVX2 1" >>confdefs.h + asmavx2=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $asmavx2" >&5 +$as_echo "$asmavx2" >&6; } + + +fi + +case $host in #( + *-*-mingw*) : + + TESTENV="$WINE" + FAILENV="$TESTENV" + ;; #( + *) : + POSIX=1 + ;; +esac + if test x"$POSIX" != x; then + HAVE_POSIX_TRUE= + HAVE_POSIX_FALSE='#' +else + HAVE_POSIX_TRUE='#' + HAVE_POSIX_FALSE= +fi + + +# Check whether --enable-profiler was given. +if test "${enable_profiler+set}" = set; then : + enableval=$enable_profiler; + CFLAGS="-O2 -pg -g -pthread" + +fi + + +# Check whether --enable-coverage was given. +if test "${enable_coverage+set}" = set; then : + enableval=$enable_coverage; + CFLAGS="-O0 -g -fprofile-arcs -ftest-coverage -pthread" + +fi + + +# Check whether --enable-valgrind was given. +if test "${enable_valgrind+set}" = set; then : + enableval=$enable_valgrind; + TESTENV="$VALGRIND --leak-check=full --error-exitcode=1" + FAILENV="$VALGRIND --error-exitcode=1" + CFLAGS="$CFLAGS -DCHECKER" + MEMORY_CHECKER=1 + +fi + + +# Check whether --enable-sgcheck was given. +if test "${enable_sgcheck+set}" = set; then : + enableval=$enable_sgcheck; + TESTENV="$VALGRIND --tool=exp-sgcheck --suppressions=valgrind.supp --error-exitcode=1" + FAILENV="$TESTENV" + CFLAGS="$CFLAGS -DCHECKER" + MEMORY_CHECKER=1 + +fi + + +# Check whether --enable-helgrind was given. +if test "${enable_helgrind+set}" = set; then : + enableval=$enable_helgrind; + TESTENV="$VALGRIND --tool=helgrind --fair-sched=try --error-exitcode=1" + FAILENV="$TESTENV" + CFLAGS="$CFLAGS -DCHECKER" + THREAD_CHECKER=1 + +fi + + +# Check whether --enable-drd was given. +if test "${enable_drd+set}" = set; then : + enableval=$enable_drd; + TESTENV="$VALGRIND --tool=drd --fair-sched=try --error-exitcode=1" + FAILENV="$TESTENV" + CFLAGS="$CFLAGS -DCHECKER" + THREAD_CHECKER=1 + +fi + + +# Check whether --enable-asan was given. +if test "${enable_asan+set}" = set; then : + enableval=$enable_asan; + CFLAGS="$CFLAGS -DCHECKER -fsanitize=address" + MEMORY_CHECKER=1 + +fi + + +# Check whether --enable-msan was given. +if test "${enable_msan+set}" = set; then : + enableval=$enable_msan; + CFLAGS="$CFLAGS -DCHECKER -fsanitize=memory" + MEMORY_CHECKER=1 + +fi + + +# Check whether --enable-ubsan was given. +if test "${enable_ubsan+set}" = set; then : + enableval=$enable_ubsan; + CFLAGS="$CFLAGS -DCHECKER -fsanitize=undefined" + MEMORY_CHECKER=1 + +fi + + +# Check whether --enable-tsan was given. +if test "${enable_tsan+set}" = set; then : + enableval=$enable_tsan; + CFLAGS="$CFLAGS -DCHECKER -fsanitize=thread" + MEMORY_CHECKER=1 + +fi + + + if test x"$MEMORY_CHECKER" != x; then + HAVE_MEMORY_CHECKER_TRUE= + HAVE_MEMORY_CHECKER_FALSE='#' +else + HAVE_MEMORY_CHECKER_TRUE='#' + HAVE_MEMORY_CHECKER_FALSE= +fi + + if test x"$THREAD_CHECKER" != x; then + HAVE_THREAD_CHECKER_TRUE= + HAVE_THREAD_CHECKER_FALSE='#' +else + HAVE_THREAD_CHECKER_TRUE='#' + HAVE_THREAD_CHECKER_FALSE= +fi + + +# Check whether --enable-sde was given. +if test "${enable_sde+set}" = set; then : + enableval=$enable_sde; + TESTENV_SSE2="$SDE -p4p --" + TESTENV_SSSE3="$SDE -mrm --" + TESTENV_SSE42="$SDE -nhm --" + TESTENV_AVX2="$SDE -hsw --" + EMULATOR=1 + # Target CPU compatible with P4 Prescott + CFLAGS="$CFLAGS -march=athlon64" + +fi + + if test x"$EMULATOR" != x; then + HAVE_EMULATOR_TRUE= + HAVE_EMULATOR_FALSE='#' +else + HAVE_EMULATOR_TRUE='#' + HAVE_EMULATOR_FALSE= +fi + + +# Check whether --enable-debug was given. +if test "${enable_debug+set}" = set; then : + enableval=$enable_debug; + CFLAGS="-Og -g -pthread -Wall -Wextra" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -rdynamic" >&5 +$as_echo_n "checking whether ${CC-cc} accepts -rdynamic... " >&6; } +echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -c -rdynamic conftest.c 2>&1`"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CFLAGS="$CFLAGS -rdynamic" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f conftest* + + +fi + + +# Check whether --enable-warning-as-error was given. +if test "${enable_warning_as_error+set}" = set; then : + enableval=$enable_warning_as_error; + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -Werror" >&5 +$as_echo_n "checking whether ${CC-cc} accepts -Werror... " >&6; } +echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -c -Werror conftest.c 2>&1`"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CFLAGS="$CFLAGS -Werror" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f conftest* + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -Wno-error=unused-command-line-argument" >&5 +$as_echo_n "checking whether ${CC-cc} accepts -Wno-error=unused-command-line-argument... " >&6; } +echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -c -Wno-error=unused-command-line-argument conftest.c 2>&1`"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CFLAGS="$CFLAGS -Wno-error=unused-command-line-argument" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f conftest* + + +fi + + +# Check whether --enable-warning was given. +if test "${enable_warning+set}" = set; then : + enableval=$enable_warning; + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -Wpointer-arith" >&5 +$as_echo_n "checking whether ${CC-cc} accepts -Wpointer-arith... " >&6; } +echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -c -Wpointer-arith conftest.c 2>&1`"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CFLAGS="$CFLAGS -Wpointer-arith" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f conftest* + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -Wcast-qual" >&5 +$as_echo_n "checking whether ${CC-cc} accepts -Wcast-qual... " >&6; } +echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -c -Wcast-qual conftest.c 2>&1`"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CFLAGS="$CFLAGS -Wcast-qual" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f conftest* + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -Wunused" >&5 +$as_echo_n "checking whether ${CC-cc} accepts -Wunused... " >&6; } +echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -c -Wunused conftest.c 2>&1`"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CFLAGS="$CFLAGS -Wunused" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f conftest* + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -Wunreachable-code" >&5 +$as_echo_n "checking whether ${CC-cc} accepts -Wunreachable-code... " >&6; } +echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -c -Wunreachable-code conftest.c 2>&1`"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CFLAGS="$CFLAGS -Wunreachable-code" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f conftest* + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -Wpadded" >&5 +$as_echo_n "checking whether ${CC-cc} accepts -Wpadded... " >&6; } +echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -c -Wpadded conftest.c 2>&1`"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CFLAGS="$CFLAGS -Wpadded" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f conftest* + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${CC-cc} accepts -Weverything" >&5 +$as_echo_n "checking whether ${CC-cc} accepts -Weverything... " >&6; } +echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -c -Weverything conftest.c 2>&1`"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CFLAGS="$CFLAGS -Weverything" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +fi +rm -f conftest* + + +fi + + + + + + + + + +ac_config_files="$ac_config_files Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +$as_echo_n "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${HAVE_ADVD2_TRUE}" && test -z "${HAVE_ADVD2_FALSE}"; then + as_fn_error $? "conditional \"HAVE_ADVD2\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +if test -z "${HAVE_POSIX_TRUE}" && test -z "${HAVE_POSIX_FALSE}"; then + as_fn_error $? "conditional \"HAVE_POSIX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_MEMORY_CHECKER_TRUE}" && test -z "${HAVE_MEMORY_CHECKER_FALSE}"; then + as_fn_error $? "conditional \"HAVE_MEMORY_CHECKER\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_THREAD_CHECKER_TRUE}" && test -z "${HAVE_THREAD_CHECKER_FALSE}"; then + as_fn_error $? "conditional \"HAVE_THREAD_CHECKER\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_EMULATOR_TRUE}" && test -z "${HAVE_EMULATOR_FALSE}"; then + as_fn_error $? "conditional \"HAVE_EMULATOR\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by snapraid $as_me 11.2, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to the package provider. +snapraid home page: ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +snapraid config.status 11.2 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + + esac + +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..6486114 --- /dev/null +++ b/configure.ac @@ -0,0 +1,372 @@ +dnl Process this file with autoconf to produce a configure script. +AC_PREREQ([2.65]) +dnl Get version number from git +m4_define([git_revision], m4_esyscmd_s([./autover.sh])) +AC_INIT([snapraid], [git_revision], [], [], [http://www.snapraid.it]) +AM_INIT_AUTOMAKE([foreign no-dependencies subdir-objects]) +AC_CONFIG_SRCDIR([cmdline/snapraid.c]) +AC_CONFIG_HEADERS([config.h]) +AC_CANONICAL_HOST + +dnl Checks for programs. +AC_PROG_CC +AC_USE_SYSTEM_EXTENSIONS +AC_CHECK_PROG([VALGRIND],[valgrind],[valgrind],[]) +AC_CHECK_PROG([WINE],[wine],[wine],[]) +AC_CHECK_PROG([SDE],[sde],[sde],[]) +AC_CHECK_PROG([ADVD2],[advd2],[advd2],[]) +AM_CONDITIONAL(HAVE_ADVD2, [test x"$ADVD2" != x]) + +dnl Compiler option to improve stacktrace +AC_CHECK_CC_OPT([-fno-omit-frame-pointer], CFLAGS="$CFLAGS -fno-omit-frame-pointer", []) +AC_CHECK_CC_OPT([-fno-inline-functions-called-once], CFLAGS="$CFLAGS -fno-inline-functions-called-once", []) +AC_CHECK_CC_OPT([-fno-inline-small-functions], CFLAGS="$CFLAGS -fno-inline-small-functions", []) +AC_CHECK_CC_OPT([-rdynamic], CFLAGS="$CFLAGS -rdynamic", []) + +dnl Checks for system. +AC_SYS_LARGEFILE + +dnl Checks for header files. +AC_HEADER_ASSERT +AC_HEADER_DIRENT +AC_HEADER_TIME +AC_HEADER_SYS_WAIT +AC_HEADER_MAJOR +AC_CHECK_HEADERS([fcntl.h stddef.h stdint.h stdlib.h string.h limits.h]) +AC_CHECK_HEADERS([unistd.h getopt.h fnmatch.h io.h inttypes.h byteswap.h]) +AC_CHECK_HEADERS([pthread.h math.h]) +AC_CHECK_HEADERS([sys/file.h sys/ioctl.h sys/vfs.h sys/statfs.h sys/param.h sys/mount.h]) +AC_CHECK_HEADERS([linux/fiemap.h linux/fs.h mach/mach_time.h execinfo.h]) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_C_INLINE +AC_C_RESTRICT +AC_C_VOLATILE +AC_TYPE_SIZE_T +AC_TYPE_OFF_T +AC_TYPE_SIZE_T +AC_TYPE_SSIZE_T +AC_TYPE_UINT32_T +AC_TYPE_UINT64_T +AC_TYPE_UINT8_T +AC_TYPE_INT8_T +AC_STRUCT_DIRENT_D_INO +AC_STRUCT_DIRENT_D_TYPE +AC_CHECK_MEMBERS([struct stat.st_nlink, struct stat.st_mtim.tv_nsec, struct stat.st_mtimensec, struct stat.st_mtimespec.tv_nsec], [], [], [[ +#if HAVE_SYS_TYPES_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +]]) +AC_CHECK_MEMBERS([struct statfs.f_type], [], [], [[ +#if HAVE_SYS_PARAM_H +#include +#endif +#if HAVE_SYS_MOUNT_H +#include +#endif +#if HAVE_SYS_VFS_H +#include +#endif +#if HAVE_SYS_STATFS_H +#include +#endif +]]) +AC_CHECK_MEMBERS([struct statfs.f_fstypename], [], [], [[ +#if HAVE_SYS_PARAM_H +#include +#endif +#if HAVE_SYS_MOUNT_H +#include +#endif +#if HAVE_SYS_VFS_H +#include +#endif +#if HAVE_SYS_STATFS_H +#include +#endif +]]) + +dnl Checks for library functions. +AC_CHECK_FUNCS([memset strchr strerror strrchr mkdir gettimeofday strtoul]) +AC_CHECK_FUNCS([getopt getopt_long snprintf vsnprintf sigaction]) +AC_CHECK_FUNCS([ftruncate fallocate access]) +AC_CHECK_FUNCS([fsync posix_fadvise sync_file_range]) +AC_CHECK_FUNCS([getc_unlocked ferror_unlocked fnmatch]) +AC_CHECK_FUNCS([futimes futimens futimesat localtime_r lutimes utimensat]) +AC_CHECK_FUNCS([fstatat flock statfs]) +AC_CHECK_FUNCS([mach_absolute_time]) +AC_CHECK_FUNCS([backtrace backtrace_symbols]) +AC_SEARCH_LIBS([clock_gettime], [rt]) +AC_CHECK_FUNCS([clock_gettime]) +AC_CHECK_CC_OPT([-pthread], CFLAGS="$CFLAGS -pthread", CFLAGS="$CFLAGS -D_REENTRANT") +AC_CHECK_FUNCS([pthread_create]) +AC_SEARCH_LIBS([exp], [m]) + +dnl Checks for libblkid +AC_ARG_WITH([blkid], + AS_HELP_STRING([--without-blkid], [Ignore presence of blkid and disable it])) +AS_IF([test "x$with_blkid" != "xno"], + [AC_SEARCH_LIBS([blkid_probe_all], [blkid], [have_blkid=yes], [have_blkid=no])], + [have_blkid=no]) +AS_IF([test "x$have_blkid" = "xyes"], + [ + AC_CHECK_HEADERS([blkid/blkid.h]) + AC_CHECK_FUNCS([blkid_devno_to_devname blkid_get_tag_value]) + ], + [AS_IF([test "x$with_blkid" = "xyes"], + [AC_MSG_ERROR([blkid requested but not found]) + ]) +]) + +dnl Checks for architecture +AC_C_BIGENDIAN + +dnl Checks for compiler +AC_CHECK_CC_OPT([-Wall], CFLAGS="$CFLAGS -Wall", []) +AC_CHECK_CC_OPT([-Wextra], CFLAGS="$CFLAGS -Wextra", []) +AC_CHECK_CC_OPT([-Wuninitialized], CFLAGS="$CFLAGS -Wuninitialized", []) +AC_CHECK_CC_OPT([-Wshadow], CFLAGS="$CFLAGS -Wshadow", []) + +dnl Checks for asm +AC_ARG_ENABLE([asm], + AS_HELP_STRING([--disable-asm], [Disable inline assembly])) +AS_IF([test "x$enable_asm" != "xno"], + [AC_DEFINE([HAVE_ASSEMBLY], [1], [Define to 1 if inline assembly should be used.])] + +dnl AS_IF(HAVE_ASSEMBLY) NOT closed here + +dnl Checks for AS supporting the SSE2 instructions. +AC_MSG_CHECKING([for sse2]) +asmsse2=no +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#if defined(__i386__) || defined(__x86_64__) + void f(void) + { + asm volatile("pxor %xmm0,%xmm1"); + } +#else +#error not x86 +#endif +]])], +[AC_DEFINE([HAVE_SSE2], [1], [Define to 1 if sse2 is supported by the assembler.]) asmsse2=yes]) +AC_MSG_RESULT([$asmsse2]) + +dnl Checks for AS supporting the SSSE3 instructions. +AC_MSG_CHECKING([for ssse3]) +asmssse3=no +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#if defined(__i386__) || defined(__x86_64__) + void f(void) + { + asm volatile("pshufb %xmm0,%xmm1"); + } +#else +#error not x86 +#endif +]])], +[AC_DEFINE([HAVE_SSSE3], [1], [Define to 1 if ssse3 is supported by the assembler.]) asmssse3=yes]) +AC_MSG_RESULT([$asmssse3]) + +dnl Checks for AS supporting the SSE4.2 instructions. +AC_MSG_CHECKING([for sse42]) +asmsse42=no +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#if defined(__i386__) || defined(__x86_64__) + unsigned f(unsigned crc, unsigned char b) + { + asm volatile("crc32b %1, %0" : "+r" (crc) : "rm" (b)); + return crc; + } +#else +#error not x86 +#endif +]])], +[AC_DEFINE([HAVE_SSE42], [1], [Define to 1 if sse4.2 is supported by the assembler.]) asmsse42=yes]) +AC_MSG_RESULT([$asmsse42]) + +dnl Checks for AS supporting the AVX2 instructions. +AC_MSG_CHECKING([for avx2]) +asmavx2=no +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#if defined(__i386__) || defined(__x86_64__) + void f(void* ptr) + { + asm volatile("vbroadcasti128 %0, %%ymm0" : : "m" (ptr)); + } +#else +#error not x86 +#endif +]])], +[AC_DEFINE([HAVE_AVX2], [1], [Define to 1 if avx2 is supported by the assembler.]) asmavx2=yes]) +AC_MSG_RESULT([$asmavx2]) + +dnl AS_IF(HAVE_ASSEMBLY) closed here +) + +dnl Checks for test environment +AS_CASE([$host], + [*-*-mingw*], + [ + TESTENV="$WINE" + FAILENV="$TESTENV" + ], + [POSIX=1] +) +AM_CONDITIONAL(HAVE_POSIX, [test x"$POSIX" != x]) + +AC_ARG_ENABLE([profiler], + [AS_HELP_STRING([--enable-profiler],[enable the use of gprof for code coverage])], + [ + CFLAGS="-O2 -pg -g -pthread" + ], + []) + +AC_ARG_ENABLE([coverage], + [AS_HELP_STRING([--enable-coverage],[enable the use of gcov for code coverage])], + [ + CFLAGS="-O0 -g -fprofile-arcs -ftest-coverage -pthread" + ], + []) + +AC_ARG_ENABLE([valgrind], + [AS_HELP_STRING([--enable-valgrind],[enable the use of valgrind in testing])], + [ + TESTENV="$VALGRIND --leak-check=full --error-exitcode=1" + FAILENV="$VALGRIND --error-exitcode=1" + CFLAGS="$CFLAGS -DCHECKER" + MEMORY_CHECKER=1 + ], + []) + +AC_ARG_ENABLE([sgcheck], + [AS_HELP_STRING([--enable-sgcheck],[enable the use of sgcheck in testing])], + [ + TESTENV="$VALGRIND --tool=exp-sgcheck --suppressions=valgrind.supp --error-exitcode=1" + FAILENV="$TESTENV" + CFLAGS="$CFLAGS -DCHECKER" + MEMORY_CHECKER=1 + ], + []) + +AC_ARG_ENABLE([helgrind], + [AS_HELP_STRING([--enable-helgrind],[enable the use of helgrind in testing])], + [ + TESTENV="$VALGRIND --tool=helgrind --fair-sched=try --error-exitcode=1" + FAILENV="$TESTENV" + CFLAGS="$CFLAGS -DCHECKER" + THREAD_CHECKER=1 + ], + []) + +AC_ARG_ENABLE([drd], + [AS_HELP_STRING([--enable-drd],[enable the use of drd in testing])], + [ + TESTENV="$VALGRIND --tool=drd --fair-sched=try --error-exitcode=1" + FAILENV="$TESTENV" + CFLAGS="$CFLAGS -DCHECKER" + THREAD_CHECKER=1 + ], + []) + +AC_ARG_ENABLE([asan], + [AS_HELP_STRING([--enable-asan],[enable the use of AddressSanitizer in testing])], + [ + CFLAGS="$CFLAGS -DCHECKER -fsanitize=address" + MEMORY_CHECKER=1 + ], + []) + +AC_ARG_ENABLE([msan], + [AS_HELP_STRING([--enable-msan],[enable the use of MemorySanitizer in testing])], + [ + CFLAGS="$CFLAGS -DCHECKER -fsanitize=memory" + MEMORY_CHECKER=1 + ], + []) + +AC_ARG_ENABLE([ubsan], + [AS_HELP_STRING([--enable-ubsan],[enable the use of UndefinedBehaviourSanitizer in testing])], + [ + CFLAGS="$CFLAGS -DCHECKER -fsanitize=undefined" + MEMORY_CHECKER=1 + ], + []) + +AC_ARG_ENABLE([tsan], + [AS_HELP_STRING([--enable-tsan],[enable the use of ThreadSanitizer in testing])], + [ + CFLAGS="$CFLAGS -DCHECKER -fsanitize=thread" +dnl Use MEMORY_CHECKER instead of THREAD_CHECKER to run the full and long test + MEMORY_CHECKER=1 + ], + []) + +AM_CONDITIONAL(HAVE_MEMORY_CHECKER, [test x"$MEMORY_CHECKER" != x]) +AM_CONDITIONAL(HAVE_THREAD_CHECKER, [test x"$THREAD_CHECKER" != x]) + +AC_ARG_ENABLE([sde], + [AS_HELP_STRING([--enable-sde],[enable the use of SDE emulator in testing])], +dnl p4p -> Pentium4 Prescott with SSE2 +dnl mrm -> Merom with SSSE3 +dnl nhm -> Nehalem with SSE4.2 +dnl hsw -> Haswell with AVX2 +dnl knl -> Knights Landing with AVX512 + [ + TESTENV_SSE2="$SDE -p4p --" + TESTENV_SSSE3="$SDE -mrm --" + TESTENV_SSE42="$SDE -nhm --" + TESTENV_AVX2="$SDE -hsw --" + EMULATOR=1 + # Target CPU compatible with P4 Prescott + CFLAGS="$CFLAGS -march=athlon64" + ], + []) +AM_CONDITIONAL(HAVE_EMULATOR, [test x"$EMULATOR" != x]) + +AC_ARG_ENABLE([debug], + [AS_HELP_STRING([--enable-debug],[enable debugging])], + [ + CFLAGS="-Og -g -pthread -Wall -Wextra" + AC_CHECK_CC_OPT([-rdynamic], CFLAGS="$CFLAGS -rdynamic", []) + ], + []) + +AC_ARG_ENABLE([warning-as-error], + [AS_HELP_STRING([--enable-warning-as-error],[stop build on warnings])], + [ + AC_CHECK_CC_OPT([-Werror], CFLAGS="$CFLAGS -Werror", []) + dnl This avoid the Darwin error: clang: error: argument unused during compilation: '-pthread' + dnl See: https://llvm.org/bugs/show_bug.cgi?id=7798 + AC_CHECK_CC_OPT([-Wno-error=unused-command-line-argument], CFLAGS="$CFLAGS -Wno-error=unused-command-line-argument", []) + ], + []) + +AC_ARG_ENABLE([warning], + [AS_HELP_STRING([--enable-warning],[enable extra warning])], + [ + AC_CHECK_CC_OPT([-Wpointer-arith], CFLAGS="$CFLAGS -Wpointer-arith", []) + AC_CHECK_CC_OPT([-Wcast-qual], CFLAGS="$CFLAGS -Wcast-qual", []) + AC_CHECK_CC_OPT([-Wunused], CFLAGS="$CFLAGS -Wunused", []) + AC_CHECK_CC_OPT([-Wunreachable-code], CFLAGS="$CFLAGS -Wunreachable-code", []) + AC_CHECK_CC_OPT([-Wpadded], CFLAGS="$CFLAGS -Wpadded", []) + AC_CHECK_CC_OPT([-Weverything], CFLAGS="$CFLAGS -Weverything", []) + ], + []) + +AC_ARG_VAR([TESTENV], [Test environment]) +AC_ARG_VAR([FAILENV], [Test environment for failing tests]) +AC_ARG_VAR([TESTENV_SSE2], [Test environment for SSE2]) +AC_ARG_VAR([TESTENV_SSSE3], [Test environment for SSSE3]) +AC_ARG_VAR([TESTENV_SSE42], [Test environment for SSE42]) +AC_ARG_VAR([TESTENV_AVX2], [Test environment for AVX2]) + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT + diff --git a/configure.windows-x64 b/configure.windows-x64 new file mode 100755 index 0000000..8b7107f --- /dev/null +++ b/configure.windows-x64 @@ -0,0 +1,3 @@ +./configure --host=x86_64-w64-mingw32.static --build=`./config.guess` $@ + + diff --git a/configure.windows-x86 b/configure.windows-x86 new file mode 100755 index 0000000..913871a --- /dev/null +++ b/configure.windows-x86 @@ -0,0 +1,3 @@ +./configure --host=i686-w64-mingw32.static --build=`./config.guess` $@ + + diff --git a/install-sh b/install-sh new file mode 100755 index 0000000..0b0fdcb --- /dev/null +++ b/install-sh @@ -0,0 +1,501 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2013-12-25.23; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +tab=' ' +nl=' +' +IFS=" $tab$nl" + +# Set DOITPROG to "echo" to test this script. + +doit=${DOITPROG-} +doit_exec=${doit:-exec} + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +is_target_a_directory=possibly + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) + is_target_a_directory=always + dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) is_target_a_directory=never;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +# We allow the use of options -d and -T together, by making -d +# take the precedence; this is for compatibility with GNU install. + +if test -n "$dir_arg"; then + if test -n "$dst_arg"; then + echo "$0: target directory not allowed when installing a directory." >&2 + exit 1 + fi +fi + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + if test $# -gt 1 || test "$is_target_a_directory" = always; then + if test ! -d "$dst_arg"; then + echo "$0: $dst_arg: Is not a directory." >&2 + exit 1 + fi + fi +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test "$is_target_a_directory" = never; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + dstdir=`dirname "$dst"` + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + oIFS=$IFS + IFS=/ + set -f + set fnord $dstdir + shift + set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + set +f && + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/missing b/missing new file mode 100755 index 0000000..f62bbae --- /dev/null +++ b/missing @@ -0,0 +1,215 @@ +#! /bin/sh +# Common wrapper for a few potentially missing GNU programs. + +scriptversion=2013-10-28.13; # UTC + +# Copyright (C) 1996-2014 Free Software Foundation, Inc. +# Originally written by Fran,cois Pinard , 1996. + +# 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 2, 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 . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try '$0 --help' for more information" + exit 1 +fi + +case $1 in + + --is-lightweight) + # Used by our autoconf macros to check whether the available missing + # script is modern enough. + exit 0 + ;; + + --run) + # Back-compat with the calling convention used by older automake. + shift + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due +to PROGRAM being missing or too old. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + +Supported PROGRAM values: + aclocal autoconf autoheader autom4te automake makeinfo + bison yacc flex lex help2man + +Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and +'g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: unknown '$1' option" + echo 1>&2 "Try '$0 --help' for more information" + exit 1 + ;; + +esac + +# Run the given program, remember its exit status. +"$@"; st=$? + +# If it succeeded, we are done. +test $st -eq 0 && exit 0 + +# Also exit now if we it failed (or wasn't found), and '--version' was +# passed; such an option is passed most likely to detect whether the +# program is present and works. +case $2 in --version|--help) exit $st;; esac + +# Exit code 63 means version mismatch. This often happens when the user +# tries to use an ancient version of a tool on a file that requires a +# minimum version. +if test $st -eq 63; then + msg="probably too old" +elif test $st -eq 127; then + # Program was missing. + msg="missing on your system" +else + # Program was found and executed, but failed. Give up. + exit $st +fi + +perl_URL=http://www.perl.org/ +flex_URL=http://flex.sourceforge.net/ +gnu_software_URL=http://www.gnu.org/software + +program_details () +{ + case $1 in + aclocal|automake) + echo "The '$1' program is part of the GNU Automake package:" + echo "<$gnu_software_URL/automake>" + echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/autoconf>" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + autoconf|autom4te|autoheader) + echo "The '$1' program is part of the GNU Autoconf package:" + echo "<$gnu_software_URL/autoconf/>" + echo "It also requires GNU m4 and Perl in order to run:" + echo "<$gnu_software_URL/m4/>" + echo "<$perl_URL>" + ;; + esac +} + +give_advice () +{ + # Normalize program name to check for. + normalized_program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + + printf '%s\n' "'$1' is $msg." + + configure_deps="'configure.ac' or m4 files included by 'configure.ac'" + case $normalized_program in + autoconf*) + echo "You should only need it if you modified 'configure.ac'," + echo "or m4 files included by it." + program_details 'autoconf' + ;; + autoheader*) + echo "You should only need it if you modified 'acconfig.h' or" + echo "$configure_deps." + program_details 'autoheader' + ;; + automake*) + echo "You should only need it if you modified 'Makefile.am' or" + echo "$configure_deps." + program_details 'automake' + ;; + aclocal*) + echo "You should only need it if you modified 'acinclude.m4' or" + echo "$configure_deps." + program_details 'aclocal' + ;; + autom4te*) + echo "You might have modified some maintainer files that require" + echo "the 'autom4te' program to be rebuilt." + program_details 'autom4te' + ;; + bison*|yacc*) + echo "You should only need it if you modified a '.y' file." + echo "You may want to install the GNU Bison package:" + echo "<$gnu_software_URL/bison/>" + ;; + lex*|flex*) + echo "You should only need it if you modified a '.l' file." + echo "You may want to install the Fast Lexical Analyzer package:" + echo "<$flex_URL>" + ;; + help2man*) + echo "You should only need it if you modified a dependency" \ + "of a man page." + echo "You may want to install the GNU Help2man package:" + echo "<$gnu_software_URL/help2man/>" + ;; + makeinfo*) + echo "You should only need it if you modified a '.texi' file, or" + echo "any other file indirectly affecting the aspect of the manual." + echo "You might want to install the Texinfo package:" + echo "<$gnu_software_URL/texinfo/>" + echo "The spurious makeinfo call might also be the consequence of" + echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" + echo "want to install GNU make:" + echo "<$gnu_software_URL/make/>" + ;; + *) + echo "You might have modified some files without having the proper" + echo "tools for further handling them. Check the 'README' file, it" + echo "often tells you about the needed prerequisites for installing" + echo "this package. You may also peek at any GNU archive site, in" + echo "case some other package contains this missing '$1' program." + ;; + esac +} + +give_advice "$1" | sed -e '1s/^/WARNING: /' \ + -e '2,$s/^/ /' >&2 + +# Propagate the correct exit status (expected to be 127 for a program +# not found, 63 for a program that failed due to version mismatch). +exit $st + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/raid/COPYING b/raid/COPYING new file mode 100644 index 0000000..a43ea21 --- /dev/null +++ b/raid/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE 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. + + END OF TERMS AND CONDITIONS + + Appendix: 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 +convey 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) 19yy + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision 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, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This 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 Library General +Public License instead of this License. diff --git a/raid/check.c b/raid/check.c new file mode 100644 index 0000000..9bed933 --- /dev/null +++ b/raid/check.c @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2015 Andrea Mazzoleni + * + * 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 2 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. + */ + +#include "internal.h" +#include "combo.h" +#include "gf.h" + +/** + * Validate the provided failed blocks. + * + * This function checks if the specified failed blocks satisfy the redundancy + * information using the data from the known valid parity blocks. + * + * It's similar at raid_check(), just with a different format for arguments. + * + * The number of failed blocks @nr must be strictly less than the number of + * parities @nv, because you need one more parity to validate the recovering. + * + * No data or parity blocks are modified. + * + * @nr Number of failed data blocks. + * @id[] Vector of @nr indexes of the failed data blocks. + * The indexes start from 0. They must be in order. + * @nv Number of valid parity blocks. + * @ip[] Vector of @nv indexes of the valid parity blocks. + * The indexes start from 0. They must be in order. + * @nd Number of data blocks. + * @size Size of the blocks pointed by @v. It must be a multipler of 64. + * @v Vector of pointers to the blocks of data and parity. + * It has (@nd + @ip[@nv - 1] + 1) elements. The starting elements are the + * blocks for data, following with the parity blocks. + * Each block has @size bytes. + * @return 0 if the check is satisfied. -1 otherwise. + */ +static int raid_validate(int nr, int *id, int nv, int *ip, int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + const uint8_t *T[RAID_PARITY_MAX][RAID_PARITY_MAX]; + uint8_t G[RAID_PARITY_MAX * RAID_PARITY_MAX]; + uint8_t V[RAID_PARITY_MAX * RAID_PARITY_MAX]; + size_t i; + int j, k, l; + + BUG_ON(nr >= nv); + + /* setup the coefficients matrix */ + for (j = 0; j < nr; ++j) + for (k = 0; k < nr; ++k) + G[j * nr + k] = A(ip[j], id[k]); + + /* invert it to solve the system of linear equations */ + raid_invert(G, V, nr); + + /* get multiplication tables */ + for (j = 0; j < nr; ++j) + for (k = 0; k < nr; ++k) + T[j][k] = table(V[j * nr + k]); + + /* check all positions */ + for (i = 0; i < size; ++i) { + uint8_t p[RAID_PARITY_MAX]; + + /* get parity */ + for (j = 0; j < nv; ++j) + p[j] = v[nd + ip[j]][i]; + + /* compute delta parity, skipping broken disks */ + for (j = 0, k = 0; j < nd; ++j) { + uint8_t b; + + /* skip broken disks */ + if (k < nr && id[k] == j) { + ++k; + continue; + } + + b = v[j][i]; + for (l = 0; l < nv; ++l) + p[l] ^= gfmul[b][gfgen[ip[l]][j]]; + } + + /* reconstruct data */ + for (j = 0; j < nr; ++j) { + uint8_t b = 0; + int idj = id[j]; + + /* recompute the data */ + for (k = 0; k < nr; ++k) + b ^= T[j][k][p[k]]; + + /* add the parity contribution of the reconstructed data */ + for (l = nr; l < nv; ++l) + p[l] ^= gfmul[b][gfgen[ip[l]][idj]]; + } + + /* check that the final parity is 0 */ + for (l = nr; l < nv; ++l) + if (p[l] != 0) + return -1; + } + + return 0; +} + +int raid_check(int nr, int *ir, int nd, int np, size_t size, void **v) +{ + /* valid parity index */ + int ip[RAID_PARITY_MAX]; + int vp; + int rd; + int i, j; + + /* enforce limit on size */ + BUG_ON(size % 64 != 0); + + /* enforce limit on number of failures */ + BUG_ON(nr >= np); /* >= because we check with extra parity */ + BUG_ON(np > RAID_PARITY_MAX); + + /* enforce order in index vector */ + BUG_ON(nr >= 2 && ir[0] >= ir[1]); + BUG_ON(nr >= 3 && ir[1] >= ir[2]); + BUG_ON(nr >= 4 && ir[2] >= ir[3]); + BUG_ON(nr >= 5 && ir[3] >= ir[4]); + BUG_ON(nr >= 6 && ir[4] >= ir[5]); + + /* enforce limit on index vector */ + BUG_ON(nr > 0 && ir[nr-1] >= nd + np); + + /* count failed data disk */ + rd = 0; + while (rd < nr && ir[rd] < nd) + ++rd; + + /* put valid parities into ip[] */ + vp = 0; + for (i = rd, j = 0; j < np; ++j) { + /* if parity is failed */ + if (i < nr && ir[i] == nd + j) { + /* skip broken parity */ + ++i; + } else { + /* store valid parity */ + ip[vp] = j; + ++vp; + } + } + + return raid_validate(rd, ir, vp, ip, nd, size, v); +} + +int raid_scan(int *ir, int nd, int np, size_t size, void **v) +{ + int r; + + /* check the special case of no failure */ + if (np != 0 && raid_check(0, 0, nd, np, size, v) == 0) + return 0; + + /* for each number of possible failures */ + for (r = 1; r < np; ++r) { + /* try all combinations of r failures on n disks */ + combination_first(r, nd + np, ir); + do { + /* verify if the combination is a valid one */ + if (raid_check(r, ir, nd, np, size, v) == 0) + return r; + } while (combination_next(r, nd + np, ir)); + } + + /* no solution found */ + return -1; +} + diff --git a/raid/combo.h b/raid/combo.h new file mode 100644 index 0000000..8efc31a --- /dev/null +++ b/raid/combo.h @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 2 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. + */ + +#ifndef __RAID_COMBO_H +#define __RAID_COMBO_H + +#include + +/** + * Get the first permutation with repetition of r of n elements. + * + * Typical use is with permutation_next() in the form : + * + * int i[R]; + * permutation_first(R, N, i); + * do { + * code using i[0], i[1], ..., i[R-1] + * } while (permutation_next(R, N, i)); + * + * It's equivalent at the code : + * + * for(i[0]=0;i[0]= n) { + + /* if we are at the first level, we have finished */ + if (i == 0) + return 0; + + /* increase the previous position */ + --i; + goto recurse; + } + + ++i; + + /* initialize all the next positions, if any */ + while (i < r) { + c[i] = 0; + ++i; + } + + return 1; +} + +/** + * Get the first combination without repetition of r of n elements. + * + * Typical use is with combination_next() in the form : + * + * int i[R]; + * combination_first(R, N, i); + * do { + * code using i[0], i[1], ..., i[R-1] + * } while (combination_next(R, N, i)); + * + * It's equivalent at the code : + * + * for(i[0]=0;i[0]= h) { + + /* if we are at the first level, we have finished */ + if (i == 0) + return 0; + + /* increase the previous position */ + --i; + --h; + goto recurse; + } + + ++i; + + /* initialize all the next positions, if any */ + while (i < r) { + /* each position start at the next value of the previous one */ + c[i] = c[i - 1] + 1; + ++i; + } + + return 1; +} +#endif + diff --git a/raid/cpu.h b/raid/cpu.h new file mode 100644 index 0000000..ed909bb --- /dev/null +++ b/raid/cpu.h @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 2 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. + */ + +#ifndef __RAID_CPU_H +#define __RAID_CPU_H + +#ifdef CONFIG_X86 + +static inline void raid_cpuid(uint32_t func_eax, uint32_t sub_ecx, uint32_t *reg) +{ + asm volatile ( +#if defined(__i386__) && defined(__PIC__) + /* allow compilation in PIC mode saving ebx */ + "xchgl %%ebx, %1\n" + "cpuid\n" + "xchgl %%ebx, %1\n" + : "=a" (reg[0]), "=r" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) + : "0" (func_eax), "2" (sub_ecx) +#else + "cpuid\n" + : "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) + : "0" (func_eax), "2" (sub_ecx) +#endif + ); +} + +static inline void raid_xgetbv(uint32_t* reg) +{ + /* get the value of the Extended Control Register ecx=0 */ + asm volatile ( + /* uses a direct encoding of the XGETBV instruction as only recent */ + /* assemblers support it. */ + /* the next line is equivalent at: "xgetbv\n" */ + ".byte 0x0f, 0x01, 0xd0\n" + : "=a" (reg[0]), "=d" (reg[3]) + : "c" (0) + ); +} + +#define CPU_VENDOR_MAX 13 + +static inline void raid_cpu_info(char *vendor, unsigned *family, unsigned *model) +{ + uint32_t reg[4]; + unsigned f, ef, m, em; + + raid_cpuid(0, 0, reg); + + ((uint32_t*)vendor)[0] = reg[1]; + ((uint32_t*)vendor)[1] = reg[3]; + ((uint32_t*)vendor)[2] = reg[2]; + vendor[12] = 0; + + raid_cpuid(1, 0, reg); + + f = (reg[0] >> 8) & 0xF; + ef = (reg[0] >> 20) & 0xFF; + m = (reg[0] >> 4) & 0xF; + em = (reg[0] >> 16) & 0xF; + + if (strcmp(vendor, "AuthenticAMD") == 0) { + if (f < 15) { + *family = f; + *model = m; + } else { + *family = f + ef; + *model = m + (em << 4); + } + } else { + *family = f + ef; + *model = m + (em << 4); + } +} + +static inline int raid_cpu_match_sse(uint32_t cpuid_1_ecx, uint32_t cpuid_1_edx) +{ + uint32_t reg[4]; + + raid_cpuid(1, 0, reg); + if ((reg[2] & cpuid_1_ecx) != cpuid_1_ecx) + return 0; + if ((reg[3] & cpuid_1_edx) != cpuid_1_edx) + return 0; + + return 1; +} + +static inline int raid_cpu_match_avx(uint32_t cpuid_1_ecx, uint32_t cpuid_7_ebx, uint32_t xcr0) +{ + uint32_t reg[4]; + + raid_cpuid(1, 0, reg); + if ((reg[2] & cpuid_1_ecx) != cpuid_1_ecx) + return 0; + + raid_xgetbv(reg); + if ((reg[0] & xcr0) != xcr0) + return 0; + + raid_cpuid(7, 0, reg); + if ((reg[1] & cpuid_7_ebx) != cpuid_7_ebx) + return 0; + + return 1; +} + +static inline int raid_cpu_has_sse2(void) +{ + /* + * Intel® 64 and IA-32 Architectures Software Developer's Manual + * 325462-048US September 2013 + * + * 11.6.2 Checking for SSE/SSE2 Support + * Before an application attempts to use the SSE and/or SSE2 extensions, it should check + * that they are present on the processor: + * 1. Check that the processor supports the CPUID instruction. Bit 21 of the EFLAGS + * register can be used to check processor's support the CPUID instruction. + * 2. Check that the processor supports the SSE and/or SSE2 extensions (true if + * CPUID.01H:EDX.SSE[bit 25] = 1 and/or CPUID.01H:EDX.SSE2[bit 26] = 1). + */ + return raid_cpu_match_sse( + 0, + 1 << 26); /* SSE2 */ +} + +static inline int raid_cpu_has_ssse3(void) +{ + /* + * Intel® 64 and IA-32 Architectures Software Developer's Manual + * 325462-048US September 2013 + * + * 12.7.2 Checking for SSSE3 Support + * Before an application attempts to use the SSSE3 extensions, the application should + * follow the steps illustrated in Section 11.6.2, "Checking for SSE/SSE2 Support." + * Next, use the additional step provided below: + * Check that the processor supports SSSE3 (if CPUID.01H:ECX.SSSE3[bit 9] = 1). + */ + return raid_cpu_match_sse( + 1 << 9, /* SSSE3 */ + 1 << 26); /* SSE2 */ +} + +static inline int raid_cpu_has_crc32(void) +{ + /* + * Intel® 64 and IA-32 Architectures Software Developer's Manual + * 325462-048US September 2013 + * + * 12.12.3 Checking for SSE4.2 Support + * ... + * Before an application attempts to use the CRC32 instruction, it must check + * that the processor supports SSE4.2 (if CPUID.01H:ECX.SSE4_2[bit 20] = 1). + */ + return raid_cpu_match_sse( + 1 << 20, /* CRC32 */ + 0); +} + +static inline int raid_cpu_has_avx2(void) +{ + /* + * Intel Architecture Instruction Set Extensions Programming Reference + * 319433-022 October 2014 + * + * 14.3 Detection of AVX instructions + * 1) Detect CPUID.1:ECX.OSXSAVE[bit 27] = 1 (XGETBV enabled for application use1) + * 2) Issue XGETBV and verify that XCR0[2:1] = `11b' (XMM state and YMM state are enabled by OS). + * 3) detect CPUID.1:ECX.AVX[bit 28] = 1 (AVX instructions supported). + * (Step 3 can be done in any order relative to 1 and 2) + * + * 14.7.1 Detection of AVX2 + * Hardware support for AVX2 is indicated by CPUID.(EAX=07H, ECX=0H):EBX.AVX2[bit 5]=1. + * Application Software must identify that hardware supports AVX, after that it must + * also detect support for AVX2 by checking CPUID.(EAX=07H, ECX=0H):EBX.AVX2[bit 5]. + */ + return raid_cpu_match_avx( + (1 << 27) | (1 << 28), /* OSXSAVE and AVX */ + 1 << 5, /* AVX2 */ + 3 << 1); /* OS saves XMM and YMM registers */ +} + +static inline int raid_cpu_has_avx512bw(void) +{ + /* + * Intel Architecture Instruction Set Extensions Programming Reference + * 319433-022 October 2014 + * + * 2.2 Detection of 512-bit Instruction Groups of Intel AVX-512 Family + * 1) Detect CPUID.1:ECX.OSXSAVE[bit 27] = 1 (XGETBV enabled for application use) + * 2) Execute XGETBV and verify that XCR0[7:5] = `111b' (OPMASK state, upper 256-bit of + * ZMM0-ZMM15 and ZMM16-ZMM31 state are enabled by OS) and that XCR0[2:1] = `11b' + * (XMM state and YMM state are enabled by OS). + * 3) Verify both CPUID.0x7.0:EBX.AVX512F[bit 16] = 1, CPUID.0x7.0:EBX.AVX512BW[bit 30] = 1. + */ + + /* note that intentionally we don't check for AVX and AVX2 */ + /* because the documentation doesn't require that */ + return raid_cpu_match_avx( + 1 << 27, /* XSAVE/XGETBV */ + (1 << 16) | (1 << 30), /* AVX512F and AVX512BW */ + (3 << 1) | (7 << 5)); /* OS saves XMM, YMM and ZMM registers */ +} + +/** + * Check if it's an Intel Atom CPU. + */ +static inline int raid_cpu_is_atom(unsigned family, unsigned model) +{ + if (family != 6) + return 0; + + /* + * x86 Architecture CPUID + * http://www.sandpile.org/x86/cpuid.htm + * + * Intel Atom + * 1C (28) Atom (45 nm) with 512 KB on-die L2 + * 26 (38) Atom (45 nm) with 512 KB on-die L2 + * 36 (54) Atom (32 nm) with 512 KB on-die L2 + * 27 (39) Atom (32 nm) with 512 KB on-die L2 + * 35 (53) Atom (?? nm) with ??? KB on-die L2 + * 4A (74) Atom 2C (22 nm) 1 MB L2 + PowerVR (TGR) + * 5A (90) Atom 4C (22 nm) 2 MB L2 + PowerVR (ANN) + * 37 (55) Atom 4C (22 nm) 2 MB L2 + Intel Gen7 (BYT) + * 4C (76) Atom 4C (14 nm) 2 MB L2 + Intel Gen8 (BSW) + * 5D (93) Atom 4C (28 nm TSMC) 1 MB L2 + Mali (SoFIA) + * 4D (77) Atom 8C (22 nm) 4 MB L2 (AVN) + * ?? Atom ?C (14 nm) ? MB L2 (DVN) + */ + return model == 28 || model == 38 || model == 54 + || model == 39 || model == 53 || model == 74 + || model == 90 || model == 55 || model == 76 + || model == 93 || model == 77; +} + +/** + * Check if the processor has a slow MULT implementation. + * If yes, it's better to use a hash not based on multiplication. + */ +static inline int raid_cpu_has_slowmult(void) +{ + char vendor[CPU_VENDOR_MAX]; + unsigned family; + unsigned model; + + /* + * In some cases Murmur3 based on MUL instruction, + * is a LOT slower than Spooky2 based on SHIFTs. + */ + raid_cpu_info(vendor, &family, &model); + + if (strcmp(vendor, "GenuineIntel") == 0) { + /* + * Intel Atom (Model 28) + * murmur3:378 MB/s, spooky2:3413 MB/s (x86) + * + * Intel Atom (Model 77) + * murmur3:1311 MB/s, spooky2:4056 MB/s (x64) + */ + if (raid_cpu_is_atom(family, model)) + return 1; + } + + return 0; +} + +/** + * Check if the processor has a slow extended set of SSE registers. + * If yes, it's better to limit the unroll to the firsrt 8 registers. + */ +static inline int raid_cpu_has_slowextendedreg(void) +{ + char vendor[CPU_VENDOR_MAX]; + unsigned family; + unsigned model; + + /* + * In some cases the PAR2 implementation using 16 SSE registers + * is a LITTLE slower than the one using only the first 8 registers. + * This doesn't happen for PARZ. + */ + raid_cpu_info(vendor, &family, &model); + + if (strcmp(vendor, "AuthenticAMD") == 0) { + /* + * AMD Bulldozer + * par2_sse2:4922 MB/s, par2_sse2e:4465 MB/s + */ + if (family == 21) + return 1; + } + + if (strcmp(vendor, "GenuineIntel") == 0) { + /* + * Intel Atom (Model 77) + * par2_sse2:5686 MB/s, par2_sse2e:5250 MB/s + * parz_sse2:3100 MB/s, parz_sse2e:3400 MB/s + * par3_sse3:1921 MB/s, par3_sse3e:1813 MB/s + * par4_sse3:1175 MB/s, par4_sse3e:1113 MB/s + * par5_sse3:876 MB/s, par5_sse3e:675 MB/s + * par6_sse3:705 MB/s, par6_sse3e:529 MB/s + * + * Intel Atom (Model 77) "Avoton C2750" + * par2_sse2:5661 MB/s, par2_sse2e:5382 MB/s + * parz_sse2:3110 MB/s, parz_sse2e:3450 MB/s + * par3_sse3:1769 MB/s, par3_sse3e:1856 MB/s + * par4_sse3:1221 MB/s, par4_sse3e:1141 MB/s + * par5_sse3:910 MB/s, par5_sse3e:675 MB/s + * par6_sse3:720 MB/s, par6_sse3e:534 MB/s + */ + if (raid_cpu_is_atom(family, model)) + return 1; + } + + return 0; +} +#endif + +#endif + diff --git a/raid/gf.h b/raid/gf.h new file mode 100644 index 0000000..1702c28 --- /dev/null +++ b/raid/gf.h @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 2 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. + */ + +#ifndef __RAID_GF_H +#define __RAID_GF_H + +/* + * Galois field operations. + * + * Basic range checks are implemented using BUG_ON(). + */ + +/* + * GF a*b. + */ +static __always_inline uint8_t mul(uint8_t a, uint8_t b) +{ + return gfmul[a][b]; +} + +/* + * GF 1/a. + * Not defined for a == 0. + */ +static __always_inline uint8_t inv(uint8_t v) +{ + BUG_ON(v == 0); /* division by zero */ + + return gfinv[v]; +} + +/* + * GF 2^a. + */ +static __always_inline uint8_t pow2(int v) +{ + BUG_ON(v < 0 || v > 254); /* invalid exponent */ + + return gfexp[v]; +} + +/* + * Gets the multiplication table for a specified value. + */ +static __always_inline const uint8_t *table(uint8_t v) +{ + return gfmul[v]; +} + +/* + * Gets the generator matrix coefficient for parity 'p' and disk 'd'. + */ +static __always_inline uint8_t A(int p, int d) +{ + return gfgen[p][d]; +} + +/* + * Dereference as uint8_t + */ +#define v_8(p) (*(uint8_t *)&(p)) + +/* + * Dereference as uint32_t + */ +#define v_32(p) (*(uint32_t *)&(p)) + +/* + * Dereference as uint64_t + */ +#define v_64(p) (*(uint64_t *)&(p)) + +/* + * Multiply each byte of a uint32 by 2 in the GF(2^8). + */ +static __always_inline uint32_t x2_32(uint32_t v) +{ + uint32_t mask = v & 0x80808080U; + + mask = (mask << 1) - (mask >> 7); + v = (v << 1) & 0xfefefefeU; + v ^= mask & 0x1d1d1d1dU; + return v; +} + +/* + * Multiply each byte of a uint64 by 2 in the GF(2^8). + */ +static __always_inline uint64_t x2_64(uint64_t v) +{ + uint64_t mask = v & 0x8080808080808080ULL; + + mask = (mask << 1) - (mask >> 7); + v = (v << 1) & 0xfefefefefefefefeULL; + v ^= mask & 0x1d1d1d1d1d1d1d1dULL; + return v; +} + +/* + * Divide each byte of a uint32 by 2 in the GF(2^8). + */ +static __always_inline uint32_t d2_32(uint32_t v) +{ + uint32_t mask = v & 0x01010101U; + + mask = (mask << 8) - mask; + v = (v >> 1) & 0x7f7f7f7fU; + v ^= mask & 0x8e8e8e8eU; + return v; +} + +/* + * Divide each byte of a uint64 by 2 in the GF(2^8). + */ +static __always_inline uint64_t d2_64(uint64_t v) +{ + uint64_t mask = v & 0x0101010101010101ULL; + + mask = (mask << 8) - mask; + v = (v >> 1) & 0x7f7f7f7f7f7f7f7fULL; + v ^= mask & 0x8e8e8e8e8e8e8e8eULL; + return v; +} + +#endif + diff --git a/raid/helper.c b/raid/helper.c new file mode 100644 index 0000000..f66093f --- /dev/null +++ b/raid/helper.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 2 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. + */ + +#include "internal.h" + +#define RAID_SWAP(a, b) \ + do { \ + if (v[a] > v[b]) { \ + int t = v[a]; \ + v[a] = v[b]; \ + v[b] = t; \ + } \ + } while (0) + +void raid_sort(int n, int *v) +{ + /* sorting networks generated with Batcher's Merge-Exchange */ + switch (n) { + case 2: + RAID_SWAP(0, 1); + break; + case 3: + RAID_SWAP(0, 2); + RAID_SWAP(0, 1); + RAID_SWAP(1, 2); + break; + case 4: + RAID_SWAP(0, 2); + RAID_SWAP(1, 3); + RAID_SWAP(0, 1); + RAID_SWAP(2, 3); + RAID_SWAP(1, 2); + break; + case 5: + RAID_SWAP(0, 4); + RAID_SWAP(0, 2); + RAID_SWAP(1, 3); + RAID_SWAP(2, 4); + RAID_SWAP(0, 1); + RAID_SWAP(2, 3); + RAID_SWAP(1, 4); + RAID_SWAP(1, 2); + RAID_SWAP(3, 4); + break; + case 6: + RAID_SWAP(0, 4); + RAID_SWAP(1, 5); + RAID_SWAP(0, 2); + RAID_SWAP(1, 3); + RAID_SWAP(2, 4); + RAID_SWAP(3, 5); + RAID_SWAP(0, 1); + RAID_SWAP(2, 3); + RAID_SWAP(4, 5); + RAID_SWAP(1, 4); + RAID_SWAP(1, 2); + RAID_SWAP(3, 4); + break; + } +} + +void raid_insert(int n, int *v, int i) +{ + /* we don't use binary search because this is intended */ + /* for very small vectors and we want to optimize the case */ + /* of elements inserted already in order */ + + /* insert at the end */ + v[n] = i; + + /* swap until in the correct position */ + while (n > 0 && v[n - 1] > v[n]) { + /* swap */ + int t = v[n - 1]; + + v[n - 1] = v[n]; + v[n] = t; + + /* previous position */ + --n; + } +} + diff --git a/raid/helper.h b/raid/helper.h new file mode 100644 index 0000000..bf68288 --- /dev/null +++ b/raid/helper.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 2 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. + */ + +#ifndef __RAID_HELPER_H +#define __RAID_HELPER_H + +/** + * Inserts an integer in a sorted vector. + * + * This function can be used to insert indexes in order, ready to be used for + * calling raid_rec(). + * + * @n Number of integers currently in the vector. + * @v Vector of integers already sorted. + * It must have extra space for the new elemet at the end. + * @i Value to insert. + */ +void raid_insert(int n, int *v, int i); + +/** + * Sorts a small vector of integers. + * + * If you have indexes not in order, you can use this function to sort them + * before calling raid_rec(). + * + * @n Number of integers. No more than RAID_PARITY_MAX. + * @v Vector of integers. + */ +void raid_sort(int n, int *v); + +#endif + diff --git a/raid/int.c b/raid/int.c new file mode 100644 index 0000000..e16332a --- /dev/null +++ b/raid/int.c @@ -0,0 +1,556 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 2 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. + */ + +#include "internal.h" +#include "gf.h" + +/* + * GEN1 (RAID5 with xor) 32bit C implementation + */ +void raid_gen1_int32(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + int d, l; + size_t i; + + uint32_t p0; + uint32_t p1; + + l = nd - 1; + p = v[nd]; + + for (i = 0; i < size; i += 8) { + p0 = v_32(v[l][i]); + p1 = v_32(v[l][i + 4]); + for (d = l - 1; d >= 0; --d) { + p0 ^= v_32(v[d][i]); + p1 ^= v_32(v[d][i + 4]); + } + v_32(p[i]) = p0; + v_32(p[i + 4]) = p1; + } +} + +/* + * GEN1 (RAID5 with xor) 64bit C implementation + */ +void raid_gen1_int64(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + int d, l; + size_t i; + + uint64_t p0; + uint64_t p1; + + l = nd - 1; + p = v[nd]; + + for (i = 0; i < size; i += 16) { + p0 = v_64(v[l][i]); + p1 = v_64(v[l][i + 8]); + for (d = l - 1; d >= 0; --d) { + p0 ^= v_64(v[d][i]); + p1 ^= v_64(v[d][i + 8]); + } + v_64(p[i]) = p0; + v_64(p[i + 8]) = p1; + } +} + +/* + * GEN2 (RAID6 with powers of 2) 32bit C implementation + */ +void raid_gen2_int32(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *q; + int d, l; + size_t i; + + uint32_t d0, q0, p0; + uint32_t d1, q1, p1; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + + for (i = 0; i < size; i += 8) { + q0 = p0 = v_32(v[l][i]); + q1 = p1 = v_32(v[l][i + 4]); + for (d = l - 1; d >= 0; --d) { + d0 = v_32(v[d][i]); + d1 = v_32(v[d][i + 4]); + + p0 ^= d0; + p1 ^= d1; + + q0 = x2_32(q0); + q1 = x2_32(q1); + + q0 ^= d0; + q1 ^= d1; + } + v_32(p[i]) = p0; + v_32(p[i + 4]) = p1; + v_32(q[i]) = q0; + v_32(q[i + 4]) = q1; + } +} + +/* + * GEN2 (RAID6 with powers of 2) 64bit C implementation + */ +void raid_gen2_int64(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *q; + int d, l; + size_t i; + + uint64_t d0, q0, p0; + uint64_t d1, q1, p1; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + + for (i = 0; i < size; i += 16) { + q0 = p0 = v_64(v[l][i]); + q1 = p1 = v_64(v[l][i + 8]); + for (d = l - 1; d >= 0; --d) { + d0 = v_64(v[d][i]); + d1 = v_64(v[d][i + 8]); + + p0 ^= d0; + p1 ^= d1; + + q0 = x2_64(q0); + q1 = x2_64(q1); + + q0 ^= d0; + q1 ^= d1; + } + v_64(p[i]) = p0; + v_64(p[i + 8]) = p1; + v_64(q[i]) = q0; + v_64(q[i + 8]) = q1; + } +} + +/* + * GEN3 (triple parity with Cauchy matrix) 8bit C implementation + * + * Note that instead of a generic multiplication table, likely resulting + * in multiple cache misses, a precomputed table could be used. + * But this is only a kind of reference function, and we are not really + * interested in speed. + */ +void raid_gen3_int8(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *q; + uint8_t *r; + int d, l; + size_t i; + + uint8_t d0, r0, q0, p0; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + r = v[nd + 2]; + + for (i = 0; i < size; i += 1) { + p0 = q0 = r0 = 0; + for (d = l; d > 0; --d) { + d0 = v_8(v[d][i]); + + p0 ^= d0; + q0 ^= gfmul[d0][gfgen[1][d]]; + r0 ^= gfmul[d0][gfgen[2][d]]; + } + + /* first disk with all coefficients at 1 */ + d0 = v_8(v[0][i]); + + p0 ^= d0; + q0 ^= d0; + r0 ^= d0; + + v_8(p[i]) = p0; + v_8(q[i]) = q0; + v_8(r[i]) = r0; + } +} + +/* + * GEN4 (quad parity with Cauchy matrix) 8bit C implementation + * + * Note that instead of a generic multiplication table, likely resulting + * in multiple cache misses, a precomputed table could be used. + * But this is only a kind of reference function, and we are not really + * interested in speed. + */ +void raid_gen4_int8(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *q; + uint8_t *r; + uint8_t *s; + int d, l; + size_t i; + + uint8_t d0, s0, r0, q0, p0; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + r = v[nd + 2]; + s = v[nd + 3]; + + for (i = 0; i < size; i += 1) { + p0 = q0 = r0 = s0 = 0; + for (d = l; d > 0; --d) { + d0 = v_8(v[d][i]); + + p0 ^= d0; + q0 ^= gfmul[d0][gfgen[1][d]]; + r0 ^= gfmul[d0][gfgen[2][d]]; + s0 ^= gfmul[d0][gfgen[3][d]]; + } + + /* first disk with all coefficients at 1 */ + d0 = v_8(v[0][i]); + + p0 ^= d0; + q0 ^= d0; + r0 ^= d0; + s0 ^= d0; + + v_8(p[i]) = p0; + v_8(q[i]) = q0; + v_8(r[i]) = r0; + v_8(s[i]) = s0; + } +} + +/* + * GEN5 (penta parity with Cauchy matrix) 8bit C implementation + * + * Note that instead of a generic multiplication table, likely resulting + * in multiple cache misses, a precomputed table could be used. + * But this is only a kind of reference function, and we are not really + * interested in speed. + */ +void raid_gen5_int8(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *q; + uint8_t *r; + uint8_t *s; + uint8_t *t; + int d, l; + size_t i; + + uint8_t d0, t0, s0, r0, q0, p0; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + r = v[nd + 2]; + s = v[nd + 3]; + t = v[nd + 4]; + + for (i = 0; i < size; i += 1) { + p0 = q0 = r0 = s0 = t0 = 0; + for (d = l; d > 0; --d) { + d0 = v_8(v[d][i]); + + p0 ^= d0; + q0 ^= gfmul[d0][gfgen[1][d]]; + r0 ^= gfmul[d0][gfgen[2][d]]; + s0 ^= gfmul[d0][gfgen[3][d]]; + t0 ^= gfmul[d0][gfgen[4][d]]; + } + + /* first disk with all coefficients at 1 */ + d0 = v_8(v[0][i]); + + p0 ^= d0; + q0 ^= d0; + r0 ^= d0; + s0 ^= d0; + t0 ^= d0; + + v_8(p[i]) = p0; + v_8(q[i]) = q0; + v_8(r[i]) = r0; + v_8(s[i]) = s0; + v_8(t[i]) = t0; + } +} + +/* + * GEN6 (hexa parity with Cauchy matrix) 8bit C implementation + * + * Note that instead of a generic multiplication table, likely resulting + * in multiple cache misses, a precomputed table could be used. + * But this is only a kind of reference function, and we are not really + * interested in speed. + */ +void raid_gen6_int8(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *q; + uint8_t *r; + uint8_t *s; + uint8_t *t; + uint8_t *u; + int d, l; + size_t i; + + uint8_t d0, u0, t0, s0, r0, q0, p0; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + r = v[nd + 2]; + s = v[nd + 3]; + t = v[nd + 4]; + u = v[nd + 5]; + + for (i = 0; i < size; i += 1) { + p0 = q0 = r0 = s0 = t0 = u0 = 0; + for (d = l; d > 0; --d) { + d0 = v_8(v[d][i]); + + p0 ^= d0; + q0 ^= gfmul[d0][gfgen[1][d]]; + r0 ^= gfmul[d0][gfgen[2][d]]; + s0 ^= gfmul[d0][gfgen[3][d]]; + t0 ^= gfmul[d0][gfgen[4][d]]; + u0 ^= gfmul[d0][gfgen[5][d]]; + } + + /* first disk with all coefficients at 1 */ + d0 = v_8(v[0][i]); + + p0 ^= d0; + q0 ^= d0; + r0 ^= d0; + s0 ^= d0; + t0 ^= d0; + u0 ^= d0; + + v_8(p[i]) = p0; + v_8(q[i]) = q0; + v_8(r[i]) = r0; + v_8(s[i]) = s0; + v_8(t[i]) = t0; + v_8(u[i]) = u0; + } +} + +/* + * Recover failure of one data block at index id[0] using parity at index + * ip[0] for any RAID level. + * + * Starting from the equation: + * + * Pd = A[ip[0],id[0]] * Dx + * + * and solving we get: + * + * Dx = A[ip[0],id[0]]^-1 * Pd + */ +void raid_rec1_int8(int nr, int *id, int *ip, int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *pa; + const uint8_t *T; + uint8_t G; + uint8_t V; + size_t i; + + (void)nr; /* unused, it's always 1 */ + + /* if it's RAID5 uses the faster function */ + if (ip[0] == 0) { + raid_rec1of1(id, nd, size, vv); + return; + } + + /* setup the coefficients matrix */ + G = A(ip[0], id[0]); + + /* invert it to solve the system of linear equations */ + V = inv(G); + + /* get multiplication tables */ + T = table(V); + + /* compute delta parity */ + raid_delta_gen(1, id, ip, nd, size, vv); + + p = v[nd + ip[0]]; + pa = v[id[0]]; + + for (i = 0; i < size; ++i) { + /* delta */ + uint8_t Pd = p[i] ^ pa[i]; + + /* reconstruct */ + pa[i] = T[Pd]; + } +} + +/* + * Recover failure of two data blocks at indexes id[0],id[1] using parity at + * indexes ip[0],ip[1] for any RAID level. + * + * Starting from the equations: + * + * Pd = A[ip[0],id[0]] * Dx + A[ip[0],id[1]] * Dy + * Qd = A[ip[1],id[0]] * Dx + A[ip[1],id[1]] * Dy + * + * we solve inverting the coefficients matrix. + */ +void raid_rec2_int8(int nr, int *id, int *ip, int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *pa; + uint8_t *q; + uint8_t *qa; + const int N = 2; + const uint8_t *T[N][N]; + uint8_t G[N * N]; + uint8_t V[N * N]; + size_t i; + int j, k; + + (void)nr; /* unused, it's always 2 */ + + /* if it's RAID6 recovering with P and Q uses the faster function */ + if (ip[0] == 0 && ip[1] == 1) { + raid_rec2of2_int8(id, ip, nd, size, vv); + return; + } + + /* setup the coefficients matrix */ + for (j = 0; j < N; ++j) + for (k = 0; k < N; ++k) + G[j * N + k] = A(ip[j], id[k]); + + /* invert it to solve the system of linear equations */ + raid_invert(G, V, N); + + /* get multiplication tables */ + for (j = 0; j < N; ++j) + for (k = 0; k < N; ++k) + T[j][k] = table(V[j * N + k]); + + /* compute delta parity */ + raid_delta_gen(2, id, ip, nd, size, vv); + + p = v[nd + ip[0]]; + q = v[nd + ip[1]]; + pa = v[id[0]]; + qa = v[id[1]]; + + for (i = 0; i < size; ++i) { + /* delta */ + uint8_t Pd = p[i] ^ pa[i]; + uint8_t Qd = q[i] ^ qa[i]; + + /* reconstruct */ + pa[i] = T[0][0][Pd] ^ T[0][1][Qd]; + qa[i] = T[1][0][Pd] ^ T[1][1][Qd]; + } +} + +/* + * Recover failure of N data blocks at indexes id[N] using parity at indexes + * ip[N] for any RAID level. + * + * Starting from the N equations, with 0<=i +#include +#include +#include + +/* + * Inverse assert. + */ +#define BUG_ON(a) assert(!(a)) + +/* + * Forced inline. + */ +#ifndef __always_inline +#define __always_inline inline __attribute__((always_inline)) +#endif + +/* + * Forced alignment. + */ +#ifndef __aligned +#define __aligned(a) __attribute__((aligned(a))) +#endif + +/* + * Align a pointer at the specified size. + */ +static __always_inline void *__align_ptr(void *ptr, uintptr_t size) +{ + uintptr_t offset = (uintptr_t)ptr; + + offset = (offset + size - 1U) & ~(size - 1U); + + return (void *)offset; +} + +/* + * Includes the main interface headers. + */ +#include "raid.h" +#include "helper.h" + +/* + * Internal functions. + * + * These are intended to provide access for testing. + */ +int raid_selftest(void); +void raid_gen_ref(int nd, int np, size_t size, void **vv); +void raid_invert(uint8_t *M, uint8_t *V, int n); +void raid_delta_gen(int nr, int *id, int *ip, int nd, size_t size, void **v); +void raid_rec1of1(int *id, int nd, size_t size, void **v); +void raid_rec2of2_int8(int *id, int *ip, int nd, size_t size, void **vv); +void raid_gen1_int32(int nd, size_t size, void **vv); +void raid_gen1_int64(int nd, size_t size, void **vv); +void raid_gen1_sse2(int nd, size_t size, void **vv); +void raid_gen1_avx2(int nd, size_t size, void **vv); +void raid_gen2_int32(int nd, size_t size, void **vv); +void raid_gen2_int64(int nd, size_t size, void **vv); +void raid_gen2_sse2(int nd, size_t size, void **vv); +void raid_gen2_avx2(int nd, size_t size, void **vv); +void raid_gen2_sse2ext(int nd, size_t size, void **vv); +void raid_genz_int32(int nd, size_t size, void **vv); +void raid_genz_int64(int nd, size_t size, void **vv); +void raid_genz_sse2(int nd, size_t size, void **vv); +void raid_genz_sse2ext(int nd, size_t size, void **vv); +void raid_genz_avx2ext(int nd, size_t size, void **vv); +void raid_gen3_int8(int nd, size_t size, void **vv); +void raid_gen3_ssse3(int nd, size_t size, void **vv); +void raid_gen3_ssse3ext(int nd, size_t size, void **vv); +void raid_gen3_avx2ext(int nd, size_t size, void **vv); +void raid_gen4_int8(int nd, size_t size, void **vv); +void raid_gen4_ssse3(int nd, size_t size, void **vv); +void raid_gen4_ssse3ext(int nd, size_t size, void **vv); +void raid_gen4_avx2ext(int nd, size_t size, void **vv); +void raid_gen5_int8(int nd, size_t size, void **vv); +void raid_gen5_ssse3(int nd, size_t size, void **vv); +void raid_gen5_ssse3ext(int nd, size_t size, void **vv); +void raid_gen5_avx2ext(int nd, size_t size, void **vv); +void raid_gen6_int8(int nd, size_t size, void **vv); +void raid_gen6_ssse3(int nd, size_t size, void **vv); +void raid_gen6_ssse3ext(int nd, size_t size, void **vv); +void raid_gen6_avx2ext(int nd, size_t size, void **vv); +void raid_rec1_int8(int nr, int *id, int *ip, int nd, size_t size, void **vv); +void raid_rec2_int8(int nr, int *id, int *ip, int nd, size_t size, void **vv); +void raid_recX_int8(int nr, int *id, int *ip, int nd, size_t size, void **vv); +void raid_rec1_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv); +void raid_rec2_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv); +void raid_recX_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv); +void raid_rec1_avx2(int nr, int *id, int *ip, int nd, size_t size, void **vv); +void raid_rec2_avx2(int nr, int *id, int *ip, int nd, size_t size, void **vv); +void raid_recX_avx2(int nr, int *id, int *ip, int nd, size_t size, void **vv); + +/* + * Internal naming. + * + * These are intented to provide access for testing. + */ +const char *raid_gen1_tag(void); +const char *raid_gen2_tag(void); +const char *raid_genz_tag(void); +const char *raid_gen3_tag(void); +const char *raid_gen4_tag(void); +const char *raid_gen5_tag(void); +const char *raid_gen6_tag(void); +const char *raid_rec1_tag(void); +const char *raid_rec2_tag(void); +const char *raid_recX_tag(void); + +/* + * Internal forwarders. + */ +extern void (*raid_gen3_ptr)(int nd, size_t size, void **vv); +extern void (*raid_genz_ptr)(int nd, size_t size, void **vv); +extern void (*raid_gen_ptr[RAID_PARITY_MAX])( + int nd, size_t size, void **vv); +extern void (*raid_rec_ptr[RAID_PARITY_MAX])( + int nr, int *id, int *ip, int nd, size_t size, void **vv); + +/* + * Tables. + */ +extern const uint8_t raid_gfmul[256][256] __aligned(256); +extern const uint8_t raid_gfexp[256] __aligned(256); +extern const uint8_t raid_gfinv[256] __aligned(256); +extern const uint8_t raid_gfvandermonde[3][256] __aligned(256); +extern const uint8_t raid_gfcauchy[6][256] __aligned(256); +extern const uint8_t raid_gfcauchypshufb[251][4][2][16] __aligned(256); +extern const uint8_t raid_gfmulpshufb[256][2][16] __aligned(256); +extern const uint8_t (*raid_gfgen)[256]; +#define gfmul raid_gfmul +#define gfexp raid_gfexp +#define gfinv raid_gfinv +#define gfvandermonde raid_gfvandermonde +#define gfcauchy raid_gfcauchy +#define gfgenpshufb raid_gfcauchypshufb +#define gfmulpshufb raid_gfmulpshufb +#define gfgen raid_gfgen + +/* + * Assembler blocks. + */ +#ifdef CONFIG_X86 +#ifdef CONFIG_SSE2 +static __always_inline void raid_sse_begin(void) +{ +} + +static __always_inline void raid_sse_end(void) +{ + /* SSE and AVX code uses non-temporal writes, like MOVNTDQ, */ + /* that use a weak memory model. To ensure that other processors */ + /* see correctly the data written, we use a store-store memory */ + /* barrier at the end of the asm code */ + asm volatile ("sfence" : : : "memory"); + + /* clobbers registers used in the asm code */ + /* this is required because in the Windows ABI, */ + /* registers xmm6-xmm15 should be kept by the callee. */ + /* this clobber list force the compiler to save any */ + /* register that needs to be saved */ + /* we check for __SSE2_ because we require that the */ + /* compiler supports SSE2 registers in the clobber list */ +#ifdef __SSE2__ + asm volatile ("" : : : "%xmm0", "%xmm1", "%xmm2", "%xmm3"); + asm volatile ("" : : : "%xmm4", "%xmm5", "%xmm6", "%xmm7"); +#ifdef CONFIG_X86_64 + asm volatile ("" : : : "%xmm8", "%xmm9", "%xmm10", "%xmm11"); + asm volatile ("" : : : "%xmm12", "%xmm13", "%xmm14", "%xmm15"); +#endif +#endif +} +#endif + +#ifdef CONFIG_AVX2 +static __always_inline void raid_avx_begin(void) +{ + raid_sse_begin(); +} + +static __always_inline void raid_avx_end(void) +{ + raid_sse_end(); + + /* reset the upper part of the ymm registers */ + /* to avoid the 70 clocks penality on the next */ + /* xmm register use */ + asm volatile ("vzeroupper" : : : "memory"); +} +#endif +#endif /* CONFIG_X86 */ + +#endif + diff --git a/raid/intz.c b/raid/intz.c new file mode 100644 index 0000000..80c2014 --- /dev/null +++ b/raid/intz.c @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 2 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. + */ + +#include "internal.h" +#include "gf.h" + +/* + * GENz (triple parity with powers of 2^-1) 32bit C implementation + */ +void raid_genz_int32(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t**)vv; + uint8_t *p; + uint8_t *q; + uint8_t *r; + int d, l; + size_t i; + + uint32_t d0, r0, q0, p0; + uint32_t d1, r1, q1, p1; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + r = v[nd + 2]; + + for (i = 0; i < size; i += 8) { + r0 = q0 = p0 = v_32(v[l][i]); + r1 = q1 = p1 = v_32(v[l][i + 4]); + for (d = l - 1; d >= 0; --d) { + d0 = v_32(v[d][i]); + d1 = v_32(v[d][i + 4]); + + p0 ^= d0; + p1 ^= d1; + + q0 = x2_32(q0); + q1 = x2_32(q1); + + q0 ^= d0; + q1 ^= d1; + + r0 = d2_32(r0); + r1 = d2_32(r1); + + r0 ^= d0; + r1 ^= d1; + } + v_32(p[i]) = p0; + v_32(p[i + 4]) = p1; + v_32(q[i]) = q0; + v_32(q[i + 4]) = q1; + v_32(r[i]) = r0; + v_32(r[i + 4]) = r1; + } +} + +/* + * GENz (triple parity with powers of 2^-1) 64bit C implementation + */ +void raid_genz_int64(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t**)vv; + uint8_t *p; + uint8_t *q; + uint8_t *r; + int d, l; + size_t i; + + uint64_t d0, r0, q0, p0; + uint64_t d1, r1, q1, p1; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + r = v[nd + 2]; + + for (i = 0; i < size; i += 16) { + r0 = q0 = p0 = v_64(v[l][i]); + r1 = q1 = p1 = v_64(v[l][i + 8]); + for (d = l - 1; d >= 0; --d) { + d0 = v_64(v[d][i]); + d1 = v_64(v[d][i + 8]); + + p0 ^= d0; + p1 ^= d1; + + q0 = x2_64(q0); + q1 = x2_64(q1); + + q0 ^= d0; + q1 ^= d1; + + r0 = d2_64(r0); + r1 = d2_64(r1); + + r0 ^= d0; + r1 ^= d1; + } + v_64(p[i]) = p0; + v_64(p[i + 8]) = p1; + v_64(q[i]) = q0; + v_64(q[i + 8]) = q1; + v_64(r[i]) = r0; + v_64(r[i + 8]) = r1; + } +} + diff --git a/raid/memory.c b/raid/memory.c new file mode 100644 index 0000000..02a5a92 --- /dev/null +++ b/raid/memory.c @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 2 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. + */ + +#include "internal.h" +#include "memory.h" + +void *raid_malloc_align(size_t size, size_t align_size, void **freeptr) +{ + unsigned char *ptr; + uintptr_t offset; + + ptr = malloc(size + align_size); + if (!ptr) { + /* LCOV_EXCL_START */ + return 0; + /* LCOV_EXCL_STOP */ + } + + *freeptr = ptr; + + offset = ((uintptr_t)ptr) % align_size; + + if (offset != 0) + ptr += align_size - offset; + + return ptr; +} + +void *raid_malloc(size_t size, void **freeptr) +{ + return raid_malloc_align(size, RAID_MALLOC_ALIGN, freeptr); +} + +void **raid_malloc_vector_align(int nd, int n, size_t size, size_t align_size, size_t displacement_size, void **freeptr) +{ + void **v; + unsigned char *va; + int i; + + BUG_ON(n <= 0 || nd < 0); + + v = malloc(n * sizeof(void *)); + if (!v) { + /* LCOV_EXCL_START */ + return 0; + /* LCOV_EXCL_STOP */ + } + + va = raid_malloc_align(n * (size + displacement_size), align_size, freeptr); + if (!va) { + /* LCOV_EXCL_START */ + free(v); + return 0; + /* LCOV_EXCL_STOP */ + } + + for (i = 0; i < n; ++i) { + v[i] = va; + va += size + displacement_size; + } + + /* reverse order of the data blocks */ + /* because they are usually accessed from the last one */ + for (i = 0; i < nd / 2; ++i) { + void *ptr = v[i]; + + v[i] = v[nd - 1 - i]; + v[nd - 1 - i] = ptr; + } + + return v; +} + +void **raid_malloc_vector(int nd, int n, size_t size, void **freeptr) +{ + return raid_malloc_vector_align(nd, n, size, RAID_MALLOC_ALIGN, RAID_MALLOC_DISPLACEMENT, freeptr); +} + +void raid_mrand_vector(unsigned seed, int n, size_t size, void **vv) +{ + unsigned char **v = (unsigned char **)vv; + int i; + size_t j; + + for (i = 0; i < n; ++i) + for (j = 0; j < size; ++j) { + /* basic C99/C11 linear congruential generator */ + seed = seed * 1103515245U + 12345U; + + v[i][j] = seed >> 16; + } +} + +int raid_mtest_vector(int n, size_t size, void **vv) +{ + unsigned char **v = (unsigned char **)vv; + int i; + size_t j; + unsigned k; + unsigned char d; + unsigned char p; + + /* fill with 0 */ + d = 0; + for (i = 0; i < n; ++i) + for (j = 0; j < size; ++j) + v[i][j] = d; + + /* test with all the byte patterns */ + for (k = 1; k < 256; ++k) { + p = d; + d = k; + + /* forward fill */ + for (i = 0; i < n; ++i) { + for (j = 0; j < size; ++j) { + if (v[i][j] != p) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + v[i][j] = d; + } + } + + p = d; + d = ~p; + /* backward fill with complement */ + for (i = 0; i < n; ++i) { + for (j = size; j > 0; --j) { + if (v[i][j - 1] != p) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + v[i][j - 1] = d; + } + } + } + + return 0; +} + diff --git a/raid/memory.h b/raid/memory.h new file mode 100644 index 0000000..de00614 --- /dev/null +++ b/raid/memory.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 2 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. + */ + +#ifndef __RAID_MEMORY_H +#define __RAID_MEMORY_H + +/** + * Memory alignment provided by raid_malloc(). + * + * It should guarantee good cache performance everywhere. + */ +#define RAID_MALLOC_ALIGN 256 + +/** + * Memory displacement to avoid cache address sharing on contiguous blocks, + * used by raid_malloc_vector(). + * + * When allocating a sequence of blocks with a size of power of 2, + * there is the risk that the addresses of each block are mapped into the + * same cache line and prefetching predictor, resulting in a lot of cache + * sharing if you access all the blocks in parallel, from the start to the + * end. + * + * To avoid this effect, it's better if all the blocks are allocated + * with a fixed displacement trying to reduce the cache addresses sharing. + * + * The selected displacement was chosen empirically with some speed tests + * with 8/12/16/20/24 data buffers of 256 KB. + * + * These are the results in MB/s with no displacement: + * + * sse2 + * gen1 15368 [MB/s] + * gen2 6814 [MB/s] + * genz 3033 [MB/s] + * + * These are the results with displacement resulting in improvments + * in the order of 20% or more: + * + * sse2 + * gen1 21936 [MB/s] + * gen2 11902 [MB/s] + * genz 5838 [MB/s] + * + */ +#define RAID_MALLOC_DISPLACEMENT (7*256) + +/** + * Aligned malloc. + * Use an alignment suitable for the raid functions. + */ +void *raid_malloc(size_t size, void **freeptr); + +/** + * Arbitrary aligned malloc. + */ +void *raid_malloc_align(size_t size, size_t align_size, void **freeptr); + +/** + * Aligned vector allocation. + * Use an alignment suitable for the raid functions. + * Returns a vector of @n pointers, each one pointing to a block of + * the specified @size. + * The first @nd elements are reversed in order. + */ +void **raid_malloc_vector(int nd, int n, size_t size, void **freeptr); + +/** + * Arbitrary aligned vector allocation. + */ +void **raid_malloc_vector_align(int nd, int n, size_t size, size_t align_size, size_t displacement_size, void **freeptr); + +/** + * Fills the memory vector with pseudo-random data based on the specified seed. + */ +void raid_mrand_vector(unsigned seed, int n, size_t size, void **vv); + +/** + * Tests the memory vector for RAM problems. + * If a problem is found, it crashes. + */ +int raid_mtest_vector(int n, size_t size, void **vv); + +#endif + diff --git a/raid/module.c b/raid/module.c new file mode 100644 index 0000000..b688d22 --- /dev/null +++ b/raid/module.c @@ -0,0 +1,473 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 2 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. + */ + +#include "internal.h" +#include "memory.h" +#include "cpu.h" + +/* + * Initializes and selects the best algorithm. + */ +void raid_init(void) +{ + raid_gen3_ptr = raid_gen3_int8; + raid_gen_ptr[3] = raid_gen4_int8; + raid_gen_ptr[4] = raid_gen5_int8; + raid_gen_ptr[5] = raid_gen6_int8; + + if (sizeof(void *) == 4) { + raid_gen_ptr[0] = raid_gen1_int32; + raid_gen_ptr[1] = raid_gen2_int32; + raid_genz_ptr = raid_genz_int32; + } else { + raid_gen_ptr[0] = raid_gen1_int64; + raid_gen_ptr[1] = raid_gen2_int64; + raid_genz_ptr = raid_genz_int64; + } + + raid_rec_ptr[0] = raid_rec1_int8; + raid_rec_ptr[1] = raid_rec2_int8; + raid_rec_ptr[2] = raid_recX_int8; + raid_rec_ptr[3] = raid_recX_int8; + raid_rec_ptr[4] = raid_recX_int8; + raid_rec_ptr[5] = raid_recX_int8; + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSE2 + if (raid_cpu_has_sse2()) { + raid_gen_ptr[0] = raid_gen1_sse2; +#ifdef CONFIG_X86_64 + if (raid_cpu_has_slowextendedreg()) { + raid_gen_ptr[1] = raid_gen2_sse2; + } else { + raid_gen_ptr[1] = raid_gen2_sse2ext; + } + /* note that raid_cpu_has_slowextendedreg() doesn't affect parz */ + raid_genz_ptr = raid_genz_sse2ext; +#else + raid_gen_ptr[1] = raid_gen2_sse2; + raid_genz_ptr = raid_genz_sse2; +#endif + } +#endif + +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) { +#ifdef CONFIG_X86_64 + if (raid_cpu_has_slowextendedreg()) { + raid_gen3_ptr = raid_gen3_ssse3; + raid_gen_ptr[3] = raid_gen4_ssse3; + raid_gen_ptr[4] = raid_gen5_ssse3; + raid_gen_ptr[5] = raid_gen6_ssse3; + } else { + raid_gen3_ptr = raid_gen3_ssse3ext; + raid_gen_ptr[3] = raid_gen4_ssse3ext; + raid_gen_ptr[4] = raid_gen5_ssse3ext; + raid_gen_ptr[5] = raid_gen6_ssse3ext; + } +#else + raid_gen3_ptr = raid_gen3_ssse3; + raid_gen_ptr[3] = raid_gen4_ssse3; + raid_gen_ptr[4] = raid_gen5_ssse3; + raid_gen_ptr[5] = raid_gen6_ssse3; +#endif + raid_rec_ptr[0] = raid_rec1_ssse3; + raid_rec_ptr[1] = raid_rec2_ssse3; + raid_rec_ptr[2] = raid_recX_ssse3; + raid_rec_ptr[3] = raid_recX_ssse3; + raid_rec_ptr[4] = raid_recX_ssse3; + raid_rec_ptr[5] = raid_recX_ssse3; + } +#endif + +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + raid_gen_ptr[0] = raid_gen1_avx2; + raid_gen_ptr[1] = raid_gen2_avx2; +#ifdef CONFIG_X86_64 + raid_gen3_ptr = raid_gen3_avx2ext; + raid_genz_ptr = raid_genz_avx2ext; + raid_gen_ptr[3] = raid_gen4_avx2ext; + raid_gen_ptr[4] = raid_gen5_avx2ext; + raid_gen_ptr[5] = raid_gen6_avx2ext; +#endif + raid_rec_ptr[0] = raid_rec1_avx2; + raid_rec_ptr[1] = raid_rec2_avx2; + raid_rec_ptr[2] = raid_recX_avx2; + raid_rec_ptr[3] = raid_recX_avx2; + raid_rec_ptr[4] = raid_recX_avx2; + raid_rec_ptr[5] = raid_recX_avx2; + } +#endif +#endif /* CONFIG_X86 */ + + /* set the default mode */ + raid_mode(RAID_MODE_CAUCHY); +} + +/* + * Reference parity computation. + */ +void raid_gen_ref(int nd, int np, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + size_t i; + + for (i = 0; i < size; ++i) { + uint8_t p[RAID_PARITY_MAX]; + int j, d; + + for (j = 0; j < np; ++j) + p[j] = 0; + + for (d = 0; d < nd; ++d) { + uint8_t b = v[d][i]; + + for (j = 0; j < np; ++j) + p[j] ^= gfmul[b][gfgen[j][d]]; + } + + for (j = 0; j < np; ++j) + v[nd + j][i] = p[j]; + } +} + +/* + * Size of the blocks to test. + */ +#define TEST_SIZE 4096 + +/* + * Number of data blocks to test. + */ +#define TEST_COUNT (65536 / TEST_SIZE) + +/* + * Parity generation test. + */ +static int raid_test_par(int nd, int np, size_t size, void **v, void **ref) +{ + int i; + void *t[TEST_COUNT + RAID_PARITY_MAX]; + + /* setup data */ + for (i = 0; i < nd; ++i) + t[i] = ref[i]; + + /* setup parity */ + for (i = 0; i < np; ++i) + t[nd + i] = v[nd + i]; + + raid_gen(nd, np, size, t); + + /* compare parity */ + for (i = 0; i < np; ++i) { + if (memcmp(t[nd + i], ref[nd + i], size) != 0) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + } + + return 0; +} + +/* + * Recovering test. + */ +static int raid_test_rec(int nr, int *ir, int nd, int np, size_t size, void **v, void **ref) +{ + int i, j; + void *t[TEST_COUNT + RAID_PARITY_MAX]; + + /* setup data and parity vector */ + for (i = 0, j = 0; i < nd + np; ++i) { + if (j < nr && ir[j] == i) { + /* this block has to be recovered */ + t[i] = v[i]; + ++j; + } else { + /* this block is used for recovering */ + t[i] = ref[i]; + } + } + + raid_rec(nr, ir, nd, np, size, t); + + /* compare all data and parity */ + for (i = 0; i < nd + np; ++i) { + if (t[i] != ref[i] + && memcmp(t[i], ref[i], size) != 0) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + } + + return 0; +} + +/* + * Recovering test for data. + */ +static int raid_test_data(int nr, int *id, int *ip, int nd, int np, size_t size, void **v, void **ref) +{ + int i, j; + void *t[TEST_COUNT + RAID_PARITY_MAX]; + + /* setup data vector */ + for (i = 0, j = 0; i < nd; ++i) { + if (j < nr && id[j] == i) { + /* this block has to be recovered */ + t[i] = v[i]; + ++j; + } else { + /* this block is left unchanged */ + t[i] = ref[i]; + } + } + + /* setup parity vector */ + for (i = 0, j = 0; i < np; ++i) { + if (j < nr && ip[j] == i) { + /* this block is used for recovering */ + t[nd + i] = ref[nd + i]; + ++j; + } else { + /* this block should not be read or written */ + t[nd + i] = 0; + } + } + + raid_data(nr, id, ip, nd, size, t); + + /* compare all data and parity */ + for (i = 0; i < nd; ++i) { + if (t[i] != ref[i] + && t[i] != 0 + && memcmp(t[i], ref[i], size) != 0) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + } + + return 0; +} + +/* + * Scan test. + */ +static int raid_test_scan(int nr, int *ir, int nd, int np, size_t size, void **v, void **ref) +{ + int i, j, ret; + void *t[TEST_COUNT + RAID_PARITY_MAX]; + int is[RAID_PARITY_MAX]; + + /* setup data and parity vector */ + for (i = 0, j = 0; i < nd + np; ++i) { + if (j < nr && ir[j] == i) { + /* this block is bad */ + t[i] = v[i]; + ++j; + } else { + /* this block is used for recovering */ + t[i] = ref[i]; + } + } + + ret = raid_scan(is, nd, np, size, t); + + /* compare identified bad blocks */ + if (ret != nr) + return -1; + for (i = 0; i < nr; ++i) { + if (ir[i] != is[i]) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + } + + return 0; +} + +/* + * Basic functionality self test. + */ +int raid_selftest(void) +{ + const int nd = TEST_COUNT; + const size_t size = TEST_SIZE; + const int nv = nd + RAID_PARITY_MAX * 2 + 1; + void *v_alloc; + void **v; + void *ref[nd + RAID_PARITY_MAX]; + int ir[RAID_PARITY_MAX]; + int ip[RAID_PARITY_MAX]; + int i, np; + int ret = 0; + + /* ensure to have enough space for data */ + BUG_ON(nd * size > 65536); + + v = raid_malloc_vector(nd, nv, size, &v_alloc); + if (!v) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + + memset(v[nv - 1], 0, size); + raid_zero(v[nv - 1]); + + /* use the multiplication table as data */ + for (i = 0; i < nd; ++i) + ref[i] = ((uint8_t *)gfmul) + size * i; + + /* setup reference parity */ + for (i = 0; i < RAID_PARITY_MAX; ++i) + ref[nd + i] = v[nd + RAID_PARITY_MAX + i]; + + /* compute reference parity */ + raid_gen_ref(nd, RAID_PARITY_MAX, size, ref); + + /* test for each parity level */ + for (np = 1; np <= RAID_PARITY_MAX; ++np) { + /* test parity generation */ + ret = raid_test_par(nd, np, size, v, ref); + if (ret != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* test recovering with broken ending data disks */ + for (i = 0; i < np; ++i) { + /* bad data */ + ir[i] = nd - np + i; + + /* good parity */ + ip[i] = i; + } + + ret = raid_test_rec(np, ir, nd, np, size, v, ref); + if (ret != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + ret = raid_test_data(np, ir, ip, nd, np, size, v, ref); + if (ret != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* test recovering with broken leading data and broken leading parity */ + for (i = 0; i < np / 2; ++i) { + /* bad data */ + ir[i] = i; + + /* good parity */ + ip[i] = (np + 1) / 2 + i; + } + + /* bad parity */ + for (i = 0; i < (np + 1) / 2; ++i) + ir[np / 2 + i] = nd + i; + + ret = raid_test_rec(np, ir, nd, np, size, v, ref); + if (ret != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + ret = raid_test_data(np / 2, ir, ip, nd, np, size, v, ref); + if (ret != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* test recovering with broken leading data and broken ending parity */ + for (i = 0; i < np / 2; ++i) { + /* bad data */ + ir[i] = i; + + /* good parity */ + ip[i] = i; + } + + /* bad parity */ + for (i = 0; i < (np + 1) / 2; ++i) + ir[np / 2 + i] = nd + np - (np + 1) / 2 + i; + + ret = raid_test_rec(np, ir, nd, np, size, v, ref); + if (ret != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + ret = raid_test_data(np / 2, ir, ip, nd, np, size, v, ref); + if (ret != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* scan test with broken data and parity */ + for (i = 0; i < np / 2; ++i) { + /* bad data */ + ir[i] = i; + } + for (i = 0; i < (np - 1) / 2; ++i) { + /* bad parity */ + ir[np / 2 + i] = nd + i; + } + for (i = 0; i < np - 1; ++i) { + /* make blocks bad */ + /* we cannot fill them with 0, because the original */ + /* data may be already filled with 0 */ + memset(v[ir[i]], 0x55, size); + } + + ret = raid_test_scan(np - 1, ir, nd, np, size, v, ref); + if (ret != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + } + + /* scan test with no parity */ + ret = raid_test_scan(0, 0, nd, 0, size, v, ref); + if (ret != -1) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + ret = 0; + +bail: + free(v); + free(v_alloc); + + return ret; +} + diff --git a/raid/raid.c b/raid/raid.c new file mode 100644 index 0000000..3052675 --- /dev/null +++ b/raid/raid.c @@ -0,0 +1,586 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 2 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. + */ + +#include "internal.h" +#include "gf.h" + +/* + * This is a RAID implementation working in the Galois Field GF(2^8) with + * the primitive polynomial x^8 + x^4 + x^3 + x^2 + 1 (285 decimal), and + * supporting up to six parity levels. + * + * For RAID5 and RAID6 it works as as described in the H. Peter Anvin's + * paper "The mathematics of RAID-6" [1]. Please refer to this paper for a + * complete explanation. + * + * To support triple parity, it was first evaluated and then dropped, an + * extension of the same approach, with additional parity coefficients set + * as powers of 2^-1, with equations: + * + * P = sum(Di) + * Q = sum(2^i * Di) + * R = sum(2^-i * Di) with 0<=i RAID_PARITY_MAX); + + raid_gen_ptr[np - 1](nd, size, v); +} + +/** + * Inverts the square matrix M of size nxn into V. + * + * This is not a general matrix inversion because we assume the matrix M + * to have all the square submatrix not singular. + * We use Gauss elimination to invert. + * + * @M Matrix to invert with @n rows and @n columns. + * @V Destination matrix where the result is put. + * @n Number of rows and columns of the matrix. + */ +void raid_invert(uint8_t *M, uint8_t *V, int n) +{ + int i, j, k; + + /* set the identity matrix in V */ + for (i = 0; i < n; ++i) + for (j = 0; j < n; ++j) + V[i * n + j] = i == j; + + /* for each element in the diagonal */ + for (k = 0; k < n; ++k) { + uint8_t f; + + /* the diagonal element cannot be 0 because */ + /* we are inverting matrices with all the square */ + /* submatrices not singular */ + BUG_ON(M[k * n + k] == 0); + + /* make the diagonal element to be 1 */ + f = inv(M[k * n + k]); + for (j = 0; j < n; ++j) { + M[k * n + j] = mul(f, M[k * n + j]); + V[k * n + j] = mul(f, V[k * n + j]); + } + + /* make all the elements over and under the diagonal */ + /* to be zero */ + for (i = 0; i < n; ++i) { + if (i == k) + continue; + f = M[i * n + k]; + for (j = 0; j < n; ++j) { + M[i * n + j] ^= mul(f, M[k * n + j]); + V[i * n + j] ^= mul(f, V[k * n + j]); + } + } + } +} + +/** + * Computes the parity without the missing data blocks + * and store it in the buffers of such data blocks. + * + * This is the parity expressed as Pa,Qa,Ra,Sa,Ta,Ua in the equations. + */ +void raid_delta_gen(int nr, int *id, int *ip, int nd, size_t size, void **v) +{ + void *p[RAID_PARITY_MAX]; + void *pa[RAID_PARITY_MAX]; + int i, j; + int np; + void *latest; + + /* total number of parities we are going to process */ + /* they are both the used and the unused ones */ + np = ip[nr - 1] + 1; + + /* latest missing data block */ + latest = v[id[nr - 1]]; + + /* setup pointers for delta computation */ + for (i = 0, j = 0; i < np; ++i) { + /* keep a copy of the original parity vector */ + p[i] = v[nd + i]; + + if (ip[j] == i) { + /* + * Set used parities to point to the missing + * data blocks. + * + * The related data blocks are instead set + * to point to the "zero" buffer. + */ + + /* the latest parity to use ends the for loop and */ + /* then it cannot happen to process more of them */ + BUG_ON(j >= nr); + + /* buffer for missing data blocks */ + pa[j] = v[id[j]]; + + /* set at zero the missing data blocks */ + v[id[j]] = raid_zero_block; + + /* compute the parity over the missing data blocks */ + v[nd + i] = pa[j]; + + /* check for the next used entry */ + ++j; + } else { + /* + * Unused parities are going to be rewritten with + * not significative data, becase we don't have + * functions able to compute only a subset of + * parities. + * + * To avoid this, we reuse parity buffers, + * assuming that all the parity functions write + * parities in order. + * + * We assign the unused parity block to the same + * block of the latest used parity that we know it + * will be written. + * + * This means that this block will be written + * multiple times and only the latest write will + * contain the correct data. + */ + v[nd + i] = latest; + } + } + + /* all the parities have to be processed */ + BUG_ON(j != nr); + + /* recompute the parity, note that np may be smaller than the */ + /* total number of parities available */ + raid_gen(nd, np, size, v); + + /* restore data buffers as before */ + for (j = 0; j < nr; ++j) + v[id[j]] = pa[j]; + + /* restore parity buffers as before */ + for (i = 0; i < np; ++i) + v[nd + i] = p[i]; +} + +/** + * Recover failure of one data block for PAR1. + * + * Starting from the equation: + * + * Pd = Dx + * + * and solving we get: + * + * Dx = Pd + */ +void raid_rec1of1(int *id, int nd, size_t size, void **v) +{ + void *p; + void *pa; + + /* for PAR1 we can directly compute the missing block */ + /* and we don't need to use the zero buffer */ + p = v[nd]; + pa = v[id[0]]; + + /* use the parity as missing data block */ + v[id[0]] = p; + + /* compute the parity over the missing data block */ + v[nd] = pa; + + /* compute */ + raid_gen(nd, 1, size, v); + + /* restore as before */ + v[id[0]] = pa; + v[nd] = p; +} + +/** + * Recover failure of two data blocks for PAR2. + * + * Starting from the equations: + * + * Pd = Dx + Dy + * Qd = 2^id[0] * Dx + 2^id[1] * Dy + * + * and solving we get: + * + * 1 2^(-id[0]) + * Dy = ------------------- * Pd + ------------------- * Qd + * 2^(id[1]-id[0]) + 1 2^(id[1]-id[0]) + 1 + * + * Dx = Dy + Pd + * + * with conditions: + * + * 2^id[0] != 0 + * 2^(id[1]-id[0]) + 1 != 0 + * + * That are always satisfied for any 0<=id[0] np); + BUG_ON(np > RAID_PARITY_MAX); + + /* enforce order in index vector */ + BUG_ON(nr >= 2 && ir[0] >= ir[1]); + BUG_ON(nr >= 3 && ir[1] >= ir[2]); + BUG_ON(nr >= 4 && ir[2] >= ir[3]); + BUG_ON(nr >= 5 && ir[3] >= ir[4]); + BUG_ON(nr >= 6 && ir[4] >= ir[5]); + + /* enforce limit on index vector */ + BUG_ON(nr > 0 && ir[nr-1] >= nd + np); + + /* count the number of data blocks to recover */ + nrd = 0; + while (nrd < nr && ir[nrd] < nd) + ++nrd; + + /* all the remaining are parity */ + nrp = nr - nrd; + + /* enforce limit on number of failures */ + BUG_ON(nrd > nd); + BUG_ON(nrp > np); + + /* if failed data is present */ + if (nrd != 0) { + int ip[RAID_PARITY_MAX]; + int i, j, k; + + /* setup the vector of parities to use */ + for (i = 0, j = 0, k = 0; i < np; ++i) { + if (j < nrp && ir[nrd + j] == nd + i) { + /* this parity has to be recovered */ + ++j; + } else { + /* this parity is used for recovering */ + ip[k] = i; + ++k; + } + } + + /* recover the nrd data blocks specified in ir[], */ + /* using the first nrd parity in ip[] for recovering */ + raid_rec_ptr[nrd - 1](nrd, ir, ip, nd, size, v); + } + + /* recompute all the parities up to the last bad one */ + if (nrp != 0) + raid_gen(nd, ir[nr - 1] - nd + 1, size, v); +} + +void raid_data(int nr, int *id, int *ip, int nd, size_t size, void **v) +{ + /* enforce limit on size */ + BUG_ON(size % 64 != 0); + + /* enforce limit on number of failures */ + BUG_ON(nr > nd); + BUG_ON(nr > RAID_PARITY_MAX); + + /* enforce order in index vector for data */ + BUG_ON(nr >= 2 && id[0] >= id[1]); + BUG_ON(nr >= 3 && id[1] >= id[2]); + BUG_ON(nr >= 4 && id[2] >= id[3]); + BUG_ON(nr >= 5 && id[3] >= id[4]); + BUG_ON(nr >= 6 && id[4] >= id[5]); + + /* enforce limit on index vector for data */ + BUG_ON(nr > 0 && id[nr-1] >= nd); + + /* enforce order in index vector for parity */ + BUG_ON(nr >= 2 && ip[0] >= ip[1]); + BUG_ON(nr >= 3 && ip[1] >= ip[2]); + BUG_ON(nr >= 4 && ip[2] >= ip[3]); + BUG_ON(nr >= 5 && ip[3] >= ip[4]); + BUG_ON(nr >= 6 && ip[4] >= ip[5]); + + /* if failed data is present */ + if (nr != 0) + raid_rec_ptr[nr - 1](nr, id, ip, nd, size, v); +} + diff --git a/raid/raid.h b/raid/raid.h new file mode 100644 index 0000000..aeeb39f --- /dev/null +++ b/raid/raid.h @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 2 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. + */ + +#ifndef __RAID_H +#define __RAID_H + +/** + * RAID mode supporting up to 6 parities. + * + * It requires SSSE3 to get good performance with triple or more parities. + * + * This is the default mode set after calling raid_init(). + */ +#define RAID_MODE_CAUCHY 0 + +/** + * RAID mode supporting up to 3 parities, + * + * It has a fast triple parity implementation without SSSE3, but it cannot + * go beyond triple parity. + * + * This is mostly intended for low end CPUs like ARM and AMD Athlon. + */ +#define RAID_MODE_VANDERMONDE 1 + +/** + * Maximum number of parity disks supported. + */ +#define RAID_PARITY_MAX 6 + +/** + * Maximum number of data disks supported. + */ +#define RAID_DATA_MAX 251 + +/** + * Initializes the RAID system. + * + * You must call this function before any other. + * + * The RAID system is initialized in the RAID_MODE_CAUCHY mode. + */ +void raid_init(void); + +/** + * Runs a basic functionality self test. + * + * The test is immediate, and it's intended to be run at application + * startup to check the integrity of the RAID system. + * + * It returns 0 on success. + */ +int raid_selftest(void); + +/** + * Sets the mode to use. One of RAID_MODE_*. + * + * You can change mode at any time, and it will affect next calls to raid_gen(), + * raid_rec() and raid_data(). + * + * The two modes are compatible for the first two levels of parity. + * The third one is different. + */ +void raid_mode(int mode); + +/** + * Sets the zero buffer to use in recovering. + * + * Before calling raid_rec() and raid_data() you must provide a memory + * buffer filled with zero with the same size of the blocks to recover. + * + * This buffer is only read and never written. + */ +void raid_zero(void *zero); + +/** + * Computes parity blocks. + * + * This function computes the specified number of parity blocks of the + * provided set of data blocks. + * + * Each parity block allows to recover one data block. + * + * @nd Number of data blocks. + * @np Number of parities blocks to compute. + * @size Size of the blocks pointed by @v. It must be a multiplier of 64. + * @v Vector of pointers to the blocks of data and parity. + * It has (@nd + @np) elements. The starting elements are the blocks for + * data, following with the parity blocks. + * Data blocks are only read and not modified. Parity blocks are written. + * Each block has @size bytes. + */ +void raid_gen(int nd, int np, size_t size, void **v); + +/** + * Recovers failures in data and parity blocks. + * + * This function recovers all the data and parity blocks marked as bad + * in the @ir vector. + * + * Ensure to have @nr <= @np, otherwise recovering is not possible. + * + * The parities blocks used for recovering are automatically selected from + * the ones NOT present in the @ir vector. + * + * In case there are more parity blocks than needed, the parities at lower + * indexes are used in the recovering, and the others are ignored. + * + * Note that no internal integrity check is done when recovering. If the + * provided parities are correct, the resulting data will be correct. + * If parities are wrong, the resulting recovered data will be wrong. + * This happens even in the case you have more parities blocks than needed, + * and some form of integrity verification would be possible. + * + * @nr Number of failed data and parity blocks to recover. + * @ir[] Vector of @nr indexes of the failed data and parity blocks. + * The indexes start from 0. They must be in order. + * The first parity is represented with value @nd, the second with value + * @nd + 1, just like positions in the @v vector. + * @nd Number of data blocks. + * @np Number of parity blocks. + * @size Size of the blocks pointed by @v. It must be a multiplier of 64. + * @v Vector of pointers to the blocks of data and parity. + * It has (@nd + @np) elements. The starting elements are the blocks + * for data, following with the parity blocks. + * Each block has @size bytes. + */ +void raid_rec(int nr, int *ir, int nd, int np, size_t size, void **v); + +/** + * Recovers failures in data blocks only. + * + * This function recovers all the data blocks marked as bad in the @id vector. + * The parity blocks are not modified. + * + * @nr Number of failed data blocks to recover. + * @id[] Vector of @nr indexes of the data blocks to recover. + * The indexes start from 0. They must be in order. + * @ip[] Vector of @nr indexes of the parity blocks to use for recovering. + * The indexes start from 0. They must be in order. + * @nd Number of data blocks. + * @size Size of the blocks pointed by @v. It must be a multiplier of 64. + * @v Vector of pointers to the blocks of data and parity. + * It has (@nd + @ip[@nr - 1] + 1) elements. The starting elements are the + * blocks for data, following with the parity blocks. + * Each blocks has @size bytes. + */ +void raid_data(int nr, int *id, int *ip, int nd, size_t size, void **v); + +/** + * Check the provided failed blocks combination. + * + * This function checks if the specified failed blocks combination satisfies + * the redundancy information. A combination is assumed matching, if the + * remaining valid parity is matching the expected value after recovering. + * + * The number of failed blocks @nr must be strictly less than the number of + * parities @np, because you need one more parity to validate the recovering. + * + * No data or parity blocks are modified. + * + * @nr Number of failed data and parity blocks. + * @ir[] Vector of @nr indexes of the failed data and parity blocks. + * The indexes start from 0. They must be in order. + * The first parity is represented with value @nd, the second with value + * @nd + 1, just like positions in the @v vector. + * @nd Number of data blocks. + * @np Number of parity blocks. + * @size Size of the blocks pointed by @v. It must be a multiplier of 64. + * @v Vector of pointers to the blocks of data and parity. + * It has (@nd + @np) elements. The starting elements are the blocks + * for data, following with the parity blocks. + * Each block has @size bytes. + * @return 0 if the check is satisfied. -1 otherwise. + */ +int raid_check(int nr, int *ir, int nd, int np, size_t size, void **v); + +/** + * Scan for failed blocks. + * + * This function identifies the failed data and parity blocks using the + * available redundancy. + * + * It uses a brute force method, and then the call can be expansive. + * The expected execution time is proportional at the binomial coefficient + * @np + @nd choose @np - 1, usually written as: + * + * ( @np + @nd ) + * ( ) + * ( @np - 1 ) + * + * No data or parity blocks are modified. + * + * The failed block indexes are returned in the @ir vector. + * It must have space for at least @np - 1 values. + * + * The returned @ir vector can then be used in a raid_rec() call to recover + * the failed data and parity blocks. + * + * @ir[] Vector filled with the indexes of the failed data and parity blocks. + * The indexes start from 0 and they are in order. + * The first parity is represented with value @nd, the second with value + * @nd + 1, just like positions in the @v vector. + * @nd Number of data blocks. + * @np Number of parity blocks. + * @size Size of the blocks pointed by @v. It must be a multiplier of 64. + * @v Vector of pointers to the blocks of data and parity. + * It has (@nd + @np) elements. The starting elements are the blocks + * for data, following with the parity blocks. + * Each block has @size bytes. + * @return Number of block indexes returned in the @ir vector. + * 0 if no error is detected. + * -1 if it's not possible to identify the failed disks. + */ +int raid_scan(int *ir, int nd, int np, size_t size, void **v); + +#endif + diff --git a/raid/tables.c b/raid/tables.c new file mode 100644 index 0000000..4903502 --- /dev/null +++ b/raid/tables.c @@ -0,0 +1,14696 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 2 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. + */ + +#include "internal.h" + +const uint8_t __aligned(256) raid_gfmul[256][256] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }, + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + }, + { + 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, + 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, + 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, + 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, + 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, + 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, + 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, + 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, + 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, + 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, + 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, + 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, + 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, + 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, + 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, + 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, + 0x1d, 0x1f, 0x19, 0x1b, 0x15, 0x17, 0x11, 0x13, + 0x0d, 0x0f, 0x09, 0x0b, 0x05, 0x07, 0x01, 0x03, + 0x3d, 0x3f, 0x39, 0x3b, 0x35, 0x37, 0x31, 0x33, + 0x2d, 0x2f, 0x29, 0x2b, 0x25, 0x27, 0x21, 0x23, + 0x5d, 0x5f, 0x59, 0x5b, 0x55, 0x57, 0x51, 0x53, + 0x4d, 0x4f, 0x49, 0x4b, 0x45, 0x47, 0x41, 0x43, + 0x7d, 0x7f, 0x79, 0x7b, 0x75, 0x77, 0x71, 0x73, + 0x6d, 0x6f, 0x69, 0x6b, 0x65, 0x67, 0x61, 0x63, + 0x9d, 0x9f, 0x99, 0x9b, 0x95, 0x97, 0x91, 0x93, + 0x8d, 0x8f, 0x89, 0x8b, 0x85, 0x87, 0x81, 0x83, + 0xbd, 0xbf, 0xb9, 0xbb, 0xb5, 0xb7, 0xb1, 0xb3, + 0xad, 0xaf, 0xa9, 0xab, 0xa5, 0xa7, 0xa1, 0xa3, + 0xdd, 0xdf, 0xd9, 0xdb, 0xd5, 0xd7, 0xd1, 0xd3, + 0xcd, 0xcf, 0xc9, 0xcb, 0xc5, 0xc7, 0xc1, 0xc3, + 0xfd, 0xff, 0xf9, 0xfb, 0xf5, 0xf7, 0xf1, 0xf3, + 0xed, 0xef, 0xe9, 0xeb, 0xe5, 0xe7, 0xe1, 0xe3, + }, + { + 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, + 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11, + 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, + 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21, + 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, + 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71, + 0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, + 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41, + 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, + 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1, + 0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, + 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1, + 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, + 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1, + 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, + 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81, + 0x9d, 0x9e, 0x9b, 0x98, 0x91, 0x92, 0x97, 0x94, + 0x85, 0x86, 0x83, 0x80, 0x89, 0x8a, 0x8f, 0x8c, + 0xad, 0xae, 0xab, 0xa8, 0xa1, 0xa2, 0xa7, 0xa4, + 0xb5, 0xb6, 0xb3, 0xb0, 0xb9, 0xba, 0xbf, 0xbc, + 0xfd, 0xfe, 0xfb, 0xf8, 0xf1, 0xf2, 0xf7, 0xf4, + 0xe5, 0xe6, 0xe3, 0xe0, 0xe9, 0xea, 0xef, 0xec, + 0xcd, 0xce, 0xcb, 0xc8, 0xc1, 0xc2, 0xc7, 0xc4, + 0xd5, 0xd6, 0xd3, 0xd0, 0xd9, 0xda, 0xdf, 0xdc, + 0x5d, 0x5e, 0x5b, 0x58, 0x51, 0x52, 0x57, 0x54, + 0x45, 0x46, 0x43, 0x40, 0x49, 0x4a, 0x4f, 0x4c, + 0x6d, 0x6e, 0x6b, 0x68, 0x61, 0x62, 0x67, 0x64, + 0x75, 0x76, 0x73, 0x70, 0x79, 0x7a, 0x7f, 0x7c, + 0x3d, 0x3e, 0x3b, 0x38, 0x31, 0x32, 0x37, 0x34, + 0x25, 0x26, 0x23, 0x20, 0x29, 0x2a, 0x2f, 0x2c, + 0x0d, 0x0e, 0x0b, 0x08, 0x01, 0x02, 0x07, 0x04, + 0x15, 0x16, 0x13, 0x10, 0x19, 0x1a, 0x1f, 0x1c, + }, + { + 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, + 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c, + 0x40, 0x44, 0x48, 0x4c, 0x50, 0x54, 0x58, 0x5c, + 0x60, 0x64, 0x68, 0x6c, 0x70, 0x74, 0x78, 0x7c, + 0x80, 0x84, 0x88, 0x8c, 0x90, 0x94, 0x98, 0x9c, + 0xa0, 0xa4, 0xa8, 0xac, 0xb0, 0xb4, 0xb8, 0xbc, + 0xc0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4, 0xd8, 0xdc, + 0xe0, 0xe4, 0xe8, 0xec, 0xf0, 0xf4, 0xf8, 0xfc, + 0x1d, 0x19, 0x15, 0x11, 0x0d, 0x09, 0x05, 0x01, + 0x3d, 0x39, 0x35, 0x31, 0x2d, 0x29, 0x25, 0x21, + 0x5d, 0x59, 0x55, 0x51, 0x4d, 0x49, 0x45, 0x41, + 0x7d, 0x79, 0x75, 0x71, 0x6d, 0x69, 0x65, 0x61, + 0x9d, 0x99, 0x95, 0x91, 0x8d, 0x89, 0x85, 0x81, + 0xbd, 0xb9, 0xb5, 0xb1, 0xad, 0xa9, 0xa5, 0xa1, + 0xdd, 0xd9, 0xd5, 0xd1, 0xcd, 0xc9, 0xc5, 0xc1, + 0xfd, 0xf9, 0xf5, 0xf1, 0xed, 0xe9, 0xe5, 0xe1, + 0x3a, 0x3e, 0x32, 0x36, 0x2a, 0x2e, 0x22, 0x26, + 0x1a, 0x1e, 0x12, 0x16, 0x0a, 0x0e, 0x02, 0x06, + 0x7a, 0x7e, 0x72, 0x76, 0x6a, 0x6e, 0x62, 0x66, + 0x5a, 0x5e, 0x52, 0x56, 0x4a, 0x4e, 0x42, 0x46, + 0xba, 0xbe, 0xb2, 0xb6, 0xaa, 0xae, 0xa2, 0xa6, + 0x9a, 0x9e, 0x92, 0x96, 0x8a, 0x8e, 0x82, 0x86, + 0xfa, 0xfe, 0xf2, 0xf6, 0xea, 0xee, 0xe2, 0xe6, + 0xda, 0xde, 0xd2, 0xd6, 0xca, 0xce, 0xc2, 0xc6, + 0x27, 0x23, 0x2f, 0x2b, 0x37, 0x33, 0x3f, 0x3b, + 0x07, 0x03, 0x0f, 0x0b, 0x17, 0x13, 0x1f, 0x1b, + 0x67, 0x63, 0x6f, 0x6b, 0x77, 0x73, 0x7f, 0x7b, + 0x47, 0x43, 0x4f, 0x4b, 0x57, 0x53, 0x5f, 0x5b, + 0xa7, 0xa3, 0xaf, 0xab, 0xb7, 0xb3, 0xbf, 0xbb, + 0x87, 0x83, 0x8f, 0x8b, 0x97, 0x93, 0x9f, 0x9b, + 0xe7, 0xe3, 0xef, 0xeb, 0xf7, 0xf3, 0xff, 0xfb, + 0xc7, 0xc3, 0xcf, 0xcb, 0xd7, 0xd3, 0xdf, 0xdb, + }, + { + 0x00, 0x05, 0x0a, 0x0f, 0x14, 0x11, 0x1e, 0x1b, + 0x28, 0x2d, 0x22, 0x27, 0x3c, 0x39, 0x36, 0x33, + 0x50, 0x55, 0x5a, 0x5f, 0x44, 0x41, 0x4e, 0x4b, + 0x78, 0x7d, 0x72, 0x77, 0x6c, 0x69, 0x66, 0x63, + 0xa0, 0xa5, 0xaa, 0xaf, 0xb4, 0xb1, 0xbe, 0xbb, + 0x88, 0x8d, 0x82, 0x87, 0x9c, 0x99, 0x96, 0x93, + 0xf0, 0xf5, 0xfa, 0xff, 0xe4, 0xe1, 0xee, 0xeb, + 0xd8, 0xdd, 0xd2, 0xd7, 0xcc, 0xc9, 0xc6, 0xc3, + 0x5d, 0x58, 0x57, 0x52, 0x49, 0x4c, 0x43, 0x46, + 0x75, 0x70, 0x7f, 0x7a, 0x61, 0x64, 0x6b, 0x6e, + 0x0d, 0x08, 0x07, 0x02, 0x19, 0x1c, 0x13, 0x16, + 0x25, 0x20, 0x2f, 0x2a, 0x31, 0x34, 0x3b, 0x3e, + 0xfd, 0xf8, 0xf7, 0xf2, 0xe9, 0xec, 0xe3, 0xe6, + 0xd5, 0xd0, 0xdf, 0xda, 0xc1, 0xc4, 0xcb, 0xce, + 0xad, 0xa8, 0xa7, 0xa2, 0xb9, 0xbc, 0xb3, 0xb6, + 0x85, 0x80, 0x8f, 0x8a, 0x91, 0x94, 0x9b, 0x9e, + 0xba, 0xbf, 0xb0, 0xb5, 0xae, 0xab, 0xa4, 0xa1, + 0x92, 0x97, 0x98, 0x9d, 0x86, 0x83, 0x8c, 0x89, + 0xea, 0xef, 0xe0, 0xe5, 0xfe, 0xfb, 0xf4, 0xf1, + 0xc2, 0xc7, 0xc8, 0xcd, 0xd6, 0xd3, 0xdc, 0xd9, + 0x1a, 0x1f, 0x10, 0x15, 0x0e, 0x0b, 0x04, 0x01, + 0x32, 0x37, 0x38, 0x3d, 0x26, 0x23, 0x2c, 0x29, + 0x4a, 0x4f, 0x40, 0x45, 0x5e, 0x5b, 0x54, 0x51, + 0x62, 0x67, 0x68, 0x6d, 0x76, 0x73, 0x7c, 0x79, + 0xe7, 0xe2, 0xed, 0xe8, 0xf3, 0xf6, 0xf9, 0xfc, + 0xcf, 0xca, 0xc5, 0xc0, 0xdb, 0xde, 0xd1, 0xd4, + 0xb7, 0xb2, 0xbd, 0xb8, 0xa3, 0xa6, 0xa9, 0xac, + 0x9f, 0x9a, 0x95, 0x90, 0x8b, 0x8e, 0x81, 0x84, + 0x47, 0x42, 0x4d, 0x48, 0x53, 0x56, 0x59, 0x5c, + 0x6f, 0x6a, 0x65, 0x60, 0x7b, 0x7e, 0x71, 0x74, + 0x17, 0x12, 0x1d, 0x18, 0x03, 0x06, 0x09, 0x0c, + 0x3f, 0x3a, 0x35, 0x30, 0x2b, 0x2e, 0x21, 0x24, + }, + { + 0x00, 0x06, 0x0c, 0x0a, 0x18, 0x1e, 0x14, 0x12, + 0x30, 0x36, 0x3c, 0x3a, 0x28, 0x2e, 0x24, 0x22, + 0x60, 0x66, 0x6c, 0x6a, 0x78, 0x7e, 0x74, 0x72, + 0x50, 0x56, 0x5c, 0x5a, 0x48, 0x4e, 0x44, 0x42, + 0xc0, 0xc6, 0xcc, 0xca, 0xd8, 0xde, 0xd4, 0xd2, + 0xf0, 0xf6, 0xfc, 0xfa, 0xe8, 0xee, 0xe4, 0xe2, + 0xa0, 0xa6, 0xac, 0xaa, 0xb8, 0xbe, 0xb4, 0xb2, + 0x90, 0x96, 0x9c, 0x9a, 0x88, 0x8e, 0x84, 0x82, + 0x9d, 0x9b, 0x91, 0x97, 0x85, 0x83, 0x89, 0x8f, + 0xad, 0xab, 0xa1, 0xa7, 0xb5, 0xb3, 0xb9, 0xbf, + 0xfd, 0xfb, 0xf1, 0xf7, 0xe5, 0xe3, 0xe9, 0xef, + 0xcd, 0xcb, 0xc1, 0xc7, 0xd5, 0xd3, 0xd9, 0xdf, + 0x5d, 0x5b, 0x51, 0x57, 0x45, 0x43, 0x49, 0x4f, + 0x6d, 0x6b, 0x61, 0x67, 0x75, 0x73, 0x79, 0x7f, + 0x3d, 0x3b, 0x31, 0x37, 0x25, 0x23, 0x29, 0x2f, + 0x0d, 0x0b, 0x01, 0x07, 0x15, 0x13, 0x19, 0x1f, + 0x27, 0x21, 0x2b, 0x2d, 0x3f, 0x39, 0x33, 0x35, + 0x17, 0x11, 0x1b, 0x1d, 0x0f, 0x09, 0x03, 0x05, + 0x47, 0x41, 0x4b, 0x4d, 0x5f, 0x59, 0x53, 0x55, + 0x77, 0x71, 0x7b, 0x7d, 0x6f, 0x69, 0x63, 0x65, + 0xe7, 0xe1, 0xeb, 0xed, 0xff, 0xf9, 0xf3, 0xf5, + 0xd7, 0xd1, 0xdb, 0xdd, 0xcf, 0xc9, 0xc3, 0xc5, + 0x87, 0x81, 0x8b, 0x8d, 0x9f, 0x99, 0x93, 0x95, + 0xb7, 0xb1, 0xbb, 0xbd, 0xaf, 0xa9, 0xa3, 0xa5, + 0xba, 0xbc, 0xb6, 0xb0, 0xa2, 0xa4, 0xae, 0xa8, + 0x8a, 0x8c, 0x86, 0x80, 0x92, 0x94, 0x9e, 0x98, + 0xda, 0xdc, 0xd6, 0xd0, 0xc2, 0xc4, 0xce, 0xc8, + 0xea, 0xec, 0xe6, 0xe0, 0xf2, 0xf4, 0xfe, 0xf8, + 0x7a, 0x7c, 0x76, 0x70, 0x62, 0x64, 0x6e, 0x68, + 0x4a, 0x4c, 0x46, 0x40, 0x52, 0x54, 0x5e, 0x58, + 0x1a, 0x1c, 0x16, 0x10, 0x02, 0x04, 0x0e, 0x08, + 0x2a, 0x2c, 0x26, 0x20, 0x32, 0x34, 0x3e, 0x38, + }, + { + 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, + 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, + 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, + 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, + 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, + 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, + 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, + 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, + 0xdd, 0xda, 0xd3, 0xd4, 0xc1, 0xc6, 0xcf, 0xc8, + 0xe5, 0xe2, 0xeb, 0xec, 0xf9, 0xfe, 0xf7, 0xf0, + 0xad, 0xaa, 0xa3, 0xa4, 0xb1, 0xb6, 0xbf, 0xb8, + 0x95, 0x92, 0x9b, 0x9c, 0x89, 0x8e, 0x87, 0x80, + 0x3d, 0x3a, 0x33, 0x34, 0x21, 0x26, 0x2f, 0x28, + 0x05, 0x02, 0x0b, 0x0c, 0x19, 0x1e, 0x17, 0x10, + 0x4d, 0x4a, 0x43, 0x44, 0x51, 0x56, 0x5f, 0x58, + 0x75, 0x72, 0x7b, 0x7c, 0x69, 0x6e, 0x67, 0x60, + 0xa7, 0xa0, 0xa9, 0xae, 0xbb, 0xbc, 0xb5, 0xb2, + 0x9f, 0x98, 0x91, 0x96, 0x83, 0x84, 0x8d, 0x8a, + 0xd7, 0xd0, 0xd9, 0xde, 0xcb, 0xcc, 0xc5, 0xc2, + 0xef, 0xe8, 0xe1, 0xe6, 0xf3, 0xf4, 0xfd, 0xfa, + 0x47, 0x40, 0x49, 0x4e, 0x5b, 0x5c, 0x55, 0x52, + 0x7f, 0x78, 0x71, 0x76, 0x63, 0x64, 0x6d, 0x6a, + 0x37, 0x30, 0x39, 0x3e, 0x2b, 0x2c, 0x25, 0x22, + 0x0f, 0x08, 0x01, 0x06, 0x13, 0x14, 0x1d, 0x1a, + 0x7a, 0x7d, 0x74, 0x73, 0x66, 0x61, 0x68, 0x6f, + 0x42, 0x45, 0x4c, 0x4b, 0x5e, 0x59, 0x50, 0x57, + 0x0a, 0x0d, 0x04, 0x03, 0x16, 0x11, 0x18, 0x1f, + 0x32, 0x35, 0x3c, 0x3b, 0x2e, 0x29, 0x20, 0x27, + 0x9a, 0x9d, 0x94, 0x93, 0x86, 0x81, 0x88, 0x8f, + 0xa2, 0xa5, 0xac, 0xab, 0xbe, 0xb9, 0xb0, 0xb7, + 0xea, 0xed, 0xe4, 0xe3, 0xf6, 0xf1, 0xf8, 0xff, + 0xd2, 0xd5, 0xdc, 0xdb, 0xce, 0xc9, 0xc0, 0xc7, + }, + { + 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, + 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78, + 0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8, + 0xc0, 0xc8, 0xd0, 0xd8, 0xe0, 0xe8, 0xf0, 0xf8, + 0x1d, 0x15, 0x0d, 0x05, 0x3d, 0x35, 0x2d, 0x25, + 0x5d, 0x55, 0x4d, 0x45, 0x7d, 0x75, 0x6d, 0x65, + 0x9d, 0x95, 0x8d, 0x85, 0xbd, 0xb5, 0xad, 0xa5, + 0xdd, 0xd5, 0xcd, 0xc5, 0xfd, 0xf5, 0xed, 0xe5, + 0x3a, 0x32, 0x2a, 0x22, 0x1a, 0x12, 0x0a, 0x02, + 0x7a, 0x72, 0x6a, 0x62, 0x5a, 0x52, 0x4a, 0x42, + 0xba, 0xb2, 0xaa, 0xa2, 0x9a, 0x92, 0x8a, 0x82, + 0xfa, 0xf2, 0xea, 0xe2, 0xda, 0xd2, 0xca, 0xc2, + 0x27, 0x2f, 0x37, 0x3f, 0x07, 0x0f, 0x17, 0x1f, + 0x67, 0x6f, 0x77, 0x7f, 0x47, 0x4f, 0x57, 0x5f, + 0xa7, 0xaf, 0xb7, 0xbf, 0x87, 0x8f, 0x97, 0x9f, + 0xe7, 0xef, 0xf7, 0xff, 0xc7, 0xcf, 0xd7, 0xdf, + 0x74, 0x7c, 0x64, 0x6c, 0x54, 0x5c, 0x44, 0x4c, + 0x34, 0x3c, 0x24, 0x2c, 0x14, 0x1c, 0x04, 0x0c, + 0xf4, 0xfc, 0xe4, 0xec, 0xd4, 0xdc, 0xc4, 0xcc, + 0xb4, 0xbc, 0xa4, 0xac, 0x94, 0x9c, 0x84, 0x8c, + 0x69, 0x61, 0x79, 0x71, 0x49, 0x41, 0x59, 0x51, + 0x29, 0x21, 0x39, 0x31, 0x09, 0x01, 0x19, 0x11, + 0xe9, 0xe1, 0xf9, 0xf1, 0xc9, 0xc1, 0xd9, 0xd1, + 0xa9, 0xa1, 0xb9, 0xb1, 0x89, 0x81, 0x99, 0x91, + 0x4e, 0x46, 0x5e, 0x56, 0x6e, 0x66, 0x7e, 0x76, + 0x0e, 0x06, 0x1e, 0x16, 0x2e, 0x26, 0x3e, 0x36, + 0xce, 0xc6, 0xde, 0xd6, 0xee, 0xe6, 0xfe, 0xf6, + 0x8e, 0x86, 0x9e, 0x96, 0xae, 0xa6, 0xbe, 0xb6, + 0x53, 0x5b, 0x43, 0x4b, 0x73, 0x7b, 0x63, 0x6b, + 0x13, 0x1b, 0x03, 0x0b, 0x33, 0x3b, 0x23, 0x2b, + 0xd3, 0xdb, 0xc3, 0xcb, 0xf3, 0xfb, 0xe3, 0xeb, + 0x93, 0x9b, 0x83, 0x8b, 0xb3, 0xbb, 0xa3, 0xab, + }, + { + 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, + 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, + 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, + 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, + 0x3d, 0x34, 0x2f, 0x26, 0x19, 0x10, 0x0b, 0x02, + 0x75, 0x7c, 0x67, 0x6e, 0x51, 0x58, 0x43, 0x4a, + 0xad, 0xa4, 0xbf, 0xb6, 0x89, 0x80, 0x9b, 0x92, + 0xe5, 0xec, 0xf7, 0xfe, 0xc1, 0xc8, 0xd3, 0xda, + 0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45, + 0x32, 0x3b, 0x20, 0x29, 0x16, 0x1f, 0x04, 0x0d, + 0xea, 0xe3, 0xf8, 0xf1, 0xce, 0xc7, 0xdc, 0xd5, + 0xa2, 0xab, 0xb0, 0xb9, 0x86, 0x8f, 0x94, 0x9d, + 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, + 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30, + 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, + 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0, + 0xf4, 0xfd, 0xe6, 0xef, 0xd0, 0xd9, 0xc2, 0xcb, + 0xbc, 0xb5, 0xae, 0xa7, 0x98, 0x91, 0x8a, 0x83, + 0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b, + 0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13, + 0xc9, 0xc0, 0xdb, 0xd2, 0xed, 0xe4, 0xff, 0xf6, + 0x81, 0x88, 0x93, 0x9a, 0xa5, 0xac, 0xb7, 0xbe, + 0x59, 0x50, 0x4b, 0x42, 0x7d, 0x74, 0x6f, 0x66, + 0x11, 0x18, 0x03, 0x0a, 0x35, 0x3c, 0x27, 0x2e, + 0x8e, 0x87, 0x9c, 0x95, 0xaa, 0xa3, 0xb8, 0xb1, + 0xc6, 0xcf, 0xd4, 0xdd, 0xe2, 0xeb, 0xf0, 0xf9, + 0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21, + 0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69, + 0xb3, 0xba, 0xa1, 0xa8, 0x97, 0x9e, 0x85, 0x8c, + 0xfb, 0xf2, 0xe9, 0xe0, 0xdf, 0xd6, 0xcd, 0xc4, + 0x23, 0x2a, 0x31, 0x38, 0x07, 0x0e, 0x15, 0x1c, + 0x6b, 0x62, 0x79, 0x70, 0x4f, 0x46, 0x5d, 0x54, + }, + { + 0x00, 0x0a, 0x14, 0x1e, 0x28, 0x22, 0x3c, 0x36, + 0x50, 0x5a, 0x44, 0x4e, 0x78, 0x72, 0x6c, 0x66, + 0xa0, 0xaa, 0xb4, 0xbe, 0x88, 0x82, 0x9c, 0x96, + 0xf0, 0xfa, 0xe4, 0xee, 0xd8, 0xd2, 0xcc, 0xc6, + 0x5d, 0x57, 0x49, 0x43, 0x75, 0x7f, 0x61, 0x6b, + 0x0d, 0x07, 0x19, 0x13, 0x25, 0x2f, 0x31, 0x3b, + 0xfd, 0xf7, 0xe9, 0xe3, 0xd5, 0xdf, 0xc1, 0xcb, + 0xad, 0xa7, 0xb9, 0xb3, 0x85, 0x8f, 0x91, 0x9b, + 0xba, 0xb0, 0xae, 0xa4, 0x92, 0x98, 0x86, 0x8c, + 0xea, 0xe0, 0xfe, 0xf4, 0xc2, 0xc8, 0xd6, 0xdc, + 0x1a, 0x10, 0x0e, 0x04, 0x32, 0x38, 0x26, 0x2c, + 0x4a, 0x40, 0x5e, 0x54, 0x62, 0x68, 0x76, 0x7c, + 0xe7, 0xed, 0xf3, 0xf9, 0xcf, 0xc5, 0xdb, 0xd1, + 0xb7, 0xbd, 0xa3, 0xa9, 0x9f, 0x95, 0x8b, 0x81, + 0x47, 0x4d, 0x53, 0x59, 0x6f, 0x65, 0x7b, 0x71, + 0x17, 0x1d, 0x03, 0x09, 0x3f, 0x35, 0x2b, 0x21, + 0x69, 0x63, 0x7d, 0x77, 0x41, 0x4b, 0x55, 0x5f, + 0x39, 0x33, 0x2d, 0x27, 0x11, 0x1b, 0x05, 0x0f, + 0xc9, 0xc3, 0xdd, 0xd7, 0xe1, 0xeb, 0xf5, 0xff, + 0x99, 0x93, 0x8d, 0x87, 0xb1, 0xbb, 0xa5, 0xaf, + 0x34, 0x3e, 0x20, 0x2a, 0x1c, 0x16, 0x08, 0x02, + 0x64, 0x6e, 0x70, 0x7a, 0x4c, 0x46, 0x58, 0x52, + 0x94, 0x9e, 0x80, 0x8a, 0xbc, 0xb6, 0xa8, 0xa2, + 0xc4, 0xce, 0xd0, 0xda, 0xec, 0xe6, 0xf8, 0xf2, + 0xd3, 0xd9, 0xc7, 0xcd, 0xfb, 0xf1, 0xef, 0xe5, + 0x83, 0x89, 0x97, 0x9d, 0xab, 0xa1, 0xbf, 0xb5, + 0x73, 0x79, 0x67, 0x6d, 0x5b, 0x51, 0x4f, 0x45, + 0x23, 0x29, 0x37, 0x3d, 0x0b, 0x01, 0x1f, 0x15, + 0x8e, 0x84, 0x9a, 0x90, 0xa6, 0xac, 0xb2, 0xb8, + 0xde, 0xd4, 0xca, 0xc0, 0xf6, 0xfc, 0xe2, 0xe8, + 0x2e, 0x24, 0x3a, 0x30, 0x06, 0x0c, 0x12, 0x18, + 0x7e, 0x74, 0x6a, 0x60, 0x56, 0x5c, 0x42, 0x48, + }, + { + 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, + 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69, + 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, + 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, + 0x7d, 0x76, 0x6b, 0x60, 0x51, 0x5a, 0x47, 0x4c, + 0x25, 0x2e, 0x33, 0x38, 0x09, 0x02, 0x1f, 0x14, + 0xcd, 0xc6, 0xdb, 0xd0, 0xe1, 0xea, 0xf7, 0xfc, + 0x95, 0x9e, 0x83, 0x88, 0xb9, 0xb2, 0xaf, 0xa4, + 0xfa, 0xf1, 0xec, 0xe7, 0xd6, 0xdd, 0xc0, 0xcb, + 0xa2, 0xa9, 0xb4, 0xbf, 0x8e, 0x85, 0x98, 0x93, + 0x4a, 0x41, 0x5c, 0x57, 0x66, 0x6d, 0x70, 0x7b, + 0x12, 0x19, 0x04, 0x0f, 0x3e, 0x35, 0x28, 0x23, + 0x87, 0x8c, 0x91, 0x9a, 0xab, 0xa0, 0xbd, 0xb6, + 0xdf, 0xd4, 0xc9, 0xc2, 0xf3, 0xf8, 0xe5, 0xee, + 0x37, 0x3c, 0x21, 0x2a, 0x1b, 0x10, 0x0d, 0x06, + 0x6f, 0x64, 0x79, 0x72, 0x43, 0x48, 0x55, 0x5e, + 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8, + 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, + 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68, + 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, + 0x94, 0x9f, 0x82, 0x89, 0xb8, 0xb3, 0xae, 0xa5, + 0xcc, 0xc7, 0xda, 0xd1, 0xe0, 0xeb, 0xf6, 0xfd, + 0x24, 0x2f, 0x32, 0x39, 0x08, 0x03, 0x1e, 0x15, + 0x7c, 0x77, 0x6a, 0x61, 0x50, 0x5b, 0x46, 0x4d, + 0x13, 0x18, 0x05, 0x0e, 0x3f, 0x34, 0x29, 0x22, + 0x4b, 0x40, 0x5d, 0x56, 0x67, 0x6c, 0x71, 0x7a, + 0xa3, 0xa8, 0xb5, 0xbe, 0x8f, 0x84, 0x99, 0x92, + 0xfb, 0xf0, 0xed, 0xe6, 0xd7, 0xdc, 0xc1, 0xca, + 0x6e, 0x65, 0x78, 0x73, 0x42, 0x49, 0x54, 0x5f, + 0x36, 0x3d, 0x20, 0x2b, 0x1a, 0x11, 0x0c, 0x07, + 0xde, 0xd5, 0xc8, 0xc3, 0xf2, 0xf9, 0xe4, 0xef, + 0x86, 0x8d, 0x90, 0x9b, 0xaa, 0xa1, 0xbc, 0xb7, + }, + { + 0x00, 0x0c, 0x18, 0x14, 0x30, 0x3c, 0x28, 0x24, + 0x60, 0x6c, 0x78, 0x74, 0x50, 0x5c, 0x48, 0x44, + 0xc0, 0xcc, 0xd8, 0xd4, 0xf0, 0xfc, 0xe8, 0xe4, + 0xa0, 0xac, 0xb8, 0xb4, 0x90, 0x9c, 0x88, 0x84, + 0x9d, 0x91, 0x85, 0x89, 0xad, 0xa1, 0xb5, 0xb9, + 0xfd, 0xf1, 0xe5, 0xe9, 0xcd, 0xc1, 0xd5, 0xd9, + 0x5d, 0x51, 0x45, 0x49, 0x6d, 0x61, 0x75, 0x79, + 0x3d, 0x31, 0x25, 0x29, 0x0d, 0x01, 0x15, 0x19, + 0x27, 0x2b, 0x3f, 0x33, 0x17, 0x1b, 0x0f, 0x03, + 0x47, 0x4b, 0x5f, 0x53, 0x77, 0x7b, 0x6f, 0x63, + 0xe7, 0xeb, 0xff, 0xf3, 0xd7, 0xdb, 0xcf, 0xc3, + 0x87, 0x8b, 0x9f, 0x93, 0xb7, 0xbb, 0xaf, 0xa3, + 0xba, 0xb6, 0xa2, 0xae, 0x8a, 0x86, 0x92, 0x9e, + 0xda, 0xd6, 0xc2, 0xce, 0xea, 0xe6, 0xf2, 0xfe, + 0x7a, 0x76, 0x62, 0x6e, 0x4a, 0x46, 0x52, 0x5e, + 0x1a, 0x16, 0x02, 0x0e, 0x2a, 0x26, 0x32, 0x3e, + 0x4e, 0x42, 0x56, 0x5a, 0x7e, 0x72, 0x66, 0x6a, + 0x2e, 0x22, 0x36, 0x3a, 0x1e, 0x12, 0x06, 0x0a, + 0x8e, 0x82, 0x96, 0x9a, 0xbe, 0xb2, 0xa6, 0xaa, + 0xee, 0xe2, 0xf6, 0xfa, 0xde, 0xd2, 0xc6, 0xca, + 0xd3, 0xdf, 0xcb, 0xc7, 0xe3, 0xef, 0xfb, 0xf7, + 0xb3, 0xbf, 0xab, 0xa7, 0x83, 0x8f, 0x9b, 0x97, + 0x13, 0x1f, 0x0b, 0x07, 0x23, 0x2f, 0x3b, 0x37, + 0x73, 0x7f, 0x6b, 0x67, 0x43, 0x4f, 0x5b, 0x57, + 0x69, 0x65, 0x71, 0x7d, 0x59, 0x55, 0x41, 0x4d, + 0x09, 0x05, 0x11, 0x1d, 0x39, 0x35, 0x21, 0x2d, + 0xa9, 0xa5, 0xb1, 0xbd, 0x99, 0x95, 0x81, 0x8d, + 0xc9, 0xc5, 0xd1, 0xdd, 0xf9, 0xf5, 0xe1, 0xed, + 0xf4, 0xf8, 0xec, 0xe0, 0xc4, 0xc8, 0xdc, 0xd0, + 0x94, 0x98, 0x8c, 0x80, 0xa4, 0xa8, 0xbc, 0xb0, + 0x34, 0x38, 0x2c, 0x20, 0x04, 0x08, 0x1c, 0x10, + 0x54, 0x58, 0x4c, 0x40, 0x64, 0x68, 0x7c, 0x70, + }, + { + 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, + 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b, + 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, + 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, + 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, + 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6, + 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, + 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26, + 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, + 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, + 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, + 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc, + 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, + 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91, + 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, + 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41, + 0xce, 0xc3, 0xd4, 0xd9, 0xfa, 0xf7, 0xe0, 0xed, + 0xa6, 0xab, 0xbc, 0xb1, 0x92, 0x9f, 0x88, 0x85, + 0x1e, 0x13, 0x04, 0x09, 0x2a, 0x27, 0x30, 0x3d, + 0x76, 0x7b, 0x6c, 0x61, 0x42, 0x4f, 0x58, 0x55, + 0x73, 0x7e, 0x69, 0x64, 0x47, 0x4a, 0x5d, 0x50, + 0x1b, 0x16, 0x01, 0x0c, 0x2f, 0x22, 0x35, 0x38, + 0xa3, 0xae, 0xb9, 0xb4, 0x97, 0x9a, 0x8d, 0x80, + 0xcb, 0xc6, 0xd1, 0xdc, 0xff, 0xf2, 0xe5, 0xe8, + 0xa9, 0xa4, 0xb3, 0xbe, 0x9d, 0x90, 0x87, 0x8a, + 0xc1, 0xcc, 0xdb, 0xd6, 0xf5, 0xf8, 0xef, 0xe2, + 0x79, 0x74, 0x63, 0x6e, 0x4d, 0x40, 0x57, 0x5a, + 0x11, 0x1c, 0x0b, 0x06, 0x25, 0x28, 0x3f, 0x32, + 0x14, 0x19, 0x0e, 0x03, 0x20, 0x2d, 0x3a, 0x37, + 0x7c, 0x71, 0x66, 0x6b, 0x48, 0x45, 0x52, 0x5f, + 0xc4, 0xc9, 0xde, 0xd3, 0xf0, 0xfd, 0xea, 0xe7, + 0xac, 0xa1, 0xb6, 0xbb, 0x98, 0x95, 0x82, 0x8f, + }, + { + 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, + 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a, + 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, + 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, + 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7, + 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, + 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17, + 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, + 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d, + 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, + 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d, + 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, + 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, + 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20, + 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, + 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0, + 0x53, 0x5d, 0x4f, 0x41, 0x6b, 0x65, 0x77, 0x79, + 0x23, 0x2d, 0x3f, 0x31, 0x1b, 0x15, 0x07, 0x09, + 0xb3, 0xbd, 0xaf, 0xa1, 0x8b, 0x85, 0x97, 0x99, + 0xc3, 0xcd, 0xdf, 0xd1, 0xfb, 0xf5, 0xe7, 0xe9, + 0x8e, 0x80, 0x92, 0x9c, 0xb6, 0xb8, 0xaa, 0xa4, + 0xfe, 0xf0, 0xe2, 0xec, 0xc6, 0xc8, 0xda, 0xd4, + 0x6e, 0x60, 0x72, 0x7c, 0x56, 0x58, 0x4a, 0x44, + 0x1e, 0x10, 0x02, 0x0c, 0x26, 0x28, 0x3a, 0x34, + 0xf4, 0xfa, 0xe8, 0xe6, 0xcc, 0xc2, 0xd0, 0xde, + 0x84, 0x8a, 0x98, 0x96, 0xbc, 0xb2, 0xa0, 0xae, + 0x14, 0x1a, 0x08, 0x06, 0x2c, 0x22, 0x30, 0x3e, + 0x64, 0x6a, 0x78, 0x76, 0x5c, 0x52, 0x40, 0x4e, + 0x29, 0x27, 0x35, 0x3b, 0x11, 0x1f, 0x0d, 0x03, + 0x59, 0x57, 0x45, 0x4b, 0x61, 0x6f, 0x7d, 0x73, + 0xc9, 0xc7, 0xd5, 0xdb, 0xf1, 0xff, 0xed, 0xe3, + 0xb9, 0xb7, 0xa5, 0xab, 0x81, 0x8f, 0x9d, 0x93, + }, + { + 0x00, 0x0f, 0x1e, 0x11, 0x3c, 0x33, 0x22, 0x2d, + 0x78, 0x77, 0x66, 0x69, 0x44, 0x4b, 0x5a, 0x55, + 0xf0, 0xff, 0xee, 0xe1, 0xcc, 0xc3, 0xd2, 0xdd, + 0x88, 0x87, 0x96, 0x99, 0xb4, 0xbb, 0xaa, 0xa5, + 0xfd, 0xf2, 0xe3, 0xec, 0xc1, 0xce, 0xdf, 0xd0, + 0x85, 0x8a, 0x9b, 0x94, 0xb9, 0xb6, 0xa7, 0xa8, + 0x0d, 0x02, 0x13, 0x1c, 0x31, 0x3e, 0x2f, 0x20, + 0x75, 0x7a, 0x6b, 0x64, 0x49, 0x46, 0x57, 0x58, + 0xe7, 0xe8, 0xf9, 0xf6, 0xdb, 0xd4, 0xc5, 0xca, + 0x9f, 0x90, 0x81, 0x8e, 0xa3, 0xac, 0xbd, 0xb2, + 0x17, 0x18, 0x09, 0x06, 0x2b, 0x24, 0x35, 0x3a, + 0x6f, 0x60, 0x71, 0x7e, 0x53, 0x5c, 0x4d, 0x42, + 0x1a, 0x15, 0x04, 0x0b, 0x26, 0x29, 0x38, 0x37, + 0x62, 0x6d, 0x7c, 0x73, 0x5e, 0x51, 0x40, 0x4f, + 0xea, 0xe5, 0xf4, 0xfb, 0xd6, 0xd9, 0xc8, 0xc7, + 0x92, 0x9d, 0x8c, 0x83, 0xae, 0xa1, 0xb0, 0xbf, + 0xd3, 0xdc, 0xcd, 0xc2, 0xef, 0xe0, 0xf1, 0xfe, + 0xab, 0xa4, 0xb5, 0xba, 0x97, 0x98, 0x89, 0x86, + 0x23, 0x2c, 0x3d, 0x32, 0x1f, 0x10, 0x01, 0x0e, + 0x5b, 0x54, 0x45, 0x4a, 0x67, 0x68, 0x79, 0x76, + 0x2e, 0x21, 0x30, 0x3f, 0x12, 0x1d, 0x0c, 0x03, + 0x56, 0x59, 0x48, 0x47, 0x6a, 0x65, 0x74, 0x7b, + 0xde, 0xd1, 0xc0, 0xcf, 0xe2, 0xed, 0xfc, 0xf3, + 0xa6, 0xa9, 0xb8, 0xb7, 0x9a, 0x95, 0x84, 0x8b, + 0x34, 0x3b, 0x2a, 0x25, 0x08, 0x07, 0x16, 0x19, + 0x4c, 0x43, 0x52, 0x5d, 0x70, 0x7f, 0x6e, 0x61, + 0xc4, 0xcb, 0xda, 0xd5, 0xf8, 0xf7, 0xe6, 0xe9, + 0xbc, 0xb3, 0xa2, 0xad, 0x80, 0x8f, 0x9e, 0x91, + 0xc9, 0xc6, 0xd7, 0xd8, 0xf5, 0xfa, 0xeb, 0xe4, + 0xb1, 0xbe, 0xaf, 0xa0, 0x8d, 0x82, 0x93, 0x9c, + 0x39, 0x36, 0x27, 0x28, 0x05, 0x0a, 0x1b, 0x14, + 0x41, 0x4e, 0x5f, 0x50, 0x7d, 0x72, 0x63, 0x6c, + }, + { + 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, + 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, + 0x1d, 0x0d, 0x3d, 0x2d, 0x5d, 0x4d, 0x7d, 0x6d, + 0x9d, 0x8d, 0xbd, 0xad, 0xdd, 0xcd, 0xfd, 0xed, + 0x3a, 0x2a, 0x1a, 0x0a, 0x7a, 0x6a, 0x5a, 0x4a, + 0xba, 0xaa, 0x9a, 0x8a, 0xfa, 0xea, 0xda, 0xca, + 0x27, 0x37, 0x07, 0x17, 0x67, 0x77, 0x47, 0x57, + 0xa7, 0xb7, 0x87, 0x97, 0xe7, 0xf7, 0xc7, 0xd7, + 0x74, 0x64, 0x54, 0x44, 0x34, 0x24, 0x14, 0x04, + 0xf4, 0xe4, 0xd4, 0xc4, 0xb4, 0xa4, 0x94, 0x84, + 0x69, 0x79, 0x49, 0x59, 0x29, 0x39, 0x09, 0x19, + 0xe9, 0xf9, 0xc9, 0xd9, 0xa9, 0xb9, 0x89, 0x99, + 0x4e, 0x5e, 0x6e, 0x7e, 0x0e, 0x1e, 0x2e, 0x3e, + 0xce, 0xde, 0xee, 0xfe, 0x8e, 0x9e, 0xae, 0xbe, + 0x53, 0x43, 0x73, 0x63, 0x13, 0x03, 0x33, 0x23, + 0xd3, 0xc3, 0xf3, 0xe3, 0x93, 0x83, 0xb3, 0xa3, + 0xe8, 0xf8, 0xc8, 0xd8, 0xa8, 0xb8, 0x88, 0x98, + 0x68, 0x78, 0x48, 0x58, 0x28, 0x38, 0x08, 0x18, + 0xf5, 0xe5, 0xd5, 0xc5, 0xb5, 0xa5, 0x95, 0x85, + 0x75, 0x65, 0x55, 0x45, 0x35, 0x25, 0x15, 0x05, + 0xd2, 0xc2, 0xf2, 0xe2, 0x92, 0x82, 0xb2, 0xa2, + 0x52, 0x42, 0x72, 0x62, 0x12, 0x02, 0x32, 0x22, + 0xcf, 0xdf, 0xef, 0xff, 0x8f, 0x9f, 0xaf, 0xbf, + 0x4f, 0x5f, 0x6f, 0x7f, 0x0f, 0x1f, 0x2f, 0x3f, + 0x9c, 0x8c, 0xbc, 0xac, 0xdc, 0xcc, 0xfc, 0xec, + 0x1c, 0x0c, 0x3c, 0x2c, 0x5c, 0x4c, 0x7c, 0x6c, + 0x81, 0x91, 0xa1, 0xb1, 0xc1, 0xd1, 0xe1, 0xf1, + 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, + 0xa6, 0xb6, 0x86, 0x96, 0xe6, 0xf6, 0xc6, 0xd6, + 0x26, 0x36, 0x06, 0x16, 0x66, 0x76, 0x46, 0x56, + 0xbb, 0xab, 0x9b, 0x8b, 0xfb, 0xeb, 0xdb, 0xcb, + 0x3b, 0x2b, 0x1b, 0x0b, 0x7b, 0x6b, 0x5b, 0x4b, + }, + { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + 0x0d, 0x1c, 0x2f, 0x3e, 0x49, 0x58, 0x6b, 0x7a, + 0x85, 0x94, 0xa7, 0xb6, 0xc1, 0xd0, 0xe3, 0xf2, + 0x1a, 0x0b, 0x38, 0x29, 0x5e, 0x4f, 0x7c, 0x6d, + 0x92, 0x83, 0xb0, 0xa1, 0xd6, 0xc7, 0xf4, 0xe5, + 0x17, 0x06, 0x35, 0x24, 0x53, 0x42, 0x71, 0x60, + 0x9f, 0x8e, 0xbd, 0xac, 0xdb, 0xca, 0xf9, 0xe8, + 0x34, 0x25, 0x16, 0x07, 0x70, 0x61, 0x52, 0x43, + 0xbc, 0xad, 0x9e, 0x8f, 0xf8, 0xe9, 0xda, 0xcb, + 0x39, 0x28, 0x1b, 0x0a, 0x7d, 0x6c, 0x5f, 0x4e, + 0xb1, 0xa0, 0x93, 0x82, 0xf5, 0xe4, 0xd7, 0xc6, + 0x2e, 0x3f, 0x0c, 0x1d, 0x6a, 0x7b, 0x48, 0x59, + 0xa6, 0xb7, 0x84, 0x95, 0xe2, 0xf3, 0xc0, 0xd1, + 0x23, 0x32, 0x01, 0x10, 0x67, 0x76, 0x45, 0x54, + 0xab, 0xba, 0x89, 0x98, 0xef, 0xfe, 0xcd, 0xdc, + 0x68, 0x79, 0x4a, 0x5b, 0x2c, 0x3d, 0x0e, 0x1f, + 0xe0, 0xf1, 0xc2, 0xd3, 0xa4, 0xb5, 0x86, 0x97, + 0x65, 0x74, 0x47, 0x56, 0x21, 0x30, 0x03, 0x12, + 0xed, 0xfc, 0xcf, 0xde, 0xa9, 0xb8, 0x8b, 0x9a, + 0x72, 0x63, 0x50, 0x41, 0x36, 0x27, 0x14, 0x05, + 0xfa, 0xeb, 0xd8, 0xc9, 0xbe, 0xaf, 0x9c, 0x8d, + 0x7f, 0x6e, 0x5d, 0x4c, 0x3b, 0x2a, 0x19, 0x08, + 0xf7, 0xe6, 0xd5, 0xc4, 0xb3, 0xa2, 0x91, 0x80, + 0x5c, 0x4d, 0x7e, 0x6f, 0x18, 0x09, 0x3a, 0x2b, + 0xd4, 0xc5, 0xf6, 0xe7, 0x90, 0x81, 0xb2, 0xa3, + 0x51, 0x40, 0x73, 0x62, 0x15, 0x04, 0x37, 0x26, + 0xd9, 0xc8, 0xfb, 0xea, 0x9d, 0x8c, 0xbf, 0xae, + 0x46, 0x57, 0x64, 0x75, 0x02, 0x13, 0x20, 0x31, + 0xce, 0xdf, 0xec, 0xfd, 0x8a, 0x9b, 0xa8, 0xb9, + 0x4b, 0x5a, 0x69, 0x78, 0x0f, 0x1e, 0x2d, 0x3c, + 0xc3, 0xd2, 0xe1, 0xf0, 0x87, 0x96, 0xa5, 0xb4, + }, + { + 0x00, 0x12, 0x24, 0x36, 0x48, 0x5a, 0x6c, 0x7e, + 0x90, 0x82, 0xb4, 0xa6, 0xd8, 0xca, 0xfc, 0xee, + 0x3d, 0x2f, 0x19, 0x0b, 0x75, 0x67, 0x51, 0x43, + 0xad, 0xbf, 0x89, 0x9b, 0xe5, 0xf7, 0xc1, 0xd3, + 0x7a, 0x68, 0x5e, 0x4c, 0x32, 0x20, 0x16, 0x04, + 0xea, 0xf8, 0xce, 0xdc, 0xa2, 0xb0, 0x86, 0x94, + 0x47, 0x55, 0x63, 0x71, 0x0f, 0x1d, 0x2b, 0x39, + 0xd7, 0xc5, 0xf3, 0xe1, 0x9f, 0x8d, 0xbb, 0xa9, + 0xf4, 0xe6, 0xd0, 0xc2, 0xbc, 0xae, 0x98, 0x8a, + 0x64, 0x76, 0x40, 0x52, 0x2c, 0x3e, 0x08, 0x1a, + 0xc9, 0xdb, 0xed, 0xff, 0x81, 0x93, 0xa5, 0xb7, + 0x59, 0x4b, 0x7d, 0x6f, 0x11, 0x03, 0x35, 0x27, + 0x8e, 0x9c, 0xaa, 0xb8, 0xc6, 0xd4, 0xe2, 0xf0, + 0x1e, 0x0c, 0x3a, 0x28, 0x56, 0x44, 0x72, 0x60, + 0xb3, 0xa1, 0x97, 0x85, 0xfb, 0xe9, 0xdf, 0xcd, + 0x23, 0x31, 0x07, 0x15, 0x6b, 0x79, 0x4f, 0x5d, + 0xf5, 0xe7, 0xd1, 0xc3, 0xbd, 0xaf, 0x99, 0x8b, + 0x65, 0x77, 0x41, 0x53, 0x2d, 0x3f, 0x09, 0x1b, + 0xc8, 0xda, 0xec, 0xfe, 0x80, 0x92, 0xa4, 0xb6, + 0x58, 0x4a, 0x7c, 0x6e, 0x10, 0x02, 0x34, 0x26, + 0x8f, 0x9d, 0xab, 0xb9, 0xc7, 0xd5, 0xe3, 0xf1, + 0x1f, 0x0d, 0x3b, 0x29, 0x57, 0x45, 0x73, 0x61, + 0xb2, 0xa0, 0x96, 0x84, 0xfa, 0xe8, 0xde, 0xcc, + 0x22, 0x30, 0x06, 0x14, 0x6a, 0x78, 0x4e, 0x5c, + 0x01, 0x13, 0x25, 0x37, 0x49, 0x5b, 0x6d, 0x7f, + 0x91, 0x83, 0xb5, 0xa7, 0xd9, 0xcb, 0xfd, 0xef, + 0x3c, 0x2e, 0x18, 0x0a, 0x74, 0x66, 0x50, 0x42, + 0xac, 0xbe, 0x88, 0x9a, 0xe4, 0xf6, 0xc0, 0xd2, + 0x7b, 0x69, 0x5f, 0x4d, 0x33, 0x21, 0x17, 0x05, + 0xeb, 0xf9, 0xcf, 0xdd, 0xa3, 0xb1, 0x87, 0x95, + 0x46, 0x54, 0x62, 0x70, 0x0e, 0x1c, 0x2a, 0x38, + 0xd6, 0xc4, 0xf2, 0xe0, 0x9e, 0x8c, 0xba, 0xa8, + }, + { + 0x00, 0x13, 0x26, 0x35, 0x4c, 0x5f, 0x6a, 0x79, + 0x98, 0x8b, 0xbe, 0xad, 0xd4, 0xc7, 0xf2, 0xe1, + 0x2d, 0x3e, 0x0b, 0x18, 0x61, 0x72, 0x47, 0x54, + 0xb5, 0xa6, 0x93, 0x80, 0xf9, 0xea, 0xdf, 0xcc, + 0x5a, 0x49, 0x7c, 0x6f, 0x16, 0x05, 0x30, 0x23, + 0xc2, 0xd1, 0xe4, 0xf7, 0x8e, 0x9d, 0xa8, 0xbb, + 0x77, 0x64, 0x51, 0x42, 0x3b, 0x28, 0x1d, 0x0e, + 0xef, 0xfc, 0xc9, 0xda, 0xa3, 0xb0, 0x85, 0x96, + 0xb4, 0xa7, 0x92, 0x81, 0xf8, 0xeb, 0xde, 0xcd, + 0x2c, 0x3f, 0x0a, 0x19, 0x60, 0x73, 0x46, 0x55, + 0x99, 0x8a, 0xbf, 0xac, 0xd5, 0xc6, 0xf3, 0xe0, + 0x01, 0x12, 0x27, 0x34, 0x4d, 0x5e, 0x6b, 0x78, + 0xee, 0xfd, 0xc8, 0xdb, 0xa2, 0xb1, 0x84, 0x97, + 0x76, 0x65, 0x50, 0x43, 0x3a, 0x29, 0x1c, 0x0f, + 0xc3, 0xd0, 0xe5, 0xf6, 0x8f, 0x9c, 0xa9, 0xba, + 0x5b, 0x48, 0x7d, 0x6e, 0x17, 0x04, 0x31, 0x22, + 0x75, 0x66, 0x53, 0x40, 0x39, 0x2a, 0x1f, 0x0c, + 0xed, 0xfe, 0xcb, 0xd8, 0xa1, 0xb2, 0x87, 0x94, + 0x58, 0x4b, 0x7e, 0x6d, 0x14, 0x07, 0x32, 0x21, + 0xc0, 0xd3, 0xe6, 0xf5, 0x8c, 0x9f, 0xaa, 0xb9, + 0x2f, 0x3c, 0x09, 0x1a, 0x63, 0x70, 0x45, 0x56, + 0xb7, 0xa4, 0x91, 0x82, 0xfb, 0xe8, 0xdd, 0xce, + 0x02, 0x11, 0x24, 0x37, 0x4e, 0x5d, 0x68, 0x7b, + 0x9a, 0x89, 0xbc, 0xaf, 0xd6, 0xc5, 0xf0, 0xe3, + 0xc1, 0xd2, 0xe7, 0xf4, 0x8d, 0x9e, 0xab, 0xb8, + 0x59, 0x4a, 0x7f, 0x6c, 0x15, 0x06, 0x33, 0x20, + 0xec, 0xff, 0xca, 0xd9, 0xa0, 0xb3, 0x86, 0x95, + 0x74, 0x67, 0x52, 0x41, 0x38, 0x2b, 0x1e, 0x0d, + 0x9b, 0x88, 0xbd, 0xae, 0xd7, 0xc4, 0xf1, 0xe2, + 0x03, 0x10, 0x25, 0x36, 0x4f, 0x5c, 0x69, 0x7a, + 0xb6, 0xa5, 0x90, 0x83, 0xfa, 0xe9, 0xdc, 0xcf, + 0x2e, 0x3d, 0x08, 0x1b, 0x62, 0x71, 0x44, 0x57, + }, + { + 0x00, 0x14, 0x28, 0x3c, 0x50, 0x44, 0x78, 0x6c, + 0xa0, 0xb4, 0x88, 0x9c, 0xf0, 0xe4, 0xd8, 0xcc, + 0x5d, 0x49, 0x75, 0x61, 0x0d, 0x19, 0x25, 0x31, + 0xfd, 0xe9, 0xd5, 0xc1, 0xad, 0xb9, 0x85, 0x91, + 0xba, 0xae, 0x92, 0x86, 0xea, 0xfe, 0xc2, 0xd6, + 0x1a, 0x0e, 0x32, 0x26, 0x4a, 0x5e, 0x62, 0x76, + 0xe7, 0xf3, 0xcf, 0xdb, 0xb7, 0xa3, 0x9f, 0x8b, + 0x47, 0x53, 0x6f, 0x7b, 0x17, 0x03, 0x3f, 0x2b, + 0x69, 0x7d, 0x41, 0x55, 0x39, 0x2d, 0x11, 0x05, + 0xc9, 0xdd, 0xe1, 0xf5, 0x99, 0x8d, 0xb1, 0xa5, + 0x34, 0x20, 0x1c, 0x08, 0x64, 0x70, 0x4c, 0x58, + 0x94, 0x80, 0xbc, 0xa8, 0xc4, 0xd0, 0xec, 0xf8, + 0xd3, 0xc7, 0xfb, 0xef, 0x83, 0x97, 0xab, 0xbf, + 0x73, 0x67, 0x5b, 0x4f, 0x23, 0x37, 0x0b, 0x1f, + 0x8e, 0x9a, 0xa6, 0xb2, 0xde, 0xca, 0xf6, 0xe2, + 0x2e, 0x3a, 0x06, 0x12, 0x7e, 0x6a, 0x56, 0x42, + 0xd2, 0xc6, 0xfa, 0xee, 0x82, 0x96, 0xaa, 0xbe, + 0x72, 0x66, 0x5a, 0x4e, 0x22, 0x36, 0x0a, 0x1e, + 0x8f, 0x9b, 0xa7, 0xb3, 0xdf, 0xcb, 0xf7, 0xe3, + 0x2f, 0x3b, 0x07, 0x13, 0x7f, 0x6b, 0x57, 0x43, + 0x68, 0x7c, 0x40, 0x54, 0x38, 0x2c, 0x10, 0x04, + 0xc8, 0xdc, 0xe0, 0xf4, 0x98, 0x8c, 0xb0, 0xa4, + 0x35, 0x21, 0x1d, 0x09, 0x65, 0x71, 0x4d, 0x59, + 0x95, 0x81, 0xbd, 0xa9, 0xc5, 0xd1, 0xed, 0xf9, + 0xbb, 0xaf, 0x93, 0x87, 0xeb, 0xff, 0xc3, 0xd7, + 0x1b, 0x0f, 0x33, 0x27, 0x4b, 0x5f, 0x63, 0x77, + 0xe6, 0xf2, 0xce, 0xda, 0xb6, 0xa2, 0x9e, 0x8a, + 0x46, 0x52, 0x6e, 0x7a, 0x16, 0x02, 0x3e, 0x2a, + 0x01, 0x15, 0x29, 0x3d, 0x51, 0x45, 0x79, 0x6d, + 0xa1, 0xb5, 0x89, 0x9d, 0xf1, 0xe5, 0xd9, 0xcd, + 0x5c, 0x48, 0x74, 0x60, 0x0c, 0x18, 0x24, 0x30, + 0xfc, 0xe8, 0xd4, 0xc0, 0xac, 0xb8, 0x84, 0x90, + }, + { + 0x00, 0x15, 0x2a, 0x3f, 0x54, 0x41, 0x7e, 0x6b, + 0xa8, 0xbd, 0x82, 0x97, 0xfc, 0xe9, 0xd6, 0xc3, + 0x4d, 0x58, 0x67, 0x72, 0x19, 0x0c, 0x33, 0x26, + 0xe5, 0xf0, 0xcf, 0xda, 0xb1, 0xa4, 0x9b, 0x8e, + 0x9a, 0x8f, 0xb0, 0xa5, 0xce, 0xdb, 0xe4, 0xf1, + 0x32, 0x27, 0x18, 0x0d, 0x66, 0x73, 0x4c, 0x59, + 0xd7, 0xc2, 0xfd, 0xe8, 0x83, 0x96, 0xa9, 0xbc, + 0x7f, 0x6a, 0x55, 0x40, 0x2b, 0x3e, 0x01, 0x14, + 0x29, 0x3c, 0x03, 0x16, 0x7d, 0x68, 0x57, 0x42, + 0x81, 0x94, 0xab, 0xbe, 0xd5, 0xc0, 0xff, 0xea, + 0x64, 0x71, 0x4e, 0x5b, 0x30, 0x25, 0x1a, 0x0f, + 0xcc, 0xd9, 0xe6, 0xf3, 0x98, 0x8d, 0xb2, 0xa7, + 0xb3, 0xa6, 0x99, 0x8c, 0xe7, 0xf2, 0xcd, 0xd8, + 0x1b, 0x0e, 0x31, 0x24, 0x4f, 0x5a, 0x65, 0x70, + 0xfe, 0xeb, 0xd4, 0xc1, 0xaa, 0xbf, 0x80, 0x95, + 0x56, 0x43, 0x7c, 0x69, 0x02, 0x17, 0x28, 0x3d, + 0x52, 0x47, 0x78, 0x6d, 0x06, 0x13, 0x2c, 0x39, + 0xfa, 0xef, 0xd0, 0xc5, 0xae, 0xbb, 0x84, 0x91, + 0x1f, 0x0a, 0x35, 0x20, 0x4b, 0x5e, 0x61, 0x74, + 0xb7, 0xa2, 0x9d, 0x88, 0xe3, 0xf6, 0xc9, 0xdc, + 0xc8, 0xdd, 0xe2, 0xf7, 0x9c, 0x89, 0xb6, 0xa3, + 0x60, 0x75, 0x4a, 0x5f, 0x34, 0x21, 0x1e, 0x0b, + 0x85, 0x90, 0xaf, 0xba, 0xd1, 0xc4, 0xfb, 0xee, + 0x2d, 0x38, 0x07, 0x12, 0x79, 0x6c, 0x53, 0x46, + 0x7b, 0x6e, 0x51, 0x44, 0x2f, 0x3a, 0x05, 0x10, + 0xd3, 0xc6, 0xf9, 0xec, 0x87, 0x92, 0xad, 0xb8, + 0x36, 0x23, 0x1c, 0x09, 0x62, 0x77, 0x48, 0x5d, + 0x9e, 0x8b, 0xb4, 0xa1, 0xca, 0xdf, 0xe0, 0xf5, + 0xe1, 0xf4, 0xcb, 0xde, 0xb5, 0xa0, 0x9f, 0x8a, + 0x49, 0x5c, 0x63, 0x76, 0x1d, 0x08, 0x37, 0x22, + 0xac, 0xb9, 0x86, 0x93, 0xf8, 0xed, 0xd2, 0xc7, + 0x04, 0x11, 0x2e, 0x3b, 0x50, 0x45, 0x7a, 0x6f, + }, + { + 0x00, 0x16, 0x2c, 0x3a, 0x58, 0x4e, 0x74, 0x62, + 0xb0, 0xa6, 0x9c, 0x8a, 0xe8, 0xfe, 0xc4, 0xd2, + 0x7d, 0x6b, 0x51, 0x47, 0x25, 0x33, 0x09, 0x1f, + 0xcd, 0xdb, 0xe1, 0xf7, 0x95, 0x83, 0xb9, 0xaf, + 0xfa, 0xec, 0xd6, 0xc0, 0xa2, 0xb4, 0x8e, 0x98, + 0x4a, 0x5c, 0x66, 0x70, 0x12, 0x04, 0x3e, 0x28, + 0x87, 0x91, 0xab, 0xbd, 0xdf, 0xc9, 0xf3, 0xe5, + 0x37, 0x21, 0x1b, 0x0d, 0x6f, 0x79, 0x43, 0x55, + 0xe9, 0xff, 0xc5, 0xd3, 0xb1, 0xa7, 0x9d, 0x8b, + 0x59, 0x4f, 0x75, 0x63, 0x01, 0x17, 0x2d, 0x3b, + 0x94, 0x82, 0xb8, 0xae, 0xcc, 0xda, 0xe0, 0xf6, + 0x24, 0x32, 0x08, 0x1e, 0x7c, 0x6a, 0x50, 0x46, + 0x13, 0x05, 0x3f, 0x29, 0x4b, 0x5d, 0x67, 0x71, + 0xa3, 0xb5, 0x8f, 0x99, 0xfb, 0xed, 0xd7, 0xc1, + 0x6e, 0x78, 0x42, 0x54, 0x36, 0x20, 0x1a, 0x0c, + 0xde, 0xc8, 0xf2, 0xe4, 0x86, 0x90, 0xaa, 0xbc, + 0xcf, 0xd9, 0xe3, 0xf5, 0x97, 0x81, 0xbb, 0xad, + 0x7f, 0x69, 0x53, 0x45, 0x27, 0x31, 0x0b, 0x1d, + 0xb2, 0xa4, 0x9e, 0x88, 0xea, 0xfc, 0xc6, 0xd0, + 0x02, 0x14, 0x2e, 0x38, 0x5a, 0x4c, 0x76, 0x60, + 0x35, 0x23, 0x19, 0x0f, 0x6d, 0x7b, 0x41, 0x57, + 0x85, 0x93, 0xa9, 0xbf, 0xdd, 0xcb, 0xf1, 0xe7, + 0x48, 0x5e, 0x64, 0x72, 0x10, 0x06, 0x3c, 0x2a, + 0xf8, 0xee, 0xd4, 0xc2, 0xa0, 0xb6, 0x8c, 0x9a, + 0x26, 0x30, 0x0a, 0x1c, 0x7e, 0x68, 0x52, 0x44, + 0x96, 0x80, 0xba, 0xac, 0xce, 0xd8, 0xe2, 0xf4, + 0x5b, 0x4d, 0x77, 0x61, 0x03, 0x15, 0x2f, 0x39, + 0xeb, 0xfd, 0xc7, 0xd1, 0xb3, 0xa5, 0x9f, 0x89, + 0xdc, 0xca, 0xf0, 0xe6, 0x84, 0x92, 0xa8, 0xbe, + 0x6c, 0x7a, 0x40, 0x56, 0x34, 0x22, 0x18, 0x0e, + 0xa1, 0xb7, 0x8d, 0x9b, 0xf9, 0xef, 0xd5, 0xc3, + 0x11, 0x07, 0x3d, 0x2b, 0x49, 0x5f, 0x65, 0x73, + }, + { + 0x00, 0x17, 0x2e, 0x39, 0x5c, 0x4b, 0x72, 0x65, + 0xb8, 0xaf, 0x96, 0x81, 0xe4, 0xf3, 0xca, 0xdd, + 0x6d, 0x7a, 0x43, 0x54, 0x31, 0x26, 0x1f, 0x08, + 0xd5, 0xc2, 0xfb, 0xec, 0x89, 0x9e, 0xa7, 0xb0, + 0xda, 0xcd, 0xf4, 0xe3, 0x86, 0x91, 0xa8, 0xbf, + 0x62, 0x75, 0x4c, 0x5b, 0x3e, 0x29, 0x10, 0x07, + 0xb7, 0xa0, 0x99, 0x8e, 0xeb, 0xfc, 0xc5, 0xd2, + 0x0f, 0x18, 0x21, 0x36, 0x53, 0x44, 0x7d, 0x6a, + 0xa9, 0xbe, 0x87, 0x90, 0xf5, 0xe2, 0xdb, 0xcc, + 0x11, 0x06, 0x3f, 0x28, 0x4d, 0x5a, 0x63, 0x74, + 0xc4, 0xd3, 0xea, 0xfd, 0x98, 0x8f, 0xb6, 0xa1, + 0x7c, 0x6b, 0x52, 0x45, 0x20, 0x37, 0x0e, 0x19, + 0x73, 0x64, 0x5d, 0x4a, 0x2f, 0x38, 0x01, 0x16, + 0xcb, 0xdc, 0xe5, 0xf2, 0x97, 0x80, 0xb9, 0xae, + 0x1e, 0x09, 0x30, 0x27, 0x42, 0x55, 0x6c, 0x7b, + 0xa6, 0xb1, 0x88, 0x9f, 0xfa, 0xed, 0xd4, 0xc3, + 0x4f, 0x58, 0x61, 0x76, 0x13, 0x04, 0x3d, 0x2a, + 0xf7, 0xe0, 0xd9, 0xce, 0xab, 0xbc, 0x85, 0x92, + 0x22, 0x35, 0x0c, 0x1b, 0x7e, 0x69, 0x50, 0x47, + 0x9a, 0x8d, 0xb4, 0xa3, 0xc6, 0xd1, 0xe8, 0xff, + 0x95, 0x82, 0xbb, 0xac, 0xc9, 0xde, 0xe7, 0xf0, + 0x2d, 0x3a, 0x03, 0x14, 0x71, 0x66, 0x5f, 0x48, + 0xf8, 0xef, 0xd6, 0xc1, 0xa4, 0xb3, 0x8a, 0x9d, + 0x40, 0x57, 0x6e, 0x79, 0x1c, 0x0b, 0x32, 0x25, + 0xe6, 0xf1, 0xc8, 0xdf, 0xba, 0xad, 0x94, 0x83, + 0x5e, 0x49, 0x70, 0x67, 0x02, 0x15, 0x2c, 0x3b, + 0x8b, 0x9c, 0xa5, 0xb2, 0xd7, 0xc0, 0xf9, 0xee, + 0x33, 0x24, 0x1d, 0x0a, 0x6f, 0x78, 0x41, 0x56, + 0x3c, 0x2b, 0x12, 0x05, 0x60, 0x77, 0x4e, 0x59, + 0x84, 0x93, 0xaa, 0xbd, 0xd8, 0xcf, 0xf6, 0xe1, + 0x51, 0x46, 0x7f, 0x68, 0x0d, 0x1a, 0x23, 0x34, + 0xe9, 0xfe, 0xc7, 0xd0, 0xb5, 0xa2, 0x9b, 0x8c, + }, + { + 0x00, 0x18, 0x30, 0x28, 0x60, 0x78, 0x50, 0x48, + 0xc0, 0xd8, 0xf0, 0xe8, 0xa0, 0xb8, 0x90, 0x88, + 0x9d, 0x85, 0xad, 0xb5, 0xfd, 0xe5, 0xcd, 0xd5, + 0x5d, 0x45, 0x6d, 0x75, 0x3d, 0x25, 0x0d, 0x15, + 0x27, 0x3f, 0x17, 0x0f, 0x47, 0x5f, 0x77, 0x6f, + 0xe7, 0xff, 0xd7, 0xcf, 0x87, 0x9f, 0xb7, 0xaf, + 0xba, 0xa2, 0x8a, 0x92, 0xda, 0xc2, 0xea, 0xf2, + 0x7a, 0x62, 0x4a, 0x52, 0x1a, 0x02, 0x2a, 0x32, + 0x4e, 0x56, 0x7e, 0x66, 0x2e, 0x36, 0x1e, 0x06, + 0x8e, 0x96, 0xbe, 0xa6, 0xee, 0xf6, 0xde, 0xc6, + 0xd3, 0xcb, 0xe3, 0xfb, 0xb3, 0xab, 0x83, 0x9b, + 0x13, 0x0b, 0x23, 0x3b, 0x73, 0x6b, 0x43, 0x5b, + 0x69, 0x71, 0x59, 0x41, 0x09, 0x11, 0x39, 0x21, + 0xa9, 0xb1, 0x99, 0x81, 0xc9, 0xd1, 0xf9, 0xe1, + 0xf4, 0xec, 0xc4, 0xdc, 0x94, 0x8c, 0xa4, 0xbc, + 0x34, 0x2c, 0x04, 0x1c, 0x54, 0x4c, 0x64, 0x7c, + 0x9c, 0x84, 0xac, 0xb4, 0xfc, 0xe4, 0xcc, 0xd4, + 0x5c, 0x44, 0x6c, 0x74, 0x3c, 0x24, 0x0c, 0x14, + 0x01, 0x19, 0x31, 0x29, 0x61, 0x79, 0x51, 0x49, + 0xc1, 0xd9, 0xf1, 0xe9, 0xa1, 0xb9, 0x91, 0x89, + 0xbb, 0xa3, 0x8b, 0x93, 0xdb, 0xc3, 0xeb, 0xf3, + 0x7b, 0x63, 0x4b, 0x53, 0x1b, 0x03, 0x2b, 0x33, + 0x26, 0x3e, 0x16, 0x0e, 0x46, 0x5e, 0x76, 0x6e, + 0xe6, 0xfe, 0xd6, 0xce, 0x86, 0x9e, 0xb6, 0xae, + 0xd2, 0xca, 0xe2, 0xfa, 0xb2, 0xaa, 0x82, 0x9a, + 0x12, 0x0a, 0x22, 0x3a, 0x72, 0x6a, 0x42, 0x5a, + 0x4f, 0x57, 0x7f, 0x67, 0x2f, 0x37, 0x1f, 0x07, + 0x8f, 0x97, 0xbf, 0xa7, 0xef, 0xf7, 0xdf, 0xc7, + 0xf5, 0xed, 0xc5, 0xdd, 0x95, 0x8d, 0xa5, 0xbd, + 0x35, 0x2d, 0x05, 0x1d, 0x55, 0x4d, 0x65, 0x7d, + 0x68, 0x70, 0x58, 0x40, 0x08, 0x10, 0x38, 0x20, + 0xa8, 0xb0, 0x98, 0x80, 0xc8, 0xd0, 0xf8, 0xe0, + }, + { + 0x00, 0x19, 0x32, 0x2b, 0x64, 0x7d, 0x56, 0x4f, + 0xc8, 0xd1, 0xfa, 0xe3, 0xac, 0xb5, 0x9e, 0x87, + 0x8d, 0x94, 0xbf, 0xa6, 0xe9, 0xf0, 0xdb, 0xc2, + 0x45, 0x5c, 0x77, 0x6e, 0x21, 0x38, 0x13, 0x0a, + 0x07, 0x1e, 0x35, 0x2c, 0x63, 0x7a, 0x51, 0x48, + 0xcf, 0xd6, 0xfd, 0xe4, 0xab, 0xb2, 0x99, 0x80, + 0x8a, 0x93, 0xb8, 0xa1, 0xee, 0xf7, 0xdc, 0xc5, + 0x42, 0x5b, 0x70, 0x69, 0x26, 0x3f, 0x14, 0x0d, + 0x0e, 0x17, 0x3c, 0x25, 0x6a, 0x73, 0x58, 0x41, + 0xc6, 0xdf, 0xf4, 0xed, 0xa2, 0xbb, 0x90, 0x89, + 0x83, 0x9a, 0xb1, 0xa8, 0xe7, 0xfe, 0xd5, 0xcc, + 0x4b, 0x52, 0x79, 0x60, 0x2f, 0x36, 0x1d, 0x04, + 0x09, 0x10, 0x3b, 0x22, 0x6d, 0x74, 0x5f, 0x46, + 0xc1, 0xd8, 0xf3, 0xea, 0xa5, 0xbc, 0x97, 0x8e, + 0x84, 0x9d, 0xb6, 0xaf, 0xe0, 0xf9, 0xd2, 0xcb, + 0x4c, 0x55, 0x7e, 0x67, 0x28, 0x31, 0x1a, 0x03, + 0x1c, 0x05, 0x2e, 0x37, 0x78, 0x61, 0x4a, 0x53, + 0xd4, 0xcd, 0xe6, 0xff, 0xb0, 0xa9, 0x82, 0x9b, + 0x91, 0x88, 0xa3, 0xba, 0xf5, 0xec, 0xc7, 0xde, + 0x59, 0x40, 0x6b, 0x72, 0x3d, 0x24, 0x0f, 0x16, + 0x1b, 0x02, 0x29, 0x30, 0x7f, 0x66, 0x4d, 0x54, + 0xd3, 0xca, 0xe1, 0xf8, 0xb7, 0xae, 0x85, 0x9c, + 0x96, 0x8f, 0xa4, 0xbd, 0xf2, 0xeb, 0xc0, 0xd9, + 0x5e, 0x47, 0x6c, 0x75, 0x3a, 0x23, 0x08, 0x11, + 0x12, 0x0b, 0x20, 0x39, 0x76, 0x6f, 0x44, 0x5d, + 0xda, 0xc3, 0xe8, 0xf1, 0xbe, 0xa7, 0x8c, 0x95, + 0x9f, 0x86, 0xad, 0xb4, 0xfb, 0xe2, 0xc9, 0xd0, + 0x57, 0x4e, 0x65, 0x7c, 0x33, 0x2a, 0x01, 0x18, + 0x15, 0x0c, 0x27, 0x3e, 0x71, 0x68, 0x43, 0x5a, + 0xdd, 0xc4, 0xef, 0xf6, 0xb9, 0xa0, 0x8b, 0x92, + 0x98, 0x81, 0xaa, 0xb3, 0xfc, 0xe5, 0xce, 0xd7, + 0x50, 0x49, 0x62, 0x7b, 0x34, 0x2d, 0x06, 0x1f, + }, + { + 0x00, 0x1a, 0x34, 0x2e, 0x68, 0x72, 0x5c, 0x46, + 0xd0, 0xca, 0xe4, 0xfe, 0xb8, 0xa2, 0x8c, 0x96, + 0xbd, 0xa7, 0x89, 0x93, 0xd5, 0xcf, 0xe1, 0xfb, + 0x6d, 0x77, 0x59, 0x43, 0x05, 0x1f, 0x31, 0x2b, + 0x67, 0x7d, 0x53, 0x49, 0x0f, 0x15, 0x3b, 0x21, + 0xb7, 0xad, 0x83, 0x99, 0xdf, 0xc5, 0xeb, 0xf1, + 0xda, 0xc0, 0xee, 0xf4, 0xb2, 0xa8, 0x86, 0x9c, + 0x0a, 0x10, 0x3e, 0x24, 0x62, 0x78, 0x56, 0x4c, + 0xce, 0xd4, 0xfa, 0xe0, 0xa6, 0xbc, 0x92, 0x88, + 0x1e, 0x04, 0x2a, 0x30, 0x76, 0x6c, 0x42, 0x58, + 0x73, 0x69, 0x47, 0x5d, 0x1b, 0x01, 0x2f, 0x35, + 0xa3, 0xb9, 0x97, 0x8d, 0xcb, 0xd1, 0xff, 0xe5, + 0xa9, 0xb3, 0x9d, 0x87, 0xc1, 0xdb, 0xf5, 0xef, + 0x79, 0x63, 0x4d, 0x57, 0x11, 0x0b, 0x25, 0x3f, + 0x14, 0x0e, 0x20, 0x3a, 0x7c, 0x66, 0x48, 0x52, + 0xc4, 0xde, 0xf0, 0xea, 0xac, 0xb6, 0x98, 0x82, + 0x81, 0x9b, 0xb5, 0xaf, 0xe9, 0xf3, 0xdd, 0xc7, + 0x51, 0x4b, 0x65, 0x7f, 0x39, 0x23, 0x0d, 0x17, + 0x3c, 0x26, 0x08, 0x12, 0x54, 0x4e, 0x60, 0x7a, + 0xec, 0xf6, 0xd8, 0xc2, 0x84, 0x9e, 0xb0, 0xaa, + 0xe6, 0xfc, 0xd2, 0xc8, 0x8e, 0x94, 0xba, 0xa0, + 0x36, 0x2c, 0x02, 0x18, 0x5e, 0x44, 0x6a, 0x70, + 0x5b, 0x41, 0x6f, 0x75, 0x33, 0x29, 0x07, 0x1d, + 0x8b, 0x91, 0xbf, 0xa5, 0xe3, 0xf9, 0xd7, 0xcd, + 0x4f, 0x55, 0x7b, 0x61, 0x27, 0x3d, 0x13, 0x09, + 0x9f, 0x85, 0xab, 0xb1, 0xf7, 0xed, 0xc3, 0xd9, + 0xf2, 0xe8, 0xc6, 0xdc, 0x9a, 0x80, 0xae, 0xb4, + 0x22, 0x38, 0x16, 0x0c, 0x4a, 0x50, 0x7e, 0x64, + 0x28, 0x32, 0x1c, 0x06, 0x40, 0x5a, 0x74, 0x6e, + 0xf8, 0xe2, 0xcc, 0xd6, 0x90, 0x8a, 0xa4, 0xbe, + 0x95, 0x8f, 0xa1, 0xbb, 0xfd, 0xe7, 0xc9, 0xd3, + 0x45, 0x5f, 0x71, 0x6b, 0x2d, 0x37, 0x19, 0x03, + }, + { + 0x00, 0x1b, 0x36, 0x2d, 0x6c, 0x77, 0x5a, 0x41, + 0xd8, 0xc3, 0xee, 0xf5, 0xb4, 0xaf, 0x82, 0x99, + 0xad, 0xb6, 0x9b, 0x80, 0xc1, 0xda, 0xf7, 0xec, + 0x75, 0x6e, 0x43, 0x58, 0x19, 0x02, 0x2f, 0x34, + 0x47, 0x5c, 0x71, 0x6a, 0x2b, 0x30, 0x1d, 0x06, + 0x9f, 0x84, 0xa9, 0xb2, 0xf3, 0xe8, 0xc5, 0xde, + 0xea, 0xf1, 0xdc, 0xc7, 0x86, 0x9d, 0xb0, 0xab, + 0x32, 0x29, 0x04, 0x1f, 0x5e, 0x45, 0x68, 0x73, + 0x8e, 0x95, 0xb8, 0xa3, 0xe2, 0xf9, 0xd4, 0xcf, + 0x56, 0x4d, 0x60, 0x7b, 0x3a, 0x21, 0x0c, 0x17, + 0x23, 0x38, 0x15, 0x0e, 0x4f, 0x54, 0x79, 0x62, + 0xfb, 0xe0, 0xcd, 0xd6, 0x97, 0x8c, 0xa1, 0xba, + 0xc9, 0xd2, 0xff, 0xe4, 0xa5, 0xbe, 0x93, 0x88, + 0x11, 0x0a, 0x27, 0x3c, 0x7d, 0x66, 0x4b, 0x50, + 0x64, 0x7f, 0x52, 0x49, 0x08, 0x13, 0x3e, 0x25, + 0xbc, 0xa7, 0x8a, 0x91, 0xd0, 0xcb, 0xe6, 0xfd, + 0x01, 0x1a, 0x37, 0x2c, 0x6d, 0x76, 0x5b, 0x40, + 0xd9, 0xc2, 0xef, 0xf4, 0xb5, 0xae, 0x83, 0x98, + 0xac, 0xb7, 0x9a, 0x81, 0xc0, 0xdb, 0xf6, 0xed, + 0x74, 0x6f, 0x42, 0x59, 0x18, 0x03, 0x2e, 0x35, + 0x46, 0x5d, 0x70, 0x6b, 0x2a, 0x31, 0x1c, 0x07, + 0x9e, 0x85, 0xa8, 0xb3, 0xf2, 0xe9, 0xc4, 0xdf, + 0xeb, 0xf0, 0xdd, 0xc6, 0x87, 0x9c, 0xb1, 0xaa, + 0x33, 0x28, 0x05, 0x1e, 0x5f, 0x44, 0x69, 0x72, + 0x8f, 0x94, 0xb9, 0xa2, 0xe3, 0xf8, 0xd5, 0xce, + 0x57, 0x4c, 0x61, 0x7a, 0x3b, 0x20, 0x0d, 0x16, + 0x22, 0x39, 0x14, 0x0f, 0x4e, 0x55, 0x78, 0x63, + 0xfa, 0xe1, 0xcc, 0xd7, 0x96, 0x8d, 0xa0, 0xbb, + 0xc8, 0xd3, 0xfe, 0xe5, 0xa4, 0xbf, 0x92, 0x89, + 0x10, 0x0b, 0x26, 0x3d, 0x7c, 0x67, 0x4a, 0x51, + 0x65, 0x7e, 0x53, 0x48, 0x09, 0x12, 0x3f, 0x24, + 0xbd, 0xa6, 0x8b, 0x90, 0xd1, 0xca, 0xe7, 0xfc, + }, + { + 0x00, 0x1c, 0x38, 0x24, 0x70, 0x6c, 0x48, 0x54, + 0xe0, 0xfc, 0xd8, 0xc4, 0x90, 0x8c, 0xa8, 0xb4, + 0xdd, 0xc1, 0xe5, 0xf9, 0xad, 0xb1, 0x95, 0x89, + 0x3d, 0x21, 0x05, 0x19, 0x4d, 0x51, 0x75, 0x69, + 0xa7, 0xbb, 0x9f, 0x83, 0xd7, 0xcb, 0xef, 0xf3, + 0x47, 0x5b, 0x7f, 0x63, 0x37, 0x2b, 0x0f, 0x13, + 0x7a, 0x66, 0x42, 0x5e, 0x0a, 0x16, 0x32, 0x2e, + 0x9a, 0x86, 0xa2, 0xbe, 0xea, 0xf6, 0xd2, 0xce, + 0x53, 0x4f, 0x6b, 0x77, 0x23, 0x3f, 0x1b, 0x07, + 0xb3, 0xaf, 0x8b, 0x97, 0xc3, 0xdf, 0xfb, 0xe7, + 0x8e, 0x92, 0xb6, 0xaa, 0xfe, 0xe2, 0xc6, 0xda, + 0x6e, 0x72, 0x56, 0x4a, 0x1e, 0x02, 0x26, 0x3a, + 0xf4, 0xe8, 0xcc, 0xd0, 0x84, 0x98, 0xbc, 0xa0, + 0x14, 0x08, 0x2c, 0x30, 0x64, 0x78, 0x5c, 0x40, + 0x29, 0x35, 0x11, 0x0d, 0x59, 0x45, 0x61, 0x7d, + 0xc9, 0xd5, 0xf1, 0xed, 0xb9, 0xa5, 0x81, 0x9d, + 0xa6, 0xba, 0x9e, 0x82, 0xd6, 0xca, 0xee, 0xf2, + 0x46, 0x5a, 0x7e, 0x62, 0x36, 0x2a, 0x0e, 0x12, + 0x7b, 0x67, 0x43, 0x5f, 0x0b, 0x17, 0x33, 0x2f, + 0x9b, 0x87, 0xa3, 0xbf, 0xeb, 0xf7, 0xd3, 0xcf, + 0x01, 0x1d, 0x39, 0x25, 0x71, 0x6d, 0x49, 0x55, + 0xe1, 0xfd, 0xd9, 0xc5, 0x91, 0x8d, 0xa9, 0xb5, + 0xdc, 0xc0, 0xe4, 0xf8, 0xac, 0xb0, 0x94, 0x88, + 0x3c, 0x20, 0x04, 0x18, 0x4c, 0x50, 0x74, 0x68, + 0xf5, 0xe9, 0xcd, 0xd1, 0x85, 0x99, 0xbd, 0xa1, + 0x15, 0x09, 0x2d, 0x31, 0x65, 0x79, 0x5d, 0x41, + 0x28, 0x34, 0x10, 0x0c, 0x58, 0x44, 0x60, 0x7c, + 0xc8, 0xd4, 0xf0, 0xec, 0xb8, 0xa4, 0x80, 0x9c, + 0x52, 0x4e, 0x6a, 0x76, 0x22, 0x3e, 0x1a, 0x06, + 0xb2, 0xae, 0x8a, 0x96, 0xc2, 0xde, 0xfa, 0xe6, + 0x8f, 0x93, 0xb7, 0xab, 0xff, 0xe3, 0xc7, 0xdb, + 0x6f, 0x73, 0x57, 0x4b, 0x1f, 0x03, 0x27, 0x3b, + }, + { + 0x00, 0x1d, 0x3a, 0x27, 0x74, 0x69, 0x4e, 0x53, + 0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb, + 0xcd, 0xd0, 0xf7, 0xea, 0xb9, 0xa4, 0x83, 0x9e, + 0x25, 0x38, 0x1f, 0x02, 0x51, 0x4c, 0x6b, 0x76, + 0x87, 0x9a, 0xbd, 0xa0, 0xf3, 0xee, 0xc9, 0xd4, + 0x6f, 0x72, 0x55, 0x48, 0x1b, 0x06, 0x21, 0x3c, + 0x4a, 0x57, 0x70, 0x6d, 0x3e, 0x23, 0x04, 0x19, + 0xa2, 0xbf, 0x98, 0x85, 0xd6, 0xcb, 0xec, 0xf1, + 0x13, 0x0e, 0x29, 0x34, 0x67, 0x7a, 0x5d, 0x40, + 0xfb, 0xe6, 0xc1, 0xdc, 0x8f, 0x92, 0xb5, 0xa8, + 0xde, 0xc3, 0xe4, 0xf9, 0xaa, 0xb7, 0x90, 0x8d, + 0x36, 0x2b, 0x0c, 0x11, 0x42, 0x5f, 0x78, 0x65, + 0x94, 0x89, 0xae, 0xb3, 0xe0, 0xfd, 0xda, 0xc7, + 0x7c, 0x61, 0x46, 0x5b, 0x08, 0x15, 0x32, 0x2f, + 0x59, 0x44, 0x63, 0x7e, 0x2d, 0x30, 0x17, 0x0a, + 0xb1, 0xac, 0x8b, 0x96, 0xc5, 0xd8, 0xff, 0xe2, + 0x26, 0x3b, 0x1c, 0x01, 0x52, 0x4f, 0x68, 0x75, + 0xce, 0xd3, 0xf4, 0xe9, 0xba, 0xa7, 0x80, 0x9d, + 0xeb, 0xf6, 0xd1, 0xcc, 0x9f, 0x82, 0xa5, 0xb8, + 0x03, 0x1e, 0x39, 0x24, 0x77, 0x6a, 0x4d, 0x50, + 0xa1, 0xbc, 0x9b, 0x86, 0xd5, 0xc8, 0xef, 0xf2, + 0x49, 0x54, 0x73, 0x6e, 0x3d, 0x20, 0x07, 0x1a, + 0x6c, 0x71, 0x56, 0x4b, 0x18, 0x05, 0x22, 0x3f, + 0x84, 0x99, 0xbe, 0xa3, 0xf0, 0xed, 0xca, 0xd7, + 0x35, 0x28, 0x0f, 0x12, 0x41, 0x5c, 0x7b, 0x66, + 0xdd, 0xc0, 0xe7, 0xfa, 0xa9, 0xb4, 0x93, 0x8e, + 0xf8, 0xe5, 0xc2, 0xdf, 0x8c, 0x91, 0xb6, 0xab, + 0x10, 0x0d, 0x2a, 0x37, 0x64, 0x79, 0x5e, 0x43, + 0xb2, 0xaf, 0x88, 0x95, 0xc6, 0xdb, 0xfc, 0xe1, + 0x5a, 0x47, 0x60, 0x7d, 0x2e, 0x33, 0x14, 0x09, + 0x7f, 0x62, 0x45, 0x58, 0x0b, 0x16, 0x31, 0x2c, + 0x97, 0x8a, 0xad, 0xb0, 0xe3, 0xfe, 0xd9, 0xc4, + }, + { + 0x00, 0x1e, 0x3c, 0x22, 0x78, 0x66, 0x44, 0x5a, + 0xf0, 0xee, 0xcc, 0xd2, 0x88, 0x96, 0xb4, 0xaa, + 0xfd, 0xe3, 0xc1, 0xdf, 0x85, 0x9b, 0xb9, 0xa7, + 0x0d, 0x13, 0x31, 0x2f, 0x75, 0x6b, 0x49, 0x57, + 0xe7, 0xf9, 0xdb, 0xc5, 0x9f, 0x81, 0xa3, 0xbd, + 0x17, 0x09, 0x2b, 0x35, 0x6f, 0x71, 0x53, 0x4d, + 0x1a, 0x04, 0x26, 0x38, 0x62, 0x7c, 0x5e, 0x40, + 0xea, 0xf4, 0xd6, 0xc8, 0x92, 0x8c, 0xae, 0xb0, + 0xd3, 0xcd, 0xef, 0xf1, 0xab, 0xb5, 0x97, 0x89, + 0x23, 0x3d, 0x1f, 0x01, 0x5b, 0x45, 0x67, 0x79, + 0x2e, 0x30, 0x12, 0x0c, 0x56, 0x48, 0x6a, 0x74, + 0xde, 0xc0, 0xe2, 0xfc, 0xa6, 0xb8, 0x9a, 0x84, + 0x34, 0x2a, 0x08, 0x16, 0x4c, 0x52, 0x70, 0x6e, + 0xc4, 0xda, 0xf8, 0xe6, 0xbc, 0xa2, 0x80, 0x9e, + 0xc9, 0xd7, 0xf5, 0xeb, 0xb1, 0xaf, 0x8d, 0x93, + 0x39, 0x27, 0x05, 0x1b, 0x41, 0x5f, 0x7d, 0x63, + 0xbb, 0xa5, 0x87, 0x99, 0xc3, 0xdd, 0xff, 0xe1, + 0x4b, 0x55, 0x77, 0x69, 0x33, 0x2d, 0x0f, 0x11, + 0x46, 0x58, 0x7a, 0x64, 0x3e, 0x20, 0x02, 0x1c, + 0xb6, 0xa8, 0x8a, 0x94, 0xce, 0xd0, 0xf2, 0xec, + 0x5c, 0x42, 0x60, 0x7e, 0x24, 0x3a, 0x18, 0x06, + 0xac, 0xb2, 0x90, 0x8e, 0xd4, 0xca, 0xe8, 0xf6, + 0xa1, 0xbf, 0x9d, 0x83, 0xd9, 0xc7, 0xe5, 0xfb, + 0x51, 0x4f, 0x6d, 0x73, 0x29, 0x37, 0x15, 0x0b, + 0x68, 0x76, 0x54, 0x4a, 0x10, 0x0e, 0x2c, 0x32, + 0x98, 0x86, 0xa4, 0xba, 0xe0, 0xfe, 0xdc, 0xc2, + 0x95, 0x8b, 0xa9, 0xb7, 0xed, 0xf3, 0xd1, 0xcf, + 0x65, 0x7b, 0x59, 0x47, 0x1d, 0x03, 0x21, 0x3f, + 0x8f, 0x91, 0xb3, 0xad, 0xf7, 0xe9, 0xcb, 0xd5, + 0x7f, 0x61, 0x43, 0x5d, 0x07, 0x19, 0x3b, 0x25, + 0x72, 0x6c, 0x4e, 0x50, 0x0a, 0x14, 0x36, 0x28, + 0x82, 0x9c, 0xbe, 0xa0, 0xfa, 0xe4, 0xc6, 0xd8, + }, + { + 0x00, 0x1f, 0x3e, 0x21, 0x7c, 0x63, 0x42, 0x5d, + 0xf8, 0xe7, 0xc6, 0xd9, 0x84, 0x9b, 0xba, 0xa5, + 0xed, 0xf2, 0xd3, 0xcc, 0x91, 0x8e, 0xaf, 0xb0, + 0x15, 0x0a, 0x2b, 0x34, 0x69, 0x76, 0x57, 0x48, + 0xc7, 0xd8, 0xf9, 0xe6, 0xbb, 0xa4, 0x85, 0x9a, + 0x3f, 0x20, 0x01, 0x1e, 0x43, 0x5c, 0x7d, 0x62, + 0x2a, 0x35, 0x14, 0x0b, 0x56, 0x49, 0x68, 0x77, + 0xd2, 0xcd, 0xec, 0xf3, 0xae, 0xb1, 0x90, 0x8f, + 0x93, 0x8c, 0xad, 0xb2, 0xef, 0xf0, 0xd1, 0xce, + 0x6b, 0x74, 0x55, 0x4a, 0x17, 0x08, 0x29, 0x36, + 0x7e, 0x61, 0x40, 0x5f, 0x02, 0x1d, 0x3c, 0x23, + 0x86, 0x99, 0xb8, 0xa7, 0xfa, 0xe5, 0xc4, 0xdb, + 0x54, 0x4b, 0x6a, 0x75, 0x28, 0x37, 0x16, 0x09, + 0xac, 0xb3, 0x92, 0x8d, 0xd0, 0xcf, 0xee, 0xf1, + 0xb9, 0xa6, 0x87, 0x98, 0xc5, 0xda, 0xfb, 0xe4, + 0x41, 0x5e, 0x7f, 0x60, 0x3d, 0x22, 0x03, 0x1c, + 0x3b, 0x24, 0x05, 0x1a, 0x47, 0x58, 0x79, 0x66, + 0xc3, 0xdc, 0xfd, 0xe2, 0xbf, 0xa0, 0x81, 0x9e, + 0xd6, 0xc9, 0xe8, 0xf7, 0xaa, 0xb5, 0x94, 0x8b, + 0x2e, 0x31, 0x10, 0x0f, 0x52, 0x4d, 0x6c, 0x73, + 0xfc, 0xe3, 0xc2, 0xdd, 0x80, 0x9f, 0xbe, 0xa1, + 0x04, 0x1b, 0x3a, 0x25, 0x78, 0x67, 0x46, 0x59, + 0x11, 0x0e, 0x2f, 0x30, 0x6d, 0x72, 0x53, 0x4c, + 0xe9, 0xf6, 0xd7, 0xc8, 0x95, 0x8a, 0xab, 0xb4, + 0xa8, 0xb7, 0x96, 0x89, 0xd4, 0xcb, 0xea, 0xf5, + 0x50, 0x4f, 0x6e, 0x71, 0x2c, 0x33, 0x12, 0x0d, + 0x45, 0x5a, 0x7b, 0x64, 0x39, 0x26, 0x07, 0x18, + 0xbd, 0xa2, 0x83, 0x9c, 0xc1, 0xde, 0xff, 0xe0, + 0x6f, 0x70, 0x51, 0x4e, 0x13, 0x0c, 0x2d, 0x32, + 0x97, 0x88, 0xa9, 0xb6, 0xeb, 0xf4, 0xd5, 0xca, + 0x82, 0x9d, 0xbc, 0xa3, 0xfe, 0xe1, 0xc0, 0xdf, + 0x7a, 0x65, 0x44, 0x5b, 0x06, 0x19, 0x38, 0x27, + }, + { + 0x00, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0, + 0x1d, 0x3d, 0x5d, 0x7d, 0x9d, 0xbd, 0xdd, 0xfd, + 0x3a, 0x1a, 0x7a, 0x5a, 0xba, 0x9a, 0xfa, 0xda, + 0x27, 0x07, 0x67, 0x47, 0xa7, 0x87, 0xe7, 0xc7, + 0x74, 0x54, 0x34, 0x14, 0xf4, 0xd4, 0xb4, 0x94, + 0x69, 0x49, 0x29, 0x09, 0xe9, 0xc9, 0xa9, 0x89, + 0x4e, 0x6e, 0x0e, 0x2e, 0xce, 0xee, 0x8e, 0xae, + 0x53, 0x73, 0x13, 0x33, 0xd3, 0xf3, 0x93, 0xb3, + 0xe8, 0xc8, 0xa8, 0x88, 0x68, 0x48, 0x28, 0x08, + 0xf5, 0xd5, 0xb5, 0x95, 0x75, 0x55, 0x35, 0x15, + 0xd2, 0xf2, 0x92, 0xb2, 0x52, 0x72, 0x12, 0x32, + 0xcf, 0xef, 0x8f, 0xaf, 0x4f, 0x6f, 0x0f, 0x2f, + 0x9c, 0xbc, 0xdc, 0xfc, 0x1c, 0x3c, 0x5c, 0x7c, + 0x81, 0xa1, 0xc1, 0xe1, 0x01, 0x21, 0x41, 0x61, + 0xa6, 0x86, 0xe6, 0xc6, 0x26, 0x06, 0x66, 0x46, + 0xbb, 0x9b, 0xfb, 0xdb, 0x3b, 0x1b, 0x7b, 0x5b, + 0xcd, 0xed, 0x8d, 0xad, 0x4d, 0x6d, 0x0d, 0x2d, + 0xd0, 0xf0, 0x90, 0xb0, 0x50, 0x70, 0x10, 0x30, + 0xf7, 0xd7, 0xb7, 0x97, 0x77, 0x57, 0x37, 0x17, + 0xea, 0xca, 0xaa, 0x8a, 0x6a, 0x4a, 0x2a, 0x0a, + 0xb9, 0x99, 0xf9, 0xd9, 0x39, 0x19, 0x79, 0x59, + 0xa4, 0x84, 0xe4, 0xc4, 0x24, 0x04, 0x64, 0x44, + 0x83, 0xa3, 0xc3, 0xe3, 0x03, 0x23, 0x43, 0x63, + 0x9e, 0xbe, 0xde, 0xfe, 0x1e, 0x3e, 0x5e, 0x7e, + 0x25, 0x05, 0x65, 0x45, 0xa5, 0x85, 0xe5, 0xc5, + 0x38, 0x18, 0x78, 0x58, 0xb8, 0x98, 0xf8, 0xd8, + 0x1f, 0x3f, 0x5f, 0x7f, 0x9f, 0xbf, 0xdf, 0xff, + 0x02, 0x22, 0x42, 0x62, 0x82, 0xa2, 0xc2, 0xe2, + 0x51, 0x71, 0x11, 0x31, 0xd1, 0xf1, 0x91, 0xb1, + 0x4c, 0x6c, 0x0c, 0x2c, 0xcc, 0xec, 0x8c, 0xac, + 0x6b, 0x4b, 0x2b, 0x0b, 0xeb, 0xcb, 0xab, 0x8b, + 0x76, 0x56, 0x36, 0x16, 0xf6, 0xd6, 0xb6, 0x96, + }, + { + 0x00, 0x21, 0x42, 0x63, 0x84, 0xa5, 0xc6, 0xe7, + 0x15, 0x34, 0x57, 0x76, 0x91, 0xb0, 0xd3, 0xf2, + 0x2a, 0x0b, 0x68, 0x49, 0xae, 0x8f, 0xec, 0xcd, + 0x3f, 0x1e, 0x7d, 0x5c, 0xbb, 0x9a, 0xf9, 0xd8, + 0x54, 0x75, 0x16, 0x37, 0xd0, 0xf1, 0x92, 0xb3, + 0x41, 0x60, 0x03, 0x22, 0xc5, 0xe4, 0x87, 0xa6, + 0x7e, 0x5f, 0x3c, 0x1d, 0xfa, 0xdb, 0xb8, 0x99, + 0x6b, 0x4a, 0x29, 0x08, 0xef, 0xce, 0xad, 0x8c, + 0xa8, 0x89, 0xea, 0xcb, 0x2c, 0x0d, 0x6e, 0x4f, + 0xbd, 0x9c, 0xff, 0xde, 0x39, 0x18, 0x7b, 0x5a, + 0x82, 0xa3, 0xc0, 0xe1, 0x06, 0x27, 0x44, 0x65, + 0x97, 0xb6, 0xd5, 0xf4, 0x13, 0x32, 0x51, 0x70, + 0xfc, 0xdd, 0xbe, 0x9f, 0x78, 0x59, 0x3a, 0x1b, + 0xe9, 0xc8, 0xab, 0x8a, 0x6d, 0x4c, 0x2f, 0x0e, + 0xd6, 0xf7, 0x94, 0xb5, 0x52, 0x73, 0x10, 0x31, + 0xc3, 0xe2, 0x81, 0xa0, 0x47, 0x66, 0x05, 0x24, + 0x4d, 0x6c, 0x0f, 0x2e, 0xc9, 0xe8, 0x8b, 0xaa, + 0x58, 0x79, 0x1a, 0x3b, 0xdc, 0xfd, 0x9e, 0xbf, + 0x67, 0x46, 0x25, 0x04, 0xe3, 0xc2, 0xa1, 0x80, + 0x72, 0x53, 0x30, 0x11, 0xf6, 0xd7, 0xb4, 0x95, + 0x19, 0x38, 0x5b, 0x7a, 0x9d, 0xbc, 0xdf, 0xfe, + 0x0c, 0x2d, 0x4e, 0x6f, 0x88, 0xa9, 0xca, 0xeb, + 0x33, 0x12, 0x71, 0x50, 0xb7, 0x96, 0xf5, 0xd4, + 0x26, 0x07, 0x64, 0x45, 0xa2, 0x83, 0xe0, 0xc1, + 0xe5, 0xc4, 0xa7, 0x86, 0x61, 0x40, 0x23, 0x02, + 0xf0, 0xd1, 0xb2, 0x93, 0x74, 0x55, 0x36, 0x17, + 0xcf, 0xee, 0x8d, 0xac, 0x4b, 0x6a, 0x09, 0x28, + 0xda, 0xfb, 0x98, 0xb9, 0x5e, 0x7f, 0x1c, 0x3d, + 0xb1, 0x90, 0xf3, 0xd2, 0x35, 0x14, 0x77, 0x56, + 0xa4, 0x85, 0xe6, 0xc7, 0x20, 0x01, 0x62, 0x43, + 0x9b, 0xba, 0xd9, 0xf8, 0x1f, 0x3e, 0x5d, 0x7c, + 0x8e, 0xaf, 0xcc, 0xed, 0x0a, 0x2b, 0x48, 0x69, + }, + { + 0x00, 0x22, 0x44, 0x66, 0x88, 0xaa, 0xcc, 0xee, + 0x0d, 0x2f, 0x49, 0x6b, 0x85, 0xa7, 0xc1, 0xe3, + 0x1a, 0x38, 0x5e, 0x7c, 0x92, 0xb0, 0xd6, 0xf4, + 0x17, 0x35, 0x53, 0x71, 0x9f, 0xbd, 0xdb, 0xf9, + 0x34, 0x16, 0x70, 0x52, 0xbc, 0x9e, 0xf8, 0xda, + 0x39, 0x1b, 0x7d, 0x5f, 0xb1, 0x93, 0xf5, 0xd7, + 0x2e, 0x0c, 0x6a, 0x48, 0xa6, 0x84, 0xe2, 0xc0, + 0x23, 0x01, 0x67, 0x45, 0xab, 0x89, 0xef, 0xcd, + 0x68, 0x4a, 0x2c, 0x0e, 0xe0, 0xc2, 0xa4, 0x86, + 0x65, 0x47, 0x21, 0x03, 0xed, 0xcf, 0xa9, 0x8b, + 0x72, 0x50, 0x36, 0x14, 0xfa, 0xd8, 0xbe, 0x9c, + 0x7f, 0x5d, 0x3b, 0x19, 0xf7, 0xd5, 0xb3, 0x91, + 0x5c, 0x7e, 0x18, 0x3a, 0xd4, 0xf6, 0x90, 0xb2, + 0x51, 0x73, 0x15, 0x37, 0xd9, 0xfb, 0x9d, 0xbf, + 0x46, 0x64, 0x02, 0x20, 0xce, 0xec, 0x8a, 0xa8, + 0x4b, 0x69, 0x0f, 0x2d, 0xc3, 0xe1, 0x87, 0xa5, + 0xd0, 0xf2, 0x94, 0xb6, 0x58, 0x7a, 0x1c, 0x3e, + 0xdd, 0xff, 0x99, 0xbb, 0x55, 0x77, 0x11, 0x33, + 0xca, 0xe8, 0x8e, 0xac, 0x42, 0x60, 0x06, 0x24, + 0xc7, 0xe5, 0x83, 0xa1, 0x4f, 0x6d, 0x0b, 0x29, + 0xe4, 0xc6, 0xa0, 0x82, 0x6c, 0x4e, 0x28, 0x0a, + 0xe9, 0xcb, 0xad, 0x8f, 0x61, 0x43, 0x25, 0x07, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0xf3, 0xd1, 0xb7, 0x95, 0x7b, 0x59, 0x3f, 0x1d, + 0xb8, 0x9a, 0xfc, 0xde, 0x30, 0x12, 0x74, 0x56, + 0xb5, 0x97, 0xf1, 0xd3, 0x3d, 0x1f, 0x79, 0x5b, + 0xa2, 0x80, 0xe6, 0xc4, 0x2a, 0x08, 0x6e, 0x4c, + 0xaf, 0x8d, 0xeb, 0xc9, 0x27, 0x05, 0x63, 0x41, + 0x8c, 0xae, 0xc8, 0xea, 0x04, 0x26, 0x40, 0x62, + 0x81, 0xa3, 0xc5, 0xe7, 0x09, 0x2b, 0x4d, 0x6f, + 0x96, 0xb4, 0xd2, 0xf0, 0x1e, 0x3c, 0x5a, 0x78, + 0x9b, 0xb9, 0xdf, 0xfd, 0x13, 0x31, 0x57, 0x75, + }, + { + 0x00, 0x23, 0x46, 0x65, 0x8c, 0xaf, 0xca, 0xe9, + 0x05, 0x26, 0x43, 0x60, 0x89, 0xaa, 0xcf, 0xec, + 0x0a, 0x29, 0x4c, 0x6f, 0x86, 0xa5, 0xc0, 0xe3, + 0x0f, 0x2c, 0x49, 0x6a, 0x83, 0xa0, 0xc5, 0xe6, + 0x14, 0x37, 0x52, 0x71, 0x98, 0xbb, 0xde, 0xfd, + 0x11, 0x32, 0x57, 0x74, 0x9d, 0xbe, 0xdb, 0xf8, + 0x1e, 0x3d, 0x58, 0x7b, 0x92, 0xb1, 0xd4, 0xf7, + 0x1b, 0x38, 0x5d, 0x7e, 0x97, 0xb4, 0xd1, 0xf2, + 0x28, 0x0b, 0x6e, 0x4d, 0xa4, 0x87, 0xe2, 0xc1, + 0x2d, 0x0e, 0x6b, 0x48, 0xa1, 0x82, 0xe7, 0xc4, + 0x22, 0x01, 0x64, 0x47, 0xae, 0x8d, 0xe8, 0xcb, + 0x27, 0x04, 0x61, 0x42, 0xab, 0x88, 0xed, 0xce, + 0x3c, 0x1f, 0x7a, 0x59, 0xb0, 0x93, 0xf6, 0xd5, + 0x39, 0x1a, 0x7f, 0x5c, 0xb5, 0x96, 0xf3, 0xd0, + 0x36, 0x15, 0x70, 0x53, 0xba, 0x99, 0xfc, 0xdf, + 0x33, 0x10, 0x75, 0x56, 0xbf, 0x9c, 0xf9, 0xda, + 0x50, 0x73, 0x16, 0x35, 0xdc, 0xff, 0x9a, 0xb9, + 0x55, 0x76, 0x13, 0x30, 0xd9, 0xfa, 0x9f, 0xbc, + 0x5a, 0x79, 0x1c, 0x3f, 0xd6, 0xf5, 0x90, 0xb3, + 0x5f, 0x7c, 0x19, 0x3a, 0xd3, 0xf0, 0x95, 0xb6, + 0x44, 0x67, 0x02, 0x21, 0xc8, 0xeb, 0x8e, 0xad, + 0x41, 0x62, 0x07, 0x24, 0xcd, 0xee, 0x8b, 0xa8, + 0x4e, 0x6d, 0x08, 0x2b, 0xc2, 0xe1, 0x84, 0xa7, + 0x4b, 0x68, 0x0d, 0x2e, 0xc7, 0xe4, 0x81, 0xa2, + 0x78, 0x5b, 0x3e, 0x1d, 0xf4, 0xd7, 0xb2, 0x91, + 0x7d, 0x5e, 0x3b, 0x18, 0xf1, 0xd2, 0xb7, 0x94, + 0x72, 0x51, 0x34, 0x17, 0xfe, 0xdd, 0xb8, 0x9b, + 0x77, 0x54, 0x31, 0x12, 0xfb, 0xd8, 0xbd, 0x9e, + 0x6c, 0x4f, 0x2a, 0x09, 0xe0, 0xc3, 0xa6, 0x85, + 0x69, 0x4a, 0x2f, 0x0c, 0xe5, 0xc6, 0xa3, 0x80, + 0x66, 0x45, 0x20, 0x03, 0xea, 0xc9, 0xac, 0x8f, + 0x63, 0x40, 0x25, 0x06, 0xef, 0xcc, 0xa9, 0x8a, + }, + { + 0x00, 0x24, 0x48, 0x6c, 0x90, 0xb4, 0xd8, 0xfc, + 0x3d, 0x19, 0x75, 0x51, 0xad, 0x89, 0xe5, 0xc1, + 0x7a, 0x5e, 0x32, 0x16, 0xea, 0xce, 0xa2, 0x86, + 0x47, 0x63, 0x0f, 0x2b, 0xd7, 0xf3, 0x9f, 0xbb, + 0xf4, 0xd0, 0xbc, 0x98, 0x64, 0x40, 0x2c, 0x08, + 0xc9, 0xed, 0x81, 0xa5, 0x59, 0x7d, 0x11, 0x35, + 0x8e, 0xaa, 0xc6, 0xe2, 0x1e, 0x3a, 0x56, 0x72, + 0xb3, 0x97, 0xfb, 0xdf, 0x23, 0x07, 0x6b, 0x4f, + 0xf5, 0xd1, 0xbd, 0x99, 0x65, 0x41, 0x2d, 0x09, + 0xc8, 0xec, 0x80, 0xa4, 0x58, 0x7c, 0x10, 0x34, + 0x8f, 0xab, 0xc7, 0xe3, 0x1f, 0x3b, 0x57, 0x73, + 0xb2, 0x96, 0xfa, 0xde, 0x22, 0x06, 0x6a, 0x4e, + 0x01, 0x25, 0x49, 0x6d, 0x91, 0xb5, 0xd9, 0xfd, + 0x3c, 0x18, 0x74, 0x50, 0xac, 0x88, 0xe4, 0xc0, + 0x7b, 0x5f, 0x33, 0x17, 0xeb, 0xcf, 0xa3, 0x87, + 0x46, 0x62, 0x0e, 0x2a, 0xd6, 0xf2, 0x9e, 0xba, + 0xf7, 0xd3, 0xbf, 0x9b, 0x67, 0x43, 0x2f, 0x0b, + 0xca, 0xee, 0x82, 0xa6, 0x5a, 0x7e, 0x12, 0x36, + 0x8d, 0xa9, 0xc5, 0xe1, 0x1d, 0x39, 0x55, 0x71, + 0xb0, 0x94, 0xf8, 0xdc, 0x20, 0x04, 0x68, 0x4c, + 0x03, 0x27, 0x4b, 0x6f, 0x93, 0xb7, 0xdb, 0xff, + 0x3e, 0x1a, 0x76, 0x52, 0xae, 0x8a, 0xe6, 0xc2, + 0x79, 0x5d, 0x31, 0x15, 0xe9, 0xcd, 0xa1, 0x85, + 0x44, 0x60, 0x0c, 0x28, 0xd4, 0xf0, 0x9c, 0xb8, + 0x02, 0x26, 0x4a, 0x6e, 0x92, 0xb6, 0xda, 0xfe, + 0x3f, 0x1b, 0x77, 0x53, 0xaf, 0x8b, 0xe7, 0xc3, + 0x78, 0x5c, 0x30, 0x14, 0xe8, 0xcc, 0xa0, 0x84, + 0x45, 0x61, 0x0d, 0x29, 0xd5, 0xf1, 0x9d, 0xb9, + 0xf6, 0xd2, 0xbe, 0x9a, 0x66, 0x42, 0x2e, 0x0a, + 0xcb, 0xef, 0x83, 0xa7, 0x5b, 0x7f, 0x13, 0x37, + 0x8c, 0xa8, 0xc4, 0xe0, 0x1c, 0x38, 0x54, 0x70, + 0xb1, 0x95, 0xf9, 0xdd, 0x21, 0x05, 0x69, 0x4d, + }, + { + 0x00, 0x25, 0x4a, 0x6f, 0x94, 0xb1, 0xde, 0xfb, + 0x35, 0x10, 0x7f, 0x5a, 0xa1, 0x84, 0xeb, 0xce, + 0x6a, 0x4f, 0x20, 0x05, 0xfe, 0xdb, 0xb4, 0x91, + 0x5f, 0x7a, 0x15, 0x30, 0xcb, 0xee, 0x81, 0xa4, + 0xd4, 0xf1, 0x9e, 0xbb, 0x40, 0x65, 0x0a, 0x2f, + 0xe1, 0xc4, 0xab, 0x8e, 0x75, 0x50, 0x3f, 0x1a, + 0xbe, 0x9b, 0xf4, 0xd1, 0x2a, 0x0f, 0x60, 0x45, + 0x8b, 0xae, 0xc1, 0xe4, 0x1f, 0x3a, 0x55, 0x70, + 0xb5, 0x90, 0xff, 0xda, 0x21, 0x04, 0x6b, 0x4e, + 0x80, 0xa5, 0xca, 0xef, 0x14, 0x31, 0x5e, 0x7b, + 0xdf, 0xfa, 0x95, 0xb0, 0x4b, 0x6e, 0x01, 0x24, + 0xea, 0xcf, 0xa0, 0x85, 0x7e, 0x5b, 0x34, 0x11, + 0x61, 0x44, 0x2b, 0x0e, 0xf5, 0xd0, 0xbf, 0x9a, + 0x54, 0x71, 0x1e, 0x3b, 0xc0, 0xe5, 0x8a, 0xaf, + 0x0b, 0x2e, 0x41, 0x64, 0x9f, 0xba, 0xd5, 0xf0, + 0x3e, 0x1b, 0x74, 0x51, 0xaa, 0x8f, 0xe0, 0xc5, + 0x77, 0x52, 0x3d, 0x18, 0xe3, 0xc6, 0xa9, 0x8c, + 0x42, 0x67, 0x08, 0x2d, 0xd6, 0xf3, 0x9c, 0xb9, + 0x1d, 0x38, 0x57, 0x72, 0x89, 0xac, 0xc3, 0xe6, + 0x28, 0x0d, 0x62, 0x47, 0xbc, 0x99, 0xf6, 0xd3, + 0xa3, 0x86, 0xe9, 0xcc, 0x37, 0x12, 0x7d, 0x58, + 0x96, 0xb3, 0xdc, 0xf9, 0x02, 0x27, 0x48, 0x6d, + 0xc9, 0xec, 0x83, 0xa6, 0x5d, 0x78, 0x17, 0x32, + 0xfc, 0xd9, 0xb6, 0x93, 0x68, 0x4d, 0x22, 0x07, + 0xc2, 0xe7, 0x88, 0xad, 0x56, 0x73, 0x1c, 0x39, + 0xf7, 0xd2, 0xbd, 0x98, 0x63, 0x46, 0x29, 0x0c, + 0xa8, 0x8d, 0xe2, 0xc7, 0x3c, 0x19, 0x76, 0x53, + 0x9d, 0xb8, 0xd7, 0xf2, 0x09, 0x2c, 0x43, 0x66, + 0x16, 0x33, 0x5c, 0x79, 0x82, 0xa7, 0xc8, 0xed, + 0x23, 0x06, 0x69, 0x4c, 0xb7, 0x92, 0xfd, 0xd8, + 0x7c, 0x59, 0x36, 0x13, 0xe8, 0xcd, 0xa2, 0x87, + 0x49, 0x6c, 0x03, 0x26, 0xdd, 0xf8, 0x97, 0xb2, + }, + { + 0x00, 0x26, 0x4c, 0x6a, 0x98, 0xbe, 0xd4, 0xf2, + 0x2d, 0x0b, 0x61, 0x47, 0xb5, 0x93, 0xf9, 0xdf, + 0x5a, 0x7c, 0x16, 0x30, 0xc2, 0xe4, 0x8e, 0xa8, + 0x77, 0x51, 0x3b, 0x1d, 0xef, 0xc9, 0xa3, 0x85, + 0xb4, 0x92, 0xf8, 0xde, 0x2c, 0x0a, 0x60, 0x46, + 0x99, 0xbf, 0xd5, 0xf3, 0x01, 0x27, 0x4d, 0x6b, + 0xee, 0xc8, 0xa2, 0x84, 0x76, 0x50, 0x3a, 0x1c, + 0xc3, 0xe5, 0x8f, 0xa9, 0x5b, 0x7d, 0x17, 0x31, + 0x75, 0x53, 0x39, 0x1f, 0xed, 0xcb, 0xa1, 0x87, + 0x58, 0x7e, 0x14, 0x32, 0xc0, 0xe6, 0x8c, 0xaa, + 0x2f, 0x09, 0x63, 0x45, 0xb7, 0x91, 0xfb, 0xdd, + 0x02, 0x24, 0x4e, 0x68, 0x9a, 0xbc, 0xd6, 0xf0, + 0xc1, 0xe7, 0x8d, 0xab, 0x59, 0x7f, 0x15, 0x33, + 0xec, 0xca, 0xa0, 0x86, 0x74, 0x52, 0x38, 0x1e, + 0x9b, 0xbd, 0xd7, 0xf1, 0x03, 0x25, 0x4f, 0x69, + 0xb6, 0x90, 0xfa, 0xdc, 0x2e, 0x08, 0x62, 0x44, + 0xea, 0xcc, 0xa6, 0x80, 0x72, 0x54, 0x3e, 0x18, + 0xc7, 0xe1, 0x8b, 0xad, 0x5f, 0x79, 0x13, 0x35, + 0xb0, 0x96, 0xfc, 0xda, 0x28, 0x0e, 0x64, 0x42, + 0x9d, 0xbb, 0xd1, 0xf7, 0x05, 0x23, 0x49, 0x6f, + 0x5e, 0x78, 0x12, 0x34, 0xc6, 0xe0, 0x8a, 0xac, + 0x73, 0x55, 0x3f, 0x19, 0xeb, 0xcd, 0xa7, 0x81, + 0x04, 0x22, 0x48, 0x6e, 0x9c, 0xba, 0xd0, 0xf6, + 0x29, 0x0f, 0x65, 0x43, 0xb1, 0x97, 0xfd, 0xdb, + 0x9f, 0xb9, 0xd3, 0xf5, 0x07, 0x21, 0x4b, 0x6d, + 0xb2, 0x94, 0xfe, 0xd8, 0x2a, 0x0c, 0x66, 0x40, + 0xc5, 0xe3, 0x89, 0xaf, 0x5d, 0x7b, 0x11, 0x37, + 0xe8, 0xce, 0xa4, 0x82, 0x70, 0x56, 0x3c, 0x1a, + 0x2b, 0x0d, 0x67, 0x41, 0xb3, 0x95, 0xff, 0xd9, + 0x06, 0x20, 0x4a, 0x6c, 0x9e, 0xb8, 0xd2, 0xf4, + 0x71, 0x57, 0x3d, 0x1b, 0xe9, 0xcf, 0xa5, 0x83, + 0x5c, 0x7a, 0x10, 0x36, 0xc4, 0xe2, 0x88, 0xae, + }, + { + 0x00, 0x27, 0x4e, 0x69, 0x9c, 0xbb, 0xd2, 0xf5, + 0x25, 0x02, 0x6b, 0x4c, 0xb9, 0x9e, 0xf7, 0xd0, + 0x4a, 0x6d, 0x04, 0x23, 0xd6, 0xf1, 0x98, 0xbf, + 0x6f, 0x48, 0x21, 0x06, 0xf3, 0xd4, 0xbd, 0x9a, + 0x94, 0xb3, 0xda, 0xfd, 0x08, 0x2f, 0x46, 0x61, + 0xb1, 0x96, 0xff, 0xd8, 0x2d, 0x0a, 0x63, 0x44, + 0xde, 0xf9, 0x90, 0xb7, 0x42, 0x65, 0x0c, 0x2b, + 0xfb, 0xdc, 0xb5, 0x92, 0x67, 0x40, 0x29, 0x0e, + 0x35, 0x12, 0x7b, 0x5c, 0xa9, 0x8e, 0xe7, 0xc0, + 0x10, 0x37, 0x5e, 0x79, 0x8c, 0xab, 0xc2, 0xe5, + 0x7f, 0x58, 0x31, 0x16, 0xe3, 0xc4, 0xad, 0x8a, + 0x5a, 0x7d, 0x14, 0x33, 0xc6, 0xe1, 0x88, 0xaf, + 0xa1, 0x86, 0xef, 0xc8, 0x3d, 0x1a, 0x73, 0x54, + 0x84, 0xa3, 0xca, 0xed, 0x18, 0x3f, 0x56, 0x71, + 0xeb, 0xcc, 0xa5, 0x82, 0x77, 0x50, 0x39, 0x1e, + 0xce, 0xe9, 0x80, 0xa7, 0x52, 0x75, 0x1c, 0x3b, + 0x6a, 0x4d, 0x24, 0x03, 0xf6, 0xd1, 0xb8, 0x9f, + 0x4f, 0x68, 0x01, 0x26, 0xd3, 0xf4, 0x9d, 0xba, + 0x20, 0x07, 0x6e, 0x49, 0xbc, 0x9b, 0xf2, 0xd5, + 0x05, 0x22, 0x4b, 0x6c, 0x99, 0xbe, 0xd7, 0xf0, + 0xfe, 0xd9, 0xb0, 0x97, 0x62, 0x45, 0x2c, 0x0b, + 0xdb, 0xfc, 0x95, 0xb2, 0x47, 0x60, 0x09, 0x2e, + 0xb4, 0x93, 0xfa, 0xdd, 0x28, 0x0f, 0x66, 0x41, + 0x91, 0xb6, 0xdf, 0xf8, 0x0d, 0x2a, 0x43, 0x64, + 0x5f, 0x78, 0x11, 0x36, 0xc3, 0xe4, 0x8d, 0xaa, + 0x7a, 0x5d, 0x34, 0x13, 0xe6, 0xc1, 0xa8, 0x8f, + 0x15, 0x32, 0x5b, 0x7c, 0x89, 0xae, 0xc7, 0xe0, + 0x30, 0x17, 0x7e, 0x59, 0xac, 0x8b, 0xe2, 0xc5, + 0xcb, 0xec, 0x85, 0xa2, 0x57, 0x70, 0x19, 0x3e, + 0xee, 0xc9, 0xa0, 0x87, 0x72, 0x55, 0x3c, 0x1b, + 0x81, 0xa6, 0xcf, 0xe8, 0x1d, 0x3a, 0x53, 0x74, + 0xa4, 0x83, 0xea, 0xcd, 0x38, 0x1f, 0x76, 0x51, + }, + { + 0x00, 0x28, 0x50, 0x78, 0xa0, 0x88, 0xf0, 0xd8, + 0x5d, 0x75, 0x0d, 0x25, 0xfd, 0xd5, 0xad, 0x85, + 0xba, 0x92, 0xea, 0xc2, 0x1a, 0x32, 0x4a, 0x62, + 0xe7, 0xcf, 0xb7, 0x9f, 0x47, 0x6f, 0x17, 0x3f, + 0x69, 0x41, 0x39, 0x11, 0xc9, 0xe1, 0x99, 0xb1, + 0x34, 0x1c, 0x64, 0x4c, 0x94, 0xbc, 0xc4, 0xec, + 0xd3, 0xfb, 0x83, 0xab, 0x73, 0x5b, 0x23, 0x0b, + 0x8e, 0xa6, 0xde, 0xf6, 0x2e, 0x06, 0x7e, 0x56, + 0xd2, 0xfa, 0x82, 0xaa, 0x72, 0x5a, 0x22, 0x0a, + 0x8f, 0xa7, 0xdf, 0xf7, 0x2f, 0x07, 0x7f, 0x57, + 0x68, 0x40, 0x38, 0x10, 0xc8, 0xe0, 0x98, 0xb0, + 0x35, 0x1d, 0x65, 0x4d, 0x95, 0xbd, 0xc5, 0xed, + 0xbb, 0x93, 0xeb, 0xc3, 0x1b, 0x33, 0x4b, 0x63, + 0xe6, 0xce, 0xb6, 0x9e, 0x46, 0x6e, 0x16, 0x3e, + 0x01, 0x29, 0x51, 0x79, 0xa1, 0x89, 0xf1, 0xd9, + 0x5c, 0x74, 0x0c, 0x24, 0xfc, 0xd4, 0xac, 0x84, + 0xb9, 0x91, 0xe9, 0xc1, 0x19, 0x31, 0x49, 0x61, + 0xe4, 0xcc, 0xb4, 0x9c, 0x44, 0x6c, 0x14, 0x3c, + 0x03, 0x2b, 0x53, 0x7b, 0xa3, 0x8b, 0xf3, 0xdb, + 0x5e, 0x76, 0x0e, 0x26, 0xfe, 0xd6, 0xae, 0x86, + 0xd0, 0xf8, 0x80, 0xa8, 0x70, 0x58, 0x20, 0x08, + 0x8d, 0xa5, 0xdd, 0xf5, 0x2d, 0x05, 0x7d, 0x55, + 0x6a, 0x42, 0x3a, 0x12, 0xca, 0xe2, 0x9a, 0xb2, + 0x37, 0x1f, 0x67, 0x4f, 0x97, 0xbf, 0xc7, 0xef, + 0x6b, 0x43, 0x3b, 0x13, 0xcb, 0xe3, 0x9b, 0xb3, + 0x36, 0x1e, 0x66, 0x4e, 0x96, 0xbe, 0xc6, 0xee, + 0xd1, 0xf9, 0x81, 0xa9, 0x71, 0x59, 0x21, 0x09, + 0x8c, 0xa4, 0xdc, 0xf4, 0x2c, 0x04, 0x7c, 0x54, + 0x02, 0x2a, 0x52, 0x7a, 0xa2, 0x8a, 0xf2, 0xda, + 0x5f, 0x77, 0x0f, 0x27, 0xff, 0xd7, 0xaf, 0x87, + 0xb8, 0x90, 0xe8, 0xc0, 0x18, 0x30, 0x48, 0x60, + 0xe5, 0xcd, 0xb5, 0x9d, 0x45, 0x6d, 0x15, 0x3d, + }, + { + 0x00, 0x29, 0x52, 0x7b, 0xa4, 0x8d, 0xf6, 0xdf, + 0x55, 0x7c, 0x07, 0x2e, 0xf1, 0xd8, 0xa3, 0x8a, + 0xaa, 0x83, 0xf8, 0xd1, 0x0e, 0x27, 0x5c, 0x75, + 0xff, 0xd6, 0xad, 0x84, 0x5b, 0x72, 0x09, 0x20, + 0x49, 0x60, 0x1b, 0x32, 0xed, 0xc4, 0xbf, 0x96, + 0x1c, 0x35, 0x4e, 0x67, 0xb8, 0x91, 0xea, 0xc3, + 0xe3, 0xca, 0xb1, 0x98, 0x47, 0x6e, 0x15, 0x3c, + 0xb6, 0x9f, 0xe4, 0xcd, 0x12, 0x3b, 0x40, 0x69, + 0x92, 0xbb, 0xc0, 0xe9, 0x36, 0x1f, 0x64, 0x4d, + 0xc7, 0xee, 0x95, 0xbc, 0x63, 0x4a, 0x31, 0x18, + 0x38, 0x11, 0x6a, 0x43, 0x9c, 0xb5, 0xce, 0xe7, + 0x6d, 0x44, 0x3f, 0x16, 0xc9, 0xe0, 0x9b, 0xb2, + 0xdb, 0xf2, 0x89, 0xa0, 0x7f, 0x56, 0x2d, 0x04, + 0x8e, 0xa7, 0xdc, 0xf5, 0x2a, 0x03, 0x78, 0x51, + 0x71, 0x58, 0x23, 0x0a, 0xd5, 0xfc, 0x87, 0xae, + 0x24, 0x0d, 0x76, 0x5f, 0x80, 0xa9, 0xd2, 0xfb, + 0x39, 0x10, 0x6b, 0x42, 0x9d, 0xb4, 0xcf, 0xe6, + 0x6c, 0x45, 0x3e, 0x17, 0xc8, 0xe1, 0x9a, 0xb3, + 0x93, 0xba, 0xc1, 0xe8, 0x37, 0x1e, 0x65, 0x4c, + 0xc6, 0xef, 0x94, 0xbd, 0x62, 0x4b, 0x30, 0x19, + 0x70, 0x59, 0x22, 0x0b, 0xd4, 0xfd, 0x86, 0xaf, + 0x25, 0x0c, 0x77, 0x5e, 0x81, 0xa8, 0xd3, 0xfa, + 0xda, 0xf3, 0x88, 0xa1, 0x7e, 0x57, 0x2c, 0x05, + 0x8f, 0xa6, 0xdd, 0xf4, 0x2b, 0x02, 0x79, 0x50, + 0xab, 0x82, 0xf9, 0xd0, 0x0f, 0x26, 0x5d, 0x74, + 0xfe, 0xd7, 0xac, 0x85, 0x5a, 0x73, 0x08, 0x21, + 0x01, 0x28, 0x53, 0x7a, 0xa5, 0x8c, 0xf7, 0xde, + 0x54, 0x7d, 0x06, 0x2f, 0xf0, 0xd9, 0xa2, 0x8b, + 0xe2, 0xcb, 0xb0, 0x99, 0x46, 0x6f, 0x14, 0x3d, + 0xb7, 0x9e, 0xe5, 0xcc, 0x13, 0x3a, 0x41, 0x68, + 0x48, 0x61, 0x1a, 0x33, 0xec, 0xc5, 0xbe, 0x97, + 0x1d, 0x34, 0x4f, 0x66, 0xb9, 0x90, 0xeb, 0xc2, + }, + { + 0x00, 0x2a, 0x54, 0x7e, 0xa8, 0x82, 0xfc, 0xd6, + 0x4d, 0x67, 0x19, 0x33, 0xe5, 0xcf, 0xb1, 0x9b, + 0x9a, 0xb0, 0xce, 0xe4, 0x32, 0x18, 0x66, 0x4c, + 0xd7, 0xfd, 0x83, 0xa9, 0x7f, 0x55, 0x2b, 0x01, + 0x29, 0x03, 0x7d, 0x57, 0x81, 0xab, 0xd5, 0xff, + 0x64, 0x4e, 0x30, 0x1a, 0xcc, 0xe6, 0x98, 0xb2, + 0xb3, 0x99, 0xe7, 0xcd, 0x1b, 0x31, 0x4f, 0x65, + 0xfe, 0xd4, 0xaa, 0x80, 0x56, 0x7c, 0x02, 0x28, + 0x52, 0x78, 0x06, 0x2c, 0xfa, 0xd0, 0xae, 0x84, + 0x1f, 0x35, 0x4b, 0x61, 0xb7, 0x9d, 0xe3, 0xc9, + 0xc8, 0xe2, 0x9c, 0xb6, 0x60, 0x4a, 0x34, 0x1e, + 0x85, 0xaf, 0xd1, 0xfb, 0x2d, 0x07, 0x79, 0x53, + 0x7b, 0x51, 0x2f, 0x05, 0xd3, 0xf9, 0x87, 0xad, + 0x36, 0x1c, 0x62, 0x48, 0x9e, 0xb4, 0xca, 0xe0, + 0xe1, 0xcb, 0xb5, 0x9f, 0x49, 0x63, 0x1d, 0x37, + 0xac, 0x86, 0xf8, 0xd2, 0x04, 0x2e, 0x50, 0x7a, + 0xa4, 0x8e, 0xf0, 0xda, 0x0c, 0x26, 0x58, 0x72, + 0xe9, 0xc3, 0xbd, 0x97, 0x41, 0x6b, 0x15, 0x3f, + 0x3e, 0x14, 0x6a, 0x40, 0x96, 0xbc, 0xc2, 0xe8, + 0x73, 0x59, 0x27, 0x0d, 0xdb, 0xf1, 0x8f, 0xa5, + 0x8d, 0xa7, 0xd9, 0xf3, 0x25, 0x0f, 0x71, 0x5b, + 0xc0, 0xea, 0x94, 0xbe, 0x68, 0x42, 0x3c, 0x16, + 0x17, 0x3d, 0x43, 0x69, 0xbf, 0x95, 0xeb, 0xc1, + 0x5a, 0x70, 0x0e, 0x24, 0xf2, 0xd8, 0xa6, 0x8c, + 0xf6, 0xdc, 0xa2, 0x88, 0x5e, 0x74, 0x0a, 0x20, + 0xbb, 0x91, 0xef, 0xc5, 0x13, 0x39, 0x47, 0x6d, + 0x6c, 0x46, 0x38, 0x12, 0xc4, 0xee, 0x90, 0xba, + 0x21, 0x0b, 0x75, 0x5f, 0x89, 0xa3, 0xdd, 0xf7, + 0xdf, 0xf5, 0x8b, 0xa1, 0x77, 0x5d, 0x23, 0x09, + 0x92, 0xb8, 0xc6, 0xec, 0x3a, 0x10, 0x6e, 0x44, + 0x45, 0x6f, 0x11, 0x3b, 0xed, 0xc7, 0xb9, 0x93, + 0x08, 0x22, 0x5c, 0x76, 0xa0, 0x8a, 0xf4, 0xde, + }, + { + 0x00, 0x2b, 0x56, 0x7d, 0xac, 0x87, 0xfa, 0xd1, + 0x45, 0x6e, 0x13, 0x38, 0xe9, 0xc2, 0xbf, 0x94, + 0x8a, 0xa1, 0xdc, 0xf7, 0x26, 0x0d, 0x70, 0x5b, + 0xcf, 0xe4, 0x99, 0xb2, 0x63, 0x48, 0x35, 0x1e, + 0x09, 0x22, 0x5f, 0x74, 0xa5, 0x8e, 0xf3, 0xd8, + 0x4c, 0x67, 0x1a, 0x31, 0xe0, 0xcb, 0xb6, 0x9d, + 0x83, 0xa8, 0xd5, 0xfe, 0x2f, 0x04, 0x79, 0x52, + 0xc6, 0xed, 0x90, 0xbb, 0x6a, 0x41, 0x3c, 0x17, + 0x12, 0x39, 0x44, 0x6f, 0xbe, 0x95, 0xe8, 0xc3, + 0x57, 0x7c, 0x01, 0x2a, 0xfb, 0xd0, 0xad, 0x86, + 0x98, 0xb3, 0xce, 0xe5, 0x34, 0x1f, 0x62, 0x49, + 0xdd, 0xf6, 0x8b, 0xa0, 0x71, 0x5a, 0x27, 0x0c, + 0x1b, 0x30, 0x4d, 0x66, 0xb7, 0x9c, 0xe1, 0xca, + 0x5e, 0x75, 0x08, 0x23, 0xf2, 0xd9, 0xa4, 0x8f, + 0x91, 0xba, 0xc7, 0xec, 0x3d, 0x16, 0x6b, 0x40, + 0xd4, 0xff, 0x82, 0xa9, 0x78, 0x53, 0x2e, 0x05, + 0x24, 0x0f, 0x72, 0x59, 0x88, 0xa3, 0xde, 0xf5, + 0x61, 0x4a, 0x37, 0x1c, 0xcd, 0xe6, 0x9b, 0xb0, + 0xae, 0x85, 0xf8, 0xd3, 0x02, 0x29, 0x54, 0x7f, + 0xeb, 0xc0, 0xbd, 0x96, 0x47, 0x6c, 0x11, 0x3a, + 0x2d, 0x06, 0x7b, 0x50, 0x81, 0xaa, 0xd7, 0xfc, + 0x68, 0x43, 0x3e, 0x15, 0xc4, 0xef, 0x92, 0xb9, + 0xa7, 0x8c, 0xf1, 0xda, 0x0b, 0x20, 0x5d, 0x76, + 0xe2, 0xc9, 0xb4, 0x9f, 0x4e, 0x65, 0x18, 0x33, + 0x36, 0x1d, 0x60, 0x4b, 0x9a, 0xb1, 0xcc, 0xe7, + 0x73, 0x58, 0x25, 0x0e, 0xdf, 0xf4, 0x89, 0xa2, + 0xbc, 0x97, 0xea, 0xc1, 0x10, 0x3b, 0x46, 0x6d, + 0xf9, 0xd2, 0xaf, 0x84, 0x55, 0x7e, 0x03, 0x28, + 0x3f, 0x14, 0x69, 0x42, 0x93, 0xb8, 0xc5, 0xee, + 0x7a, 0x51, 0x2c, 0x07, 0xd6, 0xfd, 0x80, 0xab, + 0xb5, 0x9e, 0xe3, 0xc8, 0x19, 0x32, 0x4f, 0x64, + 0xf0, 0xdb, 0xa6, 0x8d, 0x5c, 0x77, 0x0a, 0x21, + }, + { + 0x00, 0x2c, 0x58, 0x74, 0xb0, 0x9c, 0xe8, 0xc4, + 0x7d, 0x51, 0x25, 0x09, 0xcd, 0xe1, 0x95, 0xb9, + 0xfa, 0xd6, 0xa2, 0x8e, 0x4a, 0x66, 0x12, 0x3e, + 0x87, 0xab, 0xdf, 0xf3, 0x37, 0x1b, 0x6f, 0x43, + 0xe9, 0xc5, 0xb1, 0x9d, 0x59, 0x75, 0x01, 0x2d, + 0x94, 0xb8, 0xcc, 0xe0, 0x24, 0x08, 0x7c, 0x50, + 0x13, 0x3f, 0x4b, 0x67, 0xa3, 0x8f, 0xfb, 0xd7, + 0x6e, 0x42, 0x36, 0x1a, 0xde, 0xf2, 0x86, 0xaa, + 0xcf, 0xe3, 0x97, 0xbb, 0x7f, 0x53, 0x27, 0x0b, + 0xb2, 0x9e, 0xea, 0xc6, 0x02, 0x2e, 0x5a, 0x76, + 0x35, 0x19, 0x6d, 0x41, 0x85, 0xa9, 0xdd, 0xf1, + 0x48, 0x64, 0x10, 0x3c, 0xf8, 0xd4, 0xa0, 0x8c, + 0x26, 0x0a, 0x7e, 0x52, 0x96, 0xba, 0xce, 0xe2, + 0x5b, 0x77, 0x03, 0x2f, 0xeb, 0xc7, 0xb3, 0x9f, + 0xdc, 0xf0, 0x84, 0xa8, 0x6c, 0x40, 0x34, 0x18, + 0xa1, 0x8d, 0xf9, 0xd5, 0x11, 0x3d, 0x49, 0x65, + 0x83, 0xaf, 0xdb, 0xf7, 0x33, 0x1f, 0x6b, 0x47, + 0xfe, 0xd2, 0xa6, 0x8a, 0x4e, 0x62, 0x16, 0x3a, + 0x79, 0x55, 0x21, 0x0d, 0xc9, 0xe5, 0x91, 0xbd, + 0x04, 0x28, 0x5c, 0x70, 0xb4, 0x98, 0xec, 0xc0, + 0x6a, 0x46, 0x32, 0x1e, 0xda, 0xf6, 0x82, 0xae, + 0x17, 0x3b, 0x4f, 0x63, 0xa7, 0x8b, 0xff, 0xd3, + 0x90, 0xbc, 0xc8, 0xe4, 0x20, 0x0c, 0x78, 0x54, + 0xed, 0xc1, 0xb5, 0x99, 0x5d, 0x71, 0x05, 0x29, + 0x4c, 0x60, 0x14, 0x38, 0xfc, 0xd0, 0xa4, 0x88, + 0x31, 0x1d, 0x69, 0x45, 0x81, 0xad, 0xd9, 0xf5, + 0xb6, 0x9a, 0xee, 0xc2, 0x06, 0x2a, 0x5e, 0x72, + 0xcb, 0xe7, 0x93, 0xbf, 0x7b, 0x57, 0x23, 0x0f, + 0xa5, 0x89, 0xfd, 0xd1, 0x15, 0x39, 0x4d, 0x61, + 0xd8, 0xf4, 0x80, 0xac, 0x68, 0x44, 0x30, 0x1c, + 0x5f, 0x73, 0x07, 0x2b, 0xef, 0xc3, 0xb7, 0x9b, + 0x22, 0x0e, 0x7a, 0x56, 0x92, 0xbe, 0xca, 0xe6, + }, + { + 0x00, 0x2d, 0x5a, 0x77, 0xb4, 0x99, 0xee, 0xc3, + 0x75, 0x58, 0x2f, 0x02, 0xc1, 0xec, 0x9b, 0xb6, + 0xea, 0xc7, 0xb0, 0x9d, 0x5e, 0x73, 0x04, 0x29, + 0x9f, 0xb2, 0xc5, 0xe8, 0x2b, 0x06, 0x71, 0x5c, + 0xc9, 0xe4, 0x93, 0xbe, 0x7d, 0x50, 0x27, 0x0a, + 0xbc, 0x91, 0xe6, 0xcb, 0x08, 0x25, 0x52, 0x7f, + 0x23, 0x0e, 0x79, 0x54, 0x97, 0xba, 0xcd, 0xe0, + 0x56, 0x7b, 0x0c, 0x21, 0xe2, 0xcf, 0xb8, 0x95, + 0x8f, 0xa2, 0xd5, 0xf8, 0x3b, 0x16, 0x61, 0x4c, + 0xfa, 0xd7, 0xa0, 0x8d, 0x4e, 0x63, 0x14, 0x39, + 0x65, 0x48, 0x3f, 0x12, 0xd1, 0xfc, 0x8b, 0xa6, + 0x10, 0x3d, 0x4a, 0x67, 0xa4, 0x89, 0xfe, 0xd3, + 0x46, 0x6b, 0x1c, 0x31, 0xf2, 0xdf, 0xa8, 0x85, + 0x33, 0x1e, 0x69, 0x44, 0x87, 0xaa, 0xdd, 0xf0, + 0xac, 0x81, 0xf6, 0xdb, 0x18, 0x35, 0x42, 0x6f, + 0xd9, 0xf4, 0x83, 0xae, 0x6d, 0x40, 0x37, 0x1a, + 0x03, 0x2e, 0x59, 0x74, 0xb7, 0x9a, 0xed, 0xc0, + 0x76, 0x5b, 0x2c, 0x01, 0xc2, 0xef, 0x98, 0xb5, + 0xe9, 0xc4, 0xb3, 0x9e, 0x5d, 0x70, 0x07, 0x2a, + 0x9c, 0xb1, 0xc6, 0xeb, 0x28, 0x05, 0x72, 0x5f, + 0xca, 0xe7, 0x90, 0xbd, 0x7e, 0x53, 0x24, 0x09, + 0xbf, 0x92, 0xe5, 0xc8, 0x0b, 0x26, 0x51, 0x7c, + 0x20, 0x0d, 0x7a, 0x57, 0x94, 0xb9, 0xce, 0xe3, + 0x55, 0x78, 0x0f, 0x22, 0xe1, 0xcc, 0xbb, 0x96, + 0x8c, 0xa1, 0xd6, 0xfb, 0x38, 0x15, 0x62, 0x4f, + 0xf9, 0xd4, 0xa3, 0x8e, 0x4d, 0x60, 0x17, 0x3a, + 0x66, 0x4b, 0x3c, 0x11, 0xd2, 0xff, 0x88, 0xa5, + 0x13, 0x3e, 0x49, 0x64, 0xa7, 0x8a, 0xfd, 0xd0, + 0x45, 0x68, 0x1f, 0x32, 0xf1, 0xdc, 0xab, 0x86, + 0x30, 0x1d, 0x6a, 0x47, 0x84, 0xa9, 0xde, 0xf3, + 0xaf, 0x82, 0xf5, 0xd8, 0x1b, 0x36, 0x41, 0x6c, + 0xda, 0xf7, 0x80, 0xad, 0x6e, 0x43, 0x34, 0x19, + }, + { + 0x00, 0x2e, 0x5c, 0x72, 0xb8, 0x96, 0xe4, 0xca, + 0x6d, 0x43, 0x31, 0x1f, 0xd5, 0xfb, 0x89, 0xa7, + 0xda, 0xf4, 0x86, 0xa8, 0x62, 0x4c, 0x3e, 0x10, + 0xb7, 0x99, 0xeb, 0xc5, 0x0f, 0x21, 0x53, 0x7d, + 0xa9, 0x87, 0xf5, 0xdb, 0x11, 0x3f, 0x4d, 0x63, + 0xc4, 0xea, 0x98, 0xb6, 0x7c, 0x52, 0x20, 0x0e, + 0x73, 0x5d, 0x2f, 0x01, 0xcb, 0xe5, 0x97, 0xb9, + 0x1e, 0x30, 0x42, 0x6c, 0xa6, 0x88, 0xfa, 0xd4, + 0x4f, 0x61, 0x13, 0x3d, 0xf7, 0xd9, 0xab, 0x85, + 0x22, 0x0c, 0x7e, 0x50, 0x9a, 0xb4, 0xc6, 0xe8, + 0x95, 0xbb, 0xc9, 0xe7, 0x2d, 0x03, 0x71, 0x5f, + 0xf8, 0xd6, 0xa4, 0x8a, 0x40, 0x6e, 0x1c, 0x32, + 0xe6, 0xc8, 0xba, 0x94, 0x5e, 0x70, 0x02, 0x2c, + 0x8b, 0xa5, 0xd7, 0xf9, 0x33, 0x1d, 0x6f, 0x41, + 0x3c, 0x12, 0x60, 0x4e, 0x84, 0xaa, 0xd8, 0xf6, + 0x51, 0x7f, 0x0d, 0x23, 0xe9, 0xc7, 0xb5, 0x9b, + 0x9e, 0xb0, 0xc2, 0xec, 0x26, 0x08, 0x7a, 0x54, + 0xf3, 0xdd, 0xaf, 0x81, 0x4b, 0x65, 0x17, 0x39, + 0x44, 0x6a, 0x18, 0x36, 0xfc, 0xd2, 0xa0, 0x8e, + 0x29, 0x07, 0x75, 0x5b, 0x91, 0xbf, 0xcd, 0xe3, + 0x37, 0x19, 0x6b, 0x45, 0x8f, 0xa1, 0xd3, 0xfd, + 0x5a, 0x74, 0x06, 0x28, 0xe2, 0xcc, 0xbe, 0x90, + 0xed, 0xc3, 0xb1, 0x9f, 0x55, 0x7b, 0x09, 0x27, + 0x80, 0xae, 0xdc, 0xf2, 0x38, 0x16, 0x64, 0x4a, + 0xd1, 0xff, 0x8d, 0xa3, 0x69, 0x47, 0x35, 0x1b, + 0xbc, 0x92, 0xe0, 0xce, 0x04, 0x2a, 0x58, 0x76, + 0x0b, 0x25, 0x57, 0x79, 0xb3, 0x9d, 0xef, 0xc1, + 0x66, 0x48, 0x3a, 0x14, 0xde, 0xf0, 0x82, 0xac, + 0x78, 0x56, 0x24, 0x0a, 0xc0, 0xee, 0x9c, 0xb2, + 0x15, 0x3b, 0x49, 0x67, 0xad, 0x83, 0xf1, 0xdf, + 0xa2, 0x8c, 0xfe, 0xd0, 0x1a, 0x34, 0x46, 0x68, + 0xcf, 0xe1, 0x93, 0xbd, 0x77, 0x59, 0x2b, 0x05, + }, + { + 0x00, 0x2f, 0x5e, 0x71, 0xbc, 0x93, 0xe2, 0xcd, + 0x65, 0x4a, 0x3b, 0x14, 0xd9, 0xf6, 0x87, 0xa8, + 0xca, 0xe5, 0x94, 0xbb, 0x76, 0x59, 0x28, 0x07, + 0xaf, 0x80, 0xf1, 0xde, 0x13, 0x3c, 0x4d, 0x62, + 0x89, 0xa6, 0xd7, 0xf8, 0x35, 0x1a, 0x6b, 0x44, + 0xec, 0xc3, 0xb2, 0x9d, 0x50, 0x7f, 0x0e, 0x21, + 0x43, 0x6c, 0x1d, 0x32, 0xff, 0xd0, 0xa1, 0x8e, + 0x26, 0x09, 0x78, 0x57, 0x9a, 0xb5, 0xc4, 0xeb, + 0x0f, 0x20, 0x51, 0x7e, 0xb3, 0x9c, 0xed, 0xc2, + 0x6a, 0x45, 0x34, 0x1b, 0xd6, 0xf9, 0x88, 0xa7, + 0xc5, 0xea, 0x9b, 0xb4, 0x79, 0x56, 0x27, 0x08, + 0xa0, 0x8f, 0xfe, 0xd1, 0x1c, 0x33, 0x42, 0x6d, + 0x86, 0xa9, 0xd8, 0xf7, 0x3a, 0x15, 0x64, 0x4b, + 0xe3, 0xcc, 0xbd, 0x92, 0x5f, 0x70, 0x01, 0x2e, + 0x4c, 0x63, 0x12, 0x3d, 0xf0, 0xdf, 0xae, 0x81, + 0x29, 0x06, 0x77, 0x58, 0x95, 0xba, 0xcb, 0xe4, + 0x1e, 0x31, 0x40, 0x6f, 0xa2, 0x8d, 0xfc, 0xd3, + 0x7b, 0x54, 0x25, 0x0a, 0xc7, 0xe8, 0x99, 0xb6, + 0xd4, 0xfb, 0x8a, 0xa5, 0x68, 0x47, 0x36, 0x19, + 0xb1, 0x9e, 0xef, 0xc0, 0x0d, 0x22, 0x53, 0x7c, + 0x97, 0xb8, 0xc9, 0xe6, 0x2b, 0x04, 0x75, 0x5a, + 0xf2, 0xdd, 0xac, 0x83, 0x4e, 0x61, 0x10, 0x3f, + 0x5d, 0x72, 0x03, 0x2c, 0xe1, 0xce, 0xbf, 0x90, + 0x38, 0x17, 0x66, 0x49, 0x84, 0xab, 0xda, 0xf5, + 0x11, 0x3e, 0x4f, 0x60, 0xad, 0x82, 0xf3, 0xdc, + 0x74, 0x5b, 0x2a, 0x05, 0xc8, 0xe7, 0x96, 0xb9, + 0xdb, 0xf4, 0x85, 0xaa, 0x67, 0x48, 0x39, 0x16, + 0xbe, 0x91, 0xe0, 0xcf, 0x02, 0x2d, 0x5c, 0x73, + 0x98, 0xb7, 0xc6, 0xe9, 0x24, 0x0b, 0x7a, 0x55, + 0xfd, 0xd2, 0xa3, 0x8c, 0x41, 0x6e, 0x1f, 0x30, + 0x52, 0x7d, 0x0c, 0x23, 0xee, 0xc1, 0xb0, 0x9f, + 0x37, 0x18, 0x69, 0x46, 0x8b, 0xa4, 0xd5, 0xfa, + }, + { + 0x00, 0x30, 0x60, 0x50, 0xc0, 0xf0, 0xa0, 0x90, + 0x9d, 0xad, 0xfd, 0xcd, 0x5d, 0x6d, 0x3d, 0x0d, + 0x27, 0x17, 0x47, 0x77, 0xe7, 0xd7, 0x87, 0xb7, + 0xba, 0x8a, 0xda, 0xea, 0x7a, 0x4a, 0x1a, 0x2a, + 0x4e, 0x7e, 0x2e, 0x1e, 0x8e, 0xbe, 0xee, 0xde, + 0xd3, 0xe3, 0xb3, 0x83, 0x13, 0x23, 0x73, 0x43, + 0x69, 0x59, 0x09, 0x39, 0xa9, 0x99, 0xc9, 0xf9, + 0xf4, 0xc4, 0x94, 0xa4, 0x34, 0x04, 0x54, 0x64, + 0x9c, 0xac, 0xfc, 0xcc, 0x5c, 0x6c, 0x3c, 0x0c, + 0x01, 0x31, 0x61, 0x51, 0xc1, 0xf1, 0xa1, 0x91, + 0xbb, 0x8b, 0xdb, 0xeb, 0x7b, 0x4b, 0x1b, 0x2b, + 0x26, 0x16, 0x46, 0x76, 0xe6, 0xd6, 0x86, 0xb6, + 0xd2, 0xe2, 0xb2, 0x82, 0x12, 0x22, 0x72, 0x42, + 0x4f, 0x7f, 0x2f, 0x1f, 0x8f, 0xbf, 0xef, 0xdf, + 0xf5, 0xc5, 0x95, 0xa5, 0x35, 0x05, 0x55, 0x65, + 0x68, 0x58, 0x08, 0x38, 0xa8, 0x98, 0xc8, 0xf8, + 0x25, 0x15, 0x45, 0x75, 0xe5, 0xd5, 0x85, 0xb5, + 0xb8, 0x88, 0xd8, 0xe8, 0x78, 0x48, 0x18, 0x28, + 0x02, 0x32, 0x62, 0x52, 0xc2, 0xf2, 0xa2, 0x92, + 0x9f, 0xaf, 0xff, 0xcf, 0x5f, 0x6f, 0x3f, 0x0f, + 0x6b, 0x5b, 0x0b, 0x3b, 0xab, 0x9b, 0xcb, 0xfb, + 0xf6, 0xc6, 0x96, 0xa6, 0x36, 0x06, 0x56, 0x66, + 0x4c, 0x7c, 0x2c, 0x1c, 0x8c, 0xbc, 0xec, 0xdc, + 0xd1, 0xe1, 0xb1, 0x81, 0x11, 0x21, 0x71, 0x41, + 0xb9, 0x89, 0xd9, 0xe9, 0x79, 0x49, 0x19, 0x29, + 0x24, 0x14, 0x44, 0x74, 0xe4, 0xd4, 0x84, 0xb4, + 0x9e, 0xae, 0xfe, 0xce, 0x5e, 0x6e, 0x3e, 0x0e, + 0x03, 0x33, 0x63, 0x53, 0xc3, 0xf3, 0xa3, 0x93, + 0xf7, 0xc7, 0x97, 0xa7, 0x37, 0x07, 0x57, 0x67, + 0x6a, 0x5a, 0x0a, 0x3a, 0xaa, 0x9a, 0xca, 0xfa, + 0xd0, 0xe0, 0xb0, 0x80, 0x10, 0x20, 0x70, 0x40, + 0x4d, 0x7d, 0x2d, 0x1d, 0x8d, 0xbd, 0xed, 0xdd, + }, + { + 0x00, 0x31, 0x62, 0x53, 0xc4, 0xf5, 0xa6, 0x97, + 0x95, 0xa4, 0xf7, 0xc6, 0x51, 0x60, 0x33, 0x02, + 0x37, 0x06, 0x55, 0x64, 0xf3, 0xc2, 0x91, 0xa0, + 0xa2, 0x93, 0xc0, 0xf1, 0x66, 0x57, 0x04, 0x35, + 0x6e, 0x5f, 0x0c, 0x3d, 0xaa, 0x9b, 0xc8, 0xf9, + 0xfb, 0xca, 0x99, 0xa8, 0x3f, 0x0e, 0x5d, 0x6c, + 0x59, 0x68, 0x3b, 0x0a, 0x9d, 0xac, 0xff, 0xce, + 0xcc, 0xfd, 0xae, 0x9f, 0x08, 0x39, 0x6a, 0x5b, + 0xdc, 0xed, 0xbe, 0x8f, 0x18, 0x29, 0x7a, 0x4b, + 0x49, 0x78, 0x2b, 0x1a, 0x8d, 0xbc, 0xef, 0xde, + 0xeb, 0xda, 0x89, 0xb8, 0x2f, 0x1e, 0x4d, 0x7c, + 0x7e, 0x4f, 0x1c, 0x2d, 0xba, 0x8b, 0xd8, 0xe9, + 0xb2, 0x83, 0xd0, 0xe1, 0x76, 0x47, 0x14, 0x25, + 0x27, 0x16, 0x45, 0x74, 0xe3, 0xd2, 0x81, 0xb0, + 0x85, 0xb4, 0xe7, 0xd6, 0x41, 0x70, 0x23, 0x12, + 0x10, 0x21, 0x72, 0x43, 0xd4, 0xe5, 0xb6, 0x87, + 0xa5, 0x94, 0xc7, 0xf6, 0x61, 0x50, 0x03, 0x32, + 0x30, 0x01, 0x52, 0x63, 0xf4, 0xc5, 0x96, 0xa7, + 0x92, 0xa3, 0xf0, 0xc1, 0x56, 0x67, 0x34, 0x05, + 0x07, 0x36, 0x65, 0x54, 0xc3, 0xf2, 0xa1, 0x90, + 0xcb, 0xfa, 0xa9, 0x98, 0x0f, 0x3e, 0x6d, 0x5c, + 0x5e, 0x6f, 0x3c, 0x0d, 0x9a, 0xab, 0xf8, 0xc9, + 0xfc, 0xcd, 0x9e, 0xaf, 0x38, 0x09, 0x5a, 0x6b, + 0x69, 0x58, 0x0b, 0x3a, 0xad, 0x9c, 0xcf, 0xfe, + 0x79, 0x48, 0x1b, 0x2a, 0xbd, 0x8c, 0xdf, 0xee, + 0xec, 0xdd, 0x8e, 0xbf, 0x28, 0x19, 0x4a, 0x7b, + 0x4e, 0x7f, 0x2c, 0x1d, 0x8a, 0xbb, 0xe8, 0xd9, + 0xdb, 0xea, 0xb9, 0x88, 0x1f, 0x2e, 0x7d, 0x4c, + 0x17, 0x26, 0x75, 0x44, 0xd3, 0xe2, 0xb1, 0x80, + 0x82, 0xb3, 0xe0, 0xd1, 0x46, 0x77, 0x24, 0x15, + 0x20, 0x11, 0x42, 0x73, 0xe4, 0xd5, 0x86, 0xb7, + 0xb5, 0x84, 0xd7, 0xe6, 0x71, 0x40, 0x13, 0x22, + }, + { + 0x00, 0x32, 0x64, 0x56, 0xc8, 0xfa, 0xac, 0x9e, + 0x8d, 0xbf, 0xe9, 0xdb, 0x45, 0x77, 0x21, 0x13, + 0x07, 0x35, 0x63, 0x51, 0xcf, 0xfd, 0xab, 0x99, + 0x8a, 0xb8, 0xee, 0xdc, 0x42, 0x70, 0x26, 0x14, + 0x0e, 0x3c, 0x6a, 0x58, 0xc6, 0xf4, 0xa2, 0x90, + 0x83, 0xb1, 0xe7, 0xd5, 0x4b, 0x79, 0x2f, 0x1d, + 0x09, 0x3b, 0x6d, 0x5f, 0xc1, 0xf3, 0xa5, 0x97, + 0x84, 0xb6, 0xe0, 0xd2, 0x4c, 0x7e, 0x28, 0x1a, + 0x1c, 0x2e, 0x78, 0x4a, 0xd4, 0xe6, 0xb0, 0x82, + 0x91, 0xa3, 0xf5, 0xc7, 0x59, 0x6b, 0x3d, 0x0f, + 0x1b, 0x29, 0x7f, 0x4d, 0xd3, 0xe1, 0xb7, 0x85, + 0x96, 0xa4, 0xf2, 0xc0, 0x5e, 0x6c, 0x3a, 0x08, + 0x12, 0x20, 0x76, 0x44, 0xda, 0xe8, 0xbe, 0x8c, + 0x9f, 0xad, 0xfb, 0xc9, 0x57, 0x65, 0x33, 0x01, + 0x15, 0x27, 0x71, 0x43, 0xdd, 0xef, 0xb9, 0x8b, + 0x98, 0xaa, 0xfc, 0xce, 0x50, 0x62, 0x34, 0x06, + 0x38, 0x0a, 0x5c, 0x6e, 0xf0, 0xc2, 0x94, 0xa6, + 0xb5, 0x87, 0xd1, 0xe3, 0x7d, 0x4f, 0x19, 0x2b, + 0x3f, 0x0d, 0x5b, 0x69, 0xf7, 0xc5, 0x93, 0xa1, + 0xb2, 0x80, 0xd6, 0xe4, 0x7a, 0x48, 0x1e, 0x2c, + 0x36, 0x04, 0x52, 0x60, 0xfe, 0xcc, 0x9a, 0xa8, + 0xbb, 0x89, 0xdf, 0xed, 0x73, 0x41, 0x17, 0x25, + 0x31, 0x03, 0x55, 0x67, 0xf9, 0xcb, 0x9d, 0xaf, + 0xbc, 0x8e, 0xd8, 0xea, 0x74, 0x46, 0x10, 0x22, + 0x24, 0x16, 0x40, 0x72, 0xec, 0xde, 0x88, 0xba, + 0xa9, 0x9b, 0xcd, 0xff, 0x61, 0x53, 0x05, 0x37, + 0x23, 0x11, 0x47, 0x75, 0xeb, 0xd9, 0x8f, 0xbd, + 0xae, 0x9c, 0xca, 0xf8, 0x66, 0x54, 0x02, 0x30, + 0x2a, 0x18, 0x4e, 0x7c, 0xe2, 0xd0, 0x86, 0xb4, + 0xa7, 0x95, 0xc3, 0xf1, 0x6f, 0x5d, 0x0b, 0x39, + 0x2d, 0x1f, 0x49, 0x7b, 0xe5, 0xd7, 0x81, 0xb3, + 0xa0, 0x92, 0xc4, 0xf6, 0x68, 0x5a, 0x0c, 0x3e, + }, + { + 0x00, 0x33, 0x66, 0x55, 0xcc, 0xff, 0xaa, 0x99, + 0x85, 0xb6, 0xe3, 0xd0, 0x49, 0x7a, 0x2f, 0x1c, + 0x17, 0x24, 0x71, 0x42, 0xdb, 0xe8, 0xbd, 0x8e, + 0x92, 0xa1, 0xf4, 0xc7, 0x5e, 0x6d, 0x38, 0x0b, + 0x2e, 0x1d, 0x48, 0x7b, 0xe2, 0xd1, 0x84, 0xb7, + 0xab, 0x98, 0xcd, 0xfe, 0x67, 0x54, 0x01, 0x32, + 0x39, 0x0a, 0x5f, 0x6c, 0xf5, 0xc6, 0x93, 0xa0, + 0xbc, 0x8f, 0xda, 0xe9, 0x70, 0x43, 0x16, 0x25, + 0x5c, 0x6f, 0x3a, 0x09, 0x90, 0xa3, 0xf6, 0xc5, + 0xd9, 0xea, 0xbf, 0x8c, 0x15, 0x26, 0x73, 0x40, + 0x4b, 0x78, 0x2d, 0x1e, 0x87, 0xb4, 0xe1, 0xd2, + 0xce, 0xfd, 0xa8, 0x9b, 0x02, 0x31, 0x64, 0x57, + 0x72, 0x41, 0x14, 0x27, 0xbe, 0x8d, 0xd8, 0xeb, + 0xf7, 0xc4, 0x91, 0xa2, 0x3b, 0x08, 0x5d, 0x6e, + 0x65, 0x56, 0x03, 0x30, 0xa9, 0x9a, 0xcf, 0xfc, + 0xe0, 0xd3, 0x86, 0xb5, 0x2c, 0x1f, 0x4a, 0x79, + 0xb8, 0x8b, 0xde, 0xed, 0x74, 0x47, 0x12, 0x21, + 0x3d, 0x0e, 0x5b, 0x68, 0xf1, 0xc2, 0x97, 0xa4, + 0xaf, 0x9c, 0xc9, 0xfa, 0x63, 0x50, 0x05, 0x36, + 0x2a, 0x19, 0x4c, 0x7f, 0xe6, 0xd5, 0x80, 0xb3, + 0x96, 0xa5, 0xf0, 0xc3, 0x5a, 0x69, 0x3c, 0x0f, + 0x13, 0x20, 0x75, 0x46, 0xdf, 0xec, 0xb9, 0x8a, + 0x81, 0xb2, 0xe7, 0xd4, 0x4d, 0x7e, 0x2b, 0x18, + 0x04, 0x37, 0x62, 0x51, 0xc8, 0xfb, 0xae, 0x9d, + 0xe4, 0xd7, 0x82, 0xb1, 0x28, 0x1b, 0x4e, 0x7d, + 0x61, 0x52, 0x07, 0x34, 0xad, 0x9e, 0xcb, 0xf8, + 0xf3, 0xc0, 0x95, 0xa6, 0x3f, 0x0c, 0x59, 0x6a, + 0x76, 0x45, 0x10, 0x23, 0xba, 0x89, 0xdc, 0xef, + 0xca, 0xf9, 0xac, 0x9f, 0x06, 0x35, 0x60, 0x53, + 0x4f, 0x7c, 0x29, 0x1a, 0x83, 0xb0, 0xe5, 0xd6, + 0xdd, 0xee, 0xbb, 0x88, 0x11, 0x22, 0x77, 0x44, + 0x58, 0x6b, 0x3e, 0x0d, 0x94, 0xa7, 0xf2, 0xc1, + }, + { + 0x00, 0x34, 0x68, 0x5c, 0xd0, 0xe4, 0xb8, 0x8c, + 0xbd, 0x89, 0xd5, 0xe1, 0x6d, 0x59, 0x05, 0x31, + 0x67, 0x53, 0x0f, 0x3b, 0xb7, 0x83, 0xdf, 0xeb, + 0xda, 0xee, 0xb2, 0x86, 0x0a, 0x3e, 0x62, 0x56, + 0xce, 0xfa, 0xa6, 0x92, 0x1e, 0x2a, 0x76, 0x42, + 0x73, 0x47, 0x1b, 0x2f, 0xa3, 0x97, 0xcb, 0xff, + 0xa9, 0x9d, 0xc1, 0xf5, 0x79, 0x4d, 0x11, 0x25, + 0x14, 0x20, 0x7c, 0x48, 0xc4, 0xf0, 0xac, 0x98, + 0x81, 0xb5, 0xe9, 0xdd, 0x51, 0x65, 0x39, 0x0d, + 0x3c, 0x08, 0x54, 0x60, 0xec, 0xd8, 0x84, 0xb0, + 0xe6, 0xd2, 0x8e, 0xba, 0x36, 0x02, 0x5e, 0x6a, + 0x5b, 0x6f, 0x33, 0x07, 0x8b, 0xbf, 0xe3, 0xd7, + 0x4f, 0x7b, 0x27, 0x13, 0x9f, 0xab, 0xf7, 0xc3, + 0xf2, 0xc6, 0x9a, 0xae, 0x22, 0x16, 0x4a, 0x7e, + 0x28, 0x1c, 0x40, 0x74, 0xf8, 0xcc, 0x90, 0xa4, + 0x95, 0xa1, 0xfd, 0xc9, 0x45, 0x71, 0x2d, 0x19, + 0x1f, 0x2b, 0x77, 0x43, 0xcf, 0xfb, 0xa7, 0x93, + 0xa2, 0x96, 0xca, 0xfe, 0x72, 0x46, 0x1a, 0x2e, + 0x78, 0x4c, 0x10, 0x24, 0xa8, 0x9c, 0xc0, 0xf4, + 0xc5, 0xf1, 0xad, 0x99, 0x15, 0x21, 0x7d, 0x49, + 0xd1, 0xe5, 0xb9, 0x8d, 0x01, 0x35, 0x69, 0x5d, + 0x6c, 0x58, 0x04, 0x30, 0xbc, 0x88, 0xd4, 0xe0, + 0xb6, 0x82, 0xde, 0xea, 0x66, 0x52, 0x0e, 0x3a, + 0x0b, 0x3f, 0x63, 0x57, 0xdb, 0xef, 0xb3, 0x87, + 0x9e, 0xaa, 0xf6, 0xc2, 0x4e, 0x7a, 0x26, 0x12, + 0x23, 0x17, 0x4b, 0x7f, 0xf3, 0xc7, 0x9b, 0xaf, + 0xf9, 0xcd, 0x91, 0xa5, 0x29, 0x1d, 0x41, 0x75, + 0x44, 0x70, 0x2c, 0x18, 0x94, 0xa0, 0xfc, 0xc8, + 0x50, 0x64, 0x38, 0x0c, 0x80, 0xb4, 0xe8, 0xdc, + 0xed, 0xd9, 0x85, 0xb1, 0x3d, 0x09, 0x55, 0x61, + 0x37, 0x03, 0x5f, 0x6b, 0xe7, 0xd3, 0x8f, 0xbb, + 0x8a, 0xbe, 0xe2, 0xd6, 0x5a, 0x6e, 0x32, 0x06, + }, + { + 0x00, 0x35, 0x6a, 0x5f, 0xd4, 0xe1, 0xbe, 0x8b, + 0xb5, 0x80, 0xdf, 0xea, 0x61, 0x54, 0x0b, 0x3e, + 0x77, 0x42, 0x1d, 0x28, 0xa3, 0x96, 0xc9, 0xfc, + 0xc2, 0xf7, 0xa8, 0x9d, 0x16, 0x23, 0x7c, 0x49, + 0xee, 0xdb, 0x84, 0xb1, 0x3a, 0x0f, 0x50, 0x65, + 0x5b, 0x6e, 0x31, 0x04, 0x8f, 0xba, 0xe5, 0xd0, + 0x99, 0xac, 0xf3, 0xc6, 0x4d, 0x78, 0x27, 0x12, + 0x2c, 0x19, 0x46, 0x73, 0xf8, 0xcd, 0x92, 0xa7, + 0xc1, 0xf4, 0xab, 0x9e, 0x15, 0x20, 0x7f, 0x4a, + 0x74, 0x41, 0x1e, 0x2b, 0xa0, 0x95, 0xca, 0xff, + 0xb6, 0x83, 0xdc, 0xe9, 0x62, 0x57, 0x08, 0x3d, + 0x03, 0x36, 0x69, 0x5c, 0xd7, 0xe2, 0xbd, 0x88, + 0x2f, 0x1a, 0x45, 0x70, 0xfb, 0xce, 0x91, 0xa4, + 0x9a, 0xaf, 0xf0, 0xc5, 0x4e, 0x7b, 0x24, 0x11, + 0x58, 0x6d, 0x32, 0x07, 0x8c, 0xb9, 0xe6, 0xd3, + 0xed, 0xd8, 0x87, 0xb2, 0x39, 0x0c, 0x53, 0x66, + 0x9f, 0xaa, 0xf5, 0xc0, 0x4b, 0x7e, 0x21, 0x14, + 0x2a, 0x1f, 0x40, 0x75, 0xfe, 0xcb, 0x94, 0xa1, + 0xe8, 0xdd, 0x82, 0xb7, 0x3c, 0x09, 0x56, 0x63, + 0x5d, 0x68, 0x37, 0x02, 0x89, 0xbc, 0xe3, 0xd6, + 0x71, 0x44, 0x1b, 0x2e, 0xa5, 0x90, 0xcf, 0xfa, + 0xc4, 0xf1, 0xae, 0x9b, 0x10, 0x25, 0x7a, 0x4f, + 0x06, 0x33, 0x6c, 0x59, 0xd2, 0xe7, 0xb8, 0x8d, + 0xb3, 0x86, 0xd9, 0xec, 0x67, 0x52, 0x0d, 0x38, + 0x5e, 0x6b, 0x34, 0x01, 0x8a, 0xbf, 0xe0, 0xd5, + 0xeb, 0xde, 0x81, 0xb4, 0x3f, 0x0a, 0x55, 0x60, + 0x29, 0x1c, 0x43, 0x76, 0xfd, 0xc8, 0x97, 0xa2, + 0x9c, 0xa9, 0xf6, 0xc3, 0x48, 0x7d, 0x22, 0x17, + 0xb0, 0x85, 0xda, 0xef, 0x64, 0x51, 0x0e, 0x3b, + 0x05, 0x30, 0x6f, 0x5a, 0xd1, 0xe4, 0xbb, 0x8e, + 0xc7, 0xf2, 0xad, 0x98, 0x13, 0x26, 0x79, 0x4c, + 0x72, 0x47, 0x18, 0x2d, 0xa6, 0x93, 0xcc, 0xf9, + }, + { + 0x00, 0x36, 0x6c, 0x5a, 0xd8, 0xee, 0xb4, 0x82, + 0xad, 0x9b, 0xc1, 0xf7, 0x75, 0x43, 0x19, 0x2f, + 0x47, 0x71, 0x2b, 0x1d, 0x9f, 0xa9, 0xf3, 0xc5, + 0xea, 0xdc, 0x86, 0xb0, 0x32, 0x04, 0x5e, 0x68, + 0x8e, 0xb8, 0xe2, 0xd4, 0x56, 0x60, 0x3a, 0x0c, + 0x23, 0x15, 0x4f, 0x79, 0xfb, 0xcd, 0x97, 0xa1, + 0xc9, 0xff, 0xa5, 0x93, 0x11, 0x27, 0x7d, 0x4b, + 0x64, 0x52, 0x08, 0x3e, 0xbc, 0x8a, 0xd0, 0xe6, + 0x01, 0x37, 0x6d, 0x5b, 0xd9, 0xef, 0xb5, 0x83, + 0xac, 0x9a, 0xc0, 0xf6, 0x74, 0x42, 0x18, 0x2e, + 0x46, 0x70, 0x2a, 0x1c, 0x9e, 0xa8, 0xf2, 0xc4, + 0xeb, 0xdd, 0x87, 0xb1, 0x33, 0x05, 0x5f, 0x69, + 0x8f, 0xb9, 0xe3, 0xd5, 0x57, 0x61, 0x3b, 0x0d, + 0x22, 0x14, 0x4e, 0x78, 0xfa, 0xcc, 0x96, 0xa0, + 0xc8, 0xfe, 0xa4, 0x92, 0x10, 0x26, 0x7c, 0x4a, + 0x65, 0x53, 0x09, 0x3f, 0xbd, 0x8b, 0xd1, 0xe7, + 0x02, 0x34, 0x6e, 0x58, 0xda, 0xec, 0xb6, 0x80, + 0xaf, 0x99, 0xc3, 0xf5, 0x77, 0x41, 0x1b, 0x2d, + 0x45, 0x73, 0x29, 0x1f, 0x9d, 0xab, 0xf1, 0xc7, + 0xe8, 0xde, 0x84, 0xb2, 0x30, 0x06, 0x5c, 0x6a, + 0x8c, 0xba, 0xe0, 0xd6, 0x54, 0x62, 0x38, 0x0e, + 0x21, 0x17, 0x4d, 0x7b, 0xf9, 0xcf, 0x95, 0xa3, + 0xcb, 0xfd, 0xa7, 0x91, 0x13, 0x25, 0x7f, 0x49, + 0x66, 0x50, 0x0a, 0x3c, 0xbe, 0x88, 0xd2, 0xe4, + 0x03, 0x35, 0x6f, 0x59, 0xdb, 0xed, 0xb7, 0x81, + 0xae, 0x98, 0xc2, 0xf4, 0x76, 0x40, 0x1a, 0x2c, + 0x44, 0x72, 0x28, 0x1e, 0x9c, 0xaa, 0xf0, 0xc6, + 0xe9, 0xdf, 0x85, 0xb3, 0x31, 0x07, 0x5d, 0x6b, + 0x8d, 0xbb, 0xe1, 0xd7, 0x55, 0x63, 0x39, 0x0f, + 0x20, 0x16, 0x4c, 0x7a, 0xf8, 0xce, 0x94, 0xa2, + 0xca, 0xfc, 0xa6, 0x90, 0x12, 0x24, 0x7e, 0x48, + 0x67, 0x51, 0x0b, 0x3d, 0xbf, 0x89, 0xd3, 0xe5, + }, + { + 0x00, 0x37, 0x6e, 0x59, 0xdc, 0xeb, 0xb2, 0x85, + 0xa5, 0x92, 0xcb, 0xfc, 0x79, 0x4e, 0x17, 0x20, + 0x57, 0x60, 0x39, 0x0e, 0x8b, 0xbc, 0xe5, 0xd2, + 0xf2, 0xc5, 0x9c, 0xab, 0x2e, 0x19, 0x40, 0x77, + 0xae, 0x99, 0xc0, 0xf7, 0x72, 0x45, 0x1c, 0x2b, + 0x0b, 0x3c, 0x65, 0x52, 0xd7, 0xe0, 0xb9, 0x8e, + 0xf9, 0xce, 0x97, 0xa0, 0x25, 0x12, 0x4b, 0x7c, + 0x5c, 0x6b, 0x32, 0x05, 0x80, 0xb7, 0xee, 0xd9, + 0x41, 0x76, 0x2f, 0x18, 0x9d, 0xaa, 0xf3, 0xc4, + 0xe4, 0xd3, 0x8a, 0xbd, 0x38, 0x0f, 0x56, 0x61, + 0x16, 0x21, 0x78, 0x4f, 0xca, 0xfd, 0xa4, 0x93, + 0xb3, 0x84, 0xdd, 0xea, 0x6f, 0x58, 0x01, 0x36, + 0xef, 0xd8, 0x81, 0xb6, 0x33, 0x04, 0x5d, 0x6a, + 0x4a, 0x7d, 0x24, 0x13, 0x96, 0xa1, 0xf8, 0xcf, + 0xb8, 0x8f, 0xd6, 0xe1, 0x64, 0x53, 0x0a, 0x3d, + 0x1d, 0x2a, 0x73, 0x44, 0xc1, 0xf6, 0xaf, 0x98, + 0x82, 0xb5, 0xec, 0xdb, 0x5e, 0x69, 0x30, 0x07, + 0x27, 0x10, 0x49, 0x7e, 0xfb, 0xcc, 0x95, 0xa2, + 0xd5, 0xe2, 0xbb, 0x8c, 0x09, 0x3e, 0x67, 0x50, + 0x70, 0x47, 0x1e, 0x29, 0xac, 0x9b, 0xc2, 0xf5, + 0x2c, 0x1b, 0x42, 0x75, 0xf0, 0xc7, 0x9e, 0xa9, + 0x89, 0xbe, 0xe7, 0xd0, 0x55, 0x62, 0x3b, 0x0c, + 0x7b, 0x4c, 0x15, 0x22, 0xa7, 0x90, 0xc9, 0xfe, + 0xde, 0xe9, 0xb0, 0x87, 0x02, 0x35, 0x6c, 0x5b, + 0xc3, 0xf4, 0xad, 0x9a, 0x1f, 0x28, 0x71, 0x46, + 0x66, 0x51, 0x08, 0x3f, 0xba, 0x8d, 0xd4, 0xe3, + 0x94, 0xa3, 0xfa, 0xcd, 0x48, 0x7f, 0x26, 0x11, + 0x31, 0x06, 0x5f, 0x68, 0xed, 0xda, 0x83, 0xb4, + 0x6d, 0x5a, 0x03, 0x34, 0xb1, 0x86, 0xdf, 0xe8, + 0xc8, 0xff, 0xa6, 0x91, 0x14, 0x23, 0x7a, 0x4d, + 0x3a, 0x0d, 0x54, 0x63, 0xe6, 0xd1, 0x88, 0xbf, + 0x9f, 0xa8, 0xf1, 0xc6, 0x43, 0x74, 0x2d, 0x1a, + }, + { + 0x00, 0x38, 0x70, 0x48, 0xe0, 0xd8, 0x90, 0xa8, + 0xdd, 0xe5, 0xad, 0x95, 0x3d, 0x05, 0x4d, 0x75, + 0xa7, 0x9f, 0xd7, 0xef, 0x47, 0x7f, 0x37, 0x0f, + 0x7a, 0x42, 0x0a, 0x32, 0x9a, 0xa2, 0xea, 0xd2, + 0x53, 0x6b, 0x23, 0x1b, 0xb3, 0x8b, 0xc3, 0xfb, + 0x8e, 0xb6, 0xfe, 0xc6, 0x6e, 0x56, 0x1e, 0x26, + 0xf4, 0xcc, 0x84, 0xbc, 0x14, 0x2c, 0x64, 0x5c, + 0x29, 0x11, 0x59, 0x61, 0xc9, 0xf1, 0xb9, 0x81, + 0xa6, 0x9e, 0xd6, 0xee, 0x46, 0x7e, 0x36, 0x0e, + 0x7b, 0x43, 0x0b, 0x33, 0x9b, 0xa3, 0xeb, 0xd3, + 0x01, 0x39, 0x71, 0x49, 0xe1, 0xd9, 0x91, 0xa9, + 0xdc, 0xe4, 0xac, 0x94, 0x3c, 0x04, 0x4c, 0x74, + 0xf5, 0xcd, 0x85, 0xbd, 0x15, 0x2d, 0x65, 0x5d, + 0x28, 0x10, 0x58, 0x60, 0xc8, 0xf0, 0xb8, 0x80, + 0x52, 0x6a, 0x22, 0x1a, 0xb2, 0x8a, 0xc2, 0xfa, + 0x8f, 0xb7, 0xff, 0xc7, 0x6f, 0x57, 0x1f, 0x27, + 0x51, 0x69, 0x21, 0x19, 0xb1, 0x89, 0xc1, 0xf9, + 0x8c, 0xb4, 0xfc, 0xc4, 0x6c, 0x54, 0x1c, 0x24, + 0xf6, 0xce, 0x86, 0xbe, 0x16, 0x2e, 0x66, 0x5e, + 0x2b, 0x13, 0x5b, 0x63, 0xcb, 0xf3, 0xbb, 0x83, + 0x02, 0x3a, 0x72, 0x4a, 0xe2, 0xda, 0x92, 0xaa, + 0xdf, 0xe7, 0xaf, 0x97, 0x3f, 0x07, 0x4f, 0x77, + 0xa5, 0x9d, 0xd5, 0xed, 0x45, 0x7d, 0x35, 0x0d, + 0x78, 0x40, 0x08, 0x30, 0x98, 0xa0, 0xe8, 0xd0, + 0xf7, 0xcf, 0x87, 0xbf, 0x17, 0x2f, 0x67, 0x5f, + 0x2a, 0x12, 0x5a, 0x62, 0xca, 0xf2, 0xba, 0x82, + 0x50, 0x68, 0x20, 0x18, 0xb0, 0x88, 0xc0, 0xf8, + 0x8d, 0xb5, 0xfd, 0xc5, 0x6d, 0x55, 0x1d, 0x25, + 0xa4, 0x9c, 0xd4, 0xec, 0x44, 0x7c, 0x34, 0x0c, + 0x79, 0x41, 0x09, 0x31, 0x99, 0xa1, 0xe9, 0xd1, + 0x03, 0x3b, 0x73, 0x4b, 0xe3, 0xdb, 0x93, 0xab, + 0xde, 0xe6, 0xae, 0x96, 0x3e, 0x06, 0x4e, 0x76, + }, + { + 0x00, 0x39, 0x72, 0x4b, 0xe4, 0xdd, 0x96, 0xaf, + 0xd5, 0xec, 0xa7, 0x9e, 0x31, 0x08, 0x43, 0x7a, + 0xb7, 0x8e, 0xc5, 0xfc, 0x53, 0x6a, 0x21, 0x18, + 0x62, 0x5b, 0x10, 0x29, 0x86, 0xbf, 0xf4, 0xcd, + 0x73, 0x4a, 0x01, 0x38, 0x97, 0xae, 0xe5, 0xdc, + 0xa6, 0x9f, 0xd4, 0xed, 0x42, 0x7b, 0x30, 0x09, + 0xc4, 0xfd, 0xb6, 0x8f, 0x20, 0x19, 0x52, 0x6b, + 0x11, 0x28, 0x63, 0x5a, 0xf5, 0xcc, 0x87, 0xbe, + 0xe6, 0xdf, 0x94, 0xad, 0x02, 0x3b, 0x70, 0x49, + 0x33, 0x0a, 0x41, 0x78, 0xd7, 0xee, 0xa5, 0x9c, + 0x51, 0x68, 0x23, 0x1a, 0xb5, 0x8c, 0xc7, 0xfe, + 0x84, 0xbd, 0xf6, 0xcf, 0x60, 0x59, 0x12, 0x2b, + 0x95, 0xac, 0xe7, 0xde, 0x71, 0x48, 0x03, 0x3a, + 0x40, 0x79, 0x32, 0x0b, 0xa4, 0x9d, 0xd6, 0xef, + 0x22, 0x1b, 0x50, 0x69, 0xc6, 0xff, 0xb4, 0x8d, + 0xf7, 0xce, 0x85, 0xbc, 0x13, 0x2a, 0x61, 0x58, + 0xd1, 0xe8, 0xa3, 0x9a, 0x35, 0x0c, 0x47, 0x7e, + 0x04, 0x3d, 0x76, 0x4f, 0xe0, 0xd9, 0x92, 0xab, + 0x66, 0x5f, 0x14, 0x2d, 0x82, 0xbb, 0xf0, 0xc9, + 0xb3, 0x8a, 0xc1, 0xf8, 0x57, 0x6e, 0x25, 0x1c, + 0xa2, 0x9b, 0xd0, 0xe9, 0x46, 0x7f, 0x34, 0x0d, + 0x77, 0x4e, 0x05, 0x3c, 0x93, 0xaa, 0xe1, 0xd8, + 0x15, 0x2c, 0x67, 0x5e, 0xf1, 0xc8, 0x83, 0xba, + 0xc0, 0xf9, 0xb2, 0x8b, 0x24, 0x1d, 0x56, 0x6f, + 0x37, 0x0e, 0x45, 0x7c, 0xd3, 0xea, 0xa1, 0x98, + 0xe2, 0xdb, 0x90, 0xa9, 0x06, 0x3f, 0x74, 0x4d, + 0x80, 0xb9, 0xf2, 0xcb, 0x64, 0x5d, 0x16, 0x2f, + 0x55, 0x6c, 0x27, 0x1e, 0xb1, 0x88, 0xc3, 0xfa, + 0x44, 0x7d, 0x36, 0x0f, 0xa0, 0x99, 0xd2, 0xeb, + 0x91, 0xa8, 0xe3, 0xda, 0x75, 0x4c, 0x07, 0x3e, + 0xf3, 0xca, 0x81, 0xb8, 0x17, 0x2e, 0x65, 0x5c, + 0x26, 0x1f, 0x54, 0x6d, 0xc2, 0xfb, 0xb0, 0x89, + }, + { + 0x00, 0x3a, 0x74, 0x4e, 0xe8, 0xd2, 0x9c, 0xa6, + 0xcd, 0xf7, 0xb9, 0x83, 0x25, 0x1f, 0x51, 0x6b, + 0x87, 0xbd, 0xf3, 0xc9, 0x6f, 0x55, 0x1b, 0x21, + 0x4a, 0x70, 0x3e, 0x04, 0xa2, 0x98, 0xd6, 0xec, + 0x13, 0x29, 0x67, 0x5d, 0xfb, 0xc1, 0x8f, 0xb5, + 0xde, 0xe4, 0xaa, 0x90, 0x36, 0x0c, 0x42, 0x78, + 0x94, 0xae, 0xe0, 0xda, 0x7c, 0x46, 0x08, 0x32, + 0x59, 0x63, 0x2d, 0x17, 0xb1, 0x8b, 0xc5, 0xff, + 0x26, 0x1c, 0x52, 0x68, 0xce, 0xf4, 0xba, 0x80, + 0xeb, 0xd1, 0x9f, 0xa5, 0x03, 0x39, 0x77, 0x4d, + 0xa1, 0x9b, 0xd5, 0xef, 0x49, 0x73, 0x3d, 0x07, + 0x6c, 0x56, 0x18, 0x22, 0x84, 0xbe, 0xf0, 0xca, + 0x35, 0x0f, 0x41, 0x7b, 0xdd, 0xe7, 0xa9, 0x93, + 0xf8, 0xc2, 0x8c, 0xb6, 0x10, 0x2a, 0x64, 0x5e, + 0xb2, 0x88, 0xc6, 0xfc, 0x5a, 0x60, 0x2e, 0x14, + 0x7f, 0x45, 0x0b, 0x31, 0x97, 0xad, 0xe3, 0xd9, + 0x4c, 0x76, 0x38, 0x02, 0xa4, 0x9e, 0xd0, 0xea, + 0x81, 0xbb, 0xf5, 0xcf, 0x69, 0x53, 0x1d, 0x27, + 0xcb, 0xf1, 0xbf, 0x85, 0x23, 0x19, 0x57, 0x6d, + 0x06, 0x3c, 0x72, 0x48, 0xee, 0xd4, 0x9a, 0xa0, + 0x5f, 0x65, 0x2b, 0x11, 0xb7, 0x8d, 0xc3, 0xf9, + 0x92, 0xa8, 0xe6, 0xdc, 0x7a, 0x40, 0x0e, 0x34, + 0xd8, 0xe2, 0xac, 0x96, 0x30, 0x0a, 0x44, 0x7e, + 0x15, 0x2f, 0x61, 0x5b, 0xfd, 0xc7, 0x89, 0xb3, + 0x6a, 0x50, 0x1e, 0x24, 0x82, 0xb8, 0xf6, 0xcc, + 0xa7, 0x9d, 0xd3, 0xe9, 0x4f, 0x75, 0x3b, 0x01, + 0xed, 0xd7, 0x99, 0xa3, 0x05, 0x3f, 0x71, 0x4b, + 0x20, 0x1a, 0x54, 0x6e, 0xc8, 0xf2, 0xbc, 0x86, + 0x79, 0x43, 0x0d, 0x37, 0x91, 0xab, 0xe5, 0xdf, + 0xb4, 0x8e, 0xc0, 0xfa, 0x5c, 0x66, 0x28, 0x12, + 0xfe, 0xc4, 0x8a, 0xb0, 0x16, 0x2c, 0x62, 0x58, + 0x33, 0x09, 0x47, 0x7d, 0xdb, 0xe1, 0xaf, 0x95, + }, + { + 0x00, 0x3b, 0x76, 0x4d, 0xec, 0xd7, 0x9a, 0xa1, + 0xc5, 0xfe, 0xb3, 0x88, 0x29, 0x12, 0x5f, 0x64, + 0x97, 0xac, 0xe1, 0xda, 0x7b, 0x40, 0x0d, 0x36, + 0x52, 0x69, 0x24, 0x1f, 0xbe, 0x85, 0xc8, 0xf3, + 0x33, 0x08, 0x45, 0x7e, 0xdf, 0xe4, 0xa9, 0x92, + 0xf6, 0xcd, 0x80, 0xbb, 0x1a, 0x21, 0x6c, 0x57, + 0xa4, 0x9f, 0xd2, 0xe9, 0x48, 0x73, 0x3e, 0x05, + 0x61, 0x5a, 0x17, 0x2c, 0x8d, 0xb6, 0xfb, 0xc0, + 0x66, 0x5d, 0x10, 0x2b, 0x8a, 0xb1, 0xfc, 0xc7, + 0xa3, 0x98, 0xd5, 0xee, 0x4f, 0x74, 0x39, 0x02, + 0xf1, 0xca, 0x87, 0xbc, 0x1d, 0x26, 0x6b, 0x50, + 0x34, 0x0f, 0x42, 0x79, 0xd8, 0xe3, 0xae, 0x95, + 0x55, 0x6e, 0x23, 0x18, 0xb9, 0x82, 0xcf, 0xf4, + 0x90, 0xab, 0xe6, 0xdd, 0x7c, 0x47, 0x0a, 0x31, + 0xc2, 0xf9, 0xb4, 0x8f, 0x2e, 0x15, 0x58, 0x63, + 0x07, 0x3c, 0x71, 0x4a, 0xeb, 0xd0, 0x9d, 0xa6, + 0xcc, 0xf7, 0xba, 0x81, 0x20, 0x1b, 0x56, 0x6d, + 0x09, 0x32, 0x7f, 0x44, 0xe5, 0xde, 0x93, 0xa8, + 0x5b, 0x60, 0x2d, 0x16, 0xb7, 0x8c, 0xc1, 0xfa, + 0x9e, 0xa5, 0xe8, 0xd3, 0x72, 0x49, 0x04, 0x3f, + 0xff, 0xc4, 0x89, 0xb2, 0x13, 0x28, 0x65, 0x5e, + 0x3a, 0x01, 0x4c, 0x77, 0xd6, 0xed, 0xa0, 0x9b, + 0x68, 0x53, 0x1e, 0x25, 0x84, 0xbf, 0xf2, 0xc9, + 0xad, 0x96, 0xdb, 0xe0, 0x41, 0x7a, 0x37, 0x0c, + 0xaa, 0x91, 0xdc, 0xe7, 0x46, 0x7d, 0x30, 0x0b, + 0x6f, 0x54, 0x19, 0x22, 0x83, 0xb8, 0xf5, 0xce, + 0x3d, 0x06, 0x4b, 0x70, 0xd1, 0xea, 0xa7, 0x9c, + 0xf8, 0xc3, 0x8e, 0xb5, 0x14, 0x2f, 0x62, 0x59, + 0x99, 0xa2, 0xef, 0xd4, 0x75, 0x4e, 0x03, 0x38, + 0x5c, 0x67, 0x2a, 0x11, 0xb0, 0x8b, 0xc6, 0xfd, + 0x0e, 0x35, 0x78, 0x43, 0xe2, 0xd9, 0x94, 0xaf, + 0xcb, 0xf0, 0xbd, 0x86, 0x27, 0x1c, 0x51, 0x6a, + }, + { + 0x00, 0x3c, 0x78, 0x44, 0xf0, 0xcc, 0x88, 0xb4, + 0xfd, 0xc1, 0x85, 0xb9, 0x0d, 0x31, 0x75, 0x49, + 0xe7, 0xdb, 0x9f, 0xa3, 0x17, 0x2b, 0x6f, 0x53, + 0x1a, 0x26, 0x62, 0x5e, 0xea, 0xd6, 0x92, 0xae, + 0xd3, 0xef, 0xab, 0x97, 0x23, 0x1f, 0x5b, 0x67, + 0x2e, 0x12, 0x56, 0x6a, 0xde, 0xe2, 0xa6, 0x9a, + 0x34, 0x08, 0x4c, 0x70, 0xc4, 0xf8, 0xbc, 0x80, + 0xc9, 0xf5, 0xb1, 0x8d, 0x39, 0x05, 0x41, 0x7d, + 0xbb, 0x87, 0xc3, 0xff, 0x4b, 0x77, 0x33, 0x0f, + 0x46, 0x7a, 0x3e, 0x02, 0xb6, 0x8a, 0xce, 0xf2, + 0x5c, 0x60, 0x24, 0x18, 0xac, 0x90, 0xd4, 0xe8, + 0xa1, 0x9d, 0xd9, 0xe5, 0x51, 0x6d, 0x29, 0x15, + 0x68, 0x54, 0x10, 0x2c, 0x98, 0xa4, 0xe0, 0xdc, + 0x95, 0xa9, 0xed, 0xd1, 0x65, 0x59, 0x1d, 0x21, + 0x8f, 0xb3, 0xf7, 0xcb, 0x7f, 0x43, 0x07, 0x3b, + 0x72, 0x4e, 0x0a, 0x36, 0x82, 0xbe, 0xfa, 0xc6, + 0x6b, 0x57, 0x13, 0x2f, 0x9b, 0xa7, 0xe3, 0xdf, + 0x96, 0xaa, 0xee, 0xd2, 0x66, 0x5a, 0x1e, 0x22, + 0x8c, 0xb0, 0xf4, 0xc8, 0x7c, 0x40, 0x04, 0x38, + 0x71, 0x4d, 0x09, 0x35, 0x81, 0xbd, 0xf9, 0xc5, + 0xb8, 0x84, 0xc0, 0xfc, 0x48, 0x74, 0x30, 0x0c, + 0x45, 0x79, 0x3d, 0x01, 0xb5, 0x89, 0xcd, 0xf1, + 0x5f, 0x63, 0x27, 0x1b, 0xaf, 0x93, 0xd7, 0xeb, + 0xa2, 0x9e, 0xda, 0xe6, 0x52, 0x6e, 0x2a, 0x16, + 0xd0, 0xec, 0xa8, 0x94, 0x20, 0x1c, 0x58, 0x64, + 0x2d, 0x11, 0x55, 0x69, 0xdd, 0xe1, 0xa5, 0x99, + 0x37, 0x0b, 0x4f, 0x73, 0xc7, 0xfb, 0xbf, 0x83, + 0xca, 0xf6, 0xb2, 0x8e, 0x3a, 0x06, 0x42, 0x7e, + 0x03, 0x3f, 0x7b, 0x47, 0xf3, 0xcf, 0x8b, 0xb7, + 0xfe, 0xc2, 0x86, 0xba, 0x0e, 0x32, 0x76, 0x4a, + 0xe4, 0xd8, 0x9c, 0xa0, 0x14, 0x28, 0x6c, 0x50, + 0x19, 0x25, 0x61, 0x5d, 0xe9, 0xd5, 0x91, 0xad, + }, + { + 0x00, 0x3d, 0x7a, 0x47, 0xf4, 0xc9, 0x8e, 0xb3, + 0xf5, 0xc8, 0x8f, 0xb2, 0x01, 0x3c, 0x7b, 0x46, + 0xf7, 0xca, 0x8d, 0xb0, 0x03, 0x3e, 0x79, 0x44, + 0x02, 0x3f, 0x78, 0x45, 0xf6, 0xcb, 0x8c, 0xb1, + 0xf3, 0xce, 0x89, 0xb4, 0x07, 0x3a, 0x7d, 0x40, + 0x06, 0x3b, 0x7c, 0x41, 0xf2, 0xcf, 0x88, 0xb5, + 0x04, 0x39, 0x7e, 0x43, 0xf0, 0xcd, 0x8a, 0xb7, + 0xf1, 0xcc, 0x8b, 0xb6, 0x05, 0x38, 0x7f, 0x42, + 0xfb, 0xc6, 0x81, 0xbc, 0x0f, 0x32, 0x75, 0x48, + 0x0e, 0x33, 0x74, 0x49, 0xfa, 0xc7, 0x80, 0xbd, + 0x0c, 0x31, 0x76, 0x4b, 0xf8, 0xc5, 0x82, 0xbf, + 0xf9, 0xc4, 0x83, 0xbe, 0x0d, 0x30, 0x77, 0x4a, + 0x08, 0x35, 0x72, 0x4f, 0xfc, 0xc1, 0x86, 0xbb, + 0xfd, 0xc0, 0x87, 0xba, 0x09, 0x34, 0x73, 0x4e, + 0xff, 0xc2, 0x85, 0xb8, 0x0b, 0x36, 0x71, 0x4c, + 0x0a, 0x37, 0x70, 0x4d, 0xfe, 0xc3, 0x84, 0xb9, + 0xeb, 0xd6, 0x91, 0xac, 0x1f, 0x22, 0x65, 0x58, + 0x1e, 0x23, 0x64, 0x59, 0xea, 0xd7, 0x90, 0xad, + 0x1c, 0x21, 0x66, 0x5b, 0xe8, 0xd5, 0x92, 0xaf, + 0xe9, 0xd4, 0x93, 0xae, 0x1d, 0x20, 0x67, 0x5a, + 0x18, 0x25, 0x62, 0x5f, 0xec, 0xd1, 0x96, 0xab, + 0xed, 0xd0, 0x97, 0xaa, 0x19, 0x24, 0x63, 0x5e, + 0xef, 0xd2, 0x95, 0xa8, 0x1b, 0x26, 0x61, 0x5c, + 0x1a, 0x27, 0x60, 0x5d, 0xee, 0xd3, 0x94, 0xa9, + 0x10, 0x2d, 0x6a, 0x57, 0xe4, 0xd9, 0x9e, 0xa3, + 0xe5, 0xd8, 0x9f, 0xa2, 0x11, 0x2c, 0x6b, 0x56, + 0xe7, 0xda, 0x9d, 0xa0, 0x13, 0x2e, 0x69, 0x54, + 0x12, 0x2f, 0x68, 0x55, 0xe6, 0xdb, 0x9c, 0xa1, + 0xe3, 0xde, 0x99, 0xa4, 0x17, 0x2a, 0x6d, 0x50, + 0x16, 0x2b, 0x6c, 0x51, 0xe2, 0xdf, 0x98, 0xa5, + 0x14, 0x29, 0x6e, 0x53, 0xe0, 0xdd, 0x9a, 0xa7, + 0xe1, 0xdc, 0x9b, 0xa6, 0x15, 0x28, 0x6f, 0x52, + }, + { + 0x00, 0x3e, 0x7c, 0x42, 0xf8, 0xc6, 0x84, 0xba, + 0xed, 0xd3, 0x91, 0xaf, 0x15, 0x2b, 0x69, 0x57, + 0xc7, 0xf9, 0xbb, 0x85, 0x3f, 0x01, 0x43, 0x7d, + 0x2a, 0x14, 0x56, 0x68, 0xd2, 0xec, 0xae, 0x90, + 0x93, 0xad, 0xef, 0xd1, 0x6b, 0x55, 0x17, 0x29, + 0x7e, 0x40, 0x02, 0x3c, 0x86, 0xb8, 0xfa, 0xc4, + 0x54, 0x6a, 0x28, 0x16, 0xac, 0x92, 0xd0, 0xee, + 0xb9, 0x87, 0xc5, 0xfb, 0x41, 0x7f, 0x3d, 0x03, + 0x3b, 0x05, 0x47, 0x79, 0xc3, 0xfd, 0xbf, 0x81, + 0xd6, 0xe8, 0xaa, 0x94, 0x2e, 0x10, 0x52, 0x6c, + 0xfc, 0xc2, 0x80, 0xbe, 0x04, 0x3a, 0x78, 0x46, + 0x11, 0x2f, 0x6d, 0x53, 0xe9, 0xd7, 0x95, 0xab, + 0xa8, 0x96, 0xd4, 0xea, 0x50, 0x6e, 0x2c, 0x12, + 0x45, 0x7b, 0x39, 0x07, 0xbd, 0x83, 0xc1, 0xff, + 0x6f, 0x51, 0x13, 0x2d, 0x97, 0xa9, 0xeb, 0xd5, + 0x82, 0xbc, 0xfe, 0xc0, 0x7a, 0x44, 0x06, 0x38, + 0x76, 0x48, 0x0a, 0x34, 0x8e, 0xb0, 0xf2, 0xcc, + 0x9b, 0xa5, 0xe7, 0xd9, 0x63, 0x5d, 0x1f, 0x21, + 0xb1, 0x8f, 0xcd, 0xf3, 0x49, 0x77, 0x35, 0x0b, + 0x5c, 0x62, 0x20, 0x1e, 0xa4, 0x9a, 0xd8, 0xe6, + 0xe5, 0xdb, 0x99, 0xa7, 0x1d, 0x23, 0x61, 0x5f, + 0x08, 0x36, 0x74, 0x4a, 0xf0, 0xce, 0x8c, 0xb2, + 0x22, 0x1c, 0x5e, 0x60, 0xda, 0xe4, 0xa6, 0x98, + 0xcf, 0xf1, 0xb3, 0x8d, 0x37, 0x09, 0x4b, 0x75, + 0x4d, 0x73, 0x31, 0x0f, 0xb5, 0x8b, 0xc9, 0xf7, + 0xa0, 0x9e, 0xdc, 0xe2, 0x58, 0x66, 0x24, 0x1a, + 0x8a, 0xb4, 0xf6, 0xc8, 0x72, 0x4c, 0x0e, 0x30, + 0x67, 0x59, 0x1b, 0x25, 0x9f, 0xa1, 0xe3, 0xdd, + 0xde, 0xe0, 0xa2, 0x9c, 0x26, 0x18, 0x5a, 0x64, + 0x33, 0x0d, 0x4f, 0x71, 0xcb, 0xf5, 0xb7, 0x89, + 0x19, 0x27, 0x65, 0x5b, 0xe1, 0xdf, 0x9d, 0xa3, + 0xf4, 0xca, 0x88, 0xb6, 0x0c, 0x32, 0x70, 0x4e, + }, + { + 0x00, 0x3f, 0x7e, 0x41, 0xfc, 0xc3, 0x82, 0xbd, + 0xe5, 0xda, 0x9b, 0xa4, 0x19, 0x26, 0x67, 0x58, + 0xd7, 0xe8, 0xa9, 0x96, 0x2b, 0x14, 0x55, 0x6a, + 0x32, 0x0d, 0x4c, 0x73, 0xce, 0xf1, 0xb0, 0x8f, + 0xb3, 0x8c, 0xcd, 0xf2, 0x4f, 0x70, 0x31, 0x0e, + 0x56, 0x69, 0x28, 0x17, 0xaa, 0x95, 0xd4, 0xeb, + 0x64, 0x5b, 0x1a, 0x25, 0x98, 0xa7, 0xe6, 0xd9, + 0x81, 0xbe, 0xff, 0xc0, 0x7d, 0x42, 0x03, 0x3c, + 0x7b, 0x44, 0x05, 0x3a, 0x87, 0xb8, 0xf9, 0xc6, + 0x9e, 0xa1, 0xe0, 0xdf, 0x62, 0x5d, 0x1c, 0x23, + 0xac, 0x93, 0xd2, 0xed, 0x50, 0x6f, 0x2e, 0x11, + 0x49, 0x76, 0x37, 0x08, 0xb5, 0x8a, 0xcb, 0xf4, + 0xc8, 0xf7, 0xb6, 0x89, 0x34, 0x0b, 0x4a, 0x75, + 0x2d, 0x12, 0x53, 0x6c, 0xd1, 0xee, 0xaf, 0x90, + 0x1f, 0x20, 0x61, 0x5e, 0xe3, 0xdc, 0x9d, 0xa2, + 0xfa, 0xc5, 0x84, 0xbb, 0x06, 0x39, 0x78, 0x47, + 0xf6, 0xc9, 0x88, 0xb7, 0x0a, 0x35, 0x74, 0x4b, + 0x13, 0x2c, 0x6d, 0x52, 0xef, 0xd0, 0x91, 0xae, + 0x21, 0x1e, 0x5f, 0x60, 0xdd, 0xe2, 0xa3, 0x9c, + 0xc4, 0xfb, 0xba, 0x85, 0x38, 0x07, 0x46, 0x79, + 0x45, 0x7a, 0x3b, 0x04, 0xb9, 0x86, 0xc7, 0xf8, + 0xa0, 0x9f, 0xde, 0xe1, 0x5c, 0x63, 0x22, 0x1d, + 0x92, 0xad, 0xec, 0xd3, 0x6e, 0x51, 0x10, 0x2f, + 0x77, 0x48, 0x09, 0x36, 0x8b, 0xb4, 0xf5, 0xca, + 0x8d, 0xb2, 0xf3, 0xcc, 0x71, 0x4e, 0x0f, 0x30, + 0x68, 0x57, 0x16, 0x29, 0x94, 0xab, 0xea, 0xd5, + 0x5a, 0x65, 0x24, 0x1b, 0xa6, 0x99, 0xd8, 0xe7, + 0xbf, 0x80, 0xc1, 0xfe, 0x43, 0x7c, 0x3d, 0x02, + 0x3e, 0x01, 0x40, 0x7f, 0xc2, 0xfd, 0xbc, 0x83, + 0xdb, 0xe4, 0xa5, 0x9a, 0x27, 0x18, 0x59, 0x66, + 0xe9, 0xd6, 0x97, 0xa8, 0x15, 0x2a, 0x6b, 0x54, + 0x0c, 0x33, 0x72, 0x4d, 0xf0, 0xcf, 0x8e, 0xb1, + }, + { + 0x00, 0x40, 0x80, 0xc0, 0x1d, 0x5d, 0x9d, 0xdd, + 0x3a, 0x7a, 0xba, 0xfa, 0x27, 0x67, 0xa7, 0xe7, + 0x74, 0x34, 0xf4, 0xb4, 0x69, 0x29, 0xe9, 0xa9, + 0x4e, 0x0e, 0xce, 0x8e, 0x53, 0x13, 0xd3, 0x93, + 0xe8, 0xa8, 0x68, 0x28, 0xf5, 0xb5, 0x75, 0x35, + 0xd2, 0x92, 0x52, 0x12, 0xcf, 0x8f, 0x4f, 0x0f, + 0x9c, 0xdc, 0x1c, 0x5c, 0x81, 0xc1, 0x01, 0x41, + 0xa6, 0xe6, 0x26, 0x66, 0xbb, 0xfb, 0x3b, 0x7b, + 0xcd, 0x8d, 0x4d, 0x0d, 0xd0, 0x90, 0x50, 0x10, + 0xf7, 0xb7, 0x77, 0x37, 0xea, 0xaa, 0x6a, 0x2a, + 0xb9, 0xf9, 0x39, 0x79, 0xa4, 0xe4, 0x24, 0x64, + 0x83, 0xc3, 0x03, 0x43, 0x9e, 0xde, 0x1e, 0x5e, + 0x25, 0x65, 0xa5, 0xe5, 0x38, 0x78, 0xb8, 0xf8, + 0x1f, 0x5f, 0x9f, 0xdf, 0x02, 0x42, 0x82, 0xc2, + 0x51, 0x11, 0xd1, 0x91, 0x4c, 0x0c, 0xcc, 0x8c, + 0x6b, 0x2b, 0xeb, 0xab, 0x76, 0x36, 0xf6, 0xb6, + 0x87, 0xc7, 0x07, 0x47, 0x9a, 0xda, 0x1a, 0x5a, + 0xbd, 0xfd, 0x3d, 0x7d, 0xa0, 0xe0, 0x20, 0x60, + 0xf3, 0xb3, 0x73, 0x33, 0xee, 0xae, 0x6e, 0x2e, + 0xc9, 0x89, 0x49, 0x09, 0xd4, 0x94, 0x54, 0x14, + 0x6f, 0x2f, 0xef, 0xaf, 0x72, 0x32, 0xf2, 0xb2, + 0x55, 0x15, 0xd5, 0x95, 0x48, 0x08, 0xc8, 0x88, + 0x1b, 0x5b, 0x9b, 0xdb, 0x06, 0x46, 0x86, 0xc6, + 0x21, 0x61, 0xa1, 0xe1, 0x3c, 0x7c, 0xbc, 0xfc, + 0x4a, 0x0a, 0xca, 0x8a, 0x57, 0x17, 0xd7, 0x97, + 0x70, 0x30, 0xf0, 0xb0, 0x6d, 0x2d, 0xed, 0xad, + 0x3e, 0x7e, 0xbe, 0xfe, 0x23, 0x63, 0xa3, 0xe3, + 0x04, 0x44, 0x84, 0xc4, 0x19, 0x59, 0x99, 0xd9, + 0xa2, 0xe2, 0x22, 0x62, 0xbf, 0xff, 0x3f, 0x7f, + 0x98, 0xd8, 0x18, 0x58, 0x85, 0xc5, 0x05, 0x45, + 0xd6, 0x96, 0x56, 0x16, 0xcb, 0x8b, 0x4b, 0x0b, + 0xec, 0xac, 0x6c, 0x2c, 0xf1, 0xb1, 0x71, 0x31, + }, + { + 0x00, 0x41, 0x82, 0xc3, 0x19, 0x58, 0x9b, 0xda, + 0x32, 0x73, 0xb0, 0xf1, 0x2b, 0x6a, 0xa9, 0xe8, + 0x64, 0x25, 0xe6, 0xa7, 0x7d, 0x3c, 0xff, 0xbe, + 0x56, 0x17, 0xd4, 0x95, 0x4f, 0x0e, 0xcd, 0x8c, + 0xc8, 0x89, 0x4a, 0x0b, 0xd1, 0x90, 0x53, 0x12, + 0xfa, 0xbb, 0x78, 0x39, 0xe3, 0xa2, 0x61, 0x20, + 0xac, 0xed, 0x2e, 0x6f, 0xb5, 0xf4, 0x37, 0x76, + 0x9e, 0xdf, 0x1c, 0x5d, 0x87, 0xc6, 0x05, 0x44, + 0x8d, 0xcc, 0x0f, 0x4e, 0x94, 0xd5, 0x16, 0x57, + 0xbf, 0xfe, 0x3d, 0x7c, 0xa6, 0xe7, 0x24, 0x65, + 0xe9, 0xa8, 0x6b, 0x2a, 0xf0, 0xb1, 0x72, 0x33, + 0xdb, 0x9a, 0x59, 0x18, 0xc2, 0x83, 0x40, 0x01, + 0x45, 0x04, 0xc7, 0x86, 0x5c, 0x1d, 0xde, 0x9f, + 0x77, 0x36, 0xf5, 0xb4, 0x6e, 0x2f, 0xec, 0xad, + 0x21, 0x60, 0xa3, 0xe2, 0x38, 0x79, 0xba, 0xfb, + 0x13, 0x52, 0x91, 0xd0, 0x0a, 0x4b, 0x88, 0xc9, + 0x07, 0x46, 0x85, 0xc4, 0x1e, 0x5f, 0x9c, 0xdd, + 0x35, 0x74, 0xb7, 0xf6, 0x2c, 0x6d, 0xae, 0xef, + 0x63, 0x22, 0xe1, 0xa0, 0x7a, 0x3b, 0xf8, 0xb9, + 0x51, 0x10, 0xd3, 0x92, 0x48, 0x09, 0xca, 0x8b, + 0xcf, 0x8e, 0x4d, 0x0c, 0xd6, 0x97, 0x54, 0x15, + 0xfd, 0xbc, 0x7f, 0x3e, 0xe4, 0xa5, 0x66, 0x27, + 0xab, 0xea, 0x29, 0x68, 0xb2, 0xf3, 0x30, 0x71, + 0x99, 0xd8, 0x1b, 0x5a, 0x80, 0xc1, 0x02, 0x43, + 0x8a, 0xcb, 0x08, 0x49, 0x93, 0xd2, 0x11, 0x50, + 0xb8, 0xf9, 0x3a, 0x7b, 0xa1, 0xe0, 0x23, 0x62, + 0xee, 0xaf, 0x6c, 0x2d, 0xf7, 0xb6, 0x75, 0x34, + 0xdc, 0x9d, 0x5e, 0x1f, 0xc5, 0x84, 0x47, 0x06, + 0x42, 0x03, 0xc0, 0x81, 0x5b, 0x1a, 0xd9, 0x98, + 0x70, 0x31, 0xf2, 0xb3, 0x69, 0x28, 0xeb, 0xaa, + 0x26, 0x67, 0xa4, 0xe5, 0x3f, 0x7e, 0xbd, 0xfc, + 0x14, 0x55, 0x96, 0xd7, 0x0d, 0x4c, 0x8f, 0xce, + }, + { + 0x00, 0x42, 0x84, 0xc6, 0x15, 0x57, 0x91, 0xd3, + 0x2a, 0x68, 0xae, 0xec, 0x3f, 0x7d, 0xbb, 0xf9, + 0x54, 0x16, 0xd0, 0x92, 0x41, 0x03, 0xc5, 0x87, + 0x7e, 0x3c, 0xfa, 0xb8, 0x6b, 0x29, 0xef, 0xad, + 0xa8, 0xea, 0x2c, 0x6e, 0xbd, 0xff, 0x39, 0x7b, + 0x82, 0xc0, 0x06, 0x44, 0x97, 0xd5, 0x13, 0x51, + 0xfc, 0xbe, 0x78, 0x3a, 0xe9, 0xab, 0x6d, 0x2f, + 0xd6, 0x94, 0x52, 0x10, 0xc3, 0x81, 0x47, 0x05, + 0x4d, 0x0f, 0xc9, 0x8b, 0x58, 0x1a, 0xdc, 0x9e, + 0x67, 0x25, 0xe3, 0xa1, 0x72, 0x30, 0xf6, 0xb4, + 0x19, 0x5b, 0x9d, 0xdf, 0x0c, 0x4e, 0x88, 0xca, + 0x33, 0x71, 0xb7, 0xf5, 0x26, 0x64, 0xa2, 0xe0, + 0xe5, 0xa7, 0x61, 0x23, 0xf0, 0xb2, 0x74, 0x36, + 0xcf, 0x8d, 0x4b, 0x09, 0xda, 0x98, 0x5e, 0x1c, + 0xb1, 0xf3, 0x35, 0x77, 0xa4, 0xe6, 0x20, 0x62, + 0x9b, 0xd9, 0x1f, 0x5d, 0x8e, 0xcc, 0x0a, 0x48, + 0x9a, 0xd8, 0x1e, 0x5c, 0x8f, 0xcd, 0x0b, 0x49, + 0xb0, 0xf2, 0x34, 0x76, 0xa5, 0xe7, 0x21, 0x63, + 0xce, 0x8c, 0x4a, 0x08, 0xdb, 0x99, 0x5f, 0x1d, + 0xe4, 0xa6, 0x60, 0x22, 0xf1, 0xb3, 0x75, 0x37, + 0x32, 0x70, 0xb6, 0xf4, 0x27, 0x65, 0xa3, 0xe1, + 0x18, 0x5a, 0x9c, 0xde, 0x0d, 0x4f, 0x89, 0xcb, + 0x66, 0x24, 0xe2, 0xa0, 0x73, 0x31, 0xf7, 0xb5, + 0x4c, 0x0e, 0xc8, 0x8a, 0x59, 0x1b, 0xdd, 0x9f, + 0xd7, 0x95, 0x53, 0x11, 0xc2, 0x80, 0x46, 0x04, + 0xfd, 0xbf, 0x79, 0x3b, 0xe8, 0xaa, 0x6c, 0x2e, + 0x83, 0xc1, 0x07, 0x45, 0x96, 0xd4, 0x12, 0x50, + 0xa9, 0xeb, 0x2d, 0x6f, 0xbc, 0xfe, 0x38, 0x7a, + 0x7f, 0x3d, 0xfb, 0xb9, 0x6a, 0x28, 0xee, 0xac, + 0x55, 0x17, 0xd1, 0x93, 0x40, 0x02, 0xc4, 0x86, + 0x2b, 0x69, 0xaf, 0xed, 0x3e, 0x7c, 0xba, 0xf8, + 0x01, 0x43, 0x85, 0xc7, 0x14, 0x56, 0x90, 0xd2, + }, + { + 0x00, 0x43, 0x86, 0xc5, 0x11, 0x52, 0x97, 0xd4, + 0x22, 0x61, 0xa4, 0xe7, 0x33, 0x70, 0xb5, 0xf6, + 0x44, 0x07, 0xc2, 0x81, 0x55, 0x16, 0xd3, 0x90, + 0x66, 0x25, 0xe0, 0xa3, 0x77, 0x34, 0xf1, 0xb2, + 0x88, 0xcb, 0x0e, 0x4d, 0x99, 0xda, 0x1f, 0x5c, + 0xaa, 0xe9, 0x2c, 0x6f, 0xbb, 0xf8, 0x3d, 0x7e, + 0xcc, 0x8f, 0x4a, 0x09, 0xdd, 0x9e, 0x5b, 0x18, + 0xee, 0xad, 0x68, 0x2b, 0xff, 0xbc, 0x79, 0x3a, + 0x0d, 0x4e, 0x8b, 0xc8, 0x1c, 0x5f, 0x9a, 0xd9, + 0x2f, 0x6c, 0xa9, 0xea, 0x3e, 0x7d, 0xb8, 0xfb, + 0x49, 0x0a, 0xcf, 0x8c, 0x58, 0x1b, 0xde, 0x9d, + 0x6b, 0x28, 0xed, 0xae, 0x7a, 0x39, 0xfc, 0xbf, + 0x85, 0xc6, 0x03, 0x40, 0x94, 0xd7, 0x12, 0x51, + 0xa7, 0xe4, 0x21, 0x62, 0xb6, 0xf5, 0x30, 0x73, + 0xc1, 0x82, 0x47, 0x04, 0xd0, 0x93, 0x56, 0x15, + 0xe3, 0xa0, 0x65, 0x26, 0xf2, 0xb1, 0x74, 0x37, + 0x1a, 0x59, 0x9c, 0xdf, 0x0b, 0x48, 0x8d, 0xce, + 0x38, 0x7b, 0xbe, 0xfd, 0x29, 0x6a, 0xaf, 0xec, + 0x5e, 0x1d, 0xd8, 0x9b, 0x4f, 0x0c, 0xc9, 0x8a, + 0x7c, 0x3f, 0xfa, 0xb9, 0x6d, 0x2e, 0xeb, 0xa8, + 0x92, 0xd1, 0x14, 0x57, 0x83, 0xc0, 0x05, 0x46, + 0xb0, 0xf3, 0x36, 0x75, 0xa1, 0xe2, 0x27, 0x64, + 0xd6, 0x95, 0x50, 0x13, 0xc7, 0x84, 0x41, 0x02, + 0xf4, 0xb7, 0x72, 0x31, 0xe5, 0xa6, 0x63, 0x20, + 0x17, 0x54, 0x91, 0xd2, 0x06, 0x45, 0x80, 0xc3, + 0x35, 0x76, 0xb3, 0xf0, 0x24, 0x67, 0xa2, 0xe1, + 0x53, 0x10, 0xd5, 0x96, 0x42, 0x01, 0xc4, 0x87, + 0x71, 0x32, 0xf7, 0xb4, 0x60, 0x23, 0xe6, 0xa5, + 0x9f, 0xdc, 0x19, 0x5a, 0x8e, 0xcd, 0x08, 0x4b, + 0xbd, 0xfe, 0x3b, 0x78, 0xac, 0xef, 0x2a, 0x69, + 0xdb, 0x98, 0x5d, 0x1e, 0xca, 0x89, 0x4c, 0x0f, + 0xf9, 0xba, 0x7f, 0x3c, 0xe8, 0xab, 0x6e, 0x2d, + }, + { + 0x00, 0x44, 0x88, 0xcc, 0x0d, 0x49, 0x85, 0xc1, + 0x1a, 0x5e, 0x92, 0xd6, 0x17, 0x53, 0x9f, 0xdb, + 0x34, 0x70, 0xbc, 0xf8, 0x39, 0x7d, 0xb1, 0xf5, + 0x2e, 0x6a, 0xa6, 0xe2, 0x23, 0x67, 0xab, 0xef, + 0x68, 0x2c, 0xe0, 0xa4, 0x65, 0x21, 0xed, 0xa9, + 0x72, 0x36, 0xfa, 0xbe, 0x7f, 0x3b, 0xf7, 0xb3, + 0x5c, 0x18, 0xd4, 0x90, 0x51, 0x15, 0xd9, 0x9d, + 0x46, 0x02, 0xce, 0x8a, 0x4b, 0x0f, 0xc3, 0x87, + 0xd0, 0x94, 0x58, 0x1c, 0xdd, 0x99, 0x55, 0x11, + 0xca, 0x8e, 0x42, 0x06, 0xc7, 0x83, 0x4f, 0x0b, + 0xe4, 0xa0, 0x6c, 0x28, 0xe9, 0xad, 0x61, 0x25, + 0xfe, 0xba, 0x76, 0x32, 0xf3, 0xb7, 0x7b, 0x3f, + 0xb8, 0xfc, 0x30, 0x74, 0xb5, 0xf1, 0x3d, 0x79, + 0xa2, 0xe6, 0x2a, 0x6e, 0xaf, 0xeb, 0x27, 0x63, + 0x8c, 0xc8, 0x04, 0x40, 0x81, 0xc5, 0x09, 0x4d, + 0x96, 0xd2, 0x1e, 0x5a, 0x9b, 0xdf, 0x13, 0x57, + 0xbd, 0xf9, 0x35, 0x71, 0xb0, 0xf4, 0x38, 0x7c, + 0xa7, 0xe3, 0x2f, 0x6b, 0xaa, 0xee, 0x22, 0x66, + 0x89, 0xcd, 0x01, 0x45, 0x84, 0xc0, 0x0c, 0x48, + 0x93, 0xd7, 0x1b, 0x5f, 0x9e, 0xda, 0x16, 0x52, + 0xd5, 0x91, 0x5d, 0x19, 0xd8, 0x9c, 0x50, 0x14, + 0xcf, 0x8b, 0x47, 0x03, 0xc2, 0x86, 0x4a, 0x0e, + 0xe1, 0xa5, 0x69, 0x2d, 0xec, 0xa8, 0x64, 0x20, + 0xfb, 0xbf, 0x73, 0x37, 0xf6, 0xb2, 0x7e, 0x3a, + 0x6d, 0x29, 0xe5, 0xa1, 0x60, 0x24, 0xe8, 0xac, + 0x77, 0x33, 0xff, 0xbb, 0x7a, 0x3e, 0xf2, 0xb6, + 0x59, 0x1d, 0xd1, 0x95, 0x54, 0x10, 0xdc, 0x98, + 0x43, 0x07, 0xcb, 0x8f, 0x4e, 0x0a, 0xc6, 0x82, + 0x05, 0x41, 0x8d, 0xc9, 0x08, 0x4c, 0x80, 0xc4, + 0x1f, 0x5b, 0x97, 0xd3, 0x12, 0x56, 0x9a, 0xde, + 0x31, 0x75, 0xb9, 0xfd, 0x3c, 0x78, 0xb4, 0xf0, + 0x2b, 0x6f, 0xa3, 0xe7, 0x26, 0x62, 0xae, 0xea, + }, + { + 0x00, 0x45, 0x8a, 0xcf, 0x09, 0x4c, 0x83, 0xc6, + 0x12, 0x57, 0x98, 0xdd, 0x1b, 0x5e, 0x91, 0xd4, + 0x24, 0x61, 0xae, 0xeb, 0x2d, 0x68, 0xa7, 0xe2, + 0x36, 0x73, 0xbc, 0xf9, 0x3f, 0x7a, 0xb5, 0xf0, + 0x48, 0x0d, 0xc2, 0x87, 0x41, 0x04, 0xcb, 0x8e, + 0x5a, 0x1f, 0xd0, 0x95, 0x53, 0x16, 0xd9, 0x9c, + 0x6c, 0x29, 0xe6, 0xa3, 0x65, 0x20, 0xef, 0xaa, + 0x7e, 0x3b, 0xf4, 0xb1, 0x77, 0x32, 0xfd, 0xb8, + 0x90, 0xd5, 0x1a, 0x5f, 0x99, 0xdc, 0x13, 0x56, + 0x82, 0xc7, 0x08, 0x4d, 0x8b, 0xce, 0x01, 0x44, + 0xb4, 0xf1, 0x3e, 0x7b, 0xbd, 0xf8, 0x37, 0x72, + 0xa6, 0xe3, 0x2c, 0x69, 0xaf, 0xea, 0x25, 0x60, + 0xd8, 0x9d, 0x52, 0x17, 0xd1, 0x94, 0x5b, 0x1e, + 0xca, 0x8f, 0x40, 0x05, 0xc3, 0x86, 0x49, 0x0c, + 0xfc, 0xb9, 0x76, 0x33, 0xf5, 0xb0, 0x7f, 0x3a, + 0xee, 0xab, 0x64, 0x21, 0xe7, 0xa2, 0x6d, 0x28, + 0x3d, 0x78, 0xb7, 0xf2, 0x34, 0x71, 0xbe, 0xfb, + 0x2f, 0x6a, 0xa5, 0xe0, 0x26, 0x63, 0xac, 0xe9, + 0x19, 0x5c, 0x93, 0xd6, 0x10, 0x55, 0x9a, 0xdf, + 0x0b, 0x4e, 0x81, 0xc4, 0x02, 0x47, 0x88, 0xcd, + 0x75, 0x30, 0xff, 0xba, 0x7c, 0x39, 0xf6, 0xb3, + 0x67, 0x22, 0xed, 0xa8, 0x6e, 0x2b, 0xe4, 0xa1, + 0x51, 0x14, 0xdb, 0x9e, 0x58, 0x1d, 0xd2, 0x97, + 0x43, 0x06, 0xc9, 0x8c, 0x4a, 0x0f, 0xc0, 0x85, + 0xad, 0xe8, 0x27, 0x62, 0xa4, 0xe1, 0x2e, 0x6b, + 0xbf, 0xfa, 0x35, 0x70, 0xb6, 0xf3, 0x3c, 0x79, + 0x89, 0xcc, 0x03, 0x46, 0x80, 0xc5, 0x0a, 0x4f, + 0x9b, 0xde, 0x11, 0x54, 0x92, 0xd7, 0x18, 0x5d, + 0xe5, 0xa0, 0x6f, 0x2a, 0xec, 0xa9, 0x66, 0x23, + 0xf7, 0xb2, 0x7d, 0x38, 0xfe, 0xbb, 0x74, 0x31, + 0xc1, 0x84, 0x4b, 0x0e, 0xc8, 0x8d, 0x42, 0x07, + 0xd3, 0x96, 0x59, 0x1c, 0xda, 0x9f, 0x50, 0x15, + }, + { + 0x00, 0x46, 0x8c, 0xca, 0x05, 0x43, 0x89, 0xcf, + 0x0a, 0x4c, 0x86, 0xc0, 0x0f, 0x49, 0x83, 0xc5, + 0x14, 0x52, 0x98, 0xde, 0x11, 0x57, 0x9d, 0xdb, + 0x1e, 0x58, 0x92, 0xd4, 0x1b, 0x5d, 0x97, 0xd1, + 0x28, 0x6e, 0xa4, 0xe2, 0x2d, 0x6b, 0xa1, 0xe7, + 0x22, 0x64, 0xae, 0xe8, 0x27, 0x61, 0xab, 0xed, + 0x3c, 0x7a, 0xb0, 0xf6, 0x39, 0x7f, 0xb5, 0xf3, + 0x36, 0x70, 0xba, 0xfc, 0x33, 0x75, 0xbf, 0xf9, + 0x50, 0x16, 0xdc, 0x9a, 0x55, 0x13, 0xd9, 0x9f, + 0x5a, 0x1c, 0xd6, 0x90, 0x5f, 0x19, 0xd3, 0x95, + 0x44, 0x02, 0xc8, 0x8e, 0x41, 0x07, 0xcd, 0x8b, + 0x4e, 0x08, 0xc2, 0x84, 0x4b, 0x0d, 0xc7, 0x81, + 0x78, 0x3e, 0xf4, 0xb2, 0x7d, 0x3b, 0xf1, 0xb7, + 0x72, 0x34, 0xfe, 0xb8, 0x77, 0x31, 0xfb, 0xbd, + 0x6c, 0x2a, 0xe0, 0xa6, 0x69, 0x2f, 0xe5, 0xa3, + 0x66, 0x20, 0xea, 0xac, 0x63, 0x25, 0xef, 0xa9, + 0xa0, 0xe6, 0x2c, 0x6a, 0xa5, 0xe3, 0x29, 0x6f, + 0xaa, 0xec, 0x26, 0x60, 0xaf, 0xe9, 0x23, 0x65, + 0xb4, 0xf2, 0x38, 0x7e, 0xb1, 0xf7, 0x3d, 0x7b, + 0xbe, 0xf8, 0x32, 0x74, 0xbb, 0xfd, 0x37, 0x71, + 0x88, 0xce, 0x04, 0x42, 0x8d, 0xcb, 0x01, 0x47, + 0x82, 0xc4, 0x0e, 0x48, 0x87, 0xc1, 0x0b, 0x4d, + 0x9c, 0xda, 0x10, 0x56, 0x99, 0xdf, 0x15, 0x53, + 0x96, 0xd0, 0x1a, 0x5c, 0x93, 0xd5, 0x1f, 0x59, + 0xf0, 0xb6, 0x7c, 0x3a, 0xf5, 0xb3, 0x79, 0x3f, + 0xfa, 0xbc, 0x76, 0x30, 0xff, 0xb9, 0x73, 0x35, + 0xe4, 0xa2, 0x68, 0x2e, 0xe1, 0xa7, 0x6d, 0x2b, + 0xee, 0xa8, 0x62, 0x24, 0xeb, 0xad, 0x67, 0x21, + 0xd8, 0x9e, 0x54, 0x12, 0xdd, 0x9b, 0x51, 0x17, + 0xd2, 0x94, 0x5e, 0x18, 0xd7, 0x91, 0x5b, 0x1d, + 0xcc, 0x8a, 0x40, 0x06, 0xc9, 0x8f, 0x45, 0x03, + 0xc6, 0x80, 0x4a, 0x0c, 0xc3, 0x85, 0x4f, 0x09, + }, + { + 0x00, 0x47, 0x8e, 0xc9, 0x01, 0x46, 0x8f, 0xc8, + 0x02, 0x45, 0x8c, 0xcb, 0x03, 0x44, 0x8d, 0xca, + 0x04, 0x43, 0x8a, 0xcd, 0x05, 0x42, 0x8b, 0xcc, + 0x06, 0x41, 0x88, 0xcf, 0x07, 0x40, 0x89, 0xce, + 0x08, 0x4f, 0x86, 0xc1, 0x09, 0x4e, 0x87, 0xc0, + 0x0a, 0x4d, 0x84, 0xc3, 0x0b, 0x4c, 0x85, 0xc2, + 0x0c, 0x4b, 0x82, 0xc5, 0x0d, 0x4a, 0x83, 0xc4, + 0x0e, 0x49, 0x80, 0xc7, 0x0f, 0x48, 0x81, 0xc6, + 0x10, 0x57, 0x9e, 0xd9, 0x11, 0x56, 0x9f, 0xd8, + 0x12, 0x55, 0x9c, 0xdb, 0x13, 0x54, 0x9d, 0xda, + 0x14, 0x53, 0x9a, 0xdd, 0x15, 0x52, 0x9b, 0xdc, + 0x16, 0x51, 0x98, 0xdf, 0x17, 0x50, 0x99, 0xde, + 0x18, 0x5f, 0x96, 0xd1, 0x19, 0x5e, 0x97, 0xd0, + 0x1a, 0x5d, 0x94, 0xd3, 0x1b, 0x5c, 0x95, 0xd2, + 0x1c, 0x5b, 0x92, 0xd5, 0x1d, 0x5a, 0x93, 0xd4, + 0x1e, 0x59, 0x90, 0xd7, 0x1f, 0x58, 0x91, 0xd6, + 0x20, 0x67, 0xae, 0xe9, 0x21, 0x66, 0xaf, 0xe8, + 0x22, 0x65, 0xac, 0xeb, 0x23, 0x64, 0xad, 0xea, + 0x24, 0x63, 0xaa, 0xed, 0x25, 0x62, 0xab, 0xec, + 0x26, 0x61, 0xa8, 0xef, 0x27, 0x60, 0xa9, 0xee, + 0x28, 0x6f, 0xa6, 0xe1, 0x29, 0x6e, 0xa7, 0xe0, + 0x2a, 0x6d, 0xa4, 0xe3, 0x2b, 0x6c, 0xa5, 0xe2, + 0x2c, 0x6b, 0xa2, 0xe5, 0x2d, 0x6a, 0xa3, 0xe4, + 0x2e, 0x69, 0xa0, 0xe7, 0x2f, 0x68, 0xa1, 0xe6, + 0x30, 0x77, 0xbe, 0xf9, 0x31, 0x76, 0xbf, 0xf8, + 0x32, 0x75, 0xbc, 0xfb, 0x33, 0x74, 0xbd, 0xfa, + 0x34, 0x73, 0xba, 0xfd, 0x35, 0x72, 0xbb, 0xfc, + 0x36, 0x71, 0xb8, 0xff, 0x37, 0x70, 0xb9, 0xfe, + 0x38, 0x7f, 0xb6, 0xf1, 0x39, 0x7e, 0xb7, 0xf0, + 0x3a, 0x7d, 0xb4, 0xf3, 0x3b, 0x7c, 0xb5, 0xf2, + 0x3c, 0x7b, 0xb2, 0xf5, 0x3d, 0x7a, 0xb3, 0xf4, + 0x3e, 0x79, 0xb0, 0xf7, 0x3f, 0x78, 0xb1, 0xf6, + }, + { + 0x00, 0x48, 0x90, 0xd8, 0x3d, 0x75, 0xad, 0xe5, + 0x7a, 0x32, 0xea, 0xa2, 0x47, 0x0f, 0xd7, 0x9f, + 0xf4, 0xbc, 0x64, 0x2c, 0xc9, 0x81, 0x59, 0x11, + 0x8e, 0xc6, 0x1e, 0x56, 0xb3, 0xfb, 0x23, 0x6b, + 0xf5, 0xbd, 0x65, 0x2d, 0xc8, 0x80, 0x58, 0x10, + 0x8f, 0xc7, 0x1f, 0x57, 0xb2, 0xfa, 0x22, 0x6a, + 0x01, 0x49, 0x91, 0xd9, 0x3c, 0x74, 0xac, 0xe4, + 0x7b, 0x33, 0xeb, 0xa3, 0x46, 0x0e, 0xd6, 0x9e, + 0xf7, 0xbf, 0x67, 0x2f, 0xca, 0x82, 0x5a, 0x12, + 0x8d, 0xc5, 0x1d, 0x55, 0xb0, 0xf8, 0x20, 0x68, + 0x03, 0x4b, 0x93, 0xdb, 0x3e, 0x76, 0xae, 0xe6, + 0x79, 0x31, 0xe9, 0xa1, 0x44, 0x0c, 0xd4, 0x9c, + 0x02, 0x4a, 0x92, 0xda, 0x3f, 0x77, 0xaf, 0xe7, + 0x78, 0x30, 0xe8, 0xa0, 0x45, 0x0d, 0xd5, 0x9d, + 0xf6, 0xbe, 0x66, 0x2e, 0xcb, 0x83, 0x5b, 0x13, + 0x8c, 0xc4, 0x1c, 0x54, 0xb1, 0xf9, 0x21, 0x69, + 0xf3, 0xbb, 0x63, 0x2b, 0xce, 0x86, 0x5e, 0x16, + 0x89, 0xc1, 0x19, 0x51, 0xb4, 0xfc, 0x24, 0x6c, + 0x07, 0x4f, 0x97, 0xdf, 0x3a, 0x72, 0xaa, 0xe2, + 0x7d, 0x35, 0xed, 0xa5, 0x40, 0x08, 0xd0, 0x98, + 0x06, 0x4e, 0x96, 0xde, 0x3b, 0x73, 0xab, 0xe3, + 0x7c, 0x34, 0xec, 0xa4, 0x41, 0x09, 0xd1, 0x99, + 0xf2, 0xba, 0x62, 0x2a, 0xcf, 0x87, 0x5f, 0x17, + 0x88, 0xc0, 0x18, 0x50, 0xb5, 0xfd, 0x25, 0x6d, + 0x04, 0x4c, 0x94, 0xdc, 0x39, 0x71, 0xa9, 0xe1, + 0x7e, 0x36, 0xee, 0xa6, 0x43, 0x0b, 0xd3, 0x9b, + 0xf0, 0xb8, 0x60, 0x28, 0xcd, 0x85, 0x5d, 0x15, + 0x8a, 0xc2, 0x1a, 0x52, 0xb7, 0xff, 0x27, 0x6f, + 0xf1, 0xb9, 0x61, 0x29, 0xcc, 0x84, 0x5c, 0x14, + 0x8b, 0xc3, 0x1b, 0x53, 0xb6, 0xfe, 0x26, 0x6e, + 0x05, 0x4d, 0x95, 0xdd, 0x38, 0x70, 0xa8, 0xe0, + 0x7f, 0x37, 0xef, 0xa7, 0x42, 0x0a, 0xd2, 0x9a, + }, + { + 0x00, 0x49, 0x92, 0xdb, 0x39, 0x70, 0xab, 0xe2, + 0x72, 0x3b, 0xe0, 0xa9, 0x4b, 0x02, 0xd9, 0x90, + 0xe4, 0xad, 0x76, 0x3f, 0xdd, 0x94, 0x4f, 0x06, + 0x96, 0xdf, 0x04, 0x4d, 0xaf, 0xe6, 0x3d, 0x74, + 0xd5, 0x9c, 0x47, 0x0e, 0xec, 0xa5, 0x7e, 0x37, + 0xa7, 0xee, 0x35, 0x7c, 0x9e, 0xd7, 0x0c, 0x45, + 0x31, 0x78, 0xa3, 0xea, 0x08, 0x41, 0x9a, 0xd3, + 0x43, 0x0a, 0xd1, 0x98, 0x7a, 0x33, 0xe8, 0xa1, + 0xb7, 0xfe, 0x25, 0x6c, 0x8e, 0xc7, 0x1c, 0x55, + 0xc5, 0x8c, 0x57, 0x1e, 0xfc, 0xb5, 0x6e, 0x27, + 0x53, 0x1a, 0xc1, 0x88, 0x6a, 0x23, 0xf8, 0xb1, + 0x21, 0x68, 0xb3, 0xfa, 0x18, 0x51, 0x8a, 0xc3, + 0x62, 0x2b, 0xf0, 0xb9, 0x5b, 0x12, 0xc9, 0x80, + 0x10, 0x59, 0x82, 0xcb, 0x29, 0x60, 0xbb, 0xf2, + 0x86, 0xcf, 0x14, 0x5d, 0xbf, 0xf6, 0x2d, 0x64, + 0xf4, 0xbd, 0x66, 0x2f, 0xcd, 0x84, 0x5f, 0x16, + 0x73, 0x3a, 0xe1, 0xa8, 0x4a, 0x03, 0xd8, 0x91, + 0x01, 0x48, 0x93, 0xda, 0x38, 0x71, 0xaa, 0xe3, + 0x97, 0xde, 0x05, 0x4c, 0xae, 0xe7, 0x3c, 0x75, + 0xe5, 0xac, 0x77, 0x3e, 0xdc, 0x95, 0x4e, 0x07, + 0xa6, 0xef, 0x34, 0x7d, 0x9f, 0xd6, 0x0d, 0x44, + 0xd4, 0x9d, 0x46, 0x0f, 0xed, 0xa4, 0x7f, 0x36, + 0x42, 0x0b, 0xd0, 0x99, 0x7b, 0x32, 0xe9, 0xa0, + 0x30, 0x79, 0xa2, 0xeb, 0x09, 0x40, 0x9b, 0xd2, + 0xc4, 0x8d, 0x56, 0x1f, 0xfd, 0xb4, 0x6f, 0x26, + 0xb6, 0xff, 0x24, 0x6d, 0x8f, 0xc6, 0x1d, 0x54, + 0x20, 0x69, 0xb2, 0xfb, 0x19, 0x50, 0x8b, 0xc2, + 0x52, 0x1b, 0xc0, 0x89, 0x6b, 0x22, 0xf9, 0xb0, + 0x11, 0x58, 0x83, 0xca, 0x28, 0x61, 0xba, 0xf3, + 0x63, 0x2a, 0xf1, 0xb8, 0x5a, 0x13, 0xc8, 0x81, + 0xf5, 0xbc, 0x67, 0x2e, 0xcc, 0x85, 0x5e, 0x17, + 0x87, 0xce, 0x15, 0x5c, 0xbe, 0xf7, 0x2c, 0x65, + }, + { + 0x00, 0x4a, 0x94, 0xde, 0x35, 0x7f, 0xa1, 0xeb, + 0x6a, 0x20, 0xfe, 0xb4, 0x5f, 0x15, 0xcb, 0x81, + 0xd4, 0x9e, 0x40, 0x0a, 0xe1, 0xab, 0x75, 0x3f, + 0xbe, 0xf4, 0x2a, 0x60, 0x8b, 0xc1, 0x1f, 0x55, + 0xb5, 0xff, 0x21, 0x6b, 0x80, 0xca, 0x14, 0x5e, + 0xdf, 0x95, 0x4b, 0x01, 0xea, 0xa0, 0x7e, 0x34, + 0x61, 0x2b, 0xf5, 0xbf, 0x54, 0x1e, 0xc0, 0x8a, + 0x0b, 0x41, 0x9f, 0xd5, 0x3e, 0x74, 0xaa, 0xe0, + 0x77, 0x3d, 0xe3, 0xa9, 0x42, 0x08, 0xd6, 0x9c, + 0x1d, 0x57, 0x89, 0xc3, 0x28, 0x62, 0xbc, 0xf6, + 0xa3, 0xe9, 0x37, 0x7d, 0x96, 0xdc, 0x02, 0x48, + 0xc9, 0x83, 0x5d, 0x17, 0xfc, 0xb6, 0x68, 0x22, + 0xc2, 0x88, 0x56, 0x1c, 0xf7, 0xbd, 0x63, 0x29, + 0xa8, 0xe2, 0x3c, 0x76, 0x9d, 0xd7, 0x09, 0x43, + 0x16, 0x5c, 0x82, 0xc8, 0x23, 0x69, 0xb7, 0xfd, + 0x7c, 0x36, 0xe8, 0xa2, 0x49, 0x03, 0xdd, 0x97, + 0xee, 0xa4, 0x7a, 0x30, 0xdb, 0x91, 0x4f, 0x05, + 0x84, 0xce, 0x10, 0x5a, 0xb1, 0xfb, 0x25, 0x6f, + 0x3a, 0x70, 0xae, 0xe4, 0x0f, 0x45, 0x9b, 0xd1, + 0x50, 0x1a, 0xc4, 0x8e, 0x65, 0x2f, 0xf1, 0xbb, + 0x5b, 0x11, 0xcf, 0x85, 0x6e, 0x24, 0xfa, 0xb0, + 0x31, 0x7b, 0xa5, 0xef, 0x04, 0x4e, 0x90, 0xda, + 0x8f, 0xc5, 0x1b, 0x51, 0xba, 0xf0, 0x2e, 0x64, + 0xe5, 0xaf, 0x71, 0x3b, 0xd0, 0x9a, 0x44, 0x0e, + 0x99, 0xd3, 0x0d, 0x47, 0xac, 0xe6, 0x38, 0x72, + 0xf3, 0xb9, 0x67, 0x2d, 0xc6, 0x8c, 0x52, 0x18, + 0x4d, 0x07, 0xd9, 0x93, 0x78, 0x32, 0xec, 0xa6, + 0x27, 0x6d, 0xb3, 0xf9, 0x12, 0x58, 0x86, 0xcc, + 0x2c, 0x66, 0xb8, 0xf2, 0x19, 0x53, 0x8d, 0xc7, + 0x46, 0x0c, 0xd2, 0x98, 0x73, 0x39, 0xe7, 0xad, + 0xf8, 0xb2, 0x6c, 0x26, 0xcd, 0x87, 0x59, 0x13, + 0x92, 0xd8, 0x06, 0x4c, 0xa7, 0xed, 0x33, 0x79, + }, + { + 0x00, 0x4b, 0x96, 0xdd, 0x31, 0x7a, 0xa7, 0xec, + 0x62, 0x29, 0xf4, 0xbf, 0x53, 0x18, 0xc5, 0x8e, + 0xc4, 0x8f, 0x52, 0x19, 0xf5, 0xbe, 0x63, 0x28, + 0xa6, 0xed, 0x30, 0x7b, 0x97, 0xdc, 0x01, 0x4a, + 0x95, 0xde, 0x03, 0x48, 0xa4, 0xef, 0x32, 0x79, + 0xf7, 0xbc, 0x61, 0x2a, 0xc6, 0x8d, 0x50, 0x1b, + 0x51, 0x1a, 0xc7, 0x8c, 0x60, 0x2b, 0xf6, 0xbd, + 0x33, 0x78, 0xa5, 0xee, 0x02, 0x49, 0x94, 0xdf, + 0x37, 0x7c, 0xa1, 0xea, 0x06, 0x4d, 0x90, 0xdb, + 0x55, 0x1e, 0xc3, 0x88, 0x64, 0x2f, 0xf2, 0xb9, + 0xf3, 0xb8, 0x65, 0x2e, 0xc2, 0x89, 0x54, 0x1f, + 0x91, 0xda, 0x07, 0x4c, 0xa0, 0xeb, 0x36, 0x7d, + 0xa2, 0xe9, 0x34, 0x7f, 0x93, 0xd8, 0x05, 0x4e, + 0xc0, 0x8b, 0x56, 0x1d, 0xf1, 0xba, 0x67, 0x2c, + 0x66, 0x2d, 0xf0, 0xbb, 0x57, 0x1c, 0xc1, 0x8a, + 0x04, 0x4f, 0x92, 0xd9, 0x35, 0x7e, 0xa3, 0xe8, + 0x6e, 0x25, 0xf8, 0xb3, 0x5f, 0x14, 0xc9, 0x82, + 0x0c, 0x47, 0x9a, 0xd1, 0x3d, 0x76, 0xab, 0xe0, + 0xaa, 0xe1, 0x3c, 0x77, 0x9b, 0xd0, 0x0d, 0x46, + 0xc8, 0x83, 0x5e, 0x15, 0xf9, 0xb2, 0x6f, 0x24, + 0xfb, 0xb0, 0x6d, 0x26, 0xca, 0x81, 0x5c, 0x17, + 0x99, 0xd2, 0x0f, 0x44, 0xa8, 0xe3, 0x3e, 0x75, + 0x3f, 0x74, 0xa9, 0xe2, 0x0e, 0x45, 0x98, 0xd3, + 0x5d, 0x16, 0xcb, 0x80, 0x6c, 0x27, 0xfa, 0xb1, + 0x59, 0x12, 0xcf, 0x84, 0x68, 0x23, 0xfe, 0xb5, + 0x3b, 0x70, 0xad, 0xe6, 0x0a, 0x41, 0x9c, 0xd7, + 0x9d, 0xd6, 0x0b, 0x40, 0xac, 0xe7, 0x3a, 0x71, + 0xff, 0xb4, 0x69, 0x22, 0xce, 0x85, 0x58, 0x13, + 0xcc, 0x87, 0x5a, 0x11, 0xfd, 0xb6, 0x6b, 0x20, + 0xae, 0xe5, 0x38, 0x73, 0x9f, 0xd4, 0x09, 0x42, + 0x08, 0x43, 0x9e, 0xd5, 0x39, 0x72, 0xaf, 0xe4, + 0x6a, 0x21, 0xfc, 0xb7, 0x5b, 0x10, 0xcd, 0x86, + }, + { + 0x00, 0x4c, 0x98, 0xd4, 0x2d, 0x61, 0xb5, 0xf9, + 0x5a, 0x16, 0xc2, 0x8e, 0x77, 0x3b, 0xef, 0xa3, + 0xb4, 0xf8, 0x2c, 0x60, 0x99, 0xd5, 0x01, 0x4d, + 0xee, 0xa2, 0x76, 0x3a, 0xc3, 0x8f, 0x5b, 0x17, + 0x75, 0x39, 0xed, 0xa1, 0x58, 0x14, 0xc0, 0x8c, + 0x2f, 0x63, 0xb7, 0xfb, 0x02, 0x4e, 0x9a, 0xd6, + 0xc1, 0x8d, 0x59, 0x15, 0xec, 0xa0, 0x74, 0x38, + 0x9b, 0xd7, 0x03, 0x4f, 0xb6, 0xfa, 0x2e, 0x62, + 0xea, 0xa6, 0x72, 0x3e, 0xc7, 0x8b, 0x5f, 0x13, + 0xb0, 0xfc, 0x28, 0x64, 0x9d, 0xd1, 0x05, 0x49, + 0x5e, 0x12, 0xc6, 0x8a, 0x73, 0x3f, 0xeb, 0xa7, + 0x04, 0x48, 0x9c, 0xd0, 0x29, 0x65, 0xb1, 0xfd, + 0x9f, 0xd3, 0x07, 0x4b, 0xb2, 0xfe, 0x2a, 0x66, + 0xc5, 0x89, 0x5d, 0x11, 0xe8, 0xa4, 0x70, 0x3c, + 0x2b, 0x67, 0xb3, 0xff, 0x06, 0x4a, 0x9e, 0xd2, + 0x71, 0x3d, 0xe9, 0xa5, 0x5c, 0x10, 0xc4, 0x88, + 0xc9, 0x85, 0x51, 0x1d, 0xe4, 0xa8, 0x7c, 0x30, + 0x93, 0xdf, 0x0b, 0x47, 0xbe, 0xf2, 0x26, 0x6a, + 0x7d, 0x31, 0xe5, 0xa9, 0x50, 0x1c, 0xc8, 0x84, + 0x27, 0x6b, 0xbf, 0xf3, 0x0a, 0x46, 0x92, 0xde, + 0xbc, 0xf0, 0x24, 0x68, 0x91, 0xdd, 0x09, 0x45, + 0xe6, 0xaa, 0x7e, 0x32, 0xcb, 0x87, 0x53, 0x1f, + 0x08, 0x44, 0x90, 0xdc, 0x25, 0x69, 0xbd, 0xf1, + 0x52, 0x1e, 0xca, 0x86, 0x7f, 0x33, 0xe7, 0xab, + 0x23, 0x6f, 0xbb, 0xf7, 0x0e, 0x42, 0x96, 0xda, + 0x79, 0x35, 0xe1, 0xad, 0x54, 0x18, 0xcc, 0x80, + 0x97, 0xdb, 0x0f, 0x43, 0xba, 0xf6, 0x22, 0x6e, + 0xcd, 0x81, 0x55, 0x19, 0xe0, 0xac, 0x78, 0x34, + 0x56, 0x1a, 0xce, 0x82, 0x7b, 0x37, 0xe3, 0xaf, + 0x0c, 0x40, 0x94, 0xd8, 0x21, 0x6d, 0xb9, 0xf5, + 0xe2, 0xae, 0x7a, 0x36, 0xcf, 0x83, 0x57, 0x1b, + 0xb8, 0xf4, 0x20, 0x6c, 0x95, 0xd9, 0x0d, 0x41, + }, + { + 0x00, 0x4d, 0x9a, 0xd7, 0x29, 0x64, 0xb3, 0xfe, + 0x52, 0x1f, 0xc8, 0x85, 0x7b, 0x36, 0xe1, 0xac, + 0xa4, 0xe9, 0x3e, 0x73, 0x8d, 0xc0, 0x17, 0x5a, + 0xf6, 0xbb, 0x6c, 0x21, 0xdf, 0x92, 0x45, 0x08, + 0x55, 0x18, 0xcf, 0x82, 0x7c, 0x31, 0xe6, 0xab, + 0x07, 0x4a, 0x9d, 0xd0, 0x2e, 0x63, 0xb4, 0xf9, + 0xf1, 0xbc, 0x6b, 0x26, 0xd8, 0x95, 0x42, 0x0f, + 0xa3, 0xee, 0x39, 0x74, 0x8a, 0xc7, 0x10, 0x5d, + 0xaa, 0xe7, 0x30, 0x7d, 0x83, 0xce, 0x19, 0x54, + 0xf8, 0xb5, 0x62, 0x2f, 0xd1, 0x9c, 0x4b, 0x06, + 0x0e, 0x43, 0x94, 0xd9, 0x27, 0x6a, 0xbd, 0xf0, + 0x5c, 0x11, 0xc6, 0x8b, 0x75, 0x38, 0xef, 0xa2, + 0xff, 0xb2, 0x65, 0x28, 0xd6, 0x9b, 0x4c, 0x01, + 0xad, 0xe0, 0x37, 0x7a, 0x84, 0xc9, 0x1e, 0x53, + 0x5b, 0x16, 0xc1, 0x8c, 0x72, 0x3f, 0xe8, 0xa5, + 0x09, 0x44, 0x93, 0xde, 0x20, 0x6d, 0xba, 0xf7, + 0x49, 0x04, 0xd3, 0x9e, 0x60, 0x2d, 0xfa, 0xb7, + 0x1b, 0x56, 0x81, 0xcc, 0x32, 0x7f, 0xa8, 0xe5, + 0xed, 0xa0, 0x77, 0x3a, 0xc4, 0x89, 0x5e, 0x13, + 0xbf, 0xf2, 0x25, 0x68, 0x96, 0xdb, 0x0c, 0x41, + 0x1c, 0x51, 0x86, 0xcb, 0x35, 0x78, 0xaf, 0xe2, + 0x4e, 0x03, 0xd4, 0x99, 0x67, 0x2a, 0xfd, 0xb0, + 0xb8, 0xf5, 0x22, 0x6f, 0x91, 0xdc, 0x0b, 0x46, + 0xea, 0xa7, 0x70, 0x3d, 0xc3, 0x8e, 0x59, 0x14, + 0xe3, 0xae, 0x79, 0x34, 0xca, 0x87, 0x50, 0x1d, + 0xb1, 0xfc, 0x2b, 0x66, 0x98, 0xd5, 0x02, 0x4f, + 0x47, 0x0a, 0xdd, 0x90, 0x6e, 0x23, 0xf4, 0xb9, + 0x15, 0x58, 0x8f, 0xc2, 0x3c, 0x71, 0xa6, 0xeb, + 0xb6, 0xfb, 0x2c, 0x61, 0x9f, 0xd2, 0x05, 0x48, + 0xe4, 0xa9, 0x7e, 0x33, 0xcd, 0x80, 0x57, 0x1a, + 0x12, 0x5f, 0x88, 0xc5, 0x3b, 0x76, 0xa1, 0xec, + 0x40, 0x0d, 0xda, 0x97, 0x69, 0x24, 0xf3, 0xbe, + }, + { + 0x00, 0x4e, 0x9c, 0xd2, 0x25, 0x6b, 0xb9, 0xf7, + 0x4a, 0x04, 0xd6, 0x98, 0x6f, 0x21, 0xf3, 0xbd, + 0x94, 0xda, 0x08, 0x46, 0xb1, 0xff, 0x2d, 0x63, + 0xde, 0x90, 0x42, 0x0c, 0xfb, 0xb5, 0x67, 0x29, + 0x35, 0x7b, 0xa9, 0xe7, 0x10, 0x5e, 0x8c, 0xc2, + 0x7f, 0x31, 0xe3, 0xad, 0x5a, 0x14, 0xc6, 0x88, + 0xa1, 0xef, 0x3d, 0x73, 0x84, 0xca, 0x18, 0x56, + 0xeb, 0xa5, 0x77, 0x39, 0xce, 0x80, 0x52, 0x1c, + 0x6a, 0x24, 0xf6, 0xb8, 0x4f, 0x01, 0xd3, 0x9d, + 0x20, 0x6e, 0xbc, 0xf2, 0x05, 0x4b, 0x99, 0xd7, + 0xfe, 0xb0, 0x62, 0x2c, 0xdb, 0x95, 0x47, 0x09, + 0xb4, 0xfa, 0x28, 0x66, 0x91, 0xdf, 0x0d, 0x43, + 0x5f, 0x11, 0xc3, 0x8d, 0x7a, 0x34, 0xe6, 0xa8, + 0x15, 0x5b, 0x89, 0xc7, 0x30, 0x7e, 0xac, 0xe2, + 0xcb, 0x85, 0x57, 0x19, 0xee, 0xa0, 0x72, 0x3c, + 0x81, 0xcf, 0x1d, 0x53, 0xa4, 0xea, 0x38, 0x76, + 0xd4, 0x9a, 0x48, 0x06, 0xf1, 0xbf, 0x6d, 0x23, + 0x9e, 0xd0, 0x02, 0x4c, 0xbb, 0xf5, 0x27, 0x69, + 0x40, 0x0e, 0xdc, 0x92, 0x65, 0x2b, 0xf9, 0xb7, + 0x0a, 0x44, 0x96, 0xd8, 0x2f, 0x61, 0xb3, 0xfd, + 0xe1, 0xaf, 0x7d, 0x33, 0xc4, 0x8a, 0x58, 0x16, + 0xab, 0xe5, 0x37, 0x79, 0x8e, 0xc0, 0x12, 0x5c, + 0x75, 0x3b, 0xe9, 0xa7, 0x50, 0x1e, 0xcc, 0x82, + 0x3f, 0x71, 0xa3, 0xed, 0x1a, 0x54, 0x86, 0xc8, + 0xbe, 0xf0, 0x22, 0x6c, 0x9b, 0xd5, 0x07, 0x49, + 0xf4, 0xba, 0x68, 0x26, 0xd1, 0x9f, 0x4d, 0x03, + 0x2a, 0x64, 0xb6, 0xf8, 0x0f, 0x41, 0x93, 0xdd, + 0x60, 0x2e, 0xfc, 0xb2, 0x45, 0x0b, 0xd9, 0x97, + 0x8b, 0xc5, 0x17, 0x59, 0xae, 0xe0, 0x32, 0x7c, + 0xc1, 0x8f, 0x5d, 0x13, 0xe4, 0xaa, 0x78, 0x36, + 0x1f, 0x51, 0x83, 0xcd, 0x3a, 0x74, 0xa6, 0xe8, + 0x55, 0x1b, 0xc9, 0x87, 0x70, 0x3e, 0xec, 0xa2, + }, + { + 0x00, 0x4f, 0x9e, 0xd1, 0x21, 0x6e, 0xbf, 0xf0, + 0x42, 0x0d, 0xdc, 0x93, 0x63, 0x2c, 0xfd, 0xb2, + 0x84, 0xcb, 0x1a, 0x55, 0xa5, 0xea, 0x3b, 0x74, + 0xc6, 0x89, 0x58, 0x17, 0xe7, 0xa8, 0x79, 0x36, + 0x15, 0x5a, 0x8b, 0xc4, 0x34, 0x7b, 0xaa, 0xe5, + 0x57, 0x18, 0xc9, 0x86, 0x76, 0x39, 0xe8, 0xa7, + 0x91, 0xde, 0x0f, 0x40, 0xb0, 0xff, 0x2e, 0x61, + 0xd3, 0x9c, 0x4d, 0x02, 0xf2, 0xbd, 0x6c, 0x23, + 0x2a, 0x65, 0xb4, 0xfb, 0x0b, 0x44, 0x95, 0xda, + 0x68, 0x27, 0xf6, 0xb9, 0x49, 0x06, 0xd7, 0x98, + 0xae, 0xe1, 0x30, 0x7f, 0x8f, 0xc0, 0x11, 0x5e, + 0xec, 0xa3, 0x72, 0x3d, 0xcd, 0x82, 0x53, 0x1c, + 0x3f, 0x70, 0xa1, 0xee, 0x1e, 0x51, 0x80, 0xcf, + 0x7d, 0x32, 0xe3, 0xac, 0x5c, 0x13, 0xc2, 0x8d, + 0xbb, 0xf4, 0x25, 0x6a, 0x9a, 0xd5, 0x04, 0x4b, + 0xf9, 0xb6, 0x67, 0x28, 0xd8, 0x97, 0x46, 0x09, + 0x54, 0x1b, 0xca, 0x85, 0x75, 0x3a, 0xeb, 0xa4, + 0x16, 0x59, 0x88, 0xc7, 0x37, 0x78, 0xa9, 0xe6, + 0xd0, 0x9f, 0x4e, 0x01, 0xf1, 0xbe, 0x6f, 0x20, + 0x92, 0xdd, 0x0c, 0x43, 0xb3, 0xfc, 0x2d, 0x62, + 0x41, 0x0e, 0xdf, 0x90, 0x60, 0x2f, 0xfe, 0xb1, + 0x03, 0x4c, 0x9d, 0xd2, 0x22, 0x6d, 0xbc, 0xf3, + 0xc5, 0x8a, 0x5b, 0x14, 0xe4, 0xab, 0x7a, 0x35, + 0x87, 0xc8, 0x19, 0x56, 0xa6, 0xe9, 0x38, 0x77, + 0x7e, 0x31, 0xe0, 0xaf, 0x5f, 0x10, 0xc1, 0x8e, + 0x3c, 0x73, 0xa2, 0xed, 0x1d, 0x52, 0x83, 0xcc, + 0xfa, 0xb5, 0x64, 0x2b, 0xdb, 0x94, 0x45, 0x0a, + 0xb8, 0xf7, 0x26, 0x69, 0x99, 0xd6, 0x07, 0x48, + 0x6b, 0x24, 0xf5, 0xba, 0x4a, 0x05, 0xd4, 0x9b, + 0x29, 0x66, 0xb7, 0xf8, 0x08, 0x47, 0x96, 0xd9, + 0xef, 0xa0, 0x71, 0x3e, 0xce, 0x81, 0x50, 0x1f, + 0xad, 0xe2, 0x33, 0x7c, 0x8c, 0xc3, 0x12, 0x5d, + }, + { + 0x00, 0x50, 0xa0, 0xf0, 0x5d, 0x0d, 0xfd, 0xad, + 0xba, 0xea, 0x1a, 0x4a, 0xe7, 0xb7, 0x47, 0x17, + 0x69, 0x39, 0xc9, 0x99, 0x34, 0x64, 0x94, 0xc4, + 0xd3, 0x83, 0x73, 0x23, 0x8e, 0xde, 0x2e, 0x7e, + 0xd2, 0x82, 0x72, 0x22, 0x8f, 0xdf, 0x2f, 0x7f, + 0x68, 0x38, 0xc8, 0x98, 0x35, 0x65, 0x95, 0xc5, + 0xbb, 0xeb, 0x1b, 0x4b, 0xe6, 0xb6, 0x46, 0x16, + 0x01, 0x51, 0xa1, 0xf1, 0x5c, 0x0c, 0xfc, 0xac, + 0xb9, 0xe9, 0x19, 0x49, 0xe4, 0xb4, 0x44, 0x14, + 0x03, 0x53, 0xa3, 0xf3, 0x5e, 0x0e, 0xfe, 0xae, + 0xd0, 0x80, 0x70, 0x20, 0x8d, 0xdd, 0x2d, 0x7d, + 0x6a, 0x3a, 0xca, 0x9a, 0x37, 0x67, 0x97, 0xc7, + 0x6b, 0x3b, 0xcb, 0x9b, 0x36, 0x66, 0x96, 0xc6, + 0xd1, 0x81, 0x71, 0x21, 0x8c, 0xdc, 0x2c, 0x7c, + 0x02, 0x52, 0xa2, 0xf2, 0x5f, 0x0f, 0xff, 0xaf, + 0xb8, 0xe8, 0x18, 0x48, 0xe5, 0xb5, 0x45, 0x15, + 0x6f, 0x3f, 0xcf, 0x9f, 0x32, 0x62, 0x92, 0xc2, + 0xd5, 0x85, 0x75, 0x25, 0x88, 0xd8, 0x28, 0x78, + 0x06, 0x56, 0xa6, 0xf6, 0x5b, 0x0b, 0xfb, 0xab, + 0xbc, 0xec, 0x1c, 0x4c, 0xe1, 0xb1, 0x41, 0x11, + 0xbd, 0xed, 0x1d, 0x4d, 0xe0, 0xb0, 0x40, 0x10, + 0x07, 0x57, 0xa7, 0xf7, 0x5a, 0x0a, 0xfa, 0xaa, + 0xd4, 0x84, 0x74, 0x24, 0x89, 0xd9, 0x29, 0x79, + 0x6e, 0x3e, 0xce, 0x9e, 0x33, 0x63, 0x93, 0xc3, + 0xd6, 0x86, 0x76, 0x26, 0x8b, 0xdb, 0x2b, 0x7b, + 0x6c, 0x3c, 0xcc, 0x9c, 0x31, 0x61, 0x91, 0xc1, + 0xbf, 0xef, 0x1f, 0x4f, 0xe2, 0xb2, 0x42, 0x12, + 0x05, 0x55, 0xa5, 0xf5, 0x58, 0x08, 0xf8, 0xa8, + 0x04, 0x54, 0xa4, 0xf4, 0x59, 0x09, 0xf9, 0xa9, + 0xbe, 0xee, 0x1e, 0x4e, 0xe3, 0xb3, 0x43, 0x13, + 0x6d, 0x3d, 0xcd, 0x9d, 0x30, 0x60, 0x90, 0xc0, + 0xd7, 0x87, 0x77, 0x27, 0x8a, 0xda, 0x2a, 0x7a, + }, + { + 0x00, 0x51, 0xa2, 0xf3, 0x59, 0x08, 0xfb, 0xaa, + 0xb2, 0xe3, 0x10, 0x41, 0xeb, 0xba, 0x49, 0x18, + 0x79, 0x28, 0xdb, 0x8a, 0x20, 0x71, 0x82, 0xd3, + 0xcb, 0x9a, 0x69, 0x38, 0x92, 0xc3, 0x30, 0x61, + 0xf2, 0xa3, 0x50, 0x01, 0xab, 0xfa, 0x09, 0x58, + 0x40, 0x11, 0xe2, 0xb3, 0x19, 0x48, 0xbb, 0xea, + 0x8b, 0xda, 0x29, 0x78, 0xd2, 0x83, 0x70, 0x21, + 0x39, 0x68, 0x9b, 0xca, 0x60, 0x31, 0xc2, 0x93, + 0xf9, 0xa8, 0x5b, 0x0a, 0xa0, 0xf1, 0x02, 0x53, + 0x4b, 0x1a, 0xe9, 0xb8, 0x12, 0x43, 0xb0, 0xe1, + 0x80, 0xd1, 0x22, 0x73, 0xd9, 0x88, 0x7b, 0x2a, + 0x32, 0x63, 0x90, 0xc1, 0x6b, 0x3a, 0xc9, 0x98, + 0x0b, 0x5a, 0xa9, 0xf8, 0x52, 0x03, 0xf0, 0xa1, + 0xb9, 0xe8, 0x1b, 0x4a, 0xe0, 0xb1, 0x42, 0x13, + 0x72, 0x23, 0xd0, 0x81, 0x2b, 0x7a, 0x89, 0xd8, + 0xc0, 0x91, 0x62, 0x33, 0x99, 0xc8, 0x3b, 0x6a, + 0xef, 0xbe, 0x4d, 0x1c, 0xb6, 0xe7, 0x14, 0x45, + 0x5d, 0x0c, 0xff, 0xae, 0x04, 0x55, 0xa6, 0xf7, + 0x96, 0xc7, 0x34, 0x65, 0xcf, 0x9e, 0x6d, 0x3c, + 0x24, 0x75, 0x86, 0xd7, 0x7d, 0x2c, 0xdf, 0x8e, + 0x1d, 0x4c, 0xbf, 0xee, 0x44, 0x15, 0xe6, 0xb7, + 0xaf, 0xfe, 0x0d, 0x5c, 0xf6, 0xa7, 0x54, 0x05, + 0x64, 0x35, 0xc6, 0x97, 0x3d, 0x6c, 0x9f, 0xce, + 0xd6, 0x87, 0x74, 0x25, 0x8f, 0xde, 0x2d, 0x7c, + 0x16, 0x47, 0xb4, 0xe5, 0x4f, 0x1e, 0xed, 0xbc, + 0xa4, 0xf5, 0x06, 0x57, 0xfd, 0xac, 0x5f, 0x0e, + 0x6f, 0x3e, 0xcd, 0x9c, 0x36, 0x67, 0x94, 0xc5, + 0xdd, 0x8c, 0x7f, 0x2e, 0x84, 0xd5, 0x26, 0x77, + 0xe4, 0xb5, 0x46, 0x17, 0xbd, 0xec, 0x1f, 0x4e, + 0x56, 0x07, 0xf4, 0xa5, 0x0f, 0x5e, 0xad, 0xfc, + 0x9d, 0xcc, 0x3f, 0x6e, 0xc4, 0x95, 0x66, 0x37, + 0x2f, 0x7e, 0x8d, 0xdc, 0x76, 0x27, 0xd4, 0x85, + }, + { + 0x00, 0x52, 0xa4, 0xf6, 0x55, 0x07, 0xf1, 0xa3, + 0xaa, 0xf8, 0x0e, 0x5c, 0xff, 0xad, 0x5b, 0x09, + 0x49, 0x1b, 0xed, 0xbf, 0x1c, 0x4e, 0xb8, 0xea, + 0xe3, 0xb1, 0x47, 0x15, 0xb6, 0xe4, 0x12, 0x40, + 0x92, 0xc0, 0x36, 0x64, 0xc7, 0x95, 0x63, 0x31, + 0x38, 0x6a, 0x9c, 0xce, 0x6d, 0x3f, 0xc9, 0x9b, + 0xdb, 0x89, 0x7f, 0x2d, 0x8e, 0xdc, 0x2a, 0x78, + 0x71, 0x23, 0xd5, 0x87, 0x24, 0x76, 0x80, 0xd2, + 0x39, 0x6b, 0x9d, 0xcf, 0x6c, 0x3e, 0xc8, 0x9a, + 0x93, 0xc1, 0x37, 0x65, 0xc6, 0x94, 0x62, 0x30, + 0x70, 0x22, 0xd4, 0x86, 0x25, 0x77, 0x81, 0xd3, + 0xda, 0x88, 0x7e, 0x2c, 0x8f, 0xdd, 0x2b, 0x79, + 0xab, 0xf9, 0x0f, 0x5d, 0xfe, 0xac, 0x5a, 0x08, + 0x01, 0x53, 0xa5, 0xf7, 0x54, 0x06, 0xf0, 0xa2, + 0xe2, 0xb0, 0x46, 0x14, 0xb7, 0xe5, 0x13, 0x41, + 0x48, 0x1a, 0xec, 0xbe, 0x1d, 0x4f, 0xb9, 0xeb, + 0x72, 0x20, 0xd6, 0x84, 0x27, 0x75, 0x83, 0xd1, + 0xd8, 0x8a, 0x7c, 0x2e, 0x8d, 0xdf, 0x29, 0x7b, + 0x3b, 0x69, 0x9f, 0xcd, 0x6e, 0x3c, 0xca, 0x98, + 0x91, 0xc3, 0x35, 0x67, 0xc4, 0x96, 0x60, 0x32, + 0xe0, 0xb2, 0x44, 0x16, 0xb5, 0xe7, 0x11, 0x43, + 0x4a, 0x18, 0xee, 0xbc, 0x1f, 0x4d, 0xbb, 0xe9, + 0xa9, 0xfb, 0x0d, 0x5f, 0xfc, 0xae, 0x58, 0x0a, + 0x03, 0x51, 0xa7, 0xf5, 0x56, 0x04, 0xf2, 0xa0, + 0x4b, 0x19, 0xef, 0xbd, 0x1e, 0x4c, 0xba, 0xe8, + 0xe1, 0xb3, 0x45, 0x17, 0xb4, 0xe6, 0x10, 0x42, + 0x02, 0x50, 0xa6, 0xf4, 0x57, 0x05, 0xf3, 0xa1, + 0xa8, 0xfa, 0x0c, 0x5e, 0xfd, 0xaf, 0x59, 0x0b, + 0xd9, 0x8b, 0x7d, 0x2f, 0x8c, 0xde, 0x28, 0x7a, + 0x73, 0x21, 0xd7, 0x85, 0x26, 0x74, 0x82, 0xd0, + 0x90, 0xc2, 0x34, 0x66, 0xc5, 0x97, 0x61, 0x33, + 0x3a, 0x68, 0x9e, 0xcc, 0x6f, 0x3d, 0xcb, 0x99, + }, + { + 0x00, 0x53, 0xa6, 0xf5, 0x51, 0x02, 0xf7, 0xa4, + 0xa2, 0xf1, 0x04, 0x57, 0xf3, 0xa0, 0x55, 0x06, + 0x59, 0x0a, 0xff, 0xac, 0x08, 0x5b, 0xae, 0xfd, + 0xfb, 0xa8, 0x5d, 0x0e, 0xaa, 0xf9, 0x0c, 0x5f, + 0xb2, 0xe1, 0x14, 0x47, 0xe3, 0xb0, 0x45, 0x16, + 0x10, 0x43, 0xb6, 0xe5, 0x41, 0x12, 0xe7, 0xb4, + 0xeb, 0xb8, 0x4d, 0x1e, 0xba, 0xe9, 0x1c, 0x4f, + 0x49, 0x1a, 0xef, 0xbc, 0x18, 0x4b, 0xbe, 0xed, + 0x79, 0x2a, 0xdf, 0x8c, 0x28, 0x7b, 0x8e, 0xdd, + 0xdb, 0x88, 0x7d, 0x2e, 0x8a, 0xd9, 0x2c, 0x7f, + 0x20, 0x73, 0x86, 0xd5, 0x71, 0x22, 0xd7, 0x84, + 0x82, 0xd1, 0x24, 0x77, 0xd3, 0x80, 0x75, 0x26, + 0xcb, 0x98, 0x6d, 0x3e, 0x9a, 0xc9, 0x3c, 0x6f, + 0x69, 0x3a, 0xcf, 0x9c, 0x38, 0x6b, 0x9e, 0xcd, + 0x92, 0xc1, 0x34, 0x67, 0xc3, 0x90, 0x65, 0x36, + 0x30, 0x63, 0x96, 0xc5, 0x61, 0x32, 0xc7, 0x94, + 0xf2, 0xa1, 0x54, 0x07, 0xa3, 0xf0, 0x05, 0x56, + 0x50, 0x03, 0xf6, 0xa5, 0x01, 0x52, 0xa7, 0xf4, + 0xab, 0xf8, 0x0d, 0x5e, 0xfa, 0xa9, 0x5c, 0x0f, + 0x09, 0x5a, 0xaf, 0xfc, 0x58, 0x0b, 0xfe, 0xad, + 0x40, 0x13, 0xe6, 0xb5, 0x11, 0x42, 0xb7, 0xe4, + 0xe2, 0xb1, 0x44, 0x17, 0xb3, 0xe0, 0x15, 0x46, + 0x19, 0x4a, 0xbf, 0xec, 0x48, 0x1b, 0xee, 0xbd, + 0xbb, 0xe8, 0x1d, 0x4e, 0xea, 0xb9, 0x4c, 0x1f, + 0x8b, 0xd8, 0x2d, 0x7e, 0xda, 0x89, 0x7c, 0x2f, + 0x29, 0x7a, 0x8f, 0xdc, 0x78, 0x2b, 0xde, 0x8d, + 0xd2, 0x81, 0x74, 0x27, 0x83, 0xd0, 0x25, 0x76, + 0x70, 0x23, 0xd6, 0x85, 0x21, 0x72, 0x87, 0xd4, + 0x39, 0x6a, 0x9f, 0xcc, 0x68, 0x3b, 0xce, 0x9d, + 0x9b, 0xc8, 0x3d, 0x6e, 0xca, 0x99, 0x6c, 0x3f, + 0x60, 0x33, 0xc6, 0x95, 0x31, 0x62, 0x97, 0xc4, + 0xc2, 0x91, 0x64, 0x37, 0x93, 0xc0, 0x35, 0x66, + }, + { + 0x00, 0x54, 0xa8, 0xfc, 0x4d, 0x19, 0xe5, 0xb1, + 0x9a, 0xce, 0x32, 0x66, 0xd7, 0x83, 0x7f, 0x2b, + 0x29, 0x7d, 0x81, 0xd5, 0x64, 0x30, 0xcc, 0x98, + 0xb3, 0xe7, 0x1b, 0x4f, 0xfe, 0xaa, 0x56, 0x02, + 0x52, 0x06, 0xfa, 0xae, 0x1f, 0x4b, 0xb7, 0xe3, + 0xc8, 0x9c, 0x60, 0x34, 0x85, 0xd1, 0x2d, 0x79, + 0x7b, 0x2f, 0xd3, 0x87, 0x36, 0x62, 0x9e, 0xca, + 0xe1, 0xb5, 0x49, 0x1d, 0xac, 0xf8, 0x04, 0x50, + 0xa4, 0xf0, 0x0c, 0x58, 0xe9, 0xbd, 0x41, 0x15, + 0x3e, 0x6a, 0x96, 0xc2, 0x73, 0x27, 0xdb, 0x8f, + 0x8d, 0xd9, 0x25, 0x71, 0xc0, 0x94, 0x68, 0x3c, + 0x17, 0x43, 0xbf, 0xeb, 0x5a, 0x0e, 0xf2, 0xa6, + 0xf6, 0xa2, 0x5e, 0x0a, 0xbb, 0xef, 0x13, 0x47, + 0x6c, 0x38, 0xc4, 0x90, 0x21, 0x75, 0x89, 0xdd, + 0xdf, 0x8b, 0x77, 0x23, 0x92, 0xc6, 0x3a, 0x6e, + 0x45, 0x11, 0xed, 0xb9, 0x08, 0x5c, 0xa0, 0xf4, + 0x55, 0x01, 0xfd, 0xa9, 0x18, 0x4c, 0xb0, 0xe4, + 0xcf, 0x9b, 0x67, 0x33, 0x82, 0xd6, 0x2a, 0x7e, + 0x7c, 0x28, 0xd4, 0x80, 0x31, 0x65, 0x99, 0xcd, + 0xe6, 0xb2, 0x4e, 0x1a, 0xab, 0xff, 0x03, 0x57, + 0x07, 0x53, 0xaf, 0xfb, 0x4a, 0x1e, 0xe2, 0xb6, + 0x9d, 0xc9, 0x35, 0x61, 0xd0, 0x84, 0x78, 0x2c, + 0x2e, 0x7a, 0x86, 0xd2, 0x63, 0x37, 0xcb, 0x9f, + 0xb4, 0xe0, 0x1c, 0x48, 0xf9, 0xad, 0x51, 0x05, + 0xf1, 0xa5, 0x59, 0x0d, 0xbc, 0xe8, 0x14, 0x40, + 0x6b, 0x3f, 0xc3, 0x97, 0x26, 0x72, 0x8e, 0xda, + 0xd8, 0x8c, 0x70, 0x24, 0x95, 0xc1, 0x3d, 0x69, + 0x42, 0x16, 0xea, 0xbe, 0x0f, 0x5b, 0xa7, 0xf3, + 0xa3, 0xf7, 0x0b, 0x5f, 0xee, 0xba, 0x46, 0x12, + 0x39, 0x6d, 0x91, 0xc5, 0x74, 0x20, 0xdc, 0x88, + 0x8a, 0xde, 0x22, 0x76, 0xc7, 0x93, 0x6f, 0x3b, + 0x10, 0x44, 0xb8, 0xec, 0x5d, 0x09, 0xf5, 0xa1, + }, + { + 0x00, 0x55, 0xaa, 0xff, 0x49, 0x1c, 0xe3, 0xb6, + 0x92, 0xc7, 0x38, 0x6d, 0xdb, 0x8e, 0x71, 0x24, + 0x39, 0x6c, 0x93, 0xc6, 0x70, 0x25, 0xda, 0x8f, + 0xab, 0xfe, 0x01, 0x54, 0xe2, 0xb7, 0x48, 0x1d, + 0x72, 0x27, 0xd8, 0x8d, 0x3b, 0x6e, 0x91, 0xc4, + 0xe0, 0xb5, 0x4a, 0x1f, 0xa9, 0xfc, 0x03, 0x56, + 0x4b, 0x1e, 0xe1, 0xb4, 0x02, 0x57, 0xa8, 0xfd, + 0xd9, 0x8c, 0x73, 0x26, 0x90, 0xc5, 0x3a, 0x6f, + 0xe4, 0xb1, 0x4e, 0x1b, 0xad, 0xf8, 0x07, 0x52, + 0x76, 0x23, 0xdc, 0x89, 0x3f, 0x6a, 0x95, 0xc0, + 0xdd, 0x88, 0x77, 0x22, 0x94, 0xc1, 0x3e, 0x6b, + 0x4f, 0x1a, 0xe5, 0xb0, 0x06, 0x53, 0xac, 0xf9, + 0x96, 0xc3, 0x3c, 0x69, 0xdf, 0x8a, 0x75, 0x20, + 0x04, 0x51, 0xae, 0xfb, 0x4d, 0x18, 0xe7, 0xb2, + 0xaf, 0xfa, 0x05, 0x50, 0xe6, 0xb3, 0x4c, 0x19, + 0x3d, 0x68, 0x97, 0xc2, 0x74, 0x21, 0xde, 0x8b, + 0xd5, 0x80, 0x7f, 0x2a, 0x9c, 0xc9, 0x36, 0x63, + 0x47, 0x12, 0xed, 0xb8, 0x0e, 0x5b, 0xa4, 0xf1, + 0xec, 0xb9, 0x46, 0x13, 0xa5, 0xf0, 0x0f, 0x5a, + 0x7e, 0x2b, 0xd4, 0x81, 0x37, 0x62, 0x9d, 0xc8, + 0xa7, 0xf2, 0x0d, 0x58, 0xee, 0xbb, 0x44, 0x11, + 0x35, 0x60, 0x9f, 0xca, 0x7c, 0x29, 0xd6, 0x83, + 0x9e, 0xcb, 0x34, 0x61, 0xd7, 0x82, 0x7d, 0x28, + 0x0c, 0x59, 0xa6, 0xf3, 0x45, 0x10, 0xef, 0xba, + 0x31, 0x64, 0x9b, 0xce, 0x78, 0x2d, 0xd2, 0x87, + 0xa3, 0xf6, 0x09, 0x5c, 0xea, 0xbf, 0x40, 0x15, + 0x08, 0x5d, 0xa2, 0xf7, 0x41, 0x14, 0xeb, 0xbe, + 0x9a, 0xcf, 0x30, 0x65, 0xd3, 0x86, 0x79, 0x2c, + 0x43, 0x16, 0xe9, 0xbc, 0x0a, 0x5f, 0xa0, 0xf5, + 0xd1, 0x84, 0x7b, 0x2e, 0x98, 0xcd, 0x32, 0x67, + 0x7a, 0x2f, 0xd0, 0x85, 0x33, 0x66, 0x99, 0xcc, + 0xe8, 0xbd, 0x42, 0x17, 0xa1, 0xf4, 0x0b, 0x5e, + }, + { + 0x00, 0x56, 0xac, 0xfa, 0x45, 0x13, 0xe9, 0xbf, + 0x8a, 0xdc, 0x26, 0x70, 0xcf, 0x99, 0x63, 0x35, + 0x09, 0x5f, 0xa5, 0xf3, 0x4c, 0x1a, 0xe0, 0xb6, + 0x83, 0xd5, 0x2f, 0x79, 0xc6, 0x90, 0x6a, 0x3c, + 0x12, 0x44, 0xbe, 0xe8, 0x57, 0x01, 0xfb, 0xad, + 0x98, 0xce, 0x34, 0x62, 0xdd, 0x8b, 0x71, 0x27, + 0x1b, 0x4d, 0xb7, 0xe1, 0x5e, 0x08, 0xf2, 0xa4, + 0x91, 0xc7, 0x3d, 0x6b, 0xd4, 0x82, 0x78, 0x2e, + 0x24, 0x72, 0x88, 0xde, 0x61, 0x37, 0xcd, 0x9b, + 0xae, 0xf8, 0x02, 0x54, 0xeb, 0xbd, 0x47, 0x11, + 0x2d, 0x7b, 0x81, 0xd7, 0x68, 0x3e, 0xc4, 0x92, + 0xa7, 0xf1, 0x0b, 0x5d, 0xe2, 0xb4, 0x4e, 0x18, + 0x36, 0x60, 0x9a, 0xcc, 0x73, 0x25, 0xdf, 0x89, + 0xbc, 0xea, 0x10, 0x46, 0xf9, 0xaf, 0x55, 0x03, + 0x3f, 0x69, 0x93, 0xc5, 0x7a, 0x2c, 0xd6, 0x80, + 0xb5, 0xe3, 0x19, 0x4f, 0xf0, 0xa6, 0x5c, 0x0a, + 0x48, 0x1e, 0xe4, 0xb2, 0x0d, 0x5b, 0xa1, 0xf7, + 0xc2, 0x94, 0x6e, 0x38, 0x87, 0xd1, 0x2b, 0x7d, + 0x41, 0x17, 0xed, 0xbb, 0x04, 0x52, 0xa8, 0xfe, + 0xcb, 0x9d, 0x67, 0x31, 0x8e, 0xd8, 0x22, 0x74, + 0x5a, 0x0c, 0xf6, 0xa0, 0x1f, 0x49, 0xb3, 0xe5, + 0xd0, 0x86, 0x7c, 0x2a, 0x95, 0xc3, 0x39, 0x6f, + 0x53, 0x05, 0xff, 0xa9, 0x16, 0x40, 0xba, 0xec, + 0xd9, 0x8f, 0x75, 0x23, 0x9c, 0xca, 0x30, 0x66, + 0x6c, 0x3a, 0xc0, 0x96, 0x29, 0x7f, 0x85, 0xd3, + 0xe6, 0xb0, 0x4a, 0x1c, 0xa3, 0xf5, 0x0f, 0x59, + 0x65, 0x33, 0xc9, 0x9f, 0x20, 0x76, 0x8c, 0xda, + 0xef, 0xb9, 0x43, 0x15, 0xaa, 0xfc, 0x06, 0x50, + 0x7e, 0x28, 0xd2, 0x84, 0x3b, 0x6d, 0x97, 0xc1, + 0xf4, 0xa2, 0x58, 0x0e, 0xb1, 0xe7, 0x1d, 0x4b, + 0x77, 0x21, 0xdb, 0x8d, 0x32, 0x64, 0x9e, 0xc8, + 0xfd, 0xab, 0x51, 0x07, 0xb8, 0xee, 0x14, 0x42, + }, + { + 0x00, 0x57, 0xae, 0xf9, 0x41, 0x16, 0xef, 0xb8, + 0x82, 0xd5, 0x2c, 0x7b, 0xc3, 0x94, 0x6d, 0x3a, + 0x19, 0x4e, 0xb7, 0xe0, 0x58, 0x0f, 0xf6, 0xa1, + 0x9b, 0xcc, 0x35, 0x62, 0xda, 0x8d, 0x74, 0x23, + 0x32, 0x65, 0x9c, 0xcb, 0x73, 0x24, 0xdd, 0x8a, + 0xb0, 0xe7, 0x1e, 0x49, 0xf1, 0xa6, 0x5f, 0x08, + 0x2b, 0x7c, 0x85, 0xd2, 0x6a, 0x3d, 0xc4, 0x93, + 0xa9, 0xfe, 0x07, 0x50, 0xe8, 0xbf, 0x46, 0x11, + 0x64, 0x33, 0xca, 0x9d, 0x25, 0x72, 0x8b, 0xdc, + 0xe6, 0xb1, 0x48, 0x1f, 0xa7, 0xf0, 0x09, 0x5e, + 0x7d, 0x2a, 0xd3, 0x84, 0x3c, 0x6b, 0x92, 0xc5, + 0xff, 0xa8, 0x51, 0x06, 0xbe, 0xe9, 0x10, 0x47, + 0x56, 0x01, 0xf8, 0xaf, 0x17, 0x40, 0xb9, 0xee, + 0xd4, 0x83, 0x7a, 0x2d, 0x95, 0xc2, 0x3b, 0x6c, + 0x4f, 0x18, 0xe1, 0xb6, 0x0e, 0x59, 0xa0, 0xf7, + 0xcd, 0x9a, 0x63, 0x34, 0x8c, 0xdb, 0x22, 0x75, + 0xc8, 0x9f, 0x66, 0x31, 0x89, 0xde, 0x27, 0x70, + 0x4a, 0x1d, 0xe4, 0xb3, 0x0b, 0x5c, 0xa5, 0xf2, + 0xd1, 0x86, 0x7f, 0x28, 0x90, 0xc7, 0x3e, 0x69, + 0x53, 0x04, 0xfd, 0xaa, 0x12, 0x45, 0xbc, 0xeb, + 0xfa, 0xad, 0x54, 0x03, 0xbb, 0xec, 0x15, 0x42, + 0x78, 0x2f, 0xd6, 0x81, 0x39, 0x6e, 0x97, 0xc0, + 0xe3, 0xb4, 0x4d, 0x1a, 0xa2, 0xf5, 0x0c, 0x5b, + 0x61, 0x36, 0xcf, 0x98, 0x20, 0x77, 0x8e, 0xd9, + 0xac, 0xfb, 0x02, 0x55, 0xed, 0xba, 0x43, 0x14, + 0x2e, 0x79, 0x80, 0xd7, 0x6f, 0x38, 0xc1, 0x96, + 0xb5, 0xe2, 0x1b, 0x4c, 0xf4, 0xa3, 0x5a, 0x0d, + 0x37, 0x60, 0x99, 0xce, 0x76, 0x21, 0xd8, 0x8f, + 0x9e, 0xc9, 0x30, 0x67, 0xdf, 0x88, 0x71, 0x26, + 0x1c, 0x4b, 0xb2, 0xe5, 0x5d, 0x0a, 0xf3, 0xa4, + 0x87, 0xd0, 0x29, 0x7e, 0xc6, 0x91, 0x68, 0x3f, + 0x05, 0x52, 0xab, 0xfc, 0x44, 0x13, 0xea, 0xbd, + }, + { + 0x00, 0x58, 0xb0, 0xe8, 0x7d, 0x25, 0xcd, 0x95, + 0xfa, 0xa2, 0x4a, 0x12, 0x87, 0xdf, 0x37, 0x6f, + 0xe9, 0xb1, 0x59, 0x01, 0x94, 0xcc, 0x24, 0x7c, + 0x13, 0x4b, 0xa3, 0xfb, 0x6e, 0x36, 0xde, 0x86, + 0xcf, 0x97, 0x7f, 0x27, 0xb2, 0xea, 0x02, 0x5a, + 0x35, 0x6d, 0x85, 0xdd, 0x48, 0x10, 0xf8, 0xa0, + 0x26, 0x7e, 0x96, 0xce, 0x5b, 0x03, 0xeb, 0xb3, + 0xdc, 0x84, 0x6c, 0x34, 0xa1, 0xf9, 0x11, 0x49, + 0x83, 0xdb, 0x33, 0x6b, 0xfe, 0xa6, 0x4e, 0x16, + 0x79, 0x21, 0xc9, 0x91, 0x04, 0x5c, 0xb4, 0xec, + 0x6a, 0x32, 0xda, 0x82, 0x17, 0x4f, 0xa7, 0xff, + 0x90, 0xc8, 0x20, 0x78, 0xed, 0xb5, 0x5d, 0x05, + 0x4c, 0x14, 0xfc, 0xa4, 0x31, 0x69, 0x81, 0xd9, + 0xb6, 0xee, 0x06, 0x5e, 0xcb, 0x93, 0x7b, 0x23, + 0xa5, 0xfd, 0x15, 0x4d, 0xd8, 0x80, 0x68, 0x30, + 0x5f, 0x07, 0xef, 0xb7, 0x22, 0x7a, 0x92, 0xca, + 0x1b, 0x43, 0xab, 0xf3, 0x66, 0x3e, 0xd6, 0x8e, + 0xe1, 0xb9, 0x51, 0x09, 0x9c, 0xc4, 0x2c, 0x74, + 0xf2, 0xaa, 0x42, 0x1a, 0x8f, 0xd7, 0x3f, 0x67, + 0x08, 0x50, 0xb8, 0xe0, 0x75, 0x2d, 0xc5, 0x9d, + 0xd4, 0x8c, 0x64, 0x3c, 0xa9, 0xf1, 0x19, 0x41, + 0x2e, 0x76, 0x9e, 0xc6, 0x53, 0x0b, 0xe3, 0xbb, + 0x3d, 0x65, 0x8d, 0xd5, 0x40, 0x18, 0xf0, 0xa8, + 0xc7, 0x9f, 0x77, 0x2f, 0xba, 0xe2, 0x0a, 0x52, + 0x98, 0xc0, 0x28, 0x70, 0xe5, 0xbd, 0x55, 0x0d, + 0x62, 0x3a, 0xd2, 0x8a, 0x1f, 0x47, 0xaf, 0xf7, + 0x71, 0x29, 0xc1, 0x99, 0x0c, 0x54, 0xbc, 0xe4, + 0x8b, 0xd3, 0x3b, 0x63, 0xf6, 0xae, 0x46, 0x1e, + 0x57, 0x0f, 0xe7, 0xbf, 0x2a, 0x72, 0x9a, 0xc2, + 0xad, 0xf5, 0x1d, 0x45, 0xd0, 0x88, 0x60, 0x38, + 0xbe, 0xe6, 0x0e, 0x56, 0xc3, 0x9b, 0x73, 0x2b, + 0x44, 0x1c, 0xf4, 0xac, 0x39, 0x61, 0x89, 0xd1, + }, + { + 0x00, 0x59, 0xb2, 0xeb, 0x79, 0x20, 0xcb, 0x92, + 0xf2, 0xab, 0x40, 0x19, 0x8b, 0xd2, 0x39, 0x60, + 0xf9, 0xa0, 0x4b, 0x12, 0x80, 0xd9, 0x32, 0x6b, + 0x0b, 0x52, 0xb9, 0xe0, 0x72, 0x2b, 0xc0, 0x99, + 0xef, 0xb6, 0x5d, 0x04, 0x96, 0xcf, 0x24, 0x7d, + 0x1d, 0x44, 0xaf, 0xf6, 0x64, 0x3d, 0xd6, 0x8f, + 0x16, 0x4f, 0xa4, 0xfd, 0x6f, 0x36, 0xdd, 0x84, + 0xe4, 0xbd, 0x56, 0x0f, 0x9d, 0xc4, 0x2f, 0x76, + 0xc3, 0x9a, 0x71, 0x28, 0xba, 0xe3, 0x08, 0x51, + 0x31, 0x68, 0x83, 0xda, 0x48, 0x11, 0xfa, 0xa3, + 0x3a, 0x63, 0x88, 0xd1, 0x43, 0x1a, 0xf1, 0xa8, + 0xc8, 0x91, 0x7a, 0x23, 0xb1, 0xe8, 0x03, 0x5a, + 0x2c, 0x75, 0x9e, 0xc7, 0x55, 0x0c, 0xe7, 0xbe, + 0xde, 0x87, 0x6c, 0x35, 0xa7, 0xfe, 0x15, 0x4c, + 0xd5, 0x8c, 0x67, 0x3e, 0xac, 0xf5, 0x1e, 0x47, + 0x27, 0x7e, 0x95, 0xcc, 0x5e, 0x07, 0xec, 0xb5, + 0x9b, 0xc2, 0x29, 0x70, 0xe2, 0xbb, 0x50, 0x09, + 0x69, 0x30, 0xdb, 0x82, 0x10, 0x49, 0xa2, 0xfb, + 0x62, 0x3b, 0xd0, 0x89, 0x1b, 0x42, 0xa9, 0xf0, + 0x90, 0xc9, 0x22, 0x7b, 0xe9, 0xb0, 0x5b, 0x02, + 0x74, 0x2d, 0xc6, 0x9f, 0x0d, 0x54, 0xbf, 0xe6, + 0x86, 0xdf, 0x34, 0x6d, 0xff, 0xa6, 0x4d, 0x14, + 0x8d, 0xd4, 0x3f, 0x66, 0xf4, 0xad, 0x46, 0x1f, + 0x7f, 0x26, 0xcd, 0x94, 0x06, 0x5f, 0xb4, 0xed, + 0x58, 0x01, 0xea, 0xb3, 0x21, 0x78, 0x93, 0xca, + 0xaa, 0xf3, 0x18, 0x41, 0xd3, 0x8a, 0x61, 0x38, + 0xa1, 0xf8, 0x13, 0x4a, 0xd8, 0x81, 0x6a, 0x33, + 0x53, 0x0a, 0xe1, 0xb8, 0x2a, 0x73, 0x98, 0xc1, + 0xb7, 0xee, 0x05, 0x5c, 0xce, 0x97, 0x7c, 0x25, + 0x45, 0x1c, 0xf7, 0xae, 0x3c, 0x65, 0x8e, 0xd7, + 0x4e, 0x17, 0xfc, 0xa5, 0x37, 0x6e, 0x85, 0xdc, + 0xbc, 0xe5, 0x0e, 0x57, 0xc5, 0x9c, 0x77, 0x2e, + }, + { + 0x00, 0x5a, 0xb4, 0xee, 0x75, 0x2f, 0xc1, 0x9b, + 0xea, 0xb0, 0x5e, 0x04, 0x9f, 0xc5, 0x2b, 0x71, + 0xc9, 0x93, 0x7d, 0x27, 0xbc, 0xe6, 0x08, 0x52, + 0x23, 0x79, 0x97, 0xcd, 0x56, 0x0c, 0xe2, 0xb8, + 0x8f, 0xd5, 0x3b, 0x61, 0xfa, 0xa0, 0x4e, 0x14, + 0x65, 0x3f, 0xd1, 0x8b, 0x10, 0x4a, 0xa4, 0xfe, + 0x46, 0x1c, 0xf2, 0xa8, 0x33, 0x69, 0x87, 0xdd, + 0xac, 0xf6, 0x18, 0x42, 0xd9, 0x83, 0x6d, 0x37, + 0x03, 0x59, 0xb7, 0xed, 0x76, 0x2c, 0xc2, 0x98, + 0xe9, 0xb3, 0x5d, 0x07, 0x9c, 0xc6, 0x28, 0x72, + 0xca, 0x90, 0x7e, 0x24, 0xbf, 0xe5, 0x0b, 0x51, + 0x20, 0x7a, 0x94, 0xce, 0x55, 0x0f, 0xe1, 0xbb, + 0x8c, 0xd6, 0x38, 0x62, 0xf9, 0xa3, 0x4d, 0x17, + 0x66, 0x3c, 0xd2, 0x88, 0x13, 0x49, 0xa7, 0xfd, + 0x45, 0x1f, 0xf1, 0xab, 0x30, 0x6a, 0x84, 0xde, + 0xaf, 0xf5, 0x1b, 0x41, 0xda, 0x80, 0x6e, 0x34, + 0x06, 0x5c, 0xb2, 0xe8, 0x73, 0x29, 0xc7, 0x9d, + 0xec, 0xb6, 0x58, 0x02, 0x99, 0xc3, 0x2d, 0x77, + 0xcf, 0x95, 0x7b, 0x21, 0xba, 0xe0, 0x0e, 0x54, + 0x25, 0x7f, 0x91, 0xcb, 0x50, 0x0a, 0xe4, 0xbe, + 0x89, 0xd3, 0x3d, 0x67, 0xfc, 0xa6, 0x48, 0x12, + 0x63, 0x39, 0xd7, 0x8d, 0x16, 0x4c, 0xa2, 0xf8, + 0x40, 0x1a, 0xf4, 0xae, 0x35, 0x6f, 0x81, 0xdb, + 0xaa, 0xf0, 0x1e, 0x44, 0xdf, 0x85, 0x6b, 0x31, + 0x05, 0x5f, 0xb1, 0xeb, 0x70, 0x2a, 0xc4, 0x9e, + 0xef, 0xb5, 0x5b, 0x01, 0x9a, 0xc0, 0x2e, 0x74, + 0xcc, 0x96, 0x78, 0x22, 0xb9, 0xe3, 0x0d, 0x57, + 0x26, 0x7c, 0x92, 0xc8, 0x53, 0x09, 0xe7, 0xbd, + 0x8a, 0xd0, 0x3e, 0x64, 0xff, 0xa5, 0x4b, 0x11, + 0x60, 0x3a, 0xd4, 0x8e, 0x15, 0x4f, 0xa1, 0xfb, + 0x43, 0x19, 0xf7, 0xad, 0x36, 0x6c, 0x82, 0xd8, + 0xa9, 0xf3, 0x1d, 0x47, 0xdc, 0x86, 0x68, 0x32, + }, + { + 0x00, 0x5b, 0xb6, 0xed, 0x71, 0x2a, 0xc7, 0x9c, + 0xe2, 0xb9, 0x54, 0x0f, 0x93, 0xc8, 0x25, 0x7e, + 0xd9, 0x82, 0x6f, 0x34, 0xa8, 0xf3, 0x1e, 0x45, + 0x3b, 0x60, 0x8d, 0xd6, 0x4a, 0x11, 0xfc, 0xa7, + 0xaf, 0xf4, 0x19, 0x42, 0xde, 0x85, 0x68, 0x33, + 0x4d, 0x16, 0xfb, 0xa0, 0x3c, 0x67, 0x8a, 0xd1, + 0x76, 0x2d, 0xc0, 0x9b, 0x07, 0x5c, 0xb1, 0xea, + 0x94, 0xcf, 0x22, 0x79, 0xe5, 0xbe, 0x53, 0x08, + 0x43, 0x18, 0xf5, 0xae, 0x32, 0x69, 0x84, 0xdf, + 0xa1, 0xfa, 0x17, 0x4c, 0xd0, 0x8b, 0x66, 0x3d, + 0x9a, 0xc1, 0x2c, 0x77, 0xeb, 0xb0, 0x5d, 0x06, + 0x78, 0x23, 0xce, 0x95, 0x09, 0x52, 0xbf, 0xe4, + 0xec, 0xb7, 0x5a, 0x01, 0x9d, 0xc6, 0x2b, 0x70, + 0x0e, 0x55, 0xb8, 0xe3, 0x7f, 0x24, 0xc9, 0x92, + 0x35, 0x6e, 0x83, 0xd8, 0x44, 0x1f, 0xf2, 0xa9, + 0xd7, 0x8c, 0x61, 0x3a, 0xa6, 0xfd, 0x10, 0x4b, + 0x86, 0xdd, 0x30, 0x6b, 0xf7, 0xac, 0x41, 0x1a, + 0x64, 0x3f, 0xd2, 0x89, 0x15, 0x4e, 0xa3, 0xf8, + 0x5f, 0x04, 0xe9, 0xb2, 0x2e, 0x75, 0x98, 0xc3, + 0xbd, 0xe6, 0x0b, 0x50, 0xcc, 0x97, 0x7a, 0x21, + 0x29, 0x72, 0x9f, 0xc4, 0x58, 0x03, 0xee, 0xb5, + 0xcb, 0x90, 0x7d, 0x26, 0xba, 0xe1, 0x0c, 0x57, + 0xf0, 0xab, 0x46, 0x1d, 0x81, 0xda, 0x37, 0x6c, + 0x12, 0x49, 0xa4, 0xff, 0x63, 0x38, 0xd5, 0x8e, + 0xc5, 0x9e, 0x73, 0x28, 0xb4, 0xef, 0x02, 0x59, + 0x27, 0x7c, 0x91, 0xca, 0x56, 0x0d, 0xe0, 0xbb, + 0x1c, 0x47, 0xaa, 0xf1, 0x6d, 0x36, 0xdb, 0x80, + 0xfe, 0xa5, 0x48, 0x13, 0x8f, 0xd4, 0x39, 0x62, + 0x6a, 0x31, 0xdc, 0x87, 0x1b, 0x40, 0xad, 0xf6, + 0x88, 0xd3, 0x3e, 0x65, 0xf9, 0xa2, 0x4f, 0x14, + 0xb3, 0xe8, 0x05, 0x5e, 0xc2, 0x99, 0x74, 0x2f, + 0x51, 0x0a, 0xe7, 0xbc, 0x20, 0x7b, 0x96, 0xcd, + }, + { + 0x00, 0x5c, 0xb8, 0xe4, 0x6d, 0x31, 0xd5, 0x89, + 0xda, 0x86, 0x62, 0x3e, 0xb7, 0xeb, 0x0f, 0x53, + 0xa9, 0xf5, 0x11, 0x4d, 0xc4, 0x98, 0x7c, 0x20, + 0x73, 0x2f, 0xcb, 0x97, 0x1e, 0x42, 0xa6, 0xfa, + 0x4f, 0x13, 0xf7, 0xab, 0x22, 0x7e, 0x9a, 0xc6, + 0x95, 0xc9, 0x2d, 0x71, 0xf8, 0xa4, 0x40, 0x1c, + 0xe6, 0xba, 0x5e, 0x02, 0x8b, 0xd7, 0x33, 0x6f, + 0x3c, 0x60, 0x84, 0xd8, 0x51, 0x0d, 0xe9, 0xb5, + 0x9e, 0xc2, 0x26, 0x7a, 0xf3, 0xaf, 0x4b, 0x17, + 0x44, 0x18, 0xfc, 0xa0, 0x29, 0x75, 0x91, 0xcd, + 0x37, 0x6b, 0x8f, 0xd3, 0x5a, 0x06, 0xe2, 0xbe, + 0xed, 0xb1, 0x55, 0x09, 0x80, 0xdc, 0x38, 0x64, + 0xd1, 0x8d, 0x69, 0x35, 0xbc, 0xe0, 0x04, 0x58, + 0x0b, 0x57, 0xb3, 0xef, 0x66, 0x3a, 0xde, 0x82, + 0x78, 0x24, 0xc0, 0x9c, 0x15, 0x49, 0xad, 0xf1, + 0xa2, 0xfe, 0x1a, 0x46, 0xcf, 0x93, 0x77, 0x2b, + 0x21, 0x7d, 0x99, 0xc5, 0x4c, 0x10, 0xf4, 0xa8, + 0xfb, 0xa7, 0x43, 0x1f, 0x96, 0xca, 0x2e, 0x72, + 0x88, 0xd4, 0x30, 0x6c, 0xe5, 0xb9, 0x5d, 0x01, + 0x52, 0x0e, 0xea, 0xb6, 0x3f, 0x63, 0x87, 0xdb, + 0x6e, 0x32, 0xd6, 0x8a, 0x03, 0x5f, 0xbb, 0xe7, + 0xb4, 0xe8, 0x0c, 0x50, 0xd9, 0x85, 0x61, 0x3d, + 0xc7, 0x9b, 0x7f, 0x23, 0xaa, 0xf6, 0x12, 0x4e, + 0x1d, 0x41, 0xa5, 0xf9, 0x70, 0x2c, 0xc8, 0x94, + 0xbf, 0xe3, 0x07, 0x5b, 0xd2, 0x8e, 0x6a, 0x36, + 0x65, 0x39, 0xdd, 0x81, 0x08, 0x54, 0xb0, 0xec, + 0x16, 0x4a, 0xae, 0xf2, 0x7b, 0x27, 0xc3, 0x9f, + 0xcc, 0x90, 0x74, 0x28, 0xa1, 0xfd, 0x19, 0x45, + 0xf0, 0xac, 0x48, 0x14, 0x9d, 0xc1, 0x25, 0x79, + 0x2a, 0x76, 0x92, 0xce, 0x47, 0x1b, 0xff, 0xa3, + 0x59, 0x05, 0xe1, 0xbd, 0x34, 0x68, 0x8c, 0xd0, + 0x83, 0xdf, 0x3b, 0x67, 0xee, 0xb2, 0x56, 0x0a, + }, + { + 0x00, 0x5d, 0xba, 0xe7, 0x69, 0x34, 0xd3, 0x8e, + 0xd2, 0x8f, 0x68, 0x35, 0xbb, 0xe6, 0x01, 0x5c, + 0xb9, 0xe4, 0x03, 0x5e, 0xd0, 0x8d, 0x6a, 0x37, + 0x6b, 0x36, 0xd1, 0x8c, 0x02, 0x5f, 0xb8, 0xe5, + 0x6f, 0x32, 0xd5, 0x88, 0x06, 0x5b, 0xbc, 0xe1, + 0xbd, 0xe0, 0x07, 0x5a, 0xd4, 0x89, 0x6e, 0x33, + 0xd6, 0x8b, 0x6c, 0x31, 0xbf, 0xe2, 0x05, 0x58, + 0x04, 0x59, 0xbe, 0xe3, 0x6d, 0x30, 0xd7, 0x8a, + 0xde, 0x83, 0x64, 0x39, 0xb7, 0xea, 0x0d, 0x50, + 0x0c, 0x51, 0xb6, 0xeb, 0x65, 0x38, 0xdf, 0x82, + 0x67, 0x3a, 0xdd, 0x80, 0x0e, 0x53, 0xb4, 0xe9, + 0xb5, 0xe8, 0x0f, 0x52, 0xdc, 0x81, 0x66, 0x3b, + 0xb1, 0xec, 0x0b, 0x56, 0xd8, 0x85, 0x62, 0x3f, + 0x63, 0x3e, 0xd9, 0x84, 0x0a, 0x57, 0xb0, 0xed, + 0x08, 0x55, 0xb2, 0xef, 0x61, 0x3c, 0xdb, 0x86, + 0xda, 0x87, 0x60, 0x3d, 0xb3, 0xee, 0x09, 0x54, + 0xa1, 0xfc, 0x1b, 0x46, 0xc8, 0x95, 0x72, 0x2f, + 0x73, 0x2e, 0xc9, 0x94, 0x1a, 0x47, 0xa0, 0xfd, + 0x18, 0x45, 0xa2, 0xff, 0x71, 0x2c, 0xcb, 0x96, + 0xca, 0x97, 0x70, 0x2d, 0xa3, 0xfe, 0x19, 0x44, + 0xce, 0x93, 0x74, 0x29, 0xa7, 0xfa, 0x1d, 0x40, + 0x1c, 0x41, 0xa6, 0xfb, 0x75, 0x28, 0xcf, 0x92, + 0x77, 0x2a, 0xcd, 0x90, 0x1e, 0x43, 0xa4, 0xf9, + 0xa5, 0xf8, 0x1f, 0x42, 0xcc, 0x91, 0x76, 0x2b, + 0x7f, 0x22, 0xc5, 0x98, 0x16, 0x4b, 0xac, 0xf1, + 0xad, 0xf0, 0x17, 0x4a, 0xc4, 0x99, 0x7e, 0x23, + 0xc6, 0x9b, 0x7c, 0x21, 0xaf, 0xf2, 0x15, 0x48, + 0x14, 0x49, 0xae, 0xf3, 0x7d, 0x20, 0xc7, 0x9a, + 0x10, 0x4d, 0xaa, 0xf7, 0x79, 0x24, 0xc3, 0x9e, + 0xc2, 0x9f, 0x78, 0x25, 0xab, 0xf6, 0x11, 0x4c, + 0xa9, 0xf4, 0x13, 0x4e, 0xc0, 0x9d, 0x7a, 0x27, + 0x7b, 0x26, 0xc1, 0x9c, 0x12, 0x4f, 0xa8, 0xf5, + }, + { + 0x00, 0x5e, 0xbc, 0xe2, 0x65, 0x3b, 0xd9, 0x87, + 0xca, 0x94, 0x76, 0x28, 0xaf, 0xf1, 0x13, 0x4d, + 0x89, 0xd7, 0x35, 0x6b, 0xec, 0xb2, 0x50, 0x0e, + 0x43, 0x1d, 0xff, 0xa1, 0x26, 0x78, 0x9a, 0xc4, + 0x0f, 0x51, 0xb3, 0xed, 0x6a, 0x34, 0xd6, 0x88, + 0xc5, 0x9b, 0x79, 0x27, 0xa0, 0xfe, 0x1c, 0x42, + 0x86, 0xd8, 0x3a, 0x64, 0xe3, 0xbd, 0x5f, 0x01, + 0x4c, 0x12, 0xf0, 0xae, 0x29, 0x77, 0x95, 0xcb, + 0x1e, 0x40, 0xa2, 0xfc, 0x7b, 0x25, 0xc7, 0x99, + 0xd4, 0x8a, 0x68, 0x36, 0xb1, 0xef, 0x0d, 0x53, + 0x97, 0xc9, 0x2b, 0x75, 0xf2, 0xac, 0x4e, 0x10, + 0x5d, 0x03, 0xe1, 0xbf, 0x38, 0x66, 0x84, 0xda, + 0x11, 0x4f, 0xad, 0xf3, 0x74, 0x2a, 0xc8, 0x96, + 0xdb, 0x85, 0x67, 0x39, 0xbe, 0xe0, 0x02, 0x5c, + 0x98, 0xc6, 0x24, 0x7a, 0xfd, 0xa3, 0x41, 0x1f, + 0x52, 0x0c, 0xee, 0xb0, 0x37, 0x69, 0x8b, 0xd5, + 0x3c, 0x62, 0x80, 0xde, 0x59, 0x07, 0xe5, 0xbb, + 0xf6, 0xa8, 0x4a, 0x14, 0x93, 0xcd, 0x2f, 0x71, + 0xb5, 0xeb, 0x09, 0x57, 0xd0, 0x8e, 0x6c, 0x32, + 0x7f, 0x21, 0xc3, 0x9d, 0x1a, 0x44, 0xa6, 0xf8, + 0x33, 0x6d, 0x8f, 0xd1, 0x56, 0x08, 0xea, 0xb4, + 0xf9, 0xa7, 0x45, 0x1b, 0x9c, 0xc2, 0x20, 0x7e, + 0xba, 0xe4, 0x06, 0x58, 0xdf, 0x81, 0x63, 0x3d, + 0x70, 0x2e, 0xcc, 0x92, 0x15, 0x4b, 0xa9, 0xf7, + 0x22, 0x7c, 0x9e, 0xc0, 0x47, 0x19, 0xfb, 0xa5, + 0xe8, 0xb6, 0x54, 0x0a, 0x8d, 0xd3, 0x31, 0x6f, + 0xab, 0xf5, 0x17, 0x49, 0xce, 0x90, 0x72, 0x2c, + 0x61, 0x3f, 0xdd, 0x83, 0x04, 0x5a, 0xb8, 0xe6, + 0x2d, 0x73, 0x91, 0xcf, 0x48, 0x16, 0xf4, 0xaa, + 0xe7, 0xb9, 0x5b, 0x05, 0x82, 0xdc, 0x3e, 0x60, + 0xa4, 0xfa, 0x18, 0x46, 0xc1, 0x9f, 0x7d, 0x23, + 0x6e, 0x30, 0xd2, 0x8c, 0x0b, 0x55, 0xb7, 0xe9, + }, + { + 0x00, 0x5f, 0xbe, 0xe1, 0x61, 0x3e, 0xdf, 0x80, + 0xc2, 0x9d, 0x7c, 0x23, 0xa3, 0xfc, 0x1d, 0x42, + 0x99, 0xc6, 0x27, 0x78, 0xf8, 0xa7, 0x46, 0x19, + 0x5b, 0x04, 0xe5, 0xba, 0x3a, 0x65, 0x84, 0xdb, + 0x2f, 0x70, 0x91, 0xce, 0x4e, 0x11, 0xf0, 0xaf, + 0xed, 0xb2, 0x53, 0x0c, 0x8c, 0xd3, 0x32, 0x6d, + 0xb6, 0xe9, 0x08, 0x57, 0xd7, 0x88, 0x69, 0x36, + 0x74, 0x2b, 0xca, 0x95, 0x15, 0x4a, 0xab, 0xf4, + 0x5e, 0x01, 0xe0, 0xbf, 0x3f, 0x60, 0x81, 0xde, + 0x9c, 0xc3, 0x22, 0x7d, 0xfd, 0xa2, 0x43, 0x1c, + 0xc7, 0x98, 0x79, 0x26, 0xa6, 0xf9, 0x18, 0x47, + 0x05, 0x5a, 0xbb, 0xe4, 0x64, 0x3b, 0xda, 0x85, + 0x71, 0x2e, 0xcf, 0x90, 0x10, 0x4f, 0xae, 0xf1, + 0xb3, 0xec, 0x0d, 0x52, 0xd2, 0x8d, 0x6c, 0x33, + 0xe8, 0xb7, 0x56, 0x09, 0x89, 0xd6, 0x37, 0x68, + 0x2a, 0x75, 0x94, 0xcb, 0x4b, 0x14, 0xf5, 0xaa, + 0xbc, 0xe3, 0x02, 0x5d, 0xdd, 0x82, 0x63, 0x3c, + 0x7e, 0x21, 0xc0, 0x9f, 0x1f, 0x40, 0xa1, 0xfe, + 0x25, 0x7a, 0x9b, 0xc4, 0x44, 0x1b, 0xfa, 0xa5, + 0xe7, 0xb8, 0x59, 0x06, 0x86, 0xd9, 0x38, 0x67, + 0x93, 0xcc, 0x2d, 0x72, 0xf2, 0xad, 0x4c, 0x13, + 0x51, 0x0e, 0xef, 0xb0, 0x30, 0x6f, 0x8e, 0xd1, + 0x0a, 0x55, 0xb4, 0xeb, 0x6b, 0x34, 0xd5, 0x8a, + 0xc8, 0x97, 0x76, 0x29, 0xa9, 0xf6, 0x17, 0x48, + 0xe2, 0xbd, 0x5c, 0x03, 0x83, 0xdc, 0x3d, 0x62, + 0x20, 0x7f, 0x9e, 0xc1, 0x41, 0x1e, 0xff, 0xa0, + 0x7b, 0x24, 0xc5, 0x9a, 0x1a, 0x45, 0xa4, 0xfb, + 0xb9, 0xe6, 0x07, 0x58, 0xd8, 0x87, 0x66, 0x39, + 0xcd, 0x92, 0x73, 0x2c, 0xac, 0xf3, 0x12, 0x4d, + 0x0f, 0x50, 0xb1, 0xee, 0x6e, 0x31, 0xd0, 0x8f, + 0x54, 0x0b, 0xea, 0xb5, 0x35, 0x6a, 0x8b, 0xd4, + 0x96, 0xc9, 0x28, 0x77, 0xf7, 0xa8, 0x49, 0x16, + }, + { + 0x00, 0x60, 0xc0, 0xa0, 0x9d, 0xfd, 0x5d, 0x3d, + 0x27, 0x47, 0xe7, 0x87, 0xba, 0xda, 0x7a, 0x1a, + 0x4e, 0x2e, 0x8e, 0xee, 0xd3, 0xb3, 0x13, 0x73, + 0x69, 0x09, 0xa9, 0xc9, 0xf4, 0x94, 0x34, 0x54, + 0x9c, 0xfc, 0x5c, 0x3c, 0x01, 0x61, 0xc1, 0xa1, + 0xbb, 0xdb, 0x7b, 0x1b, 0x26, 0x46, 0xe6, 0x86, + 0xd2, 0xb2, 0x12, 0x72, 0x4f, 0x2f, 0x8f, 0xef, + 0xf5, 0x95, 0x35, 0x55, 0x68, 0x08, 0xa8, 0xc8, + 0x25, 0x45, 0xe5, 0x85, 0xb8, 0xd8, 0x78, 0x18, + 0x02, 0x62, 0xc2, 0xa2, 0x9f, 0xff, 0x5f, 0x3f, + 0x6b, 0x0b, 0xab, 0xcb, 0xf6, 0x96, 0x36, 0x56, + 0x4c, 0x2c, 0x8c, 0xec, 0xd1, 0xb1, 0x11, 0x71, + 0xb9, 0xd9, 0x79, 0x19, 0x24, 0x44, 0xe4, 0x84, + 0x9e, 0xfe, 0x5e, 0x3e, 0x03, 0x63, 0xc3, 0xa3, + 0xf7, 0x97, 0x37, 0x57, 0x6a, 0x0a, 0xaa, 0xca, + 0xd0, 0xb0, 0x10, 0x70, 0x4d, 0x2d, 0x8d, 0xed, + 0x4a, 0x2a, 0x8a, 0xea, 0xd7, 0xb7, 0x17, 0x77, + 0x6d, 0x0d, 0xad, 0xcd, 0xf0, 0x90, 0x30, 0x50, + 0x04, 0x64, 0xc4, 0xa4, 0x99, 0xf9, 0x59, 0x39, + 0x23, 0x43, 0xe3, 0x83, 0xbe, 0xde, 0x7e, 0x1e, + 0xd6, 0xb6, 0x16, 0x76, 0x4b, 0x2b, 0x8b, 0xeb, + 0xf1, 0x91, 0x31, 0x51, 0x6c, 0x0c, 0xac, 0xcc, + 0x98, 0xf8, 0x58, 0x38, 0x05, 0x65, 0xc5, 0xa5, + 0xbf, 0xdf, 0x7f, 0x1f, 0x22, 0x42, 0xe2, 0x82, + 0x6f, 0x0f, 0xaf, 0xcf, 0xf2, 0x92, 0x32, 0x52, + 0x48, 0x28, 0x88, 0xe8, 0xd5, 0xb5, 0x15, 0x75, + 0x21, 0x41, 0xe1, 0x81, 0xbc, 0xdc, 0x7c, 0x1c, + 0x06, 0x66, 0xc6, 0xa6, 0x9b, 0xfb, 0x5b, 0x3b, + 0xf3, 0x93, 0x33, 0x53, 0x6e, 0x0e, 0xae, 0xce, + 0xd4, 0xb4, 0x14, 0x74, 0x49, 0x29, 0x89, 0xe9, + 0xbd, 0xdd, 0x7d, 0x1d, 0x20, 0x40, 0xe0, 0x80, + 0x9a, 0xfa, 0x5a, 0x3a, 0x07, 0x67, 0xc7, 0xa7, + }, + { + 0x00, 0x61, 0xc2, 0xa3, 0x99, 0xf8, 0x5b, 0x3a, + 0x2f, 0x4e, 0xed, 0x8c, 0xb6, 0xd7, 0x74, 0x15, + 0x5e, 0x3f, 0x9c, 0xfd, 0xc7, 0xa6, 0x05, 0x64, + 0x71, 0x10, 0xb3, 0xd2, 0xe8, 0x89, 0x2a, 0x4b, + 0xbc, 0xdd, 0x7e, 0x1f, 0x25, 0x44, 0xe7, 0x86, + 0x93, 0xf2, 0x51, 0x30, 0x0a, 0x6b, 0xc8, 0xa9, + 0xe2, 0x83, 0x20, 0x41, 0x7b, 0x1a, 0xb9, 0xd8, + 0xcd, 0xac, 0x0f, 0x6e, 0x54, 0x35, 0x96, 0xf7, + 0x65, 0x04, 0xa7, 0xc6, 0xfc, 0x9d, 0x3e, 0x5f, + 0x4a, 0x2b, 0x88, 0xe9, 0xd3, 0xb2, 0x11, 0x70, + 0x3b, 0x5a, 0xf9, 0x98, 0xa2, 0xc3, 0x60, 0x01, + 0x14, 0x75, 0xd6, 0xb7, 0x8d, 0xec, 0x4f, 0x2e, + 0xd9, 0xb8, 0x1b, 0x7a, 0x40, 0x21, 0x82, 0xe3, + 0xf6, 0x97, 0x34, 0x55, 0x6f, 0x0e, 0xad, 0xcc, + 0x87, 0xe6, 0x45, 0x24, 0x1e, 0x7f, 0xdc, 0xbd, + 0xa8, 0xc9, 0x6a, 0x0b, 0x31, 0x50, 0xf3, 0x92, + 0xca, 0xab, 0x08, 0x69, 0x53, 0x32, 0x91, 0xf0, + 0xe5, 0x84, 0x27, 0x46, 0x7c, 0x1d, 0xbe, 0xdf, + 0x94, 0xf5, 0x56, 0x37, 0x0d, 0x6c, 0xcf, 0xae, + 0xbb, 0xda, 0x79, 0x18, 0x22, 0x43, 0xe0, 0x81, + 0x76, 0x17, 0xb4, 0xd5, 0xef, 0x8e, 0x2d, 0x4c, + 0x59, 0x38, 0x9b, 0xfa, 0xc0, 0xa1, 0x02, 0x63, + 0x28, 0x49, 0xea, 0x8b, 0xb1, 0xd0, 0x73, 0x12, + 0x07, 0x66, 0xc5, 0xa4, 0x9e, 0xff, 0x5c, 0x3d, + 0xaf, 0xce, 0x6d, 0x0c, 0x36, 0x57, 0xf4, 0x95, + 0x80, 0xe1, 0x42, 0x23, 0x19, 0x78, 0xdb, 0xba, + 0xf1, 0x90, 0x33, 0x52, 0x68, 0x09, 0xaa, 0xcb, + 0xde, 0xbf, 0x1c, 0x7d, 0x47, 0x26, 0x85, 0xe4, + 0x13, 0x72, 0xd1, 0xb0, 0x8a, 0xeb, 0x48, 0x29, + 0x3c, 0x5d, 0xfe, 0x9f, 0xa5, 0xc4, 0x67, 0x06, + 0x4d, 0x2c, 0x8f, 0xee, 0xd4, 0xb5, 0x16, 0x77, + 0x62, 0x03, 0xa0, 0xc1, 0xfb, 0x9a, 0x39, 0x58, + }, + { + 0x00, 0x62, 0xc4, 0xa6, 0x95, 0xf7, 0x51, 0x33, + 0x37, 0x55, 0xf3, 0x91, 0xa2, 0xc0, 0x66, 0x04, + 0x6e, 0x0c, 0xaa, 0xc8, 0xfb, 0x99, 0x3f, 0x5d, + 0x59, 0x3b, 0x9d, 0xff, 0xcc, 0xae, 0x08, 0x6a, + 0xdc, 0xbe, 0x18, 0x7a, 0x49, 0x2b, 0x8d, 0xef, + 0xeb, 0x89, 0x2f, 0x4d, 0x7e, 0x1c, 0xba, 0xd8, + 0xb2, 0xd0, 0x76, 0x14, 0x27, 0x45, 0xe3, 0x81, + 0x85, 0xe7, 0x41, 0x23, 0x10, 0x72, 0xd4, 0xb6, + 0xa5, 0xc7, 0x61, 0x03, 0x30, 0x52, 0xf4, 0x96, + 0x92, 0xf0, 0x56, 0x34, 0x07, 0x65, 0xc3, 0xa1, + 0xcb, 0xa9, 0x0f, 0x6d, 0x5e, 0x3c, 0x9a, 0xf8, + 0xfc, 0x9e, 0x38, 0x5a, 0x69, 0x0b, 0xad, 0xcf, + 0x79, 0x1b, 0xbd, 0xdf, 0xec, 0x8e, 0x28, 0x4a, + 0x4e, 0x2c, 0x8a, 0xe8, 0xdb, 0xb9, 0x1f, 0x7d, + 0x17, 0x75, 0xd3, 0xb1, 0x82, 0xe0, 0x46, 0x24, + 0x20, 0x42, 0xe4, 0x86, 0xb5, 0xd7, 0x71, 0x13, + 0x57, 0x35, 0x93, 0xf1, 0xc2, 0xa0, 0x06, 0x64, + 0x60, 0x02, 0xa4, 0xc6, 0xf5, 0x97, 0x31, 0x53, + 0x39, 0x5b, 0xfd, 0x9f, 0xac, 0xce, 0x68, 0x0a, + 0x0e, 0x6c, 0xca, 0xa8, 0x9b, 0xf9, 0x5f, 0x3d, + 0x8b, 0xe9, 0x4f, 0x2d, 0x1e, 0x7c, 0xda, 0xb8, + 0xbc, 0xde, 0x78, 0x1a, 0x29, 0x4b, 0xed, 0x8f, + 0xe5, 0x87, 0x21, 0x43, 0x70, 0x12, 0xb4, 0xd6, + 0xd2, 0xb0, 0x16, 0x74, 0x47, 0x25, 0x83, 0xe1, + 0xf2, 0x90, 0x36, 0x54, 0x67, 0x05, 0xa3, 0xc1, + 0xc5, 0xa7, 0x01, 0x63, 0x50, 0x32, 0x94, 0xf6, + 0x9c, 0xfe, 0x58, 0x3a, 0x09, 0x6b, 0xcd, 0xaf, + 0xab, 0xc9, 0x6f, 0x0d, 0x3e, 0x5c, 0xfa, 0x98, + 0x2e, 0x4c, 0xea, 0x88, 0xbb, 0xd9, 0x7f, 0x1d, + 0x19, 0x7b, 0xdd, 0xbf, 0x8c, 0xee, 0x48, 0x2a, + 0x40, 0x22, 0x84, 0xe6, 0xd5, 0xb7, 0x11, 0x73, + 0x77, 0x15, 0xb3, 0xd1, 0xe2, 0x80, 0x26, 0x44, + }, + { + 0x00, 0x63, 0xc6, 0xa5, 0x91, 0xf2, 0x57, 0x34, + 0x3f, 0x5c, 0xf9, 0x9a, 0xae, 0xcd, 0x68, 0x0b, + 0x7e, 0x1d, 0xb8, 0xdb, 0xef, 0x8c, 0x29, 0x4a, + 0x41, 0x22, 0x87, 0xe4, 0xd0, 0xb3, 0x16, 0x75, + 0xfc, 0x9f, 0x3a, 0x59, 0x6d, 0x0e, 0xab, 0xc8, + 0xc3, 0xa0, 0x05, 0x66, 0x52, 0x31, 0x94, 0xf7, + 0x82, 0xe1, 0x44, 0x27, 0x13, 0x70, 0xd5, 0xb6, + 0xbd, 0xde, 0x7b, 0x18, 0x2c, 0x4f, 0xea, 0x89, + 0xe5, 0x86, 0x23, 0x40, 0x74, 0x17, 0xb2, 0xd1, + 0xda, 0xb9, 0x1c, 0x7f, 0x4b, 0x28, 0x8d, 0xee, + 0x9b, 0xf8, 0x5d, 0x3e, 0x0a, 0x69, 0xcc, 0xaf, + 0xa4, 0xc7, 0x62, 0x01, 0x35, 0x56, 0xf3, 0x90, + 0x19, 0x7a, 0xdf, 0xbc, 0x88, 0xeb, 0x4e, 0x2d, + 0x26, 0x45, 0xe0, 0x83, 0xb7, 0xd4, 0x71, 0x12, + 0x67, 0x04, 0xa1, 0xc2, 0xf6, 0x95, 0x30, 0x53, + 0x58, 0x3b, 0x9e, 0xfd, 0xc9, 0xaa, 0x0f, 0x6c, + 0xd7, 0xb4, 0x11, 0x72, 0x46, 0x25, 0x80, 0xe3, + 0xe8, 0x8b, 0x2e, 0x4d, 0x79, 0x1a, 0xbf, 0xdc, + 0xa9, 0xca, 0x6f, 0x0c, 0x38, 0x5b, 0xfe, 0x9d, + 0x96, 0xf5, 0x50, 0x33, 0x07, 0x64, 0xc1, 0xa2, + 0x2b, 0x48, 0xed, 0x8e, 0xba, 0xd9, 0x7c, 0x1f, + 0x14, 0x77, 0xd2, 0xb1, 0x85, 0xe6, 0x43, 0x20, + 0x55, 0x36, 0x93, 0xf0, 0xc4, 0xa7, 0x02, 0x61, + 0x6a, 0x09, 0xac, 0xcf, 0xfb, 0x98, 0x3d, 0x5e, + 0x32, 0x51, 0xf4, 0x97, 0xa3, 0xc0, 0x65, 0x06, + 0x0d, 0x6e, 0xcb, 0xa8, 0x9c, 0xff, 0x5a, 0x39, + 0x4c, 0x2f, 0x8a, 0xe9, 0xdd, 0xbe, 0x1b, 0x78, + 0x73, 0x10, 0xb5, 0xd6, 0xe2, 0x81, 0x24, 0x47, + 0xce, 0xad, 0x08, 0x6b, 0x5f, 0x3c, 0x99, 0xfa, + 0xf1, 0x92, 0x37, 0x54, 0x60, 0x03, 0xa6, 0xc5, + 0xb0, 0xd3, 0x76, 0x15, 0x21, 0x42, 0xe7, 0x84, + 0x8f, 0xec, 0x49, 0x2a, 0x1e, 0x7d, 0xd8, 0xbb, + }, + { + 0x00, 0x64, 0xc8, 0xac, 0x8d, 0xe9, 0x45, 0x21, + 0x07, 0x63, 0xcf, 0xab, 0x8a, 0xee, 0x42, 0x26, + 0x0e, 0x6a, 0xc6, 0xa2, 0x83, 0xe7, 0x4b, 0x2f, + 0x09, 0x6d, 0xc1, 0xa5, 0x84, 0xe0, 0x4c, 0x28, + 0x1c, 0x78, 0xd4, 0xb0, 0x91, 0xf5, 0x59, 0x3d, + 0x1b, 0x7f, 0xd3, 0xb7, 0x96, 0xf2, 0x5e, 0x3a, + 0x12, 0x76, 0xda, 0xbe, 0x9f, 0xfb, 0x57, 0x33, + 0x15, 0x71, 0xdd, 0xb9, 0x98, 0xfc, 0x50, 0x34, + 0x38, 0x5c, 0xf0, 0x94, 0xb5, 0xd1, 0x7d, 0x19, + 0x3f, 0x5b, 0xf7, 0x93, 0xb2, 0xd6, 0x7a, 0x1e, + 0x36, 0x52, 0xfe, 0x9a, 0xbb, 0xdf, 0x73, 0x17, + 0x31, 0x55, 0xf9, 0x9d, 0xbc, 0xd8, 0x74, 0x10, + 0x24, 0x40, 0xec, 0x88, 0xa9, 0xcd, 0x61, 0x05, + 0x23, 0x47, 0xeb, 0x8f, 0xae, 0xca, 0x66, 0x02, + 0x2a, 0x4e, 0xe2, 0x86, 0xa7, 0xc3, 0x6f, 0x0b, + 0x2d, 0x49, 0xe5, 0x81, 0xa0, 0xc4, 0x68, 0x0c, + 0x70, 0x14, 0xb8, 0xdc, 0xfd, 0x99, 0x35, 0x51, + 0x77, 0x13, 0xbf, 0xdb, 0xfa, 0x9e, 0x32, 0x56, + 0x7e, 0x1a, 0xb6, 0xd2, 0xf3, 0x97, 0x3b, 0x5f, + 0x79, 0x1d, 0xb1, 0xd5, 0xf4, 0x90, 0x3c, 0x58, + 0x6c, 0x08, 0xa4, 0xc0, 0xe1, 0x85, 0x29, 0x4d, + 0x6b, 0x0f, 0xa3, 0xc7, 0xe6, 0x82, 0x2e, 0x4a, + 0x62, 0x06, 0xaa, 0xce, 0xef, 0x8b, 0x27, 0x43, + 0x65, 0x01, 0xad, 0xc9, 0xe8, 0x8c, 0x20, 0x44, + 0x48, 0x2c, 0x80, 0xe4, 0xc5, 0xa1, 0x0d, 0x69, + 0x4f, 0x2b, 0x87, 0xe3, 0xc2, 0xa6, 0x0a, 0x6e, + 0x46, 0x22, 0x8e, 0xea, 0xcb, 0xaf, 0x03, 0x67, + 0x41, 0x25, 0x89, 0xed, 0xcc, 0xa8, 0x04, 0x60, + 0x54, 0x30, 0x9c, 0xf8, 0xd9, 0xbd, 0x11, 0x75, + 0x53, 0x37, 0x9b, 0xff, 0xde, 0xba, 0x16, 0x72, + 0x5a, 0x3e, 0x92, 0xf6, 0xd7, 0xb3, 0x1f, 0x7b, + 0x5d, 0x39, 0x95, 0xf1, 0xd0, 0xb4, 0x18, 0x7c, + }, + { + 0x00, 0x65, 0xca, 0xaf, 0x89, 0xec, 0x43, 0x26, + 0x0f, 0x6a, 0xc5, 0xa0, 0x86, 0xe3, 0x4c, 0x29, + 0x1e, 0x7b, 0xd4, 0xb1, 0x97, 0xf2, 0x5d, 0x38, + 0x11, 0x74, 0xdb, 0xbe, 0x98, 0xfd, 0x52, 0x37, + 0x3c, 0x59, 0xf6, 0x93, 0xb5, 0xd0, 0x7f, 0x1a, + 0x33, 0x56, 0xf9, 0x9c, 0xba, 0xdf, 0x70, 0x15, + 0x22, 0x47, 0xe8, 0x8d, 0xab, 0xce, 0x61, 0x04, + 0x2d, 0x48, 0xe7, 0x82, 0xa4, 0xc1, 0x6e, 0x0b, + 0x78, 0x1d, 0xb2, 0xd7, 0xf1, 0x94, 0x3b, 0x5e, + 0x77, 0x12, 0xbd, 0xd8, 0xfe, 0x9b, 0x34, 0x51, + 0x66, 0x03, 0xac, 0xc9, 0xef, 0x8a, 0x25, 0x40, + 0x69, 0x0c, 0xa3, 0xc6, 0xe0, 0x85, 0x2a, 0x4f, + 0x44, 0x21, 0x8e, 0xeb, 0xcd, 0xa8, 0x07, 0x62, + 0x4b, 0x2e, 0x81, 0xe4, 0xc2, 0xa7, 0x08, 0x6d, + 0x5a, 0x3f, 0x90, 0xf5, 0xd3, 0xb6, 0x19, 0x7c, + 0x55, 0x30, 0x9f, 0xfa, 0xdc, 0xb9, 0x16, 0x73, + 0xf0, 0x95, 0x3a, 0x5f, 0x79, 0x1c, 0xb3, 0xd6, + 0xff, 0x9a, 0x35, 0x50, 0x76, 0x13, 0xbc, 0xd9, + 0xee, 0x8b, 0x24, 0x41, 0x67, 0x02, 0xad, 0xc8, + 0xe1, 0x84, 0x2b, 0x4e, 0x68, 0x0d, 0xa2, 0xc7, + 0xcc, 0xa9, 0x06, 0x63, 0x45, 0x20, 0x8f, 0xea, + 0xc3, 0xa6, 0x09, 0x6c, 0x4a, 0x2f, 0x80, 0xe5, + 0xd2, 0xb7, 0x18, 0x7d, 0x5b, 0x3e, 0x91, 0xf4, + 0xdd, 0xb8, 0x17, 0x72, 0x54, 0x31, 0x9e, 0xfb, + 0x88, 0xed, 0x42, 0x27, 0x01, 0x64, 0xcb, 0xae, + 0x87, 0xe2, 0x4d, 0x28, 0x0e, 0x6b, 0xc4, 0xa1, + 0x96, 0xf3, 0x5c, 0x39, 0x1f, 0x7a, 0xd5, 0xb0, + 0x99, 0xfc, 0x53, 0x36, 0x10, 0x75, 0xda, 0xbf, + 0xb4, 0xd1, 0x7e, 0x1b, 0x3d, 0x58, 0xf7, 0x92, + 0xbb, 0xde, 0x71, 0x14, 0x32, 0x57, 0xf8, 0x9d, + 0xaa, 0xcf, 0x60, 0x05, 0x23, 0x46, 0xe9, 0x8c, + 0xa5, 0xc0, 0x6f, 0x0a, 0x2c, 0x49, 0xe6, 0x83, + }, + { + 0x00, 0x66, 0xcc, 0xaa, 0x85, 0xe3, 0x49, 0x2f, + 0x17, 0x71, 0xdb, 0xbd, 0x92, 0xf4, 0x5e, 0x38, + 0x2e, 0x48, 0xe2, 0x84, 0xab, 0xcd, 0x67, 0x01, + 0x39, 0x5f, 0xf5, 0x93, 0xbc, 0xda, 0x70, 0x16, + 0x5c, 0x3a, 0x90, 0xf6, 0xd9, 0xbf, 0x15, 0x73, + 0x4b, 0x2d, 0x87, 0xe1, 0xce, 0xa8, 0x02, 0x64, + 0x72, 0x14, 0xbe, 0xd8, 0xf7, 0x91, 0x3b, 0x5d, + 0x65, 0x03, 0xa9, 0xcf, 0xe0, 0x86, 0x2c, 0x4a, + 0xb8, 0xde, 0x74, 0x12, 0x3d, 0x5b, 0xf1, 0x97, + 0xaf, 0xc9, 0x63, 0x05, 0x2a, 0x4c, 0xe6, 0x80, + 0x96, 0xf0, 0x5a, 0x3c, 0x13, 0x75, 0xdf, 0xb9, + 0x81, 0xe7, 0x4d, 0x2b, 0x04, 0x62, 0xc8, 0xae, + 0xe4, 0x82, 0x28, 0x4e, 0x61, 0x07, 0xad, 0xcb, + 0xf3, 0x95, 0x3f, 0x59, 0x76, 0x10, 0xba, 0xdc, + 0xca, 0xac, 0x06, 0x60, 0x4f, 0x29, 0x83, 0xe5, + 0xdd, 0xbb, 0x11, 0x77, 0x58, 0x3e, 0x94, 0xf2, + 0x6d, 0x0b, 0xa1, 0xc7, 0xe8, 0x8e, 0x24, 0x42, + 0x7a, 0x1c, 0xb6, 0xd0, 0xff, 0x99, 0x33, 0x55, + 0x43, 0x25, 0x8f, 0xe9, 0xc6, 0xa0, 0x0a, 0x6c, + 0x54, 0x32, 0x98, 0xfe, 0xd1, 0xb7, 0x1d, 0x7b, + 0x31, 0x57, 0xfd, 0x9b, 0xb4, 0xd2, 0x78, 0x1e, + 0x26, 0x40, 0xea, 0x8c, 0xa3, 0xc5, 0x6f, 0x09, + 0x1f, 0x79, 0xd3, 0xb5, 0x9a, 0xfc, 0x56, 0x30, + 0x08, 0x6e, 0xc4, 0xa2, 0x8d, 0xeb, 0x41, 0x27, + 0xd5, 0xb3, 0x19, 0x7f, 0x50, 0x36, 0x9c, 0xfa, + 0xc2, 0xa4, 0x0e, 0x68, 0x47, 0x21, 0x8b, 0xed, + 0xfb, 0x9d, 0x37, 0x51, 0x7e, 0x18, 0xb2, 0xd4, + 0xec, 0x8a, 0x20, 0x46, 0x69, 0x0f, 0xa5, 0xc3, + 0x89, 0xef, 0x45, 0x23, 0x0c, 0x6a, 0xc0, 0xa6, + 0x9e, 0xf8, 0x52, 0x34, 0x1b, 0x7d, 0xd7, 0xb1, + 0xa7, 0xc1, 0x6b, 0x0d, 0x22, 0x44, 0xee, 0x88, + 0xb0, 0xd6, 0x7c, 0x1a, 0x35, 0x53, 0xf9, 0x9f, + }, + { + 0x00, 0x67, 0xce, 0xa9, 0x81, 0xe6, 0x4f, 0x28, + 0x1f, 0x78, 0xd1, 0xb6, 0x9e, 0xf9, 0x50, 0x37, + 0x3e, 0x59, 0xf0, 0x97, 0xbf, 0xd8, 0x71, 0x16, + 0x21, 0x46, 0xef, 0x88, 0xa0, 0xc7, 0x6e, 0x09, + 0x7c, 0x1b, 0xb2, 0xd5, 0xfd, 0x9a, 0x33, 0x54, + 0x63, 0x04, 0xad, 0xca, 0xe2, 0x85, 0x2c, 0x4b, + 0x42, 0x25, 0x8c, 0xeb, 0xc3, 0xa4, 0x0d, 0x6a, + 0x5d, 0x3a, 0x93, 0xf4, 0xdc, 0xbb, 0x12, 0x75, + 0xf8, 0x9f, 0x36, 0x51, 0x79, 0x1e, 0xb7, 0xd0, + 0xe7, 0x80, 0x29, 0x4e, 0x66, 0x01, 0xa8, 0xcf, + 0xc6, 0xa1, 0x08, 0x6f, 0x47, 0x20, 0x89, 0xee, + 0xd9, 0xbe, 0x17, 0x70, 0x58, 0x3f, 0x96, 0xf1, + 0x84, 0xe3, 0x4a, 0x2d, 0x05, 0x62, 0xcb, 0xac, + 0x9b, 0xfc, 0x55, 0x32, 0x1a, 0x7d, 0xd4, 0xb3, + 0xba, 0xdd, 0x74, 0x13, 0x3b, 0x5c, 0xf5, 0x92, + 0xa5, 0xc2, 0x6b, 0x0c, 0x24, 0x43, 0xea, 0x8d, + 0xed, 0x8a, 0x23, 0x44, 0x6c, 0x0b, 0xa2, 0xc5, + 0xf2, 0x95, 0x3c, 0x5b, 0x73, 0x14, 0xbd, 0xda, + 0xd3, 0xb4, 0x1d, 0x7a, 0x52, 0x35, 0x9c, 0xfb, + 0xcc, 0xab, 0x02, 0x65, 0x4d, 0x2a, 0x83, 0xe4, + 0x91, 0xf6, 0x5f, 0x38, 0x10, 0x77, 0xde, 0xb9, + 0x8e, 0xe9, 0x40, 0x27, 0x0f, 0x68, 0xc1, 0xa6, + 0xaf, 0xc8, 0x61, 0x06, 0x2e, 0x49, 0xe0, 0x87, + 0xb0, 0xd7, 0x7e, 0x19, 0x31, 0x56, 0xff, 0x98, + 0x15, 0x72, 0xdb, 0xbc, 0x94, 0xf3, 0x5a, 0x3d, + 0x0a, 0x6d, 0xc4, 0xa3, 0x8b, 0xec, 0x45, 0x22, + 0x2b, 0x4c, 0xe5, 0x82, 0xaa, 0xcd, 0x64, 0x03, + 0x34, 0x53, 0xfa, 0x9d, 0xb5, 0xd2, 0x7b, 0x1c, + 0x69, 0x0e, 0xa7, 0xc0, 0xe8, 0x8f, 0x26, 0x41, + 0x76, 0x11, 0xb8, 0xdf, 0xf7, 0x90, 0x39, 0x5e, + 0x57, 0x30, 0x99, 0xfe, 0xd6, 0xb1, 0x18, 0x7f, + 0x48, 0x2f, 0x86, 0xe1, 0xc9, 0xae, 0x07, 0x60, + }, + { + 0x00, 0x68, 0xd0, 0xb8, 0xbd, 0xd5, 0x6d, 0x05, + 0x67, 0x0f, 0xb7, 0xdf, 0xda, 0xb2, 0x0a, 0x62, + 0xce, 0xa6, 0x1e, 0x76, 0x73, 0x1b, 0xa3, 0xcb, + 0xa9, 0xc1, 0x79, 0x11, 0x14, 0x7c, 0xc4, 0xac, + 0x81, 0xe9, 0x51, 0x39, 0x3c, 0x54, 0xec, 0x84, + 0xe6, 0x8e, 0x36, 0x5e, 0x5b, 0x33, 0x8b, 0xe3, + 0x4f, 0x27, 0x9f, 0xf7, 0xf2, 0x9a, 0x22, 0x4a, + 0x28, 0x40, 0xf8, 0x90, 0x95, 0xfd, 0x45, 0x2d, + 0x1f, 0x77, 0xcf, 0xa7, 0xa2, 0xca, 0x72, 0x1a, + 0x78, 0x10, 0xa8, 0xc0, 0xc5, 0xad, 0x15, 0x7d, + 0xd1, 0xb9, 0x01, 0x69, 0x6c, 0x04, 0xbc, 0xd4, + 0xb6, 0xde, 0x66, 0x0e, 0x0b, 0x63, 0xdb, 0xb3, + 0x9e, 0xf6, 0x4e, 0x26, 0x23, 0x4b, 0xf3, 0x9b, + 0xf9, 0x91, 0x29, 0x41, 0x44, 0x2c, 0x94, 0xfc, + 0x50, 0x38, 0x80, 0xe8, 0xed, 0x85, 0x3d, 0x55, + 0x37, 0x5f, 0xe7, 0x8f, 0x8a, 0xe2, 0x5a, 0x32, + 0x3e, 0x56, 0xee, 0x86, 0x83, 0xeb, 0x53, 0x3b, + 0x59, 0x31, 0x89, 0xe1, 0xe4, 0x8c, 0x34, 0x5c, + 0xf0, 0x98, 0x20, 0x48, 0x4d, 0x25, 0x9d, 0xf5, + 0x97, 0xff, 0x47, 0x2f, 0x2a, 0x42, 0xfa, 0x92, + 0xbf, 0xd7, 0x6f, 0x07, 0x02, 0x6a, 0xd2, 0xba, + 0xd8, 0xb0, 0x08, 0x60, 0x65, 0x0d, 0xb5, 0xdd, + 0x71, 0x19, 0xa1, 0xc9, 0xcc, 0xa4, 0x1c, 0x74, + 0x16, 0x7e, 0xc6, 0xae, 0xab, 0xc3, 0x7b, 0x13, + 0x21, 0x49, 0xf1, 0x99, 0x9c, 0xf4, 0x4c, 0x24, + 0x46, 0x2e, 0x96, 0xfe, 0xfb, 0x93, 0x2b, 0x43, + 0xef, 0x87, 0x3f, 0x57, 0x52, 0x3a, 0x82, 0xea, + 0x88, 0xe0, 0x58, 0x30, 0x35, 0x5d, 0xe5, 0x8d, + 0xa0, 0xc8, 0x70, 0x18, 0x1d, 0x75, 0xcd, 0xa5, + 0xc7, 0xaf, 0x17, 0x7f, 0x7a, 0x12, 0xaa, 0xc2, + 0x6e, 0x06, 0xbe, 0xd6, 0xd3, 0xbb, 0x03, 0x6b, + 0x09, 0x61, 0xd9, 0xb1, 0xb4, 0xdc, 0x64, 0x0c, + }, + { + 0x00, 0x69, 0xd2, 0xbb, 0xb9, 0xd0, 0x6b, 0x02, + 0x6f, 0x06, 0xbd, 0xd4, 0xd6, 0xbf, 0x04, 0x6d, + 0xde, 0xb7, 0x0c, 0x65, 0x67, 0x0e, 0xb5, 0xdc, + 0xb1, 0xd8, 0x63, 0x0a, 0x08, 0x61, 0xda, 0xb3, + 0xa1, 0xc8, 0x73, 0x1a, 0x18, 0x71, 0xca, 0xa3, + 0xce, 0xa7, 0x1c, 0x75, 0x77, 0x1e, 0xa5, 0xcc, + 0x7f, 0x16, 0xad, 0xc4, 0xc6, 0xaf, 0x14, 0x7d, + 0x10, 0x79, 0xc2, 0xab, 0xa9, 0xc0, 0x7b, 0x12, + 0x5f, 0x36, 0x8d, 0xe4, 0xe6, 0x8f, 0x34, 0x5d, + 0x30, 0x59, 0xe2, 0x8b, 0x89, 0xe0, 0x5b, 0x32, + 0x81, 0xe8, 0x53, 0x3a, 0x38, 0x51, 0xea, 0x83, + 0xee, 0x87, 0x3c, 0x55, 0x57, 0x3e, 0x85, 0xec, + 0xfe, 0x97, 0x2c, 0x45, 0x47, 0x2e, 0x95, 0xfc, + 0x91, 0xf8, 0x43, 0x2a, 0x28, 0x41, 0xfa, 0x93, + 0x20, 0x49, 0xf2, 0x9b, 0x99, 0xf0, 0x4b, 0x22, + 0x4f, 0x26, 0x9d, 0xf4, 0xf6, 0x9f, 0x24, 0x4d, + 0xbe, 0xd7, 0x6c, 0x05, 0x07, 0x6e, 0xd5, 0xbc, + 0xd1, 0xb8, 0x03, 0x6a, 0x68, 0x01, 0xba, 0xd3, + 0x60, 0x09, 0xb2, 0xdb, 0xd9, 0xb0, 0x0b, 0x62, + 0x0f, 0x66, 0xdd, 0xb4, 0xb6, 0xdf, 0x64, 0x0d, + 0x1f, 0x76, 0xcd, 0xa4, 0xa6, 0xcf, 0x74, 0x1d, + 0x70, 0x19, 0xa2, 0xcb, 0xc9, 0xa0, 0x1b, 0x72, + 0xc1, 0xa8, 0x13, 0x7a, 0x78, 0x11, 0xaa, 0xc3, + 0xae, 0xc7, 0x7c, 0x15, 0x17, 0x7e, 0xc5, 0xac, + 0xe1, 0x88, 0x33, 0x5a, 0x58, 0x31, 0x8a, 0xe3, + 0x8e, 0xe7, 0x5c, 0x35, 0x37, 0x5e, 0xe5, 0x8c, + 0x3f, 0x56, 0xed, 0x84, 0x86, 0xef, 0x54, 0x3d, + 0x50, 0x39, 0x82, 0xeb, 0xe9, 0x80, 0x3b, 0x52, + 0x40, 0x29, 0x92, 0xfb, 0xf9, 0x90, 0x2b, 0x42, + 0x2f, 0x46, 0xfd, 0x94, 0x96, 0xff, 0x44, 0x2d, + 0x9e, 0xf7, 0x4c, 0x25, 0x27, 0x4e, 0xf5, 0x9c, + 0xf1, 0x98, 0x23, 0x4a, 0x48, 0x21, 0x9a, 0xf3, + }, + { + 0x00, 0x6a, 0xd4, 0xbe, 0xb5, 0xdf, 0x61, 0x0b, + 0x77, 0x1d, 0xa3, 0xc9, 0xc2, 0xa8, 0x16, 0x7c, + 0xee, 0x84, 0x3a, 0x50, 0x5b, 0x31, 0x8f, 0xe5, + 0x99, 0xf3, 0x4d, 0x27, 0x2c, 0x46, 0xf8, 0x92, + 0xc1, 0xab, 0x15, 0x7f, 0x74, 0x1e, 0xa0, 0xca, + 0xb6, 0xdc, 0x62, 0x08, 0x03, 0x69, 0xd7, 0xbd, + 0x2f, 0x45, 0xfb, 0x91, 0x9a, 0xf0, 0x4e, 0x24, + 0x58, 0x32, 0x8c, 0xe6, 0xed, 0x87, 0x39, 0x53, + 0x9f, 0xf5, 0x4b, 0x21, 0x2a, 0x40, 0xfe, 0x94, + 0xe8, 0x82, 0x3c, 0x56, 0x5d, 0x37, 0x89, 0xe3, + 0x71, 0x1b, 0xa5, 0xcf, 0xc4, 0xae, 0x10, 0x7a, + 0x06, 0x6c, 0xd2, 0xb8, 0xb3, 0xd9, 0x67, 0x0d, + 0x5e, 0x34, 0x8a, 0xe0, 0xeb, 0x81, 0x3f, 0x55, + 0x29, 0x43, 0xfd, 0x97, 0x9c, 0xf6, 0x48, 0x22, + 0xb0, 0xda, 0x64, 0x0e, 0x05, 0x6f, 0xd1, 0xbb, + 0xc7, 0xad, 0x13, 0x79, 0x72, 0x18, 0xa6, 0xcc, + 0x23, 0x49, 0xf7, 0x9d, 0x96, 0xfc, 0x42, 0x28, + 0x54, 0x3e, 0x80, 0xea, 0xe1, 0x8b, 0x35, 0x5f, + 0xcd, 0xa7, 0x19, 0x73, 0x78, 0x12, 0xac, 0xc6, + 0xba, 0xd0, 0x6e, 0x04, 0x0f, 0x65, 0xdb, 0xb1, + 0xe2, 0x88, 0x36, 0x5c, 0x57, 0x3d, 0x83, 0xe9, + 0x95, 0xff, 0x41, 0x2b, 0x20, 0x4a, 0xf4, 0x9e, + 0x0c, 0x66, 0xd8, 0xb2, 0xb9, 0xd3, 0x6d, 0x07, + 0x7b, 0x11, 0xaf, 0xc5, 0xce, 0xa4, 0x1a, 0x70, + 0xbc, 0xd6, 0x68, 0x02, 0x09, 0x63, 0xdd, 0xb7, + 0xcb, 0xa1, 0x1f, 0x75, 0x7e, 0x14, 0xaa, 0xc0, + 0x52, 0x38, 0x86, 0xec, 0xe7, 0x8d, 0x33, 0x59, + 0x25, 0x4f, 0xf1, 0x9b, 0x90, 0xfa, 0x44, 0x2e, + 0x7d, 0x17, 0xa9, 0xc3, 0xc8, 0xa2, 0x1c, 0x76, + 0x0a, 0x60, 0xde, 0xb4, 0xbf, 0xd5, 0x6b, 0x01, + 0x93, 0xf9, 0x47, 0x2d, 0x26, 0x4c, 0xf2, 0x98, + 0xe4, 0x8e, 0x30, 0x5a, 0x51, 0x3b, 0x85, 0xef, + }, + { + 0x00, 0x6b, 0xd6, 0xbd, 0xb1, 0xda, 0x67, 0x0c, + 0x7f, 0x14, 0xa9, 0xc2, 0xce, 0xa5, 0x18, 0x73, + 0xfe, 0x95, 0x28, 0x43, 0x4f, 0x24, 0x99, 0xf2, + 0x81, 0xea, 0x57, 0x3c, 0x30, 0x5b, 0xe6, 0x8d, + 0xe1, 0x8a, 0x37, 0x5c, 0x50, 0x3b, 0x86, 0xed, + 0x9e, 0xf5, 0x48, 0x23, 0x2f, 0x44, 0xf9, 0x92, + 0x1f, 0x74, 0xc9, 0xa2, 0xae, 0xc5, 0x78, 0x13, + 0x60, 0x0b, 0xb6, 0xdd, 0xd1, 0xba, 0x07, 0x6c, + 0xdf, 0xb4, 0x09, 0x62, 0x6e, 0x05, 0xb8, 0xd3, + 0xa0, 0xcb, 0x76, 0x1d, 0x11, 0x7a, 0xc7, 0xac, + 0x21, 0x4a, 0xf7, 0x9c, 0x90, 0xfb, 0x46, 0x2d, + 0x5e, 0x35, 0x88, 0xe3, 0xef, 0x84, 0x39, 0x52, + 0x3e, 0x55, 0xe8, 0x83, 0x8f, 0xe4, 0x59, 0x32, + 0x41, 0x2a, 0x97, 0xfc, 0xf0, 0x9b, 0x26, 0x4d, + 0xc0, 0xab, 0x16, 0x7d, 0x71, 0x1a, 0xa7, 0xcc, + 0xbf, 0xd4, 0x69, 0x02, 0x0e, 0x65, 0xd8, 0xb3, + 0xa3, 0xc8, 0x75, 0x1e, 0x12, 0x79, 0xc4, 0xaf, + 0xdc, 0xb7, 0x0a, 0x61, 0x6d, 0x06, 0xbb, 0xd0, + 0x5d, 0x36, 0x8b, 0xe0, 0xec, 0x87, 0x3a, 0x51, + 0x22, 0x49, 0xf4, 0x9f, 0x93, 0xf8, 0x45, 0x2e, + 0x42, 0x29, 0x94, 0xff, 0xf3, 0x98, 0x25, 0x4e, + 0x3d, 0x56, 0xeb, 0x80, 0x8c, 0xe7, 0x5a, 0x31, + 0xbc, 0xd7, 0x6a, 0x01, 0x0d, 0x66, 0xdb, 0xb0, + 0xc3, 0xa8, 0x15, 0x7e, 0x72, 0x19, 0xa4, 0xcf, + 0x7c, 0x17, 0xaa, 0xc1, 0xcd, 0xa6, 0x1b, 0x70, + 0x03, 0x68, 0xd5, 0xbe, 0xb2, 0xd9, 0x64, 0x0f, + 0x82, 0xe9, 0x54, 0x3f, 0x33, 0x58, 0xe5, 0x8e, + 0xfd, 0x96, 0x2b, 0x40, 0x4c, 0x27, 0x9a, 0xf1, + 0x9d, 0xf6, 0x4b, 0x20, 0x2c, 0x47, 0xfa, 0x91, + 0xe2, 0x89, 0x34, 0x5f, 0x53, 0x38, 0x85, 0xee, + 0x63, 0x08, 0xb5, 0xde, 0xd2, 0xb9, 0x04, 0x6f, + 0x1c, 0x77, 0xca, 0xa1, 0xad, 0xc6, 0x7b, 0x10, + }, + { + 0x00, 0x6c, 0xd8, 0xb4, 0xad, 0xc1, 0x75, 0x19, + 0x47, 0x2b, 0x9f, 0xf3, 0xea, 0x86, 0x32, 0x5e, + 0x8e, 0xe2, 0x56, 0x3a, 0x23, 0x4f, 0xfb, 0x97, + 0xc9, 0xa5, 0x11, 0x7d, 0x64, 0x08, 0xbc, 0xd0, + 0x01, 0x6d, 0xd9, 0xb5, 0xac, 0xc0, 0x74, 0x18, + 0x46, 0x2a, 0x9e, 0xf2, 0xeb, 0x87, 0x33, 0x5f, + 0x8f, 0xe3, 0x57, 0x3b, 0x22, 0x4e, 0xfa, 0x96, + 0xc8, 0xa4, 0x10, 0x7c, 0x65, 0x09, 0xbd, 0xd1, + 0x02, 0x6e, 0xda, 0xb6, 0xaf, 0xc3, 0x77, 0x1b, + 0x45, 0x29, 0x9d, 0xf1, 0xe8, 0x84, 0x30, 0x5c, + 0x8c, 0xe0, 0x54, 0x38, 0x21, 0x4d, 0xf9, 0x95, + 0xcb, 0xa7, 0x13, 0x7f, 0x66, 0x0a, 0xbe, 0xd2, + 0x03, 0x6f, 0xdb, 0xb7, 0xae, 0xc2, 0x76, 0x1a, + 0x44, 0x28, 0x9c, 0xf0, 0xe9, 0x85, 0x31, 0x5d, + 0x8d, 0xe1, 0x55, 0x39, 0x20, 0x4c, 0xf8, 0x94, + 0xca, 0xa6, 0x12, 0x7e, 0x67, 0x0b, 0xbf, 0xd3, + 0x04, 0x68, 0xdc, 0xb0, 0xa9, 0xc5, 0x71, 0x1d, + 0x43, 0x2f, 0x9b, 0xf7, 0xee, 0x82, 0x36, 0x5a, + 0x8a, 0xe6, 0x52, 0x3e, 0x27, 0x4b, 0xff, 0x93, + 0xcd, 0xa1, 0x15, 0x79, 0x60, 0x0c, 0xb8, 0xd4, + 0x05, 0x69, 0xdd, 0xb1, 0xa8, 0xc4, 0x70, 0x1c, + 0x42, 0x2e, 0x9a, 0xf6, 0xef, 0x83, 0x37, 0x5b, + 0x8b, 0xe7, 0x53, 0x3f, 0x26, 0x4a, 0xfe, 0x92, + 0xcc, 0xa0, 0x14, 0x78, 0x61, 0x0d, 0xb9, 0xd5, + 0x06, 0x6a, 0xde, 0xb2, 0xab, 0xc7, 0x73, 0x1f, + 0x41, 0x2d, 0x99, 0xf5, 0xec, 0x80, 0x34, 0x58, + 0x88, 0xe4, 0x50, 0x3c, 0x25, 0x49, 0xfd, 0x91, + 0xcf, 0xa3, 0x17, 0x7b, 0x62, 0x0e, 0xba, 0xd6, + 0x07, 0x6b, 0xdf, 0xb3, 0xaa, 0xc6, 0x72, 0x1e, + 0x40, 0x2c, 0x98, 0xf4, 0xed, 0x81, 0x35, 0x59, + 0x89, 0xe5, 0x51, 0x3d, 0x24, 0x48, 0xfc, 0x90, + 0xce, 0xa2, 0x16, 0x7a, 0x63, 0x0f, 0xbb, 0xd7, + }, + { + 0x00, 0x6d, 0xda, 0xb7, 0xa9, 0xc4, 0x73, 0x1e, + 0x4f, 0x22, 0x95, 0xf8, 0xe6, 0x8b, 0x3c, 0x51, + 0x9e, 0xf3, 0x44, 0x29, 0x37, 0x5a, 0xed, 0x80, + 0xd1, 0xbc, 0x0b, 0x66, 0x78, 0x15, 0xa2, 0xcf, + 0x21, 0x4c, 0xfb, 0x96, 0x88, 0xe5, 0x52, 0x3f, + 0x6e, 0x03, 0xb4, 0xd9, 0xc7, 0xaa, 0x1d, 0x70, + 0xbf, 0xd2, 0x65, 0x08, 0x16, 0x7b, 0xcc, 0xa1, + 0xf0, 0x9d, 0x2a, 0x47, 0x59, 0x34, 0x83, 0xee, + 0x42, 0x2f, 0x98, 0xf5, 0xeb, 0x86, 0x31, 0x5c, + 0x0d, 0x60, 0xd7, 0xba, 0xa4, 0xc9, 0x7e, 0x13, + 0xdc, 0xb1, 0x06, 0x6b, 0x75, 0x18, 0xaf, 0xc2, + 0x93, 0xfe, 0x49, 0x24, 0x3a, 0x57, 0xe0, 0x8d, + 0x63, 0x0e, 0xb9, 0xd4, 0xca, 0xa7, 0x10, 0x7d, + 0x2c, 0x41, 0xf6, 0x9b, 0x85, 0xe8, 0x5f, 0x32, + 0xfd, 0x90, 0x27, 0x4a, 0x54, 0x39, 0x8e, 0xe3, + 0xb2, 0xdf, 0x68, 0x05, 0x1b, 0x76, 0xc1, 0xac, + 0x84, 0xe9, 0x5e, 0x33, 0x2d, 0x40, 0xf7, 0x9a, + 0xcb, 0xa6, 0x11, 0x7c, 0x62, 0x0f, 0xb8, 0xd5, + 0x1a, 0x77, 0xc0, 0xad, 0xb3, 0xde, 0x69, 0x04, + 0x55, 0x38, 0x8f, 0xe2, 0xfc, 0x91, 0x26, 0x4b, + 0xa5, 0xc8, 0x7f, 0x12, 0x0c, 0x61, 0xd6, 0xbb, + 0xea, 0x87, 0x30, 0x5d, 0x43, 0x2e, 0x99, 0xf4, + 0x3b, 0x56, 0xe1, 0x8c, 0x92, 0xff, 0x48, 0x25, + 0x74, 0x19, 0xae, 0xc3, 0xdd, 0xb0, 0x07, 0x6a, + 0xc6, 0xab, 0x1c, 0x71, 0x6f, 0x02, 0xb5, 0xd8, + 0x89, 0xe4, 0x53, 0x3e, 0x20, 0x4d, 0xfa, 0x97, + 0x58, 0x35, 0x82, 0xef, 0xf1, 0x9c, 0x2b, 0x46, + 0x17, 0x7a, 0xcd, 0xa0, 0xbe, 0xd3, 0x64, 0x09, + 0xe7, 0x8a, 0x3d, 0x50, 0x4e, 0x23, 0x94, 0xf9, + 0xa8, 0xc5, 0x72, 0x1f, 0x01, 0x6c, 0xdb, 0xb6, + 0x79, 0x14, 0xa3, 0xce, 0xd0, 0xbd, 0x0a, 0x67, + 0x36, 0x5b, 0xec, 0x81, 0x9f, 0xf2, 0x45, 0x28, + }, + { + 0x00, 0x6e, 0xdc, 0xb2, 0xa5, 0xcb, 0x79, 0x17, + 0x57, 0x39, 0x8b, 0xe5, 0xf2, 0x9c, 0x2e, 0x40, + 0xae, 0xc0, 0x72, 0x1c, 0x0b, 0x65, 0xd7, 0xb9, + 0xf9, 0x97, 0x25, 0x4b, 0x5c, 0x32, 0x80, 0xee, + 0x41, 0x2f, 0x9d, 0xf3, 0xe4, 0x8a, 0x38, 0x56, + 0x16, 0x78, 0xca, 0xa4, 0xb3, 0xdd, 0x6f, 0x01, + 0xef, 0x81, 0x33, 0x5d, 0x4a, 0x24, 0x96, 0xf8, + 0xb8, 0xd6, 0x64, 0x0a, 0x1d, 0x73, 0xc1, 0xaf, + 0x82, 0xec, 0x5e, 0x30, 0x27, 0x49, 0xfb, 0x95, + 0xd5, 0xbb, 0x09, 0x67, 0x70, 0x1e, 0xac, 0xc2, + 0x2c, 0x42, 0xf0, 0x9e, 0x89, 0xe7, 0x55, 0x3b, + 0x7b, 0x15, 0xa7, 0xc9, 0xde, 0xb0, 0x02, 0x6c, + 0xc3, 0xad, 0x1f, 0x71, 0x66, 0x08, 0xba, 0xd4, + 0x94, 0xfa, 0x48, 0x26, 0x31, 0x5f, 0xed, 0x83, + 0x6d, 0x03, 0xb1, 0xdf, 0xc8, 0xa6, 0x14, 0x7a, + 0x3a, 0x54, 0xe6, 0x88, 0x9f, 0xf1, 0x43, 0x2d, + 0x19, 0x77, 0xc5, 0xab, 0xbc, 0xd2, 0x60, 0x0e, + 0x4e, 0x20, 0x92, 0xfc, 0xeb, 0x85, 0x37, 0x59, + 0xb7, 0xd9, 0x6b, 0x05, 0x12, 0x7c, 0xce, 0xa0, + 0xe0, 0x8e, 0x3c, 0x52, 0x45, 0x2b, 0x99, 0xf7, + 0x58, 0x36, 0x84, 0xea, 0xfd, 0x93, 0x21, 0x4f, + 0x0f, 0x61, 0xd3, 0xbd, 0xaa, 0xc4, 0x76, 0x18, + 0xf6, 0x98, 0x2a, 0x44, 0x53, 0x3d, 0x8f, 0xe1, + 0xa1, 0xcf, 0x7d, 0x13, 0x04, 0x6a, 0xd8, 0xb6, + 0x9b, 0xf5, 0x47, 0x29, 0x3e, 0x50, 0xe2, 0x8c, + 0xcc, 0xa2, 0x10, 0x7e, 0x69, 0x07, 0xb5, 0xdb, + 0x35, 0x5b, 0xe9, 0x87, 0x90, 0xfe, 0x4c, 0x22, + 0x62, 0x0c, 0xbe, 0xd0, 0xc7, 0xa9, 0x1b, 0x75, + 0xda, 0xb4, 0x06, 0x68, 0x7f, 0x11, 0xa3, 0xcd, + 0x8d, 0xe3, 0x51, 0x3f, 0x28, 0x46, 0xf4, 0x9a, + 0x74, 0x1a, 0xa8, 0xc6, 0xd1, 0xbf, 0x0d, 0x63, + 0x23, 0x4d, 0xff, 0x91, 0x86, 0xe8, 0x5a, 0x34, + }, + { + 0x00, 0x6f, 0xde, 0xb1, 0xa1, 0xce, 0x7f, 0x10, + 0x5f, 0x30, 0x81, 0xee, 0xfe, 0x91, 0x20, 0x4f, + 0xbe, 0xd1, 0x60, 0x0f, 0x1f, 0x70, 0xc1, 0xae, + 0xe1, 0x8e, 0x3f, 0x50, 0x40, 0x2f, 0x9e, 0xf1, + 0x61, 0x0e, 0xbf, 0xd0, 0xc0, 0xaf, 0x1e, 0x71, + 0x3e, 0x51, 0xe0, 0x8f, 0x9f, 0xf0, 0x41, 0x2e, + 0xdf, 0xb0, 0x01, 0x6e, 0x7e, 0x11, 0xa0, 0xcf, + 0x80, 0xef, 0x5e, 0x31, 0x21, 0x4e, 0xff, 0x90, + 0xc2, 0xad, 0x1c, 0x73, 0x63, 0x0c, 0xbd, 0xd2, + 0x9d, 0xf2, 0x43, 0x2c, 0x3c, 0x53, 0xe2, 0x8d, + 0x7c, 0x13, 0xa2, 0xcd, 0xdd, 0xb2, 0x03, 0x6c, + 0x23, 0x4c, 0xfd, 0x92, 0x82, 0xed, 0x5c, 0x33, + 0xa3, 0xcc, 0x7d, 0x12, 0x02, 0x6d, 0xdc, 0xb3, + 0xfc, 0x93, 0x22, 0x4d, 0x5d, 0x32, 0x83, 0xec, + 0x1d, 0x72, 0xc3, 0xac, 0xbc, 0xd3, 0x62, 0x0d, + 0x42, 0x2d, 0x9c, 0xf3, 0xe3, 0x8c, 0x3d, 0x52, + 0x99, 0xf6, 0x47, 0x28, 0x38, 0x57, 0xe6, 0x89, + 0xc6, 0xa9, 0x18, 0x77, 0x67, 0x08, 0xb9, 0xd6, + 0x27, 0x48, 0xf9, 0x96, 0x86, 0xe9, 0x58, 0x37, + 0x78, 0x17, 0xa6, 0xc9, 0xd9, 0xb6, 0x07, 0x68, + 0xf8, 0x97, 0x26, 0x49, 0x59, 0x36, 0x87, 0xe8, + 0xa7, 0xc8, 0x79, 0x16, 0x06, 0x69, 0xd8, 0xb7, + 0x46, 0x29, 0x98, 0xf7, 0xe7, 0x88, 0x39, 0x56, + 0x19, 0x76, 0xc7, 0xa8, 0xb8, 0xd7, 0x66, 0x09, + 0x5b, 0x34, 0x85, 0xea, 0xfa, 0x95, 0x24, 0x4b, + 0x04, 0x6b, 0xda, 0xb5, 0xa5, 0xca, 0x7b, 0x14, + 0xe5, 0x8a, 0x3b, 0x54, 0x44, 0x2b, 0x9a, 0xf5, + 0xba, 0xd5, 0x64, 0x0b, 0x1b, 0x74, 0xc5, 0xaa, + 0x3a, 0x55, 0xe4, 0x8b, 0x9b, 0xf4, 0x45, 0x2a, + 0x65, 0x0a, 0xbb, 0xd4, 0xc4, 0xab, 0x1a, 0x75, + 0x84, 0xeb, 0x5a, 0x35, 0x25, 0x4a, 0xfb, 0x94, + 0xdb, 0xb4, 0x05, 0x6a, 0x7a, 0x15, 0xa4, 0xcb, + }, + { + 0x00, 0x70, 0xe0, 0x90, 0xdd, 0xad, 0x3d, 0x4d, + 0xa7, 0xd7, 0x47, 0x37, 0x7a, 0x0a, 0x9a, 0xea, + 0x53, 0x23, 0xb3, 0xc3, 0x8e, 0xfe, 0x6e, 0x1e, + 0xf4, 0x84, 0x14, 0x64, 0x29, 0x59, 0xc9, 0xb9, + 0xa6, 0xd6, 0x46, 0x36, 0x7b, 0x0b, 0x9b, 0xeb, + 0x01, 0x71, 0xe1, 0x91, 0xdc, 0xac, 0x3c, 0x4c, + 0xf5, 0x85, 0x15, 0x65, 0x28, 0x58, 0xc8, 0xb8, + 0x52, 0x22, 0xb2, 0xc2, 0x8f, 0xff, 0x6f, 0x1f, + 0x51, 0x21, 0xb1, 0xc1, 0x8c, 0xfc, 0x6c, 0x1c, + 0xf6, 0x86, 0x16, 0x66, 0x2b, 0x5b, 0xcb, 0xbb, + 0x02, 0x72, 0xe2, 0x92, 0xdf, 0xaf, 0x3f, 0x4f, + 0xa5, 0xd5, 0x45, 0x35, 0x78, 0x08, 0x98, 0xe8, + 0xf7, 0x87, 0x17, 0x67, 0x2a, 0x5a, 0xca, 0xba, + 0x50, 0x20, 0xb0, 0xc0, 0x8d, 0xfd, 0x6d, 0x1d, + 0xa4, 0xd4, 0x44, 0x34, 0x79, 0x09, 0x99, 0xe9, + 0x03, 0x73, 0xe3, 0x93, 0xde, 0xae, 0x3e, 0x4e, + 0xa2, 0xd2, 0x42, 0x32, 0x7f, 0x0f, 0x9f, 0xef, + 0x05, 0x75, 0xe5, 0x95, 0xd8, 0xa8, 0x38, 0x48, + 0xf1, 0x81, 0x11, 0x61, 0x2c, 0x5c, 0xcc, 0xbc, + 0x56, 0x26, 0xb6, 0xc6, 0x8b, 0xfb, 0x6b, 0x1b, + 0x04, 0x74, 0xe4, 0x94, 0xd9, 0xa9, 0x39, 0x49, + 0xa3, 0xd3, 0x43, 0x33, 0x7e, 0x0e, 0x9e, 0xee, + 0x57, 0x27, 0xb7, 0xc7, 0x8a, 0xfa, 0x6a, 0x1a, + 0xf0, 0x80, 0x10, 0x60, 0x2d, 0x5d, 0xcd, 0xbd, + 0xf3, 0x83, 0x13, 0x63, 0x2e, 0x5e, 0xce, 0xbe, + 0x54, 0x24, 0xb4, 0xc4, 0x89, 0xf9, 0x69, 0x19, + 0xa0, 0xd0, 0x40, 0x30, 0x7d, 0x0d, 0x9d, 0xed, + 0x07, 0x77, 0xe7, 0x97, 0xda, 0xaa, 0x3a, 0x4a, + 0x55, 0x25, 0xb5, 0xc5, 0x88, 0xf8, 0x68, 0x18, + 0xf2, 0x82, 0x12, 0x62, 0x2f, 0x5f, 0xcf, 0xbf, + 0x06, 0x76, 0xe6, 0x96, 0xdb, 0xab, 0x3b, 0x4b, + 0xa1, 0xd1, 0x41, 0x31, 0x7c, 0x0c, 0x9c, 0xec, + }, + { + 0x00, 0x71, 0xe2, 0x93, 0xd9, 0xa8, 0x3b, 0x4a, + 0xaf, 0xde, 0x4d, 0x3c, 0x76, 0x07, 0x94, 0xe5, + 0x43, 0x32, 0xa1, 0xd0, 0x9a, 0xeb, 0x78, 0x09, + 0xec, 0x9d, 0x0e, 0x7f, 0x35, 0x44, 0xd7, 0xa6, + 0x86, 0xf7, 0x64, 0x15, 0x5f, 0x2e, 0xbd, 0xcc, + 0x29, 0x58, 0xcb, 0xba, 0xf0, 0x81, 0x12, 0x63, + 0xc5, 0xb4, 0x27, 0x56, 0x1c, 0x6d, 0xfe, 0x8f, + 0x6a, 0x1b, 0x88, 0xf9, 0xb3, 0xc2, 0x51, 0x20, + 0x11, 0x60, 0xf3, 0x82, 0xc8, 0xb9, 0x2a, 0x5b, + 0xbe, 0xcf, 0x5c, 0x2d, 0x67, 0x16, 0x85, 0xf4, + 0x52, 0x23, 0xb0, 0xc1, 0x8b, 0xfa, 0x69, 0x18, + 0xfd, 0x8c, 0x1f, 0x6e, 0x24, 0x55, 0xc6, 0xb7, + 0x97, 0xe6, 0x75, 0x04, 0x4e, 0x3f, 0xac, 0xdd, + 0x38, 0x49, 0xda, 0xab, 0xe1, 0x90, 0x03, 0x72, + 0xd4, 0xa5, 0x36, 0x47, 0x0d, 0x7c, 0xef, 0x9e, + 0x7b, 0x0a, 0x99, 0xe8, 0xa2, 0xd3, 0x40, 0x31, + 0x22, 0x53, 0xc0, 0xb1, 0xfb, 0x8a, 0x19, 0x68, + 0x8d, 0xfc, 0x6f, 0x1e, 0x54, 0x25, 0xb6, 0xc7, + 0x61, 0x10, 0x83, 0xf2, 0xb8, 0xc9, 0x5a, 0x2b, + 0xce, 0xbf, 0x2c, 0x5d, 0x17, 0x66, 0xf5, 0x84, + 0xa4, 0xd5, 0x46, 0x37, 0x7d, 0x0c, 0x9f, 0xee, + 0x0b, 0x7a, 0xe9, 0x98, 0xd2, 0xa3, 0x30, 0x41, + 0xe7, 0x96, 0x05, 0x74, 0x3e, 0x4f, 0xdc, 0xad, + 0x48, 0x39, 0xaa, 0xdb, 0x91, 0xe0, 0x73, 0x02, + 0x33, 0x42, 0xd1, 0xa0, 0xea, 0x9b, 0x08, 0x79, + 0x9c, 0xed, 0x7e, 0x0f, 0x45, 0x34, 0xa7, 0xd6, + 0x70, 0x01, 0x92, 0xe3, 0xa9, 0xd8, 0x4b, 0x3a, + 0xdf, 0xae, 0x3d, 0x4c, 0x06, 0x77, 0xe4, 0x95, + 0xb5, 0xc4, 0x57, 0x26, 0x6c, 0x1d, 0x8e, 0xff, + 0x1a, 0x6b, 0xf8, 0x89, 0xc3, 0xb2, 0x21, 0x50, + 0xf6, 0x87, 0x14, 0x65, 0x2f, 0x5e, 0xcd, 0xbc, + 0x59, 0x28, 0xbb, 0xca, 0x80, 0xf1, 0x62, 0x13, + }, + { + 0x00, 0x72, 0xe4, 0x96, 0xd5, 0xa7, 0x31, 0x43, + 0xb7, 0xc5, 0x53, 0x21, 0x62, 0x10, 0x86, 0xf4, + 0x73, 0x01, 0x97, 0xe5, 0xa6, 0xd4, 0x42, 0x30, + 0xc4, 0xb6, 0x20, 0x52, 0x11, 0x63, 0xf5, 0x87, + 0xe6, 0x94, 0x02, 0x70, 0x33, 0x41, 0xd7, 0xa5, + 0x51, 0x23, 0xb5, 0xc7, 0x84, 0xf6, 0x60, 0x12, + 0x95, 0xe7, 0x71, 0x03, 0x40, 0x32, 0xa4, 0xd6, + 0x22, 0x50, 0xc6, 0xb4, 0xf7, 0x85, 0x13, 0x61, + 0xd1, 0xa3, 0x35, 0x47, 0x04, 0x76, 0xe0, 0x92, + 0x66, 0x14, 0x82, 0xf0, 0xb3, 0xc1, 0x57, 0x25, + 0xa2, 0xd0, 0x46, 0x34, 0x77, 0x05, 0x93, 0xe1, + 0x15, 0x67, 0xf1, 0x83, 0xc0, 0xb2, 0x24, 0x56, + 0x37, 0x45, 0xd3, 0xa1, 0xe2, 0x90, 0x06, 0x74, + 0x80, 0xf2, 0x64, 0x16, 0x55, 0x27, 0xb1, 0xc3, + 0x44, 0x36, 0xa0, 0xd2, 0x91, 0xe3, 0x75, 0x07, + 0xf3, 0x81, 0x17, 0x65, 0x26, 0x54, 0xc2, 0xb0, + 0xbf, 0xcd, 0x5b, 0x29, 0x6a, 0x18, 0x8e, 0xfc, + 0x08, 0x7a, 0xec, 0x9e, 0xdd, 0xaf, 0x39, 0x4b, + 0xcc, 0xbe, 0x28, 0x5a, 0x19, 0x6b, 0xfd, 0x8f, + 0x7b, 0x09, 0x9f, 0xed, 0xae, 0xdc, 0x4a, 0x38, + 0x59, 0x2b, 0xbd, 0xcf, 0x8c, 0xfe, 0x68, 0x1a, + 0xee, 0x9c, 0x0a, 0x78, 0x3b, 0x49, 0xdf, 0xad, + 0x2a, 0x58, 0xce, 0xbc, 0xff, 0x8d, 0x1b, 0x69, + 0x9d, 0xef, 0x79, 0x0b, 0x48, 0x3a, 0xac, 0xde, + 0x6e, 0x1c, 0x8a, 0xf8, 0xbb, 0xc9, 0x5f, 0x2d, + 0xd9, 0xab, 0x3d, 0x4f, 0x0c, 0x7e, 0xe8, 0x9a, + 0x1d, 0x6f, 0xf9, 0x8b, 0xc8, 0xba, 0x2c, 0x5e, + 0xaa, 0xd8, 0x4e, 0x3c, 0x7f, 0x0d, 0x9b, 0xe9, + 0x88, 0xfa, 0x6c, 0x1e, 0x5d, 0x2f, 0xb9, 0xcb, + 0x3f, 0x4d, 0xdb, 0xa9, 0xea, 0x98, 0x0e, 0x7c, + 0xfb, 0x89, 0x1f, 0x6d, 0x2e, 0x5c, 0xca, 0xb8, + 0x4c, 0x3e, 0xa8, 0xda, 0x99, 0xeb, 0x7d, 0x0f, + }, + { + 0x00, 0x73, 0xe6, 0x95, 0xd1, 0xa2, 0x37, 0x44, + 0xbf, 0xcc, 0x59, 0x2a, 0x6e, 0x1d, 0x88, 0xfb, + 0x63, 0x10, 0x85, 0xf6, 0xb2, 0xc1, 0x54, 0x27, + 0xdc, 0xaf, 0x3a, 0x49, 0x0d, 0x7e, 0xeb, 0x98, + 0xc6, 0xb5, 0x20, 0x53, 0x17, 0x64, 0xf1, 0x82, + 0x79, 0x0a, 0x9f, 0xec, 0xa8, 0xdb, 0x4e, 0x3d, + 0xa5, 0xd6, 0x43, 0x30, 0x74, 0x07, 0x92, 0xe1, + 0x1a, 0x69, 0xfc, 0x8f, 0xcb, 0xb8, 0x2d, 0x5e, + 0x91, 0xe2, 0x77, 0x04, 0x40, 0x33, 0xa6, 0xd5, + 0x2e, 0x5d, 0xc8, 0xbb, 0xff, 0x8c, 0x19, 0x6a, + 0xf2, 0x81, 0x14, 0x67, 0x23, 0x50, 0xc5, 0xb6, + 0x4d, 0x3e, 0xab, 0xd8, 0x9c, 0xef, 0x7a, 0x09, + 0x57, 0x24, 0xb1, 0xc2, 0x86, 0xf5, 0x60, 0x13, + 0xe8, 0x9b, 0x0e, 0x7d, 0x39, 0x4a, 0xdf, 0xac, + 0x34, 0x47, 0xd2, 0xa1, 0xe5, 0x96, 0x03, 0x70, + 0x8b, 0xf8, 0x6d, 0x1e, 0x5a, 0x29, 0xbc, 0xcf, + 0x3f, 0x4c, 0xd9, 0xaa, 0xee, 0x9d, 0x08, 0x7b, + 0x80, 0xf3, 0x66, 0x15, 0x51, 0x22, 0xb7, 0xc4, + 0x5c, 0x2f, 0xba, 0xc9, 0x8d, 0xfe, 0x6b, 0x18, + 0xe3, 0x90, 0x05, 0x76, 0x32, 0x41, 0xd4, 0xa7, + 0xf9, 0x8a, 0x1f, 0x6c, 0x28, 0x5b, 0xce, 0xbd, + 0x46, 0x35, 0xa0, 0xd3, 0x97, 0xe4, 0x71, 0x02, + 0x9a, 0xe9, 0x7c, 0x0f, 0x4b, 0x38, 0xad, 0xde, + 0x25, 0x56, 0xc3, 0xb0, 0xf4, 0x87, 0x12, 0x61, + 0xae, 0xdd, 0x48, 0x3b, 0x7f, 0x0c, 0x99, 0xea, + 0x11, 0x62, 0xf7, 0x84, 0xc0, 0xb3, 0x26, 0x55, + 0xcd, 0xbe, 0x2b, 0x58, 0x1c, 0x6f, 0xfa, 0x89, + 0x72, 0x01, 0x94, 0xe7, 0xa3, 0xd0, 0x45, 0x36, + 0x68, 0x1b, 0x8e, 0xfd, 0xb9, 0xca, 0x5f, 0x2c, + 0xd7, 0xa4, 0x31, 0x42, 0x06, 0x75, 0xe0, 0x93, + 0x0b, 0x78, 0xed, 0x9e, 0xda, 0xa9, 0x3c, 0x4f, + 0xb4, 0xc7, 0x52, 0x21, 0x65, 0x16, 0x83, 0xf0, + }, + { + 0x00, 0x74, 0xe8, 0x9c, 0xcd, 0xb9, 0x25, 0x51, + 0x87, 0xf3, 0x6f, 0x1b, 0x4a, 0x3e, 0xa2, 0xd6, + 0x13, 0x67, 0xfb, 0x8f, 0xde, 0xaa, 0x36, 0x42, + 0x94, 0xe0, 0x7c, 0x08, 0x59, 0x2d, 0xb1, 0xc5, + 0x26, 0x52, 0xce, 0xba, 0xeb, 0x9f, 0x03, 0x77, + 0xa1, 0xd5, 0x49, 0x3d, 0x6c, 0x18, 0x84, 0xf0, + 0x35, 0x41, 0xdd, 0xa9, 0xf8, 0x8c, 0x10, 0x64, + 0xb2, 0xc6, 0x5a, 0x2e, 0x7f, 0x0b, 0x97, 0xe3, + 0x4c, 0x38, 0xa4, 0xd0, 0x81, 0xf5, 0x69, 0x1d, + 0xcb, 0xbf, 0x23, 0x57, 0x06, 0x72, 0xee, 0x9a, + 0x5f, 0x2b, 0xb7, 0xc3, 0x92, 0xe6, 0x7a, 0x0e, + 0xd8, 0xac, 0x30, 0x44, 0x15, 0x61, 0xfd, 0x89, + 0x6a, 0x1e, 0x82, 0xf6, 0xa7, 0xd3, 0x4f, 0x3b, + 0xed, 0x99, 0x05, 0x71, 0x20, 0x54, 0xc8, 0xbc, + 0x79, 0x0d, 0x91, 0xe5, 0xb4, 0xc0, 0x5c, 0x28, + 0xfe, 0x8a, 0x16, 0x62, 0x33, 0x47, 0xdb, 0xaf, + 0x98, 0xec, 0x70, 0x04, 0x55, 0x21, 0xbd, 0xc9, + 0x1f, 0x6b, 0xf7, 0x83, 0xd2, 0xa6, 0x3a, 0x4e, + 0x8b, 0xff, 0x63, 0x17, 0x46, 0x32, 0xae, 0xda, + 0x0c, 0x78, 0xe4, 0x90, 0xc1, 0xb5, 0x29, 0x5d, + 0xbe, 0xca, 0x56, 0x22, 0x73, 0x07, 0x9b, 0xef, + 0x39, 0x4d, 0xd1, 0xa5, 0xf4, 0x80, 0x1c, 0x68, + 0xad, 0xd9, 0x45, 0x31, 0x60, 0x14, 0x88, 0xfc, + 0x2a, 0x5e, 0xc2, 0xb6, 0xe7, 0x93, 0x0f, 0x7b, + 0xd4, 0xa0, 0x3c, 0x48, 0x19, 0x6d, 0xf1, 0x85, + 0x53, 0x27, 0xbb, 0xcf, 0x9e, 0xea, 0x76, 0x02, + 0xc7, 0xb3, 0x2f, 0x5b, 0x0a, 0x7e, 0xe2, 0x96, + 0x40, 0x34, 0xa8, 0xdc, 0x8d, 0xf9, 0x65, 0x11, + 0xf2, 0x86, 0x1a, 0x6e, 0x3f, 0x4b, 0xd7, 0xa3, + 0x75, 0x01, 0x9d, 0xe9, 0xb8, 0xcc, 0x50, 0x24, + 0xe1, 0x95, 0x09, 0x7d, 0x2c, 0x58, 0xc4, 0xb0, + 0x66, 0x12, 0x8e, 0xfa, 0xab, 0xdf, 0x43, 0x37, + }, + { + 0x00, 0x75, 0xea, 0x9f, 0xc9, 0xbc, 0x23, 0x56, + 0x8f, 0xfa, 0x65, 0x10, 0x46, 0x33, 0xac, 0xd9, + 0x03, 0x76, 0xe9, 0x9c, 0xca, 0xbf, 0x20, 0x55, + 0x8c, 0xf9, 0x66, 0x13, 0x45, 0x30, 0xaf, 0xda, + 0x06, 0x73, 0xec, 0x99, 0xcf, 0xba, 0x25, 0x50, + 0x89, 0xfc, 0x63, 0x16, 0x40, 0x35, 0xaa, 0xdf, + 0x05, 0x70, 0xef, 0x9a, 0xcc, 0xb9, 0x26, 0x53, + 0x8a, 0xff, 0x60, 0x15, 0x43, 0x36, 0xa9, 0xdc, + 0x0c, 0x79, 0xe6, 0x93, 0xc5, 0xb0, 0x2f, 0x5a, + 0x83, 0xf6, 0x69, 0x1c, 0x4a, 0x3f, 0xa0, 0xd5, + 0x0f, 0x7a, 0xe5, 0x90, 0xc6, 0xb3, 0x2c, 0x59, + 0x80, 0xf5, 0x6a, 0x1f, 0x49, 0x3c, 0xa3, 0xd6, + 0x0a, 0x7f, 0xe0, 0x95, 0xc3, 0xb6, 0x29, 0x5c, + 0x85, 0xf0, 0x6f, 0x1a, 0x4c, 0x39, 0xa6, 0xd3, + 0x09, 0x7c, 0xe3, 0x96, 0xc0, 0xb5, 0x2a, 0x5f, + 0x86, 0xf3, 0x6c, 0x19, 0x4f, 0x3a, 0xa5, 0xd0, + 0x18, 0x6d, 0xf2, 0x87, 0xd1, 0xa4, 0x3b, 0x4e, + 0x97, 0xe2, 0x7d, 0x08, 0x5e, 0x2b, 0xb4, 0xc1, + 0x1b, 0x6e, 0xf1, 0x84, 0xd2, 0xa7, 0x38, 0x4d, + 0x94, 0xe1, 0x7e, 0x0b, 0x5d, 0x28, 0xb7, 0xc2, + 0x1e, 0x6b, 0xf4, 0x81, 0xd7, 0xa2, 0x3d, 0x48, + 0x91, 0xe4, 0x7b, 0x0e, 0x58, 0x2d, 0xb2, 0xc7, + 0x1d, 0x68, 0xf7, 0x82, 0xd4, 0xa1, 0x3e, 0x4b, + 0x92, 0xe7, 0x78, 0x0d, 0x5b, 0x2e, 0xb1, 0xc4, + 0x14, 0x61, 0xfe, 0x8b, 0xdd, 0xa8, 0x37, 0x42, + 0x9b, 0xee, 0x71, 0x04, 0x52, 0x27, 0xb8, 0xcd, + 0x17, 0x62, 0xfd, 0x88, 0xde, 0xab, 0x34, 0x41, + 0x98, 0xed, 0x72, 0x07, 0x51, 0x24, 0xbb, 0xce, + 0x12, 0x67, 0xf8, 0x8d, 0xdb, 0xae, 0x31, 0x44, + 0x9d, 0xe8, 0x77, 0x02, 0x54, 0x21, 0xbe, 0xcb, + 0x11, 0x64, 0xfb, 0x8e, 0xd8, 0xad, 0x32, 0x47, + 0x9e, 0xeb, 0x74, 0x01, 0x57, 0x22, 0xbd, 0xc8, + }, + { + 0x00, 0x76, 0xec, 0x9a, 0xc5, 0xb3, 0x29, 0x5f, + 0x97, 0xe1, 0x7b, 0x0d, 0x52, 0x24, 0xbe, 0xc8, + 0x33, 0x45, 0xdf, 0xa9, 0xf6, 0x80, 0x1a, 0x6c, + 0xa4, 0xd2, 0x48, 0x3e, 0x61, 0x17, 0x8d, 0xfb, + 0x66, 0x10, 0x8a, 0xfc, 0xa3, 0xd5, 0x4f, 0x39, + 0xf1, 0x87, 0x1d, 0x6b, 0x34, 0x42, 0xd8, 0xae, + 0x55, 0x23, 0xb9, 0xcf, 0x90, 0xe6, 0x7c, 0x0a, + 0xc2, 0xb4, 0x2e, 0x58, 0x07, 0x71, 0xeb, 0x9d, + 0xcc, 0xba, 0x20, 0x56, 0x09, 0x7f, 0xe5, 0x93, + 0x5b, 0x2d, 0xb7, 0xc1, 0x9e, 0xe8, 0x72, 0x04, + 0xff, 0x89, 0x13, 0x65, 0x3a, 0x4c, 0xd6, 0xa0, + 0x68, 0x1e, 0x84, 0xf2, 0xad, 0xdb, 0x41, 0x37, + 0xaa, 0xdc, 0x46, 0x30, 0x6f, 0x19, 0x83, 0xf5, + 0x3d, 0x4b, 0xd1, 0xa7, 0xf8, 0x8e, 0x14, 0x62, + 0x99, 0xef, 0x75, 0x03, 0x5c, 0x2a, 0xb0, 0xc6, + 0x0e, 0x78, 0xe2, 0x94, 0xcb, 0xbd, 0x27, 0x51, + 0x85, 0xf3, 0x69, 0x1f, 0x40, 0x36, 0xac, 0xda, + 0x12, 0x64, 0xfe, 0x88, 0xd7, 0xa1, 0x3b, 0x4d, + 0xb6, 0xc0, 0x5a, 0x2c, 0x73, 0x05, 0x9f, 0xe9, + 0x21, 0x57, 0xcd, 0xbb, 0xe4, 0x92, 0x08, 0x7e, + 0xe3, 0x95, 0x0f, 0x79, 0x26, 0x50, 0xca, 0xbc, + 0x74, 0x02, 0x98, 0xee, 0xb1, 0xc7, 0x5d, 0x2b, + 0xd0, 0xa6, 0x3c, 0x4a, 0x15, 0x63, 0xf9, 0x8f, + 0x47, 0x31, 0xab, 0xdd, 0x82, 0xf4, 0x6e, 0x18, + 0x49, 0x3f, 0xa5, 0xd3, 0x8c, 0xfa, 0x60, 0x16, + 0xde, 0xa8, 0x32, 0x44, 0x1b, 0x6d, 0xf7, 0x81, + 0x7a, 0x0c, 0x96, 0xe0, 0xbf, 0xc9, 0x53, 0x25, + 0xed, 0x9b, 0x01, 0x77, 0x28, 0x5e, 0xc4, 0xb2, + 0x2f, 0x59, 0xc3, 0xb5, 0xea, 0x9c, 0x06, 0x70, + 0xb8, 0xce, 0x54, 0x22, 0x7d, 0x0b, 0x91, 0xe7, + 0x1c, 0x6a, 0xf0, 0x86, 0xd9, 0xaf, 0x35, 0x43, + 0x8b, 0xfd, 0x67, 0x11, 0x4e, 0x38, 0xa2, 0xd4, + }, + { + 0x00, 0x77, 0xee, 0x99, 0xc1, 0xb6, 0x2f, 0x58, + 0x9f, 0xe8, 0x71, 0x06, 0x5e, 0x29, 0xb0, 0xc7, + 0x23, 0x54, 0xcd, 0xba, 0xe2, 0x95, 0x0c, 0x7b, + 0xbc, 0xcb, 0x52, 0x25, 0x7d, 0x0a, 0x93, 0xe4, + 0x46, 0x31, 0xa8, 0xdf, 0x87, 0xf0, 0x69, 0x1e, + 0xd9, 0xae, 0x37, 0x40, 0x18, 0x6f, 0xf6, 0x81, + 0x65, 0x12, 0x8b, 0xfc, 0xa4, 0xd3, 0x4a, 0x3d, + 0xfa, 0x8d, 0x14, 0x63, 0x3b, 0x4c, 0xd5, 0xa2, + 0x8c, 0xfb, 0x62, 0x15, 0x4d, 0x3a, 0xa3, 0xd4, + 0x13, 0x64, 0xfd, 0x8a, 0xd2, 0xa5, 0x3c, 0x4b, + 0xaf, 0xd8, 0x41, 0x36, 0x6e, 0x19, 0x80, 0xf7, + 0x30, 0x47, 0xde, 0xa9, 0xf1, 0x86, 0x1f, 0x68, + 0xca, 0xbd, 0x24, 0x53, 0x0b, 0x7c, 0xe5, 0x92, + 0x55, 0x22, 0xbb, 0xcc, 0x94, 0xe3, 0x7a, 0x0d, + 0xe9, 0x9e, 0x07, 0x70, 0x28, 0x5f, 0xc6, 0xb1, + 0x76, 0x01, 0x98, 0xef, 0xb7, 0xc0, 0x59, 0x2e, + 0x05, 0x72, 0xeb, 0x9c, 0xc4, 0xb3, 0x2a, 0x5d, + 0x9a, 0xed, 0x74, 0x03, 0x5b, 0x2c, 0xb5, 0xc2, + 0x26, 0x51, 0xc8, 0xbf, 0xe7, 0x90, 0x09, 0x7e, + 0xb9, 0xce, 0x57, 0x20, 0x78, 0x0f, 0x96, 0xe1, + 0x43, 0x34, 0xad, 0xda, 0x82, 0xf5, 0x6c, 0x1b, + 0xdc, 0xab, 0x32, 0x45, 0x1d, 0x6a, 0xf3, 0x84, + 0x60, 0x17, 0x8e, 0xf9, 0xa1, 0xd6, 0x4f, 0x38, + 0xff, 0x88, 0x11, 0x66, 0x3e, 0x49, 0xd0, 0xa7, + 0x89, 0xfe, 0x67, 0x10, 0x48, 0x3f, 0xa6, 0xd1, + 0x16, 0x61, 0xf8, 0x8f, 0xd7, 0xa0, 0x39, 0x4e, + 0xaa, 0xdd, 0x44, 0x33, 0x6b, 0x1c, 0x85, 0xf2, + 0x35, 0x42, 0xdb, 0xac, 0xf4, 0x83, 0x1a, 0x6d, + 0xcf, 0xb8, 0x21, 0x56, 0x0e, 0x79, 0xe0, 0x97, + 0x50, 0x27, 0xbe, 0xc9, 0x91, 0xe6, 0x7f, 0x08, + 0xec, 0x9b, 0x02, 0x75, 0x2d, 0x5a, 0xc3, 0xb4, + 0x73, 0x04, 0x9d, 0xea, 0xb2, 0xc5, 0x5c, 0x2b, + }, + { + 0x00, 0x78, 0xf0, 0x88, 0xfd, 0x85, 0x0d, 0x75, + 0xe7, 0x9f, 0x17, 0x6f, 0x1a, 0x62, 0xea, 0x92, + 0xd3, 0xab, 0x23, 0x5b, 0x2e, 0x56, 0xde, 0xa6, + 0x34, 0x4c, 0xc4, 0xbc, 0xc9, 0xb1, 0x39, 0x41, + 0xbb, 0xc3, 0x4b, 0x33, 0x46, 0x3e, 0xb6, 0xce, + 0x5c, 0x24, 0xac, 0xd4, 0xa1, 0xd9, 0x51, 0x29, + 0x68, 0x10, 0x98, 0xe0, 0x95, 0xed, 0x65, 0x1d, + 0x8f, 0xf7, 0x7f, 0x07, 0x72, 0x0a, 0x82, 0xfa, + 0x6b, 0x13, 0x9b, 0xe3, 0x96, 0xee, 0x66, 0x1e, + 0x8c, 0xf4, 0x7c, 0x04, 0x71, 0x09, 0x81, 0xf9, + 0xb8, 0xc0, 0x48, 0x30, 0x45, 0x3d, 0xb5, 0xcd, + 0x5f, 0x27, 0xaf, 0xd7, 0xa2, 0xda, 0x52, 0x2a, + 0xd0, 0xa8, 0x20, 0x58, 0x2d, 0x55, 0xdd, 0xa5, + 0x37, 0x4f, 0xc7, 0xbf, 0xca, 0xb2, 0x3a, 0x42, + 0x03, 0x7b, 0xf3, 0x8b, 0xfe, 0x86, 0x0e, 0x76, + 0xe4, 0x9c, 0x14, 0x6c, 0x19, 0x61, 0xe9, 0x91, + 0xd6, 0xae, 0x26, 0x5e, 0x2b, 0x53, 0xdb, 0xa3, + 0x31, 0x49, 0xc1, 0xb9, 0xcc, 0xb4, 0x3c, 0x44, + 0x05, 0x7d, 0xf5, 0x8d, 0xf8, 0x80, 0x08, 0x70, + 0xe2, 0x9a, 0x12, 0x6a, 0x1f, 0x67, 0xef, 0x97, + 0x6d, 0x15, 0x9d, 0xe5, 0x90, 0xe8, 0x60, 0x18, + 0x8a, 0xf2, 0x7a, 0x02, 0x77, 0x0f, 0x87, 0xff, + 0xbe, 0xc6, 0x4e, 0x36, 0x43, 0x3b, 0xb3, 0xcb, + 0x59, 0x21, 0xa9, 0xd1, 0xa4, 0xdc, 0x54, 0x2c, + 0xbd, 0xc5, 0x4d, 0x35, 0x40, 0x38, 0xb0, 0xc8, + 0x5a, 0x22, 0xaa, 0xd2, 0xa7, 0xdf, 0x57, 0x2f, + 0x6e, 0x16, 0x9e, 0xe6, 0x93, 0xeb, 0x63, 0x1b, + 0x89, 0xf1, 0x79, 0x01, 0x74, 0x0c, 0x84, 0xfc, + 0x06, 0x7e, 0xf6, 0x8e, 0xfb, 0x83, 0x0b, 0x73, + 0xe1, 0x99, 0x11, 0x69, 0x1c, 0x64, 0xec, 0x94, + 0xd5, 0xad, 0x25, 0x5d, 0x28, 0x50, 0xd8, 0xa0, + 0x32, 0x4a, 0xc2, 0xba, 0xcf, 0xb7, 0x3f, 0x47, + }, + { + 0x00, 0x79, 0xf2, 0x8b, 0xf9, 0x80, 0x0b, 0x72, + 0xef, 0x96, 0x1d, 0x64, 0x16, 0x6f, 0xe4, 0x9d, + 0xc3, 0xba, 0x31, 0x48, 0x3a, 0x43, 0xc8, 0xb1, + 0x2c, 0x55, 0xde, 0xa7, 0xd5, 0xac, 0x27, 0x5e, + 0x9b, 0xe2, 0x69, 0x10, 0x62, 0x1b, 0x90, 0xe9, + 0x74, 0x0d, 0x86, 0xff, 0x8d, 0xf4, 0x7f, 0x06, + 0x58, 0x21, 0xaa, 0xd3, 0xa1, 0xd8, 0x53, 0x2a, + 0xb7, 0xce, 0x45, 0x3c, 0x4e, 0x37, 0xbc, 0xc5, + 0x2b, 0x52, 0xd9, 0xa0, 0xd2, 0xab, 0x20, 0x59, + 0xc4, 0xbd, 0x36, 0x4f, 0x3d, 0x44, 0xcf, 0xb6, + 0xe8, 0x91, 0x1a, 0x63, 0x11, 0x68, 0xe3, 0x9a, + 0x07, 0x7e, 0xf5, 0x8c, 0xfe, 0x87, 0x0c, 0x75, + 0xb0, 0xc9, 0x42, 0x3b, 0x49, 0x30, 0xbb, 0xc2, + 0x5f, 0x26, 0xad, 0xd4, 0xa6, 0xdf, 0x54, 0x2d, + 0x73, 0x0a, 0x81, 0xf8, 0x8a, 0xf3, 0x78, 0x01, + 0x9c, 0xe5, 0x6e, 0x17, 0x65, 0x1c, 0x97, 0xee, + 0x56, 0x2f, 0xa4, 0xdd, 0xaf, 0xd6, 0x5d, 0x24, + 0xb9, 0xc0, 0x4b, 0x32, 0x40, 0x39, 0xb2, 0xcb, + 0x95, 0xec, 0x67, 0x1e, 0x6c, 0x15, 0x9e, 0xe7, + 0x7a, 0x03, 0x88, 0xf1, 0x83, 0xfa, 0x71, 0x08, + 0xcd, 0xb4, 0x3f, 0x46, 0x34, 0x4d, 0xc6, 0xbf, + 0x22, 0x5b, 0xd0, 0xa9, 0xdb, 0xa2, 0x29, 0x50, + 0x0e, 0x77, 0xfc, 0x85, 0xf7, 0x8e, 0x05, 0x7c, + 0xe1, 0x98, 0x13, 0x6a, 0x18, 0x61, 0xea, 0x93, + 0x7d, 0x04, 0x8f, 0xf6, 0x84, 0xfd, 0x76, 0x0f, + 0x92, 0xeb, 0x60, 0x19, 0x6b, 0x12, 0x99, 0xe0, + 0xbe, 0xc7, 0x4c, 0x35, 0x47, 0x3e, 0xb5, 0xcc, + 0x51, 0x28, 0xa3, 0xda, 0xa8, 0xd1, 0x5a, 0x23, + 0xe6, 0x9f, 0x14, 0x6d, 0x1f, 0x66, 0xed, 0x94, + 0x09, 0x70, 0xfb, 0x82, 0xf0, 0x89, 0x02, 0x7b, + 0x25, 0x5c, 0xd7, 0xae, 0xdc, 0xa5, 0x2e, 0x57, + 0xca, 0xb3, 0x38, 0x41, 0x33, 0x4a, 0xc1, 0xb8, + }, + { + 0x00, 0x7a, 0xf4, 0x8e, 0xf5, 0x8f, 0x01, 0x7b, + 0xf7, 0x8d, 0x03, 0x79, 0x02, 0x78, 0xf6, 0x8c, + 0xf3, 0x89, 0x07, 0x7d, 0x06, 0x7c, 0xf2, 0x88, + 0x04, 0x7e, 0xf0, 0x8a, 0xf1, 0x8b, 0x05, 0x7f, + 0xfb, 0x81, 0x0f, 0x75, 0x0e, 0x74, 0xfa, 0x80, + 0x0c, 0x76, 0xf8, 0x82, 0xf9, 0x83, 0x0d, 0x77, + 0x08, 0x72, 0xfc, 0x86, 0xfd, 0x87, 0x09, 0x73, + 0xff, 0x85, 0x0b, 0x71, 0x0a, 0x70, 0xfe, 0x84, + 0xeb, 0x91, 0x1f, 0x65, 0x1e, 0x64, 0xea, 0x90, + 0x1c, 0x66, 0xe8, 0x92, 0xe9, 0x93, 0x1d, 0x67, + 0x18, 0x62, 0xec, 0x96, 0xed, 0x97, 0x19, 0x63, + 0xef, 0x95, 0x1b, 0x61, 0x1a, 0x60, 0xee, 0x94, + 0x10, 0x6a, 0xe4, 0x9e, 0xe5, 0x9f, 0x11, 0x6b, + 0xe7, 0x9d, 0x13, 0x69, 0x12, 0x68, 0xe6, 0x9c, + 0xe3, 0x99, 0x17, 0x6d, 0x16, 0x6c, 0xe2, 0x98, + 0x14, 0x6e, 0xe0, 0x9a, 0xe1, 0x9b, 0x15, 0x6f, + 0xcb, 0xb1, 0x3f, 0x45, 0x3e, 0x44, 0xca, 0xb0, + 0x3c, 0x46, 0xc8, 0xb2, 0xc9, 0xb3, 0x3d, 0x47, + 0x38, 0x42, 0xcc, 0xb6, 0xcd, 0xb7, 0x39, 0x43, + 0xcf, 0xb5, 0x3b, 0x41, 0x3a, 0x40, 0xce, 0xb4, + 0x30, 0x4a, 0xc4, 0xbe, 0xc5, 0xbf, 0x31, 0x4b, + 0xc7, 0xbd, 0x33, 0x49, 0x32, 0x48, 0xc6, 0xbc, + 0xc3, 0xb9, 0x37, 0x4d, 0x36, 0x4c, 0xc2, 0xb8, + 0x34, 0x4e, 0xc0, 0xba, 0xc1, 0xbb, 0x35, 0x4f, + 0x20, 0x5a, 0xd4, 0xae, 0xd5, 0xaf, 0x21, 0x5b, + 0xd7, 0xad, 0x23, 0x59, 0x22, 0x58, 0xd6, 0xac, + 0xd3, 0xa9, 0x27, 0x5d, 0x26, 0x5c, 0xd2, 0xa8, + 0x24, 0x5e, 0xd0, 0xaa, 0xd1, 0xab, 0x25, 0x5f, + 0xdb, 0xa1, 0x2f, 0x55, 0x2e, 0x54, 0xda, 0xa0, + 0x2c, 0x56, 0xd8, 0xa2, 0xd9, 0xa3, 0x2d, 0x57, + 0x28, 0x52, 0xdc, 0xa6, 0xdd, 0xa7, 0x29, 0x53, + 0xdf, 0xa5, 0x2b, 0x51, 0x2a, 0x50, 0xde, 0xa4, + }, + { + 0x00, 0x7b, 0xf6, 0x8d, 0xf1, 0x8a, 0x07, 0x7c, + 0xff, 0x84, 0x09, 0x72, 0x0e, 0x75, 0xf8, 0x83, + 0xe3, 0x98, 0x15, 0x6e, 0x12, 0x69, 0xe4, 0x9f, + 0x1c, 0x67, 0xea, 0x91, 0xed, 0x96, 0x1b, 0x60, + 0xdb, 0xa0, 0x2d, 0x56, 0x2a, 0x51, 0xdc, 0xa7, + 0x24, 0x5f, 0xd2, 0xa9, 0xd5, 0xae, 0x23, 0x58, + 0x38, 0x43, 0xce, 0xb5, 0xc9, 0xb2, 0x3f, 0x44, + 0xc7, 0xbc, 0x31, 0x4a, 0x36, 0x4d, 0xc0, 0xbb, + 0xab, 0xd0, 0x5d, 0x26, 0x5a, 0x21, 0xac, 0xd7, + 0x54, 0x2f, 0xa2, 0xd9, 0xa5, 0xde, 0x53, 0x28, + 0x48, 0x33, 0xbe, 0xc5, 0xb9, 0xc2, 0x4f, 0x34, + 0xb7, 0xcc, 0x41, 0x3a, 0x46, 0x3d, 0xb0, 0xcb, + 0x70, 0x0b, 0x86, 0xfd, 0x81, 0xfa, 0x77, 0x0c, + 0x8f, 0xf4, 0x79, 0x02, 0x7e, 0x05, 0x88, 0xf3, + 0x93, 0xe8, 0x65, 0x1e, 0x62, 0x19, 0x94, 0xef, + 0x6c, 0x17, 0x9a, 0xe1, 0x9d, 0xe6, 0x6b, 0x10, + 0x4b, 0x30, 0xbd, 0xc6, 0xba, 0xc1, 0x4c, 0x37, + 0xb4, 0xcf, 0x42, 0x39, 0x45, 0x3e, 0xb3, 0xc8, + 0xa8, 0xd3, 0x5e, 0x25, 0x59, 0x22, 0xaf, 0xd4, + 0x57, 0x2c, 0xa1, 0xda, 0xa6, 0xdd, 0x50, 0x2b, + 0x90, 0xeb, 0x66, 0x1d, 0x61, 0x1a, 0x97, 0xec, + 0x6f, 0x14, 0x99, 0xe2, 0x9e, 0xe5, 0x68, 0x13, + 0x73, 0x08, 0x85, 0xfe, 0x82, 0xf9, 0x74, 0x0f, + 0x8c, 0xf7, 0x7a, 0x01, 0x7d, 0x06, 0x8b, 0xf0, + 0xe0, 0x9b, 0x16, 0x6d, 0x11, 0x6a, 0xe7, 0x9c, + 0x1f, 0x64, 0xe9, 0x92, 0xee, 0x95, 0x18, 0x63, + 0x03, 0x78, 0xf5, 0x8e, 0xf2, 0x89, 0x04, 0x7f, + 0xfc, 0x87, 0x0a, 0x71, 0x0d, 0x76, 0xfb, 0x80, + 0x3b, 0x40, 0xcd, 0xb6, 0xca, 0xb1, 0x3c, 0x47, + 0xc4, 0xbf, 0x32, 0x49, 0x35, 0x4e, 0xc3, 0xb8, + 0xd8, 0xa3, 0x2e, 0x55, 0x29, 0x52, 0xdf, 0xa4, + 0x27, 0x5c, 0xd1, 0xaa, 0xd6, 0xad, 0x20, 0x5b, + }, + { + 0x00, 0x7c, 0xf8, 0x84, 0xed, 0x91, 0x15, 0x69, + 0xc7, 0xbb, 0x3f, 0x43, 0x2a, 0x56, 0xd2, 0xae, + 0x93, 0xef, 0x6b, 0x17, 0x7e, 0x02, 0x86, 0xfa, + 0x54, 0x28, 0xac, 0xd0, 0xb9, 0xc5, 0x41, 0x3d, + 0x3b, 0x47, 0xc3, 0xbf, 0xd6, 0xaa, 0x2e, 0x52, + 0xfc, 0x80, 0x04, 0x78, 0x11, 0x6d, 0xe9, 0x95, + 0xa8, 0xd4, 0x50, 0x2c, 0x45, 0x39, 0xbd, 0xc1, + 0x6f, 0x13, 0x97, 0xeb, 0x82, 0xfe, 0x7a, 0x06, + 0x76, 0x0a, 0x8e, 0xf2, 0x9b, 0xe7, 0x63, 0x1f, + 0xb1, 0xcd, 0x49, 0x35, 0x5c, 0x20, 0xa4, 0xd8, + 0xe5, 0x99, 0x1d, 0x61, 0x08, 0x74, 0xf0, 0x8c, + 0x22, 0x5e, 0xda, 0xa6, 0xcf, 0xb3, 0x37, 0x4b, + 0x4d, 0x31, 0xb5, 0xc9, 0xa0, 0xdc, 0x58, 0x24, + 0x8a, 0xf6, 0x72, 0x0e, 0x67, 0x1b, 0x9f, 0xe3, + 0xde, 0xa2, 0x26, 0x5a, 0x33, 0x4f, 0xcb, 0xb7, + 0x19, 0x65, 0xe1, 0x9d, 0xf4, 0x88, 0x0c, 0x70, + 0xec, 0x90, 0x14, 0x68, 0x01, 0x7d, 0xf9, 0x85, + 0x2b, 0x57, 0xd3, 0xaf, 0xc6, 0xba, 0x3e, 0x42, + 0x7f, 0x03, 0x87, 0xfb, 0x92, 0xee, 0x6a, 0x16, + 0xb8, 0xc4, 0x40, 0x3c, 0x55, 0x29, 0xad, 0xd1, + 0xd7, 0xab, 0x2f, 0x53, 0x3a, 0x46, 0xc2, 0xbe, + 0x10, 0x6c, 0xe8, 0x94, 0xfd, 0x81, 0x05, 0x79, + 0x44, 0x38, 0xbc, 0xc0, 0xa9, 0xd5, 0x51, 0x2d, + 0x83, 0xff, 0x7b, 0x07, 0x6e, 0x12, 0x96, 0xea, + 0x9a, 0xe6, 0x62, 0x1e, 0x77, 0x0b, 0x8f, 0xf3, + 0x5d, 0x21, 0xa5, 0xd9, 0xb0, 0xcc, 0x48, 0x34, + 0x09, 0x75, 0xf1, 0x8d, 0xe4, 0x98, 0x1c, 0x60, + 0xce, 0xb2, 0x36, 0x4a, 0x23, 0x5f, 0xdb, 0xa7, + 0xa1, 0xdd, 0x59, 0x25, 0x4c, 0x30, 0xb4, 0xc8, + 0x66, 0x1a, 0x9e, 0xe2, 0x8b, 0xf7, 0x73, 0x0f, + 0x32, 0x4e, 0xca, 0xb6, 0xdf, 0xa3, 0x27, 0x5b, + 0xf5, 0x89, 0x0d, 0x71, 0x18, 0x64, 0xe0, 0x9c, + }, + { + 0x00, 0x7d, 0xfa, 0x87, 0xe9, 0x94, 0x13, 0x6e, + 0xcf, 0xb2, 0x35, 0x48, 0x26, 0x5b, 0xdc, 0xa1, + 0x83, 0xfe, 0x79, 0x04, 0x6a, 0x17, 0x90, 0xed, + 0x4c, 0x31, 0xb6, 0xcb, 0xa5, 0xd8, 0x5f, 0x22, + 0x1b, 0x66, 0xe1, 0x9c, 0xf2, 0x8f, 0x08, 0x75, + 0xd4, 0xa9, 0x2e, 0x53, 0x3d, 0x40, 0xc7, 0xba, + 0x98, 0xe5, 0x62, 0x1f, 0x71, 0x0c, 0x8b, 0xf6, + 0x57, 0x2a, 0xad, 0xd0, 0xbe, 0xc3, 0x44, 0x39, + 0x36, 0x4b, 0xcc, 0xb1, 0xdf, 0xa2, 0x25, 0x58, + 0xf9, 0x84, 0x03, 0x7e, 0x10, 0x6d, 0xea, 0x97, + 0xb5, 0xc8, 0x4f, 0x32, 0x5c, 0x21, 0xa6, 0xdb, + 0x7a, 0x07, 0x80, 0xfd, 0x93, 0xee, 0x69, 0x14, + 0x2d, 0x50, 0xd7, 0xaa, 0xc4, 0xb9, 0x3e, 0x43, + 0xe2, 0x9f, 0x18, 0x65, 0x0b, 0x76, 0xf1, 0x8c, + 0xae, 0xd3, 0x54, 0x29, 0x47, 0x3a, 0xbd, 0xc0, + 0x61, 0x1c, 0x9b, 0xe6, 0x88, 0xf5, 0x72, 0x0f, + 0x6c, 0x11, 0x96, 0xeb, 0x85, 0xf8, 0x7f, 0x02, + 0xa3, 0xde, 0x59, 0x24, 0x4a, 0x37, 0xb0, 0xcd, + 0xef, 0x92, 0x15, 0x68, 0x06, 0x7b, 0xfc, 0x81, + 0x20, 0x5d, 0xda, 0xa7, 0xc9, 0xb4, 0x33, 0x4e, + 0x77, 0x0a, 0x8d, 0xf0, 0x9e, 0xe3, 0x64, 0x19, + 0xb8, 0xc5, 0x42, 0x3f, 0x51, 0x2c, 0xab, 0xd6, + 0xf4, 0x89, 0x0e, 0x73, 0x1d, 0x60, 0xe7, 0x9a, + 0x3b, 0x46, 0xc1, 0xbc, 0xd2, 0xaf, 0x28, 0x55, + 0x5a, 0x27, 0xa0, 0xdd, 0xb3, 0xce, 0x49, 0x34, + 0x95, 0xe8, 0x6f, 0x12, 0x7c, 0x01, 0x86, 0xfb, + 0xd9, 0xa4, 0x23, 0x5e, 0x30, 0x4d, 0xca, 0xb7, + 0x16, 0x6b, 0xec, 0x91, 0xff, 0x82, 0x05, 0x78, + 0x41, 0x3c, 0xbb, 0xc6, 0xa8, 0xd5, 0x52, 0x2f, + 0x8e, 0xf3, 0x74, 0x09, 0x67, 0x1a, 0x9d, 0xe0, + 0xc2, 0xbf, 0x38, 0x45, 0x2b, 0x56, 0xd1, 0xac, + 0x0d, 0x70, 0xf7, 0x8a, 0xe4, 0x99, 0x1e, 0x63, + }, + { + 0x00, 0x7e, 0xfc, 0x82, 0xe5, 0x9b, 0x19, 0x67, + 0xd7, 0xa9, 0x2b, 0x55, 0x32, 0x4c, 0xce, 0xb0, + 0xb3, 0xcd, 0x4f, 0x31, 0x56, 0x28, 0xaa, 0xd4, + 0x64, 0x1a, 0x98, 0xe6, 0x81, 0xff, 0x7d, 0x03, + 0x7b, 0x05, 0x87, 0xf9, 0x9e, 0xe0, 0x62, 0x1c, + 0xac, 0xd2, 0x50, 0x2e, 0x49, 0x37, 0xb5, 0xcb, + 0xc8, 0xb6, 0x34, 0x4a, 0x2d, 0x53, 0xd1, 0xaf, + 0x1f, 0x61, 0xe3, 0x9d, 0xfa, 0x84, 0x06, 0x78, + 0xf6, 0x88, 0x0a, 0x74, 0x13, 0x6d, 0xef, 0x91, + 0x21, 0x5f, 0xdd, 0xa3, 0xc4, 0xba, 0x38, 0x46, + 0x45, 0x3b, 0xb9, 0xc7, 0xa0, 0xde, 0x5c, 0x22, + 0x92, 0xec, 0x6e, 0x10, 0x77, 0x09, 0x8b, 0xf5, + 0x8d, 0xf3, 0x71, 0x0f, 0x68, 0x16, 0x94, 0xea, + 0x5a, 0x24, 0xa6, 0xd8, 0xbf, 0xc1, 0x43, 0x3d, + 0x3e, 0x40, 0xc2, 0xbc, 0xdb, 0xa5, 0x27, 0x59, + 0xe9, 0x97, 0x15, 0x6b, 0x0c, 0x72, 0xf0, 0x8e, + 0xf1, 0x8f, 0x0d, 0x73, 0x14, 0x6a, 0xe8, 0x96, + 0x26, 0x58, 0xda, 0xa4, 0xc3, 0xbd, 0x3f, 0x41, + 0x42, 0x3c, 0xbe, 0xc0, 0xa7, 0xd9, 0x5b, 0x25, + 0x95, 0xeb, 0x69, 0x17, 0x70, 0x0e, 0x8c, 0xf2, + 0x8a, 0xf4, 0x76, 0x08, 0x6f, 0x11, 0x93, 0xed, + 0x5d, 0x23, 0xa1, 0xdf, 0xb8, 0xc6, 0x44, 0x3a, + 0x39, 0x47, 0xc5, 0xbb, 0xdc, 0xa2, 0x20, 0x5e, + 0xee, 0x90, 0x12, 0x6c, 0x0b, 0x75, 0xf7, 0x89, + 0x07, 0x79, 0xfb, 0x85, 0xe2, 0x9c, 0x1e, 0x60, + 0xd0, 0xae, 0x2c, 0x52, 0x35, 0x4b, 0xc9, 0xb7, + 0xb4, 0xca, 0x48, 0x36, 0x51, 0x2f, 0xad, 0xd3, + 0x63, 0x1d, 0x9f, 0xe1, 0x86, 0xf8, 0x7a, 0x04, + 0x7c, 0x02, 0x80, 0xfe, 0x99, 0xe7, 0x65, 0x1b, + 0xab, 0xd5, 0x57, 0x29, 0x4e, 0x30, 0xb2, 0xcc, + 0xcf, 0xb1, 0x33, 0x4d, 0x2a, 0x54, 0xd6, 0xa8, + 0x18, 0x66, 0xe4, 0x9a, 0xfd, 0x83, 0x01, 0x7f, + }, + { + 0x00, 0x7f, 0xfe, 0x81, 0xe1, 0x9e, 0x1f, 0x60, + 0xdf, 0xa0, 0x21, 0x5e, 0x3e, 0x41, 0xc0, 0xbf, + 0xa3, 0xdc, 0x5d, 0x22, 0x42, 0x3d, 0xbc, 0xc3, + 0x7c, 0x03, 0x82, 0xfd, 0x9d, 0xe2, 0x63, 0x1c, + 0x5b, 0x24, 0xa5, 0xda, 0xba, 0xc5, 0x44, 0x3b, + 0x84, 0xfb, 0x7a, 0x05, 0x65, 0x1a, 0x9b, 0xe4, + 0xf8, 0x87, 0x06, 0x79, 0x19, 0x66, 0xe7, 0x98, + 0x27, 0x58, 0xd9, 0xa6, 0xc6, 0xb9, 0x38, 0x47, + 0xb6, 0xc9, 0x48, 0x37, 0x57, 0x28, 0xa9, 0xd6, + 0x69, 0x16, 0x97, 0xe8, 0x88, 0xf7, 0x76, 0x09, + 0x15, 0x6a, 0xeb, 0x94, 0xf4, 0x8b, 0x0a, 0x75, + 0xca, 0xb5, 0x34, 0x4b, 0x2b, 0x54, 0xd5, 0xaa, + 0xed, 0x92, 0x13, 0x6c, 0x0c, 0x73, 0xf2, 0x8d, + 0x32, 0x4d, 0xcc, 0xb3, 0xd3, 0xac, 0x2d, 0x52, + 0x4e, 0x31, 0xb0, 0xcf, 0xaf, 0xd0, 0x51, 0x2e, + 0x91, 0xee, 0x6f, 0x10, 0x70, 0x0f, 0x8e, 0xf1, + 0x71, 0x0e, 0x8f, 0xf0, 0x90, 0xef, 0x6e, 0x11, + 0xae, 0xd1, 0x50, 0x2f, 0x4f, 0x30, 0xb1, 0xce, + 0xd2, 0xad, 0x2c, 0x53, 0x33, 0x4c, 0xcd, 0xb2, + 0x0d, 0x72, 0xf3, 0x8c, 0xec, 0x93, 0x12, 0x6d, + 0x2a, 0x55, 0xd4, 0xab, 0xcb, 0xb4, 0x35, 0x4a, + 0xf5, 0x8a, 0x0b, 0x74, 0x14, 0x6b, 0xea, 0x95, + 0x89, 0xf6, 0x77, 0x08, 0x68, 0x17, 0x96, 0xe9, + 0x56, 0x29, 0xa8, 0xd7, 0xb7, 0xc8, 0x49, 0x36, + 0xc7, 0xb8, 0x39, 0x46, 0x26, 0x59, 0xd8, 0xa7, + 0x18, 0x67, 0xe6, 0x99, 0xf9, 0x86, 0x07, 0x78, + 0x64, 0x1b, 0x9a, 0xe5, 0x85, 0xfa, 0x7b, 0x04, + 0xbb, 0xc4, 0x45, 0x3a, 0x5a, 0x25, 0xa4, 0xdb, + 0x9c, 0xe3, 0x62, 0x1d, 0x7d, 0x02, 0x83, 0xfc, + 0x43, 0x3c, 0xbd, 0xc2, 0xa2, 0xdd, 0x5c, 0x23, + 0x3f, 0x40, 0xc1, 0xbe, 0xde, 0xa1, 0x20, 0x5f, + 0xe0, 0x9f, 0x1e, 0x61, 0x01, 0x7e, 0xff, 0x80, + }, + { + 0x00, 0x80, 0x1d, 0x9d, 0x3a, 0xba, 0x27, 0xa7, + 0x74, 0xf4, 0x69, 0xe9, 0x4e, 0xce, 0x53, 0xd3, + 0xe8, 0x68, 0xf5, 0x75, 0xd2, 0x52, 0xcf, 0x4f, + 0x9c, 0x1c, 0x81, 0x01, 0xa6, 0x26, 0xbb, 0x3b, + 0xcd, 0x4d, 0xd0, 0x50, 0xf7, 0x77, 0xea, 0x6a, + 0xb9, 0x39, 0xa4, 0x24, 0x83, 0x03, 0x9e, 0x1e, + 0x25, 0xa5, 0x38, 0xb8, 0x1f, 0x9f, 0x02, 0x82, + 0x51, 0xd1, 0x4c, 0xcc, 0x6b, 0xeb, 0x76, 0xf6, + 0x87, 0x07, 0x9a, 0x1a, 0xbd, 0x3d, 0xa0, 0x20, + 0xf3, 0x73, 0xee, 0x6e, 0xc9, 0x49, 0xd4, 0x54, + 0x6f, 0xef, 0x72, 0xf2, 0x55, 0xd5, 0x48, 0xc8, + 0x1b, 0x9b, 0x06, 0x86, 0x21, 0xa1, 0x3c, 0xbc, + 0x4a, 0xca, 0x57, 0xd7, 0x70, 0xf0, 0x6d, 0xed, + 0x3e, 0xbe, 0x23, 0xa3, 0x04, 0x84, 0x19, 0x99, + 0xa2, 0x22, 0xbf, 0x3f, 0x98, 0x18, 0x85, 0x05, + 0xd6, 0x56, 0xcb, 0x4b, 0xec, 0x6c, 0xf1, 0x71, + 0x13, 0x93, 0x0e, 0x8e, 0x29, 0xa9, 0x34, 0xb4, + 0x67, 0xe7, 0x7a, 0xfa, 0x5d, 0xdd, 0x40, 0xc0, + 0xfb, 0x7b, 0xe6, 0x66, 0xc1, 0x41, 0xdc, 0x5c, + 0x8f, 0x0f, 0x92, 0x12, 0xb5, 0x35, 0xa8, 0x28, + 0xde, 0x5e, 0xc3, 0x43, 0xe4, 0x64, 0xf9, 0x79, + 0xaa, 0x2a, 0xb7, 0x37, 0x90, 0x10, 0x8d, 0x0d, + 0x36, 0xb6, 0x2b, 0xab, 0x0c, 0x8c, 0x11, 0x91, + 0x42, 0xc2, 0x5f, 0xdf, 0x78, 0xf8, 0x65, 0xe5, + 0x94, 0x14, 0x89, 0x09, 0xae, 0x2e, 0xb3, 0x33, + 0xe0, 0x60, 0xfd, 0x7d, 0xda, 0x5a, 0xc7, 0x47, + 0x7c, 0xfc, 0x61, 0xe1, 0x46, 0xc6, 0x5b, 0xdb, + 0x08, 0x88, 0x15, 0x95, 0x32, 0xb2, 0x2f, 0xaf, + 0x59, 0xd9, 0x44, 0xc4, 0x63, 0xe3, 0x7e, 0xfe, + 0x2d, 0xad, 0x30, 0xb0, 0x17, 0x97, 0x0a, 0x8a, + 0xb1, 0x31, 0xac, 0x2c, 0x8b, 0x0b, 0x96, 0x16, + 0xc5, 0x45, 0xd8, 0x58, 0xff, 0x7f, 0xe2, 0x62, + }, + { + 0x00, 0x81, 0x1f, 0x9e, 0x3e, 0xbf, 0x21, 0xa0, + 0x7c, 0xfd, 0x63, 0xe2, 0x42, 0xc3, 0x5d, 0xdc, + 0xf8, 0x79, 0xe7, 0x66, 0xc6, 0x47, 0xd9, 0x58, + 0x84, 0x05, 0x9b, 0x1a, 0xba, 0x3b, 0xa5, 0x24, + 0xed, 0x6c, 0xf2, 0x73, 0xd3, 0x52, 0xcc, 0x4d, + 0x91, 0x10, 0x8e, 0x0f, 0xaf, 0x2e, 0xb0, 0x31, + 0x15, 0x94, 0x0a, 0x8b, 0x2b, 0xaa, 0x34, 0xb5, + 0x69, 0xe8, 0x76, 0xf7, 0x57, 0xd6, 0x48, 0xc9, + 0xc7, 0x46, 0xd8, 0x59, 0xf9, 0x78, 0xe6, 0x67, + 0xbb, 0x3a, 0xa4, 0x25, 0x85, 0x04, 0x9a, 0x1b, + 0x3f, 0xbe, 0x20, 0xa1, 0x01, 0x80, 0x1e, 0x9f, + 0x43, 0xc2, 0x5c, 0xdd, 0x7d, 0xfc, 0x62, 0xe3, + 0x2a, 0xab, 0x35, 0xb4, 0x14, 0x95, 0x0b, 0x8a, + 0x56, 0xd7, 0x49, 0xc8, 0x68, 0xe9, 0x77, 0xf6, + 0xd2, 0x53, 0xcd, 0x4c, 0xec, 0x6d, 0xf3, 0x72, + 0xae, 0x2f, 0xb1, 0x30, 0x90, 0x11, 0x8f, 0x0e, + 0x93, 0x12, 0x8c, 0x0d, 0xad, 0x2c, 0xb2, 0x33, + 0xef, 0x6e, 0xf0, 0x71, 0xd1, 0x50, 0xce, 0x4f, + 0x6b, 0xea, 0x74, 0xf5, 0x55, 0xd4, 0x4a, 0xcb, + 0x17, 0x96, 0x08, 0x89, 0x29, 0xa8, 0x36, 0xb7, + 0x7e, 0xff, 0x61, 0xe0, 0x40, 0xc1, 0x5f, 0xde, + 0x02, 0x83, 0x1d, 0x9c, 0x3c, 0xbd, 0x23, 0xa2, + 0x86, 0x07, 0x99, 0x18, 0xb8, 0x39, 0xa7, 0x26, + 0xfa, 0x7b, 0xe5, 0x64, 0xc4, 0x45, 0xdb, 0x5a, + 0x54, 0xd5, 0x4b, 0xca, 0x6a, 0xeb, 0x75, 0xf4, + 0x28, 0xa9, 0x37, 0xb6, 0x16, 0x97, 0x09, 0x88, + 0xac, 0x2d, 0xb3, 0x32, 0x92, 0x13, 0x8d, 0x0c, + 0xd0, 0x51, 0xcf, 0x4e, 0xee, 0x6f, 0xf1, 0x70, + 0xb9, 0x38, 0xa6, 0x27, 0x87, 0x06, 0x98, 0x19, + 0xc5, 0x44, 0xda, 0x5b, 0xfb, 0x7a, 0xe4, 0x65, + 0x41, 0xc0, 0x5e, 0xdf, 0x7f, 0xfe, 0x60, 0xe1, + 0x3d, 0xbc, 0x22, 0xa3, 0x03, 0x82, 0x1c, 0x9d, + }, + { + 0x00, 0x82, 0x19, 0x9b, 0x32, 0xb0, 0x2b, 0xa9, + 0x64, 0xe6, 0x7d, 0xff, 0x56, 0xd4, 0x4f, 0xcd, + 0xc8, 0x4a, 0xd1, 0x53, 0xfa, 0x78, 0xe3, 0x61, + 0xac, 0x2e, 0xb5, 0x37, 0x9e, 0x1c, 0x87, 0x05, + 0x8d, 0x0f, 0x94, 0x16, 0xbf, 0x3d, 0xa6, 0x24, + 0xe9, 0x6b, 0xf0, 0x72, 0xdb, 0x59, 0xc2, 0x40, + 0x45, 0xc7, 0x5c, 0xde, 0x77, 0xf5, 0x6e, 0xec, + 0x21, 0xa3, 0x38, 0xba, 0x13, 0x91, 0x0a, 0x88, + 0x07, 0x85, 0x1e, 0x9c, 0x35, 0xb7, 0x2c, 0xae, + 0x63, 0xe1, 0x7a, 0xf8, 0x51, 0xd3, 0x48, 0xca, + 0xcf, 0x4d, 0xd6, 0x54, 0xfd, 0x7f, 0xe4, 0x66, + 0xab, 0x29, 0xb2, 0x30, 0x99, 0x1b, 0x80, 0x02, + 0x8a, 0x08, 0x93, 0x11, 0xb8, 0x3a, 0xa1, 0x23, + 0xee, 0x6c, 0xf7, 0x75, 0xdc, 0x5e, 0xc5, 0x47, + 0x42, 0xc0, 0x5b, 0xd9, 0x70, 0xf2, 0x69, 0xeb, + 0x26, 0xa4, 0x3f, 0xbd, 0x14, 0x96, 0x0d, 0x8f, + 0x0e, 0x8c, 0x17, 0x95, 0x3c, 0xbe, 0x25, 0xa7, + 0x6a, 0xe8, 0x73, 0xf1, 0x58, 0xda, 0x41, 0xc3, + 0xc6, 0x44, 0xdf, 0x5d, 0xf4, 0x76, 0xed, 0x6f, + 0xa2, 0x20, 0xbb, 0x39, 0x90, 0x12, 0x89, 0x0b, + 0x83, 0x01, 0x9a, 0x18, 0xb1, 0x33, 0xa8, 0x2a, + 0xe7, 0x65, 0xfe, 0x7c, 0xd5, 0x57, 0xcc, 0x4e, + 0x4b, 0xc9, 0x52, 0xd0, 0x79, 0xfb, 0x60, 0xe2, + 0x2f, 0xad, 0x36, 0xb4, 0x1d, 0x9f, 0x04, 0x86, + 0x09, 0x8b, 0x10, 0x92, 0x3b, 0xb9, 0x22, 0xa0, + 0x6d, 0xef, 0x74, 0xf6, 0x5f, 0xdd, 0x46, 0xc4, + 0xc1, 0x43, 0xd8, 0x5a, 0xf3, 0x71, 0xea, 0x68, + 0xa5, 0x27, 0xbc, 0x3e, 0x97, 0x15, 0x8e, 0x0c, + 0x84, 0x06, 0x9d, 0x1f, 0xb6, 0x34, 0xaf, 0x2d, + 0xe0, 0x62, 0xf9, 0x7b, 0xd2, 0x50, 0xcb, 0x49, + 0x4c, 0xce, 0x55, 0xd7, 0x7e, 0xfc, 0x67, 0xe5, + 0x28, 0xaa, 0x31, 0xb3, 0x1a, 0x98, 0x03, 0x81, + }, + { + 0x00, 0x83, 0x1b, 0x98, 0x36, 0xb5, 0x2d, 0xae, + 0x6c, 0xef, 0x77, 0xf4, 0x5a, 0xd9, 0x41, 0xc2, + 0xd8, 0x5b, 0xc3, 0x40, 0xee, 0x6d, 0xf5, 0x76, + 0xb4, 0x37, 0xaf, 0x2c, 0x82, 0x01, 0x99, 0x1a, + 0xad, 0x2e, 0xb6, 0x35, 0x9b, 0x18, 0x80, 0x03, + 0xc1, 0x42, 0xda, 0x59, 0xf7, 0x74, 0xec, 0x6f, + 0x75, 0xf6, 0x6e, 0xed, 0x43, 0xc0, 0x58, 0xdb, + 0x19, 0x9a, 0x02, 0x81, 0x2f, 0xac, 0x34, 0xb7, + 0x47, 0xc4, 0x5c, 0xdf, 0x71, 0xf2, 0x6a, 0xe9, + 0x2b, 0xa8, 0x30, 0xb3, 0x1d, 0x9e, 0x06, 0x85, + 0x9f, 0x1c, 0x84, 0x07, 0xa9, 0x2a, 0xb2, 0x31, + 0xf3, 0x70, 0xe8, 0x6b, 0xc5, 0x46, 0xde, 0x5d, + 0xea, 0x69, 0xf1, 0x72, 0xdc, 0x5f, 0xc7, 0x44, + 0x86, 0x05, 0x9d, 0x1e, 0xb0, 0x33, 0xab, 0x28, + 0x32, 0xb1, 0x29, 0xaa, 0x04, 0x87, 0x1f, 0x9c, + 0x5e, 0xdd, 0x45, 0xc6, 0x68, 0xeb, 0x73, 0xf0, + 0x8e, 0x0d, 0x95, 0x16, 0xb8, 0x3b, 0xa3, 0x20, + 0xe2, 0x61, 0xf9, 0x7a, 0xd4, 0x57, 0xcf, 0x4c, + 0x56, 0xd5, 0x4d, 0xce, 0x60, 0xe3, 0x7b, 0xf8, + 0x3a, 0xb9, 0x21, 0xa2, 0x0c, 0x8f, 0x17, 0x94, + 0x23, 0xa0, 0x38, 0xbb, 0x15, 0x96, 0x0e, 0x8d, + 0x4f, 0xcc, 0x54, 0xd7, 0x79, 0xfa, 0x62, 0xe1, + 0xfb, 0x78, 0xe0, 0x63, 0xcd, 0x4e, 0xd6, 0x55, + 0x97, 0x14, 0x8c, 0x0f, 0xa1, 0x22, 0xba, 0x39, + 0xc9, 0x4a, 0xd2, 0x51, 0xff, 0x7c, 0xe4, 0x67, + 0xa5, 0x26, 0xbe, 0x3d, 0x93, 0x10, 0x88, 0x0b, + 0x11, 0x92, 0x0a, 0x89, 0x27, 0xa4, 0x3c, 0xbf, + 0x7d, 0xfe, 0x66, 0xe5, 0x4b, 0xc8, 0x50, 0xd3, + 0x64, 0xe7, 0x7f, 0xfc, 0x52, 0xd1, 0x49, 0xca, + 0x08, 0x8b, 0x13, 0x90, 0x3e, 0xbd, 0x25, 0xa6, + 0xbc, 0x3f, 0xa7, 0x24, 0x8a, 0x09, 0x91, 0x12, + 0xd0, 0x53, 0xcb, 0x48, 0xe6, 0x65, 0xfd, 0x7e, + }, + { + 0x00, 0x84, 0x15, 0x91, 0x2a, 0xae, 0x3f, 0xbb, + 0x54, 0xd0, 0x41, 0xc5, 0x7e, 0xfa, 0x6b, 0xef, + 0xa8, 0x2c, 0xbd, 0x39, 0x82, 0x06, 0x97, 0x13, + 0xfc, 0x78, 0xe9, 0x6d, 0xd6, 0x52, 0xc3, 0x47, + 0x4d, 0xc9, 0x58, 0xdc, 0x67, 0xe3, 0x72, 0xf6, + 0x19, 0x9d, 0x0c, 0x88, 0x33, 0xb7, 0x26, 0xa2, + 0xe5, 0x61, 0xf0, 0x74, 0xcf, 0x4b, 0xda, 0x5e, + 0xb1, 0x35, 0xa4, 0x20, 0x9b, 0x1f, 0x8e, 0x0a, + 0x9a, 0x1e, 0x8f, 0x0b, 0xb0, 0x34, 0xa5, 0x21, + 0xce, 0x4a, 0xdb, 0x5f, 0xe4, 0x60, 0xf1, 0x75, + 0x32, 0xb6, 0x27, 0xa3, 0x18, 0x9c, 0x0d, 0x89, + 0x66, 0xe2, 0x73, 0xf7, 0x4c, 0xc8, 0x59, 0xdd, + 0xd7, 0x53, 0xc2, 0x46, 0xfd, 0x79, 0xe8, 0x6c, + 0x83, 0x07, 0x96, 0x12, 0xa9, 0x2d, 0xbc, 0x38, + 0x7f, 0xfb, 0x6a, 0xee, 0x55, 0xd1, 0x40, 0xc4, + 0x2b, 0xaf, 0x3e, 0xba, 0x01, 0x85, 0x14, 0x90, + 0x29, 0xad, 0x3c, 0xb8, 0x03, 0x87, 0x16, 0x92, + 0x7d, 0xf9, 0x68, 0xec, 0x57, 0xd3, 0x42, 0xc6, + 0x81, 0x05, 0x94, 0x10, 0xab, 0x2f, 0xbe, 0x3a, + 0xd5, 0x51, 0xc0, 0x44, 0xff, 0x7b, 0xea, 0x6e, + 0x64, 0xe0, 0x71, 0xf5, 0x4e, 0xca, 0x5b, 0xdf, + 0x30, 0xb4, 0x25, 0xa1, 0x1a, 0x9e, 0x0f, 0x8b, + 0xcc, 0x48, 0xd9, 0x5d, 0xe6, 0x62, 0xf3, 0x77, + 0x98, 0x1c, 0x8d, 0x09, 0xb2, 0x36, 0xa7, 0x23, + 0xb3, 0x37, 0xa6, 0x22, 0x99, 0x1d, 0x8c, 0x08, + 0xe7, 0x63, 0xf2, 0x76, 0xcd, 0x49, 0xd8, 0x5c, + 0x1b, 0x9f, 0x0e, 0x8a, 0x31, 0xb5, 0x24, 0xa0, + 0x4f, 0xcb, 0x5a, 0xde, 0x65, 0xe1, 0x70, 0xf4, + 0xfe, 0x7a, 0xeb, 0x6f, 0xd4, 0x50, 0xc1, 0x45, + 0xaa, 0x2e, 0xbf, 0x3b, 0x80, 0x04, 0x95, 0x11, + 0x56, 0xd2, 0x43, 0xc7, 0x7c, 0xf8, 0x69, 0xed, + 0x02, 0x86, 0x17, 0x93, 0x28, 0xac, 0x3d, 0xb9, + }, + { + 0x00, 0x85, 0x17, 0x92, 0x2e, 0xab, 0x39, 0xbc, + 0x5c, 0xd9, 0x4b, 0xce, 0x72, 0xf7, 0x65, 0xe0, + 0xb8, 0x3d, 0xaf, 0x2a, 0x96, 0x13, 0x81, 0x04, + 0xe4, 0x61, 0xf3, 0x76, 0xca, 0x4f, 0xdd, 0x58, + 0x6d, 0xe8, 0x7a, 0xff, 0x43, 0xc6, 0x54, 0xd1, + 0x31, 0xb4, 0x26, 0xa3, 0x1f, 0x9a, 0x08, 0x8d, + 0xd5, 0x50, 0xc2, 0x47, 0xfb, 0x7e, 0xec, 0x69, + 0x89, 0x0c, 0x9e, 0x1b, 0xa7, 0x22, 0xb0, 0x35, + 0xda, 0x5f, 0xcd, 0x48, 0xf4, 0x71, 0xe3, 0x66, + 0x86, 0x03, 0x91, 0x14, 0xa8, 0x2d, 0xbf, 0x3a, + 0x62, 0xe7, 0x75, 0xf0, 0x4c, 0xc9, 0x5b, 0xde, + 0x3e, 0xbb, 0x29, 0xac, 0x10, 0x95, 0x07, 0x82, + 0xb7, 0x32, 0xa0, 0x25, 0x99, 0x1c, 0x8e, 0x0b, + 0xeb, 0x6e, 0xfc, 0x79, 0xc5, 0x40, 0xd2, 0x57, + 0x0f, 0x8a, 0x18, 0x9d, 0x21, 0xa4, 0x36, 0xb3, + 0x53, 0xd6, 0x44, 0xc1, 0x7d, 0xf8, 0x6a, 0xef, + 0xa9, 0x2c, 0xbe, 0x3b, 0x87, 0x02, 0x90, 0x15, + 0xf5, 0x70, 0xe2, 0x67, 0xdb, 0x5e, 0xcc, 0x49, + 0x11, 0x94, 0x06, 0x83, 0x3f, 0xba, 0x28, 0xad, + 0x4d, 0xc8, 0x5a, 0xdf, 0x63, 0xe6, 0x74, 0xf1, + 0xc4, 0x41, 0xd3, 0x56, 0xea, 0x6f, 0xfd, 0x78, + 0x98, 0x1d, 0x8f, 0x0a, 0xb6, 0x33, 0xa1, 0x24, + 0x7c, 0xf9, 0x6b, 0xee, 0x52, 0xd7, 0x45, 0xc0, + 0x20, 0xa5, 0x37, 0xb2, 0x0e, 0x8b, 0x19, 0x9c, + 0x73, 0xf6, 0x64, 0xe1, 0x5d, 0xd8, 0x4a, 0xcf, + 0x2f, 0xaa, 0x38, 0xbd, 0x01, 0x84, 0x16, 0x93, + 0xcb, 0x4e, 0xdc, 0x59, 0xe5, 0x60, 0xf2, 0x77, + 0x97, 0x12, 0x80, 0x05, 0xb9, 0x3c, 0xae, 0x2b, + 0x1e, 0x9b, 0x09, 0x8c, 0x30, 0xb5, 0x27, 0xa2, + 0x42, 0xc7, 0x55, 0xd0, 0x6c, 0xe9, 0x7b, 0xfe, + 0xa6, 0x23, 0xb1, 0x34, 0x88, 0x0d, 0x9f, 0x1a, + 0xfa, 0x7f, 0xed, 0x68, 0xd4, 0x51, 0xc3, 0x46, + }, + { + 0x00, 0x86, 0x11, 0x97, 0x22, 0xa4, 0x33, 0xb5, + 0x44, 0xc2, 0x55, 0xd3, 0x66, 0xe0, 0x77, 0xf1, + 0x88, 0x0e, 0x99, 0x1f, 0xaa, 0x2c, 0xbb, 0x3d, + 0xcc, 0x4a, 0xdd, 0x5b, 0xee, 0x68, 0xff, 0x79, + 0x0d, 0x8b, 0x1c, 0x9a, 0x2f, 0xa9, 0x3e, 0xb8, + 0x49, 0xcf, 0x58, 0xde, 0x6b, 0xed, 0x7a, 0xfc, + 0x85, 0x03, 0x94, 0x12, 0xa7, 0x21, 0xb6, 0x30, + 0xc1, 0x47, 0xd0, 0x56, 0xe3, 0x65, 0xf2, 0x74, + 0x1a, 0x9c, 0x0b, 0x8d, 0x38, 0xbe, 0x29, 0xaf, + 0x5e, 0xd8, 0x4f, 0xc9, 0x7c, 0xfa, 0x6d, 0xeb, + 0x92, 0x14, 0x83, 0x05, 0xb0, 0x36, 0xa1, 0x27, + 0xd6, 0x50, 0xc7, 0x41, 0xf4, 0x72, 0xe5, 0x63, + 0x17, 0x91, 0x06, 0x80, 0x35, 0xb3, 0x24, 0xa2, + 0x53, 0xd5, 0x42, 0xc4, 0x71, 0xf7, 0x60, 0xe6, + 0x9f, 0x19, 0x8e, 0x08, 0xbd, 0x3b, 0xac, 0x2a, + 0xdb, 0x5d, 0xca, 0x4c, 0xf9, 0x7f, 0xe8, 0x6e, + 0x34, 0xb2, 0x25, 0xa3, 0x16, 0x90, 0x07, 0x81, + 0x70, 0xf6, 0x61, 0xe7, 0x52, 0xd4, 0x43, 0xc5, + 0xbc, 0x3a, 0xad, 0x2b, 0x9e, 0x18, 0x8f, 0x09, + 0xf8, 0x7e, 0xe9, 0x6f, 0xda, 0x5c, 0xcb, 0x4d, + 0x39, 0xbf, 0x28, 0xae, 0x1b, 0x9d, 0x0a, 0x8c, + 0x7d, 0xfb, 0x6c, 0xea, 0x5f, 0xd9, 0x4e, 0xc8, + 0xb1, 0x37, 0xa0, 0x26, 0x93, 0x15, 0x82, 0x04, + 0xf5, 0x73, 0xe4, 0x62, 0xd7, 0x51, 0xc6, 0x40, + 0x2e, 0xa8, 0x3f, 0xb9, 0x0c, 0x8a, 0x1d, 0x9b, + 0x6a, 0xec, 0x7b, 0xfd, 0x48, 0xce, 0x59, 0xdf, + 0xa6, 0x20, 0xb7, 0x31, 0x84, 0x02, 0x95, 0x13, + 0xe2, 0x64, 0xf3, 0x75, 0xc0, 0x46, 0xd1, 0x57, + 0x23, 0xa5, 0x32, 0xb4, 0x01, 0x87, 0x10, 0x96, + 0x67, 0xe1, 0x76, 0xf0, 0x45, 0xc3, 0x54, 0xd2, + 0xab, 0x2d, 0xba, 0x3c, 0x89, 0x0f, 0x98, 0x1e, + 0xef, 0x69, 0xfe, 0x78, 0xcd, 0x4b, 0xdc, 0x5a, + }, + { + 0x00, 0x87, 0x13, 0x94, 0x26, 0xa1, 0x35, 0xb2, + 0x4c, 0xcb, 0x5f, 0xd8, 0x6a, 0xed, 0x79, 0xfe, + 0x98, 0x1f, 0x8b, 0x0c, 0xbe, 0x39, 0xad, 0x2a, + 0xd4, 0x53, 0xc7, 0x40, 0xf2, 0x75, 0xe1, 0x66, + 0x2d, 0xaa, 0x3e, 0xb9, 0x0b, 0x8c, 0x18, 0x9f, + 0x61, 0xe6, 0x72, 0xf5, 0x47, 0xc0, 0x54, 0xd3, + 0xb5, 0x32, 0xa6, 0x21, 0x93, 0x14, 0x80, 0x07, + 0xf9, 0x7e, 0xea, 0x6d, 0xdf, 0x58, 0xcc, 0x4b, + 0x5a, 0xdd, 0x49, 0xce, 0x7c, 0xfb, 0x6f, 0xe8, + 0x16, 0x91, 0x05, 0x82, 0x30, 0xb7, 0x23, 0xa4, + 0xc2, 0x45, 0xd1, 0x56, 0xe4, 0x63, 0xf7, 0x70, + 0x8e, 0x09, 0x9d, 0x1a, 0xa8, 0x2f, 0xbb, 0x3c, + 0x77, 0xf0, 0x64, 0xe3, 0x51, 0xd6, 0x42, 0xc5, + 0x3b, 0xbc, 0x28, 0xaf, 0x1d, 0x9a, 0x0e, 0x89, + 0xef, 0x68, 0xfc, 0x7b, 0xc9, 0x4e, 0xda, 0x5d, + 0xa3, 0x24, 0xb0, 0x37, 0x85, 0x02, 0x96, 0x11, + 0xb4, 0x33, 0xa7, 0x20, 0x92, 0x15, 0x81, 0x06, + 0xf8, 0x7f, 0xeb, 0x6c, 0xde, 0x59, 0xcd, 0x4a, + 0x2c, 0xab, 0x3f, 0xb8, 0x0a, 0x8d, 0x19, 0x9e, + 0x60, 0xe7, 0x73, 0xf4, 0x46, 0xc1, 0x55, 0xd2, + 0x99, 0x1e, 0x8a, 0x0d, 0xbf, 0x38, 0xac, 0x2b, + 0xd5, 0x52, 0xc6, 0x41, 0xf3, 0x74, 0xe0, 0x67, + 0x01, 0x86, 0x12, 0x95, 0x27, 0xa0, 0x34, 0xb3, + 0x4d, 0xca, 0x5e, 0xd9, 0x6b, 0xec, 0x78, 0xff, + 0xee, 0x69, 0xfd, 0x7a, 0xc8, 0x4f, 0xdb, 0x5c, + 0xa2, 0x25, 0xb1, 0x36, 0x84, 0x03, 0x97, 0x10, + 0x76, 0xf1, 0x65, 0xe2, 0x50, 0xd7, 0x43, 0xc4, + 0x3a, 0xbd, 0x29, 0xae, 0x1c, 0x9b, 0x0f, 0x88, + 0xc3, 0x44, 0xd0, 0x57, 0xe5, 0x62, 0xf6, 0x71, + 0x8f, 0x08, 0x9c, 0x1b, 0xa9, 0x2e, 0xba, 0x3d, + 0x5b, 0xdc, 0x48, 0xcf, 0x7d, 0xfa, 0x6e, 0xe9, + 0x17, 0x90, 0x04, 0x83, 0x31, 0xb6, 0x22, 0xa5, + }, + { + 0x00, 0x88, 0x0d, 0x85, 0x1a, 0x92, 0x17, 0x9f, + 0x34, 0xbc, 0x39, 0xb1, 0x2e, 0xa6, 0x23, 0xab, + 0x68, 0xe0, 0x65, 0xed, 0x72, 0xfa, 0x7f, 0xf7, + 0x5c, 0xd4, 0x51, 0xd9, 0x46, 0xce, 0x4b, 0xc3, + 0xd0, 0x58, 0xdd, 0x55, 0xca, 0x42, 0xc7, 0x4f, + 0xe4, 0x6c, 0xe9, 0x61, 0xfe, 0x76, 0xf3, 0x7b, + 0xb8, 0x30, 0xb5, 0x3d, 0xa2, 0x2a, 0xaf, 0x27, + 0x8c, 0x04, 0x81, 0x09, 0x96, 0x1e, 0x9b, 0x13, + 0xbd, 0x35, 0xb0, 0x38, 0xa7, 0x2f, 0xaa, 0x22, + 0x89, 0x01, 0x84, 0x0c, 0x93, 0x1b, 0x9e, 0x16, + 0xd5, 0x5d, 0xd8, 0x50, 0xcf, 0x47, 0xc2, 0x4a, + 0xe1, 0x69, 0xec, 0x64, 0xfb, 0x73, 0xf6, 0x7e, + 0x6d, 0xe5, 0x60, 0xe8, 0x77, 0xff, 0x7a, 0xf2, + 0x59, 0xd1, 0x54, 0xdc, 0x43, 0xcb, 0x4e, 0xc6, + 0x05, 0x8d, 0x08, 0x80, 0x1f, 0x97, 0x12, 0x9a, + 0x31, 0xb9, 0x3c, 0xb4, 0x2b, 0xa3, 0x26, 0xae, + 0x67, 0xef, 0x6a, 0xe2, 0x7d, 0xf5, 0x70, 0xf8, + 0x53, 0xdb, 0x5e, 0xd6, 0x49, 0xc1, 0x44, 0xcc, + 0x0f, 0x87, 0x02, 0x8a, 0x15, 0x9d, 0x18, 0x90, + 0x3b, 0xb3, 0x36, 0xbe, 0x21, 0xa9, 0x2c, 0xa4, + 0xb7, 0x3f, 0xba, 0x32, 0xad, 0x25, 0xa0, 0x28, + 0x83, 0x0b, 0x8e, 0x06, 0x99, 0x11, 0x94, 0x1c, + 0xdf, 0x57, 0xd2, 0x5a, 0xc5, 0x4d, 0xc8, 0x40, + 0xeb, 0x63, 0xe6, 0x6e, 0xf1, 0x79, 0xfc, 0x74, + 0xda, 0x52, 0xd7, 0x5f, 0xc0, 0x48, 0xcd, 0x45, + 0xee, 0x66, 0xe3, 0x6b, 0xf4, 0x7c, 0xf9, 0x71, + 0xb2, 0x3a, 0xbf, 0x37, 0xa8, 0x20, 0xa5, 0x2d, + 0x86, 0x0e, 0x8b, 0x03, 0x9c, 0x14, 0x91, 0x19, + 0x0a, 0x82, 0x07, 0x8f, 0x10, 0x98, 0x1d, 0x95, + 0x3e, 0xb6, 0x33, 0xbb, 0x24, 0xac, 0x29, 0xa1, + 0x62, 0xea, 0x6f, 0xe7, 0x78, 0xf0, 0x75, 0xfd, + 0x56, 0xde, 0x5b, 0xd3, 0x4c, 0xc4, 0x41, 0xc9, + }, + { + 0x00, 0x89, 0x0f, 0x86, 0x1e, 0x97, 0x11, 0x98, + 0x3c, 0xb5, 0x33, 0xba, 0x22, 0xab, 0x2d, 0xa4, + 0x78, 0xf1, 0x77, 0xfe, 0x66, 0xef, 0x69, 0xe0, + 0x44, 0xcd, 0x4b, 0xc2, 0x5a, 0xd3, 0x55, 0xdc, + 0xf0, 0x79, 0xff, 0x76, 0xee, 0x67, 0xe1, 0x68, + 0xcc, 0x45, 0xc3, 0x4a, 0xd2, 0x5b, 0xdd, 0x54, + 0x88, 0x01, 0x87, 0x0e, 0x96, 0x1f, 0x99, 0x10, + 0xb4, 0x3d, 0xbb, 0x32, 0xaa, 0x23, 0xa5, 0x2c, + 0xfd, 0x74, 0xf2, 0x7b, 0xe3, 0x6a, 0xec, 0x65, + 0xc1, 0x48, 0xce, 0x47, 0xdf, 0x56, 0xd0, 0x59, + 0x85, 0x0c, 0x8a, 0x03, 0x9b, 0x12, 0x94, 0x1d, + 0xb9, 0x30, 0xb6, 0x3f, 0xa7, 0x2e, 0xa8, 0x21, + 0x0d, 0x84, 0x02, 0x8b, 0x13, 0x9a, 0x1c, 0x95, + 0x31, 0xb8, 0x3e, 0xb7, 0x2f, 0xa6, 0x20, 0xa9, + 0x75, 0xfc, 0x7a, 0xf3, 0x6b, 0xe2, 0x64, 0xed, + 0x49, 0xc0, 0x46, 0xcf, 0x57, 0xde, 0x58, 0xd1, + 0xe7, 0x6e, 0xe8, 0x61, 0xf9, 0x70, 0xf6, 0x7f, + 0xdb, 0x52, 0xd4, 0x5d, 0xc5, 0x4c, 0xca, 0x43, + 0x9f, 0x16, 0x90, 0x19, 0x81, 0x08, 0x8e, 0x07, + 0xa3, 0x2a, 0xac, 0x25, 0xbd, 0x34, 0xb2, 0x3b, + 0x17, 0x9e, 0x18, 0x91, 0x09, 0x80, 0x06, 0x8f, + 0x2b, 0xa2, 0x24, 0xad, 0x35, 0xbc, 0x3a, 0xb3, + 0x6f, 0xe6, 0x60, 0xe9, 0x71, 0xf8, 0x7e, 0xf7, + 0x53, 0xda, 0x5c, 0xd5, 0x4d, 0xc4, 0x42, 0xcb, + 0x1a, 0x93, 0x15, 0x9c, 0x04, 0x8d, 0x0b, 0x82, + 0x26, 0xaf, 0x29, 0xa0, 0x38, 0xb1, 0x37, 0xbe, + 0x62, 0xeb, 0x6d, 0xe4, 0x7c, 0xf5, 0x73, 0xfa, + 0x5e, 0xd7, 0x51, 0xd8, 0x40, 0xc9, 0x4f, 0xc6, + 0xea, 0x63, 0xe5, 0x6c, 0xf4, 0x7d, 0xfb, 0x72, + 0xd6, 0x5f, 0xd9, 0x50, 0xc8, 0x41, 0xc7, 0x4e, + 0x92, 0x1b, 0x9d, 0x14, 0x8c, 0x05, 0x83, 0x0a, + 0xae, 0x27, 0xa1, 0x28, 0xb0, 0x39, 0xbf, 0x36, + }, + { + 0x00, 0x8a, 0x09, 0x83, 0x12, 0x98, 0x1b, 0x91, + 0x24, 0xae, 0x2d, 0xa7, 0x36, 0xbc, 0x3f, 0xb5, + 0x48, 0xc2, 0x41, 0xcb, 0x5a, 0xd0, 0x53, 0xd9, + 0x6c, 0xe6, 0x65, 0xef, 0x7e, 0xf4, 0x77, 0xfd, + 0x90, 0x1a, 0x99, 0x13, 0x82, 0x08, 0x8b, 0x01, + 0xb4, 0x3e, 0xbd, 0x37, 0xa6, 0x2c, 0xaf, 0x25, + 0xd8, 0x52, 0xd1, 0x5b, 0xca, 0x40, 0xc3, 0x49, + 0xfc, 0x76, 0xf5, 0x7f, 0xee, 0x64, 0xe7, 0x6d, + 0x3d, 0xb7, 0x34, 0xbe, 0x2f, 0xa5, 0x26, 0xac, + 0x19, 0x93, 0x10, 0x9a, 0x0b, 0x81, 0x02, 0x88, + 0x75, 0xff, 0x7c, 0xf6, 0x67, 0xed, 0x6e, 0xe4, + 0x51, 0xdb, 0x58, 0xd2, 0x43, 0xc9, 0x4a, 0xc0, + 0xad, 0x27, 0xa4, 0x2e, 0xbf, 0x35, 0xb6, 0x3c, + 0x89, 0x03, 0x80, 0x0a, 0x9b, 0x11, 0x92, 0x18, + 0xe5, 0x6f, 0xec, 0x66, 0xf7, 0x7d, 0xfe, 0x74, + 0xc1, 0x4b, 0xc8, 0x42, 0xd3, 0x59, 0xda, 0x50, + 0x7a, 0xf0, 0x73, 0xf9, 0x68, 0xe2, 0x61, 0xeb, + 0x5e, 0xd4, 0x57, 0xdd, 0x4c, 0xc6, 0x45, 0xcf, + 0x32, 0xb8, 0x3b, 0xb1, 0x20, 0xaa, 0x29, 0xa3, + 0x16, 0x9c, 0x1f, 0x95, 0x04, 0x8e, 0x0d, 0x87, + 0xea, 0x60, 0xe3, 0x69, 0xf8, 0x72, 0xf1, 0x7b, + 0xce, 0x44, 0xc7, 0x4d, 0xdc, 0x56, 0xd5, 0x5f, + 0xa2, 0x28, 0xab, 0x21, 0xb0, 0x3a, 0xb9, 0x33, + 0x86, 0x0c, 0x8f, 0x05, 0x94, 0x1e, 0x9d, 0x17, + 0x47, 0xcd, 0x4e, 0xc4, 0x55, 0xdf, 0x5c, 0xd6, + 0x63, 0xe9, 0x6a, 0xe0, 0x71, 0xfb, 0x78, 0xf2, + 0x0f, 0x85, 0x06, 0x8c, 0x1d, 0x97, 0x14, 0x9e, + 0x2b, 0xa1, 0x22, 0xa8, 0x39, 0xb3, 0x30, 0xba, + 0xd7, 0x5d, 0xde, 0x54, 0xc5, 0x4f, 0xcc, 0x46, + 0xf3, 0x79, 0xfa, 0x70, 0xe1, 0x6b, 0xe8, 0x62, + 0x9f, 0x15, 0x96, 0x1c, 0x8d, 0x07, 0x84, 0x0e, + 0xbb, 0x31, 0xb2, 0x38, 0xa9, 0x23, 0xa0, 0x2a, + }, + { + 0x00, 0x8b, 0x0b, 0x80, 0x16, 0x9d, 0x1d, 0x96, + 0x2c, 0xa7, 0x27, 0xac, 0x3a, 0xb1, 0x31, 0xba, + 0x58, 0xd3, 0x53, 0xd8, 0x4e, 0xc5, 0x45, 0xce, + 0x74, 0xff, 0x7f, 0xf4, 0x62, 0xe9, 0x69, 0xe2, + 0xb0, 0x3b, 0xbb, 0x30, 0xa6, 0x2d, 0xad, 0x26, + 0x9c, 0x17, 0x97, 0x1c, 0x8a, 0x01, 0x81, 0x0a, + 0xe8, 0x63, 0xe3, 0x68, 0xfe, 0x75, 0xf5, 0x7e, + 0xc4, 0x4f, 0xcf, 0x44, 0xd2, 0x59, 0xd9, 0x52, + 0x7d, 0xf6, 0x76, 0xfd, 0x6b, 0xe0, 0x60, 0xeb, + 0x51, 0xda, 0x5a, 0xd1, 0x47, 0xcc, 0x4c, 0xc7, + 0x25, 0xae, 0x2e, 0xa5, 0x33, 0xb8, 0x38, 0xb3, + 0x09, 0x82, 0x02, 0x89, 0x1f, 0x94, 0x14, 0x9f, + 0xcd, 0x46, 0xc6, 0x4d, 0xdb, 0x50, 0xd0, 0x5b, + 0xe1, 0x6a, 0xea, 0x61, 0xf7, 0x7c, 0xfc, 0x77, + 0x95, 0x1e, 0x9e, 0x15, 0x83, 0x08, 0x88, 0x03, + 0xb9, 0x32, 0xb2, 0x39, 0xaf, 0x24, 0xa4, 0x2f, + 0xfa, 0x71, 0xf1, 0x7a, 0xec, 0x67, 0xe7, 0x6c, + 0xd6, 0x5d, 0xdd, 0x56, 0xc0, 0x4b, 0xcb, 0x40, + 0xa2, 0x29, 0xa9, 0x22, 0xb4, 0x3f, 0xbf, 0x34, + 0x8e, 0x05, 0x85, 0x0e, 0x98, 0x13, 0x93, 0x18, + 0x4a, 0xc1, 0x41, 0xca, 0x5c, 0xd7, 0x57, 0xdc, + 0x66, 0xed, 0x6d, 0xe6, 0x70, 0xfb, 0x7b, 0xf0, + 0x12, 0x99, 0x19, 0x92, 0x04, 0x8f, 0x0f, 0x84, + 0x3e, 0xb5, 0x35, 0xbe, 0x28, 0xa3, 0x23, 0xa8, + 0x87, 0x0c, 0x8c, 0x07, 0x91, 0x1a, 0x9a, 0x11, + 0xab, 0x20, 0xa0, 0x2b, 0xbd, 0x36, 0xb6, 0x3d, + 0xdf, 0x54, 0xd4, 0x5f, 0xc9, 0x42, 0xc2, 0x49, + 0xf3, 0x78, 0xf8, 0x73, 0xe5, 0x6e, 0xee, 0x65, + 0x37, 0xbc, 0x3c, 0xb7, 0x21, 0xaa, 0x2a, 0xa1, + 0x1b, 0x90, 0x10, 0x9b, 0x0d, 0x86, 0x06, 0x8d, + 0x6f, 0xe4, 0x64, 0xef, 0x79, 0xf2, 0x72, 0xf9, + 0x43, 0xc8, 0x48, 0xc3, 0x55, 0xde, 0x5e, 0xd5, + }, + { + 0x00, 0x8c, 0x05, 0x89, 0x0a, 0x86, 0x0f, 0x83, + 0x14, 0x98, 0x11, 0x9d, 0x1e, 0x92, 0x1b, 0x97, + 0x28, 0xa4, 0x2d, 0xa1, 0x22, 0xae, 0x27, 0xab, + 0x3c, 0xb0, 0x39, 0xb5, 0x36, 0xba, 0x33, 0xbf, + 0x50, 0xdc, 0x55, 0xd9, 0x5a, 0xd6, 0x5f, 0xd3, + 0x44, 0xc8, 0x41, 0xcd, 0x4e, 0xc2, 0x4b, 0xc7, + 0x78, 0xf4, 0x7d, 0xf1, 0x72, 0xfe, 0x77, 0xfb, + 0x6c, 0xe0, 0x69, 0xe5, 0x66, 0xea, 0x63, 0xef, + 0xa0, 0x2c, 0xa5, 0x29, 0xaa, 0x26, 0xaf, 0x23, + 0xb4, 0x38, 0xb1, 0x3d, 0xbe, 0x32, 0xbb, 0x37, + 0x88, 0x04, 0x8d, 0x01, 0x82, 0x0e, 0x87, 0x0b, + 0x9c, 0x10, 0x99, 0x15, 0x96, 0x1a, 0x93, 0x1f, + 0xf0, 0x7c, 0xf5, 0x79, 0xfa, 0x76, 0xff, 0x73, + 0xe4, 0x68, 0xe1, 0x6d, 0xee, 0x62, 0xeb, 0x67, + 0xd8, 0x54, 0xdd, 0x51, 0xd2, 0x5e, 0xd7, 0x5b, + 0xcc, 0x40, 0xc9, 0x45, 0xc6, 0x4a, 0xc3, 0x4f, + 0x5d, 0xd1, 0x58, 0xd4, 0x57, 0xdb, 0x52, 0xde, + 0x49, 0xc5, 0x4c, 0xc0, 0x43, 0xcf, 0x46, 0xca, + 0x75, 0xf9, 0x70, 0xfc, 0x7f, 0xf3, 0x7a, 0xf6, + 0x61, 0xed, 0x64, 0xe8, 0x6b, 0xe7, 0x6e, 0xe2, + 0x0d, 0x81, 0x08, 0x84, 0x07, 0x8b, 0x02, 0x8e, + 0x19, 0x95, 0x1c, 0x90, 0x13, 0x9f, 0x16, 0x9a, + 0x25, 0xa9, 0x20, 0xac, 0x2f, 0xa3, 0x2a, 0xa6, + 0x31, 0xbd, 0x34, 0xb8, 0x3b, 0xb7, 0x3e, 0xb2, + 0xfd, 0x71, 0xf8, 0x74, 0xf7, 0x7b, 0xf2, 0x7e, + 0xe9, 0x65, 0xec, 0x60, 0xe3, 0x6f, 0xe6, 0x6a, + 0xd5, 0x59, 0xd0, 0x5c, 0xdf, 0x53, 0xda, 0x56, + 0xc1, 0x4d, 0xc4, 0x48, 0xcb, 0x47, 0xce, 0x42, + 0xad, 0x21, 0xa8, 0x24, 0xa7, 0x2b, 0xa2, 0x2e, + 0xb9, 0x35, 0xbc, 0x30, 0xb3, 0x3f, 0xb6, 0x3a, + 0x85, 0x09, 0x80, 0x0c, 0x8f, 0x03, 0x8a, 0x06, + 0x91, 0x1d, 0x94, 0x18, 0x9b, 0x17, 0x9e, 0x12, + }, + { + 0x00, 0x8d, 0x07, 0x8a, 0x0e, 0x83, 0x09, 0x84, + 0x1c, 0x91, 0x1b, 0x96, 0x12, 0x9f, 0x15, 0x98, + 0x38, 0xb5, 0x3f, 0xb2, 0x36, 0xbb, 0x31, 0xbc, + 0x24, 0xa9, 0x23, 0xae, 0x2a, 0xa7, 0x2d, 0xa0, + 0x70, 0xfd, 0x77, 0xfa, 0x7e, 0xf3, 0x79, 0xf4, + 0x6c, 0xe1, 0x6b, 0xe6, 0x62, 0xef, 0x65, 0xe8, + 0x48, 0xc5, 0x4f, 0xc2, 0x46, 0xcb, 0x41, 0xcc, + 0x54, 0xd9, 0x53, 0xde, 0x5a, 0xd7, 0x5d, 0xd0, + 0xe0, 0x6d, 0xe7, 0x6a, 0xee, 0x63, 0xe9, 0x64, + 0xfc, 0x71, 0xfb, 0x76, 0xf2, 0x7f, 0xf5, 0x78, + 0xd8, 0x55, 0xdf, 0x52, 0xd6, 0x5b, 0xd1, 0x5c, + 0xc4, 0x49, 0xc3, 0x4e, 0xca, 0x47, 0xcd, 0x40, + 0x90, 0x1d, 0x97, 0x1a, 0x9e, 0x13, 0x99, 0x14, + 0x8c, 0x01, 0x8b, 0x06, 0x82, 0x0f, 0x85, 0x08, + 0xa8, 0x25, 0xaf, 0x22, 0xa6, 0x2b, 0xa1, 0x2c, + 0xb4, 0x39, 0xb3, 0x3e, 0xba, 0x37, 0xbd, 0x30, + 0xdd, 0x50, 0xda, 0x57, 0xd3, 0x5e, 0xd4, 0x59, + 0xc1, 0x4c, 0xc6, 0x4b, 0xcf, 0x42, 0xc8, 0x45, + 0xe5, 0x68, 0xe2, 0x6f, 0xeb, 0x66, 0xec, 0x61, + 0xf9, 0x74, 0xfe, 0x73, 0xf7, 0x7a, 0xf0, 0x7d, + 0xad, 0x20, 0xaa, 0x27, 0xa3, 0x2e, 0xa4, 0x29, + 0xb1, 0x3c, 0xb6, 0x3b, 0xbf, 0x32, 0xb8, 0x35, + 0x95, 0x18, 0x92, 0x1f, 0x9b, 0x16, 0x9c, 0x11, + 0x89, 0x04, 0x8e, 0x03, 0x87, 0x0a, 0x80, 0x0d, + 0x3d, 0xb0, 0x3a, 0xb7, 0x33, 0xbe, 0x34, 0xb9, + 0x21, 0xac, 0x26, 0xab, 0x2f, 0xa2, 0x28, 0xa5, + 0x05, 0x88, 0x02, 0x8f, 0x0b, 0x86, 0x0c, 0x81, + 0x19, 0x94, 0x1e, 0x93, 0x17, 0x9a, 0x10, 0x9d, + 0x4d, 0xc0, 0x4a, 0xc7, 0x43, 0xce, 0x44, 0xc9, + 0x51, 0xdc, 0x56, 0xdb, 0x5f, 0xd2, 0x58, 0xd5, + 0x75, 0xf8, 0x72, 0xff, 0x7b, 0xf6, 0x7c, 0xf1, + 0x69, 0xe4, 0x6e, 0xe3, 0x67, 0xea, 0x60, 0xed, + }, + { + 0x00, 0x8e, 0x01, 0x8f, 0x02, 0x8c, 0x03, 0x8d, + 0x04, 0x8a, 0x05, 0x8b, 0x06, 0x88, 0x07, 0x89, + 0x08, 0x86, 0x09, 0x87, 0x0a, 0x84, 0x0b, 0x85, + 0x0c, 0x82, 0x0d, 0x83, 0x0e, 0x80, 0x0f, 0x81, + 0x10, 0x9e, 0x11, 0x9f, 0x12, 0x9c, 0x13, 0x9d, + 0x14, 0x9a, 0x15, 0x9b, 0x16, 0x98, 0x17, 0x99, + 0x18, 0x96, 0x19, 0x97, 0x1a, 0x94, 0x1b, 0x95, + 0x1c, 0x92, 0x1d, 0x93, 0x1e, 0x90, 0x1f, 0x91, + 0x20, 0xae, 0x21, 0xaf, 0x22, 0xac, 0x23, 0xad, + 0x24, 0xaa, 0x25, 0xab, 0x26, 0xa8, 0x27, 0xa9, + 0x28, 0xa6, 0x29, 0xa7, 0x2a, 0xa4, 0x2b, 0xa5, + 0x2c, 0xa2, 0x2d, 0xa3, 0x2e, 0xa0, 0x2f, 0xa1, + 0x30, 0xbe, 0x31, 0xbf, 0x32, 0xbc, 0x33, 0xbd, + 0x34, 0xba, 0x35, 0xbb, 0x36, 0xb8, 0x37, 0xb9, + 0x38, 0xb6, 0x39, 0xb7, 0x3a, 0xb4, 0x3b, 0xb5, + 0x3c, 0xb2, 0x3d, 0xb3, 0x3e, 0xb0, 0x3f, 0xb1, + 0x40, 0xce, 0x41, 0xcf, 0x42, 0xcc, 0x43, 0xcd, + 0x44, 0xca, 0x45, 0xcb, 0x46, 0xc8, 0x47, 0xc9, + 0x48, 0xc6, 0x49, 0xc7, 0x4a, 0xc4, 0x4b, 0xc5, + 0x4c, 0xc2, 0x4d, 0xc3, 0x4e, 0xc0, 0x4f, 0xc1, + 0x50, 0xde, 0x51, 0xdf, 0x52, 0xdc, 0x53, 0xdd, + 0x54, 0xda, 0x55, 0xdb, 0x56, 0xd8, 0x57, 0xd9, + 0x58, 0xd6, 0x59, 0xd7, 0x5a, 0xd4, 0x5b, 0xd5, + 0x5c, 0xd2, 0x5d, 0xd3, 0x5e, 0xd0, 0x5f, 0xd1, + 0x60, 0xee, 0x61, 0xef, 0x62, 0xec, 0x63, 0xed, + 0x64, 0xea, 0x65, 0xeb, 0x66, 0xe8, 0x67, 0xe9, + 0x68, 0xe6, 0x69, 0xe7, 0x6a, 0xe4, 0x6b, 0xe5, + 0x6c, 0xe2, 0x6d, 0xe3, 0x6e, 0xe0, 0x6f, 0xe1, + 0x70, 0xfe, 0x71, 0xff, 0x72, 0xfc, 0x73, 0xfd, + 0x74, 0xfa, 0x75, 0xfb, 0x76, 0xf8, 0x77, 0xf9, + 0x78, 0xf6, 0x79, 0xf7, 0x7a, 0xf4, 0x7b, 0xf5, + 0x7c, 0xf2, 0x7d, 0xf3, 0x7e, 0xf0, 0x7f, 0xf1, + }, + { + 0x00, 0x8f, 0x03, 0x8c, 0x06, 0x89, 0x05, 0x8a, + 0x0c, 0x83, 0x0f, 0x80, 0x0a, 0x85, 0x09, 0x86, + 0x18, 0x97, 0x1b, 0x94, 0x1e, 0x91, 0x1d, 0x92, + 0x14, 0x9b, 0x17, 0x98, 0x12, 0x9d, 0x11, 0x9e, + 0x30, 0xbf, 0x33, 0xbc, 0x36, 0xb9, 0x35, 0xba, + 0x3c, 0xb3, 0x3f, 0xb0, 0x3a, 0xb5, 0x39, 0xb6, + 0x28, 0xa7, 0x2b, 0xa4, 0x2e, 0xa1, 0x2d, 0xa2, + 0x24, 0xab, 0x27, 0xa8, 0x22, 0xad, 0x21, 0xae, + 0x60, 0xef, 0x63, 0xec, 0x66, 0xe9, 0x65, 0xea, + 0x6c, 0xe3, 0x6f, 0xe0, 0x6a, 0xe5, 0x69, 0xe6, + 0x78, 0xf7, 0x7b, 0xf4, 0x7e, 0xf1, 0x7d, 0xf2, + 0x74, 0xfb, 0x77, 0xf8, 0x72, 0xfd, 0x71, 0xfe, + 0x50, 0xdf, 0x53, 0xdc, 0x56, 0xd9, 0x55, 0xda, + 0x5c, 0xd3, 0x5f, 0xd0, 0x5a, 0xd5, 0x59, 0xd6, + 0x48, 0xc7, 0x4b, 0xc4, 0x4e, 0xc1, 0x4d, 0xc2, + 0x44, 0xcb, 0x47, 0xc8, 0x42, 0xcd, 0x41, 0xce, + 0xc0, 0x4f, 0xc3, 0x4c, 0xc6, 0x49, 0xc5, 0x4a, + 0xcc, 0x43, 0xcf, 0x40, 0xca, 0x45, 0xc9, 0x46, + 0xd8, 0x57, 0xdb, 0x54, 0xde, 0x51, 0xdd, 0x52, + 0xd4, 0x5b, 0xd7, 0x58, 0xd2, 0x5d, 0xd1, 0x5e, + 0xf0, 0x7f, 0xf3, 0x7c, 0xf6, 0x79, 0xf5, 0x7a, + 0xfc, 0x73, 0xff, 0x70, 0xfa, 0x75, 0xf9, 0x76, + 0xe8, 0x67, 0xeb, 0x64, 0xee, 0x61, 0xed, 0x62, + 0xe4, 0x6b, 0xe7, 0x68, 0xe2, 0x6d, 0xe1, 0x6e, + 0xa0, 0x2f, 0xa3, 0x2c, 0xa6, 0x29, 0xa5, 0x2a, + 0xac, 0x23, 0xaf, 0x20, 0xaa, 0x25, 0xa9, 0x26, + 0xb8, 0x37, 0xbb, 0x34, 0xbe, 0x31, 0xbd, 0x32, + 0xb4, 0x3b, 0xb7, 0x38, 0xb2, 0x3d, 0xb1, 0x3e, + 0x90, 0x1f, 0x93, 0x1c, 0x96, 0x19, 0x95, 0x1a, + 0x9c, 0x13, 0x9f, 0x10, 0x9a, 0x15, 0x99, 0x16, + 0x88, 0x07, 0x8b, 0x04, 0x8e, 0x01, 0x8d, 0x02, + 0x84, 0x0b, 0x87, 0x08, 0x82, 0x0d, 0x81, 0x0e, + }, + { + 0x00, 0x90, 0x3d, 0xad, 0x7a, 0xea, 0x47, 0xd7, + 0xf4, 0x64, 0xc9, 0x59, 0x8e, 0x1e, 0xb3, 0x23, + 0xf5, 0x65, 0xc8, 0x58, 0x8f, 0x1f, 0xb2, 0x22, + 0x01, 0x91, 0x3c, 0xac, 0x7b, 0xeb, 0x46, 0xd6, + 0xf7, 0x67, 0xca, 0x5a, 0x8d, 0x1d, 0xb0, 0x20, + 0x03, 0x93, 0x3e, 0xae, 0x79, 0xe9, 0x44, 0xd4, + 0x02, 0x92, 0x3f, 0xaf, 0x78, 0xe8, 0x45, 0xd5, + 0xf6, 0x66, 0xcb, 0x5b, 0x8c, 0x1c, 0xb1, 0x21, + 0xf3, 0x63, 0xce, 0x5e, 0x89, 0x19, 0xb4, 0x24, + 0x07, 0x97, 0x3a, 0xaa, 0x7d, 0xed, 0x40, 0xd0, + 0x06, 0x96, 0x3b, 0xab, 0x7c, 0xec, 0x41, 0xd1, + 0xf2, 0x62, 0xcf, 0x5f, 0x88, 0x18, 0xb5, 0x25, + 0x04, 0x94, 0x39, 0xa9, 0x7e, 0xee, 0x43, 0xd3, + 0xf0, 0x60, 0xcd, 0x5d, 0x8a, 0x1a, 0xb7, 0x27, + 0xf1, 0x61, 0xcc, 0x5c, 0x8b, 0x1b, 0xb6, 0x26, + 0x05, 0x95, 0x38, 0xa8, 0x7f, 0xef, 0x42, 0xd2, + 0xfb, 0x6b, 0xc6, 0x56, 0x81, 0x11, 0xbc, 0x2c, + 0x0f, 0x9f, 0x32, 0xa2, 0x75, 0xe5, 0x48, 0xd8, + 0x0e, 0x9e, 0x33, 0xa3, 0x74, 0xe4, 0x49, 0xd9, + 0xfa, 0x6a, 0xc7, 0x57, 0x80, 0x10, 0xbd, 0x2d, + 0x0c, 0x9c, 0x31, 0xa1, 0x76, 0xe6, 0x4b, 0xdb, + 0xf8, 0x68, 0xc5, 0x55, 0x82, 0x12, 0xbf, 0x2f, + 0xf9, 0x69, 0xc4, 0x54, 0x83, 0x13, 0xbe, 0x2e, + 0x0d, 0x9d, 0x30, 0xa0, 0x77, 0xe7, 0x4a, 0xda, + 0x08, 0x98, 0x35, 0xa5, 0x72, 0xe2, 0x4f, 0xdf, + 0xfc, 0x6c, 0xc1, 0x51, 0x86, 0x16, 0xbb, 0x2b, + 0xfd, 0x6d, 0xc0, 0x50, 0x87, 0x17, 0xba, 0x2a, + 0x09, 0x99, 0x34, 0xa4, 0x73, 0xe3, 0x4e, 0xde, + 0xff, 0x6f, 0xc2, 0x52, 0x85, 0x15, 0xb8, 0x28, + 0x0b, 0x9b, 0x36, 0xa6, 0x71, 0xe1, 0x4c, 0xdc, + 0x0a, 0x9a, 0x37, 0xa7, 0x70, 0xe0, 0x4d, 0xdd, + 0xfe, 0x6e, 0xc3, 0x53, 0x84, 0x14, 0xb9, 0x29, + }, + { + 0x00, 0x91, 0x3f, 0xae, 0x7e, 0xef, 0x41, 0xd0, + 0xfc, 0x6d, 0xc3, 0x52, 0x82, 0x13, 0xbd, 0x2c, + 0xe5, 0x74, 0xda, 0x4b, 0x9b, 0x0a, 0xa4, 0x35, + 0x19, 0x88, 0x26, 0xb7, 0x67, 0xf6, 0x58, 0xc9, + 0xd7, 0x46, 0xe8, 0x79, 0xa9, 0x38, 0x96, 0x07, + 0x2b, 0xba, 0x14, 0x85, 0x55, 0xc4, 0x6a, 0xfb, + 0x32, 0xa3, 0x0d, 0x9c, 0x4c, 0xdd, 0x73, 0xe2, + 0xce, 0x5f, 0xf1, 0x60, 0xb0, 0x21, 0x8f, 0x1e, + 0xb3, 0x22, 0x8c, 0x1d, 0xcd, 0x5c, 0xf2, 0x63, + 0x4f, 0xde, 0x70, 0xe1, 0x31, 0xa0, 0x0e, 0x9f, + 0x56, 0xc7, 0x69, 0xf8, 0x28, 0xb9, 0x17, 0x86, + 0xaa, 0x3b, 0x95, 0x04, 0xd4, 0x45, 0xeb, 0x7a, + 0x64, 0xf5, 0x5b, 0xca, 0x1a, 0x8b, 0x25, 0xb4, + 0x98, 0x09, 0xa7, 0x36, 0xe6, 0x77, 0xd9, 0x48, + 0x81, 0x10, 0xbe, 0x2f, 0xff, 0x6e, 0xc0, 0x51, + 0x7d, 0xec, 0x42, 0xd3, 0x03, 0x92, 0x3c, 0xad, + 0x7b, 0xea, 0x44, 0xd5, 0x05, 0x94, 0x3a, 0xab, + 0x87, 0x16, 0xb8, 0x29, 0xf9, 0x68, 0xc6, 0x57, + 0x9e, 0x0f, 0xa1, 0x30, 0xe0, 0x71, 0xdf, 0x4e, + 0x62, 0xf3, 0x5d, 0xcc, 0x1c, 0x8d, 0x23, 0xb2, + 0xac, 0x3d, 0x93, 0x02, 0xd2, 0x43, 0xed, 0x7c, + 0x50, 0xc1, 0x6f, 0xfe, 0x2e, 0xbf, 0x11, 0x80, + 0x49, 0xd8, 0x76, 0xe7, 0x37, 0xa6, 0x08, 0x99, + 0xb5, 0x24, 0x8a, 0x1b, 0xcb, 0x5a, 0xf4, 0x65, + 0xc8, 0x59, 0xf7, 0x66, 0xb6, 0x27, 0x89, 0x18, + 0x34, 0xa5, 0x0b, 0x9a, 0x4a, 0xdb, 0x75, 0xe4, + 0x2d, 0xbc, 0x12, 0x83, 0x53, 0xc2, 0x6c, 0xfd, + 0xd1, 0x40, 0xee, 0x7f, 0xaf, 0x3e, 0x90, 0x01, + 0x1f, 0x8e, 0x20, 0xb1, 0x61, 0xf0, 0x5e, 0xcf, + 0xe3, 0x72, 0xdc, 0x4d, 0x9d, 0x0c, 0xa2, 0x33, + 0xfa, 0x6b, 0xc5, 0x54, 0x84, 0x15, 0xbb, 0x2a, + 0x06, 0x97, 0x39, 0xa8, 0x78, 0xe9, 0x47, 0xd6, + }, + { + 0x00, 0x92, 0x39, 0xab, 0x72, 0xe0, 0x4b, 0xd9, + 0xe4, 0x76, 0xdd, 0x4f, 0x96, 0x04, 0xaf, 0x3d, + 0xd5, 0x47, 0xec, 0x7e, 0xa7, 0x35, 0x9e, 0x0c, + 0x31, 0xa3, 0x08, 0x9a, 0x43, 0xd1, 0x7a, 0xe8, + 0xb7, 0x25, 0x8e, 0x1c, 0xc5, 0x57, 0xfc, 0x6e, + 0x53, 0xc1, 0x6a, 0xf8, 0x21, 0xb3, 0x18, 0x8a, + 0x62, 0xf0, 0x5b, 0xc9, 0x10, 0x82, 0x29, 0xbb, + 0x86, 0x14, 0xbf, 0x2d, 0xf4, 0x66, 0xcd, 0x5f, + 0x73, 0xe1, 0x4a, 0xd8, 0x01, 0x93, 0x38, 0xaa, + 0x97, 0x05, 0xae, 0x3c, 0xe5, 0x77, 0xdc, 0x4e, + 0xa6, 0x34, 0x9f, 0x0d, 0xd4, 0x46, 0xed, 0x7f, + 0x42, 0xd0, 0x7b, 0xe9, 0x30, 0xa2, 0x09, 0x9b, + 0xc4, 0x56, 0xfd, 0x6f, 0xb6, 0x24, 0x8f, 0x1d, + 0x20, 0xb2, 0x19, 0x8b, 0x52, 0xc0, 0x6b, 0xf9, + 0x11, 0x83, 0x28, 0xba, 0x63, 0xf1, 0x5a, 0xc8, + 0xf5, 0x67, 0xcc, 0x5e, 0x87, 0x15, 0xbe, 0x2c, + 0xe6, 0x74, 0xdf, 0x4d, 0x94, 0x06, 0xad, 0x3f, + 0x02, 0x90, 0x3b, 0xa9, 0x70, 0xe2, 0x49, 0xdb, + 0x33, 0xa1, 0x0a, 0x98, 0x41, 0xd3, 0x78, 0xea, + 0xd7, 0x45, 0xee, 0x7c, 0xa5, 0x37, 0x9c, 0x0e, + 0x51, 0xc3, 0x68, 0xfa, 0x23, 0xb1, 0x1a, 0x88, + 0xb5, 0x27, 0x8c, 0x1e, 0xc7, 0x55, 0xfe, 0x6c, + 0x84, 0x16, 0xbd, 0x2f, 0xf6, 0x64, 0xcf, 0x5d, + 0x60, 0xf2, 0x59, 0xcb, 0x12, 0x80, 0x2b, 0xb9, + 0x95, 0x07, 0xac, 0x3e, 0xe7, 0x75, 0xde, 0x4c, + 0x71, 0xe3, 0x48, 0xda, 0x03, 0x91, 0x3a, 0xa8, + 0x40, 0xd2, 0x79, 0xeb, 0x32, 0xa0, 0x0b, 0x99, + 0xa4, 0x36, 0x9d, 0x0f, 0xd6, 0x44, 0xef, 0x7d, + 0x22, 0xb0, 0x1b, 0x89, 0x50, 0xc2, 0x69, 0xfb, + 0xc6, 0x54, 0xff, 0x6d, 0xb4, 0x26, 0x8d, 0x1f, + 0xf7, 0x65, 0xce, 0x5c, 0x85, 0x17, 0xbc, 0x2e, + 0x13, 0x81, 0x2a, 0xb8, 0x61, 0xf3, 0x58, 0xca, + }, + { + 0x00, 0x93, 0x3b, 0xa8, 0x76, 0xe5, 0x4d, 0xde, + 0xec, 0x7f, 0xd7, 0x44, 0x9a, 0x09, 0xa1, 0x32, + 0xc5, 0x56, 0xfe, 0x6d, 0xb3, 0x20, 0x88, 0x1b, + 0x29, 0xba, 0x12, 0x81, 0x5f, 0xcc, 0x64, 0xf7, + 0x97, 0x04, 0xac, 0x3f, 0xe1, 0x72, 0xda, 0x49, + 0x7b, 0xe8, 0x40, 0xd3, 0x0d, 0x9e, 0x36, 0xa5, + 0x52, 0xc1, 0x69, 0xfa, 0x24, 0xb7, 0x1f, 0x8c, + 0xbe, 0x2d, 0x85, 0x16, 0xc8, 0x5b, 0xf3, 0x60, + 0x33, 0xa0, 0x08, 0x9b, 0x45, 0xd6, 0x7e, 0xed, + 0xdf, 0x4c, 0xe4, 0x77, 0xa9, 0x3a, 0x92, 0x01, + 0xf6, 0x65, 0xcd, 0x5e, 0x80, 0x13, 0xbb, 0x28, + 0x1a, 0x89, 0x21, 0xb2, 0x6c, 0xff, 0x57, 0xc4, + 0xa4, 0x37, 0x9f, 0x0c, 0xd2, 0x41, 0xe9, 0x7a, + 0x48, 0xdb, 0x73, 0xe0, 0x3e, 0xad, 0x05, 0x96, + 0x61, 0xf2, 0x5a, 0xc9, 0x17, 0x84, 0x2c, 0xbf, + 0x8d, 0x1e, 0xb6, 0x25, 0xfb, 0x68, 0xc0, 0x53, + 0x66, 0xf5, 0x5d, 0xce, 0x10, 0x83, 0x2b, 0xb8, + 0x8a, 0x19, 0xb1, 0x22, 0xfc, 0x6f, 0xc7, 0x54, + 0xa3, 0x30, 0x98, 0x0b, 0xd5, 0x46, 0xee, 0x7d, + 0x4f, 0xdc, 0x74, 0xe7, 0x39, 0xaa, 0x02, 0x91, + 0xf1, 0x62, 0xca, 0x59, 0x87, 0x14, 0xbc, 0x2f, + 0x1d, 0x8e, 0x26, 0xb5, 0x6b, 0xf8, 0x50, 0xc3, + 0x34, 0xa7, 0x0f, 0x9c, 0x42, 0xd1, 0x79, 0xea, + 0xd8, 0x4b, 0xe3, 0x70, 0xae, 0x3d, 0x95, 0x06, + 0x55, 0xc6, 0x6e, 0xfd, 0x23, 0xb0, 0x18, 0x8b, + 0xb9, 0x2a, 0x82, 0x11, 0xcf, 0x5c, 0xf4, 0x67, + 0x90, 0x03, 0xab, 0x38, 0xe6, 0x75, 0xdd, 0x4e, + 0x7c, 0xef, 0x47, 0xd4, 0x0a, 0x99, 0x31, 0xa2, + 0xc2, 0x51, 0xf9, 0x6a, 0xb4, 0x27, 0x8f, 0x1c, + 0x2e, 0xbd, 0x15, 0x86, 0x58, 0xcb, 0x63, 0xf0, + 0x07, 0x94, 0x3c, 0xaf, 0x71, 0xe2, 0x4a, 0xd9, + 0xeb, 0x78, 0xd0, 0x43, 0x9d, 0x0e, 0xa6, 0x35, + }, + { + 0x00, 0x94, 0x35, 0xa1, 0x6a, 0xfe, 0x5f, 0xcb, + 0xd4, 0x40, 0xe1, 0x75, 0xbe, 0x2a, 0x8b, 0x1f, + 0xb5, 0x21, 0x80, 0x14, 0xdf, 0x4b, 0xea, 0x7e, + 0x61, 0xf5, 0x54, 0xc0, 0x0b, 0x9f, 0x3e, 0xaa, + 0x77, 0xe3, 0x42, 0xd6, 0x1d, 0x89, 0x28, 0xbc, + 0xa3, 0x37, 0x96, 0x02, 0xc9, 0x5d, 0xfc, 0x68, + 0xc2, 0x56, 0xf7, 0x63, 0xa8, 0x3c, 0x9d, 0x09, + 0x16, 0x82, 0x23, 0xb7, 0x7c, 0xe8, 0x49, 0xdd, + 0xee, 0x7a, 0xdb, 0x4f, 0x84, 0x10, 0xb1, 0x25, + 0x3a, 0xae, 0x0f, 0x9b, 0x50, 0xc4, 0x65, 0xf1, + 0x5b, 0xcf, 0x6e, 0xfa, 0x31, 0xa5, 0x04, 0x90, + 0x8f, 0x1b, 0xba, 0x2e, 0xe5, 0x71, 0xd0, 0x44, + 0x99, 0x0d, 0xac, 0x38, 0xf3, 0x67, 0xc6, 0x52, + 0x4d, 0xd9, 0x78, 0xec, 0x27, 0xb3, 0x12, 0x86, + 0x2c, 0xb8, 0x19, 0x8d, 0x46, 0xd2, 0x73, 0xe7, + 0xf8, 0x6c, 0xcd, 0x59, 0x92, 0x06, 0xa7, 0x33, + 0xc1, 0x55, 0xf4, 0x60, 0xab, 0x3f, 0x9e, 0x0a, + 0x15, 0x81, 0x20, 0xb4, 0x7f, 0xeb, 0x4a, 0xde, + 0x74, 0xe0, 0x41, 0xd5, 0x1e, 0x8a, 0x2b, 0xbf, + 0xa0, 0x34, 0x95, 0x01, 0xca, 0x5e, 0xff, 0x6b, + 0xb6, 0x22, 0x83, 0x17, 0xdc, 0x48, 0xe9, 0x7d, + 0x62, 0xf6, 0x57, 0xc3, 0x08, 0x9c, 0x3d, 0xa9, + 0x03, 0x97, 0x36, 0xa2, 0x69, 0xfd, 0x5c, 0xc8, + 0xd7, 0x43, 0xe2, 0x76, 0xbd, 0x29, 0x88, 0x1c, + 0x2f, 0xbb, 0x1a, 0x8e, 0x45, 0xd1, 0x70, 0xe4, + 0xfb, 0x6f, 0xce, 0x5a, 0x91, 0x05, 0xa4, 0x30, + 0x9a, 0x0e, 0xaf, 0x3b, 0xf0, 0x64, 0xc5, 0x51, + 0x4e, 0xda, 0x7b, 0xef, 0x24, 0xb0, 0x11, 0x85, + 0x58, 0xcc, 0x6d, 0xf9, 0x32, 0xa6, 0x07, 0x93, + 0x8c, 0x18, 0xb9, 0x2d, 0xe6, 0x72, 0xd3, 0x47, + 0xed, 0x79, 0xd8, 0x4c, 0x87, 0x13, 0xb2, 0x26, + 0x39, 0xad, 0x0c, 0x98, 0x53, 0xc7, 0x66, 0xf2, + }, + { + 0x00, 0x95, 0x37, 0xa2, 0x6e, 0xfb, 0x59, 0xcc, + 0xdc, 0x49, 0xeb, 0x7e, 0xb2, 0x27, 0x85, 0x10, + 0xa5, 0x30, 0x92, 0x07, 0xcb, 0x5e, 0xfc, 0x69, + 0x79, 0xec, 0x4e, 0xdb, 0x17, 0x82, 0x20, 0xb5, + 0x57, 0xc2, 0x60, 0xf5, 0x39, 0xac, 0x0e, 0x9b, + 0x8b, 0x1e, 0xbc, 0x29, 0xe5, 0x70, 0xd2, 0x47, + 0xf2, 0x67, 0xc5, 0x50, 0x9c, 0x09, 0xab, 0x3e, + 0x2e, 0xbb, 0x19, 0x8c, 0x40, 0xd5, 0x77, 0xe2, + 0xae, 0x3b, 0x99, 0x0c, 0xc0, 0x55, 0xf7, 0x62, + 0x72, 0xe7, 0x45, 0xd0, 0x1c, 0x89, 0x2b, 0xbe, + 0x0b, 0x9e, 0x3c, 0xa9, 0x65, 0xf0, 0x52, 0xc7, + 0xd7, 0x42, 0xe0, 0x75, 0xb9, 0x2c, 0x8e, 0x1b, + 0xf9, 0x6c, 0xce, 0x5b, 0x97, 0x02, 0xa0, 0x35, + 0x25, 0xb0, 0x12, 0x87, 0x4b, 0xde, 0x7c, 0xe9, + 0x5c, 0xc9, 0x6b, 0xfe, 0x32, 0xa7, 0x05, 0x90, + 0x80, 0x15, 0xb7, 0x22, 0xee, 0x7b, 0xd9, 0x4c, + 0x41, 0xd4, 0x76, 0xe3, 0x2f, 0xba, 0x18, 0x8d, + 0x9d, 0x08, 0xaa, 0x3f, 0xf3, 0x66, 0xc4, 0x51, + 0xe4, 0x71, 0xd3, 0x46, 0x8a, 0x1f, 0xbd, 0x28, + 0x38, 0xad, 0x0f, 0x9a, 0x56, 0xc3, 0x61, 0xf4, + 0x16, 0x83, 0x21, 0xb4, 0x78, 0xed, 0x4f, 0xda, + 0xca, 0x5f, 0xfd, 0x68, 0xa4, 0x31, 0x93, 0x06, + 0xb3, 0x26, 0x84, 0x11, 0xdd, 0x48, 0xea, 0x7f, + 0x6f, 0xfa, 0x58, 0xcd, 0x01, 0x94, 0x36, 0xa3, + 0xef, 0x7a, 0xd8, 0x4d, 0x81, 0x14, 0xb6, 0x23, + 0x33, 0xa6, 0x04, 0x91, 0x5d, 0xc8, 0x6a, 0xff, + 0x4a, 0xdf, 0x7d, 0xe8, 0x24, 0xb1, 0x13, 0x86, + 0x96, 0x03, 0xa1, 0x34, 0xf8, 0x6d, 0xcf, 0x5a, + 0xb8, 0x2d, 0x8f, 0x1a, 0xd6, 0x43, 0xe1, 0x74, + 0x64, 0xf1, 0x53, 0xc6, 0x0a, 0x9f, 0x3d, 0xa8, + 0x1d, 0x88, 0x2a, 0xbf, 0x73, 0xe6, 0x44, 0xd1, + 0xc1, 0x54, 0xf6, 0x63, 0xaf, 0x3a, 0x98, 0x0d, + }, + { + 0x00, 0x96, 0x31, 0xa7, 0x62, 0xf4, 0x53, 0xc5, + 0xc4, 0x52, 0xf5, 0x63, 0xa6, 0x30, 0x97, 0x01, + 0x95, 0x03, 0xa4, 0x32, 0xf7, 0x61, 0xc6, 0x50, + 0x51, 0xc7, 0x60, 0xf6, 0x33, 0xa5, 0x02, 0x94, + 0x37, 0xa1, 0x06, 0x90, 0x55, 0xc3, 0x64, 0xf2, + 0xf3, 0x65, 0xc2, 0x54, 0x91, 0x07, 0xa0, 0x36, + 0xa2, 0x34, 0x93, 0x05, 0xc0, 0x56, 0xf1, 0x67, + 0x66, 0xf0, 0x57, 0xc1, 0x04, 0x92, 0x35, 0xa3, + 0x6e, 0xf8, 0x5f, 0xc9, 0x0c, 0x9a, 0x3d, 0xab, + 0xaa, 0x3c, 0x9b, 0x0d, 0xc8, 0x5e, 0xf9, 0x6f, + 0xfb, 0x6d, 0xca, 0x5c, 0x99, 0x0f, 0xa8, 0x3e, + 0x3f, 0xa9, 0x0e, 0x98, 0x5d, 0xcb, 0x6c, 0xfa, + 0x59, 0xcf, 0x68, 0xfe, 0x3b, 0xad, 0x0a, 0x9c, + 0x9d, 0x0b, 0xac, 0x3a, 0xff, 0x69, 0xce, 0x58, + 0xcc, 0x5a, 0xfd, 0x6b, 0xae, 0x38, 0x9f, 0x09, + 0x08, 0x9e, 0x39, 0xaf, 0x6a, 0xfc, 0x5b, 0xcd, + 0xdc, 0x4a, 0xed, 0x7b, 0xbe, 0x28, 0x8f, 0x19, + 0x18, 0x8e, 0x29, 0xbf, 0x7a, 0xec, 0x4b, 0xdd, + 0x49, 0xdf, 0x78, 0xee, 0x2b, 0xbd, 0x1a, 0x8c, + 0x8d, 0x1b, 0xbc, 0x2a, 0xef, 0x79, 0xde, 0x48, + 0xeb, 0x7d, 0xda, 0x4c, 0x89, 0x1f, 0xb8, 0x2e, + 0x2f, 0xb9, 0x1e, 0x88, 0x4d, 0xdb, 0x7c, 0xea, + 0x7e, 0xe8, 0x4f, 0xd9, 0x1c, 0x8a, 0x2d, 0xbb, + 0xba, 0x2c, 0x8b, 0x1d, 0xd8, 0x4e, 0xe9, 0x7f, + 0xb2, 0x24, 0x83, 0x15, 0xd0, 0x46, 0xe1, 0x77, + 0x76, 0xe0, 0x47, 0xd1, 0x14, 0x82, 0x25, 0xb3, + 0x27, 0xb1, 0x16, 0x80, 0x45, 0xd3, 0x74, 0xe2, + 0xe3, 0x75, 0xd2, 0x44, 0x81, 0x17, 0xb0, 0x26, + 0x85, 0x13, 0xb4, 0x22, 0xe7, 0x71, 0xd6, 0x40, + 0x41, 0xd7, 0x70, 0xe6, 0x23, 0xb5, 0x12, 0x84, + 0x10, 0x86, 0x21, 0xb7, 0x72, 0xe4, 0x43, 0xd5, + 0xd4, 0x42, 0xe5, 0x73, 0xb6, 0x20, 0x87, 0x11, + }, + { + 0x00, 0x97, 0x33, 0xa4, 0x66, 0xf1, 0x55, 0xc2, + 0xcc, 0x5b, 0xff, 0x68, 0xaa, 0x3d, 0x99, 0x0e, + 0x85, 0x12, 0xb6, 0x21, 0xe3, 0x74, 0xd0, 0x47, + 0x49, 0xde, 0x7a, 0xed, 0x2f, 0xb8, 0x1c, 0x8b, + 0x17, 0x80, 0x24, 0xb3, 0x71, 0xe6, 0x42, 0xd5, + 0xdb, 0x4c, 0xe8, 0x7f, 0xbd, 0x2a, 0x8e, 0x19, + 0x92, 0x05, 0xa1, 0x36, 0xf4, 0x63, 0xc7, 0x50, + 0x5e, 0xc9, 0x6d, 0xfa, 0x38, 0xaf, 0x0b, 0x9c, + 0x2e, 0xb9, 0x1d, 0x8a, 0x48, 0xdf, 0x7b, 0xec, + 0xe2, 0x75, 0xd1, 0x46, 0x84, 0x13, 0xb7, 0x20, + 0xab, 0x3c, 0x98, 0x0f, 0xcd, 0x5a, 0xfe, 0x69, + 0x67, 0xf0, 0x54, 0xc3, 0x01, 0x96, 0x32, 0xa5, + 0x39, 0xae, 0x0a, 0x9d, 0x5f, 0xc8, 0x6c, 0xfb, + 0xf5, 0x62, 0xc6, 0x51, 0x93, 0x04, 0xa0, 0x37, + 0xbc, 0x2b, 0x8f, 0x18, 0xda, 0x4d, 0xe9, 0x7e, + 0x70, 0xe7, 0x43, 0xd4, 0x16, 0x81, 0x25, 0xb2, + 0x5c, 0xcb, 0x6f, 0xf8, 0x3a, 0xad, 0x09, 0x9e, + 0x90, 0x07, 0xa3, 0x34, 0xf6, 0x61, 0xc5, 0x52, + 0xd9, 0x4e, 0xea, 0x7d, 0xbf, 0x28, 0x8c, 0x1b, + 0x15, 0x82, 0x26, 0xb1, 0x73, 0xe4, 0x40, 0xd7, + 0x4b, 0xdc, 0x78, 0xef, 0x2d, 0xba, 0x1e, 0x89, + 0x87, 0x10, 0xb4, 0x23, 0xe1, 0x76, 0xd2, 0x45, + 0xce, 0x59, 0xfd, 0x6a, 0xa8, 0x3f, 0x9b, 0x0c, + 0x02, 0x95, 0x31, 0xa6, 0x64, 0xf3, 0x57, 0xc0, + 0x72, 0xe5, 0x41, 0xd6, 0x14, 0x83, 0x27, 0xb0, + 0xbe, 0x29, 0x8d, 0x1a, 0xd8, 0x4f, 0xeb, 0x7c, + 0xf7, 0x60, 0xc4, 0x53, 0x91, 0x06, 0xa2, 0x35, + 0x3b, 0xac, 0x08, 0x9f, 0x5d, 0xca, 0x6e, 0xf9, + 0x65, 0xf2, 0x56, 0xc1, 0x03, 0x94, 0x30, 0xa7, + 0xa9, 0x3e, 0x9a, 0x0d, 0xcf, 0x58, 0xfc, 0x6b, + 0xe0, 0x77, 0xd3, 0x44, 0x86, 0x11, 0xb5, 0x22, + 0x2c, 0xbb, 0x1f, 0x88, 0x4a, 0xdd, 0x79, 0xee, + }, + { + 0x00, 0x98, 0x2d, 0xb5, 0x5a, 0xc2, 0x77, 0xef, + 0xb4, 0x2c, 0x99, 0x01, 0xee, 0x76, 0xc3, 0x5b, + 0x75, 0xed, 0x58, 0xc0, 0x2f, 0xb7, 0x02, 0x9a, + 0xc1, 0x59, 0xec, 0x74, 0x9b, 0x03, 0xb6, 0x2e, + 0xea, 0x72, 0xc7, 0x5f, 0xb0, 0x28, 0x9d, 0x05, + 0x5e, 0xc6, 0x73, 0xeb, 0x04, 0x9c, 0x29, 0xb1, + 0x9f, 0x07, 0xb2, 0x2a, 0xc5, 0x5d, 0xe8, 0x70, + 0x2b, 0xb3, 0x06, 0x9e, 0x71, 0xe9, 0x5c, 0xc4, + 0xc9, 0x51, 0xe4, 0x7c, 0x93, 0x0b, 0xbe, 0x26, + 0x7d, 0xe5, 0x50, 0xc8, 0x27, 0xbf, 0x0a, 0x92, + 0xbc, 0x24, 0x91, 0x09, 0xe6, 0x7e, 0xcb, 0x53, + 0x08, 0x90, 0x25, 0xbd, 0x52, 0xca, 0x7f, 0xe7, + 0x23, 0xbb, 0x0e, 0x96, 0x79, 0xe1, 0x54, 0xcc, + 0x97, 0x0f, 0xba, 0x22, 0xcd, 0x55, 0xe0, 0x78, + 0x56, 0xce, 0x7b, 0xe3, 0x0c, 0x94, 0x21, 0xb9, + 0xe2, 0x7a, 0xcf, 0x57, 0xb8, 0x20, 0x95, 0x0d, + 0x8f, 0x17, 0xa2, 0x3a, 0xd5, 0x4d, 0xf8, 0x60, + 0x3b, 0xa3, 0x16, 0x8e, 0x61, 0xf9, 0x4c, 0xd4, + 0xfa, 0x62, 0xd7, 0x4f, 0xa0, 0x38, 0x8d, 0x15, + 0x4e, 0xd6, 0x63, 0xfb, 0x14, 0x8c, 0x39, 0xa1, + 0x65, 0xfd, 0x48, 0xd0, 0x3f, 0xa7, 0x12, 0x8a, + 0xd1, 0x49, 0xfc, 0x64, 0x8b, 0x13, 0xa6, 0x3e, + 0x10, 0x88, 0x3d, 0xa5, 0x4a, 0xd2, 0x67, 0xff, + 0xa4, 0x3c, 0x89, 0x11, 0xfe, 0x66, 0xd3, 0x4b, + 0x46, 0xde, 0x6b, 0xf3, 0x1c, 0x84, 0x31, 0xa9, + 0xf2, 0x6a, 0xdf, 0x47, 0xa8, 0x30, 0x85, 0x1d, + 0x33, 0xab, 0x1e, 0x86, 0x69, 0xf1, 0x44, 0xdc, + 0x87, 0x1f, 0xaa, 0x32, 0xdd, 0x45, 0xf0, 0x68, + 0xac, 0x34, 0x81, 0x19, 0xf6, 0x6e, 0xdb, 0x43, + 0x18, 0x80, 0x35, 0xad, 0x42, 0xda, 0x6f, 0xf7, + 0xd9, 0x41, 0xf4, 0x6c, 0x83, 0x1b, 0xae, 0x36, + 0x6d, 0xf5, 0x40, 0xd8, 0x37, 0xaf, 0x1a, 0x82, + }, + { + 0x00, 0x99, 0x2f, 0xb6, 0x5e, 0xc7, 0x71, 0xe8, + 0xbc, 0x25, 0x93, 0x0a, 0xe2, 0x7b, 0xcd, 0x54, + 0x65, 0xfc, 0x4a, 0xd3, 0x3b, 0xa2, 0x14, 0x8d, + 0xd9, 0x40, 0xf6, 0x6f, 0x87, 0x1e, 0xa8, 0x31, + 0xca, 0x53, 0xe5, 0x7c, 0x94, 0x0d, 0xbb, 0x22, + 0x76, 0xef, 0x59, 0xc0, 0x28, 0xb1, 0x07, 0x9e, + 0xaf, 0x36, 0x80, 0x19, 0xf1, 0x68, 0xde, 0x47, + 0x13, 0x8a, 0x3c, 0xa5, 0x4d, 0xd4, 0x62, 0xfb, + 0x89, 0x10, 0xa6, 0x3f, 0xd7, 0x4e, 0xf8, 0x61, + 0x35, 0xac, 0x1a, 0x83, 0x6b, 0xf2, 0x44, 0xdd, + 0xec, 0x75, 0xc3, 0x5a, 0xb2, 0x2b, 0x9d, 0x04, + 0x50, 0xc9, 0x7f, 0xe6, 0x0e, 0x97, 0x21, 0xb8, + 0x43, 0xda, 0x6c, 0xf5, 0x1d, 0x84, 0x32, 0xab, + 0xff, 0x66, 0xd0, 0x49, 0xa1, 0x38, 0x8e, 0x17, + 0x26, 0xbf, 0x09, 0x90, 0x78, 0xe1, 0x57, 0xce, + 0x9a, 0x03, 0xb5, 0x2c, 0xc4, 0x5d, 0xeb, 0x72, + 0x0f, 0x96, 0x20, 0xb9, 0x51, 0xc8, 0x7e, 0xe7, + 0xb3, 0x2a, 0x9c, 0x05, 0xed, 0x74, 0xc2, 0x5b, + 0x6a, 0xf3, 0x45, 0xdc, 0x34, 0xad, 0x1b, 0x82, + 0xd6, 0x4f, 0xf9, 0x60, 0x88, 0x11, 0xa7, 0x3e, + 0xc5, 0x5c, 0xea, 0x73, 0x9b, 0x02, 0xb4, 0x2d, + 0x79, 0xe0, 0x56, 0xcf, 0x27, 0xbe, 0x08, 0x91, + 0xa0, 0x39, 0x8f, 0x16, 0xfe, 0x67, 0xd1, 0x48, + 0x1c, 0x85, 0x33, 0xaa, 0x42, 0xdb, 0x6d, 0xf4, + 0x86, 0x1f, 0xa9, 0x30, 0xd8, 0x41, 0xf7, 0x6e, + 0x3a, 0xa3, 0x15, 0x8c, 0x64, 0xfd, 0x4b, 0xd2, + 0xe3, 0x7a, 0xcc, 0x55, 0xbd, 0x24, 0x92, 0x0b, + 0x5f, 0xc6, 0x70, 0xe9, 0x01, 0x98, 0x2e, 0xb7, + 0x4c, 0xd5, 0x63, 0xfa, 0x12, 0x8b, 0x3d, 0xa4, + 0xf0, 0x69, 0xdf, 0x46, 0xae, 0x37, 0x81, 0x18, + 0x29, 0xb0, 0x06, 0x9f, 0x77, 0xee, 0x58, 0xc1, + 0x95, 0x0c, 0xba, 0x23, 0xcb, 0x52, 0xe4, 0x7d, + }, + { + 0x00, 0x9a, 0x29, 0xb3, 0x52, 0xc8, 0x7b, 0xe1, + 0xa4, 0x3e, 0x8d, 0x17, 0xf6, 0x6c, 0xdf, 0x45, + 0x55, 0xcf, 0x7c, 0xe6, 0x07, 0x9d, 0x2e, 0xb4, + 0xf1, 0x6b, 0xd8, 0x42, 0xa3, 0x39, 0x8a, 0x10, + 0xaa, 0x30, 0x83, 0x19, 0xf8, 0x62, 0xd1, 0x4b, + 0x0e, 0x94, 0x27, 0xbd, 0x5c, 0xc6, 0x75, 0xef, + 0xff, 0x65, 0xd6, 0x4c, 0xad, 0x37, 0x84, 0x1e, + 0x5b, 0xc1, 0x72, 0xe8, 0x09, 0x93, 0x20, 0xba, + 0x49, 0xd3, 0x60, 0xfa, 0x1b, 0x81, 0x32, 0xa8, + 0xed, 0x77, 0xc4, 0x5e, 0xbf, 0x25, 0x96, 0x0c, + 0x1c, 0x86, 0x35, 0xaf, 0x4e, 0xd4, 0x67, 0xfd, + 0xb8, 0x22, 0x91, 0x0b, 0xea, 0x70, 0xc3, 0x59, + 0xe3, 0x79, 0xca, 0x50, 0xb1, 0x2b, 0x98, 0x02, + 0x47, 0xdd, 0x6e, 0xf4, 0x15, 0x8f, 0x3c, 0xa6, + 0xb6, 0x2c, 0x9f, 0x05, 0xe4, 0x7e, 0xcd, 0x57, + 0x12, 0x88, 0x3b, 0xa1, 0x40, 0xda, 0x69, 0xf3, + 0x92, 0x08, 0xbb, 0x21, 0xc0, 0x5a, 0xe9, 0x73, + 0x36, 0xac, 0x1f, 0x85, 0x64, 0xfe, 0x4d, 0xd7, + 0xc7, 0x5d, 0xee, 0x74, 0x95, 0x0f, 0xbc, 0x26, + 0x63, 0xf9, 0x4a, 0xd0, 0x31, 0xab, 0x18, 0x82, + 0x38, 0xa2, 0x11, 0x8b, 0x6a, 0xf0, 0x43, 0xd9, + 0x9c, 0x06, 0xb5, 0x2f, 0xce, 0x54, 0xe7, 0x7d, + 0x6d, 0xf7, 0x44, 0xde, 0x3f, 0xa5, 0x16, 0x8c, + 0xc9, 0x53, 0xe0, 0x7a, 0x9b, 0x01, 0xb2, 0x28, + 0xdb, 0x41, 0xf2, 0x68, 0x89, 0x13, 0xa0, 0x3a, + 0x7f, 0xe5, 0x56, 0xcc, 0x2d, 0xb7, 0x04, 0x9e, + 0x8e, 0x14, 0xa7, 0x3d, 0xdc, 0x46, 0xf5, 0x6f, + 0x2a, 0xb0, 0x03, 0x99, 0x78, 0xe2, 0x51, 0xcb, + 0x71, 0xeb, 0x58, 0xc2, 0x23, 0xb9, 0x0a, 0x90, + 0xd5, 0x4f, 0xfc, 0x66, 0x87, 0x1d, 0xae, 0x34, + 0x24, 0xbe, 0x0d, 0x97, 0x76, 0xec, 0x5f, 0xc5, + 0x80, 0x1a, 0xa9, 0x33, 0xd2, 0x48, 0xfb, 0x61, + }, + { + 0x00, 0x9b, 0x2b, 0xb0, 0x56, 0xcd, 0x7d, 0xe6, + 0xac, 0x37, 0x87, 0x1c, 0xfa, 0x61, 0xd1, 0x4a, + 0x45, 0xde, 0x6e, 0xf5, 0x13, 0x88, 0x38, 0xa3, + 0xe9, 0x72, 0xc2, 0x59, 0xbf, 0x24, 0x94, 0x0f, + 0x8a, 0x11, 0xa1, 0x3a, 0xdc, 0x47, 0xf7, 0x6c, + 0x26, 0xbd, 0x0d, 0x96, 0x70, 0xeb, 0x5b, 0xc0, + 0xcf, 0x54, 0xe4, 0x7f, 0x99, 0x02, 0xb2, 0x29, + 0x63, 0xf8, 0x48, 0xd3, 0x35, 0xae, 0x1e, 0x85, + 0x09, 0x92, 0x22, 0xb9, 0x5f, 0xc4, 0x74, 0xef, + 0xa5, 0x3e, 0x8e, 0x15, 0xf3, 0x68, 0xd8, 0x43, + 0x4c, 0xd7, 0x67, 0xfc, 0x1a, 0x81, 0x31, 0xaa, + 0xe0, 0x7b, 0xcb, 0x50, 0xb6, 0x2d, 0x9d, 0x06, + 0x83, 0x18, 0xa8, 0x33, 0xd5, 0x4e, 0xfe, 0x65, + 0x2f, 0xb4, 0x04, 0x9f, 0x79, 0xe2, 0x52, 0xc9, + 0xc6, 0x5d, 0xed, 0x76, 0x90, 0x0b, 0xbb, 0x20, + 0x6a, 0xf1, 0x41, 0xda, 0x3c, 0xa7, 0x17, 0x8c, + 0x12, 0x89, 0x39, 0xa2, 0x44, 0xdf, 0x6f, 0xf4, + 0xbe, 0x25, 0x95, 0x0e, 0xe8, 0x73, 0xc3, 0x58, + 0x57, 0xcc, 0x7c, 0xe7, 0x01, 0x9a, 0x2a, 0xb1, + 0xfb, 0x60, 0xd0, 0x4b, 0xad, 0x36, 0x86, 0x1d, + 0x98, 0x03, 0xb3, 0x28, 0xce, 0x55, 0xe5, 0x7e, + 0x34, 0xaf, 0x1f, 0x84, 0x62, 0xf9, 0x49, 0xd2, + 0xdd, 0x46, 0xf6, 0x6d, 0x8b, 0x10, 0xa0, 0x3b, + 0x71, 0xea, 0x5a, 0xc1, 0x27, 0xbc, 0x0c, 0x97, + 0x1b, 0x80, 0x30, 0xab, 0x4d, 0xd6, 0x66, 0xfd, + 0xb7, 0x2c, 0x9c, 0x07, 0xe1, 0x7a, 0xca, 0x51, + 0x5e, 0xc5, 0x75, 0xee, 0x08, 0x93, 0x23, 0xb8, + 0xf2, 0x69, 0xd9, 0x42, 0xa4, 0x3f, 0x8f, 0x14, + 0x91, 0x0a, 0xba, 0x21, 0xc7, 0x5c, 0xec, 0x77, + 0x3d, 0xa6, 0x16, 0x8d, 0x6b, 0xf0, 0x40, 0xdb, + 0xd4, 0x4f, 0xff, 0x64, 0x82, 0x19, 0xa9, 0x32, + 0x78, 0xe3, 0x53, 0xc8, 0x2e, 0xb5, 0x05, 0x9e, + }, + { + 0x00, 0x9c, 0x25, 0xb9, 0x4a, 0xd6, 0x6f, 0xf3, + 0x94, 0x08, 0xb1, 0x2d, 0xde, 0x42, 0xfb, 0x67, + 0x35, 0xa9, 0x10, 0x8c, 0x7f, 0xe3, 0x5a, 0xc6, + 0xa1, 0x3d, 0x84, 0x18, 0xeb, 0x77, 0xce, 0x52, + 0x6a, 0xf6, 0x4f, 0xd3, 0x20, 0xbc, 0x05, 0x99, + 0xfe, 0x62, 0xdb, 0x47, 0xb4, 0x28, 0x91, 0x0d, + 0x5f, 0xc3, 0x7a, 0xe6, 0x15, 0x89, 0x30, 0xac, + 0xcb, 0x57, 0xee, 0x72, 0x81, 0x1d, 0xa4, 0x38, + 0xd4, 0x48, 0xf1, 0x6d, 0x9e, 0x02, 0xbb, 0x27, + 0x40, 0xdc, 0x65, 0xf9, 0x0a, 0x96, 0x2f, 0xb3, + 0xe1, 0x7d, 0xc4, 0x58, 0xab, 0x37, 0x8e, 0x12, + 0x75, 0xe9, 0x50, 0xcc, 0x3f, 0xa3, 0x1a, 0x86, + 0xbe, 0x22, 0x9b, 0x07, 0xf4, 0x68, 0xd1, 0x4d, + 0x2a, 0xb6, 0x0f, 0x93, 0x60, 0xfc, 0x45, 0xd9, + 0x8b, 0x17, 0xae, 0x32, 0xc1, 0x5d, 0xe4, 0x78, + 0x1f, 0x83, 0x3a, 0xa6, 0x55, 0xc9, 0x70, 0xec, + 0xb5, 0x29, 0x90, 0x0c, 0xff, 0x63, 0xda, 0x46, + 0x21, 0xbd, 0x04, 0x98, 0x6b, 0xf7, 0x4e, 0xd2, + 0x80, 0x1c, 0xa5, 0x39, 0xca, 0x56, 0xef, 0x73, + 0x14, 0x88, 0x31, 0xad, 0x5e, 0xc2, 0x7b, 0xe7, + 0xdf, 0x43, 0xfa, 0x66, 0x95, 0x09, 0xb0, 0x2c, + 0x4b, 0xd7, 0x6e, 0xf2, 0x01, 0x9d, 0x24, 0xb8, + 0xea, 0x76, 0xcf, 0x53, 0xa0, 0x3c, 0x85, 0x19, + 0x7e, 0xe2, 0x5b, 0xc7, 0x34, 0xa8, 0x11, 0x8d, + 0x61, 0xfd, 0x44, 0xd8, 0x2b, 0xb7, 0x0e, 0x92, + 0xf5, 0x69, 0xd0, 0x4c, 0xbf, 0x23, 0x9a, 0x06, + 0x54, 0xc8, 0x71, 0xed, 0x1e, 0x82, 0x3b, 0xa7, + 0xc0, 0x5c, 0xe5, 0x79, 0x8a, 0x16, 0xaf, 0x33, + 0x0b, 0x97, 0x2e, 0xb2, 0x41, 0xdd, 0x64, 0xf8, + 0x9f, 0x03, 0xba, 0x26, 0xd5, 0x49, 0xf0, 0x6c, + 0x3e, 0xa2, 0x1b, 0x87, 0x74, 0xe8, 0x51, 0xcd, + 0xaa, 0x36, 0x8f, 0x13, 0xe0, 0x7c, 0xc5, 0x59, + }, + { + 0x00, 0x9d, 0x27, 0xba, 0x4e, 0xd3, 0x69, 0xf4, + 0x9c, 0x01, 0xbb, 0x26, 0xd2, 0x4f, 0xf5, 0x68, + 0x25, 0xb8, 0x02, 0x9f, 0x6b, 0xf6, 0x4c, 0xd1, + 0xb9, 0x24, 0x9e, 0x03, 0xf7, 0x6a, 0xd0, 0x4d, + 0x4a, 0xd7, 0x6d, 0xf0, 0x04, 0x99, 0x23, 0xbe, + 0xd6, 0x4b, 0xf1, 0x6c, 0x98, 0x05, 0xbf, 0x22, + 0x6f, 0xf2, 0x48, 0xd5, 0x21, 0xbc, 0x06, 0x9b, + 0xf3, 0x6e, 0xd4, 0x49, 0xbd, 0x20, 0x9a, 0x07, + 0x94, 0x09, 0xb3, 0x2e, 0xda, 0x47, 0xfd, 0x60, + 0x08, 0x95, 0x2f, 0xb2, 0x46, 0xdb, 0x61, 0xfc, + 0xb1, 0x2c, 0x96, 0x0b, 0xff, 0x62, 0xd8, 0x45, + 0x2d, 0xb0, 0x0a, 0x97, 0x63, 0xfe, 0x44, 0xd9, + 0xde, 0x43, 0xf9, 0x64, 0x90, 0x0d, 0xb7, 0x2a, + 0x42, 0xdf, 0x65, 0xf8, 0x0c, 0x91, 0x2b, 0xb6, + 0xfb, 0x66, 0xdc, 0x41, 0xb5, 0x28, 0x92, 0x0f, + 0x67, 0xfa, 0x40, 0xdd, 0x29, 0xb4, 0x0e, 0x93, + 0x35, 0xa8, 0x12, 0x8f, 0x7b, 0xe6, 0x5c, 0xc1, + 0xa9, 0x34, 0x8e, 0x13, 0xe7, 0x7a, 0xc0, 0x5d, + 0x10, 0x8d, 0x37, 0xaa, 0x5e, 0xc3, 0x79, 0xe4, + 0x8c, 0x11, 0xab, 0x36, 0xc2, 0x5f, 0xe5, 0x78, + 0x7f, 0xe2, 0x58, 0xc5, 0x31, 0xac, 0x16, 0x8b, + 0xe3, 0x7e, 0xc4, 0x59, 0xad, 0x30, 0x8a, 0x17, + 0x5a, 0xc7, 0x7d, 0xe0, 0x14, 0x89, 0x33, 0xae, + 0xc6, 0x5b, 0xe1, 0x7c, 0x88, 0x15, 0xaf, 0x32, + 0xa1, 0x3c, 0x86, 0x1b, 0xef, 0x72, 0xc8, 0x55, + 0x3d, 0xa0, 0x1a, 0x87, 0x73, 0xee, 0x54, 0xc9, + 0x84, 0x19, 0xa3, 0x3e, 0xca, 0x57, 0xed, 0x70, + 0x18, 0x85, 0x3f, 0xa2, 0x56, 0xcb, 0x71, 0xec, + 0xeb, 0x76, 0xcc, 0x51, 0xa5, 0x38, 0x82, 0x1f, + 0x77, 0xea, 0x50, 0xcd, 0x39, 0xa4, 0x1e, 0x83, + 0xce, 0x53, 0xe9, 0x74, 0x80, 0x1d, 0xa7, 0x3a, + 0x52, 0xcf, 0x75, 0xe8, 0x1c, 0x81, 0x3b, 0xa6, + }, + { + 0x00, 0x9e, 0x21, 0xbf, 0x42, 0xdc, 0x63, 0xfd, + 0x84, 0x1a, 0xa5, 0x3b, 0xc6, 0x58, 0xe7, 0x79, + 0x15, 0x8b, 0x34, 0xaa, 0x57, 0xc9, 0x76, 0xe8, + 0x91, 0x0f, 0xb0, 0x2e, 0xd3, 0x4d, 0xf2, 0x6c, + 0x2a, 0xb4, 0x0b, 0x95, 0x68, 0xf6, 0x49, 0xd7, + 0xae, 0x30, 0x8f, 0x11, 0xec, 0x72, 0xcd, 0x53, + 0x3f, 0xa1, 0x1e, 0x80, 0x7d, 0xe3, 0x5c, 0xc2, + 0xbb, 0x25, 0x9a, 0x04, 0xf9, 0x67, 0xd8, 0x46, + 0x54, 0xca, 0x75, 0xeb, 0x16, 0x88, 0x37, 0xa9, + 0xd0, 0x4e, 0xf1, 0x6f, 0x92, 0x0c, 0xb3, 0x2d, + 0x41, 0xdf, 0x60, 0xfe, 0x03, 0x9d, 0x22, 0xbc, + 0xc5, 0x5b, 0xe4, 0x7a, 0x87, 0x19, 0xa6, 0x38, + 0x7e, 0xe0, 0x5f, 0xc1, 0x3c, 0xa2, 0x1d, 0x83, + 0xfa, 0x64, 0xdb, 0x45, 0xb8, 0x26, 0x99, 0x07, + 0x6b, 0xf5, 0x4a, 0xd4, 0x29, 0xb7, 0x08, 0x96, + 0xef, 0x71, 0xce, 0x50, 0xad, 0x33, 0x8c, 0x12, + 0xa8, 0x36, 0x89, 0x17, 0xea, 0x74, 0xcb, 0x55, + 0x2c, 0xb2, 0x0d, 0x93, 0x6e, 0xf0, 0x4f, 0xd1, + 0xbd, 0x23, 0x9c, 0x02, 0xff, 0x61, 0xde, 0x40, + 0x39, 0xa7, 0x18, 0x86, 0x7b, 0xe5, 0x5a, 0xc4, + 0x82, 0x1c, 0xa3, 0x3d, 0xc0, 0x5e, 0xe1, 0x7f, + 0x06, 0x98, 0x27, 0xb9, 0x44, 0xda, 0x65, 0xfb, + 0x97, 0x09, 0xb6, 0x28, 0xd5, 0x4b, 0xf4, 0x6a, + 0x13, 0x8d, 0x32, 0xac, 0x51, 0xcf, 0x70, 0xee, + 0xfc, 0x62, 0xdd, 0x43, 0xbe, 0x20, 0x9f, 0x01, + 0x78, 0xe6, 0x59, 0xc7, 0x3a, 0xa4, 0x1b, 0x85, + 0xe9, 0x77, 0xc8, 0x56, 0xab, 0x35, 0x8a, 0x14, + 0x6d, 0xf3, 0x4c, 0xd2, 0x2f, 0xb1, 0x0e, 0x90, + 0xd6, 0x48, 0xf7, 0x69, 0x94, 0x0a, 0xb5, 0x2b, + 0x52, 0xcc, 0x73, 0xed, 0x10, 0x8e, 0x31, 0xaf, + 0xc3, 0x5d, 0xe2, 0x7c, 0x81, 0x1f, 0xa0, 0x3e, + 0x47, 0xd9, 0x66, 0xf8, 0x05, 0x9b, 0x24, 0xba, + }, + { + 0x00, 0x9f, 0x23, 0xbc, 0x46, 0xd9, 0x65, 0xfa, + 0x8c, 0x13, 0xaf, 0x30, 0xca, 0x55, 0xe9, 0x76, + 0x05, 0x9a, 0x26, 0xb9, 0x43, 0xdc, 0x60, 0xff, + 0x89, 0x16, 0xaa, 0x35, 0xcf, 0x50, 0xec, 0x73, + 0x0a, 0x95, 0x29, 0xb6, 0x4c, 0xd3, 0x6f, 0xf0, + 0x86, 0x19, 0xa5, 0x3a, 0xc0, 0x5f, 0xe3, 0x7c, + 0x0f, 0x90, 0x2c, 0xb3, 0x49, 0xd6, 0x6a, 0xf5, + 0x83, 0x1c, 0xa0, 0x3f, 0xc5, 0x5a, 0xe6, 0x79, + 0x14, 0x8b, 0x37, 0xa8, 0x52, 0xcd, 0x71, 0xee, + 0x98, 0x07, 0xbb, 0x24, 0xde, 0x41, 0xfd, 0x62, + 0x11, 0x8e, 0x32, 0xad, 0x57, 0xc8, 0x74, 0xeb, + 0x9d, 0x02, 0xbe, 0x21, 0xdb, 0x44, 0xf8, 0x67, + 0x1e, 0x81, 0x3d, 0xa2, 0x58, 0xc7, 0x7b, 0xe4, + 0x92, 0x0d, 0xb1, 0x2e, 0xd4, 0x4b, 0xf7, 0x68, + 0x1b, 0x84, 0x38, 0xa7, 0x5d, 0xc2, 0x7e, 0xe1, + 0x97, 0x08, 0xb4, 0x2b, 0xd1, 0x4e, 0xf2, 0x6d, + 0x28, 0xb7, 0x0b, 0x94, 0x6e, 0xf1, 0x4d, 0xd2, + 0xa4, 0x3b, 0x87, 0x18, 0xe2, 0x7d, 0xc1, 0x5e, + 0x2d, 0xb2, 0x0e, 0x91, 0x6b, 0xf4, 0x48, 0xd7, + 0xa1, 0x3e, 0x82, 0x1d, 0xe7, 0x78, 0xc4, 0x5b, + 0x22, 0xbd, 0x01, 0x9e, 0x64, 0xfb, 0x47, 0xd8, + 0xae, 0x31, 0x8d, 0x12, 0xe8, 0x77, 0xcb, 0x54, + 0x27, 0xb8, 0x04, 0x9b, 0x61, 0xfe, 0x42, 0xdd, + 0xab, 0x34, 0x88, 0x17, 0xed, 0x72, 0xce, 0x51, + 0x3c, 0xa3, 0x1f, 0x80, 0x7a, 0xe5, 0x59, 0xc6, + 0xb0, 0x2f, 0x93, 0x0c, 0xf6, 0x69, 0xd5, 0x4a, + 0x39, 0xa6, 0x1a, 0x85, 0x7f, 0xe0, 0x5c, 0xc3, + 0xb5, 0x2a, 0x96, 0x09, 0xf3, 0x6c, 0xd0, 0x4f, + 0x36, 0xa9, 0x15, 0x8a, 0x70, 0xef, 0x53, 0xcc, + 0xba, 0x25, 0x99, 0x06, 0xfc, 0x63, 0xdf, 0x40, + 0x33, 0xac, 0x10, 0x8f, 0x75, 0xea, 0x56, 0xc9, + 0xbf, 0x20, 0x9c, 0x03, 0xf9, 0x66, 0xda, 0x45, + }, + { + 0x00, 0xa0, 0x5d, 0xfd, 0xba, 0x1a, 0xe7, 0x47, + 0x69, 0xc9, 0x34, 0x94, 0xd3, 0x73, 0x8e, 0x2e, + 0xd2, 0x72, 0x8f, 0x2f, 0x68, 0xc8, 0x35, 0x95, + 0xbb, 0x1b, 0xe6, 0x46, 0x01, 0xa1, 0x5c, 0xfc, + 0xb9, 0x19, 0xe4, 0x44, 0x03, 0xa3, 0x5e, 0xfe, + 0xd0, 0x70, 0x8d, 0x2d, 0x6a, 0xca, 0x37, 0x97, + 0x6b, 0xcb, 0x36, 0x96, 0xd1, 0x71, 0x8c, 0x2c, + 0x02, 0xa2, 0x5f, 0xff, 0xb8, 0x18, 0xe5, 0x45, + 0x6f, 0xcf, 0x32, 0x92, 0xd5, 0x75, 0x88, 0x28, + 0x06, 0xa6, 0x5b, 0xfb, 0xbc, 0x1c, 0xe1, 0x41, + 0xbd, 0x1d, 0xe0, 0x40, 0x07, 0xa7, 0x5a, 0xfa, + 0xd4, 0x74, 0x89, 0x29, 0x6e, 0xce, 0x33, 0x93, + 0xd6, 0x76, 0x8b, 0x2b, 0x6c, 0xcc, 0x31, 0x91, + 0xbf, 0x1f, 0xe2, 0x42, 0x05, 0xa5, 0x58, 0xf8, + 0x04, 0xa4, 0x59, 0xf9, 0xbe, 0x1e, 0xe3, 0x43, + 0x6d, 0xcd, 0x30, 0x90, 0xd7, 0x77, 0x8a, 0x2a, + 0xde, 0x7e, 0x83, 0x23, 0x64, 0xc4, 0x39, 0x99, + 0xb7, 0x17, 0xea, 0x4a, 0x0d, 0xad, 0x50, 0xf0, + 0x0c, 0xac, 0x51, 0xf1, 0xb6, 0x16, 0xeb, 0x4b, + 0x65, 0xc5, 0x38, 0x98, 0xdf, 0x7f, 0x82, 0x22, + 0x67, 0xc7, 0x3a, 0x9a, 0xdd, 0x7d, 0x80, 0x20, + 0x0e, 0xae, 0x53, 0xf3, 0xb4, 0x14, 0xe9, 0x49, + 0xb5, 0x15, 0xe8, 0x48, 0x0f, 0xaf, 0x52, 0xf2, + 0xdc, 0x7c, 0x81, 0x21, 0x66, 0xc6, 0x3b, 0x9b, + 0xb1, 0x11, 0xec, 0x4c, 0x0b, 0xab, 0x56, 0xf6, + 0xd8, 0x78, 0x85, 0x25, 0x62, 0xc2, 0x3f, 0x9f, + 0x63, 0xc3, 0x3e, 0x9e, 0xd9, 0x79, 0x84, 0x24, + 0x0a, 0xaa, 0x57, 0xf7, 0xb0, 0x10, 0xed, 0x4d, + 0x08, 0xa8, 0x55, 0xf5, 0xb2, 0x12, 0xef, 0x4f, + 0x61, 0xc1, 0x3c, 0x9c, 0xdb, 0x7b, 0x86, 0x26, + 0xda, 0x7a, 0x87, 0x27, 0x60, 0xc0, 0x3d, 0x9d, + 0xb3, 0x13, 0xee, 0x4e, 0x09, 0xa9, 0x54, 0xf4, + }, + { + 0x00, 0xa1, 0x5f, 0xfe, 0xbe, 0x1f, 0xe1, 0x40, + 0x61, 0xc0, 0x3e, 0x9f, 0xdf, 0x7e, 0x80, 0x21, + 0xc2, 0x63, 0x9d, 0x3c, 0x7c, 0xdd, 0x23, 0x82, + 0xa3, 0x02, 0xfc, 0x5d, 0x1d, 0xbc, 0x42, 0xe3, + 0x99, 0x38, 0xc6, 0x67, 0x27, 0x86, 0x78, 0xd9, + 0xf8, 0x59, 0xa7, 0x06, 0x46, 0xe7, 0x19, 0xb8, + 0x5b, 0xfa, 0x04, 0xa5, 0xe5, 0x44, 0xba, 0x1b, + 0x3a, 0x9b, 0x65, 0xc4, 0x84, 0x25, 0xdb, 0x7a, + 0x2f, 0x8e, 0x70, 0xd1, 0x91, 0x30, 0xce, 0x6f, + 0x4e, 0xef, 0x11, 0xb0, 0xf0, 0x51, 0xaf, 0x0e, + 0xed, 0x4c, 0xb2, 0x13, 0x53, 0xf2, 0x0c, 0xad, + 0x8c, 0x2d, 0xd3, 0x72, 0x32, 0x93, 0x6d, 0xcc, + 0xb6, 0x17, 0xe9, 0x48, 0x08, 0xa9, 0x57, 0xf6, + 0xd7, 0x76, 0x88, 0x29, 0x69, 0xc8, 0x36, 0x97, + 0x74, 0xd5, 0x2b, 0x8a, 0xca, 0x6b, 0x95, 0x34, + 0x15, 0xb4, 0x4a, 0xeb, 0xab, 0x0a, 0xf4, 0x55, + 0x5e, 0xff, 0x01, 0xa0, 0xe0, 0x41, 0xbf, 0x1e, + 0x3f, 0x9e, 0x60, 0xc1, 0x81, 0x20, 0xde, 0x7f, + 0x9c, 0x3d, 0xc3, 0x62, 0x22, 0x83, 0x7d, 0xdc, + 0xfd, 0x5c, 0xa2, 0x03, 0x43, 0xe2, 0x1c, 0xbd, + 0xc7, 0x66, 0x98, 0x39, 0x79, 0xd8, 0x26, 0x87, + 0xa6, 0x07, 0xf9, 0x58, 0x18, 0xb9, 0x47, 0xe6, + 0x05, 0xa4, 0x5a, 0xfb, 0xbb, 0x1a, 0xe4, 0x45, + 0x64, 0xc5, 0x3b, 0x9a, 0xda, 0x7b, 0x85, 0x24, + 0x71, 0xd0, 0x2e, 0x8f, 0xcf, 0x6e, 0x90, 0x31, + 0x10, 0xb1, 0x4f, 0xee, 0xae, 0x0f, 0xf1, 0x50, + 0xb3, 0x12, 0xec, 0x4d, 0x0d, 0xac, 0x52, 0xf3, + 0xd2, 0x73, 0x8d, 0x2c, 0x6c, 0xcd, 0x33, 0x92, + 0xe8, 0x49, 0xb7, 0x16, 0x56, 0xf7, 0x09, 0xa8, + 0x89, 0x28, 0xd6, 0x77, 0x37, 0x96, 0x68, 0xc9, + 0x2a, 0x8b, 0x75, 0xd4, 0x94, 0x35, 0xcb, 0x6a, + 0x4b, 0xea, 0x14, 0xb5, 0xf5, 0x54, 0xaa, 0x0b, + }, + { + 0x00, 0xa2, 0x59, 0xfb, 0xb2, 0x10, 0xeb, 0x49, + 0x79, 0xdb, 0x20, 0x82, 0xcb, 0x69, 0x92, 0x30, + 0xf2, 0x50, 0xab, 0x09, 0x40, 0xe2, 0x19, 0xbb, + 0x8b, 0x29, 0xd2, 0x70, 0x39, 0x9b, 0x60, 0xc2, + 0xf9, 0x5b, 0xa0, 0x02, 0x4b, 0xe9, 0x12, 0xb0, + 0x80, 0x22, 0xd9, 0x7b, 0x32, 0x90, 0x6b, 0xc9, + 0x0b, 0xa9, 0x52, 0xf0, 0xb9, 0x1b, 0xe0, 0x42, + 0x72, 0xd0, 0x2b, 0x89, 0xc0, 0x62, 0x99, 0x3b, + 0xef, 0x4d, 0xb6, 0x14, 0x5d, 0xff, 0x04, 0xa6, + 0x96, 0x34, 0xcf, 0x6d, 0x24, 0x86, 0x7d, 0xdf, + 0x1d, 0xbf, 0x44, 0xe6, 0xaf, 0x0d, 0xf6, 0x54, + 0x64, 0xc6, 0x3d, 0x9f, 0xd6, 0x74, 0x8f, 0x2d, + 0x16, 0xb4, 0x4f, 0xed, 0xa4, 0x06, 0xfd, 0x5f, + 0x6f, 0xcd, 0x36, 0x94, 0xdd, 0x7f, 0x84, 0x26, + 0xe4, 0x46, 0xbd, 0x1f, 0x56, 0xf4, 0x0f, 0xad, + 0x9d, 0x3f, 0xc4, 0x66, 0x2f, 0x8d, 0x76, 0xd4, + 0xc3, 0x61, 0x9a, 0x38, 0x71, 0xd3, 0x28, 0x8a, + 0xba, 0x18, 0xe3, 0x41, 0x08, 0xaa, 0x51, 0xf3, + 0x31, 0x93, 0x68, 0xca, 0x83, 0x21, 0xda, 0x78, + 0x48, 0xea, 0x11, 0xb3, 0xfa, 0x58, 0xa3, 0x01, + 0x3a, 0x98, 0x63, 0xc1, 0x88, 0x2a, 0xd1, 0x73, + 0x43, 0xe1, 0x1a, 0xb8, 0xf1, 0x53, 0xa8, 0x0a, + 0xc8, 0x6a, 0x91, 0x33, 0x7a, 0xd8, 0x23, 0x81, + 0xb1, 0x13, 0xe8, 0x4a, 0x03, 0xa1, 0x5a, 0xf8, + 0x2c, 0x8e, 0x75, 0xd7, 0x9e, 0x3c, 0xc7, 0x65, + 0x55, 0xf7, 0x0c, 0xae, 0xe7, 0x45, 0xbe, 0x1c, + 0xde, 0x7c, 0x87, 0x25, 0x6c, 0xce, 0x35, 0x97, + 0xa7, 0x05, 0xfe, 0x5c, 0x15, 0xb7, 0x4c, 0xee, + 0xd5, 0x77, 0x8c, 0x2e, 0x67, 0xc5, 0x3e, 0x9c, + 0xac, 0x0e, 0xf5, 0x57, 0x1e, 0xbc, 0x47, 0xe5, + 0x27, 0x85, 0x7e, 0xdc, 0x95, 0x37, 0xcc, 0x6e, + 0x5e, 0xfc, 0x07, 0xa5, 0xec, 0x4e, 0xb5, 0x17, + }, + { + 0x00, 0xa3, 0x5b, 0xf8, 0xb6, 0x15, 0xed, 0x4e, + 0x71, 0xd2, 0x2a, 0x89, 0xc7, 0x64, 0x9c, 0x3f, + 0xe2, 0x41, 0xb9, 0x1a, 0x54, 0xf7, 0x0f, 0xac, + 0x93, 0x30, 0xc8, 0x6b, 0x25, 0x86, 0x7e, 0xdd, + 0xd9, 0x7a, 0x82, 0x21, 0x6f, 0xcc, 0x34, 0x97, + 0xa8, 0x0b, 0xf3, 0x50, 0x1e, 0xbd, 0x45, 0xe6, + 0x3b, 0x98, 0x60, 0xc3, 0x8d, 0x2e, 0xd6, 0x75, + 0x4a, 0xe9, 0x11, 0xb2, 0xfc, 0x5f, 0xa7, 0x04, + 0xaf, 0x0c, 0xf4, 0x57, 0x19, 0xba, 0x42, 0xe1, + 0xde, 0x7d, 0x85, 0x26, 0x68, 0xcb, 0x33, 0x90, + 0x4d, 0xee, 0x16, 0xb5, 0xfb, 0x58, 0xa0, 0x03, + 0x3c, 0x9f, 0x67, 0xc4, 0x8a, 0x29, 0xd1, 0x72, + 0x76, 0xd5, 0x2d, 0x8e, 0xc0, 0x63, 0x9b, 0x38, + 0x07, 0xa4, 0x5c, 0xff, 0xb1, 0x12, 0xea, 0x49, + 0x94, 0x37, 0xcf, 0x6c, 0x22, 0x81, 0x79, 0xda, + 0xe5, 0x46, 0xbe, 0x1d, 0x53, 0xf0, 0x08, 0xab, + 0x43, 0xe0, 0x18, 0xbb, 0xf5, 0x56, 0xae, 0x0d, + 0x32, 0x91, 0x69, 0xca, 0x84, 0x27, 0xdf, 0x7c, + 0xa1, 0x02, 0xfa, 0x59, 0x17, 0xb4, 0x4c, 0xef, + 0xd0, 0x73, 0x8b, 0x28, 0x66, 0xc5, 0x3d, 0x9e, + 0x9a, 0x39, 0xc1, 0x62, 0x2c, 0x8f, 0x77, 0xd4, + 0xeb, 0x48, 0xb0, 0x13, 0x5d, 0xfe, 0x06, 0xa5, + 0x78, 0xdb, 0x23, 0x80, 0xce, 0x6d, 0x95, 0x36, + 0x09, 0xaa, 0x52, 0xf1, 0xbf, 0x1c, 0xe4, 0x47, + 0xec, 0x4f, 0xb7, 0x14, 0x5a, 0xf9, 0x01, 0xa2, + 0x9d, 0x3e, 0xc6, 0x65, 0x2b, 0x88, 0x70, 0xd3, + 0x0e, 0xad, 0x55, 0xf6, 0xb8, 0x1b, 0xe3, 0x40, + 0x7f, 0xdc, 0x24, 0x87, 0xc9, 0x6a, 0x92, 0x31, + 0x35, 0x96, 0x6e, 0xcd, 0x83, 0x20, 0xd8, 0x7b, + 0x44, 0xe7, 0x1f, 0xbc, 0xf2, 0x51, 0xa9, 0x0a, + 0xd7, 0x74, 0x8c, 0x2f, 0x61, 0xc2, 0x3a, 0x99, + 0xa6, 0x05, 0xfd, 0x5e, 0x10, 0xb3, 0x4b, 0xe8, + }, + { + 0x00, 0xa4, 0x55, 0xf1, 0xaa, 0x0e, 0xff, 0x5b, + 0x49, 0xed, 0x1c, 0xb8, 0xe3, 0x47, 0xb6, 0x12, + 0x92, 0x36, 0xc7, 0x63, 0x38, 0x9c, 0x6d, 0xc9, + 0xdb, 0x7f, 0x8e, 0x2a, 0x71, 0xd5, 0x24, 0x80, + 0x39, 0x9d, 0x6c, 0xc8, 0x93, 0x37, 0xc6, 0x62, + 0x70, 0xd4, 0x25, 0x81, 0xda, 0x7e, 0x8f, 0x2b, + 0xab, 0x0f, 0xfe, 0x5a, 0x01, 0xa5, 0x54, 0xf0, + 0xe2, 0x46, 0xb7, 0x13, 0x48, 0xec, 0x1d, 0xb9, + 0x72, 0xd6, 0x27, 0x83, 0xd8, 0x7c, 0x8d, 0x29, + 0x3b, 0x9f, 0x6e, 0xca, 0x91, 0x35, 0xc4, 0x60, + 0xe0, 0x44, 0xb5, 0x11, 0x4a, 0xee, 0x1f, 0xbb, + 0xa9, 0x0d, 0xfc, 0x58, 0x03, 0xa7, 0x56, 0xf2, + 0x4b, 0xef, 0x1e, 0xba, 0xe1, 0x45, 0xb4, 0x10, + 0x02, 0xa6, 0x57, 0xf3, 0xa8, 0x0c, 0xfd, 0x59, + 0xd9, 0x7d, 0x8c, 0x28, 0x73, 0xd7, 0x26, 0x82, + 0x90, 0x34, 0xc5, 0x61, 0x3a, 0x9e, 0x6f, 0xcb, + 0xe4, 0x40, 0xb1, 0x15, 0x4e, 0xea, 0x1b, 0xbf, + 0xad, 0x09, 0xf8, 0x5c, 0x07, 0xa3, 0x52, 0xf6, + 0x76, 0xd2, 0x23, 0x87, 0xdc, 0x78, 0x89, 0x2d, + 0x3f, 0x9b, 0x6a, 0xce, 0x95, 0x31, 0xc0, 0x64, + 0xdd, 0x79, 0x88, 0x2c, 0x77, 0xd3, 0x22, 0x86, + 0x94, 0x30, 0xc1, 0x65, 0x3e, 0x9a, 0x6b, 0xcf, + 0x4f, 0xeb, 0x1a, 0xbe, 0xe5, 0x41, 0xb0, 0x14, + 0x06, 0xa2, 0x53, 0xf7, 0xac, 0x08, 0xf9, 0x5d, + 0x96, 0x32, 0xc3, 0x67, 0x3c, 0x98, 0x69, 0xcd, + 0xdf, 0x7b, 0x8a, 0x2e, 0x75, 0xd1, 0x20, 0x84, + 0x04, 0xa0, 0x51, 0xf5, 0xae, 0x0a, 0xfb, 0x5f, + 0x4d, 0xe9, 0x18, 0xbc, 0xe7, 0x43, 0xb2, 0x16, + 0xaf, 0x0b, 0xfa, 0x5e, 0x05, 0xa1, 0x50, 0xf4, + 0xe6, 0x42, 0xb3, 0x17, 0x4c, 0xe8, 0x19, 0xbd, + 0x3d, 0x99, 0x68, 0xcc, 0x97, 0x33, 0xc2, 0x66, + 0x74, 0xd0, 0x21, 0x85, 0xde, 0x7a, 0x8b, 0x2f, + }, + { + 0x00, 0xa5, 0x57, 0xf2, 0xae, 0x0b, 0xf9, 0x5c, + 0x41, 0xe4, 0x16, 0xb3, 0xef, 0x4a, 0xb8, 0x1d, + 0x82, 0x27, 0xd5, 0x70, 0x2c, 0x89, 0x7b, 0xde, + 0xc3, 0x66, 0x94, 0x31, 0x6d, 0xc8, 0x3a, 0x9f, + 0x19, 0xbc, 0x4e, 0xeb, 0xb7, 0x12, 0xe0, 0x45, + 0x58, 0xfd, 0x0f, 0xaa, 0xf6, 0x53, 0xa1, 0x04, + 0x9b, 0x3e, 0xcc, 0x69, 0x35, 0x90, 0x62, 0xc7, + 0xda, 0x7f, 0x8d, 0x28, 0x74, 0xd1, 0x23, 0x86, + 0x32, 0x97, 0x65, 0xc0, 0x9c, 0x39, 0xcb, 0x6e, + 0x73, 0xd6, 0x24, 0x81, 0xdd, 0x78, 0x8a, 0x2f, + 0xb0, 0x15, 0xe7, 0x42, 0x1e, 0xbb, 0x49, 0xec, + 0xf1, 0x54, 0xa6, 0x03, 0x5f, 0xfa, 0x08, 0xad, + 0x2b, 0x8e, 0x7c, 0xd9, 0x85, 0x20, 0xd2, 0x77, + 0x6a, 0xcf, 0x3d, 0x98, 0xc4, 0x61, 0x93, 0x36, + 0xa9, 0x0c, 0xfe, 0x5b, 0x07, 0xa2, 0x50, 0xf5, + 0xe8, 0x4d, 0xbf, 0x1a, 0x46, 0xe3, 0x11, 0xb4, + 0x64, 0xc1, 0x33, 0x96, 0xca, 0x6f, 0x9d, 0x38, + 0x25, 0x80, 0x72, 0xd7, 0x8b, 0x2e, 0xdc, 0x79, + 0xe6, 0x43, 0xb1, 0x14, 0x48, 0xed, 0x1f, 0xba, + 0xa7, 0x02, 0xf0, 0x55, 0x09, 0xac, 0x5e, 0xfb, + 0x7d, 0xd8, 0x2a, 0x8f, 0xd3, 0x76, 0x84, 0x21, + 0x3c, 0x99, 0x6b, 0xce, 0x92, 0x37, 0xc5, 0x60, + 0xff, 0x5a, 0xa8, 0x0d, 0x51, 0xf4, 0x06, 0xa3, + 0xbe, 0x1b, 0xe9, 0x4c, 0x10, 0xb5, 0x47, 0xe2, + 0x56, 0xf3, 0x01, 0xa4, 0xf8, 0x5d, 0xaf, 0x0a, + 0x17, 0xb2, 0x40, 0xe5, 0xb9, 0x1c, 0xee, 0x4b, + 0xd4, 0x71, 0x83, 0x26, 0x7a, 0xdf, 0x2d, 0x88, + 0x95, 0x30, 0xc2, 0x67, 0x3b, 0x9e, 0x6c, 0xc9, + 0x4f, 0xea, 0x18, 0xbd, 0xe1, 0x44, 0xb6, 0x13, + 0x0e, 0xab, 0x59, 0xfc, 0xa0, 0x05, 0xf7, 0x52, + 0xcd, 0x68, 0x9a, 0x3f, 0x63, 0xc6, 0x34, 0x91, + 0x8c, 0x29, 0xdb, 0x7e, 0x22, 0x87, 0x75, 0xd0, + }, + { + 0x00, 0xa6, 0x51, 0xf7, 0xa2, 0x04, 0xf3, 0x55, + 0x59, 0xff, 0x08, 0xae, 0xfb, 0x5d, 0xaa, 0x0c, + 0xb2, 0x14, 0xe3, 0x45, 0x10, 0xb6, 0x41, 0xe7, + 0xeb, 0x4d, 0xba, 0x1c, 0x49, 0xef, 0x18, 0xbe, + 0x79, 0xdf, 0x28, 0x8e, 0xdb, 0x7d, 0x8a, 0x2c, + 0x20, 0x86, 0x71, 0xd7, 0x82, 0x24, 0xd3, 0x75, + 0xcb, 0x6d, 0x9a, 0x3c, 0x69, 0xcf, 0x38, 0x9e, + 0x92, 0x34, 0xc3, 0x65, 0x30, 0x96, 0x61, 0xc7, + 0xf2, 0x54, 0xa3, 0x05, 0x50, 0xf6, 0x01, 0xa7, + 0xab, 0x0d, 0xfa, 0x5c, 0x09, 0xaf, 0x58, 0xfe, + 0x40, 0xe6, 0x11, 0xb7, 0xe2, 0x44, 0xb3, 0x15, + 0x19, 0xbf, 0x48, 0xee, 0xbb, 0x1d, 0xea, 0x4c, + 0x8b, 0x2d, 0xda, 0x7c, 0x29, 0x8f, 0x78, 0xde, + 0xd2, 0x74, 0x83, 0x25, 0x70, 0xd6, 0x21, 0x87, + 0x39, 0x9f, 0x68, 0xce, 0x9b, 0x3d, 0xca, 0x6c, + 0x60, 0xc6, 0x31, 0x97, 0xc2, 0x64, 0x93, 0x35, + 0xf9, 0x5f, 0xa8, 0x0e, 0x5b, 0xfd, 0x0a, 0xac, + 0xa0, 0x06, 0xf1, 0x57, 0x02, 0xa4, 0x53, 0xf5, + 0x4b, 0xed, 0x1a, 0xbc, 0xe9, 0x4f, 0xb8, 0x1e, + 0x12, 0xb4, 0x43, 0xe5, 0xb0, 0x16, 0xe1, 0x47, + 0x80, 0x26, 0xd1, 0x77, 0x22, 0x84, 0x73, 0xd5, + 0xd9, 0x7f, 0x88, 0x2e, 0x7b, 0xdd, 0x2a, 0x8c, + 0x32, 0x94, 0x63, 0xc5, 0x90, 0x36, 0xc1, 0x67, + 0x6b, 0xcd, 0x3a, 0x9c, 0xc9, 0x6f, 0x98, 0x3e, + 0x0b, 0xad, 0x5a, 0xfc, 0xa9, 0x0f, 0xf8, 0x5e, + 0x52, 0xf4, 0x03, 0xa5, 0xf0, 0x56, 0xa1, 0x07, + 0xb9, 0x1f, 0xe8, 0x4e, 0x1b, 0xbd, 0x4a, 0xec, + 0xe0, 0x46, 0xb1, 0x17, 0x42, 0xe4, 0x13, 0xb5, + 0x72, 0xd4, 0x23, 0x85, 0xd0, 0x76, 0x81, 0x27, + 0x2b, 0x8d, 0x7a, 0xdc, 0x89, 0x2f, 0xd8, 0x7e, + 0xc0, 0x66, 0x91, 0x37, 0x62, 0xc4, 0x33, 0x95, + 0x99, 0x3f, 0xc8, 0x6e, 0x3b, 0x9d, 0x6a, 0xcc, + }, + { + 0x00, 0xa7, 0x53, 0xf4, 0xa6, 0x01, 0xf5, 0x52, + 0x51, 0xf6, 0x02, 0xa5, 0xf7, 0x50, 0xa4, 0x03, + 0xa2, 0x05, 0xf1, 0x56, 0x04, 0xa3, 0x57, 0xf0, + 0xf3, 0x54, 0xa0, 0x07, 0x55, 0xf2, 0x06, 0xa1, + 0x59, 0xfe, 0x0a, 0xad, 0xff, 0x58, 0xac, 0x0b, + 0x08, 0xaf, 0x5b, 0xfc, 0xae, 0x09, 0xfd, 0x5a, + 0xfb, 0x5c, 0xa8, 0x0f, 0x5d, 0xfa, 0x0e, 0xa9, + 0xaa, 0x0d, 0xf9, 0x5e, 0x0c, 0xab, 0x5f, 0xf8, + 0xb2, 0x15, 0xe1, 0x46, 0x14, 0xb3, 0x47, 0xe0, + 0xe3, 0x44, 0xb0, 0x17, 0x45, 0xe2, 0x16, 0xb1, + 0x10, 0xb7, 0x43, 0xe4, 0xb6, 0x11, 0xe5, 0x42, + 0x41, 0xe6, 0x12, 0xb5, 0xe7, 0x40, 0xb4, 0x13, + 0xeb, 0x4c, 0xb8, 0x1f, 0x4d, 0xea, 0x1e, 0xb9, + 0xba, 0x1d, 0xe9, 0x4e, 0x1c, 0xbb, 0x4f, 0xe8, + 0x49, 0xee, 0x1a, 0xbd, 0xef, 0x48, 0xbc, 0x1b, + 0x18, 0xbf, 0x4b, 0xec, 0xbe, 0x19, 0xed, 0x4a, + 0x79, 0xde, 0x2a, 0x8d, 0xdf, 0x78, 0x8c, 0x2b, + 0x28, 0x8f, 0x7b, 0xdc, 0x8e, 0x29, 0xdd, 0x7a, + 0xdb, 0x7c, 0x88, 0x2f, 0x7d, 0xda, 0x2e, 0x89, + 0x8a, 0x2d, 0xd9, 0x7e, 0x2c, 0x8b, 0x7f, 0xd8, + 0x20, 0x87, 0x73, 0xd4, 0x86, 0x21, 0xd5, 0x72, + 0x71, 0xd6, 0x22, 0x85, 0xd7, 0x70, 0x84, 0x23, + 0x82, 0x25, 0xd1, 0x76, 0x24, 0x83, 0x77, 0xd0, + 0xd3, 0x74, 0x80, 0x27, 0x75, 0xd2, 0x26, 0x81, + 0xcb, 0x6c, 0x98, 0x3f, 0x6d, 0xca, 0x3e, 0x99, + 0x9a, 0x3d, 0xc9, 0x6e, 0x3c, 0x9b, 0x6f, 0xc8, + 0x69, 0xce, 0x3a, 0x9d, 0xcf, 0x68, 0x9c, 0x3b, + 0x38, 0x9f, 0x6b, 0xcc, 0x9e, 0x39, 0xcd, 0x6a, + 0x92, 0x35, 0xc1, 0x66, 0x34, 0x93, 0x67, 0xc0, + 0xc3, 0x64, 0x90, 0x37, 0x65, 0xc2, 0x36, 0x91, + 0x30, 0x97, 0x63, 0xc4, 0x96, 0x31, 0xc5, 0x62, + 0x61, 0xc6, 0x32, 0x95, 0xc7, 0x60, 0x94, 0x33, + }, + { + 0x00, 0xa8, 0x4d, 0xe5, 0x9a, 0x32, 0xd7, 0x7f, + 0x29, 0x81, 0x64, 0xcc, 0xb3, 0x1b, 0xfe, 0x56, + 0x52, 0xfa, 0x1f, 0xb7, 0xc8, 0x60, 0x85, 0x2d, + 0x7b, 0xd3, 0x36, 0x9e, 0xe1, 0x49, 0xac, 0x04, + 0xa4, 0x0c, 0xe9, 0x41, 0x3e, 0x96, 0x73, 0xdb, + 0x8d, 0x25, 0xc0, 0x68, 0x17, 0xbf, 0x5a, 0xf2, + 0xf6, 0x5e, 0xbb, 0x13, 0x6c, 0xc4, 0x21, 0x89, + 0xdf, 0x77, 0x92, 0x3a, 0x45, 0xed, 0x08, 0xa0, + 0x55, 0xfd, 0x18, 0xb0, 0xcf, 0x67, 0x82, 0x2a, + 0x7c, 0xd4, 0x31, 0x99, 0xe6, 0x4e, 0xab, 0x03, + 0x07, 0xaf, 0x4a, 0xe2, 0x9d, 0x35, 0xd0, 0x78, + 0x2e, 0x86, 0x63, 0xcb, 0xb4, 0x1c, 0xf9, 0x51, + 0xf1, 0x59, 0xbc, 0x14, 0x6b, 0xc3, 0x26, 0x8e, + 0xd8, 0x70, 0x95, 0x3d, 0x42, 0xea, 0x0f, 0xa7, + 0xa3, 0x0b, 0xee, 0x46, 0x39, 0x91, 0x74, 0xdc, + 0x8a, 0x22, 0xc7, 0x6f, 0x10, 0xb8, 0x5d, 0xf5, + 0xaa, 0x02, 0xe7, 0x4f, 0x30, 0x98, 0x7d, 0xd5, + 0x83, 0x2b, 0xce, 0x66, 0x19, 0xb1, 0x54, 0xfc, + 0xf8, 0x50, 0xb5, 0x1d, 0x62, 0xca, 0x2f, 0x87, + 0xd1, 0x79, 0x9c, 0x34, 0x4b, 0xe3, 0x06, 0xae, + 0x0e, 0xa6, 0x43, 0xeb, 0x94, 0x3c, 0xd9, 0x71, + 0x27, 0x8f, 0x6a, 0xc2, 0xbd, 0x15, 0xf0, 0x58, + 0x5c, 0xf4, 0x11, 0xb9, 0xc6, 0x6e, 0x8b, 0x23, + 0x75, 0xdd, 0x38, 0x90, 0xef, 0x47, 0xa2, 0x0a, + 0xff, 0x57, 0xb2, 0x1a, 0x65, 0xcd, 0x28, 0x80, + 0xd6, 0x7e, 0x9b, 0x33, 0x4c, 0xe4, 0x01, 0xa9, + 0xad, 0x05, 0xe0, 0x48, 0x37, 0x9f, 0x7a, 0xd2, + 0x84, 0x2c, 0xc9, 0x61, 0x1e, 0xb6, 0x53, 0xfb, + 0x5b, 0xf3, 0x16, 0xbe, 0xc1, 0x69, 0x8c, 0x24, + 0x72, 0xda, 0x3f, 0x97, 0xe8, 0x40, 0xa5, 0x0d, + 0x09, 0xa1, 0x44, 0xec, 0x93, 0x3b, 0xde, 0x76, + 0x20, 0x88, 0x6d, 0xc5, 0xba, 0x12, 0xf7, 0x5f, + }, + { + 0x00, 0xa9, 0x4f, 0xe6, 0x9e, 0x37, 0xd1, 0x78, + 0x21, 0x88, 0x6e, 0xc7, 0xbf, 0x16, 0xf0, 0x59, + 0x42, 0xeb, 0x0d, 0xa4, 0xdc, 0x75, 0x93, 0x3a, + 0x63, 0xca, 0x2c, 0x85, 0xfd, 0x54, 0xb2, 0x1b, + 0x84, 0x2d, 0xcb, 0x62, 0x1a, 0xb3, 0x55, 0xfc, + 0xa5, 0x0c, 0xea, 0x43, 0x3b, 0x92, 0x74, 0xdd, + 0xc6, 0x6f, 0x89, 0x20, 0x58, 0xf1, 0x17, 0xbe, + 0xe7, 0x4e, 0xa8, 0x01, 0x79, 0xd0, 0x36, 0x9f, + 0x15, 0xbc, 0x5a, 0xf3, 0x8b, 0x22, 0xc4, 0x6d, + 0x34, 0x9d, 0x7b, 0xd2, 0xaa, 0x03, 0xe5, 0x4c, + 0x57, 0xfe, 0x18, 0xb1, 0xc9, 0x60, 0x86, 0x2f, + 0x76, 0xdf, 0x39, 0x90, 0xe8, 0x41, 0xa7, 0x0e, + 0x91, 0x38, 0xde, 0x77, 0x0f, 0xa6, 0x40, 0xe9, + 0xb0, 0x19, 0xff, 0x56, 0x2e, 0x87, 0x61, 0xc8, + 0xd3, 0x7a, 0x9c, 0x35, 0x4d, 0xe4, 0x02, 0xab, + 0xf2, 0x5b, 0xbd, 0x14, 0x6c, 0xc5, 0x23, 0x8a, + 0x2a, 0x83, 0x65, 0xcc, 0xb4, 0x1d, 0xfb, 0x52, + 0x0b, 0xa2, 0x44, 0xed, 0x95, 0x3c, 0xda, 0x73, + 0x68, 0xc1, 0x27, 0x8e, 0xf6, 0x5f, 0xb9, 0x10, + 0x49, 0xe0, 0x06, 0xaf, 0xd7, 0x7e, 0x98, 0x31, + 0xae, 0x07, 0xe1, 0x48, 0x30, 0x99, 0x7f, 0xd6, + 0x8f, 0x26, 0xc0, 0x69, 0x11, 0xb8, 0x5e, 0xf7, + 0xec, 0x45, 0xa3, 0x0a, 0x72, 0xdb, 0x3d, 0x94, + 0xcd, 0x64, 0x82, 0x2b, 0x53, 0xfa, 0x1c, 0xb5, + 0x3f, 0x96, 0x70, 0xd9, 0xa1, 0x08, 0xee, 0x47, + 0x1e, 0xb7, 0x51, 0xf8, 0x80, 0x29, 0xcf, 0x66, + 0x7d, 0xd4, 0x32, 0x9b, 0xe3, 0x4a, 0xac, 0x05, + 0x5c, 0xf5, 0x13, 0xba, 0xc2, 0x6b, 0x8d, 0x24, + 0xbb, 0x12, 0xf4, 0x5d, 0x25, 0x8c, 0x6a, 0xc3, + 0x9a, 0x33, 0xd5, 0x7c, 0x04, 0xad, 0x4b, 0xe2, + 0xf9, 0x50, 0xb6, 0x1f, 0x67, 0xce, 0x28, 0x81, + 0xd8, 0x71, 0x97, 0x3e, 0x46, 0xef, 0x09, 0xa0, + }, + { + 0x00, 0xaa, 0x49, 0xe3, 0x92, 0x38, 0xdb, 0x71, + 0x39, 0x93, 0x70, 0xda, 0xab, 0x01, 0xe2, 0x48, + 0x72, 0xd8, 0x3b, 0x91, 0xe0, 0x4a, 0xa9, 0x03, + 0x4b, 0xe1, 0x02, 0xa8, 0xd9, 0x73, 0x90, 0x3a, + 0xe4, 0x4e, 0xad, 0x07, 0x76, 0xdc, 0x3f, 0x95, + 0xdd, 0x77, 0x94, 0x3e, 0x4f, 0xe5, 0x06, 0xac, + 0x96, 0x3c, 0xdf, 0x75, 0x04, 0xae, 0x4d, 0xe7, + 0xaf, 0x05, 0xe6, 0x4c, 0x3d, 0x97, 0x74, 0xde, + 0xd5, 0x7f, 0x9c, 0x36, 0x47, 0xed, 0x0e, 0xa4, + 0xec, 0x46, 0xa5, 0x0f, 0x7e, 0xd4, 0x37, 0x9d, + 0xa7, 0x0d, 0xee, 0x44, 0x35, 0x9f, 0x7c, 0xd6, + 0x9e, 0x34, 0xd7, 0x7d, 0x0c, 0xa6, 0x45, 0xef, + 0x31, 0x9b, 0x78, 0xd2, 0xa3, 0x09, 0xea, 0x40, + 0x08, 0xa2, 0x41, 0xeb, 0x9a, 0x30, 0xd3, 0x79, + 0x43, 0xe9, 0x0a, 0xa0, 0xd1, 0x7b, 0x98, 0x32, + 0x7a, 0xd0, 0x33, 0x99, 0xe8, 0x42, 0xa1, 0x0b, + 0xb7, 0x1d, 0xfe, 0x54, 0x25, 0x8f, 0x6c, 0xc6, + 0x8e, 0x24, 0xc7, 0x6d, 0x1c, 0xb6, 0x55, 0xff, + 0xc5, 0x6f, 0x8c, 0x26, 0x57, 0xfd, 0x1e, 0xb4, + 0xfc, 0x56, 0xb5, 0x1f, 0x6e, 0xc4, 0x27, 0x8d, + 0x53, 0xf9, 0x1a, 0xb0, 0xc1, 0x6b, 0x88, 0x22, + 0x6a, 0xc0, 0x23, 0x89, 0xf8, 0x52, 0xb1, 0x1b, + 0x21, 0x8b, 0x68, 0xc2, 0xb3, 0x19, 0xfa, 0x50, + 0x18, 0xb2, 0x51, 0xfb, 0x8a, 0x20, 0xc3, 0x69, + 0x62, 0xc8, 0x2b, 0x81, 0xf0, 0x5a, 0xb9, 0x13, + 0x5b, 0xf1, 0x12, 0xb8, 0xc9, 0x63, 0x80, 0x2a, + 0x10, 0xba, 0x59, 0xf3, 0x82, 0x28, 0xcb, 0x61, + 0x29, 0x83, 0x60, 0xca, 0xbb, 0x11, 0xf2, 0x58, + 0x86, 0x2c, 0xcf, 0x65, 0x14, 0xbe, 0x5d, 0xf7, + 0xbf, 0x15, 0xf6, 0x5c, 0x2d, 0x87, 0x64, 0xce, + 0xf4, 0x5e, 0xbd, 0x17, 0x66, 0xcc, 0x2f, 0x85, + 0xcd, 0x67, 0x84, 0x2e, 0x5f, 0xf5, 0x16, 0xbc, + }, + { + 0x00, 0xab, 0x4b, 0xe0, 0x96, 0x3d, 0xdd, 0x76, + 0x31, 0x9a, 0x7a, 0xd1, 0xa7, 0x0c, 0xec, 0x47, + 0x62, 0xc9, 0x29, 0x82, 0xf4, 0x5f, 0xbf, 0x14, + 0x53, 0xf8, 0x18, 0xb3, 0xc5, 0x6e, 0x8e, 0x25, + 0xc4, 0x6f, 0x8f, 0x24, 0x52, 0xf9, 0x19, 0xb2, + 0xf5, 0x5e, 0xbe, 0x15, 0x63, 0xc8, 0x28, 0x83, + 0xa6, 0x0d, 0xed, 0x46, 0x30, 0x9b, 0x7b, 0xd0, + 0x97, 0x3c, 0xdc, 0x77, 0x01, 0xaa, 0x4a, 0xe1, + 0x95, 0x3e, 0xde, 0x75, 0x03, 0xa8, 0x48, 0xe3, + 0xa4, 0x0f, 0xef, 0x44, 0x32, 0x99, 0x79, 0xd2, + 0xf7, 0x5c, 0xbc, 0x17, 0x61, 0xca, 0x2a, 0x81, + 0xc6, 0x6d, 0x8d, 0x26, 0x50, 0xfb, 0x1b, 0xb0, + 0x51, 0xfa, 0x1a, 0xb1, 0xc7, 0x6c, 0x8c, 0x27, + 0x60, 0xcb, 0x2b, 0x80, 0xf6, 0x5d, 0xbd, 0x16, + 0x33, 0x98, 0x78, 0xd3, 0xa5, 0x0e, 0xee, 0x45, + 0x02, 0xa9, 0x49, 0xe2, 0x94, 0x3f, 0xdf, 0x74, + 0x37, 0x9c, 0x7c, 0xd7, 0xa1, 0x0a, 0xea, 0x41, + 0x06, 0xad, 0x4d, 0xe6, 0x90, 0x3b, 0xdb, 0x70, + 0x55, 0xfe, 0x1e, 0xb5, 0xc3, 0x68, 0x88, 0x23, + 0x64, 0xcf, 0x2f, 0x84, 0xf2, 0x59, 0xb9, 0x12, + 0xf3, 0x58, 0xb8, 0x13, 0x65, 0xce, 0x2e, 0x85, + 0xc2, 0x69, 0x89, 0x22, 0x54, 0xff, 0x1f, 0xb4, + 0x91, 0x3a, 0xda, 0x71, 0x07, 0xac, 0x4c, 0xe7, + 0xa0, 0x0b, 0xeb, 0x40, 0x36, 0x9d, 0x7d, 0xd6, + 0xa2, 0x09, 0xe9, 0x42, 0x34, 0x9f, 0x7f, 0xd4, + 0x93, 0x38, 0xd8, 0x73, 0x05, 0xae, 0x4e, 0xe5, + 0xc0, 0x6b, 0x8b, 0x20, 0x56, 0xfd, 0x1d, 0xb6, + 0xf1, 0x5a, 0xba, 0x11, 0x67, 0xcc, 0x2c, 0x87, + 0x66, 0xcd, 0x2d, 0x86, 0xf0, 0x5b, 0xbb, 0x10, + 0x57, 0xfc, 0x1c, 0xb7, 0xc1, 0x6a, 0x8a, 0x21, + 0x04, 0xaf, 0x4f, 0xe4, 0x92, 0x39, 0xd9, 0x72, + 0x35, 0x9e, 0x7e, 0xd5, 0xa3, 0x08, 0xe8, 0x43, + }, + { + 0x00, 0xac, 0x45, 0xe9, 0x8a, 0x26, 0xcf, 0x63, + 0x09, 0xa5, 0x4c, 0xe0, 0x83, 0x2f, 0xc6, 0x6a, + 0x12, 0xbe, 0x57, 0xfb, 0x98, 0x34, 0xdd, 0x71, + 0x1b, 0xb7, 0x5e, 0xf2, 0x91, 0x3d, 0xd4, 0x78, + 0x24, 0x88, 0x61, 0xcd, 0xae, 0x02, 0xeb, 0x47, + 0x2d, 0x81, 0x68, 0xc4, 0xa7, 0x0b, 0xe2, 0x4e, + 0x36, 0x9a, 0x73, 0xdf, 0xbc, 0x10, 0xf9, 0x55, + 0x3f, 0x93, 0x7a, 0xd6, 0xb5, 0x19, 0xf0, 0x5c, + 0x48, 0xe4, 0x0d, 0xa1, 0xc2, 0x6e, 0x87, 0x2b, + 0x41, 0xed, 0x04, 0xa8, 0xcb, 0x67, 0x8e, 0x22, + 0x5a, 0xf6, 0x1f, 0xb3, 0xd0, 0x7c, 0x95, 0x39, + 0x53, 0xff, 0x16, 0xba, 0xd9, 0x75, 0x9c, 0x30, + 0x6c, 0xc0, 0x29, 0x85, 0xe6, 0x4a, 0xa3, 0x0f, + 0x65, 0xc9, 0x20, 0x8c, 0xef, 0x43, 0xaa, 0x06, + 0x7e, 0xd2, 0x3b, 0x97, 0xf4, 0x58, 0xb1, 0x1d, + 0x77, 0xdb, 0x32, 0x9e, 0xfd, 0x51, 0xb8, 0x14, + 0x90, 0x3c, 0xd5, 0x79, 0x1a, 0xb6, 0x5f, 0xf3, + 0x99, 0x35, 0xdc, 0x70, 0x13, 0xbf, 0x56, 0xfa, + 0x82, 0x2e, 0xc7, 0x6b, 0x08, 0xa4, 0x4d, 0xe1, + 0x8b, 0x27, 0xce, 0x62, 0x01, 0xad, 0x44, 0xe8, + 0xb4, 0x18, 0xf1, 0x5d, 0x3e, 0x92, 0x7b, 0xd7, + 0xbd, 0x11, 0xf8, 0x54, 0x37, 0x9b, 0x72, 0xde, + 0xa6, 0x0a, 0xe3, 0x4f, 0x2c, 0x80, 0x69, 0xc5, + 0xaf, 0x03, 0xea, 0x46, 0x25, 0x89, 0x60, 0xcc, + 0xd8, 0x74, 0x9d, 0x31, 0x52, 0xfe, 0x17, 0xbb, + 0xd1, 0x7d, 0x94, 0x38, 0x5b, 0xf7, 0x1e, 0xb2, + 0xca, 0x66, 0x8f, 0x23, 0x40, 0xec, 0x05, 0xa9, + 0xc3, 0x6f, 0x86, 0x2a, 0x49, 0xe5, 0x0c, 0xa0, + 0xfc, 0x50, 0xb9, 0x15, 0x76, 0xda, 0x33, 0x9f, + 0xf5, 0x59, 0xb0, 0x1c, 0x7f, 0xd3, 0x3a, 0x96, + 0xee, 0x42, 0xab, 0x07, 0x64, 0xc8, 0x21, 0x8d, + 0xe7, 0x4b, 0xa2, 0x0e, 0x6d, 0xc1, 0x28, 0x84, + }, + { + 0x00, 0xad, 0x47, 0xea, 0x8e, 0x23, 0xc9, 0x64, + 0x01, 0xac, 0x46, 0xeb, 0x8f, 0x22, 0xc8, 0x65, + 0x02, 0xaf, 0x45, 0xe8, 0x8c, 0x21, 0xcb, 0x66, + 0x03, 0xae, 0x44, 0xe9, 0x8d, 0x20, 0xca, 0x67, + 0x04, 0xa9, 0x43, 0xee, 0x8a, 0x27, 0xcd, 0x60, + 0x05, 0xa8, 0x42, 0xef, 0x8b, 0x26, 0xcc, 0x61, + 0x06, 0xab, 0x41, 0xec, 0x88, 0x25, 0xcf, 0x62, + 0x07, 0xaa, 0x40, 0xed, 0x89, 0x24, 0xce, 0x63, + 0x08, 0xa5, 0x4f, 0xe2, 0x86, 0x2b, 0xc1, 0x6c, + 0x09, 0xa4, 0x4e, 0xe3, 0x87, 0x2a, 0xc0, 0x6d, + 0x0a, 0xa7, 0x4d, 0xe0, 0x84, 0x29, 0xc3, 0x6e, + 0x0b, 0xa6, 0x4c, 0xe1, 0x85, 0x28, 0xc2, 0x6f, + 0x0c, 0xa1, 0x4b, 0xe6, 0x82, 0x2f, 0xc5, 0x68, + 0x0d, 0xa0, 0x4a, 0xe7, 0x83, 0x2e, 0xc4, 0x69, + 0x0e, 0xa3, 0x49, 0xe4, 0x80, 0x2d, 0xc7, 0x6a, + 0x0f, 0xa2, 0x48, 0xe5, 0x81, 0x2c, 0xc6, 0x6b, + 0x10, 0xbd, 0x57, 0xfa, 0x9e, 0x33, 0xd9, 0x74, + 0x11, 0xbc, 0x56, 0xfb, 0x9f, 0x32, 0xd8, 0x75, + 0x12, 0xbf, 0x55, 0xf8, 0x9c, 0x31, 0xdb, 0x76, + 0x13, 0xbe, 0x54, 0xf9, 0x9d, 0x30, 0xda, 0x77, + 0x14, 0xb9, 0x53, 0xfe, 0x9a, 0x37, 0xdd, 0x70, + 0x15, 0xb8, 0x52, 0xff, 0x9b, 0x36, 0xdc, 0x71, + 0x16, 0xbb, 0x51, 0xfc, 0x98, 0x35, 0xdf, 0x72, + 0x17, 0xba, 0x50, 0xfd, 0x99, 0x34, 0xde, 0x73, + 0x18, 0xb5, 0x5f, 0xf2, 0x96, 0x3b, 0xd1, 0x7c, + 0x19, 0xb4, 0x5e, 0xf3, 0x97, 0x3a, 0xd0, 0x7d, + 0x1a, 0xb7, 0x5d, 0xf0, 0x94, 0x39, 0xd3, 0x7e, + 0x1b, 0xb6, 0x5c, 0xf1, 0x95, 0x38, 0xd2, 0x7f, + 0x1c, 0xb1, 0x5b, 0xf6, 0x92, 0x3f, 0xd5, 0x78, + 0x1d, 0xb0, 0x5a, 0xf7, 0x93, 0x3e, 0xd4, 0x79, + 0x1e, 0xb3, 0x59, 0xf4, 0x90, 0x3d, 0xd7, 0x7a, + 0x1f, 0xb2, 0x58, 0xf5, 0x91, 0x3c, 0xd6, 0x7b, + }, + { + 0x00, 0xae, 0x41, 0xef, 0x82, 0x2c, 0xc3, 0x6d, + 0x19, 0xb7, 0x58, 0xf6, 0x9b, 0x35, 0xda, 0x74, + 0x32, 0x9c, 0x73, 0xdd, 0xb0, 0x1e, 0xf1, 0x5f, + 0x2b, 0x85, 0x6a, 0xc4, 0xa9, 0x07, 0xe8, 0x46, + 0x64, 0xca, 0x25, 0x8b, 0xe6, 0x48, 0xa7, 0x09, + 0x7d, 0xd3, 0x3c, 0x92, 0xff, 0x51, 0xbe, 0x10, + 0x56, 0xf8, 0x17, 0xb9, 0xd4, 0x7a, 0x95, 0x3b, + 0x4f, 0xe1, 0x0e, 0xa0, 0xcd, 0x63, 0x8c, 0x22, + 0xc8, 0x66, 0x89, 0x27, 0x4a, 0xe4, 0x0b, 0xa5, + 0xd1, 0x7f, 0x90, 0x3e, 0x53, 0xfd, 0x12, 0xbc, + 0xfa, 0x54, 0xbb, 0x15, 0x78, 0xd6, 0x39, 0x97, + 0xe3, 0x4d, 0xa2, 0x0c, 0x61, 0xcf, 0x20, 0x8e, + 0xac, 0x02, 0xed, 0x43, 0x2e, 0x80, 0x6f, 0xc1, + 0xb5, 0x1b, 0xf4, 0x5a, 0x37, 0x99, 0x76, 0xd8, + 0x9e, 0x30, 0xdf, 0x71, 0x1c, 0xb2, 0x5d, 0xf3, + 0x87, 0x29, 0xc6, 0x68, 0x05, 0xab, 0x44, 0xea, + 0x8d, 0x23, 0xcc, 0x62, 0x0f, 0xa1, 0x4e, 0xe0, + 0x94, 0x3a, 0xd5, 0x7b, 0x16, 0xb8, 0x57, 0xf9, + 0xbf, 0x11, 0xfe, 0x50, 0x3d, 0x93, 0x7c, 0xd2, + 0xa6, 0x08, 0xe7, 0x49, 0x24, 0x8a, 0x65, 0xcb, + 0xe9, 0x47, 0xa8, 0x06, 0x6b, 0xc5, 0x2a, 0x84, + 0xf0, 0x5e, 0xb1, 0x1f, 0x72, 0xdc, 0x33, 0x9d, + 0xdb, 0x75, 0x9a, 0x34, 0x59, 0xf7, 0x18, 0xb6, + 0xc2, 0x6c, 0x83, 0x2d, 0x40, 0xee, 0x01, 0xaf, + 0x45, 0xeb, 0x04, 0xaa, 0xc7, 0x69, 0x86, 0x28, + 0x5c, 0xf2, 0x1d, 0xb3, 0xde, 0x70, 0x9f, 0x31, + 0x77, 0xd9, 0x36, 0x98, 0xf5, 0x5b, 0xb4, 0x1a, + 0x6e, 0xc0, 0x2f, 0x81, 0xec, 0x42, 0xad, 0x03, + 0x21, 0x8f, 0x60, 0xce, 0xa3, 0x0d, 0xe2, 0x4c, + 0x38, 0x96, 0x79, 0xd7, 0xba, 0x14, 0xfb, 0x55, + 0x13, 0xbd, 0x52, 0xfc, 0x91, 0x3f, 0xd0, 0x7e, + 0x0a, 0xa4, 0x4b, 0xe5, 0x88, 0x26, 0xc9, 0x67, + }, + { + 0x00, 0xaf, 0x43, 0xec, 0x86, 0x29, 0xc5, 0x6a, + 0x11, 0xbe, 0x52, 0xfd, 0x97, 0x38, 0xd4, 0x7b, + 0x22, 0x8d, 0x61, 0xce, 0xa4, 0x0b, 0xe7, 0x48, + 0x33, 0x9c, 0x70, 0xdf, 0xb5, 0x1a, 0xf6, 0x59, + 0x44, 0xeb, 0x07, 0xa8, 0xc2, 0x6d, 0x81, 0x2e, + 0x55, 0xfa, 0x16, 0xb9, 0xd3, 0x7c, 0x90, 0x3f, + 0x66, 0xc9, 0x25, 0x8a, 0xe0, 0x4f, 0xa3, 0x0c, + 0x77, 0xd8, 0x34, 0x9b, 0xf1, 0x5e, 0xb2, 0x1d, + 0x88, 0x27, 0xcb, 0x64, 0x0e, 0xa1, 0x4d, 0xe2, + 0x99, 0x36, 0xda, 0x75, 0x1f, 0xb0, 0x5c, 0xf3, + 0xaa, 0x05, 0xe9, 0x46, 0x2c, 0x83, 0x6f, 0xc0, + 0xbb, 0x14, 0xf8, 0x57, 0x3d, 0x92, 0x7e, 0xd1, + 0xcc, 0x63, 0x8f, 0x20, 0x4a, 0xe5, 0x09, 0xa6, + 0xdd, 0x72, 0x9e, 0x31, 0x5b, 0xf4, 0x18, 0xb7, + 0xee, 0x41, 0xad, 0x02, 0x68, 0xc7, 0x2b, 0x84, + 0xff, 0x50, 0xbc, 0x13, 0x79, 0xd6, 0x3a, 0x95, + 0x0d, 0xa2, 0x4e, 0xe1, 0x8b, 0x24, 0xc8, 0x67, + 0x1c, 0xb3, 0x5f, 0xf0, 0x9a, 0x35, 0xd9, 0x76, + 0x2f, 0x80, 0x6c, 0xc3, 0xa9, 0x06, 0xea, 0x45, + 0x3e, 0x91, 0x7d, 0xd2, 0xb8, 0x17, 0xfb, 0x54, + 0x49, 0xe6, 0x0a, 0xa5, 0xcf, 0x60, 0x8c, 0x23, + 0x58, 0xf7, 0x1b, 0xb4, 0xde, 0x71, 0x9d, 0x32, + 0x6b, 0xc4, 0x28, 0x87, 0xed, 0x42, 0xae, 0x01, + 0x7a, 0xd5, 0x39, 0x96, 0xfc, 0x53, 0xbf, 0x10, + 0x85, 0x2a, 0xc6, 0x69, 0x03, 0xac, 0x40, 0xef, + 0x94, 0x3b, 0xd7, 0x78, 0x12, 0xbd, 0x51, 0xfe, + 0xa7, 0x08, 0xe4, 0x4b, 0x21, 0x8e, 0x62, 0xcd, + 0xb6, 0x19, 0xf5, 0x5a, 0x30, 0x9f, 0x73, 0xdc, + 0xc1, 0x6e, 0x82, 0x2d, 0x47, 0xe8, 0x04, 0xab, + 0xd0, 0x7f, 0x93, 0x3c, 0x56, 0xf9, 0x15, 0xba, + 0xe3, 0x4c, 0xa0, 0x0f, 0x65, 0xca, 0x26, 0x89, + 0xf2, 0x5d, 0xb1, 0x1e, 0x74, 0xdb, 0x37, 0x98, + }, + { + 0x00, 0xb0, 0x7d, 0xcd, 0xfa, 0x4a, 0x87, 0x37, + 0xe9, 0x59, 0x94, 0x24, 0x13, 0xa3, 0x6e, 0xde, + 0xcf, 0x7f, 0xb2, 0x02, 0x35, 0x85, 0x48, 0xf8, + 0x26, 0x96, 0x5b, 0xeb, 0xdc, 0x6c, 0xa1, 0x11, + 0x83, 0x33, 0xfe, 0x4e, 0x79, 0xc9, 0x04, 0xb4, + 0x6a, 0xda, 0x17, 0xa7, 0x90, 0x20, 0xed, 0x5d, + 0x4c, 0xfc, 0x31, 0x81, 0xb6, 0x06, 0xcb, 0x7b, + 0xa5, 0x15, 0xd8, 0x68, 0x5f, 0xef, 0x22, 0x92, + 0x1b, 0xab, 0x66, 0xd6, 0xe1, 0x51, 0x9c, 0x2c, + 0xf2, 0x42, 0x8f, 0x3f, 0x08, 0xb8, 0x75, 0xc5, + 0xd4, 0x64, 0xa9, 0x19, 0x2e, 0x9e, 0x53, 0xe3, + 0x3d, 0x8d, 0x40, 0xf0, 0xc7, 0x77, 0xba, 0x0a, + 0x98, 0x28, 0xe5, 0x55, 0x62, 0xd2, 0x1f, 0xaf, + 0x71, 0xc1, 0x0c, 0xbc, 0x8b, 0x3b, 0xf6, 0x46, + 0x57, 0xe7, 0x2a, 0x9a, 0xad, 0x1d, 0xd0, 0x60, + 0xbe, 0x0e, 0xc3, 0x73, 0x44, 0xf4, 0x39, 0x89, + 0x36, 0x86, 0x4b, 0xfb, 0xcc, 0x7c, 0xb1, 0x01, + 0xdf, 0x6f, 0xa2, 0x12, 0x25, 0x95, 0x58, 0xe8, + 0xf9, 0x49, 0x84, 0x34, 0x03, 0xb3, 0x7e, 0xce, + 0x10, 0xa0, 0x6d, 0xdd, 0xea, 0x5a, 0x97, 0x27, + 0xb5, 0x05, 0xc8, 0x78, 0x4f, 0xff, 0x32, 0x82, + 0x5c, 0xec, 0x21, 0x91, 0xa6, 0x16, 0xdb, 0x6b, + 0x7a, 0xca, 0x07, 0xb7, 0x80, 0x30, 0xfd, 0x4d, + 0x93, 0x23, 0xee, 0x5e, 0x69, 0xd9, 0x14, 0xa4, + 0x2d, 0x9d, 0x50, 0xe0, 0xd7, 0x67, 0xaa, 0x1a, + 0xc4, 0x74, 0xb9, 0x09, 0x3e, 0x8e, 0x43, 0xf3, + 0xe2, 0x52, 0x9f, 0x2f, 0x18, 0xa8, 0x65, 0xd5, + 0x0b, 0xbb, 0x76, 0xc6, 0xf1, 0x41, 0x8c, 0x3c, + 0xae, 0x1e, 0xd3, 0x63, 0x54, 0xe4, 0x29, 0x99, + 0x47, 0xf7, 0x3a, 0x8a, 0xbd, 0x0d, 0xc0, 0x70, + 0x61, 0xd1, 0x1c, 0xac, 0x9b, 0x2b, 0xe6, 0x56, + 0x88, 0x38, 0xf5, 0x45, 0x72, 0xc2, 0x0f, 0xbf, + }, + { + 0x00, 0xb1, 0x7f, 0xce, 0xfe, 0x4f, 0x81, 0x30, + 0xe1, 0x50, 0x9e, 0x2f, 0x1f, 0xae, 0x60, 0xd1, + 0xdf, 0x6e, 0xa0, 0x11, 0x21, 0x90, 0x5e, 0xef, + 0x3e, 0x8f, 0x41, 0xf0, 0xc0, 0x71, 0xbf, 0x0e, + 0xa3, 0x12, 0xdc, 0x6d, 0x5d, 0xec, 0x22, 0x93, + 0x42, 0xf3, 0x3d, 0x8c, 0xbc, 0x0d, 0xc3, 0x72, + 0x7c, 0xcd, 0x03, 0xb2, 0x82, 0x33, 0xfd, 0x4c, + 0x9d, 0x2c, 0xe2, 0x53, 0x63, 0xd2, 0x1c, 0xad, + 0x5b, 0xea, 0x24, 0x95, 0xa5, 0x14, 0xda, 0x6b, + 0xba, 0x0b, 0xc5, 0x74, 0x44, 0xf5, 0x3b, 0x8a, + 0x84, 0x35, 0xfb, 0x4a, 0x7a, 0xcb, 0x05, 0xb4, + 0x65, 0xd4, 0x1a, 0xab, 0x9b, 0x2a, 0xe4, 0x55, + 0xf8, 0x49, 0x87, 0x36, 0x06, 0xb7, 0x79, 0xc8, + 0x19, 0xa8, 0x66, 0xd7, 0xe7, 0x56, 0x98, 0x29, + 0x27, 0x96, 0x58, 0xe9, 0xd9, 0x68, 0xa6, 0x17, + 0xc6, 0x77, 0xb9, 0x08, 0x38, 0x89, 0x47, 0xf6, + 0xb6, 0x07, 0xc9, 0x78, 0x48, 0xf9, 0x37, 0x86, + 0x57, 0xe6, 0x28, 0x99, 0xa9, 0x18, 0xd6, 0x67, + 0x69, 0xd8, 0x16, 0xa7, 0x97, 0x26, 0xe8, 0x59, + 0x88, 0x39, 0xf7, 0x46, 0x76, 0xc7, 0x09, 0xb8, + 0x15, 0xa4, 0x6a, 0xdb, 0xeb, 0x5a, 0x94, 0x25, + 0xf4, 0x45, 0x8b, 0x3a, 0x0a, 0xbb, 0x75, 0xc4, + 0xca, 0x7b, 0xb5, 0x04, 0x34, 0x85, 0x4b, 0xfa, + 0x2b, 0x9a, 0x54, 0xe5, 0xd5, 0x64, 0xaa, 0x1b, + 0xed, 0x5c, 0x92, 0x23, 0x13, 0xa2, 0x6c, 0xdd, + 0x0c, 0xbd, 0x73, 0xc2, 0xf2, 0x43, 0x8d, 0x3c, + 0x32, 0x83, 0x4d, 0xfc, 0xcc, 0x7d, 0xb3, 0x02, + 0xd3, 0x62, 0xac, 0x1d, 0x2d, 0x9c, 0x52, 0xe3, + 0x4e, 0xff, 0x31, 0x80, 0xb0, 0x01, 0xcf, 0x7e, + 0xaf, 0x1e, 0xd0, 0x61, 0x51, 0xe0, 0x2e, 0x9f, + 0x91, 0x20, 0xee, 0x5f, 0x6f, 0xde, 0x10, 0xa1, + 0x70, 0xc1, 0x0f, 0xbe, 0x8e, 0x3f, 0xf1, 0x40, + }, + { + 0x00, 0xb2, 0x79, 0xcb, 0xf2, 0x40, 0x8b, 0x39, + 0xf9, 0x4b, 0x80, 0x32, 0x0b, 0xb9, 0x72, 0xc0, + 0xef, 0x5d, 0x96, 0x24, 0x1d, 0xaf, 0x64, 0xd6, + 0x16, 0xa4, 0x6f, 0xdd, 0xe4, 0x56, 0x9d, 0x2f, + 0xc3, 0x71, 0xba, 0x08, 0x31, 0x83, 0x48, 0xfa, + 0x3a, 0x88, 0x43, 0xf1, 0xc8, 0x7a, 0xb1, 0x03, + 0x2c, 0x9e, 0x55, 0xe7, 0xde, 0x6c, 0xa7, 0x15, + 0xd5, 0x67, 0xac, 0x1e, 0x27, 0x95, 0x5e, 0xec, + 0x9b, 0x29, 0xe2, 0x50, 0x69, 0xdb, 0x10, 0xa2, + 0x62, 0xd0, 0x1b, 0xa9, 0x90, 0x22, 0xe9, 0x5b, + 0x74, 0xc6, 0x0d, 0xbf, 0x86, 0x34, 0xff, 0x4d, + 0x8d, 0x3f, 0xf4, 0x46, 0x7f, 0xcd, 0x06, 0xb4, + 0x58, 0xea, 0x21, 0x93, 0xaa, 0x18, 0xd3, 0x61, + 0xa1, 0x13, 0xd8, 0x6a, 0x53, 0xe1, 0x2a, 0x98, + 0xb7, 0x05, 0xce, 0x7c, 0x45, 0xf7, 0x3c, 0x8e, + 0x4e, 0xfc, 0x37, 0x85, 0xbc, 0x0e, 0xc5, 0x77, + 0x2b, 0x99, 0x52, 0xe0, 0xd9, 0x6b, 0xa0, 0x12, + 0xd2, 0x60, 0xab, 0x19, 0x20, 0x92, 0x59, 0xeb, + 0xc4, 0x76, 0xbd, 0x0f, 0x36, 0x84, 0x4f, 0xfd, + 0x3d, 0x8f, 0x44, 0xf6, 0xcf, 0x7d, 0xb6, 0x04, + 0xe8, 0x5a, 0x91, 0x23, 0x1a, 0xa8, 0x63, 0xd1, + 0x11, 0xa3, 0x68, 0xda, 0xe3, 0x51, 0x9a, 0x28, + 0x07, 0xb5, 0x7e, 0xcc, 0xf5, 0x47, 0x8c, 0x3e, + 0xfe, 0x4c, 0x87, 0x35, 0x0c, 0xbe, 0x75, 0xc7, + 0xb0, 0x02, 0xc9, 0x7b, 0x42, 0xf0, 0x3b, 0x89, + 0x49, 0xfb, 0x30, 0x82, 0xbb, 0x09, 0xc2, 0x70, + 0x5f, 0xed, 0x26, 0x94, 0xad, 0x1f, 0xd4, 0x66, + 0xa6, 0x14, 0xdf, 0x6d, 0x54, 0xe6, 0x2d, 0x9f, + 0x73, 0xc1, 0x0a, 0xb8, 0x81, 0x33, 0xf8, 0x4a, + 0x8a, 0x38, 0xf3, 0x41, 0x78, 0xca, 0x01, 0xb3, + 0x9c, 0x2e, 0xe5, 0x57, 0x6e, 0xdc, 0x17, 0xa5, + 0x65, 0xd7, 0x1c, 0xae, 0x97, 0x25, 0xee, 0x5c, + }, + { + 0x00, 0xb3, 0x7b, 0xc8, 0xf6, 0x45, 0x8d, 0x3e, + 0xf1, 0x42, 0x8a, 0x39, 0x07, 0xb4, 0x7c, 0xcf, + 0xff, 0x4c, 0x84, 0x37, 0x09, 0xba, 0x72, 0xc1, + 0x0e, 0xbd, 0x75, 0xc6, 0xf8, 0x4b, 0x83, 0x30, + 0xe3, 0x50, 0x98, 0x2b, 0x15, 0xa6, 0x6e, 0xdd, + 0x12, 0xa1, 0x69, 0xda, 0xe4, 0x57, 0x9f, 0x2c, + 0x1c, 0xaf, 0x67, 0xd4, 0xea, 0x59, 0x91, 0x22, + 0xed, 0x5e, 0x96, 0x25, 0x1b, 0xa8, 0x60, 0xd3, + 0xdb, 0x68, 0xa0, 0x13, 0x2d, 0x9e, 0x56, 0xe5, + 0x2a, 0x99, 0x51, 0xe2, 0xdc, 0x6f, 0xa7, 0x14, + 0x24, 0x97, 0x5f, 0xec, 0xd2, 0x61, 0xa9, 0x1a, + 0xd5, 0x66, 0xae, 0x1d, 0x23, 0x90, 0x58, 0xeb, + 0x38, 0x8b, 0x43, 0xf0, 0xce, 0x7d, 0xb5, 0x06, + 0xc9, 0x7a, 0xb2, 0x01, 0x3f, 0x8c, 0x44, 0xf7, + 0xc7, 0x74, 0xbc, 0x0f, 0x31, 0x82, 0x4a, 0xf9, + 0x36, 0x85, 0x4d, 0xfe, 0xc0, 0x73, 0xbb, 0x08, + 0xab, 0x18, 0xd0, 0x63, 0x5d, 0xee, 0x26, 0x95, + 0x5a, 0xe9, 0x21, 0x92, 0xac, 0x1f, 0xd7, 0x64, + 0x54, 0xe7, 0x2f, 0x9c, 0xa2, 0x11, 0xd9, 0x6a, + 0xa5, 0x16, 0xde, 0x6d, 0x53, 0xe0, 0x28, 0x9b, + 0x48, 0xfb, 0x33, 0x80, 0xbe, 0x0d, 0xc5, 0x76, + 0xb9, 0x0a, 0xc2, 0x71, 0x4f, 0xfc, 0x34, 0x87, + 0xb7, 0x04, 0xcc, 0x7f, 0x41, 0xf2, 0x3a, 0x89, + 0x46, 0xf5, 0x3d, 0x8e, 0xb0, 0x03, 0xcb, 0x78, + 0x70, 0xc3, 0x0b, 0xb8, 0x86, 0x35, 0xfd, 0x4e, + 0x81, 0x32, 0xfa, 0x49, 0x77, 0xc4, 0x0c, 0xbf, + 0x8f, 0x3c, 0xf4, 0x47, 0x79, 0xca, 0x02, 0xb1, + 0x7e, 0xcd, 0x05, 0xb6, 0x88, 0x3b, 0xf3, 0x40, + 0x93, 0x20, 0xe8, 0x5b, 0x65, 0xd6, 0x1e, 0xad, + 0x62, 0xd1, 0x19, 0xaa, 0x94, 0x27, 0xef, 0x5c, + 0x6c, 0xdf, 0x17, 0xa4, 0x9a, 0x29, 0xe1, 0x52, + 0x9d, 0x2e, 0xe6, 0x55, 0x6b, 0xd8, 0x10, 0xa3, + }, + { + 0x00, 0xb4, 0x75, 0xc1, 0xea, 0x5e, 0x9f, 0x2b, + 0xc9, 0x7d, 0xbc, 0x08, 0x23, 0x97, 0x56, 0xe2, + 0x8f, 0x3b, 0xfa, 0x4e, 0x65, 0xd1, 0x10, 0xa4, + 0x46, 0xf2, 0x33, 0x87, 0xac, 0x18, 0xd9, 0x6d, + 0x03, 0xb7, 0x76, 0xc2, 0xe9, 0x5d, 0x9c, 0x28, + 0xca, 0x7e, 0xbf, 0x0b, 0x20, 0x94, 0x55, 0xe1, + 0x8c, 0x38, 0xf9, 0x4d, 0x66, 0xd2, 0x13, 0xa7, + 0x45, 0xf1, 0x30, 0x84, 0xaf, 0x1b, 0xda, 0x6e, + 0x06, 0xb2, 0x73, 0xc7, 0xec, 0x58, 0x99, 0x2d, + 0xcf, 0x7b, 0xba, 0x0e, 0x25, 0x91, 0x50, 0xe4, + 0x89, 0x3d, 0xfc, 0x48, 0x63, 0xd7, 0x16, 0xa2, + 0x40, 0xf4, 0x35, 0x81, 0xaa, 0x1e, 0xdf, 0x6b, + 0x05, 0xb1, 0x70, 0xc4, 0xef, 0x5b, 0x9a, 0x2e, + 0xcc, 0x78, 0xb9, 0x0d, 0x26, 0x92, 0x53, 0xe7, + 0x8a, 0x3e, 0xff, 0x4b, 0x60, 0xd4, 0x15, 0xa1, + 0x43, 0xf7, 0x36, 0x82, 0xa9, 0x1d, 0xdc, 0x68, + 0x0c, 0xb8, 0x79, 0xcd, 0xe6, 0x52, 0x93, 0x27, + 0xc5, 0x71, 0xb0, 0x04, 0x2f, 0x9b, 0x5a, 0xee, + 0x83, 0x37, 0xf6, 0x42, 0x69, 0xdd, 0x1c, 0xa8, + 0x4a, 0xfe, 0x3f, 0x8b, 0xa0, 0x14, 0xd5, 0x61, + 0x0f, 0xbb, 0x7a, 0xce, 0xe5, 0x51, 0x90, 0x24, + 0xc6, 0x72, 0xb3, 0x07, 0x2c, 0x98, 0x59, 0xed, + 0x80, 0x34, 0xf5, 0x41, 0x6a, 0xde, 0x1f, 0xab, + 0x49, 0xfd, 0x3c, 0x88, 0xa3, 0x17, 0xd6, 0x62, + 0x0a, 0xbe, 0x7f, 0xcb, 0xe0, 0x54, 0x95, 0x21, + 0xc3, 0x77, 0xb6, 0x02, 0x29, 0x9d, 0x5c, 0xe8, + 0x85, 0x31, 0xf0, 0x44, 0x6f, 0xdb, 0x1a, 0xae, + 0x4c, 0xf8, 0x39, 0x8d, 0xa6, 0x12, 0xd3, 0x67, + 0x09, 0xbd, 0x7c, 0xc8, 0xe3, 0x57, 0x96, 0x22, + 0xc0, 0x74, 0xb5, 0x01, 0x2a, 0x9e, 0x5f, 0xeb, + 0x86, 0x32, 0xf3, 0x47, 0x6c, 0xd8, 0x19, 0xad, + 0x4f, 0xfb, 0x3a, 0x8e, 0xa5, 0x11, 0xd0, 0x64, + }, + { + 0x00, 0xb5, 0x77, 0xc2, 0xee, 0x5b, 0x99, 0x2c, + 0xc1, 0x74, 0xb6, 0x03, 0x2f, 0x9a, 0x58, 0xed, + 0x9f, 0x2a, 0xe8, 0x5d, 0x71, 0xc4, 0x06, 0xb3, + 0x5e, 0xeb, 0x29, 0x9c, 0xb0, 0x05, 0xc7, 0x72, + 0x23, 0x96, 0x54, 0xe1, 0xcd, 0x78, 0xba, 0x0f, + 0xe2, 0x57, 0x95, 0x20, 0x0c, 0xb9, 0x7b, 0xce, + 0xbc, 0x09, 0xcb, 0x7e, 0x52, 0xe7, 0x25, 0x90, + 0x7d, 0xc8, 0x0a, 0xbf, 0x93, 0x26, 0xe4, 0x51, + 0x46, 0xf3, 0x31, 0x84, 0xa8, 0x1d, 0xdf, 0x6a, + 0x87, 0x32, 0xf0, 0x45, 0x69, 0xdc, 0x1e, 0xab, + 0xd9, 0x6c, 0xae, 0x1b, 0x37, 0x82, 0x40, 0xf5, + 0x18, 0xad, 0x6f, 0xda, 0xf6, 0x43, 0x81, 0x34, + 0x65, 0xd0, 0x12, 0xa7, 0x8b, 0x3e, 0xfc, 0x49, + 0xa4, 0x11, 0xd3, 0x66, 0x4a, 0xff, 0x3d, 0x88, + 0xfa, 0x4f, 0x8d, 0x38, 0x14, 0xa1, 0x63, 0xd6, + 0x3b, 0x8e, 0x4c, 0xf9, 0xd5, 0x60, 0xa2, 0x17, + 0x8c, 0x39, 0xfb, 0x4e, 0x62, 0xd7, 0x15, 0xa0, + 0x4d, 0xf8, 0x3a, 0x8f, 0xa3, 0x16, 0xd4, 0x61, + 0x13, 0xa6, 0x64, 0xd1, 0xfd, 0x48, 0x8a, 0x3f, + 0xd2, 0x67, 0xa5, 0x10, 0x3c, 0x89, 0x4b, 0xfe, + 0xaf, 0x1a, 0xd8, 0x6d, 0x41, 0xf4, 0x36, 0x83, + 0x6e, 0xdb, 0x19, 0xac, 0x80, 0x35, 0xf7, 0x42, + 0x30, 0x85, 0x47, 0xf2, 0xde, 0x6b, 0xa9, 0x1c, + 0xf1, 0x44, 0x86, 0x33, 0x1f, 0xaa, 0x68, 0xdd, + 0xca, 0x7f, 0xbd, 0x08, 0x24, 0x91, 0x53, 0xe6, + 0x0b, 0xbe, 0x7c, 0xc9, 0xe5, 0x50, 0x92, 0x27, + 0x55, 0xe0, 0x22, 0x97, 0xbb, 0x0e, 0xcc, 0x79, + 0x94, 0x21, 0xe3, 0x56, 0x7a, 0xcf, 0x0d, 0xb8, + 0xe9, 0x5c, 0x9e, 0x2b, 0x07, 0xb2, 0x70, 0xc5, + 0x28, 0x9d, 0x5f, 0xea, 0xc6, 0x73, 0xb1, 0x04, + 0x76, 0xc3, 0x01, 0xb4, 0x98, 0x2d, 0xef, 0x5a, + 0xb7, 0x02, 0xc0, 0x75, 0x59, 0xec, 0x2e, 0x9b, + }, + { + 0x00, 0xb6, 0x71, 0xc7, 0xe2, 0x54, 0x93, 0x25, + 0xd9, 0x6f, 0xa8, 0x1e, 0x3b, 0x8d, 0x4a, 0xfc, + 0xaf, 0x19, 0xde, 0x68, 0x4d, 0xfb, 0x3c, 0x8a, + 0x76, 0xc0, 0x07, 0xb1, 0x94, 0x22, 0xe5, 0x53, + 0x43, 0xf5, 0x32, 0x84, 0xa1, 0x17, 0xd0, 0x66, + 0x9a, 0x2c, 0xeb, 0x5d, 0x78, 0xce, 0x09, 0xbf, + 0xec, 0x5a, 0x9d, 0x2b, 0x0e, 0xb8, 0x7f, 0xc9, + 0x35, 0x83, 0x44, 0xf2, 0xd7, 0x61, 0xa6, 0x10, + 0x86, 0x30, 0xf7, 0x41, 0x64, 0xd2, 0x15, 0xa3, + 0x5f, 0xe9, 0x2e, 0x98, 0xbd, 0x0b, 0xcc, 0x7a, + 0x29, 0x9f, 0x58, 0xee, 0xcb, 0x7d, 0xba, 0x0c, + 0xf0, 0x46, 0x81, 0x37, 0x12, 0xa4, 0x63, 0xd5, + 0xc5, 0x73, 0xb4, 0x02, 0x27, 0x91, 0x56, 0xe0, + 0x1c, 0xaa, 0x6d, 0xdb, 0xfe, 0x48, 0x8f, 0x39, + 0x6a, 0xdc, 0x1b, 0xad, 0x88, 0x3e, 0xf9, 0x4f, + 0xb3, 0x05, 0xc2, 0x74, 0x51, 0xe7, 0x20, 0x96, + 0x11, 0xa7, 0x60, 0xd6, 0xf3, 0x45, 0x82, 0x34, + 0xc8, 0x7e, 0xb9, 0x0f, 0x2a, 0x9c, 0x5b, 0xed, + 0xbe, 0x08, 0xcf, 0x79, 0x5c, 0xea, 0x2d, 0x9b, + 0x67, 0xd1, 0x16, 0xa0, 0x85, 0x33, 0xf4, 0x42, + 0x52, 0xe4, 0x23, 0x95, 0xb0, 0x06, 0xc1, 0x77, + 0x8b, 0x3d, 0xfa, 0x4c, 0x69, 0xdf, 0x18, 0xae, + 0xfd, 0x4b, 0x8c, 0x3a, 0x1f, 0xa9, 0x6e, 0xd8, + 0x24, 0x92, 0x55, 0xe3, 0xc6, 0x70, 0xb7, 0x01, + 0x97, 0x21, 0xe6, 0x50, 0x75, 0xc3, 0x04, 0xb2, + 0x4e, 0xf8, 0x3f, 0x89, 0xac, 0x1a, 0xdd, 0x6b, + 0x38, 0x8e, 0x49, 0xff, 0xda, 0x6c, 0xab, 0x1d, + 0xe1, 0x57, 0x90, 0x26, 0x03, 0xb5, 0x72, 0xc4, + 0xd4, 0x62, 0xa5, 0x13, 0x36, 0x80, 0x47, 0xf1, + 0x0d, 0xbb, 0x7c, 0xca, 0xef, 0x59, 0x9e, 0x28, + 0x7b, 0xcd, 0x0a, 0xbc, 0x99, 0x2f, 0xe8, 0x5e, + 0xa2, 0x14, 0xd3, 0x65, 0x40, 0xf6, 0x31, 0x87, + }, + { + 0x00, 0xb7, 0x73, 0xc4, 0xe6, 0x51, 0x95, 0x22, + 0xd1, 0x66, 0xa2, 0x15, 0x37, 0x80, 0x44, 0xf3, + 0xbf, 0x08, 0xcc, 0x7b, 0x59, 0xee, 0x2a, 0x9d, + 0x6e, 0xd9, 0x1d, 0xaa, 0x88, 0x3f, 0xfb, 0x4c, + 0x63, 0xd4, 0x10, 0xa7, 0x85, 0x32, 0xf6, 0x41, + 0xb2, 0x05, 0xc1, 0x76, 0x54, 0xe3, 0x27, 0x90, + 0xdc, 0x6b, 0xaf, 0x18, 0x3a, 0x8d, 0x49, 0xfe, + 0x0d, 0xba, 0x7e, 0xc9, 0xeb, 0x5c, 0x98, 0x2f, + 0xc6, 0x71, 0xb5, 0x02, 0x20, 0x97, 0x53, 0xe4, + 0x17, 0xa0, 0x64, 0xd3, 0xf1, 0x46, 0x82, 0x35, + 0x79, 0xce, 0x0a, 0xbd, 0x9f, 0x28, 0xec, 0x5b, + 0xa8, 0x1f, 0xdb, 0x6c, 0x4e, 0xf9, 0x3d, 0x8a, + 0xa5, 0x12, 0xd6, 0x61, 0x43, 0xf4, 0x30, 0x87, + 0x74, 0xc3, 0x07, 0xb0, 0x92, 0x25, 0xe1, 0x56, + 0x1a, 0xad, 0x69, 0xde, 0xfc, 0x4b, 0x8f, 0x38, + 0xcb, 0x7c, 0xb8, 0x0f, 0x2d, 0x9a, 0x5e, 0xe9, + 0x91, 0x26, 0xe2, 0x55, 0x77, 0xc0, 0x04, 0xb3, + 0x40, 0xf7, 0x33, 0x84, 0xa6, 0x11, 0xd5, 0x62, + 0x2e, 0x99, 0x5d, 0xea, 0xc8, 0x7f, 0xbb, 0x0c, + 0xff, 0x48, 0x8c, 0x3b, 0x19, 0xae, 0x6a, 0xdd, + 0xf2, 0x45, 0x81, 0x36, 0x14, 0xa3, 0x67, 0xd0, + 0x23, 0x94, 0x50, 0xe7, 0xc5, 0x72, 0xb6, 0x01, + 0x4d, 0xfa, 0x3e, 0x89, 0xab, 0x1c, 0xd8, 0x6f, + 0x9c, 0x2b, 0xef, 0x58, 0x7a, 0xcd, 0x09, 0xbe, + 0x57, 0xe0, 0x24, 0x93, 0xb1, 0x06, 0xc2, 0x75, + 0x86, 0x31, 0xf5, 0x42, 0x60, 0xd7, 0x13, 0xa4, + 0xe8, 0x5f, 0x9b, 0x2c, 0x0e, 0xb9, 0x7d, 0xca, + 0x39, 0x8e, 0x4a, 0xfd, 0xdf, 0x68, 0xac, 0x1b, + 0x34, 0x83, 0x47, 0xf0, 0xd2, 0x65, 0xa1, 0x16, + 0xe5, 0x52, 0x96, 0x21, 0x03, 0xb4, 0x70, 0xc7, + 0x8b, 0x3c, 0xf8, 0x4f, 0x6d, 0xda, 0x1e, 0xa9, + 0x5a, 0xed, 0x29, 0x9e, 0xbc, 0x0b, 0xcf, 0x78, + }, + { + 0x00, 0xb8, 0x6d, 0xd5, 0xda, 0x62, 0xb7, 0x0f, + 0xa9, 0x11, 0xc4, 0x7c, 0x73, 0xcb, 0x1e, 0xa6, + 0x4f, 0xf7, 0x22, 0x9a, 0x95, 0x2d, 0xf8, 0x40, + 0xe6, 0x5e, 0x8b, 0x33, 0x3c, 0x84, 0x51, 0xe9, + 0x9e, 0x26, 0xf3, 0x4b, 0x44, 0xfc, 0x29, 0x91, + 0x37, 0x8f, 0x5a, 0xe2, 0xed, 0x55, 0x80, 0x38, + 0xd1, 0x69, 0xbc, 0x04, 0x0b, 0xb3, 0x66, 0xde, + 0x78, 0xc0, 0x15, 0xad, 0xa2, 0x1a, 0xcf, 0x77, + 0x21, 0x99, 0x4c, 0xf4, 0xfb, 0x43, 0x96, 0x2e, + 0x88, 0x30, 0xe5, 0x5d, 0x52, 0xea, 0x3f, 0x87, + 0x6e, 0xd6, 0x03, 0xbb, 0xb4, 0x0c, 0xd9, 0x61, + 0xc7, 0x7f, 0xaa, 0x12, 0x1d, 0xa5, 0x70, 0xc8, + 0xbf, 0x07, 0xd2, 0x6a, 0x65, 0xdd, 0x08, 0xb0, + 0x16, 0xae, 0x7b, 0xc3, 0xcc, 0x74, 0xa1, 0x19, + 0xf0, 0x48, 0x9d, 0x25, 0x2a, 0x92, 0x47, 0xff, + 0x59, 0xe1, 0x34, 0x8c, 0x83, 0x3b, 0xee, 0x56, + 0x42, 0xfa, 0x2f, 0x97, 0x98, 0x20, 0xf5, 0x4d, + 0xeb, 0x53, 0x86, 0x3e, 0x31, 0x89, 0x5c, 0xe4, + 0x0d, 0xb5, 0x60, 0xd8, 0xd7, 0x6f, 0xba, 0x02, + 0xa4, 0x1c, 0xc9, 0x71, 0x7e, 0xc6, 0x13, 0xab, + 0xdc, 0x64, 0xb1, 0x09, 0x06, 0xbe, 0x6b, 0xd3, + 0x75, 0xcd, 0x18, 0xa0, 0xaf, 0x17, 0xc2, 0x7a, + 0x93, 0x2b, 0xfe, 0x46, 0x49, 0xf1, 0x24, 0x9c, + 0x3a, 0x82, 0x57, 0xef, 0xe0, 0x58, 0x8d, 0x35, + 0x63, 0xdb, 0x0e, 0xb6, 0xb9, 0x01, 0xd4, 0x6c, + 0xca, 0x72, 0xa7, 0x1f, 0x10, 0xa8, 0x7d, 0xc5, + 0x2c, 0x94, 0x41, 0xf9, 0xf6, 0x4e, 0x9b, 0x23, + 0x85, 0x3d, 0xe8, 0x50, 0x5f, 0xe7, 0x32, 0x8a, + 0xfd, 0x45, 0x90, 0x28, 0x27, 0x9f, 0x4a, 0xf2, + 0x54, 0xec, 0x39, 0x81, 0x8e, 0x36, 0xe3, 0x5b, + 0xb2, 0x0a, 0xdf, 0x67, 0x68, 0xd0, 0x05, 0xbd, + 0x1b, 0xa3, 0x76, 0xce, 0xc1, 0x79, 0xac, 0x14, + }, + { + 0x00, 0xb9, 0x6f, 0xd6, 0xde, 0x67, 0xb1, 0x08, + 0xa1, 0x18, 0xce, 0x77, 0x7f, 0xc6, 0x10, 0xa9, + 0x5f, 0xe6, 0x30, 0x89, 0x81, 0x38, 0xee, 0x57, + 0xfe, 0x47, 0x91, 0x28, 0x20, 0x99, 0x4f, 0xf6, + 0xbe, 0x07, 0xd1, 0x68, 0x60, 0xd9, 0x0f, 0xb6, + 0x1f, 0xa6, 0x70, 0xc9, 0xc1, 0x78, 0xae, 0x17, + 0xe1, 0x58, 0x8e, 0x37, 0x3f, 0x86, 0x50, 0xe9, + 0x40, 0xf9, 0x2f, 0x96, 0x9e, 0x27, 0xf1, 0x48, + 0x61, 0xd8, 0x0e, 0xb7, 0xbf, 0x06, 0xd0, 0x69, + 0xc0, 0x79, 0xaf, 0x16, 0x1e, 0xa7, 0x71, 0xc8, + 0x3e, 0x87, 0x51, 0xe8, 0xe0, 0x59, 0x8f, 0x36, + 0x9f, 0x26, 0xf0, 0x49, 0x41, 0xf8, 0x2e, 0x97, + 0xdf, 0x66, 0xb0, 0x09, 0x01, 0xb8, 0x6e, 0xd7, + 0x7e, 0xc7, 0x11, 0xa8, 0xa0, 0x19, 0xcf, 0x76, + 0x80, 0x39, 0xef, 0x56, 0x5e, 0xe7, 0x31, 0x88, + 0x21, 0x98, 0x4e, 0xf7, 0xff, 0x46, 0x90, 0x29, + 0xc2, 0x7b, 0xad, 0x14, 0x1c, 0xa5, 0x73, 0xca, + 0x63, 0xda, 0x0c, 0xb5, 0xbd, 0x04, 0xd2, 0x6b, + 0x9d, 0x24, 0xf2, 0x4b, 0x43, 0xfa, 0x2c, 0x95, + 0x3c, 0x85, 0x53, 0xea, 0xe2, 0x5b, 0x8d, 0x34, + 0x7c, 0xc5, 0x13, 0xaa, 0xa2, 0x1b, 0xcd, 0x74, + 0xdd, 0x64, 0xb2, 0x0b, 0x03, 0xba, 0x6c, 0xd5, + 0x23, 0x9a, 0x4c, 0xf5, 0xfd, 0x44, 0x92, 0x2b, + 0x82, 0x3b, 0xed, 0x54, 0x5c, 0xe5, 0x33, 0x8a, + 0xa3, 0x1a, 0xcc, 0x75, 0x7d, 0xc4, 0x12, 0xab, + 0x02, 0xbb, 0x6d, 0xd4, 0xdc, 0x65, 0xb3, 0x0a, + 0xfc, 0x45, 0x93, 0x2a, 0x22, 0x9b, 0x4d, 0xf4, + 0x5d, 0xe4, 0x32, 0x8b, 0x83, 0x3a, 0xec, 0x55, + 0x1d, 0xa4, 0x72, 0xcb, 0xc3, 0x7a, 0xac, 0x15, + 0xbc, 0x05, 0xd3, 0x6a, 0x62, 0xdb, 0x0d, 0xb4, + 0x42, 0xfb, 0x2d, 0x94, 0x9c, 0x25, 0xf3, 0x4a, + 0xe3, 0x5a, 0x8c, 0x35, 0x3d, 0x84, 0x52, 0xeb, + }, + { + 0x00, 0xba, 0x69, 0xd3, 0xd2, 0x68, 0xbb, 0x01, + 0xb9, 0x03, 0xd0, 0x6a, 0x6b, 0xd1, 0x02, 0xb8, + 0x6f, 0xd5, 0x06, 0xbc, 0xbd, 0x07, 0xd4, 0x6e, + 0xd6, 0x6c, 0xbf, 0x05, 0x04, 0xbe, 0x6d, 0xd7, + 0xde, 0x64, 0xb7, 0x0d, 0x0c, 0xb6, 0x65, 0xdf, + 0x67, 0xdd, 0x0e, 0xb4, 0xb5, 0x0f, 0xdc, 0x66, + 0xb1, 0x0b, 0xd8, 0x62, 0x63, 0xd9, 0x0a, 0xb0, + 0x08, 0xb2, 0x61, 0xdb, 0xda, 0x60, 0xb3, 0x09, + 0xa1, 0x1b, 0xc8, 0x72, 0x73, 0xc9, 0x1a, 0xa0, + 0x18, 0xa2, 0x71, 0xcb, 0xca, 0x70, 0xa3, 0x19, + 0xce, 0x74, 0xa7, 0x1d, 0x1c, 0xa6, 0x75, 0xcf, + 0x77, 0xcd, 0x1e, 0xa4, 0xa5, 0x1f, 0xcc, 0x76, + 0x7f, 0xc5, 0x16, 0xac, 0xad, 0x17, 0xc4, 0x7e, + 0xc6, 0x7c, 0xaf, 0x15, 0x14, 0xae, 0x7d, 0xc7, + 0x10, 0xaa, 0x79, 0xc3, 0xc2, 0x78, 0xab, 0x11, + 0xa9, 0x13, 0xc0, 0x7a, 0x7b, 0xc1, 0x12, 0xa8, + 0x5f, 0xe5, 0x36, 0x8c, 0x8d, 0x37, 0xe4, 0x5e, + 0xe6, 0x5c, 0x8f, 0x35, 0x34, 0x8e, 0x5d, 0xe7, + 0x30, 0x8a, 0x59, 0xe3, 0xe2, 0x58, 0x8b, 0x31, + 0x89, 0x33, 0xe0, 0x5a, 0x5b, 0xe1, 0x32, 0x88, + 0x81, 0x3b, 0xe8, 0x52, 0x53, 0xe9, 0x3a, 0x80, + 0x38, 0x82, 0x51, 0xeb, 0xea, 0x50, 0x83, 0x39, + 0xee, 0x54, 0x87, 0x3d, 0x3c, 0x86, 0x55, 0xef, + 0x57, 0xed, 0x3e, 0x84, 0x85, 0x3f, 0xec, 0x56, + 0xfe, 0x44, 0x97, 0x2d, 0x2c, 0x96, 0x45, 0xff, + 0x47, 0xfd, 0x2e, 0x94, 0x95, 0x2f, 0xfc, 0x46, + 0x91, 0x2b, 0xf8, 0x42, 0x43, 0xf9, 0x2a, 0x90, + 0x28, 0x92, 0x41, 0xfb, 0xfa, 0x40, 0x93, 0x29, + 0x20, 0x9a, 0x49, 0xf3, 0xf2, 0x48, 0x9b, 0x21, + 0x99, 0x23, 0xf0, 0x4a, 0x4b, 0xf1, 0x22, 0x98, + 0x4f, 0xf5, 0x26, 0x9c, 0x9d, 0x27, 0xf4, 0x4e, + 0xf6, 0x4c, 0x9f, 0x25, 0x24, 0x9e, 0x4d, 0xf7, + }, + { + 0x00, 0xbb, 0x6b, 0xd0, 0xd6, 0x6d, 0xbd, 0x06, + 0xb1, 0x0a, 0xda, 0x61, 0x67, 0xdc, 0x0c, 0xb7, + 0x7f, 0xc4, 0x14, 0xaf, 0xa9, 0x12, 0xc2, 0x79, + 0xce, 0x75, 0xa5, 0x1e, 0x18, 0xa3, 0x73, 0xc8, + 0xfe, 0x45, 0x95, 0x2e, 0x28, 0x93, 0x43, 0xf8, + 0x4f, 0xf4, 0x24, 0x9f, 0x99, 0x22, 0xf2, 0x49, + 0x81, 0x3a, 0xea, 0x51, 0x57, 0xec, 0x3c, 0x87, + 0x30, 0x8b, 0x5b, 0xe0, 0xe6, 0x5d, 0x8d, 0x36, + 0xe1, 0x5a, 0x8a, 0x31, 0x37, 0x8c, 0x5c, 0xe7, + 0x50, 0xeb, 0x3b, 0x80, 0x86, 0x3d, 0xed, 0x56, + 0x9e, 0x25, 0xf5, 0x4e, 0x48, 0xf3, 0x23, 0x98, + 0x2f, 0x94, 0x44, 0xff, 0xf9, 0x42, 0x92, 0x29, + 0x1f, 0xa4, 0x74, 0xcf, 0xc9, 0x72, 0xa2, 0x19, + 0xae, 0x15, 0xc5, 0x7e, 0x78, 0xc3, 0x13, 0xa8, + 0x60, 0xdb, 0x0b, 0xb0, 0xb6, 0x0d, 0xdd, 0x66, + 0xd1, 0x6a, 0xba, 0x01, 0x07, 0xbc, 0x6c, 0xd7, + 0xdf, 0x64, 0xb4, 0x0f, 0x09, 0xb2, 0x62, 0xd9, + 0x6e, 0xd5, 0x05, 0xbe, 0xb8, 0x03, 0xd3, 0x68, + 0xa0, 0x1b, 0xcb, 0x70, 0x76, 0xcd, 0x1d, 0xa6, + 0x11, 0xaa, 0x7a, 0xc1, 0xc7, 0x7c, 0xac, 0x17, + 0x21, 0x9a, 0x4a, 0xf1, 0xf7, 0x4c, 0x9c, 0x27, + 0x90, 0x2b, 0xfb, 0x40, 0x46, 0xfd, 0x2d, 0x96, + 0x5e, 0xe5, 0x35, 0x8e, 0x88, 0x33, 0xe3, 0x58, + 0xef, 0x54, 0x84, 0x3f, 0x39, 0x82, 0x52, 0xe9, + 0x3e, 0x85, 0x55, 0xee, 0xe8, 0x53, 0x83, 0x38, + 0x8f, 0x34, 0xe4, 0x5f, 0x59, 0xe2, 0x32, 0x89, + 0x41, 0xfa, 0x2a, 0x91, 0x97, 0x2c, 0xfc, 0x47, + 0xf0, 0x4b, 0x9b, 0x20, 0x26, 0x9d, 0x4d, 0xf6, + 0xc0, 0x7b, 0xab, 0x10, 0x16, 0xad, 0x7d, 0xc6, + 0x71, 0xca, 0x1a, 0xa1, 0xa7, 0x1c, 0xcc, 0x77, + 0xbf, 0x04, 0xd4, 0x6f, 0x69, 0xd2, 0x02, 0xb9, + 0x0e, 0xb5, 0x65, 0xde, 0xd8, 0x63, 0xb3, 0x08, + }, + { + 0x00, 0xbc, 0x65, 0xd9, 0xca, 0x76, 0xaf, 0x13, + 0x89, 0x35, 0xec, 0x50, 0x43, 0xff, 0x26, 0x9a, + 0x0f, 0xb3, 0x6a, 0xd6, 0xc5, 0x79, 0xa0, 0x1c, + 0x86, 0x3a, 0xe3, 0x5f, 0x4c, 0xf0, 0x29, 0x95, + 0x1e, 0xa2, 0x7b, 0xc7, 0xd4, 0x68, 0xb1, 0x0d, + 0x97, 0x2b, 0xf2, 0x4e, 0x5d, 0xe1, 0x38, 0x84, + 0x11, 0xad, 0x74, 0xc8, 0xdb, 0x67, 0xbe, 0x02, + 0x98, 0x24, 0xfd, 0x41, 0x52, 0xee, 0x37, 0x8b, + 0x3c, 0x80, 0x59, 0xe5, 0xf6, 0x4a, 0x93, 0x2f, + 0xb5, 0x09, 0xd0, 0x6c, 0x7f, 0xc3, 0x1a, 0xa6, + 0x33, 0x8f, 0x56, 0xea, 0xf9, 0x45, 0x9c, 0x20, + 0xba, 0x06, 0xdf, 0x63, 0x70, 0xcc, 0x15, 0xa9, + 0x22, 0x9e, 0x47, 0xfb, 0xe8, 0x54, 0x8d, 0x31, + 0xab, 0x17, 0xce, 0x72, 0x61, 0xdd, 0x04, 0xb8, + 0x2d, 0x91, 0x48, 0xf4, 0xe7, 0x5b, 0x82, 0x3e, + 0xa4, 0x18, 0xc1, 0x7d, 0x6e, 0xd2, 0x0b, 0xb7, + 0x78, 0xc4, 0x1d, 0xa1, 0xb2, 0x0e, 0xd7, 0x6b, + 0xf1, 0x4d, 0x94, 0x28, 0x3b, 0x87, 0x5e, 0xe2, + 0x77, 0xcb, 0x12, 0xae, 0xbd, 0x01, 0xd8, 0x64, + 0xfe, 0x42, 0x9b, 0x27, 0x34, 0x88, 0x51, 0xed, + 0x66, 0xda, 0x03, 0xbf, 0xac, 0x10, 0xc9, 0x75, + 0xef, 0x53, 0x8a, 0x36, 0x25, 0x99, 0x40, 0xfc, + 0x69, 0xd5, 0x0c, 0xb0, 0xa3, 0x1f, 0xc6, 0x7a, + 0xe0, 0x5c, 0x85, 0x39, 0x2a, 0x96, 0x4f, 0xf3, + 0x44, 0xf8, 0x21, 0x9d, 0x8e, 0x32, 0xeb, 0x57, + 0xcd, 0x71, 0xa8, 0x14, 0x07, 0xbb, 0x62, 0xde, + 0x4b, 0xf7, 0x2e, 0x92, 0x81, 0x3d, 0xe4, 0x58, + 0xc2, 0x7e, 0xa7, 0x1b, 0x08, 0xb4, 0x6d, 0xd1, + 0x5a, 0xe6, 0x3f, 0x83, 0x90, 0x2c, 0xf5, 0x49, + 0xd3, 0x6f, 0xb6, 0x0a, 0x19, 0xa5, 0x7c, 0xc0, + 0x55, 0xe9, 0x30, 0x8c, 0x9f, 0x23, 0xfa, 0x46, + 0xdc, 0x60, 0xb9, 0x05, 0x16, 0xaa, 0x73, 0xcf, + }, + { + 0x00, 0xbd, 0x67, 0xda, 0xce, 0x73, 0xa9, 0x14, + 0x81, 0x3c, 0xe6, 0x5b, 0x4f, 0xf2, 0x28, 0x95, + 0x1f, 0xa2, 0x78, 0xc5, 0xd1, 0x6c, 0xb6, 0x0b, + 0x9e, 0x23, 0xf9, 0x44, 0x50, 0xed, 0x37, 0x8a, + 0x3e, 0x83, 0x59, 0xe4, 0xf0, 0x4d, 0x97, 0x2a, + 0xbf, 0x02, 0xd8, 0x65, 0x71, 0xcc, 0x16, 0xab, + 0x21, 0x9c, 0x46, 0xfb, 0xef, 0x52, 0x88, 0x35, + 0xa0, 0x1d, 0xc7, 0x7a, 0x6e, 0xd3, 0x09, 0xb4, + 0x7c, 0xc1, 0x1b, 0xa6, 0xb2, 0x0f, 0xd5, 0x68, + 0xfd, 0x40, 0x9a, 0x27, 0x33, 0x8e, 0x54, 0xe9, + 0x63, 0xde, 0x04, 0xb9, 0xad, 0x10, 0xca, 0x77, + 0xe2, 0x5f, 0x85, 0x38, 0x2c, 0x91, 0x4b, 0xf6, + 0x42, 0xff, 0x25, 0x98, 0x8c, 0x31, 0xeb, 0x56, + 0xc3, 0x7e, 0xa4, 0x19, 0x0d, 0xb0, 0x6a, 0xd7, + 0x5d, 0xe0, 0x3a, 0x87, 0x93, 0x2e, 0xf4, 0x49, + 0xdc, 0x61, 0xbb, 0x06, 0x12, 0xaf, 0x75, 0xc8, + 0xf8, 0x45, 0x9f, 0x22, 0x36, 0x8b, 0x51, 0xec, + 0x79, 0xc4, 0x1e, 0xa3, 0xb7, 0x0a, 0xd0, 0x6d, + 0xe7, 0x5a, 0x80, 0x3d, 0x29, 0x94, 0x4e, 0xf3, + 0x66, 0xdb, 0x01, 0xbc, 0xa8, 0x15, 0xcf, 0x72, + 0xc6, 0x7b, 0xa1, 0x1c, 0x08, 0xb5, 0x6f, 0xd2, + 0x47, 0xfa, 0x20, 0x9d, 0x89, 0x34, 0xee, 0x53, + 0xd9, 0x64, 0xbe, 0x03, 0x17, 0xaa, 0x70, 0xcd, + 0x58, 0xe5, 0x3f, 0x82, 0x96, 0x2b, 0xf1, 0x4c, + 0x84, 0x39, 0xe3, 0x5e, 0x4a, 0xf7, 0x2d, 0x90, + 0x05, 0xb8, 0x62, 0xdf, 0xcb, 0x76, 0xac, 0x11, + 0x9b, 0x26, 0xfc, 0x41, 0x55, 0xe8, 0x32, 0x8f, + 0x1a, 0xa7, 0x7d, 0xc0, 0xd4, 0x69, 0xb3, 0x0e, + 0xba, 0x07, 0xdd, 0x60, 0x74, 0xc9, 0x13, 0xae, + 0x3b, 0x86, 0x5c, 0xe1, 0xf5, 0x48, 0x92, 0x2f, + 0xa5, 0x18, 0xc2, 0x7f, 0x6b, 0xd6, 0x0c, 0xb1, + 0x24, 0x99, 0x43, 0xfe, 0xea, 0x57, 0x8d, 0x30, + }, + { + 0x00, 0xbe, 0x61, 0xdf, 0xc2, 0x7c, 0xa3, 0x1d, + 0x99, 0x27, 0xf8, 0x46, 0x5b, 0xe5, 0x3a, 0x84, + 0x2f, 0x91, 0x4e, 0xf0, 0xed, 0x53, 0x8c, 0x32, + 0xb6, 0x08, 0xd7, 0x69, 0x74, 0xca, 0x15, 0xab, + 0x5e, 0xe0, 0x3f, 0x81, 0x9c, 0x22, 0xfd, 0x43, + 0xc7, 0x79, 0xa6, 0x18, 0x05, 0xbb, 0x64, 0xda, + 0x71, 0xcf, 0x10, 0xae, 0xb3, 0x0d, 0xd2, 0x6c, + 0xe8, 0x56, 0x89, 0x37, 0x2a, 0x94, 0x4b, 0xf5, + 0xbc, 0x02, 0xdd, 0x63, 0x7e, 0xc0, 0x1f, 0xa1, + 0x25, 0x9b, 0x44, 0xfa, 0xe7, 0x59, 0x86, 0x38, + 0x93, 0x2d, 0xf2, 0x4c, 0x51, 0xef, 0x30, 0x8e, + 0x0a, 0xb4, 0x6b, 0xd5, 0xc8, 0x76, 0xa9, 0x17, + 0xe2, 0x5c, 0x83, 0x3d, 0x20, 0x9e, 0x41, 0xff, + 0x7b, 0xc5, 0x1a, 0xa4, 0xb9, 0x07, 0xd8, 0x66, + 0xcd, 0x73, 0xac, 0x12, 0x0f, 0xb1, 0x6e, 0xd0, + 0x54, 0xea, 0x35, 0x8b, 0x96, 0x28, 0xf7, 0x49, + 0x65, 0xdb, 0x04, 0xba, 0xa7, 0x19, 0xc6, 0x78, + 0xfc, 0x42, 0x9d, 0x23, 0x3e, 0x80, 0x5f, 0xe1, + 0x4a, 0xf4, 0x2b, 0x95, 0x88, 0x36, 0xe9, 0x57, + 0xd3, 0x6d, 0xb2, 0x0c, 0x11, 0xaf, 0x70, 0xce, + 0x3b, 0x85, 0x5a, 0xe4, 0xf9, 0x47, 0x98, 0x26, + 0xa2, 0x1c, 0xc3, 0x7d, 0x60, 0xde, 0x01, 0xbf, + 0x14, 0xaa, 0x75, 0xcb, 0xd6, 0x68, 0xb7, 0x09, + 0x8d, 0x33, 0xec, 0x52, 0x4f, 0xf1, 0x2e, 0x90, + 0xd9, 0x67, 0xb8, 0x06, 0x1b, 0xa5, 0x7a, 0xc4, + 0x40, 0xfe, 0x21, 0x9f, 0x82, 0x3c, 0xe3, 0x5d, + 0xf6, 0x48, 0x97, 0x29, 0x34, 0x8a, 0x55, 0xeb, + 0x6f, 0xd1, 0x0e, 0xb0, 0xad, 0x13, 0xcc, 0x72, + 0x87, 0x39, 0xe6, 0x58, 0x45, 0xfb, 0x24, 0x9a, + 0x1e, 0xa0, 0x7f, 0xc1, 0xdc, 0x62, 0xbd, 0x03, + 0xa8, 0x16, 0xc9, 0x77, 0x6a, 0xd4, 0x0b, 0xb5, + 0x31, 0x8f, 0x50, 0xee, 0xf3, 0x4d, 0x92, 0x2c, + }, + { + 0x00, 0xbf, 0x63, 0xdc, 0xc6, 0x79, 0xa5, 0x1a, + 0x91, 0x2e, 0xf2, 0x4d, 0x57, 0xe8, 0x34, 0x8b, + 0x3f, 0x80, 0x5c, 0xe3, 0xf9, 0x46, 0x9a, 0x25, + 0xae, 0x11, 0xcd, 0x72, 0x68, 0xd7, 0x0b, 0xb4, + 0x7e, 0xc1, 0x1d, 0xa2, 0xb8, 0x07, 0xdb, 0x64, + 0xef, 0x50, 0x8c, 0x33, 0x29, 0x96, 0x4a, 0xf5, + 0x41, 0xfe, 0x22, 0x9d, 0x87, 0x38, 0xe4, 0x5b, + 0xd0, 0x6f, 0xb3, 0x0c, 0x16, 0xa9, 0x75, 0xca, + 0xfc, 0x43, 0x9f, 0x20, 0x3a, 0x85, 0x59, 0xe6, + 0x6d, 0xd2, 0x0e, 0xb1, 0xab, 0x14, 0xc8, 0x77, + 0xc3, 0x7c, 0xa0, 0x1f, 0x05, 0xba, 0x66, 0xd9, + 0x52, 0xed, 0x31, 0x8e, 0x94, 0x2b, 0xf7, 0x48, + 0x82, 0x3d, 0xe1, 0x5e, 0x44, 0xfb, 0x27, 0x98, + 0x13, 0xac, 0x70, 0xcf, 0xd5, 0x6a, 0xb6, 0x09, + 0xbd, 0x02, 0xde, 0x61, 0x7b, 0xc4, 0x18, 0xa7, + 0x2c, 0x93, 0x4f, 0xf0, 0xea, 0x55, 0x89, 0x36, + 0xe5, 0x5a, 0x86, 0x39, 0x23, 0x9c, 0x40, 0xff, + 0x74, 0xcb, 0x17, 0xa8, 0xb2, 0x0d, 0xd1, 0x6e, + 0xda, 0x65, 0xb9, 0x06, 0x1c, 0xa3, 0x7f, 0xc0, + 0x4b, 0xf4, 0x28, 0x97, 0x8d, 0x32, 0xee, 0x51, + 0x9b, 0x24, 0xf8, 0x47, 0x5d, 0xe2, 0x3e, 0x81, + 0x0a, 0xb5, 0x69, 0xd6, 0xcc, 0x73, 0xaf, 0x10, + 0xa4, 0x1b, 0xc7, 0x78, 0x62, 0xdd, 0x01, 0xbe, + 0x35, 0x8a, 0x56, 0xe9, 0xf3, 0x4c, 0x90, 0x2f, + 0x19, 0xa6, 0x7a, 0xc5, 0xdf, 0x60, 0xbc, 0x03, + 0x88, 0x37, 0xeb, 0x54, 0x4e, 0xf1, 0x2d, 0x92, + 0x26, 0x99, 0x45, 0xfa, 0xe0, 0x5f, 0x83, 0x3c, + 0xb7, 0x08, 0xd4, 0x6b, 0x71, 0xce, 0x12, 0xad, + 0x67, 0xd8, 0x04, 0xbb, 0xa1, 0x1e, 0xc2, 0x7d, + 0xf6, 0x49, 0x95, 0x2a, 0x30, 0x8f, 0x53, 0xec, + 0x58, 0xe7, 0x3b, 0x84, 0x9e, 0x21, 0xfd, 0x42, + 0xc9, 0x76, 0xaa, 0x15, 0x0f, 0xb0, 0x6c, 0xd3, + }, + { + 0x00, 0xc0, 0x9d, 0x5d, 0x27, 0xe7, 0xba, 0x7a, + 0x4e, 0x8e, 0xd3, 0x13, 0x69, 0xa9, 0xf4, 0x34, + 0x9c, 0x5c, 0x01, 0xc1, 0xbb, 0x7b, 0x26, 0xe6, + 0xd2, 0x12, 0x4f, 0x8f, 0xf5, 0x35, 0x68, 0xa8, + 0x25, 0xe5, 0xb8, 0x78, 0x02, 0xc2, 0x9f, 0x5f, + 0x6b, 0xab, 0xf6, 0x36, 0x4c, 0x8c, 0xd1, 0x11, + 0xb9, 0x79, 0x24, 0xe4, 0x9e, 0x5e, 0x03, 0xc3, + 0xf7, 0x37, 0x6a, 0xaa, 0xd0, 0x10, 0x4d, 0x8d, + 0x4a, 0x8a, 0xd7, 0x17, 0x6d, 0xad, 0xf0, 0x30, + 0x04, 0xc4, 0x99, 0x59, 0x23, 0xe3, 0xbe, 0x7e, + 0xd6, 0x16, 0x4b, 0x8b, 0xf1, 0x31, 0x6c, 0xac, + 0x98, 0x58, 0x05, 0xc5, 0xbf, 0x7f, 0x22, 0xe2, + 0x6f, 0xaf, 0xf2, 0x32, 0x48, 0x88, 0xd5, 0x15, + 0x21, 0xe1, 0xbc, 0x7c, 0x06, 0xc6, 0x9b, 0x5b, + 0xf3, 0x33, 0x6e, 0xae, 0xd4, 0x14, 0x49, 0x89, + 0xbd, 0x7d, 0x20, 0xe0, 0x9a, 0x5a, 0x07, 0xc7, + 0x94, 0x54, 0x09, 0xc9, 0xb3, 0x73, 0x2e, 0xee, + 0xda, 0x1a, 0x47, 0x87, 0xfd, 0x3d, 0x60, 0xa0, + 0x08, 0xc8, 0x95, 0x55, 0x2f, 0xef, 0xb2, 0x72, + 0x46, 0x86, 0xdb, 0x1b, 0x61, 0xa1, 0xfc, 0x3c, + 0xb1, 0x71, 0x2c, 0xec, 0x96, 0x56, 0x0b, 0xcb, + 0xff, 0x3f, 0x62, 0xa2, 0xd8, 0x18, 0x45, 0x85, + 0x2d, 0xed, 0xb0, 0x70, 0x0a, 0xca, 0x97, 0x57, + 0x63, 0xa3, 0xfe, 0x3e, 0x44, 0x84, 0xd9, 0x19, + 0xde, 0x1e, 0x43, 0x83, 0xf9, 0x39, 0x64, 0xa4, + 0x90, 0x50, 0x0d, 0xcd, 0xb7, 0x77, 0x2a, 0xea, + 0x42, 0x82, 0xdf, 0x1f, 0x65, 0xa5, 0xf8, 0x38, + 0x0c, 0xcc, 0x91, 0x51, 0x2b, 0xeb, 0xb6, 0x76, + 0xfb, 0x3b, 0x66, 0xa6, 0xdc, 0x1c, 0x41, 0x81, + 0xb5, 0x75, 0x28, 0xe8, 0x92, 0x52, 0x0f, 0xcf, + 0x67, 0xa7, 0xfa, 0x3a, 0x40, 0x80, 0xdd, 0x1d, + 0x29, 0xe9, 0xb4, 0x74, 0x0e, 0xce, 0x93, 0x53, + }, + { + 0x00, 0xc1, 0x9f, 0x5e, 0x23, 0xe2, 0xbc, 0x7d, + 0x46, 0x87, 0xd9, 0x18, 0x65, 0xa4, 0xfa, 0x3b, + 0x8c, 0x4d, 0x13, 0xd2, 0xaf, 0x6e, 0x30, 0xf1, + 0xca, 0x0b, 0x55, 0x94, 0xe9, 0x28, 0x76, 0xb7, + 0x05, 0xc4, 0x9a, 0x5b, 0x26, 0xe7, 0xb9, 0x78, + 0x43, 0x82, 0xdc, 0x1d, 0x60, 0xa1, 0xff, 0x3e, + 0x89, 0x48, 0x16, 0xd7, 0xaa, 0x6b, 0x35, 0xf4, + 0xcf, 0x0e, 0x50, 0x91, 0xec, 0x2d, 0x73, 0xb2, + 0x0a, 0xcb, 0x95, 0x54, 0x29, 0xe8, 0xb6, 0x77, + 0x4c, 0x8d, 0xd3, 0x12, 0x6f, 0xae, 0xf0, 0x31, + 0x86, 0x47, 0x19, 0xd8, 0xa5, 0x64, 0x3a, 0xfb, + 0xc0, 0x01, 0x5f, 0x9e, 0xe3, 0x22, 0x7c, 0xbd, + 0x0f, 0xce, 0x90, 0x51, 0x2c, 0xed, 0xb3, 0x72, + 0x49, 0x88, 0xd6, 0x17, 0x6a, 0xab, 0xf5, 0x34, + 0x83, 0x42, 0x1c, 0xdd, 0xa0, 0x61, 0x3f, 0xfe, + 0xc5, 0x04, 0x5a, 0x9b, 0xe6, 0x27, 0x79, 0xb8, + 0x14, 0xd5, 0x8b, 0x4a, 0x37, 0xf6, 0xa8, 0x69, + 0x52, 0x93, 0xcd, 0x0c, 0x71, 0xb0, 0xee, 0x2f, + 0x98, 0x59, 0x07, 0xc6, 0xbb, 0x7a, 0x24, 0xe5, + 0xde, 0x1f, 0x41, 0x80, 0xfd, 0x3c, 0x62, 0xa3, + 0x11, 0xd0, 0x8e, 0x4f, 0x32, 0xf3, 0xad, 0x6c, + 0x57, 0x96, 0xc8, 0x09, 0x74, 0xb5, 0xeb, 0x2a, + 0x9d, 0x5c, 0x02, 0xc3, 0xbe, 0x7f, 0x21, 0xe0, + 0xdb, 0x1a, 0x44, 0x85, 0xf8, 0x39, 0x67, 0xa6, + 0x1e, 0xdf, 0x81, 0x40, 0x3d, 0xfc, 0xa2, 0x63, + 0x58, 0x99, 0xc7, 0x06, 0x7b, 0xba, 0xe4, 0x25, + 0x92, 0x53, 0x0d, 0xcc, 0xb1, 0x70, 0x2e, 0xef, + 0xd4, 0x15, 0x4b, 0x8a, 0xf7, 0x36, 0x68, 0xa9, + 0x1b, 0xda, 0x84, 0x45, 0x38, 0xf9, 0xa7, 0x66, + 0x5d, 0x9c, 0xc2, 0x03, 0x7e, 0xbf, 0xe1, 0x20, + 0x97, 0x56, 0x08, 0xc9, 0xb4, 0x75, 0x2b, 0xea, + 0xd1, 0x10, 0x4e, 0x8f, 0xf2, 0x33, 0x6d, 0xac, + }, + { + 0x00, 0xc2, 0x99, 0x5b, 0x2f, 0xed, 0xb6, 0x74, + 0x5e, 0x9c, 0xc7, 0x05, 0x71, 0xb3, 0xe8, 0x2a, + 0xbc, 0x7e, 0x25, 0xe7, 0x93, 0x51, 0x0a, 0xc8, + 0xe2, 0x20, 0x7b, 0xb9, 0xcd, 0x0f, 0x54, 0x96, + 0x65, 0xa7, 0xfc, 0x3e, 0x4a, 0x88, 0xd3, 0x11, + 0x3b, 0xf9, 0xa2, 0x60, 0x14, 0xd6, 0x8d, 0x4f, + 0xd9, 0x1b, 0x40, 0x82, 0xf6, 0x34, 0x6f, 0xad, + 0x87, 0x45, 0x1e, 0xdc, 0xa8, 0x6a, 0x31, 0xf3, + 0xca, 0x08, 0x53, 0x91, 0xe5, 0x27, 0x7c, 0xbe, + 0x94, 0x56, 0x0d, 0xcf, 0xbb, 0x79, 0x22, 0xe0, + 0x76, 0xb4, 0xef, 0x2d, 0x59, 0x9b, 0xc0, 0x02, + 0x28, 0xea, 0xb1, 0x73, 0x07, 0xc5, 0x9e, 0x5c, + 0xaf, 0x6d, 0x36, 0xf4, 0x80, 0x42, 0x19, 0xdb, + 0xf1, 0x33, 0x68, 0xaa, 0xde, 0x1c, 0x47, 0x85, + 0x13, 0xd1, 0x8a, 0x48, 0x3c, 0xfe, 0xa5, 0x67, + 0x4d, 0x8f, 0xd4, 0x16, 0x62, 0xa0, 0xfb, 0x39, + 0x89, 0x4b, 0x10, 0xd2, 0xa6, 0x64, 0x3f, 0xfd, + 0xd7, 0x15, 0x4e, 0x8c, 0xf8, 0x3a, 0x61, 0xa3, + 0x35, 0xf7, 0xac, 0x6e, 0x1a, 0xd8, 0x83, 0x41, + 0x6b, 0xa9, 0xf2, 0x30, 0x44, 0x86, 0xdd, 0x1f, + 0xec, 0x2e, 0x75, 0xb7, 0xc3, 0x01, 0x5a, 0x98, + 0xb2, 0x70, 0x2b, 0xe9, 0x9d, 0x5f, 0x04, 0xc6, + 0x50, 0x92, 0xc9, 0x0b, 0x7f, 0xbd, 0xe6, 0x24, + 0x0e, 0xcc, 0x97, 0x55, 0x21, 0xe3, 0xb8, 0x7a, + 0x43, 0x81, 0xda, 0x18, 0x6c, 0xae, 0xf5, 0x37, + 0x1d, 0xdf, 0x84, 0x46, 0x32, 0xf0, 0xab, 0x69, + 0xff, 0x3d, 0x66, 0xa4, 0xd0, 0x12, 0x49, 0x8b, + 0xa1, 0x63, 0x38, 0xfa, 0x8e, 0x4c, 0x17, 0xd5, + 0x26, 0xe4, 0xbf, 0x7d, 0x09, 0xcb, 0x90, 0x52, + 0x78, 0xba, 0xe1, 0x23, 0x57, 0x95, 0xce, 0x0c, + 0x9a, 0x58, 0x03, 0xc1, 0xb5, 0x77, 0x2c, 0xee, + 0xc4, 0x06, 0x5d, 0x9f, 0xeb, 0x29, 0x72, 0xb0, + }, + { + 0x00, 0xc3, 0x9b, 0x58, 0x2b, 0xe8, 0xb0, 0x73, + 0x56, 0x95, 0xcd, 0x0e, 0x7d, 0xbe, 0xe6, 0x25, + 0xac, 0x6f, 0x37, 0xf4, 0x87, 0x44, 0x1c, 0xdf, + 0xfa, 0x39, 0x61, 0xa2, 0xd1, 0x12, 0x4a, 0x89, + 0x45, 0x86, 0xde, 0x1d, 0x6e, 0xad, 0xf5, 0x36, + 0x13, 0xd0, 0x88, 0x4b, 0x38, 0xfb, 0xa3, 0x60, + 0xe9, 0x2a, 0x72, 0xb1, 0xc2, 0x01, 0x59, 0x9a, + 0xbf, 0x7c, 0x24, 0xe7, 0x94, 0x57, 0x0f, 0xcc, + 0x8a, 0x49, 0x11, 0xd2, 0xa1, 0x62, 0x3a, 0xf9, + 0xdc, 0x1f, 0x47, 0x84, 0xf7, 0x34, 0x6c, 0xaf, + 0x26, 0xe5, 0xbd, 0x7e, 0x0d, 0xce, 0x96, 0x55, + 0x70, 0xb3, 0xeb, 0x28, 0x5b, 0x98, 0xc0, 0x03, + 0xcf, 0x0c, 0x54, 0x97, 0xe4, 0x27, 0x7f, 0xbc, + 0x99, 0x5a, 0x02, 0xc1, 0xb2, 0x71, 0x29, 0xea, + 0x63, 0xa0, 0xf8, 0x3b, 0x48, 0x8b, 0xd3, 0x10, + 0x35, 0xf6, 0xae, 0x6d, 0x1e, 0xdd, 0x85, 0x46, + 0x09, 0xca, 0x92, 0x51, 0x22, 0xe1, 0xb9, 0x7a, + 0x5f, 0x9c, 0xc4, 0x07, 0x74, 0xb7, 0xef, 0x2c, + 0xa5, 0x66, 0x3e, 0xfd, 0x8e, 0x4d, 0x15, 0xd6, + 0xf3, 0x30, 0x68, 0xab, 0xd8, 0x1b, 0x43, 0x80, + 0x4c, 0x8f, 0xd7, 0x14, 0x67, 0xa4, 0xfc, 0x3f, + 0x1a, 0xd9, 0x81, 0x42, 0x31, 0xf2, 0xaa, 0x69, + 0xe0, 0x23, 0x7b, 0xb8, 0xcb, 0x08, 0x50, 0x93, + 0xb6, 0x75, 0x2d, 0xee, 0x9d, 0x5e, 0x06, 0xc5, + 0x83, 0x40, 0x18, 0xdb, 0xa8, 0x6b, 0x33, 0xf0, + 0xd5, 0x16, 0x4e, 0x8d, 0xfe, 0x3d, 0x65, 0xa6, + 0x2f, 0xec, 0xb4, 0x77, 0x04, 0xc7, 0x9f, 0x5c, + 0x79, 0xba, 0xe2, 0x21, 0x52, 0x91, 0xc9, 0x0a, + 0xc6, 0x05, 0x5d, 0x9e, 0xed, 0x2e, 0x76, 0xb5, + 0x90, 0x53, 0x0b, 0xc8, 0xbb, 0x78, 0x20, 0xe3, + 0x6a, 0xa9, 0xf1, 0x32, 0x41, 0x82, 0xda, 0x19, + 0x3c, 0xff, 0xa7, 0x64, 0x17, 0xd4, 0x8c, 0x4f, + }, + { + 0x00, 0xc4, 0x95, 0x51, 0x37, 0xf3, 0xa2, 0x66, + 0x6e, 0xaa, 0xfb, 0x3f, 0x59, 0x9d, 0xcc, 0x08, + 0xdc, 0x18, 0x49, 0x8d, 0xeb, 0x2f, 0x7e, 0xba, + 0xb2, 0x76, 0x27, 0xe3, 0x85, 0x41, 0x10, 0xd4, + 0xa5, 0x61, 0x30, 0xf4, 0x92, 0x56, 0x07, 0xc3, + 0xcb, 0x0f, 0x5e, 0x9a, 0xfc, 0x38, 0x69, 0xad, + 0x79, 0xbd, 0xec, 0x28, 0x4e, 0x8a, 0xdb, 0x1f, + 0x17, 0xd3, 0x82, 0x46, 0x20, 0xe4, 0xb5, 0x71, + 0x57, 0x93, 0xc2, 0x06, 0x60, 0xa4, 0xf5, 0x31, + 0x39, 0xfd, 0xac, 0x68, 0x0e, 0xca, 0x9b, 0x5f, + 0x8b, 0x4f, 0x1e, 0xda, 0xbc, 0x78, 0x29, 0xed, + 0xe5, 0x21, 0x70, 0xb4, 0xd2, 0x16, 0x47, 0x83, + 0xf2, 0x36, 0x67, 0xa3, 0xc5, 0x01, 0x50, 0x94, + 0x9c, 0x58, 0x09, 0xcd, 0xab, 0x6f, 0x3e, 0xfa, + 0x2e, 0xea, 0xbb, 0x7f, 0x19, 0xdd, 0x8c, 0x48, + 0x40, 0x84, 0xd5, 0x11, 0x77, 0xb3, 0xe2, 0x26, + 0xae, 0x6a, 0x3b, 0xff, 0x99, 0x5d, 0x0c, 0xc8, + 0xc0, 0x04, 0x55, 0x91, 0xf7, 0x33, 0x62, 0xa6, + 0x72, 0xb6, 0xe7, 0x23, 0x45, 0x81, 0xd0, 0x14, + 0x1c, 0xd8, 0x89, 0x4d, 0x2b, 0xef, 0xbe, 0x7a, + 0x0b, 0xcf, 0x9e, 0x5a, 0x3c, 0xf8, 0xa9, 0x6d, + 0x65, 0xa1, 0xf0, 0x34, 0x52, 0x96, 0xc7, 0x03, + 0xd7, 0x13, 0x42, 0x86, 0xe0, 0x24, 0x75, 0xb1, + 0xb9, 0x7d, 0x2c, 0xe8, 0x8e, 0x4a, 0x1b, 0xdf, + 0xf9, 0x3d, 0x6c, 0xa8, 0xce, 0x0a, 0x5b, 0x9f, + 0x97, 0x53, 0x02, 0xc6, 0xa0, 0x64, 0x35, 0xf1, + 0x25, 0xe1, 0xb0, 0x74, 0x12, 0xd6, 0x87, 0x43, + 0x4b, 0x8f, 0xde, 0x1a, 0x7c, 0xb8, 0xe9, 0x2d, + 0x5c, 0x98, 0xc9, 0x0d, 0x6b, 0xaf, 0xfe, 0x3a, + 0x32, 0xf6, 0xa7, 0x63, 0x05, 0xc1, 0x90, 0x54, + 0x80, 0x44, 0x15, 0xd1, 0xb7, 0x73, 0x22, 0xe6, + 0xee, 0x2a, 0x7b, 0xbf, 0xd9, 0x1d, 0x4c, 0x88, + }, + { + 0x00, 0xc5, 0x97, 0x52, 0x33, 0xf6, 0xa4, 0x61, + 0x66, 0xa3, 0xf1, 0x34, 0x55, 0x90, 0xc2, 0x07, + 0xcc, 0x09, 0x5b, 0x9e, 0xff, 0x3a, 0x68, 0xad, + 0xaa, 0x6f, 0x3d, 0xf8, 0x99, 0x5c, 0x0e, 0xcb, + 0x85, 0x40, 0x12, 0xd7, 0xb6, 0x73, 0x21, 0xe4, + 0xe3, 0x26, 0x74, 0xb1, 0xd0, 0x15, 0x47, 0x82, + 0x49, 0x8c, 0xde, 0x1b, 0x7a, 0xbf, 0xed, 0x28, + 0x2f, 0xea, 0xb8, 0x7d, 0x1c, 0xd9, 0x8b, 0x4e, + 0x17, 0xd2, 0x80, 0x45, 0x24, 0xe1, 0xb3, 0x76, + 0x71, 0xb4, 0xe6, 0x23, 0x42, 0x87, 0xd5, 0x10, + 0xdb, 0x1e, 0x4c, 0x89, 0xe8, 0x2d, 0x7f, 0xba, + 0xbd, 0x78, 0x2a, 0xef, 0x8e, 0x4b, 0x19, 0xdc, + 0x92, 0x57, 0x05, 0xc0, 0xa1, 0x64, 0x36, 0xf3, + 0xf4, 0x31, 0x63, 0xa6, 0xc7, 0x02, 0x50, 0x95, + 0x5e, 0x9b, 0xc9, 0x0c, 0x6d, 0xa8, 0xfa, 0x3f, + 0x38, 0xfd, 0xaf, 0x6a, 0x0b, 0xce, 0x9c, 0x59, + 0x2e, 0xeb, 0xb9, 0x7c, 0x1d, 0xd8, 0x8a, 0x4f, + 0x48, 0x8d, 0xdf, 0x1a, 0x7b, 0xbe, 0xec, 0x29, + 0xe2, 0x27, 0x75, 0xb0, 0xd1, 0x14, 0x46, 0x83, + 0x84, 0x41, 0x13, 0xd6, 0xb7, 0x72, 0x20, 0xe5, + 0xab, 0x6e, 0x3c, 0xf9, 0x98, 0x5d, 0x0f, 0xca, + 0xcd, 0x08, 0x5a, 0x9f, 0xfe, 0x3b, 0x69, 0xac, + 0x67, 0xa2, 0xf0, 0x35, 0x54, 0x91, 0xc3, 0x06, + 0x01, 0xc4, 0x96, 0x53, 0x32, 0xf7, 0xa5, 0x60, + 0x39, 0xfc, 0xae, 0x6b, 0x0a, 0xcf, 0x9d, 0x58, + 0x5f, 0x9a, 0xc8, 0x0d, 0x6c, 0xa9, 0xfb, 0x3e, + 0xf5, 0x30, 0x62, 0xa7, 0xc6, 0x03, 0x51, 0x94, + 0x93, 0x56, 0x04, 0xc1, 0xa0, 0x65, 0x37, 0xf2, + 0xbc, 0x79, 0x2b, 0xee, 0x8f, 0x4a, 0x18, 0xdd, + 0xda, 0x1f, 0x4d, 0x88, 0xe9, 0x2c, 0x7e, 0xbb, + 0x70, 0xb5, 0xe7, 0x22, 0x43, 0x86, 0xd4, 0x11, + 0x16, 0xd3, 0x81, 0x44, 0x25, 0xe0, 0xb2, 0x77, + }, + { + 0x00, 0xc6, 0x91, 0x57, 0x3f, 0xf9, 0xae, 0x68, + 0x7e, 0xb8, 0xef, 0x29, 0x41, 0x87, 0xd0, 0x16, + 0xfc, 0x3a, 0x6d, 0xab, 0xc3, 0x05, 0x52, 0x94, + 0x82, 0x44, 0x13, 0xd5, 0xbd, 0x7b, 0x2c, 0xea, + 0xe5, 0x23, 0x74, 0xb2, 0xda, 0x1c, 0x4b, 0x8d, + 0x9b, 0x5d, 0x0a, 0xcc, 0xa4, 0x62, 0x35, 0xf3, + 0x19, 0xdf, 0x88, 0x4e, 0x26, 0xe0, 0xb7, 0x71, + 0x67, 0xa1, 0xf6, 0x30, 0x58, 0x9e, 0xc9, 0x0f, + 0xd7, 0x11, 0x46, 0x80, 0xe8, 0x2e, 0x79, 0xbf, + 0xa9, 0x6f, 0x38, 0xfe, 0x96, 0x50, 0x07, 0xc1, + 0x2b, 0xed, 0xba, 0x7c, 0x14, 0xd2, 0x85, 0x43, + 0x55, 0x93, 0xc4, 0x02, 0x6a, 0xac, 0xfb, 0x3d, + 0x32, 0xf4, 0xa3, 0x65, 0x0d, 0xcb, 0x9c, 0x5a, + 0x4c, 0x8a, 0xdd, 0x1b, 0x73, 0xb5, 0xe2, 0x24, + 0xce, 0x08, 0x5f, 0x99, 0xf1, 0x37, 0x60, 0xa6, + 0xb0, 0x76, 0x21, 0xe7, 0x8f, 0x49, 0x1e, 0xd8, + 0xb3, 0x75, 0x22, 0xe4, 0x8c, 0x4a, 0x1d, 0xdb, + 0xcd, 0x0b, 0x5c, 0x9a, 0xf2, 0x34, 0x63, 0xa5, + 0x4f, 0x89, 0xde, 0x18, 0x70, 0xb6, 0xe1, 0x27, + 0x31, 0xf7, 0xa0, 0x66, 0x0e, 0xc8, 0x9f, 0x59, + 0x56, 0x90, 0xc7, 0x01, 0x69, 0xaf, 0xf8, 0x3e, + 0x28, 0xee, 0xb9, 0x7f, 0x17, 0xd1, 0x86, 0x40, + 0xaa, 0x6c, 0x3b, 0xfd, 0x95, 0x53, 0x04, 0xc2, + 0xd4, 0x12, 0x45, 0x83, 0xeb, 0x2d, 0x7a, 0xbc, + 0x64, 0xa2, 0xf5, 0x33, 0x5b, 0x9d, 0xca, 0x0c, + 0x1a, 0xdc, 0x8b, 0x4d, 0x25, 0xe3, 0xb4, 0x72, + 0x98, 0x5e, 0x09, 0xcf, 0xa7, 0x61, 0x36, 0xf0, + 0xe6, 0x20, 0x77, 0xb1, 0xd9, 0x1f, 0x48, 0x8e, + 0x81, 0x47, 0x10, 0xd6, 0xbe, 0x78, 0x2f, 0xe9, + 0xff, 0x39, 0x6e, 0xa8, 0xc0, 0x06, 0x51, 0x97, + 0x7d, 0xbb, 0xec, 0x2a, 0x42, 0x84, 0xd3, 0x15, + 0x03, 0xc5, 0x92, 0x54, 0x3c, 0xfa, 0xad, 0x6b, + }, + { + 0x00, 0xc7, 0x93, 0x54, 0x3b, 0xfc, 0xa8, 0x6f, + 0x76, 0xb1, 0xe5, 0x22, 0x4d, 0x8a, 0xde, 0x19, + 0xec, 0x2b, 0x7f, 0xb8, 0xd7, 0x10, 0x44, 0x83, + 0x9a, 0x5d, 0x09, 0xce, 0xa1, 0x66, 0x32, 0xf5, + 0xc5, 0x02, 0x56, 0x91, 0xfe, 0x39, 0x6d, 0xaa, + 0xb3, 0x74, 0x20, 0xe7, 0x88, 0x4f, 0x1b, 0xdc, + 0x29, 0xee, 0xba, 0x7d, 0x12, 0xd5, 0x81, 0x46, + 0x5f, 0x98, 0xcc, 0x0b, 0x64, 0xa3, 0xf7, 0x30, + 0x97, 0x50, 0x04, 0xc3, 0xac, 0x6b, 0x3f, 0xf8, + 0xe1, 0x26, 0x72, 0xb5, 0xda, 0x1d, 0x49, 0x8e, + 0x7b, 0xbc, 0xe8, 0x2f, 0x40, 0x87, 0xd3, 0x14, + 0x0d, 0xca, 0x9e, 0x59, 0x36, 0xf1, 0xa5, 0x62, + 0x52, 0x95, 0xc1, 0x06, 0x69, 0xae, 0xfa, 0x3d, + 0x24, 0xe3, 0xb7, 0x70, 0x1f, 0xd8, 0x8c, 0x4b, + 0xbe, 0x79, 0x2d, 0xea, 0x85, 0x42, 0x16, 0xd1, + 0xc8, 0x0f, 0x5b, 0x9c, 0xf3, 0x34, 0x60, 0xa7, + 0x33, 0xf4, 0xa0, 0x67, 0x08, 0xcf, 0x9b, 0x5c, + 0x45, 0x82, 0xd6, 0x11, 0x7e, 0xb9, 0xed, 0x2a, + 0xdf, 0x18, 0x4c, 0x8b, 0xe4, 0x23, 0x77, 0xb0, + 0xa9, 0x6e, 0x3a, 0xfd, 0x92, 0x55, 0x01, 0xc6, + 0xf6, 0x31, 0x65, 0xa2, 0xcd, 0x0a, 0x5e, 0x99, + 0x80, 0x47, 0x13, 0xd4, 0xbb, 0x7c, 0x28, 0xef, + 0x1a, 0xdd, 0x89, 0x4e, 0x21, 0xe6, 0xb2, 0x75, + 0x6c, 0xab, 0xff, 0x38, 0x57, 0x90, 0xc4, 0x03, + 0xa4, 0x63, 0x37, 0xf0, 0x9f, 0x58, 0x0c, 0xcb, + 0xd2, 0x15, 0x41, 0x86, 0xe9, 0x2e, 0x7a, 0xbd, + 0x48, 0x8f, 0xdb, 0x1c, 0x73, 0xb4, 0xe0, 0x27, + 0x3e, 0xf9, 0xad, 0x6a, 0x05, 0xc2, 0x96, 0x51, + 0x61, 0xa6, 0xf2, 0x35, 0x5a, 0x9d, 0xc9, 0x0e, + 0x17, 0xd0, 0x84, 0x43, 0x2c, 0xeb, 0xbf, 0x78, + 0x8d, 0x4a, 0x1e, 0xd9, 0xb6, 0x71, 0x25, 0xe2, + 0xfb, 0x3c, 0x68, 0xaf, 0xc0, 0x07, 0x53, 0x94, + }, + { + 0x00, 0xc8, 0x8d, 0x45, 0x07, 0xcf, 0x8a, 0x42, + 0x0e, 0xc6, 0x83, 0x4b, 0x09, 0xc1, 0x84, 0x4c, + 0x1c, 0xd4, 0x91, 0x59, 0x1b, 0xd3, 0x96, 0x5e, + 0x12, 0xda, 0x9f, 0x57, 0x15, 0xdd, 0x98, 0x50, + 0x38, 0xf0, 0xb5, 0x7d, 0x3f, 0xf7, 0xb2, 0x7a, + 0x36, 0xfe, 0xbb, 0x73, 0x31, 0xf9, 0xbc, 0x74, + 0x24, 0xec, 0xa9, 0x61, 0x23, 0xeb, 0xae, 0x66, + 0x2a, 0xe2, 0xa7, 0x6f, 0x2d, 0xe5, 0xa0, 0x68, + 0x70, 0xb8, 0xfd, 0x35, 0x77, 0xbf, 0xfa, 0x32, + 0x7e, 0xb6, 0xf3, 0x3b, 0x79, 0xb1, 0xf4, 0x3c, + 0x6c, 0xa4, 0xe1, 0x29, 0x6b, 0xa3, 0xe6, 0x2e, + 0x62, 0xaa, 0xef, 0x27, 0x65, 0xad, 0xe8, 0x20, + 0x48, 0x80, 0xc5, 0x0d, 0x4f, 0x87, 0xc2, 0x0a, + 0x46, 0x8e, 0xcb, 0x03, 0x41, 0x89, 0xcc, 0x04, + 0x54, 0x9c, 0xd9, 0x11, 0x53, 0x9b, 0xde, 0x16, + 0x5a, 0x92, 0xd7, 0x1f, 0x5d, 0x95, 0xd0, 0x18, + 0xe0, 0x28, 0x6d, 0xa5, 0xe7, 0x2f, 0x6a, 0xa2, + 0xee, 0x26, 0x63, 0xab, 0xe9, 0x21, 0x64, 0xac, + 0xfc, 0x34, 0x71, 0xb9, 0xfb, 0x33, 0x76, 0xbe, + 0xf2, 0x3a, 0x7f, 0xb7, 0xf5, 0x3d, 0x78, 0xb0, + 0xd8, 0x10, 0x55, 0x9d, 0xdf, 0x17, 0x52, 0x9a, + 0xd6, 0x1e, 0x5b, 0x93, 0xd1, 0x19, 0x5c, 0x94, + 0xc4, 0x0c, 0x49, 0x81, 0xc3, 0x0b, 0x4e, 0x86, + 0xca, 0x02, 0x47, 0x8f, 0xcd, 0x05, 0x40, 0x88, + 0x90, 0x58, 0x1d, 0xd5, 0x97, 0x5f, 0x1a, 0xd2, + 0x9e, 0x56, 0x13, 0xdb, 0x99, 0x51, 0x14, 0xdc, + 0x8c, 0x44, 0x01, 0xc9, 0x8b, 0x43, 0x06, 0xce, + 0x82, 0x4a, 0x0f, 0xc7, 0x85, 0x4d, 0x08, 0xc0, + 0xa8, 0x60, 0x25, 0xed, 0xaf, 0x67, 0x22, 0xea, + 0xa6, 0x6e, 0x2b, 0xe3, 0xa1, 0x69, 0x2c, 0xe4, + 0xb4, 0x7c, 0x39, 0xf1, 0xb3, 0x7b, 0x3e, 0xf6, + 0xba, 0x72, 0x37, 0xff, 0xbd, 0x75, 0x30, 0xf8, + }, + { + 0x00, 0xc9, 0x8f, 0x46, 0x03, 0xca, 0x8c, 0x45, + 0x06, 0xcf, 0x89, 0x40, 0x05, 0xcc, 0x8a, 0x43, + 0x0c, 0xc5, 0x83, 0x4a, 0x0f, 0xc6, 0x80, 0x49, + 0x0a, 0xc3, 0x85, 0x4c, 0x09, 0xc0, 0x86, 0x4f, + 0x18, 0xd1, 0x97, 0x5e, 0x1b, 0xd2, 0x94, 0x5d, + 0x1e, 0xd7, 0x91, 0x58, 0x1d, 0xd4, 0x92, 0x5b, + 0x14, 0xdd, 0x9b, 0x52, 0x17, 0xde, 0x98, 0x51, + 0x12, 0xdb, 0x9d, 0x54, 0x11, 0xd8, 0x9e, 0x57, + 0x30, 0xf9, 0xbf, 0x76, 0x33, 0xfa, 0xbc, 0x75, + 0x36, 0xff, 0xb9, 0x70, 0x35, 0xfc, 0xba, 0x73, + 0x3c, 0xf5, 0xb3, 0x7a, 0x3f, 0xf6, 0xb0, 0x79, + 0x3a, 0xf3, 0xb5, 0x7c, 0x39, 0xf0, 0xb6, 0x7f, + 0x28, 0xe1, 0xa7, 0x6e, 0x2b, 0xe2, 0xa4, 0x6d, + 0x2e, 0xe7, 0xa1, 0x68, 0x2d, 0xe4, 0xa2, 0x6b, + 0x24, 0xed, 0xab, 0x62, 0x27, 0xee, 0xa8, 0x61, + 0x22, 0xeb, 0xad, 0x64, 0x21, 0xe8, 0xae, 0x67, + 0x60, 0xa9, 0xef, 0x26, 0x63, 0xaa, 0xec, 0x25, + 0x66, 0xaf, 0xe9, 0x20, 0x65, 0xac, 0xea, 0x23, + 0x6c, 0xa5, 0xe3, 0x2a, 0x6f, 0xa6, 0xe0, 0x29, + 0x6a, 0xa3, 0xe5, 0x2c, 0x69, 0xa0, 0xe6, 0x2f, + 0x78, 0xb1, 0xf7, 0x3e, 0x7b, 0xb2, 0xf4, 0x3d, + 0x7e, 0xb7, 0xf1, 0x38, 0x7d, 0xb4, 0xf2, 0x3b, + 0x74, 0xbd, 0xfb, 0x32, 0x77, 0xbe, 0xf8, 0x31, + 0x72, 0xbb, 0xfd, 0x34, 0x71, 0xb8, 0xfe, 0x37, + 0x50, 0x99, 0xdf, 0x16, 0x53, 0x9a, 0xdc, 0x15, + 0x56, 0x9f, 0xd9, 0x10, 0x55, 0x9c, 0xda, 0x13, + 0x5c, 0x95, 0xd3, 0x1a, 0x5f, 0x96, 0xd0, 0x19, + 0x5a, 0x93, 0xd5, 0x1c, 0x59, 0x90, 0xd6, 0x1f, + 0x48, 0x81, 0xc7, 0x0e, 0x4b, 0x82, 0xc4, 0x0d, + 0x4e, 0x87, 0xc1, 0x08, 0x4d, 0x84, 0xc2, 0x0b, + 0x44, 0x8d, 0xcb, 0x02, 0x47, 0x8e, 0xc8, 0x01, + 0x42, 0x8b, 0xcd, 0x04, 0x41, 0x88, 0xce, 0x07, + }, + { + 0x00, 0xca, 0x89, 0x43, 0x0f, 0xc5, 0x86, 0x4c, + 0x1e, 0xd4, 0x97, 0x5d, 0x11, 0xdb, 0x98, 0x52, + 0x3c, 0xf6, 0xb5, 0x7f, 0x33, 0xf9, 0xba, 0x70, + 0x22, 0xe8, 0xab, 0x61, 0x2d, 0xe7, 0xa4, 0x6e, + 0x78, 0xb2, 0xf1, 0x3b, 0x77, 0xbd, 0xfe, 0x34, + 0x66, 0xac, 0xef, 0x25, 0x69, 0xa3, 0xe0, 0x2a, + 0x44, 0x8e, 0xcd, 0x07, 0x4b, 0x81, 0xc2, 0x08, + 0x5a, 0x90, 0xd3, 0x19, 0x55, 0x9f, 0xdc, 0x16, + 0xf0, 0x3a, 0x79, 0xb3, 0xff, 0x35, 0x76, 0xbc, + 0xee, 0x24, 0x67, 0xad, 0xe1, 0x2b, 0x68, 0xa2, + 0xcc, 0x06, 0x45, 0x8f, 0xc3, 0x09, 0x4a, 0x80, + 0xd2, 0x18, 0x5b, 0x91, 0xdd, 0x17, 0x54, 0x9e, + 0x88, 0x42, 0x01, 0xcb, 0x87, 0x4d, 0x0e, 0xc4, + 0x96, 0x5c, 0x1f, 0xd5, 0x99, 0x53, 0x10, 0xda, + 0xb4, 0x7e, 0x3d, 0xf7, 0xbb, 0x71, 0x32, 0xf8, + 0xaa, 0x60, 0x23, 0xe9, 0xa5, 0x6f, 0x2c, 0xe6, + 0xfd, 0x37, 0x74, 0xbe, 0xf2, 0x38, 0x7b, 0xb1, + 0xe3, 0x29, 0x6a, 0xa0, 0xec, 0x26, 0x65, 0xaf, + 0xc1, 0x0b, 0x48, 0x82, 0xce, 0x04, 0x47, 0x8d, + 0xdf, 0x15, 0x56, 0x9c, 0xd0, 0x1a, 0x59, 0x93, + 0x85, 0x4f, 0x0c, 0xc6, 0x8a, 0x40, 0x03, 0xc9, + 0x9b, 0x51, 0x12, 0xd8, 0x94, 0x5e, 0x1d, 0xd7, + 0xb9, 0x73, 0x30, 0xfa, 0xb6, 0x7c, 0x3f, 0xf5, + 0xa7, 0x6d, 0x2e, 0xe4, 0xa8, 0x62, 0x21, 0xeb, + 0x0d, 0xc7, 0x84, 0x4e, 0x02, 0xc8, 0x8b, 0x41, + 0x13, 0xd9, 0x9a, 0x50, 0x1c, 0xd6, 0x95, 0x5f, + 0x31, 0xfb, 0xb8, 0x72, 0x3e, 0xf4, 0xb7, 0x7d, + 0x2f, 0xe5, 0xa6, 0x6c, 0x20, 0xea, 0xa9, 0x63, + 0x75, 0xbf, 0xfc, 0x36, 0x7a, 0xb0, 0xf3, 0x39, + 0x6b, 0xa1, 0xe2, 0x28, 0x64, 0xae, 0xed, 0x27, + 0x49, 0x83, 0xc0, 0x0a, 0x46, 0x8c, 0xcf, 0x05, + 0x57, 0x9d, 0xde, 0x14, 0x58, 0x92, 0xd1, 0x1b, + }, + { + 0x00, 0xcb, 0x8b, 0x40, 0x0b, 0xc0, 0x80, 0x4b, + 0x16, 0xdd, 0x9d, 0x56, 0x1d, 0xd6, 0x96, 0x5d, + 0x2c, 0xe7, 0xa7, 0x6c, 0x27, 0xec, 0xac, 0x67, + 0x3a, 0xf1, 0xb1, 0x7a, 0x31, 0xfa, 0xba, 0x71, + 0x58, 0x93, 0xd3, 0x18, 0x53, 0x98, 0xd8, 0x13, + 0x4e, 0x85, 0xc5, 0x0e, 0x45, 0x8e, 0xce, 0x05, + 0x74, 0xbf, 0xff, 0x34, 0x7f, 0xb4, 0xf4, 0x3f, + 0x62, 0xa9, 0xe9, 0x22, 0x69, 0xa2, 0xe2, 0x29, + 0xb0, 0x7b, 0x3b, 0xf0, 0xbb, 0x70, 0x30, 0xfb, + 0xa6, 0x6d, 0x2d, 0xe6, 0xad, 0x66, 0x26, 0xed, + 0x9c, 0x57, 0x17, 0xdc, 0x97, 0x5c, 0x1c, 0xd7, + 0x8a, 0x41, 0x01, 0xca, 0x81, 0x4a, 0x0a, 0xc1, + 0xe8, 0x23, 0x63, 0xa8, 0xe3, 0x28, 0x68, 0xa3, + 0xfe, 0x35, 0x75, 0xbe, 0xf5, 0x3e, 0x7e, 0xb5, + 0xc4, 0x0f, 0x4f, 0x84, 0xcf, 0x04, 0x44, 0x8f, + 0xd2, 0x19, 0x59, 0x92, 0xd9, 0x12, 0x52, 0x99, + 0x7d, 0xb6, 0xf6, 0x3d, 0x76, 0xbd, 0xfd, 0x36, + 0x6b, 0xa0, 0xe0, 0x2b, 0x60, 0xab, 0xeb, 0x20, + 0x51, 0x9a, 0xda, 0x11, 0x5a, 0x91, 0xd1, 0x1a, + 0x47, 0x8c, 0xcc, 0x07, 0x4c, 0x87, 0xc7, 0x0c, + 0x25, 0xee, 0xae, 0x65, 0x2e, 0xe5, 0xa5, 0x6e, + 0x33, 0xf8, 0xb8, 0x73, 0x38, 0xf3, 0xb3, 0x78, + 0x09, 0xc2, 0x82, 0x49, 0x02, 0xc9, 0x89, 0x42, + 0x1f, 0xd4, 0x94, 0x5f, 0x14, 0xdf, 0x9f, 0x54, + 0xcd, 0x06, 0x46, 0x8d, 0xc6, 0x0d, 0x4d, 0x86, + 0xdb, 0x10, 0x50, 0x9b, 0xd0, 0x1b, 0x5b, 0x90, + 0xe1, 0x2a, 0x6a, 0xa1, 0xea, 0x21, 0x61, 0xaa, + 0xf7, 0x3c, 0x7c, 0xb7, 0xfc, 0x37, 0x77, 0xbc, + 0x95, 0x5e, 0x1e, 0xd5, 0x9e, 0x55, 0x15, 0xde, + 0x83, 0x48, 0x08, 0xc3, 0x88, 0x43, 0x03, 0xc8, + 0xb9, 0x72, 0x32, 0xf9, 0xb2, 0x79, 0x39, 0xf2, + 0xaf, 0x64, 0x24, 0xef, 0xa4, 0x6f, 0x2f, 0xe4, + }, + { + 0x00, 0xcc, 0x85, 0x49, 0x17, 0xdb, 0x92, 0x5e, + 0x2e, 0xe2, 0xab, 0x67, 0x39, 0xf5, 0xbc, 0x70, + 0x5c, 0x90, 0xd9, 0x15, 0x4b, 0x87, 0xce, 0x02, + 0x72, 0xbe, 0xf7, 0x3b, 0x65, 0xa9, 0xe0, 0x2c, + 0xb8, 0x74, 0x3d, 0xf1, 0xaf, 0x63, 0x2a, 0xe6, + 0x96, 0x5a, 0x13, 0xdf, 0x81, 0x4d, 0x04, 0xc8, + 0xe4, 0x28, 0x61, 0xad, 0xf3, 0x3f, 0x76, 0xba, + 0xca, 0x06, 0x4f, 0x83, 0xdd, 0x11, 0x58, 0x94, + 0x6d, 0xa1, 0xe8, 0x24, 0x7a, 0xb6, 0xff, 0x33, + 0x43, 0x8f, 0xc6, 0x0a, 0x54, 0x98, 0xd1, 0x1d, + 0x31, 0xfd, 0xb4, 0x78, 0x26, 0xea, 0xa3, 0x6f, + 0x1f, 0xd3, 0x9a, 0x56, 0x08, 0xc4, 0x8d, 0x41, + 0xd5, 0x19, 0x50, 0x9c, 0xc2, 0x0e, 0x47, 0x8b, + 0xfb, 0x37, 0x7e, 0xb2, 0xec, 0x20, 0x69, 0xa5, + 0x89, 0x45, 0x0c, 0xc0, 0x9e, 0x52, 0x1b, 0xd7, + 0xa7, 0x6b, 0x22, 0xee, 0xb0, 0x7c, 0x35, 0xf9, + 0xda, 0x16, 0x5f, 0x93, 0xcd, 0x01, 0x48, 0x84, + 0xf4, 0x38, 0x71, 0xbd, 0xe3, 0x2f, 0x66, 0xaa, + 0x86, 0x4a, 0x03, 0xcf, 0x91, 0x5d, 0x14, 0xd8, + 0xa8, 0x64, 0x2d, 0xe1, 0xbf, 0x73, 0x3a, 0xf6, + 0x62, 0xae, 0xe7, 0x2b, 0x75, 0xb9, 0xf0, 0x3c, + 0x4c, 0x80, 0xc9, 0x05, 0x5b, 0x97, 0xde, 0x12, + 0x3e, 0xf2, 0xbb, 0x77, 0x29, 0xe5, 0xac, 0x60, + 0x10, 0xdc, 0x95, 0x59, 0x07, 0xcb, 0x82, 0x4e, + 0xb7, 0x7b, 0x32, 0xfe, 0xa0, 0x6c, 0x25, 0xe9, + 0x99, 0x55, 0x1c, 0xd0, 0x8e, 0x42, 0x0b, 0xc7, + 0xeb, 0x27, 0x6e, 0xa2, 0xfc, 0x30, 0x79, 0xb5, + 0xc5, 0x09, 0x40, 0x8c, 0xd2, 0x1e, 0x57, 0x9b, + 0x0f, 0xc3, 0x8a, 0x46, 0x18, 0xd4, 0x9d, 0x51, + 0x21, 0xed, 0xa4, 0x68, 0x36, 0xfa, 0xb3, 0x7f, + 0x53, 0x9f, 0xd6, 0x1a, 0x44, 0x88, 0xc1, 0x0d, + 0x7d, 0xb1, 0xf8, 0x34, 0x6a, 0xa6, 0xef, 0x23, + }, + { + 0x00, 0xcd, 0x87, 0x4a, 0x13, 0xde, 0x94, 0x59, + 0x26, 0xeb, 0xa1, 0x6c, 0x35, 0xf8, 0xb2, 0x7f, + 0x4c, 0x81, 0xcb, 0x06, 0x5f, 0x92, 0xd8, 0x15, + 0x6a, 0xa7, 0xed, 0x20, 0x79, 0xb4, 0xfe, 0x33, + 0x98, 0x55, 0x1f, 0xd2, 0x8b, 0x46, 0x0c, 0xc1, + 0xbe, 0x73, 0x39, 0xf4, 0xad, 0x60, 0x2a, 0xe7, + 0xd4, 0x19, 0x53, 0x9e, 0xc7, 0x0a, 0x40, 0x8d, + 0xf2, 0x3f, 0x75, 0xb8, 0xe1, 0x2c, 0x66, 0xab, + 0x2d, 0xe0, 0xaa, 0x67, 0x3e, 0xf3, 0xb9, 0x74, + 0x0b, 0xc6, 0x8c, 0x41, 0x18, 0xd5, 0x9f, 0x52, + 0x61, 0xac, 0xe6, 0x2b, 0x72, 0xbf, 0xf5, 0x38, + 0x47, 0x8a, 0xc0, 0x0d, 0x54, 0x99, 0xd3, 0x1e, + 0xb5, 0x78, 0x32, 0xff, 0xa6, 0x6b, 0x21, 0xec, + 0x93, 0x5e, 0x14, 0xd9, 0x80, 0x4d, 0x07, 0xca, + 0xf9, 0x34, 0x7e, 0xb3, 0xea, 0x27, 0x6d, 0xa0, + 0xdf, 0x12, 0x58, 0x95, 0xcc, 0x01, 0x4b, 0x86, + 0x5a, 0x97, 0xdd, 0x10, 0x49, 0x84, 0xce, 0x03, + 0x7c, 0xb1, 0xfb, 0x36, 0x6f, 0xa2, 0xe8, 0x25, + 0x16, 0xdb, 0x91, 0x5c, 0x05, 0xc8, 0x82, 0x4f, + 0x30, 0xfd, 0xb7, 0x7a, 0x23, 0xee, 0xa4, 0x69, + 0xc2, 0x0f, 0x45, 0x88, 0xd1, 0x1c, 0x56, 0x9b, + 0xe4, 0x29, 0x63, 0xae, 0xf7, 0x3a, 0x70, 0xbd, + 0x8e, 0x43, 0x09, 0xc4, 0x9d, 0x50, 0x1a, 0xd7, + 0xa8, 0x65, 0x2f, 0xe2, 0xbb, 0x76, 0x3c, 0xf1, + 0x77, 0xba, 0xf0, 0x3d, 0x64, 0xa9, 0xe3, 0x2e, + 0x51, 0x9c, 0xd6, 0x1b, 0x42, 0x8f, 0xc5, 0x08, + 0x3b, 0xf6, 0xbc, 0x71, 0x28, 0xe5, 0xaf, 0x62, + 0x1d, 0xd0, 0x9a, 0x57, 0x0e, 0xc3, 0x89, 0x44, + 0xef, 0x22, 0x68, 0xa5, 0xfc, 0x31, 0x7b, 0xb6, + 0xc9, 0x04, 0x4e, 0x83, 0xda, 0x17, 0x5d, 0x90, + 0xa3, 0x6e, 0x24, 0xe9, 0xb0, 0x7d, 0x37, 0xfa, + 0x85, 0x48, 0x02, 0xcf, 0x96, 0x5b, 0x11, 0xdc, + }, + { + 0x00, 0xce, 0x81, 0x4f, 0x1f, 0xd1, 0x9e, 0x50, + 0x3e, 0xf0, 0xbf, 0x71, 0x21, 0xef, 0xa0, 0x6e, + 0x7c, 0xb2, 0xfd, 0x33, 0x63, 0xad, 0xe2, 0x2c, + 0x42, 0x8c, 0xc3, 0x0d, 0x5d, 0x93, 0xdc, 0x12, + 0xf8, 0x36, 0x79, 0xb7, 0xe7, 0x29, 0x66, 0xa8, + 0xc6, 0x08, 0x47, 0x89, 0xd9, 0x17, 0x58, 0x96, + 0x84, 0x4a, 0x05, 0xcb, 0x9b, 0x55, 0x1a, 0xd4, + 0xba, 0x74, 0x3b, 0xf5, 0xa5, 0x6b, 0x24, 0xea, + 0xed, 0x23, 0x6c, 0xa2, 0xf2, 0x3c, 0x73, 0xbd, + 0xd3, 0x1d, 0x52, 0x9c, 0xcc, 0x02, 0x4d, 0x83, + 0x91, 0x5f, 0x10, 0xde, 0x8e, 0x40, 0x0f, 0xc1, + 0xaf, 0x61, 0x2e, 0xe0, 0xb0, 0x7e, 0x31, 0xff, + 0x15, 0xdb, 0x94, 0x5a, 0x0a, 0xc4, 0x8b, 0x45, + 0x2b, 0xe5, 0xaa, 0x64, 0x34, 0xfa, 0xb5, 0x7b, + 0x69, 0xa7, 0xe8, 0x26, 0x76, 0xb8, 0xf7, 0x39, + 0x57, 0x99, 0xd6, 0x18, 0x48, 0x86, 0xc9, 0x07, + 0xc7, 0x09, 0x46, 0x88, 0xd8, 0x16, 0x59, 0x97, + 0xf9, 0x37, 0x78, 0xb6, 0xe6, 0x28, 0x67, 0xa9, + 0xbb, 0x75, 0x3a, 0xf4, 0xa4, 0x6a, 0x25, 0xeb, + 0x85, 0x4b, 0x04, 0xca, 0x9a, 0x54, 0x1b, 0xd5, + 0x3f, 0xf1, 0xbe, 0x70, 0x20, 0xee, 0xa1, 0x6f, + 0x01, 0xcf, 0x80, 0x4e, 0x1e, 0xd0, 0x9f, 0x51, + 0x43, 0x8d, 0xc2, 0x0c, 0x5c, 0x92, 0xdd, 0x13, + 0x7d, 0xb3, 0xfc, 0x32, 0x62, 0xac, 0xe3, 0x2d, + 0x2a, 0xe4, 0xab, 0x65, 0x35, 0xfb, 0xb4, 0x7a, + 0x14, 0xda, 0x95, 0x5b, 0x0b, 0xc5, 0x8a, 0x44, + 0x56, 0x98, 0xd7, 0x19, 0x49, 0x87, 0xc8, 0x06, + 0x68, 0xa6, 0xe9, 0x27, 0x77, 0xb9, 0xf6, 0x38, + 0xd2, 0x1c, 0x53, 0x9d, 0xcd, 0x03, 0x4c, 0x82, + 0xec, 0x22, 0x6d, 0xa3, 0xf3, 0x3d, 0x72, 0xbc, + 0xae, 0x60, 0x2f, 0xe1, 0xb1, 0x7f, 0x30, 0xfe, + 0x90, 0x5e, 0x11, 0xdf, 0x8f, 0x41, 0x0e, 0xc0, + }, + { + 0x00, 0xcf, 0x83, 0x4c, 0x1b, 0xd4, 0x98, 0x57, + 0x36, 0xf9, 0xb5, 0x7a, 0x2d, 0xe2, 0xae, 0x61, + 0x6c, 0xa3, 0xef, 0x20, 0x77, 0xb8, 0xf4, 0x3b, + 0x5a, 0x95, 0xd9, 0x16, 0x41, 0x8e, 0xc2, 0x0d, + 0xd8, 0x17, 0x5b, 0x94, 0xc3, 0x0c, 0x40, 0x8f, + 0xee, 0x21, 0x6d, 0xa2, 0xf5, 0x3a, 0x76, 0xb9, + 0xb4, 0x7b, 0x37, 0xf8, 0xaf, 0x60, 0x2c, 0xe3, + 0x82, 0x4d, 0x01, 0xce, 0x99, 0x56, 0x1a, 0xd5, + 0xad, 0x62, 0x2e, 0xe1, 0xb6, 0x79, 0x35, 0xfa, + 0x9b, 0x54, 0x18, 0xd7, 0x80, 0x4f, 0x03, 0xcc, + 0xc1, 0x0e, 0x42, 0x8d, 0xda, 0x15, 0x59, 0x96, + 0xf7, 0x38, 0x74, 0xbb, 0xec, 0x23, 0x6f, 0xa0, + 0x75, 0xba, 0xf6, 0x39, 0x6e, 0xa1, 0xed, 0x22, + 0x43, 0x8c, 0xc0, 0x0f, 0x58, 0x97, 0xdb, 0x14, + 0x19, 0xd6, 0x9a, 0x55, 0x02, 0xcd, 0x81, 0x4e, + 0x2f, 0xe0, 0xac, 0x63, 0x34, 0xfb, 0xb7, 0x78, + 0x47, 0x88, 0xc4, 0x0b, 0x5c, 0x93, 0xdf, 0x10, + 0x71, 0xbe, 0xf2, 0x3d, 0x6a, 0xa5, 0xe9, 0x26, + 0x2b, 0xe4, 0xa8, 0x67, 0x30, 0xff, 0xb3, 0x7c, + 0x1d, 0xd2, 0x9e, 0x51, 0x06, 0xc9, 0x85, 0x4a, + 0x9f, 0x50, 0x1c, 0xd3, 0x84, 0x4b, 0x07, 0xc8, + 0xa9, 0x66, 0x2a, 0xe5, 0xb2, 0x7d, 0x31, 0xfe, + 0xf3, 0x3c, 0x70, 0xbf, 0xe8, 0x27, 0x6b, 0xa4, + 0xc5, 0x0a, 0x46, 0x89, 0xde, 0x11, 0x5d, 0x92, + 0xea, 0x25, 0x69, 0xa6, 0xf1, 0x3e, 0x72, 0xbd, + 0xdc, 0x13, 0x5f, 0x90, 0xc7, 0x08, 0x44, 0x8b, + 0x86, 0x49, 0x05, 0xca, 0x9d, 0x52, 0x1e, 0xd1, + 0xb0, 0x7f, 0x33, 0xfc, 0xab, 0x64, 0x28, 0xe7, + 0x32, 0xfd, 0xb1, 0x7e, 0x29, 0xe6, 0xaa, 0x65, + 0x04, 0xcb, 0x87, 0x48, 0x1f, 0xd0, 0x9c, 0x53, + 0x5e, 0x91, 0xdd, 0x12, 0x45, 0x8a, 0xc6, 0x09, + 0x68, 0xa7, 0xeb, 0x24, 0x73, 0xbc, 0xf0, 0x3f, + }, + { + 0x00, 0xd0, 0xbd, 0x6d, 0x67, 0xb7, 0xda, 0x0a, + 0xce, 0x1e, 0x73, 0xa3, 0xa9, 0x79, 0x14, 0xc4, + 0x81, 0x51, 0x3c, 0xec, 0xe6, 0x36, 0x5b, 0x8b, + 0x4f, 0x9f, 0xf2, 0x22, 0x28, 0xf8, 0x95, 0x45, + 0x1f, 0xcf, 0xa2, 0x72, 0x78, 0xa8, 0xc5, 0x15, + 0xd1, 0x01, 0x6c, 0xbc, 0xb6, 0x66, 0x0b, 0xdb, + 0x9e, 0x4e, 0x23, 0xf3, 0xf9, 0x29, 0x44, 0x94, + 0x50, 0x80, 0xed, 0x3d, 0x37, 0xe7, 0x8a, 0x5a, + 0x3e, 0xee, 0x83, 0x53, 0x59, 0x89, 0xe4, 0x34, + 0xf0, 0x20, 0x4d, 0x9d, 0x97, 0x47, 0x2a, 0xfa, + 0xbf, 0x6f, 0x02, 0xd2, 0xd8, 0x08, 0x65, 0xb5, + 0x71, 0xa1, 0xcc, 0x1c, 0x16, 0xc6, 0xab, 0x7b, + 0x21, 0xf1, 0x9c, 0x4c, 0x46, 0x96, 0xfb, 0x2b, + 0xef, 0x3f, 0x52, 0x82, 0x88, 0x58, 0x35, 0xe5, + 0xa0, 0x70, 0x1d, 0xcd, 0xc7, 0x17, 0x7a, 0xaa, + 0x6e, 0xbe, 0xd3, 0x03, 0x09, 0xd9, 0xb4, 0x64, + 0x7c, 0xac, 0xc1, 0x11, 0x1b, 0xcb, 0xa6, 0x76, + 0xb2, 0x62, 0x0f, 0xdf, 0xd5, 0x05, 0x68, 0xb8, + 0xfd, 0x2d, 0x40, 0x90, 0x9a, 0x4a, 0x27, 0xf7, + 0x33, 0xe3, 0x8e, 0x5e, 0x54, 0x84, 0xe9, 0x39, + 0x63, 0xb3, 0xde, 0x0e, 0x04, 0xd4, 0xb9, 0x69, + 0xad, 0x7d, 0x10, 0xc0, 0xca, 0x1a, 0x77, 0xa7, + 0xe2, 0x32, 0x5f, 0x8f, 0x85, 0x55, 0x38, 0xe8, + 0x2c, 0xfc, 0x91, 0x41, 0x4b, 0x9b, 0xf6, 0x26, + 0x42, 0x92, 0xff, 0x2f, 0x25, 0xf5, 0x98, 0x48, + 0x8c, 0x5c, 0x31, 0xe1, 0xeb, 0x3b, 0x56, 0x86, + 0xc3, 0x13, 0x7e, 0xae, 0xa4, 0x74, 0x19, 0xc9, + 0x0d, 0xdd, 0xb0, 0x60, 0x6a, 0xba, 0xd7, 0x07, + 0x5d, 0x8d, 0xe0, 0x30, 0x3a, 0xea, 0x87, 0x57, + 0x93, 0x43, 0x2e, 0xfe, 0xf4, 0x24, 0x49, 0x99, + 0xdc, 0x0c, 0x61, 0xb1, 0xbb, 0x6b, 0x06, 0xd6, + 0x12, 0xc2, 0xaf, 0x7f, 0x75, 0xa5, 0xc8, 0x18, + }, + { + 0x00, 0xd1, 0xbf, 0x6e, 0x63, 0xb2, 0xdc, 0x0d, + 0xc6, 0x17, 0x79, 0xa8, 0xa5, 0x74, 0x1a, 0xcb, + 0x91, 0x40, 0x2e, 0xff, 0xf2, 0x23, 0x4d, 0x9c, + 0x57, 0x86, 0xe8, 0x39, 0x34, 0xe5, 0x8b, 0x5a, + 0x3f, 0xee, 0x80, 0x51, 0x5c, 0x8d, 0xe3, 0x32, + 0xf9, 0x28, 0x46, 0x97, 0x9a, 0x4b, 0x25, 0xf4, + 0xae, 0x7f, 0x11, 0xc0, 0xcd, 0x1c, 0x72, 0xa3, + 0x68, 0xb9, 0xd7, 0x06, 0x0b, 0xda, 0xb4, 0x65, + 0x7e, 0xaf, 0xc1, 0x10, 0x1d, 0xcc, 0xa2, 0x73, + 0xb8, 0x69, 0x07, 0xd6, 0xdb, 0x0a, 0x64, 0xb5, + 0xef, 0x3e, 0x50, 0x81, 0x8c, 0x5d, 0x33, 0xe2, + 0x29, 0xf8, 0x96, 0x47, 0x4a, 0x9b, 0xf5, 0x24, + 0x41, 0x90, 0xfe, 0x2f, 0x22, 0xf3, 0x9d, 0x4c, + 0x87, 0x56, 0x38, 0xe9, 0xe4, 0x35, 0x5b, 0x8a, + 0xd0, 0x01, 0x6f, 0xbe, 0xb3, 0x62, 0x0c, 0xdd, + 0x16, 0xc7, 0xa9, 0x78, 0x75, 0xa4, 0xca, 0x1b, + 0xfc, 0x2d, 0x43, 0x92, 0x9f, 0x4e, 0x20, 0xf1, + 0x3a, 0xeb, 0x85, 0x54, 0x59, 0x88, 0xe6, 0x37, + 0x6d, 0xbc, 0xd2, 0x03, 0x0e, 0xdf, 0xb1, 0x60, + 0xab, 0x7a, 0x14, 0xc5, 0xc8, 0x19, 0x77, 0xa6, + 0xc3, 0x12, 0x7c, 0xad, 0xa0, 0x71, 0x1f, 0xce, + 0x05, 0xd4, 0xba, 0x6b, 0x66, 0xb7, 0xd9, 0x08, + 0x52, 0x83, 0xed, 0x3c, 0x31, 0xe0, 0x8e, 0x5f, + 0x94, 0x45, 0x2b, 0xfa, 0xf7, 0x26, 0x48, 0x99, + 0x82, 0x53, 0x3d, 0xec, 0xe1, 0x30, 0x5e, 0x8f, + 0x44, 0x95, 0xfb, 0x2a, 0x27, 0xf6, 0x98, 0x49, + 0x13, 0xc2, 0xac, 0x7d, 0x70, 0xa1, 0xcf, 0x1e, + 0xd5, 0x04, 0x6a, 0xbb, 0xb6, 0x67, 0x09, 0xd8, + 0xbd, 0x6c, 0x02, 0xd3, 0xde, 0x0f, 0x61, 0xb0, + 0x7b, 0xaa, 0xc4, 0x15, 0x18, 0xc9, 0xa7, 0x76, + 0x2c, 0xfd, 0x93, 0x42, 0x4f, 0x9e, 0xf0, 0x21, + 0xea, 0x3b, 0x55, 0x84, 0x89, 0x58, 0x36, 0xe7, + }, + { + 0x00, 0xd2, 0xb9, 0x6b, 0x6f, 0xbd, 0xd6, 0x04, + 0xde, 0x0c, 0x67, 0xb5, 0xb1, 0x63, 0x08, 0xda, + 0xa1, 0x73, 0x18, 0xca, 0xce, 0x1c, 0x77, 0xa5, + 0x7f, 0xad, 0xc6, 0x14, 0x10, 0xc2, 0xa9, 0x7b, + 0x5f, 0x8d, 0xe6, 0x34, 0x30, 0xe2, 0x89, 0x5b, + 0x81, 0x53, 0x38, 0xea, 0xee, 0x3c, 0x57, 0x85, + 0xfe, 0x2c, 0x47, 0x95, 0x91, 0x43, 0x28, 0xfa, + 0x20, 0xf2, 0x99, 0x4b, 0x4f, 0x9d, 0xf6, 0x24, + 0xbe, 0x6c, 0x07, 0xd5, 0xd1, 0x03, 0x68, 0xba, + 0x60, 0xb2, 0xd9, 0x0b, 0x0f, 0xdd, 0xb6, 0x64, + 0x1f, 0xcd, 0xa6, 0x74, 0x70, 0xa2, 0xc9, 0x1b, + 0xc1, 0x13, 0x78, 0xaa, 0xae, 0x7c, 0x17, 0xc5, + 0xe1, 0x33, 0x58, 0x8a, 0x8e, 0x5c, 0x37, 0xe5, + 0x3f, 0xed, 0x86, 0x54, 0x50, 0x82, 0xe9, 0x3b, + 0x40, 0x92, 0xf9, 0x2b, 0x2f, 0xfd, 0x96, 0x44, + 0x9e, 0x4c, 0x27, 0xf5, 0xf1, 0x23, 0x48, 0x9a, + 0x61, 0xb3, 0xd8, 0x0a, 0x0e, 0xdc, 0xb7, 0x65, + 0xbf, 0x6d, 0x06, 0xd4, 0xd0, 0x02, 0x69, 0xbb, + 0xc0, 0x12, 0x79, 0xab, 0xaf, 0x7d, 0x16, 0xc4, + 0x1e, 0xcc, 0xa7, 0x75, 0x71, 0xa3, 0xc8, 0x1a, + 0x3e, 0xec, 0x87, 0x55, 0x51, 0x83, 0xe8, 0x3a, + 0xe0, 0x32, 0x59, 0x8b, 0x8f, 0x5d, 0x36, 0xe4, + 0x9f, 0x4d, 0x26, 0xf4, 0xf0, 0x22, 0x49, 0x9b, + 0x41, 0x93, 0xf8, 0x2a, 0x2e, 0xfc, 0x97, 0x45, + 0xdf, 0x0d, 0x66, 0xb4, 0xb0, 0x62, 0x09, 0xdb, + 0x01, 0xd3, 0xb8, 0x6a, 0x6e, 0xbc, 0xd7, 0x05, + 0x7e, 0xac, 0xc7, 0x15, 0x11, 0xc3, 0xa8, 0x7a, + 0xa0, 0x72, 0x19, 0xcb, 0xcf, 0x1d, 0x76, 0xa4, + 0x80, 0x52, 0x39, 0xeb, 0xef, 0x3d, 0x56, 0x84, + 0x5e, 0x8c, 0xe7, 0x35, 0x31, 0xe3, 0x88, 0x5a, + 0x21, 0xf3, 0x98, 0x4a, 0x4e, 0x9c, 0xf7, 0x25, + 0xff, 0x2d, 0x46, 0x94, 0x90, 0x42, 0x29, 0xfb, + }, + { + 0x00, 0xd3, 0xbb, 0x68, 0x6b, 0xb8, 0xd0, 0x03, + 0xd6, 0x05, 0x6d, 0xbe, 0xbd, 0x6e, 0x06, 0xd5, + 0xb1, 0x62, 0x0a, 0xd9, 0xda, 0x09, 0x61, 0xb2, + 0x67, 0xb4, 0xdc, 0x0f, 0x0c, 0xdf, 0xb7, 0x64, + 0x7f, 0xac, 0xc4, 0x17, 0x14, 0xc7, 0xaf, 0x7c, + 0xa9, 0x7a, 0x12, 0xc1, 0xc2, 0x11, 0x79, 0xaa, + 0xce, 0x1d, 0x75, 0xa6, 0xa5, 0x76, 0x1e, 0xcd, + 0x18, 0xcb, 0xa3, 0x70, 0x73, 0xa0, 0xc8, 0x1b, + 0xfe, 0x2d, 0x45, 0x96, 0x95, 0x46, 0x2e, 0xfd, + 0x28, 0xfb, 0x93, 0x40, 0x43, 0x90, 0xf8, 0x2b, + 0x4f, 0x9c, 0xf4, 0x27, 0x24, 0xf7, 0x9f, 0x4c, + 0x99, 0x4a, 0x22, 0xf1, 0xf2, 0x21, 0x49, 0x9a, + 0x81, 0x52, 0x3a, 0xe9, 0xea, 0x39, 0x51, 0x82, + 0x57, 0x84, 0xec, 0x3f, 0x3c, 0xef, 0x87, 0x54, + 0x30, 0xe3, 0x8b, 0x58, 0x5b, 0x88, 0xe0, 0x33, + 0xe6, 0x35, 0x5d, 0x8e, 0x8d, 0x5e, 0x36, 0xe5, + 0xe1, 0x32, 0x5a, 0x89, 0x8a, 0x59, 0x31, 0xe2, + 0x37, 0xe4, 0x8c, 0x5f, 0x5c, 0x8f, 0xe7, 0x34, + 0x50, 0x83, 0xeb, 0x38, 0x3b, 0xe8, 0x80, 0x53, + 0x86, 0x55, 0x3d, 0xee, 0xed, 0x3e, 0x56, 0x85, + 0x9e, 0x4d, 0x25, 0xf6, 0xf5, 0x26, 0x4e, 0x9d, + 0x48, 0x9b, 0xf3, 0x20, 0x23, 0xf0, 0x98, 0x4b, + 0x2f, 0xfc, 0x94, 0x47, 0x44, 0x97, 0xff, 0x2c, + 0xf9, 0x2a, 0x42, 0x91, 0x92, 0x41, 0x29, 0xfa, + 0x1f, 0xcc, 0xa4, 0x77, 0x74, 0xa7, 0xcf, 0x1c, + 0xc9, 0x1a, 0x72, 0xa1, 0xa2, 0x71, 0x19, 0xca, + 0xae, 0x7d, 0x15, 0xc6, 0xc5, 0x16, 0x7e, 0xad, + 0x78, 0xab, 0xc3, 0x10, 0x13, 0xc0, 0xa8, 0x7b, + 0x60, 0xb3, 0xdb, 0x08, 0x0b, 0xd8, 0xb0, 0x63, + 0xb6, 0x65, 0x0d, 0xde, 0xdd, 0x0e, 0x66, 0xb5, + 0xd1, 0x02, 0x6a, 0xb9, 0xba, 0x69, 0x01, 0xd2, + 0x07, 0xd4, 0xbc, 0x6f, 0x6c, 0xbf, 0xd7, 0x04, + }, + { + 0x00, 0xd4, 0xb5, 0x61, 0x77, 0xa3, 0xc2, 0x16, + 0xee, 0x3a, 0x5b, 0x8f, 0x99, 0x4d, 0x2c, 0xf8, + 0xc1, 0x15, 0x74, 0xa0, 0xb6, 0x62, 0x03, 0xd7, + 0x2f, 0xfb, 0x9a, 0x4e, 0x58, 0x8c, 0xed, 0x39, + 0x9f, 0x4b, 0x2a, 0xfe, 0xe8, 0x3c, 0x5d, 0x89, + 0x71, 0xa5, 0xc4, 0x10, 0x06, 0xd2, 0xb3, 0x67, + 0x5e, 0x8a, 0xeb, 0x3f, 0x29, 0xfd, 0x9c, 0x48, + 0xb0, 0x64, 0x05, 0xd1, 0xc7, 0x13, 0x72, 0xa6, + 0x23, 0xf7, 0x96, 0x42, 0x54, 0x80, 0xe1, 0x35, + 0xcd, 0x19, 0x78, 0xac, 0xba, 0x6e, 0x0f, 0xdb, + 0xe2, 0x36, 0x57, 0x83, 0x95, 0x41, 0x20, 0xf4, + 0x0c, 0xd8, 0xb9, 0x6d, 0x7b, 0xaf, 0xce, 0x1a, + 0xbc, 0x68, 0x09, 0xdd, 0xcb, 0x1f, 0x7e, 0xaa, + 0x52, 0x86, 0xe7, 0x33, 0x25, 0xf1, 0x90, 0x44, + 0x7d, 0xa9, 0xc8, 0x1c, 0x0a, 0xde, 0xbf, 0x6b, + 0x93, 0x47, 0x26, 0xf2, 0xe4, 0x30, 0x51, 0x85, + 0x46, 0x92, 0xf3, 0x27, 0x31, 0xe5, 0x84, 0x50, + 0xa8, 0x7c, 0x1d, 0xc9, 0xdf, 0x0b, 0x6a, 0xbe, + 0x87, 0x53, 0x32, 0xe6, 0xf0, 0x24, 0x45, 0x91, + 0x69, 0xbd, 0xdc, 0x08, 0x1e, 0xca, 0xab, 0x7f, + 0xd9, 0x0d, 0x6c, 0xb8, 0xae, 0x7a, 0x1b, 0xcf, + 0x37, 0xe3, 0x82, 0x56, 0x40, 0x94, 0xf5, 0x21, + 0x18, 0xcc, 0xad, 0x79, 0x6f, 0xbb, 0xda, 0x0e, + 0xf6, 0x22, 0x43, 0x97, 0x81, 0x55, 0x34, 0xe0, + 0x65, 0xb1, 0xd0, 0x04, 0x12, 0xc6, 0xa7, 0x73, + 0x8b, 0x5f, 0x3e, 0xea, 0xfc, 0x28, 0x49, 0x9d, + 0xa4, 0x70, 0x11, 0xc5, 0xd3, 0x07, 0x66, 0xb2, + 0x4a, 0x9e, 0xff, 0x2b, 0x3d, 0xe9, 0x88, 0x5c, + 0xfa, 0x2e, 0x4f, 0x9b, 0x8d, 0x59, 0x38, 0xec, + 0x14, 0xc0, 0xa1, 0x75, 0x63, 0xb7, 0xd6, 0x02, + 0x3b, 0xef, 0x8e, 0x5a, 0x4c, 0x98, 0xf9, 0x2d, + 0xd5, 0x01, 0x60, 0xb4, 0xa2, 0x76, 0x17, 0xc3, + }, + { + 0x00, 0xd5, 0xb7, 0x62, 0x73, 0xa6, 0xc4, 0x11, + 0xe6, 0x33, 0x51, 0x84, 0x95, 0x40, 0x22, 0xf7, + 0xd1, 0x04, 0x66, 0xb3, 0xa2, 0x77, 0x15, 0xc0, + 0x37, 0xe2, 0x80, 0x55, 0x44, 0x91, 0xf3, 0x26, + 0xbf, 0x6a, 0x08, 0xdd, 0xcc, 0x19, 0x7b, 0xae, + 0x59, 0x8c, 0xee, 0x3b, 0x2a, 0xff, 0x9d, 0x48, + 0x6e, 0xbb, 0xd9, 0x0c, 0x1d, 0xc8, 0xaa, 0x7f, + 0x88, 0x5d, 0x3f, 0xea, 0xfb, 0x2e, 0x4c, 0x99, + 0x63, 0xb6, 0xd4, 0x01, 0x10, 0xc5, 0xa7, 0x72, + 0x85, 0x50, 0x32, 0xe7, 0xf6, 0x23, 0x41, 0x94, + 0xb2, 0x67, 0x05, 0xd0, 0xc1, 0x14, 0x76, 0xa3, + 0x54, 0x81, 0xe3, 0x36, 0x27, 0xf2, 0x90, 0x45, + 0xdc, 0x09, 0x6b, 0xbe, 0xaf, 0x7a, 0x18, 0xcd, + 0x3a, 0xef, 0x8d, 0x58, 0x49, 0x9c, 0xfe, 0x2b, + 0x0d, 0xd8, 0xba, 0x6f, 0x7e, 0xab, 0xc9, 0x1c, + 0xeb, 0x3e, 0x5c, 0x89, 0x98, 0x4d, 0x2f, 0xfa, + 0xc6, 0x13, 0x71, 0xa4, 0xb5, 0x60, 0x02, 0xd7, + 0x20, 0xf5, 0x97, 0x42, 0x53, 0x86, 0xe4, 0x31, + 0x17, 0xc2, 0xa0, 0x75, 0x64, 0xb1, 0xd3, 0x06, + 0xf1, 0x24, 0x46, 0x93, 0x82, 0x57, 0x35, 0xe0, + 0x79, 0xac, 0xce, 0x1b, 0x0a, 0xdf, 0xbd, 0x68, + 0x9f, 0x4a, 0x28, 0xfd, 0xec, 0x39, 0x5b, 0x8e, + 0xa8, 0x7d, 0x1f, 0xca, 0xdb, 0x0e, 0x6c, 0xb9, + 0x4e, 0x9b, 0xf9, 0x2c, 0x3d, 0xe8, 0x8a, 0x5f, + 0xa5, 0x70, 0x12, 0xc7, 0xd6, 0x03, 0x61, 0xb4, + 0x43, 0x96, 0xf4, 0x21, 0x30, 0xe5, 0x87, 0x52, + 0x74, 0xa1, 0xc3, 0x16, 0x07, 0xd2, 0xb0, 0x65, + 0x92, 0x47, 0x25, 0xf0, 0xe1, 0x34, 0x56, 0x83, + 0x1a, 0xcf, 0xad, 0x78, 0x69, 0xbc, 0xde, 0x0b, + 0xfc, 0x29, 0x4b, 0x9e, 0x8f, 0x5a, 0x38, 0xed, + 0xcb, 0x1e, 0x7c, 0xa9, 0xb8, 0x6d, 0x0f, 0xda, + 0x2d, 0xf8, 0x9a, 0x4f, 0x5e, 0x8b, 0xe9, 0x3c, + }, + { + 0x00, 0xd6, 0xb1, 0x67, 0x7f, 0xa9, 0xce, 0x18, + 0xfe, 0x28, 0x4f, 0x99, 0x81, 0x57, 0x30, 0xe6, + 0xe1, 0x37, 0x50, 0x86, 0x9e, 0x48, 0x2f, 0xf9, + 0x1f, 0xc9, 0xae, 0x78, 0x60, 0xb6, 0xd1, 0x07, + 0xdf, 0x09, 0x6e, 0xb8, 0xa0, 0x76, 0x11, 0xc7, + 0x21, 0xf7, 0x90, 0x46, 0x5e, 0x88, 0xef, 0x39, + 0x3e, 0xe8, 0x8f, 0x59, 0x41, 0x97, 0xf0, 0x26, + 0xc0, 0x16, 0x71, 0xa7, 0xbf, 0x69, 0x0e, 0xd8, + 0xa3, 0x75, 0x12, 0xc4, 0xdc, 0x0a, 0x6d, 0xbb, + 0x5d, 0x8b, 0xec, 0x3a, 0x22, 0xf4, 0x93, 0x45, + 0x42, 0x94, 0xf3, 0x25, 0x3d, 0xeb, 0x8c, 0x5a, + 0xbc, 0x6a, 0x0d, 0xdb, 0xc3, 0x15, 0x72, 0xa4, + 0x7c, 0xaa, 0xcd, 0x1b, 0x03, 0xd5, 0xb2, 0x64, + 0x82, 0x54, 0x33, 0xe5, 0xfd, 0x2b, 0x4c, 0x9a, + 0x9d, 0x4b, 0x2c, 0xfa, 0xe2, 0x34, 0x53, 0x85, + 0x63, 0xb5, 0xd2, 0x04, 0x1c, 0xca, 0xad, 0x7b, + 0x5b, 0x8d, 0xea, 0x3c, 0x24, 0xf2, 0x95, 0x43, + 0xa5, 0x73, 0x14, 0xc2, 0xda, 0x0c, 0x6b, 0xbd, + 0xba, 0x6c, 0x0b, 0xdd, 0xc5, 0x13, 0x74, 0xa2, + 0x44, 0x92, 0xf5, 0x23, 0x3b, 0xed, 0x8a, 0x5c, + 0x84, 0x52, 0x35, 0xe3, 0xfb, 0x2d, 0x4a, 0x9c, + 0x7a, 0xac, 0xcb, 0x1d, 0x05, 0xd3, 0xb4, 0x62, + 0x65, 0xb3, 0xd4, 0x02, 0x1a, 0xcc, 0xab, 0x7d, + 0x9b, 0x4d, 0x2a, 0xfc, 0xe4, 0x32, 0x55, 0x83, + 0xf8, 0x2e, 0x49, 0x9f, 0x87, 0x51, 0x36, 0xe0, + 0x06, 0xd0, 0xb7, 0x61, 0x79, 0xaf, 0xc8, 0x1e, + 0x19, 0xcf, 0xa8, 0x7e, 0x66, 0xb0, 0xd7, 0x01, + 0xe7, 0x31, 0x56, 0x80, 0x98, 0x4e, 0x29, 0xff, + 0x27, 0xf1, 0x96, 0x40, 0x58, 0x8e, 0xe9, 0x3f, + 0xd9, 0x0f, 0x68, 0xbe, 0xa6, 0x70, 0x17, 0xc1, + 0xc6, 0x10, 0x77, 0xa1, 0xb9, 0x6f, 0x08, 0xde, + 0x38, 0xee, 0x89, 0x5f, 0x47, 0x91, 0xf6, 0x20, + }, + { + 0x00, 0xd7, 0xb3, 0x64, 0x7b, 0xac, 0xc8, 0x1f, + 0xf6, 0x21, 0x45, 0x92, 0x8d, 0x5a, 0x3e, 0xe9, + 0xf1, 0x26, 0x42, 0x95, 0x8a, 0x5d, 0x39, 0xee, + 0x07, 0xd0, 0xb4, 0x63, 0x7c, 0xab, 0xcf, 0x18, + 0xff, 0x28, 0x4c, 0x9b, 0x84, 0x53, 0x37, 0xe0, + 0x09, 0xde, 0xba, 0x6d, 0x72, 0xa5, 0xc1, 0x16, + 0x0e, 0xd9, 0xbd, 0x6a, 0x75, 0xa2, 0xc6, 0x11, + 0xf8, 0x2f, 0x4b, 0x9c, 0x83, 0x54, 0x30, 0xe7, + 0xe3, 0x34, 0x50, 0x87, 0x98, 0x4f, 0x2b, 0xfc, + 0x15, 0xc2, 0xa6, 0x71, 0x6e, 0xb9, 0xdd, 0x0a, + 0x12, 0xc5, 0xa1, 0x76, 0x69, 0xbe, 0xda, 0x0d, + 0xe4, 0x33, 0x57, 0x80, 0x9f, 0x48, 0x2c, 0xfb, + 0x1c, 0xcb, 0xaf, 0x78, 0x67, 0xb0, 0xd4, 0x03, + 0xea, 0x3d, 0x59, 0x8e, 0x91, 0x46, 0x22, 0xf5, + 0xed, 0x3a, 0x5e, 0x89, 0x96, 0x41, 0x25, 0xf2, + 0x1b, 0xcc, 0xa8, 0x7f, 0x60, 0xb7, 0xd3, 0x04, + 0xdb, 0x0c, 0x68, 0xbf, 0xa0, 0x77, 0x13, 0xc4, + 0x2d, 0xfa, 0x9e, 0x49, 0x56, 0x81, 0xe5, 0x32, + 0x2a, 0xfd, 0x99, 0x4e, 0x51, 0x86, 0xe2, 0x35, + 0xdc, 0x0b, 0x6f, 0xb8, 0xa7, 0x70, 0x14, 0xc3, + 0x24, 0xf3, 0x97, 0x40, 0x5f, 0x88, 0xec, 0x3b, + 0xd2, 0x05, 0x61, 0xb6, 0xa9, 0x7e, 0x1a, 0xcd, + 0xd5, 0x02, 0x66, 0xb1, 0xae, 0x79, 0x1d, 0xca, + 0x23, 0xf4, 0x90, 0x47, 0x58, 0x8f, 0xeb, 0x3c, + 0x38, 0xef, 0x8b, 0x5c, 0x43, 0x94, 0xf0, 0x27, + 0xce, 0x19, 0x7d, 0xaa, 0xb5, 0x62, 0x06, 0xd1, + 0xc9, 0x1e, 0x7a, 0xad, 0xb2, 0x65, 0x01, 0xd6, + 0x3f, 0xe8, 0x8c, 0x5b, 0x44, 0x93, 0xf7, 0x20, + 0xc7, 0x10, 0x74, 0xa3, 0xbc, 0x6b, 0x0f, 0xd8, + 0x31, 0xe6, 0x82, 0x55, 0x4a, 0x9d, 0xf9, 0x2e, + 0x36, 0xe1, 0x85, 0x52, 0x4d, 0x9a, 0xfe, 0x29, + 0xc0, 0x17, 0x73, 0xa4, 0xbb, 0x6c, 0x08, 0xdf, + }, + { + 0x00, 0xd8, 0xad, 0x75, 0x47, 0x9f, 0xea, 0x32, + 0x8e, 0x56, 0x23, 0xfb, 0xc9, 0x11, 0x64, 0xbc, + 0x01, 0xd9, 0xac, 0x74, 0x46, 0x9e, 0xeb, 0x33, + 0x8f, 0x57, 0x22, 0xfa, 0xc8, 0x10, 0x65, 0xbd, + 0x02, 0xda, 0xaf, 0x77, 0x45, 0x9d, 0xe8, 0x30, + 0x8c, 0x54, 0x21, 0xf9, 0xcb, 0x13, 0x66, 0xbe, + 0x03, 0xdb, 0xae, 0x76, 0x44, 0x9c, 0xe9, 0x31, + 0x8d, 0x55, 0x20, 0xf8, 0xca, 0x12, 0x67, 0xbf, + 0x04, 0xdc, 0xa9, 0x71, 0x43, 0x9b, 0xee, 0x36, + 0x8a, 0x52, 0x27, 0xff, 0xcd, 0x15, 0x60, 0xb8, + 0x05, 0xdd, 0xa8, 0x70, 0x42, 0x9a, 0xef, 0x37, + 0x8b, 0x53, 0x26, 0xfe, 0xcc, 0x14, 0x61, 0xb9, + 0x06, 0xde, 0xab, 0x73, 0x41, 0x99, 0xec, 0x34, + 0x88, 0x50, 0x25, 0xfd, 0xcf, 0x17, 0x62, 0xba, + 0x07, 0xdf, 0xaa, 0x72, 0x40, 0x98, 0xed, 0x35, + 0x89, 0x51, 0x24, 0xfc, 0xce, 0x16, 0x63, 0xbb, + 0x08, 0xd0, 0xa5, 0x7d, 0x4f, 0x97, 0xe2, 0x3a, + 0x86, 0x5e, 0x2b, 0xf3, 0xc1, 0x19, 0x6c, 0xb4, + 0x09, 0xd1, 0xa4, 0x7c, 0x4e, 0x96, 0xe3, 0x3b, + 0x87, 0x5f, 0x2a, 0xf2, 0xc0, 0x18, 0x6d, 0xb5, + 0x0a, 0xd2, 0xa7, 0x7f, 0x4d, 0x95, 0xe0, 0x38, + 0x84, 0x5c, 0x29, 0xf1, 0xc3, 0x1b, 0x6e, 0xb6, + 0x0b, 0xd3, 0xa6, 0x7e, 0x4c, 0x94, 0xe1, 0x39, + 0x85, 0x5d, 0x28, 0xf0, 0xc2, 0x1a, 0x6f, 0xb7, + 0x0c, 0xd4, 0xa1, 0x79, 0x4b, 0x93, 0xe6, 0x3e, + 0x82, 0x5a, 0x2f, 0xf7, 0xc5, 0x1d, 0x68, 0xb0, + 0x0d, 0xd5, 0xa0, 0x78, 0x4a, 0x92, 0xe7, 0x3f, + 0x83, 0x5b, 0x2e, 0xf6, 0xc4, 0x1c, 0x69, 0xb1, + 0x0e, 0xd6, 0xa3, 0x7b, 0x49, 0x91, 0xe4, 0x3c, + 0x80, 0x58, 0x2d, 0xf5, 0xc7, 0x1f, 0x6a, 0xb2, + 0x0f, 0xd7, 0xa2, 0x7a, 0x48, 0x90, 0xe5, 0x3d, + 0x81, 0x59, 0x2c, 0xf4, 0xc6, 0x1e, 0x6b, 0xb3, + }, + { + 0x00, 0xd9, 0xaf, 0x76, 0x43, 0x9a, 0xec, 0x35, + 0x86, 0x5f, 0x29, 0xf0, 0xc5, 0x1c, 0x6a, 0xb3, + 0x11, 0xc8, 0xbe, 0x67, 0x52, 0x8b, 0xfd, 0x24, + 0x97, 0x4e, 0x38, 0xe1, 0xd4, 0x0d, 0x7b, 0xa2, + 0x22, 0xfb, 0x8d, 0x54, 0x61, 0xb8, 0xce, 0x17, + 0xa4, 0x7d, 0x0b, 0xd2, 0xe7, 0x3e, 0x48, 0x91, + 0x33, 0xea, 0x9c, 0x45, 0x70, 0xa9, 0xdf, 0x06, + 0xb5, 0x6c, 0x1a, 0xc3, 0xf6, 0x2f, 0x59, 0x80, + 0x44, 0x9d, 0xeb, 0x32, 0x07, 0xde, 0xa8, 0x71, + 0xc2, 0x1b, 0x6d, 0xb4, 0x81, 0x58, 0x2e, 0xf7, + 0x55, 0x8c, 0xfa, 0x23, 0x16, 0xcf, 0xb9, 0x60, + 0xd3, 0x0a, 0x7c, 0xa5, 0x90, 0x49, 0x3f, 0xe6, + 0x66, 0xbf, 0xc9, 0x10, 0x25, 0xfc, 0x8a, 0x53, + 0xe0, 0x39, 0x4f, 0x96, 0xa3, 0x7a, 0x0c, 0xd5, + 0x77, 0xae, 0xd8, 0x01, 0x34, 0xed, 0x9b, 0x42, + 0xf1, 0x28, 0x5e, 0x87, 0xb2, 0x6b, 0x1d, 0xc4, + 0x88, 0x51, 0x27, 0xfe, 0xcb, 0x12, 0x64, 0xbd, + 0x0e, 0xd7, 0xa1, 0x78, 0x4d, 0x94, 0xe2, 0x3b, + 0x99, 0x40, 0x36, 0xef, 0xda, 0x03, 0x75, 0xac, + 0x1f, 0xc6, 0xb0, 0x69, 0x5c, 0x85, 0xf3, 0x2a, + 0xaa, 0x73, 0x05, 0xdc, 0xe9, 0x30, 0x46, 0x9f, + 0x2c, 0xf5, 0x83, 0x5a, 0x6f, 0xb6, 0xc0, 0x19, + 0xbb, 0x62, 0x14, 0xcd, 0xf8, 0x21, 0x57, 0x8e, + 0x3d, 0xe4, 0x92, 0x4b, 0x7e, 0xa7, 0xd1, 0x08, + 0xcc, 0x15, 0x63, 0xba, 0x8f, 0x56, 0x20, 0xf9, + 0x4a, 0x93, 0xe5, 0x3c, 0x09, 0xd0, 0xa6, 0x7f, + 0xdd, 0x04, 0x72, 0xab, 0x9e, 0x47, 0x31, 0xe8, + 0x5b, 0x82, 0xf4, 0x2d, 0x18, 0xc1, 0xb7, 0x6e, + 0xee, 0x37, 0x41, 0x98, 0xad, 0x74, 0x02, 0xdb, + 0x68, 0xb1, 0xc7, 0x1e, 0x2b, 0xf2, 0x84, 0x5d, + 0xff, 0x26, 0x50, 0x89, 0xbc, 0x65, 0x13, 0xca, + 0x79, 0xa0, 0xd6, 0x0f, 0x3a, 0xe3, 0x95, 0x4c, + }, + { + 0x00, 0xda, 0xa9, 0x73, 0x4f, 0x95, 0xe6, 0x3c, + 0x9e, 0x44, 0x37, 0xed, 0xd1, 0x0b, 0x78, 0xa2, + 0x21, 0xfb, 0x88, 0x52, 0x6e, 0xb4, 0xc7, 0x1d, + 0xbf, 0x65, 0x16, 0xcc, 0xf0, 0x2a, 0x59, 0x83, + 0x42, 0x98, 0xeb, 0x31, 0x0d, 0xd7, 0xa4, 0x7e, + 0xdc, 0x06, 0x75, 0xaf, 0x93, 0x49, 0x3a, 0xe0, + 0x63, 0xb9, 0xca, 0x10, 0x2c, 0xf6, 0x85, 0x5f, + 0xfd, 0x27, 0x54, 0x8e, 0xb2, 0x68, 0x1b, 0xc1, + 0x84, 0x5e, 0x2d, 0xf7, 0xcb, 0x11, 0x62, 0xb8, + 0x1a, 0xc0, 0xb3, 0x69, 0x55, 0x8f, 0xfc, 0x26, + 0xa5, 0x7f, 0x0c, 0xd6, 0xea, 0x30, 0x43, 0x99, + 0x3b, 0xe1, 0x92, 0x48, 0x74, 0xae, 0xdd, 0x07, + 0xc6, 0x1c, 0x6f, 0xb5, 0x89, 0x53, 0x20, 0xfa, + 0x58, 0x82, 0xf1, 0x2b, 0x17, 0xcd, 0xbe, 0x64, + 0xe7, 0x3d, 0x4e, 0x94, 0xa8, 0x72, 0x01, 0xdb, + 0x79, 0xa3, 0xd0, 0x0a, 0x36, 0xec, 0x9f, 0x45, + 0x15, 0xcf, 0xbc, 0x66, 0x5a, 0x80, 0xf3, 0x29, + 0x8b, 0x51, 0x22, 0xf8, 0xc4, 0x1e, 0x6d, 0xb7, + 0x34, 0xee, 0x9d, 0x47, 0x7b, 0xa1, 0xd2, 0x08, + 0xaa, 0x70, 0x03, 0xd9, 0xe5, 0x3f, 0x4c, 0x96, + 0x57, 0x8d, 0xfe, 0x24, 0x18, 0xc2, 0xb1, 0x6b, + 0xc9, 0x13, 0x60, 0xba, 0x86, 0x5c, 0x2f, 0xf5, + 0x76, 0xac, 0xdf, 0x05, 0x39, 0xe3, 0x90, 0x4a, + 0xe8, 0x32, 0x41, 0x9b, 0xa7, 0x7d, 0x0e, 0xd4, + 0x91, 0x4b, 0x38, 0xe2, 0xde, 0x04, 0x77, 0xad, + 0x0f, 0xd5, 0xa6, 0x7c, 0x40, 0x9a, 0xe9, 0x33, + 0xb0, 0x6a, 0x19, 0xc3, 0xff, 0x25, 0x56, 0x8c, + 0x2e, 0xf4, 0x87, 0x5d, 0x61, 0xbb, 0xc8, 0x12, + 0xd3, 0x09, 0x7a, 0xa0, 0x9c, 0x46, 0x35, 0xef, + 0x4d, 0x97, 0xe4, 0x3e, 0x02, 0xd8, 0xab, 0x71, + 0xf2, 0x28, 0x5b, 0x81, 0xbd, 0x67, 0x14, 0xce, + 0x6c, 0xb6, 0xc5, 0x1f, 0x23, 0xf9, 0x8a, 0x50, + }, + { + 0x00, 0xdb, 0xab, 0x70, 0x4b, 0x90, 0xe0, 0x3b, + 0x96, 0x4d, 0x3d, 0xe6, 0xdd, 0x06, 0x76, 0xad, + 0x31, 0xea, 0x9a, 0x41, 0x7a, 0xa1, 0xd1, 0x0a, + 0xa7, 0x7c, 0x0c, 0xd7, 0xec, 0x37, 0x47, 0x9c, + 0x62, 0xb9, 0xc9, 0x12, 0x29, 0xf2, 0x82, 0x59, + 0xf4, 0x2f, 0x5f, 0x84, 0xbf, 0x64, 0x14, 0xcf, + 0x53, 0x88, 0xf8, 0x23, 0x18, 0xc3, 0xb3, 0x68, + 0xc5, 0x1e, 0x6e, 0xb5, 0x8e, 0x55, 0x25, 0xfe, + 0xc4, 0x1f, 0x6f, 0xb4, 0x8f, 0x54, 0x24, 0xff, + 0x52, 0x89, 0xf9, 0x22, 0x19, 0xc2, 0xb2, 0x69, + 0xf5, 0x2e, 0x5e, 0x85, 0xbe, 0x65, 0x15, 0xce, + 0x63, 0xb8, 0xc8, 0x13, 0x28, 0xf3, 0x83, 0x58, + 0xa6, 0x7d, 0x0d, 0xd6, 0xed, 0x36, 0x46, 0x9d, + 0x30, 0xeb, 0x9b, 0x40, 0x7b, 0xa0, 0xd0, 0x0b, + 0x97, 0x4c, 0x3c, 0xe7, 0xdc, 0x07, 0x77, 0xac, + 0x01, 0xda, 0xaa, 0x71, 0x4a, 0x91, 0xe1, 0x3a, + 0x95, 0x4e, 0x3e, 0xe5, 0xde, 0x05, 0x75, 0xae, + 0x03, 0xd8, 0xa8, 0x73, 0x48, 0x93, 0xe3, 0x38, + 0xa4, 0x7f, 0x0f, 0xd4, 0xef, 0x34, 0x44, 0x9f, + 0x32, 0xe9, 0x99, 0x42, 0x79, 0xa2, 0xd2, 0x09, + 0xf7, 0x2c, 0x5c, 0x87, 0xbc, 0x67, 0x17, 0xcc, + 0x61, 0xba, 0xca, 0x11, 0x2a, 0xf1, 0x81, 0x5a, + 0xc6, 0x1d, 0x6d, 0xb6, 0x8d, 0x56, 0x26, 0xfd, + 0x50, 0x8b, 0xfb, 0x20, 0x1b, 0xc0, 0xb0, 0x6b, + 0x51, 0x8a, 0xfa, 0x21, 0x1a, 0xc1, 0xb1, 0x6a, + 0xc7, 0x1c, 0x6c, 0xb7, 0x8c, 0x57, 0x27, 0xfc, + 0x60, 0xbb, 0xcb, 0x10, 0x2b, 0xf0, 0x80, 0x5b, + 0xf6, 0x2d, 0x5d, 0x86, 0xbd, 0x66, 0x16, 0xcd, + 0x33, 0xe8, 0x98, 0x43, 0x78, 0xa3, 0xd3, 0x08, + 0xa5, 0x7e, 0x0e, 0xd5, 0xee, 0x35, 0x45, 0x9e, + 0x02, 0xd9, 0xa9, 0x72, 0x49, 0x92, 0xe2, 0x39, + 0x94, 0x4f, 0x3f, 0xe4, 0xdf, 0x04, 0x74, 0xaf, + }, + { + 0x00, 0xdc, 0xa5, 0x79, 0x57, 0x8b, 0xf2, 0x2e, + 0xae, 0x72, 0x0b, 0xd7, 0xf9, 0x25, 0x5c, 0x80, + 0x41, 0x9d, 0xe4, 0x38, 0x16, 0xca, 0xb3, 0x6f, + 0xef, 0x33, 0x4a, 0x96, 0xb8, 0x64, 0x1d, 0xc1, + 0x82, 0x5e, 0x27, 0xfb, 0xd5, 0x09, 0x70, 0xac, + 0x2c, 0xf0, 0x89, 0x55, 0x7b, 0xa7, 0xde, 0x02, + 0xc3, 0x1f, 0x66, 0xba, 0x94, 0x48, 0x31, 0xed, + 0x6d, 0xb1, 0xc8, 0x14, 0x3a, 0xe6, 0x9f, 0x43, + 0x19, 0xc5, 0xbc, 0x60, 0x4e, 0x92, 0xeb, 0x37, + 0xb7, 0x6b, 0x12, 0xce, 0xe0, 0x3c, 0x45, 0x99, + 0x58, 0x84, 0xfd, 0x21, 0x0f, 0xd3, 0xaa, 0x76, + 0xf6, 0x2a, 0x53, 0x8f, 0xa1, 0x7d, 0x04, 0xd8, + 0x9b, 0x47, 0x3e, 0xe2, 0xcc, 0x10, 0x69, 0xb5, + 0x35, 0xe9, 0x90, 0x4c, 0x62, 0xbe, 0xc7, 0x1b, + 0xda, 0x06, 0x7f, 0xa3, 0x8d, 0x51, 0x28, 0xf4, + 0x74, 0xa8, 0xd1, 0x0d, 0x23, 0xff, 0x86, 0x5a, + 0x32, 0xee, 0x97, 0x4b, 0x65, 0xb9, 0xc0, 0x1c, + 0x9c, 0x40, 0x39, 0xe5, 0xcb, 0x17, 0x6e, 0xb2, + 0x73, 0xaf, 0xd6, 0x0a, 0x24, 0xf8, 0x81, 0x5d, + 0xdd, 0x01, 0x78, 0xa4, 0x8a, 0x56, 0x2f, 0xf3, + 0xb0, 0x6c, 0x15, 0xc9, 0xe7, 0x3b, 0x42, 0x9e, + 0x1e, 0xc2, 0xbb, 0x67, 0x49, 0x95, 0xec, 0x30, + 0xf1, 0x2d, 0x54, 0x88, 0xa6, 0x7a, 0x03, 0xdf, + 0x5f, 0x83, 0xfa, 0x26, 0x08, 0xd4, 0xad, 0x71, + 0x2b, 0xf7, 0x8e, 0x52, 0x7c, 0xa0, 0xd9, 0x05, + 0x85, 0x59, 0x20, 0xfc, 0xd2, 0x0e, 0x77, 0xab, + 0x6a, 0xb6, 0xcf, 0x13, 0x3d, 0xe1, 0x98, 0x44, + 0xc4, 0x18, 0x61, 0xbd, 0x93, 0x4f, 0x36, 0xea, + 0xa9, 0x75, 0x0c, 0xd0, 0xfe, 0x22, 0x5b, 0x87, + 0x07, 0xdb, 0xa2, 0x7e, 0x50, 0x8c, 0xf5, 0x29, + 0xe8, 0x34, 0x4d, 0x91, 0xbf, 0x63, 0x1a, 0xc6, + 0x46, 0x9a, 0xe3, 0x3f, 0x11, 0xcd, 0xb4, 0x68, + }, + { + 0x00, 0xdd, 0xa7, 0x7a, 0x53, 0x8e, 0xf4, 0x29, + 0xa6, 0x7b, 0x01, 0xdc, 0xf5, 0x28, 0x52, 0x8f, + 0x51, 0x8c, 0xf6, 0x2b, 0x02, 0xdf, 0xa5, 0x78, + 0xf7, 0x2a, 0x50, 0x8d, 0xa4, 0x79, 0x03, 0xde, + 0xa2, 0x7f, 0x05, 0xd8, 0xf1, 0x2c, 0x56, 0x8b, + 0x04, 0xd9, 0xa3, 0x7e, 0x57, 0x8a, 0xf0, 0x2d, + 0xf3, 0x2e, 0x54, 0x89, 0xa0, 0x7d, 0x07, 0xda, + 0x55, 0x88, 0xf2, 0x2f, 0x06, 0xdb, 0xa1, 0x7c, + 0x59, 0x84, 0xfe, 0x23, 0x0a, 0xd7, 0xad, 0x70, + 0xff, 0x22, 0x58, 0x85, 0xac, 0x71, 0x0b, 0xd6, + 0x08, 0xd5, 0xaf, 0x72, 0x5b, 0x86, 0xfc, 0x21, + 0xae, 0x73, 0x09, 0xd4, 0xfd, 0x20, 0x5a, 0x87, + 0xfb, 0x26, 0x5c, 0x81, 0xa8, 0x75, 0x0f, 0xd2, + 0x5d, 0x80, 0xfa, 0x27, 0x0e, 0xd3, 0xa9, 0x74, + 0xaa, 0x77, 0x0d, 0xd0, 0xf9, 0x24, 0x5e, 0x83, + 0x0c, 0xd1, 0xab, 0x76, 0x5f, 0x82, 0xf8, 0x25, + 0xb2, 0x6f, 0x15, 0xc8, 0xe1, 0x3c, 0x46, 0x9b, + 0x14, 0xc9, 0xb3, 0x6e, 0x47, 0x9a, 0xe0, 0x3d, + 0xe3, 0x3e, 0x44, 0x99, 0xb0, 0x6d, 0x17, 0xca, + 0x45, 0x98, 0xe2, 0x3f, 0x16, 0xcb, 0xb1, 0x6c, + 0x10, 0xcd, 0xb7, 0x6a, 0x43, 0x9e, 0xe4, 0x39, + 0xb6, 0x6b, 0x11, 0xcc, 0xe5, 0x38, 0x42, 0x9f, + 0x41, 0x9c, 0xe6, 0x3b, 0x12, 0xcf, 0xb5, 0x68, + 0xe7, 0x3a, 0x40, 0x9d, 0xb4, 0x69, 0x13, 0xce, + 0xeb, 0x36, 0x4c, 0x91, 0xb8, 0x65, 0x1f, 0xc2, + 0x4d, 0x90, 0xea, 0x37, 0x1e, 0xc3, 0xb9, 0x64, + 0xba, 0x67, 0x1d, 0xc0, 0xe9, 0x34, 0x4e, 0x93, + 0x1c, 0xc1, 0xbb, 0x66, 0x4f, 0x92, 0xe8, 0x35, + 0x49, 0x94, 0xee, 0x33, 0x1a, 0xc7, 0xbd, 0x60, + 0xef, 0x32, 0x48, 0x95, 0xbc, 0x61, 0x1b, 0xc6, + 0x18, 0xc5, 0xbf, 0x62, 0x4b, 0x96, 0xec, 0x31, + 0xbe, 0x63, 0x19, 0xc4, 0xed, 0x30, 0x4a, 0x97, + }, + { + 0x00, 0xde, 0xa1, 0x7f, 0x5f, 0x81, 0xfe, 0x20, + 0xbe, 0x60, 0x1f, 0xc1, 0xe1, 0x3f, 0x40, 0x9e, + 0x61, 0xbf, 0xc0, 0x1e, 0x3e, 0xe0, 0x9f, 0x41, + 0xdf, 0x01, 0x7e, 0xa0, 0x80, 0x5e, 0x21, 0xff, + 0xc2, 0x1c, 0x63, 0xbd, 0x9d, 0x43, 0x3c, 0xe2, + 0x7c, 0xa2, 0xdd, 0x03, 0x23, 0xfd, 0x82, 0x5c, + 0xa3, 0x7d, 0x02, 0xdc, 0xfc, 0x22, 0x5d, 0x83, + 0x1d, 0xc3, 0xbc, 0x62, 0x42, 0x9c, 0xe3, 0x3d, + 0x99, 0x47, 0x38, 0xe6, 0xc6, 0x18, 0x67, 0xb9, + 0x27, 0xf9, 0x86, 0x58, 0x78, 0xa6, 0xd9, 0x07, + 0xf8, 0x26, 0x59, 0x87, 0xa7, 0x79, 0x06, 0xd8, + 0x46, 0x98, 0xe7, 0x39, 0x19, 0xc7, 0xb8, 0x66, + 0x5b, 0x85, 0xfa, 0x24, 0x04, 0xda, 0xa5, 0x7b, + 0xe5, 0x3b, 0x44, 0x9a, 0xba, 0x64, 0x1b, 0xc5, + 0x3a, 0xe4, 0x9b, 0x45, 0x65, 0xbb, 0xc4, 0x1a, + 0x84, 0x5a, 0x25, 0xfb, 0xdb, 0x05, 0x7a, 0xa4, + 0x2f, 0xf1, 0x8e, 0x50, 0x70, 0xae, 0xd1, 0x0f, + 0x91, 0x4f, 0x30, 0xee, 0xce, 0x10, 0x6f, 0xb1, + 0x4e, 0x90, 0xef, 0x31, 0x11, 0xcf, 0xb0, 0x6e, + 0xf0, 0x2e, 0x51, 0x8f, 0xaf, 0x71, 0x0e, 0xd0, + 0xed, 0x33, 0x4c, 0x92, 0xb2, 0x6c, 0x13, 0xcd, + 0x53, 0x8d, 0xf2, 0x2c, 0x0c, 0xd2, 0xad, 0x73, + 0x8c, 0x52, 0x2d, 0xf3, 0xd3, 0x0d, 0x72, 0xac, + 0x32, 0xec, 0x93, 0x4d, 0x6d, 0xb3, 0xcc, 0x12, + 0xb6, 0x68, 0x17, 0xc9, 0xe9, 0x37, 0x48, 0x96, + 0x08, 0xd6, 0xa9, 0x77, 0x57, 0x89, 0xf6, 0x28, + 0xd7, 0x09, 0x76, 0xa8, 0x88, 0x56, 0x29, 0xf7, + 0x69, 0xb7, 0xc8, 0x16, 0x36, 0xe8, 0x97, 0x49, + 0x74, 0xaa, 0xd5, 0x0b, 0x2b, 0xf5, 0x8a, 0x54, + 0xca, 0x14, 0x6b, 0xb5, 0x95, 0x4b, 0x34, 0xea, + 0x15, 0xcb, 0xb4, 0x6a, 0x4a, 0x94, 0xeb, 0x35, + 0xab, 0x75, 0x0a, 0xd4, 0xf4, 0x2a, 0x55, 0x8b, + }, + { + 0x00, 0xdf, 0xa3, 0x7c, 0x5b, 0x84, 0xf8, 0x27, + 0xb6, 0x69, 0x15, 0xca, 0xed, 0x32, 0x4e, 0x91, + 0x71, 0xae, 0xd2, 0x0d, 0x2a, 0xf5, 0x89, 0x56, + 0xc7, 0x18, 0x64, 0xbb, 0x9c, 0x43, 0x3f, 0xe0, + 0xe2, 0x3d, 0x41, 0x9e, 0xb9, 0x66, 0x1a, 0xc5, + 0x54, 0x8b, 0xf7, 0x28, 0x0f, 0xd0, 0xac, 0x73, + 0x93, 0x4c, 0x30, 0xef, 0xc8, 0x17, 0x6b, 0xb4, + 0x25, 0xfa, 0x86, 0x59, 0x7e, 0xa1, 0xdd, 0x02, + 0xd9, 0x06, 0x7a, 0xa5, 0x82, 0x5d, 0x21, 0xfe, + 0x6f, 0xb0, 0xcc, 0x13, 0x34, 0xeb, 0x97, 0x48, + 0xa8, 0x77, 0x0b, 0xd4, 0xf3, 0x2c, 0x50, 0x8f, + 0x1e, 0xc1, 0xbd, 0x62, 0x45, 0x9a, 0xe6, 0x39, + 0x3b, 0xe4, 0x98, 0x47, 0x60, 0xbf, 0xc3, 0x1c, + 0x8d, 0x52, 0x2e, 0xf1, 0xd6, 0x09, 0x75, 0xaa, + 0x4a, 0x95, 0xe9, 0x36, 0x11, 0xce, 0xb2, 0x6d, + 0xfc, 0x23, 0x5f, 0x80, 0xa7, 0x78, 0x04, 0xdb, + 0xaf, 0x70, 0x0c, 0xd3, 0xf4, 0x2b, 0x57, 0x88, + 0x19, 0xc6, 0xba, 0x65, 0x42, 0x9d, 0xe1, 0x3e, + 0xde, 0x01, 0x7d, 0xa2, 0x85, 0x5a, 0x26, 0xf9, + 0x68, 0xb7, 0xcb, 0x14, 0x33, 0xec, 0x90, 0x4f, + 0x4d, 0x92, 0xee, 0x31, 0x16, 0xc9, 0xb5, 0x6a, + 0xfb, 0x24, 0x58, 0x87, 0xa0, 0x7f, 0x03, 0xdc, + 0x3c, 0xe3, 0x9f, 0x40, 0x67, 0xb8, 0xc4, 0x1b, + 0x8a, 0x55, 0x29, 0xf6, 0xd1, 0x0e, 0x72, 0xad, + 0x76, 0xa9, 0xd5, 0x0a, 0x2d, 0xf2, 0x8e, 0x51, + 0xc0, 0x1f, 0x63, 0xbc, 0x9b, 0x44, 0x38, 0xe7, + 0x07, 0xd8, 0xa4, 0x7b, 0x5c, 0x83, 0xff, 0x20, + 0xb1, 0x6e, 0x12, 0xcd, 0xea, 0x35, 0x49, 0x96, + 0x94, 0x4b, 0x37, 0xe8, 0xcf, 0x10, 0x6c, 0xb3, + 0x22, 0xfd, 0x81, 0x5e, 0x79, 0xa6, 0xda, 0x05, + 0xe5, 0x3a, 0x46, 0x99, 0xbe, 0x61, 0x1d, 0xc2, + 0x53, 0x8c, 0xf0, 0x2f, 0x08, 0xd7, 0xab, 0x74, + }, + { + 0x00, 0xe0, 0xdd, 0x3d, 0xa7, 0x47, 0x7a, 0x9a, + 0x53, 0xb3, 0x8e, 0x6e, 0xf4, 0x14, 0x29, 0xc9, + 0xa6, 0x46, 0x7b, 0x9b, 0x01, 0xe1, 0xdc, 0x3c, + 0xf5, 0x15, 0x28, 0xc8, 0x52, 0xb2, 0x8f, 0x6f, + 0x51, 0xb1, 0x8c, 0x6c, 0xf6, 0x16, 0x2b, 0xcb, + 0x02, 0xe2, 0xdf, 0x3f, 0xa5, 0x45, 0x78, 0x98, + 0xf7, 0x17, 0x2a, 0xca, 0x50, 0xb0, 0x8d, 0x6d, + 0xa4, 0x44, 0x79, 0x99, 0x03, 0xe3, 0xde, 0x3e, + 0xa2, 0x42, 0x7f, 0x9f, 0x05, 0xe5, 0xd8, 0x38, + 0xf1, 0x11, 0x2c, 0xcc, 0x56, 0xb6, 0x8b, 0x6b, + 0x04, 0xe4, 0xd9, 0x39, 0xa3, 0x43, 0x7e, 0x9e, + 0x57, 0xb7, 0x8a, 0x6a, 0xf0, 0x10, 0x2d, 0xcd, + 0xf3, 0x13, 0x2e, 0xce, 0x54, 0xb4, 0x89, 0x69, + 0xa0, 0x40, 0x7d, 0x9d, 0x07, 0xe7, 0xda, 0x3a, + 0x55, 0xb5, 0x88, 0x68, 0xf2, 0x12, 0x2f, 0xcf, + 0x06, 0xe6, 0xdb, 0x3b, 0xa1, 0x41, 0x7c, 0x9c, + 0x59, 0xb9, 0x84, 0x64, 0xfe, 0x1e, 0x23, 0xc3, + 0x0a, 0xea, 0xd7, 0x37, 0xad, 0x4d, 0x70, 0x90, + 0xff, 0x1f, 0x22, 0xc2, 0x58, 0xb8, 0x85, 0x65, + 0xac, 0x4c, 0x71, 0x91, 0x0b, 0xeb, 0xd6, 0x36, + 0x08, 0xe8, 0xd5, 0x35, 0xaf, 0x4f, 0x72, 0x92, + 0x5b, 0xbb, 0x86, 0x66, 0xfc, 0x1c, 0x21, 0xc1, + 0xae, 0x4e, 0x73, 0x93, 0x09, 0xe9, 0xd4, 0x34, + 0xfd, 0x1d, 0x20, 0xc0, 0x5a, 0xba, 0x87, 0x67, + 0xfb, 0x1b, 0x26, 0xc6, 0x5c, 0xbc, 0x81, 0x61, + 0xa8, 0x48, 0x75, 0x95, 0x0f, 0xef, 0xd2, 0x32, + 0x5d, 0xbd, 0x80, 0x60, 0xfa, 0x1a, 0x27, 0xc7, + 0x0e, 0xee, 0xd3, 0x33, 0xa9, 0x49, 0x74, 0x94, + 0xaa, 0x4a, 0x77, 0x97, 0x0d, 0xed, 0xd0, 0x30, + 0xf9, 0x19, 0x24, 0xc4, 0x5e, 0xbe, 0x83, 0x63, + 0x0c, 0xec, 0xd1, 0x31, 0xab, 0x4b, 0x76, 0x96, + 0x5f, 0xbf, 0x82, 0x62, 0xf8, 0x18, 0x25, 0xc5, + }, + { + 0x00, 0xe1, 0xdf, 0x3e, 0xa3, 0x42, 0x7c, 0x9d, + 0x5b, 0xba, 0x84, 0x65, 0xf8, 0x19, 0x27, 0xc6, + 0xb6, 0x57, 0x69, 0x88, 0x15, 0xf4, 0xca, 0x2b, + 0xed, 0x0c, 0x32, 0xd3, 0x4e, 0xaf, 0x91, 0x70, + 0x71, 0x90, 0xae, 0x4f, 0xd2, 0x33, 0x0d, 0xec, + 0x2a, 0xcb, 0xf5, 0x14, 0x89, 0x68, 0x56, 0xb7, + 0xc7, 0x26, 0x18, 0xf9, 0x64, 0x85, 0xbb, 0x5a, + 0x9c, 0x7d, 0x43, 0xa2, 0x3f, 0xde, 0xe0, 0x01, + 0xe2, 0x03, 0x3d, 0xdc, 0x41, 0xa0, 0x9e, 0x7f, + 0xb9, 0x58, 0x66, 0x87, 0x1a, 0xfb, 0xc5, 0x24, + 0x54, 0xb5, 0x8b, 0x6a, 0xf7, 0x16, 0x28, 0xc9, + 0x0f, 0xee, 0xd0, 0x31, 0xac, 0x4d, 0x73, 0x92, + 0x93, 0x72, 0x4c, 0xad, 0x30, 0xd1, 0xef, 0x0e, + 0xc8, 0x29, 0x17, 0xf6, 0x6b, 0x8a, 0xb4, 0x55, + 0x25, 0xc4, 0xfa, 0x1b, 0x86, 0x67, 0x59, 0xb8, + 0x7e, 0x9f, 0xa1, 0x40, 0xdd, 0x3c, 0x02, 0xe3, + 0xd9, 0x38, 0x06, 0xe7, 0x7a, 0x9b, 0xa5, 0x44, + 0x82, 0x63, 0x5d, 0xbc, 0x21, 0xc0, 0xfe, 0x1f, + 0x6f, 0x8e, 0xb0, 0x51, 0xcc, 0x2d, 0x13, 0xf2, + 0x34, 0xd5, 0xeb, 0x0a, 0x97, 0x76, 0x48, 0xa9, + 0xa8, 0x49, 0x77, 0x96, 0x0b, 0xea, 0xd4, 0x35, + 0xf3, 0x12, 0x2c, 0xcd, 0x50, 0xb1, 0x8f, 0x6e, + 0x1e, 0xff, 0xc1, 0x20, 0xbd, 0x5c, 0x62, 0x83, + 0x45, 0xa4, 0x9a, 0x7b, 0xe6, 0x07, 0x39, 0xd8, + 0x3b, 0xda, 0xe4, 0x05, 0x98, 0x79, 0x47, 0xa6, + 0x60, 0x81, 0xbf, 0x5e, 0xc3, 0x22, 0x1c, 0xfd, + 0x8d, 0x6c, 0x52, 0xb3, 0x2e, 0xcf, 0xf1, 0x10, + 0xd6, 0x37, 0x09, 0xe8, 0x75, 0x94, 0xaa, 0x4b, + 0x4a, 0xab, 0x95, 0x74, 0xe9, 0x08, 0x36, 0xd7, + 0x11, 0xf0, 0xce, 0x2f, 0xb2, 0x53, 0x6d, 0x8c, + 0xfc, 0x1d, 0x23, 0xc2, 0x5f, 0xbe, 0x80, 0x61, + 0xa7, 0x46, 0x78, 0x99, 0x04, 0xe5, 0xdb, 0x3a, + }, + { + 0x00, 0xe2, 0xd9, 0x3b, 0xaf, 0x4d, 0x76, 0x94, + 0x43, 0xa1, 0x9a, 0x78, 0xec, 0x0e, 0x35, 0xd7, + 0x86, 0x64, 0x5f, 0xbd, 0x29, 0xcb, 0xf0, 0x12, + 0xc5, 0x27, 0x1c, 0xfe, 0x6a, 0x88, 0xb3, 0x51, + 0x11, 0xf3, 0xc8, 0x2a, 0xbe, 0x5c, 0x67, 0x85, + 0x52, 0xb0, 0x8b, 0x69, 0xfd, 0x1f, 0x24, 0xc6, + 0x97, 0x75, 0x4e, 0xac, 0x38, 0xda, 0xe1, 0x03, + 0xd4, 0x36, 0x0d, 0xef, 0x7b, 0x99, 0xa2, 0x40, + 0x22, 0xc0, 0xfb, 0x19, 0x8d, 0x6f, 0x54, 0xb6, + 0x61, 0x83, 0xb8, 0x5a, 0xce, 0x2c, 0x17, 0xf5, + 0xa4, 0x46, 0x7d, 0x9f, 0x0b, 0xe9, 0xd2, 0x30, + 0xe7, 0x05, 0x3e, 0xdc, 0x48, 0xaa, 0x91, 0x73, + 0x33, 0xd1, 0xea, 0x08, 0x9c, 0x7e, 0x45, 0xa7, + 0x70, 0x92, 0xa9, 0x4b, 0xdf, 0x3d, 0x06, 0xe4, + 0xb5, 0x57, 0x6c, 0x8e, 0x1a, 0xf8, 0xc3, 0x21, + 0xf6, 0x14, 0x2f, 0xcd, 0x59, 0xbb, 0x80, 0x62, + 0x44, 0xa6, 0x9d, 0x7f, 0xeb, 0x09, 0x32, 0xd0, + 0x07, 0xe5, 0xde, 0x3c, 0xa8, 0x4a, 0x71, 0x93, + 0xc2, 0x20, 0x1b, 0xf9, 0x6d, 0x8f, 0xb4, 0x56, + 0x81, 0x63, 0x58, 0xba, 0x2e, 0xcc, 0xf7, 0x15, + 0x55, 0xb7, 0x8c, 0x6e, 0xfa, 0x18, 0x23, 0xc1, + 0x16, 0xf4, 0xcf, 0x2d, 0xb9, 0x5b, 0x60, 0x82, + 0xd3, 0x31, 0x0a, 0xe8, 0x7c, 0x9e, 0xa5, 0x47, + 0x90, 0x72, 0x49, 0xab, 0x3f, 0xdd, 0xe6, 0x04, + 0x66, 0x84, 0xbf, 0x5d, 0xc9, 0x2b, 0x10, 0xf2, + 0x25, 0xc7, 0xfc, 0x1e, 0x8a, 0x68, 0x53, 0xb1, + 0xe0, 0x02, 0x39, 0xdb, 0x4f, 0xad, 0x96, 0x74, + 0xa3, 0x41, 0x7a, 0x98, 0x0c, 0xee, 0xd5, 0x37, + 0x77, 0x95, 0xae, 0x4c, 0xd8, 0x3a, 0x01, 0xe3, + 0x34, 0xd6, 0xed, 0x0f, 0x9b, 0x79, 0x42, 0xa0, + 0xf1, 0x13, 0x28, 0xca, 0x5e, 0xbc, 0x87, 0x65, + 0xb2, 0x50, 0x6b, 0x89, 0x1d, 0xff, 0xc4, 0x26, + }, + { + 0x00, 0xe3, 0xdb, 0x38, 0xab, 0x48, 0x70, 0x93, + 0x4b, 0xa8, 0x90, 0x73, 0xe0, 0x03, 0x3b, 0xd8, + 0x96, 0x75, 0x4d, 0xae, 0x3d, 0xde, 0xe6, 0x05, + 0xdd, 0x3e, 0x06, 0xe5, 0x76, 0x95, 0xad, 0x4e, + 0x31, 0xd2, 0xea, 0x09, 0x9a, 0x79, 0x41, 0xa2, + 0x7a, 0x99, 0xa1, 0x42, 0xd1, 0x32, 0x0a, 0xe9, + 0xa7, 0x44, 0x7c, 0x9f, 0x0c, 0xef, 0xd7, 0x34, + 0xec, 0x0f, 0x37, 0xd4, 0x47, 0xa4, 0x9c, 0x7f, + 0x62, 0x81, 0xb9, 0x5a, 0xc9, 0x2a, 0x12, 0xf1, + 0x29, 0xca, 0xf2, 0x11, 0x82, 0x61, 0x59, 0xba, + 0xf4, 0x17, 0x2f, 0xcc, 0x5f, 0xbc, 0x84, 0x67, + 0xbf, 0x5c, 0x64, 0x87, 0x14, 0xf7, 0xcf, 0x2c, + 0x53, 0xb0, 0x88, 0x6b, 0xf8, 0x1b, 0x23, 0xc0, + 0x18, 0xfb, 0xc3, 0x20, 0xb3, 0x50, 0x68, 0x8b, + 0xc5, 0x26, 0x1e, 0xfd, 0x6e, 0x8d, 0xb5, 0x56, + 0x8e, 0x6d, 0x55, 0xb6, 0x25, 0xc6, 0xfe, 0x1d, + 0xc4, 0x27, 0x1f, 0xfc, 0x6f, 0x8c, 0xb4, 0x57, + 0x8f, 0x6c, 0x54, 0xb7, 0x24, 0xc7, 0xff, 0x1c, + 0x52, 0xb1, 0x89, 0x6a, 0xf9, 0x1a, 0x22, 0xc1, + 0x19, 0xfa, 0xc2, 0x21, 0xb2, 0x51, 0x69, 0x8a, + 0xf5, 0x16, 0x2e, 0xcd, 0x5e, 0xbd, 0x85, 0x66, + 0xbe, 0x5d, 0x65, 0x86, 0x15, 0xf6, 0xce, 0x2d, + 0x63, 0x80, 0xb8, 0x5b, 0xc8, 0x2b, 0x13, 0xf0, + 0x28, 0xcb, 0xf3, 0x10, 0x83, 0x60, 0x58, 0xbb, + 0xa6, 0x45, 0x7d, 0x9e, 0x0d, 0xee, 0xd6, 0x35, + 0xed, 0x0e, 0x36, 0xd5, 0x46, 0xa5, 0x9d, 0x7e, + 0x30, 0xd3, 0xeb, 0x08, 0x9b, 0x78, 0x40, 0xa3, + 0x7b, 0x98, 0xa0, 0x43, 0xd0, 0x33, 0x0b, 0xe8, + 0x97, 0x74, 0x4c, 0xaf, 0x3c, 0xdf, 0xe7, 0x04, + 0xdc, 0x3f, 0x07, 0xe4, 0x77, 0x94, 0xac, 0x4f, + 0x01, 0xe2, 0xda, 0x39, 0xaa, 0x49, 0x71, 0x92, + 0x4a, 0xa9, 0x91, 0x72, 0xe1, 0x02, 0x3a, 0xd9, + }, + { + 0x00, 0xe4, 0xd5, 0x31, 0xb7, 0x53, 0x62, 0x86, + 0x73, 0x97, 0xa6, 0x42, 0xc4, 0x20, 0x11, 0xf5, + 0xe6, 0x02, 0x33, 0xd7, 0x51, 0xb5, 0x84, 0x60, + 0x95, 0x71, 0x40, 0xa4, 0x22, 0xc6, 0xf7, 0x13, + 0xd1, 0x35, 0x04, 0xe0, 0x66, 0x82, 0xb3, 0x57, + 0xa2, 0x46, 0x77, 0x93, 0x15, 0xf1, 0xc0, 0x24, + 0x37, 0xd3, 0xe2, 0x06, 0x80, 0x64, 0x55, 0xb1, + 0x44, 0xa0, 0x91, 0x75, 0xf3, 0x17, 0x26, 0xc2, + 0xbf, 0x5b, 0x6a, 0x8e, 0x08, 0xec, 0xdd, 0x39, + 0xcc, 0x28, 0x19, 0xfd, 0x7b, 0x9f, 0xae, 0x4a, + 0x59, 0xbd, 0x8c, 0x68, 0xee, 0x0a, 0x3b, 0xdf, + 0x2a, 0xce, 0xff, 0x1b, 0x9d, 0x79, 0x48, 0xac, + 0x6e, 0x8a, 0xbb, 0x5f, 0xd9, 0x3d, 0x0c, 0xe8, + 0x1d, 0xf9, 0xc8, 0x2c, 0xaa, 0x4e, 0x7f, 0x9b, + 0x88, 0x6c, 0x5d, 0xb9, 0x3f, 0xdb, 0xea, 0x0e, + 0xfb, 0x1f, 0x2e, 0xca, 0x4c, 0xa8, 0x99, 0x7d, + 0x63, 0x87, 0xb6, 0x52, 0xd4, 0x30, 0x01, 0xe5, + 0x10, 0xf4, 0xc5, 0x21, 0xa7, 0x43, 0x72, 0x96, + 0x85, 0x61, 0x50, 0xb4, 0x32, 0xd6, 0xe7, 0x03, + 0xf6, 0x12, 0x23, 0xc7, 0x41, 0xa5, 0x94, 0x70, + 0xb2, 0x56, 0x67, 0x83, 0x05, 0xe1, 0xd0, 0x34, + 0xc1, 0x25, 0x14, 0xf0, 0x76, 0x92, 0xa3, 0x47, + 0x54, 0xb0, 0x81, 0x65, 0xe3, 0x07, 0x36, 0xd2, + 0x27, 0xc3, 0xf2, 0x16, 0x90, 0x74, 0x45, 0xa1, + 0xdc, 0x38, 0x09, 0xed, 0x6b, 0x8f, 0xbe, 0x5a, + 0xaf, 0x4b, 0x7a, 0x9e, 0x18, 0xfc, 0xcd, 0x29, + 0x3a, 0xde, 0xef, 0x0b, 0x8d, 0x69, 0x58, 0xbc, + 0x49, 0xad, 0x9c, 0x78, 0xfe, 0x1a, 0x2b, 0xcf, + 0x0d, 0xe9, 0xd8, 0x3c, 0xba, 0x5e, 0x6f, 0x8b, + 0x7e, 0x9a, 0xab, 0x4f, 0xc9, 0x2d, 0x1c, 0xf8, + 0xeb, 0x0f, 0x3e, 0xda, 0x5c, 0xb8, 0x89, 0x6d, + 0x98, 0x7c, 0x4d, 0xa9, 0x2f, 0xcb, 0xfa, 0x1e, + }, + { + 0x00, 0xe5, 0xd7, 0x32, 0xb3, 0x56, 0x64, 0x81, + 0x7b, 0x9e, 0xac, 0x49, 0xc8, 0x2d, 0x1f, 0xfa, + 0xf6, 0x13, 0x21, 0xc4, 0x45, 0xa0, 0x92, 0x77, + 0x8d, 0x68, 0x5a, 0xbf, 0x3e, 0xdb, 0xe9, 0x0c, + 0xf1, 0x14, 0x26, 0xc3, 0x42, 0xa7, 0x95, 0x70, + 0x8a, 0x6f, 0x5d, 0xb8, 0x39, 0xdc, 0xee, 0x0b, + 0x07, 0xe2, 0xd0, 0x35, 0xb4, 0x51, 0x63, 0x86, + 0x7c, 0x99, 0xab, 0x4e, 0xcf, 0x2a, 0x18, 0xfd, + 0xff, 0x1a, 0x28, 0xcd, 0x4c, 0xa9, 0x9b, 0x7e, + 0x84, 0x61, 0x53, 0xb6, 0x37, 0xd2, 0xe0, 0x05, + 0x09, 0xec, 0xde, 0x3b, 0xba, 0x5f, 0x6d, 0x88, + 0x72, 0x97, 0xa5, 0x40, 0xc1, 0x24, 0x16, 0xf3, + 0x0e, 0xeb, 0xd9, 0x3c, 0xbd, 0x58, 0x6a, 0x8f, + 0x75, 0x90, 0xa2, 0x47, 0xc6, 0x23, 0x11, 0xf4, + 0xf8, 0x1d, 0x2f, 0xca, 0x4b, 0xae, 0x9c, 0x79, + 0x83, 0x66, 0x54, 0xb1, 0x30, 0xd5, 0xe7, 0x02, + 0xe3, 0x06, 0x34, 0xd1, 0x50, 0xb5, 0x87, 0x62, + 0x98, 0x7d, 0x4f, 0xaa, 0x2b, 0xce, 0xfc, 0x19, + 0x15, 0xf0, 0xc2, 0x27, 0xa6, 0x43, 0x71, 0x94, + 0x6e, 0x8b, 0xb9, 0x5c, 0xdd, 0x38, 0x0a, 0xef, + 0x12, 0xf7, 0xc5, 0x20, 0xa1, 0x44, 0x76, 0x93, + 0x69, 0x8c, 0xbe, 0x5b, 0xda, 0x3f, 0x0d, 0xe8, + 0xe4, 0x01, 0x33, 0xd6, 0x57, 0xb2, 0x80, 0x65, + 0x9f, 0x7a, 0x48, 0xad, 0x2c, 0xc9, 0xfb, 0x1e, + 0x1c, 0xf9, 0xcb, 0x2e, 0xaf, 0x4a, 0x78, 0x9d, + 0x67, 0x82, 0xb0, 0x55, 0xd4, 0x31, 0x03, 0xe6, + 0xea, 0x0f, 0x3d, 0xd8, 0x59, 0xbc, 0x8e, 0x6b, + 0x91, 0x74, 0x46, 0xa3, 0x22, 0xc7, 0xf5, 0x10, + 0xed, 0x08, 0x3a, 0xdf, 0x5e, 0xbb, 0x89, 0x6c, + 0x96, 0x73, 0x41, 0xa4, 0x25, 0xc0, 0xf2, 0x17, + 0x1b, 0xfe, 0xcc, 0x29, 0xa8, 0x4d, 0x7f, 0x9a, + 0x60, 0x85, 0xb7, 0x52, 0xd3, 0x36, 0x04, 0xe1, + }, + { + 0x00, 0xe6, 0xd1, 0x37, 0xbf, 0x59, 0x6e, 0x88, + 0x63, 0x85, 0xb2, 0x54, 0xdc, 0x3a, 0x0d, 0xeb, + 0xc6, 0x20, 0x17, 0xf1, 0x79, 0x9f, 0xa8, 0x4e, + 0xa5, 0x43, 0x74, 0x92, 0x1a, 0xfc, 0xcb, 0x2d, + 0x91, 0x77, 0x40, 0xa6, 0x2e, 0xc8, 0xff, 0x19, + 0xf2, 0x14, 0x23, 0xc5, 0x4d, 0xab, 0x9c, 0x7a, + 0x57, 0xb1, 0x86, 0x60, 0xe8, 0x0e, 0x39, 0xdf, + 0x34, 0xd2, 0xe5, 0x03, 0x8b, 0x6d, 0x5a, 0xbc, + 0x3f, 0xd9, 0xee, 0x08, 0x80, 0x66, 0x51, 0xb7, + 0x5c, 0xba, 0x8d, 0x6b, 0xe3, 0x05, 0x32, 0xd4, + 0xf9, 0x1f, 0x28, 0xce, 0x46, 0xa0, 0x97, 0x71, + 0x9a, 0x7c, 0x4b, 0xad, 0x25, 0xc3, 0xf4, 0x12, + 0xae, 0x48, 0x7f, 0x99, 0x11, 0xf7, 0xc0, 0x26, + 0xcd, 0x2b, 0x1c, 0xfa, 0x72, 0x94, 0xa3, 0x45, + 0x68, 0x8e, 0xb9, 0x5f, 0xd7, 0x31, 0x06, 0xe0, + 0x0b, 0xed, 0xda, 0x3c, 0xb4, 0x52, 0x65, 0x83, + 0x7e, 0x98, 0xaf, 0x49, 0xc1, 0x27, 0x10, 0xf6, + 0x1d, 0xfb, 0xcc, 0x2a, 0xa2, 0x44, 0x73, 0x95, + 0xb8, 0x5e, 0x69, 0x8f, 0x07, 0xe1, 0xd6, 0x30, + 0xdb, 0x3d, 0x0a, 0xec, 0x64, 0x82, 0xb5, 0x53, + 0xef, 0x09, 0x3e, 0xd8, 0x50, 0xb6, 0x81, 0x67, + 0x8c, 0x6a, 0x5d, 0xbb, 0x33, 0xd5, 0xe2, 0x04, + 0x29, 0xcf, 0xf8, 0x1e, 0x96, 0x70, 0x47, 0xa1, + 0x4a, 0xac, 0x9b, 0x7d, 0xf5, 0x13, 0x24, 0xc2, + 0x41, 0xa7, 0x90, 0x76, 0xfe, 0x18, 0x2f, 0xc9, + 0x22, 0xc4, 0xf3, 0x15, 0x9d, 0x7b, 0x4c, 0xaa, + 0x87, 0x61, 0x56, 0xb0, 0x38, 0xde, 0xe9, 0x0f, + 0xe4, 0x02, 0x35, 0xd3, 0x5b, 0xbd, 0x8a, 0x6c, + 0xd0, 0x36, 0x01, 0xe7, 0x6f, 0x89, 0xbe, 0x58, + 0xb3, 0x55, 0x62, 0x84, 0x0c, 0xea, 0xdd, 0x3b, + 0x16, 0xf0, 0xc7, 0x21, 0xa9, 0x4f, 0x78, 0x9e, + 0x75, 0x93, 0xa4, 0x42, 0xca, 0x2c, 0x1b, 0xfd, + }, + { + 0x00, 0xe7, 0xd3, 0x34, 0xbb, 0x5c, 0x68, 0x8f, + 0x6b, 0x8c, 0xb8, 0x5f, 0xd0, 0x37, 0x03, 0xe4, + 0xd6, 0x31, 0x05, 0xe2, 0x6d, 0x8a, 0xbe, 0x59, + 0xbd, 0x5a, 0x6e, 0x89, 0x06, 0xe1, 0xd5, 0x32, + 0xb1, 0x56, 0x62, 0x85, 0x0a, 0xed, 0xd9, 0x3e, + 0xda, 0x3d, 0x09, 0xee, 0x61, 0x86, 0xb2, 0x55, + 0x67, 0x80, 0xb4, 0x53, 0xdc, 0x3b, 0x0f, 0xe8, + 0x0c, 0xeb, 0xdf, 0x38, 0xb7, 0x50, 0x64, 0x83, + 0x7f, 0x98, 0xac, 0x4b, 0xc4, 0x23, 0x17, 0xf0, + 0x14, 0xf3, 0xc7, 0x20, 0xaf, 0x48, 0x7c, 0x9b, + 0xa9, 0x4e, 0x7a, 0x9d, 0x12, 0xf5, 0xc1, 0x26, + 0xc2, 0x25, 0x11, 0xf6, 0x79, 0x9e, 0xaa, 0x4d, + 0xce, 0x29, 0x1d, 0xfa, 0x75, 0x92, 0xa6, 0x41, + 0xa5, 0x42, 0x76, 0x91, 0x1e, 0xf9, 0xcd, 0x2a, + 0x18, 0xff, 0xcb, 0x2c, 0xa3, 0x44, 0x70, 0x97, + 0x73, 0x94, 0xa0, 0x47, 0xc8, 0x2f, 0x1b, 0xfc, + 0xfe, 0x19, 0x2d, 0xca, 0x45, 0xa2, 0x96, 0x71, + 0x95, 0x72, 0x46, 0xa1, 0x2e, 0xc9, 0xfd, 0x1a, + 0x28, 0xcf, 0xfb, 0x1c, 0x93, 0x74, 0x40, 0xa7, + 0x43, 0xa4, 0x90, 0x77, 0xf8, 0x1f, 0x2b, 0xcc, + 0x4f, 0xa8, 0x9c, 0x7b, 0xf4, 0x13, 0x27, 0xc0, + 0x24, 0xc3, 0xf7, 0x10, 0x9f, 0x78, 0x4c, 0xab, + 0x99, 0x7e, 0x4a, 0xad, 0x22, 0xc5, 0xf1, 0x16, + 0xf2, 0x15, 0x21, 0xc6, 0x49, 0xae, 0x9a, 0x7d, + 0x81, 0x66, 0x52, 0xb5, 0x3a, 0xdd, 0xe9, 0x0e, + 0xea, 0x0d, 0x39, 0xde, 0x51, 0xb6, 0x82, 0x65, + 0x57, 0xb0, 0x84, 0x63, 0xec, 0x0b, 0x3f, 0xd8, + 0x3c, 0xdb, 0xef, 0x08, 0x87, 0x60, 0x54, 0xb3, + 0x30, 0xd7, 0xe3, 0x04, 0x8b, 0x6c, 0x58, 0xbf, + 0x5b, 0xbc, 0x88, 0x6f, 0xe0, 0x07, 0x33, 0xd4, + 0xe6, 0x01, 0x35, 0xd2, 0x5d, 0xba, 0x8e, 0x69, + 0x8d, 0x6a, 0x5e, 0xb9, 0x36, 0xd1, 0xe5, 0x02, + }, + { + 0x00, 0xe8, 0xcd, 0x25, 0x87, 0x6f, 0x4a, 0xa2, + 0x13, 0xfb, 0xde, 0x36, 0x94, 0x7c, 0x59, 0xb1, + 0x26, 0xce, 0xeb, 0x03, 0xa1, 0x49, 0x6c, 0x84, + 0x35, 0xdd, 0xf8, 0x10, 0xb2, 0x5a, 0x7f, 0x97, + 0x4c, 0xa4, 0x81, 0x69, 0xcb, 0x23, 0x06, 0xee, + 0x5f, 0xb7, 0x92, 0x7a, 0xd8, 0x30, 0x15, 0xfd, + 0x6a, 0x82, 0xa7, 0x4f, 0xed, 0x05, 0x20, 0xc8, + 0x79, 0x91, 0xb4, 0x5c, 0xfe, 0x16, 0x33, 0xdb, + 0x98, 0x70, 0x55, 0xbd, 0x1f, 0xf7, 0xd2, 0x3a, + 0x8b, 0x63, 0x46, 0xae, 0x0c, 0xe4, 0xc1, 0x29, + 0xbe, 0x56, 0x73, 0x9b, 0x39, 0xd1, 0xf4, 0x1c, + 0xad, 0x45, 0x60, 0x88, 0x2a, 0xc2, 0xe7, 0x0f, + 0xd4, 0x3c, 0x19, 0xf1, 0x53, 0xbb, 0x9e, 0x76, + 0xc7, 0x2f, 0x0a, 0xe2, 0x40, 0xa8, 0x8d, 0x65, + 0xf2, 0x1a, 0x3f, 0xd7, 0x75, 0x9d, 0xb8, 0x50, + 0xe1, 0x09, 0x2c, 0xc4, 0x66, 0x8e, 0xab, 0x43, + 0x2d, 0xc5, 0xe0, 0x08, 0xaa, 0x42, 0x67, 0x8f, + 0x3e, 0xd6, 0xf3, 0x1b, 0xb9, 0x51, 0x74, 0x9c, + 0x0b, 0xe3, 0xc6, 0x2e, 0x8c, 0x64, 0x41, 0xa9, + 0x18, 0xf0, 0xd5, 0x3d, 0x9f, 0x77, 0x52, 0xba, + 0x61, 0x89, 0xac, 0x44, 0xe6, 0x0e, 0x2b, 0xc3, + 0x72, 0x9a, 0xbf, 0x57, 0xf5, 0x1d, 0x38, 0xd0, + 0x47, 0xaf, 0x8a, 0x62, 0xc0, 0x28, 0x0d, 0xe5, + 0x54, 0xbc, 0x99, 0x71, 0xd3, 0x3b, 0x1e, 0xf6, + 0xb5, 0x5d, 0x78, 0x90, 0x32, 0xda, 0xff, 0x17, + 0xa6, 0x4e, 0x6b, 0x83, 0x21, 0xc9, 0xec, 0x04, + 0x93, 0x7b, 0x5e, 0xb6, 0x14, 0xfc, 0xd9, 0x31, + 0x80, 0x68, 0x4d, 0xa5, 0x07, 0xef, 0xca, 0x22, + 0xf9, 0x11, 0x34, 0xdc, 0x7e, 0x96, 0xb3, 0x5b, + 0xea, 0x02, 0x27, 0xcf, 0x6d, 0x85, 0xa0, 0x48, + 0xdf, 0x37, 0x12, 0xfa, 0x58, 0xb0, 0x95, 0x7d, + 0xcc, 0x24, 0x01, 0xe9, 0x4b, 0xa3, 0x86, 0x6e, + }, + { + 0x00, 0xe9, 0xcf, 0x26, 0x83, 0x6a, 0x4c, 0xa5, + 0x1b, 0xf2, 0xd4, 0x3d, 0x98, 0x71, 0x57, 0xbe, + 0x36, 0xdf, 0xf9, 0x10, 0xb5, 0x5c, 0x7a, 0x93, + 0x2d, 0xc4, 0xe2, 0x0b, 0xae, 0x47, 0x61, 0x88, + 0x6c, 0x85, 0xa3, 0x4a, 0xef, 0x06, 0x20, 0xc9, + 0x77, 0x9e, 0xb8, 0x51, 0xf4, 0x1d, 0x3b, 0xd2, + 0x5a, 0xb3, 0x95, 0x7c, 0xd9, 0x30, 0x16, 0xff, + 0x41, 0xa8, 0x8e, 0x67, 0xc2, 0x2b, 0x0d, 0xe4, + 0xd8, 0x31, 0x17, 0xfe, 0x5b, 0xb2, 0x94, 0x7d, + 0xc3, 0x2a, 0x0c, 0xe5, 0x40, 0xa9, 0x8f, 0x66, + 0xee, 0x07, 0x21, 0xc8, 0x6d, 0x84, 0xa2, 0x4b, + 0xf5, 0x1c, 0x3a, 0xd3, 0x76, 0x9f, 0xb9, 0x50, + 0xb4, 0x5d, 0x7b, 0x92, 0x37, 0xde, 0xf8, 0x11, + 0xaf, 0x46, 0x60, 0x89, 0x2c, 0xc5, 0xe3, 0x0a, + 0x82, 0x6b, 0x4d, 0xa4, 0x01, 0xe8, 0xce, 0x27, + 0x99, 0x70, 0x56, 0xbf, 0x1a, 0xf3, 0xd5, 0x3c, + 0xad, 0x44, 0x62, 0x8b, 0x2e, 0xc7, 0xe1, 0x08, + 0xb6, 0x5f, 0x79, 0x90, 0x35, 0xdc, 0xfa, 0x13, + 0x9b, 0x72, 0x54, 0xbd, 0x18, 0xf1, 0xd7, 0x3e, + 0x80, 0x69, 0x4f, 0xa6, 0x03, 0xea, 0xcc, 0x25, + 0xc1, 0x28, 0x0e, 0xe7, 0x42, 0xab, 0x8d, 0x64, + 0xda, 0x33, 0x15, 0xfc, 0x59, 0xb0, 0x96, 0x7f, + 0xf7, 0x1e, 0x38, 0xd1, 0x74, 0x9d, 0xbb, 0x52, + 0xec, 0x05, 0x23, 0xca, 0x6f, 0x86, 0xa0, 0x49, + 0x75, 0x9c, 0xba, 0x53, 0xf6, 0x1f, 0x39, 0xd0, + 0x6e, 0x87, 0xa1, 0x48, 0xed, 0x04, 0x22, 0xcb, + 0x43, 0xaa, 0x8c, 0x65, 0xc0, 0x29, 0x0f, 0xe6, + 0x58, 0xb1, 0x97, 0x7e, 0xdb, 0x32, 0x14, 0xfd, + 0x19, 0xf0, 0xd6, 0x3f, 0x9a, 0x73, 0x55, 0xbc, + 0x02, 0xeb, 0xcd, 0x24, 0x81, 0x68, 0x4e, 0xa7, + 0x2f, 0xc6, 0xe0, 0x09, 0xac, 0x45, 0x63, 0x8a, + 0x34, 0xdd, 0xfb, 0x12, 0xb7, 0x5e, 0x78, 0x91, + }, + { + 0x00, 0xea, 0xc9, 0x23, 0x8f, 0x65, 0x46, 0xac, + 0x03, 0xe9, 0xca, 0x20, 0x8c, 0x66, 0x45, 0xaf, + 0x06, 0xec, 0xcf, 0x25, 0x89, 0x63, 0x40, 0xaa, + 0x05, 0xef, 0xcc, 0x26, 0x8a, 0x60, 0x43, 0xa9, + 0x0c, 0xe6, 0xc5, 0x2f, 0x83, 0x69, 0x4a, 0xa0, + 0x0f, 0xe5, 0xc6, 0x2c, 0x80, 0x6a, 0x49, 0xa3, + 0x0a, 0xe0, 0xc3, 0x29, 0x85, 0x6f, 0x4c, 0xa6, + 0x09, 0xe3, 0xc0, 0x2a, 0x86, 0x6c, 0x4f, 0xa5, + 0x18, 0xf2, 0xd1, 0x3b, 0x97, 0x7d, 0x5e, 0xb4, + 0x1b, 0xf1, 0xd2, 0x38, 0x94, 0x7e, 0x5d, 0xb7, + 0x1e, 0xf4, 0xd7, 0x3d, 0x91, 0x7b, 0x58, 0xb2, + 0x1d, 0xf7, 0xd4, 0x3e, 0x92, 0x78, 0x5b, 0xb1, + 0x14, 0xfe, 0xdd, 0x37, 0x9b, 0x71, 0x52, 0xb8, + 0x17, 0xfd, 0xde, 0x34, 0x98, 0x72, 0x51, 0xbb, + 0x12, 0xf8, 0xdb, 0x31, 0x9d, 0x77, 0x54, 0xbe, + 0x11, 0xfb, 0xd8, 0x32, 0x9e, 0x74, 0x57, 0xbd, + 0x30, 0xda, 0xf9, 0x13, 0xbf, 0x55, 0x76, 0x9c, + 0x33, 0xd9, 0xfa, 0x10, 0xbc, 0x56, 0x75, 0x9f, + 0x36, 0xdc, 0xff, 0x15, 0xb9, 0x53, 0x70, 0x9a, + 0x35, 0xdf, 0xfc, 0x16, 0xba, 0x50, 0x73, 0x99, + 0x3c, 0xd6, 0xf5, 0x1f, 0xb3, 0x59, 0x7a, 0x90, + 0x3f, 0xd5, 0xf6, 0x1c, 0xb0, 0x5a, 0x79, 0x93, + 0x3a, 0xd0, 0xf3, 0x19, 0xb5, 0x5f, 0x7c, 0x96, + 0x39, 0xd3, 0xf0, 0x1a, 0xb6, 0x5c, 0x7f, 0x95, + 0x28, 0xc2, 0xe1, 0x0b, 0xa7, 0x4d, 0x6e, 0x84, + 0x2b, 0xc1, 0xe2, 0x08, 0xa4, 0x4e, 0x6d, 0x87, + 0x2e, 0xc4, 0xe7, 0x0d, 0xa1, 0x4b, 0x68, 0x82, + 0x2d, 0xc7, 0xe4, 0x0e, 0xa2, 0x48, 0x6b, 0x81, + 0x24, 0xce, 0xed, 0x07, 0xab, 0x41, 0x62, 0x88, + 0x27, 0xcd, 0xee, 0x04, 0xa8, 0x42, 0x61, 0x8b, + 0x22, 0xc8, 0xeb, 0x01, 0xad, 0x47, 0x64, 0x8e, + 0x21, 0xcb, 0xe8, 0x02, 0xae, 0x44, 0x67, 0x8d, + }, + { + 0x00, 0xeb, 0xcb, 0x20, 0x8b, 0x60, 0x40, 0xab, + 0x0b, 0xe0, 0xc0, 0x2b, 0x80, 0x6b, 0x4b, 0xa0, + 0x16, 0xfd, 0xdd, 0x36, 0x9d, 0x76, 0x56, 0xbd, + 0x1d, 0xf6, 0xd6, 0x3d, 0x96, 0x7d, 0x5d, 0xb6, + 0x2c, 0xc7, 0xe7, 0x0c, 0xa7, 0x4c, 0x6c, 0x87, + 0x27, 0xcc, 0xec, 0x07, 0xac, 0x47, 0x67, 0x8c, + 0x3a, 0xd1, 0xf1, 0x1a, 0xb1, 0x5a, 0x7a, 0x91, + 0x31, 0xda, 0xfa, 0x11, 0xba, 0x51, 0x71, 0x9a, + 0x58, 0xb3, 0x93, 0x78, 0xd3, 0x38, 0x18, 0xf3, + 0x53, 0xb8, 0x98, 0x73, 0xd8, 0x33, 0x13, 0xf8, + 0x4e, 0xa5, 0x85, 0x6e, 0xc5, 0x2e, 0x0e, 0xe5, + 0x45, 0xae, 0x8e, 0x65, 0xce, 0x25, 0x05, 0xee, + 0x74, 0x9f, 0xbf, 0x54, 0xff, 0x14, 0x34, 0xdf, + 0x7f, 0x94, 0xb4, 0x5f, 0xf4, 0x1f, 0x3f, 0xd4, + 0x62, 0x89, 0xa9, 0x42, 0xe9, 0x02, 0x22, 0xc9, + 0x69, 0x82, 0xa2, 0x49, 0xe2, 0x09, 0x29, 0xc2, + 0xb0, 0x5b, 0x7b, 0x90, 0x3b, 0xd0, 0xf0, 0x1b, + 0xbb, 0x50, 0x70, 0x9b, 0x30, 0xdb, 0xfb, 0x10, + 0xa6, 0x4d, 0x6d, 0x86, 0x2d, 0xc6, 0xe6, 0x0d, + 0xad, 0x46, 0x66, 0x8d, 0x26, 0xcd, 0xed, 0x06, + 0x9c, 0x77, 0x57, 0xbc, 0x17, 0xfc, 0xdc, 0x37, + 0x97, 0x7c, 0x5c, 0xb7, 0x1c, 0xf7, 0xd7, 0x3c, + 0x8a, 0x61, 0x41, 0xaa, 0x01, 0xea, 0xca, 0x21, + 0x81, 0x6a, 0x4a, 0xa1, 0x0a, 0xe1, 0xc1, 0x2a, + 0xe8, 0x03, 0x23, 0xc8, 0x63, 0x88, 0xa8, 0x43, + 0xe3, 0x08, 0x28, 0xc3, 0x68, 0x83, 0xa3, 0x48, + 0xfe, 0x15, 0x35, 0xde, 0x75, 0x9e, 0xbe, 0x55, + 0xf5, 0x1e, 0x3e, 0xd5, 0x7e, 0x95, 0xb5, 0x5e, + 0xc4, 0x2f, 0x0f, 0xe4, 0x4f, 0xa4, 0x84, 0x6f, + 0xcf, 0x24, 0x04, 0xef, 0x44, 0xaf, 0x8f, 0x64, + 0xd2, 0x39, 0x19, 0xf2, 0x59, 0xb2, 0x92, 0x79, + 0xd9, 0x32, 0x12, 0xf9, 0x52, 0xb9, 0x99, 0x72, + }, + { + 0x00, 0xec, 0xc5, 0x29, 0x97, 0x7b, 0x52, 0xbe, + 0x33, 0xdf, 0xf6, 0x1a, 0xa4, 0x48, 0x61, 0x8d, + 0x66, 0x8a, 0xa3, 0x4f, 0xf1, 0x1d, 0x34, 0xd8, + 0x55, 0xb9, 0x90, 0x7c, 0xc2, 0x2e, 0x07, 0xeb, + 0xcc, 0x20, 0x09, 0xe5, 0x5b, 0xb7, 0x9e, 0x72, + 0xff, 0x13, 0x3a, 0xd6, 0x68, 0x84, 0xad, 0x41, + 0xaa, 0x46, 0x6f, 0x83, 0x3d, 0xd1, 0xf8, 0x14, + 0x99, 0x75, 0x5c, 0xb0, 0x0e, 0xe2, 0xcb, 0x27, + 0x85, 0x69, 0x40, 0xac, 0x12, 0xfe, 0xd7, 0x3b, + 0xb6, 0x5a, 0x73, 0x9f, 0x21, 0xcd, 0xe4, 0x08, + 0xe3, 0x0f, 0x26, 0xca, 0x74, 0x98, 0xb1, 0x5d, + 0xd0, 0x3c, 0x15, 0xf9, 0x47, 0xab, 0x82, 0x6e, + 0x49, 0xa5, 0x8c, 0x60, 0xde, 0x32, 0x1b, 0xf7, + 0x7a, 0x96, 0xbf, 0x53, 0xed, 0x01, 0x28, 0xc4, + 0x2f, 0xc3, 0xea, 0x06, 0xb8, 0x54, 0x7d, 0x91, + 0x1c, 0xf0, 0xd9, 0x35, 0x8b, 0x67, 0x4e, 0xa2, + 0x17, 0xfb, 0xd2, 0x3e, 0x80, 0x6c, 0x45, 0xa9, + 0x24, 0xc8, 0xe1, 0x0d, 0xb3, 0x5f, 0x76, 0x9a, + 0x71, 0x9d, 0xb4, 0x58, 0xe6, 0x0a, 0x23, 0xcf, + 0x42, 0xae, 0x87, 0x6b, 0xd5, 0x39, 0x10, 0xfc, + 0xdb, 0x37, 0x1e, 0xf2, 0x4c, 0xa0, 0x89, 0x65, + 0xe8, 0x04, 0x2d, 0xc1, 0x7f, 0x93, 0xba, 0x56, + 0xbd, 0x51, 0x78, 0x94, 0x2a, 0xc6, 0xef, 0x03, + 0x8e, 0x62, 0x4b, 0xa7, 0x19, 0xf5, 0xdc, 0x30, + 0x92, 0x7e, 0x57, 0xbb, 0x05, 0xe9, 0xc0, 0x2c, + 0xa1, 0x4d, 0x64, 0x88, 0x36, 0xda, 0xf3, 0x1f, + 0xf4, 0x18, 0x31, 0xdd, 0x63, 0x8f, 0xa6, 0x4a, + 0xc7, 0x2b, 0x02, 0xee, 0x50, 0xbc, 0x95, 0x79, + 0x5e, 0xb2, 0x9b, 0x77, 0xc9, 0x25, 0x0c, 0xe0, + 0x6d, 0x81, 0xa8, 0x44, 0xfa, 0x16, 0x3f, 0xd3, + 0x38, 0xd4, 0xfd, 0x11, 0xaf, 0x43, 0x6a, 0x86, + 0x0b, 0xe7, 0xce, 0x22, 0x9c, 0x70, 0x59, 0xb5, + }, + { + 0x00, 0xed, 0xc7, 0x2a, 0x93, 0x7e, 0x54, 0xb9, + 0x3b, 0xd6, 0xfc, 0x11, 0xa8, 0x45, 0x6f, 0x82, + 0x76, 0x9b, 0xb1, 0x5c, 0xe5, 0x08, 0x22, 0xcf, + 0x4d, 0xa0, 0x8a, 0x67, 0xde, 0x33, 0x19, 0xf4, + 0xec, 0x01, 0x2b, 0xc6, 0x7f, 0x92, 0xb8, 0x55, + 0xd7, 0x3a, 0x10, 0xfd, 0x44, 0xa9, 0x83, 0x6e, + 0x9a, 0x77, 0x5d, 0xb0, 0x09, 0xe4, 0xce, 0x23, + 0xa1, 0x4c, 0x66, 0x8b, 0x32, 0xdf, 0xf5, 0x18, + 0xc5, 0x28, 0x02, 0xef, 0x56, 0xbb, 0x91, 0x7c, + 0xfe, 0x13, 0x39, 0xd4, 0x6d, 0x80, 0xaa, 0x47, + 0xb3, 0x5e, 0x74, 0x99, 0x20, 0xcd, 0xe7, 0x0a, + 0x88, 0x65, 0x4f, 0xa2, 0x1b, 0xf6, 0xdc, 0x31, + 0x29, 0xc4, 0xee, 0x03, 0xba, 0x57, 0x7d, 0x90, + 0x12, 0xff, 0xd5, 0x38, 0x81, 0x6c, 0x46, 0xab, + 0x5f, 0xb2, 0x98, 0x75, 0xcc, 0x21, 0x0b, 0xe6, + 0x64, 0x89, 0xa3, 0x4e, 0xf7, 0x1a, 0x30, 0xdd, + 0x97, 0x7a, 0x50, 0xbd, 0x04, 0xe9, 0xc3, 0x2e, + 0xac, 0x41, 0x6b, 0x86, 0x3f, 0xd2, 0xf8, 0x15, + 0xe1, 0x0c, 0x26, 0xcb, 0x72, 0x9f, 0xb5, 0x58, + 0xda, 0x37, 0x1d, 0xf0, 0x49, 0xa4, 0x8e, 0x63, + 0x7b, 0x96, 0xbc, 0x51, 0xe8, 0x05, 0x2f, 0xc2, + 0x40, 0xad, 0x87, 0x6a, 0xd3, 0x3e, 0x14, 0xf9, + 0x0d, 0xe0, 0xca, 0x27, 0x9e, 0x73, 0x59, 0xb4, + 0x36, 0xdb, 0xf1, 0x1c, 0xa5, 0x48, 0x62, 0x8f, + 0x52, 0xbf, 0x95, 0x78, 0xc1, 0x2c, 0x06, 0xeb, + 0x69, 0x84, 0xae, 0x43, 0xfa, 0x17, 0x3d, 0xd0, + 0x24, 0xc9, 0xe3, 0x0e, 0xb7, 0x5a, 0x70, 0x9d, + 0x1f, 0xf2, 0xd8, 0x35, 0x8c, 0x61, 0x4b, 0xa6, + 0xbe, 0x53, 0x79, 0x94, 0x2d, 0xc0, 0xea, 0x07, + 0x85, 0x68, 0x42, 0xaf, 0x16, 0xfb, 0xd1, 0x3c, + 0xc8, 0x25, 0x0f, 0xe2, 0x5b, 0xb6, 0x9c, 0x71, + 0xf3, 0x1e, 0x34, 0xd9, 0x60, 0x8d, 0xa7, 0x4a, + }, + { + 0x00, 0xee, 0xc1, 0x2f, 0x9f, 0x71, 0x5e, 0xb0, + 0x23, 0xcd, 0xe2, 0x0c, 0xbc, 0x52, 0x7d, 0x93, + 0x46, 0xa8, 0x87, 0x69, 0xd9, 0x37, 0x18, 0xf6, + 0x65, 0x8b, 0xa4, 0x4a, 0xfa, 0x14, 0x3b, 0xd5, + 0x8c, 0x62, 0x4d, 0xa3, 0x13, 0xfd, 0xd2, 0x3c, + 0xaf, 0x41, 0x6e, 0x80, 0x30, 0xde, 0xf1, 0x1f, + 0xca, 0x24, 0x0b, 0xe5, 0x55, 0xbb, 0x94, 0x7a, + 0xe9, 0x07, 0x28, 0xc6, 0x76, 0x98, 0xb7, 0x59, + 0x05, 0xeb, 0xc4, 0x2a, 0x9a, 0x74, 0x5b, 0xb5, + 0x26, 0xc8, 0xe7, 0x09, 0xb9, 0x57, 0x78, 0x96, + 0x43, 0xad, 0x82, 0x6c, 0xdc, 0x32, 0x1d, 0xf3, + 0x60, 0x8e, 0xa1, 0x4f, 0xff, 0x11, 0x3e, 0xd0, + 0x89, 0x67, 0x48, 0xa6, 0x16, 0xf8, 0xd7, 0x39, + 0xaa, 0x44, 0x6b, 0x85, 0x35, 0xdb, 0xf4, 0x1a, + 0xcf, 0x21, 0x0e, 0xe0, 0x50, 0xbe, 0x91, 0x7f, + 0xec, 0x02, 0x2d, 0xc3, 0x73, 0x9d, 0xb2, 0x5c, + 0x0a, 0xe4, 0xcb, 0x25, 0x95, 0x7b, 0x54, 0xba, + 0x29, 0xc7, 0xe8, 0x06, 0xb6, 0x58, 0x77, 0x99, + 0x4c, 0xa2, 0x8d, 0x63, 0xd3, 0x3d, 0x12, 0xfc, + 0x6f, 0x81, 0xae, 0x40, 0xf0, 0x1e, 0x31, 0xdf, + 0x86, 0x68, 0x47, 0xa9, 0x19, 0xf7, 0xd8, 0x36, + 0xa5, 0x4b, 0x64, 0x8a, 0x3a, 0xd4, 0xfb, 0x15, + 0xc0, 0x2e, 0x01, 0xef, 0x5f, 0xb1, 0x9e, 0x70, + 0xe3, 0x0d, 0x22, 0xcc, 0x7c, 0x92, 0xbd, 0x53, + 0x0f, 0xe1, 0xce, 0x20, 0x90, 0x7e, 0x51, 0xbf, + 0x2c, 0xc2, 0xed, 0x03, 0xb3, 0x5d, 0x72, 0x9c, + 0x49, 0xa7, 0x88, 0x66, 0xd6, 0x38, 0x17, 0xf9, + 0x6a, 0x84, 0xab, 0x45, 0xf5, 0x1b, 0x34, 0xda, + 0x83, 0x6d, 0x42, 0xac, 0x1c, 0xf2, 0xdd, 0x33, + 0xa0, 0x4e, 0x61, 0x8f, 0x3f, 0xd1, 0xfe, 0x10, + 0xc5, 0x2b, 0x04, 0xea, 0x5a, 0xb4, 0x9b, 0x75, + 0xe6, 0x08, 0x27, 0xc9, 0x79, 0x97, 0xb8, 0x56, + }, + { + 0x00, 0xef, 0xc3, 0x2c, 0x9b, 0x74, 0x58, 0xb7, + 0x2b, 0xc4, 0xe8, 0x07, 0xb0, 0x5f, 0x73, 0x9c, + 0x56, 0xb9, 0x95, 0x7a, 0xcd, 0x22, 0x0e, 0xe1, + 0x7d, 0x92, 0xbe, 0x51, 0xe6, 0x09, 0x25, 0xca, + 0xac, 0x43, 0x6f, 0x80, 0x37, 0xd8, 0xf4, 0x1b, + 0x87, 0x68, 0x44, 0xab, 0x1c, 0xf3, 0xdf, 0x30, + 0xfa, 0x15, 0x39, 0xd6, 0x61, 0x8e, 0xa2, 0x4d, + 0xd1, 0x3e, 0x12, 0xfd, 0x4a, 0xa5, 0x89, 0x66, + 0x45, 0xaa, 0x86, 0x69, 0xde, 0x31, 0x1d, 0xf2, + 0x6e, 0x81, 0xad, 0x42, 0xf5, 0x1a, 0x36, 0xd9, + 0x13, 0xfc, 0xd0, 0x3f, 0x88, 0x67, 0x4b, 0xa4, + 0x38, 0xd7, 0xfb, 0x14, 0xa3, 0x4c, 0x60, 0x8f, + 0xe9, 0x06, 0x2a, 0xc5, 0x72, 0x9d, 0xb1, 0x5e, + 0xc2, 0x2d, 0x01, 0xee, 0x59, 0xb6, 0x9a, 0x75, + 0xbf, 0x50, 0x7c, 0x93, 0x24, 0xcb, 0xe7, 0x08, + 0x94, 0x7b, 0x57, 0xb8, 0x0f, 0xe0, 0xcc, 0x23, + 0x8a, 0x65, 0x49, 0xa6, 0x11, 0xfe, 0xd2, 0x3d, + 0xa1, 0x4e, 0x62, 0x8d, 0x3a, 0xd5, 0xf9, 0x16, + 0xdc, 0x33, 0x1f, 0xf0, 0x47, 0xa8, 0x84, 0x6b, + 0xf7, 0x18, 0x34, 0xdb, 0x6c, 0x83, 0xaf, 0x40, + 0x26, 0xc9, 0xe5, 0x0a, 0xbd, 0x52, 0x7e, 0x91, + 0x0d, 0xe2, 0xce, 0x21, 0x96, 0x79, 0x55, 0xba, + 0x70, 0x9f, 0xb3, 0x5c, 0xeb, 0x04, 0x28, 0xc7, + 0x5b, 0xb4, 0x98, 0x77, 0xc0, 0x2f, 0x03, 0xec, + 0xcf, 0x20, 0x0c, 0xe3, 0x54, 0xbb, 0x97, 0x78, + 0xe4, 0x0b, 0x27, 0xc8, 0x7f, 0x90, 0xbc, 0x53, + 0x99, 0x76, 0x5a, 0xb5, 0x02, 0xed, 0xc1, 0x2e, + 0xb2, 0x5d, 0x71, 0x9e, 0x29, 0xc6, 0xea, 0x05, + 0x63, 0x8c, 0xa0, 0x4f, 0xf8, 0x17, 0x3b, 0xd4, + 0x48, 0xa7, 0x8b, 0x64, 0xd3, 0x3c, 0x10, 0xff, + 0x35, 0xda, 0xf6, 0x19, 0xae, 0x41, 0x6d, 0x82, + 0x1e, 0xf1, 0xdd, 0x32, 0x85, 0x6a, 0x46, 0xa9, + }, + { + 0x00, 0xf0, 0xfd, 0x0d, 0xe7, 0x17, 0x1a, 0xea, + 0xd3, 0x23, 0x2e, 0xde, 0x34, 0xc4, 0xc9, 0x39, + 0xbb, 0x4b, 0x46, 0xb6, 0x5c, 0xac, 0xa1, 0x51, + 0x68, 0x98, 0x95, 0x65, 0x8f, 0x7f, 0x72, 0x82, + 0x6b, 0x9b, 0x96, 0x66, 0x8c, 0x7c, 0x71, 0x81, + 0xb8, 0x48, 0x45, 0xb5, 0x5f, 0xaf, 0xa2, 0x52, + 0xd0, 0x20, 0x2d, 0xdd, 0x37, 0xc7, 0xca, 0x3a, + 0x03, 0xf3, 0xfe, 0x0e, 0xe4, 0x14, 0x19, 0xe9, + 0xd6, 0x26, 0x2b, 0xdb, 0x31, 0xc1, 0xcc, 0x3c, + 0x05, 0xf5, 0xf8, 0x08, 0xe2, 0x12, 0x1f, 0xef, + 0x6d, 0x9d, 0x90, 0x60, 0x8a, 0x7a, 0x77, 0x87, + 0xbe, 0x4e, 0x43, 0xb3, 0x59, 0xa9, 0xa4, 0x54, + 0xbd, 0x4d, 0x40, 0xb0, 0x5a, 0xaa, 0xa7, 0x57, + 0x6e, 0x9e, 0x93, 0x63, 0x89, 0x79, 0x74, 0x84, + 0x06, 0xf6, 0xfb, 0x0b, 0xe1, 0x11, 0x1c, 0xec, + 0xd5, 0x25, 0x28, 0xd8, 0x32, 0xc2, 0xcf, 0x3f, + 0xb1, 0x41, 0x4c, 0xbc, 0x56, 0xa6, 0xab, 0x5b, + 0x62, 0x92, 0x9f, 0x6f, 0x85, 0x75, 0x78, 0x88, + 0x0a, 0xfa, 0xf7, 0x07, 0xed, 0x1d, 0x10, 0xe0, + 0xd9, 0x29, 0x24, 0xd4, 0x3e, 0xce, 0xc3, 0x33, + 0xda, 0x2a, 0x27, 0xd7, 0x3d, 0xcd, 0xc0, 0x30, + 0x09, 0xf9, 0xf4, 0x04, 0xee, 0x1e, 0x13, 0xe3, + 0x61, 0x91, 0x9c, 0x6c, 0x86, 0x76, 0x7b, 0x8b, + 0xb2, 0x42, 0x4f, 0xbf, 0x55, 0xa5, 0xa8, 0x58, + 0x67, 0x97, 0x9a, 0x6a, 0x80, 0x70, 0x7d, 0x8d, + 0xb4, 0x44, 0x49, 0xb9, 0x53, 0xa3, 0xae, 0x5e, + 0xdc, 0x2c, 0x21, 0xd1, 0x3b, 0xcb, 0xc6, 0x36, + 0x0f, 0xff, 0xf2, 0x02, 0xe8, 0x18, 0x15, 0xe5, + 0x0c, 0xfc, 0xf1, 0x01, 0xeb, 0x1b, 0x16, 0xe6, + 0xdf, 0x2f, 0x22, 0xd2, 0x38, 0xc8, 0xc5, 0x35, + 0xb7, 0x47, 0x4a, 0xba, 0x50, 0xa0, 0xad, 0x5d, + 0x64, 0x94, 0x99, 0x69, 0x83, 0x73, 0x7e, 0x8e, + }, + { + 0x00, 0xf1, 0xff, 0x0e, 0xe3, 0x12, 0x1c, 0xed, + 0xdb, 0x2a, 0x24, 0xd5, 0x38, 0xc9, 0xc7, 0x36, + 0xab, 0x5a, 0x54, 0xa5, 0x48, 0xb9, 0xb7, 0x46, + 0x70, 0x81, 0x8f, 0x7e, 0x93, 0x62, 0x6c, 0x9d, + 0x4b, 0xba, 0xb4, 0x45, 0xa8, 0x59, 0x57, 0xa6, + 0x90, 0x61, 0x6f, 0x9e, 0x73, 0x82, 0x8c, 0x7d, + 0xe0, 0x11, 0x1f, 0xee, 0x03, 0xf2, 0xfc, 0x0d, + 0x3b, 0xca, 0xc4, 0x35, 0xd8, 0x29, 0x27, 0xd6, + 0x96, 0x67, 0x69, 0x98, 0x75, 0x84, 0x8a, 0x7b, + 0x4d, 0xbc, 0xb2, 0x43, 0xae, 0x5f, 0x51, 0xa0, + 0x3d, 0xcc, 0xc2, 0x33, 0xde, 0x2f, 0x21, 0xd0, + 0xe6, 0x17, 0x19, 0xe8, 0x05, 0xf4, 0xfa, 0x0b, + 0xdd, 0x2c, 0x22, 0xd3, 0x3e, 0xcf, 0xc1, 0x30, + 0x06, 0xf7, 0xf9, 0x08, 0xe5, 0x14, 0x1a, 0xeb, + 0x76, 0x87, 0x89, 0x78, 0x95, 0x64, 0x6a, 0x9b, + 0xad, 0x5c, 0x52, 0xa3, 0x4e, 0xbf, 0xb1, 0x40, + 0x31, 0xc0, 0xce, 0x3f, 0xd2, 0x23, 0x2d, 0xdc, + 0xea, 0x1b, 0x15, 0xe4, 0x09, 0xf8, 0xf6, 0x07, + 0x9a, 0x6b, 0x65, 0x94, 0x79, 0x88, 0x86, 0x77, + 0x41, 0xb0, 0xbe, 0x4f, 0xa2, 0x53, 0x5d, 0xac, + 0x7a, 0x8b, 0x85, 0x74, 0x99, 0x68, 0x66, 0x97, + 0xa1, 0x50, 0x5e, 0xaf, 0x42, 0xb3, 0xbd, 0x4c, + 0xd1, 0x20, 0x2e, 0xdf, 0x32, 0xc3, 0xcd, 0x3c, + 0x0a, 0xfb, 0xf5, 0x04, 0xe9, 0x18, 0x16, 0xe7, + 0xa7, 0x56, 0x58, 0xa9, 0x44, 0xb5, 0xbb, 0x4a, + 0x7c, 0x8d, 0x83, 0x72, 0x9f, 0x6e, 0x60, 0x91, + 0x0c, 0xfd, 0xf3, 0x02, 0xef, 0x1e, 0x10, 0xe1, + 0xd7, 0x26, 0x28, 0xd9, 0x34, 0xc5, 0xcb, 0x3a, + 0xec, 0x1d, 0x13, 0xe2, 0x0f, 0xfe, 0xf0, 0x01, + 0x37, 0xc6, 0xc8, 0x39, 0xd4, 0x25, 0x2b, 0xda, + 0x47, 0xb6, 0xb8, 0x49, 0xa4, 0x55, 0x5b, 0xaa, + 0x9c, 0x6d, 0x63, 0x92, 0x7f, 0x8e, 0x80, 0x71, + }, + { + 0x00, 0xf2, 0xf9, 0x0b, 0xef, 0x1d, 0x16, 0xe4, + 0xc3, 0x31, 0x3a, 0xc8, 0x2c, 0xde, 0xd5, 0x27, + 0x9b, 0x69, 0x62, 0x90, 0x74, 0x86, 0x8d, 0x7f, + 0x58, 0xaa, 0xa1, 0x53, 0xb7, 0x45, 0x4e, 0xbc, + 0x2b, 0xd9, 0xd2, 0x20, 0xc4, 0x36, 0x3d, 0xcf, + 0xe8, 0x1a, 0x11, 0xe3, 0x07, 0xf5, 0xfe, 0x0c, + 0xb0, 0x42, 0x49, 0xbb, 0x5f, 0xad, 0xa6, 0x54, + 0x73, 0x81, 0x8a, 0x78, 0x9c, 0x6e, 0x65, 0x97, + 0x56, 0xa4, 0xaf, 0x5d, 0xb9, 0x4b, 0x40, 0xb2, + 0x95, 0x67, 0x6c, 0x9e, 0x7a, 0x88, 0x83, 0x71, + 0xcd, 0x3f, 0x34, 0xc6, 0x22, 0xd0, 0xdb, 0x29, + 0x0e, 0xfc, 0xf7, 0x05, 0xe1, 0x13, 0x18, 0xea, + 0x7d, 0x8f, 0x84, 0x76, 0x92, 0x60, 0x6b, 0x99, + 0xbe, 0x4c, 0x47, 0xb5, 0x51, 0xa3, 0xa8, 0x5a, + 0xe6, 0x14, 0x1f, 0xed, 0x09, 0xfb, 0xf0, 0x02, + 0x25, 0xd7, 0xdc, 0x2e, 0xca, 0x38, 0x33, 0xc1, + 0xac, 0x5e, 0x55, 0xa7, 0x43, 0xb1, 0xba, 0x48, + 0x6f, 0x9d, 0x96, 0x64, 0x80, 0x72, 0x79, 0x8b, + 0x37, 0xc5, 0xce, 0x3c, 0xd8, 0x2a, 0x21, 0xd3, + 0xf4, 0x06, 0x0d, 0xff, 0x1b, 0xe9, 0xe2, 0x10, + 0x87, 0x75, 0x7e, 0x8c, 0x68, 0x9a, 0x91, 0x63, + 0x44, 0xb6, 0xbd, 0x4f, 0xab, 0x59, 0x52, 0xa0, + 0x1c, 0xee, 0xe5, 0x17, 0xf3, 0x01, 0x0a, 0xf8, + 0xdf, 0x2d, 0x26, 0xd4, 0x30, 0xc2, 0xc9, 0x3b, + 0xfa, 0x08, 0x03, 0xf1, 0x15, 0xe7, 0xec, 0x1e, + 0x39, 0xcb, 0xc0, 0x32, 0xd6, 0x24, 0x2f, 0xdd, + 0x61, 0x93, 0x98, 0x6a, 0x8e, 0x7c, 0x77, 0x85, + 0xa2, 0x50, 0x5b, 0xa9, 0x4d, 0xbf, 0xb4, 0x46, + 0xd1, 0x23, 0x28, 0xda, 0x3e, 0xcc, 0xc7, 0x35, + 0x12, 0xe0, 0xeb, 0x19, 0xfd, 0x0f, 0x04, 0xf6, + 0x4a, 0xb8, 0xb3, 0x41, 0xa5, 0x57, 0x5c, 0xae, + 0x89, 0x7b, 0x70, 0x82, 0x66, 0x94, 0x9f, 0x6d, + }, + { + 0x00, 0xf3, 0xfb, 0x08, 0xeb, 0x18, 0x10, 0xe3, + 0xcb, 0x38, 0x30, 0xc3, 0x20, 0xd3, 0xdb, 0x28, + 0x8b, 0x78, 0x70, 0x83, 0x60, 0x93, 0x9b, 0x68, + 0x40, 0xb3, 0xbb, 0x48, 0xab, 0x58, 0x50, 0xa3, + 0x0b, 0xf8, 0xf0, 0x03, 0xe0, 0x13, 0x1b, 0xe8, + 0xc0, 0x33, 0x3b, 0xc8, 0x2b, 0xd8, 0xd0, 0x23, + 0x80, 0x73, 0x7b, 0x88, 0x6b, 0x98, 0x90, 0x63, + 0x4b, 0xb8, 0xb0, 0x43, 0xa0, 0x53, 0x5b, 0xa8, + 0x16, 0xe5, 0xed, 0x1e, 0xfd, 0x0e, 0x06, 0xf5, + 0xdd, 0x2e, 0x26, 0xd5, 0x36, 0xc5, 0xcd, 0x3e, + 0x9d, 0x6e, 0x66, 0x95, 0x76, 0x85, 0x8d, 0x7e, + 0x56, 0xa5, 0xad, 0x5e, 0xbd, 0x4e, 0x46, 0xb5, + 0x1d, 0xee, 0xe6, 0x15, 0xf6, 0x05, 0x0d, 0xfe, + 0xd6, 0x25, 0x2d, 0xde, 0x3d, 0xce, 0xc6, 0x35, + 0x96, 0x65, 0x6d, 0x9e, 0x7d, 0x8e, 0x86, 0x75, + 0x5d, 0xae, 0xa6, 0x55, 0xb6, 0x45, 0x4d, 0xbe, + 0x2c, 0xdf, 0xd7, 0x24, 0xc7, 0x34, 0x3c, 0xcf, + 0xe7, 0x14, 0x1c, 0xef, 0x0c, 0xff, 0xf7, 0x04, + 0xa7, 0x54, 0x5c, 0xaf, 0x4c, 0xbf, 0xb7, 0x44, + 0x6c, 0x9f, 0x97, 0x64, 0x87, 0x74, 0x7c, 0x8f, + 0x27, 0xd4, 0xdc, 0x2f, 0xcc, 0x3f, 0x37, 0xc4, + 0xec, 0x1f, 0x17, 0xe4, 0x07, 0xf4, 0xfc, 0x0f, + 0xac, 0x5f, 0x57, 0xa4, 0x47, 0xb4, 0xbc, 0x4f, + 0x67, 0x94, 0x9c, 0x6f, 0x8c, 0x7f, 0x77, 0x84, + 0x3a, 0xc9, 0xc1, 0x32, 0xd1, 0x22, 0x2a, 0xd9, + 0xf1, 0x02, 0x0a, 0xf9, 0x1a, 0xe9, 0xe1, 0x12, + 0xb1, 0x42, 0x4a, 0xb9, 0x5a, 0xa9, 0xa1, 0x52, + 0x7a, 0x89, 0x81, 0x72, 0x91, 0x62, 0x6a, 0x99, + 0x31, 0xc2, 0xca, 0x39, 0xda, 0x29, 0x21, 0xd2, + 0xfa, 0x09, 0x01, 0xf2, 0x11, 0xe2, 0xea, 0x19, + 0xba, 0x49, 0x41, 0xb2, 0x51, 0xa2, 0xaa, 0x59, + 0x71, 0x82, 0x8a, 0x79, 0x9a, 0x69, 0x61, 0x92, + }, + { + 0x00, 0xf4, 0xf5, 0x01, 0xf7, 0x03, 0x02, 0xf6, + 0xf3, 0x07, 0x06, 0xf2, 0x04, 0xf0, 0xf1, 0x05, + 0xfb, 0x0f, 0x0e, 0xfa, 0x0c, 0xf8, 0xf9, 0x0d, + 0x08, 0xfc, 0xfd, 0x09, 0xff, 0x0b, 0x0a, 0xfe, + 0xeb, 0x1f, 0x1e, 0xea, 0x1c, 0xe8, 0xe9, 0x1d, + 0x18, 0xec, 0xed, 0x19, 0xef, 0x1b, 0x1a, 0xee, + 0x10, 0xe4, 0xe5, 0x11, 0xe7, 0x13, 0x12, 0xe6, + 0xe3, 0x17, 0x16, 0xe2, 0x14, 0xe0, 0xe1, 0x15, + 0xcb, 0x3f, 0x3e, 0xca, 0x3c, 0xc8, 0xc9, 0x3d, + 0x38, 0xcc, 0xcd, 0x39, 0xcf, 0x3b, 0x3a, 0xce, + 0x30, 0xc4, 0xc5, 0x31, 0xc7, 0x33, 0x32, 0xc6, + 0xc3, 0x37, 0x36, 0xc2, 0x34, 0xc0, 0xc1, 0x35, + 0x20, 0xd4, 0xd5, 0x21, 0xd7, 0x23, 0x22, 0xd6, + 0xd3, 0x27, 0x26, 0xd2, 0x24, 0xd0, 0xd1, 0x25, + 0xdb, 0x2f, 0x2e, 0xda, 0x2c, 0xd8, 0xd9, 0x2d, + 0x28, 0xdc, 0xdd, 0x29, 0xdf, 0x2b, 0x2a, 0xde, + 0x8b, 0x7f, 0x7e, 0x8a, 0x7c, 0x88, 0x89, 0x7d, + 0x78, 0x8c, 0x8d, 0x79, 0x8f, 0x7b, 0x7a, 0x8e, + 0x70, 0x84, 0x85, 0x71, 0x87, 0x73, 0x72, 0x86, + 0x83, 0x77, 0x76, 0x82, 0x74, 0x80, 0x81, 0x75, + 0x60, 0x94, 0x95, 0x61, 0x97, 0x63, 0x62, 0x96, + 0x93, 0x67, 0x66, 0x92, 0x64, 0x90, 0x91, 0x65, + 0x9b, 0x6f, 0x6e, 0x9a, 0x6c, 0x98, 0x99, 0x6d, + 0x68, 0x9c, 0x9d, 0x69, 0x9f, 0x6b, 0x6a, 0x9e, + 0x40, 0xb4, 0xb5, 0x41, 0xb7, 0x43, 0x42, 0xb6, + 0xb3, 0x47, 0x46, 0xb2, 0x44, 0xb0, 0xb1, 0x45, + 0xbb, 0x4f, 0x4e, 0xba, 0x4c, 0xb8, 0xb9, 0x4d, + 0x48, 0xbc, 0xbd, 0x49, 0xbf, 0x4b, 0x4a, 0xbe, + 0xab, 0x5f, 0x5e, 0xaa, 0x5c, 0xa8, 0xa9, 0x5d, + 0x58, 0xac, 0xad, 0x59, 0xaf, 0x5b, 0x5a, 0xae, + 0x50, 0xa4, 0xa5, 0x51, 0xa7, 0x53, 0x52, 0xa6, + 0xa3, 0x57, 0x56, 0xa2, 0x54, 0xa0, 0xa1, 0x55, + }, + { + 0x00, 0xf5, 0xf7, 0x02, 0xf3, 0x06, 0x04, 0xf1, + 0xfb, 0x0e, 0x0c, 0xf9, 0x08, 0xfd, 0xff, 0x0a, + 0xeb, 0x1e, 0x1c, 0xe9, 0x18, 0xed, 0xef, 0x1a, + 0x10, 0xe5, 0xe7, 0x12, 0xe3, 0x16, 0x14, 0xe1, + 0xcb, 0x3e, 0x3c, 0xc9, 0x38, 0xcd, 0xcf, 0x3a, + 0x30, 0xc5, 0xc7, 0x32, 0xc3, 0x36, 0x34, 0xc1, + 0x20, 0xd5, 0xd7, 0x22, 0xd3, 0x26, 0x24, 0xd1, + 0xdb, 0x2e, 0x2c, 0xd9, 0x28, 0xdd, 0xdf, 0x2a, + 0x8b, 0x7e, 0x7c, 0x89, 0x78, 0x8d, 0x8f, 0x7a, + 0x70, 0x85, 0x87, 0x72, 0x83, 0x76, 0x74, 0x81, + 0x60, 0x95, 0x97, 0x62, 0x93, 0x66, 0x64, 0x91, + 0x9b, 0x6e, 0x6c, 0x99, 0x68, 0x9d, 0x9f, 0x6a, + 0x40, 0xb5, 0xb7, 0x42, 0xb3, 0x46, 0x44, 0xb1, + 0xbb, 0x4e, 0x4c, 0xb9, 0x48, 0xbd, 0xbf, 0x4a, + 0xab, 0x5e, 0x5c, 0xa9, 0x58, 0xad, 0xaf, 0x5a, + 0x50, 0xa5, 0xa7, 0x52, 0xa3, 0x56, 0x54, 0xa1, + 0x0b, 0xfe, 0xfc, 0x09, 0xf8, 0x0d, 0x0f, 0xfa, + 0xf0, 0x05, 0x07, 0xf2, 0x03, 0xf6, 0xf4, 0x01, + 0xe0, 0x15, 0x17, 0xe2, 0x13, 0xe6, 0xe4, 0x11, + 0x1b, 0xee, 0xec, 0x19, 0xe8, 0x1d, 0x1f, 0xea, + 0xc0, 0x35, 0x37, 0xc2, 0x33, 0xc6, 0xc4, 0x31, + 0x3b, 0xce, 0xcc, 0x39, 0xc8, 0x3d, 0x3f, 0xca, + 0x2b, 0xde, 0xdc, 0x29, 0xd8, 0x2d, 0x2f, 0xda, + 0xd0, 0x25, 0x27, 0xd2, 0x23, 0xd6, 0xd4, 0x21, + 0x80, 0x75, 0x77, 0x82, 0x73, 0x86, 0x84, 0x71, + 0x7b, 0x8e, 0x8c, 0x79, 0x88, 0x7d, 0x7f, 0x8a, + 0x6b, 0x9e, 0x9c, 0x69, 0x98, 0x6d, 0x6f, 0x9a, + 0x90, 0x65, 0x67, 0x92, 0x63, 0x96, 0x94, 0x61, + 0x4b, 0xbe, 0xbc, 0x49, 0xb8, 0x4d, 0x4f, 0xba, + 0xb0, 0x45, 0x47, 0xb2, 0x43, 0xb6, 0xb4, 0x41, + 0xa0, 0x55, 0x57, 0xa2, 0x53, 0xa6, 0xa4, 0x51, + 0x5b, 0xae, 0xac, 0x59, 0xa8, 0x5d, 0x5f, 0xaa, + }, + { + 0x00, 0xf6, 0xf1, 0x07, 0xff, 0x09, 0x0e, 0xf8, + 0xe3, 0x15, 0x12, 0xe4, 0x1c, 0xea, 0xed, 0x1b, + 0xdb, 0x2d, 0x2a, 0xdc, 0x24, 0xd2, 0xd5, 0x23, + 0x38, 0xce, 0xc9, 0x3f, 0xc7, 0x31, 0x36, 0xc0, + 0xab, 0x5d, 0x5a, 0xac, 0x54, 0xa2, 0xa5, 0x53, + 0x48, 0xbe, 0xb9, 0x4f, 0xb7, 0x41, 0x46, 0xb0, + 0x70, 0x86, 0x81, 0x77, 0x8f, 0x79, 0x7e, 0x88, + 0x93, 0x65, 0x62, 0x94, 0x6c, 0x9a, 0x9d, 0x6b, + 0x4b, 0xbd, 0xba, 0x4c, 0xb4, 0x42, 0x45, 0xb3, + 0xa8, 0x5e, 0x59, 0xaf, 0x57, 0xa1, 0xa6, 0x50, + 0x90, 0x66, 0x61, 0x97, 0x6f, 0x99, 0x9e, 0x68, + 0x73, 0x85, 0x82, 0x74, 0x8c, 0x7a, 0x7d, 0x8b, + 0xe0, 0x16, 0x11, 0xe7, 0x1f, 0xe9, 0xee, 0x18, + 0x03, 0xf5, 0xf2, 0x04, 0xfc, 0x0a, 0x0d, 0xfb, + 0x3b, 0xcd, 0xca, 0x3c, 0xc4, 0x32, 0x35, 0xc3, + 0xd8, 0x2e, 0x29, 0xdf, 0x27, 0xd1, 0xd6, 0x20, + 0x96, 0x60, 0x67, 0x91, 0x69, 0x9f, 0x98, 0x6e, + 0x75, 0x83, 0x84, 0x72, 0x8a, 0x7c, 0x7b, 0x8d, + 0x4d, 0xbb, 0xbc, 0x4a, 0xb2, 0x44, 0x43, 0xb5, + 0xae, 0x58, 0x5f, 0xa9, 0x51, 0xa7, 0xa0, 0x56, + 0x3d, 0xcb, 0xcc, 0x3a, 0xc2, 0x34, 0x33, 0xc5, + 0xde, 0x28, 0x2f, 0xd9, 0x21, 0xd7, 0xd0, 0x26, + 0xe6, 0x10, 0x17, 0xe1, 0x19, 0xef, 0xe8, 0x1e, + 0x05, 0xf3, 0xf4, 0x02, 0xfa, 0x0c, 0x0b, 0xfd, + 0xdd, 0x2b, 0x2c, 0xda, 0x22, 0xd4, 0xd3, 0x25, + 0x3e, 0xc8, 0xcf, 0x39, 0xc1, 0x37, 0x30, 0xc6, + 0x06, 0xf0, 0xf7, 0x01, 0xf9, 0x0f, 0x08, 0xfe, + 0xe5, 0x13, 0x14, 0xe2, 0x1a, 0xec, 0xeb, 0x1d, + 0x76, 0x80, 0x87, 0x71, 0x89, 0x7f, 0x78, 0x8e, + 0x95, 0x63, 0x64, 0x92, 0x6a, 0x9c, 0x9b, 0x6d, + 0xad, 0x5b, 0x5c, 0xaa, 0x52, 0xa4, 0xa3, 0x55, + 0x4e, 0xb8, 0xbf, 0x49, 0xb1, 0x47, 0x40, 0xb6, + }, + { + 0x00, 0xf7, 0xf3, 0x04, 0xfb, 0x0c, 0x08, 0xff, + 0xeb, 0x1c, 0x18, 0xef, 0x10, 0xe7, 0xe3, 0x14, + 0xcb, 0x3c, 0x38, 0xcf, 0x30, 0xc7, 0xc3, 0x34, + 0x20, 0xd7, 0xd3, 0x24, 0xdb, 0x2c, 0x28, 0xdf, + 0x8b, 0x7c, 0x78, 0x8f, 0x70, 0x87, 0x83, 0x74, + 0x60, 0x97, 0x93, 0x64, 0x9b, 0x6c, 0x68, 0x9f, + 0x40, 0xb7, 0xb3, 0x44, 0xbb, 0x4c, 0x48, 0xbf, + 0xab, 0x5c, 0x58, 0xaf, 0x50, 0xa7, 0xa3, 0x54, + 0x0b, 0xfc, 0xf8, 0x0f, 0xf0, 0x07, 0x03, 0xf4, + 0xe0, 0x17, 0x13, 0xe4, 0x1b, 0xec, 0xe8, 0x1f, + 0xc0, 0x37, 0x33, 0xc4, 0x3b, 0xcc, 0xc8, 0x3f, + 0x2b, 0xdc, 0xd8, 0x2f, 0xd0, 0x27, 0x23, 0xd4, + 0x80, 0x77, 0x73, 0x84, 0x7b, 0x8c, 0x88, 0x7f, + 0x6b, 0x9c, 0x98, 0x6f, 0x90, 0x67, 0x63, 0x94, + 0x4b, 0xbc, 0xb8, 0x4f, 0xb0, 0x47, 0x43, 0xb4, + 0xa0, 0x57, 0x53, 0xa4, 0x5b, 0xac, 0xa8, 0x5f, + 0x16, 0xe1, 0xe5, 0x12, 0xed, 0x1a, 0x1e, 0xe9, + 0xfd, 0x0a, 0x0e, 0xf9, 0x06, 0xf1, 0xf5, 0x02, + 0xdd, 0x2a, 0x2e, 0xd9, 0x26, 0xd1, 0xd5, 0x22, + 0x36, 0xc1, 0xc5, 0x32, 0xcd, 0x3a, 0x3e, 0xc9, + 0x9d, 0x6a, 0x6e, 0x99, 0x66, 0x91, 0x95, 0x62, + 0x76, 0x81, 0x85, 0x72, 0x8d, 0x7a, 0x7e, 0x89, + 0x56, 0xa1, 0xa5, 0x52, 0xad, 0x5a, 0x5e, 0xa9, + 0xbd, 0x4a, 0x4e, 0xb9, 0x46, 0xb1, 0xb5, 0x42, + 0x1d, 0xea, 0xee, 0x19, 0xe6, 0x11, 0x15, 0xe2, + 0xf6, 0x01, 0x05, 0xf2, 0x0d, 0xfa, 0xfe, 0x09, + 0xd6, 0x21, 0x25, 0xd2, 0x2d, 0xda, 0xde, 0x29, + 0x3d, 0xca, 0xce, 0x39, 0xc6, 0x31, 0x35, 0xc2, + 0x96, 0x61, 0x65, 0x92, 0x6d, 0x9a, 0x9e, 0x69, + 0x7d, 0x8a, 0x8e, 0x79, 0x86, 0x71, 0x75, 0x82, + 0x5d, 0xaa, 0xae, 0x59, 0xa6, 0x51, 0x55, 0xa2, + 0xb6, 0x41, 0x45, 0xb2, 0x4d, 0xba, 0xbe, 0x49, + }, + { + 0x00, 0xf8, 0xed, 0x15, 0xc7, 0x3f, 0x2a, 0xd2, + 0x93, 0x6b, 0x7e, 0x86, 0x54, 0xac, 0xb9, 0x41, + 0x3b, 0xc3, 0xd6, 0x2e, 0xfc, 0x04, 0x11, 0xe9, + 0xa8, 0x50, 0x45, 0xbd, 0x6f, 0x97, 0x82, 0x7a, + 0x76, 0x8e, 0x9b, 0x63, 0xb1, 0x49, 0x5c, 0xa4, + 0xe5, 0x1d, 0x08, 0xf0, 0x22, 0xda, 0xcf, 0x37, + 0x4d, 0xb5, 0xa0, 0x58, 0x8a, 0x72, 0x67, 0x9f, + 0xde, 0x26, 0x33, 0xcb, 0x19, 0xe1, 0xf4, 0x0c, + 0xec, 0x14, 0x01, 0xf9, 0x2b, 0xd3, 0xc6, 0x3e, + 0x7f, 0x87, 0x92, 0x6a, 0xb8, 0x40, 0x55, 0xad, + 0xd7, 0x2f, 0x3a, 0xc2, 0x10, 0xe8, 0xfd, 0x05, + 0x44, 0xbc, 0xa9, 0x51, 0x83, 0x7b, 0x6e, 0x96, + 0x9a, 0x62, 0x77, 0x8f, 0x5d, 0xa5, 0xb0, 0x48, + 0x09, 0xf1, 0xe4, 0x1c, 0xce, 0x36, 0x23, 0xdb, + 0xa1, 0x59, 0x4c, 0xb4, 0x66, 0x9e, 0x8b, 0x73, + 0x32, 0xca, 0xdf, 0x27, 0xf5, 0x0d, 0x18, 0xe0, + 0xc5, 0x3d, 0x28, 0xd0, 0x02, 0xfa, 0xef, 0x17, + 0x56, 0xae, 0xbb, 0x43, 0x91, 0x69, 0x7c, 0x84, + 0xfe, 0x06, 0x13, 0xeb, 0x39, 0xc1, 0xd4, 0x2c, + 0x6d, 0x95, 0x80, 0x78, 0xaa, 0x52, 0x47, 0xbf, + 0xb3, 0x4b, 0x5e, 0xa6, 0x74, 0x8c, 0x99, 0x61, + 0x20, 0xd8, 0xcd, 0x35, 0xe7, 0x1f, 0x0a, 0xf2, + 0x88, 0x70, 0x65, 0x9d, 0x4f, 0xb7, 0xa2, 0x5a, + 0x1b, 0xe3, 0xf6, 0x0e, 0xdc, 0x24, 0x31, 0xc9, + 0x29, 0xd1, 0xc4, 0x3c, 0xee, 0x16, 0x03, 0xfb, + 0xba, 0x42, 0x57, 0xaf, 0x7d, 0x85, 0x90, 0x68, + 0x12, 0xea, 0xff, 0x07, 0xd5, 0x2d, 0x38, 0xc0, + 0x81, 0x79, 0x6c, 0x94, 0x46, 0xbe, 0xab, 0x53, + 0x5f, 0xa7, 0xb2, 0x4a, 0x98, 0x60, 0x75, 0x8d, + 0xcc, 0x34, 0x21, 0xd9, 0x0b, 0xf3, 0xe6, 0x1e, + 0x64, 0x9c, 0x89, 0x71, 0xa3, 0x5b, 0x4e, 0xb6, + 0xf7, 0x0f, 0x1a, 0xe2, 0x30, 0xc8, 0xdd, 0x25, + }, + { + 0x00, 0xf9, 0xef, 0x16, 0xc3, 0x3a, 0x2c, 0xd5, + 0x9b, 0x62, 0x74, 0x8d, 0x58, 0xa1, 0xb7, 0x4e, + 0x2b, 0xd2, 0xc4, 0x3d, 0xe8, 0x11, 0x07, 0xfe, + 0xb0, 0x49, 0x5f, 0xa6, 0x73, 0x8a, 0x9c, 0x65, + 0x56, 0xaf, 0xb9, 0x40, 0x95, 0x6c, 0x7a, 0x83, + 0xcd, 0x34, 0x22, 0xdb, 0x0e, 0xf7, 0xe1, 0x18, + 0x7d, 0x84, 0x92, 0x6b, 0xbe, 0x47, 0x51, 0xa8, + 0xe6, 0x1f, 0x09, 0xf0, 0x25, 0xdc, 0xca, 0x33, + 0xac, 0x55, 0x43, 0xba, 0x6f, 0x96, 0x80, 0x79, + 0x37, 0xce, 0xd8, 0x21, 0xf4, 0x0d, 0x1b, 0xe2, + 0x87, 0x7e, 0x68, 0x91, 0x44, 0xbd, 0xab, 0x52, + 0x1c, 0xe5, 0xf3, 0x0a, 0xdf, 0x26, 0x30, 0xc9, + 0xfa, 0x03, 0x15, 0xec, 0x39, 0xc0, 0xd6, 0x2f, + 0x61, 0x98, 0x8e, 0x77, 0xa2, 0x5b, 0x4d, 0xb4, + 0xd1, 0x28, 0x3e, 0xc7, 0x12, 0xeb, 0xfd, 0x04, + 0x4a, 0xb3, 0xa5, 0x5c, 0x89, 0x70, 0x66, 0x9f, + 0x45, 0xbc, 0xaa, 0x53, 0x86, 0x7f, 0x69, 0x90, + 0xde, 0x27, 0x31, 0xc8, 0x1d, 0xe4, 0xf2, 0x0b, + 0x6e, 0x97, 0x81, 0x78, 0xad, 0x54, 0x42, 0xbb, + 0xf5, 0x0c, 0x1a, 0xe3, 0x36, 0xcf, 0xd9, 0x20, + 0x13, 0xea, 0xfc, 0x05, 0xd0, 0x29, 0x3f, 0xc6, + 0x88, 0x71, 0x67, 0x9e, 0x4b, 0xb2, 0xa4, 0x5d, + 0x38, 0xc1, 0xd7, 0x2e, 0xfb, 0x02, 0x14, 0xed, + 0xa3, 0x5a, 0x4c, 0xb5, 0x60, 0x99, 0x8f, 0x76, + 0xe9, 0x10, 0x06, 0xff, 0x2a, 0xd3, 0xc5, 0x3c, + 0x72, 0x8b, 0x9d, 0x64, 0xb1, 0x48, 0x5e, 0xa7, + 0xc2, 0x3b, 0x2d, 0xd4, 0x01, 0xf8, 0xee, 0x17, + 0x59, 0xa0, 0xb6, 0x4f, 0x9a, 0x63, 0x75, 0x8c, + 0xbf, 0x46, 0x50, 0xa9, 0x7c, 0x85, 0x93, 0x6a, + 0x24, 0xdd, 0xcb, 0x32, 0xe7, 0x1e, 0x08, 0xf1, + 0x94, 0x6d, 0x7b, 0x82, 0x57, 0xae, 0xb8, 0x41, + 0x0f, 0xf6, 0xe0, 0x19, 0xcc, 0x35, 0x23, 0xda, + }, + { + 0x00, 0xfa, 0xe9, 0x13, 0xcf, 0x35, 0x26, 0xdc, + 0x83, 0x79, 0x6a, 0x90, 0x4c, 0xb6, 0xa5, 0x5f, + 0x1b, 0xe1, 0xf2, 0x08, 0xd4, 0x2e, 0x3d, 0xc7, + 0x98, 0x62, 0x71, 0x8b, 0x57, 0xad, 0xbe, 0x44, + 0x36, 0xcc, 0xdf, 0x25, 0xf9, 0x03, 0x10, 0xea, + 0xb5, 0x4f, 0x5c, 0xa6, 0x7a, 0x80, 0x93, 0x69, + 0x2d, 0xd7, 0xc4, 0x3e, 0xe2, 0x18, 0x0b, 0xf1, + 0xae, 0x54, 0x47, 0xbd, 0x61, 0x9b, 0x88, 0x72, + 0x6c, 0x96, 0x85, 0x7f, 0xa3, 0x59, 0x4a, 0xb0, + 0xef, 0x15, 0x06, 0xfc, 0x20, 0xda, 0xc9, 0x33, + 0x77, 0x8d, 0x9e, 0x64, 0xb8, 0x42, 0x51, 0xab, + 0xf4, 0x0e, 0x1d, 0xe7, 0x3b, 0xc1, 0xd2, 0x28, + 0x5a, 0xa0, 0xb3, 0x49, 0x95, 0x6f, 0x7c, 0x86, + 0xd9, 0x23, 0x30, 0xca, 0x16, 0xec, 0xff, 0x05, + 0x41, 0xbb, 0xa8, 0x52, 0x8e, 0x74, 0x67, 0x9d, + 0xc2, 0x38, 0x2b, 0xd1, 0x0d, 0xf7, 0xe4, 0x1e, + 0xd8, 0x22, 0x31, 0xcb, 0x17, 0xed, 0xfe, 0x04, + 0x5b, 0xa1, 0xb2, 0x48, 0x94, 0x6e, 0x7d, 0x87, + 0xc3, 0x39, 0x2a, 0xd0, 0x0c, 0xf6, 0xe5, 0x1f, + 0x40, 0xba, 0xa9, 0x53, 0x8f, 0x75, 0x66, 0x9c, + 0xee, 0x14, 0x07, 0xfd, 0x21, 0xdb, 0xc8, 0x32, + 0x6d, 0x97, 0x84, 0x7e, 0xa2, 0x58, 0x4b, 0xb1, + 0xf5, 0x0f, 0x1c, 0xe6, 0x3a, 0xc0, 0xd3, 0x29, + 0x76, 0x8c, 0x9f, 0x65, 0xb9, 0x43, 0x50, 0xaa, + 0xb4, 0x4e, 0x5d, 0xa7, 0x7b, 0x81, 0x92, 0x68, + 0x37, 0xcd, 0xde, 0x24, 0xf8, 0x02, 0x11, 0xeb, + 0xaf, 0x55, 0x46, 0xbc, 0x60, 0x9a, 0x89, 0x73, + 0x2c, 0xd6, 0xc5, 0x3f, 0xe3, 0x19, 0x0a, 0xf0, + 0x82, 0x78, 0x6b, 0x91, 0x4d, 0xb7, 0xa4, 0x5e, + 0x01, 0xfb, 0xe8, 0x12, 0xce, 0x34, 0x27, 0xdd, + 0x99, 0x63, 0x70, 0x8a, 0x56, 0xac, 0xbf, 0x45, + 0x1a, 0xe0, 0xf3, 0x09, 0xd5, 0x2f, 0x3c, 0xc6, + }, + { + 0x00, 0xfb, 0xeb, 0x10, 0xcb, 0x30, 0x20, 0xdb, + 0x8b, 0x70, 0x60, 0x9b, 0x40, 0xbb, 0xab, 0x50, + 0x0b, 0xf0, 0xe0, 0x1b, 0xc0, 0x3b, 0x2b, 0xd0, + 0x80, 0x7b, 0x6b, 0x90, 0x4b, 0xb0, 0xa0, 0x5b, + 0x16, 0xed, 0xfd, 0x06, 0xdd, 0x26, 0x36, 0xcd, + 0x9d, 0x66, 0x76, 0x8d, 0x56, 0xad, 0xbd, 0x46, + 0x1d, 0xe6, 0xf6, 0x0d, 0xd6, 0x2d, 0x3d, 0xc6, + 0x96, 0x6d, 0x7d, 0x86, 0x5d, 0xa6, 0xb6, 0x4d, + 0x2c, 0xd7, 0xc7, 0x3c, 0xe7, 0x1c, 0x0c, 0xf7, + 0xa7, 0x5c, 0x4c, 0xb7, 0x6c, 0x97, 0x87, 0x7c, + 0x27, 0xdc, 0xcc, 0x37, 0xec, 0x17, 0x07, 0xfc, + 0xac, 0x57, 0x47, 0xbc, 0x67, 0x9c, 0x8c, 0x77, + 0x3a, 0xc1, 0xd1, 0x2a, 0xf1, 0x0a, 0x1a, 0xe1, + 0xb1, 0x4a, 0x5a, 0xa1, 0x7a, 0x81, 0x91, 0x6a, + 0x31, 0xca, 0xda, 0x21, 0xfa, 0x01, 0x11, 0xea, + 0xba, 0x41, 0x51, 0xaa, 0x71, 0x8a, 0x9a, 0x61, + 0x58, 0xa3, 0xb3, 0x48, 0x93, 0x68, 0x78, 0x83, + 0xd3, 0x28, 0x38, 0xc3, 0x18, 0xe3, 0xf3, 0x08, + 0x53, 0xa8, 0xb8, 0x43, 0x98, 0x63, 0x73, 0x88, + 0xd8, 0x23, 0x33, 0xc8, 0x13, 0xe8, 0xf8, 0x03, + 0x4e, 0xb5, 0xa5, 0x5e, 0x85, 0x7e, 0x6e, 0x95, + 0xc5, 0x3e, 0x2e, 0xd5, 0x0e, 0xf5, 0xe5, 0x1e, + 0x45, 0xbe, 0xae, 0x55, 0x8e, 0x75, 0x65, 0x9e, + 0xce, 0x35, 0x25, 0xde, 0x05, 0xfe, 0xee, 0x15, + 0x74, 0x8f, 0x9f, 0x64, 0xbf, 0x44, 0x54, 0xaf, + 0xff, 0x04, 0x14, 0xef, 0x34, 0xcf, 0xdf, 0x24, + 0x7f, 0x84, 0x94, 0x6f, 0xb4, 0x4f, 0x5f, 0xa4, + 0xf4, 0x0f, 0x1f, 0xe4, 0x3f, 0xc4, 0xd4, 0x2f, + 0x62, 0x99, 0x89, 0x72, 0xa9, 0x52, 0x42, 0xb9, + 0xe9, 0x12, 0x02, 0xf9, 0x22, 0xd9, 0xc9, 0x32, + 0x69, 0x92, 0x82, 0x79, 0xa2, 0x59, 0x49, 0xb2, + 0xe2, 0x19, 0x09, 0xf2, 0x29, 0xd2, 0xc2, 0x39, + }, + { + 0x00, 0xfc, 0xe5, 0x19, 0xd7, 0x2b, 0x32, 0xce, + 0xb3, 0x4f, 0x56, 0xaa, 0x64, 0x98, 0x81, 0x7d, + 0x7b, 0x87, 0x9e, 0x62, 0xac, 0x50, 0x49, 0xb5, + 0xc8, 0x34, 0x2d, 0xd1, 0x1f, 0xe3, 0xfa, 0x06, + 0xf6, 0x0a, 0x13, 0xef, 0x21, 0xdd, 0xc4, 0x38, + 0x45, 0xb9, 0xa0, 0x5c, 0x92, 0x6e, 0x77, 0x8b, + 0x8d, 0x71, 0x68, 0x94, 0x5a, 0xa6, 0xbf, 0x43, + 0x3e, 0xc2, 0xdb, 0x27, 0xe9, 0x15, 0x0c, 0xf0, + 0xf1, 0x0d, 0x14, 0xe8, 0x26, 0xda, 0xc3, 0x3f, + 0x42, 0xbe, 0xa7, 0x5b, 0x95, 0x69, 0x70, 0x8c, + 0x8a, 0x76, 0x6f, 0x93, 0x5d, 0xa1, 0xb8, 0x44, + 0x39, 0xc5, 0xdc, 0x20, 0xee, 0x12, 0x0b, 0xf7, + 0x07, 0xfb, 0xe2, 0x1e, 0xd0, 0x2c, 0x35, 0xc9, + 0xb4, 0x48, 0x51, 0xad, 0x63, 0x9f, 0x86, 0x7a, + 0x7c, 0x80, 0x99, 0x65, 0xab, 0x57, 0x4e, 0xb2, + 0xcf, 0x33, 0x2a, 0xd6, 0x18, 0xe4, 0xfd, 0x01, + 0xff, 0x03, 0x1a, 0xe6, 0x28, 0xd4, 0xcd, 0x31, + 0x4c, 0xb0, 0xa9, 0x55, 0x9b, 0x67, 0x7e, 0x82, + 0x84, 0x78, 0x61, 0x9d, 0x53, 0xaf, 0xb6, 0x4a, + 0x37, 0xcb, 0xd2, 0x2e, 0xe0, 0x1c, 0x05, 0xf9, + 0x09, 0xf5, 0xec, 0x10, 0xde, 0x22, 0x3b, 0xc7, + 0xba, 0x46, 0x5f, 0xa3, 0x6d, 0x91, 0x88, 0x74, + 0x72, 0x8e, 0x97, 0x6b, 0xa5, 0x59, 0x40, 0xbc, + 0xc1, 0x3d, 0x24, 0xd8, 0x16, 0xea, 0xf3, 0x0f, + 0x0e, 0xf2, 0xeb, 0x17, 0xd9, 0x25, 0x3c, 0xc0, + 0xbd, 0x41, 0x58, 0xa4, 0x6a, 0x96, 0x8f, 0x73, + 0x75, 0x89, 0x90, 0x6c, 0xa2, 0x5e, 0x47, 0xbb, + 0xc6, 0x3a, 0x23, 0xdf, 0x11, 0xed, 0xf4, 0x08, + 0xf8, 0x04, 0x1d, 0xe1, 0x2f, 0xd3, 0xca, 0x36, + 0x4b, 0xb7, 0xae, 0x52, 0x9c, 0x60, 0x79, 0x85, + 0x83, 0x7f, 0x66, 0x9a, 0x54, 0xa8, 0xb1, 0x4d, + 0x30, 0xcc, 0xd5, 0x29, 0xe7, 0x1b, 0x02, 0xfe, + }, + { + 0x00, 0xfd, 0xe7, 0x1a, 0xd3, 0x2e, 0x34, 0xc9, + 0xbb, 0x46, 0x5c, 0xa1, 0x68, 0x95, 0x8f, 0x72, + 0x6b, 0x96, 0x8c, 0x71, 0xb8, 0x45, 0x5f, 0xa2, + 0xd0, 0x2d, 0x37, 0xca, 0x03, 0xfe, 0xe4, 0x19, + 0xd6, 0x2b, 0x31, 0xcc, 0x05, 0xf8, 0xe2, 0x1f, + 0x6d, 0x90, 0x8a, 0x77, 0xbe, 0x43, 0x59, 0xa4, + 0xbd, 0x40, 0x5a, 0xa7, 0x6e, 0x93, 0x89, 0x74, + 0x06, 0xfb, 0xe1, 0x1c, 0xd5, 0x28, 0x32, 0xcf, + 0xb1, 0x4c, 0x56, 0xab, 0x62, 0x9f, 0x85, 0x78, + 0x0a, 0xf7, 0xed, 0x10, 0xd9, 0x24, 0x3e, 0xc3, + 0xda, 0x27, 0x3d, 0xc0, 0x09, 0xf4, 0xee, 0x13, + 0x61, 0x9c, 0x86, 0x7b, 0xb2, 0x4f, 0x55, 0xa8, + 0x67, 0x9a, 0x80, 0x7d, 0xb4, 0x49, 0x53, 0xae, + 0xdc, 0x21, 0x3b, 0xc6, 0x0f, 0xf2, 0xe8, 0x15, + 0x0c, 0xf1, 0xeb, 0x16, 0xdf, 0x22, 0x38, 0xc5, + 0xb7, 0x4a, 0x50, 0xad, 0x64, 0x99, 0x83, 0x7e, + 0x7f, 0x82, 0x98, 0x65, 0xac, 0x51, 0x4b, 0xb6, + 0xc4, 0x39, 0x23, 0xde, 0x17, 0xea, 0xf0, 0x0d, + 0x14, 0xe9, 0xf3, 0x0e, 0xc7, 0x3a, 0x20, 0xdd, + 0xaf, 0x52, 0x48, 0xb5, 0x7c, 0x81, 0x9b, 0x66, + 0xa9, 0x54, 0x4e, 0xb3, 0x7a, 0x87, 0x9d, 0x60, + 0x12, 0xef, 0xf5, 0x08, 0xc1, 0x3c, 0x26, 0xdb, + 0xc2, 0x3f, 0x25, 0xd8, 0x11, 0xec, 0xf6, 0x0b, + 0x79, 0x84, 0x9e, 0x63, 0xaa, 0x57, 0x4d, 0xb0, + 0xce, 0x33, 0x29, 0xd4, 0x1d, 0xe0, 0xfa, 0x07, + 0x75, 0x88, 0x92, 0x6f, 0xa6, 0x5b, 0x41, 0xbc, + 0xa5, 0x58, 0x42, 0xbf, 0x76, 0x8b, 0x91, 0x6c, + 0x1e, 0xe3, 0xf9, 0x04, 0xcd, 0x30, 0x2a, 0xd7, + 0x18, 0xe5, 0xff, 0x02, 0xcb, 0x36, 0x2c, 0xd1, + 0xa3, 0x5e, 0x44, 0xb9, 0x70, 0x8d, 0x97, 0x6a, + 0x73, 0x8e, 0x94, 0x69, 0xa0, 0x5d, 0x47, 0xba, + 0xc8, 0x35, 0x2f, 0xd2, 0x1b, 0xe6, 0xfc, 0x01, + }, + { + 0x00, 0xfe, 0xe1, 0x1f, 0xdf, 0x21, 0x3e, 0xc0, + 0xa3, 0x5d, 0x42, 0xbc, 0x7c, 0x82, 0x9d, 0x63, + 0x5b, 0xa5, 0xba, 0x44, 0x84, 0x7a, 0x65, 0x9b, + 0xf8, 0x06, 0x19, 0xe7, 0x27, 0xd9, 0xc6, 0x38, + 0xb6, 0x48, 0x57, 0xa9, 0x69, 0x97, 0x88, 0x76, + 0x15, 0xeb, 0xf4, 0x0a, 0xca, 0x34, 0x2b, 0xd5, + 0xed, 0x13, 0x0c, 0xf2, 0x32, 0xcc, 0xd3, 0x2d, + 0x4e, 0xb0, 0xaf, 0x51, 0x91, 0x6f, 0x70, 0x8e, + 0x71, 0x8f, 0x90, 0x6e, 0xae, 0x50, 0x4f, 0xb1, + 0xd2, 0x2c, 0x33, 0xcd, 0x0d, 0xf3, 0xec, 0x12, + 0x2a, 0xd4, 0xcb, 0x35, 0xf5, 0x0b, 0x14, 0xea, + 0x89, 0x77, 0x68, 0x96, 0x56, 0xa8, 0xb7, 0x49, + 0xc7, 0x39, 0x26, 0xd8, 0x18, 0xe6, 0xf9, 0x07, + 0x64, 0x9a, 0x85, 0x7b, 0xbb, 0x45, 0x5a, 0xa4, + 0x9c, 0x62, 0x7d, 0x83, 0x43, 0xbd, 0xa2, 0x5c, + 0x3f, 0xc1, 0xde, 0x20, 0xe0, 0x1e, 0x01, 0xff, + 0xe2, 0x1c, 0x03, 0xfd, 0x3d, 0xc3, 0xdc, 0x22, + 0x41, 0xbf, 0xa0, 0x5e, 0x9e, 0x60, 0x7f, 0x81, + 0xb9, 0x47, 0x58, 0xa6, 0x66, 0x98, 0x87, 0x79, + 0x1a, 0xe4, 0xfb, 0x05, 0xc5, 0x3b, 0x24, 0xda, + 0x54, 0xaa, 0xb5, 0x4b, 0x8b, 0x75, 0x6a, 0x94, + 0xf7, 0x09, 0x16, 0xe8, 0x28, 0xd6, 0xc9, 0x37, + 0x0f, 0xf1, 0xee, 0x10, 0xd0, 0x2e, 0x31, 0xcf, + 0xac, 0x52, 0x4d, 0xb3, 0x73, 0x8d, 0x92, 0x6c, + 0x93, 0x6d, 0x72, 0x8c, 0x4c, 0xb2, 0xad, 0x53, + 0x30, 0xce, 0xd1, 0x2f, 0xef, 0x11, 0x0e, 0xf0, + 0xc8, 0x36, 0x29, 0xd7, 0x17, 0xe9, 0xf6, 0x08, + 0x6b, 0x95, 0x8a, 0x74, 0xb4, 0x4a, 0x55, 0xab, + 0x25, 0xdb, 0xc4, 0x3a, 0xfa, 0x04, 0x1b, 0xe5, + 0x86, 0x78, 0x67, 0x99, 0x59, 0xa7, 0xb8, 0x46, + 0x7e, 0x80, 0x9f, 0x61, 0xa1, 0x5f, 0x40, 0xbe, + 0xdd, 0x23, 0x3c, 0xc2, 0x02, 0xfc, 0xe3, 0x1d, + }, + { + 0x00, 0xff, 0xe3, 0x1c, 0xdb, 0x24, 0x38, 0xc7, + 0xab, 0x54, 0x48, 0xb7, 0x70, 0x8f, 0x93, 0x6c, + 0x4b, 0xb4, 0xa8, 0x57, 0x90, 0x6f, 0x73, 0x8c, + 0xe0, 0x1f, 0x03, 0xfc, 0x3b, 0xc4, 0xd8, 0x27, + 0x96, 0x69, 0x75, 0x8a, 0x4d, 0xb2, 0xae, 0x51, + 0x3d, 0xc2, 0xde, 0x21, 0xe6, 0x19, 0x05, 0xfa, + 0xdd, 0x22, 0x3e, 0xc1, 0x06, 0xf9, 0xe5, 0x1a, + 0x76, 0x89, 0x95, 0x6a, 0xad, 0x52, 0x4e, 0xb1, + 0x31, 0xce, 0xd2, 0x2d, 0xea, 0x15, 0x09, 0xf6, + 0x9a, 0x65, 0x79, 0x86, 0x41, 0xbe, 0xa2, 0x5d, + 0x7a, 0x85, 0x99, 0x66, 0xa1, 0x5e, 0x42, 0xbd, + 0xd1, 0x2e, 0x32, 0xcd, 0x0a, 0xf5, 0xe9, 0x16, + 0xa7, 0x58, 0x44, 0xbb, 0x7c, 0x83, 0x9f, 0x60, + 0x0c, 0xf3, 0xef, 0x10, 0xd7, 0x28, 0x34, 0xcb, + 0xec, 0x13, 0x0f, 0xf0, 0x37, 0xc8, 0xd4, 0x2b, + 0x47, 0xb8, 0xa4, 0x5b, 0x9c, 0x63, 0x7f, 0x80, + 0x62, 0x9d, 0x81, 0x7e, 0xb9, 0x46, 0x5a, 0xa5, + 0xc9, 0x36, 0x2a, 0xd5, 0x12, 0xed, 0xf1, 0x0e, + 0x29, 0xd6, 0xca, 0x35, 0xf2, 0x0d, 0x11, 0xee, + 0x82, 0x7d, 0x61, 0x9e, 0x59, 0xa6, 0xba, 0x45, + 0xf4, 0x0b, 0x17, 0xe8, 0x2f, 0xd0, 0xcc, 0x33, + 0x5f, 0xa0, 0xbc, 0x43, 0x84, 0x7b, 0x67, 0x98, + 0xbf, 0x40, 0x5c, 0xa3, 0x64, 0x9b, 0x87, 0x78, + 0x14, 0xeb, 0xf7, 0x08, 0xcf, 0x30, 0x2c, 0xd3, + 0x53, 0xac, 0xb0, 0x4f, 0x88, 0x77, 0x6b, 0x94, + 0xf8, 0x07, 0x1b, 0xe4, 0x23, 0xdc, 0xc0, 0x3f, + 0x18, 0xe7, 0xfb, 0x04, 0xc3, 0x3c, 0x20, 0xdf, + 0xb3, 0x4c, 0x50, 0xaf, 0x68, 0x97, 0x8b, 0x74, + 0xc5, 0x3a, 0x26, 0xd9, 0x1e, 0xe1, 0xfd, 0x02, + 0x6e, 0x91, 0x8d, 0x72, 0xb5, 0x4a, 0x56, 0xa9, + 0x8e, 0x71, 0x6d, 0x92, 0x55, 0xaa, 0xb6, 0x49, + 0x25, 0xda, 0xc6, 0x39, 0xfe, 0x01, 0x1d, 0xe2, + }, +}; + +const uint8_t __aligned(256) raid_gfexp[256] = +{ + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, + 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26, + 0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, + 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, + 0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, + 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23, + 0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, + 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1, + 0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, + 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0, + 0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, + 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2, + 0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, + 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce, + 0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, + 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc, + 0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, + 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54, + 0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, + 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73, + 0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, + 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff, + 0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, + 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41, + 0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, + 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6, + 0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, + 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09, + 0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, + 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16, + 0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, + 0x1b, 0x36, 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x01, +}; + +const uint8_t __aligned(256) raid_gfinv[256] = +{ + /* note that the first element is not significative */ + 0x00, 0x01, 0x8e, 0xf4, 0x47, 0xa7, 0x7a, 0xba, + 0xad, 0x9d, 0xdd, 0x98, 0x3d, 0xaa, 0x5d, 0x96, + 0xd8, 0x72, 0xc0, 0x58, 0xe0, 0x3e, 0x4c, 0x66, + 0x90, 0xde, 0x55, 0x80, 0xa0, 0x83, 0x4b, 0x2a, + 0x6c, 0xed, 0x39, 0x51, 0x60, 0x56, 0x2c, 0x8a, + 0x70, 0xd0, 0x1f, 0x4a, 0x26, 0x8b, 0x33, 0x6e, + 0x48, 0x89, 0x6f, 0x2e, 0xa4, 0xc3, 0x40, 0x5e, + 0x50, 0x22, 0xcf, 0xa9, 0xab, 0x0c, 0x15, 0xe1, + 0x36, 0x5f, 0xf8, 0xd5, 0x92, 0x4e, 0xa6, 0x04, + 0x30, 0x88, 0x2b, 0x1e, 0x16, 0x67, 0x45, 0x93, + 0x38, 0x23, 0x68, 0x8c, 0x81, 0x1a, 0x25, 0x61, + 0x13, 0xc1, 0xcb, 0x63, 0x97, 0x0e, 0x37, 0x41, + 0x24, 0x57, 0xca, 0x5b, 0xb9, 0xc4, 0x17, 0x4d, + 0x52, 0x8d, 0xef, 0xb3, 0x20, 0xec, 0x2f, 0x32, + 0x28, 0xd1, 0x11, 0xd9, 0xe9, 0xfb, 0xda, 0x79, + 0xdb, 0x77, 0x06, 0xbb, 0x84, 0xcd, 0xfe, 0xfc, + 0x1b, 0x54, 0xa1, 0x1d, 0x7c, 0xcc, 0xe4, 0xb0, + 0x49, 0x31, 0x27, 0x2d, 0x53, 0x69, 0x02, 0xf5, + 0x18, 0xdf, 0x44, 0x4f, 0x9b, 0xbc, 0x0f, 0x5c, + 0x0b, 0xdc, 0xbd, 0x94, 0xac, 0x09, 0xc7, 0xa2, + 0x1c, 0x82, 0x9f, 0xc6, 0x34, 0xc2, 0x46, 0x05, + 0xce, 0x3b, 0x0d, 0x3c, 0x9c, 0x08, 0xbe, 0xb7, + 0x87, 0xe5, 0xee, 0x6b, 0xeb, 0xf2, 0xbf, 0xaf, + 0xc5, 0x64, 0x07, 0x7b, 0x95, 0x9a, 0xae, 0xb6, + 0x12, 0x59, 0xa5, 0x35, 0x65, 0xb8, 0xa3, 0x9e, + 0xd2, 0xf7, 0x62, 0x5a, 0x85, 0x7d, 0xa8, 0x3a, + 0x29, 0x71, 0xc8, 0xf6, 0xf9, 0x43, 0xd7, 0xd6, + 0x10, 0x73, 0x76, 0x78, 0x99, 0x0a, 0x19, 0x91, + 0x14, 0x3f, 0xe6, 0xf0, 0x86, 0xb1, 0xe2, 0xf1, + 0xfa, 0x74, 0xf3, 0xb4, 0x6d, 0x21, 0xb2, 0x6a, + 0xe3, 0xe7, 0xb5, 0xea, 0x03, 0x8f, 0xd3, 0xc9, + 0x42, 0xd4, 0xe8, 0x75, 0x7f, 0xff, 0x7e, 0xfd, +}; + +/** + * Power matrix used to generate parity. + * This matrix is valid for up to 3 parity with 251 data disks. + * + * 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + * 01 02 04 08 10 20 40 80 1d 3a 74 e8 cd 87 13 26 4c 98 2d 5a b4 75 ea c9 8f 03 06 0c 18 30 60 c0 9d 27 4e 9c 25 4a 94 35 6a d4 b5 77 ee c1 9f 23 46 8c 05 0a 14 28 50 a0 5d ba 69 d2 b9 6f de a1 5f be 61 c2 99 2f 5e bc 65 ca 89 0f 1e 3c 78 f0 fd e7 d3 bb 6b d6 b1 7f fe e1 df a3 5b b6 71 e2 d9 af 43 86 11 22 44 88 0d 1a 34 68 d0 bd 67 ce 81 1f 3e 7c f8 ed c7 93 3b 76 ec c5 97 33 66 cc 85 17 2e 5c b8 6d da a9 4f 9e 21 42 84 15 2a 54 a8 4d 9a 29 52 a4 55 aa 49 92 39 72 e4 d5 b7 73 e6 d1 bf 63 c6 91 3f 7e fc e5 d7 b3 7b f6 f1 ff e3 db ab 4b 96 31 62 c4 95 37 6e dc a5 57 ae 41 82 19 32 64 c8 8d 07 0e 1c 38 70 e0 dd a7 53 a6 51 a2 59 b2 79 f2 f9 ef c3 9b 2b 56 ac 45 8a 09 12 24 48 90 3d 7a f4 f5 f7 f3 fb eb cb 8b 0b 16 2c 58 b0 7d fa e9 cf 83 1b 36 6c + * 01 8e 47 ad d8 6c 36 1b 83 cf e9 fa 7d b0 58 2c 16 0b 8b cb eb fb f3 f7 f5 f4 7a 3d 90 48 24 12 09 8a 45 ac 56 2b 9b c3 ef f9 f2 79 b2 59 a2 51 a6 53 a7 dd e0 70 38 1c 0e 07 8d c8 64 32 19 82 41 ae 57 a5 dc 6e 37 95 c4 62 31 96 4b ab db e3 ff f1 f6 7b b3 d7 e5 fc 7e 3f 91 c6 63 bf d1 e6 73 b7 d5 e4 72 39 92 49 aa 55 a4 52 29 9a 4d a8 54 2a 15 84 42 21 9e 4f a9 da 6d b8 5c 2e 17 85 cc 66 33 97 c5 ec 76 3b 93 c7 ed f8 7c 3e 1f 81 ce 67 bd d0 68 34 1a 0d 88 44 22 11 86 43 af d9 e2 71 b6 5b a3 df e1 fe 7f b1 d6 6b bb d3 e7 fd f0 78 3c 1e 0f 89 ca 65 bc 5e 2f 99 c2 61 be 5f a1 de 6f b9 d2 69 ba 5d a0 50 28 14 0a 05 8c 46 23 9f c1 ee 77 b5 d4 6a 35 94 4a 25 9c 4e 27 9d c0 60 30 18 0c 06 03 8f c9 ea 75 b4 5a 2d 98 4c 26 13 87 cd e8 74 3a 1d 80 40 20 + */ +const uint8_t __aligned(256) raid_gfvandermonde[3][256] = +{ + { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, + }, + { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, + 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26, + 0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, + 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, + 0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, + 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23, + 0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, + 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1, + 0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, + 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0, + 0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, + 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2, + 0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, + 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce, + 0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, + 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc, + 0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, + 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54, + 0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, + 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73, + 0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, + 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff, + 0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, + 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41, + 0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, + 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6, + 0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, + 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09, + 0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, + 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16, + 0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, + 0x1b, 0x36, 0x6c, + }, + { + 0x01, 0x8e, 0x47, 0xad, 0xd8, 0x6c, 0x36, 0x1b, + 0x83, 0xcf, 0xe9, 0xfa, 0x7d, 0xb0, 0x58, 0x2c, + 0x16, 0x0b, 0x8b, 0xcb, 0xeb, 0xfb, 0xf3, 0xf7, + 0xf5, 0xf4, 0x7a, 0x3d, 0x90, 0x48, 0x24, 0x12, + 0x09, 0x8a, 0x45, 0xac, 0x56, 0x2b, 0x9b, 0xc3, + 0xef, 0xf9, 0xf2, 0x79, 0xb2, 0x59, 0xa2, 0x51, + 0xa6, 0x53, 0xa7, 0xdd, 0xe0, 0x70, 0x38, 0x1c, + 0x0e, 0x07, 0x8d, 0xc8, 0x64, 0x32, 0x19, 0x82, + 0x41, 0xae, 0x57, 0xa5, 0xdc, 0x6e, 0x37, 0x95, + 0xc4, 0x62, 0x31, 0x96, 0x4b, 0xab, 0xdb, 0xe3, + 0xff, 0xf1, 0xf6, 0x7b, 0xb3, 0xd7, 0xe5, 0xfc, + 0x7e, 0x3f, 0x91, 0xc6, 0x63, 0xbf, 0xd1, 0xe6, + 0x73, 0xb7, 0xd5, 0xe4, 0x72, 0x39, 0x92, 0x49, + 0xaa, 0x55, 0xa4, 0x52, 0x29, 0x9a, 0x4d, 0xa8, + 0x54, 0x2a, 0x15, 0x84, 0x42, 0x21, 0x9e, 0x4f, + 0xa9, 0xda, 0x6d, 0xb8, 0x5c, 0x2e, 0x17, 0x85, + 0xcc, 0x66, 0x33, 0x97, 0xc5, 0xec, 0x76, 0x3b, + 0x93, 0xc7, 0xed, 0xf8, 0x7c, 0x3e, 0x1f, 0x81, + 0xce, 0x67, 0xbd, 0xd0, 0x68, 0x34, 0x1a, 0x0d, + 0x88, 0x44, 0x22, 0x11, 0x86, 0x43, 0xaf, 0xd9, + 0xe2, 0x71, 0xb6, 0x5b, 0xa3, 0xdf, 0xe1, 0xfe, + 0x7f, 0xb1, 0xd6, 0x6b, 0xbb, 0xd3, 0xe7, 0xfd, + 0xf0, 0x78, 0x3c, 0x1e, 0x0f, 0x89, 0xca, 0x65, + 0xbc, 0x5e, 0x2f, 0x99, 0xc2, 0x61, 0xbe, 0x5f, + 0xa1, 0xde, 0x6f, 0xb9, 0xd2, 0x69, 0xba, 0x5d, + 0xa0, 0x50, 0x28, 0x14, 0x0a, 0x05, 0x8c, 0x46, + 0x23, 0x9f, 0xc1, 0xee, 0x77, 0xb5, 0xd4, 0x6a, + 0x35, 0x94, 0x4a, 0x25, 0x9c, 0x4e, 0x27, 0x9d, + 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x8f, + 0xc9, 0xea, 0x75, 0xb4, 0x5a, 0x2d, 0x98, 0x4c, + 0x26, 0x13, 0x87, 0xcd, 0xe8, 0x74, 0x3a, 0x1d, + 0x80, 0x40, 0x20, + }, +}; + +/** + * Cauchy matrix used to generate parity. + * This matrix is valid for up to 6 parity with 251 data disks. + * + * 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 + * 01 02 04 08 10 20 40 80 1d 3a 74 e8 cd 87 13 26 4c 98 2d 5a b4 75 ea c9 8f 03 06 0c 18 30 60 c0 9d 27 4e 9c 25 4a 94 35 6a d4 b5 77 ee c1 9f 23 46 8c 05 0a 14 28 50 a0 5d ba 69 d2 b9 6f de a1 5f be 61 c2 99 2f 5e bc 65 ca 89 0f 1e 3c 78 f0 fd e7 d3 bb 6b d6 b1 7f fe e1 df a3 5b b6 71 e2 d9 af 43 86 11 22 44 88 0d 1a 34 68 d0 bd 67 ce 81 1f 3e 7c f8 ed c7 93 3b 76 ec c5 97 33 66 cc 85 17 2e 5c b8 6d da a9 4f 9e 21 42 84 15 2a 54 a8 4d 9a 29 52 a4 55 aa 49 92 39 72 e4 d5 b7 73 e6 d1 bf 63 c6 91 3f 7e fc e5 d7 b3 7b f6 f1 ff e3 db ab 4b 96 31 62 c4 95 37 6e dc a5 57 ae 41 82 19 32 64 c8 8d 07 0e 1c 38 70 e0 dd a7 53 a6 51 a2 59 b2 79 f2 f9 ef c3 9b 2b 56 ac 45 8a 09 12 24 48 90 3d 7a f4 f5 f7 f3 fb eb cb 8b 0b 16 2c 58 b0 7d fa e9 cf 83 1b 36 6c + * 01 f5 d2 c4 9a 71 f1 7f fc 87 c1 c6 19 2f 40 55 3d ba 53 04 9c 61 34 8c 46 68 70 3e cc 7d 74 75 b5 db 0c df 9e 6d 79 eb 63 9f 38 d0 94 a5 24 89 5c 65 5b ae 37 33 4c dd 47 f4 02 a6 39 d8 9d 2d 62 b9 2e 0f 2b 60 58 e4 f8 6c 72 b0 85 4d 95 41 1c 23 05 99 32 c5 0e 82 91 14 d1 af f9 b3 07 97 6e 0b 67 3b 78 e6 28 22 4f a3 ca 48 de 1d a8 17 6f 90 aa 31 5a f3 e9 a9 44 30 56 09 59 6a 42 cd e5 d6 86 d9 bf cb 26 66 7c d5 be 25 1f e0 98 27 92 51 c7 45 2c c0 ad a7 69 f7 b4 e8 84 e1 18 88 3c 76 20 5e 9b 1e 0d 81 4a bd 16 8a ac 93 ce 1a c2 0a 3f fd e3 77 6b d7 ef a4 80 a1 36 ed a2 12 57 b6 29 8d 7b c8 52 c3 bc b8 21 d4 ea d3 06 ab 2a 1b 5f b7 10 ec 64 f6 e2 11 50 83 54 3a fa fb f2 43 b1 ff e7 c9 03 bb ee 13 8b dc 35 b2 da cf a0 96 49 4e 08 73 f0 7e fe 15 4b + * 01 bb a6 d7 c7 07 ce 82 4a 2f a5 9b b6 60 f1 ad e7 f4 06 d2 df 2e ca 65 5c 48 21 aa cd 4e c1 61 38 0a 3e d1 d5 cb 10 dc 5e 24 b8 de 79 36 43 72 d9 f8 f9 a2 a4 6a 3d ea 8e 03 f5 ab b4 5d b5 53 6b 39 86 b0 50 74 96 84 5a 4b e8 49 e5 51 ef 12 bc 89 5b 2b 29 09 c3 57 1e 37 76 0b 64 8a 52 59 80 da a8 44 95 3c 33 e6 7c af 6c b1 9d fc 92 d6 d8 ff a7 77 04 13 73 66 28 7d 83 fb 5f 63 25 19 bd c5 3b 6e 20 35 55 42 31 e1 b9 9e 90 d4 ba db f7 2a e9 3a a0 75 7a d3 02 ee 9c c6 1f 14 cc 22 4d 30 71 58 11 85 4f 6f 6d 1d cf fa 54 a9 17 a3 0f ae 0d 1c c2 d0 32 16 f6 c0 7f 2d 15 f3 1b f2 ed b3 45 c8 ac 7b 2c e2 e4 bf be 9f 34 05 70 3f 98 fe 62 18 9a 56 8d 93 97 78 4c 7e 27 87 08 8b ec 67 0e 1a 23 8c 68 99 94 40 b2 a1 eb b7 26 f0 dd e3 69 0c c4 88 41 81 91 e0 fd + * 01 97 7f 9c 7c 18 bd a2 58 1a da 74 70 a3 e5 47 29 07 f5 80 23 e9 fa 46 54 a0 99 95 53 9b 0b c7 09 c0 78 89 92 e3 0d b0 2a 8c fb 17 3f 26 65 87 27 5c 66 61 79 4d 32 b3 8d 52 e2 82 3d f9 c5 02 bc 4c 73 48 62 af ba 41 d9 c4 2f b1 33 b8 15 7d cf 3a a9 5f 84 6d 34 1b 44 94 72 81 42 be cc 4b 0a 6f 5a 22 36 b5 3c 9d 13 7e 08 dd d6 5e 04 fc 5b ec ef f1 6e 1e 77 24 e6 c6 aa cb fd 51 67 06 6a 4a 88 db b2 c2 5d 43 40 f7 50 a8 f2 7a 71 a4 d2 bf 31 90 19 9a 8e f6 c3 a6 e7 60 12 ee 2d de 38 e8 b7 98 c1 28 f3 05 96 63 d1 b9 14 9f 1d 83 68 75 ed 16 03 ce e4 df e0 10 ae 69 55 91 2e 4e fe 21 1f 9e e1 d5 cd ca f0 8b 2b c9 8a 93 bb 57 20 86 1c a1 4f 3e 25 d4 6c a5 6b a7 37 ff 39 35 0c f8 ea 56 45 8f 2c 59 ab 85 eb 49 0f dc d8 76 b6 f4 0e 11 b4 d0 30 d3 3b ad d7 + * 01 2b 3f cf 73 2c d6 ed cb 74 15 78 8a c1 17 c9 89 68 21 ab 76 3b 4b 5a 6e 0e b9 d3 b6 3e 36 86 bf a2 a7 30 14 eb c7 2d 96 67 20 b5 9a e0 a8 c6 80 04 8d fe 75 5e 23 ca 8f 48 99 0d df 8e b8 70 29 9c 44 69 3d a5 c2 90 d2 1c 9b 02 1d 98 93 ec 84 e8 64 4c 3a 8b 97 f3 e5 c0 7d 26 c8 08 a0 62 82 55 f7 33 f6 51 63 4d 77 da fd c3 38 6d ee 09 47 a3 05 de a6 f1 22 25 6a 0c 81 b2 6b 58 d5 b3 fc fb 28 7f 07 dc 7a 9e d0 37 b4 e1 1a 24 03 ae 94 ba 88 2f ea 2e 8c 5b bb 79 d1 11 ff a4 19 3c 2a 4e 52 e3 95 bd 31 5d 35 4a 41 c4 db 42 c5 0b 49 1b 7c e4 b0 9d 45 f0 a9 61 57 06 d4 40 91 56 13 fa 87 ac 27 54 dd 59 1f 71 39 43 6c f9 be 4f f4 1e 32 cd e9 7e 7b 66 5f ef e7 6f 0a 60 d7 b7 83 92 e2 af 72 f8 b1 50 10 ce 18 53 a1 cc ad 12 34 0f f5 aa 16 e6 f2 d8 85 9f bc + */ +const uint8_t __aligned(256) raid_gfcauchy[6][256] = +{ + { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, + }, + { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, + 0x1d, 0x3a, 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26, + 0x4c, 0x98, 0x2d, 0x5a, 0xb4, 0x75, 0xea, 0xc9, + 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, + 0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, + 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23, + 0x46, 0x8c, 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, + 0x5d, 0xba, 0x69, 0xd2, 0xb9, 0x6f, 0xde, 0xa1, + 0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, 0x5e, 0xbc, + 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0, + 0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, + 0xfe, 0xe1, 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2, + 0xd9, 0xaf, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, + 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, 0x67, 0xce, + 0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, + 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc, + 0x85, 0x17, 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, + 0x4f, 0x9e, 0x21, 0x42, 0x84, 0x15, 0x2a, 0x54, + 0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, 0x55, 0xaa, + 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73, + 0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, + 0xfc, 0xe5, 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff, + 0xe3, 0xdb, 0xab, 0x4b, 0x96, 0x31, 0x62, 0xc4, + 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, 0xae, 0x41, + 0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, + 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6, + 0x51, 0xa2, 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, + 0xc3, 0x9b, 0x2b, 0x56, 0xac, 0x45, 0x8a, 0x09, + 0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, 0xf4, 0xf5, + 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16, + 0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, + 0x1b, 0x36, 0x6c, + }, + { + 0x01, 0xf5, 0xd2, 0xc4, 0x9a, 0x71, 0xf1, 0x7f, + 0xfc, 0x87, 0xc1, 0xc6, 0x19, 0x2f, 0x40, 0x55, + 0x3d, 0xba, 0x53, 0x04, 0x9c, 0x61, 0x34, 0x8c, + 0x46, 0x68, 0x70, 0x3e, 0xcc, 0x7d, 0x74, 0x75, + 0xb5, 0xdb, 0x0c, 0xdf, 0x9e, 0x6d, 0x79, 0xeb, + 0x63, 0x9f, 0x38, 0xd0, 0x94, 0xa5, 0x24, 0x89, + 0x5c, 0x65, 0x5b, 0xae, 0x37, 0x33, 0x4c, 0xdd, + 0x47, 0xf4, 0x02, 0xa6, 0x39, 0xd8, 0x9d, 0x2d, + 0x62, 0xb9, 0x2e, 0x0f, 0x2b, 0x60, 0x58, 0xe4, + 0xf8, 0x6c, 0x72, 0xb0, 0x85, 0x4d, 0x95, 0x41, + 0x1c, 0x23, 0x05, 0x99, 0x32, 0xc5, 0x0e, 0x82, + 0x91, 0x14, 0xd1, 0xaf, 0xf9, 0xb3, 0x07, 0x97, + 0x6e, 0x0b, 0x67, 0x3b, 0x78, 0xe6, 0x28, 0x22, + 0x4f, 0xa3, 0xca, 0x48, 0xde, 0x1d, 0xa8, 0x17, + 0x6f, 0x90, 0xaa, 0x31, 0x5a, 0xf3, 0xe9, 0xa9, + 0x44, 0x30, 0x56, 0x09, 0x59, 0x6a, 0x42, 0xcd, + 0xe5, 0xd6, 0x86, 0xd9, 0xbf, 0xcb, 0x26, 0x66, + 0x7c, 0xd5, 0xbe, 0x25, 0x1f, 0xe0, 0x98, 0x27, + 0x92, 0x51, 0xc7, 0x45, 0x2c, 0xc0, 0xad, 0xa7, + 0x69, 0xf7, 0xb4, 0xe8, 0x84, 0xe1, 0x18, 0x88, + 0x3c, 0x76, 0x20, 0x5e, 0x9b, 0x1e, 0x0d, 0x81, + 0x4a, 0xbd, 0x16, 0x8a, 0xac, 0x93, 0xce, 0x1a, + 0xc2, 0x0a, 0x3f, 0xfd, 0xe3, 0x77, 0x6b, 0xd7, + 0xef, 0xa4, 0x80, 0xa1, 0x36, 0xed, 0xa2, 0x12, + 0x57, 0xb6, 0x29, 0x8d, 0x7b, 0xc8, 0x52, 0xc3, + 0xbc, 0xb8, 0x21, 0xd4, 0xea, 0xd3, 0x06, 0xab, + 0x2a, 0x1b, 0x5f, 0xb7, 0x10, 0xec, 0x64, 0xf6, + 0xe2, 0x11, 0x50, 0x83, 0x54, 0x3a, 0xfa, 0xfb, + 0xf2, 0x43, 0xb1, 0xff, 0xe7, 0xc9, 0x03, 0xbb, + 0xee, 0x13, 0x8b, 0xdc, 0x35, 0xb2, 0xda, 0xcf, + 0xa0, 0x96, 0x49, 0x4e, 0x08, 0x73, 0xf0, 0x7e, + 0xfe, 0x15, 0x4b, + }, + { + 0x01, 0xbb, 0xa6, 0xd7, 0xc7, 0x07, 0xce, 0x82, + 0x4a, 0x2f, 0xa5, 0x9b, 0xb6, 0x60, 0xf1, 0xad, + 0xe7, 0xf4, 0x06, 0xd2, 0xdf, 0x2e, 0xca, 0x65, + 0x5c, 0x48, 0x21, 0xaa, 0xcd, 0x4e, 0xc1, 0x61, + 0x38, 0x0a, 0x3e, 0xd1, 0xd5, 0xcb, 0x10, 0xdc, + 0x5e, 0x24, 0xb8, 0xde, 0x79, 0x36, 0x43, 0x72, + 0xd9, 0xf8, 0xf9, 0xa2, 0xa4, 0x6a, 0x3d, 0xea, + 0x8e, 0x03, 0xf5, 0xab, 0xb4, 0x5d, 0xb5, 0x53, + 0x6b, 0x39, 0x86, 0xb0, 0x50, 0x74, 0x96, 0x84, + 0x5a, 0x4b, 0xe8, 0x49, 0xe5, 0x51, 0xef, 0x12, + 0xbc, 0x89, 0x5b, 0x2b, 0x29, 0x09, 0xc3, 0x57, + 0x1e, 0x37, 0x76, 0x0b, 0x64, 0x8a, 0x52, 0x59, + 0x80, 0xda, 0xa8, 0x44, 0x95, 0x3c, 0x33, 0xe6, + 0x7c, 0xaf, 0x6c, 0xb1, 0x9d, 0xfc, 0x92, 0xd6, + 0xd8, 0xff, 0xa7, 0x77, 0x04, 0x13, 0x73, 0x66, + 0x28, 0x7d, 0x83, 0xfb, 0x5f, 0x63, 0x25, 0x19, + 0xbd, 0xc5, 0x3b, 0x6e, 0x20, 0x35, 0x55, 0x42, + 0x31, 0xe1, 0xb9, 0x9e, 0x90, 0xd4, 0xba, 0xdb, + 0xf7, 0x2a, 0xe9, 0x3a, 0xa0, 0x75, 0x7a, 0xd3, + 0x02, 0xee, 0x9c, 0xc6, 0x1f, 0x14, 0xcc, 0x22, + 0x4d, 0x30, 0x71, 0x58, 0x11, 0x85, 0x4f, 0x6f, + 0x6d, 0x1d, 0xcf, 0xfa, 0x54, 0xa9, 0x17, 0xa3, + 0x0f, 0xae, 0x0d, 0x1c, 0xc2, 0xd0, 0x32, 0x16, + 0xf6, 0xc0, 0x7f, 0x2d, 0x15, 0xf3, 0x1b, 0xf2, + 0xed, 0xb3, 0x45, 0xc8, 0xac, 0x7b, 0x2c, 0xe2, + 0xe4, 0xbf, 0xbe, 0x9f, 0x34, 0x05, 0x70, 0x3f, + 0x98, 0xfe, 0x62, 0x18, 0x9a, 0x56, 0x8d, 0x93, + 0x97, 0x78, 0x4c, 0x7e, 0x27, 0x87, 0x08, 0x8b, + 0xec, 0x67, 0x0e, 0x1a, 0x23, 0x8c, 0x68, 0x99, + 0x94, 0x40, 0xb2, 0xa1, 0xeb, 0xb7, 0x26, 0xf0, + 0xdd, 0xe3, 0x69, 0x0c, 0xc4, 0x88, 0x41, 0x81, + 0x91, 0xe0, 0xfd, + }, + { + 0x01, 0x97, 0x7f, 0x9c, 0x7c, 0x18, 0xbd, 0xa2, + 0x58, 0x1a, 0xda, 0x74, 0x70, 0xa3, 0xe5, 0x47, + 0x29, 0x07, 0xf5, 0x80, 0x23, 0xe9, 0xfa, 0x46, + 0x54, 0xa0, 0x99, 0x95, 0x53, 0x9b, 0x0b, 0xc7, + 0x09, 0xc0, 0x78, 0x89, 0x92, 0xe3, 0x0d, 0xb0, + 0x2a, 0x8c, 0xfb, 0x17, 0x3f, 0x26, 0x65, 0x87, + 0x27, 0x5c, 0x66, 0x61, 0x79, 0x4d, 0x32, 0xb3, + 0x8d, 0x52, 0xe2, 0x82, 0x3d, 0xf9, 0xc5, 0x02, + 0xbc, 0x4c, 0x73, 0x48, 0x62, 0xaf, 0xba, 0x41, + 0xd9, 0xc4, 0x2f, 0xb1, 0x33, 0xb8, 0x15, 0x7d, + 0xcf, 0x3a, 0xa9, 0x5f, 0x84, 0x6d, 0x34, 0x1b, + 0x44, 0x94, 0x72, 0x81, 0x42, 0xbe, 0xcc, 0x4b, + 0x0a, 0x6f, 0x5a, 0x22, 0x36, 0xb5, 0x3c, 0x9d, + 0x13, 0x7e, 0x08, 0xdd, 0xd6, 0x5e, 0x04, 0xfc, + 0x5b, 0xec, 0xef, 0xf1, 0x6e, 0x1e, 0x77, 0x24, + 0xe6, 0xc6, 0xaa, 0xcb, 0xfd, 0x51, 0x67, 0x06, + 0x6a, 0x4a, 0x88, 0xdb, 0xb2, 0xc2, 0x5d, 0x43, + 0x40, 0xf7, 0x50, 0xa8, 0xf2, 0x7a, 0x71, 0xa4, + 0xd2, 0xbf, 0x31, 0x90, 0x19, 0x9a, 0x8e, 0xf6, + 0xc3, 0xa6, 0xe7, 0x60, 0x12, 0xee, 0x2d, 0xde, + 0x38, 0xe8, 0xb7, 0x98, 0xc1, 0x28, 0xf3, 0x05, + 0x96, 0x63, 0xd1, 0xb9, 0x14, 0x9f, 0x1d, 0x83, + 0x68, 0x75, 0xed, 0x16, 0x03, 0xce, 0xe4, 0xdf, + 0xe0, 0x10, 0xae, 0x69, 0x55, 0x91, 0x2e, 0x4e, + 0xfe, 0x21, 0x1f, 0x9e, 0xe1, 0xd5, 0xcd, 0xca, + 0xf0, 0x8b, 0x2b, 0xc9, 0x8a, 0x93, 0xbb, 0x57, + 0x20, 0x86, 0x1c, 0xa1, 0x4f, 0x3e, 0x25, 0xd4, + 0x6c, 0xa5, 0x6b, 0xa7, 0x37, 0xff, 0x39, 0x35, + 0x0c, 0xf8, 0xea, 0x56, 0x45, 0x8f, 0x2c, 0x59, + 0xab, 0x85, 0xeb, 0x49, 0x0f, 0xdc, 0xd8, 0x76, + 0xb6, 0xf4, 0x0e, 0x11, 0xb4, 0xd0, 0x30, 0xd3, + 0x3b, 0xad, 0xd7, + }, + { + 0x01, 0x2b, 0x3f, 0xcf, 0x73, 0x2c, 0xd6, 0xed, + 0xcb, 0x74, 0x15, 0x78, 0x8a, 0xc1, 0x17, 0xc9, + 0x89, 0x68, 0x21, 0xab, 0x76, 0x3b, 0x4b, 0x5a, + 0x6e, 0x0e, 0xb9, 0xd3, 0xb6, 0x3e, 0x36, 0x86, + 0xbf, 0xa2, 0xa7, 0x30, 0x14, 0xeb, 0xc7, 0x2d, + 0x96, 0x67, 0x20, 0xb5, 0x9a, 0xe0, 0xa8, 0xc6, + 0x80, 0x04, 0x8d, 0xfe, 0x75, 0x5e, 0x23, 0xca, + 0x8f, 0x48, 0x99, 0x0d, 0xdf, 0x8e, 0xb8, 0x70, + 0x29, 0x9c, 0x44, 0x69, 0x3d, 0xa5, 0xc2, 0x90, + 0xd2, 0x1c, 0x9b, 0x02, 0x1d, 0x98, 0x93, 0xec, + 0x84, 0xe8, 0x64, 0x4c, 0x3a, 0x8b, 0x97, 0xf3, + 0xe5, 0xc0, 0x7d, 0x26, 0xc8, 0x08, 0xa0, 0x62, + 0x82, 0x55, 0xf7, 0x33, 0xf6, 0x51, 0x63, 0x4d, + 0x77, 0xda, 0xfd, 0xc3, 0x38, 0x6d, 0xee, 0x09, + 0x47, 0xa3, 0x05, 0xde, 0xa6, 0xf1, 0x22, 0x25, + 0x6a, 0x0c, 0x81, 0xb2, 0x6b, 0x58, 0xd5, 0xb3, + 0xfc, 0xfb, 0x28, 0x7f, 0x07, 0xdc, 0x7a, 0x9e, + 0xd0, 0x37, 0xb4, 0xe1, 0x1a, 0x24, 0x03, 0xae, + 0x94, 0xba, 0x88, 0x2f, 0xea, 0x2e, 0x8c, 0x5b, + 0xbb, 0x79, 0xd1, 0x11, 0xff, 0xa4, 0x19, 0x3c, + 0x2a, 0x4e, 0x52, 0xe3, 0x95, 0xbd, 0x31, 0x5d, + 0x35, 0x4a, 0x41, 0xc4, 0xdb, 0x42, 0xc5, 0x0b, + 0x49, 0x1b, 0x7c, 0xe4, 0xb0, 0x9d, 0x45, 0xf0, + 0xa9, 0x61, 0x57, 0x06, 0xd4, 0x40, 0x91, 0x56, + 0x13, 0xfa, 0x87, 0xac, 0x27, 0x54, 0xdd, 0x59, + 0x1f, 0x71, 0x39, 0x43, 0x6c, 0xf9, 0xbe, 0x4f, + 0xf4, 0x1e, 0x32, 0xcd, 0xe9, 0x7e, 0x7b, 0x66, + 0x5f, 0xef, 0xe7, 0x6f, 0x0a, 0x60, 0xd7, 0xb7, + 0x83, 0x92, 0xe2, 0xaf, 0x72, 0xf8, 0xb1, 0x50, + 0x10, 0xce, 0x18, 0x53, 0xa1, 0xcc, 0xad, 0x12, + 0x34, 0x0f, 0xf5, 0xaa, 0x16, 0xe6, 0xf2, 0xd8, + 0x85, 0x9f, 0xbc, + }, +}; + +#ifdef CONFIG_X86 +/** + * PSHUFB tables for the Cauchy matrix. + * + * Indexes are [DISK][PARITY - 2][LH]. + * Where DISK is from 0 to 250, PARITY from 2 to 5, LH from 0 to 1. + */ +const uint8_t __aligned(256) raid_gfcauchypshufb[251][4][2][16] = +{ + { + { + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0 }, + }, + { + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0 }, + }, + { + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0 }, + }, + { + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0 }, + }, + }, + { + { + { 0x00, 0xf5, 0xf7, 0x02, 0xf3, 0x06, 0x04, 0xf1, 0xfb, 0x0e, 0x0c, 0xf9, 0x08, 0xfd, 0xff, 0x0a }, + { 0x00, 0xeb, 0xcb, 0x20, 0x8b, 0x60, 0x40, 0xab, 0x0b, 0xe0, 0xc0, 0x2b, 0x80, 0x6b, 0x4b, 0xa0 }, + }, + { + { 0x00, 0xbb, 0x6b, 0xd0, 0xd6, 0x6d, 0xbd, 0x06, 0xb1, 0x0a, 0xda, 0x61, 0x67, 0xdc, 0x0c, 0xb7 }, + { 0x00, 0x7f, 0xfe, 0x81, 0xe1, 0x9e, 0x1f, 0x60, 0xdf, 0xa0, 0x21, 0x5e, 0x3e, 0x41, 0xc0, 0xbf }, + }, + { + { 0x00, 0x97, 0x33, 0xa4, 0x66, 0xf1, 0x55, 0xc2, 0xcc, 0x5b, 0xff, 0x68, 0xaa, 0x3d, 0x99, 0x0e }, + { 0x00, 0x85, 0x17, 0x92, 0x2e, 0xab, 0x39, 0xbc, 0x5c, 0xd9, 0x4b, 0xce, 0x72, 0xf7, 0x65, 0xe0 }, + }, + { + { 0x00, 0x2b, 0x56, 0x7d, 0xac, 0x87, 0xfa, 0xd1, 0x45, 0x6e, 0x13, 0x38, 0xe9, 0xc2, 0xbf, 0x94 }, + { 0x00, 0x8a, 0x09, 0x83, 0x12, 0x98, 0x1b, 0x91, 0x24, 0xae, 0x2d, 0xa7, 0x36, 0xbc, 0x3f, 0xb5 }, + }, + }, + { + { + { 0x00, 0xd2, 0xb9, 0x6b, 0x6f, 0xbd, 0xd6, 0x04, 0xde, 0x0c, 0x67, 0xb5, 0xb1, 0x63, 0x08, 0xda }, + { 0x00, 0xa1, 0x5f, 0xfe, 0xbe, 0x1f, 0xe1, 0x40, 0x61, 0xc0, 0x3e, 0x9f, 0xdf, 0x7e, 0x80, 0x21 }, + }, + { + { 0x00, 0xa6, 0x51, 0xf7, 0xa2, 0x04, 0xf3, 0x55, 0x59, 0xff, 0x08, 0xae, 0xfb, 0x5d, 0xaa, 0x0c }, + { 0x00, 0xb2, 0x79, 0xcb, 0xf2, 0x40, 0x8b, 0x39, 0xf9, 0x4b, 0x80, 0x32, 0x0b, 0xb9, 0x72, 0xc0 }, + }, + { + { 0x00, 0x7f, 0xfe, 0x81, 0xe1, 0x9e, 0x1f, 0x60, 0xdf, 0xa0, 0x21, 0x5e, 0x3e, 0x41, 0xc0, 0xbf }, + { 0x00, 0xa3, 0x5b, 0xf8, 0xb6, 0x15, 0xed, 0x4e, 0x71, 0xd2, 0x2a, 0x89, 0xc7, 0x64, 0x9c, 0x3f }, + }, + { + { 0x00, 0x3f, 0x7e, 0x41, 0xfc, 0xc3, 0x82, 0xbd, 0xe5, 0xda, 0x9b, 0xa4, 0x19, 0x26, 0x67, 0x58 }, + { 0x00, 0xd7, 0xb3, 0x64, 0x7b, 0xac, 0xc8, 0x1f, 0xf6, 0x21, 0x45, 0x92, 0x8d, 0x5a, 0x3e, 0xe9 }, + }, + }, + { + { + { 0x00, 0xc4, 0x95, 0x51, 0x37, 0xf3, 0xa2, 0x66, 0x6e, 0xaa, 0xfb, 0x3f, 0x59, 0x9d, 0xcc, 0x08 }, + { 0x00, 0xdc, 0xa5, 0x79, 0x57, 0x8b, 0xf2, 0x2e, 0xae, 0x72, 0x0b, 0xd7, 0xf9, 0x25, 0x5c, 0x80 }, + }, + { + { 0x00, 0xd7, 0xb3, 0x64, 0x7b, 0xac, 0xc8, 0x1f, 0xf6, 0x21, 0x45, 0x92, 0x8d, 0x5a, 0x3e, 0xe9 }, + { 0x00, 0xf1, 0xff, 0x0e, 0xe3, 0x12, 0x1c, 0xed, 0xdb, 0x2a, 0x24, 0xd5, 0x38, 0xc9, 0xc7, 0x36 }, + }, + { + { 0x00, 0x9c, 0x25, 0xb9, 0x4a, 0xd6, 0x6f, 0xf3, 0x94, 0x08, 0xb1, 0x2d, 0xde, 0x42, 0xfb, 0x67 }, + { 0x00, 0x35, 0x6a, 0x5f, 0xd4, 0xe1, 0xbe, 0x8b, 0xb5, 0x80, 0xdf, 0xea, 0x61, 0x54, 0x0b, 0x3e }, + }, + { + { 0x00, 0xcf, 0x83, 0x4c, 0x1b, 0xd4, 0x98, 0x57, 0x36, 0xf9, 0xb5, 0x7a, 0x2d, 0xe2, 0xae, 0x61 }, + { 0x00, 0x6c, 0xd8, 0xb4, 0xad, 0xc1, 0x75, 0x19, 0x47, 0x2b, 0x9f, 0xf3, 0xea, 0x86, 0x32, 0x5e }, + }, + }, + { + { + { 0x00, 0x9a, 0x29, 0xb3, 0x52, 0xc8, 0x7b, 0xe1, 0xa4, 0x3e, 0x8d, 0x17, 0xf6, 0x6c, 0xdf, 0x45 }, + { 0x00, 0x55, 0xaa, 0xff, 0x49, 0x1c, 0xe3, 0xb6, 0x92, 0xc7, 0x38, 0x6d, 0xdb, 0x8e, 0x71, 0x24 }, + }, + { + { 0x00, 0xc7, 0x93, 0x54, 0x3b, 0xfc, 0xa8, 0x6f, 0x76, 0xb1, 0xe5, 0x22, 0x4d, 0x8a, 0xde, 0x19 }, + { 0x00, 0xec, 0xc5, 0x29, 0x97, 0x7b, 0x52, 0xbe, 0x33, 0xdf, 0xf6, 0x1a, 0xa4, 0x48, 0x61, 0x8d }, + }, + { + { 0x00, 0x7c, 0xf8, 0x84, 0xed, 0x91, 0x15, 0x69, 0xc7, 0xbb, 0x3f, 0x43, 0x2a, 0x56, 0xd2, 0xae }, + { 0x00, 0x93, 0x3b, 0xa8, 0x76, 0xe5, 0x4d, 0xde, 0xec, 0x7f, 0xd7, 0x44, 0x9a, 0x09, 0xa1, 0x32 }, + }, + { + { 0x00, 0x73, 0xe6, 0x95, 0xd1, 0xa2, 0x37, 0x44, 0xbf, 0xcc, 0x59, 0x2a, 0x6e, 0x1d, 0x88, 0xfb }, + { 0x00, 0x63, 0xc6, 0xa5, 0x91, 0xf2, 0x57, 0x34, 0x3f, 0x5c, 0xf9, 0x9a, 0xae, 0xcd, 0x68, 0x0b }, + }, + }, + { + { + { 0x00, 0x71, 0xe2, 0x93, 0xd9, 0xa8, 0x3b, 0x4a, 0xaf, 0xde, 0x4d, 0x3c, 0x76, 0x07, 0x94, 0xe5 }, + { 0x00, 0x43, 0x86, 0xc5, 0x11, 0x52, 0x97, 0xd4, 0x22, 0x61, 0xa4, 0xe7, 0x33, 0x70, 0xb5, 0xf6 }, + }, + { + { 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d }, + { 0x00, 0x70, 0xe0, 0x90, 0xdd, 0xad, 0x3d, 0x4d, 0xa7, 0xd7, 0x47, 0x37, 0x7a, 0x0a, 0x9a, 0xea }, + }, + { + { 0x00, 0x18, 0x30, 0x28, 0x60, 0x78, 0x50, 0x48, 0xc0, 0xd8, 0xf0, 0xe8, 0xa0, 0xb8, 0x90, 0x88 }, + { 0x00, 0x9d, 0x27, 0xba, 0x4e, 0xd3, 0x69, 0xf4, 0x9c, 0x01, 0xbb, 0x26, 0xd2, 0x4f, 0xf5, 0x68 }, + }, + { + { 0x00, 0x2c, 0x58, 0x74, 0xb0, 0x9c, 0xe8, 0xc4, 0x7d, 0x51, 0x25, 0x09, 0xcd, 0xe1, 0x95, 0xb9 }, + { 0x00, 0xfa, 0xe9, 0x13, 0xcf, 0x35, 0x26, 0xdc, 0x83, 0x79, 0x6a, 0x90, 0x4c, 0xb6, 0xa5, 0x5f }, + }, + }, + { + { + { 0x00, 0xf1, 0xff, 0x0e, 0xe3, 0x12, 0x1c, 0xed, 0xdb, 0x2a, 0x24, 0xd5, 0x38, 0xc9, 0xc7, 0x36 }, + { 0x00, 0xab, 0x4b, 0xe0, 0x96, 0x3d, 0xdd, 0x76, 0x31, 0x9a, 0x7a, 0xd1, 0xa7, 0x0c, 0xec, 0x47 }, + }, + { + { 0x00, 0xce, 0x81, 0x4f, 0x1f, 0xd1, 0x9e, 0x50, 0x3e, 0xf0, 0xbf, 0x71, 0x21, 0xef, 0xa0, 0x6e }, + { 0x00, 0x7c, 0xf8, 0x84, 0xed, 0x91, 0x15, 0x69, 0xc7, 0xbb, 0x3f, 0x43, 0x2a, 0x56, 0xd2, 0xae }, + }, + { + { 0x00, 0xbd, 0x67, 0xda, 0xce, 0x73, 0xa9, 0x14, 0x81, 0x3c, 0xe6, 0x5b, 0x4f, 0xf2, 0x28, 0x95 }, + { 0x00, 0x1f, 0x3e, 0x21, 0x7c, 0x63, 0x42, 0x5d, 0xf8, 0xe7, 0xc6, 0xd9, 0x84, 0x9b, 0xba, 0xa5 }, + }, + { + { 0x00, 0xd6, 0xb1, 0x67, 0x7f, 0xa9, 0xce, 0x18, 0xfe, 0x28, 0x4f, 0x99, 0x81, 0x57, 0x30, 0xe6 }, + { 0x00, 0xe1, 0xdf, 0x3e, 0xa3, 0x42, 0x7c, 0x9d, 0x5b, 0xba, 0x84, 0x65, 0xf8, 0x19, 0x27, 0xc6 }, + }, + }, + { + { + { 0x00, 0x7f, 0xfe, 0x81, 0xe1, 0x9e, 0x1f, 0x60, 0xdf, 0xa0, 0x21, 0x5e, 0x3e, 0x41, 0xc0, 0xbf }, + { 0x00, 0xa3, 0x5b, 0xf8, 0xb6, 0x15, 0xed, 0x4e, 0x71, 0xd2, 0x2a, 0x89, 0xc7, 0x64, 0x9c, 0x3f }, + }, + { + { 0x00, 0x82, 0x19, 0x9b, 0x32, 0xb0, 0x2b, 0xa9, 0x64, 0xe6, 0x7d, 0xff, 0x56, 0xd4, 0x4f, 0xcd }, + { 0x00, 0xc8, 0x8d, 0x45, 0x07, 0xcf, 0x8a, 0x42, 0x0e, 0xc6, 0x83, 0x4b, 0x09, 0xc1, 0x84, 0x4c }, + }, + { + { 0x00, 0xa2, 0x59, 0xfb, 0xb2, 0x10, 0xeb, 0x49, 0x79, 0xdb, 0x20, 0x82, 0xcb, 0x69, 0x92, 0x30 }, + { 0x00, 0xf2, 0xf9, 0x0b, 0xef, 0x1d, 0x16, 0xe4, 0xc3, 0x31, 0x3a, 0xc8, 0x2c, 0xde, 0xd5, 0x27 }, + }, + { + { 0x00, 0xed, 0xc7, 0x2a, 0x93, 0x7e, 0x54, 0xb9, 0x3b, 0xd6, 0xfc, 0x11, 0xa8, 0x45, 0x6f, 0x82 }, + { 0x00, 0x76, 0xec, 0x9a, 0xc5, 0xb3, 0x29, 0x5f, 0x97, 0xe1, 0x7b, 0x0d, 0x52, 0x24, 0xbe, 0xc8 }, + }, + }, + { + { + { 0x00, 0xfc, 0xe5, 0x19, 0xd7, 0x2b, 0x32, 0xce, 0xb3, 0x4f, 0x56, 0xaa, 0x64, 0x98, 0x81, 0x7d }, + { 0x00, 0x7b, 0xf6, 0x8d, 0xf1, 0x8a, 0x07, 0x7c, 0xff, 0x84, 0x09, 0x72, 0x0e, 0x75, 0xf8, 0x83 }, + }, + { + { 0x00, 0x4a, 0x94, 0xde, 0x35, 0x7f, 0xa1, 0xeb, 0x6a, 0x20, 0xfe, 0xb4, 0x5f, 0x15, 0xcb, 0x81 }, + { 0x00, 0xd4, 0xb5, 0x61, 0x77, 0xa3, 0xc2, 0x16, 0xee, 0x3a, 0x5b, 0x8f, 0x99, 0x4d, 0x2c, 0xf8 }, + }, + { + { 0x00, 0x58, 0xb0, 0xe8, 0x7d, 0x25, 0xcd, 0x95, 0xfa, 0xa2, 0x4a, 0x12, 0x87, 0xdf, 0x37, 0x6f }, + { 0x00, 0xe9, 0xcf, 0x26, 0x83, 0x6a, 0x4c, 0xa5, 0x1b, 0xf2, 0xd4, 0x3d, 0x98, 0x71, 0x57, 0xbe }, + }, + { + { 0x00, 0xcb, 0x8b, 0x40, 0x0b, 0xc0, 0x80, 0x4b, 0x16, 0xdd, 0x9d, 0x56, 0x1d, 0xd6, 0x96, 0x5d }, + { 0x00, 0x2c, 0x58, 0x74, 0xb0, 0x9c, 0xe8, 0xc4, 0x7d, 0x51, 0x25, 0x09, 0xcd, 0xe1, 0x95, 0xb9 }, + }, + }, + { + { + { 0x00, 0x87, 0x13, 0x94, 0x26, 0xa1, 0x35, 0xb2, 0x4c, 0xcb, 0x5f, 0xd8, 0x6a, 0xed, 0x79, 0xfe }, + { 0x00, 0x98, 0x2d, 0xb5, 0x5a, 0xc2, 0x77, 0xef, 0xb4, 0x2c, 0x99, 0x01, 0xee, 0x76, 0xc3, 0x5b }, + }, + { + { 0x00, 0x2f, 0x5e, 0x71, 0xbc, 0x93, 0xe2, 0xcd, 0x65, 0x4a, 0x3b, 0x14, 0xd9, 0xf6, 0x87, 0xa8 }, + { 0x00, 0xca, 0x89, 0x43, 0x0f, 0xc5, 0x86, 0x4c, 0x1e, 0xd4, 0x97, 0x5d, 0x11, 0xdb, 0x98, 0x52 }, + }, + { + { 0x00, 0x1a, 0x34, 0x2e, 0x68, 0x72, 0x5c, 0x46, 0xd0, 0xca, 0xe4, 0xfe, 0xb8, 0xa2, 0x8c, 0x96 }, + { 0x00, 0xbd, 0x67, 0xda, 0xce, 0x73, 0xa9, 0x14, 0x81, 0x3c, 0xe6, 0x5b, 0x4f, 0xf2, 0x28, 0x95 }, + }, + { + { 0x00, 0x74, 0xe8, 0x9c, 0xcd, 0xb9, 0x25, 0x51, 0x87, 0xf3, 0x6f, 0x1b, 0x4a, 0x3e, 0xa2, 0xd6 }, + { 0x00, 0x13, 0x26, 0x35, 0x4c, 0x5f, 0x6a, 0x79, 0x98, 0x8b, 0xbe, 0xad, 0xd4, 0xc7, 0xf2, 0xe1 }, + }, + }, + { + { + { 0x00, 0xc1, 0x9f, 0x5e, 0x23, 0xe2, 0xbc, 0x7d, 0x46, 0x87, 0xd9, 0x18, 0x65, 0xa4, 0xfa, 0x3b }, + { 0x00, 0x8c, 0x05, 0x89, 0x0a, 0x86, 0x0f, 0x83, 0x14, 0x98, 0x11, 0x9d, 0x1e, 0x92, 0x1b, 0x97 }, + }, + { + { 0x00, 0xa5, 0x57, 0xf2, 0xae, 0x0b, 0xf9, 0x5c, 0x41, 0xe4, 0x16, 0xb3, 0xef, 0x4a, 0xb8, 0x1d }, + { 0x00, 0x82, 0x19, 0x9b, 0x32, 0xb0, 0x2b, 0xa9, 0x64, 0xe6, 0x7d, 0xff, 0x56, 0xd4, 0x4f, 0xcd }, + }, + { + { 0x00, 0xda, 0xa9, 0x73, 0x4f, 0x95, 0xe6, 0x3c, 0x9e, 0x44, 0x37, 0xed, 0xd1, 0x0b, 0x78, 0xa2 }, + { 0x00, 0x21, 0x42, 0x63, 0x84, 0xa5, 0xc6, 0xe7, 0x15, 0x34, 0x57, 0x76, 0x91, 0xb0, 0xd3, 0xf2 }, + }, + { + { 0x00, 0x15, 0x2a, 0x3f, 0x54, 0x41, 0x7e, 0x6b, 0xa8, 0xbd, 0x82, 0x97, 0xfc, 0xe9, 0xd6, 0xc3 }, + { 0x00, 0x4d, 0x9a, 0xd7, 0x29, 0x64, 0xb3, 0xfe, 0x52, 0x1f, 0xc8, 0x85, 0x7b, 0x36, 0xe1, 0xac }, + }, + }, + { + { + { 0x00, 0xc6, 0x91, 0x57, 0x3f, 0xf9, 0xae, 0x68, 0x7e, 0xb8, 0xef, 0x29, 0x41, 0x87, 0xd0, 0x16 }, + { 0x00, 0xfc, 0xe5, 0x19, 0xd7, 0x2b, 0x32, 0xce, 0xb3, 0x4f, 0x56, 0xaa, 0x64, 0x98, 0x81, 0x7d }, + }, + { + { 0x00, 0x9b, 0x2b, 0xb0, 0x56, 0xcd, 0x7d, 0xe6, 0xac, 0x37, 0x87, 0x1c, 0xfa, 0x61, 0xd1, 0x4a }, + { 0x00, 0x45, 0x8a, 0xcf, 0x09, 0x4c, 0x83, 0xc6, 0x12, 0x57, 0x98, 0xdd, 0x1b, 0x5e, 0x91, 0xd4 }, + }, + { + { 0x00, 0x74, 0xe8, 0x9c, 0xcd, 0xb9, 0x25, 0x51, 0x87, 0xf3, 0x6f, 0x1b, 0x4a, 0x3e, 0xa2, 0xd6 }, + { 0x00, 0x13, 0x26, 0x35, 0x4c, 0x5f, 0x6a, 0x79, 0x98, 0x8b, 0xbe, 0xad, 0xd4, 0xc7, 0xf2, 0xe1 }, + }, + { + { 0x00, 0x78, 0xf0, 0x88, 0xfd, 0x85, 0x0d, 0x75, 0xe7, 0x9f, 0x17, 0x6f, 0x1a, 0x62, 0xea, 0x92 }, + { 0x00, 0xd3, 0xbb, 0x68, 0x6b, 0xb8, 0xd0, 0x03, 0xd6, 0x05, 0x6d, 0xbe, 0xbd, 0x6e, 0x06, 0xd5 }, + }, + }, + { + { + { 0x00, 0x19, 0x32, 0x2b, 0x64, 0x7d, 0x56, 0x4f, 0xc8, 0xd1, 0xfa, 0xe3, 0xac, 0xb5, 0x9e, 0x87 }, + { 0x00, 0x8d, 0x07, 0x8a, 0x0e, 0x83, 0x09, 0x84, 0x1c, 0x91, 0x1b, 0x96, 0x12, 0x9f, 0x15, 0x98 }, + }, + { + { 0x00, 0xb6, 0x71, 0xc7, 0xe2, 0x54, 0x93, 0x25, 0xd9, 0x6f, 0xa8, 0x1e, 0x3b, 0x8d, 0x4a, 0xfc }, + { 0x00, 0xaf, 0x43, 0xec, 0x86, 0x29, 0xc5, 0x6a, 0x11, 0xbe, 0x52, 0xfd, 0x97, 0x38, 0xd4, 0x7b }, + }, + { + { 0x00, 0x70, 0xe0, 0x90, 0xdd, 0xad, 0x3d, 0x4d, 0xa7, 0xd7, 0x47, 0x37, 0x7a, 0x0a, 0x9a, 0xea }, + { 0x00, 0x53, 0xa6, 0xf5, 0x51, 0x02, 0xf7, 0xa4, 0xa2, 0xf1, 0x04, 0x57, 0xf3, 0xa0, 0x55, 0x06 }, + }, + { + { 0x00, 0x8a, 0x09, 0x83, 0x12, 0x98, 0x1b, 0x91, 0x24, 0xae, 0x2d, 0xa7, 0x36, 0xbc, 0x3f, 0xb5 }, + { 0x00, 0x48, 0x90, 0xd8, 0x3d, 0x75, 0xad, 0xe5, 0x7a, 0x32, 0xea, 0xa2, 0x47, 0x0f, 0xd7, 0x9f }, + }, + }, + { + { + { 0x00, 0x2f, 0x5e, 0x71, 0xbc, 0x93, 0xe2, 0xcd, 0x65, 0x4a, 0x3b, 0x14, 0xd9, 0xf6, 0x87, 0xa8 }, + { 0x00, 0xca, 0x89, 0x43, 0x0f, 0xc5, 0x86, 0x4c, 0x1e, 0xd4, 0x97, 0x5d, 0x11, 0xdb, 0x98, 0x52 }, + }, + { + { 0x00, 0x60, 0xc0, 0xa0, 0x9d, 0xfd, 0x5d, 0x3d, 0x27, 0x47, 0xe7, 0x87, 0xba, 0xda, 0x7a, 0x1a }, + { 0x00, 0x4e, 0x9c, 0xd2, 0x25, 0x6b, 0xb9, 0xf7, 0x4a, 0x04, 0xd6, 0x98, 0x6f, 0x21, 0xf3, 0xbd }, + }, + { + { 0x00, 0xa3, 0x5b, 0xf8, 0xb6, 0x15, 0xed, 0x4e, 0x71, 0xd2, 0x2a, 0x89, 0xc7, 0x64, 0x9c, 0x3f }, + { 0x00, 0xe2, 0xd9, 0x3b, 0xaf, 0x4d, 0x76, 0x94, 0x43, 0xa1, 0x9a, 0x78, 0xec, 0x0e, 0x35, 0xd7 }, + }, + { + { 0x00, 0xc1, 0x9f, 0x5e, 0x23, 0xe2, 0xbc, 0x7d, 0x46, 0x87, 0xd9, 0x18, 0x65, 0xa4, 0xfa, 0x3b }, + { 0x00, 0x8c, 0x05, 0x89, 0x0a, 0x86, 0x0f, 0x83, 0x14, 0x98, 0x11, 0x9d, 0x1e, 0x92, 0x1b, 0x97 }, + }, + }, + { + { + { 0x00, 0x40, 0x80, 0xc0, 0x1d, 0x5d, 0x9d, 0xdd, 0x3a, 0x7a, 0xba, 0xfa, 0x27, 0x67, 0xa7, 0xe7 }, + { 0x00, 0x74, 0xe8, 0x9c, 0xcd, 0xb9, 0x25, 0x51, 0x87, 0xf3, 0x6f, 0x1b, 0x4a, 0x3e, 0xa2, 0xd6 }, + }, + { + { 0x00, 0xf1, 0xff, 0x0e, 0xe3, 0x12, 0x1c, 0xed, 0xdb, 0x2a, 0x24, 0xd5, 0x38, 0xc9, 0xc7, 0x36 }, + { 0x00, 0xab, 0x4b, 0xe0, 0x96, 0x3d, 0xdd, 0x76, 0x31, 0x9a, 0x7a, 0xd1, 0xa7, 0x0c, 0xec, 0x47 }, + }, + { + { 0x00, 0xe5, 0xd7, 0x32, 0xb3, 0x56, 0x64, 0x81, 0x7b, 0x9e, 0xac, 0x49, 0xc8, 0x2d, 0x1f, 0xfa }, + { 0x00, 0xf6, 0xf1, 0x07, 0xff, 0x09, 0x0e, 0xf8, 0xe3, 0x15, 0x12, 0xe4, 0x1c, 0xea, 0xed, 0x1b }, + }, + { + { 0x00, 0x17, 0x2e, 0x39, 0x5c, 0x4b, 0x72, 0x65, 0xb8, 0xaf, 0x96, 0x81, 0xe4, 0xf3, 0xca, 0xdd }, + { 0x00, 0x6d, 0xda, 0xb7, 0xa9, 0xc4, 0x73, 0x1e, 0x4f, 0x22, 0x95, 0xf8, 0xe6, 0x8b, 0x3c, 0x51 }, + }, + }, + { + { + { 0x00, 0x55, 0xaa, 0xff, 0x49, 0x1c, 0xe3, 0xb6, 0x92, 0xc7, 0x38, 0x6d, 0xdb, 0x8e, 0x71, 0x24 }, + { 0x00, 0x39, 0x72, 0x4b, 0xe4, 0xdd, 0x96, 0xaf, 0xd5, 0xec, 0xa7, 0x9e, 0x31, 0x08, 0x43, 0x7a }, + }, + { + { 0x00, 0xad, 0x47, 0xea, 0x8e, 0x23, 0xc9, 0x64, 0x01, 0xac, 0x46, 0xeb, 0x8f, 0x22, 0xc8, 0x65 }, + { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e }, + }, + { + { 0x00, 0x47, 0x8e, 0xc9, 0x01, 0x46, 0x8f, 0xc8, 0x02, 0x45, 0x8c, 0xcb, 0x03, 0x44, 0x8d, 0xca }, + { 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c }, + }, + { + { 0x00, 0xc9, 0x8f, 0x46, 0x03, 0xca, 0x8c, 0x45, 0x06, 0xcf, 0x89, 0x40, 0x05, 0xcc, 0x8a, 0x43 }, + { 0x00, 0x0c, 0x18, 0x14, 0x30, 0x3c, 0x28, 0x24, 0x60, 0x6c, 0x78, 0x74, 0x50, 0x5c, 0x48, 0x44 }, + }, + }, + { + { + { 0x00, 0x3d, 0x7a, 0x47, 0xf4, 0xc9, 0x8e, 0xb3, 0xf5, 0xc8, 0x8f, 0xb2, 0x01, 0x3c, 0x7b, 0x46 }, + { 0x00, 0xf7, 0xf3, 0x04, 0xfb, 0x0c, 0x08, 0xff, 0xeb, 0x1c, 0x18, 0xef, 0x10, 0xe7, 0xe3, 0x14 }, + }, + { + { 0x00, 0xe7, 0xd3, 0x34, 0xbb, 0x5c, 0x68, 0x8f, 0x6b, 0x8c, 0xb8, 0x5f, 0xd0, 0x37, 0x03, 0xe4 }, + { 0x00, 0xd6, 0xb1, 0x67, 0x7f, 0xa9, 0xce, 0x18, 0xfe, 0x28, 0x4f, 0x99, 0x81, 0x57, 0x30, 0xe6 }, + }, + { + { 0x00, 0x29, 0x52, 0x7b, 0xa4, 0x8d, 0xf6, 0xdf, 0x55, 0x7c, 0x07, 0x2e, 0xf1, 0xd8, 0xa3, 0x8a }, + { 0x00, 0xaa, 0x49, 0xe3, 0x92, 0x38, 0xdb, 0x71, 0x39, 0x93, 0x70, 0xda, 0xab, 0x01, 0xe2, 0x48 }, + }, + { + { 0x00, 0x89, 0x0f, 0x86, 0x1e, 0x97, 0x11, 0x98, 0x3c, 0xb5, 0x33, 0xba, 0x22, 0xab, 0x2d, 0xa4 }, + { 0x00, 0x78, 0xf0, 0x88, 0xfd, 0x85, 0x0d, 0x75, 0xe7, 0x9f, 0x17, 0x6f, 0x1a, 0x62, 0xea, 0x92 }, + }, + }, + { + { + { 0x00, 0xba, 0x69, 0xd3, 0xd2, 0x68, 0xbb, 0x01, 0xb9, 0x03, 0xd0, 0x6a, 0x6b, 0xd1, 0x02, 0xb8 }, + { 0x00, 0x6f, 0xde, 0xb1, 0xa1, 0xce, 0x7f, 0x10, 0x5f, 0x30, 0x81, 0xee, 0xfe, 0x91, 0x20, 0x4f }, + }, + { + { 0x00, 0xf4, 0xf5, 0x01, 0xf7, 0x03, 0x02, 0xf6, 0xf3, 0x07, 0x06, 0xf2, 0x04, 0xf0, 0xf1, 0x05 }, + { 0x00, 0xfb, 0xeb, 0x10, 0xcb, 0x30, 0x20, 0xdb, 0x8b, 0x70, 0x60, 0x9b, 0x40, 0xbb, 0xab, 0x50 }, + }, + { + { 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d }, + { 0x00, 0x70, 0xe0, 0x90, 0xdd, 0xad, 0x3d, 0x4d, 0xa7, 0xd7, 0x47, 0x37, 0x7a, 0x0a, 0x9a, 0xea }, + }, + { + { 0x00, 0x68, 0xd0, 0xb8, 0xbd, 0xd5, 0x6d, 0x05, 0x67, 0x0f, 0xb7, 0xdf, 0xda, 0xb2, 0x0a, 0x62 }, + { 0x00, 0xce, 0x81, 0x4f, 0x1f, 0xd1, 0x9e, 0x50, 0x3e, 0xf0, 0xbf, 0x71, 0x21, 0xef, 0xa0, 0x6e }, + }, + }, + { + { + { 0x00, 0x53, 0xa6, 0xf5, 0x51, 0x02, 0xf7, 0xa4, 0xa2, 0xf1, 0x04, 0x57, 0xf3, 0xa0, 0x55, 0x06 }, + { 0x00, 0x59, 0xb2, 0xeb, 0x79, 0x20, 0xcb, 0x92, 0xf2, 0xab, 0x40, 0x19, 0x8b, 0xd2, 0x39, 0x60 }, + }, + { + { 0x00, 0x06, 0x0c, 0x0a, 0x18, 0x1e, 0x14, 0x12, 0x30, 0x36, 0x3c, 0x3a, 0x28, 0x2e, 0x24, 0x22 }, + { 0x00, 0x60, 0xc0, 0xa0, 0x9d, 0xfd, 0x5d, 0x3d, 0x27, 0x47, 0xe7, 0x87, 0xba, 0xda, 0x7a, 0x1a }, + }, + { + { 0x00, 0xf5, 0xf7, 0x02, 0xf3, 0x06, 0x04, 0xf1, 0xfb, 0x0e, 0x0c, 0xf9, 0x08, 0xfd, 0xff, 0x0a }, + { 0x00, 0xeb, 0xcb, 0x20, 0x8b, 0x60, 0x40, 0xab, 0x0b, 0xe0, 0xc0, 0x2b, 0x80, 0x6b, 0x4b, 0xa0 }, + }, + { + { 0x00, 0x21, 0x42, 0x63, 0x84, 0xa5, 0xc6, 0xe7, 0x15, 0x34, 0x57, 0x76, 0x91, 0xb0, 0xd3, 0xf2 }, + { 0x00, 0x2a, 0x54, 0x7e, 0xa8, 0x82, 0xfc, 0xd6, 0x4d, 0x67, 0x19, 0x33, 0xe5, 0xcf, 0xb1, 0x9b }, + }, + }, + { + { + { 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c }, + { 0x00, 0x40, 0x80, 0xc0, 0x1d, 0x5d, 0x9d, 0xdd, 0x3a, 0x7a, 0xba, 0xfa, 0x27, 0x67, 0xa7, 0xe7 }, + }, + { + { 0x00, 0xd2, 0xb9, 0x6b, 0x6f, 0xbd, 0xd6, 0x04, 0xde, 0x0c, 0x67, 0xb5, 0xb1, 0x63, 0x08, 0xda }, + { 0x00, 0xa1, 0x5f, 0xfe, 0xbe, 0x1f, 0xe1, 0x40, 0x61, 0xc0, 0x3e, 0x9f, 0xdf, 0x7e, 0x80, 0x21 }, + }, + { + { 0x00, 0x80, 0x1d, 0x9d, 0x3a, 0xba, 0x27, 0xa7, 0x74, 0xf4, 0x69, 0xe9, 0x4e, 0xce, 0x53, 0xd3 }, + { 0x00, 0xe8, 0xcd, 0x25, 0x87, 0x6f, 0x4a, 0xa2, 0x13, 0xfb, 0xde, 0x36, 0x94, 0x7c, 0x59, 0xb1 }, + }, + { + { 0x00, 0xab, 0x4b, 0xe0, 0x96, 0x3d, 0xdd, 0x76, 0x31, 0x9a, 0x7a, 0xd1, 0xa7, 0x0c, 0xec, 0x47 }, + { 0x00, 0x62, 0xc4, 0xa6, 0x95, 0xf7, 0x51, 0x33, 0x37, 0x55, 0xf3, 0x91, 0xa2, 0xc0, 0x66, 0x04 }, + }, + }, + { + { + { 0x00, 0x9c, 0x25, 0xb9, 0x4a, 0xd6, 0x6f, 0xf3, 0x94, 0x08, 0xb1, 0x2d, 0xde, 0x42, 0xfb, 0x67 }, + { 0x00, 0x35, 0x6a, 0x5f, 0xd4, 0xe1, 0xbe, 0x8b, 0xb5, 0x80, 0xdf, 0xea, 0x61, 0x54, 0x0b, 0x3e }, + }, + { + { 0x00, 0xdf, 0xa3, 0x7c, 0x5b, 0x84, 0xf8, 0x27, 0xb6, 0x69, 0x15, 0xca, 0xed, 0x32, 0x4e, 0x91 }, + { 0x00, 0x71, 0xe2, 0x93, 0xd9, 0xa8, 0x3b, 0x4a, 0xaf, 0xde, 0x4d, 0x3c, 0x76, 0x07, 0x94, 0xe5 }, + }, + { + { 0x00, 0x23, 0x46, 0x65, 0x8c, 0xaf, 0xca, 0xe9, 0x05, 0x26, 0x43, 0x60, 0x89, 0xaa, 0xcf, 0xec }, + { 0x00, 0x0a, 0x14, 0x1e, 0x28, 0x22, 0x3c, 0x36, 0x50, 0x5a, 0x44, 0x4e, 0x78, 0x72, 0x6c, 0x66 }, + }, + { + { 0x00, 0x76, 0xec, 0x9a, 0xc5, 0xb3, 0x29, 0x5f, 0x97, 0xe1, 0x7b, 0x0d, 0x52, 0x24, 0xbe, 0xc8 }, + { 0x00, 0x33, 0x66, 0x55, 0xcc, 0xff, 0xaa, 0x99, 0x85, 0xb6, 0xe3, 0xd0, 0x49, 0x7a, 0x2f, 0x1c }, + }, + }, + { + { + { 0x00, 0x61, 0xc2, 0xa3, 0x99, 0xf8, 0x5b, 0x3a, 0x2f, 0x4e, 0xed, 0x8c, 0xb6, 0xd7, 0x74, 0x15 }, + { 0x00, 0x5e, 0xbc, 0xe2, 0x65, 0x3b, 0xd9, 0x87, 0xca, 0x94, 0x76, 0x28, 0xaf, 0xf1, 0x13, 0x4d }, + }, + { + { 0x00, 0x2e, 0x5c, 0x72, 0xb8, 0x96, 0xe4, 0xca, 0x6d, 0x43, 0x31, 0x1f, 0xd5, 0xfb, 0x89, 0xa7 }, + { 0x00, 0xda, 0xa9, 0x73, 0x4f, 0x95, 0xe6, 0x3c, 0x9e, 0x44, 0x37, 0xed, 0xd1, 0x0b, 0x78, 0xa2 }, + }, + { + { 0x00, 0xe9, 0xcf, 0x26, 0x83, 0x6a, 0x4c, 0xa5, 0x1b, 0xf2, 0xd4, 0x3d, 0x98, 0x71, 0x57, 0xbe }, + { 0x00, 0x36, 0x6c, 0x5a, 0xd8, 0xee, 0xb4, 0x82, 0xad, 0x9b, 0xc1, 0xf7, 0x75, 0x43, 0x19, 0x2f }, + }, + { + { 0x00, 0x3b, 0x76, 0x4d, 0xec, 0xd7, 0x9a, 0xa1, 0xc5, 0xfe, 0xb3, 0x88, 0x29, 0x12, 0x5f, 0x64 }, + { 0x00, 0x97, 0x33, 0xa4, 0x66, 0xf1, 0x55, 0xc2, 0xcc, 0x5b, 0xff, 0x68, 0xaa, 0x3d, 0x99, 0x0e }, + }, + }, + { + { + { 0x00, 0x34, 0x68, 0x5c, 0xd0, 0xe4, 0xb8, 0x8c, 0xbd, 0x89, 0xd5, 0xe1, 0x6d, 0x59, 0x05, 0x31 }, + { 0x00, 0x67, 0xce, 0xa9, 0x81, 0xe6, 0x4f, 0x28, 0x1f, 0x78, 0xd1, 0xb6, 0x9e, 0xf9, 0x50, 0x37 }, + }, + { + { 0x00, 0xca, 0x89, 0x43, 0x0f, 0xc5, 0x86, 0x4c, 0x1e, 0xd4, 0x97, 0x5d, 0x11, 0xdb, 0x98, 0x52 }, + { 0x00, 0x3c, 0x78, 0x44, 0xf0, 0xcc, 0x88, 0xb4, 0xfd, 0xc1, 0x85, 0xb9, 0x0d, 0x31, 0x75, 0x49 }, + }, + { + { 0x00, 0xfa, 0xe9, 0x13, 0xcf, 0x35, 0x26, 0xdc, 0x83, 0x79, 0x6a, 0x90, 0x4c, 0xb6, 0xa5, 0x5f }, + { 0x00, 0x1b, 0x36, 0x2d, 0x6c, 0x77, 0x5a, 0x41, 0xd8, 0xc3, 0xee, 0xf5, 0xb4, 0xaf, 0x82, 0x99 }, + }, + { + { 0x00, 0x4b, 0x96, 0xdd, 0x31, 0x7a, 0xa7, 0xec, 0x62, 0x29, 0xf4, 0xbf, 0x53, 0x18, 0xc5, 0x8e }, + { 0x00, 0xc4, 0x95, 0x51, 0x37, 0xf3, 0xa2, 0x66, 0x6e, 0xaa, 0xfb, 0x3f, 0x59, 0x9d, 0xcc, 0x08 }, + }, + }, + { + { + { 0x00, 0x8c, 0x05, 0x89, 0x0a, 0x86, 0x0f, 0x83, 0x14, 0x98, 0x11, 0x9d, 0x1e, 0x92, 0x1b, 0x97 }, + { 0x00, 0x28, 0x50, 0x78, 0xa0, 0x88, 0xf0, 0xd8, 0x5d, 0x75, 0x0d, 0x25, 0xfd, 0xd5, 0xad, 0x85 }, + }, + { + { 0x00, 0x65, 0xca, 0xaf, 0x89, 0xec, 0x43, 0x26, 0x0f, 0x6a, 0xc5, 0xa0, 0x86, 0xe3, 0x4c, 0x29 }, + { 0x00, 0x1e, 0x3c, 0x22, 0x78, 0x66, 0x44, 0x5a, 0xf0, 0xee, 0xcc, 0xd2, 0x88, 0x96, 0xb4, 0xaa }, + }, + { + { 0x00, 0x46, 0x8c, 0xca, 0x05, 0x43, 0x89, 0xcf, 0x0a, 0x4c, 0x86, 0xc0, 0x0f, 0x49, 0x83, 0xc5 }, + { 0x00, 0x14, 0x28, 0x3c, 0x50, 0x44, 0x78, 0x6c, 0xa0, 0xb4, 0x88, 0x9c, 0xf0, 0xe4, 0xd8, 0xcc }, + }, + { + { 0x00, 0x5a, 0xb4, 0xee, 0x75, 0x2f, 0xc1, 0x9b, 0xea, 0xb0, 0x5e, 0x04, 0x9f, 0xc5, 0x2b, 0x71 }, + { 0x00, 0xc9, 0x8f, 0x46, 0x03, 0xca, 0x8c, 0x45, 0x06, 0xcf, 0x89, 0x40, 0x05, 0xcc, 0x8a, 0x43 }, + }, + }, + { + { + { 0x00, 0x46, 0x8c, 0xca, 0x05, 0x43, 0x89, 0xcf, 0x0a, 0x4c, 0x86, 0xc0, 0x0f, 0x49, 0x83, 0xc5 }, + { 0x00, 0x14, 0x28, 0x3c, 0x50, 0x44, 0x78, 0x6c, 0xa0, 0xb4, 0x88, 0x9c, 0xf0, 0xe4, 0xd8, 0xcc }, + }, + { + { 0x00, 0x5c, 0xb8, 0xe4, 0x6d, 0x31, 0xd5, 0x89, 0xda, 0x86, 0x62, 0x3e, 0xb7, 0xeb, 0x0f, 0x53 }, + { 0x00, 0xa9, 0x4f, 0xe6, 0x9e, 0x37, 0xd1, 0x78, 0x21, 0x88, 0x6e, 0xc7, 0xbf, 0x16, 0xf0, 0x59 }, + }, + { + { 0x00, 0x54, 0xa8, 0xfc, 0x4d, 0x19, 0xe5, 0xb1, 0x9a, 0xce, 0x32, 0x66, 0xd7, 0x83, 0x7f, 0x2b }, + { 0x00, 0x29, 0x52, 0x7b, 0xa4, 0x8d, 0xf6, 0xdf, 0x55, 0x7c, 0x07, 0x2e, 0xf1, 0xd8, 0xa3, 0x8a }, + }, + { + { 0x00, 0x6e, 0xdc, 0xb2, 0xa5, 0xcb, 0x79, 0x17, 0x57, 0x39, 0x8b, 0xe5, 0xf2, 0x9c, 0x2e, 0x40 }, + { 0x00, 0xae, 0x41, 0xef, 0x82, 0x2c, 0xc3, 0x6d, 0x19, 0xb7, 0x58, 0xf6, 0x9b, 0x35, 0xda, 0x74 }, + }, + }, + { + { + { 0x00, 0x68, 0xd0, 0xb8, 0xbd, 0xd5, 0x6d, 0x05, 0x67, 0x0f, 0xb7, 0xdf, 0xda, 0xb2, 0x0a, 0x62 }, + { 0x00, 0xce, 0x81, 0x4f, 0x1f, 0xd1, 0x9e, 0x50, 0x3e, 0xf0, 0xbf, 0x71, 0x21, 0xef, 0xa0, 0x6e }, + }, + { + { 0x00, 0x48, 0x90, 0xd8, 0x3d, 0x75, 0xad, 0xe5, 0x7a, 0x32, 0xea, 0xa2, 0x47, 0x0f, 0xd7, 0x9f }, + { 0x00, 0xf4, 0xf5, 0x01, 0xf7, 0x03, 0x02, 0xf6, 0xf3, 0x07, 0x06, 0xf2, 0x04, 0xf0, 0xf1, 0x05 }, + }, + { + { 0x00, 0xa0, 0x5d, 0xfd, 0xba, 0x1a, 0xe7, 0x47, 0x69, 0xc9, 0x34, 0x94, 0xd3, 0x73, 0x8e, 0x2e }, + { 0x00, 0xd2, 0xb9, 0x6b, 0x6f, 0xbd, 0xd6, 0x04, 0xde, 0x0c, 0x67, 0xb5, 0xb1, 0x63, 0x08, 0xda }, + }, + { + { 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a }, + { 0x00, 0xe0, 0xdd, 0x3d, 0xa7, 0x47, 0x7a, 0x9a, 0x53, 0xb3, 0x8e, 0x6e, 0xf4, 0x14, 0x29, 0xc9 }, + }, + }, + { + { + { 0x00, 0x70, 0xe0, 0x90, 0xdd, 0xad, 0x3d, 0x4d, 0xa7, 0xd7, 0x47, 0x37, 0x7a, 0x0a, 0x9a, 0xea }, + { 0x00, 0x53, 0xa6, 0xf5, 0x51, 0x02, 0xf7, 0xa4, 0xa2, 0xf1, 0x04, 0x57, 0xf3, 0xa0, 0x55, 0x06 }, + }, + { + { 0x00, 0x21, 0x42, 0x63, 0x84, 0xa5, 0xc6, 0xe7, 0x15, 0x34, 0x57, 0x76, 0x91, 0xb0, 0xd3, 0xf2 }, + { 0x00, 0x2a, 0x54, 0x7e, 0xa8, 0x82, 0xfc, 0xd6, 0x4d, 0x67, 0x19, 0x33, 0xe5, 0xcf, 0xb1, 0x9b }, + }, + { + { 0x00, 0x99, 0x2f, 0xb6, 0x5e, 0xc7, 0x71, 0xe8, 0xbc, 0x25, 0x93, 0x0a, 0xe2, 0x7b, 0xcd, 0x54 }, + { 0x00, 0x65, 0xca, 0xaf, 0x89, 0xec, 0x43, 0x26, 0x0f, 0x6a, 0xc5, 0xa0, 0x86, 0xe3, 0x4c, 0x29 }, + }, + { + { 0x00, 0xb9, 0x6f, 0xd6, 0xde, 0x67, 0xb1, 0x08, 0xa1, 0x18, 0xce, 0x77, 0x7f, 0xc6, 0x10, 0xa9 }, + { 0x00, 0x5f, 0xbe, 0xe1, 0x61, 0x3e, 0xdf, 0x80, 0xc2, 0x9d, 0x7c, 0x23, 0xa3, 0xfc, 0x1d, 0x42 }, + }, + }, + { + { + { 0x00, 0x3e, 0x7c, 0x42, 0xf8, 0xc6, 0x84, 0xba, 0xed, 0xd3, 0x91, 0xaf, 0x15, 0x2b, 0x69, 0x57 }, + { 0x00, 0xc7, 0x93, 0x54, 0x3b, 0xfc, 0xa8, 0x6f, 0x76, 0xb1, 0xe5, 0x22, 0x4d, 0x8a, 0xde, 0x19 }, + }, + { + { 0x00, 0xaa, 0x49, 0xe3, 0x92, 0x38, 0xdb, 0x71, 0x39, 0x93, 0x70, 0xda, 0xab, 0x01, 0xe2, 0x48 }, + { 0x00, 0x72, 0xe4, 0x96, 0xd5, 0xa7, 0x31, 0x43, 0xb7, 0xc5, 0x53, 0x21, 0x62, 0x10, 0x86, 0xf4 }, + }, + { + { 0x00, 0x95, 0x37, 0xa2, 0x6e, 0xfb, 0x59, 0xcc, 0xdc, 0x49, 0xeb, 0x7e, 0xb2, 0x27, 0x85, 0x10 }, + { 0x00, 0xa5, 0x57, 0xf2, 0xae, 0x0b, 0xf9, 0x5c, 0x41, 0xe4, 0x16, 0xb3, 0xef, 0x4a, 0xb8, 0x1d }, + }, + { + { 0x00, 0xd3, 0xbb, 0x68, 0x6b, 0xb8, 0xd0, 0x03, 0xd6, 0x05, 0x6d, 0xbe, 0xbd, 0x6e, 0x06, 0xd5 }, + { 0x00, 0xb1, 0x7f, 0xce, 0xfe, 0x4f, 0x81, 0x30, 0xe1, 0x50, 0x9e, 0x2f, 0x1f, 0xae, 0x60, 0xd1 }, + }, + }, + { + { + { 0x00, 0xcc, 0x85, 0x49, 0x17, 0xdb, 0x92, 0x5e, 0x2e, 0xe2, 0xab, 0x67, 0x39, 0xf5, 0xbc, 0x70 }, + { 0x00, 0x5c, 0xb8, 0xe4, 0x6d, 0x31, 0xd5, 0x89, 0xda, 0x86, 0x62, 0x3e, 0xb7, 0xeb, 0x0f, 0x53 }, + }, + { + { 0x00, 0xcd, 0x87, 0x4a, 0x13, 0xde, 0x94, 0x59, 0x26, 0xeb, 0xa1, 0x6c, 0x35, 0xf8, 0xb2, 0x7f }, + { 0x00, 0x4c, 0x98, 0xd4, 0x2d, 0x61, 0xb5, 0xf9, 0x5a, 0x16, 0xc2, 0x8e, 0x77, 0x3b, 0xef, 0xa3 }, + }, + { + { 0x00, 0x53, 0xa6, 0xf5, 0x51, 0x02, 0xf7, 0xa4, 0xa2, 0xf1, 0x04, 0x57, 0xf3, 0xa0, 0x55, 0x06 }, + { 0x00, 0x59, 0xb2, 0xeb, 0x79, 0x20, 0xcb, 0x92, 0xf2, 0xab, 0x40, 0x19, 0x8b, 0xd2, 0x39, 0x60 }, + }, + { + { 0x00, 0xb6, 0x71, 0xc7, 0xe2, 0x54, 0x93, 0x25, 0xd9, 0x6f, 0xa8, 0x1e, 0x3b, 0x8d, 0x4a, 0xfc }, + { 0x00, 0xaf, 0x43, 0xec, 0x86, 0x29, 0xc5, 0x6a, 0x11, 0xbe, 0x52, 0xfd, 0x97, 0x38, 0xd4, 0x7b }, + }, + }, + { + { + { 0x00, 0x7d, 0xfa, 0x87, 0xe9, 0x94, 0x13, 0x6e, 0xcf, 0xb2, 0x35, 0x48, 0x26, 0x5b, 0xdc, 0xa1 }, + { 0x00, 0x83, 0x1b, 0x98, 0x36, 0xb5, 0x2d, 0xae, 0x6c, 0xef, 0x77, 0xf4, 0x5a, 0xd9, 0x41, 0xc2 }, + }, + { + { 0x00, 0x4e, 0x9c, 0xd2, 0x25, 0x6b, 0xb9, 0xf7, 0x4a, 0x04, 0xd6, 0x98, 0x6f, 0x21, 0xf3, 0xbd }, + { 0x00, 0x94, 0x35, 0xa1, 0x6a, 0xfe, 0x5f, 0xcb, 0xd4, 0x40, 0xe1, 0x75, 0xbe, 0x2a, 0x8b, 0x1f }, + }, + { + { 0x00, 0x9b, 0x2b, 0xb0, 0x56, 0xcd, 0x7d, 0xe6, 0xac, 0x37, 0x87, 0x1c, 0xfa, 0x61, 0xd1, 0x4a }, + { 0x00, 0x45, 0x8a, 0xcf, 0x09, 0x4c, 0x83, 0xc6, 0x12, 0x57, 0x98, 0xdd, 0x1b, 0x5e, 0x91, 0xd4 }, + }, + { + { 0x00, 0x3e, 0x7c, 0x42, 0xf8, 0xc6, 0x84, 0xba, 0xed, 0xd3, 0x91, 0xaf, 0x15, 0x2b, 0x69, 0x57 }, + { 0x00, 0xc7, 0x93, 0x54, 0x3b, 0xfc, 0xa8, 0x6f, 0x76, 0xb1, 0xe5, 0x22, 0x4d, 0x8a, 0xde, 0x19 }, + }, + }, + { + { + { 0x00, 0x74, 0xe8, 0x9c, 0xcd, 0xb9, 0x25, 0x51, 0x87, 0xf3, 0x6f, 0x1b, 0x4a, 0x3e, 0xa2, 0xd6 }, + { 0x00, 0x13, 0x26, 0x35, 0x4c, 0x5f, 0x6a, 0x79, 0x98, 0x8b, 0xbe, 0xad, 0xd4, 0xc7, 0xf2, 0xe1 }, + }, + { + { 0x00, 0xc1, 0x9f, 0x5e, 0x23, 0xe2, 0xbc, 0x7d, 0x46, 0x87, 0xd9, 0x18, 0x65, 0xa4, 0xfa, 0x3b }, + { 0x00, 0x8c, 0x05, 0x89, 0x0a, 0x86, 0x0f, 0x83, 0x14, 0x98, 0x11, 0x9d, 0x1e, 0x92, 0x1b, 0x97 }, + }, + { + { 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69 }, + { 0x00, 0xb0, 0x7d, 0xcd, 0xfa, 0x4a, 0x87, 0x37, 0xe9, 0x59, 0x94, 0x24, 0x13, 0xa3, 0x6e, 0xde }, + }, + { + { 0x00, 0x36, 0x6c, 0x5a, 0xd8, 0xee, 0xb4, 0x82, 0xad, 0x9b, 0xc1, 0xf7, 0x75, 0x43, 0x19, 0x2f }, + { 0x00, 0x47, 0x8e, 0xc9, 0x01, 0x46, 0x8f, 0xc8, 0x02, 0x45, 0x8c, 0xcb, 0x03, 0x44, 0x8d, 0xca }, + }, + }, + { + { + { 0x00, 0x75, 0xea, 0x9f, 0xc9, 0xbc, 0x23, 0x56, 0x8f, 0xfa, 0x65, 0x10, 0x46, 0x33, 0xac, 0xd9 }, + { 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11 }, + }, + { + { 0x00, 0x61, 0xc2, 0xa3, 0x99, 0xf8, 0x5b, 0x3a, 0x2f, 0x4e, 0xed, 0x8c, 0xb6, 0xd7, 0x74, 0x15 }, + { 0x00, 0x5e, 0xbc, 0xe2, 0x65, 0x3b, 0xd9, 0x87, 0xca, 0x94, 0x76, 0x28, 0xaf, 0xf1, 0x13, 0x4d }, + }, + { + { 0x00, 0xc7, 0x93, 0x54, 0x3b, 0xfc, 0xa8, 0x6f, 0x76, 0xb1, 0xe5, 0x22, 0x4d, 0x8a, 0xde, 0x19 }, + { 0x00, 0xec, 0xc5, 0x29, 0x97, 0x7b, 0x52, 0xbe, 0x33, 0xdf, 0xf6, 0x1a, 0xa4, 0x48, 0x61, 0x8d }, + }, + { + { 0x00, 0x86, 0x11, 0x97, 0x22, 0xa4, 0x33, 0xb5, 0x44, 0xc2, 0x55, 0xd3, 0x66, 0xe0, 0x77, 0xf1 }, + { 0x00, 0x88, 0x0d, 0x85, 0x1a, 0x92, 0x17, 0x9f, 0x34, 0xbc, 0x39, 0xb1, 0x2e, 0xa6, 0x23, 0xab }, + }, + }, + { + { + { 0x00, 0xb5, 0x77, 0xc2, 0xee, 0x5b, 0x99, 0x2c, 0xc1, 0x74, 0xb6, 0x03, 0x2f, 0x9a, 0x58, 0xed }, + { 0x00, 0x9f, 0x23, 0xbc, 0x46, 0xd9, 0x65, 0xfa, 0x8c, 0x13, 0xaf, 0x30, 0xca, 0x55, 0xe9, 0x76 }, + }, + { + { 0x00, 0x38, 0x70, 0x48, 0xe0, 0xd8, 0x90, 0xa8, 0xdd, 0xe5, 0xad, 0x95, 0x3d, 0x05, 0x4d, 0x75 }, + { 0x00, 0xa7, 0x53, 0xf4, 0xa6, 0x01, 0xf5, 0x52, 0x51, 0xf6, 0x02, 0xa5, 0xf7, 0x50, 0xa4, 0x03 }, + }, + { + { 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77 }, + { 0x00, 0x90, 0x3d, 0xad, 0x7a, 0xea, 0x47, 0xd7, 0xf4, 0x64, 0xc9, 0x59, 0x8e, 0x1e, 0xb3, 0x23 }, + }, + { + { 0x00, 0xbf, 0x63, 0xdc, 0xc6, 0x79, 0xa5, 0x1a, 0x91, 0x2e, 0xf2, 0x4d, 0x57, 0xe8, 0x34, 0x8b }, + { 0x00, 0x3f, 0x7e, 0x41, 0xfc, 0xc3, 0x82, 0xbd, 0xe5, 0xda, 0x9b, 0xa4, 0x19, 0x26, 0x67, 0x58 }, + }, + }, + { + { + { 0x00, 0xdb, 0xab, 0x70, 0x4b, 0x90, 0xe0, 0x3b, 0x96, 0x4d, 0x3d, 0xe6, 0xdd, 0x06, 0x76, 0xad }, + { 0x00, 0x31, 0x62, 0x53, 0xc4, 0xf5, 0xa6, 0x97, 0x95, 0xa4, 0xf7, 0xc6, 0x51, 0x60, 0x33, 0x02 }, + }, + { + { 0x00, 0x0a, 0x14, 0x1e, 0x28, 0x22, 0x3c, 0x36, 0x50, 0x5a, 0x44, 0x4e, 0x78, 0x72, 0x6c, 0x66 }, + { 0x00, 0xa0, 0x5d, 0xfd, 0xba, 0x1a, 0xe7, 0x47, 0x69, 0xc9, 0x34, 0x94, 0xd3, 0x73, 0x8e, 0x2e }, + }, + { + { 0x00, 0xc0, 0x9d, 0x5d, 0x27, 0xe7, 0xba, 0x7a, 0x4e, 0x8e, 0xd3, 0x13, 0x69, 0xa9, 0xf4, 0x34 }, + { 0x00, 0x9c, 0x25, 0xb9, 0x4a, 0xd6, 0x6f, 0xf3, 0x94, 0x08, 0xb1, 0x2d, 0xde, 0x42, 0xfb, 0x67 }, + }, + { + { 0x00, 0xa2, 0x59, 0xfb, 0xb2, 0x10, 0xeb, 0x49, 0x79, 0xdb, 0x20, 0x82, 0xcb, 0x69, 0x92, 0x30 }, + { 0x00, 0xf2, 0xf9, 0x0b, 0xef, 0x1d, 0x16, 0xe4, 0xc3, 0x31, 0x3a, 0xc8, 0x2c, 0xde, 0xd5, 0x27 }, + }, + }, + { + { + { 0x00, 0x0c, 0x18, 0x14, 0x30, 0x3c, 0x28, 0x24, 0x60, 0x6c, 0x78, 0x74, 0x50, 0x5c, 0x48, 0x44 }, + { 0x00, 0xc0, 0x9d, 0x5d, 0x27, 0xe7, 0xba, 0x7a, 0x4e, 0x8e, 0xd3, 0x13, 0x69, 0xa9, 0xf4, 0x34 }, + }, + { + { 0x00, 0x3e, 0x7c, 0x42, 0xf8, 0xc6, 0x84, 0xba, 0xed, 0xd3, 0x91, 0xaf, 0x15, 0x2b, 0x69, 0x57 }, + { 0x00, 0xc7, 0x93, 0x54, 0x3b, 0xfc, 0xa8, 0x6f, 0x76, 0xb1, 0xe5, 0x22, 0x4d, 0x8a, 0xde, 0x19 }, + }, + { + { 0x00, 0x78, 0xf0, 0x88, 0xfd, 0x85, 0x0d, 0x75, 0xe7, 0x9f, 0x17, 0x6f, 0x1a, 0x62, 0xea, 0x92 }, + { 0x00, 0xd3, 0xbb, 0x68, 0x6b, 0xb8, 0xd0, 0x03, 0xd6, 0x05, 0x6d, 0xbe, 0xbd, 0x6e, 0x06, 0xd5 }, + }, + { + { 0x00, 0xa7, 0x53, 0xf4, 0xa6, 0x01, 0xf5, 0x52, 0x51, 0xf6, 0x02, 0xa5, 0xf7, 0x50, 0xa4, 0x03 }, + { 0x00, 0xa2, 0x59, 0xfb, 0xb2, 0x10, 0xeb, 0x49, 0x79, 0xdb, 0x20, 0x82, 0xcb, 0x69, 0x92, 0x30 }, + }, + }, + { + { + { 0x00, 0xdf, 0xa3, 0x7c, 0x5b, 0x84, 0xf8, 0x27, 0xb6, 0x69, 0x15, 0xca, 0xed, 0x32, 0x4e, 0x91 }, + { 0x00, 0x71, 0xe2, 0x93, 0xd9, 0xa8, 0x3b, 0x4a, 0xaf, 0xde, 0x4d, 0x3c, 0x76, 0x07, 0x94, 0xe5 }, + }, + { + { 0x00, 0xd1, 0xbf, 0x6e, 0x63, 0xb2, 0xdc, 0x0d, 0xc6, 0x17, 0x79, 0xa8, 0xa5, 0x74, 0x1a, 0xcb }, + { 0x00, 0x91, 0x3f, 0xae, 0x7e, 0xef, 0x41, 0xd0, 0xfc, 0x6d, 0xc3, 0x52, 0x82, 0x13, 0xbd, 0x2c }, + }, + { + { 0x00, 0x89, 0x0f, 0x86, 0x1e, 0x97, 0x11, 0x98, 0x3c, 0xb5, 0x33, 0xba, 0x22, 0xab, 0x2d, 0xa4 }, + { 0x00, 0x78, 0xf0, 0x88, 0xfd, 0x85, 0x0d, 0x75, 0xe7, 0x9f, 0x17, 0x6f, 0x1a, 0x62, 0xea, 0x92 }, + }, + { + { 0x00, 0x30, 0x60, 0x50, 0xc0, 0xf0, 0xa0, 0x90, 0x9d, 0xad, 0xfd, 0xcd, 0x5d, 0x6d, 0x3d, 0x0d }, + { 0x00, 0x27, 0x4e, 0x69, 0x9c, 0xbb, 0xd2, 0xf5, 0x25, 0x02, 0x6b, 0x4c, 0xb9, 0x9e, 0xf7, 0xd0 }, + }, + }, + { + { + { 0x00, 0x9e, 0x21, 0xbf, 0x42, 0xdc, 0x63, 0xfd, 0x84, 0x1a, 0xa5, 0x3b, 0xc6, 0x58, 0xe7, 0x79 }, + { 0x00, 0x15, 0x2a, 0x3f, 0x54, 0x41, 0x7e, 0x6b, 0xa8, 0xbd, 0x82, 0x97, 0xfc, 0xe9, 0xd6, 0xc3 }, + }, + { + { 0x00, 0xd5, 0xb7, 0x62, 0x73, 0xa6, 0xc4, 0x11, 0xe6, 0x33, 0x51, 0x84, 0x95, 0x40, 0x22, 0xf7 }, + { 0x00, 0xd1, 0xbf, 0x6e, 0x63, 0xb2, 0xdc, 0x0d, 0xc6, 0x17, 0x79, 0xa8, 0xa5, 0x74, 0x1a, 0xcb }, + }, + { + { 0x00, 0x92, 0x39, 0xab, 0x72, 0xe0, 0x4b, 0xd9, 0xe4, 0x76, 0xdd, 0x4f, 0x96, 0x04, 0xaf, 0x3d }, + { 0x00, 0xd5, 0xb7, 0x62, 0x73, 0xa6, 0xc4, 0x11, 0xe6, 0x33, 0x51, 0x84, 0x95, 0x40, 0x22, 0xf7 }, + }, + { + { 0x00, 0x14, 0x28, 0x3c, 0x50, 0x44, 0x78, 0x6c, 0xa0, 0xb4, 0x88, 0x9c, 0xf0, 0xe4, 0xd8, 0xcc }, + { 0x00, 0x5d, 0xba, 0xe7, 0x69, 0x34, 0xd3, 0x8e, 0xd2, 0x8f, 0x68, 0x35, 0xbb, 0xe6, 0x01, 0x5c }, + }, + }, + { + { + { 0x00, 0x6d, 0xda, 0xb7, 0xa9, 0xc4, 0x73, 0x1e, 0x4f, 0x22, 0x95, 0xf8, 0xe6, 0x8b, 0x3c, 0x51 }, + { 0x00, 0x9e, 0x21, 0xbf, 0x42, 0xdc, 0x63, 0xfd, 0x84, 0x1a, 0xa5, 0x3b, 0xc6, 0x58, 0xe7, 0x79 }, + }, + { + { 0x00, 0xcb, 0x8b, 0x40, 0x0b, 0xc0, 0x80, 0x4b, 0x16, 0xdd, 0x9d, 0x56, 0x1d, 0xd6, 0x96, 0x5d }, + { 0x00, 0x2c, 0x58, 0x74, 0xb0, 0x9c, 0xe8, 0xc4, 0x7d, 0x51, 0x25, 0x09, 0xcd, 0xe1, 0x95, 0xb9 }, + }, + { + { 0x00, 0xe3, 0xdb, 0x38, 0xab, 0x48, 0x70, 0x93, 0x4b, 0xa8, 0x90, 0x73, 0xe0, 0x03, 0x3b, 0xd8 }, + { 0x00, 0x96, 0x31, 0xa7, 0x62, 0xf4, 0x53, 0xc5, 0xc4, 0x52, 0xf5, 0x63, 0xa6, 0x30, 0x97, 0x01 }, + }, + { + { 0x00, 0xeb, 0xcb, 0x20, 0x8b, 0x60, 0x40, 0xab, 0x0b, 0xe0, 0xc0, 0x2b, 0x80, 0x6b, 0x4b, 0xa0 }, + { 0x00, 0x16, 0x2c, 0x3a, 0x58, 0x4e, 0x74, 0x62, 0xb0, 0xa6, 0x9c, 0x8a, 0xe8, 0xfe, 0xc4, 0xd2 }, + }, + }, + { + { + { 0x00, 0x79, 0xf2, 0x8b, 0xf9, 0x80, 0x0b, 0x72, 0xef, 0x96, 0x1d, 0x64, 0x16, 0x6f, 0xe4, 0x9d }, + { 0x00, 0xc3, 0x9b, 0x58, 0x2b, 0xe8, 0xb0, 0x73, 0x56, 0x95, 0xcd, 0x0e, 0x7d, 0xbe, 0xe6, 0x25 }, + }, + { + { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0 }, + { 0x00, 0x1d, 0x3a, 0x27, 0x74, 0x69, 0x4e, 0x53, 0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb }, + }, + { + { 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b }, + { 0x00, 0xd0, 0xbd, 0x6d, 0x67, 0xb7, 0xda, 0x0a, 0xce, 0x1e, 0x73, 0xa3, 0xa9, 0x79, 0x14, 0xc4 }, + }, + { + { 0x00, 0xc7, 0x93, 0x54, 0x3b, 0xfc, 0xa8, 0x6f, 0x76, 0xb1, 0xe5, 0x22, 0x4d, 0x8a, 0xde, 0x19 }, + { 0x00, 0xec, 0xc5, 0x29, 0x97, 0x7b, 0x52, 0xbe, 0x33, 0xdf, 0xf6, 0x1a, 0xa4, 0x48, 0x61, 0x8d }, + }, + }, + { + { + { 0x00, 0xeb, 0xcb, 0x20, 0x8b, 0x60, 0x40, 0xab, 0x0b, 0xe0, 0xc0, 0x2b, 0x80, 0x6b, 0x4b, 0xa0 }, + { 0x00, 0x16, 0x2c, 0x3a, 0x58, 0x4e, 0x74, 0x62, 0xb0, 0xa6, 0x9c, 0x8a, 0xe8, 0xfe, 0xc4, 0xd2 }, + }, + { + { 0x00, 0xdc, 0xa5, 0x79, 0x57, 0x8b, 0xf2, 0x2e, 0xae, 0x72, 0x0b, 0xd7, 0xf9, 0x25, 0x5c, 0x80 }, + { 0x00, 0x41, 0x82, 0xc3, 0x19, 0x58, 0x9b, 0xda, 0x32, 0x73, 0xb0, 0xf1, 0x2b, 0x6a, 0xa9, 0xe8 }, + }, + { + { 0x00, 0xb0, 0x7d, 0xcd, 0xfa, 0x4a, 0x87, 0x37, 0xe9, 0x59, 0x94, 0x24, 0x13, 0xa3, 0x6e, 0xde }, + { 0x00, 0xcf, 0x83, 0x4c, 0x1b, 0xd4, 0x98, 0x57, 0x36, 0xf9, 0xb5, 0x7a, 0x2d, 0xe2, 0xae, 0x61 }, + }, + { + { 0x00, 0x2d, 0x5a, 0x77, 0xb4, 0x99, 0xee, 0xc3, 0x75, 0x58, 0x2f, 0x02, 0xc1, 0xec, 0x9b, 0xb6 }, + { 0x00, 0xea, 0xc9, 0x23, 0x8f, 0x65, 0x46, 0xac, 0x03, 0xe9, 0xca, 0x20, 0x8c, 0x66, 0x45, 0xaf }, + }, + }, + { + { + { 0x00, 0x63, 0xc6, 0xa5, 0x91, 0xf2, 0x57, 0x34, 0x3f, 0x5c, 0xf9, 0x9a, 0xae, 0xcd, 0x68, 0x0b }, + { 0x00, 0x7e, 0xfc, 0x82, 0xe5, 0x9b, 0x19, 0x67, 0xd7, 0xa9, 0x2b, 0x55, 0x32, 0x4c, 0xce, 0xb0 }, + }, + { + { 0x00, 0x5e, 0xbc, 0xe2, 0x65, 0x3b, 0xd9, 0x87, 0xca, 0x94, 0x76, 0x28, 0xaf, 0xf1, 0x13, 0x4d }, + { 0x00, 0x89, 0x0f, 0x86, 0x1e, 0x97, 0x11, 0x98, 0x3c, 0xb5, 0x33, 0xba, 0x22, 0xab, 0x2d, 0xa4 }, + }, + { + { 0x00, 0x2a, 0x54, 0x7e, 0xa8, 0x82, 0xfc, 0xd6, 0x4d, 0x67, 0x19, 0x33, 0xe5, 0xcf, 0xb1, 0x9b }, + { 0x00, 0x9a, 0x29, 0xb3, 0x52, 0xc8, 0x7b, 0xe1, 0xa4, 0x3e, 0x8d, 0x17, 0xf6, 0x6c, 0xdf, 0x45 }, + }, + { + { 0x00, 0x96, 0x31, 0xa7, 0x62, 0xf4, 0x53, 0xc5, 0xc4, 0x52, 0xf5, 0x63, 0xa6, 0x30, 0x97, 0x01 }, + { 0x00, 0x95, 0x37, 0xa2, 0x6e, 0xfb, 0x59, 0xcc, 0xdc, 0x49, 0xeb, 0x7e, 0xb2, 0x27, 0x85, 0x10 }, + }, + }, + { + { + { 0x00, 0x9f, 0x23, 0xbc, 0x46, 0xd9, 0x65, 0xfa, 0x8c, 0x13, 0xaf, 0x30, 0xca, 0x55, 0xe9, 0x76 }, + { 0x00, 0x05, 0x0a, 0x0f, 0x14, 0x11, 0x1e, 0x1b, 0x28, 0x2d, 0x22, 0x27, 0x3c, 0x39, 0x36, 0x33 }, + }, + { + { 0x00, 0x24, 0x48, 0x6c, 0x90, 0xb4, 0xd8, 0xfc, 0x3d, 0x19, 0x75, 0x51, 0xad, 0x89, 0xe5, 0xc1 }, + { 0x00, 0x7a, 0xf4, 0x8e, 0xf5, 0x8f, 0x01, 0x7b, 0xf7, 0x8d, 0x03, 0x79, 0x02, 0x78, 0xf6, 0x8c }, + }, + { + { 0x00, 0x8c, 0x05, 0x89, 0x0a, 0x86, 0x0f, 0x83, 0x14, 0x98, 0x11, 0x9d, 0x1e, 0x92, 0x1b, 0x97 }, + { 0x00, 0x28, 0x50, 0x78, 0xa0, 0x88, 0xf0, 0xd8, 0x5d, 0x75, 0x0d, 0x25, 0xfd, 0xd5, 0xad, 0x85 }, + }, + { + { 0x00, 0x67, 0xce, 0xa9, 0x81, 0xe6, 0x4f, 0x28, 0x1f, 0x78, 0xd1, 0xb6, 0x9e, 0xf9, 0x50, 0x37 }, + { 0x00, 0x3e, 0x7c, 0x42, 0xf8, 0xc6, 0x84, 0xba, 0xed, 0xd3, 0x91, 0xaf, 0x15, 0x2b, 0x69, 0x57 }, + }, + }, + { + { + { 0x00, 0x38, 0x70, 0x48, 0xe0, 0xd8, 0x90, 0xa8, 0xdd, 0xe5, 0xad, 0x95, 0x3d, 0x05, 0x4d, 0x75 }, + { 0x00, 0xa7, 0x53, 0xf4, 0xa6, 0x01, 0xf5, 0x52, 0x51, 0xf6, 0x02, 0xa5, 0xf7, 0x50, 0xa4, 0x03 }, + }, + { + { 0x00, 0xb8, 0x6d, 0xd5, 0xda, 0x62, 0xb7, 0x0f, 0xa9, 0x11, 0xc4, 0x7c, 0x73, 0xcb, 0x1e, 0xa6 }, + { 0x00, 0x4f, 0x9e, 0xd1, 0x21, 0x6e, 0xbf, 0xf0, 0x42, 0x0d, 0xdc, 0x93, 0x63, 0x2c, 0xfd, 0xb2 }, + }, + { + { 0x00, 0xfb, 0xeb, 0x10, 0xcb, 0x30, 0x20, 0xdb, 0x8b, 0x70, 0x60, 0x9b, 0x40, 0xbb, 0xab, 0x50 }, + { 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69 }, + }, + { + { 0x00, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0, 0x1d, 0x3d, 0x5d, 0x7d, 0x9d, 0xbd, 0xdd, 0xfd }, + { 0x00, 0x3a, 0x74, 0x4e, 0xe8, 0xd2, 0x9c, 0xa6, 0xcd, 0xf7, 0xb9, 0x83, 0x25, 0x1f, 0x51, 0x6b }, + }, + }, + { + { + { 0x00, 0xd0, 0xbd, 0x6d, 0x67, 0xb7, 0xda, 0x0a, 0xce, 0x1e, 0x73, 0xa3, 0xa9, 0x79, 0x14, 0xc4 }, + { 0x00, 0x81, 0x1f, 0x9e, 0x3e, 0xbf, 0x21, 0xa0, 0x7c, 0xfd, 0x63, 0xe2, 0x42, 0xc3, 0x5d, 0xdc }, + }, + { + { 0x00, 0xde, 0xa1, 0x7f, 0x5f, 0x81, 0xfe, 0x20, 0xbe, 0x60, 0x1f, 0xc1, 0xe1, 0x3f, 0x40, 0x9e }, + { 0x00, 0x61, 0xc2, 0xa3, 0x99, 0xf8, 0x5b, 0x3a, 0x2f, 0x4e, 0xed, 0x8c, 0xb6, 0xd7, 0x74, 0x15 }, + }, + { + { 0x00, 0x17, 0x2e, 0x39, 0x5c, 0x4b, 0x72, 0x65, 0xb8, 0xaf, 0x96, 0x81, 0xe4, 0xf3, 0xca, 0xdd }, + { 0x00, 0x6d, 0xda, 0xb7, 0xa9, 0xc4, 0x73, 0x1e, 0x4f, 0x22, 0x95, 0xf8, 0xe6, 0x8b, 0x3c, 0x51 }, + }, + { + { 0x00, 0xb5, 0x77, 0xc2, 0xee, 0x5b, 0x99, 0x2c, 0xc1, 0x74, 0xb6, 0x03, 0x2f, 0x9a, 0x58, 0xed }, + { 0x00, 0x9f, 0x23, 0xbc, 0x46, 0xd9, 0x65, 0xfa, 0x8c, 0x13, 0xaf, 0x30, 0xca, 0x55, 0xe9, 0x76 }, + }, + }, + { + { + { 0x00, 0x94, 0x35, 0xa1, 0x6a, 0xfe, 0x5f, 0xcb, 0xd4, 0x40, 0xe1, 0x75, 0xbe, 0x2a, 0x8b, 0x1f }, + { 0x00, 0xb5, 0x77, 0xc2, 0xee, 0x5b, 0x99, 0x2c, 0xc1, 0x74, 0xb6, 0x03, 0x2f, 0x9a, 0x58, 0xed }, + }, + { + { 0x00, 0x79, 0xf2, 0x8b, 0xf9, 0x80, 0x0b, 0x72, 0xef, 0x96, 0x1d, 0x64, 0x16, 0x6f, 0xe4, 0x9d }, + { 0x00, 0xc3, 0x9b, 0x58, 0x2b, 0xe8, 0xb0, 0x73, 0x56, 0x95, 0xcd, 0x0e, 0x7d, 0xbe, 0xe6, 0x25 }, + }, + { + { 0x00, 0x3f, 0x7e, 0x41, 0xfc, 0xc3, 0x82, 0xbd, 0xe5, 0xda, 0x9b, 0xa4, 0x19, 0x26, 0x67, 0x58 }, + { 0x00, 0xd7, 0xb3, 0x64, 0x7b, 0xac, 0xc8, 0x1f, 0xf6, 0x21, 0x45, 0x92, 0x8d, 0x5a, 0x3e, 0xe9 }, + }, + { + { 0x00, 0x9a, 0x29, 0xb3, 0x52, 0xc8, 0x7b, 0xe1, 0xa4, 0x3e, 0x8d, 0x17, 0xf6, 0x6c, 0xdf, 0x45 }, + { 0x00, 0x55, 0xaa, 0xff, 0x49, 0x1c, 0xe3, 0xb6, 0x92, 0xc7, 0x38, 0x6d, 0xdb, 0x8e, 0x71, 0x24 }, + }, + }, + { + { + { 0x00, 0xa5, 0x57, 0xf2, 0xae, 0x0b, 0xf9, 0x5c, 0x41, 0xe4, 0x16, 0xb3, 0xef, 0x4a, 0xb8, 0x1d }, + { 0x00, 0x82, 0x19, 0x9b, 0x32, 0xb0, 0x2b, 0xa9, 0x64, 0xe6, 0x7d, 0xff, 0x56, 0xd4, 0x4f, 0xcd }, + }, + { + { 0x00, 0x36, 0x6c, 0x5a, 0xd8, 0xee, 0xb4, 0x82, 0xad, 0x9b, 0xc1, 0xf7, 0x75, 0x43, 0x19, 0x2f }, + { 0x00, 0x47, 0x8e, 0xc9, 0x01, 0x46, 0x8f, 0xc8, 0x02, 0x45, 0x8c, 0xcb, 0x03, 0x44, 0x8d, 0xca }, + }, + { + { 0x00, 0x26, 0x4c, 0x6a, 0x98, 0xbe, 0xd4, 0xf2, 0x2d, 0x0b, 0x61, 0x47, 0xb5, 0x93, 0xf9, 0xdf }, + { 0x00, 0x5a, 0xb4, 0xee, 0x75, 0x2f, 0xc1, 0x9b, 0xea, 0xb0, 0x5e, 0x04, 0x9f, 0xc5, 0x2b, 0x71 }, + }, + { + { 0x00, 0xe0, 0xdd, 0x3d, 0xa7, 0x47, 0x7a, 0x9a, 0x53, 0xb3, 0x8e, 0x6e, 0xf4, 0x14, 0x29, 0xc9 }, + { 0x00, 0xa6, 0x51, 0xf7, 0xa2, 0x04, 0xf3, 0x55, 0x59, 0xff, 0x08, 0xae, 0xfb, 0x5d, 0xaa, 0x0c }, + }, + }, + { + { + { 0x00, 0x24, 0x48, 0x6c, 0x90, 0xb4, 0xd8, 0xfc, 0x3d, 0x19, 0x75, 0x51, 0xad, 0x89, 0xe5, 0xc1 }, + { 0x00, 0x7a, 0xf4, 0x8e, 0xf5, 0x8f, 0x01, 0x7b, 0xf7, 0x8d, 0x03, 0x79, 0x02, 0x78, 0xf6, 0x8c }, + }, + { + { 0x00, 0x43, 0x86, 0xc5, 0x11, 0x52, 0x97, 0xd4, 0x22, 0x61, 0xa4, 0xe7, 0x33, 0x70, 0xb5, 0xf6 }, + { 0x00, 0x44, 0x88, 0xcc, 0x0d, 0x49, 0x85, 0xc1, 0x1a, 0x5e, 0x92, 0xd6, 0x17, 0x53, 0x9f, 0xdb }, + }, + { + { 0x00, 0x65, 0xca, 0xaf, 0x89, 0xec, 0x43, 0x26, 0x0f, 0x6a, 0xc5, 0xa0, 0x86, 0xe3, 0x4c, 0x29 }, + { 0x00, 0x1e, 0x3c, 0x22, 0x78, 0x66, 0x44, 0x5a, 0xf0, 0xee, 0xcc, 0xd2, 0x88, 0x96, 0xb4, 0xaa }, + }, + { + { 0x00, 0xa8, 0x4d, 0xe5, 0x9a, 0x32, 0xd7, 0x7f, 0x29, 0x81, 0x64, 0xcc, 0xb3, 0x1b, 0xfe, 0x56 }, + { 0x00, 0x52, 0xa4, 0xf6, 0x55, 0x07, 0xf1, 0xa3, 0xaa, 0xf8, 0x0e, 0x5c, 0xff, 0xad, 0x5b, 0x09 }, + }, + }, + { + { + { 0x00, 0x89, 0x0f, 0x86, 0x1e, 0x97, 0x11, 0x98, 0x3c, 0xb5, 0x33, 0xba, 0x22, 0xab, 0x2d, 0xa4 }, + { 0x00, 0x78, 0xf0, 0x88, 0xfd, 0x85, 0x0d, 0x75, 0xe7, 0x9f, 0x17, 0x6f, 0x1a, 0x62, 0xea, 0x92 }, + }, + { + { 0x00, 0x72, 0xe4, 0x96, 0xd5, 0xa7, 0x31, 0x43, 0xb7, 0xc5, 0x53, 0x21, 0x62, 0x10, 0x86, 0xf4 }, + { 0x00, 0x73, 0xe6, 0x95, 0xd1, 0xa2, 0x37, 0x44, 0xbf, 0xcc, 0x59, 0x2a, 0x6e, 0x1d, 0x88, 0xfb }, + }, + { + { 0x00, 0x87, 0x13, 0x94, 0x26, 0xa1, 0x35, 0xb2, 0x4c, 0xcb, 0x5f, 0xd8, 0x6a, 0xed, 0x79, 0xfe }, + { 0x00, 0x98, 0x2d, 0xb5, 0x5a, 0xc2, 0x77, 0xef, 0xb4, 0x2c, 0x99, 0x01, 0xee, 0x76, 0xc3, 0x5b }, + }, + { + { 0x00, 0xc6, 0x91, 0x57, 0x3f, 0xf9, 0xae, 0x68, 0x7e, 0xb8, 0xef, 0x29, 0x41, 0x87, 0xd0, 0x16 }, + { 0x00, 0xfc, 0xe5, 0x19, 0xd7, 0x2b, 0x32, 0xce, 0xb3, 0x4f, 0x56, 0xaa, 0x64, 0x98, 0x81, 0x7d }, + }, + }, + { + { + { 0x00, 0x5c, 0xb8, 0xe4, 0x6d, 0x31, 0xd5, 0x89, 0xda, 0x86, 0x62, 0x3e, 0xb7, 0xeb, 0x0f, 0x53 }, + { 0x00, 0xa9, 0x4f, 0xe6, 0x9e, 0x37, 0xd1, 0x78, 0x21, 0x88, 0x6e, 0xc7, 0xbf, 0x16, 0xf0, 0x59 }, + }, + { + { 0x00, 0xd9, 0xaf, 0x76, 0x43, 0x9a, 0xec, 0x35, 0x86, 0x5f, 0x29, 0xf0, 0xc5, 0x1c, 0x6a, 0xb3 }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + }, + { + { 0x00, 0x27, 0x4e, 0x69, 0x9c, 0xbb, 0xd2, 0xf5, 0x25, 0x02, 0x6b, 0x4c, 0xb9, 0x9e, 0xf7, 0xd0 }, + { 0x00, 0x4a, 0x94, 0xde, 0x35, 0x7f, 0xa1, 0xeb, 0x6a, 0x20, 0xfe, 0xb4, 0x5f, 0x15, 0xcb, 0x81 }, + }, + { + { 0x00, 0x80, 0x1d, 0x9d, 0x3a, 0xba, 0x27, 0xa7, 0x74, 0xf4, 0x69, 0xe9, 0x4e, 0xce, 0x53, 0xd3 }, + { 0x00, 0xe8, 0xcd, 0x25, 0x87, 0x6f, 0x4a, 0xa2, 0x13, 0xfb, 0xde, 0x36, 0x94, 0x7c, 0x59, 0xb1 }, + }, + }, + { + { + { 0x00, 0x65, 0xca, 0xaf, 0x89, 0xec, 0x43, 0x26, 0x0f, 0x6a, 0xc5, 0xa0, 0x86, 0xe3, 0x4c, 0x29 }, + { 0x00, 0x1e, 0x3c, 0x22, 0x78, 0x66, 0x44, 0x5a, 0xf0, 0xee, 0xcc, 0xd2, 0x88, 0x96, 0xb4, 0xaa }, + }, + { + { 0x00, 0xf8, 0xed, 0x15, 0xc7, 0x3f, 0x2a, 0xd2, 0x93, 0x6b, 0x7e, 0x86, 0x54, 0xac, 0xb9, 0x41 }, + { 0x00, 0x3b, 0x76, 0x4d, 0xec, 0xd7, 0x9a, 0xa1, 0xc5, 0xfe, 0xb3, 0x88, 0x29, 0x12, 0x5f, 0x64 }, + }, + { + { 0x00, 0x5c, 0xb8, 0xe4, 0x6d, 0x31, 0xd5, 0x89, 0xda, 0x86, 0x62, 0x3e, 0xb7, 0xeb, 0x0f, 0x53 }, + { 0x00, 0xa9, 0x4f, 0xe6, 0x9e, 0x37, 0xd1, 0x78, 0x21, 0x88, 0x6e, 0xc7, 0xbf, 0x16, 0xf0, 0x59 }, + }, + { + { 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c }, + { 0x00, 0x40, 0x80, 0xc0, 0x1d, 0x5d, 0x9d, 0xdd, 0x3a, 0x7a, 0xba, 0xfa, 0x27, 0x67, 0xa7, 0xe7 }, + }, + }, + { + { + { 0x00, 0x5b, 0xb6, 0xed, 0x71, 0x2a, 0xc7, 0x9c, 0xe2, 0xb9, 0x54, 0x0f, 0x93, 0xc8, 0x25, 0x7e }, + { 0x00, 0xd9, 0xaf, 0x76, 0x43, 0x9a, 0xec, 0x35, 0x86, 0x5f, 0x29, 0xf0, 0xc5, 0x1c, 0x6a, 0xb3 }, + }, + { + { 0x00, 0xf9, 0xef, 0x16, 0xc3, 0x3a, 0x2c, 0xd5, 0x9b, 0x62, 0x74, 0x8d, 0x58, 0xa1, 0xb7, 0x4e }, + { 0x00, 0x2b, 0x56, 0x7d, 0xac, 0x87, 0xfa, 0xd1, 0x45, 0x6e, 0x13, 0x38, 0xe9, 0xc2, 0xbf, 0x94 }, + }, + { + { 0x00, 0x66, 0xcc, 0xaa, 0x85, 0xe3, 0x49, 0x2f, 0x17, 0x71, 0xdb, 0xbd, 0x92, 0xf4, 0x5e, 0x38 }, + { 0x00, 0x2e, 0x5c, 0x72, 0xb8, 0x96, 0xe4, 0xca, 0x6d, 0x43, 0x31, 0x1f, 0xd5, 0xfb, 0x89, 0xa7 }, + }, + { + { 0x00, 0x8d, 0x07, 0x8a, 0x0e, 0x83, 0x09, 0x84, 0x1c, 0x91, 0x1b, 0x96, 0x12, 0x9f, 0x15, 0x98 }, + { 0x00, 0x38, 0x70, 0x48, 0xe0, 0xd8, 0x90, 0xa8, 0xdd, 0xe5, 0xad, 0x95, 0x3d, 0x05, 0x4d, 0x75 }, + }, + }, + { + { + { 0x00, 0xae, 0x41, 0xef, 0x82, 0x2c, 0xc3, 0x6d, 0x19, 0xb7, 0x58, 0xf6, 0x9b, 0x35, 0xda, 0x74 }, + { 0x00, 0x32, 0x64, 0x56, 0xc8, 0xfa, 0xac, 0x9e, 0x8d, 0xbf, 0xe9, 0xdb, 0x45, 0x77, 0x21, 0x13 }, + }, + { + { 0x00, 0xa2, 0x59, 0xfb, 0xb2, 0x10, 0xeb, 0x49, 0x79, 0xdb, 0x20, 0x82, 0xcb, 0x69, 0x92, 0x30 }, + { 0x00, 0xf2, 0xf9, 0x0b, 0xef, 0x1d, 0x16, 0xe4, 0xc3, 0x31, 0x3a, 0xc8, 0x2c, 0xde, 0xd5, 0x27 }, + }, + { + { 0x00, 0x61, 0xc2, 0xa3, 0x99, 0xf8, 0x5b, 0x3a, 0x2f, 0x4e, 0xed, 0x8c, 0xb6, 0xd7, 0x74, 0x15 }, + { 0x00, 0x5e, 0xbc, 0xe2, 0x65, 0x3b, 0xd9, 0x87, 0xca, 0x94, 0x76, 0x28, 0xaf, 0xf1, 0x13, 0x4d }, + }, + { + { 0x00, 0xfe, 0xe1, 0x1f, 0xdf, 0x21, 0x3e, 0xc0, 0xa3, 0x5d, 0x42, 0xbc, 0x7c, 0x82, 0x9d, 0x63 }, + { 0x00, 0x5b, 0xb6, 0xed, 0x71, 0x2a, 0xc7, 0x9c, 0xe2, 0xb9, 0x54, 0x0f, 0x93, 0xc8, 0x25, 0x7e }, + }, + }, + { + { + { 0x00, 0x37, 0x6e, 0x59, 0xdc, 0xeb, 0xb2, 0x85, 0xa5, 0x92, 0xcb, 0xfc, 0x79, 0x4e, 0x17, 0x20 }, + { 0x00, 0x57, 0xae, 0xf9, 0x41, 0x16, 0xef, 0xb8, 0x82, 0xd5, 0x2c, 0x7b, 0xc3, 0x94, 0x6d, 0x3a }, + }, + { + { 0x00, 0xa4, 0x55, 0xf1, 0xaa, 0x0e, 0xff, 0x5b, 0x49, 0xed, 0x1c, 0xb8, 0xe3, 0x47, 0xb6, 0x12 }, + { 0x00, 0x92, 0x39, 0xab, 0x72, 0xe0, 0x4b, 0xd9, 0xe4, 0x76, 0xdd, 0x4f, 0x96, 0x04, 0xaf, 0x3d }, + }, + { + { 0x00, 0x79, 0xf2, 0x8b, 0xf9, 0x80, 0x0b, 0x72, 0xef, 0x96, 0x1d, 0x64, 0x16, 0x6f, 0xe4, 0x9d }, + { 0x00, 0xc3, 0x9b, 0x58, 0x2b, 0xe8, 0xb0, 0x73, 0x56, 0x95, 0xcd, 0x0e, 0x7d, 0xbe, 0xe6, 0x25 }, + }, + { + { 0x00, 0x75, 0xea, 0x9f, 0xc9, 0xbc, 0x23, 0x56, 0x8f, 0xfa, 0x65, 0x10, 0x46, 0x33, 0xac, 0xd9 }, + { 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11 }, + }, + }, + { + { + { 0x00, 0x33, 0x66, 0x55, 0xcc, 0xff, 0xaa, 0x99, 0x85, 0xb6, 0xe3, 0xd0, 0x49, 0x7a, 0x2f, 0x1c }, + { 0x00, 0x17, 0x2e, 0x39, 0x5c, 0x4b, 0x72, 0x65, 0xb8, 0xaf, 0x96, 0x81, 0xe4, 0xf3, 0xca, 0xdd }, + }, + { + { 0x00, 0x6a, 0xd4, 0xbe, 0xb5, 0xdf, 0x61, 0x0b, 0x77, 0x1d, 0xa3, 0xc9, 0xc2, 0xa8, 0x16, 0x7c }, + { 0x00, 0xee, 0xc1, 0x2f, 0x9f, 0x71, 0x5e, 0xb0, 0x23, 0xcd, 0xe2, 0x0c, 0xbc, 0x52, 0x7d, 0x93 }, + }, + { + { 0x00, 0x4d, 0x9a, 0xd7, 0x29, 0x64, 0xb3, 0xfe, 0x52, 0x1f, 0xc8, 0x85, 0x7b, 0x36, 0xe1, 0xac }, + { 0x00, 0xa4, 0x55, 0xf1, 0xaa, 0x0e, 0xff, 0x5b, 0x49, 0xed, 0x1c, 0xb8, 0xe3, 0x47, 0xb6, 0x12 }, + }, + { + { 0x00, 0x5e, 0xbc, 0xe2, 0x65, 0x3b, 0xd9, 0x87, 0xca, 0x94, 0x76, 0x28, 0xaf, 0xf1, 0x13, 0x4d }, + { 0x00, 0x89, 0x0f, 0x86, 0x1e, 0x97, 0x11, 0x98, 0x3c, 0xb5, 0x33, 0xba, 0x22, 0xab, 0x2d, 0xa4 }, + }, + }, + { + { + { 0x00, 0x4c, 0x98, 0xd4, 0x2d, 0x61, 0xb5, 0xf9, 0x5a, 0x16, 0xc2, 0x8e, 0x77, 0x3b, 0xef, 0xa3 }, + { 0x00, 0xb4, 0x75, 0xc1, 0xea, 0x5e, 0x9f, 0x2b, 0xc9, 0x7d, 0xbc, 0x08, 0x23, 0x97, 0x56, 0xe2 }, + }, + { + { 0x00, 0x3d, 0x7a, 0x47, 0xf4, 0xc9, 0x8e, 0xb3, 0xf5, 0xc8, 0x8f, 0xb2, 0x01, 0x3c, 0x7b, 0x46 }, + { 0x00, 0xf7, 0xf3, 0x04, 0xfb, 0x0c, 0x08, 0xff, 0xeb, 0x1c, 0x18, 0xef, 0x10, 0xe7, 0xe3, 0x14 }, + }, + { + { 0x00, 0x32, 0x64, 0x56, 0xc8, 0xfa, 0xac, 0x9e, 0x8d, 0xbf, 0xe9, 0xdb, 0x45, 0x77, 0x21, 0x13 }, + { 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d }, + }, + { + { 0x00, 0x23, 0x46, 0x65, 0x8c, 0xaf, 0xca, 0xe9, 0x05, 0x26, 0x43, 0x60, 0x89, 0xaa, 0xcf, 0xec }, + { 0x00, 0x0a, 0x14, 0x1e, 0x28, 0x22, 0x3c, 0x36, 0x50, 0x5a, 0x44, 0x4e, 0x78, 0x72, 0x6c, 0x66 }, + }, + }, + { + { + { 0x00, 0xdd, 0xa7, 0x7a, 0x53, 0x8e, 0xf4, 0x29, 0xa6, 0x7b, 0x01, 0xdc, 0xf5, 0x28, 0x52, 0x8f }, + { 0x00, 0x51, 0xa2, 0xf3, 0x59, 0x08, 0xfb, 0xaa, 0xb2, 0xe3, 0x10, 0x41, 0xeb, 0xba, 0x49, 0x18 }, + }, + { + { 0x00, 0xea, 0xc9, 0x23, 0x8f, 0x65, 0x46, 0xac, 0x03, 0xe9, 0xca, 0x20, 0x8c, 0x66, 0x45, 0xaf }, + { 0x00, 0x06, 0x0c, 0x0a, 0x18, 0x1e, 0x14, 0x12, 0x30, 0x36, 0x3c, 0x3a, 0x28, 0x2e, 0x24, 0x22 }, + }, + { + { 0x00, 0xb3, 0x7b, 0xc8, 0xf6, 0x45, 0x8d, 0x3e, 0xf1, 0x42, 0x8a, 0x39, 0x07, 0xb4, 0x7c, 0xcf }, + { 0x00, 0xff, 0xe3, 0x1c, 0xdb, 0x24, 0x38, 0xc7, 0xab, 0x54, 0x48, 0xb7, 0x70, 0x8f, 0x93, 0x6c }, + }, + { + { 0x00, 0xca, 0x89, 0x43, 0x0f, 0xc5, 0x86, 0x4c, 0x1e, 0xd4, 0x97, 0x5d, 0x11, 0xdb, 0x98, 0x52 }, + { 0x00, 0x3c, 0x78, 0x44, 0xf0, 0xcc, 0x88, 0xb4, 0xfd, 0xc1, 0x85, 0xb9, 0x0d, 0x31, 0x75, 0x49 }, + }, + }, + { + { + { 0x00, 0x47, 0x8e, 0xc9, 0x01, 0x46, 0x8f, 0xc8, 0x02, 0x45, 0x8c, 0xcb, 0x03, 0x44, 0x8d, 0xca }, + { 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c }, + }, + { + { 0x00, 0x8e, 0x01, 0x8f, 0x02, 0x8c, 0x03, 0x8d, 0x04, 0x8a, 0x05, 0x8b, 0x06, 0x88, 0x07, 0x89 }, + { 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78 }, + }, + { + { 0x00, 0x8d, 0x07, 0x8a, 0x0e, 0x83, 0x09, 0x84, 0x1c, 0x91, 0x1b, 0x96, 0x12, 0x9f, 0x15, 0x98 }, + { 0x00, 0x38, 0x70, 0x48, 0xe0, 0xd8, 0x90, 0xa8, 0xdd, 0xe5, 0xad, 0x95, 0x3d, 0x05, 0x4d, 0x75 }, + }, + { + { 0x00, 0x8f, 0x03, 0x8c, 0x06, 0x89, 0x05, 0x8a, 0x0c, 0x83, 0x0f, 0x80, 0x0a, 0x85, 0x09, 0x86 }, + { 0x00, 0x18, 0x30, 0x28, 0x60, 0x78, 0x50, 0x48, 0xc0, 0xd8, 0xf0, 0xe8, 0xa0, 0xb8, 0x90, 0x88 }, + }, + }, + { + { + { 0x00, 0xf4, 0xf5, 0x01, 0xf7, 0x03, 0x02, 0xf6, 0xf3, 0x07, 0x06, 0xf2, 0x04, 0xf0, 0xf1, 0x05 }, + { 0x00, 0xfb, 0xeb, 0x10, 0xcb, 0x30, 0x20, 0xdb, 0x8b, 0x70, 0x60, 0x9b, 0x40, 0xbb, 0xab, 0x50 }, + }, + { + { 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11 }, + { 0x00, 0x30, 0x60, 0x50, 0xc0, 0xf0, 0xa0, 0x90, 0x9d, 0xad, 0xfd, 0xcd, 0x5d, 0x6d, 0x3d, 0x0d }, + }, + { + { 0x00, 0x52, 0xa4, 0xf6, 0x55, 0x07, 0xf1, 0xa3, 0xaa, 0xf8, 0x0e, 0x5c, 0xff, 0xad, 0x5b, 0x09 }, + { 0x00, 0x49, 0x92, 0xdb, 0x39, 0x70, 0xab, 0xe2, 0x72, 0x3b, 0xe0, 0xa9, 0x4b, 0x02, 0xd9, 0x90 }, + }, + { + { 0x00, 0x48, 0x90, 0xd8, 0x3d, 0x75, 0xad, 0xe5, 0x7a, 0x32, 0xea, 0xa2, 0x47, 0x0f, 0xd7, 0x9f }, + { 0x00, 0xf4, 0xf5, 0x01, 0xf7, 0x03, 0x02, 0xf6, 0xf3, 0x07, 0x06, 0xf2, 0x04, 0xf0, 0xf1, 0x05 }, + }, + }, + { + { + { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e }, + { 0x00, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0, 0x1d, 0x3d, 0x5d, 0x7d, 0x9d, 0xbd, 0xdd, 0xfd }, + }, + { + { 0x00, 0xf5, 0xf7, 0x02, 0xf3, 0x06, 0x04, 0xf1, 0xfb, 0x0e, 0x0c, 0xf9, 0x08, 0xfd, 0xff, 0x0a }, + { 0x00, 0xeb, 0xcb, 0x20, 0x8b, 0x60, 0x40, 0xab, 0x0b, 0xe0, 0xc0, 0x2b, 0x80, 0x6b, 0x4b, 0xa0 }, + }, + { + { 0x00, 0xe2, 0xd9, 0x3b, 0xaf, 0x4d, 0x76, 0x94, 0x43, 0xa1, 0x9a, 0x78, 0xec, 0x0e, 0x35, 0xd7 }, + { 0x00, 0x86, 0x11, 0x97, 0x22, 0xa4, 0x33, 0xb5, 0x44, 0xc2, 0x55, 0xd3, 0x66, 0xe0, 0x77, 0xf1 }, + }, + { + { 0x00, 0x99, 0x2f, 0xb6, 0x5e, 0xc7, 0x71, 0xe8, 0xbc, 0x25, 0x93, 0x0a, 0xe2, 0x7b, 0xcd, 0x54 }, + { 0x00, 0x65, 0xca, 0xaf, 0x89, 0xec, 0x43, 0x26, 0x0f, 0x6a, 0xc5, 0xa0, 0x86, 0xe3, 0x4c, 0x29 }, + }, + }, + { + { + { 0x00, 0xa6, 0x51, 0xf7, 0xa2, 0x04, 0xf3, 0x55, 0x59, 0xff, 0x08, 0xae, 0xfb, 0x5d, 0xaa, 0x0c }, + { 0x00, 0xb2, 0x79, 0xcb, 0xf2, 0x40, 0x8b, 0x39, 0xf9, 0x4b, 0x80, 0x32, 0x0b, 0xb9, 0x72, 0xc0 }, + }, + { + { 0x00, 0xab, 0x4b, 0xe0, 0x96, 0x3d, 0xdd, 0x76, 0x31, 0x9a, 0x7a, 0xd1, 0xa7, 0x0c, 0xec, 0x47 }, + { 0x00, 0x62, 0xc4, 0xa6, 0x95, 0xf7, 0x51, 0x33, 0x37, 0x55, 0xf3, 0x91, 0xa2, 0xc0, 0x66, 0x04 }, + }, + { + { 0x00, 0x82, 0x19, 0x9b, 0x32, 0xb0, 0x2b, 0xa9, 0x64, 0xe6, 0x7d, 0xff, 0x56, 0xd4, 0x4f, 0xcd }, + { 0x00, 0xc8, 0x8d, 0x45, 0x07, 0xcf, 0x8a, 0x42, 0x0e, 0xc6, 0x83, 0x4b, 0x09, 0xc1, 0x84, 0x4c }, + }, + { + { 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b }, + { 0x00, 0xd0, 0xbd, 0x6d, 0x67, 0xb7, 0xda, 0x0a, 0xce, 0x1e, 0x73, 0xa3, 0xa9, 0x79, 0x14, 0xc4 }, + }, + }, + { + { + { 0x00, 0x39, 0x72, 0x4b, 0xe4, 0xdd, 0x96, 0xaf, 0xd5, 0xec, 0xa7, 0x9e, 0x31, 0x08, 0x43, 0x7a }, + { 0x00, 0xb7, 0x73, 0xc4, 0xe6, 0x51, 0x95, 0x22, 0xd1, 0x66, 0xa2, 0x15, 0x37, 0x80, 0x44, 0xf3 }, + }, + { + { 0x00, 0xb4, 0x75, 0xc1, 0xea, 0x5e, 0x9f, 0x2b, 0xc9, 0x7d, 0xbc, 0x08, 0x23, 0x97, 0x56, 0xe2 }, + { 0x00, 0x8f, 0x03, 0x8c, 0x06, 0x89, 0x05, 0x8a, 0x0c, 0x83, 0x0f, 0x80, 0x0a, 0x85, 0x09, 0x86 }, + }, + { + { 0x00, 0x3d, 0x7a, 0x47, 0xf4, 0xc9, 0x8e, 0xb3, 0xf5, 0xc8, 0x8f, 0xb2, 0x01, 0x3c, 0x7b, 0x46 }, + { 0x00, 0xf7, 0xf3, 0x04, 0xfb, 0x0c, 0x08, 0xff, 0xeb, 0x1c, 0x18, 0xef, 0x10, 0xe7, 0xe3, 0x14 }, + }, + { + { 0x00, 0xdf, 0xa3, 0x7c, 0x5b, 0x84, 0xf8, 0x27, 0xb6, 0x69, 0x15, 0xca, 0xed, 0x32, 0x4e, 0x91 }, + { 0x00, 0x71, 0xe2, 0x93, 0xd9, 0xa8, 0x3b, 0x4a, 0xaf, 0xde, 0x4d, 0x3c, 0x76, 0x07, 0x94, 0xe5 }, + }, + }, + { + { + { 0x00, 0xd8, 0xad, 0x75, 0x47, 0x9f, 0xea, 0x32, 0x8e, 0x56, 0x23, 0xfb, 0xc9, 0x11, 0x64, 0xbc }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + }, + { + { 0x00, 0x5d, 0xba, 0xe7, 0x69, 0x34, 0xd3, 0x8e, 0xd2, 0x8f, 0x68, 0x35, 0xbb, 0xe6, 0x01, 0x5c }, + { 0x00, 0xb9, 0x6f, 0xd6, 0xde, 0x67, 0xb1, 0x08, 0xa1, 0x18, 0xce, 0x77, 0x7f, 0xc6, 0x10, 0xa9 }, + }, + { + { 0x00, 0xf9, 0xef, 0x16, 0xc3, 0x3a, 0x2c, 0xd5, 0x9b, 0x62, 0x74, 0x8d, 0x58, 0xa1, 0xb7, 0x4e }, + { 0x00, 0x2b, 0x56, 0x7d, 0xac, 0x87, 0xfa, 0xd1, 0x45, 0x6e, 0x13, 0x38, 0xe9, 0xc2, 0xbf, 0x94 }, + }, + { + { 0x00, 0x8e, 0x01, 0x8f, 0x02, 0x8c, 0x03, 0x8d, 0x04, 0x8a, 0x05, 0x8b, 0x06, 0x88, 0x07, 0x89 }, + { 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78 }, + }, + }, + { + { + { 0x00, 0x9d, 0x27, 0xba, 0x4e, 0xd3, 0x69, 0xf4, 0x9c, 0x01, 0xbb, 0x26, 0xd2, 0x4f, 0xf5, 0x68 }, + { 0x00, 0x25, 0x4a, 0x6f, 0x94, 0xb1, 0xde, 0xfb, 0x35, 0x10, 0x7f, 0x5a, 0xa1, 0x84, 0xeb, 0xce }, + }, + { + { 0x00, 0xb5, 0x77, 0xc2, 0xee, 0x5b, 0x99, 0x2c, 0xc1, 0x74, 0xb6, 0x03, 0x2f, 0x9a, 0x58, 0xed }, + { 0x00, 0x9f, 0x23, 0xbc, 0x46, 0xd9, 0x65, 0xfa, 0x8c, 0x13, 0xaf, 0x30, 0xca, 0x55, 0xe9, 0x76 }, + }, + { + { 0x00, 0xc5, 0x97, 0x52, 0x33, 0xf6, 0xa4, 0x61, 0x66, 0xa3, 0xf1, 0x34, 0x55, 0x90, 0xc2, 0x07 }, + { 0x00, 0xcc, 0x85, 0x49, 0x17, 0xdb, 0x92, 0x5e, 0x2e, 0xe2, 0xab, 0x67, 0x39, 0xf5, 0xbc, 0x70 }, + }, + { + { 0x00, 0xb8, 0x6d, 0xd5, 0xda, 0x62, 0xb7, 0x0f, 0xa9, 0x11, 0xc4, 0x7c, 0x73, 0xcb, 0x1e, 0xa6 }, + { 0x00, 0x4f, 0x9e, 0xd1, 0x21, 0x6e, 0xbf, 0xf0, 0x42, 0x0d, 0xdc, 0x93, 0x63, 0x2c, 0xfd, 0xb2 }, + }, + }, + { + { + { 0x00, 0x2d, 0x5a, 0x77, 0xb4, 0x99, 0xee, 0xc3, 0x75, 0x58, 0x2f, 0x02, 0xc1, 0xec, 0x9b, 0xb6 }, + { 0x00, 0xea, 0xc9, 0x23, 0x8f, 0x65, 0x46, 0xac, 0x03, 0xe9, 0xca, 0x20, 0x8c, 0x66, 0x45, 0xaf }, + }, + { + { 0x00, 0x53, 0xa6, 0xf5, 0x51, 0x02, 0xf7, 0xa4, 0xa2, 0xf1, 0x04, 0x57, 0xf3, 0xa0, 0x55, 0x06 }, + { 0x00, 0x59, 0xb2, 0xeb, 0x79, 0x20, 0xcb, 0x92, 0xf2, 0xab, 0x40, 0x19, 0x8b, 0xd2, 0x39, 0x60 }, + }, + { + { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e }, + { 0x00, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0, 0x1d, 0x3d, 0x5d, 0x7d, 0x9d, 0xbd, 0xdd, 0xfd }, + }, + { + { 0x00, 0x70, 0xe0, 0x90, 0xdd, 0xad, 0x3d, 0x4d, 0xa7, 0xd7, 0x47, 0x37, 0x7a, 0x0a, 0x9a, 0xea }, + { 0x00, 0x53, 0xa6, 0xf5, 0x51, 0x02, 0xf7, 0xa4, 0xa2, 0xf1, 0x04, 0x57, 0xf3, 0xa0, 0x55, 0x06 }, + }, + }, + { + { + { 0x00, 0x62, 0xc4, 0xa6, 0x95, 0xf7, 0x51, 0x33, 0x37, 0x55, 0xf3, 0x91, 0xa2, 0xc0, 0x66, 0x04 }, + { 0x00, 0x6e, 0xdc, 0xb2, 0xa5, 0xcb, 0x79, 0x17, 0x57, 0x39, 0x8b, 0xe5, 0xf2, 0x9c, 0x2e, 0x40 }, + }, + { + { 0x00, 0x6b, 0xd6, 0xbd, 0xb1, 0xda, 0x67, 0x0c, 0x7f, 0x14, 0xa9, 0xc2, 0xce, 0xa5, 0x18, 0x73 }, + { 0x00, 0xfe, 0xe1, 0x1f, 0xdf, 0x21, 0x3e, 0xc0, 0xa3, 0x5d, 0x42, 0xbc, 0x7c, 0x82, 0x9d, 0x63 }, + }, + { + { 0x00, 0xbc, 0x65, 0xd9, 0xca, 0x76, 0xaf, 0x13, 0x89, 0x35, 0xec, 0x50, 0x43, 0xff, 0x26, 0x9a }, + { 0x00, 0x0f, 0x1e, 0x11, 0x3c, 0x33, 0x22, 0x2d, 0x78, 0x77, 0x66, 0x69, 0x44, 0x4b, 0x5a, 0x55 }, + }, + { + { 0x00, 0x29, 0x52, 0x7b, 0xa4, 0x8d, 0xf6, 0xdf, 0x55, 0x7c, 0x07, 0x2e, 0xf1, 0xd8, 0xa3, 0x8a }, + { 0x00, 0xaa, 0x49, 0xe3, 0x92, 0x38, 0xdb, 0x71, 0x39, 0x93, 0x70, 0xda, 0xab, 0x01, 0xe2, 0x48 }, + }, + }, + { + { + { 0x00, 0xb9, 0x6f, 0xd6, 0xde, 0x67, 0xb1, 0x08, 0xa1, 0x18, 0xce, 0x77, 0x7f, 0xc6, 0x10, 0xa9 }, + { 0x00, 0x5f, 0xbe, 0xe1, 0x61, 0x3e, 0xdf, 0x80, 0xc2, 0x9d, 0x7c, 0x23, 0xa3, 0xfc, 0x1d, 0x42 }, + }, + { + { 0x00, 0x39, 0x72, 0x4b, 0xe4, 0xdd, 0x96, 0xaf, 0xd5, 0xec, 0xa7, 0x9e, 0x31, 0x08, 0x43, 0x7a }, + { 0x00, 0xb7, 0x73, 0xc4, 0xe6, 0x51, 0x95, 0x22, 0xd1, 0x66, 0xa2, 0x15, 0x37, 0x80, 0x44, 0xf3 }, + }, + { + { 0x00, 0x4c, 0x98, 0xd4, 0x2d, 0x61, 0xb5, 0xf9, 0x5a, 0x16, 0xc2, 0x8e, 0x77, 0x3b, 0xef, 0xa3 }, + { 0x00, 0xb4, 0x75, 0xc1, 0xea, 0x5e, 0x9f, 0x2b, 0xc9, 0x7d, 0xbc, 0x08, 0x23, 0x97, 0x56, 0xe2 }, + }, + { + { 0x00, 0x9c, 0x25, 0xb9, 0x4a, 0xd6, 0x6f, 0xf3, 0x94, 0x08, 0xb1, 0x2d, 0xde, 0x42, 0xfb, 0x67 }, + { 0x00, 0x35, 0x6a, 0x5f, 0xd4, 0xe1, 0xbe, 0x8b, 0xb5, 0x80, 0xdf, 0xea, 0x61, 0x54, 0x0b, 0x3e }, + }, + }, + { + { + { 0x00, 0x2e, 0x5c, 0x72, 0xb8, 0x96, 0xe4, 0xca, 0x6d, 0x43, 0x31, 0x1f, 0xd5, 0xfb, 0x89, 0xa7 }, + { 0x00, 0xda, 0xa9, 0x73, 0x4f, 0x95, 0xe6, 0x3c, 0x9e, 0x44, 0x37, 0xed, 0xd1, 0x0b, 0x78, 0xa2 }, + }, + { + { 0x00, 0x86, 0x11, 0x97, 0x22, 0xa4, 0x33, 0xb5, 0x44, 0xc2, 0x55, 0xd3, 0x66, 0xe0, 0x77, 0xf1 }, + { 0x00, 0x88, 0x0d, 0x85, 0x1a, 0x92, 0x17, 0x9f, 0x34, 0xbc, 0x39, 0xb1, 0x2e, 0xa6, 0x23, 0xab }, + }, + { + { 0x00, 0x73, 0xe6, 0x95, 0xd1, 0xa2, 0x37, 0x44, 0xbf, 0xcc, 0x59, 0x2a, 0x6e, 0x1d, 0x88, 0xfb }, + { 0x00, 0x63, 0xc6, 0xa5, 0x91, 0xf2, 0x57, 0x34, 0x3f, 0x5c, 0xf9, 0x9a, 0xae, 0xcd, 0x68, 0x0b }, + }, + { + { 0x00, 0x44, 0x88, 0xcc, 0x0d, 0x49, 0x85, 0xc1, 0x1a, 0x5e, 0x92, 0xd6, 0x17, 0x53, 0x9f, 0xdb }, + { 0x00, 0x34, 0x68, 0x5c, 0xd0, 0xe4, 0xb8, 0x8c, 0xbd, 0x89, 0xd5, 0xe1, 0x6d, 0x59, 0x05, 0x31 }, + }, + }, + { + { + { 0x00, 0x0f, 0x1e, 0x11, 0x3c, 0x33, 0x22, 0x2d, 0x78, 0x77, 0x66, 0x69, 0x44, 0x4b, 0x5a, 0x55 }, + { 0x00, 0xf0, 0xfd, 0x0d, 0xe7, 0x17, 0x1a, 0xea, 0xd3, 0x23, 0x2e, 0xde, 0x34, 0xc4, 0xc9, 0x39 }, + }, + { + { 0x00, 0xb0, 0x7d, 0xcd, 0xfa, 0x4a, 0x87, 0x37, 0xe9, 0x59, 0x94, 0x24, 0x13, 0xa3, 0x6e, 0xde }, + { 0x00, 0xcf, 0x83, 0x4c, 0x1b, 0xd4, 0x98, 0x57, 0x36, 0xf9, 0xb5, 0x7a, 0x2d, 0xe2, 0xae, 0x61 }, + }, + { + { 0x00, 0x48, 0x90, 0xd8, 0x3d, 0x75, 0xad, 0xe5, 0x7a, 0x32, 0xea, 0xa2, 0x47, 0x0f, 0xd7, 0x9f }, + { 0x00, 0xf4, 0xf5, 0x01, 0xf7, 0x03, 0x02, 0xf6, 0xf3, 0x07, 0x06, 0xf2, 0x04, 0xf0, 0xf1, 0x05 }, + }, + { + { 0x00, 0x69, 0xd2, 0xbb, 0xb9, 0xd0, 0x6b, 0x02, 0x6f, 0x06, 0xbd, 0xd4, 0xd6, 0xbf, 0x04, 0x6d }, + { 0x00, 0xde, 0xa1, 0x7f, 0x5f, 0x81, 0xfe, 0x20, 0xbe, 0x60, 0x1f, 0xc1, 0xe1, 0x3f, 0x40, 0x9e }, + }, + }, + { + { + { 0x00, 0x2b, 0x56, 0x7d, 0xac, 0x87, 0xfa, 0xd1, 0x45, 0x6e, 0x13, 0x38, 0xe9, 0xc2, 0xbf, 0x94 }, + { 0x00, 0x8a, 0x09, 0x83, 0x12, 0x98, 0x1b, 0x91, 0x24, 0xae, 0x2d, 0xa7, 0x36, 0xbc, 0x3f, 0xb5 }, + }, + { + { 0x00, 0x50, 0xa0, 0xf0, 0x5d, 0x0d, 0xfd, 0xad, 0xba, 0xea, 0x1a, 0x4a, 0xe7, 0xb7, 0x47, 0x17 }, + { 0x00, 0x69, 0xd2, 0xbb, 0xb9, 0xd0, 0x6b, 0x02, 0x6f, 0x06, 0xbd, 0xd4, 0xd6, 0xbf, 0x04, 0x6d }, + }, + { + { 0x00, 0x62, 0xc4, 0xa6, 0x95, 0xf7, 0x51, 0x33, 0x37, 0x55, 0xf3, 0x91, 0xa2, 0xc0, 0x66, 0x04 }, + { 0x00, 0x6e, 0xdc, 0xb2, 0xa5, 0xcb, 0x79, 0x17, 0x57, 0x39, 0x8b, 0xe5, 0xf2, 0x9c, 0x2e, 0x40 }, + }, + { + { 0x00, 0x3d, 0x7a, 0x47, 0xf4, 0xc9, 0x8e, 0xb3, 0xf5, 0xc8, 0x8f, 0xb2, 0x01, 0x3c, 0x7b, 0x46 }, + { 0x00, 0xf7, 0xf3, 0x04, 0xfb, 0x0c, 0x08, 0xff, 0xeb, 0x1c, 0x18, 0xef, 0x10, 0xe7, 0xe3, 0x14 }, + }, + }, + { + { + { 0x00, 0x60, 0xc0, 0xa0, 0x9d, 0xfd, 0x5d, 0x3d, 0x27, 0x47, 0xe7, 0x87, 0xba, 0xda, 0x7a, 0x1a }, + { 0x00, 0x4e, 0x9c, 0xd2, 0x25, 0x6b, 0xb9, 0xf7, 0x4a, 0x04, 0xd6, 0x98, 0x6f, 0x21, 0xf3, 0xbd }, + }, + { + { 0x00, 0x74, 0xe8, 0x9c, 0xcd, 0xb9, 0x25, 0x51, 0x87, 0xf3, 0x6f, 0x1b, 0x4a, 0x3e, 0xa2, 0xd6 }, + { 0x00, 0x13, 0x26, 0x35, 0x4c, 0x5f, 0x6a, 0x79, 0x98, 0x8b, 0xbe, 0xad, 0xd4, 0xc7, 0xf2, 0xe1 }, + }, + { + { 0x00, 0xaf, 0x43, 0xec, 0x86, 0x29, 0xc5, 0x6a, 0x11, 0xbe, 0x52, 0xfd, 0x97, 0x38, 0xd4, 0x7b }, + { 0x00, 0x22, 0x44, 0x66, 0x88, 0xaa, 0xcc, 0xee, 0x0d, 0x2f, 0x49, 0x6b, 0x85, 0xa7, 0xc1, 0xe3 }, + }, + { + { 0x00, 0xa5, 0x57, 0xf2, 0xae, 0x0b, 0xf9, 0x5c, 0x41, 0xe4, 0x16, 0xb3, 0xef, 0x4a, 0xb8, 0x1d }, + { 0x00, 0x82, 0x19, 0x9b, 0x32, 0xb0, 0x2b, 0xa9, 0x64, 0xe6, 0x7d, 0xff, 0x56, 0xd4, 0x4f, 0xcd }, + }, + }, + { + { + { 0x00, 0x58, 0xb0, 0xe8, 0x7d, 0x25, 0xcd, 0x95, 0xfa, 0xa2, 0x4a, 0x12, 0x87, 0xdf, 0x37, 0x6f }, + { 0x00, 0xe9, 0xcf, 0x26, 0x83, 0x6a, 0x4c, 0xa5, 0x1b, 0xf2, 0xd4, 0x3d, 0x98, 0x71, 0x57, 0xbe }, + }, + { + { 0x00, 0x96, 0x31, 0xa7, 0x62, 0xf4, 0x53, 0xc5, 0xc4, 0x52, 0xf5, 0x63, 0xa6, 0x30, 0x97, 0x01 }, + { 0x00, 0x95, 0x37, 0xa2, 0x6e, 0xfb, 0x59, 0xcc, 0xdc, 0x49, 0xeb, 0x7e, 0xb2, 0x27, 0x85, 0x10 }, + }, + { + { 0x00, 0xba, 0x69, 0xd3, 0xd2, 0x68, 0xbb, 0x01, 0xb9, 0x03, 0xd0, 0x6a, 0x6b, 0xd1, 0x02, 0xb8 }, + { 0x00, 0x6f, 0xde, 0xb1, 0xa1, 0xce, 0x7f, 0x10, 0x5f, 0x30, 0x81, 0xee, 0xfe, 0x91, 0x20, 0x4f }, + }, + { + { 0x00, 0xc2, 0x99, 0x5b, 0x2f, 0xed, 0xb6, 0x74, 0x5e, 0x9c, 0xc7, 0x05, 0x71, 0xb3, 0xe8, 0x2a }, + { 0x00, 0xbc, 0x65, 0xd9, 0xca, 0x76, 0xaf, 0x13, 0x89, 0x35, 0xec, 0x50, 0x43, 0xff, 0x26, 0x9a }, + }, + }, + { + { + { 0x00, 0xe4, 0xd5, 0x31, 0xb7, 0x53, 0x62, 0x86, 0x73, 0x97, 0xa6, 0x42, 0xc4, 0x20, 0x11, 0xf5 }, + { 0x00, 0xe6, 0xd1, 0x37, 0xbf, 0x59, 0x6e, 0x88, 0x63, 0x85, 0xb2, 0x54, 0xdc, 0x3a, 0x0d, 0xeb }, + }, + { + { 0x00, 0x84, 0x15, 0x91, 0x2a, 0xae, 0x3f, 0xbb, 0x54, 0xd0, 0x41, 0xc5, 0x7e, 0xfa, 0x6b, 0xef }, + { 0x00, 0xa8, 0x4d, 0xe5, 0x9a, 0x32, 0xd7, 0x7f, 0x29, 0x81, 0x64, 0xcc, 0xb3, 0x1b, 0xfe, 0x56 }, + }, + { + { 0x00, 0x41, 0x82, 0xc3, 0x19, 0x58, 0x9b, 0xda, 0x32, 0x73, 0xb0, 0xf1, 0x2b, 0x6a, 0xa9, 0xe8 }, + { 0x00, 0x64, 0xc8, 0xac, 0x8d, 0xe9, 0x45, 0x21, 0x07, 0x63, 0xcf, 0xab, 0x8a, 0xee, 0x42, 0x26 }, + }, + { + { 0x00, 0x90, 0x3d, 0xad, 0x7a, 0xea, 0x47, 0xd7, 0xf4, 0x64, 0xc9, 0x59, 0x8e, 0x1e, 0xb3, 0x23 }, + { 0x00, 0xf5, 0xf7, 0x02, 0xf3, 0x06, 0x04, 0xf1, 0xfb, 0x0e, 0x0c, 0xf9, 0x08, 0xfd, 0xff, 0x0a }, + }, + }, + { + { + { 0x00, 0xf8, 0xed, 0x15, 0xc7, 0x3f, 0x2a, 0xd2, 0x93, 0x6b, 0x7e, 0x86, 0x54, 0xac, 0xb9, 0x41 }, + { 0x00, 0x3b, 0x76, 0x4d, 0xec, 0xd7, 0x9a, 0xa1, 0xc5, 0xfe, 0xb3, 0x88, 0x29, 0x12, 0x5f, 0x64 }, + }, + { + { 0x00, 0x5a, 0xb4, 0xee, 0x75, 0x2f, 0xc1, 0x9b, 0xea, 0xb0, 0x5e, 0x04, 0x9f, 0xc5, 0x2b, 0x71 }, + { 0x00, 0xc9, 0x8f, 0x46, 0x03, 0xca, 0x8c, 0x45, 0x06, 0xcf, 0x89, 0x40, 0x05, 0xcc, 0x8a, 0x43 }, + }, + { + { 0x00, 0xd9, 0xaf, 0x76, 0x43, 0x9a, 0xec, 0x35, 0x86, 0x5f, 0x29, 0xf0, 0xc5, 0x1c, 0x6a, 0xb3 }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + }, + { + { 0x00, 0xd2, 0xb9, 0x6b, 0x6f, 0xbd, 0xd6, 0x04, 0xde, 0x0c, 0x67, 0xb5, 0xb1, 0x63, 0x08, 0xda }, + { 0x00, 0xa1, 0x5f, 0xfe, 0xbe, 0x1f, 0xe1, 0x40, 0x61, 0xc0, 0x3e, 0x9f, 0xdf, 0x7e, 0x80, 0x21 }, + }, + }, + { + { + { 0x00, 0x6c, 0xd8, 0xb4, 0xad, 0xc1, 0x75, 0x19, 0x47, 0x2b, 0x9f, 0xf3, 0xea, 0x86, 0x32, 0x5e }, + { 0x00, 0x8e, 0x01, 0x8f, 0x02, 0x8c, 0x03, 0x8d, 0x04, 0x8a, 0x05, 0x8b, 0x06, 0x88, 0x07, 0x89 }, + }, + { + { 0x00, 0x4b, 0x96, 0xdd, 0x31, 0x7a, 0xa7, 0xec, 0x62, 0x29, 0xf4, 0xbf, 0x53, 0x18, 0xc5, 0x8e }, + { 0x00, 0xc4, 0x95, 0x51, 0x37, 0xf3, 0xa2, 0x66, 0x6e, 0xaa, 0xfb, 0x3f, 0x59, 0x9d, 0xcc, 0x08 }, + }, + { + { 0x00, 0xc4, 0x95, 0x51, 0x37, 0xf3, 0xa2, 0x66, 0x6e, 0xaa, 0xfb, 0x3f, 0x59, 0x9d, 0xcc, 0x08 }, + { 0x00, 0xdc, 0xa5, 0x79, 0x57, 0x8b, 0xf2, 0x2e, 0xae, 0x72, 0x0b, 0xd7, 0xf9, 0x25, 0x5c, 0x80 }, + }, + { + { 0x00, 0x1c, 0x38, 0x24, 0x70, 0x6c, 0x48, 0x54, 0xe0, 0xfc, 0xd8, 0xc4, 0x90, 0x8c, 0xa8, 0xb4 }, + { 0x00, 0xdd, 0xa7, 0x7a, 0x53, 0x8e, 0xf4, 0x29, 0xa6, 0x7b, 0x01, 0xdc, 0xf5, 0x28, 0x52, 0x8f }, + }, + }, + { + { + { 0x00, 0x72, 0xe4, 0x96, 0xd5, 0xa7, 0x31, 0x43, 0xb7, 0xc5, 0x53, 0x21, 0x62, 0x10, 0x86, 0xf4 }, + { 0x00, 0x73, 0xe6, 0x95, 0xd1, 0xa2, 0x37, 0x44, 0xbf, 0xcc, 0x59, 0x2a, 0x6e, 0x1d, 0x88, 0xfb }, + }, + { + { 0x00, 0xe8, 0xcd, 0x25, 0x87, 0x6f, 0x4a, 0xa2, 0x13, 0xfb, 0xde, 0x36, 0x94, 0x7c, 0x59, 0xb1 }, + { 0x00, 0x26, 0x4c, 0x6a, 0x98, 0xbe, 0xd4, 0xf2, 0x2d, 0x0b, 0x61, 0x47, 0xb5, 0x93, 0xf9, 0xdf }, + }, + { + { 0x00, 0x2f, 0x5e, 0x71, 0xbc, 0x93, 0xe2, 0xcd, 0x65, 0x4a, 0x3b, 0x14, 0xd9, 0xf6, 0x87, 0xa8 }, + { 0x00, 0xca, 0x89, 0x43, 0x0f, 0xc5, 0x86, 0x4c, 0x1e, 0xd4, 0x97, 0x5d, 0x11, 0xdb, 0x98, 0x52 }, + }, + { + { 0x00, 0x9b, 0x2b, 0xb0, 0x56, 0xcd, 0x7d, 0xe6, 0xac, 0x37, 0x87, 0x1c, 0xfa, 0x61, 0xd1, 0x4a }, + { 0x00, 0x45, 0x8a, 0xcf, 0x09, 0x4c, 0x83, 0xc6, 0x12, 0x57, 0x98, 0xdd, 0x1b, 0x5e, 0x91, 0xd4 }, + }, + }, + { + { + { 0x00, 0xb0, 0x7d, 0xcd, 0xfa, 0x4a, 0x87, 0x37, 0xe9, 0x59, 0x94, 0x24, 0x13, 0xa3, 0x6e, 0xde }, + { 0x00, 0xcf, 0x83, 0x4c, 0x1b, 0xd4, 0x98, 0x57, 0x36, 0xf9, 0xb5, 0x7a, 0x2d, 0xe2, 0xae, 0x61 }, + }, + { + { 0x00, 0x49, 0x92, 0xdb, 0x39, 0x70, 0xab, 0xe2, 0x72, 0x3b, 0xe0, 0xa9, 0x4b, 0x02, 0xd9, 0x90 }, + { 0x00, 0xe4, 0xd5, 0x31, 0xb7, 0x53, 0x62, 0x86, 0x73, 0x97, 0xa6, 0x42, 0xc4, 0x20, 0x11, 0xf5 }, + }, + { + { 0x00, 0xb1, 0x7f, 0xce, 0xfe, 0x4f, 0x81, 0x30, 0xe1, 0x50, 0x9e, 0x2f, 0x1f, 0xae, 0x60, 0xd1 }, + { 0x00, 0xdf, 0xa3, 0x7c, 0x5b, 0x84, 0xf8, 0x27, 0xb6, 0x69, 0x15, 0xca, 0xed, 0x32, 0x4e, 0x91 }, + }, + { + { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e }, + { 0x00, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0, 0x1d, 0x3d, 0x5d, 0x7d, 0x9d, 0xbd, 0xdd, 0xfd }, + }, + }, + { + { + { 0x00, 0x85, 0x17, 0x92, 0x2e, 0xab, 0x39, 0xbc, 0x5c, 0xd9, 0x4b, 0xce, 0x72, 0xf7, 0x65, 0xe0 }, + { 0x00, 0xb8, 0x6d, 0xd5, 0xda, 0x62, 0xb7, 0x0f, 0xa9, 0x11, 0xc4, 0x7c, 0x73, 0xcb, 0x1e, 0xa6 }, + }, + { + { 0x00, 0xe5, 0xd7, 0x32, 0xb3, 0x56, 0x64, 0x81, 0x7b, 0x9e, 0xac, 0x49, 0xc8, 0x2d, 0x1f, 0xfa }, + { 0x00, 0xf6, 0xf1, 0x07, 0xff, 0x09, 0x0e, 0xf8, 0xe3, 0x15, 0x12, 0xe4, 0x1c, 0xea, 0xed, 0x1b }, + }, + { + { 0x00, 0x33, 0x66, 0x55, 0xcc, 0xff, 0xaa, 0x99, 0x85, 0xb6, 0xe3, 0xd0, 0x49, 0x7a, 0x2f, 0x1c }, + { 0x00, 0x17, 0x2e, 0x39, 0x5c, 0x4b, 0x72, 0x65, 0xb8, 0xaf, 0x96, 0x81, 0xe4, 0xf3, 0xca, 0xdd }, + }, + { + { 0x00, 0x1d, 0x3a, 0x27, 0x74, 0x69, 0x4e, 0x53, 0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb }, + { 0x00, 0xcd, 0x87, 0x4a, 0x13, 0xde, 0x94, 0x59, 0x26, 0xeb, 0xa1, 0x6c, 0x35, 0xf8, 0xb2, 0x7f }, + }, + }, + { + { + { 0x00, 0x4d, 0x9a, 0xd7, 0x29, 0x64, 0xb3, 0xfe, 0x52, 0x1f, 0xc8, 0x85, 0x7b, 0x36, 0xe1, 0xac }, + { 0x00, 0xa4, 0x55, 0xf1, 0xaa, 0x0e, 0xff, 0x5b, 0x49, 0xed, 0x1c, 0xb8, 0xe3, 0x47, 0xb6, 0x12 }, + }, + { + { 0x00, 0x51, 0xa2, 0xf3, 0x59, 0x08, 0xfb, 0xaa, 0xb2, 0xe3, 0x10, 0x41, 0xeb, 0xba, 0x49, 0x18 }, + { 0x00, 0x79, 0xf2, 0x8b, 0xf9, 0x80, 0x0b, 0x72, 0xef, 0x96, 0x1d, 0x64, 0x16, 0x6f, 0xe4, 0x9d }, + }, + { + { 0x00, 0xb8, 0x6d, 0xd5, 0xda, 0x62, 0xb7, 0x0f, 0xa9, 0x11, 0xc4, 0x7c, 0x73, 0xcb, 0x1e, 0xa6 }, + { 0x00, 0x4f, 0x9e, 0xd1, 0x21, 0x6e, 0xbf, 0xf0, 0x42, 0x0d, 0xdc, 0x93, 0x63, 0x2c, 0xfd, 0xb2 }, + }, + { + { 0x00, 0x98, 0x2d, 0xb5, 0x5a, 0xc2, 0x77, 0xef, 0xb4, 0x2c, 0x99, 0x01, 0xee, 0x76, 0xc3, 0x5b }, + { 0x00, 0x75, 0xea, 0x9f, 0xc9, 0xbc, 0x23, 0x56, 0x8f, 0xfa, 0x65, 0x10, 0x46, 0x33, 0xac, 0xd9 }, + }, + }, + { + { + { 0x00, 0x95, 0x37, 0xa2, 0x6e, 0xfb, 0x59, 0xcc, 0xdc, 0x49, 0xeb, 0x7e, 0xb2, 0x27, 0x85, 0x10 }, + { 0x00, 0xa5, 0x57, 0xf2, 0xae, 0x0b, 0xf9, 0x5c, 0x41, 0xe4, 0x16, 0xb3, 0xef, 0x4a, 0xb8, 0x1d }, + }, + { + { 0x00, 0xef, 0xc3, 0x2c, 0x9b, 0x74, 0x58, 0xb7, 0x2b, 0xc4, 0xe8, 0x07, 0xb0, 0x5f, 0x73, 0x9c }, + { 0x00, 0x56, 0xac, 0xfa, 0x45, 0x13, 0xe9, 0xbf, 0x8a, 0xdc, 0x26, 0x70, 0xcf, 0x99, 0x63, 0x35 }, + }, + { + { 0x00, 0x15, 0x2a, 0x3f, 0x54, 0x41, 0x7e, 0x6b, 0xa8, 0xbd, 0x82, 0x97, 0xfc, 0xe9, 0xd6, 0xc3 }, + { 0x00, 0x4d, 0x9a, 0xd7, 0x29, 0x64, 0xb3, 0xfe, 0x52, 0x1f, 0xc8, 0x85, 0x7b, 0x36, 0xe1, 0xac }, + }, + { + { 0x00, 0x93, 0x3b, 0xa8, 0x76, 0xe5, 0x4d, 0xde, 0xec, 0x7f, 0xd7, 0x44, 0x9a, 0x09, 0xa1, 0x32 }, + { 0x00, 0xc5, 0x97, 0x52, 0x33, 0xf6, 0xa4, 0x61, 0x66, 0xa3, 0xf1, 0x34, 0x55, 0x90, 0xc2, 0x07 }, + }, + }, + { + { + { 0x00, 0x41, 0x82, 0xc3, 0x19, 0x58, 0x9b, 0xda, 0x32, 0x73, 0xb0, 0xf1, 0x2b, 0x6a, 0xa9, 0xe8 }, + { 0x00, 0x64, 0xc8, 0xac, 0x8d, 0xe9, 0x45, 0x21, 0x07, 0x63, 0xcf, 0xab, 0x8a, 0xee, 0x42, 0x26 }, + }, + { + { 0x00, 0x12, 0x24, 0x36, 0x48, 0x5a, 0x6c, 0x7e, 0x90, 0x82, 0xb4, 0xa6, 0xd8, 0xca, 0xfc, 0xee }, + { 0x00, 0x3d, 0x7a, 0x47, 0xf4, 0xc9, 0x8e, 0xb3, 0xf5, 0xc8, 0x8f, 0xb2, 0x01, 0x3c, 0x7b, 0x46 }, + }, + { + { 0x00, 0x7d, 0xfa, 0x87, 0xe9, 0x94, 0x13, 0x6e, 0xcf, 0xb2, 0x35, 0x48, 0x26, 0x5b, 0xdc, 0xa1 }, + { 0x00, 0x83, 0x1b, 0x98, 0x36, 0xb5, 0x2d, 0xae, 0x6c, 0xef, 0x77, 0xf4, 0x5a, 0xd9, 0x41, 0xc2 }, + }, + { + { 0x00, 0xec, 0xc5, 0x29, 0x97, 0x7b, 0x52, 0xbe, 0x33, 0xdf, 0xf6, 0x1a, 0xa4, 0x48, 0x61, 0x8d }, + { 0x00, 0x66, 0xcc, 0xaa, 0x85, 0xe3, 0x49, 0x2f, 0x17, 0x71, 0xdb, 0xbd, 0x92, 0xf4, 0x5e, 0x38 }, + }, + }, + { + { + { 0x00, 0x1c, 0x38, 0x24, 0x70, 0x6c, 0x48, 0x54, 0xe0, 0xfc, 0xd8, 0xc4, 0x90, 0x8c, 0xa8, 0xb4 }, + { 0x00, 0xdd, 0xa7, 0x7a, 0x53, 0x8e, 0xf4, 0x29, 0xa6, 0x7b, 0x01, 0xdc, 0xf5, 0x28, 0x52, 0x8f }, + }, + { + { 0x00, 0xbc, 0x65, 0xd9, 0xca, 0x76, 0xaf, 0x13, 0x89, 0x35, 0xec, 0x50, 0x43, 0xff, 0x26, 0x9a }, + { 0x00, 0x0f, 0x1e, 0x11, 0x3c, 0x33, 0x22, 0x2d, 0x78, 0x77, 0x66, 0x69, 0x44, 0x4b, 0x5a, 0x55 }, + }, + { + { 0x00, 0xcf, 0x83, 0x4c, 0x1b, 0xd4, 0x98, 0x57, 0x36, 0xf9, 0xb5, 0x7a, 0x2d, 0xe2, 0xae, 0x61 }, + { 0x00, 0x6c, 0xd8, 0xb4, 0xad, 0xc1, 0x75, 0x19, 0x47, 0x2b, 0x9f, 0xf3, 0xea, 0x86, 0x32, 0x5e }, + }, + { + { 0x00, 0x84, 0x15, 0x91, 0x2a, 0xae, 0x3f, 0xbb, 0x54, 0xd0, 0x41, 0xc5, 0x7e, 0xfa, 0x6b, 0xef }, + { 0x00, 0xa8, 0x4d, 0xe5, 0x9a, 0x32, 0xd7, 0x7f, 0x29, 0x81, 0x64, 0xcc, 0xb3, 0x1b, 0xfe, 0x56 }, + }, + }, + { + { + { 0x00, 0x23, 0x46, 0x65, 0x8c, 0xaf, 0xca, 0xe9, 0x05, 0x26, 0x43, 0x60, 0x89, 0xaa, 0xcf, 0xec }, + { 0x00, 0x0a, 0x14, 0x1e, 0x28, 0x22, 0x3c, 0x36, 0x50, 0x5a, 0x44, 0x4e, 0x78, 0x72, 0x6c, 0x66 }, + }, + { + { 0x00, 0x89, 0x0f, 0x86, 0x1e, 0x97, 0x11, 0x98, 0x3c, 0xb5, 0x33, 0xba, 0x22, 0xab, 0x2d, 0xa4 }, + { 0x00, 0x78, 0xf0, 0x88, 0xfd, 0x85, 0x0d, 0x75, 0xe7, 0x9f, 0x17, 0x6f, 0x1a, 0x62, 0xea, 0x92 }, + }, + { + { 0x00, 0x3a, 0x74, 0x4e, 0xe8, 0xd2, 0x9c, 0xa6, 0xcd, 0xf7, 0xb9, 0x83, 0x25, 0x1f, 0x51, 0x6b }, + { 0x00, 0x87, 0x13, 0x94, 0x26, 0xa1, 0x35, 0xb2, 0x4c, 0xcb, 0x5f, 0xd8, 0x6a, 0xed, 0x79, 0xfe }, + }, + { + { 0x00, 0xe8, 0xcd, 0x25, 0x87, 0x6f, 0x4a, 0xa2, 0x13, 0xfb, 0xde, 0x36, 0x94, 0x7c, 0x59, 0xb1 }, + { 0x00, 0x26, 0x4c, 0x6a, 0x98, 0xbe, 0xd4, 0xf2, 0x2d, 0x0b, 0x61, 0x47, 0xb5, 0x93, 0xf9, 0xdf }, + }, + }, + { + { + { 0x00, 0x05, 0x0a, 0x0f, 0x14, 0x11, 0x1e, 0x1b, 0x28, 0x2d, 0x22, 0x27, 0x3c, 0x39, 0x36, 0x33 }, + { 0x00, 0x50, 0xa0, 0xf0, 0x5d, 0x0d, 0xfd, 0xad, 0xba, 0xea, 0x1a, 0x4a, 0xe7, 0xb7, 0x47, 0x17 }, + }, + { + { 0x00, 0x5b, 0xb6, 0xed, 0x71, 0x2a, 0xc7, 0x9c, 0xe2, 0xb9, 0x54, 0x0f, 0x93, 0xc8, 0x25, 0x7e }, + { 0x00, 0xd9, 0xaf, 0x76, 0x43, 0x9a, 0xec, 0x35, 0x86, 0x5f, 0x29, 0xf0, 0xc5, 0x1c, 0x6a, 0xb3 }, + }, + { + { 0x00, 0xa9, 0x4f, 0xe6, 0x9e, 0x37, 0xd1, 0x78, 0x21, 0x88, 0x6e, 0xc7, 0xbf, 0x16, 0xf0, 0x59 }, + { 0x00, 0x42, 0x84, 0xc6, 0x15, 0x57, 0x91, 0xd3, 0x2a, 0x68, 0xae, 0xec, 0x3f, 0x7d, 0xbb, 0xf9 }, + }, + { + { 0x00, 0x64, 0xc8, 0xac, 0x8d, 0xe9, 0x45, 0x21, 0x07, 0x63, 0xcf, 0xab, 0x8a, 0xee, 0x42, 0x26 }, + { 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a }, + }, + }, + { + { + { 0x00, 0x99, 0x2f, 0xb6, 0x5e, 0xc7, 0x71, 0xe8, 0xbc, 0x25, 0x93, 0x0a, 0xe2, 0x7b, 0xcd, 0x54 }, + { 0x00, 0x65, 0xca, 0xaf, 0x89, 0xec, 0x43, 0x26, 0x0f, 0x6a, 0xc5, 0xa0, 0x86, 0xe3, 0x4c, 0x29 }, + }, + { + { 0x00, 0x2b, 0x56, 0x7d, 0xac, 0x87, 0xfa, 0xd1, 0x45, 0x6e, 0x13, 0x38, 0xe9, 0xc2, 0xbf, 0x94 }, + { 0x00, 0x8a, 0x09, 0x83, 0x12, 0x98, 0x1b, 0x91, 0x24, 0xae, 0x2d, 0xa7, 0x36, 0xbc, 0x3f, 0xb5 }, + }, + { + { 0x00, 0x5f, 0xbe, 0xe1, 0x61, 0x3e, 0xdf, 0x80, 0xc2, 0x9d, 0x7c, 0x23, 0xa3, 0xfc, 0x1d, 0x42 }, + { 0x00, 0x99, 0x2f, 0xb6, 0x5e, 0xc7, 0x71, 0xe8, 0xbc, 0x25, 0x93, 0x0a, 0xe2, 0x7b, 0xcd, 0x54 }, + }, + { + { 0x00, 0x4c, 0x98, 0xd4, 0x2d, 0x61, 0xb5, 0xf9, 0x5a, 0x16, 0xc2, 0x8e, 0x77, 0x3b, 0xef, 0xa3 }, + { 0x00, 0xb4, 0x75, 0xc1, 0xea, 0x5e, 0x9f, 0x2b, 0xc9, 0x7d, 0xbc, 0x08, 0x23, 0x97, 0x56, 0xe2 }, + }, + }, + { + { + { 0x00, 0x32, 0x64, 0x56, 0xc8, 0xfa, 0xac, 0x9e, 0x8d, 0xbf, 0xe9, 0xdb, 0x45, 0x77, 0x21, 0x13 }, + { 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d }, + }, + { + { 0x00, 0x29, 0x52, 0x7b, 0xa4, 0x8d, 0xf6, 0xdf, 0x55, 0x7c, 0x07, 0x2e, 0xf1, 0xd8, 0xa3, 0x8a }, + { 0x00, 0xaa, 0x49, 0xe3, 0x92, 0x38, 0xdb, 0x71, 0x39, 0x93, 0x70, 0xda, 0xab, 0x01, 0xe2, 0x48 }, + }, + { + { 0x00, 0x84, 0x15, 0x91, 0x2a, 0xae, 0x3f, 0xbb, 0x54, 0xd0, 0x41, 0xc5, 0x7e, 0xfa, 0x6b, 0xef }, + { 0x00, 0xa8, 0x4d, 0xe5, 0x9a, 0x32, 0xd7, 0x7f, 0x29, 0x81, 0x64, 0xcc, 0xb3, 0x1b, 0xfe, 0x56 }, + }, + { + { 0x00, 0x3a, 0x74, 0x4e, 0xe8, 0xd2, 0x9c, 0xa6, 0xcd, 0xf7, 0xb9, 0x83, 0x25, 0x1f, 0x51, 0x6b }, + { 0x00, 0x87, 0x13, 0x94, 0x26, 0xa1, 0x35, 0xb2, 0x4c, 0xcb, 0x5f, 0xd8, 0x6a, 0xed, 0x79, 0xfe }, + }, + }, + { + { + { 0x00, 0xc5, 0x97, 0x52, 0x33, 0xf6, 0xa4, 0x61, 0x66, 0xa3, 0xf1, 0x34, 0x55, 0x90, 0xc2, 0x07 }, + { 0x00, 0xcc, 0x85, 0x49, 0x17, 0xdb, 0x92, 0x5e, 0x2e, 0xe2, 0xab, 0x67, 0x39, 0xf5, 0xbc, 0x70 }, + }, + { + { 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77 }, + { 0x00, 0x90, 0x3d, 0xad, 0x7a, 0xea, 0x47, 0xd7, 0xf4, 0x64, 0xc9, 0x59, 0x8e, 0x1e, 0xb3, 0x23 }, + }, + { + { 0x00, 0x6d, 0xda, 0xb7, 0xa9, 0xc4, 0x73, 0x1e, 0x4f, 0x22, 0x95, 0xf8, 0xe6, 0x8b, 0x3c, 0x51 }, + { 0x00, 0x9e, 0x21, 0xbf, 0x42, 0xdc, 0x63, 0xfd, 0x84, 0x1a, 0xa5, 0x3b, 0xc6, 0x58, 0xe7, 0x79 }, + }, + { + { 0x00, 0x8b, 0x0b, 0x80, 0x16, 0x9d, 0x1d, 0x96, 0x2c, 0xa7, 0x27, 0xac, 0x3a, 0xb1, 0x31, 0xba }, + { 0x00, 0x58, 0xb0, 0xe8, 0x7d, 0x25, 0xcd, 0x95, 0xfa, 0xa2, 0x4a, 0x12, 0x87, 0xdf, 0x37, 0x6f }, + }, + }, + { + { + { 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a }, + { 0x00, 0xe0, 0xdd, 0x3d, 0xa7, 0x47, 0x7a, 0x9a, 0x53, 0xb3, 0x8e, 0x6e, 0xf4, 0x14, 0x29, 0xc9 }, + }, + { + { 0x00, 0xc3, 0x9b, 0x58, 0x2b, 0xe8, 0xb0, 0x73, 0x56, 0x95, 0xcd, 0x0e, 0x7d, 0xbe, 0xe6, 0x25 }, + { 0x00, 0xac, 0x45, 0xe9, 0x8a, 0x26, 0xcf, 0x63, 0x09, 0xa5, 0x4c, 0xe0, 0x83, 0x2f, 0xc6, 0x6a }, + }, + { + { 0x00, 0x34, 0x68, 0x5c, 0xd0, 0xe4, 0xb8, 0x8c, 0xbd, 0x89, 0xd5, 0xe1, 0x6d, 0x59, 0x05, 0x31 }, + { 0x00, 0x67, 0xce, 0xa9, 0x81, 0xe6, 0x4f, 0x28, 0x1f, 0x78, 0xd1, 0xb6, 0x9e, 0xf9, 0x50, 0x37 }, + }, + { + { 0x00, 0x97, 0x33, 0xa4, 0x66, 0xf1, 0x55, 0xc2, 0xcc, 0x5b, 0xff, 0x68, 0xaa, 0x3d, 0x99, 0x0e }, + { 0x00, 0x85, 0x17, 0x92, 0x2e, 0xab, 0x39, 0xbc, 0x5c, 0xd9, 0x4b, 0xce, 0x72, 0xf7, 0x65, 0xe0 }, + }, + }, + { + { + { 0x00, 0x82, 0x19, 0x9b, 0x32, 0xb0, 0x2b, 0xa9, 0x64, 0xe6, 0x7d, 0xff, 0x56, 0xd4, 0x4f, 0xcd }, + { 0x00, 0xc8, 0x8d, 0x45, 0x07, 0xcf, 0x8a, 0x42, 0x0e, 0xc6, 0x83, 0x4b, 0x09, 0xc1, 0x84, 0x4c }, + }, + { + { 0x00, 0x57, 0xae, 0xf9, 0x41, 0x16, 0xef, 0xb8, 0x82, 0xd5, 0x2c, 0x7b, 0xc3, 0x94, 0x6d, 0x3a }, + { 0x00, 0x19, 0x32, 0x2b, 0x64, 0x7d, 0x56, 0x4f, 0xc8, 0xd1, 0xfa, 0xe3, 0xac, 0xb5, 0x9e, 0x87 }, + }, + { + { 0x00, 0x1b, 0x36, 0x2d, 0x6c, 0x77, 0x5a, 0x41, 0xd8, 0xc3, 0xee, 0xf5, 0xb4, 0xaf, 0x82, 0x99 }, + { 0x00, 0xad, 0x47, 0xea, 0x8e, 0x23, 0xc9, 0x64, 0x01, 0xac, 0x46, 0xeb, 0x8f, 0x22, 0xc8, 0x65 }, + }, + { + { 0x00, 0xf3, 0xfb, 0x08, 0xeb, 0x18, 0x10, 0xe3, 0xcb, 0x38, 0x30, 0xc3, 0x20, 0xd3, 0xdb, 0x28 }, + { 0x00, 0x8b, 0x0b, 0x80, 0x16, 0x9d, 0x1d, 0x96, 0x2c, 0xa7, 0x27, 0xac, 0x3a, 0xb1, 0x31, 0xba }, + }, + }, + { + { + { 0x00, 0x91, 0x3f, 0xae, 0x7e, 0xef, 0x41, 0xd0, 0xfc, 0x6d, 0xc3, 0x52, 0x82, 0x13, 0xbd, 0x2c }, + { 0x00, 0xe5, 0xd7, 0x32, 0xb3, 0x56, 0x64, 0x81, 0x7b, 0x9e, 0xac, 0x49, 0xc8, 0x2d, 0x1f, 0xfa }, + }, + { + { 0x00, 0x1e, 0x3c, 0x22, 0x78, 0x66, 0x44, 0x5a, 0xf0, 0xee, 0xcc, 0xd2, 0x88, 0x96, 0xb4, 0xaa }, + { 0x00, 0xfd, 0xe7, 0x1a, 0xd3, 0x2e, 0x34, 0xc9, 0xbb, 0x46, 0x5c, 0xa1, 0x68, 0x95, 0x8f, 0x72 }, + }, + { + { 0x00, 0x44, 0x88, 0xcc, 0x0d, 0x49, 0x85, 0xc1, 0x1a, 0x5e, 0x92, 0xd6, 0x17, 0x53, 0x9f, 0xdb }, + { 0x00, 0x34, 0x68, 0x5c, 0xd0, 0xe4, 0xb8, 0x8c, 0xbd, 0x89, 0xd5, 0xe1, 0x6d, 0x59, 0x05, 0x31 }, + }, + { + { 0x00, 0xe5, 0xd7, 0x32, 0xb3, 0x56, 0x64, 0x81, 0x7b, 0x9e, 0xac, 0x49, 0xc8, 0x2d, 0x1f, 0xfa }, + { 0x00, 0xf6, 0xf1, 0x07, 0xff, 0x09, 0x0e, 0xf8, 0xe3, 0x15, 0x12, 0xe4, 0x1c, 0xea, 0xed, 0x1b }, + }, + }, + { + { + { 0x00, 0x14, 0x28, 0x3c, 0x50, 0x44, 0x78, 0x6c, 0xa0, 0xb4, 0x88, 0x9c, 0xf0, 0xe4, 0xd8, 0xcc }, + { 0x00, 0x5d, 0xba, 0xe7, 0x69, 0x34, 0xd3, 0x8e, 0xd2, 0x8f, 0x68, 0x35, 0xbb, 0xe6, 0x01, 0x5c }, + }, + { + { 0x00, 0x37, 0x6e, 0x59, 0xdc, 0xeb, 0xb2, 0x85, 0xa5, 0x92, 0xcb, 0xfc, 0x79, 0x4e, 0x17, 0x20 }, + { 0x00, 0x57, 0xae, 0xf9, 0x41, 0x16, 0xef, 0xb8, 0x82, 0xd5, 0x2c, 0x7b, 0xc3, 0x94, 0x6d, 0x3a }, + }, + { + { 0x00, 0x94, 0x35, 0xa1, 0x6a, 0xfe, 0x5f, 0xcb, 0xd4, 0x40, 0xe1, 0x75, 0xbe, 0x2a, 0x8b, 0x1f }, + { 0x00, 0xb5, 0x77, 0xc2, 0xee, 0x5b, 0x99, 0x2c, 0xc1, 0x74, 0xb6, 0x03, 0x2f, 0x9a, 0x58, 0xed }, + }, + { + { 0x00, 0xc0, 0x9d, 0x5d, 0x27, 0xe7, 0xba, 0x7a, 0x4e, 0x8e, 0xd3, 0x13, 0x69, 0xa9, 0xf4, 0x34 }, + { 0x00, 0x9c, 0x25, 0xb9, 0x4a, 0xd6, 0x6f, 0xf3, 0x94, 0x08, 0xb1, 0x2d, 0xde, 0x42, 0xfb, 0x67 }, + }, + }, + { + { + { 0x00, 0xd1, 0xbf, 0x6e, 0x63, 0xb2, 0xdc, 0x0d, 0xc6, 0x17, 0x79, 0xa8, 0xa5, 0x74, 0x1a, 0xcb }, + { 0x00, 0x91, 0x3f, 0xae, 0x7e, 0xef, 0x41, 0xd0, 0xfc, 0x6d, 0xc3, 0x52, 0x82, 0x13, 0xbd, 0x2c }, + }, + { + { 0x00, 0x76, 0xec, 0x9a, 0xc5, 0xb3, 0x29, 0x5f, 0x97, 0xe1, 0x7b, 0x0d, 0x52, 0x24, 0xbe, 0xc8 }, + { 0x00, 0x33, 0x66, 0x55, 0xcc, 0xff, 0xaa, 0x99, 0x85, 0xb6, 0xe3, 0xd0, 0x49, 0x7a, 0x2f, 0x1c }, + }, + { + { 0x00, 0x72, 0xe4, 0x96, 0xd5, 0xa7, 0x31, 0x43, 0xb7, 0xc5, 0x53, 0x21, 0x62, 0x10, 0x86, 0xf4 }, + { 0x00, 0x73, 0xe6, 0x95, 0xd1, 0xa2, 0x37, 0x44, 0xbf, 0xcc, 0x59, 0x2a, 0x6e, 0x1d, 0x88, 0xfb }, + }, + { + { 0x00, 0x7d, 0xfa, 0x87, 0xe9, 0x94, 0x13, 0x6e, 0xcf, 0xb2, 0x35, 0x48, 0x26, 0x5b, 0xdc, 0xa1 }, + { 0x00, 0x83, 0x1b, 0x98, 0x36, 0xb5, 0x2d, 0xae, 0x6c, 0xef, 0x77, 0xf4, 0x5a, 0xd9, 0x41, 0xc2 }, + }, + }, + { + { + { 0x00, 0xaf, 0x43, 0xec, 0x86, 0x29, 0xc5, 0x6a, 0x11, 0xbe, 0x52, 0xfd, 0x97, 0x38, 0xd4, 0x7b }, + { 0x00, 0x22, 0x44, 0x66, 0x88, 0xaa, 0xcc, 0xee, 0x0d, 0x2f, 0x49, 0x6b, 0x85, 0xa7, 0xc1, 0xe3 }, + }, + { + { 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69 }, + { 0x00, 0xb0, 0x7d, 0xcd, 0xfa, 0x4a, 0x87, 0x37, 0xe9, 0x59, 0x94, 0x24, 0x13, 0xa3, 0x6e, 0xde }, + }, + { + { 0x00, 0x81, 0x1f, 0x9e, 0x3e, 0xbf, 0x21, 0xa0, 0x7c, 0xfd, 0x63, 0xe2, 0x42, 0xc3, 0x5d, 0xdc }, + { 0x00, 0xf8, 0xed, 0x15, 0xc7, 0x3f, 0x2a, 0xd2, 0x93, 0x6b, 0x7e, 0x86, 0x54, 0xac, 0xb9, 0x41 }, + }, + { + { 0x00, 0x26, 0x4c, 0x6a, 0x98, 0xbe, 0xd4, 0xf2, 0x2d, 0x0b, 0x61, 0x47, 0xb5, 0x93, 0xf9, 0xdf }, + { 0x00, 0x5a, 0xb4, 0xee, 0x75, 0x2f, 0xc1, 0x9b, 0xea, 0xb0, 0x5e, 0x04, 0x9f, 0xc5, 0x2b, 0x71 }, + }, + }, + { + { + { 0x00, 0xf9, 0xef, 0x16, 0xc3, 0x3a, 0x2c, 0xd5, 0x9b, 0x62, 0x74, 0x8d, 0x58, 0xa1, 0xb7, 0x4e }, + { 0x00, 0x2b, 0x56, 0x7d, 0xac, 0x87, 0xfa, 0xd1, 0x45, 0x6e, 0x13, 0x38, 0xe9, 0xc2, 0xbf, 0x94 }, + }, + { + { 0x00, 0x64, 0xc8, 0xac, 0x8d, 0xe9, 0x45, 0x21, 0x07, 0x63, 0xcf, 0xab, 0x8a, 0xee, 0x42, 0x26 }, + { 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a }, + }, + { + { 0x00, 0x42, 0x84, 0xc6, 0x15, 0x57, 0x91, 0xd3, 0x2a, 0x68, 0xae, 0xec, 0x3f, 0x7d, 0xbb, 0xf9 }, + { 0x00, 0x54, 0xa8, 0xfc, 0x4d, 0x19, 0xe5, 0xb1, 0x9a, 0xce, 0x32, 0x66, 0xd7, 0x83, 0x7f, 0x2b }, + }, + { + { 0x00, 0xc8, 0x8d, 0x45, 0x07, 0xcf, 0x8a, 0x42, 0x0e, 0xc6, 0x83, 0x4b, 0x09, 0xc1, 0x84, 0x4c }, + { 0x00, 0x1c, 0x38, 0x24, 0x70, 0x6c, 0x48, 0x54, 0xe0, 0xfc, 0xd8, 0xc4, 0x90, 0x8c, 0xa8, 0xb4 }, + }, + }, + { + { + { 0x00, 0xb3, 0x7b, 0xc8, 0xf6, 0x45, 0x8d, 0x3e, 0xf1, 0x42, 0x8a, 0x39, 0x07, 0xb4, 0x7c, 0xcf }, + { 0x00, 0xff, 0xe3, 0x1c, 0xdb, 0x24, 0x38, 0xc7, 0xab, 0x54, 0x48, 0xb7, 0x70, 0x8f, 0x93, 0x6c }, + }, + { + { 0x00, 0x8a, 0x09, 0x83, 0x12, 0x98, 0x1b, 0x91, 0x24, 0xae, 0x2d, 0xa7, 0x36, 0xbc, 0x3f, 0xb5 }, + { 0x00, 0x48, 0x90, 0xd8, 0x3d, 0x75, 0xad, 0xe5, 0x7a, 0x32, 0xea, 0xa2, 0x47, 0x0f, 0xd7, 0x9f }, + }, + { + { 0x00, 0xbe, 0x61, 0xdf, 0xc2, 0x7c, 0xa3, 0x1d, 0x99, 0x27, 0xf8, 0x46, 0x5b, 0xe5, 0x3a, 0x84 }, + { 0x00, 0x2f, 0x5e, 0x71, 0xbc, 0x93, 0xe2, 0xcd, 0x65, 0x4a, 0x3b, 0x14, 0xd9, 0xf6, 0x87, 0xa8 }, + }, + { + { 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78 }, + { 0x00, 0x80, 0x1d, 0x9d, 0x3a, 0xba, 0x27, 0xa7, 0x74, 0xf4, 0x69, 0xe9, 0x4e, 0xce, 0x53, 0xd3 }, + }, + }, + { + { + { 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d }, + { 0x00, 0x70, 0xe0, 0x90, 0xdd, 0xad, 0x3d, 0x4d, 0xa7, 0xd7, 0x47, 0x37, 0x7a, 0x0a, 0x9a, 0xea }, + }, + { + { 0x00, 0x52, 0xa4, 0xf6, 0x55, 0x07, 0xf1, 0xa3, 0xaa, 0xf8, 0x0e, 0x5c, 0xff, 0xad, 0x5b, 0x09 }, + { 0x00, 0x49, 0x92, 0xdb, 0x39, 0x70, 0xab, 0xe2, 0x72, 0x3b, 0xe0, 0xa9, 0x4b, 0x02, 0xd9, 0x90 }, + }, + { + { 0x00, 0xcc, 0x85, 0x49, 0x17, 0xdb, 0x92, 0x5e, 0x2e, 0xe2, 0xab, 0x67, 0x39, 0xf5, 0xbc, 0x70 }, + { 0x00, 0x5c, 0xb8, 0xe4, 0x6d, 0x31, 0xd5, 0x89, 0xda, 0x86, 0x62, 0x3e, 0xb7, 0xeb, 0x0f, 0x53 }, + }, + { + { 0x00, 0xa0, 0x5d, 0xfd, 0xba, 0x1a, 0xe7, 0x47, 0x69, 0xc9, 0x34, 0x94, 0xd3, 0x73, 0x8e, 0x2e }, + { 0x00, 0xd2, 0xb9, 0x6b, 0x6f, 0xbd, 0xd6, 0x04, 0xde, 0x0c, 0x67, 0xb5, 0xb1, 0x63, 0x08, 0xda }, + }, + }, + { + { + { 0x00, 0x97, 0x33, 0xa4, 0x66, 0xf1, 0x55, 0xc2, 0xcc, 0x5b, 0xff, 0x68, 0xaa, 0x3d, 0x99, 0x0e }, + { 0x00, 0x85, 0x17, 0x92, 0x2e, 0xab, 0x39, 0xbc, 0x5c, 0xd9, 0x4b, 0xce, 0x72, 0xf7, 0x65, 0xe0 }, + }, + { + { 0x00, 0x59, 0xb2, 0xeb, 0x79, 0x20, 0xcb, 0x92, 0xf2, 0xab, 0x40, 0x19, 0x8b, 0xd2, 0x39, 0x60 }, + { 0x00, 0xf9, 0xef, 0x16, 0xc3, 0x3a, 0x2c, 0xd5, 0x9b, 0x62, 0x74, 0x8d, 0x58, 0xa1, 0xb7, 0x4e }, + }, + { + { 0x00, 0x4b, 0x96, 0xdd, 0x31, 0x7a, 0xa7, 0xec, 0x62, 0x29, 0xf4, 0xbf, 0x53, 0x18, 0xc5, 0x8e }, + { 0x00, 0xc4, 0x95, 0x51, 0x37, 0xf3, 0xa2, 0x66, 0x6e, 0xaa, 0xfb, 0x3f, 0x59, 0x9d, 0xcc, 0x08 }, + }, + { + { 0x00, 0x62, 0xc4, 0xa6, 0x95, 0xf7, 0x51, 0x33, 0x37, 0x55, 0xf3, 0x91, 0xa2, 0xc0, 0x66, 0x04 }, + { 0x00, 0x6e, 0xdc, 0xb2, 0xa5, 0xcb, 0x79, 0x17, 0x57, 0x39, 0x8b, 0xe5, 0xf2, 0x9c, 0x2e, 0x40 }, + }, + }, + { + { + { 0x00, 0x6e, 0xdc, 0xb2, 0xa5, 0xcb, 0x79, 0x17, 0x57, 0x39, 0x8b, 0xe5, 0xf2, 0x9c, 0x2e, 0x40 }, + { 0x00, 0xae, 0x41, 0xef, 0x82, 0x2c, 0xc3, 0x6d, 0x19, 0xb7, 0x58, 0xf6, 0x9b, 0x35, 0xda, 0x74 }, + }, + { + { 0x00, 0x80, 0x1d, 0x9d, 0x3a, 0xba, 0x27, 0xa7, 0x74, 0xf4, 0x69, 0xe9, 0x4e, 0xce, 0x53, 0xd3 }, + { 0x00, 0xe8, 0xcd, 0x25, 0x87, 0x6f, 0x4a, 0xa2, 0x13, 0xfb, 0xde, 0x36, 0x94, 0x7c, 0x59, 0xb1 }, + }, + { + { 0x00, 0x0a, 0x14, 0x1e, 0x28, 0x22, 0x3c, 0x36, 0x50, 0x5a, 0x44, 0x4e, 0x78, 0x72, 0x6c, 0x66 }, + { 0x00, 0xa0, 0x5d, 0xfd, 0xba, 0x1a, 0xe7, 0x47, 0x69, 0xc9, 0x34, 0x94, 0xd3, 0x73, 0x8e, 0x2e }, + }, + { + { 0x00, 0x82, 0x19, 0x9b, 0x32, 0xb0, 0x2b, 0xa9, 0x64, 0xe6, 0x7d, 0xff, 0x56, 0xd4, 0x4f, 0xcd }, + { 0x00, 0xc8, 0x8d, 0x45, 0x07, 0xcf, 0x8a, 0x42, 0x0e, 0xc6, 0x83, 0x4b, 0x09, 0xc1, 0x84, 0x4c }, + }, + }, + { + { + { 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69 }, + { 0x00, 0xb0, 0x7d, 0xcd, 0xfa, 0x4a, 0x87, 0x37, 0xe9, 0x59, 0x94, 0x24, 0x13, 0xa3, 0x6e, 0xde }, + }, + { + { 0x00, 0xda, 0xa9, 0x73, 0x4f, 0x95, 0xe6, 0x3c, 0x9e, 0x44, 0x37, 0xed, 0xd1, 0x0b, 0x78, 0xa2 }, + { 0x00, 0x21, 0x42, 0x63, 0x84, 0xa5, 0xc6, 0xe7, 0x15, 0x34, 0x57, 0x76, 0x91, 0xb0, 0xd3, 0xf2 }, + }, + { + { 0x00, 0x6f, 0xde, 0xb1, 0xa1, 0xce, 0x7f, 0x10, 0x5f, 0x30, 0x81, 0xee, 0xfe, 0x91, 0x20, 0x4f }, + { 0x00, 0xbe, 0x61, 0xdf, 0xc2, 0x7c, 0xa3, 0x1d, 0x99, 0x27, 0xf8, 0x46, 0x5b, 0xe5, 0x3a, 0x84 }, + }, + { + { 0x00, 0x55, 0xaa, 0xff, 0x49, 0x1c, 0xe3, 0xb6, 0x92, 0xc7, 0x38, 0x6d, 0xdb, 0x8e, 0x71, 0x24 }, + { 0x00, 0x39, 0x72, 0x4b, 0xe4, 0xdd, 0x96, 0xaf, 0xd5, 0xec, 0xa7, 0x9e, 0x31, 0x08, 0x43, 0x7a }, + }, + }, + { + { + { 0x00, 0x67, 0xce, 0xa9, 0x81, 0xe6, 0x4f, 0x28, 0x1f, 0x78, 0xd1, 0xb6, 0x9e, 0xf9, 0x50, 0x37 }, + { 0x00, 0x3e, 0x7c, 0x42, 0xf8, 0xc6, 0x84, 0xba, 0xed, 0xd3, 0x91, 0xaf, 0x15, 0x2b, 0x69, 0x57 }, + }, + { + { 0x00, 0xa8, 0x4d, 0xe5, 0x9a, 0x32, 0xd7, 0x7f, 0x29, 0x81, 0x64, 0xcc, 0xb3, 0x1b, 0xfe, 0x56 }, + { 0x00, 0x52, 0xa4, 0xf6, 0x55, 0x07, 0xf1, 0xa3, 0xaa, 0xf8, 0x0e, 0x5c, 0xff, 0xad, 0x5b, 0x09 }, + }, + { + { 0x00, 0x5a, 0xb4, 0xee, 0x75, 0x2f, 0xc1, 0x9b, 0xea, 0xb0, 0x5e, 0x04, 0x9f, 0xc5, 0x2b, 0x71 }, + { 0x00, 0xc9, 0x8f, 0x46, 0x03, 0xca, 0x8c, 0x45, 0x06, 0xcf, 0x89, 0x40, 0x05, 0xcc, 0x8a, 0x43 }, + }, + { + { 0x00, 0xf7, 0xf3, 0x04, 0xfb, 0x0c, 0x08, 0xff, 0xeb, 0x1c, 0x18, 0xef, 0x10, 0xe7, 0xe3, 0x14 }, + { 0x00, 0xcb, 0x8b, 0x40, 0x0b, 0xc0, 0x80, 0x4b, 0x16, 0xdd, 0x9d, 0x56, 0x1d, 0xd6, 0x96, 0x5d }, + }, + }, + { + { + { 0x00, 0x3b, 0x76, 0x4d, 0xec, 0xd7, 0x9a, 0xa1, 0xc5, 0xfe, 0xb3, 0x88, 0x29, 0x12, 0x5f, 0x64 }, + { 0x00, 0x97, 0x33, 0xa4, 0x66, 0xf1, 0x55, 0xc2, 0xcc, 0x5b, 0xff, 0x68, 0xaa, 0x3d, 0x99, 0x0e }, + }, + { + { 0x00, 0x44, 0x88, 0xcc, 0x0d, 0x49, 0x85, 0xc1, 0x1a, 0x5e, 0x92, 0xd6, 0x17, 0x53, 0x9f, 0xdb }, + { 0x00, 0x34, 0x68, 0x5c, 0xd0, 0xe4, 0xb8, 0x8c, 0xbd, 0x89, 0xd5, 0xe1, 0x6d, 0x59, 0x05, 0x31 }, + }, + { + { 0x00, 0x22, 0x44, 0x66, 0x88, 0xaa, 0xcc, 0xee, 0x0d, 0x2f, 0x49, 0x6b, 0x85, 0xa7, 0xc1, 0xe3 }, + { 0x00, 0x1a, 0x34, 0x2e, 0x68, 0x72, 0x5c, 0x46, 0xd0, 0xca, 0xe4, 0xfe, 0xb8, 0xa2, 0x8c, 0x96 }, + }, + { + { 0x00, 0x33, 0x66, 0x55, 0xcc, 0xff, 0xaa, 0x99, 0x85, 0xb6, 0xe3, 0xd0, 0x49, 0x7a, 0x2f, 0x1c }, + { 0x00, 0x17, 0x2e, 0x39, 0x5c, 0x4b, 0x72, 0x65, 0xb8, 0xaf, 0x96, 0x81, 0xe4, 0xf3, 0xca, 0xdd }, + }, + }, + { + { + { 0x00, 0x78, 0xf0, 0x88, 0xfd, 0x85, 0x0d, 0x75, 0xe7, 0x9f, 0x17, 0x6f, 0x1a, 0x62, 0xea, 0x92 }, + { 0x00, 0xd3, 0xbb, 0x68, 0x6b, 0xb8, 0xd0, 0x03, 0xd6, 0x05, 0x6d, 0xbe, 0xbd, 0x6e, 0x06, 0xd5 }, + }, + { + { 0x00, 0x95, 0x37, 0xa2, 0x6e, 0xfb, 0x59, 0xcc, 0xdc, 0x49, 0xeb, 0x7e, 0xb2, 0x27, 0x85, 0x10 }, + { 0x00, 0xa5, 0x57, 0xf2, 0xae, 0x0b, 0xf9, 0x5c, 0x41, 0xe4, 0x16, 0xb3, 0xef, 0x4a, 0xb8, 0x1d }, + }, + { + { 0x00, 0x36, 0x6c, 0x5a, 0xd8, 0xee, 0xb4, 0x82, 0xad, 0x9b, 0xc1, 0xf7, 0x75, 0x43, 0x19, 0x2f }, + { 0x00, 0x47, 0x8e, 0xc9, 0x01, 0x46, 0x8f, 0xc8, 0x02, 0x45, 0x8c, 0xcb, 0x03, 0x44, 0x8d, 0xca }, + }, + { + { 0x00, 0xf6, 0xf1, 0x07, 0xff, 0x09, 0x0e, 0xf8, 0xe3, 0x15, 0x12, 0xe4, 0x1c, 0xea, 0xed, 0x1b }, + { 0x00, 0xdb, 0xab, 0x70, 0x4b, 0x90, 0xe0, 0x3b, 0x96, 0x4d, 0x3d, 0xe6, 0xdd, 0x06, 0x76, 0xad }, + }, + }, + { + { + { 0x00, 0xe6, 0xd1, 0x37, 0xbf, 0x59, 0x6e, 0x88, 0x63, 0x85, 0xb2, 0x54, 0xdc, 0x3a, 0x0d, 0xeb }, + { 0x00, 0xc6, 0x91, 0x57, 0x3f, 0xf9, 0xae, 0x68, 0x7e, 0xb8, 0xef, 0x29, 0x41, 0x87, 0xd0, 0x16 }, + }, + { + { 0x00, 0x3c, 0x78, 0x44, 0xf0, 0xcc, 0x88, 0xb4, 0xfd, 0xc1, 0x85, 0xb9, 0x0d, 0x31, 0x75, 0x49 }, + { 0x00, 0xe7, 0xd3, 0x34, 0xbb, 0x5c, 0x68, 0x8f, 0x6b, 0x8c, 0xb8, 0x5f, 0xd0, 0x37, 0x03, 0xe4 }, + }, + { + { 0x00, 0xb5, 0x77, 0xc2, 0xee, 0x5b, 0x99, 0x2c, 0xc1, 0x74, 0xb6, 0x03, 0x2f, 0x9a, 0x58, 0xed }, + { 0x00, 0x9f, 0x23, 0xbc, 0x46, 0xd9, 0x65, 0xfa, 0x8c, 0x13, 0xaf, 0x30, 0xca, 0x55, 0xe9, 0x76 }, + }, + { + { 0x00, 0x51, 0xa2, 0xf3, 0x59, 0x08, 0xfb, 0xaa, 0xb2, 0xe3, 0x10, 0x41, 0xeb, 0xba, 0x49, 0x18 }, + { 0x00, 0x79, 0xf2, 0x8b, 0xf9, 0x80, 0x0b, 0x72, 0xef, 0x96, 0x1d, 0x64, 0x16, 0x6f, 0xe4, 0x9d }, + }, + }, + { + { + { 0x00, 0x28, 0x50, 0x78, 0xa0, 0x88, 0xf0, 0xd8, 0x5d, 0x75, 0x0d, 0x25, 0xfd, 0xd5, 0xad, 0x85 }, + { 0x00, 0xba, 0x69, 0xd3, 0xd2, 0x68, 0xbb, 0x01, 0xb9, 0x03, 0xd0, 0x6a, 0x6b, 0xd1, 0x02, 0xb8 }, + }, + { + { 0x00, 0x33, 0x66, 0x55, 0xcc, 0xff, 0xaa, 0x99, 0x85, 0xb6, 0xe3, 0xd0, 0x49, 0x7a, 0x2f, 0x1c }, + { 0x00, 0x17, 0x2e, 0x39, 0x5c, 0x4b, 0x72, 0x65, 0xb8, 0xaf, 0x96, 0x81, 0xe4, 0xf3, 0xca, 0xdd }, + }, + { + { 0x00, 0x3c, 0x78, 0x44, 0xf0, 0xcc, 0x88, 0xb4, 0xfd, 0xc1, 0x85, 0xb9, 0x0d, 0x31, 0x75, 0x49 }, + { 0x00, 0xe7, 0xd3, 0x34, 0xbb, 0x5c, 0x68, 0x8f, 0x6b, 0x8c, 0xb8, 0x5f, 0xd0, 0x37, 0x03, 0xe4 }, + }, + { + { 0x00, 0x63, 0xc6, 0xa5, 0x91, 0xf2, 0x57, 0x34, 0x3f, 0x5c, 0xf9, 0x9a, 0xae, 0xcd, 0x68, 0x0b }, + { 0x00, 0x7e, 0xfc, 0x82, 0xe5, 0x9b, 0x19, 0x67, 0xd7, 0xa9, 0x2b, 0x55, 0x32, 0x4c, 0xce, 0xb0 }, + }, + }, + { + { + { 0x00, 0x22, 0x44, 0x66, 0x88, 0xaa, 0xcc, 0xee, 0x0d, 0x2f, 0x49, 0x6b, 0x85, 0xa7, 0xc1, 0xe3 }, + { 0x00, 0x1a, 0x34, 0x2e, 0x68, 0x72, 0x5c, 0x46, 0xd0, 0xca, 0xe4, 0xfe, 0xb8, 0xa2, 0x8c, 0x96 }, + }, + { + { 0x00, 0xe6, 0xd1, 0x37, 0xbf, 0x59, 0x6e, 0x88, 0x63, 0x85, 0xb2, 0x54, 0xdc, 0x3a, 0x0d, 0xeb }, + { 0x00, 0xc6, 0x91, 0x57, 0x3f, 0xf9, 0xae, 0x68, 0x7e, 0xb8, 0xef, 0x29, 0x41, 0x87, 0xd0, 0x16 }, + }, + { + { 0x00, 0x9d, 0x27, 0xba, 0x4e, 0xd3, 0x69, 0xf4, 0x9c, 0x01, 0xbb, 0x26, 0xd2, 0x4f, 0xf5, 0x68 }, + { 0x00, 0x25, 0x4a, 0x6f, 0x94, 0xb1, 0xde, 0xfb, 0x35, 0x10, 0x7f, 0x5a, 0xa1, 0x84, 0xeb, 0xce }, + }, + { + { 0x00, 0x4d, 0x9a, 0xd7, 0x29, 0x64, 0xb3, 0xfe, 0x52, 0x1f, 0xc8, 0x85, 0x7b, 0x36, 0xe1, 0xac }, + { 0x00, 0xa4, 0x55, 0xf1, 0xaa, 0x0e, 0xff, 0x5b, 0x49, 0xed, 0x1c, 0xb8, 0xe3, 0x47, 0xb6, 0x12 }, + }, + }, + { + { + { 0x00, 0x4f, 0x9e, 0xd1, 0x21, 0x6e, 0xbf, 0xf0, 0x42, 0x0d, 0xdc, 0x93, 0x63, 0x2c, 0xfd, 0xb2 }, + { 0x00, 0x84, 0x15, 0x91, 0x2a, 0xae, 0x3f, 0xbb, 0x54, 0xd0, 0x41, 0xc5, 0x7e, 0xfa, 0x6b, 0xef }, + }, + { + { 0x00, 0x7c, 0xf8, 0x84, 0xed, 0x91, 0x15, 0x69, 0xc7, 0xbb, 0x3f, 0x43, 0x2a, 0x56, 0xd2, 0xae }, + { 0x00, 0x93, 0x3b, 0xa8, 0x76, 0xe5, 0x4d, 0xde, 0xec, 0x7f, 0xd7, 0x44, 0x9a, 0x09, 0xa1, 0x32 }, + }, + { + { 0x00, 0x13, 0x26, 0x35, 0x4c, 0x5f, 0x6a, 0x79, 0x98, 0x8b, 0xbe, 0xad, 0xd4, 0xc7, 0xf2, 0xe1 }, + { 0x00, 0x2d, 0x5a, 0x77, 0xb4, 0x99, 0xee, 0xc3, 0x75, 0x58, 0x2f, 0x02, 0xc1, 0xec, 0x9b, 0xb6 }, + }, + { + { 0x00, 0x77, 0xee, 0x99, 0xc1, 0xb6, 0x2f, 0x58, 0x9f, 0xe8, 0x71, 0x06, 0x5e, 0x29, 0xb0, 0xc7 }, + { 0x00, 0x23, 0x46, 0x65, 0x8c, 0xaf, 0xca, 0xe9, 0x05, 0x26, 0x43, 0x60, 0x89, 0xaa, 0xcf, 0xec }, + }, + }, + { + { + { 0x00, 0xa3, 0x5b, 0xf8, 0xb6, 0x15, 0xed, 0x4e, 0x71, 0xd2, 0x2a, 0x89, 0xc7, 0x64, 0x9c, 0x3f }, + { 0x00, 0xe2, 0xd9, 0x3b, 0xaf, 0x4d, 0x76, 0x94, 0x43, 0xa1, 0x9a, 0x78, 0xec, 0x0e, 0x35, 0xd7 }, + }, + { + { 0x00, 0xaf, 0x43, 0xec, 0x86, 0x29, 0xc5, 0x6a, 0x11, 0xbe, 0x52, 0xfd, 0x97, 0x38, 0xd4, 0x7b }, + { 0x00, 0x22, 0x44, 0x66, 0x88, 0xaa, 0xcc, 0xee, 0x0d, 0x2f, 0x49, 0x6b, 0x85, 0xa7, 0xc1, 0xe3 }, + }, + { + { 0x00, 0x7e, 0xfc, 0x82, 0xe5, 0x9b, 0x19, 0x67, 0xd7, 0xa9, 0x2b, 0x55, 0x32, 0x4c, 0xce, 0xb0 }, + { 0x00, 0xb3, 0x7b, 0xc8, 0xf6, 0x45, 0x8d, 0x3e, 0xf1, 0x42, 0x8a, 0x39, 0x07, 0xb4, 0x7c, 0xcf }, + }, + { + { 0x00, 0xda, 0xa9, 0x73, 0x4f, 0x95, 0xe6, 0x3c, 0x9e, 0x44, 0x37, 0xed, 0xd1, 0x0b, 0x78, 0xa2 }, + { 0x00, 0x21, 0x42, 0x63, 0x84, 0xa5, 0xc6, 0xe7, 0x15, 0x34, 0x57, 0x76, 0x91, 0xb0, 0xd3, 0xf2 }, + }, + }, + { + { + { 0x00, 0xca, 0x89, 0x43, 0x0f, 0xc5, 0x86, 0x4c, 0x1e, 0xd4, 0x97, 0x5d, 0x11, 0xdb, 0x98, 0x52 }, + { 0x00, 0x3c, 0x78, 0x44, 0xf0, 0xcc, 0x88, 0xb4, 0xfd, 0xc1, 0x85, 0xb9, 0x0d, 0x31, 0x75, 0x49 }, + }, + { + { 0x00, 0x6c, 0xd8, 0xb4, 0xad, 0xc1, 0x75, 0x19, 0x47, 0x2b, 0x9f, 0xf3, 0xea, 0x86, 0x32, 0x5e }, + { 0x00, 0x8e, 0x01, 0x8f, 0x02, 0x8c, 0x03, 0x8d, 0x04, 0x8a, 0x05, 0x8b, 0x06, 0x88, 0x07, 0x89 }, + }, + { + { 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78 }, + { 0x00, 0x80, 0x1d, 0x9d, 0x3a, 0xba, 0x27, 0xa7, 0x74, 0xf4, 0x69, 0xe9, 0x4e, 0xce, 0x53, 0xd3 }, + }, + { + { 0x00, 0xfd, 0xe7, 0x1a, 0xd3, 0x2e, 0x34, 0xc9, 0xbb, 0x46, 0x5c, 0xa1, 0x68, 0x95, 0x8f, 0x72 }, + { 0x00, 0x6b, 0xd6, 0xbd, 0xb1, 0xda, 0x67, 0x0c, 0x7f, 0x14, 0xa9, 0xc2, 0xce, 0xa5, 0x18, 0x73 }, + }, + }, + { + { + { 0x00, 0x48, 0x90, 0xd8, 0x3d, 0x75, 0xad, 0xe5, 0x7a, 0x32, 0xea, 0xa2, 0x47, 0x0f, 0xd7, 0x9f }, + { 0x00, 0xf4, 0xf5, 0x01, 0xf7, 0x03, 0x02, 0xf6, 0xf3, 0x07, 0x06, 0xf2, 0x04, 0xf0, 0xf1, 0x05 }, + }, + { + { 0x00, 0xb1, 0x7f, 0xce, 0xfe, 0x4f, 0x81, 0x30, 0xe1, 0x50, 0x9e, 0x2f, 0x1f, 0xae, 0x60, 0xd1 }, + { 0x00, 0xdf, 0xa3, 0x7c, 0x5b, 0x84, 0xf8, 0x27, 0xb6, 0x69, 0x15, 0xca, 0xed, 0x32, 0x4e, 0x91 }, + }, + { + { 0x00, 0xdd, 0xa7, 0x7a, 0x53, 0x8e, 0xf4, 0x29, 0xa6, 0x7b, 0x01, 0xdc, 0xf5, 0x28, 0x52, 0x8f }, + { 0x00, 0x51, 0xa2, 0xf3, 0x59, 0x08, 0xfb, 0xaa, 0xb2, 0xe3, 0x10, 0x41, 0xeb, 0xba, 0x49, 0x18 }, + }, + { + { 0x00, 0xc3, 0x9b, 0x58, 0x2b, 0xe8, 0xb0, 0x73, 0x56, 0x95, 0xcd, 0x0e, 0x7d, 0xbe, 0xe6, 0x25 }, + { 0x00, 0xac, 0x45, 0xe9, 0x8a, 0x26, 0xcf, 0x63, 0x09, 0xa5, 0x4c, 0xe0, 0x83, 0x2f, 0xc6, 0x6a }, + }, + }, + { + { + { 0x00, 0xde, 0xa1, 0x7f, 0x5f, 0x81, 0xfe, 0x20, 0xbe, 0x60, 0x1f, 0xc1, 0xe1, 0x3f, 0x40, 0x9e }, + { 0x00, 0x61, 0xc2, 0xa3, 0x99, 0xf8, 0x5b, 0x3a, 0x2f, 0x4e, 0xed, 0x8c, 0xb6, 0xd7, 0x74, 0x15 }, + }, + { + { 0x00, 0x9d, 0x27, 0xba, 0x4e, 0xd3, 0x69, 0xf4, 0x9c, 0x01, 0xbb, 0x26, 0xd2, 0x4f, 0xf5, 0x68 }, + { 0x00, 0x25, 0x4a, 0x6f, 0x94, 0xb1, 0xde, 0xfb, 0x35, 0x10, 0x7f, 0x5a, 0xa1, 0x84, 0xeb, 0xce }, + }, + { + { 0x00, 0xd6, 0xb1, 0x67, 0x7f, 0xa9, 0xce, 0x18, 0xfe, 0x28, 0x4f, 0x99, 0x81, 0x57, 0x30, 0xe6 }, + { 0x00, 0xe1, 0xdf, 0x3e, 0xa3, 0x42, 0x7c, 0x9d, 0x5b, 0xba, 0x84, 0x65, 0xf8, 0x19, 0x27, 0xc6 }, + }, + { + { 0x00, 0x38, 0x70, 0x48, 0xe0, 0xd8, 0x90, 0xa8, 0xdd, 0xe5, 0xad, 0x95, 0x3d, 0x05, 0x4d, 0x75 }, + { 0x00, 0xa7, 0x53, 0xf4, 0xa6, 0x01, 0xf5, 0x52, 0x51, 0xf6, 0x02, 0xa5, 0xf7, 0x50, 0xa4, 0x03 }, + }, + }, + { + { + { 0x00, 0x1d, 0x3a, 0x27, 0x74, 0x69, 0x4e, 0x53, 0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb }, + { 0x00, 0xcd, 0x87, 0x4a, 0x13, 0xde, 0x94, 0x59, 0x26, 0xeb, 0xa1, 0x6c, 0x35, 0xf8, 0xb2, 0x7f }, + }, + { + { 0x00, 0xfc, 0xe5, 0x19, 0xd7, 0x2b, 0x32, 0xce, 0xb3, 0x4f, 0x56, 0xaa, 0x64, 0x98, 0x81, 0x7d }, + { 0x00, 0x7b, 0xf6, 0x8d, 0xf1, 0x8a, 0x07, 0x7c, 0xff, 0x84, 0x09, 0x72, 0x0e, 0x75, 0xf8, 0x83 }, + }, + { + { 0x00, 0x5e, 0xbc, 0xe2, 0x65, 0x3b, 0xd9, 0x87, 0xca, 0x94, 0x76, 0x28, 0xaf, 0xf1, 0x13, 0x4d }, + { 0x00, 0x89, 0x0f, 0x86, 0x1e, 0x97, 0x11, 0x98, 0x3c, 0xb5, 0x33, 0xba, 0x22, 0xab, 0x2d, 0xa4 }, + }, + { + { 0x00, 0x6d, 0xda, 0xb7, 0xa9, 0xc4, 0x73, 0x1e, 0x4f, 0x22, 0x95, 0xf8, 0xe6, 0x8b, 0x3c, 0x51 }, + { 0x00, 0x9e, 0x21, 0xbf, 0x42, 0xdc, 0x63, 0xfd, 0x84, 0x1a, 0xa5, 0x3b, 0xc6, 0x58, 0xe7, 0x79 }, + }, + }, + { + { + { 0x00, 0xa8, 0x4d, 0xe5, 0x9a, 0x32, 0xd7, 0x7f, 0x29, 0x81, 0x64, 0xcc, 0xb3, 0x1b, 0xfe, 0x56 }, + { 0x00, 0x52, 0xa4, 0xf6, 0x55, 0x07, 0xf1, 0xa3, 0xaa, 0xf8, 0x0e, 0x5c, 0xff, 0xad, 0x5b, 0x09 }, + }, + { + { 0x00, 0x92, 0x39, 0xab, 0x72, 0xe0, 0x4b, 0xd9, 0xe4, 0x76, 0xdd, 0x4f, 0x96, 0x04, 0xaf, 0x3d }, + { 0x00, 0xd5, 0xb7, 0x62, 0x73, 0xa6, 0xc4, 0x11, 0xe6, 0x33, 0x51, 0x84, 0x95, 0x40, 0x22, 0xf7 }, + }, + { + { 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c }, + { 0x00, 0x40, 0x80, 0xc0, 0x1d, 0x5d, 0x9d, 0xdd, 0x3a, 0x7a, 0xba, 0xfa, 0x27, 0x67, 0xa7, 0xe7 }, + }, + { + { 0x00, 0xee, 0xc1, 0x2f, 0x9f, 0x71, 0x5e, 0xb0, 0x23, 0xcd, 0xe2, 0x0c, 0xbc, 0x52, 0x7d, 0x93 }, + { 0x00, 0x46, 0x8c, 0xca, 0x05, 0x43, 0x89, 0xcf, 0x0a, 0x4c, 0x86, 0xc0, 0x0f, 0x49, 0x83, 0xc5 }, + }, + }, + { + { + { 0x00, 0x17, 0x2e, 0x39, 0x5c, 0x4b, 0x72, 0x65, 0xb8, 0xaf, 0x96, 0x81, 0xe4, 0xf3, 0xca, 0xdd }, + { 0x00, 0x6d, 0xda, 0xb7, 0xa9, 0xc4, 0x73, 0x1e, 0x4f, 0x22, 0x95, 0xf8, 0xe6, 0x8b, 0x3c, 0x51 }, + }, + { + { 0x00, 0xd6, 0xb1, 0x67, 0x7f, 0xa9, 0xce, 0x18, 0xfe, 0x28, 0x4f, 0x99, 0x81, 0x57, 0x30, 0xe6 }, + { 0x00, 0xe1, 0xdf, 0x3e, 0xa3, 0x42, 0x7c, 0x9d, 0x5b, 0xba, 0x84, 0x65, 0xf8, 0x19, 0x27, 0xc6 }, + }, + { + { 0x00, 0xfc, 0xe5, 0x19, 0xd7, 0x2b, 0x32, 0xce, 0xb3, 0x4f, 0x56, 0xaa, 0x64, 0x98, 0x81, 0x7d }, + { 0x00, 0x7b, 0xf6, 0x8d, 0xf1, 0x8a, 0x07, 0x7c, 0xff, 0x84, 0x09, 0x72, 0x0e, 0x75, 0xf8, 0x83 }, + }, + { + { 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77 }, + { 0x00, 0x90, 0x3d, 0xad, 0x7a, 0xea, 0x47, 0xd7, 0xf4, 0x64, 0xc9, 0x59, 0x8e, 0x1e, 0xb3, 0x23 }, + }, + }, + { + { + { 0x00, 0x6f, 0xde, 0xb1, 0xa1, 0xce, 0x7f, 0x10, 0x5f, 0x30, 0x81, 0xee, 0xfe, 0x91, 0x20, 0x4f }, + { 0x00, 0xbe, 0x61, 0xdf, 0xc2, 0x7c, 0xa3, 0x1d, 0x99, 0x27, 0xf8, 0x46, 0x5b, 0xe5, 0x3a, 0x84 }, + }, + { + { 0x00, 0xd8, 0xad, 0x75, 0x47, 0x9f, 0xea, 0x32, 0x8e, 0x56, 0x23, 0xfb, 0xc9, 0x11, 0x64, 0xbc }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + }, + { + { 0x00, 0x5b, 0xb6, 0xed, 0x71, 0x2a, 0xc7, 0x9c, 0xe2, 0xb9, 0x54, 0x0f, 0x93, 0xc8, 0x25, 0x7e }, + { 0x00, 0xd9, 0xaf, 0x76, 0x43, 0x9a, 0xec, 0x35, 0x86, 0x5f, 0x29, 0xf0, 0xc5, 0x1c, 0x6a, 0xb3 }, + }, + { + { 0x00, 0x47, 0x8e, 0xc9, 0x01, 0x46, 0x8f, 0xc8, 0x02, 0x45, 0x8c, 0xcb, 0x03, 0x44, 0x8d, 0xca }, + { 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c }, + }, + }, + { + { + { 0x00, 0x90, 0x3d, 0xad, 0x7a, 0xea, 0x47, 0xd7, 0xf4, 0x64, 0xc9, 0x59, 0x8e, 0x1e, 0xb3, 0x23 }, + { 0x00, 0xf5, 0xf7, 0x02, 0xf3, 0x06, 0x04, 0xf1, 0xfb, 0x0e, 0x0c, 0xf9, 0x08, 0xfd, 0xff, 0x0a }, + }, + { + { 0x00, 0xff, 0xe3, 0x1c, 0xdb, 0x24, 0x38, 0xc7, 0xab, 0x54, 0x48, 0xb7, 0x70, 0x8f, 0x93, 0x6c }, + { 0x00, 0x4b, 0x96, 0xdd, 0x31, 0x7a, 0xa7, 0xec, 0x62, 0x29, 0xf4, 0xbf, 0x53, 0x18, 0xc5, 0x8e }, + }, + { + { 0x00, 0xec, 0xc5, 0x29, 0x97, 0x7b, 0x52, 0xbe, 0x33, 0xdf, 0xf6, 0x1a, 0xa4, 0x48, 0x61, 0x8d }, + { 0x00, 0x66, 0xcc, 0xaa, 0x85, 0xe3, 0x49, 0x2f, 0x17, 0x71, 0xdb, 0xbd, 0x92, 0xf4, 0x5e, 0x38 }, + }, + { + { 0x00, 0xa3, 0x5b, 0xf8, 0xb6, 0x15, 0xed, 0x4e, 0x71, 0xd2, 0x2a, 0x89, 0xc7, 0x64, 0x9c, 0x3f }, + { 0x00, 0xe2, 0xd9, 0x3b, 0xaf, 0x4d, 0x76, 0x94, 0x43, 0xa1, 0x9a, 0x78, 0xec, 0x0e, 0x35, 0xd7 }, + }, + }, + { + { + { 0x00, 0xaa, 0x49, 0xe3, 0x92, 0x38, 0xdb, 0x71, 0x39, 0x93, 0x70, 0xda, 0xab, 0x01, 0xe2, 0x48 }, + { 0x00, 0x72, 0xe4, 0x96, 0xd5, 0xa7, 0x31, 0x43, 0xb7, 0xc5, 0x53, 0x21, 0x62, 0x10, 0x86, 0xf4 }, + }, + { + { 0x00, 0xa7, 0x53, 0xf4, 0xa6, 0x01, 0xf5, 0x52, 0x51, 0xf6, 0x02, 0xa5, 0xf7, 0x50, 0xa4, 0x03 }, + { 0x00, 0xa2, 0x59, 0xfb, 0xb2, 0x10, 0xeb, 0x49, 0x79, 0xdb, 0x20, 0x82, 0xcb, 0x69, 0x92, 0x30 }, + }, + { + { 0x00, 0xef, 0xc3, 0x2c, 0x9b, 0x74, 0x58, 0xb7, 0x2b, 0xc4, 0xe8, 0x07, 0xb0, 0x5f, 0x73, 0x9c }, + { 0x00, 0x56, 0xac, 0xfa, 0x45, 0x13, 0xe9, 0xbf, 0x8a, 0xdc, 0x26, 0x70, 0xcf, 0x99, 0x63, 0x35 }, + }, + { + { 0x00, 0x05, 0x0a, 0x0f, 0x14, 0x11, 0x1e, 0x1b, 0x28, 0x2d, 0x22, 0x27, 0x3c, 0x39, 0x36, 0x33 }, + { 0x00, 0x50, 0xa0, 0xf0, 0x5d, 0x0d, 0xfd, 0xad, 0xba, 0xea, 0x1a, 0x4a, 0xe7, 0xb7, 0x47, 0x17 }, + }, + }, + { + { + { 0x00, 0x31, 0x62, 0x53, 0xc4, 0xf5, 0xa6, 0x97, 0x95, 0xa4, 0xf7, 0xc6, 0x51, 0x60, 0x33, 0x02 }, + { 0x00, 0x37, 0x6e, 0x59, 0xdc, 0xeb, 0xb2, 0x85, 0xa5, 0x92, 0xcb, 0xfc, 0x79, 0x4e, 0x17, 0x20 }, + }, + { + { 0x00, 0x77, 0xee, 0x99, 0xc1, 0xb6, 0x2f, 0x58, 0x9f, 0xe8, 0x71, 0x06, 0x5e, 0x29, 0xb0, 0xc7 }, + { 0x00, 0x23, 0x46, 0x65, 0x8c, 0xaf, 0xca, 0xe9, 0x05, 0x26, 0x43, 0x60, 0x89, 0xaa, 0xcf, 0xec }, + }, + { + { 0x00, 0xf1, 0xff, 0x0e, 0xe3, 0x12, 0x1c, 0xed, 0xdb, 0x2a, 0x24, 0xd5, 0x38, 0xc9, 0xc7, 0x36 }, + { 0x00, 0xab, 0x4b, 0xe0, 0x96, 0x3d, 0xdd, 0x76, 0x31, 0x9a, 0x7a, 0xd1, 0xa7, 0x0c, 0xec, 0x47 }, + }, + { + { 0x00, 0xde, 0xa1, 0x7f, 0x5f, 0x81, 0xfe, 0x20, 0xbe, 0x60, 0x1f, 0xc1, 0xe1, 0x3f, 0x40, 0x9e }, + { 0x00, 0x61, 0xc2, 0xa3, 0x99, 0xf8, 0x5b, 0x3a, 0x2f, 0x4e, 0xed, 0x8c, 0xb6, 0xd7, 0x74, 0x15 }, + }, + }, + { + { + { 0x00, 0x5a, 0xb4, 0xee, 0x75, 0x2f, 0xc1, 0x9b, 0xea, 0xb0, 0x5e, 0x04, 0x9f, 0xc5, 0x2b, 0x71 }, + { 0x00, 0xc9, 0x8f, 0x46, 0x03, 0xca, 0x8c, 0x45, 0x06, 0xcf, 0x89, 0x40, 0x05, 0xcc, 0x8a, 0x43 }, + }, + { + { 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c }, + { 0x00, 0x40, 0x80, 0xc0, 0x1d, 0x5d, 0x9d, 0xdd, 0x3a, 0x7a, 0xba, 0xfa, 0x27, 0x67, 0xa7, 0xe7 }, + }, + { + { 0x00, 0x6e, 0xdc, 0xb2, 0xa5, 0xcb, 0x79, 0x17, 0x57, 0x39, 0x8b, 0xe5, 0xf2, 0x9c, 0x2e, 0x40 }, + { 0x00, 0xae, 0x41, 0xef, 0x82, 0x2c, 0xc3, 0x6d, 0x19, 0xb7, 0x58, 0xf6, 0x9b, 0x35, 0xda, 0x74 }, + }, + { + { 0x00, 0xa6, 0x51, 0xf7, 0xa2, 0x04, 0xf3, 0x55, 0x59, 0xff, 0x08, 0xae, 0xfb, 0x5d, 0xaa, 0x0c }, + { 0x00, 0xb2, 0x79, 0xcb, 0xf2, 0x40, 0x8b, 0x39, 0xf9, 0x4b, 0x80, 0x32, 0x0b, 0xb9, 0x72, 0xc0 }, + }, + }, + { + { + { 0x00, 0xf3, 0xfb, 0x08, 0xeb, 0x18, 0x10, 0xe3, 0xcb, 0x38, 0x30, 0xc3, 0x20, 0xd3, 0xdb, 0x28 }, + { 0x00, 0x8b, 0x0b, 0x80, 0x16, 0x9d, 0x1d, 0x96, 0x2c, 0xa7, 0x27, 0xac, 0x3a, 0xb1, 0x31, 0xba }, + }, + { + { 0x00, 0x13, 0x26, 0x35, 0x4c, 0x5f, 0x6a, 0x79, 0x98, 0x8b, 0xbe, 0xad, 0xd4, 0xc7, 0xf2, 0xe1 }, + { 0x00, 0x2d, 0x5a, 0x77, 0xb4, 0x99, 0xee, 0xc3, 0x75, 0x58, 0x2f, 0x02, 0xc1, 0xec, 0x9b, 0xb6 }, + }, + { + { 0x00, 0x1e, 0x3c, 0x22, 0x78, 0x66, 0x44, 0x5a, 0xf0, 0xee, 0xcc, 0xd2, 0x88, 0x96, 0xb4, 0xaa }, + { 0x00, 0xfd, 0xe7, 0x1a, 0xd3, 0x2e, 0x34, 0xc9, 0xbb, 0x46, 0x5c, 0xa1, 0x68, 0x95, 0x8f, 0x72 }, + }, + { + { 0x00, 0xf1, 0xff, 0x0e, 0xe3, 0x12, 0x1c, 0xed, 0xdb, 0x2a, 0x24, 0xd5, 0x38, 0xc9, 0xc7, 0x36 }, + { 0x00, 0xab, 0x4b, 0xe0, 0x96, 0x3d, 0xdd, 0x76, 0x31, 0x9a, 0x7a, 0xd1, 0xa7, 0x0c, 0xec, 0x47 }, + }, + }, + { + { + { 0x00, 0xe9, 0xcf, 0x26, 0x83, 0x6a, 0x4c, 0xa5, 0x1b, 0xf2, 0xd4, 0x3d, 0x98, 0x71, 0x57, 0xbe }, + { 0x00, 0x36, 0x6c, 0x5a, 0xd8, 0xee, 0xb4, 0x82, 0xad, 0x9b, 0xc1, 0xf7, 0x75, 0x43, 0x19, 0x2f }, + }, + { + { 0x00, 0x73, 0xe6, 0x95, 0xd1, 0xa2, 0x37, 0x44, 0xbf, 0xcc, 0x59, 0x2a, 0x6e, 0x1d, 0x88, 0xfb }, + { 0x00, 0x63, 0xc6, 0xa5, 0x91, 0xf2, 0x57, 0x34, 0x3f, 0x5c, 0xf9, 0x9a, 0xae, 0xcd, 0x68, 0x0b }, + }, + { + { 0x00, 0x77, 0xee, 0x99, 0xc1, 0xb6, 0x2f, 0x58, 0x9f, 0xe8, 0x71, 0x06, 0x5e, 0x29, 0xb0, 0xc7 }, + { 0x00, 0x23, 0x46, 0x65, 0x8c, 0xaf, 0xca, 0xe9, 0x05, 0x26, 0x43, 0x60, 0x89, 0xaa, 0xcf, 0xec }, + }, + { + { 0x00, 0x22, 0x44, 0x66, 0x88, 0xaa, 0xcc, 0xee, 0x0d, 0x2f, 0x49, 0x6b, 0x85, 0xa7, 0xc1, 0xe3 }, + { 0x00, 0x1a, 0x34, 0x2e, 0x68, 0x72, 0x5c, 0x46, 0xd0, 0xca, 0xe4, 0xfe, 0xb8, 0xa2, 0x8c, 0x96 }, + }, + }, + { + { + { 0x00, 0xa9, 0x4f, 0xe6, 0x9e, 0x37, 0xd1, 0x78, 0x21, 0x88, 0x6e, 0xc7, 0xbf, 0x16, 0xf0, 0x59 }, + { 0x00, 0x42, 0x84, 0xc6, 0x15, 0x57, 0x91, 0xd3, 0x2a, 0x68, 0xae, 0xec, 0x3f, 0x7d, 0xbb, 0xf9 }, + }, + { + { 0x00, 0x66, 0xcc, 0xaa, 0x85, 0xe3, 0x49, 0x2f, 0x17, 0x71, 0xdb, 0xbd, 0x92, 0xf4, 0x5e, 0x38 }, + { 0x00, 0x2e, 0x5c, 0x72, 0xb8, 0x96, 0xe4, 0xca, 0x6d, 0x43, 0x31, 0x1f, 0xd5, 0xfb, 0x89, 0xa7 }, + }, + { + { 0x00, 0x24, 0x48, 0x6c, 0x90, 0xb4, 0xd8, 0xfc, 0x3d, 0x19, 0x75, 0x51, 0xad, 0x89, 0xe5, 0xc1 }, + { 0x00, 0x7a, 0xf4, 0x8e, 0xf5, 0x8f, 0x01, 0x7b, 0xf7, 0x8d, 0x03, 0x79, 0x02, 0x78, 0xf6, 0x8c }, + }, + { + { 0x00, 0x25, 0x4a, 0x6f, 0x94, 0xb1, 0xde, 0xfb, 0x35, 0x10, 0x7f, 0x5a, 0xa1, 0x84, 0xeb, 0xce }, + { 0x00, 0x6a, 0xd4, 0xbe, 0xb5, 0xdf, 0x61, 0x0b, 0x77, 0x1d, 0xa3, 0xc9, 0xc2, 0xa8, 0x16, 0x7c }, + }, + }, + { + { + { 0x00, 0x44, 0x88, 0xcc, 0x0d, 0x49, 0x85, 0xc1, 0x1a, 0x5e, 0x92, 0xd6, 0x17, 0x53, 0x9f, 0xdb }, + { 0x00, 0x34, 0x68, 0x5c, 0xd0, 0xe4, 0xb8, 0x8c, 0xbd, 0x89, 0xd5, 0xe1, 0x6d, 0x59, 0x05, 0x31 }, + }, + { + { 0x00, 0x28, 0x50, 0x78, 0xa0, 0x88, 0xf0, 0xd8, 0x5d, 0x75, 0x0d, 0x25, 0xfd, 0xd5, 0xad, 0x85 }, + { 0x00, 0xba, 0x69, 0xd3, 0xd2, 0x68, 0xbb, 0x01, 0xb9, 0x03, 0xd0, 0x6a, 0x6b, 0xd1, 0x02, 0xb8 }, + }, + { + { 0x00, 0xe6, 0xd1, 0x37, 0xbf, 0x59, 0x6e, 0x88, 0x63, 0x85, 0xb2, 0x54, 0xdc, 0x3a, 0x0d, 0xeb }, + { 0x00, 0xc6, 0x91, 0x57, 0x3f, 0xf9, 0xae, 0x68, 0x7e, 0xb8, 0xef, 0x29, 0x41, 0x87, 0xd0, 0x16 }, + }, + { + { 0x00, 0x6a, 0xd4, 0xbe, 0xb5, 0xdf, 0x61, 0x0b, 0x77, 0x1d, 0xa3, 0xc9, 0xc2, 0xa8, 0x16, 0x7c }, + { 0x00, 0xee, 0xc1, 0x2f, 0x9f, 0x71, 0x5e, 0xb0, 0x23, 0xcd, 0xe2, 0x0c, 0xbc, 0x52, 0x7d, 0x93 }, + }, + }, + { + { + { 0x00, 0x30, 0x60, 0x50, 0xc0, 0xf0, 0xa0, 0x90, 0x9d, 0xad, 0xfd, 0xcd, 0x5d, 0x6d, 0x3d, 0x0d }, + { 0x00, 0x27, 0x4e, 0x69, 0x9c, 0xbb, 0xd2, 0xf5, 0x25, 0x02, 0x6b, 0x4c, 0xb9, 0x9e, 0xf7, 0xd0 }, + }, + { + { 0x00, 0x7d, 0xfa, 0x87, 0xe9, 0x94, 0x13, 0x6e, 0xcf, 0xb2, 0x35, 0x48, 0x26, 0x5b, 0xdc, 0xa1 }, + { 0x00, 0x83, 0x1b, 0x98, 0x36, 0xb5, 0x2d, 0xae, 0x6c, 0xef, 0x77, 0xf4, 0x5a, 0xd9, 0x41, 0xc2 }, + }, + { + { 0x00, 0xc6, 0x91, 0x57, 0x3f, 0xf9, 0xae, 0x68, 0x7e, 0xb8, 0xef, 0x29, 0x41, 0x87, 0xd0, 0x16 }, + { 0x00, 0xfc, 0xe5, 0x19, 0xd7, 0x2b, 0x32, 0xce, 0xb3, 0x4f, 0x56, 0xaa, 0x64, 0x98, 0x81, 0x7d }, + }, + { + { 0x00, 0x0c, 0x18, 0x14, 0x30, 0x3c, 0x28, 0x24, 0x60, 0x6c, 0x78, 0x74, 0x50, 0x5c, 0x48, 0x44 }, + { 0x00, 0xc0, 0x9d, 0x5d, 0x27, 0xe7, 0xba, 0x7a, 0x4e, 0x8e, 0xd3, 0x13, 0x69, 0xa9, 0xf4, 0x34 }, + }, + }, + { + { + { 0x00, 0x56, 0xac, 0xfa, 0x45, 0x13, 0xe9, 0xbf, 0x8a, 0xdc, 0x26, 0x70, 0xcf, 0x99, 0x63, 0x35 }, + { 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77 }, + }, + { + { 0x00, 0x83, 0x1b, 0x98, 0x36, 0xb5, 0x2d, 0xae, 0x6c, 0xef, 0x77, 0xf4, 0x5a, 0xd9, 0x41, 0xc2 }, + { 0x00, 0xd8, 0xad, 0x75, 0x47, 0x9f, 0xea, 0x32, 0x8e, 0x56, 0x23, 0xfb, 0xc9, 0x11, 0x64, 0xbc }, + }, + { + { 0x00, 0xaa, 0x49, 0xe3, 0x92, 0x38, 0xdb, 0x71, 0x39, 0x93, 0x70, 0xda, 0xab, 0x01, 0xe2, 0x48 }, + { 0x00, 0x72, 0xe4, 0x96, 0xd5, 0xa7, 0x31, 0x43, 0xb7, 0xc5, 0x53, 0x21, 0x62, 0x10, 0x86, 0xf4 }, + }, + { + { 0x00, 0x81, 0x1f, 0x9e, 0x3e, 0xbf, 0x21, 0xa0, 0x7c, 0xfd, 0x63, 0xe2, 0x42, 0xc3, 0x5d, 0xdc }, + { 0x00, 0xf8, 0xed, 0x15, 0xc7, 0x3f, 0x2a, 0xd2, 0x93, 0x6b, 0x7e, 0x86, 0x54, 0xac, 0xb9, 0x41 }, + }, + }, + { + { + { 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77 }, + { 0x00, 0x90, 0x3d, 0xad, 0x7a, 0xea, 0x47, 0xd7, 0xf4, 0x64, 0xc9, 0x59, 0x8e, 0x1e, 0xb3, 0x23 }, + }, + { + { 0x00, 0xfb, 0xeb, 0x10, 0xcb, 0x30, 0x20, 0xdb, 0x8b, 0x70, 0x60, 0x9b, 0x40, 0xbb, 0xab, 0x50 }, + { 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69 }, + }, + { + { 0x00, 0xcb, 0x8b, 0x40, 0x0b, 0xc0, 0x80, 0x4b, 0x16, 0xdd, 0x9d, 0x56, 0x1d, 0xd6, 0x96, 0x5d }, + { 0x00, 0x2c, 0x58, 0x74, 0xb0, 0x9c, 0xe8, 0xc4, 0x7d, 0x51, 0x25, 0x09, 0xcd, 0xe1, 0x95, 0xb9 }, + }, + { + { 0x00, 0xb2, 0x79, 0xcb, 0xf2, 0x40, 0x8b, 0x39, 0xf9, 0x4b, 0x80, 0x32, 0x0b, 0xb9, 0x72, 0xc0 }, + { 0x00, 0xef, 0xc3, 0x2c, 0x9b, 0x74, 0x58, 0xb7, 0x2b, 0xc4, 0xe8, 0x07, 0xb0, 0x5f, 0x73, 0x9c }, + }, + }, + { + { + { 0x00, 0x59, 0xb2, 0xeb, 0x79, 0x20, 0xcb, 0x92, 0xf2, 0xab, 0x40, 0x19, 0x8b, 0xd2, 0x39, 0x60 }, + { 0x00, 0xf9, 0xef, 0x16, 0xc3, 0x3a, 0x2c, 0xd5, 0x9b, 0x62, 0x74, 0x8d, 0x58, 0xa1, 0xb7, 0x4e }, + }, + { + { 0x00, 0x5f, 0xbe, 0xe1, 0x61, 0x3e, 0xdf, 0x80, 0xc2, 0x9d, 0x7c, 0x23, 0xa3, 0xfc, 0x1d, 0x42 }, + { 0x00, 0x99, 0x2f, 0xb6, 0x5e, 0xc7, 0x71, 0xe8, 0xbc, 0x25, 0x93, 0x0a, 0xe2, 0x7b, 0xcd, 0x54 }, + }, + { + { 0x00, 0xfd, 0xe7, 0x1a, 0xd3, 0x2e, 0x34, 0xc9, 0xbb, 0x46, 0x5c, 0xa1, 0x68, 0x95, 0x8f, 0x72 }, + { 0x00, 0x6b, 0xd6, 0xbd, 0xb1, 0xda, 0x67, 0x0c, 0x7f, 0x14, 0xa9, 0xc2, 0xce, 0xa5, 0x18, 0x73 }, + }, + { + { 0x00, 0x6b, 0xd6, 0xbd, 0xb1, 0xda, 0x67, 0x0c, 0x7f, 0x14, 0xa9, 0xc2, 0xce, 0xa5, 0x18, 0x73 }, + { 0x00, 0xfe, 0xe1, 0x1f, 0xdf, 0x21, 0x3e, 0xc0, 0xa3, 0x5d, 0x42, 0xbc, 0x7c, 0x82, 0x9d, 0x63 }, + }, + }, + { + { + { 0x00, 0x6a, 0xd4, 0xbe, 0xb5, 0xdf, 0x61, 0x0b, 0x77, 0x1d, 0xa3, 0xc9, 0xc2, 0xa8, 0x16, 0x7c }, + { 0x00, 0xee, 0xc1, 0x2f, 0x9f, 0x71, 0x5e, 0xb0, 0x23, 0xcd, 0xe2, 0x0c, 0xbc, 0x52, 0x7d, 0x93 }, + }, + { + { 0x00, 0x63, 0xc6, 0xa5, 0x91, 0xf2, 0x57, 0x34, 0x3f, 0x5c, 0xf9, 0x9a, 0xae, 0xcd, 0x68, 0x0b }, + { 0x00, 0x7e, 0xfc, 0x82, 0xe5, 0x9b, 0x19, 0x67, 0xd7, 0xa9, 0x2b, 0x55, 0x32, 0x4c, 0xce, 0xb0 }, + }, + { + { 0x00, 0x51, 0xa2, 0xf3, 0x59, 0x08, 0xfb, 0xaa, 0xb2, 0xe3, 0x10, 0x41, 0xeb, 0xba, 0x49, 0x18 }, + { 0x00, 0x79, 0xf2, 0x8b, 0xf9, 0x80, 0x0b, 0x72, 0xef, 0x96, 0x1d, 0x64, 0x16, 0x6f, 0xe4, 0x9d }, + }, + { + { 0x00, 0x58, 0xb0, 0xe8, 0x7d, 0x25, 0xcd, 0x95, 0xfa, 0xa2, 0x4a, 0x12, 0x87, 0xdf, 0x37, 0x6f }, + { 0x00, 0xe9, 0xcf, 0x26, 0x83, 0x6a, 0x4c, 0xa5, 0x1b, 0xf2, 0xd4, 0x3d, 0x98, 0x71, 0x57, 0xbe }, + }, + }, + { + { + { 0x00, 0x42, 0x84, 0xc6, 0x15, 0x57, 0x91, 0xd3, 0x2a, 0x68, 0xae, 0xec, 0x3f, 0x7d, 0xbb, 0xf9 }, + { 0x00, 0x54, 0xa8, 0xfc, 0x4d, 0x19, 0xe5, 0xb1, 0x9a, 0xce, 0x32, 0x66, 0xd7, 0x83, 0x7f, 0x2b }, + }, + { + { 0x00, 0x25, 0x4a, 0x6f, 0x94, 0xb1, 0xde, 0xfb, 0x35, 0x10, 0x7f, 0x5a, 0xa1, 0x84, 0xeb, 0xce }, + { 0x00, 0x6a, 0xd4, 0xbe, 0xb5, 0xdf, 0x61, 0x0b, 0x77, 0x1d, 0xa3, 0xc9, 0xc2, 0xa8, 0x16, 0x7c }, + }, + { + { 0x00, 0x67, 0xce, 0xa9, 0x81, 0xe6, 0x4f, 0x28, 0x1f, 0x78, 0xd1, 0xb6, 0x9e, 0xf9, 0x50, 0x37 }, + { 0x00, 0x3e, 0x7c, 0x42, 0xf8, 0xc6, 0x84, 0xba, 0xed, 0xd3, 0x91, 0xaf, 0x15, 0x2b, 0x69, 0x57 }, + }, + { + { 0x00, 0xd5, 0xb7, 0x62, 0x73, 0xa6, 0xc4, 0x11, 0xe6, 0x33, 0x51, 0x84, 0x95, 0x40, 0x22, 0xf7 }, + { 0x00, 0xd1, 0xbf, 0x6e, 0x63, 0xb2, 0xdc, 0x0d, 0xc6, 0x17, 0x79, 0xa8, 0xa5, 0x74, 0x1a, 0xcb }, + }, + }, + { + { + { 0x00, 0xcd, 0x87, 0x4a, 0x13, 0xde, 0x94, 0x59, 0x26, 0xeb, 0xa1, 0x6c, 0x35, 0xf8, 0xb2, 0x7f }, + { 0x00, 0x4c, 0x98, 0xd4, 0x2d, 0x61, 0xb5, 0xf9, 0x5a, 0x16, 0xc2, 0x8e, 0x77, 0x3b, 0xef, 0xa3 }, + }, + { + { 0x00, 0x19, 0x32, 0x2b, 0x64, 0x7d, 0x56, 0x4f, 0xc8, 0xd1, 0xfa, 0xe3, 0xac, 0xb5, 0x9e, 0x87 }, + { 0x00, 0x8d, 0x07, 0x8a, 0x0e, 0x83, 0x09, 0x84, 0x1c, 0x91, 0x1b, 0x96, 0x12, 0x9f, 0x15, 0x98 }, + }, + { + { 0x00, 0x06, 0x0c, 0x0a, 0x18, 0x1e, 0x14, 0x12, 0x30, 0x36, 0x3c, 0x3a, 0x28, 0x2e, 0x24, 0x22 }, + { 0x00, 0x60, 0xc0, 0xa0, 0x9d, 0xfd, 0x5d, 0x3d, 0x27, 0x47, 0xe7, 0x87, 0xba, 0xda, 0x7a, 0x1a }, + }, + { + { 0x00, 0xb3, 0x7b, 0xc8, 0xf6, 0x45, 0x8d, 0x3e, 0xf1, 0x42, 0x8a, 0x39, 0x07, 0xb4, 0x7c, 0xcf }, + { 0x00, 0xff, 0xe3, 0x1c, 0xdb, 0x24, 0x38, 0xc7, 0xab, 0x54, 0x48, 0xb7, 0x70, 0x8f, 0x93, 0x6c }, + }, + }, + { + { + { 0x00, 0xe5, 0xd7, 0x32, 0xb3, 0x56, 0x64, 0x81, 0x7b, 0x9e, 0xac, 0x49, 0xc8, 0x2d, 0x1f, 0xfa }, + { 0x00, 0xf6, 0xf1, 0x07, 0xff, 0x09, 0x0e, 0xf8, 0xe3, 0x15, 0x12, 0xe4, 0x1c, 0xea, 0xed, 0x1b }, + }, + { + { 0x00, 0xbd, 0x67, 0xda, 0xce, 0x73, 0xa9, 0x14, 0x81, 0x3c, 0xe6, 0x5b, 0x4f, 0xf2, 0x28, 0x95 }, + { 0x00, 0x1f, 0x3e, 0x21, 0x7c, 0x63, 0x42, 0x5d, 0xf8, 0xe7, 0xc6, 0xd9, 0x84, 0x9b, 0xba, 0xa5 }, + }, + { + { 0x00, 0x6a, 0xd4, 0xbe, 0xb5, 0xdf, 0x61, 0x0b, 0x77, 0x1d, 0xa3, 0xc9, 0xc2, 0xa8, 0x16, 0x7c }, + { 0x00, 0xee, 0xc1, 0x2f, 0x9f, 0x71, 0x5e, 0xb0, 0x23, 0xcd, 0xe2, 0x0c, 0xbc, 0x52, 0x7d, 0x93 }, + }, + { + { 0x00, 0xfc, 0xe5, 0x19, 0xd7, 0x2b, 0x32, 0xce, 0xb3, 0x4f, 0x56, 0xaa, 0x64, 0x98, 0x81, 0x7d }, + { 0x00, 0x7b, 0xf6, 0x8d, 0xf1, 0x8a, 0x07, 0x7c, 0xff, 0x84, 0x09, 0x72, 0x0e, 0x75, 0xf8, 0x83 }, + }, + }, + { + { + { 0x00, 0xd6, 0xb1, 0x67, 0x7f, 0xa9, 0xce, 0x18, 0xfe, 0x28, 0x4f, 0x99, 0x81, 0x57, 0x30, 0xe6 }, + { 0x00, 0xe1, 0xdf, 0x3e, 0xa3, 0x42, 0x7c, 0x9d, 0x5b, 0xba, 0x84, 0x65, 0xf8, 0x19, 0x27, 0xc6 }, + }, + { + { 0x00, 0xc5, 0x97, 0x52, 0x33, 0xf6, 0xa4, 0x61, 0x66, 0xa3, 0xf1, 0x34, 0x55, 0x90, 0xc2, 0x07 }, + { 0x00, 0xcc, 0x85, 0x49, 0x17, 0xdb, 0x92, 0x5e, 0x2e, 0xe2, 0xab, 0x67, 0x39, 0xf5, 0xbc, 0x70 }, + }, + { + { 0x00, 0x4a, 0x94, 0xde, 0x35, 0x7f, 0xa1, 0xeb, 0x6a, 0x20, 0xfe, 0xb4, 0x5f, 0x15, 0xcb, 0x81 }, + { 0x00, 0xd4, 0xb5, 0x61, 0x77, 0xa3, 0xc2, 0x16, 0xee, 0x3a, 0x5b, 0x8f, 0x99, 0x4d, 0x2c, 0xf8 }, + }, + { + { 0x00, 0xfb, 0xeb, 0x10, 0xcb, 0x30, 0x20, 0xdb, 0x8b, 0x70, 0x60, 0x9b, 0x40, 0xbb, 0xab, 0x50 }, + { 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69 }, + }, + }, + { + { + { 0x00, 0x86, 0x11, 0x97, 0x22, 0xa4, 0x33, 0xb5, 0x44, 0xc2, 0x55, 0xd3, 0x66, 0xe0, 0x77, 0xf1 }, + { 0x00, 0x88, 0x0d, 0x85, 0x1a, 0x92, 0x17, 0x9f, 0x34, 0xbc, 0x39, 0xb1, 0x2e, 0xa6, 0x23, 0xab }, + }, + { + { 0x00, 0x3b, 0x76, 0x4d, 0xec, 0xd7, 0x9a, 0xa1, 0xc5, 0xfe, 0xb3, 0x88, 0x29, 0x12, 0x5f, 0x64 }, + { 0x00, 0x97, 0x33, 0xa4, 0x66, 0xf1, 0x55, 0xc2, 0xcc, 0x5b, 0xff, 0x68, 0xaa, 0x3d, 0x99, 0x0e }, + }, + { + { 0x00, 0x88, 0x0d, 0x85, 0x1a, 0x92, 0x17, 0x9f, 0x34, 0xbc, 0x39, 0xb1, 0x2e, 0xa6, 0x23, 0xab }, + { 0x00, 0x68, 0xd0, 0xb8, 0xbd, 0xd5, 0x6d, 0x05, 0x67, 0x0f, 0xb7, 0xdf, 0xda, 0xb2, 0x0a, 0x62 }, + }, + { + { 0x00, 0x28, 0x50, 0x78, 0xa0, 0x88, 0xf0, 0xd8, 0x5d, 0x75, 0x0d, 0x25, 0xfd, 0xd5, 0xad, 0x85 }, + { 0x00, 0xba, 0x69, 0xd3, 0xd2, 0x68, 0xbb, 0x01, 0xb9, 0x03, 0xd0, 0x6a, 0x6b, 0xd1, 0x02, 0xb8 }, + }, + }, + { + { + { 0x00, 0xd9, 0xaf, 0x76, 0x43, 0x9a, 0xec, 0x35, 0x86, 0x5f, 0x29, 0xf0, 0xc5, 0x1c, 0x6a, 0xb3 }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + }, + { + { 0x00, 0x6e, 0xdc, 0xb2, 0xa5, 0xcb, 0x79, 0x17, 0x57, 0x39, 0x8b, 0xe5, 0xf2, 0x9c, 0x2e, 0x40 }, + { 0x00, 0xae, 0x41, 0xef, 0x82, 0x2c, 0xc3, 0x6d, 0x19, 0xb7, 0x58, 0xf6, 0x9b, 0x35, 0xda, 0x74 }, + }, + { + { 0x00, 0xdb, 0xab, 0x70, 0x4b, 0x90, 0xe0, 0x3b, 0x96, 0x4d, 0x3d, 0xe6, 0xdd, 0x06, 0x76, 0xad }, + { 0x00, 0x31, 0x62, 0x53, 0xc4, 0xf5, 0xa6, 0x97, 0x95, 0xa4, 0xf7, 0xc6, 0x51, 0x60, 0x33, 0x02 }, + }, + { + { 0x00, 0x7f, 0xfe, 0x81, 0xe1, 0x9e, 0x1f, 0x60, 0xdf, 0xa0, 0x21, 0x5e, 0x3e, 0x41, 0xc0, 0xbf }, + { 0x00, 0xa3, 0x5b, 0xf8, 0xb6, 0x15, 0xed, 0x4e, 0x71, 0xd2, 0x2a, 0x89, 0xc7, 0x64, 0x9c, 0x3f }, + }, + }, + { + { + { 0x00, 0xbf, 0x63, 0xdc, 0xc6, 0x79, 0xa5, 0x1a, 0x91, 0x2e, 0xf2, 0x4d, 0x57, 0xe8, 0x34, 0x8b }, + { 0x00, 0x3f, 0x7e, 0x41, 0xfc, 0xc3, 0x82, 0xbd, 0xe5, 0xda, 0x9b, 0xa4, 0x19, 0x26, 0x67, 0x58 }, + }, + { + { 0x00, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0, 0x1d, 0x3d, 0x5d, 0x7d, 0x9d, 0xbd, 0xdd, 0xfd }, + { 0x00, 0x3a, 0x74, 0x4e, 0xe8, 0xd2, 0x9c, 0xa6, 0xcd, 0xf7, 0xb9, 0x83, 0x25, 0x1f, 0x51, 0x6b }, + }, + { + { 0x00, 0xb2, 0x79, 0xcb, 0xf2, 0x40, 0x8b, 0x39, 0xf9, 0x4b, 0x80, 0x32, 0x0b, 0xb9, 0x72, 0xc0 }, + { 0x00, 0xef, 0xc3, 0x2c, 0x9b, 0x74, 0x58, 0xb7, 0x2b, 0xc4, 0xe8, 0x07, 0xb0, 0x5f, 0x73, 0x9c }, + }, + { + { 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d }, + { 0x00, 0x70, 0xe0, 0x90, 0xdd, 0xad, 0x3d, 0x4d, 0xa7, 0xd7, 0x47, 0x37, 0x7a, 0x0a, 0x9a, 0xea }, + }, + }, + { + { + { 0x00, 0xcb, 0x8b, 0x40, 0x0b, 0xc0, 0x80, 0x4b, 0x16, 0xdd, 0x9d, 0x56, 0x1d, 0xd6, 0x96, 0x5d }, + { 0x00, 0x2c, 0x58, 0x74, 0xb0, 0x9c, 0xe8, 0xc4, 0x7d, 0x51, 0x25, 0x09, 0xcd, 0xe1, 0x95, 0xb9 }, + }, + { + { 0x00, 0x35, 0x6a, 0x5f, 0xd4, 0xe1, 0xbe, 0x8b, 0xb5, 0x80, 0xdf, 0xea, 0x61, 0x54, 0x0b, 0x3e }, + { 0x00, 0x77, 0xee, 0x99, 0xc1, 0xb6, 0x2f, 0x58, 0x9f, 0xe8, 0x71, 0x06, 0x5e, 0x29, 0xb0, 0xc7 }, + }, + { + { 0x00, 0xc2, 0x99, 0x5b, 0x2f, 0xed, 0xb6, 0x74, 0x5e, 0x9c, 0xc7, 0x05, 0x71, 0xb3, 0xe8, 0x2a }, + { 0x00, 0xbc, 0x65, 0xd9, 0xca, 0x76, 0xaf, 0x13, 0x89, 0x35, 0xec, 0x50, 0x43, 0xff, 0x26, 0x9a }, + }, + { + { 0x00, 0xdc, 0xa5, 0x79, 0x57, 0x8b, 0xf2, 0x2e, 0xae, 0x72, 0x0b, 0xd7, 0xf9, 0x25, 0x5c, 0x80 }, + { 0x00, 0x41, 0x82, 0xc3, 0x19, 0x58, 0x9b, 0xda, 0x32, 0x73, 0xb0, 0xf1, 0x2b, 0x6a, 0xa9, 0xe8 }, + }, + }, + { + { + { 0x00, 0x26, 0x4c, 0x6a, 0x98, 0xbe, 0xd4, 0xf2, 0x2d, 0x0b, 0x61, 0x47, 0xb5, 0x93, 0xf9, 0xdf }, + { 0x00, 0x5a, 0xb4, 0xee, 0x75, 0x2f, 0xc1, 0x9b, 0xea, 0xb0, 0x5e, 0x04, 0x9f, 0xc5, 0x2b, 0x71 }, + }, + { + { 0x00, 0x55, 0xaa, 0xff, 0x49, 0x1c, 0xe3, 0xb6, 0x92, 0xc7, 0x38, 0x6d, 0xdb, 0x8e, 0x71, 0x24 }, + { 0x00, 0x39, 0x72, 0x4b, 0xe4, 0xdd, 0x96, 0xaf, 0xd5, 0xec, 0xa7, 0x9e, 0x31, 0x08, 0x43, 0x7a }, + }, + { + { 0x00, 0x5d, 0xba, 0xe7, 0x69, 0x34, 0xd3, 0x8e, 0xd2, 0x8f, 0x68, 0x35, 0xbb, 0xe6, 0x01, 0x5c }, + { 0x00, 0xb9, 0x6f, 0xd6, 0xde, 0x67, 0xb1, 0x08, 0xa1, 0x18, 0xce, 0x77, 0x7f, 0xc6, 0x10, 0xa9 }, + }, + { + { 0x00, 0x7a, 0xf4, 0x8e, 0xf5, 0x8f, 0x01, 0x7b, 0xf7, 0x8d, 0x03, 0x79, 0x02, 0x78, 0xf6, 0x8c }, + { 0x00, 0xf3, 0xfb, 0x08, 0xeb, 0x18, 0x10, 0xe3, 0xcb, 0x38, 0x30, 0xc3, 0x20, 0xd3, 0xdb, 0x28 }, + }, + }, + { + { + { 0x00, 0x66, 0xcc, 0xaa, 0x85, 0xe3, 0x49, 0x2f, 0x17, 0x71, 0xdb, 0xbd, 0x92, 0xf4, 0x5e, 0x38 }, + { 0x00, 0x2e, 0x5c, 0x72, 0xb8, 0x96, 0xe4, 0xca, 0x6d, 0x43, 0x31, 0x1f, 0xd5, 0xfb, 0x89, 0xa7 }, + }, + { + { 0x00, 0x42, 0x84, 0xc6, 0x15, 0x57, 0x91, 0xd3, 0x2a, 0x68, 0xae, 0xec, 0x3f, 0x7d, 0xbb, 0xf9 }, + { 0x00, 0x54, 0xa8, 0xfc, 0x4d, 0x19, 0xe5, 0xb1, 0x9a, 0xce, 0x32, 0x66, 0xd7, 0x83, 0x7f, 0x2b }, + }, + { + { 0x00, 0x43, 0x86, 0xc5, 0x11, 0x52, 0x97, 0xd4, 0x22, 0x61, 0xa4, 0xe7, 0x33, 0x70, 0xb5, 0xf6 }, + { 0x00, 0x44, 0x88, 0xcc, 0x0d, 0x49, 0x85, 0xc1, 0x1a, 0x5e, 0x92, 0xd6, 0x17, 0x53, 0x9f, 0xdb }, + }, + { + { 0x00, 0x9e, 0x21, 0xbf, 0x42, 0xdc, 0x63, 0xfd, 0x84, 0x1a, 0xa5, 0x3b, 0xc6, 0x58, 0xe7, 0x79 }, + { 0x00, 0x15, 0x2a, 0x3f, 0x54, 0x41, 0x7e, 0x6b, 0xa8, 0xbd, 0x82, 0x97, 0xfc, 0xe9, 0xd6, 0xc3 }, + }, + }, + { + { + { 0x00, 0x7c, 0xf8, 0x84, 0xed, 0x91, 0x15, 0x69, 0xc7, 0xbb, 0x3f, 0x43, 0x2a, 0x56, 0xd2, 0xae }, + { 0x00, 0x93, 0x3b, 0xa8, 0x76, 0xe5, 0x4d, 0xde, 0xec, 0x7f, 0xd7, 0x44, 0x9a, 0x09, 0xa1, 0x32 }, + }, + { + { 0x00, 0x31, 0x62, 0x53, 0xc4, 0xf5, 0xa6, 0x97, 0x95, 0xa4, 0xf7, 0xc6, 0x51, 0x60, 0x33, 0x02 }, + { 0x00, 0x37, 0x6e, 0x59, 0xdc, 0xeb, 0xb2, 0x85, 0xa5, 0x92, 0xcb, 0xfc, 0x79, 0x4e, 0x17, 0x20 }, + }, + { + { 0x00, 0x40, 0x80, 0xc0, 0x1d, 0x5d, 0x9d, 0xdd, 0x3a, 0x7a, 0xba, 0xfa, 0x27, 0x67, 0xa7, 0xe7 }, + { 0x00, 0x74, 0xe8, 0x9c, 0xcd, 0xb9, 0x25, 0x51, 0x87, 0xf3, 0x6f, 0x1b, 0x4a, 0x3e, 0xa2, 0xd6 }, + }, + { + { 0x00, 0xd0, 0xbd, 0x6d, 0x67, 0xb7, 0xda, 0x0a, 0xce, 0x1e, 0x73, 0xa3, 0xa9, 0x79, 0x14, 0xc4 }, + { 0x00, 0x81, 0x1f, 0x9e, 0x3e, 0xbf, 0x21, 0xa0, 0x7c, 0xfd, 0x63, 0xe2, 0x42, 0xc3, 0x5d, 0xdc }, + }, + }, + { + { + { 0x00, 0xd5, 0xb7, 0x62, 0x73, 0xa6, 0xc4, 0x11, 0xe6, 0x33, 0x51, 0x84, 0x95, 0x40, 0x22, 0xf7 }, + { 0x00, 0xd1, 0xbf, 0x6e, 0x63, 0xb2, 0xdc, 0x0d, 0xc6, 0x17, 0x79, 0xa8, 0xa5, 0x74, 0x1a, 0xcb }, + }, + { + { 0x00, 0xe1, 0xdf, 0x3e, 0xa3, 0x42, 0x7c, 0x9d, 0x5b, 0xba, 0x84, 0x65, 0xf8, 0x19, 0x27, 0xc6 }, + { 0x00, 0xb6, 0x71, 0xc7, 0xe2, 0x54, 0x93, 0x25, 0xd9, 0x6f, 0xa8, 0x1e, 0x3b, 0x8d, 0x4a, 0xfc }, + }, + { + { 0x00, 0xf7, 0xf3, 0x04, 0xfb, 0x0c, 0x08, 0xff, 0xeb, 0x1c, 0x18, 0xef, 0x10, 0xe7, 0xe3, 0x14 }, + { 0x00, 0xcb, 0x8b, 0x40, 0x0b, 0xc0, 0x80, 0x4b, 0x16, 0xdd, 0x9d, 0x56, 0x1d, 0xd6, 0x96, 0x5d }, + }, + { + { 0x00, 0x37, 0x6e, 0x59, 0xdc, 0xeb, 0xb2, 0x85, 0xa5, 0x92, 0xcb, 0xfc, 0x79, 0x4e, 0x17, 0x20 }, + { 0x00, 0x57, 0xae, 0xf9, 0x41, 0x16, 0xef, 0xb8, 0x82, 0xd5, 0x2c, 0x7b, 0xc3, 0x94, 0x6d, 0x3a }, + }, + }, + { + { + { 0x00, 0xbe, 0x61, 0xdf, 0xc2, 0x7c, 0xa3, 0x1d, 0x99, 0x27, 0xf8, 0x46, 0x5b, 0xe5, 0x3a, 0x84 }, + { 0x00, 0x2f, 0x5e, 0x71, 0xbc, 0x93, 0xe2, 0xcd, 0x65, 0x4a, 0x3b, 0x14, 0xd9, 0xf6, 0x87, 0xa8 }, + }, + { + { 0x00, 0xb9, 0x6f, 0xd6, 0xde, 0x67, 0xb1, 0x08, 0xa1, 0x18, 0xce, 0x77, 0x7f, 0xc6, 0x10, 0xa9 }, + { 0x00, 0x5f, 0xbe, 0xe1, 0x61, 0x3e, 0xdf, 0x80, 0xc2, 0x9d, 0x7c, 0x23, 0xa3, 0xfc, 0x1d, 0x42 }, + }, + { + { 0x00, 0x50, 0xa0, 0xf0, 0x5d, 0x0d, 0xfd, 0xad, 0xba, 0xea, 0x1a, 0x4a, 0xe7, 0xb7, 0x47, 0x17 }, + { 0x00, 0x69, 0xd2, 0xbb, 0xb9, 0xd0, 0x6b, 0x02, 0x6f, 0x06, 0xbd, 0xd4, 0xd6, 0xbf, 0x04, 0x6d }, + }, + { + { 0x00, 0xb4, 0x75, 0xc1, 0xea, 0x5e, 0x9f, 0x2b, 0xc9, 0x7d, 0xbc, 0x08, 0x23, 0x97, 0x56, 0xe2 }, + { 0x00, 0x8f, 0x03, 0x8c, 0x06, 0x89, 0x05, 0x8a, 0x0c, 0x83, 0x0f, 0x80, 0x0a, 0x85, 0x09, 0x86 }, + }, + }, + { + { + { 0x00, 0x25, 0x4a, 0x6f, 0x94, 0xb1, 0xde, 0xfb, 0x35, 0x10, 0x7f, 0x5a, 0xa1, 0x84, 0xeb, 0xce }, + { 0x00, 0x6a, 0xd4, 0xbe, 0xb5, 0xdf, 0x61, 0x0b, 0x77, 0x1d, 0xa3, 0xc9, 0xc2, 0xa8, 0x16, 0x7c }, + }, + { + { 0x00, 0x9e, 0x21, 0xbf, 0x42, 0xdc, 0x63, 0xfd, 0x84, 0x1a, 0xa5, 0x3b, 0xc6, 0x58, 0xe7, 0x79 }, + { 0x00, 0x15, 0x2a, 0x3f, 0x54, 0x41, 0x7e, 0x6b, 0xa8, 0xbd, 0x82, 0x97, 0xfc, 0xe9, 0xd6, 0xc3 }, + }, + { + { 0x00, 0xa8, 0x4d, 0xe5, 0x9a, 0x32, 0xd7, 0x7f, 0x29, 0x81, 0x64, 0xcc, 0xb3, 0x1b, 0xfe, 0x56 }, + { 0x00, 0x52, 0xa4, 0xf6, 0x55, 0x07, 0xf1, 0xa3, 0xaa, 0xf8, 0x0e, 0x5c, 0xff, 0xad, 0x5b, 0x09 }, + }, + { + { 0x00, 0xe1, 0xdf, 0x3e, 0xa3, 0x42, 0x7c, 0x9d, 0x5b, 0xba, 0x84, 0x65, 0xf8, 0x19, 0x27, 0xc6 }, + { 0x00, 0xb6, 0x71, 0xc7, 0xe2, 0x54, 0x93, 0x25, 0xd9, 0x6f, 0xa8, 0x1e, 0x3b, 0x8d, 0x4a, 0xfc }, + }, + }, + { + { + { 0x00, 0x1f, 0x3e, 0x21, 0x7c, 0x63, 0x42, 0x5d, 0xf8, 0xe7, 0xc6, 0xd9, 0x84, 0x9b, 0xba, 0xa5 }, + { 0x00, 0xed, 0xc7, 0x2a, 0x93, 0x7e, 0x54, 0xb9, 0x3b, 0xd6, 0xfc, 0x11, 0xa8, 0x45, 0x6f, 0x82 }, + }, + { + { 0x00, 0x90, 0x3d, 0xad, 0x7a, 0xea, 0x47, 0xd7, 0xf4, 0x64, 0xc9, 0x59, 0x8e, 0x1e, 0xb3, 0x23 }, + { 0x00, 0xf5, 0xf7, 0x02, 0xf3, 0x06, 0x04, 0xf1, 0xfb, 0x0e, 0x0c, 0xf9, 0x08, 0xfd, 0xff, 0x0a }, + }, + { + { 0x00, 0xf2, 0xf9, 0x0b, 0xef, 0x1d, 0x16, 0xe4, 0xc3, 0x31, 0x3a, 0xc8, 0x2c, 0xde, 0xd5, 0x27 }, + { 0x00, 0x9b, 0x2b, 0xb0, 0x56, 0xcd, 0x7d, 0xe6, 0xac, 0x37, 0x87, 0x1c, 0xfa, 0x61, 0xd1, 0x4a }, + }, + { + { 0x00, 0x1a, 0x34, 0x2e, 0x68, 0x72, 0x5c, 0x46, 0xd0, 0xca, 0xe4, 0xfe, 0xb8, 0xa2, 0x8c, 0x96 }, + { 0x00, 0xbd, 0x67, 0xda, 0xce, 0x73, 0xa9, 0x14, 0x81, 0x3c, 0xe6, 0x5b, 0x4f, 0xf2, 0x28, 0x95 }, + }, + }, + { + { + { 0x00, 0xe0, 0xdd, 0x3d, 0xa7, 0x47, 0x7a, 0x9a, 0x53, 0xb3, 0x8e, 0x6e, 0xf4, 0x14, 0x29, 0xc9 }, + { 0x00, 0xa6, 0x51, 0xf7, 0xa2, 0x04, 0xf3, 0x55, 0x59, 0xff, 0x08, 0xae, 0xfb, 0x5d, 0xaa, 0x0c }, + }, + { + { 0x00, 0xd4, 0xb5, 0x61, 0x77, 0xa3, 0xc2, 0x16, 0xee, 0x3a, 0x5b, 0x8f, 0x99, 0x4d, 0x2c, 0xf8 }, + { 0x00, 0xc1, 0x9f, 0x5e, 0x23, 0xe2, 0xbc, 0x7d, 0x46, 0x87, 0xd9, 0x18, 0x65, 0xa4, 0xfa, 0x3b }, + }, + { + { 0x00, 0x7a, 0xf4, 0x8e, 0xf5, 0x8f, 0x01, 0x7b, 0xf7, 0x8d, 0x03, 0x79, 0x02, 0x78, 0xf6, 0x8c }, + { 0x00, 0xf3, 0xfb, 0x08, 0xeb, 0x18, 0x10, 0xe3, 0xcb, 0x38, 0x30, 0xc3, 0x20, 0xd3, 0xdb, 0x28 }, + }, + { + { 0x00, 0x24, 0x48, 0x6c, 0x90, 0xb4, 0xd8, 0xfc, 0x3d, 0x19, 0x75, 0x51, 0xad, 0x89, 0xe5, 0xc1 }, + { 0x00, 0x7a, 0xf4, 0x8e, 0xf5, 0x8f, 0x01, 0x7b, 0xf7, 0x8d, 0x03, 0x79, 0x02, 0x78, 0xf6, 0x8c }, + }, + }, + { + { + { 0x00, 0x98, 0x2d, 0xb5, 0x5a, 0xc2, 0x77, 0xef, 0xb4, 0x2c, 0x99, 0x01, 0xee, 0x76, 0xc3, 0x5b }, + { 0x00, 0x75, 0xea, 0x9f, 0xc9, 0xbc, 0x23, 0x56, 0x8f, 0xfa, 0x65, 0x10, 0x46, 0x33, 0xac, 0xd9 }, + }, + { + { 0x00, 0xba, 0x69, 0xd3, 0xd2, 0x68, 0xbb, 0x01, 0xb9, 0x03, 0xd0, 0x6a, 0x6b, 0xd1, 0x02, 0xb8 }, + { 0x00, 0x6f, 0xde, 0xb1, 0xa1, 0xce, 0x7f, 0x10, 0x5f, 0x30, 0x81, 0xee, 0xfe, 0x91, 0x20, 0x4f }, + }, + { + { 0x00, 0x71, 0xe2, 0x93, 0xd9, 0xa8, 0x3b, 0x4a, 0xaf, 0xde, 0x4d, 0x3c, 0x76, 0x07, 0x94, 0xe5 }, + { 0x00, 0x43, 0x86, 0xc5, 0x11, 0x52, 0x97, 0xd4, 0x22, 0x61, 0xa4, 0xe7, 0x33, 0x70, 0xb5, 0xf6 }, + }, + { + { 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11 }, + { 0x00, 0x30, 0x60, 0x50, 0xc0, 0xf0, 0xa0, 0x90, 0x9d, 0xad, 0xfd, 0xcd, 0x5d, 0x6d, 0x3d, 0x0d }, + }, + }, + { + { + { 0x00, 0x27, 0x4e, 0x69, 0x9c, 0xbb, 0xd2, 0xf5, 0x25, 0x02, 0x6b, 0x4c, 0xb9, 0x9e, 0xf7, 0xd0 }, + { 0x00, 0x4a, 0x94, 0xde, 0x35, 0x7f, 0xa1, 0xeb, 0x6a, 0x20, 0xfe, 0xb4, 0x5f, 0x15, 0xcb, 0x81 }, + }, + { + { 0x00, 0xdb, 0xab, 0x70, 0x4b, 0x90, 0xe0, 0x3b, 0x96, 0x4d, 0x3d, 0xe6, 0xdd, 0x06, 0x76, 0xad }, + { 0x00, 0x31, 0x62, 0x53, 0xc4, 0xf5, 0xa6, 0x97, 0x95, 0xa4, 0xf7, 0xc6, 0x51, 0x60, 0x33, 0x02 }, + }, + { + { 0x00, 0xa4, 0x55, 0xf1, 0xaa, 0x0e, 0xff, 0x5b, 0x49, 0xed, 0x1c, 0xb8, 0xe3, 0x47, 0xb6, 0x12 }, + { 0x00, 0x92, 0x39, 0xab, 0x72, 0xe0, 0x4b, 0xd9, 0xe4, 0x76, 0xdd, 0x4f, 0x96, 0x04, 0xaf, 0x3d }, + }, + { + { 0x00, 0xae, 0x41, 0xef, 0x82, 0x2c, 0xc3, 0x6d, 0x19, 0xb7, 0x58, 0xf6, 0x9b, 0x35, 0xda, 0x74 }, + { 0x00, 0x32, 0x64, 0x56, 0xc8, 0xfa, 0xac, 0x9e, 0x8d, 0xbf, 0xe9, 0xdb, 0x45, 0x77, 0x21, 0x13 }, + }, + }, + { + { + { 0x00, 0x92, 0x39, 0xab, 0x72, 0xe0, 0x4b, 0xd9, 0xe4, 0x76, 0xdd, 0x4f, 0x96, 0x04, 0xaf, 0x3d }, + { 0x00, 0xd5, 0xb7, 0x62, 0x73, 0xa6, 0xc4, 0x11, 0xe6, 0x33, 0x51, 0x84, 0x95, 0x40, 0x22, 0xf7 }, + }, + { + { 0x00, 0xf7, 0xf3, 0x04, 0xfb, 0x0c, 0x08, 0xff, 0xeb, 0x1c, 0x18, 0xef, 0x10, 0xe7, 0xe3, 0x14 }, + { 0x00, 0xcb, 0x8b, 0x40, 0x0b, 0xc0, 0x80, 0x4b, 0x16, 0xdd, 0x9d, 0x56, 0x1d, 0xd6, 0x96, 0x5d }, + }, + { + { 0x00, 0xd2, 0xb9, 0x6b, 0x6f, 0xbd, 0xd6, 0x04, 0xde, 0x0c, 0x67, 0xb5, 0xb1, 0x63, 0x08, 0xda }, + { 0x00, 0xa1, 0x5f, 0xfe, 0xbe, 0x1f, 0xe1, 0x40, 0x61, 0xc0, 0x3e, 0x9f, 0xdf, 0x7e, 0x80, 0x21 }, + }, + { + { 0x00, 0x94, 0x35, 0xa1, 0x6a, 0xfe, 0x5f, 0xcb, 0xd4, 0x40, 0xe1, 0x75, 0xbe, 0x2a, 0x8b, 0x1f }, + { 0x00, 0xb5, 0x77, 0xc2, 0xee, 0x5b, 0x99, 0x2c, 0xc1, 0x74, 0xb6, 0x03, 0x2f, 0x9a, 0x58, 0xed }, + }, + }, + { + { + { 0x00, 0x51, 0xa2, 0xf3, 0x59, 0x08, 0xfb, 0xaa, 0xb2, 0xe3, 0x10, 0x41, 0xeb, 0xba, 0x49, 0x18 }, + { 0x00, 0x79, 0xf2, 0x8b, 0xf9, 0x80, 0x0b, 0x72, 0xef, 0x96, 0x1d, 0x64, 0x16, 0x6f, 0xe4, 0x9d }, + }, + { + { 0x00, 0x2a, 0x54, 0x7e, 0xa8, 0x82, 0xfc, 0xd6, 0x4d, 0x67, 0x19, 0x33, 0xe5, 0xcf, 0xb1, 0x9b }, + { 0x00, 0x9a, 0x29, 0xb3, 0x52, 0xc8, 0x7b, 0xe1, 0xa4, 0x3e, 0x8d, 0x17, 0xf6, 0x6c, 0xdf, 0x45 }, + }, + { + { 0x00, 0xbf, 0x63, 0xdc, 0xc6, 0x79, 0xa5, 0x1a, 0x91, 0x2e, 0xf2, 0x4d, 0x57, 0xe8, 0x34, 0x8b }, + { 0x00, 0x3f, 0x7e, 0x41, 0xfc, 0xc3, 0x82, 0xbd, 0xe5, 0xda, 0x9b, 0xa4, 0x19, 0x26, 0x67, 0x58 }, + }, + { + { 0x00, 0xba, 0x69, 0xd3, 0xd2, 0x68, 0xbb, 0x01, 0xb9, 0x03, 0xd0, 0x6a, 0x6b, 0xd1, 0x02, 0xb8 }, + { 0x00, 0x6f, 0xde, 0xb1, 0xa1, 0xce, 0x7f, 0x10, 0x5f, 0x30, 0x81, 0xee, 0xfe, 0x91, 0x20, 0x4f }, + }, + }, + { + { + { 0x00, 0xc7, 0x93, 0x54, 0x3b, 0xfc, 0xa8, 0x6f, 0x76, 0xb1, 0xe5, 0x22, 0x4d, 0x8a, 0xde, 0x19 }, + { 0x00, 0xec, 0xc5, 0x29, 0x97, 0x7b, 0x52, 0xbe, 0x33, 0xdf, 0xf6, 0x1a, 0xa4, 0x48, 0x61, 0x8d }, + }, + { + { 0x00, 0xe9, 0xcf, 0x26, 0x83, 0x6a, 0x4c, 0xa5, 0x1b, 0xf2, 0xd4, 0x3d, 0x98, 0x71, 0x57, 0xbe }, + { 0x00, 0x36, 0x6c, 0x5a, 0xd8, 0xee, 0xb4, 0x82, 0xad, 0x9b, 0xc1, 0xf7, 0x75, 0x43, 0x19, 0x2f }, + }, + { + { 0x00, 0x31, 0x62, 0x53, 0xc4, 0xf5, 0xa6, 0x97, 0x95, 0xa4, 0xf7, 0xc6, 0x51, 0x60, 0x33, 0x02 }, + { 0x00, 0x37, 0x6e, 0x59, 0xdc, 0xeb, 0xb2, 0x85, 0xa5, 0x92, 0xcb, 0xfc, 0x79, 0x4e, 0x17, 0x20 }, + }, + { + { 0x00, 0x88, 0x0d, 0x85, 0x1a, 0x92, 0x17, 0x9f, 0x34, 0xbc, 0x39, 0xb1, 0x2e, 0xa6, 0x23, 0xab }, + { 0x00, 0x68, 0xd0, 0xb8, 0xbd, 0xd5, 0x6d, 0x05, 0x67, 0x0f, 0xb7, 0xdf, 0xda, 0xb2, 0x0a, 0x62 }, + }, + }, + { + { + { 0x00, 0x45, 0x8a, 0xcf, 0x09, 0x4c, 0x83, 0xc6, 0x12, 0x57, 0x98, 0xdd, 0x1b, 0x5e, 0x91, 0xd4 }, + { 0x00, 0x24, 0x48, 0x6c, 0x90, 0xb4, 0xd8, 0xfc, 0x3d, 0x19, 0x75, 0x51, 0xad, 0x89, 0xe5, 0xc1 }, + }, + { + { 0x00, 0x3a, 0x74, 0x4e, 0xe8, 0xd2, 0x9c, 0xa6, 0xcd, 0xf7, 0xb9, 0x83, 0x25, 0x1f, 0x51, 0x6b }, + { 0x00, 0x87, 0x13, 0x94, 0x26, 0xa1, 0x35, 0xb2, 0x4c, 0xcb, 0x5f, 0xd8, 0x6a, 0xed, 0x79, 0xfe }, + }, + { + { 0x00, 0x90, 0x3d, 0xad, 0x7a, 0xea, 0x47, 0xd7, 0xf4, 0x64, 0xc9, 0x59, 0x8e, 0x1e, 0xb3, 0x23 }, + { 0x00, 0xf5, 0xf7, 0x02, 0xf3, 0x06, 0x04, 0xf1, 0xfb, 0x0e, 0x0c, 0xf9, 0x08, 0xfd, 0xff, 0x0a }, + }, + { + { 0x00, 0x2f, 0x5e, 0x71, 0xbc, 0x93, 0xe2, 0xcd, 0x65, 0x4a, 0x3b, 0x14, 0xd9, 0xf6, 0x87, 0xa8 }, + { 0x00, 0xca, 0x89, 0x43, 0x0f, 0xc5, 0x86, 0x4c, 0x1e, 0xd4, 0x97, 0x5d, 0x11, 0xdb, 0x98, 0x52 }, + }, + }, + { + { + { 0x00, 0x2c, 0x58, 0x74, 0xb0, 0x9c, 0xe8, 0xc4, 0x7d, 0x51, 0x25, 0x09, 0xcd, 0xe1, 0x95, 0xb9 }, + { 0x00, 0xfa, 0xe9, 0x13, 0xcf, 0x35, 0x26, 0xdc, 0x83, 0x79, 0x6a, 0x90, 0x4c, 0xb6, 0xa5, 0x5f }, + }, + { + { 0x00, 0xa0, 0x5d, 0xfd, 0xba, 0x1a, 0xe7, 0x47, 0x69, 0xc9, 0x34, 0x94, 0xd3, 0x73, 0x8e, 0x2e }, + { 0x00, 0xd2, 0xb9, 0x6b, 0x6f, 0xbd, 0xd6, 0x04, 0xde, 0x0c, 0x67, 0xb5, 0xb1, 0x63, 0x08, 0xda }, + }, + { + { 0x00, 0x19, 0x32, 0x2b, 0x64, 0x7d, 0x56, 0x4f, 0xc8, 0xd1, 0xfa, 0xe3, 0xac, 0xb5, 0x9e, 0x87 }, + { 0x00, 0x8d, 0x07, 0x8a, 0x0e, 0x83, 0x09, 0x84, 0x1c, 0x91, 0x1b, 0x96, 0x12, 0x9f, 0x15, 0x98 }, + }, + { + { 0x00, 0xea, 0xc9, 0x23, 0x8f, 0x65, 0x46, 0xac, 0x03, 0xe9, 0xca, 0x20, 0x8c, 0x66, 0x45, 0xaf }, + { 0x00, 0x06, 0x0c, 0x0a, 0x18, 0x1e, 0x14, 0x12, 0x30, 0x36, 0x3c, 0x3a, 0x28, 0x2e, 0x24, 0x22 }, + }, + }, + { + { + { 0x00, 0xc0, 0x9d, 0x5d, 0x27, 0xe7, 0xba, 0x7a, 0x4e, 0x8e, 0xd3, 0x13, 0x69, 0xa9, 0xf4, 0x34 }, + { 0x00, 0x9c, 0x25, 0xb9, 0x4a, 0xd6, 0x6f, 0xf3, 0x94, 0x08, 0xb1, 0x2d, 0xde, 0x42, 0xfb, 0x67 }, + }, + { + { 0x00, 0x75, 0xea, 0x9f, 0xc9, 0xbc, 0x23, 0x56, 0x8f, 0xfa, 0x65, 0x10, 0x46, 0x33, 0xac, 0xd9 }, + { 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11 }, + }, + { + { 0x00, 0x9a, 0x29, 0xb3, 0x52, 0xc8, 0x7b, 0xe1, 0xa4, 0x3e, 0x8d, 0x17, 0xf6, 0x6c, 0xdf, 0x45 }, + { 0x00, 0x55, 0xaa, 0xff, 0x49, 0x1c, 0xe3, 0xb6, 0x92, 0xc7, 0x38, 0x6d, 0xdb, 0x8e, 0x71, 0x24 }, + }, + { + { 0x00, 0x2e, 0x5c, 0x72, 0xb8, 0x96, 0xe4, 0xca, 0x6d, 0x43, 0x31, 0x1f, 0xd5, 0xfb, 0x89, 0xa7 }, + { 0x00, 0xda, 0xa9, 0x73, 0x4f, 0x95, 0xe6, 0x3c, 0x9e, 0x44, 0x37, 0xed, 0xd1, 0x0b, 0x78, 0xa2 }, + }, + }, + { + { + { 0x00, 0xad, 0x47, 0xea, 0x8e, 0x23, 0xc9, 0x64, 0x01, 0xac, 0x46, 0xeb, 0x8f, 0x22, 0xc8, 0x65 }, + { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e }, + }, + { + { 0x00, 0x7a, 0xf4, 0x8e, 0xf5, 0x8f, 0x01, 0x7b, 0xf7, 0x8d, 0x03, 0x79, 0x02, 0x78, 0xf6, 0x8c }, + { 0x00, 0xf3, 0xfb, 0x08, 0xeb, 0x18, 0x10, 0xe3, 0xcb, 0x38, 0x30, 0xc3, 0x20, 0xd3, 0xdb, 0x28 }, + }, + { + { 0x00, 0x8e, 0x01, 0x8f, 0x02, 0x8c, 0x03, 0x8d, 0x04, 0x8a, 0x05, 0x8b, 0x06, 0x88, 0x07, 0x89 }, + { 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78 }, + }, + { + { 0x00, 0x8c, 0x05, 0x89, 0x0a, 0x86, 0x0f, 0x83, 0x14, 0x98, 0x11, 0x9d, 0x1e, 0x92, 0x1b, 0x97 }, + { 0x00, 0x28, 0x50, 0x78, 0xa0, 0x88, 0xf0, 0xd8, 0x5d, 0x75, 0x0d, 0x25, 0xfd, 0xd5, 0xad, 0x85 }, + }, + }, + { + { + { 0x00, 0xa7, 0x53, 0xf4, 0xa6, 0x01, 0xf5, 0x52, 0x51, 0xf6, 0x02, 0xa5, 0xf7, 0x50, 0xa4, 0x03 }, + { 0x00, 0xa2, 0x59, 0xfb, 0xb2, 0x10, 0xeb, 0x49, 0x79, 0xdb, 0x20, 0x82, 0xcb, 0x69, 0x92, 0x30 }, + }, + { + { 0x00, 0xd3, 0xbb, 0x68, 0x6b, 0xb8, 0xd0, 0x03, 0xd6, 0x05, 0x6d, 0xbe, 0xbd, 0x6e, 0x06, 0xd5 }, + { 0x00, 0xb1, 0x7f, 0xce, 0xfe, 0x4f, 0x81, 0x30, 0xe1, 0x50, 0x9e, 0x2f, 0x1f, 0xae, 0x60, 0xd1 }, + }, + { + { 0x00, 0xf6, 0xf1, 0x07, 0xff, 0x09, 0x0e, 0xf8, 0xe3, 0x15, 0x12, 0xe4, 0x1c, 0xea, 0xed, 0x1b }, + { 0x00, 0xdb, 0xab, 0x70, 0x4b, 0x90, 0xe0, 0x3b, 0x96, 0x4d, 0x3d, 0xe6, 0xdd, 0x06, 0x76, 0xad }, + }, + { + { 0x00, 0x5b, 0xb6, 0xed, 0x71, 0x2a, 0xc7, 0x9c, 0xe2, 0xb9, 0x54, 0x0f, 0x93, 0xc8, 0x25, 0x7e }, + { 0x00, 0xd9, 0xaf, 0x76, 0x43, 0x9a, 0xec, 0x35, 0x86, 0x5f, 0x29, 0xf0, 0xc5, 0x1c, 0x6a, 0xb3 }, + }, + }, + { + { + { 0x00, 0x69, 0xd2, 0xbb, 0xb9, 0xd0, 0x6b, 0x02, 0x6f, 0x06, 0xbd, 0xd4, 0xd6, 0xbf, 0x04, 0x6d }, + { 0x00, 0xde, 0xa1, 0x7f, 0x5f, 0x81, 0xfe, 0x20, 0xbe, 0x60, 0x1f, 0xc1, 0xe1, 0x3f, 0x40, 0x9e }, + }, + { + { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e }, + { 0x00, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0, 0x1d, 0x3d, 0x5d, 0x7d, 0x9d, 0xbd, 0xdd, 0xfd }, + }, + { + { 0x00, 0xc3, 0x9b, 0x58, 0x2b, 0xe8, 0xb0, 0x73, 0x56, 0x95, 0xcd, 0x0e, 0x7d, 0xbe, 0xe6, 0x25 }, + { 0x00, 0xac, 0x45, 0xe9, 0x8a, 0x26, 0xcf, 0x63, 0x09, 0xa5, 0x4c, 0xe0, 0x83, 0x2f, 0xc6, 0x6a }, + }, + { + { 0x00, 0xbb, 0x6b, 0xd0, 0xd6, 0x6d, 0xbd, 0x06, 0xb1, 0x0a, 0xda, 0x61, 0x67, 0xdc, 0x0c, 0xb7 }, + { 0x00, 0x7f, 0xfe, 0x81, 0xe1, 0x9e, 0x1f, 0x60, 0xdf, 0xa0, 0x21, 0x5e, 0x3e, 0x41, 0xc0, 0xbf }, + }, + }, + { + { + { 0x00, 0xf7, 0xf3, 0x04, 0xfb, 0x0c, 0x08, 0xff, 0xeb, 0x1c, 0x18, 0xef, 0x10, 0xe7, 0xe3, 0x14 }, + { 0x00, 0xcb, 0x8b, 0x40, 0x0b, 0xc0, 0x80, 0x4b, 0x16, 0xdd, 0x9d, 0x56, 0x1d, 0xd6, 0x96, 0x5d }, + }, + { + { 0x00, 0xee, 0xc1, 0x2f, 0x9f, 0x71, 0x5e, 0xb0, 0x23, 0xcd, 0xe2, 0x0c, 0xbc, 0x52, 0x7d, 0x93 }, + { 0x00, 0x46, 0x8c, 0xca, 0x05, 0x43, 0x89, 0xcf, 0x0a, 0x4c, 0x86, 0xc0, 0x0f, 0x49, 0x83, 0xc5 }, + }, + { + { 0x00, 0xa6, 0x51, 0xf7, 0xa2, 0x04, 0xf3, 0x55, 0x59, 0xff, 0x08, 0xae, 0xfb, 0x5d, 0xaa, 0x0c }, + { 0x00, 0xb2, 0x79, 0xcb, 0xf2, 0x40, 0x8b, 0x39, 0xf9, 0x4b, 0x80, 0x32, 0x0b, 0xb9, 0x72, 0xc0 }, + }, + { + { 0x00, 0x79, 0xf2, 0x8b, 0xf9, 0x80, 0x0b, 0x72, 0xef, 0x96, 0x1d, 0x64, 0x16, 0x6f, 0xe4, 0x9d }, + { 0x00, 0xc3, 0x9b, 0x58, 0x2b, 0xe8, 0xb0, 0x73, 0x56, 0x95, 0xcd, 0x0e, 0x7d, 0xbe, 0xe6, 0x25 }, + }, + }, + { + { + { 0x00, 0xb4, 0x75, 0xc1, 0xea, 0x5e, 0x9f, 0x2b, 0xc9, 0x7d, 0xbc, 0x08, 0x23, 0x97, 0x56, 0xe2 }, + { 0x00, 0x8f, 0x03, 0x8c, 0x06, 0x89, 0x05, 0x8a, 0x0c, 0x83, 0x0f, 0x80, 0x0a, 0x85, 0x09, 0x86 }, + }, + { + { 0x00, 0x9c, 0x25, 0xb9, 0x4a, 0xd6, 0x6f, 0xf3, 0x94, 0x08, 0xb1, 0x2d, 0xde, 0x42, 0xfb, 0x67 }, + { 0x00, 0x35, 0x6a, 0x5f, 0xd4, 0xe1, 0xbe, 0x8b, 0xb5, 0x80, 0xdf, 0xea, 0x61, 0x54, 0x0b, 0x3e }, + }, + { + { 0x00, 0xe7, 0xd3, 0x34, 0xbb, 0x5c, 0x68, 0x8f, 0x6b, 0x8c, 0xb8, 0x5f, 0xd0, 0x37, 0x03, 0xe4 }, + { 0x00, 0xd6, 0xb1, 0x67, 0x7f, 0xa9, 0xce, 0x18, 0xfe, 0x28, 0x4f, 0x99, 0x81, 0x57, 0x30, 0xe6 }, + }, + { + { 0x00, 0xd1, 0xbf, 0x6e, 0x63, 0xb2, 0xdc, 0x0d, 0xc6, 0x17, 0x79, 0xa8, 0xa5, 0x74, 0x1a, 0xcb }, + { 0x00, 0x91, 0x3f, 0xae, 0x7e, 0xef, 0x41, 0xd0, 0xfc, 0x6d, 0xc3, 0x52, 0x82, 0x13, 0xbd, 0x2c }, + }, + }, + { + { + { 0x00, 0xe8, 0xcd, 0x25, 0x87, 0x6f, 0x4a, 0xa2, 0x13, 0xfb, 0xde, 0x36, 0x94, 0x7c, 0x59, 0xb1 }, + { 0x00, 0x26, 0x4c, 0x6a, 0x98, 0xbe, 0xd4, 0xf2, 0x2d, 0x0b, 0x61, 0x47, 0xb5, 0x93, 0xf9, 0xdf }, + }, + { + { 0x00, 0xc6, 0x91, 0x57, 0x3f, 0xf9, 0xae, 0x68, 0x7e, 0xb8, 0xef, 0x29, 0x41, 0x87, 0xd0, 0x16 }, + { 0x00, 0xfc, 0xe5, 0x19, 0xd7, 0x2b, 0x32, 0xce, 0xb3, 0x4f, 0x56, 0xaa, 0x64, 0x98, 0x81, 0x7d }, + }, + { + { 0x00, 0x60, 0xc0, 0xa0, 0x9d, 0xfd, 0x5d, 0x3d, 0x27, 0x47, 0xe7, 0x87, 0xba, 0xda, 0x7a, 0x1a }, + { 0x00, 0x4e, 0x9c, 0xd2, 0x25, 0x6b, 0xb9, 0xf7, 0x4a, 0x04, 0xd6, 0x98, 0x6f, 0x21, 0xf3, 0xbd }, + }, + { + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b }, + }, + }, + { + { + { 0x00, 0x84, 0x15, 0x91, 0x2a, 0xae, 0x3f, 0xbb, 0x54, 0xd0, 0x41, 0xc5, 0x7e, 0xfa, 0x6b, 0xef }, + { 0x00, 0xa8, 0x4d, 0xe5, 0x9a, 0x32, 0xd7, 0x7f, 0x29, 0x81, 0x64, 0xcc, 0xb3, 0x1b, 0xfe, 0x56 }, + }, + { + { 0x00, 0x1f, 0x3e, 0x21, 0x7c, 0x63, 0x42, 0x5d, 0xf8, 0xe7, 0xc6, 0xd9, 0x84, 0x9b, 0xba, 0xa5 }, + { 0x00, 0xed, 0xc7, 0x2a, 0x93, 0x7e, 0x54, 0xb9, 0x3b, 0xd6, 0xfc, 0x11, 0xa8, 0x45, 0x6f, 0x82 }, + }, + { + { 0x00, 0x12, 0x24, 0x36, 0x48, 0x5a, 0x6c, 0x7e, 0x90, 0x82, 0xb4, 0xa6, 0xd8, 0xca, 0xfc, 0xee }, + { 0x00, 0x3d, 0x7a, 0x47, 0xf4, 0xc9, 0x8e, 0xb3, 0xf5, 0xc8, 0x8f, 0xb2, 0x01, 0x3c, 0x7b, 0x46 }, + }, + { + { 0x00, 0xff, 0xe3, 0x1c, 0xdb, 0x24, 0x38, 0xc7, 0xab, 0x54, 0x48, 0xb7, 0x70, 0x8f, 0x93, 0x6c }, + { 0x00, 0x4b, 0x96, 0xdd, 0x31, 0x7a, 0xa7, 0xec, 0x62, 0x29, 0xf4, 0xbf, 0x53, 0x18, 0xc5, 0x8e }, + }, + }, + { + { + { 0x00, 0xe1, 0xdf, 0x3e, 0xa3, 0x42, 0x7c, 0x9d, 0x5b, 0xba, 0x84, 0x65, 0xf8, 0x19, 0x27, 0xc6 }, + { 0x00, 0xb6, 0x71, 0xc7, 0xe2, 0x54, 0x93, 0x25, 0xd9, 0x6f, 0xa8, 0x1e, 0x3b, 0x8d, 0x4a, 0xfc }, + }, + { + { 0x00, 0x14, 0x28, 0x3c, 0x50, 0x44, 0x78, 0x6c, 0xa0, 0xb4, 0x88, 0x9c, 0xf0, 0xe4, 0xd8, 0xcc }, + { 0x00, 0x5d, 0xba, 0xe7, 0x69, 0x34, 0xd3, 0x8e, 0xd2, 0x8f, 0x68, 0x35, 0xbb, 0xe6, 0x01, 0x5c }, + }, + { + { 0x00, 0xee, 0xc1, 0x2f, 0x9f, 0x71, 0x5e, 0xb0, 0x23, 0xcd, 0xe2, 0x0c, 0xbc, 0x52, 0x7d, 0x93 }, + { 0x00, 0x46, 0x8c, 0xca, 0x05, 0x43, 0x89, 0xcf, 0x0a, 0x4c, 0x86, 0xc0, 0x0f, 0x49, 0x83, 0xc5 }, + }, + { + { 0x00, 0xa4, 0x55, 0xf1, 0xaa, 0x0e, 0xff, 0x5b, 0x49, 0xed, 0x1c, 0xb8, 0xe3, 0x47, 0xb6, 0x12 }, + { 0x00, 0x92, 0x39, 0xab, 0x72, 0xe0, 0x4b, 0xd9, 0xe4, 0x76, 0xdd, 0x4f, 0x96, 0x04, 0xaf, 0x3d }, + }, + }, + { + { + { 0x00, 0x18, 0x30, 0x28, 0x60, 0x78, 0x50, 0x48, 0xc0, 0xd8, 0xf0, 0xe8, 0xa0, 0xb8, 0x90, 0x88 }, + { 0x00, 0x9d, 0x27, 0xba, 0x4e, 0xd3, 0x69, 0xf4, 0x9c, 0x01, 0xbb, 0x26, 0xd2, 0x4f, 0xf5, 0x68 }, + }, + { + { 0x00, 0xcc, 0x85, 0x49, 0x17, 0xdb, 0x92, 0x5e, 0x2e, 0xe2, 0xab, 0x67, 0x39, 0xf5, 0xbc, 0x70 }, + { 0x00, 0x5c, 0xb8, 0xe4, 0x6d, 0x31, 0xd5, 0x89, 0xda, 0x86, 0x62, 0x3e, 0xb7, 0xeb, 0x0f, 0x53 }, + }, + { + { 0x00, 0x2d, 0x5a, 0x77, 0xb4, 0x99, 0xee, 0xc3, 0x75, 0x58, 0x2f, 0x02, 0xc1, 0xec, 0x9b, 0xb6 }, + { 0x00, 0xea, 0xc9, 0x23, 0x8f, 0x65, 0x46, 0xac, 0x03, 0xe9, 0xca, 0x20, 0x8c, 0x66, 0x45, 0xaf }, + }, + { + { 0x00, 0x19, 0x32, 0x2b, 0x64, 0x7d, 0x56, 0x4f, 0xc8, 0xd1, 0xfa, 0xe3, 0xac, 0xb5, 0x9e, 0x87 }, + { 0x00, 0x8d, 0x07, 0x8a, 0x0e, 0x83, 0x09, 0x84, 0x1c, 0x91, 0x1b, 0x96, 0x12, 0x9f, 0x15, 0x98 }, + }, + }, + { + { + { 0x00, 0x88, 0x0d, 0x85, 0x1a, 0x92, 0x17, 0x9f, 0x34, 0xbc, 0x39, 0xb1, 0x2e, 0xa6, 0x23, 0xab }, + { 0x00, 0x68, 0xd0, 0xb8, 0xbd, 0xd5, 0x6d, 0x05, 0x67, 0x0f, 0xb7, 0xdf, 0xda, 0xb2, 0x0a, 0x62 }, + }, + { + { 0x00, 0x22, 0x44, 0x66, 0x88, 0xaa, 0xcc, 0xee, 0x0d, 0x2f, 0x49, 0x6b, 0x85, 0xa7, 0xc1, 0xe3 }, + { 0x00, 0x1a, 0x34, 0x2e, 0x68, 0x72, 0x5c, 0x46, 0xd0, 0xca, 0xe4, 0xfe, 0xb8, 0xa2, 0x8c, 0x96 }, + }, + { + { 0x00, 0xde, 0xa1, 0x7f, 0x5f, 0x81, 0xfe, 0x20, 0xbe, 0x60, 0x1f, 0xc1, 0xe1, 0x3f, 0x40, 0x9e }, + { 0x00, 0x61, 0xc2, 0xa3, 0x99, 0xf8, 0x5b, 0x3a, 0x2f, 0x4e, 0xed, 0x8c, 0xb6, 0xd7, 0x74, 0x15 }, + }, + { + { 0x00, 0x3c, 0x78, 0x44, 0xf0, 0xcc, 0x88, 0xb4, 0xfd, 0xc1, 0x85, 0xb9, 0x0d, 0x31, 0x75, 0x49 }, + { 0x00, 0xe7, 0xd3, 0x34, 0xbb, 0x5c, 0x68, 0x8f, 0x6b, 0x8c, 0xb8, 0x5f, 0xd0, 0x37, 0x03, 0xe4 }, + }, + }, + { + { + { 0x00, 0x3c, 0x78, 0x44, 0xf0, 0xcc, 0x88, 0xb4, 0xfd, 0xc1, 0x85, 0xb9, 0x0d, 0x31, 0x75, 0x49 }, + { 0x00, 0xe7, 0xd3, 0x34, 0xbb, 0x5c, 0x68, 0x8f, 0x6b, 0x8c, 0xb8, 0x5f, 0xd0, 0x37, 0x03, 0xe4 }, + }, + { + { 0x00, 0x4d, 0x9a, 0xd7, 0x29, 0x64, 0xb3, 0xfe, 0x52, 0x1f, 0xc8, 0x85, 0x7b, 0x36, 0xe1, 0xac }, + { 0x00, 0xa4, 0x55, 0xf1, 0xaa, 0x0e, 0xff, 0x5b, 0x49, 0xed, 0x1c, 0xb8, 0xe3, 0x47, 0xb6, 0x12 }, + }, + { + { 0x00, 0x38, 0x70, 0x48, 0xe0, 0xd8, 0x90, 0xa8, 0xdd, 0xe5, 0xad, 0x95, 0x3d, 0x05, 0x4d, 0x75 }, + { 0x00, 0xa7, 0x53, 0xf4, 0xa6, 0x01, 0xf5, 0x52, 0x51, 0xf6, 0x02, 0xa5, 0xf7, 0x50, 0xa4, 0x03 }, + }, + { + { 0x00, 0x2a, 0x54, 0x7e, 0xa8, 0x82, 0xfc, 0xd6, 0x4d, 0x67, 0x19, 0x33, 0xe5, 0xcf, 0xb1, 0x9b }, + { 0x00, 0x9a, 0x29, 0xb3, 0x52, 0xc8, 0x7b, 0xe1, 0xa4, 0x3e, 0x8d, 0x17, 0xf6, 0x6c, 0xdf, 0x45 }, + }, + }, + { + { + { 0x00, 0x76, 0xec, 0x9a, 0xc5, 0xb3, 0x29, 0x5f, 0x97, 0xe1, 0x7b, 0x0d, 0x52, 0x24, 0xbe, 0xc8 }, + { 0x00, 0x33, 0x66, 0x55, 0xcc, 0xff, 0xaa, 0x99, 0x85, 0xb6, 0xe3, 0xd0, 0x49, 0x7a, 0x2f, 0x1c }, + }, + { + { 0x00, 0x30, 0x60, 0x50, 0xc0, 0xf0, 0xa0, 0x90, 0x9d, 0xad, 0xfd, 0xcd, 0x5d, 0x6d, 0x3d, 0x0d }, + { 0x00, 0x27, 0x4e, 0x69, 0x9c, 0xbb, 0xd2, 0xf5, 0x25, 0x02, 0x6b, 0x4c, 0xb9, 0x9e, 0xf7, 0xd0 }, + }, + { + { 0x00, 0xe8, 0xcd, 0x25, 0x87, 0x6f, 0x4a, 0xa2, 0x13, 0xfb, 0xde, 0x36, 0x94, 0x7c, 0x59, 0xb1 }, + { 0x00, 0x26, 0x4c, 0x6a, 0x98, 0xbe, 0xd4, 0xf2, 0x2d, 0x0b, 0x61, 0x47, 0xb5, 0x93, 0xf9, 0xdf }, + }, + { + { 0x00, 0x4e, 0x9c, 0xd2, 0x25, 0x6b, 0xb9, 0xf7, 0x4a, 0x04, 0xd6, 0x98, 0x6f, 0x21, 0xf3, 0xbd }, + { 0x00, 0x94, 0x35, 0xa1, 0x6a, 0xfe, 0x5f, 0xcb, 0xd4, 0x40, 0xe1, 0x75, 0xbe, 0x2a, 0x8b, 0x1f }, + }, + }, + { + { + { 0x00, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0, 0x1d, 0x3d, 0x5d, 0x7d, 0x9d, 0xbd, 0xdd, 0xfd }, + { 0x00, 0x3a, 0x74, 0x4e, 0xe8, 0xd2, 0x9c, 0xa6, 0xcd, 0xf7, 0xb9, 0x83, 0x25, 0x1f, 0x51, 0x6b }, + }, + { + { 0x00, 0x71, 0xe2, 0x93, 0xd9, 0xa8, 0x3b, 0x4a, 0xaf, 0xde, 0x4d, 0x3c, 0x76, 0x07, 0x94, 0xe5 }, + { 0x00, 0x43, 0x86, 0xc5, 0x11, 0x52, 0x97, 0xd4, 0x22, 0x61, 0xa4, 0xe7, 0x33, 0x70, 0xb5, 0xf6 }, + }, + { + { 0x00, 0xb7, 0x73, 0xc4, 0xe6, 0x51, 0x95, 0x22, 0xd1, 0x66, 0xa2, 0x15, 0x37, 0x80, 0x44, 0xf3 }, + { 0x00, 0xbf, 0x63, 0xdc, 0xc6, 0x79, 0xa5, 0x1a, 0x91, 0x2e, 0xf2, 0x4d, 0x57, 0xe8, 0x34, 0x8b }, + }, + { + { 0x00, 0x52, 0xa4, 0xf6, 0x55, 0x07, 0xf1, 0xa3, 0xaa, 0xf8, 0x0e, 0x5c, 0xff, 0xad, 0x5b, 0x09 }, + { 0x00, 0x49, 0x92, 0xdb, 0x39, 0x70, 0xab, 0xe2, 0x72, 0x3b, 0xe0, 0xa9, 0x4b, 0x02, 0xd9, 0x90 }, + }, + }, + { + { + { 0x00, 0x5e, 0xbc, 0xe2, 0x65, 0x3b, 0xd9, 0x87, 0xca, 0x94, 0x76, 0x28, 0xaf, 0xf1, 0x13, 0x4d }, + { 0x00, 0x89, 0x0f, 0x86, 0x1e, 0x97, 0x11, 0x98, 0x3c, 0xb5, 0x33, 0xba, 0x22, 0xab, 0x2d, 0xa4 }, + }, + { + { 0x00, 0x58, 0xb0, 0xe8, 0x7d, 0x25, 0xcd, 0x95, 0xfa, 0xa2, 0x4a, 0x12, 0x87, 0xdf, 0x37, 0x6f }, + { 0x00, 0xe9, 0xcf, 0x26, 0x83, 0x6a, 0x4c, 0xa5, 0x1b, 0xf2, 0xd4, 0x3d, 0x98, 0x71, 0x57, 0xbe }, + }, + { + { 0x00, 0x98, 0x2d, 0xb5, 0x5a, 0xc2, 0x77, 0xef, 0xb4, 0x2c, 0x99, 0x01, 0xee, 0x76, 0xc3, 0x5b }, + { 0x00, 0x75, 0xea, 0x9f, 0xc9, 0xbc, 0x23, 0x56, 0x8f, 0xfa, 0x65, 0x10, 0x46, 0x33, 0xac, 0xd9 }, + }, + { + { 0x00, 0xe3, 0xdb, 0x38, 0xab, 0x48, 0x70, 0x93, 0x4b, 0xa8, 0x90, 0x73, 0xe0, 0x03, 0x3b, 0xd8 }, + { 0x00, 0x96, 0x31, 0xa7, 0x62, 0xf4, 0x53, 0xc5, 0xc4, 0x52, 0xf5, 0x63, 0xa6, 0x30, 0x97, 0x01 }, + }, + }, + { + { + { 0x00, 0x9b, 0x2b, 0xb0, 0x56, 0xcd, 0x7d, 0xe6, 0xac, 0x37, 0x87, 0x1c, 0xfa, 0x61, 0xd1, 0x4a }, + { 0x00, 0x45, 0x8a, 0xcf, 0x09, 0x4c, 0x83, 0xc6, 0x12, 0x57, 0x98, 0xdd, 0x1b, 0x5e, 0x91, 0xd4 }, + }, + { + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b }, + }, + { + { 0x00, 0xc1, 0x9f, 0x5e, 0x23, 0xe2, 0xbc, 0x7d, 0x46, 0x87, 0xd9, 0x18, 0x65, 0xa4, 0xfa, 0x3b }, + { 0x00, 0x8c, 0x05, 0x89, 0x0a, 0x86, 0x0f, 0x83, 0x14, 0x98, 0x11, 0x9d, 0x1e, 0x92, 0x1b, 0x97 }, + }, + { + { 0x00, 0x95, 0x37, 0xa2, 0x6e, 0xfb, 0x59, 0xcc, 0xdc, 0x49, 0xeb, 0x7e, 0xb2, 0x27, 0x85, 0x10 }, + { 0x00, 0xa5, 0x57, 0xf2, 0xae, 0x0b, 0xf9, 0x5c, 0x41, 0xe4, 0x16, 0xb3, 0xef, 0x4a, 0xb8, 0x1d }, + }, + }, + { + { + { 0x00, 0x1e, 0x3c, 0x22, 0x78, 0x66, 0x44, 0x5a, 0xf0, 0xee, 0xcc, 0xd2, 0x88, 0x96, 0xb4, 0xaa }, + { 0x00, 0xfd, 0xe7, 0x1a, 0xd3, 0x2e, 0x34, 0xc9, 0xbb, 0x46, 0x5c, 0xa1, 0x68, 0x95, 0x8f, 0x72 }, + }, + { + { 0x00, 0x85, 0x17, 0x92, 0x2e, 0xab, 0x39, 0xbc, 0x5c, 0xd9, 0x4b, 0xce, 0x72, 0xf7, 0x65, 0xe0 }, + { 0x00, 0xb8, 0x6d, 0xd5, 0xda, 0x62, 0xb7, 0x0f, 0xa9, 0x11, 0xc4, 0x7c, 0x73, 0xcb, 0x1e, 0xa6 }, + }, + { + { 0x00, 0x28, 0x50, 0x78, 0xa0, 0x88, 0xf0, 0xd8, 0x5d, 0x75, 0x0d, 0x25, 0xfd, 0xd5, 0xad, 0x85 }, + { 0x00, 0xba, 0x69, 0xd3, 0xd2, 0x68, 0xbb, 0x01, 0xb9, 0x03, 0xd0, 0x6a, 0x6b, 0xd1, 0x02, 0xb8 }, + }, + { + { 0x00, 0xbd, 0x67, 0xda, 0xce, 0x73, 0xa9, 0x14, 0x81, 0x3c, 0xe6, 0x5b, 0x4f, 0xf2, 0x28, 0x95 }, + { 0x00, 0x1f, 0x3e, 0x21, 0x7c, 0x63, 0x42, 0x5d, 0xf8, 0xe7, 0xc6, 0xd9, 0x84, 0x9b, 0xba, 0xa5 }, + }, + }, + { + { + { 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b }, + { 0x00, 0xd0, 0xbd, 0x6d, 0x67, 0xb7, 0xda, 0x0a, 0xce, 0x1e, 0x73, 0xa3, 0xa9, 0x79, 0x14, 0xc4 }, + }, + { + { 0x00, 0x4f, 0x9e, 0xd1, 0x21, 0x6e, 0xbf, 0xf0, 0x42, 0x0d, 0xdc, 0x93, 0x63, 0x2c, 0xfd, 0xb2 }, + { 0x00, 0x84, 0x15, 0x91, 0x2a, 0xae, 0x3f, 0xbb, 0x54, 0xd0, 0x41, 0xc5, 0x7e, 0xfa, 0x6b, 0xef }, + }, + { + { 0x00, 0xf3, 0xfb, 0x08, 0xeb, 0x18, 0x10, 0xe3, 0xcb, 0x38, 0x30, 0xc3, 0x20, 0xd3, 0xdb, 0x28 }, + { 0x00, 0x8b, 0x0b, 0x80, 0x16, 0x9d, 0x1d, 0x96, 0x2c, 0xa7, 0x27, 0xac, 0x3a, 0xb1, 0x31, 0xba }, + }, + { + { 0x00, 0x31, 0x62, 0x53, 0xc4, 0xf5, 0xa6, 0x97, 0x95, 0xa4, 0xf7, 0xc6, 0x51, 0x60, 0x33, 0x02 }, + { 0x00, 0x37, 0x6e, 0x59, 0xdc, 0xeb, 0xb2, 0x85, 0xa5, 0x92, 0xcb, 0xfc, 0x79, 0x4e, 0x17, 0x20 }, + }, + }, + { + { + { 0x00, 0x81, 0x1f, 0x9e, 0x3e, 0xbf, 0x21, 0xa0, 0x7c, 0xfd, 0x63, 0xe2, 0x42, 0xc3, 0x5d, 0xdc }, + { 0x00, 0xf8, 0xed, 0x15, 0xc7, 0x3f, 0x2a, 0xd2, 0x93, 0x6b, 0x7e, 0x86, 0x54, 0xac, 0xb9, 0x41 }, + }, + { + { 0x00, 0x6f, 0xde, 0xb1, 0xa1, 0xce, 0x7f, 0x10, 0x5f, 0x30, 0x81, 0xee, 0xfe, 0x91, 0x20, 0x4f }, + { 0x00, 0xbe, 0x61, 0xdf, 0xc2, 0x7c, 0xa3, 0x1d, 0x99, 0x27, 0xf8, 0x46, 0x5b, 0xe5, 0x3a, 0x84 }, + }, + { + { 0x00, 0x05, 0x0a, 0x0f, 0x14, 0x11, 0x1e, 0x1b, 0x28, 0x2d, 0x22, 0x27, 0x3c, 0x39, 0x36, 0x33 }, + { 0x00, 0x50, 0xa0, 0xf0, 0x5d, 0x0d, 0xfd, 0xad, 0xba, 0xea, 0x1a, 0x4a, 0xe7, 0xb7, 0x47, 0x17 }, + }, + { + { 0x00, 0x5d, 0xba, 0xe7, 0x69, 0x34, 0xd3, 0x8e, 0xd2, 0x8f, 0x68, 0x35, 0xbb, 0xe6, 0x01, 0x5c }, + { 0x00, 0xb9, 0x6f, 0xd6, 0xde, 0x67, 0xb1, 0x08, 0xa1, 0x18, 0xce, 0x77, 0x7f, 0xc6, 0x10, 0xa9 }, + }, + }, + { + { + { 0x00, 0x4a, 0x94, 0xde, 0x35, 0x7f, 0xa1, 0xeb, 0x6a, 0x20, 0xfe, 0xb4, 0x5f, 0x15, 0xcb, 0x81 }, + { 0x00, 0xd4, 0xb5, 0x61, 0x77, 0xa3, 0xc2, 0x16, 0xee, 0x3a, 0x5b, 0x8f, 0x99, 0x4d, 0x2c, 0xf8 }, + }, + { + { 0x00, 0x6d, 0xda, 0xb7, 0xa9, 0xc4, 0x73, 0x1e, 0x4f, 0x22, 0x95, 0xf8, 0xe6, 0x8b, 0x3c, 0x51 }, + { 0x00, 0x9e, 0x21, 0xbf, 0x42, 0xdc, 0x63, 0xfd, 0x84, 0x1a, 0xa5, 0x3b, 0xc6, 0x58, 0xe7, 0x79 }, + }, + { + { 0x00, 0x96, 0x31, 0xa7, 0x62, 0xf4, 0x53, 0xc5, 0xc4, 0x52, 0xf5, 0x63, 0xa6, 0x30, 0x97, 0x01 }, + { 0x00, 0x95, 0x37, 0xa2, 0x6e, 0xfb, 0x59, 0xcc, 0xdc, 0x49, 0xeb, 0x7e, 0xb2, 0x27, 0x85, 0x10 }, + }, + { + { 0x00, 0x35, 0x6a, 0x5f, 0xd4, 0xe1, 0xbe, 0x8b, 0xb5, 0x80, 0xdf, 0xea, 0x61, 0x54, 0x0b, 0x3e }, + { 0x00, 0x77, 0xee, 0x99, 0xc1, 0xb6, 0x2f, 0x58, 0x9f, 0xe8, 0x71, 0x06, 0x5e, 0x29, 0xb0, 0xc7 }, + }, + }, + { + { + { 0x00, 0xbd, 0x67, 0xda, 0xce, 0x73, 0xa9, 0x14, 0x81, 0x3c, 0xe6, 0x5b, 0x4f, 0xf2, 0x28, 0x95 }, + { 0x00, 0x1f, 0x3e, 0x21, 0x7c, 0x63, 0x42, 0x5d, 0xf8, 0xe7, 0xc6, 0xd9, 0x84, 0x9b, 0xba, 0xa5 }, + }, + { + { 0x00, 0x1d, 0x3a, 0x27, 0x74, 0x69, 0x4e, 0x53, 0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb }, + { 0x00, 0xcd, 0x87, 0x4a, 0x13, 0xde, 0x94, 0x59, 0x26, 0xeb, 0xa1, 0x6c, 0x35, 0xf8, 0xb2, 0x7f }, + }, + { + { 0x00, 0x63, 0xc6, 0xa5, 0x91, 0xf2, 0x57, 0x34, 0x3f, 0x5c, 0xf9, 0x9a, 0xae, 0xcd, 0x68, 0x0b }, + { 0x00, 0x7e, 0xfc, 0x82, 0xe5, 0x9b, 0x19, 0x67, 0xd7, 0xa9, 0x2b, 0x55, 0x32, 0x4c, 0xce, 0xb0 }, + }, + { + { 0x00, 0x4a, 0x94, 0xde, 0x35, 0x7f, 0xa1, 0xeb, 0x6a, 0x20, 0xfe, 0xb4, 0x5f, 0x15, 0xcb, 0x81 }, + { 0x00, 0xd4, 0xb5, 0x61, 0x77, 0xa3, 0xc2, 0x16, 0xee, 0x3a, 0x5b, 0x8f, 0x99, 0x4d, 0x2c, 0xf8 }, + }, + }, + { + { + { 0x00, 0x16, 0x2c, 0x3a, 0x58, 0x4e, 0x74, 0x62, 0xb0, 0xa6, 0x9c, 0x8a, 0xe8, 0xfe, 0xc4, 0xd2 }, + { 0x00, 0x7d, 0xfa, 0x87, 0xe9, 0x94, 0x13, 0x6e, 0xcf, 0xb2, 0x35, 0x48, 0x26, 0x5b, 0xdc, 0xa1 }, + }, + { + { 0x00, 0xcf, 0x83, 0x4c, 0x1b, 0xd4, 0x98, 0x57, 0x36, 0xf9, 0xb5, 0x7a, 0x2d, 0xe2, 0xae, 0x61 }, + { 0x00, 0x6c, 0xd8, 0xb4, 0xad, 0xc1, 0x75, 0x19, 0x47, 0x2b, 0x9f, 0xf3, 0xea, 0x86, 0x32, 0x5e }, + }, + { + { 0x00, 0xd1, 0xbf, 0x6e, 0x63, 0xb2, 0xdc, 0x0d, 0xc6, 0x17, 0x79, 0xa8, 0xa5, 0x74, 0x1a, 0xcb }, + { 0x00, 0x91, 0x3f, 0xae, 0x7e, 0xef, 0x41, 0xd0, 0xfc, 0x6d, 0xc3, 0x52, 0x82, 0x13, 0xbd, 0x2c }, + }, + { + { 0x00, 0x41, 0x82, 0xc3, 0x19, 0x58, 0x9b, 0xda, 0x32, 0x73, 0xb0, 0xf1, 0x2b, 0x6a, 0xa9, 0xe8 }, + { 0x00, 0x64, 0xc8, 0xac, 0x8d, 0xe9, 0x45, 0x21, 0x07, 0x63, 0xcf, 0xab, 0x8a, 0xee, 0x42, 0x26 }, + }, + }, + { + { + { 0x00, 0x8a, 0x09, 0x83, 0x12, 0x98, 0x1b, 0x91, 0x24, 0xae, 0x2d, 0xa7, 0x36, 0xbc, 0x3f, 0xb5 }, + { 0x00, 0x48, 0x90, 0xd8, 0x3d, 0x75, 0xad, 0xe5, 0x7a, 0x32, 0xea, 0xa2, 0x47, 0x0f, 0xd7, 0x9f }, + }, + { + { 0x00, 0xfa, 0xe9, 0x13, 0xcf, 0x35, 0x26, 0xdc, 0x83, 0x79, 0x6a, 0x90, 0x4c, 0xb6, 0xa5, 0x5f }, + { 0x00, 0x1b, 0x36, 0x2d, 0x6c, 0x77, 0x5a, 0x41, 0xd8, 0xc3, 0xee, 0xf5, 0xb4, 0xaf, 0x82, 0x99 }, + }, + { + { 0x00, 0xb9, 0x6f, 0xd6, 0xde, 0x67, 0xb1, 0x08, 0xa1, 0x18, 0xce, 0x77, 0x7f, 0xc6, 0x10, 0xa9 }, + { 0x00, 0x5f, 0xbe, 0xe1, 0x61, 0x3e, 0xdf, 0x80, 0xc2, 0x9d, 0x7c, 0x23, 0xa3, 0xfc, 0x1d, 0x42 }, + }, + { + { 0x00, 0xc4, 0x95, 0x51, 0x37, 0xf3, 0xa2, 0x66, 0x6e, 0xaa, 0xfb, 0x3f, 0x59, 0x9d, 0xcc, 0x08 }, + { 0x00, 0xdc, 0xa5, 0x79, 0x57, 0x8b, 0xf2, 0x2e, 0xae, 0x72, 0x0b, 0xd7, 0xf9, 0x25, 0x5c, 0x80 }, + }, + }, + { + { + { 0x00, 0xac, 0x45, 0xe9, 0x8a, 0x26, 0xcf, 0x63, 0x09, 0xa5, 0x4c, 0xe0, 0x83, 0x2f, 0xc6, 0x6a }, + { 0x00, 0x12, 0x24, 0x36, 0x48, 0x5a, 0x6c, 0x7e, 0x90, 0x82, 0xb4, 0xa6, 0xd8, 0xca, 0xfc, 0xee }, + }, + { + { 0x00, 0x54, 0xa8, 0xfc, 0x4d, 0x19, 0xe5, 0xb1, 0x9a, 0xce, 0x32, 0x66, 0xd7, 0x83, 0x7f, 0x2b }, + { 0x00, 0x29, 0x52, 0x7b, 0xa4, 0x8d, 0xf6, 0xdf, 0x55, 0x7c, 0x07, 0x2e, 0xf1, 0xd8, 0xa3, 0x8a }, + }, + { + { 0x00, 0x14, 0x28, 0x3c, 0x50, 0x44, 0x78, 0x6c, 0xa0, 0xb4, 0x88, 0x9c, 0xf0, 0xe4, 0xd8, 0xcc }, + { 0x00, 0x5d, 0xba, 0xe7, 0x69, 0x34, 0xd3, 0x8e, 0xd2, 0x8f, 0x68, 0x35, 0xbb, 0xe6, 0x01, 0x5c }, + }, + { + { 0x00, 0xdb, 0xab, 0x70, 0x4b, 0x90, 0xe0, 0x3b, 0x96, 0x4d, 0x3d, 0xe6, 0xdd, 0x06, 0x76, 0xad }, + { 0x00, 0x31, 0x62, 0x53, 0xc4, 0xf5, 0xa6, 0x97, 0x95, 0xa4, 0xf7, 0xc6, 0x51, 0x60, 0x33, 0x02 }, + }, + }, + { + { + { 0x00, 0x93, 0x3b, 0xa8, 0x76, 0xe5, 0x4d, 0xde, 0xec, 0x7f, 0xd7, 0x44, 0x9a, 0x09, 0xa1, 0x32 }, + { 0x00, 0xc5, 0x97, 0x52, 0x33, 0xf6, 0xa4, 0x61, 0x66, 0xa3, 0xf1, 0x34, 0x55, 0x90, 0xc2, 0x07 }, + }, + { + { 0x00, 0xa9, 0x4f, 0xe6, 0x9e, 0x37, 0xd1, 0x78, 0x21, 0x88, 0x6e, 0xc7, 0xbf, 0x16, 0xf0, 0x59 }, + { 0x00, 0x42, 0x84, 0xc6, 0x15, 0x57, 0x91, 0xd3, 0x2a, 0x68, 0xae, 0xec, 0x3f, 0x7d, 0xbb, 0xf9 }, + }, + { + { 0x00, 0x9f, 0x23, 0xbc, 0x46, 0xd9, 0x65, 0xfa, 0x8c, 0x13, 0xaf, 0x30, 0xca, 0x55, 0xe9, 0x76 }, + { 0x00, 0x05, 0x0a, 0x0f, 0x14, 0x11, 0x1e, 0x1b, 0x28, 0x2d, 0x22, 0x27, 0x3c, 0x39, 0x36, 0x33 }, + }, + { + { 0x00, 0x42, 0x84, 0xc6, 0x15, 0x57, 0x91, 0xd3, 0x2a, 0x68, 0xae, 0xec, 0x3f, 0x7d, 0xbb, 0xf9 }, + { 0x00, 0x54, 0xa8, 0xfc, 0x4d, 0x19, 0xe5, 0xb1, 0x9a, 0xce, 0x32, 0x66, 0xd7, 0x83, 0x7f, 0x2b }, + }, + }, + { + { + { 0x00, 0xce, 0x81, 0x4f, 0x1f, 0xd1, 0x9e, 0x50, 0x3e, 0xf0, 0xbf, 0x71, 0x21, 0xef, 0xa0, 0x6e }, + { 0x00, 0x7c, 0xf8, 0x84, 0xed, 0x91, 0x15, 0x69, 0xc7, 0xbb, 0x3f, 0x43, 0x2a, 0x56, 0xd2, 0xae }, + }, + { + { 0x00, 0x17, 0x2e, 0x39, 0x5c, 0x4b, 0x72, 0x65, 0xb8, 0xaf, 0x96, 0x81, 0xe4, 0xf3, 0xca, 0xdd }, + { 0x00, 0x6d, 0xda, 0xb7, 0xa9, 0xc4, 0x73, 0x1e, 0x4f, 0x22, 0x95, 0xf8, 0xe6, 0x8b, 0x3c, 0x51 }, + }, + { + { 0x00, 0x1d, 0x3a, 0x27, 0x74, 0x69, 0x4e, 0x53, 0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb }, + { 0x00, 0xcd, 0x87, 0x4a, 0x13, 0xde, 0x94, 0x59, 0x26, 0xeb, 0xa1, 0x6c, 0x35, 0xf8, 0xb2, 0x7f }, + }, + { + { 0x00, 0xc5, 0x97, 0x52, 0x33, 0xf6, 0xa4, 0x61, 0x66, 0xa3, 0xf1, 0x34, 0x55, 0x90, 0xc2, 0x07 }, + { 0x00, 0xcc, 0x85, 0x49, 0x17, 0xdb, 0x92, 0x5e, 0x2e, 0xe2, 0xab, 0x67, 0x39, 0xf5, 0xbc, 0x70 }, + }, + }, + { + { + { 0x00, 0x1a, 0x34, 0x2e, 0x68, 0x72, 0x5c, 0x46, 0xd0, 0xca, 0xe4, 0xfe, 0xb8, 0xa2, 0x8c, 0x96 }, + { 0x00, 0xbd, 0x67, 0xda, 0xce, 0x73, 0xa9, 0x14, 0x81, 0x3c, 0xe6, 0x5b, 0x4f, 0xf2, 0x28, 0x95 }, + }, + { + { 0x00, 0xa3, 0x5b, 0xf8, 0xb6, 0x15, 0xed, 0x4e, 0x71, 0xd2, 0x2a, 0x89, 0xc7, 0x64, 0x9c, 0x3f }, + { 0x00, 0xe2, 0xd9, 0x3b, 0xaf, 0x4d, 0x76, 0x94, 0x43, 0xa1, 0x9a, 0x78, 0xec, 0x0e, 0x35, 0xd7 }, + }, + { + { 0x00, 0x83, 0x1b, 0x98, 0x36, 0xb5, 0x2d, 0xae, 0x6c, 0xef, 0x77, 0xf4, 0x5a, 0xd9, 0x41, 0xc2 }, + { 0x00, 0xd8, 0xad, 0x75, 0x47, 0x9f, 0xea, 0x32, 0x8e, 0x56, 0x23, 0xfb, 0xc9, 0x11, 0x64, 0xbc }, + }, + { + { 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69 }, + { 0x00, 0xb0, 0x7d, 0xcd, 0xfa, 0x4a, 0x87, 0x37, 0xe9, 0x59, 0x94, 0x24, 0x13, 0xa3, 0x6e, 0xde }, + }, + }, + { + { + { 0x00, 0xc2, 0x99, 0x5b, 0x2f, 0xed, 0xb6, 0x74, 0x5e, 0x9c, 0xc7, 0x05, 0x71, 0xb3, 0xe8, 0x2a }, + { 0x00, 0xbc, 0x65, 0xd9, 0xca, 0x76, 0xaf, 0x13, 0x89, 0x35, 0xec, 0x50, 0x43, 0xff, 0x26, 0x9a }, + }, + { + { 0x00, 0x0f, 0x1e, 0x11, 0x3c, 0x33, 0x22, 0x2d, 0x78, 0x77, 0x66, 0x69, 0x44, 0x4b, 0x5a, 0x55 }, + { 0x00, 0xf0, 0xfd, 0x0d, 0xe7, 0x17, 0x1a, 0xea, 0xd3, 0x23, 0x2e, 0xde, 0x34, 0xc4, 0xc9, 0x39 }, + }, + { + { 0x00, 0x68, 0xd0, 0xb8, 0xbd, 0xd5, 0x6d, 0x05, 0x67, 0x0f, 0xb7, 0xdf, 0xda, 0xb2, 0x0a, 0x62 }, + { 0x00, 0xce, 0x81, 0x4f, 0x1f, 0xd1, 0x9e, 0x50, 0x3e, 0xf0, 0xbf, 0x71, 0x21, 0xef, 0xa0, 0x6e }, + }, + { + { 0x00, 0x49, 0x92, 0xdb, 0x39, 0x70, 0xab, 0xe2, 0x72, 0x3b, 0xe0, 0xa9, 0x4b, 0x02, 0xd9, 0x90 }, + { 0x00, 0xe4, 0xd5, 0x31, 0xb7, 0x53, 0x62, 0x86, 0x73, 0x97, 0xa6, 0x42, 0xc4, 0x20, 0x11, 0xf5 }, + }, + }, + { + { + { 0x00, 0x0a, 0x14, 0x1e, 0x28, 0x22, 0x3c, 0x36, 0x50, 0x5a, 0x44, 0x4e, 0x78, 0x72, 0x6c, 0x66 }, + { 0x00, 0xa0, 0x5d, 0xfd, 0xba, 0x1a, 0xe7, 0x47, 0x69, 0xc9, 0x34, 0x94, 0xd3, 0x73, 0x8e, 0x2e }, + }, + { + { 0x00, 0xae, 0x41, 0xef, 0x82, 0x2c, 0xc3, 0x6d, 0x19, 0xb7, 0x58, 0xf6, 0x9b, 0x35, 0xda, 0x74 }, + { 0x00, 0x32, 0x64, 0x56, 0xc8, 0xfa, 0xac, 0x9e, 0x8d, 0xbf, 0xe9, 0xdb, 0x45, 0x77, 0x21, 0x13 }, + }, + { + { 0x00, 0x75, 0xea, 0x9f, 0xc9, 0xbc, 0x23, 0x56, 0x8f, 0xfa, 0x65, 0x10, 0x46, 0x33, 0xac, 0xd9 }, + { 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11 }, + }, + { + { 0x00, 0x1b, 0x36, 0x2d, 0x6c, 0x77, 0x5a, 0x41, 0xd8, 0xc3, 0xee, 0xf5, 0xb4, 0xaf, 0x82, 0x99 }, + { 0x00, 0xad, 0x47, 0xea, 0x8e, 0x23, 0xc9, 0x64, 0x01, 0xac, 0x46, 0xeb, 0x8f, 0x22, 0xc8, 0x65 }, + }, + }, + { + { + { 0x00, 0x3f, 0x7e, 0x41, 0xfc, 0xc3, 0x82, 0xbd, 0xe5, 0xda, 0x9b, 0xa4, 0x19, 0x26, 0x67, 0x58 }, + { 0x00, 0xd7, 0xb3, 0x64, 0x7b, 0xac, 0xc8, 0x1f, 0xf6, 0x21, 0x45, 0x92, 0x8d, 0x5a, 0x3e, 0xe9 }, + }, + { + { 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b }, + { 0x00, 0xd0, 0xbd, 0x6d, 0x67, 0xb7, 0xda, 0x0a, 0xce, 0x1e, 0x73, 0xa3, 0xa9, 0x79, 0x14, 0xc4 }, + }, + { + { 0x00, 0xed, 0xc7, 0x2a, 0x93, 0x7e, 0x54, 0xb9, 0x3b, 0xd6, 0xfc, 0x11, 0xa8, 0x45, 0x6f, 0x82 }, + { 0x00, 0x76, 0xec, 0x9a, 0xc5, 0xb3, 0x29, 0x5f, 0x97, 0xe1, 0x7b, 0x0d, 0x52, 0x24, 0xbe, 0xc8 }, + }, + { + { 0x00, 0x7c, 0xf8, 0x84, 0xed, 0x91, 0x15, 0x69, 0xc7, 0xbb, 0x3f, 0x43, 0x2a, 0x56, 0xd2, 0xae }, + { 0x00, 0x93, 0x3b, 0xa8, 0x76, 0xe5, 0x4d, 0xde, 0xec, 0x7f, 0xd7, 0x44, 0x9a, 0x09, 0xa1, 0x32 }, + }, + }, + { + { + { 0x00, 0xfd, 0xe7, 0x1a, 0xd3, 0x2e, 0x34, 0xc9, 0xbb, 0x46, 0x5c, 0xa1, 0x68, 0x95, 0x8f, 0x72 }, + { 0x00, 0x6b, 0xd6, 0xbd, 0xb1, 0xda, 0x67, 0x0c, 0x7f, 0x14, 0xa9, 0xc2, 0xce, 0xa5, 0x18, 0x73 }, + }, + { + { 0x00, 0x1c, 0x38, 0x24, 0x70, 0x6c, 0x48, 0x54, 0xe0, 0xfc, 0xd8, 0xc4, 0x90, 0x8c, 0xa8, 0xb4 }, + { 0x00, 0xdd, 0xa7, 0x7a, 0x53, 0x8e, 0xf4, 0x29, 0xa6, 0x7b, 0x01, 0xdc, 0xf5, 0x28, 0x52, 0x8f }, + }, + { + { 0x00, 0x16, 0x2c, 0x3a, 0x58, 0x4e, 0x74, 0x62, 0xb0, 0xa6, 0x9c, 0x8a, 0xe8, 0xfe, 0xc4, 0xd2 }, + { 0x00, 0x7d, 0xfa, 0x87, 0xe9, 0x94, 0x13, 0x6e, 0xcf, 0xb2, 0x35, 0x48, 0x26, 0x5b, 0xdc, 0xa1 }, + }, + { + { 0x00, 0xe4, 0xd5, 0x31, 0xb7, 0x53, 0x62, 0x86, 0x73, 0x97, 0xa6, 0x42, 0xc4, 0x20, 0x11, 0xf5 }, + { 0x00, 0xe6, 0xd1, 0x37, 0xbf, 0x59, 0x6e, 0x88, 0x63, 0x85, 0xb2, 0x54, 0xdc, 0x3a, 0x0d, 0xeb }, + }, + }, + { + { + { 0x00, 0xe3, 0xdb, 0x38, 0xab, 0x48, 0x70, 0x93, 0x4b, 0xa8, 0x90, 0x73, 0xe0, 0x03, 0x3b, 0xd8 }, + { 0x00, 0x96, 0x31, 0xa7, 0x62, 0xf4, 0x53, 0xc5, 0xc4, 0x52, 0xf5, 0x63, 0xa6, 0x30, 0x97, 0x01 }, + }, + { + { 0x00, 0xc2, 0x99, 0x5b, 0x2f, 0xed, 0xb6, 0x74, 0x5e, 0x9c, 0xc7, 0x05, 0x71, 0xb3, 0xe8, 0x2a }, + { 0x00, 0xbc, 0x65, 0xd9, 0xca, 0x76, 0xaf, 0x13, 0x89, 0x35, 0xec, 0x50, 0x43, 0xff, 0x26, 0x9a }, + }, + { + { 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11 }, + { 0x00, 0x30, 0x60, 0x50, 0xc0, 0xf0, 0xa0, 0x90, 0x9d, 0xad, 0xfd, 0xcd, 0x5d, 0x6d, 0x3d, 0x0d }, + }, + { + { 0x00, 0xb0, 0x7d, 0xcd, 0xfa, 0x4a, 0x87, 0x37, 0xe9, 0x59, 0x94, 0x24, 0x13, 0xa3, 0x6e, 0xde }, + { 0x00, 0xcf, 0x83, 0x4c, 0x1b, 0xd4, 0x98, 0x57, 0x36, 0xf9, 0xb5, 0x7a, 0x2d, 0xe2, 0xae, 0x61 }, + }, + }, + { + { + { 0x00, 0x77, 0xee, 0x99, 0xc1, 0xb6, 0x2f, 0x58, 0x9f, 0xe8, 0x71, 0x06, 0x5e, 0x29, 0xb0, 0xc7 }, + { 0x00, 0x23, 0x46, 0x65, 0x8c, 0xaf, 0xca, 0xe9, 0x05, 0x26, 0x43, 0x60, 0x89, 0xaa, 0xcf, 0xec }, + }, + { + { 0x00, 0xd0, 0xbd, 0x6d, 0x67, 0xb7, 0xda, 0x0a, 0xce, 0x1e, 0x73, 0xa3, 0xa9, 0x79, 0x14, 0xc4 }, + { 0x00, 0x81, 0x1f, 0x9e, 0x3e, 0xbf, 0x21, 0xa0, 0x7c, 0xfd, 0x63, 0xe2, 0x42, 0xc3, 0x5d, 0xdc }, + }, + { + { 0x00, 0xce, 0x81, 0x4f, 0x1f, 0xd1, 0x9e, 0x50, 0x3e, 0xf0, 0xbf, 0x71, 0x21, 0xef, 0xa0, 0x6e }, + { 0x00, 0x7c, 0xf8, 0x84, 0xed, 0x91, 0x15, 0x69, 0xc7, 0xbb, 0x3f, 0x43, 0x2a, 0x56, 0xd2, 0xae }, + }, + { + { 0x00, 0x9d, 0x27, 0xba, 0x4e, 0xd3, 0x69, 0xf4, 0x9c, 0x01, 0xbb, 0x26, 0xd2, 0x4f, 0xf5, 0x68 }, + { 0x00, 0x25, 0x4a, 0x6f, 0x94, 0xb1, 0xde, 0xfb, 0x35, 0x10, 0x7f, 0x5a, 0xa1, 0x84, 0xeb, 0xce }, + }, + }, + { + { + { 0x00, 0x6b, 0xd6, 0xbd, 0xb1, 0xda, 0x67, 0x0c, 0x7f, 0x14, 0xa9, 0xc2, 0xce, 0xa5, 0x18, 0x73 }, + { 0x00, 0xfe, 0xe1, 0x1f, 0xdf, 0x21, 0x3e, 0xc0, 0xa3, 0x5d, 0x42, 0xbc, 0x7c, 0x82, 0x9d, 0x63 }, + }, + { + { 0x00, 0x32, 0x64, 0x56, 0xc8, 0xfa, 0xac, 0x9e, 0x8d, 0xbf, 0xe9, 0xdb, 0x45, 0x77, 0x21, 0x13 }, + { 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d }, + }, + { + { 0x00, 0xe4, 0xd5, 0x31, 0xb7, 0x53, 0x62, 0x86, 0x73, 0x97, 0xa6, 0x42, 0xc4, 0x20, 0x11, 0xf5 }, + { 0x00, 0xe6, 0xd1, 0x37, 0xbf, 0x59, 0x6e, 0x88, 0x63, 0x85, 0xb2, 0x54, 0xdc, 0x3a, 0x0d, 0xeb }, + }, + { + { 0x00, 0x45, 0x8a, 0xcf, 0x09, 0x4c, 0x83, 0xc6, 0x12, 0x57, 0x98, 0xdd, 0x1b, 0x5e, 0x91, 0xd4 }, + { 0x00, 0x24, 0x48, 0x6c, 0x90, 0xb4, 0xd8, 0xfc, 0x3d, 0x19, 0x75, 0x51, 0xad, 0x89, 0xe5, 0xc1 }, + }, + }, + { + { + { 0x00, 0xd7, 0xb3, 0x64, 0x7b, 0xac, 0xc8, 0x1f, 0xf6, 0x21, 0x45, 0x92, 0x8d, 0x5a, 0x3e, 0xe9 }, + { 0x00, 0xf1, 0xff, 0x0e, 0xe3, 0x12, 0x1c, 0xed, 0xdb, 0x2a, 0x24, 0xd5, 0x38, 0xc9, 0xc7, 0x36 }, + }, + { + { 0x00, 0x16, 0x2c, 0x3a, 0x58, 0x4e, 0x74, 0x62, 0xb0, 0xa6, 0x9c, 0x8a, 0xe8, 0xfe, 0xc4, 0xd2 }, + { 0x00, 0x7d, 0xfa, 0x87, 0xe9, 0x94, 0x13, 0x6e, 0xcf, 0xb2, 0x35, 0x48, 0x26, 0x5b, 0xdc, 0xa1 }, + }, + { + { 0x00, 0xdf, 0xa3, 0x7c, 0x5b, 0x84, 0xf8, 0x27, 0xb6, 0x69, 0x15, 0xca, 0xed, 0x32, 0x4e, 0x91 }, + { 0x00, 0x71, 0xe2, 0x93, 0xd9, 0xa8, 0x3b, 0x4a, 0xaf, 0xde, 0x4d, 0x3c, 0x76, 0x07, 0x94, 0xe5 }, + }, + { + { 0x00, 0xf0, 0xfd, 0x0d, 0xe7, 0x17, 0x1a, 0xea, 0xd3, 0x23, 0x2e, 0xde, 0x34, 0xc4, 0xc9, 0x39 }, + { 0x00, 0xbb, 0x6b, 0xd0, 0xd6, 0x6d, 0xbd, 0x06, 0xb1, 0x0a, 0xda, 0x61, 0x67, 0xdc, 0x0c, 0xb7 }, + }, + }, + { + { + { 0x00, 0xef, 0xc3, 0x2c, 0x9b, 0x74, 0x58, 0xb7, 0x2b, 0xc4, 0xe8, 0x07, 0xb0, 0x5f, 0x73, 0x9c }, + { 0x00, 0x56, 0xac, 0xfa, 0x45, 0x13, 0xe9, 0xbf, 0x8a, 0xdc, 0x26, 0x70, 0xcf, 0x99, 0x63, 0x35 }, + }, + { + { 0x00, 0xf6, 0xf1, 0x07, 0xff, 0x09, 0x0e, 0xf8, 0xe3, 0x15, 0x12, 0xe4, 0x1c, 0xea, 0xed, 0x1b }, + { 0x00, 0xdb, 0xab, 0x70, 0x4b, 0x90, 0xe0, 0x3b, 0x96, 0x4d, 0x3d, 0xe6, 0xdd, 0x06, 0x76, 0xad }, + }, + { + { 0x00, 0xe0, 0xdd, 0x3d, 0xa7, 0x47, 0x7a, 0x9a, 0x53, 0xb3, 0x8e, 0x6e, 0xf4, 0x14, 0x29, 0xc9 }, + { 0x00, 0xa6, 0x51, 0xf7, 0xa2, 0x04, 0xf3, 0x55, 0x59, 0xff, 0x08, 0xae, 0xfb, 0x5d, 0xaa, 0x0c }, + }, + { + { 0x00, 0xa9, 0x4f, 0xe6, 0x9e, 0x37, 0xd1, 0x78, 0x21, 0x88, 0x6e, 0xc7, 0xbf, 0x16, 0xf0, 0x59 }, + { 0x00, 0x42, 0x84, 0xc6, 0x15, 0x57, 0x91, 0xd3, 0x2a, 0x68, 0xae, 0xec, 0x3f, 0x7d, 0xbb, 0xf9 }, + }, + }, + { + { + { 0x00, 0xa4, 0x55, 0xf1, 0xaa, 0x0e, 0xff, 0x5b, 0x49, 0xed, 0x1c, 0xb8, 0xe3, 0x47, 0xb6, 0x12 }, + { 0x00, 0x92, 0x39, 0xab, 0x72, 0xe0, 0x4b, 0xd9, 0xe4, 0x76, 0xdd, 0x4f, 0x96, 0x04, 0xaf, 0x3d }, + }, + { + { 0x00, 0xc0, 0x9d, 0x5d, 0x27, 0xe7, 0xba, 0x7a, 0x4e, 0x8e, 0xd3, 0x13, 0x69, 0xa9, 0xf4, 0x34 }, + { 0x00, 0x9c, 0x25, 0xb9, 0x4a, 0xd6, 0x6f, 0xf3, 0x94, 0x08, 0xb1, 0x2d, 0xde, 0x42, 0xfb, 0x67 }, + }, + { + { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0 }, + { 0x00, 0x1d, 0x3a, 0x27, 0x74, 0x69, 0x4e, 0x53, 0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb }, + }, + { + { 0x00, 0x61, 0xc2, 0xa3, 0x99, 0xf8, 0x5b, 0x3a, 0x2f, 0x4e, 0xed, 0x8c, 0xb6, 0xd7, 0x74, 0x15 }, + { 0x00, 0x5e, 0xbc, 0xe2, 0x65, 0x3b, 0xd9, 0x87, 0xca, 0x94, 0x76, 0x28, 0xaf, 0xf1, 0x13, 0x4d }, + }, + }, + { + { + { 0x00, 0x80, 0x1d, 0x9d, 0x3a, 0xba, 0x27, 0xa7, 0x74, 0xf4, 0x69, 0xe9, 0x4e, 0xce, 0x53, 0xd3 }, + { 0x00, 0xe8, 0xcd, 0x25, 0x87, 0x6f, 0x4a, 0xa2, 0x13, 0xfb, 0xde, 0x36, 0x94, 0x7c, 0x59, 0xb1 }, + }, + { + { 0x00, 0x7f, 0xfe, 0x81, 0xe1, 0x9e, 0x1f, 0x60, 0xdf, 0xa0, 0x21, 0x5e, 0x3e, 0x41, 0xc0, 0xbf }, + { 0x00, 0xa3, 0x5b, 0xf8, 0xb6, 0x15, 0xed, 0x4e, 0x71, 0xd2, 0x2a, 0x89, 0xc7, 0x64, 0x9c, 0x3f }, + }, + { + { 0x00, 0xae, 0x41, 0xef, 0x82, 0x2c, 0xc3, 0x6d, 0x19, 0xb7, 0x58, 0xf6, 0x9b, 0x35, 0xda, 0x74 }, + { 0x00, 0x32, 0x64, 0x56, 0xc8, 0xfa, 0xac, 0x9e, 0x8d, 0xbf, 0xe9, 0xdb, 0x45, 0x77, 0x21, 0x13 }, + }, + { + { 0x00, 0x57, 0xae, 0xf9, 0x41, 0x16, 0xef, 0xb8, 0x82, 0xd5, 0x2c, 0x7b, 0xc3, 0x94, 0x6d, 0x3a }, + { 0x00, 0x19, 0x32, 0x2b, 0x64, 0x7d, 0x56, 0x4f, 0xc8, 0xd1, 0xfa, 0xe3, 0xac, 0xb5, 0x9e, 0x87 }, + }, + }, + { + { + { 0x00, 0xa1, 0x5f, 0xfe, 0xbe, 0x1f, 0xe1, 0x40, 0x61, 0xc0, 0x3e, 0x9f, 0xdf, 0x7e, 0x80, 0x21 }, + { 0x00, 0xc2, 0x99, 0x5b, 0x2f, 0xed, 0xb6, 0x74, 0x5e, 0x9c, 0xc7, 0x05, 0x71, 0xb3, 0xe8, 0x2a }, + }, + { + { 0x00, 0x2d, 0x5a, 0x77, 0xb4, 0x99, 0xee, 0xc3, 0x75, 0x58, 0x2f, 0x02, 0xc1, 0xec, 0x9b, 0xb6 }, + { 0x00, 0xea, 0xc9, 0x23, 0x8f, 0x65, 0x46, 0xac, 0x03, 0xe9, 0xca, 0x20, 0x8c, 0x66, 0x45, 0xaf }, + }, + { + { 0x00, 0x69, 0xd2, 0xbb, 0xb9, 0xd0, 0x6b, 0x02, 0x6f, 0x06, 0xbd, 0xd4, 0xd6, 0xbf, 0x04, 0x6d }, + { 0x00, 0xde, 0xa1, 0x7f, 0x5f, 0x81, 0xfe, 0x20, 0xbe, 0x60, 0x1f, 0xc1, 0xe1, 0x3f, 0x40, 0x9e }, + }, + { + { 0x00, 0x06, 0x0c, 0x0a, 0x18, 0x1e, 0x14, 0x12, 0x30, 0x36, 0x3c, 0x3a, 0x28, 0x2e, 0x24, 0x22 }, + { 0x00, 0x60, 0xc0, 0xa0, 0x9d, 0xfd, 0x5d, 0x3d, 0x27, 0x47, 0xe7, 0x87, 0xba, 0xda, 0x7a, 0x1a }, + }, + }, + { + { + { 0x00, 0x36, 0x6c, 0x5a, 0xd8, 0xee, 0xb4, 0x82, 0xad, 0x9b, 0xc1, 0xf7, 0x75, 0x43, 0x19, 0x2f }, + { 0x00, 0x47, 0x8e, 0xc9, 0x01, 0x46, 0x8f, 0xc8, 0x02, 0x45, 0x8c, 0xcb, 0x03, 0x44, 0x8d, 0xca }, + }, + { + { 0x00, 0x15, 0x2a, 0x3f, 0x54, 0x41, 0x7e, 0x6b, 0xa8, 0xbd, 0x82, 0x97, 0xfc, 0xe9, 0xd6, 0xc3 }, + { 0x00, 0x4d, 0x9a, 0xd7, 0x29, 0x64, 0xb3, 0xfe, 0x52, 0x1f, 0xc8, 0x85, 0x7b, 0x36, 0xe1, 0xac }, + }, + { + { 0x00, 0x55, 0xaa, 0xff, 0x49, 0x1c, 0xe3, 0xb6, 0x92, 0xc7, 0x38, 0x6d, 0xdb, 0x8e, 0x71, 0x24 }, + { 0x00, 0x39, 0x72, 0x4b, 0xe4, 0xdd, 0x96, 0xaf, 0xd5, 0xec, 0xa7, 0x9e, 0x31, 0x08, 0x43, 0x7a }, + }, + { + { 0x00, 0xd4, 0xb5, 0x61, 0x77, 0xa3, 0xc2, 0x16, 0xee, 0x3a, 0x5b, 0x8f, 0x99, 0x4d, 0x2c, 0xf8 }, + { 0x00, 0xc1, 0x9f, 0x5e, 0x23, 0xe2, 0xbc, 0x7d, 0x46, 0x87, 0xd9, 0x18, 0x65, 0xa4, 0xfa, 0x3b }, + }, + }, + { + { + { 0x00, 0xed, 0xc7, 0x2a, 0x93, 0x7e, 0x54, 0xb9, 0x3b, 0xd6, 0xfc, 0x11, 0xa8, 0x45, 0x6f, 0x82 }, + { 0x00, 0x76, 0xec, 0x9a, 0xc5, 0xb3, 0x29, 0x5f, 0x97, 0xe1, 0x7b, 0x0d, 0x52, 0x24, 0xbe, 0xc8 }, + }, + { + { 0x00, 0xf3, 0xfb, 0x08, 0xeb, 0x18, 0x10, 0xe3, 0xcb, 0x38, 0x30, 0xc3, 0x20, 0xd3, 0xdb, 0x28 }, + { 0x00, 0x8b, 0x0b, 0x80, 0x16, 0x9d, 0x1d, 0x96, 0x2c, 0xa7, 0x27, 0xac, 0x3a, 0xb1, 0x31, 0xba }, + }, + { + { 0x00, 0x91, 0x3f, 0xae, 0x7e, 0xef, 0x41, 0xd0, 0xfc, 0x6d, 0xc3, 0x52, 0x82, 0x13, 0xbd, 0x2c }, + { 0x00, 0xe5, 0xd7, 0x32, 0xb3, 0x56, 0x64, 0x81, 0x7b, 0x9e, 0xac, 0x49, 0xc8, 0x2d, 0x1f, 0xfa }, + }, + { + { 0x00, 0x40, 0x80, 0xc0, 0x1d, 0x5d, 0x9d, 0xdd, 0x3a, 0x7a, 0xba, 0xfa, 0x27, 0x67, 0xa7, 0xe7 }, + { 0x00, 0x74, 0xe8, 0x9c, 0xcd, 0xb9, 0x25, 0x51, 0x87, 0xf3, 0x6f, 0x1b, 0x4a, 0x3e, 0xa2, 0xd6 }, + }, + }, + { + { + { 0x00, 0xa2, 0x59, 0xfb, 0xb2, 0x10, 0xeb, 0x49, 0x79, 0xdb, 0x20, 0x82, 0xcb, 0x69, 0x92, 0x30 }, + { 0x00, 0xf2, 0xf9, 0x0b, 0xef, 0x1d, 0x16, 0xe4, 0xc3, 0x31, 0x3a, 0xc8, 0x2c, 0xde, 0xd5, 0x27 }, + }, + { + { 0x00, 0x1b, 0x36, 0x2d, 0x6c, 0x77, 0x5a, 0x41, 0xd8, 0xc3, 0xee, 0xf5, 0xb4, 0xaf, 0x82, 0x99 }, + { 0x00, 0xad, 0x47, 0xea, 0x8e, 0x23, 0xc9, 0x64, 0x01, 0xac, 0x46, 0xeb, 0x8f, 0x22, 0xc8, 0x65 }, + }, + { + { 0x00, 0x2e, 0x5c, 0x72, 0xb8, 0x96, 0xe4, 0xca, 0x6d, 0x43, 0x31, 0x1f, 0xd5, 0xfb, 0x89, 0xa7 }, + { 0x00, 0xda, 0xa9, 0x73, 0x4f, 0x95, 0xe6, 0x3c, 0x9e, 0x44, 0x37, 0xed, 0xd1, 0x0b, 0x78, 0xa2 }, + }, + { + { 0x00, 0x91, 0x3f, 0xae, 0x7e, 0xef, 0x41, 0xd0, 0xfc, 0x6d, 0xc3, 0x52, 0x82, 0x13, 0xbd, 0x2c }, + { 0x00, 0xe5, 0xd7, 0x32, 0xb3, 0x56, 0x64, 0x81, 0x7b, 0x9e, 0xac, 0x49, 0xc8, 0x2d, 0x1f, 0xfa }, + }, + }, + { + { + { 0x00, 0x12, 0x24, 0x36, 0x48, 0x5a, 0x6c, 0x7e, 0x90, 0x82, 0xb4, 0xa6, 0xd8, 0xca, 0xfc, 0xee }, + { 0x00, 0x3d, 0x7a, 0x47, 0xf4, 0xc9, 0x8e, 0xb3, 0xf5, 0xc8, 0x8f, 0xb2, 0x01, 0x3c, 0x7b, 0x46 }, + }, + { + { 0x00, 0xf2, 0xf9, 0x0b, 0xef, 0x1d, 0x16, 0xe4, 0xc3, 0x31, 0x3a, 0xc8, 0x2c, 0xde, 0xd5, 0x27 }, + { 0x00, 0x9b, 0x2b, 0xb0, 0x56, 0xcd, 0x7d, 0xe6, 0xac, 0x37, 0x87, 0x1c, 0xfa, 0x61, 0xd1, 0x4a }, + }, + { + { 0x00, 0x4e, 0x9c, 0xd2, 0x25, 0x6b, 0xb9, 0xf7, 0x4a, 0x04, 0xd6, 0x98, 0x6f, 0x21, 0xf3, 0xbd }, + { 0x00, 0x94, 0x35, 0xa1, 0x6a, 0xfe, 0x5f, 0xcb, 0xd4, 0x40, 0xe1, 0x75, 0xbe, 0x2a, 0x8b, 0x1f }, + }, + { + { 0x00, 0x56, 0xac, 0xfa, 0x45, 0x13, 0xe9, 0xbf, 0x8a, 0xdc, 0x26, 0x70, 0xcf, 0x99, 0x63, 0x35 }, + { 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77 }, + }, + }, + { + { + { 0x00, 0x57, 0xae, 0xf9, 0x41, 0x16, 0xef, 0xb8, 0x82, 0xd5, 0x2c, 0x7b, 0xc3, 0x94, 0x6d, 0x3a }, + { 0x00, 0x19, 0x32, 0x2b, 0x64, 0x7d, 0x56, 0x4f, 0xc8, 0xd1, 0xfa, 0xe3, 0xac, 0xb5, 0x9e, 0x87 }, + }, + { + { 0x00, 0xed, 0xc7, 0x2a, 0x93, 0x7e, 0x54, 0xb9, 0x3b, 0xd6, 0xfc, 0x11, 0xa8, 0x45, 0x6f, 0x82 }, + { 0x00, 0x76, 0xec, 0x9a, 0xc5, 0xb3, 0x29, 0x5f, 0x97, 0xe1, 0x7b, 0x0d, 0x52, 0x24, 0xbe, 0xc8 }, + }, + { + { 0x00, 0xfe, 0xe1, 0x1f, 0xdf, 0x21, 0x3e, 0xc0, 0xa3, 0x5d, 0x42, 0xbc, 0x7c, 0x82, 0x9d, 0x63 }, + { 0x00, 0x5b, 0xb6, 0xed, 0x71, 0x2a, 0xc7, 0x9c, 0xe2, 0xb9, 0x54, 0x0f, 0x93, 0xc8, 0x25, 0x7e }, + }, + { + { 0x00, 0x13, 0x26, 0x35, 0x4c, 0x5f, 0x6a, 0x79, 0x98, 0x8b, 0xbe, 0xad, 0xd4, 0xc7, 0xf2, 0xe1 }, + { 0x00, 0x2d, 0x5a, 0x77, 0xb4, 0x99, 0xee, 0xc3, 0x75, 0x58, 0x2f, 0x02, 0xc1, 0xec, 0x9b, 0xb6 }, + }, + }, + { + { + { 0x00, 0xb6, 0x71, 0xc7, 0xe2, 0x54, 0x93, 0x25, 0xd9, 0x6f, 0xa8, 0x1e, 0x3b, 0x8d, 0x4a, 0xfc }, + { 0x00, 0xaf, 0x43, 0xec, 0x86, 0x29, 0xc5, 0x6a, 0x11, 0xbe, 0x52, 0xfd, 0x97, 0x38, 0xd4, 0x7b }, + }, + { + { 0x00, 0xb3, 0x7b, 0xc8, 0xf6, 0x45, 0x8d, 0x3e, 0xf1, 0x42, 0x8a, 0x39, 0x07, 0xb4, 0x7c, 0xcf }, + { 0x00, 0xff, 0xe3, 0x1c, 0xdb, 0x24, 0x38, 0xc7, 0xab, 0x54, 0x48, 0xb7, 0x70, 0x8f, 0x93, 0x6c }, + }, + { + { 0x00, 0x21, 0x42, 0x63, 0x84, 0xa5, 0xc6, 0xe7, 0x15, 0x34, 0x57, 0x76, 0x91, 0xb0, 0xd3, 0xf2 }, + { 0x00, 0x2a, 0x54, 0x7e, 0xa8, 0x82, 0xfc, 0xd6, 0x4d, 0x67, 0x19, 0x33, 0xe5, 0xcf, 0xb1, 0x9b }, + }, + { + { 0x00, 0xfa, 0xe9, 0x13, 0xcf, 0x35, 0x26, 0xdc, 0x83, 0x79, 0x6a, 0x90, 0x4c, 0xb6, 0xa5, 0x5f }, + { 0x00, 0x1b, 0x36, 0x2d, 0x6c, 0x77, 0x5a, 0x41, 0xd8, 0xc3, 0xee, 0xf5, 0xb4, 0xaf, 0x82, 0x99 }, + }, + }, + { + { + { 0x00, 0x29, 0x52, 0x7b, 0xa4, 0x8d, 0xf6, 0xdf, 0x55, 0x7c, 0x07, 0x2e, 0xf1, 0xd8, 0xa3, 0x8a }, + { 0x00, 0xaa, 0x49, 0xe3, 0x92, 0x38, 0xdb, 0x71, 0x39, 0x93, 0x70, 0xda, 0xab, 0x01, 0xe2, 0x48 }, + }, + { + { 0x00, 0x45, 0x8a, 0xcf, 0x09, 0x4c, 0x83, 0xc6, 0x12, 0x57, 0x98, 0xdd, 0x1b, 0x5e, 0x91, 0xd4 }, + { 0x00, 0x24, 0x48, 0x6c, 0x90, 0xb4, 0xd8, 0xfc, 0x3d, 0x19, 0x75, 0x51, 0xad, 0x89, 0xe5, 0xc1 }, + }, + { + { 0x00, 0x1f, 0x3e, 0x21, 0x7c, 0x63, 0x42, 0x5d, 0xf8, 0xe7, 0xc6, 0xd9, 0x84, 0x9b, 0xba, 0xa5 }, + { 0x00, 0xed, 0xc7, 0x2a, 0x93, 0x7e, 0x54, 0xb9, 0x3b, 0xd6, 0xfc, 0x11, 0xa8, 0x45, 0x6f, 0x82 }, + }, + { + { 0x00, 0x87, 0x13, 0x94, 0x26, 0xa1, 0x35, 0xb2, 0x4c, 0xcb, 0x5f, 0xd8, 0x6a, 0xed, 0x79, 0xfe }, + { 0x00, 0x98, 0x2d, 0xb5, 0x5a, 0xc2, 0x77, 0xef, 0xb4, 0x2c, 0x99, 0x01, 0xee, 0x76, 0xc3, 0x5b }, + }, + }, + { + { + { 0x00, 0x8d, 0x07, 0x8a, 0x0e, 0x83, 0x09, 0x84, 0x1c, 0x91, 0x1b, 0x96, 0x12, 0x9f, 0x15, 0x98 }, + { 0x00, 0x38, 0x70, 0x48, 0xe0, 0xd8, 0x90, 0xa8, 0xdd, 0xe5, 0xad, 0x95, 0x3d, 0x05, 0x4d, 0x75 }, + }, + { + { 0x00, 0xc8, 0x8d, 0x45, 0x07, 0xcf, 0x8a, 0x42, 0x0e, 0xc6, 0x83, 0x4b, 0x09, 0xc1, 0x84, 0x4c }, + { 0x00, 0x1c, 0x38, 0x24, 0x70, 0x6c, 0x48, 0x54, 0xe0, 0xfc, 0xd8, 0xc4, 0x90, 0x8c, 0xa8, 0xb4 }, + }, + { + { 0x00, 0x9e, 0x21, 0xbf, 0x42, 0xdc, 0x63, 0xfd, 0x84, 0x1a, 0xa5, 0x3b, 0xc6, 0x58, 0xe7, 0x79 }, + { 0x00, 0x15, 0x2a, 0x3f, 0x54, 0x41, 0x7e, 0x6b, 0xa8, 0xbd, 0x82, 0x97, 0xfc, 0xe9, 0xd6, 0xc3 }, + }, + { + { 0x00, 0xac, 0x45, 0xe9, 0x8a, 0x26, 0xcf, 0x63, 0x09, 0xa5, 0x4c, 0xe0, 0x83, 0x2f, 0xc6, 0x6a }, + { 0x00, 0x12, 0x24, 0x36, 0x48, 0x5a, 0x6c, 0x7e, 0x90, 0x82, 0xb4, 0xa6, 0xd8, 0xca, 0xfc, 0xee }, + }, + }, + { + { + { 0x00, 0x7b, 0xf6, 0x8d, 0xf1, 0x8a, 0x07, 0x7c, 0xff, 0x84, 0x09, 0x72, 0x0e, 0x75, 0xf8, 0x83 }, + { 0x00, 0xe3, 0xdb, 0x38, 0xab, 0x48, 0x70, 0x93, 0x4b, 0xa8, 0x90, 0x73, 0xe0, 0x03, 0x3b, 0xd8 }, + }, + { + { 0x00, 0xac, 0x45, 0xe9, 0x8a, 0x26, 0xcf, 0x63, 0x09, 0xa5, 0x4c, 0xe0, 0x83, 0x2f, 0xc6, 0x6a }, + { 0x00, 0x12, 0x24, 0x36, 0x48, 0x5a, 0x6c, 0x7e, 0x90, 0x82, 0xb4, 0xa6, 0xd8, 0xca, 0xfc, 0xee }, + }, + { + { 0x00, 0xe1, 0xdf, 0x3e, 0xa3, 0x42, 0x7c, 0x9d, 0x5b, 0xba, 0x84, 0x65, 0xf8, 0x19, 0x27, 0xc6 }, + { 0x00, 0xb6, 0x71, 0xc7, 0xe2, 0x54, 0x93, 0x25, 0xd9, 0x6f, 0xa8, 0x1e, 0x3b, 0x8d, 0x4a, 0xfc }, + }, + { + { 0x00, 0x27, 0x4e, 0x69, 0x9c, 0xbb, 0xd2, 0xf5, 0x25, 0x02, 0x6b, 0x4c, 0xb9, 0x9e, 0xf7, 0xd0 }, + { 0x00, 0x4a, 0x94, 0xde, 0x35, 0x7f, 0xa1, 0xeb, 0x6a, 0x20, 0xfe, 0xb4, 0x5f, 0x15, 0xcb, 0x81 }, + }, + }, + { + { + { 0x00, 0xc8, 0x8d, 0x45, 0x07, 0xcf, 0x8a, 0x42, 0x0e, 0xc6, 0x83, 0x4b, 0x09, 0xc1, 0x84, 0x4c }, + { 0x00, 0x1c, 0x38, 0x24, 0x70, 0x6c, 0x48, 0x54, 0xe0, 0xfc, 0xd8, 0xc4, 0x90, 0x8c, 0xa8, 0xb4 }, + }, + { + { 0x00, 0x7b, 0xf6, 0x8d, 0xf1, 0x8a, 0x07, 0x7c, 0xff, 0x84, 0x09, 0x72, 0x0e, 0x75, 0xf8, 0x83 }, + { 0x00, 0xe3, 0xdb, 0x38, 0xab, 0x48, 0x70, 0x93, 0x4b, 0xa8, 0x90, 0x73, 0xe0, 0x03, 0x3b, 0xd8 }, + }, + { + { 0x00, 0xd5, 0xb7, 0x62, 0x73, 0xa6, 0xc4, 0x11, 0xe6, 0x33, 0x51, 0x84, 0x95, 0x40, 0x22, 0xf7 }, + { 0x00, 0xd1, 0xbf, 0x6e, 0x63, 0xb2, 0xdc, 0x0d, 0xc6, 0x17, 0x79, 0xa8, 0xa5, 0x74, 0x1a, 0xcb }, + }, + { + { 0x00, 0x54, 0xa8, 0xfc, 0x4d, 0x19, 0xe5, 0xb1, 0x9a, 0xce, 0x32, 0x66, 0xd7, 0x83, 0x7f, 0x2b }, + { 0x00, 0x29, 0x52, 0x7b, 0xa4, 0x8d, 0xf6, 0xdf, 0x55, 0x7c, 0x07, 0x2e, 0xf1, 0xd8, 0xa3, 0x8a }, + }, + }, + { + { + { 0x00, 0x52, 0xa4, 0xf6, 0x55, 0x07, 0xf1, 0xa3, 0xaa, 0xf8, 0x0e, 0x5c, 0xff, 0xad, 0x5b, 0x09 }, + { 0x00, 0x49, 0x92, 0xdb, 0x39, 0x70, 0xab, 0xe2, 0x72, 0x3b, 0xe0, 0xa9, 0x4b, 0x02, 0xd9, 0x90 }, + }, + { + { 0x00, 0x2c, 0x58, 0x74, 0xb0, 0x9c, 0xe8, 0xc4, 0x7d, 0x51, 0x25, 0x09, 0xcd, 0xe1, 0x95, 0xb9 }, + { 0x00, 0xfa, 0xe9, 0x13, 0xcf, 0x35, 0x26, 0xdc, 0x83, 0x79, 0x6a, 0x90, 0x4c, 0xb6, 0xa5, 0x5f }, + }, + { + { 0x00, 0xcd, 0x87, 0x4a, 0x13, 0xde, 0x94, 0x59, 0x26, 0xeb, 0xa1, 0x6c, 0x35, 0xf8, 0xb2, 0x7f }, + { 0x00, 0x4c, 0x98, 0xd4, 0x2d, 0x61, 0xb5, 0xf9, 0x5a, 0x16, 0xc2, 0x8e, 0x77, 0x3b, 0xef, 0xa3 }, + }, + { + { 0x00, 0xdd, 0xa7, 0x7a, 0x53, 0x8e, 0xf4, 0x29, 0xa6, 0x7b, 0x01, 0xdc, 0xf5, 0x28, 0x52, 0x8f }, + { 0x00, 0x51, 0xa2, 0xf3, 0x59, 0x08, 0xfb, 0xaa, 0xb2, 0xe3, 0x10, 0x41, 0xeb, 0xba, 0x49, 0x18 }, + }, + }, + { + { + { 0x00, 0xc3, 0x9b, 0x58, 0x2b, 0xe8, 0xb0, 0x73, 0x56, 0x95, 0xcd, 0x0e, 0x7d, 0xbe, 0xe6, 0x25 }, + { 0x00, 0xac, 0x45, 0xe9, 0x8a, 0x26, 0xcf, 0x63, 0x09, 0xa5, 0x4c, 0xe0, 0x83, 0x2f, 0xc6, 0x6a }, + }, + { + { 0x00, 0xe2, 0xd9, 0x3b, 0xaf, 0x4d, 0x76, 0x94, 0x43, 0xa1, 0x9a, 0x78, 0xec, 0x0e, 0x35, 0xd7 }, + { 0x00, 0x86, 0x11, 0x97, 0x22, 0xa4, 0x33, 0xb5, 0x44, 0xc2, 0x55, 0xd3, 0x66, 0xe0, 0x77, 0xf1 }, + }, + { + { 0x00, 0xca, 0x89, 0x43, 0x0f, 0xc5, 0x86, 0x4c, 0x1e, 0xd4, 0x97, 0x5d, 0x11, 0xdb, 0x98, 0x52 }, + { 0x00, 0x3c, 0x78, 0x44, 0xf0, 0xcc, 0x88, 0xb4, 0xfd, 0xc1, 0x85, 0xb9, 0x0d, 0x31, 0x75, 0x49 }, + }, + { + { 0x00, 0x59, 0xb2, 0xeb, 0x79, 0x20, 0xcb, 0x92, 0xf2, 0xab, 0x40, 0x19, 0x8b, 0xd2, 0x39, 0x60 }, + { 0x00, 0xf9, 0xef, 0x16, 0xc3, 0x3a, 0x2c, 0xd5, 0x9b, 0x62, 0x74, 0x8d, 0x58, 0xa1, 0xb7, 0x4e }, + }, + }, + { + { + { 0x00, 0xbc, 0x65, 0xd9, 0xca, 0x76, 0xaf, 0x13, 0x89, 0x35, 0xec, 0x50, 0x43, 0xff, 0x26, 0x9a }, + { 0x00, 0x0f, 0x1e, 0x11, 0x3c, 0x33, 0x22, 0x2d, 0x78, 0x77, 0x66, 0x69, 0x44, 0x4b, 0x5a, 0x55 }, + }, + { + { 0x00, 0xe4, 0xd5, 0x31, 0xb7, 0x53, 0x62, 0x86, 0x73, 0x97, 0xa6, 0x42, 0xc4, 0x20, 0x11, 0xf5 }, + { 0x00, 0xe6, 0xd1, 0x37, 0xbf, 0x59, 0x6e, 0x88, 0x63, 0x85, 0xb2, 0x54, 0xdc, 0x3a, 0x0d, 0xeb }, + }, + { + { 0x00, 0xf0, 0xfd, 0x0d, 0xe7, 0x17, 0x1a, 0xea, 0xd3, 0x23, 0x2e, 0xde, 0x34, 0xc4, 0xc9, 0x39 }, + { 0x00, 0xbb, 0x6b, 0xd0, 0xd6, 0x6d, 0xbd, 0x06, 0xb1, 0x0a, 0xda, 0x61, 0x67, 0xdc, 0x0c, 0xb7 }, + }, + { + { 0x00, 0x1f, 0x3e, 0x21, 0x7c, 0x63, 0x42, 0x5d, 0xf8, 0xe7, 0xc6, 0xd9, 0x84, 0x9b, 0xba, 0xa5 }, + { 0x00, 0xed, 0xc7, 0x2a, 0x93, 0x7e, 0x54, 0xb9, 0x3b, 0xd6, 0xfc, 0x11, 0xa8, 0x45, 0x6f, 0x82 }, + }, + }, + { + { + { 0x00, 0xb8, 0x6d, 0xd5, 0xda, 0x62, 0xb7, 0x0f, 0xa9, 0x11, 0xc4, 0x7c, 0x73, 0xcb, 0x1e, 0xa6 }, + { 0x00, 0x4f, 0x9e, 0xd1, 0x21, 0x6e, 0xbf, 0xf0, 0x42, 0x0d, 0xdc, 0x93, 0x63, 0x2c, 0xfd, 0xb2 }, + }, + { + { 0x00, 0xbf, 0x63, 0xdc, 0xc6, 0x79, 0xa5, 0x1a, 0x91, 0x2e, 0xf2, 0x4d, 0x57, 0xe8, 0x34, 0x8b }, + { 0x00, 0x3f, 0x7e, 0x41, 0xfc, 0xc3, 0x82, 0xbd, 0xe5, 0xda, 0x9b, 0xa4, 0x19, 0x26, 0x67, 0x58 }, + }, + { + { 0x00, 0x8b, 0x0b, 0x80, 0x16, 0x9d, 0x1d, 0x96, 0x2c, 0xa7, 0x27, 0xac, 0x3a, 0xb1, 0x31, 0xba }, + { 0x00, 0x58, 0xb0, 0xe8, 0x7d, 0x25, 0xcd, 0x95, 0xfa, 0xa2, 0x4a, 0x12, 0x87, 0xdf, 0x37, 0x6f }, + }, + { + { 0x00, 0x71, 0xe2, 0x93, 0xd9, 0xa8, 0x3b, 0x4a, 0xaf, 0xde, 0x4d, 0x3c, 0x76, 0x07, 0x94, 0xe5 }, + { 0x00, 0x43, 0x86, 0xc5, 0x11, 0x52, 0x97, 0xd4, 0x22, 0x61, 0xa4, 0xe7, 0x33, 0x70, 0xb5, 0xf6 }, + }, + }, + { + { + { 0x00, 0x21, 0x42, 0x63, 0x84, 0xa5, 0xc6, 0xe7, 0x15, 0x34, 0x57, 0x76, 0x91, 0xb0, 0xd3, 0xf2 }, + { 0x00, 0x2a, 0x54, 0x7e, 0xa8, 0x82, 0xfc, 0xd6, 0x4d, 0x67, 0x19, 0x33, 0xe5, 0xcf, 0xb1, 0x9b }, + }, + { + { 0x00, 0xbe, 0x61, 0xdf, 0xc2, 0x7c, 0xa3, 0x1d, 0x99, 0x27, 0xf8, 0x46, 0x5b, 0xe5, 0x3a, 0x84 }, + { 0x00, 0x2f, 0x5e, 0x71, 0xbc, 0x93, 0xe2, 0xcd, 0x65, 0x4a, 0x3b, 0x14, 0xd9, 0xf6, 0x87, 0xa8 }, + }, + { + { 0x00, 0x2b, 0x56, 0x7d, 0xac, 0x87, 0xfa, 0xd1, 0x45, 0x6e, 0x13, 0x38, 0xe9, 0xc2, 0xbf, 0x94 }, + { 0x00, 0x8a, 0x09, 0x83, 0x12, 0x98, 0x1b, 0x91, 0x24, 0xae, 0x2d, 0xa7, 0x36, 0xbc, 0x3f, 0xb5 }, + }, + { + { 0x00, 0x39, 0x72, 0x4b, 0xe4, 0xdd, 0x96, 0xaf, 0xd5, 0xec, 0xa7, 0x9e, 0x31, 0x08, 0x43, 0x7a }, + { 0x00, 0xb7, 0x73, 0xc4, 0xe6, 0x51, 0x95, 0x22, 0xd1, 0x66, 0xa2, 0x15, 0x37, 0x80, 0x44, 0xf3 }, + }, + }, + { + { + { 0x00, 0xd4, 0xb5, 0x61, 0x77, 0xa3, 0xc2, 0x16, 0xee, 0x3a, 0x5b, 0x8f, 0x99, 0x4d, 0x2c, 0xf8 }, + { 0x00, 0xc1, 0x9f, 0x5e, 0x23, 0xe2, 0xbc, 0x7d, 0x46, 0x87, 0xd9, 0x18, 0x65, 0xa4, 0xfa, 0x3b }, + }, + { + { 0x00, 0x9f, 0x23, 0xbc, 0x46, 0xd9, 0x65, 0xfa, 0x8c, 0x13, 0xaf, 0x30, 0xca, 0x55, 0xe9, 0x76 }, + { 0x00, 0x05, 0x0a, 0x0f, 0x14, 0x11, 0x1e, 0x1b, 0x28, 0x2d, 0x22, 0x27, 0x3c, 0x39, 0x36, 0x33 }, + }, + { + { 0x00, 0xc9, 0x8f, 0x46, 0x03, 0xca, 0x8c, 0x45, 0x06, 0xcf, 0x89, 0x40, 0x05, 0xcc, 0x8a, 0x43 }, + { 0x00, 0x0c, 0x18, 0x14, 0x30, 0x3c, 0x28, 0x24, 0x60, 0x6c, 0x78, 0x74, 0x50, 0x5c, 0x48, 0x44 }, + }, + { + { 0x00, 0x43, 0x86, 0xc5, 0x11, 0x52, 0x97, 0xd4, 0x22, 0x61, 0xa4, 0xe7, 0x33, 0x70, 0xb5, 0xf6 }, + { 0x00, 0x44, 0x88, 0xcc, 0x0d, 0x49, 0x85, 0xc1, 0x1a, 0x5e, 0x92, 0xd6, 0x17, 0x53, 0x9f, 0xdb }, + }, + }, + { + { + { 0x00, 0xea, 0xc9, 0x23, 0x8f, 0x65, 0x46, 0xac, 0x03, 0xe9, 0xca, 0x20, 0x8c, 0x66, 0x45, 0xaf }, + { 0x00, 0x06, 0x0c, 0x0a, 0x18, 0x1e, 0x14, 0x12, 0x30, 0x36, 0x3c, 0x3a, 0x28, 0x2e, 0x24, 0x22 }, + }, + { + { 0x00, 0x34, 0x68, 0x5c, 0xd0, 0xe4, 0xb8, 0x8c, 0xbd, 0x89, 0xd5, 0xe1, 0x6d, 0x59, 0x05, 0x31 }, + { 0x00, 0x67, 0xce, 0xa9, 0x81, 0xe6, 0x4f, 0x28, 0x1f, 0x78, 0xd1, 0xb6, 0x9e, 0xf9, 0x50, 0x37 }, + }, + { + { 0x00, 0x8a, 0x09, 0x83, 0x12, 0x98, 0x1b, 0x91, 0x24, 0xae, 0x2d, 0xa7, 0x36, 0xbc, 0x3f, 0xb5 }, + { 0x00, 0x48, 0x90, 0xd8, 0x3d, 0x75, 0xad, 0xe5, 0x7a, 0x32, 0xea, 0xa2, 0x47, 0x0f, 0xd7, 0x9f }, + }, + { + { 0x00, 0x6c, 0xd8, 0xb4, 0xad, 0xc1, 0x75, 0x19, 0x47, 0x2b, 0x9f, 0xf3, 0xea, 0x86, 0x32, 0x5e }, + { 0x00, 0x8e, 0x01, 0x8f, 0x02, 0x8c, 0x03, 0x8d, 0x04, 0x8a, 0x05, 0x8b, 0x06, 0x88, 0x07, 0x89 }, + }, + }, + { + { + { 0x00, 0xd3, 0xbb, 0x68, 0x6b, 0xb8, 0xd0, 0x03, 0xd6, 0x05, 0x6d, 0xbe, 0xbd, 0x6e, 0x06, 0xd5 }, + { 0x00, 0xb1, 0x7f, 0xce, 0xfe, 0x4f, 0x81, 0x30, 0xe1, 0x50, 0x9e, 0x2f, 0x1f, 0xae, 0x60, 0xd1 }, + }, + { + { 0x00, 0x05, 0x0a, 0x0f, 0x14, 0x11, 0x1e, 0x1b, 0x28, 0x2d, 0x22, 0x27, 0x3c, 0x39, 0x36, 0x33 }, + { 0x00, 0x50, 0xa0, 0xf0, 0x5d, 0x0d, 0xfd, 0xad, 0xba, 0xea, 0x1a, 0x4a, 0xe7, 0xb7, 0x47, 0x17 }, + }, + { + { 0x00, 0x93, 0x3b, 0xa8, 0x76, 0xe5, 0x4d, 0xde, 0xec, 0x7f, 0xd7, 0x44, 0x9a, 0x09, 0xa1, 0x32 }, + { 0x00, 0xc5, 0x97, 0x52, 0x33, 0xf6, 0xa4, 0x61, 0x66, 0xa3, 0xf1, 0x34, 0x55, 0x90, 0xc2, 0x07 }, + }, + { + { 0x00, 0xf9, 0xef, 0x16, 0xc3, 0x3a, 0x2c, 0xd5, 0x9b, 0x62, 0x74, 0x8d, 0x58, 0xa1, 0xb7, 0x4e }, + { 0x00, 0x2b, 0x56, 0x7d, 0xac, 0x87, 0xfa, 0xd1, 0x45, 0x6e, 0x13, 0x38, 0xe9, 0xc2, 0xbf, 0x94 }, + }, + }, + { + { + { 0x00, 0x06, 0x0c, 0x0a, 0x18, 0x1e, 0x14, 0x12, 0x30, 0x36, 0x3c, 0x3a, 0x28, 0x2e, 0x24, 0x22 }, + { 0x00, 0x60, 0xc0, 0xa0, 0x9d, 0xfd, 0x5d, 0x3d, 0x27, 0x47, 0xe7, 0x87, 0xba, 0xda, 0x7a, 0x1a }, + }, + { + { 0x00, 0x70, 0xe0, 0x90, 0xdd, 0xad, 0x3d, 0x4d, 0xa7, 0xd7, 0x47, 0x37, 0x7a, 0x0a, 0x9a, 0xea }, + { 0x00, 0x53, 0xa6, 0xf5, 0x51, 0x02, 0xf7, 0xa4, 0xa2, 0xf1, 0x04, 0x57, 0xf3, 0xa0, 0x55, 0x06 }, + }, + { + { 0x00, 0xbb, 0x6b, 0xd0, 0xd6, 0x6d, 0xbd, 0x06, 0xb1, 0x0a, 0xda, 0x61, 0x67, 0xdc, 0x0c, 0xb7 }, + { 0x00, 0x7f, 0xfe, 0x81, 0xe1, 0x9e, 0x1f, 0x60, 0xdf, 0xa0, 0x21, 0x5e, 0x3e, 0x41, 0xc0, 0xbf }, + }, + { + { 0x00, 0xbe, 0x61, 0xdf, 0xc2, 0x7c, 0xa3, 0x1d, 0x99, 0x27, 0xf8, 0x46, 0x5b, 0xe5, 0x3a, 0x84 }, + { 0x00, 0x2f, 0x5e, 0x71, 0xbc, 0x93, 0xe2, 0xcd, 0x65, 0x4a, 0x3b, 0x14, 0xd9, 0xf6, 0x87, 0xa8 }, + }, + }, + { + { + { 0x00, 0xab, 0x4b, 0xe0, 0x96, 0x3d, 0xdd, 0x76, 0x31, 0x9a, 0x7a, 0xd1, 0xa7, 0x0c, 0xec, 0x47 }, + { 0x00, 0x62, 0xc4, 0xa6, 0x95, 0xf7, 0x51, 0x33, 0x37, 0x55, 0xf3, 0x91, 0xa2, 0xc0, 0x66, 0x04 }, + }, + { + { 0x00, 0x3f, 0x7e, 0x41, 0xfc, 0xc3, 0x82, 0xbd, 0xe5, 0xda, 0x9b, 0xa4, 0x19, 0x26, 0x67, 0x58 }, + { 0x00, 0xd7, 0xb3, 0x64, 0x7b, 0xac, 0xc8, 0x1f, 0xf6, 0x21, 0x45, 0x92, 0x8d, 0x5a, 0x3e, 0xe9 }, + }, + { + { 0x00, 0x57, 0xae, 0xf9, 0x41, 0x16, 0xef, 0xb8, 0x82, 0xd5, 0x2c, 0x7b, 0xc3, 0x94, 0x6d, 0x3a }, + { 0x00, 0x19, 0x32, 0x2b, 0x64, 0x7d, 0x56, 0x4f, 0xc8, 0xd1, 0xfa, 0xe3, 0xac, 0xb5, 0x9e, 0x87 }, + }, + { + { 0x00, 0x4f, 0x9e, 0xd1, 0x21, 0x6e, 0xbf, 0xf0, 0x42, 0x0d, 0xdc, 0x93, 0x63, 0x2c, 0xfd, 0xb2 }, + { 0x00, 0x84, 0x15, 0x91, 0x2a, 0xae, 0x3f, 0xbb, 0x54, 0xd0, 0x41, 0xc5, 0x7e, 0xfa, 0x6b, 0xef }, + }, + }, + { + { + { 0x00, 0x2a, 0x54, 0x7e, 0xa8, 0x82, 0xfc, 0xd6, 0x4d, 0x67, 0x19, 0x33, 0xe5, 0xcf, 0xb1, 0x9b }, + { 0x00, 0x9a, 0x29, 0xb3, 0x52, 0xc8, 0x7b, 0xe1, 0xa4, 0x3e, 0x8d, 0x17, 0xf6, 0x6c, 0xdf, 0x45 }, + }, + { + { 0x00, 0x98, 0x2d, 0xb5, 0x5a, 0xc2, 0x77, 0xef, 0xb4, 0x2c, 0x99, 0x01, 0xee, 0x76, 0xc3, 0x5b }, + { 0x00, 0x75, 0xea, 0x9f, 0xc9, 0xbc, 0x23, 0x56, 0x8f, 0xfa, 0x65, 0x10, 0x46, 0x33, 0xac, 0xd9 }, + }, + { + { 0x00, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0, 0x1d, 0x3d, 0x5d, 0x7d, 0x9d, 0xbd, 0xdd, 0xfd }, + { 0x00, 0x3a, 0x74, 0x4e, 0xe8, 0xd2, 0x9c, 0xa6, 0xcd, 0xf7, 0xb9, 0x83, 0x25, 0x1f, 0x51, 0x6b }, + }, + { + { 0x00, 0xf4, 0xf5, 0x01, 0xf7, 0x03, 0x02, 0xf6, 0xf3, 0x07, 0x06, 0xf2, 0x04, 0xf0, 0xf1, 0x05 }, + { 0x00, 0xfb, 0xeb, 0x10, 0xcb, 0x30, 0x20, 0xdb, 0x8b, 0x70, 0x60, 0x9b, 0x40, 0xbb, 0xab, 0x50 }, + }, + }, + { + { + { 0x00, 0x1b, 0x36, 0x2d, 0x6c, 0x77, 0x5a, 0x41, 0xd8, 0xc3, 0xee, 0xf5, 0xb4, 0xaf, 0x82, 0x99 }, + { 0x00, 0xad, 0x47, 0xea, 0x8e, 0x23, 0xc9, 0x64, 0x01, 0xac, 0x46, 0xeb, 0x8f, 0x22, 0xc8, 0x65 }, + }, + { + { 0x00, 0xfe, 0xe1, 0x1f, 0xdf, 0x21, 0x3e, 0xc0, 0xa3, 0x5d, 0x42, 0xbc, 0x7c, 0x82, 0x9d, 0x63 }, + { 0x00, 0x5b, 0xb6, 0xed, 0x71, 0x2a, 0xc7, 0x9c, 0xe2, 0xb9, 0x54, 0x0f, 0x93, 0xc8, 0x25, 0x7e }, + }, + { + { 0x00, 0x86, 0x11, 0x97, 0x22, 0xa4, 0x33, 0xb5, 0x44, 0xc2, 0x55, 0xd3, 0x66, 0xe0, 0x77, 0xf1 }, + { 0x00, 0x88, 0x0d, 0x85, 0x1a, 0x92, 0x17, 0x9f, 0x34, 0xbc, 0x39, 0xb1, 0x2e, 0xa6, 0x23, 0xab }, + }, + { + { 0x00, 0x1e, 0x3c, 0x22, 0x78, 0x66, 0x44, 0x5a, 0xf0, 0xee, 0xcc, 0xd2, 0x88, 0x96, 0xb4, 0xaa }, + { 0x00, 0xfd, 0xe7, 0x1a, 0xd3, 0x2e, 0x34, 0xc9, 0xbb, 0x46, 0x5c, 0xa1, 0x68, 0x95, 0x8f, 0x72 }, + }, + }, + { + { + { 0x00, 0x5f, 0xbe, 0xe1, 0x61, 0x3e, 0xdf, 0x80, 0xc2, 0x9d, 0x7c, 0x23, 0xa3, 0xfc, 0x1d, 0x42 }, + { 0x00, 0x99, 0x2f, 0xb6, 0x5e, 0xc7, 0x71, 0xe8, 0xbc, 0x25, 0x93, 0x0a, 0xe2, 0x7b, 0xcd, 0x54 }, + }, + { + { 0x00, 0x62, 0xc4, 0xa6, 0x95, 0xf7, 0x51, 0x33, 0x37, 0x55, 0xf3, 0x91, 0xa2, 0xc0, 0x66, 0x04 }, + { 0x00, 0x6e, 0xdc, 0xb2, 0xa5, 0xcb, 0x79, 0x17, 0x57, 0x39, 0x8b, 0xe5, 0xf2, 0x9c, 0x2e, 0x40 }, + }, + { + { 0x00, 0x1c, 0x38, 0x24, 0x70, 0x6c, 0x48, 0x54, 0xe0, 0xfc, 0xd8, 0xc4, 0x90, 0x8c, 0xa8, 0xb4 }, + { 0x00, 0xdd, 0xa7, 0x7a, 0x53, 0x8e, 0xf4, 0x29, 0xa6, 0x7b, 0x01, 0xdc, 0xf5, 0x28, 0x52, 0x8f }, + }, + { + { 0x00, 0x32, 0x64, 0x56, 0xc8, 0xfa, 0xac, 0x9e, 0x8d, 0xbf, 0xe9, 0xdb, 0x45, 0x77, 0x21, 0x13 }, + { 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d }, + }, + }, + { + { + { 0x00, 0xb7, 0x73, 0xc4, 0xe6, 0x51, 0x95, 0x22, 0xd1, 0x66, 0xa2, 0x15, 0x37, 0x80, 0x44, 0xf3 }, + { 0x00, 0xbf, 0x63, 0xdc, 0xc6, 0x79, 0xa5, 0x1a, 0x91, 0x2e, 0xf2, 0x4d, 0x57, 0xe8, 0x34, 0x8b }, + }, + { + { 0x00, 0x18, 0x30, 0x28, 0x60, 0x78, 0x50, 0x48, 0xc0, 0xd8, 0xf0, 0xe8, 0xa0, 0xb8, 0x90, 0x88 }, + { 0x00, 0x9d, 0x27, 0xba, 0x4e, 0xd3, 0x69, 0xf4, 0x9c, 0x01, 0xbb, 0x26, 0xd2, 0x4f, 0xf5, 0x68 }, + }, + { + { 0x00, 0xa1, 0x5f, 0xfe, 0xbe, 0x1f, 0xe1, 0x40, 0x61, 0xc0, 0x3e, 0x9f, 0xdf, 0x7e, 0x80, 0x21 }, + { 0x00, 0xc2, 0x99, 0x5b, 0x2f, 0xed, 0xb6, 0x74, 0x5e, 0x9c, 0xc7, 0x05, 0x71, 0xb3, 0xe8, 0x2a }, + }, + { + { 0x00, 0xcd, 0x87, 0x4a, 0x13, 0xde, 0x94, 0x59, 0x26, 0xeb, 0xa1, 0x6c, 0x35, 0xf8, 0xb2, 0x7f }, + { 0x00, 0x4c, 0x98, 0xd4, 0x2d, 0x61, 0xb5, 0xf9, 0x5a, 0x16, 0xc2, 0x8e, 0x77, 0x3b, 0xef, 0xa3 }, + }, + }, + { + { + { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0 }, + { 0x00, 0x1d, 0x3a, 0x27, 0x74, 0x69, 0x4e, 0x53, 0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb }, + }, + { + { 0x00, 0x9a, 0x29, 0xb3, 0x52, 0xc8, 0x7b, 0xe1, 0xa4, 0x3e, 0x8d, 0x17, 0xf6, 0x6c, 0xdf, 0x45 }, + { 0x00, 0x55, 0xaa, 0xff, 0x49, 0x1c, 0xe3, 0xb6, 0x92, 0xc7, 0x38, 0x6d, 0xdb, 0x8e, 0x71, 0x24 }, + }, + { + { 0x00, 0x4f, 0x9e, 0xd1, 0x21, 0x6e, 0xbf, 0xf0, 0x42, 0x0d, 0xdc, 0x93, 0x63, 0x2c, 0xfd, 0xb2 }, + { 0x00, 0x84, 0x15, 0x91, 0x2a, 0xae, 0x3f, 0xbb, 0x54, 0xd0, 0x41, 0xc5, 0x7e, 0xfa, 0x6b, 0xef }, + }, + { + { 0x00, 0xe9, 0xcf, 0x26, 0x83, 0x6a, 0x4c, 0xa5, 0x1b, 0xf2, 0xd4, 0x3d, 0x98, 0x71, 0x57, 0xbe }, + { 0x00, 0x36, 0x6c, 0x5a, 0xd8, 0xee, 0xb4, 0x82, 0xad, 0x9b, 0xc1, 0xf7, 0x75, 0x43, 0x19, 0x2f }, + }, + }, + { + { + { 0x00, 0xec, 0xc5, 0x29, 0x97, 0x7b, 0x52, 0xbe, 0x33, 0xdf, 0xf6, 0x1a, 0xa4, 0x48, 0x61, 0x8d }, + { 0x00, 0x66, 0xcc, 0xaa, 0x85, 0xe3, 0x49, 0x2f, 0x17, 0x71, 0xdb, 0xbd, 0x92, 0xf4, 0x5e, 0x38 }, + }, + { + { 0x00, 0x56, 0xac, 0xfa, 0x45, 0x13, 0xe9, 0xbf, 0x8a, 0xdc, 0x26, 0x70, 0xcf, 0x99, 0x63, 0x35 }, + { 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77 }, + }, + { + { 0x00, 0x3e, 0x7c, 0x42, 0xf8, 0xc6, 0x84, 0xba, 0xed, 0xd3, 0x91, 0xaf, 0x15, 0x2b, 0x69, 0x57 }, + { 0x00, 0xc7, 0x93, 0x54, 0x3b, 0xfc, 0xa8, 0x6f, 0x76, 0xb1, 0xe5, 0x22, 0x4d, 0x8a, 0xde, 0x19 }, + }, + { + { 0x00, 0x7e, 0xfc, 0x82, 0xe5, 0x9b, 0x19, 0x67, 0xd7, 0xa9, 0x2b, 0x55, 0x32, 0x4c, 0xce, 0xb0 }, + { 0x00, 0xb3, 0x7b, 0xc8, 0xf6, 0x45, 0x8d, 0x3e, 0xf1, 0x42, 0x8a, 0x39, 0x07, 0xb4, 0x7c, 0xcf }, + }, + }, + { + { + { 0x00, 0x64, 0xc8, 0xac, 0x8d, 0xe9, 0x45, 0x21, 0x07, 0x63, 0xcf, 0xab, 0x8a, 0xee, 0x42, 0x26 }, + { 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a }, + }, + { + { 0x00, 0x8d, 0x07, 0x8a, 0x0e, 0x83, 0x09, 0x84, 0x1c, 0x91, 0x1b, 0x96, 0x12, 0x9f, 0x15, 0x98 }, + { 0x00, 0x38, 0x70, 0x48, 0xe0, 0xd8, 0x90, 0xa8, 0xdd, 0xe5, 0xad, 0x95, 0x3d, 0x05, 0x4d, 0x75 }, + }, + { + { 0x00, 0x25, 0x4a, 0x6f, 0x94, 0xb1, 0xde, 0xfb, 0x35, 0x10, 0x7f, 0x5a, 0xa1, 0x84, 0xeb, 0xce }, + { 0x00, 0x6a, 0xd4, 0xbe, 0xb5, 0xdf, 0x61, 0x0b, 0x77, 0x1d, 0xa3, 0xc9, 0xc2, 0xa8, 0x16, 0x7c }, + }, + { + { 0x00, 0x7b, 0xf6, 0x8d, 0xf1, 0x8a, 0x07, 0x7c, 0xff, 0x84, 0x09, 0x72, 0x0e, 0x75, 0xf8, 0x83 }, + { 0x00, 0xe3, 0xdb, 0x38, 0xab, 0x48, 0x70, 0x93, 0x4b, 0xa8, 0x90, 0x73, 0xe0, 0x03, 0x3b, 0xd8 }, + }, + }, + { + { + { 0x00, 0xf6, 0xf1, 0x07, 0xff, 0x09, 0x0e, 0xf8, 0xe3, 0x15, 0x12, 0xe4, 0x1c, 0xea, 0xed, 0x1b }, + { 0x00, 0xdb, 0xab, 0x70, 0x4b, 0x90, 0xe0, 0x3b, 0x96, 0x4d, 0x3d, 0xe6, 0xdd, 0x06, 0x76, 0xad }, + }, + { + { 0x00, 0x93, 0x3b, 0xa8, 0x76, 0xe5, 0x4d, 0xde, 0xec, 0x7f, 0xd7, 0x44, 0x9a, 0x09, 0xa1, 0x32 }, + { 0x00, 0xc5, 0x97, 0x52, 0x33, 0xf6, 0xa4, 0x61, 0x66, 0xa3, 0xf1, 0x34, 0x55, 0x90, 0xc2, 0x07 }, + }, + { + { 0x00, 0xd4, 0xb5, 0x61, 0x77, 0xa3, 0xc2, 0x16, 0xee, 0x3a, 0x5b, 0x8f, 0x99, 0x4d, 0x2c, 0xf8 }, + { 0x00, 0xc1, 0x9f, 0x5e, 0x23, 0xe2, 0xbc, 0x7d, 0x46, 0x87, 0xd9, 0x18, 0x65, 0xa4, 0xfa, 0x3b }, + }, + { + { 0x00, 0x66, 0xcc, 0xaa, 0x85, 0xe3, 0x49, 0x2f, 0x17, 0x71, 0xdb, 0xbd, 0x92, 0xf4, 0x5e, 0x38 }, + { 0x00, 0x2e, 0x5c, 0x72, 0xb8, 0x96, 0xe4, 0xca, 0x6d, 0x43, 0x31, 0x1f, 0xd5, 0xfb, 0x89, 0xa7 }, + }, + }, + { + { + { 0x00, 0xe2, 0xd9, 0x3b, 0xaf, 0x4d, 0x76, 0x94, 0x43, 0xa1, 0x9a, 0x78, 0xec, 0x0e, 0x35, 0xd7 }, + { 0x00, 0x86, 0x11, 0x97, 0x22, 0xa4, 0x33, 0xb5, 0x44, 0xc2, 0x55, 0xd3, 0x66, 0xe0, 0x77, 0xf1 }, + }, + { + { 0x00, 0x97, 0x33, 0xa4, 0x66, 0xf1, 0x55, 0xc2, 0xcc, 0x5b, 0xff, 0x68, 0xaa, 0x3d, 0x99, 0x0e }, + { 0x00, 0x85, 0x17, 0x92, 0x2e, 0xab, 0x39, 0xbc, 0x5c, 0xd9, 0x4b, 0xce, 0x72, 0xf7, 0x65, 0xe0 }, + }, + { + { 0x00, 0x6c, 0xd8, 0xb4, 0xad, 0xc1, 0x75, 0x19, 0x47, 0x2b, 0x9f, 0xf3, 0xea, 0x86, 0x32, 0x5e }, + { 0x00, 0x8e, 0x01, 0x8f, 0x02, 0x8c, 0x03, 0x8d, 0x04, 0x8a, 0x05, 0x8b, 0x06, 0x88, 0x07, 0x89 }, + }, + { + { 0x00, 0x5f, 0xbe, 0xe1, 0x61, 0x3e, 0xdf, 0x80, 0xc2, 0x9d, 0x7c, 0x23, 0xa3, 0xfc, 0x1d, 0x42 }, + { 0x00, 0x99, 0x2f, 0xb6, 0x5e, 0xc7, 0x71, 0xe8, 0xbc, 0x25, 0x93, 0x0a, 0xe2, 0x7b, 0xcd, 0x54 }, + }, + }, + { + { + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b }, + }, + { + { 0x00, 0x78, 0xf0, 0x88, 0xfd, 0x85, 0x0d, 0x75, 0xe7, 0x9f, 0x17, 0x6f, 0x1a, 0x62, 0xea, 0x92 }, + { 0x00, 0xd3, 0xbb, 0x68, 0x6b, 0xb8, 0xd0, 0x03, 0xd6, 0x05, 0x6d, 0xbe, 0xbd, 0x6e, 0x06, 0xd5 }, + }, + { + { 0x00, 0xa5, 0x57, 0xf2, 0xae, 0x0b, 0xf9, 0x5c, 0x41, 0xe4, 0x16, 0xb3, 0xef, 0x4a, 0xb8, 0x1d }, + { 0x00, 0x82, 0x19, 0x9b, 0x32, 0xb0, 0x2b, 0xa9, 0x64, 0xe6, 0x7d, 0xff, 0x56, 0xd4, 0x4f, 0xcd }, + }, + { + { 0x00, 0xef, 0xc3, 0x2c, 0x9b, 0x74, 0x58, 0xb7, 0x2b, 0xc4, 0xe8, 0x07, 0xb0, 0x5f, 0x73, 0x9c }, + { 0x00, 0x56, 0xac, 0xfa, 0x45, 0x13, 0xe9, 0xbf, 0x8a, 0xdc, 0x26, 0x70, 0xcf, 0x99, 0x63, 0x35 }, + }, + }, + { + { + { 0x00, 0x50, 0xa0, 0xf0, 0x5d, 0x0d, 0xfd, 0xad, 0xba, 0xea, 0x1a, 0x4a, 0xe7, 0xb7, 0x47, 0x17 }, + { 0x00, 0x69, 0xd2, 0xbb, 0xb9, 0xd0, 0x6b, 0x02, 0x6f, 0x06, 0xbd, 0xd4, 0xd6, 0xbf, 0x04, 0x6d }, + }, + { + { 0x00, 0x4c, 0x98, 0xd4, 0x2d, 0x61, 0xb5, 0xf9, 0x5a, 0x16, 0xc2, 0x8e, 0x77, 0x3b, 0xef, 0xa3 }, + { 0x00, 0xb4, 0x75, 0xc1, 0xea, 0x5e, 0x9f, 0x2b, 0xc9, 0x7d, 0xbc, 0x08, 0x23, 0x97, 0x56, 0xe2 }, + }, + { + { 0x00, 0x6b, 0xd6, 0xbd, 0xb1, 0xda, 0x67, 0x0c, 0x7f, 0x14, 0xa9, 0xc2, 0xce, 0xa5, 0x18, 0x73 }, + { 0x00, 0xfe, 0xe1, 0x1f, 0xdf, 0x21, 0x3e, 0xc0, 0xa3, 0x5d, 0x42, 0xbc, 0x7c, 0x82, 0x9d, 0x63 }, + }, + { + { 0x00, 0xe7, 0xd3, 0x34, 0xbb, 0x5c, 0x68, 0x8f, 0x6b, 0x8c, 0xb8, 0x5f, 0xd0, 0x37, 0x03, 0xe4 }, + { 0x00, 0xd6, 0xb1, 0x67, 0x7f, 0xa9, 0xce, 0x18, 0xfe, 0x28, 0x4f, 0x99, 0x81, 0x57, 0x30, 0xe6 }, + }, + }, + { + { + { 0x00, 0x83, 0x1b, 0x98, 0x36, 0xb5, 0x2d, 0xae, 0x6c, 0xef, 0x77, 0xf4, 0x5a, 0xd9, 0x41, 0xc2 }, + { 0x00, 0xd8, 0xad, 0x75, 0x47, 0x9f, 0xea, 0x32, 0x8e, 0x56, 0x23, 0xfb, 0xc9, 0x11, 0x64, 0xbc }, + }, + { + { 0x00, 0x7e, 0xfc, 0x82, 0xe5, 0x9b, 0x19, 0x67, 0xd7, 0xa9, 0x2b, 0x55, 0x32, 0x4c, 0xce, 0xb0 }, + { 0x00, 0xb3, 0x7b, 0xc8, 0xf6, 0x45, 0x8d, 0x3e, 0xf1, 0x42, 0x8a, 0x39, 0x07, 0xb4, 0x7c, 0xcf }, + }, + { + { 0x00, 0xa7, 0x53, 0xf4, 0xa6, 0x01, 0xf5, 0x52, 0x51, 0xf6, 0x02, 0xa5, 0xf7, 0x50, 0xa4, 0x03 }, + { 0x00, 0xa2, 0x59, 0xfb, 0xb2, 0x10, 0xeb, 0x49, 0x79, 0xdb, 0x20, 0x82, 0xcb, 0x69, 0x92, 0x30 }, + }, + { + { 0x00, 0x6f, 0xde, 0xb1, 0xa1, 0xce, 0x7f, 0x10, 0x5f, 0x30, 0x81, 0xee, 0xfe, 0x91, 0x20, 0x4f }, + { 0x00, 0xbe, 0x61, 0xdf, 0xc2, 0x7c, 0xa3, 0x1d, 0x99, 0x27, 0xf8, 0x46, 0x5b, 0xe5, 0x3a, 0x84 }, + }, + }, + { + { + { 0x00, 0x54, 0xa8, 0xfc, 0x4d, 0x19, 0xe5, 0xb1, 0x9a, 0xce, 0x32, 0x66, 0xd7, 0x83, 0x7f, 0x2b }, + { 0x00, 0x29, 0x52, 0x7b, 0xa4, 0x8d, 0xf6, 0xdf, 0x55, 0x7c, 0x07, 0x2e, 0xf1, 0xd8, 0xa3, 0x8a }, + }, + { + { 0x00, 0x27, 0x4e, 0x69, 0x9c, 0xbb, 0xd2, 0xf5, 0x25, 0x02, 0x6b, 0x4c, 0xb9, 0x9e, 0xf7, 0xd0 }, + { 0x00, 0x4a, 0x94, 0xde, 0x35, 0x7f, 0xa1, 0xeb, 0x6a, 0x20, 0xfe, 0xb4, 0x5f, 0x15, 0xcb, 0x81 }, + }, + { + { 0x00, 0x37, 0x6e, 0x59, 0xdc, 0xeb, 0xb2, 0x85, 0xa5, 0x92, 0xcb, 0xfc, 0x79, 0x4e, 0x17, 0x20 }, + { 0x00, 0x57, 0xae, 0xf9, 0x41, 0x16, 0xef, 0xb8, 0x82, 0xd5, 0x2c, 0x7b, 0xc3, 0x94, 0x6d, 0x3a }, + }, + { + { 0x00, 0x0a, 0x14, 0x1e, 0x28, 0x22, 0x3c, 0x36, 0x50, 0x5a, 0x44, 0x4e, 0x78, 0x72, 0x6c, 0x66 }, + { 0x00, 0xa0, 0x5d, 0xfd, 0xba, 0x1a, 0xe7, 0x47, 0x69, 0xc9, 0x34, 0x94, 0xd3, 0x73, 0x8e, 0x2e }, + }, + }, + { + { + { 0x00, 0x3a, 0x74, 0x4e, 0xe8, 0xd2, 0x9c, 0xa6, 0xcd, 0xf7, 0xb9, 0x83, 0x25, 0x1f, 0x51, 0x6b }, + { 0x00, 0x87, 0x13, 0x94, 0x26, 0xa1, 0x35, 0xb2, 0x4c, 0xcb, 0x5f, 0xd8, 0x6a, 0xed, 0x79, 0xfe }, + }, + { + { 0x00, 0x87, 0x13, 0x94, 0x26, 0xa1, 0x35, 0xb2, 0x4c, 0xcb, 0x5f, 0xd8, 0x6a, 0xed, 0x79, 0xfe }, + { 0x00, 0x98, 0x2d, 0xb5, 0x5a, 0xc2, 0x77, 0xef, 0xb4, 0x2c, 0x99, 0x01, 0xee, 0x76, 0xc3, 0x5b }, + }, + { + { 0x00, 0xff, 0xe3, 0x1c, 0xdb, 0x24, 0x38, 0xc7, 0xab, 0x54, 0x48, 0xb7, 0x70, 0x8f, 0x93, 0x6c }, + { 0x00, 0x4b, 0x96, 0xdd, 0x31, 0x7a, 0xa7, 0xec, 0x62, 0x29, 0xf4, 0xbf, 0x53, 0x18, 0xc5, 0x8e }, + }, + { + { 0x00, 0x60, 0xc0, 0xa0, 0x9d, 0xfd, 0x5d, 0x3d, 0x27, 0x47, 0xe7, 0x87, 0xba, 0xda, 0x7a, 0x1a }, + { 0x00, 0x4e, 0x9c, 0xd2, 0x25, 0x6b, 0xb9, 0xf7, 0x4a, 0x04, 0xd6, 0x98, 0x6f, 0x21, 0xf3, 0xbd }, + }, + }, + { + { + { 0x00, 0xfa, 0xe9, 0x13, 0xcf, 0x35, 0x26, 0xdc, 0x83, 0x79, 0x6a, 0x90, 0x4c, 0xb6, 0xa5, 0x5f }, + { 0x00, 0x1b, 0x36, 0x2d, 0x6c, 0x77, 0x5a, 0x41, 0xd8, 0xc3, 0xee, 0xf5, 0xb4, 0xaf, 0x82, 0x99 }, + }, + { + { 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78 }, + { 0x00, 0x80, 0x1d, 0x9d, 0x3a, 0xba, 0x27, 0xa7, 0x74, 0xf4, 0x69, 0xe9, 0x4e, 0xce, 0x53, 0xd3 }, + }, + { + { 0x00, 0x39, 0x72, 0x4b, 0xe4, 0xdd, 0x96, 0xaf, 0xd5, 0xec, 0xa7, 0x9e, 0x31, 0x08, 0x43, 0x7a }, + { 0x00, 0xb7, 0x73, 0xc4, 0xe6, 0x51, 0x95, 0x22, 0xd1, 0x66, 0xa2, 0x15, 0x37, 0x80, 0x44, 0xf3 }, + }, + { + { 0x00, 0xd7, 0xb3, 0x64, 0x7b, 0xac, 0xc8, 0x1f, 0xf6, 0x21, 0x45, 0x92, 0x8d, 0x5a, 0x3e, 0xe9 }, + { 0x00, 0xf1, 0xff, 0x0e, 0xe3, 0x12, 0x1c, 0xed, 0xdb, 0x2a, 0x24, 0xd5, 0x38, 0xc9, 0xc7, 0x36 }, + }, + }, + { + { + { 0x00, 0xfb, 0xeb, 0x10, 0xcb, 0x30, 0x20, 0xdb, 0x8b, 0x70, 0x60, 0x9b, 0x40, 0xbb, 0xab, 0x50 }, + { 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69 }, + }, + { + { 0x00, 0x8b, 0x0b, 0x80, 0x16, 0x9d, 0x1d, 0x96, 0x2c, 0xa7, 0x27, 0xac, 0x3a, 0xb1, 0x31, 0xba }, + { 0x00, 0x58, 0xb0, 0xe8, 0x7d, 0x25, 0xcd, 0x95, 0xfa, 0xa2, 0x4a, 0x12, 0x87, 0xdf, 0x37, 0x6f }, + }, + { + { 0x00, 0x35, 0x6a, 0x5f, 0xd4, 0xe1, 0xbe, 0x8b, 0xb5, 0x80, 0xdf, 0xea, 0x61, 0x54, 0x0b, 0x3e }, + { 0x00, 0x77, 0xee, 0x99, 0xc1, 0xb6, 0x2f, 0x58, 0x9f, 0xe8, 0x71, 0x06, 0x5e, 0x29, 0xb0, 0xc7 }, + }, + { + { 0x00, 0xb7, 0x73, 0xc4, 0xe6, 0x51, 0x95, 0x22, 0xd1, 0x66, 0xa2, 0x15, 0x37, 0x80, 0x44, 0xf3 }, + { 0x00, 0xbf, 0x63, 0xdc, 0xc6, 0x79, 0xa5, 0x1a, 0x91, 0x2e, 0xf2, 0x4d, 0x57, 0xe8, 0x34, 0x8b }, + }, + }, + { + { + { 0x00, 0xf2, 0xf9, 0x0b, 0xef, 0x1d, 0x16, 0xe4, 0xc3, 0x31, 0x3a, 0xc8, 0x2c, 0xde, 0xd5, 0x27 }, + { 0x00, 0x9b, 0x2b, 0xb0, 0x56, 0xcd, 0x7d, 0xe6, 0xac, 0x37, 0x87, 0x1c, 0xfa, 0x61, 0xd1, 0x4a }, + }, + { + { 0x00, 0xec, 0xc5, 0x29, 0x97, 0x7b, 0x52, 0xbe, 0x33, 0xdf, 0xf6, 0x1a, 0xa4, 0x48, 0x61, 0x8d }, + { 0x00, 0x66, 0xcc, 0xaa, 0x85, 0xe3, 0x49, 0x2f, 0x17, 0x71, 0xdb, 0xbd, 0x92, 0xf4, 0x5e, 0x38 }, + }, + { + { 0x00, 0x0c, 0x18, 0x14, 0x30, 0x3c, 0x28, 0x24, 0x60, 0x6c, 0x78, 0x74, 0x50, 0x5c, 0x48, 0x44 }, + { 0x00, 0xc0, 0x9d, 0x5d, 0x27, 0xe7, 0xba, 0x7a, 0x4e, 0x8e, 0xd3, 0x13, 0x69, 0xa9, 0xf4, 0x34 }, + }, + { + { 0x00, 0x83, 0x1b, 0x98, 0x36, 0xb5, 0x2d, 0xae, 0x6c, 0xef, 0x77, 0xf4, 0x5a, 0xd9, 0x41, 0xc2 }, + { 0x00, 0xd8, 0xad, 0x75, 0x47, 0x9f, 0xea, 0x32, 0x8e, 0x56, 0x23, 0xfb, 0xc9, 0x11, 0x64, 0xbc }, + }, + }, + { + { + { 0x00, 0x43, 0x86, 0xc5, 0x11, 0x52, 0x97, 0xd4, 0x22, 0x61, 0xa4, 0xe7, 0x33, 0x70, 0xb5, 0xf6 }, + { 0x00, 0x44, 0x88, 0xcc, 0x0d, 0x49, 0x85, 0xc1, 0x1a, 0x5e, 0x92, 0xd6, 0x17, 0x53, 0x9f, 0xdb }, + }, + { + { 0x00, 0x67, 0xce, 0xa9, 0x81, 0xe6, 0x4f, 0x28, 0x1f, 0x78, 0xd1, 0xb6, 0x9e, 0xf9, 0x50, 0x37 }, + { 0x00, 0x3e, 0x7c, 0x42, 0xf8, 0xc6, 0x84, 0xba, 0xed, 0xd3, 0x91, 0xaf, 0x15, 0x2b, 0x69, 0x57 }, + }, + { + { 0x00, 0xf8, 0xed, 0x15, 0xc7, 0x3f, 0x2a, 0xd2, 0x93, 0x6b, 0x7e, 0x86, 0x54, 0xac, 0xb9, 0x41 }, + { 0x00, 0x3b, 0x76, 0x4d, 0xec, 0xd7, 0x9a, 0xa1, 0xc5, 0xfe, 0xb3, 0x88, 0x29, 0x12, 0x5f, 0x64 }, + }, + { + { 0x00, 0x92, 0x39, 0xab, 0x72, 0xe0, 0x4b, 0xd9, 0xe4, 0x76, 0xdd, 0x4f, 0x96, 0x04, 0xaf, 0x3d }, + { 0x00, 0xd5, 0xb7, 0x62, 0x73, 0xa6, 0xc4, 0x11, 0xe6, 0x33, 0x51, 0x84, 0x95, 0x40, 0x22, 0xf7 }, + }, + }, + { + { + { 0x00, 0xb1, 0x7f, 0xce, 0xfe, 0x4f, 0x81, 0x30, 0xe1, 0x50, 0x9e, 0x2f, 0x1f, 0xae, 0x60, 0xd1 }, + { 0x00, 0xdf, 0xa3, 0x7c, 0x5b, 0x84, 0xf8, 0x27, 0xb6, 0x69, 0x15, 0xca, 0xed, 0x32, 0x4e, 0x91 }, + }, + { + { 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a }, + { 0x00, 0xe0, 0xdd, 0x3d, 0xa7, 0x47, 0x7a, 0x9a, 0x53, 0xb3, 0x8e, 0x6e, 0xf4, 0x14, 0x29, 0xc9 }, + }, + { + { 0x00, 0xea, 0xc9, 0x23, 0x8f, 0x65, 0x46, 0xac, 0x03, 0xe9, 0xca, 0x20, 0x8c, 0x66, 0x45, 0xaf }, + { 0x00, 0x06, 0x0c, 0x0a, 0x18, 0x1e, 0x14, 0x12, 0x30, 0x36, 0x3c, 0x3a, 0x28, 0x2e, 0x24, 0x22 }, + }, + { + { 0x00, 0xe2, 0xd9, 0x3b, 0xaf, 0x4d, 0x76, 0x94, 0x43, 0xa1, 0x9a, 0x78, 0xec, 0x0e, 0x35, 0xd7 }, + { 0x00, 0x86, 0x11, 0x97, 0x22, 0xa4, 0x33, 0xb5, 0x44, 0xc2, 0x55, 0xd3, 0x66, 0xe0, 0x77, 0xf1 }, + }, + }, + { + { + { 0x00, 0xff, 0xe3, 0x1c, 0xdb, 0x24, 0x38, 0xc7, 0xab, 0x54, 0x48, 0xb7, 0x70, 0x8f, 0x93, 0x6c }, + { 0x00, 0x4b, 0x96, 0xdd, 0x31, 0x7a, 0xa7, 0xec, 0x62, 0x29, 0xf4, 0xbf, 0x53, 0x18, 0xc5, 0x8e }, + }, + { + { 0x00, 0x1a, 0x34, 0x2e, 0x68, 0x72, 0x5c, 0x46, 0xd0, 0xca, 0xe4, 0xfe, 0xb8, 0xa2, 0x8c, 0x96 }, + { 0x00, 0xbd, 0x67, 0xda, 0xce, 0x73, 0xa9, 0x14, 0x81, 0x3c, 0xe6, 0x5b, 0x4f, 0xf2, 0x28, 0x95 }, + }, + { + { 0x00, 0x56, 0xac, 0xfa, 0x45, 0x13, 0xe9, 0xbf, 0x8a, 0xdc, 0x26, 0x70, 0xcf, 0x99, 0x63, 0x35 }, + { 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77 }, + }, + { + { 0x00, 0xaf, 0x43, 0xec, 0x86, 0x29, 0xc5, 0x6a, 0x11, 0xbe, 0x52, 0xfd, 0x97, 0x38, 0xd4, 0x7b }, + { 0x00, 0x22, 0x44, 0x66, 0x88, 0xaa, 0xcc, 0xee, 0x0d, 0x2f, 0x49, 0x6b, 0x85, 0xa7, 0xc1, 0xe3 }, + }, + }, + { + { + { 0x00, 0xe7, 0xd3, 0x34, 0xbb, 0x5c, 0x68, 0x8f, 0x6b, 0x8c, 0xb8, 0x5f, 0xd0, 0x37, 0x03, 0xe4 }, + { 0x00, 0xd6, 0xb1, 0x67, 0x7f, 0xa9, 0xce, 0x18, 0xfe, 0x28, 0x4f, 0x99, 0x81, 0x57, 0x30, 0xe6 }, + }, + { + { 0x00, 0x23, 0x46, 0x65, 0x8c, 0xaf, 0xca, 0xe9, 0x05, 0x26, 0x43, 0x60, 0x89, 0xaa, 0xcf, 0xec }, + { 0x00, 0x0a, 0x14, 0x1e, 0x28, 0x22, 0x3c, 0x36, 0x50, 0x5a, 0x44, 0x4e, 0x78, 0x72, 0x6c, 0x66 }, + }, + { + { 0x00, 0x45, 0x8a, 0xcf, 0x09, 0x4c, 0x83, 0xc6, 0x12, 0x57, 0x98, 0xdd, 0x1b, 0x5e, 0x91, 0xd4 }, + { 0x00, 0x24, 0x48, 0x6c, 0x90, 0xb4, 0xd8, 0xfc, 0x3d, 0x19, 0x75, 0x51, 0xad, 0x89, 0xe5, 0xc1 }, + }, + { + { 0x00, 0x72, 0xe4, 0x96, 0xd5, 0xa7, 0x31, 0x43, 0xb7, 0xc5, 0x53, 0x21, 0x62, 0x10, 0x86, 0xf4 }, + { 0x00, 0x73, 0xe6, 0x95, 0xd1, 0xa2, 0x37, 0x44, 0xbf, 0xcc, 0x59, 0x2a, 0x6e, 0x1d, 0x88, 0xfb }, + }, + }, + { + { + { 0x00, 0xc9, 0x8f, 0x46, 0x03, 0xca, 0x8c, 0x45, 0x06, 0xcf, 0x89, 0x40, 0x05, 0xcc, 0x8a, 0x43 }, + { 0x00, 0x0c, 0x18, 0x14, 0x30, 0x3c, 0x28, 0x24, 0x60, 0x6c, 0x78, 0x74, 0x50, 0x5c, 0x48, 0x44 }, + }, + { + { 0x00, 0x8c, 0x05, 0x89, 0x0a, 0x86, 0x0f, 0x83, 0x14, 0x98, 0x11, 0x9d, 0x1e, 0x92, 0x1b, 0x97 }, + { 0x00, 0x28, 0x50, 0x78, 0xa0, 0x88, 0xf0, 0xd8, 0x5d, 0x75, 0x0d, 0x25, 0xfd, 0xd5, 0xad, 0x85 }, + }, + { + { 0x00, 0x8f, 0x03, 0x8c, 0x06, 0x89, 0x05, 0x8a, 0x0c, 0x83, 0x0f, 0x80, 0x0a, 0x85, 0x09, 0x86 }, + { 0x00, 0x18, 0x30, 0x28, 0x60, 0x78, 0x50, 0x48, 0xc0, 0xd8, 0xf0, 0xe8, 0xa0, 0xb8, 0x90, 0x88 }, + }, + { + { 0x00, 0xf8, 0xed, 0x15, 0xc7, 0x3f, 0x2a, 0xd2, 0x93, 0x6b, 0x7e, 0x86, 0x54, 0xac, 0xb9, 0x41 }, + { 0x00, 0x3b, 0x76, 0x4d, 0xec, 0xd7, 0x9a, 0xa1, 0xc5, 0xfe, 0xb3, 0x88, 0x29, 0x12, 0x5f, 0x64 }, + }, + }, + { + { + { 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11 }, + { 0x00, 0x30, 0x60, 0x50, 0xc0, 0xf0, 0xa0, 0x90, 0x9d, 0xad, 0xfd, 0xcd, 0x5d, 0x6d, 0x3d, 0x0d }, + }, + { + { 0x00, 0x68, 0xd0, 0xb8, 0xbd, 0xd5, 0x6d, 0x05, 0x67, 0x0f, 0xb7, 0xdf, 0xda, 0xb2, 0x0a, 0x62 }, + { 0x00, 0xce, 0x81, 0x4f, 0x1f, 0xd1, 0x9e, 0x50, 0x3e, 0xf0, 0xbf, 0x71, 0x21, 0xef, 0xa0, 0x6e }, + }, + { + { 0x00, 0x2c, 0x58, 0x74, 0xb0, 0x9c, 0xe8, 0xc4, 0x7d, 0x51, 0x25, 0x09, 0xcd, 0xe1, 0x95, 0xb9 }, + { 0x00, 0xfa, 0xe9, 0x13, 0xcf, 0x35, 0x26, 0xdc, 0x83, 0x79, 0x6a, 0x90, 0x4c, 0xb6, 0xa5, 0x5f }, + }, + { + { 0x00, 0xb1, 0x7f, 0xce, 0xfe, 0x4f, 0x81, 0x30, 0xe1, 0x50, 0x9e, 0x2f, 0x1f, 0xae, 0x60, 0xd1 }, + { 0x00, 0xdf, 0xa3, 0x7c, 0x5b, 0x84, 0xf8, 0x27, 0xb6, 0x69, 0x15, 0xca, 0xed, 0x32, 0x4e, 0x91 }, + }, + }, + { + { + { 0x00, 0xbb, 0x6b, 0xd0, 0xd6, 0x6d, 0xbd, 0x06, 0xb1, 0x0a, 0xda, 0x61, 0x67, 0xdc, 0x0c, 0xb7 }, + { 0x00, 0x7f, 0xfe, 0x81, 0xe1, 0x9e, 0x1f, 0x60, 0xdf, 0xa0, 0x21, 0x5e, 0x3e, 0x41, 0xc0, 0xbf }, + }, + { + { 0x00, 0x99, 0x2f, 0xb6, 0x5e, 0xc7, 0x71, 0xe8, 0xbc, 0x25, 0x93, 0x0a, 0xe2, 0x7b, 0xcd, 0x54 }, + { 0x00, 0x65, 0xca, 0xaf, 0x89, 0xec, 0x43, 0x26, 0x0f, 0x6a, 0xc5, 0xa0, 0x86, 0xe3, 0x4c, 0x29 }, + }, + { + { 0x00, 0x59, 0xb2, 0xeb, 0x79, 0x20, 0xcb, 0x92, 0xf2, 0xab, 0x40, 0x19, 0x8b, 0xd2, 0x39, 0x60 }, + { 0x00, 0xf9, 0xef, 0x16, 0xc3, 0x3a, 0x2c, 0xd5, 0x9b, 0x62, 0x74, 0x8d, 0x58, 0xa1, 0xb7, 0x4e }, + }, + { + { 0x00, 0x50, 0xa0, 0xf0, 0x5d, 0x0d, 0xfd, 0xad, 0xba, 0xea, 0x1a, 0x4a, 0xe7, 0xb7, 0x47, 0x17 }, + { 0x00, 0x69, 0xd2, 0xbb, 0xb9, 0xd0, 0x6b, 0x02, 0x6f, 0x06, 0xbd, 0xd4, 0xd6, 0xbf, 0x04, 0x6d }, + }, + }, + { + { + { 0x00, 0xee, 0xc1, 0x2f, 0x9f, 0x71, 0x5e, 0xb0, 0x23, 0xcd, 0xe2, 0x0c, 0xbc, 0x52, 0x7d, 0x93 }, + { 0x00, 0x46, 0x8c, 0xca, 0x05, 0x43, 0x89, 0xcf, 0x0a, 0x4c, 0x86, 0xc0, 0x0f, 0x49, 0x83, 0xc5 }, + }, + { + { 0x00, 0x94, 0x35, 0xa1, 0x6a, 0xfe, 0x5f, 0xcb, 0xd4, 0x40, 0xe1, 0x75, 0xbe, 0x2a, 0x8b, 0x1f }, + { 0x00, 0xb5, 0x77, 0xc2, 0xee, 0x5b, 0x99, 0x2c, 0xc1, 0x74, 0xb6, 0x03, 0x2f, 0x9a, 0x58, 0xed }, + }, + { + { 0x00, 0xab, 0x4b, 0xe0, 0x96, 0x3d, 0xdd, 0x76, 0x31, 0x9a, 0x7a, 0xd1, 0xa7, 0x0c, 0xec, 0x47 }, + { 0x00, 0x62, 0xc4, 0xa6, 0x95, 0xf7, 0x51, 0x33, 0x37, 0x55, 0xf3, 0x91, 0xa2, 0xc0, 0x66, 0x04 }, + }, + { + { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0 }, + { 0x00, 0x1d, 0x3a, 0x27, 0x74, 0x69, 0x4e, 0x53, 0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb }, + }, + }, + { + { + { 0x00, 0x13, 0x26, 0x35, 0x4c, 0x5f, 0x6a, 0x79, 0x98, 0x8b, 0xbe, 0xad, 0xd4, 0xc7, 0xf2, 0xe1 }, + { 0x00, 0x2d, 0x5a, 0x77, 0xb4, 0x99, 0xee, 0xc3, 0x75, 0x58, 0x2f, 0x02, 0xc1, 0xec, 0x9b, 0xb6 }, + }, + { + { 0x00, 0x40, 0x80, 0xc0, 0x1d, 0x5d, 0x9d, 0xdd, 0x3a, 0x7a, 0xba, 0xfa, 0x27, 0x67, 0xa7, 0xe7 }, + { 0x00, 0x74, 0xe8, 0x9c, 0xcd, 0xb9, 0x25, 0x51, 0x87, 0xf3, 0x6f, 0x1b, 0x4a, 0x3e, 0xa2, 0xd6 }, + }, + { + { 0x00, 0x85, 0x17, 0x92, 0x2e, 0xab, 0x39, 0xbc, 0x5c, 0xd9, 0x4b, 0xce, 0x72, 0xf7, 0x65, 0xe0 }, + { 0x00, 0xb8, 0x6d, 0xd5, 0xda, 0x62, 0xb7, 0x0f, 0xa9, 0x11, 0xc4, 0x7c, 0x73, 0xcb, 0x1e, 0xa6 }, + }, + { + { 0x00, 0xce, 0x81, 0x4f, 0x1f, 0xd1, 0x9e, 0x50, 0x3e, 0xf0, 0xbf, 0x71, 0x21, 0xef, 0xa0, 0x6e }, + { 0x00, 0x7c, 0xf8, 0x84, 0xed, 0x91, 0x15, 0x69, 0xc7, 0xbb, 0x3f, 0x43, 0x2a, 0x56, 0xd2, 0xae }, + }, + }, + { + { + { 0x00, 0x8b, 0x0b, 0x80, 0x16, 0x9d, 0x1d, 0x96, 0x2c, 0xa7, 0x27, 0xac, 0x3a, 0xb1, 0x31, 0xba }, + { 0x00, 0x58, 0xb0, 0xe8, 0x7d, 0x25, 0xcd, 0x95, 0xfa, 0xa2, 0x4a, 0x12, 0x87, 0xdf, 0x37, 0x6f }, + }, + { + { 0x00, 0xb2, 0x79, 0xcb, 0xf2, 0x40, 0x8b, 0x39, 0xf9, 0x4b, 0x80, 0x32, 0x0b, 0xb9, 0x72, 0xc0 }, + { 0x00, 0xef, 0xc3, 0x2c, 0x9b, 0x74, 0x58, 0xb7, 0x2b, 0xc4, 0xe8, 0x07, 0xb0, 0x5f, 0x73, 0x9c }, + }, + { + { 0x00, 0xeb, 0xcb, 0x20, 0x8b, 0x60, 0x40, 0xab, 0x0b, 0xe0, 0xc0, 0x2b, 0x80, 0x6b, 0x4b, 0xa0 }, + { 0x00, 0x16, 0x2c, 0x3a, 0x58, 0x4e, 0x74, 0x62, 0xb0, 0xa6, 0x9c, 0x8a, 0xe8, 0xfe, 0xc4, 0xd2 }, + }, + { + { 0x00, 0x18, 0x30, 0x28, 0x60, 0x78, 0x50, 0x48, 0xc0, 0xd8, 0xf0, 0xe8, 0xa0, 0xb8, 0x90, 0x88 }, + { 0x00, 0x9d, 0x27, 0xba, 0x4e, 0xd3, 0x69, 0xf4, 0x9c, 0x01, 0xbb, 0x26, 0xd2, 0x4f, 0xf5, 0x68 }, + }, + }, + { + { + { 0x00, 0xdc, 0xa5, 0x79, 0x57, 0x8b, 0xf2, 0x2e, 0xae, 0x72, 0x0b, 0xd7, 0xf9, 0x25, 0x5c, 0x80 }, + { 0x00, 0x41, 0x82, 0xc3, 0x19, 0x58, 0x9b, 0xda, 0x32, 0x73, 0xb0, 0xf1, 0x2b, 0x6a, 0xa9, 0xe8 }, + }, + { + { 0x00, 0xa1, 0x5f, 0xfe, 0xbe, 0x1f, 0xe1, 0x40, 0x61, 0xc0, 0x3e, 0x9f, 0xdf, 0x7e, 0x80, 0x21 }, + { 0x00, 0xc2, 0x99, 0x5b, 0x2f, 0xed, 0xb6, 0x74, 0x5e, 0x9c, 0xc7, 0x05, 0x71, 0xb3, 0xe8, 0x2a }, + }, + { + { 0x00, 0x49, 0x92, 0xdb, 0x39, 0x70, 0xab, 0xe2, 0x72, 0x3b, 0xe0, 0xa9, 0x4b, 0x02, 0xd9, 0x90 }, + { 0x00, 0xe4, 0xd5, 0x31, 0xb7, 0x53, 0x62, 0x86, 0x73, 0x97, 0xa6, 0x42, 0xc4, 0x20, 0x11, 0xf5 }, + }, + { + { 0x00, 0x53, 0xa6, 0xf5, 0x51, 0x02, 0xf7, 0xa4, 0xa2, 0xf1, 0x04, 0x57, 0xf3, 0xa0, 0x55, 0x06 }, + { 0x00, 0x59, 0xb2, 0xeb, 0x79, 0x20, 0xcb, 0x92, 0xf2, 0xab, 0x40, 0x19, 0x8b, 0xd2, 0x39, 0x60 }, + }, + }, + { + { + { 0x00, 0x35, 0x6a, 0x5f, 0xd4, 0xe1, 0xbe, 0x8b, 0xb5, 0x80, 0xdf, 0xea, 0x61, 0x54, 0x0b, 0x3e }, + { 0x00, 0x77, 0xee, 0x99, 0xc1, 0xb6, 0x2f, 0x58, 0x9f, 0xe8, 0x71, 0x06, 0x5e, 0x29, 0xb0, 0xc7 }, + }, + { + { 0x00, 0xeb, 0xcb, 0x20, 0x8b, 0x60, 0x40, 0xab, 0x0b, 0xe0, 0xc0, 0x2b, 0x80, 0x6b, 0x4b, 0xa0 }, + { 0x00, 0x16, 0x2c, 0x3a, 0x58, 0x4e, 0x74, 0x62, 0xb0, 0xa6, 0x9c, 0x8a, 0xe8, 0xfe, 0xc4, 0xd2 }, + }, + { + { 0x00, 0x0f, 0x1e, 0x11, 0x3c, 0x33, 0x22, 0x2d, 0x78, 0x77, 0x66, 0x69, 0x44, 0x4b, 0x5a, 0x55 }, + { 0x00, 0xf0, 0xfd, 0x0d, 0xe7, 0x17, 0x1a, 0xea, 0xd3, 0x23, 0x2e, 0xde, 0x34, 0xc4, 0xc9, 0x39 }, + }, + { + { 0x00, 0xa1, 0x5f, 0xfe, 0xbe, 0x1f, 0xe1, 0x40, 0x61, 0xc0, 0x3e, 0x9f, 0xdf, 0x7e, 0x80, 0x21 }, + { 0x00, 0xc2, 0x99, 0x5b, 0x2f, 0xed, 0xb6, 0x74, 0x5e, 0x9c, 0xc7, 0x05, 0x71, 0xb3, 0xe8, 0x2a }, + }, + }, + { + { + { 0x00, 0xb2, 0x79, 0xcb, 0xf2, 0x40, 0x8b, 0x39, 0xf9, 0x4b, 0x80, 0x32, 0x0b, 0xb9, 0x72, 0xc0 }, + { 0x00, 0xef, 0xc3, 0x2c, 0x9b, 0x74, 0x58, 0xb7, 0x2b, 0xc4, 0xe8, 0x07, 0xb0, 0x5f, 0x73, 0x9c }, + }, + { + { 0x00, 0xb7, 0x73, 0xc4, 0xe6, 0x51, 0x95, 0x22, 0xd1, 0x66, 0xa2, 0x15, 0x37, 0x80, 0x44, 0xf3 }, + { 0x00, 0xbf, 0x63, 0xdc, 0xc6, 0x79, 0xa5, 0x1a, 0x91, 0x2e, 0xf2, 0x4d, 0x57, 0xe8, 0x34, 0x8b }, + }, + { + { 0x00, 0xdc, 0xa5, 0x79, 0x57, 0x8b, 0xf2, 0x2e, 0xae, 0x72, 0x0b, 0xd7, 0xf9, 0x25, 0x5c, 0x80 }, + { 0x00, 0x41, 0x82, 0xc3, 0x19, 0x58, 0x9b, 0xda, 0x32, 0x73, 0xb0, 0xf1, 0x2b, 0x6a, 0xa9, 0xe8 }, + }, + { + { 0x00, 0xcc, 0x85, 0x49, 0x17, 0xdb, 0x92, 0x5e, 0x2e, 0xe2, 0xab, 0x67, 0x39, 0xf5, 0xbc, 0x70 }, + { 0x00, 0x5c, 0xb8, 0xe4, 0x6d, 0x31, 0xd5, 0x89, 0xda, 0x86, 0x62, 0x3e, 0xb7, 0xeb, 0x0f, 0x53 }, + }, + }, + { + { + { 0x00, 0xda, 0xa9, 0x73, 0x4f, 0x95, 0xe6, 0x3c, 0x9e, 0x44, 0x37, 0xed, 0xd1, 0x0b, 0x78, 0xa2 }, + { 0x00, 0x21, 0x42, 0x63, 0x84, 0xa5, 0xc6, 0xe7, 0x15, 0x34, 0x57, 0x76, 0x91, 0xb0, 0xd3, 0xf2 }, + }, + { + { 0x00, 0x26, 0x4c, 0x6a, 0x98, 0xbe, 0xd4, 0xf2, 0x2d, 0x0b, 0x61, 0x47, 0xb5, 0x93, 0xf9, 0xdf }, + { 0x00, 0x5a, 0xb4, 0xee, 0x75, 0x2f, 0xc1, 0x9b, 0xea, 0xb0, 0x5e, 0x04, 0x9f, 0xc5, 0x2b, 0x71 }, + }, + { + { 0x00, 0xd8, 0xad, 0x75, 0x47, 0x9f, 0xea, 0x32, 0x8e, 0x56, 0x23, 0xfb, 0xc9, 0x11, 0x64, 0xbc }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + }, + { + { 0x00, 0xad, 0x47, 0xea, 0x8e, 0x23, 0xc9, 0x64, 0x01, 0xac, 0x46, 0xeb, 0x8f, 0x22, 0xc8, 0x65 }, + { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e }, + }, + }, + { + { + { 0x00, 0xcf, 0x83, 0x4c, 0x1b, 0xd4, 0x98, 0x57, 0x36, 0xf9, 0xb5, 0x7a, 0x2d, 0xe2, 0xae, 0x61 }, + { 0x00, 0x6c, 0xd8, 0xb4, 0xad, 0xc1, 0x75, 0x19, 0x47, 0x2b, 0x9f, 0xf3, 0xea, 0x86, 0x32, 0x5e }, + }, + { + { 0x00, 0xf0, 0xfd, 0x0d, 0xe7, 0x17, 0x1a, 0xea, 0xd3, 0x23, 0x2e, 0xde, 0x34, 0xc4, 0xc9, 0x39 }, + { 0x00, 0xbb, 0x6b, 0xd0, 0xd6, 0x6d, 0xbd, 0x06, 0xb1, 0x0a, 0xda, 0x61, 0x67, 0xdc, 0x0c, 0xb7 }, + }, + { + { 0x00, 0x76, 0xec, 0x9a, 0xc5, 0xb3, 0x29, 0x5f, 0x97, 0xe1, 0x7b, 0x0d, 0x52, 0x24, 0xbe, 0xc8 }, + { 0x00, 0x33, 0x66, 0x55, 0xcc, 0xff, 0xaa, 0x99, 0x85, 0xb6, 0xe3, 0xd0, 0x49, 0x7a, 0x2f, 0x1c }, + }, + { + { 0x00, 0x12, 0x24, 0x36, 0x48, 0x5a, 0x6c, 0x7e, 0x90, 0x82, 0xb4, 0xa6, 0xd8, 0xca, 0xfc, 0xee }, + { 0x00, 0x3d, 0x7a, 0x47, 0xf4, 0xc9, 0x8e, 0xb3, 0xf5, 0xc8, 0x8f, 0xb2, 0x01, 0x3c, 0x7b, 0x46 }, + }, + }, + { + { + { 0x00, 0xa0, 0x5d, 0xfd, 0xba, 0x1a, 0xe7, 0x47, 0x69, 0xc9, 0x34, 0x94, 0xd3, 0x73, 0x8e, 0x2e }, + { 0x00, 0xd2, 0xb9, 0x6b, 0x6f, 0xbd, 0xd6, 0x04, 0xde, 0x0c, 0x67, 0xb5, 0xb1, 0x63, 0x08, 0xda }, + }, + { + { 0x00, 0xdd, 0xa7, 0x7a, 0x53, 0x8e, 0xf4, 0x29, 0xa6, 0x7b, 0x01, 0xdc, 0xf5, 0x28, 0x52, 0x8f }, + { 0x00, 0x51, 0xa2, 0xf3, 0x59, 0x08, 0xfb, 0xaa, 0xb2, 0xe3, 0x10, 0x41, 0xeb, 0xba, 0x49, 0x18 }, + }, + { + { 0x00, 0xb6, 0x71, 0xc7, 0xe2, 0x54, 0x93, 0x25, 0xd9, 0x6f, 0xa8, 0x1e, 0x3b, 0x8d, 0x4a, 0xfc }, + { 0x00, 0xaf, 0x43, 0xec, 0x86, 0x29, 0xc5, 0x6a, 0x11, 0xbe, 0x52, 0xfd, 0x97, 0x38, 0xd4, 0x7b }, + }, + { + { 0x00, 0x34, 0x68, 0x5c, 0xd0, 0xe4, 0xb8, 0x8c, 0xbd, 0x89, 0xd5, 0xe1, 0x6d, 0x59, 0x05, 0x31 }, + { 0x00, 0x67, 0xce, 0xa9, 0x81, 0xe6, 0x4f, 0x28, 0x1f, 0x78, 0xd1, 0xb6, 0x9e, 0xf9, 0x50, 0x37 }, + }, + }, + { + { + { 0x00, 0x96, 0x31, 0xa7, 0x62, 0xf4, 0x53, 0xc5, 0xc4, 0x52, 0xf5, 0x63, 0xa6, 0x30, 0x97, 0x01 }, + { 0x00, 0x95, 0x37, 0xa2, 0x6e, 0xfb, 0x59, 0xcc, 0xdc, 0x49, 0xeb, 0x7e, 0xb2, 0x27, 0x85, 0x10 }, + }, + { + { 0x00, 0xe3, 0xdb, 0x38, 0xab, 0x48, 0x70, 0x93, 0x4b, 0xa8, 0x90, 0x73, 0xe0, 0x03, 0x3b, 0xd8 }, + { 0x00, 0x96, 0x31, 0xa7, 0x62, 0xf4, 0x53, 0xc5, 0xc4, 0x52, 0xf5, 0x63, 0xa6, 0x30, 0x97, 0x01 }, + }, + { + { 0x00, 0xf4, 0xf5, 0x01, 0xf7, 0x03, 0x02, 0xf6, 0xf3, 0x07, 0x06, 0xf2, 0x04, 0xf0, 0xf1, 0x05 }, + { 0x00, 0xfb, 0xeb, 0x10, 0xcb, 0x30, 0x20, 0xdb, 0x8b, 0x70, 0x60, 0x9b, 0x40, 0xbb, 0xab, 0x50 }, + }, + { + { 0x00, 0x0f, 0x1e, 0x11, 0x3c, 0x33, 0x22, 0x2d, 0x78, 0x77, 0x66, 0x69, 0x44, 0x4b, 0x5a, 0x55 }, + { 0x00, 0xf0, 0xfd, 0x0d, 0xe7, 0x17, 0x1a, 0xea, 0xd3, 0x23, 0x2e, 0xde, 0x34, 0xc4, 0xc9, 0x39 }, + }, + }, + { + { + { 0x00, 0x49, 0x92, 0xdb, 0x39, 0x70, 0xab, 0xe2, 0x72, 0x3b, 0xe0, 0xa9, 0x4b, 0x02, 0xd9, 0x90 }, + { 0x00, 0xe4, 0xd5, 0x31, 0xb7, 0x53, 0x62, 0x86, 0x73, 0x97, 0xa6, 0x42, 0xc4, 0x20, 0x11, 0xf5 }, + }, + { + { 0x00, 0x69, 0xd2, 0xbb, 0xb9, 0xd0, 0x6b, 0x02, 0x6f, 0x06, 0xbd, 0xd4, 0xd6, 0xbf, 0x04, 0x6d }, + { 0x00, 0xde, 0xa1, 0x7f, 0x5f, 0x81, 0xfe, 0x20, 0xbe, 0x60, 0x1f, 0xc1, 0xe1, 0x3f, 0x40, 0x9e }, + }, + { + { 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a }, + { 0x00, 0xe0, 0xdd, 0x3d, 0xa7, 0x47, 0x7a, 0x9a, 0x53, 0xb3, 0x8e, 0x6e, 0xf4, 0x14, 0x29, 0xc9 }, + }, + { + { 0x00, 0xf5, 0xf7, 0x02, 0xf3, 0x06, 0x04, 0xf1, 0xfb, 0x0e, 0x0c, 0xf9, 0x08, 0xfd, 0xff, 0x0a }, + { 0x00, 0xeb, 0xcb, 0x20, 0x8b, 0x60, 0x40, 0xab, 0x0b, 0xe0, 0xc0, 0x2b, 0x80, 0x6b, 0x4b, 0xa0 }, + }, + }, + { + { + { 0x00, 0x4e, 0x9c, 0xd2, 0x25, 0x6b, 0xb9, 0xf7, 0x4a, 0x04, 0xd6, 0x98, 0x6f, 0x21, 0xf3, 0xbd }, + { 0x00, 0x94, 0x35, 0xa1, 0x6a, 0xfe, 0x5f, 0xcb, 0xd4, 0x40, 0xe1, 0x75, 0xbe, 0x2a, 0x8b, 0x1f }, + }, + { + { 0x00, 0x0c, 0x18, 0x14, 0x30, 0x3c, 0x28, 0x24, 0x60, 0x6c, 0x78, 0x74, 0x50, 0x5c, 0x48, 0x44 }, + { 0x00, 0xc0, 0x9d, 0x5d, 0x27, 0xe7, 0xba, 0x7a, 0x4e, 0x8e, 0xd3, 0x13, 0x69, 0xa9, 0xf4, 0x34 }, + }, + { + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b }, + }, + { + { 0x00, 0xaa, 0x49, 0xe3, 0x92, 0x38, 0xdb, 0x71, 0x39, 0x93, 0x70, 0xda, 0xab, 0x01, 0xe2, 0x48 }, + { 0x00, 0x72, 0xe4, 0x96, 0xd5, 0xa7, 0x31, 0x43, 0xb7, 0xc5, 0x53, 0x21, 0x62, 0x10, 0x86, 0xf4 }, + }, + }, + { + { + { 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78 }, + { 0x00, 0x80, 0x1d, 0x9d, 0x3a, 0xba, 0x27, 0xa7, 0x74, 0xf4, 0x69, 0xe9, 0x4e, 0xce, 0x53, 0xd3 }, + }, + { + { 0x00, 0xc4, 0x95, 0x51, 0x37, 0xf3, 0xa2, 0x66, 0x6e, 0xaa, 0xfb, 0x3f, 0x59, 0x9d, 0xcc, 0x08 }, + { 0x00, 0xdc, 0xa5, 0x79, 0x57, 0x8b, 0xf2, 0x2e, 0xae, 0x72, 0x0b, 0xd7, 0xf9, 0x25, 0x5c, 0x80 }, + }, + { + { 0x00, 0xb4, 0x75, 0xc1, 0xea, 0x5e, 0x9f, 0x2b, 0xc9, 0x7d, 0xbc, 0x08, 0x23, 0x97, 0x56, 0xe2 }, + { 0x00, 0x8f, 0x03, 0x8c, 0x06, 0x89, 0x05, 0x8a, 0x0c, 0x83, 0x0f, 0x80, 0x0a, 0x85, 0x09, 0x86 }, + }, + { + { 0x00, 0x16, 0x2c, 0x3a, 0x58, 0x4e, 0x74, 0x62, 0xb0, 0xa6, 0x9c, 0x8a, 0xe8, 0xfe, 0xc4, 0xd2 }, + { 0x00, 0x7d, 0xfa, 0x87, 0xe9, 0x94, 0x13, 0x6e, 0xcf, 0xb2, 0x35, 0x48, 0x26, 0x5b, 0xdc, 0xa1 }, + }, + }, + { + { + { 0x00, 0x73, 0xe6, 0x95, 0xd1, 0xa2, 0x37, 0x44, 0xbf, 0xcc, 0x59, 0x2a, 0x6e, 0x1d, 0x88, 0xfb }, + { 0x00, 0x63, 0xc6, 0xa5, 0x91, 0xf2, 0x57, 0x34, 0x3f, 0x5c, 0xf9, 0x9a, 0xae, 0xcd, 0x68, 0x0b }, + }, + { + { 0x00, 0x88, 0x0d, 0x85, 0x1a, 0x92, 0x17, 0x9f, 0x34, 0xbc, 0x39, 0xb1, 0x2e, 0xa6, 0x23, 0xab }, + { 0x00, 0x68, 0xd0, 0xb8, 0xbd, 0xd5, 0x6d, 0x05, 0x67, 0x0f, 0xb7, 0xdf, 0xda, 0xb2, 0x0a, 0x62 }, + }, + { + { 0x00, 0xd0, 0xbd, 0x6d, 0x67, 0xb7, 0xda, 0x0a, 0xce, 0x1e, 0x73, 0xa3, 0xa9, 0x79, 0x14, 0xc4 }, + { 0x00, 0x81, 0x1f, 0x9e, 0x3e, 0xbf, 0x21, 0xa0, 0x7c, 0xfd, 0x63, 0xe2, 0x42, 0xc3, 0x5d, 0xdc }, + }, + { + { 0x00, 0xe6, 0xd1, 0x37, 0xbf, 0x59, 0x6e, 0x88, 0x63, 0x85, 0xb2, 0x54, 0xdc, 0x3a, 0x0d, 0xeb }, + { 0x00, 0xc6, 0x91, 0x57, 0x3f, 0xf9, 0xae, 0x68, 0x7e, 0xb8, 0xef, 0x29, 0x41, 0x87, 0xd0, 0x16 }, + }, + }, + { + { + { 0x00, 0xf0, 0xfd, 0x0d, 0xe7, 0x17, 0x1a, 0xea, 0xd3, 0x23, 0x2e, 0xde, 0x34, 0xc4, 0xc9, 0x39 }, + { 0x00, 0xbb, 0x6b, 0xd0, 0xd6, 0x6d, 0xbd, 0x06, 0xb1, 0x0a, 0xda, 0x61, 0x67, 0xdc, 0x0c, 0xb7 }, + }, + { + { 0x00, 0x41, 0x82, 0xc3, 0x19, 0x58, 0x9b, 0xda, 0x32, 0x73, 0xb0, 0xf1, 0x2b, 0x6a, 0xa9, 0xe8 }, + { 0x00, 0x64, 0xc8, 0xac, 0x8d, 0xe9, 0x45, 0x21, 0x07, 0x63, 0xcf, 0xab, 0x8a, 0xee, 0x42, 0x26 }, + }, + { + { 0x00, 0x30, 0x60, 0x50, 0xc0, 0xf0, 0xa0, 0x90, 0x9d, 0xad, 0xfd, 0xcd, 0x5d, 0x6d, 0x3d, 0x0d }, + { 0x00, 0x27, 0x4e, 0x69, 0x9c, 0xbb, 0xd2, 0xf5, 0x25, 0x02, 0x6b, 0x4c, 0xb9, 0x9e, 0xf7, 0xd0 }, + }, + { + { 0x00, 0xf2, 0xf9, 0x0b, 0xef, 0x1d, 0x16, 0xe4, 0xc3, 0x31, 0x3a, 0xc8, 0x2c, 0xde, 0xd5, 0x27 }, + { 0x00, 0x9b, 0x2b, 0xb0, 0x56, 0xcd, 0x7d, 0xe6, 0xac, 0x37, 0x87, 0x1c, 0xfa, 0x61, 0xd1, 0x4a }, + }, + }, + { + { + { 0x00, 0x7e, 0xfc, 0x82, 0xe5, 0x9b, 0x19, 0x67, 0xd7, 0xa9, 0x2b, 0x55, 0x32, 0x4c, 0xce, 0xb0 }, + { 0x00, 0xb3, 0x7b, 0xc8, 0xf6, 0x45, 0x8d, 0x3e, 0xf1, 0x42, 0x8a, 0x39, 0x07, 0xb4, 0x7c, 0xcf }, + }, + { + { 0x00, 0x81, 0x1f, 0x9e, 0x3e, 0xbf, 0x21, 0xa0, 0x7c, 0xfd, 0x63, 0xe2, 0x42, 0xc3, 0x5d, 0xdc }, + { 0x00, 0xf8, 0xed, 0x15, 0xc7, 0x3f, 0x2a, 0xd2, 0x93, 0x6b, 0x7e, 0x86, 0x54, 0xac, 0xb9, 0x41 }, + }, + { + { 0x00, 0xd3, 0xbb, 0x68, 0x6b, 0xb8, 0xd0, 0x03, 0xd6, 0x05, 0x6d, 0xbe, 0xbd, 0x6e, 0x06, 0xd5 }, + { 0x00, 0xb1, 0x7f, 0xce, 0xfe, 0x4f, 0x81, 0x30, 0xe1, 0x50, 0x9e, 0x2f, 0x1f, 0xae, 0x60, 0xd1 }, + }, + { + { 0x00, 0xd8, 0xad, 0x75, 0x47, 0x9f, 0xea, 0x32, 0x8e, 0x56, 0x23, 0xfb, 0xc9, 0x11, 0x64, 0xbc }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + }, + }, + { + { + { 0x00, 0xfe, 0xe1, 0x1f, 0xdf, 0x21, 0x3e, 0xc0, 0xa3, 0x5d, 0x42, 0xbc, 0x7c, 0x82, 0x9d, 0x63 }, + { 0x00, 0x5b, 0xb6, 0xed, 0x71, 0x2a, 0xc7, 0x9c, 0xe2, 0xb9, 0x54, 0x0f, 0x93, 0xc8, 0x25, 0x7e }, + }, + { + { 0x00, 0x91, 0x3f, 0xae, 0x7e, 0xef, 0x41, 0xd0, 0xfc, 0x6d, 0xc3, 0x52, 0x82, 0x13, 0xbd, 0x2c }, + { 0x00, 0xe5, 0xd7, 0x32, 0xb3, 0x56, 0x64, 0x81, 0x7b, 0x9e, 0xac, 0x49, 0xc8, 0x2d, 0x1f, 0xfa }, + }, + { + { 0x00, 0x3b, 0x76, 0x4d, 0xec, 0xd7, 0x9a, 0xa1, 0xc5, 0xfe, 0xb3, 0x88, 0x29, 0x12, 0x5f, 0x64 }, + { 0x00, 0x97, 0x33, 0xa4, 0x66, 0xf1, 0x55, 0xc2, 0xcc, 0x5b, 0xff, 0x68, 0xaa, 0x3d, 0x99, 0x0e }, + }, + { + { 0x00, 0x85, 0x17, 0x92, 0x2e, 0xab, 0x39, 0xbc, 0x5c, 0xd9, 0x4b, 0xce, 0x72, 0xf7, 0x65, 0xe0 }, + { 0x00, 0xb8, 0x6d, 0xd5, 0xda, 0x62, 0xb7, 0x0f, 0xa9, 0x11, 0xc4, 0x7c, 0x73, 0xcb, 0x1e, 0xa6 }, + }, + }, + { + { + { 0x00, 0x15, 0x2a, 0x3f, 0x54, 0x41, 0x7e, 0x6b, 0xa8, 0xbd, 0x82, 0x97, 0xfc, 0xe9, 0xd6, 0xc3 }, + { 0x00, 0x4d, 0x9a, 0xd7, 0x29, 0x64, 0xb3, 0xfe, 0x52, 0x1f, 0xc8, 0x85, 0x7b, 0x36, 0xe1, 0xac }, + }, + { + { 0x00, 0xe0, 0xdd, 0x3d, 0xa7, 0x47, 0x7a, 0x9a, 0x53, 0xb3, 0x8e, 0x6e, 0xf4, 0x14, 0x29, 0xc9 }, + { 0x00, 0xa6, 0x51, 0xf7, 0xa2, 0x04, 0xf3, 0x55, 0x59, 0xff, 0x08, 0xae, 0xfb, 0x5d, 0xaa, 0x0c }, + }, + { + { 0x00, 0xad, 0x47, 0xea, 0x8e, 0x23, 0xc9, 0x64, 0x01, 0xac, 0x46, 0xeb, 0x8f, 0x22, 0xc8, 0x65 }, + { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e }, + }, + { + { 0x00, 0x9f, 0x23, 0xbc, 0x46, 0xd9, 0x65, 0xfa, 0x8c, 0x13, 0xaf, 0x30, 0xca, 0x55, 0xe9, 0x76 }, + { 0x00, 0x05, 0x0a, 0x0f, 0x14, 0x11, 0x1e, 0x1b, 0x28, 0x2d, 0x22, 0x27, 0x3c, 0x39, 0x36, 0x33 }, + }, + }, + { + { + { 0x00, 0x4b, 0x96, 0xdd, 0x31, 0x7a, 0xa7, 0xec, 0x62, 0x29, 0xf4, 0xbf, 0x53, 0x18, 0xc5, 0x8e }, + { 0x00, 0xc4, 0x95, 0x51, 0x37, 0xf3, 0xa2, 0x66, 0x6e, 0xaa, 0xfb, 0x3f, 0x59, 0x9d, 0xcc, 0x08 }, + }, + { + { 0x00, 0xfd, 0xe7, 0x1a, 0xd3, 0x2e, 0x34, 0xc9, 0xbb, 0x46, 0x5c, 0xa1, 0x68, 0x95, 0x8f, 0x72 }, + { 0x00, 0x6b, 0xd6, 0xbd, 0xb1, 0xda, 0x67, 0x0c, 0x7f, 0x14, 0xa9, 0xc2, 0xce, 0xa5, 0x18, 0x73 }, + }, + { + { 0x00, 0xd7, 0xb3, 0x64, 0x7b, 0xac, 0xc8, 0x1f, 0xf6, 0x21, 0x45, 0x92, 0x8d, 0x5a, 0x3e, 0xe9 }, + { 0x00, 0xf1, 0xff, 0x0e, 0xe3, 0x12, 0x1c, 0xed, 0xdb, 0x2a, 0x24, 0xd5, 0x38, 0xc9, 0xc7, 0x36 }, + }, + { + { 0x00, 0xbc, 0x65, 0xd9, 0xca, 0x76, 0xaf, 0x13, 0x89, 0x35, 0xec, 0x50, 0x43, 0xff, 0x26, 0x9a }, + { 0x00, 0x0f, 0x1e, 0x11, 0x3c, 0x33, 0x22, 0x2d, 0x78, 0x77, 0x66, 0x69, 0x44, 0x4b, 0x5a, 0x55 }, + }, + }, +}; +#endif + +#ifdef CONFIG_X86 +/** + * PSHUFB tables for generic multiplication. + * + * Indexes are [MULTIPLER][LH]. + * Where MULTIPLER is from 0 to 255, LH from 0 to 1. + */ +const uint8_t __aligned(256) raid_gfmulpshufb[256][2][16] = +{ + { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + }, + { + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0 }, + }, + { + { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e }, + { 0x00, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0, 0x1d, 0x3d, 0x5d, 0x7d, 0x9d, 0xbd, 0xdd, 0xfd }, + }, + { + { 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11 }, + { 0x00, 0x30, 0x60, 0x50, 0xc0, 0xf0, 0xa0, 0x90, 0x9d, 0xad, 0xfd, 0xcd, 0x5d, 0x6d, 0x3d, 0x0d }, + }, + { + { 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c }, + { 0x00, 0x40, 0x80, 0xc0, 0x1d, 0x5d, 0x9d, 0xdd, 0x3a, 0x7a, 0xba, 0xfa, 0x27, 0x67, 0xa7, 0xe7 }, + }, + { + { 0x00, 0x05, 0x0a, 0x0f, 0x14, 0x11, 0x1e, 0x1b, 0x28, 0x2d, 0x22, 0x27, 0x3c, 0x39, 0x36, 0x33 }, + { 0x00, 0x50, 0xa0, 0xf0, 0x5d, 0x0d, 0xfd, 0xad, 0xba, 0xea, 0x1a, 0x4a, 0xe7, 0xb7, 0x47, 0x17 }, + }, + { + { 0x00, 0x06, 0x0c, 0x0a, 0x18, 0x1e, 0x14, 0x12, 0x30, 0x36, 0x3c, 0x3a, 0x28, 0x2e, 0x24, 0x22 }, + { 0x00, 0x60, 0xc0, 0xa0, 0x9d, 0xfd, 0x5d, 0x3d, 0x27, 0x47, 0xe7, 0x87, 0xba, 0xda, 0x7a, 0x1a }, + }, + { + { 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d }, + { 0x00, 0x70, 0xe0, 0x90, 0xdd, 0xad, 0x3d, 0x4d, 0xa7, 0xd7, 0x47, 0x37, 0x7a, 0x0a, 0x9a, 0xea }, + }, + { + { 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78 }, + { 0x00, 0x80, 0x1d, 0x9d, 0x3a, 0xba, 0x27, 0xa7, 0x74, 0xf4, 0x69, 0xe9, 0x4e, 0xce, 0x53, 0xd3 }, + }, + { + { 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77 }, + { 0x00, 0x90, 0x3d, 0xad, 0x7a, 0xea, 0x47, 0xd7, 0xf4, 0x64, 0xc9, 0x59, 0x8e, 0x1e, 0xb3, 0x23 }, + }, + { + { 0x00, 0x0a, 0x14, 0x1e, 0x28, 0x22, 0x3c, 0x36, 0x50, 0x5a, 0x44, 0x4e, 0x78, 0x72, 0x6c, 0x66 }, + { 0x00, 0xa0, 0x5d, 0xfd, 0xba, 0x1a, 0xe7, 0x47, 0x69, 0xc9, 0x34, 0x94, 0xd3, 0x73, 0x8e, 0x2e }, + }, + { + { 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69 }, + { 0x00, 0xb0, 0x7d, 0xcd, 0xfa, 0x4a, 0x87, 0x37, 0xe9, 0x59, 0x94, 0x24, 0x13, 0xa3, 0x6e, 0xde }, + }, + { + { 0x00, 0x0c, 0x18, 0x14, 0x30, 0x3c, 0x28, 0x24, 0x60, 0x6c, 0x78, 0x74, 0x50, 0x5c, 0x48, 0x44 }, + { 0x00, 0xc0, 0x9d, 0x5d, 0x27, 0xe7, 0xba, 0x7a, 0x4e, 0x8e, 0xd3, 0x13, 0x69, 0xa9, 0xf4, 0x34 }, + }, + { + { 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b }, + { 0x00, 0xd0, 0xbd, 0x6d, 0x67, 0xb7, 0xda, 0x0a, 0xce, 0x1e, 0x73, 0xa3, 0xa9, 0x79, 0x14, 0xc4 }, + }, + { + { 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a }, + { 0x00, 0xe0, 0xdd, 0x3d, 0xa7, 0x47, 0x7a, 0x9a, 0x53, 0xb3, 0x8e, 0x6e, 0xf4, 0x14, 0x29, 0xc9 }, + }, + { + { 0x00, 0x0f, 0x1e, 0x11, 0x3c, 0x33, 0x22, 0x2d, 0x78, 0x77, 0x66, 0x69, 0x44, 0x4b, 0x5a, 0x55 }, + { 0x00, 0xf0, 0xfd, 0x0d, 0xe7, 0x17, 0x1a, 0xea, 0xd3, 0x23, 0x2e, 0xde, 0x34, 0xc4, 0xc9, 0x39 }, + }, + { + { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0 }, + { 0x00, 0x1d, 0x3a, 0x27, 0x74, 0x69, 0x4e, 0x53, 0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb }, + }, + { + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b }, + }, + { + { 0x00, 0x12, 0x24, 0x36, 0x48, 0x5a, 0x6c, 0x7e, 0x90, 0x82, 0xb4, 0xa6, 0xd8, 0xca, 0xfc, 0xee }, + { 0x00, 0x3d, 0x7a, 0x47, 0xf4, 0xc9, 0x8e, 0xb3, 0xf5, 0xc8, 0x8f, 0xb2, 0x01, 0x3c, 0x7b, 0x46 }, + }, + { + { 0x00, 0x13, 0x26, 0x35, 0x4c, 0x5f, 0x6a, 0x79, 0x98, 0x8b, 0xbe, 0xad, 0xd4, 0xc7, 0xf2, 0xe1 }, + { 0x00, 0x2d, 0x5a, 0x77, 0xb4, 0x99, 0xee, 0xc3, 0x75, 0x58, 0x2f, 0x02, 0xc1, 0xec, 0x9b, 0xb6 }, + }, + { + { 0x00, 0x14, 0x28, 0x3c, 0x50, 0x44, 0x78, 0x6c, 0xa0, 0xb4, 0x88, 0x9c, 0xf0, 0xe4, 0xd8, 0xcc }, + { 0x00, 0x5d, 0xba, 0xe7, 0x69, 0x34, 0xd3, 0x8e, 0xd2, 0x8f, 0x68, 0x35, 0xbb, 0xe6, 0x01, 0x5c }, + }, + { + { 0x00, 0x15, 0x2a, 0x3f, 0x54, 0x41, 0x7e, 0x6b, 0xa8, 0xbd, 0x82, 0x97, 0xfc, 0xe9, 0xd6, 0xc3 }, + { 0x00, 0x4d, 0x9a, 0xd7, 0x29, 0x64, 0xb3, 0xfe, 0x52, 0x1f, 0xc8, 0x85, 0x7b, 0x36, 0xe1, 0xac }, + }, + { + { 0x00, 0x16, 0x2c, 0x3a, 0x58, 0x4e, 0x74, 0x62, 0xb0, 0xa6, 0x9c, 0x8a, 0xe8, 0xfe, 0xc4, 0xd2 }, + { 0x00, 0x7d, 0xfa, 0x87, 0xe9, 0x94, 0x13, 0x6e, 0xcf, 0xb2, 0x35, 0x48, 0x26, 0x5b, 0xdc, 0xa1 }, + }, + { + { 0x00, 0x17, 0x2e, 0x39, 0x5c, 0x4b, 0x72, 0x65, 0xb8, 0xaf, 0x96, 0x81, 0xe4, 0xf3, 0xca, 0xdd }, + { 0x00, 0x6d, 0xda, 0xb7, 0xa9, 0xc4, 0x73, 0x1e, 0x4f, 0x22, 0x95, 0xf8, 0xe6, 0x8b, 0x3c, 0x51 }, + }, + { + { 0x00, 0x18, 0x30, 0x28, 0x60, 0x78, 0x50, 0x48, 0xc0, 0xd8, 0xf0, 0xe8, 0xa0, 0xb8, 0x90, 0x88 }, + { 0x00, 0x9d, 0x27, 0xba, 0x4e, 0xd3, 0x69, 0xf4, 0x9c, 0x01, 0xbb, 0x26, 0xd2, 0x4f, 0xf5, 0x68 }, + }, + { + { 0x00, 0x19, 0x32, 0x2b, 0x64, 0x7d, 0x56, 0x4f, 0xc8, 0xd1, 0xfa, 0xe3, 0xac, 0xb5, 0x9e, 0x87 }, + { 0x00, 0x8d, 0x07, 0x8a, 0x0e, 0x83, 0x09, 0x84, 0x1c, 0x91, 0x1b, 0x96, 0x12, 0x9f, 0x15, 0x98 }, + }, + { + { 0x00, 0x1a, 0x34, 0x2e, 0x68, 0x72, 0x5c, 0x46, 0xd0, 0xca, 0xe4, 0xfe, 0xb8, 0xa2, 0x8c, 0x96 }, + { 0x00, 0xbd, 0x67, 0xda, 0xce, 0x73, 0xa9, 0x14, 0x81, 0x3c, 0xe6, 0x5b, 0x4f, 0xf2, 0x28, 0x95 }, + }, + { + { 0x00, 0x1b, 0x36, 0x2d, 0x6c, 0x77, 0x5a, 0x41, 0xd8, 0xc3, 0xee, 0xf5, 0xb4, 0xaf, 0x82, 0x99 }, + { 0x00, 0xad, 0x47, 0xea, 0x8e, 0x23, 0xc9, 0x64, 0x01, 0xac, 0x46, 0xeb, 0x8f, 0x22, 0xc8, 0x65 }, + }, + { + { 0x00, 0x1c, 0x38, 0x24, 0x70, 0x6c, 0x48, 0x54, 0xe0, 0xfc, 0xd8, 0xc4, 0x90, 0x8c, 0xa8, 0xb4 }, + { 0x00, 0xdd, 0xa7, 0x7a, 0x53, 0x8e, 0xf4, 0x29, 0xa6, 0x7b, 0x01, 0xdc, 0xf5, 0x28, 0x52, 0x8f }, + }, + { + { 0x00, 0x1d, 0x3a, 0x27, 0x74, 0x69, 0x4e, 0x53, 0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb }, + { 0x00, 0xcd, 0x87, 0x4a, 0x13, 0xde, 0x94, 0x59, 0x26, 0xeb, 0xa1, 0x6c, 0x35, 0xf8, 0xb2, 0x7f }, + }, + { + { 0x00, 0x1e, 0x3c, 0x22, 0x78, 0x66, 0x44, 0x5a, 0xf0, 0xee, 0xcc, 0xd2, 0x88, 0x96, 0xb4, 0xaa }, + { 0x00, 0xfd, 0xe7, 0x1a, 0xd3, 0x2e, 0x34, 0xc9, 0xbb, 0x46, 0x5c, 0xa1, 0x68, 0x95, 0x8f, 0x72 }, + }, + { + { 0x00, 0x1f, 0x3e, 0x21, 0x7c, 0x63, 0x42, 0x5d, 0xf8, 0xe7, 0xc6, 0xd9, 0x84, 0x9b, 0xba, 0xa5 }, + { 0x00, 0xed, 0xc7, 0x2a, 0x93, 0x7e, 0x54, 0xb9, 0x3b, 0xd6, 0xfc, 0x11, 0xa8, 0x45, 0x6f, 0x82 }, + }, + { + { 0x00, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0, 0x1d, 0x3d, 0x5d, 0x7d, 0x9d, 0xbd, 0xdd, 0xfd }, + { 0x00, 0x3a, 0x74, 0x4e, 0xe8, 0xd2, 0x9c, 0xa6, 0xcd, 0xf7, 0xb9, 0x83, 0x25, 0x1f, 0x51, 0x6b }, + }, + { + { 0x00, 0x21, 0x42, 0x63, 0x84, 0xa5, 0xc6, 0xe7, 0x15, 0x34, 0x57, 0x76, 0x91, 0xb0, 0xd3, 0xf2 }, + { 0x00, 0x2a, 0x54, 0x7e, 0xa8, 0x82, 0xfc, 0xd6, 0x4d, 0x67, 0x19, 0x33, 0xe5, 0xcf, 0xb1, 0x9b }, + }, + { + { 0x00, 0x22, 0x44, 0x66, 0x88, 0xaa, 0xcc, 0xee, 0x0d, 0x2f, 0x49, 0x6b, 0x85, 0xa7, 0xc1, 0xe3 }, + { 0x00, 0x1a, 0x34, 0x2e, 0x68, 0x72, 0x5c, 0x46, 0xd0, 0xca, 0xe4, 0xfe, 0xb8, 0xa2, 0x8c, 0x96 }, + }, + { + { 0x00, 0x23, 0x46, 0x65, 0x8c, 0xaf, 0xca, 0xe9, 0x05, 0x26, 0x43, 0x60, 0x89, 0xaa, 0xcf, 0xec }, + { 0x00, 0x0a, 0x14, 0x1e, 0x28, 0x22, 0x3c, 0x36, 0x50, 0x5a, 0x44, 0x4e, 0x78, 0x72, 0x6c, 0x66 }, + }, + { + { 0x00, 0x24, 0x48, 0x6c, 0x90, 0xb4, 0xd8, 0xfc, 0x3d, 0x19, 0x75, 0x51, 0xad, 0x89, 0xe5, 0xc1 }, + { 0x00, 0x7a, 0xf4, 0x8e, 0xf5, 0x8f, 0x01, 0x7b, 0xf7, 0x8d, 0x03, 0x79, 0x02, 0x78, 0xf6, 0x8c }, + }, + { + { 0x00, 0x25, 0x4a, 0x6f, 0x94, 0xb1, 0xde, 0xfb, 0x35, 0x10, 0x7f, 0x5a, 0xa1, 0x84, 0xeb, 0xce }, + { 0x00, 0x6a, 0xd4, 0xbe, 0xb5, 0xdf, 0x61, 0x0b, 0x77, 0x1d, 0xa3, 0xc9, 0xc2, 0xa8, 0x16, 0x7c }, + }, + { + { 0x00, 0x26, 0x4c, 0x6a, 0x98, 0xbe, 0xd4, 0xf2, 0x2d, 0x0b, 0x61, 0x47, 0xb5, 0x93, 0xf9, 0xdf }, + { 0x00, 0x5a, 0xb4, 0xee, 0x75, 0x2f, 0xc1, 0x9b, 0xea, 0xb0, 0x5e, 0x04, 0x9f, 0xc5, 0x2b, 0x71 }, + }, + { + { 0x00, 0x27, 0x4e, 0x69, 0x9c, 0xbb, 0xd2, 0xf5, 0x25, 0x02, 0x6b, 0x4c, 0xb9, 0x9e, 0xf7, 0xd0 }, + { 0x00, 0x4a, 0x94, 0xde, 0x35, 0x7f, 0xa1, 0xeb, 0x6a, 0x20, 0xfe, 0xb4, 0x5f, 0x15, 0xcb, 0x81 }, + }, + { + { 0x00, 0x28, 0x50, 0x78, 0xa0, 0x88, 0xf0, 0xd8, 0x5d, 0x75, 0x0d, 0x25, 0xfd, 0xd5, 0xad, 0x85 }, + { 0x00, 0xba, 0x69, 0xd3, 0xd2, 0x68, 0xbb, 0x01, 0xb9, 0x03, 0xd0, 0x6a, 0x6b, 0xd1, 0x02, 0xb8 }, + }, + { + { 0x00, 0x29, 0x52, 0x7b, 0xa4, 0x8d, 0xf6, 0xdf, 0x55, 0x7c, 0x07, 0x2e, 0xf1, 0xd8, 0xa3, 0x8a }, + { 0x00, 0xaa, 0x49, 0xe3, 0x92, 0x38, 0xdb, 0x71, 0x39, 0x93, 0x70, 0xda, 0xab, 0x01, 0xe2, 0x48 }, + }, + { + { 0x00, 0x2a, 0x54, 0x7e, 0xa8, 0x82, 0xfc, 0xd6, 0x4d, 0x67, 0x19, 0x33, 0xe5, 0xcf, 0xb1, 0x9b }, + { 0x00, 0x9a, 0x29, 0xb3, 0x52, 0xc8, 0x7b, 0xe1, 0xa4, 0x3e, 0x8d, 0x17, 0xf6, 0x6c, 0xdf, 0x45 }, + }, + { + { 0x00, 0x2b, 0x56, 0x7d, 0xac, 0x87, 0xfa, 0xd1, 0x45, 0x6e, 0x13, 0x38, 0xe9, 0xc2, 0xbf, 0x94 }, + { 0x00, 0x8a, 0x09, 0x83, 0x12, 0x98, 0x1b, 0x91, 0x24, 0xae, 0x2d, 0xa7, 0x36, 0xbc, 0x3f, 0xb5 }, + }, + { + { 0x00, 0x2c, 0x58, 0x74, 0xb0, 0x9c, 0xe8, 0xc4, 0x7d, 0x51, 0x25, 0x09, 0xcd, 0xe1, 0x95, 0xb9 }, + { 0x00, 0xfa, 0xe9, 0x13, 0xcf, 0x35, 0x26, 0xdc, 0x83, 0x79, 0x6a, 0x90, 0x4c, 0xb6, 0xa5, 0x5f }, + }, + { + { 0x00, 0x2d, 0x5a, 0x77, 0xb4, 0x99, 0xee, 0xc3, 0x75, 0x58, 0x2f, 0x02, 0xc1, 0xec, 0x9b, 0xb6 }, + { 0x00, 0xea, 0xc9, 0x23, 0x8f, 0x65, 0x46, 0xac, 0x03, 0xe9, 0xca, 0x20, 0x8c, 0x66, 0x45, 0xaf }, + }, + { + { 0x00, 0x2e, 0x5c, 0x72, 0xb8, 0x96, 0xe4, 0xca, 0x6d, 0x43, 0x31, 0x1f, 0xd5, 0xfb, 0x89, 0xa7 }, + { 0x00, 0xda, 0xa9, 0x73, 0x4f, 0x95, 0xe6, 0x3c, 0x9e, 0x44, 0x37, 0xed, 0xd1, 0x0b, 0x78, 0xa2 }, + }, + { + { 0x00, 0x2f, 0x5e, 0x71, 0xbc, 0x93, 0xe2, 0xcd, 0x65, 0x4a, 0x3b, 0x14, 0xd9, 0xf6, 0x87, 0xa8 }, + { 0x00, 0xca, 0x89, 0x43, 0x0f, 0xc5, 0x86, 0x4c, 0x1e, 0xd4, 0x97, 0x5d, 0x11, 0xdb, 0x98, 0x52 }, + }, + { + { 0x00, 0x30, 0x60, 0x50, 0xc0, 0xf0, 0xa0, 0x90, 0x9d, 0xad, 0xfd, 0xcd, 0x5d, 0x6d, 0x3d, 0x0d }, + { 0x00, 0x27, 0x4e, 0x69, 0x9c, 0xbb, 0xd2, 0xf5, 0x25, 0x02, 0x6b, 0x4c, 0xb9, 0x9e, 0xf7, 0xd0 }, + }, + { + { 0x00, 0x31, 0x62, 0x53, 0xc4, 0xf5, 0xa6, 0x97, 0x95, 0xa4, 0xf7, 0xc6, 0x51, 0x60, 0x33, 0x02 }, + { 0x00, 0x37, 0x6e, 0x59, 0xdc, 0xeb, 0xb2, 0x85, 0xa5, 0x92, 0xcb, 0xfc, 0x79, 0x4e, 0x17, 0x20 }, + }, + { + { 0x00, 0x32, 0x64, 0x56, 0xc8, 0xfa, 0xac, 0x9e, 0x8d, 0xbf, 0xe9, 0xdb, 0x45, 0x77, 0x21, 0x13 }, + { 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d }, + }, + { + { 0x00, 0x33, 0x66, 0x55, 0xcc, 0xff, 0xaa, 0x99, 0x85, 0xb6, 0xe3, 0xd0, 0x49, 0x7a, 0x2f, 0x1c }, + { 0x00, 0x17, 0x2e, 0x39, 0x5c, 0x4b, 0x72, 0x65, 0xb8, 0xaf, 0x96, 0x81, 0xe4, 0xf3, 0xca, 0xdd }, + }, + { + { 0x00, 0x34, 0x68, 0x5c, 0xd0, 0xe4, 0xb8, 0x8c, 0xbd, 0x89, 0xd5, 0xe1, 0x6d, 0x59, 0x05, 0x31 }, + { 0x00, 0x67, 0xce, 0xa9, 0x81, 0xe6, 0x4f, 0x28, 0x1f, 0x78, 0xd1, 0xb6, 0x9e, 0xf9, 0x50, 0x37 }, + }, + { + { 0x00, 0x35, 0x6a, 0x5f, 0xd4, 0xe1, 0xbe, 0x8b, 0xb5, 0x80, 0xdf, 0xea, 0x61, 0x54, 0x0b, 0x3e }, + { 0x00, 0x77, 0xee, 0x99, 0xc1, 0xb6, 0x2f, 0x58, 0x9f, 0xe8, 0x71, 0x06, 0x5e, 0x29, 0xb0, 0xc7 }, + }, + { + { 0x00, 0x36, 0x6c, 0x5a, 0xd8, 0xee, 0xb4, 0x82, 0xad, 0x9b, 0xc1, 0xf7, 0x75, 0x43, 0x19, 0x2f }, + { 0x00, 0x47, 0x8e, 0xc9, 0x01, 0x46, 0x8f, 0xc8, 0x02, 0x45, 0x8c, 0xcb, 0x03, 0x44, 0x8d, 0xca }, + }, + { + { 0x00, 0x37, 0x6e, 0x59, 0xdc, 0xeb, 0xb2, 0x85, 0xa5, 0x92, 0xcb, 0xfc, 0x79, 0x4e, 0x17, 0x20 }, + { 0x00, 0x57, 0xae, 0xf9, 0x41, 0x16, 0xef, 0xb8, 0x82, 0xd5, 0x2c, 0x7b, 0xc3, 0x94, 0x6d, 0x3a }, + }, + { + { 0x00, 0x38, 0x70, 0x48, 0xe0, 0xd8, 0x90, 0xa8, 0xdd, 0xe5, 0xad, 0x95, 0x3d, 0x05, 0x4d, 0x75 }, + { 0x00, 0xa7, 0x53, 0xf4, 0xa6, 0x01, 0xf5, 0x52, 0x51, 0xf6, 0x02, 0xa5, 0xf7, 0x50, 0xa4, 0x03 }, + }, + { + { 0x00, 0x39, 0x72, 0x4b, 0xe4, 0xdd, 0x96, 0xaf, 0xd5, 0xec, 0xa7, 0x9e, 0x31, 0x08, 0x43, 0x7a }, + { 0x00, 0xb7, 0x73, 0xc4, 0xe6, 0x51, 0x95, 0x22, 0xd1, 0x66, 0xa2, 0x15, 0x37, 0x80, 0x44, 0xf3 }, + }, + { + { 0x00, 0x3a, 0x74, 0x4e, 0xe8, 0xd2, 0x9c, 0xa6, 0xcd, 0xf7, 0xb9, 0x83, 0x25, 0x1f, 0x51, 0x6b }, + { 0x00, 0x87, 0x13, 0x94, 0x26, 0xa1, 0x35, 0xb2, 0x4c, 0xcb, 0x5f, 0xd8, 0x6a, 0xed, 0x79, 0xfe }, + }, + { + { 0x00, 0x3b, 0x76, 0x4d, 0xec, 0xd7, 0x9a, 0xa1, 0xc5, 0xfe, 0xb3, 0x88, 0x29, 0x12, 0x5f, 0x64 }, + { 0x00, 0x97, 0x33, 0xa4, 0x66, 0xf1, 0x55, 0xc2, 0xcc, 0x5b, 0xff, 0x68, 0xaa, 0x3d, 0x99, 0x0e }, + }, + { + { 0x00, 0x3c, 0x78, 0x44, 0xf0, 0xcc, 0x88, 0xb4, 0xfd, 0xc1, 0x85, 0xb9, 0x0d, 0x31, 0x75, 0x49 }, + { 0x00, 0xe7, 0xd3, 0x34, 0xbb, 0x5c, 0x68, 0x8f, 0x6b, 0x8c, 0xb8, 0x5f, 0xd0, 0x37, 0x03, 0xe4 }, + }, + { + { 0x00, 0x3d, 0x7a, 0x47, 0xf4, 0xc9, 0x8e, 0xb3, 0xf5, 0xc8, 0x8f, 0xb2, 0x01, 0x3c, 0x7b, 0x46 }, + { 0x00, 0xf7, 0xf3, 0x04, 0xfb, 0x0c, 0x08, 0xff, 0xeb, 0x1c, 0x18, 0xef, 0x10, 0xe7, 0xe3, 0x14 }, + }, + { + { 0x00, 0x3e, 0x7c, 0x42, 0xf8, 0xc6, 0x84, 0xba, 0xed, 0xd3, 0x91, 0xaf, 0x15, 0x2b, 0x69, 0x57 }, + { 0x00, 0xc7, 0x93, 0x54, 0x3b, 0xfc, 0xa8, 0x6f, 0x76, 0xb1, 0xe5, 0x22, 0x4d, 0x8a, 0xde, 0x19 }, + }, + { + { 0x00, 0x3f, 0x7e, 0x41, 0xfc, 0xc3, 0x82, 0xbd, 0xe5, 0xda, 0x9b, 0xa4, 0x19, 0x26, 0x67, 0x58 }, + { 0x00, 0xd7, 0xb3, 0x64, 0x7b, 0xac, 0xc8, 0x1f, 0xf6, 0x21, 0x45, 0x92, 0x8d, 0x5a, 0x3e, 0xe9 }, + }, + { + { 0x00, 0x40, 0x80, 0xc0, 0x1d, 0x5d, 0x9d, 0xdd, 0x3a, 0x7a, 0xba, 0xfa, 0x27, 0x67, 0xa7, 0xe7 }, + { 0x00, 0x74, 0xe8, 0x9c, 0xcd, 0xb9, 0x25, 0x51, 0x87, 0xf3, 0x6f, 0x1b, 0x4a, 0x3e, 0xa2, 0xd6 }, + }, + { + { 0x00, 0x41, 0x82, 0xc3, 0x19, 0x58, 0x9b, 0xda, 0x32, 0x73, 0xb0, 0xf1, 0x2b, 0x6a, 0xa9, 0xe8 }, + { 0x00, 0x64, 0xc8, 0xac, 0x8d, 0xe9, 0x45, 0x21, 0x07, 0x63, 0xcf, 0xab, 0x8a, 0xee, 0x42, 0x26 }, + }, + { + { 0x00, 0x42, 0x84, 0xc6, 0x15, 0x57, 0x91, 0xd3, 0x2a, 0x68, 0xae, 0xec, 0x3f, 0x7d, 0xbb, 0xf9 }, + { 0x00, 0x54, 0xa8, 0xfc, 0x4d, 0x19, 0xe5, 0xb1, 0x9a, 0xce, 0x32, 0x66, 0xd7, 0x83, 0x7f, 0x2b }, + }, + { + { 0x00, 0x43, 0x86, 0xc5, 0x11, 0x52, 0x97, 0xd4, 0x22, 0x61, 0xa4, 0xe7, 0x33, 0x70, 0xb5, 0xf6 }, + { 0x00, 0x44, 0x88, 0xcc, 0x0d, 0x49, 0x85, 0xc1, 0x1a, 0x5e, 0x92, 0xd6, 0x17, 0x53, 0x9f, 0xdb }, + }, + { + { 0x00, 0x44, 0x88, 0xcc, 0x0d, 0x49, 0x85, 0xc1, 0x1a, 0x5e, 0x92, 0xd6, 0x17, 0x53, 0x9f, 0xdb }, + { 0x00, 0x34, 0x68, 0x5c, 0xd0, 0xe4, 0xb8, 0x8c, 0xbd, 0x89, 0xd5, 0xe1, 0x6d, 0x59, 0x05, 0x31 }, + }, + { + { 0x00, 0x45, 0x8a, 0xcf, 0x09, 0x4c, 0x83, 0xc6, 0x12, 0x57, 0x98, 0xdd, 0x1b, 0x5e, 0x91, 0xd4 }, + { 0x00, 0x24, 0x48, 0x6c, 0x90, 0xb4, 0xd8, 0xfc, 0x3d, 0x19, 0x75, 0x51, 0xad, 0x89, 0xe5, 0xc1 }, + }, + { + { 0x00, 0x46, 0x8c, 0xca, 0x05, 0x43, 0x89, 0xcf, 0x0a, 0x4c, 0x86, 0xc0, 0x0f, 0x49, 0x83, 0xc5 }, + { 0x00, 0x14, 0x28, 0x3c, 0x50, 0x44, 0x78, 0x6c, 0xa0, 0xb4, 0x88, 0x9c, 0xf0, 0xe4, 0xd8, 0xcc }, + }, + { + { 0x00, 0x47, 0x8e, 0xc9, 0x01, 0x46, 0x8f, 0xc8, 0x02, 0x45, 0x8c, 0xcb, 0x03, 0x44, 0x8d, 0xca }, + { 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c }, + }, + { + { 0x00, 0x48, 0x90, 0xd8, 0x3d, 0x75, 0xad, 0xe5, 0x7a, 0x32, 0xea, 0xa2, 0x47, 0x0f, 0xd7, 0x9f }, + { 0x00, 0xf4, 0xf5, 0x01, 0xf7, 0x03, 0x02, 0xf6, 0xf3, 0x07, 0x06, 0xf2, 0x04, 0xf0, 0xf1, 0x05 }, + }, + { + { 0x00, 0x49, 0x92, 0xdb, 0x39, 0x70, 0xab, 0xe2, 0x72, 0x3b, 0xe0, 0xa9, 0x4b, 0x02, 0xd9, 0x90 }, + { 0x00, 0xe4, 0xd5, 0x31, 0xb7, 0x53, 0x62, 0x86, 0x73, 0x97, 0xa6, 0x42, 0xc4, 0x20, 0x11, 0xf5 }, + }, + { + { 0x00, 0x4a, 0x94, 0xde, 0x35, 0x7f, 0xa1, 0xeb, 0x6a, 0x20, 0xfe, 0xb4, 0x5f, 0x15, 0xcb, 0x81 }, + { 0x00, 0xd4, 0xb5, 0x61, 0x77, 0xa3, 0xc2, 0x16, 0xee, 0x3a, 0x5b, 0x8f, 0x99, 0x4d, 0x2c, 0xf8 }, + }, + { + { 0x00, 0x4b, 0x96, 0xdd, 0x31, 0x7a, 0xa7, 0xec, 0x62, 0x29, 0xf4, 0xbf, 0x53, 0x18, 0xc5, 0x8e }, + { 0x00, 0xc4, 0x95, 0x51, 0x37, 0xf3, 0xa2, 0x66, 0x6e, 0xaa, 0xfb, 0x3f, 0x59, 0x9d, 0xcc, 0x08 }, + }, + { + { 0x00, 0x4c, 0x98, 0xd4, 0x2d, 0x61, 0xb5, 0xf9, 0x5a, 0x16, 0xc2, 0x8e, 0x77, 0x3b, 0xef, 0xa3 }, + { 0x00, 0xb4, 0x75, 0xc1, 0xea, 0x5e, 0x9f, 0x2b, 0xc9, 0x7d, 0xbc, 0x08, 0x23, 0x97, 0x56, 0xe2 }, + }, + { + { 0x00, 0x4d, 0x9a, 0xd7, 0x29, 0x64, 0xb3, 0xfe, 0x52, 0x1f, 0xc8, 0x85, 0x7b, 0x36, 0xe1, 0xac }, + { 0x00, 0xa4, 0x55, 0xf1, 0xaa, 0x0e, 0xff, 0x5b, 0x49, 0xed, 0x1c, 0xb8, 0xe3, 0x47, 0xb6, 0x12 }, + }, + { + { 0x00, 0x4e, 0x9c, 0xd2, 0x25, 0x6b, 0xb9, 0xf7, 0x4a, 0x04, 0xd6, 0x98, 0x6f, 0x21, 0xf3, 0xbd }, + { 0x00, 0x94, 0x35, 0xa1, 0x6a, 0xfe, 0x5f, 0xcb, 0xd4, 0x40, 0xe1, 0x75, 0xbe, 0x2a, 0x8b, 0x1f }, + }, + { + { 0x00, 0x4f, 0x9e, 0xd1, 0x21, 0x6e, 0xbf, 0xf0, 0x42, 0x0d, 0xdc, 0x93, 0x63, 0x2c, 0xfd, 0xb2 }, + { 0x00, 0x84, 0x15, 0x91, 0x2a, 0xae, 0x3f, 0xbb, 0x54, 0xd0, 0x41, 0xc5, 0x7e, 0xfa, 0x6b, 0xef }, + }, + { + { 0x00, 0x50, 0xa0, 0xf0, 0x5d, 0x0d, 0xfd, 0xad, 0xba, 0xea, 0x1a, 0x4a, 0xe7, 0xb7, 0x47, 0x17 }, + { 0x00, 0x69, 0xd2, 0xbb, 0xb9, 0xd0, 0x6b, 0x02, 0x6f, 0x06, 0xbd, 0xd4, 0xd6, 0xbf, 0x04, 0x6d }, + }, + { + { 0x00, 0x51, 0xa2, 0xf3, 0x59, 0x08, 0xfb, 0xaa, 0xb2, 0xe3, 0x10, 0x41, 0xeb, 0xba, 0x49, 0x18 }, + { 0x00, 0x79, 0xf2, 0x8b, 0xf9, 0x80, 0x0b, 0x72, 0xef, 0x96, 0x1d, 0x64, 0x16, 0x6f, 0xe4, 0x9d }, + }, + { + { 0x00, 0x52, 0xa4, 0xf6, 0x55, 0x07, 0xf1, 0xa3, 0xaa, 0xf8, 0x0e, 0x5c, 0xff, 0xad, 0x5b, 0x09 }, + { 0x00, 0x49, 0x92, 0xdb, 0x39, 0x70, 0xab, 0xe2, 0x72, 0x3b, 0xe0, 0xa9, 0x4b, 0x02, 0xd9, 0x90 }, + }, + { + { 0x00, 0x53, 0xa6, 0xf5, 0x51, 0x02, 0xf7, 0xa4, 0xa2, 0xf1, 0x04, 0x57, 0xf3, 0xa0, 0x55, 0x06 }, + { 0x00, 0x59, 0xb2, 0xeb, 0x79, 0x20, 0xcb, 0x92, 0xf2, 0xab, 0x40, 0x19, 0x8b, 0xd2, 0x39, 0x60 }, + }, + { + { 0x00, 0x54, 0xa8, 0xfc, 0x4d, 0x19, 0xe5, 0xb1, 0x9a, 0xce, 0x32, 0x66, 0xd7, 0x83, 0x7f, 0x2b }, + { 0x00, 0x29, 0x52, 0x7b, 0xa4, 0x8d, 0xf6, 0xdf, 0x55, 0x7c, 0x07, 0x2e, 0xf1, 0xd8, 0xa3, 0x8a }, + }, + { + { 0x00, 0x55, 0xaa, 0xff, 0x49, 0x1c, 0xe3, 0xb6, 0x92, 0xc7, 0x38, 0x6d, 0xdb, 0x8e, 0x71, 0x24 }, + { 0x00, 0x39, 0x72, 0x4b, 0xe4, 0xdd, 0x96, 0xaf, 0xd5, 0xec, 0xa7, 0x9e, 0x31, 0x08, 0x43, 0x7a }, + }, + { + { 0x00, 0x56, 0xac, 0xfa, 0x45, 0x13, 0xe9, 0xbf, 0x8a, 0xdc, 0x26, 0x70, 0xcf, 0x99, 0x63, 0x35 }, + { 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77 }, + }, + { + { 0x00, 0x57, 0xae, 0xf9, 0x41, 0x16, 0xef, 0xb8, 0x82, 0xd5, 0x2c, 0x7b, 0xc3, 0x94, 0x6d, 0x3a }, + { 0x00, 0x19, 0x32, 0x2b, 0x64, 0x7d, 0x56, 0x4f, 0xc8, 0xd1, 0xfa, 0xe3, 0xac, 0xb5, 0x9e, 0x87 }, + }, + { + { 0x00, 0x58, 0xb0, 0xe8, 0x7d, 0x25, 0xcd, 0x95, 0xfa, 0xa2, 0x4a, 0x12, 0x87, 0xdf, 0x37, 0x6f }, + { 0x00, 0xe9, 0xcf, 0x26, 0x83, 0x6a, 0x4c, 0xa5, 0x1b, 0xf2, 0xd4, 0x3d, 0x98, 0x71, 0x57, 0xbe }, + }, + { + { 0x00, 0x59, 0xb2, 0xeb, 0x79, 0x20, 0xcb, 0x92, 0xf2, 0xab, 0x40, 0x19, 0x8b, 0xd2, 0x39, 0x60 }, + { 0x00, 0xf9, 0xef, 0x16, 0xc3, 0x3a, 0x2c, 0xd5, 0x9b, 0x62, 0x74, 0x8d, 0x58, 0xa1, 0xb7, 0x4e }, + }, + { + { 0x00, 0x5a, 0xb4, 0xee, 0x75, 0x2f, 0xc1, 0x9b, 0xea, 0xb0, 0x5e, 0x04, 0x9f, 0xc5, 0x2b, 0x71 }, + { 0x00, 0xc9, 0x8f, 0x46, 0x03, 0xca, 0x8c, 0x45, 0x06, 0xcf, 0x89, 0x40, 0x05, 0xcc, 0x8a, 0x43 }, + }, + { + { 0x00, 0x5b, 0xb6, 0xed, 0x71, 0x2a, 0xc7, 0x9c, 0xe2, 0xb9, 0x54, 0x0f, 0x93, 0xc8, 0x25, 0x7e }, + { 0x00, 0xd9, 0xaf, 0x76, 0x43, 0x9a, 0xec, 0x35, 0x86, 0x5f, 0x29, 0xf0, 0xc5, 0x1c, 0x6a, 0xb3 }, + }, + { + { 0x00, 0x5c, 0xb8, 0xe4, 0x6d, 0x31, 0xd5, 0x89, 0xda, 0x86, 0x62, 0x3e, 0xb7, 0xeb, 0x0f, 0x53 }, + { 0x00, 0xa9, 0x4f, 0xe6, 0x9e, 0x37, 0xd1, 0x78, 0x21, 0x88, 0x6e, 0xc7, 0xbf, 0x16, 0xf0, 0x59 }, + }, + { + { 0x00, 0x5d, 0xba, 0xe7, 0x69, 0x34, 0xd3, 0x8e, 0xd2, 0x8f, 0x68, 0x35, 0xbb, 0xe6, 0x01, 0x5c }, + { 0x00, 0xb9, 0x6f, 0xd6, 0xde, 0x67, 0xb1, 0x08, 0xa1, 0x18, 0xce, 0x77, 0x7f, 0xc6, 0x10, 0xa9 }, + }, + { + { 0x00, 0x5e, 0xbc, 0xe2, 0x65, 0x3b, 0xd9, 0x87, 0xca, 0x94, 0x76, 0x28, 0xaf, 0xf1, 0x13, 0x4d }, + { 0x00, 0x89, 0x0f, 0x86, 0x1e, 0x97, 0x11, 0x98, 0x3c, 0xb5, 0x33, 0xba, 0x22, 0xab, 0x2d, 0xa4 }, + }, + { + { 0x00, 0x5f, 0xbe, 0xe1, 0x61, 0x3e, 0xdf, 0x80, 0xc2, 0x9d, 0x7c, 0x23, 0xa3, 0xfc, 0x1d, 0x42 }, + { 0x00, 0x99, 0x2f, 0xb6, 0x5e, 0xc7, 0x71, 0xe8, 0xbc, 0x25, 0x93, 0x0a, 0xe2, 0x7b, 0xcd, 0x54 }, + }, + { + { 0x00, 0x60, 0xc0, 0xa0, 0x9d, 0xfd, 0x5d, 0x3d, 0x27, 0x47, 0xe7, 0x87, 0xba, 0xda, 0x7a, 0x1a }, + { 0x00, 0x4e, 0x9c, 0xd2, 0x25, 0x6b, 0xb9, 0xf7, 0x4a, 0x04, 0xd6, 0x98, 0x6f, 0x21, 0xf3, 0xbd }, + }, + { + { 0x00, 0x61, 0xc2, 0xa3, 0x99, 0xf8, 0x5b, 0x3a, 0x2f, 0x4e, 0xed, 0x8c, 0xb6, 0xd7, 0x74, 0x15 }, + { 0x00, 0x5e, 0xbc, 0xe2, 0x65, 0x3b, 0xd9, 0x87, 0xca, 0x94, 0x76, 0x28, 0xaf, 0xf1, 0x13, 0x4d }, + }, + { + { 0x00, 0x62, 0xc4, 0xa6, 0x95, 0xf7, 0x51, 0x33, 0x37, 0x55, 0xf3, 0x91, 0xa2, 0xc0, 0x66, 0x04 }, + { 0x00, 0x6e, 0xdc, 0xb2, 0xa5, 0xcb, 0x79, 0x17, 0x57, 0x39, 0x8b, 0xe5, 0xf2, 0x9c, 0x2e, 0x40 }, + }, + { + { 0x00, 0x63, 0xc6, 0xa5, 0x91, 0xf2, 0x57, 0x34, 0x3f, 0x5c, 0xf9, 0x9a, 0xae, 0xcd, 0x68, 0x0b }, + { 0x00, 0x7e, 0xfc, 0x82, 0xe5, 0x9b, 0x19, 0x67, 0xd7, 0xa9, 0x2b, 0x55, 0x32, 0x4c, 0xce, 0xb0 }, + }, + { + { 0x00, 0x64, 0xc8, 0xac, 0x8d, 0xe9, 0x45, 0x21, 0x07, 0x63, 0xcf, 0xab, 0x8a, 0xee, 0x42, 0x26 }, + { 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a }, + }, + { + { 0x00, 0x65, 0xca, 0xaf, 0x89, 0xec, 0x43, 0x26, 0x0f, 0x6a, 0xc5, 0xa0, 0x86, 0xe3, 0x4c, 0x29 }, + { 0x00, 0x1e, 0x3c, 0x22, 0x78, 0x66, 0x44, 0x5a, 0xf0, 0xee, 0xcc, 0xd2, 0x88, 0x96, 0xb4, 0xaa }, + }, + { + { 0x00, 0x66, 0xcc, 0xaa, 0x85, 0xe3, 0x49, 0x2f, 0x17, 0x71, 0xdb, 0xbd, 0x92, 0xf4, 0x5e, 0x38 }, + { 0x00, 0x2e, 0x5c, 0x72, 0xb8, 0x96, 0xe4, 0xca, 0x6d, 0x43, 0x31, 0x1f, 0xd5, 0xfb, 0x89, 0xa7 }, + }, + { + { 0x00, 0x67, 0xce, 0xa9, 0x81, 0xe6, 0x4f, 0x28, 0x1f, 0x78, 0xd1, 0xb6, 0x9e, 0xf9, 0x50, 0x37 }, + { 0x00, 0x3e, 0x7c, 0x42, 0xf8, 0xc6, 0x84, 0xba, 0xed, 0xd3, 0x91, 0xaf, 0x15, 0x2b, 0x69, 0x57 }, + }, + { + { 0x00, 0x68, 0xd0, 0xb8, 0xbd, 0xd5, 0x6d, 0x05, 0x67, 0x0f, 0xb7, 0xdf, 0xda, 0xb2, 0x0a, 0x62 }, + { 0x00, 0xce, 0x81, 0x4f, 0x1f, 0xd1, 0x9e, 0x50, 0x3e, 0xf0, 0xbf, 0x71, 0x21, 0xef, 0xa0, 0x6e }, + }, + { + { 0x00, 0x69, 0xd2, 0xbb, 0xb9, 0xd0, 0x6b, 0x02, 0x6f, 0x06, 0xbd, 0xd4, 0xd6, 0xbf, 0x04, 0x6d }, + { 0x00, 0xde, 0xa1, 0x7f, 0x5f, 0x81, 0xfe, 0x20, 0xbe, 0x60, 0x1f, 0xc1, 0xe1, 0x3f, 0x40, 0x9e }, + }, + { + { 0x00, 0x6a, 0xd4, 0xbe, 0xb5, 0xdf, 0x61, 0x0b, 0x77, 0x1d, 0xa3, 0xc9, 0xc2, 0xa8, 0x16, 0x7c }, + { 0x00, 0xee, 0xc1, 0x2f, 0x9f, 0x71, 0x5e, 0xb0, 0x23, 0xcd, 0xe2, 0x0c, 0xbc, 0x52, 0x7d, 0x93 }, + }, + { + { 0x00, 0x6b, 0xd6, 0xbd, 0xb1, 0xda, 0x67, 0x0c, 0x7f, 0x14, 0xa9, 0xc2, 0xce, 0xa5, 0x18, 0x73 }, + { 0x00, 0xfe, 0xe1, 0x1f, 0xdf, 0x21, 0x3e, 0xc0, 0xa3, 0x5d, 0x42, 0xbc, 0x7c, 0x82, 0x9d, 0x63 }, + }, + { + { 0x00, 0x6c, 0xd8, 0xb4, 0xad, 0xc1, 0x75, 0x19, 0x47, 0x2b, 0x9f, 0xf3, 0xea, 0x86, 0x32, 0x5e }, + { 0x00, 0x8e, 0x01, 0x8f, 0x02, 0x8c, 0x03, 0x8d, 0x04, 0x8a, 0x05, 0x8b, 0x06, 0x88, 0x07, 0x89 }, + }, + { + { 0x00, 0x6d, 0xda, 0xb7, 0xa9, 0xc4, 0x73, 0x1e, 0x4f, 0x22, 0x95, 0xf8, 0xe6, 0x8b, 0x3c, 0x51 }, + { 0x00, 0x9e, 0x21, 0xbf, 0x42, 0xdc, 0x63, 0xfd, 0x84, 0x1a, 0xa5, 0x3b, 0xc6, 0x58, 0xe7, 0x79 }, + }, + { + { 0x00, 0x6e, 0xdc, 0xb2, 0xa5, 0xcb, 0x79, 0x17, 0x57, 0x39, 0x8b, 0xe5, 0xf2, 0x9c, 0x2e, 0x40 }, + { 0x00, 0xae, 0x41, 0xef, 0x82, 0x2c, 0xc3, 0x6d, 0x19, 0xb7, 0x58, 0xf6, 0x9b, 0x35, 0xda, 0x74 }, + }, + { + { 0x00, 0x6f, 0xde, 0xb1, 0xa1, 0xce, 0x7f, 0x10, 0x5f, 0x30, 0x81, 0xee, 0xfe, 0x91, 0x20, 0x4f }, + { 0x00, 0xbe, 0x61, 0xdf, 0xc2, 0x7c, 0xa3, 0x1d, 0x99, 0x27, 0xf8, 0x46, 0x5b, 0xe5, 0x3a, 0x84 }, + }, + { + { 0x00, 0x70, 0xe0, 0x90, 0xdd, 0xad, 0x3d, 0x4d, 0xa7, 0xd7, 0x47, 0x37, 0x7a, 0x0a, 0x9a, 0xea }, + { 0x00, 0x53, 0xa6, 0xf5, 0x51, 0x02, 0xf7, 0xa4, 0xa2, 0xf1, 0x04, 0x57, 0xf3, 0xa0, 0x55, 0x06 }, + }, + { + { 0x00, 0x71, 0xe2, 0x93, 0xd9, 0xa8, 0x3b, 0x4a, 0xaf, 0xde, 0x4d, 0x3c, 0x76, 0x07, 0x94, 0xe5 }, + { 0x00, 0x43, 0x86, 0xc5, 0x11, 0x52, 0x97, 0xd4, 0x22, 0x61, 0xa4, 0xe7, 0x33, 0x70, 0xb5, 0xf6 }, + }, + { + { 0x00, 0x72, 0xe4, 0x96, 0xd5, 0xa7, 0x31, 0x43, 0xb7, 0xc5, 0x53, 0x21, 0x62, 0x10, 0x86, 0xf4 }, + { 0x00, 0x73, 0xe6, 0x95, 0xd1, 0xa2, 0x37, 0x44, 0xbf, 0xcc, 0x59, 0x2a, 0x6e, 0x1d, 0x88, 0xfb }, + }, + { + { 0x00, 0x73, 0xe6, 0x95, 0xd1, 0xa2, 0x37, 0x44, 0xbf, 0xcc, 0x59, 0x2a, 0x6e, 0x1d, 0x88, 0xfb }, + { 0x00, 0x63, 0xc6, 0xa5, 0x91, 0xf2, 0x57, 0x34, 0x3f, 0x5c, 0xf9, 0x9a, 0xae, 0xcd, 0x68, 0x0b }, + }, + { + { 0x00, 0x74, 0xe8, 0x9c, 0xcd, 0xb9, 0x25, 0x51, 0x87, 0xf3, 0x6f, 0x1b, 0x4a, 0x3e, 0xa2, 0xd6 }, + { 0x00, 0x13, 0x26, 0x35, 0x4c, 0x5f, 0x6a, 0x79, 0x98, 0x8b, 0xbe, 0xad, 0xd4, 0xc7, 0xf2, 0xe1 }, + }, + { + { 0x00, 0x75, 0xea, 0x9f, 0xc9, 0xbc, 0x23, 0x56, 0x8f, 0xfa, 0x65, 0x10, 0x46, 0x33, 0xac, 0xd9 }, + { 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11 }, + }, + { + { 0x00, 0x76, 0xec, 0x9a, 0xc5, 0xb3, 0x29, 0x5f, 0x97, 0xe1, 0x7b, 0x0d, 0x52, 0x24, 0xbe, 0xc8 }, + { 0x00, 0x33, 0x66, 0x55, 0xcc, 0xff, 0xaa, 0x99, 0x85, 0xb6, 0xe3, 0xd0, 0x49, 0x7a, 0x2f, 0x1c }, + }, + { + { 0x00, 0x77, 0xee, 0x99, 0xc1, 0xb6, 0x2f, 0x58, 0x9f, 0xe8, 0x71, 0x06, 0x5e, 0x29, 0xb0, 0xc7 }, + { 0x00, 0x23, 0x46, 0x65, 0x8c, 0xaf, 0xca, 0xe9, 0x05, 0x26, 0x43, 0x60, 0x89, 0xaa, 0xcf, 0xec }, + }, + { + { 0x00, 0x78, 0xf0, 0x88, 0xfd, 0x85, 0x0d, 0x75, 0xe7, 0x9f, 0x17, 0x6f, 0x1a, 0x62, 0xea, 0x92 }, + { 0x00, 0xd3, 0xbb, 0x68, 0x6b, 0xb8, 0xd0, 0x03, 0xd6, 0x05, 0x6d, 0xbe, 0xbd, 0x6e, 0x06, 0xd5 }, + }, + { + { 0x00, 0x79, 0xf2, 0x8b, 0xf9, 0x80, 0x0b, 0x72, 0xef, 0x96, 0x1d, 0x64, 0x16, 0x6f, 0xe4, 0x9d }, + { 0x00, 0xc3, 0x9b, 0x58, 0x2b, 0xe8, 0xb0, 0x73, 0x56, 0x95, 0xcd, 0x0e, 0x7d, 0xbe, 0xe6, 0x25 }, + }, + { + { 0x00, 0x7a, 0xf4, 0x8e, 0xf5, 0x8f, 0x01, 0x7b, 0xf7, 0x8d, 0x03, 0x79, 0x02, 0x78, 0xf6, 0x8c }, + { 0x00, 0xf3, 0xfb, 0x08, 0xeb, 0x18, 0x10, 0xe3, 0xcb, 0x38, 0x30, 0xc3, 0x20, 0xd3, 0xdb, 0x28 }, + }, + { + { 0x00, 0x7b, 0xf6, 0x8d, 0xf1, 0x8a, 0x07, 0x7c, 0xff, 0x84, 0x09, 0x72, 0x0e, 0x75, 0xf8, 0x83 }, + { 0x00, 0xe3, 0xdb, 0x38, 0xab, 0x48, 0x70, 0x93, 0x4b, 0xa8, 0x90, 0x73, 0xe0, 0x03, 0x3b, 0xd8 }, + }, + { + { 0x00, 0x7c, 0xf8, 0x84, 0xed, 0x91, 0x15, 0x69, 0xc7, 0xbb, 0x3f, 0x43, 0x2a, 0x56, 0xd2, 0xae }, + { 0x00, 0x93, 0x3b, 0xa8, 0x76, 0xe5, 0x4d, 0xde, 0xec, 0x7f, 0xd7, 0x44, 0x9a, 0x09, 0xa1, 0x32 }, + }, + { + { 0x00, 0x7d, 0xfa, 0x87, 0xe9, 0x94, 0x13, 0x6e, 0xcf, 0xb2, 0x35, 0x48, 0x26, 0x5b, 0xdc, 0xa1 }, + { 0x00, 0x83, 0x1b, 0x98, 0x36, 0xb5, 0x2d, 0xae, 0x6c, 0xef, 0x77, 0xf4, 0x5a, 0xd9, 0x41, 0xc2 }, + }, + { + { 0x00, 0x7e, 0xfc, 0x82, 0xe5, 0x9b, 0x19, 0x67, 0xd7, 0xa9, 0x2b, 0x55, 0x32, 0x4c, 0xce, 0xb0 }, + { 0x00, 0xb3, 0x7b, 0xc8, 0xf6, 0x45, 0x8d, 0x3e, 0xf1, 0x42, 0x8a, 0x39, 0x07, 0xb4, 0x7c, 0xcf }, + }, + { + { 0x00, 0x7f, 0xfe, 0x81, 0xe1, 0x9e, 0x1f, 0x60, 0xdf, 0xa0, 0x21, 0x5e, 0x3e, 0x41, 0xc0, 0xbf }, + { 0x00, 0xa3, 0x5b, 0xf8, 0xb6, 0x15, 0xed, 0x4e, 0x71, 0xd2, 0x2a, 0x89, 0xc7, 0x64, 0x9c, 0x3f }, + }, + { + { 0x00, 0x80, 0x1d, 0x9d, 0x3a, 0xba, 0x27, 0xa7, 0x74, 0xf4, 0x69, 0xe9, 0x4e, 0xce, 0x53, 0xd3 }, + { 0x00, 0xe8, 0xcd, 0x25, 0x87, 0x6f, 0x4a, 0xa2, 0x13, 0xfb, 0xde, 0x36, 0x94, 0x7c, 0x59, 0xb1 }, + }, + { + { 0x00, 0x81, 0x1f, 0x9e, 0x3e, 0xbf, 0x21, 0xa0, 0x7c, 0xfd, 0x63, 0xe2, 0x42, 0xc3, 0x5d, 0xdc }, + { 0x00, 0xf8, 0xed, 0x15, 0xc7, 0x3f, 0x2a, 0xd2, 0x93, 0x6b, 0x7e, 0x86, 0x54, 0xac, 0xb9, 0x41 }, + }, + { + { 0x00, 0x82, 0x19, 0x9b, 0x32, 0xb0, 0x2b, 0xa9, 0x64, 0xe6, 0x7d, 0xff, 0x56, 0xd4, 0x4f, 0xcd }, + { 0x00, 0xc8, 0x8d, 0x45, 0x07, 0xcf, 0x8a, 0x42, 0x0e, 0xc6, 0x83, 0x4b, 0x09, 0xc1, 0x84, 0x4c }, + }, + { + { 0x00, 0x83, 0x1b, 0x98, 0x36, 0xb5, 0x2d, 0xae, 0x6c, 0xef, 0x77, 0xf4, 0x5a, 0xd9, 0x41, 0xc2 }, + { 0x00, 0xd8, 0xad, 0x75, 0x47, 0x9f, 0xea, 0x32, 0x8e, 0x56, 0x23, 0xfb, 0xc9, 0x11, 0x64, 0xbc }, + }, + { + { 0x00, 0x84, 0x15, 0x91, 0x2a, 0xae, 0x3f, 0xbb, 0x54, 0xd0, 0x41, 0xc5, 0x7e, 0xfa, 0x6b, 0xef }, + { 0x00, 0xa8, 0x4d, 0xe5, 0x9a, 0x32, 0xd7, 0x7f, 0x29, 0x81, 0x64, 0xcc, 0xb3, 0x1b, 0xfe, 0x56 }, + }, + { + { 0x00, 0x85, 0x17, 0x92, 0x2e, 0xab, 0x39, 0xbc, 0x5c, 0xd9, 0x4b, 0xce, 0x72, 0xf7, 0x65, 0xe0 }, + { 0x00, 0xb8, 0x6d, 0xd5, 0xda, 0x62, 0xb7, 0x0f, 0xa9, 0x11, 0xc4, 0x7c, 0x73, 0xcb, 0x1e, 0xa6 }, + }, + { + { 0x00, 0x86, 0x11, 0x97, 0x22, 0xa4, 0x33, 0xb5, 0x44, 0xc2, 0x55, 0xd3, 0x66, 0xe0, 0x77, 0xf1 }, + { 0x00, 0x88, 0x0d, 0x85, 0x1a, 0x92, 0x17, 0x9f, 0x34, 0xbc, 0x39, 0xb1, 0x2e, 0xa6, 0x23, 0xab }, + }, + { + { 0x00, 0x87, 0x13, 0x94, 0x26, 0xa1, 0x35, 0xb2, 0x4c, 0xcb, 0x5f, 0xd8, 0x6a, 0xed, 0x79, 0xfe }, + { 0x00, 0x98, 0x2d, 0xb5, 0x5a, 0xc2, 0x77, 0xef, 0xb4, 0x2c, 0x99, 0x01, 0xee, 0x76, 0xc3, 0x5b }, + }, + { + { 0x00, 0x88, 0x0d, 0x85, 0x1a, 0x92, 0x17, 0x9f, 0x34, 0xbc, 0x39, 0xb1, 0x2e, 0xa6, 0x23, 0xab }, + { 0x00, 0x68, 0xd0, 0xb8, 0xbd, 0xd5, 0x6d, 0x05, 0x67, 0x0f, 0xb7, 0xdf, 0xda, 0xb2, 0x0a, 0x62 }, + }, + { + { 0x00, 0x89, 0x0f, 0x86, 0x1e, 0x97, 0x11, 0x98, 0x3c, 0xb5, 0x33, 0xba, 0x22, 0xab, 0x2d, 0xa4 }, + { 0x00, 0x78, 0xf0, 0x88, 0xfd, 0x85, 0x0d, 0x75, 0xe7, 0x9f, 0x17, 0x6f, 0x1a, 0x62, 0xea, 0x92 }, + }, + { + { 0x00, 0x8a, 0x09, 0x83, 0x12, 0x98, 0x1b, 0x91, 0x24, 0xae, 0x2d, 0xa7, 0x36, 0xbc, 0x3f, 0xb5 }, + { 0x00, 0x48, 0x90, 0xd8, 0x3d, 0x75, 0xad, 0xe5, 0x7a, 0x32, 0xea, 0xa2, 0x47, 0x0f, 0xd7, 0x9f }, + }, + { + { 0x00, 0x8b, 0x0b, 0x80, 0x16, 0x9d, 0x1d, 0x96, 0x2c, 0xa7, 0x27, 0xac, 0x3a, 0xb1, 0x31, 0xba }, + { 0x00, 0x58, 0xb0, 0xe8, 0x7d, 0x25, 0xcd, 0x95, 0xfa, 0xa2, 0x4a, 0x12, 0x87, 0xdf, 0x37, 0x6f }, + }, + { + { 0x00, 0x8c, 0x05, 0x89, 0x0a, 0x86, 0x0f, 0x83, 0x14, 0x98, 0x11, 0x9d, 0x1e, 0x92, 0x1b, 0x97 }, + { 0x00, 0x28, 0x50, 0x78, 0xa0, 0x88, 0xf0, 0xd8, 0x5d, 0x75, 0x0d, 0x25, 0xfd, 0xd5, 0xad, 0x85 }, + }, + { + { 0x00, 0x8d, 0x07, 0x8a, 0x0e, 0x83, 0x09, 0x84, 0x1c, 0x91, 0x1b, 0x96, 0x12, 0x9f, 0x15, 0x98 }, + { 0x00, 0x38, 0x70, 0x48, 0xe0, 0xd8, 0x90, 0xa8, 0xdd, 0xe5, 0xad, 0x95, 0x3d, 0x05, 0x4d, 0x75 }, + }, + { + { 0x00, 0x8e, 0x01, 0x8f, 0x02, 0x8c, 0x03, 0x8d, 0x04, 0x8a, 0x05, 0x8b, 0x06, 0x88, 0x07, 0x89 }, + { 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78 }, + }, + { + { 0x00, 0x8f, 0x03, 0x8c, 0x06, 0x89, 0x05, 0x8a, 0x0c, 0x83, 0x0f, 0x80, 0x0a, 0x85, 0x09, 0x86 }, + { 0x00, 0x18, 0x30, 0x28, 0x60, 0x78, 0x50, 0x48, 0xc0, 0xd8, 0xf0, 0xe8, 0xa0, 0xb8, 0x90, 0x88 }, + }, + { + { 0x00, 0x90, 0x3d, 0xad, 0x7a, 0xea, 0x47, 0xd7, 0xf4, 0x64, 0xc9, 0x59, 0x8e, 0x1e, 0xb3, 0x23 }, + { 0x00, 0xf5, 0xf7, 0x02, 0xf3, 0x06, 0x04, 0xf1, 0xfb, 0x0e, 0x0c, 0xf9, 0x08, 0xfd, 0xff, 0x0a }, + }, + { + { 0x00, 0x91, 0x3f, 0xae, 0x7e, 0xef, 0x41, 0xd0, 0xfc, 0x6d, 0xc3, 0x52, 0x82, 0x13, 0xbd, 0x2c }, + { 0x00, 0xe5, 0xd7, 0x32, 0xb3, 0x56, 0x64, 0x81, 0x7b, 0x9e, 0xac, 0x49, 0xc8, 0x2d, 0x1f, 0xfa }, + }, + { + { 0x00, 0x92, 0x39, 0xab, 0x72, 0xe0, 0x4b, 0xd9, 0xe4, 0x76, 0xdd, 0x4f, 0x96, 0x04, 0xaf, 0x3d }, + { 0x00, 0xd5, 0xb7, 0x62, 0x73, 0xa6, 0xc4, 0x11, 0xe6, 0x33, 0x51, 0x84, 0x95, 0x40, 0x22, 0xf7 }, + }, + { + { 0x00, 0x93, 0x3b, 0xa8, 0x76, 0xe5, 0x4d, 0xde, 0xec, 0x7f, 0xd7, 0x44, 0x9a, 0x09, 0xa1, 0x32 }, + { 0x00, 0xc5, 0x97, 0x52, 0x33, 0xf6, 0xa4, 0x61, 0x66, 0xa3, 0xf1, 0x34, 0x55, 0x90, 0xc2, 0x07 }, + }, + { + { 0x00, 0x94, 0x35, 0xa1, 0x6a, 0xfe, 0x5f, 0xcb, 0xd4, 0x40, 0xe1, 0x75, 0xbe, 0x2a, 0x8b, 0x1f }, + { 0x00, 0xb5, 0x77, 0xc2, 0xee, 0x5b, 0x99, 0x2c, 0xc1, 0x74, 0xb6, 0x03, 0x2f, 0x9a, 0x58, 0xed }, + }, + { + { 0x00, 0x95, 0x37, 0xa2, 0x6e, 0xfb, 0x59, 0xcc, 0xdc, 0x49, 0xeb, 0x7e, 0xb2, 0x27, 0x85, 0x10 }, + { 0x00, 0xa5, 0x57, 0xf2, 0xae, 0x0b, 0xf9, 0x5c, 0x41, 0xe4, 0x16, 0xb3, 0xef, 0x4a, 0xb8, 0x1d }, + }, + { + { 0x00, 0x96, 0x31, 0xa7, 0x62, 0xf4, 0x53, 0xc5, 0xc4, 0x52, 0xf5, 0x63, 0xa6, 0x30, 0x97, 0x01 }, + { 0x00, 0x95, 0x37, 0xa2, 0x6e, 0xfb, 0x59, 0xcc, 0xdc, 0x49, 0xeb, 0x7e, 0xb2, 0x27, 0x85, 0x10 }, + }, + { + { 0x00, 0x97, 0x33, 0xa4, 0x66, 0xf1, 0x55, 0xc2, 0xcc, 0x5b, 0xff, 0x68, 0xaa, 0x3d, 0x99, 0x0e }, + { 0x00, 0x85, 0x17, 0x92, 0x2e, 0xab, 0x39, 0xbc, 0x5c, 0xd9, 0x4b, 0xce, 0x72, 0xf7, 0x65, 0xe0 }, + }, + { + { 0x00, 0x98, 0x2d, 0xb5, 0x5a, 0xc2, 0x77, 0xef, 0xb4, 0x2c, 0x99, 0x01, 0xee, 0x76, 0xc3, 0x5b }, + { 0x00, 0x75, 0xea, 0x9f, 0xc9, 0xbc, 0x23, 0x56, 0x8f, 0xfa, 0x65, 0x10, 0x46, 0x33, 0xac, 0xd9 }, + }, + { + { 0x00, 0x99, 0x2f, 0xb6, 0x5e, 0xc7, 0x71, 0xe8, 0xbc, 0x25, 0x93, 0x0a, 0xe2, 0x7b, 0xcd, 0x54 }, + { 0x00, 0x65, 0xca, 0xaf, 0x89, 0xec, 0x43, 0x26, 0x0f, 0x6a, 0xc5, 0xa0, 0x86, 0xe3, 0x4c, 0x29 }, + }, + { + { 0x00, 0x9a, 0x29, 0xb3, 0x52, 0xc8, 0x7b, 0xe1, 0xa4, 0x3e, 0x8d, 0x17, 0xf6, 0x6c, 0xdf, 0x45 }, + { 0x00, 0x55, 0xaa, 0xff, 0x49, 0x1c, 0xe3, 0xb6, 0x92, 0xc7, 0x38, 0x6d, 0xdb, 0x8e, 0x71, 0x24 }, + }, + { + { 0x00, 0x9b, 0x2b, 0xb0, 0x56, 0xcd, 0x7d, 0xe6, 0xac, 0x37, 0x87, 0x1c, 0xfa, 0x61, 0xd1, 0x4a }, + { 0x00, 0x45, 0x8a, 0xcf, 0x09, 0x4c, 0x83, 0xc6, 0x12, 0x57, 0x98, 0xdd, 0x1b, 0x5e, 0x91, 0xd4 }, + }, + { + { 0x00, 0x9c, 0x25, 0xb9, 0x4a, 0xd6, 0x6f, 0xf3, 0x94, 0x08, 0xb1, 0x2d, 0xde, 0x42, 0xfb, 0x67 }, + { 0x00, 0x35, 0x6a, 0x5f, 0xd4, 0xe1, 0xbe, 0x8b, 0xb5, 0x80, 0xdf, 0xea, 0x61, 0x54, 0x0b, 0x3e }, + }, + { + { 0x00, 0x9d, 0x27, 0xba, 0x4e, 0xd3, 0x69, 0xf4, 0x9c, 0x01, 0xbb, 0x26, 0xd2, 0x4f, 0xf5, 0x68 }, + { 0x00, 0x25, 0x4a, 0x6f, 0x94, 0xb1, 0xde, 0xfb, 0x35, 0x10, 0x7f, 0x5a, 0xa1, 0x84, 0xeb, 0xce }, + }, + { + { 0x00, 0x9e, 0x21, 0xbf, 0x42, 0xdc, 0x63, 0xfd, 0x84, 0x1a, 0xa5, 0x3b, 0xc6, 0x58, 0xe7, 0x79 }, + { 0x00, 0x15, 0x2a, 0x3f, 0x54, 0x41, 0x7e, 0x6b, 0xa8, 0xbd, 0x82, 0x97, 0xfc, 0xe9, 0xd6, 0xc3 }, + }, + { + { 0x00, 0x9f, 0x23, 0xbc, 0x46, 0xd9, 0x65, 0xfa, 0x8c, 0x13, 0xaf, 0x30, 0xca, 0x55, 0xe9, 0x76 }, + { 0x00, 0x05, 0x0a, 0x0f, 0x14, 0x11, 0x1e, 0x1b, 0x28, 0x2d, 0x22, 0x27, 0x3c, 0x39, 0x36, 0x33 }, + }, + { + { 0x00, 0xa0, 0x5d, 0xfd, 0xba, 0x1a, 0xe7, 0x47, 0x69, 0xc9, 0x34, 0x94, 0xd3, 0x73, 0x8e, 0x2e }, + { 0x00, 0xd2, 0xb9, 0x6b, 0x6f, 0xbd, 0xd6, 0x04, 0xde, 0x0c, 0x67, 0xb5, 0xb1, 0x63, 0x08, 0xda }, + }, + { + { 0x00, 0xa1, 0x5f, 0xfe, 0xbe, 0x1f, 0xe1, 0x40, 0x61, 0xc0, 0x3e, 0x9f, 0xdf, 0x7e, 0x80, 0x21 }, + { 0x00, 0xc2, 0x99, 0x5b, 0x2f, 0xed, 0xb6, 0x74, 0x5e, 0x9c, 0xc7, 0x05, 0x71, 0xb3, 0xe8, 0x2a }, + }, + { + { 0x00, 0xa2, 0x59, 0xfb, 0xb2, 0x10, 0xeb, 0x49, 0x79, 0xdb, 0x20, 0x82, 0xcb, 0x69, 0x92, 0x30 }, + { 0x00, 0xf2, 0xf9, 0x0b, 0xef, 0x1d, 0x16, 0xe4, 0xc3, 0x31, 0x3a, 0xc8, 0x2c, 0xde, 0xd5, 0x27 }, + }, + { + { 0x00, 0xa3, 0x5b, 0xf8, 0xb6, 0x15, 0xed, 0x4e, 0x71, 0xd2, 0x2a, 0x89, 0xc7, 0x64, 0x9c, 0x3f }, + { 0x00, 0xe2, 0xd9, 0x3b, 0xaf, 0x4d, 0x76, 0x94, 0x43, 0xa1, 0x9a, 0x78, 0xec, 0x0e, 0x35, 0xd7 }, + }, + { + { 0x00, 0xa4, 0x55, 0xf1, 0xaa, 0x0e, 0xff, 0x5b, 0x49, 0xed, 0x1c, 0xb8, 0xe3, 0x47, 0xb6, 0x12 }, + { 0x00, 0x92, 0x39, 0xab, 0x72, 0xe0, 0x4b, 0xd9, 0xe4, 0x76, 0xdd, 0x4f, 0x96, 0x04, 0xaf, 0x3d }, + }, + { + { 0x00, 0xa5, 0x57, 0xf2, 0xae, 0x0b, 0xf9, 0x5c, 0x41, 0xe4, 0x16, 0xb3, 0xef, 0x4a, 0xb8, 0x1d }, + { 0x00, 0x82, 0x19, 0x9b, 0x32, 0xb0, 0x2b, 0xa9, 0x64, 0xe6, 0x7d, 0xff, 0x56, 0xd4, 0x4f, 0xcd }, + }, + { + { 0x00, 0xa6, 0x51, 0xf7, 0xa2, 0x04, 0xf3, 0x55, 0x59, 0xff, 0x08, 0xae, 0xfb, 0x5d, 0xaa, 0x0c }, + { 0x00, 0xb2, 0x79, 0xcb, 0xf2, 0x40, 0x8b, 0x39, 0xf9, 0x4b, 0x80, 0x32, 0x0b, 0xb9, 0x72, 0xc0 }, + }, + { + { 0x00, 0xa7, 0x53, 0xf4, 0xa6, 0x01, 0xf5, 0x52, 0x51, 0xf6, 0x02, 0xa5, 0xf7, 0x50, 0xa4, 0x03 }, + { 0x00, 0xa2, 0x59, 0xfb, 0xb2, 0x10, 0xeb, 0x49, 0x79, 0xdb, 0x20, 0x82, 0xcb, 0x69, 0x92, 0x30 }, + }, + { + { 0x00, 0xa8, 0x4d, 0xe5, 0x9a, 0x32, 0xd7, 0x7f, 0x29, 0x81, 0x64, 0xcc, 0xb3, 0x1b, 0xfe, 0x56 }, + { 0x00, 0x52, 0xa4, 0xf6, 0x55, 0x07, 0xf1, 0xa3, 0xaa, 0xf8, 0x0e, 0x5c, 0xff, 0xad, 0x5b, 0x09 }, + }, + { + { 0x00, 0xa9, 0x4f, 0xe6, 0x9e, 0x37, 0xd1, 0x78, 0x21, 0x88, 0x6e, 0xc7, 0xbf, 0x16, 0xf0, 0x59 }, + { 0x00, 0x42, 0x84, 0xc6, 0x15, 0x57, 0x91, 0xd3, 0x2a, 0x68, 0xae, 0xec, 0x3f, 0x7d, 0xbb, 0xf9 }, + }, + { + { 0x00, 0xaa, 0x49, 0xe3, 0x92, 0x38, 0xdb, 0x71, 0x39, 0x93, 0x70, 0xda, 0xab, 0x01, 0xe2, 0x48 }, + { 0x00, 0x72, 0xe4, 0x96, 0xd5, 0xa7, 0x31, 0x43, 0xb7, 0xc5, 0x53, 0x21, 0x62, 0x10, 0x86, 0xf4 }, + }, + { + { 0x00, 0xab, 0x4b, 0xe0, 0x96, 0x3d, 0xdd, 0x76, 0x31, 0x9a, 0x7a, 0xd1, 0xa7, 0x0c, 0xec, 0x47 }, + { 0x00, 0x62, 0xc4, 0xa6, 0x95, 0xf7, 0x51, 0x33, 0x37, 0x55, 0xf3, 0x91, 0xa2, 0xc0, 0x66, 0x04 }, + }, + { + { 0x00, 0xac, 0x45, 0xe9, 0x8a, 0x26, 0xcf, 0x63, 0x09, 0xa5, 0x4c, 0xe0, 0x83, 0x2f, 0xc6, 0x6a }, + { 0x00, 0x12, 0x24, 0x36, 0x48, 0x5a, 0x6c, 0x7e, 0x90, 0x82, 0xb4, 0xa6, 0xd8, 0xca, 0xfc, 0xee }, + }, + { + { 0x00, 0xad, 0x47, 0xea, 0x8e, 0x23, 0xc9, 0x64, 0x01, 0xac, 0x46, 0xeb, 0x8f, 0x22, 0xc8, 0x65 }, + { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e }, + }, + { + { 0x00, 0xae, 0x41, 0xef, 0x82, 0x2c, 0xc3, 0x6d, 0x19, 0xb7, 0x58, 0xf6, 0x9b, 0x35, 0xda, 0x74 }, + { 0x00, 0x32, 0x64, 0x56, 0xc8, 0xfa, 0xac, 0x9e, 0x8d, 0xbf, 0xe9, 0xdb, 0x45, 0x77, 0x21, 0x13 }, + }, + { + { 0x00, 0xaf, 0x43, 0xec, 0x86, 0x29, 0xc5, 0x6a, 0x11, 0xbe, 0x52, 0xfd, 0x97, 0x38, 0xd4, 0x7b }, + { 0x00, 0x22, 0x44, 0x66, 0x88, 0xaa, 0xcc, 0xee, 0x0d, 0x2f, 0x49, 0x6b, 0x85, 0xa7, 0xc1, 0xe3 }, + }, + { + { 0x00, 0xb0, 0x7d, 0xcd, 0xfa, 0x4a, 0x87, 0x37, 0xe9, 0x59, 0x94, 0x24, 0x13, 0xa3, 0x6e, 0xde }, + { 0x00, 0xcf, 0x83, 0x4c, 0x1b, 0xd4, 0x98, 0x57, 0x36, 0xf9, 0xb5, 0x7a, 0x2d, 0xe2, 0xae, 0x61 }, + }, + { + { 0x00, 0xb1, 0x7f, 0xce, 0xfe, 0x4f, 0x81, 0x30, 0xe1, 0x50, 0x9e, 0x2f, 0x1f, 0xae, 0x60, 0xd1 }, + { 0x00, 0xdf, 0xa3, 0x7c, 0x5b, 0x84, 0xf8, 0x27, 0xb6, 0x69, 0x15, 0xca, 0xed, 0x32, 0x4e, 0x91 }, + }, + { + { 0x00, 0xb2, 0x79, 0xcb, 0xf2, 0x40, 0x8b, 0x39, 0xf9, 0x4b, 0x80, 0x32, 0x0b, 0xb9, 0x72, 0xc0 }, + { 0x00, 0xef, 0xc3, 0x2c, 0x9b, 0x74, 0x58, 0xb7, 0x2b, 0xc4, 0xe8, 0x07, 0xb0, 0x5f, 0x73, 0x9c }, + }, + { + { 0x00, 0xb3, 0x7b, 0xc8, 0xf6, 0x45, 0x8d, 0x3e, 0xf1, 0x42, 0x8a, 0x39, 0x07, 0xb4, 0x7c, 0xcf }, + { 0x00, 0xff, 0xe3, 0x1c, 0xdb, 0x24, 0x38, 0xc7, 0xab, 0x54, 0x48, 0xb7, 0x70, 0x8f, 0x93, 0x6c }, + }, + { + { 0x00, 0xb4, 0x75, 0xc1, 0xea, 0x5e, 0x9f, 0x2b, 0xc9, 0x7d, 0xbc, 0x08, 0x23, 0x97, 0x56, 0xe2 }, + { 0x00, 0x8f, 0x03, 0x8c, 0x06, 0x89, 0x05, 0x8a, 0x0c, 0x83, 0x0f, 0x80, 0x0a, 0x85, 0x09, 0x86 }, + }, + { + { 0x00, 0xb5, 0x77, 0xc2, 0xee, 0x5b, 0x99, 0x2c, 0xc1, 0x74, 0xb6, 0x03, 0x2f, 0x9a, 0x58, 0xed }, + { 0x00, 0x9f, 0x23, 0xbc, 0x46, 0xd9, 0x65, 0xfa, 0x8c, 0x13, 0xaf, 0x30, 0xca, 0x55, 0xe9, 0x76 }, + }, + { + { 0x00, 0xb6, 0x71, 0xc7, 0xe2, 0x54, 0x93, 0x25, 0xd9, 0x6f, 0xa8, 0x1e, 0x3b, 0x8d, 0x4a, 0xfc }, + { 0x00, 0xaf, 0x43, 0xec, 0x86, 0x29, 0xc5, 0x6a, 0x11, 0xbe, 0x52, 0xfd, 0x97, 0x38, 0xd4, 0x7b }, + }, + { + { 0x00, 0xb7, 0x73, 0xc4, 0xe6, 0x51, 0x95, 0x22, 0xd1, 0x66, 0xa2, 0x15, 0x37, 0x80, 0x44, 0xf3 }, + { 0x00, 0xbf, 0x63, 0xdc, 0xc6, 0x79, 0xa5, 0x1a, 0x91, 0x2e, 0xf2, 0x4d, 0x57, 0xe8, 0x34, 0x8b }, + }, + { + { 0x00, 0xb8, 0x6d, 0xd5, 0xda, 0x62, 0xb7, 0x0f, 0xa9, 0x11, 0xc4, 0x7c, 0x73, 0xcb, 0x1e, 0xa6 }, + { 0x00, 0x4f, 0x9e, 0xd1, 0x21, 0x6e, 0xbf, 0xf0, 0x42, 0x0d, 0xdc, 0x93, 0x63, 0x2c, 0xfd, 0xb2 }, + }, + { + { 0x00, 0xb9, 0x6f, 0xd6, 0xde, 0x67, 0xb1, 0x08, 0xa1, 0x18, 0xce, 0x77, 0x7f, 0xc6, 0x10, 0xa9 }, + { 0x00, 0x5f, 0xbe, 0xe1, 0x61, 0x3e, 0xdf, 0x80, 0xc2, 0x9d, 0x7c, 0x23, 0xa3, 0xfc, 0x1d, 0x42 }, + }, + { + { 0x00, 0xba, 0x69, 0xd3, 0xd2, 0x68, 0xbb, 0x01, 0xb9, 0x03, 0xd0, 0x6a, 0x6b, 0xd1, 0x02, 0xb8 }, + { 0x00, 0x6f, 0xde, 0xb1, 0xa1, 0xce, 0x7f, 0x10, 0x5f, 0x30, 0x81, 0xee, 0xfe, 0x91, 0x20, 0x4f }, + }, + { + { 0x00, 0xbb, 0x6b, 0xd0, 0xd6, 0x6d, 0xbd, 0x06, 0xb1, 0x0a, 0xda, 0x61, 0x67, 0xdc, 0x0c, 0xb7 }, + { 0x00, 0x7f, 0xfe, 0x81, 0xe1, 0x9e, 0x1f, 0x60, 0xdf, 0xa0, 0x21, 0x5e, 0x3e, 0x41, 0xc0, 0xbf }, + }, + { + { 0x00, 0xbc, 0x65, 0xd9, 0xca, 0x76, 0xaf, 0x13, 0x89, 0x35, 0xec, 0x50, 0x43, 0xff, 0x26, 0x9a }, + { 0x00, 0x0f, 0x1e, 0x11, 0x3c, 0x33, 0x22, 0x2d, 0x78, 0x77, 0x66, 0x69, 0x44, 0x4b, 0x5a, 0x55 }, + }, + { + { 0x00, 0xbd, 0x67, 0xda, 0xce, 0x73, 0xa9, 0x14, 0x81, 0x3c, 0xe6, 0x5b, 0x4f, 0xf2, 0x28, 0x95 }, + { 0x00, 0x1f, 0x3e, 0x21, 0x7c, 0x63, 0x42, 0x5d, 0xf8, 0xe7, 0xc6, 0xd9, 0x84, 0x9b, 0xba, 0xa5 }, + }, + { + { 0x00, 0xbe, 0x61, 0xdf, 0xc2, 0x7c, 0xa3, 0x1d, 0x99, 0x27, 0xf8, 0x46, 0x5b, 0xe5, 0x3a, 0x84 }, + { 0x00, 0x2f, 0x5e, 0x71, 0xbc, 0x93, 0xe2, 0xcd, 0x65, 0x4a, 0x3b, 0x14, 0xd9, 0xf6, 0x87, 0xa8 }, + }, + { + { 0x00, 0xbf, 0x63, 0xdc, 0xc6, 0x79, 0xa5, 0x1a, 0x91, 0x2e, 0xf2, 0x4d, 0x57, 0xe8, 0x34, 0x8b }, + { 0x00, 0x3f, 0x7e, 0x41, 0xfc, 0xc3, 0x82, 0xbd, 0xe5, 0xda, 0x9b, 0xa4, 0x19, 0x26, 0x67, 0x58 }, + }, + { + { 0x00, 0xc0, 0x9d, 0x5d, 0x27, 0xe7, 0xba, 0x7a, 0x4e, 0x8e, 0xd3, 0x13, 0x69, 0xa9, 0xf4, 0x34 }, + { 0x00, 0x9c, 0x25, 0xb9, 0x4a, 0xd6, 0x6f, 0xf3, 0x94, 0x08, 0xb1, 0x2d, 0xde, 0x42, 0xfb, 0x67 }, + }, + { + { 0x00, 0xc1, 0x9f, 0x5e, 0x23, 0xe2, 0xbc, 0x7d, 0x46, 0x87, 0xd9, 0x18, 0x65, 0xa4, 0xfa, 0x3b }, + { 0x00, 0x8c, 0x05, 0x89, 0x0a, 0x86, 0x0f, 0x83, 0x14, 0x98, 0x11, 0x9d, 0x1e, 0x92, 0x1b, 0x97 }, + }, + { + { 0x00, 0xc2, 0x99, 0x5b, 0x2f, 0xed, 0xb6, 0x74, 0x5e, 0x9c, 0xc7, 0x05, 0x71, 0xb3, 0xe8, 0x2a }, + { 0x00, 0xbc, 0x65, 0xd9, 0xca, 0x76, 0xaf, 0x13, 0x89, 0x35, 0xec, 0x50, 0x43, 0xff, 0x26, 0x9a }, + }, + { + { 0x00, 0xc3, 0x9b, 0x58, 0x2b, 0xe8, 0xb0, 0x73, 0x56, 0x95, 0xcd, 0x0e, 0x7d, 0xbe, 0xe6, 0x25 }, + { 0x00, 0xac, 0x45, 0xe9, 0x8a, 0x26, 0xcf, 0x63, 0x09, 0xa5, 0x4c, 0xe0, 0x83, 0x2f, 0xc6, 0x6a }, + }, + { + { 0x00, 0xc4, 0x95, 0x51, 0x37, 0xf3, 0xa2, 0x66, 0x6e, 0xaa, 0xfb, 0x3f, 0x59, 0x9d, 0xcc, 0x08 }, + { 0x00, 0xdc, 0xa5, 0x79, 0x57, 0x8b, 0xf2, 0x2e, 0xae, 0x72, 0x0b, 0xd7, 0xf9, 0x25, 0x5c, 0x80 }, + }, + { + { 0x00, 0xc5, 0x97, 0x52, 0x33, 0xf6, 0xa4, 0x61, 0x66, 0xa3, 0xf1, 0x34, 0x55, 0x90, 0xc2, 0x07 }, + { 0x00, 0xcc, 0x85, 0x49, 0x17, 0xdb, 0x92, 0x5e, 0x2e, 0xe2, 0xab, 0x67, 0x39, 0xf5, 0xbc, 0x70 }, + }, + { + { 0x00, 0xc6, 0x91, 0x57, 0x3f, 0xf9, 0xae, 0x68, 0x7e, 0xb8, 0xef, 0x29, 0x41, 0x87, 0xd0, 0x16 }, + { 0x00, 0xfc, 0xe5, 0x19, 0xd7, 0x2b, 0x32, 0xce, 0xb3, 0x4f, 0x56, 0xaa, 0x64, 0x98, 0x81, 0x7d }, + }, + { + { 0x00, 0xc7, 0x93, 0x54, 0x3b, 0xfc, 0xa8, 0x6f, 0x76, 0xb1, 0xe5, 0x22, 0x4d, 0x8a, 0xde, 0x19 }, + { 0x00, 0xec, 0xc5, 0x29, 0x97, 0x7b, 0x52, 0xbe, 0x33, 0xdf, 0xf6, 0x1a, 0xa4, 0x48, 0x61, 0x8d }, + }, + { + { 0x00, 0xc8, 0x8d, 0x45, 0x07, 0xcf, 0x8a, 0x42, 0x0e, 0xc6, 0x83, 0x4b, 0x09, 0xc1, 0x84, 0x4c }, + { 0x00, 0x1c, 0x38, 0x24, 0x70, 0x6c, 0x48, 0x54, 0xe0, 0xfc, 0xd8, 0xc4, 0x90, 0x8c, 0xa8, 0xb4 }, + }, + { + { 0x00, 0xc9, 0x8f, 0x46, 0x03, 0xca, 0x8c, 0x45, 0x06, 0xcf, 0x89, 0x40, 0x05, 0xcc, 0x8a, 0x43 }, + { 0x00, 0x0c, 0x18, 0x14, 0x30, 0x3c, 0x28, 0x24, 0x60, 0x6c, 0x78, 0x74, 0x50, 0x5c, 0x48, 0x44 }, + }, + { + { 0x00, 0xca, 0x89, 0x43, 0x0f, 0xc5, 0x86, 0x4c, 0x1e, 0xd4, 0x97, 0x5d, 0x11, 0xdb, 0x98, 0x52 }, + { 0x00, 0x3c, 0x78, 0x44, 0xf0, 0xcc, 0x88, 0xb4, 0xfd, 0xc1, 0x85, 0xb9, 0x0d, 0x31, 0x75, 0x49 }, + }, + { + { 0x00, 0xcb, 0x8b, 0x40, 0x0b, 0xc0, 0x80, 0x4b, 0x16, 0xdd, 0x9d, 0x56, 0x1d, 0xd6, 0x96, 0x5d }, + { 0x00, 0x2c, 0x58, 0x74, 0xb0, 0x9c, 0xe8, 0xc4, 0x7d, 0x51, 0x25, 0x09, 0xcd, 0xe1, 0x95, 0xb9 }, + }, + { + { 0x00, 0xcc, 0x85, 0x49, 0x17, 0xdb, 0x92, 0x5e, 0x2e, 0xe2, 0xab, 0x67, 0x39, 0xf5, 0xbc, 0x70 }, + { 0x00, 0x5c, 0xb8, 0xe4, 0x6d, 0x31, 0xd5, 0x89, 0xda, 0x86, 0x62, 0x3e, 0xb7, 0xeb, 0x0f, 0x53 }, + }, + { + { 0x00, 0xcd, 0x87, 0x4a, 0x13, 0xde, 0x94, 0x59, 0x26, 0xeb, 0xa1, 0x6c, 0x35, 0xf8, 0xb2, 0x7f }, + { 0x00, 0x4c, 0x98, 0xd4, 0x2d, 0x61, 0xb5, 0xf9, 0x5a, 0x16, 0xc2, 0x8e, 0x77, 0x3b, 0xef, 0xa3 }, + }, + { + { 0x00, 0xce, 0x81, 0x4f, 0x1f, 0xd1, 0x9e, 0x50, 0x3e, 0xf0, 0xbf, 0x71, 0x21, 0xef, 0xa0, 0x6e }, + { 0x00, 0x7c, 0xf8, 0x84, 0xed, 0x91, 0x15, 0x69, 0xc7, 0xbb, 0x3f, 0x43, 0x2a, 0x56, 0xd2, 0xae }, + }, + { + { 0x00, 0xcf, 0x83, 0x4c, 0x1b, 0xd4, 0x98, 0x57, 0x36, 0xf9, 0xb5, 0x7a, 0x2d, 0xe2, 0xae, 0x61 }, + { 0x00, 0x6c, 0xd8, 0xb4, 0xad, 0xc1, 0x75, 0x19, 0x47, 0x2b, 0x9f, 0xf3, 0xea, 0x86, 0x32, 0x5e }, + }, + { + { 0x00, 0xd0, 0xbd, 0x6d, 0x67, 0xb7, 0xda, 0x0a, 0xce, 0x1e, 0x73, 0xa3, 0xa9, 0x79, 0x14, 0xc4 }, + { 0x00, 0x81, 0x1f, 0x9e, 0x3e, 0xbf, 0x21, 0xa0, 0x7c, 0xfd, 0x63, 0xe2, 0x42, 0xc3, 0x5d, 0xdc }, + }, + { + { 0x00, 0xd1, 0xbf, 0x6e, 0x63, 0xb2, 0xdc, 0x0d, 0xc6, 0x17, 0x79, 0xa8, 0xa5, 0x74, 0x1a, 0xcb }, + { 0x00, 0x91, 0x3f, 0xae, 0x7e, 0xef, 0x41, 0xd0, 0xfc, 0x6d, 0xc3, 0x52, 0x82, 0x13, 0xbd, 0x2c }, + }, + { + { 0x00, 0xd2, 0xb9, 0x6b, 0x6f, 0xbd, 0xd6, 0x04, 0xde, 0x0c, 0x67, 0xb5, 0xb1, 0x63, 0x08, 0xda }, + { 0x00, 0xa1, 0x5f, 0xfe, 0xbe, 0x1f, 0xe1, 0x40, 0x61, 0xc0, 0x3e, 0x9f, 0xdf, 0x7e, 0x80, 0x21 }, + }, + { + { 0x00, 0xd3, 0xbb, 0x68, 0x6b, 0xb8, 0xd0, 0x03, 0xd6, 0x05, 0x6d, 0xbe, 0xbd, 0x6e, 0x06, 0xd5 }, + { 0x00, 0xb1, 0x7f, 0xce, 0xfe, 0x4f, 0x81, 0x30, 0xe1, 0x50, 0x9e, 0x2f, 0x1f, 0xae, 0x60, 0xd1 }, + }, + { + { 0x00, 0xd4, 0xb5, 0x61, 0x77, 0xa3, 0xc2, 0x16, 0xee, 0x3a, 0x5b, 0x8f, 0x99, 0x4d, 0x2c, 0xf8 }, + { 0x00, 0xc1, 0x9f, 0x5e, 0x23, 0xe2, 0xbc, 0x7d, 0x46, 0x87, 0xd9, 0x18, 0x65, 0xa4, 0xfa, 0x3b }, + }, + { + { 0x00, 0xd5, 0xb7, 0x62, 0x73, 0xa6, 0xc4, 0x11, 0xe6, 0x33, 0x51, 0x84, 0x95, 0x40, 0x22, 0xf7 }, + { 0x00, 0xd1, 0xbf, 0x6e, 0x63, 0xb2, 0xdc, 0x0d, 0xc6, 0x17, 0x79, 0xa8, 0xa5, 0x74, 0x1a, 0xcb }, + }, + { + { 0x00, 0xd6, 0xb1, 0x67, 0x7f, 0xa9, 0xce, 0x18, 0xfe, 0x28, 0x4f, 0x99, 0x81, 0x57, 0x30, 0xe6 }, + { 0x00, 0xe1, 0xdf, 0x3e, 0xa3, 0x42, 0x7c, 0x9d, 0x5b, 0xba, 0x84, 0x65, 0xf8, 0x19, 0x27, 0xc6 }, + }, + { + { 0x00, 0xd7, 0xb3, 0x64, 0x7b, 0xac, 0xc8, 0x1f, 0xf6, 0x21, 0x45, 0x92, 0x8d, 0x5a, 0x3e, 0xe9 }, + { 0x00, 0xf1, 0xff, 0x0e, 0xe3, 0x12, 0x1c, 0xed, 0xdb, 0x2a, 0x24, 0xd5, 0x38, 0xc9, 0xc7, 0x36 }, + }, + { + { 0x00, 0xd8, 0xad, 0x75, 0x47, 0x9f, 0xea, 0x32, 0x8e, 0x56, 0x23, 0xfb, 0xc9, 0x11, 0x64, 0xbc }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, + }, + { + { 0x00, 0xd9, 0xaf, 0x76, 0x43, 0x9a, 0xec, 0x35, 0x86, 0x5f, 0x29, 0xf0, 0xc5, 0x1c, 0x6a, 0xb3 }, + { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + }, + { + { 0x00, 0xda, 0xa9, 0x73, 0x4f, 0x95, 0xe6, 0x3c, 0x9e, 0x44, 0x37, 0xed, 0xd1, 0x0b, 0x78, 0xa2 }, + { 0x00, 0x21, 0x42, 0x63, 0x84, 0xa5, 0xc6, 0xe7, 0x15, 0x34, 0x57, 0x76, 0x91, 0xb0, 0xd3, 0xf2 }, + }, + { + { 0x00, 0xdb, 0xab, 0x70, 0x4b, 0x90, 0xe0, 0x3b, 0x96, 0x4d, 0x3d, 0xe6, 0xdd, 0x06, 0x76, 0xad }, + { 0x00, 0x31, 0x62, 0x53, 0xc4, 0xf5, 0xa6, 0x97, 0x95, 0xa4, 0xf7, 0xc6, 0x51, 0x60, 0x33, 0x02 }, + }, + { + { 0x00, 0xdc, 0xa5, 0x79, 0x57, 0x8b, 0xf2, 0x2e, 0xae, 0x72, 0x0b, 0xd7, 0xf9, 0x25, 0x5c, 0x80 }, + { 0x00, 0x41, 0x82, 0xc3, 0x19, 0x58, 0x9b, 0xda, 0x32, 0x73, 0xb0, 0xf1, 0x2b, 0x6a, 0xa9, 0xe8 }, + }, + { + { 0x00, 0xdd, 0xa7, 0x7a, 0x53, 0x8e, 0xf4, 0x29, 0xa6, 0x7b, 0x01, 0xdc, 0xf5, 0x28, 0x52, 0x8f }, + { 0x00, 0x51, 0xa2, 0xf3, 0x59, 0x08, 0xfb, 0xaa, 0xb2, 0xe3, 0x10, 0x41, 0xeb, 0xba, 0x49, 0x18 }, + }, + { + { 0x00, 0xde, 0xa1, 0x7f, 0x5f, 0x81, 0xfe, 0x20, 0xbe, 0x60, 0x1f, 0xc1, 0xe1, 0x3f, 0x40, 0x9e }, + { 0x00, 0x61, 0xc2, 0xa3, 0x99, 0xf8, 0x5b, 0x3a, 0x2f, 0x4e, 0xed, 0x8c, 0xb6, 0xd7, 0x74, 0x15 }, + }, + { + { 0x00, 0xdf, 0xa3, 0x7c, 0x5b, 0x84, 0xf8, 0x27, 0xb6, 0x69, 0x15, 0xca, 0xed, 0x32, 0x4e, 0x91 }, + { 0x00, 0x71, 0xe2, 0x93, 0xd9, 0xa8, 0x3b, 0x4a, 0xaf, 0xde, 0x4d, 0x3c, 0x76, 0x07, 0x94, 0xe5 }, + }, + { + { 0x00, 0xe0, 0xdd, 0x3d, 0xa7, 0x47, 0x7a, 0x9a, 0x53, 0xb3, 0x8e, 0x6e, 0xf4, 0x14, 0x29, 0xc9 }, + { 0x00, 0xa6, 0x51, 0xf7, 0xa2, 0x04, 0xf3, 0x55, 0x59, 0xff, 0x08, 0xae, 0xfb, 0x5d, 0xaa, 0x0c }, + }, + { + { 0x00, 0xe1, 0xdf, 0x3e, 0xa3, 0x42, 0x7c, 0x9d, 0x5b, 0xba, 0x84, 0x65, 0xf8, 0x19, 0x27, 0xc6 }, + { 0x00, 0xb6, 0x71, 0xc7, 0xe2, 0x54, 0x93, 0x25, 0xd9, 0x6f, 0xa8, 0x1e, 0x3b, 0x8d, 0x4a, 0xfc }, + }, + { + { 0x00, 0xe2, 0xd9, 0x3b, 0xaf, 0x4d, 0x76, 0x94, 0x43, 0xa1, 0x9a, 0x78, 0xec, 0x0e, 0x35, 0xd7 }, + { 0x00, 0x86, 0x11, 0x97, 0x22, 0xa4, 0x33, 0xb5, 0x44, 0xc2, 0x55, 0xd3, 0x66, 0xe0, 0x77, 0xf1 }, + }, + { + { 0x00, 0xe3, 0xdb, 0x38, 0xab, 0x48, 0x70, 0x93, 0x4b, 0xa8, 0x90, 0x73, 0xe0, 0x03, 0x3b, 0xd8 }, + { 0x00, 0x96, 0x31, 0xa7, 0x62, 0xf4, 0x53, 0xc5, 0xc4, 0x52, 0xf5, 0x63, 0xa6, 0x30, 0x97, 0x01 }, + }, + { + { 0x00, 0xe4, 0xd5, 0x31, 0xb7, 0x53, 0x62, 0x86, 0x73, 0x97, 0xa6, 0x42, 0xc4, 0x20, 0x11, 0xf5 }, + { 0x00, 0xe6, 0xd1, 0x37, 0xbf, 0x59, 0x6e, 0x88, 0x63, 0x85, 0xb2, 0x54, 0xdc, 0x3a, 0x0d, 0xeb }, + }, + { + { 0x00, 0xe5, 0xd7, 0x32, 0xb3, 0x56, 0x64, 0x81, 0x7b, 0x9e, 0xac, 0x49, 0xc8, 0x2d, 0x1f, 0xfa }, + { 0x00, 0xf6, 0xf1, 0x07, 0xff, 0x09, 0x0e, 0xf8, 0xe3, 0x15, 0x12, 0xe4, 0x1c, 0xea, 0xed, 0x1b }, + }, + { + { 0x00, 0xe6, 0xd1, 0x37, 0xbf, 0x59, 0x6e, 0x88, 0x63, 0x85, 0xb2, 0x54, 0xdc, 0x3a, 0x0d, 0xeb }, + { 0x00, 0xc6, 0x91, 0x57, 0x3f, 0xf9, 0xae, 0x68, 0x7e, 0xb8, 0xef, 0x29, 0x41, 0x87, 0xd0, 0x16 }, + }, + { + { 0x00, 0xe7, 0xd3, 0x34, 0xbb, 0x5c, 0x68, 0x8f, 0x6b, 0x8c, 0xb8, 0x5f, 0xd0, 0x37, 0x03, 0xe4 }, + { 0x00, 0xd6, 0xb1, 0x67, 0x7f, 0xa9, 0xce, 0x18, 0xfe, 0x28, 0x4f, 0x99, 0x81, 0x57, 0x30, 0xe6 }, + }, + { + { 0x00, 0xe8, 0xcd, 0x25, 0x87, 0x6f, 0x4a, 0xa2, 0x13, 0xfb, 0xde, 0x36, 0x94, 0x7c, 0x59, 0xb1 }, + { 0x00, 0x26, 0x4c, 0x6a, 0x98, 0xbe, 0xd4, 0xf2, 0x2d, 0x0b, 0x61, 0x47, 0xb5, 0x93, 0xf9, 0xdf }, + }, + { + { 0x00, 0xe9, 0xcf, 0x26, 0x83, 0x6a, 0x4c, 0xa5, 0x1b, 0xf2, 0xd4, 0x3d, 0x98, 0x71, 0x57, 0xbe }, + { 0x00, 0x36, 0x6c, 0x5a, 0xd8, 0xee, 0xb4, 0x82, 0xad, 0x9b, 0xc1, 0xf7, 0x75, 0x43, 0x19, 0x2f }, + }, + { + { 0x00, 0xea, 0xc9, 0x23, 0x8f, 0x65, 0x46, 0xac, 0x03, 0xe9, 0xca, 0x20, 0x8c, 0x66, 0x45, 0xaf }, + { 0x00, 0x06, 0x0c, 0x0a, 0x18, 0x1e, 0x14, 0x12, 0x30, 0x36, 0x3c, 0x3a, 0x28, 0x2e, 0x24, 0x22 }, + }, + { + { 0x00, 0xeb, 0xcb, 0x20, 0x8b, 0x60, 0x40, 0xab, 0x0b, 0xe0, 0xc0, 0x2b, 0x80, 0x6b, 0x4b, 0xa0 }, + { 0x00, 0x16, 0x2c, 0x3a, 0x58, 0x4e, 0x74, 0x62, 0xb0, 0xa6, 0x9c, 0x8a, 0xe8, 0xfe, 0xc4, 0xd2 }, + }, + { + { 0x00, 0xec, 0xc5, 0x29, 0x97, 0x7b, 0x52, 0xbe, 0x33, 0xdf, 0xf6, 0x1a, 0xa4, 0x48, 0x61, 0x8d }, + { 0x00, 0x66, 0xcc, 0xaa, 0x85, 0xe3, 0x49, 0x2f, 0x17, 0x71, 0xdb, 0xbd, 0x92, 0xf4, 0x5e, 0x38 }, + }, + { + { 0x00, 0xed, 0xc7, 0x2a, 0x93, 0x7e, 0x54, 0xb9, 0x3b, 0xd6, 0xfc, 0x11, 0xa8, 0x45, 0x6f, 0x82 }, + { 0x00, 0x76, 0xec, 0x9a, 0xc5, 0xb3, 0x29, 0x5f, 0x97, 0xe1, 0x7b, 0x0d, 0x52, 0x24, 0xbe, 0xc8 }, + }, + { + { 0x00, 0xee, 0xc1, 0x2f, 0x9f, 0x71, 0x5e, 0xb0, 0x23, 0xcd, 0xe2, 0x0c, 0xbc, 0x52, 0x7d, 0x93 }, + { 0x00, 0x46, 0x8c, 0xca, 0x05, 0x43, 0x89, 0xcf, 0x0a, 0x4c, 0x86, 0xc0, 0x0f, 0x49, 0x83, 0xc5 }, + }, + { + { 0x00, 0xef, 0xc3, 0x2c, 0x9b, 0x74, 0x58, 0xb7, 0x2b, 0xc4, 0xe8, 0x07, 0xb0, 0x5f, 0x73, 0x9c }, + { 0x00, 0x56, 0xac, 0xfa, 0x45, 0x13, 0xe9, 0xbf, 0x8a, 0xdc, 0x26, 0x70, 0xcf, 0x99, 0x63, 0x35 }, + }, + { + { 0x00, 0xf0, 0xfd, 0x0d, 0xe7, 0x17, 0x1a, 0xea, 0xd3, 0x23, 0x2e, 0xde, 0x34, 0xc4, 0xc9, 0x39 }, + { 0x00, 0xbb, 0x6b, 0xd0, 0xd6, 0x6d, 0xbd, 0x06, 0xb1, 0x0a, 0xda, 0x61, 0x67, 0xdc, 0x0c, 0xb7 }, + }, + { + { 0x00, 0xf1, 0xff, 0x0e, 0xe3, 0x12, 0x1c, 0xed, 0xdb, 0x2a, 0x24, 0xd5, 0x38, 0xc9, 0xc7, 0x36 }, + { 0x00, 0xab, 0x4b, 0xe0, 0x96, 0x3d, 0xdd, 0x76, 0x31, 0x9a, 0x7a, 0xd1, 0xa7, 0x0c, 0xec, 0x47 }, + }, + { + { 0x00, 0xf2, 0xf9, 0x0b, 0xef, 0x1d, 0x16, 0xe4, 0xc3, 0x31, 0x3a, 0xc8, 0x2c, 0xde, 0xd5, 0x27 }, + { 0x00, 0x9b, 0x2b, 0xb0, 0x56, 0xcd, 0x7d, 0xe6, 0xac, 0x37, 0x87, 0x1c, 0xfa, 0x61, 0xd1, 0x4a }, + }, + { + { 0x00, 0xf3, 0xfb, 0x08, 0xeb, 0x18, 0x10, 0xe3, 0xcb, 0x38, 0x30, 0xc3, 0x20, 0xd3, 0xdb, 0x28 }, + { 0x00, 0x8b, 0x0b, 0x80, 0x16, 0x9d, 0x1d, 0x96, 0x2c, 0xa7, 0x27, 0xac, 0x3a, 0xb1, 0x31, 0xba }, + }, + { + { 0x00, 0xf4, 0xf5, 0x01, 0xf7, 0x03, 0x02, 0xf6, 0xf3, 0x07, 0x06, 0xf2, 0x04, 0xf0, 0xf1, 0x05 }, + { 0x00, 0xfb, 0xeb, 0x10, 0xcb, 0x30, 0x20, 0xdb, 0x8b, 0x70, 0x60, 0x9b, 0x40, 0xbb, 0xab, 0x50 }, + }, + { + { 0x00, 0xf5, 0xf7, 0x02, 0xf3, 0x06, 0x04, 0xf1, 0xfb, 0x0e, 0x0c, 0xf9, 0x08, 0xfd, 0xff, 0x0a }, + { 0x00, 0xeb, 0xcb, 0x20, 0x8b, 0x60, 0x40, 0xab, 0x0b, 0xe0, 0xc0, 0x2b, 0x80, 0x6b, 0x4b, 0xa0 }, + }, + { + { 0x00, 0xf6, 0xf1, 0x07, 0xff, 0x09, 0x0e, 0xf8, 0xe3, 0x15, 0x12, 0xe4, 0x1c, 0xea, 0xed, 0x1b }, + { 0x00, 0xdb, 0xab, 0x70, 0x4b, 0x90, 0xe0, 0x3b, 0x96, 0x4d, 0x3d, 0xe6, 0xdd, 0x06, 0x76, 0xad }, + }, + { + { 0x00, 0xf7, 0xf3, 0x04, 0xfb, 0x0c, 0x08, 0xff, 0xeb, 0x1c, 0x18, 0xef, 0x10, 0xe7, 0xe3, 0x14 }, + { 0x00, 0xcb, 0x8b, 0x40, 0x0b, 0xc0, 0x80, 0x4b, 0x16, 0xdd, 0x9d, 0x56, 0x1d, 0xd6, 0x96, 0x5d }, + }, + { + { 0x00, 0xf8, 0xed, 0x15, 0xc7, 0x3f, 0x2a, 0xd2, 0x93, 0x6b, 0x7e, 0x86, 0x54, 0xac, 0xb9, 0x41 }, + { 0x00, 0x3b, 0x76, 0x4d, 0xec, 0xd7, 0x9a, 0xa1, 0xc5, 0xfe, 0xb3, 0x88, 0x29, 0x12, 0x5f, 0x64 }, + }, + { + { 0x00, 0xf9, 0xef, 0x16, 0xc3, 0x3a, 0x2c, 0xd5, 0x9b, 0x62, 0x74, 0x8d, 0x58, 0xa1, 0xb7, 0x4e }, + { 0x00, 0x2b, 0x56, 0x7d, 0xac, 0x87, 0xfa, 0xd1, 0x45, 0x6e, 0x13, 0x38, 0xe9, 0xc2, 0xbf, 0x94 }, + }, + { + { 0x00, 0xfa, 0xe9, 0x13, 0xcf, 0x35, 0x26, 0xdc, 0x83, 0x79, 0x6a, 0x90, 0x4c, 0xb6, 0xa5, 0x5f }, + { 0x00, 0x1b, 0x36, 0x2d, 0x6c, 0x77, 0x5a, 0x41, 0xd8, 0xc3, 0xee, 0xf5, 0xb4, 0xaf, 0x82, 0x99 }, + }, + { + { 0x00, 0xfb, 0xeb, 0x10, 0xcb, 0x30, 0x20, 0xdb, 0x8b, 0x70, 0x60, 0x9b, 0x40, 0xbb, 0xab, 0x50 }, + { 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69 }, + }, + { + { 0x00, 0xfc, 0xe5, 0x19, 0xd7, 0x2b, 0x32, 0xce, 0xb3, 0x4f, 0x56, 0xaa, 0x64, 0x98, 0x81, 0x7d }, + { 0x00, 0x7b, 0xf6, 0x8d, 0xf1, 0x8a, 0x07, 0x7c, 0xff, 0x84, 0x09, 0x72, 0x0e, 0x75, 0xf8, 0x83 }, + }, + { + { 0x00, 0xfd, 0xe7, 0x1a, 0xd3, 0x2e, 0x34, 0xc9, 0xbb, 0x46, 0x5c, 0xa1, 0x68, 0x95, 0x8f, 0x72 }, + { 0x00, 0x6b, 0xd6, 0xbd, 0xb1, 0xda, 0x67, 0x0c, 0x7f, 0x14, 0xa9, 0xc2, 0xce, 0xa5, 0x18, 0x73 }, + }, + { + { 0x00, 0xfe, 0xe1, 0x1f, 0xdf, 0x21, 0x3e, 0xc0, 0xa3, 0x5d, 0x42, 0xbc, 0x7c, 0x82, 0x9d, 0x63 }, + { 0x00, 0x5b, 0xb6, 0xed, 0x71, 0x2a, 0xc7, 0x9c, 0xe2, 0xb9, 0x54, 0x0f, 0x93, 0xc8, 0x25, 0x7e }, + }, + { + { 0x00, 0xff, 0xe3, 0x1c, 0xdb, 0x24, 0x38, 0xc7, 0xab, 0x54, 0x48, 0xb7, 0x70, 0x8f, 0x93, 0x6c }, + { 0x00, 0x4b, 0x96, 0xdd, 0x31, 0x7a, 0xa7, 0xec, 0x62, 0x29, 0xf4, 0xbf, 0x53, 0x18, 0xc5, 0x8e }, + }, +}; +#endif + diff --git a/raid/tag.c b/raid/tag.c new file mode 100644 index 0000000..bfeefaa --- /dev/null +++ b/raid/tag.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 2 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. + */ + +#include "internal.h" + +static struct raid_func { + const char *name; + void (*p)(); +} RAID_FUNC[] = { + { "int8", raid_gen3_int8 }, + { "int8", raid_gen4_int8 }, + { "int8", raid_gen5_int8 }, + { "int8", raid_gen6_int8 }, + { "int32", raid_gen1_int32 }, + { "int64", raid_gen1_int64 }, + { "int32", raid_gen2_int32 }, + { "int64", raid_gen2_int64 }, + { "int32", raid_genz_int32 }, + { "int64", raid_genz_int64 }, + { "int8", raid_rec1_int8 }, + { "int8", raid_rec2_int8 }, + { "int8", raid_recX_int8 }, + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSE2 + { "sse2", raid_gen1_sse2 }, + { "sse2", raid_gen2_sse2 }, + { "sse2", raid_genz_sse2 }, +#endif +#ifdef CONFIG_SSSE3 + { "ssse3", raid_gen3_ssse3 }, + { "ssse3", raid_gen4_ssse3 }, + { "ssse3", raid_gen5_ssse3 }, + { "ssse3", raid_gen6_ssse3 }, + { "ssse3", raid_rec1_ssse3 }, + { "ssse3", raid_rec2_ssse3 }, + { "ssse3", raid_recX_ssse3 }, +#endif +#ifdef CONFIG_AVX2 + { "avx2", raid_gen1_avx2 }, + { "avx2", raid_gen2_avx2 }, + { "avx2", raid_rec1_avx2 }, + { "avx2", raid_rec2_avx2 }, + { "avx2", raid_recX_avx2 }, +#endif +#endif + +#ifdef CONFIG_X86_64 +#ifdef CONFIG_SSE2 + { "sse2e", raid_gen2_sse2ext }, + { "sse2e", raid_genz_sse2ext }, +#endif +#ifdef CONFIG_SSSE3 + { "ssse3e", raid_gen3_ssse3ext }, + { "ssse3e", raid_gen4_ssse3ext }, + { "ssse3e", raid_gen5_ssse3ext }, + { "ssse3e", raid_gen6_ssse3ext }, +#endif +#ifdef CONFIG_AVX2 + { "avx2e", raid_gen3_avx2ext }, + { "avx2e", raid_genz_avx2ext }, + { "avx2e", raid_gen4_avx2ext }, + { "avx2e", raid_gen5_avx2ext }, + { "avx2e", raid_gen6_avx2ext }, +#endif +#endif + { 0, 0 } +}; + +static const char *raid_tag(void (*func)()) +{ + struct raid_func *i = RAID_FUNC; + + while (i->name != 0) { + if (i->p == func) + return i->name; + ++i; + } + + /* LCOV_EXCL_START */ + return "unknown"; + /* LCOV_EXCL_STOP */ +} + +const char *raid_gen1_tag(void) +{ + return raid_tag(raid_gen_ptr[0]); +} + +const char *raid_gen2_tag(void) +{ + return raid_tag(raid_gen_ptr[1]); +} + +const char *raid_genz_tag(void) +{ + return raid_tag(raid_genz_ptr); +} + +const char *raid_gen3_tag(void) +{ + return raid_tag(raid_gen_ptr[2]); +} + +const char *raid_gen4_tag(void) +{ + return raid_tag(raid_gen_ptr[3]); +} + +const char *raid_gen5_tag(void) +{ + return raid_tag(raid_gen_ptr[4]); +} + +const char *raid_gen6_tag(void) +{ + return raid_tag(raid_gen_ptr[5]); +} + +const char *raid_rec1_tag(void) +{ + return raid_tag(raid_rec_ptr[0]); +} + +const char *raid_rec2_tag(void) +{ + return raid_tag(raid_rec_ptr[1]); +} + +const char *raid_recX_tag(void) +{ + return raid_tag(raid_rec_ptr[2]); +} + diff --git a/raid/test.c b/raid/test.c new file mode 100644 index 0000000..feb8a41 --- /dev/null +++ b/raid/test.c @@ -0,0 +1,452 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 2 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. + */ + +#include "internal.h" +#include "cpu.h" +#include "combo.h" +#include "memory.h" + +/** + * Binomial coefficient of n over r. + */ +static int ibc(int n, int r) +{ + if (r == 0 || n == r) + return 1; + else + return ibc(n - 1, r - 1) + ibc(n - 1, r); +} + +/** + * Power n ^ r; + */ +static int ipow(int n, int r) +{ + int v = 1; + + while (r) { + v *= n; + --r; + } + return v; +} + +int raid_test_combo(void) +{ + int r; + int count; + int p[RAID_PARITY_MAX]; + + for (r = 1; r <= RAID_PARITY_MAX; ++r) { + /* count combination (r of RAID_PARITY_MAX) elements */ + count = 0; + combination_first(r, RAID_PARITY_MAX, p); + + do { + ++count; + } while (combination_next(r, RAID_PARITY_MAX, p)); + + if (count != ibc(RAID_PARITY_MAX, r)) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + } + + for (r = 1; r <= RAID_PARITY_MAX; ++r) { + /* count permutation (r of RAID_PARITY_MAX) elements */ + count = 0; + permutation_first(r, RAID_PARITY_MAX, p); + + do { + ++count; + } while (permutation_next(r, RAID_PARITY_MAX, p)); + + if (count != ipow(RAID_PARITY_MAX, r)) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + } + + return 0; +} + +int raid_test_insert(void) +{ + int p[RAID_PARITY_MAX]; + int r; + + for (r = 1; r <= RAID_PARITY_MAX; ++r) { + permutation_first(r, RAID_PARITY_MAX, p); + do { + int i[RAID_PARITY_MAX]; + int j; + + /* insert in order */ + for (j = 0; j < r; ++j) + raid_insert(j, i, p[j]); + + /* check order */ + for (j = 1; j < r; ++j) { + if (i[j - 1] > i[j]) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + } + } while (permutation_next(r, RAID_PARITY_MAX, p)); + } + + return 0; +} + +int raid_test_sort(void) +{ + int p[RAID_PARITY_MAX]; + int r; + + for (r = 1; r <= RAID_PARITY_MAX; ++r) { + permutation_first(r, RAID_PARITY_MAX, p); + do { + int i[RAID_PARITY_MAX]; + int j; + + /* make a copy */ + for (j = 0; j < r; ++j) + i[j] = p[j]; + + raid_sort(r, i); + + /* check order */ + for (j = 1; j < r; ++j) { + if (i[j - 1] > i[j]) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + } + } while (permutation_next(r, RAID_PARITY_MAX, p)); + } + + return 0; +} + +int raid_test_rec(int mode, int nd, size_t size) +{ + void (*f[RAID_PARITY_MAX][4])( + int nr, int *id, int *ip, int nd, size_t size, void **vbuf); + void *v_alloc; + void **v; + void **data; + void **parity; + void **test; + void *data_save[RAID_PARITY_MAX]; + void *parity_save[RAID_PARITY_MAX]; + void *waste; + int nv; + int id[RAID_PARITY_MAX]; + int ip[RAID_PARITY_MAX]; + int i; + int j; + int nr; + int nf[RAID_PARITY_MAX]; + int np; + + raid_mode(mode); + if (mode == RAID_MODE_CAUCHY) + np = RAID_PARITY_MAX; + else + np = 3; + + nv = nd + np * 2 + 2; + + v = raid_malloc_vector(nd, nv, size, &v_alloc); + if (!v) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + + data = v; + parity = v + nd; + test = v + nd + np; + + for (i = 0; i < np; ++i) + parity_save[i] = parity[i]; + + memset(v[nv - 2], 0, size); + raid_zero(v[nv - 2]); + + waste = v[nv - 1]; + + /* fill with pseudo-random data with the arbitrary seed "1" */ + raid_mrand_vector(1, nd, size, v); + + /* setup recov functions */ + for (i = 0; i < np; ++i) { + nf[i] = 0; + if (i == 0) { + f[i][nf[i]++] = raid_rec1_int8; +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) + f[i][nf[i]++] = raid_rec1_ssse3; +#endif +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) + f[i][nf[i]++] = raid_rec1_avx2; +#endif +#endif + } else if (i == 1) { + f[i][nf[i]++] = raid_rec2_int8; +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) + f[i][nf[i]++] = raid_rec2_ssse3; +#endif +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) + f[i][nf[i]++] = raid_rec2_avx2; +#endif +#endif + } else { + f[i][nf[i]++] = raid_recX_int8; +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) + f[i][nf[i]++] = raid_recX_ssse3; +#endif +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) + f[i][nf[i]++] = raid_recX_avx2; +#endif +#endif + } + } + + /* compute the parity */ + raid_gen_ref(nd, np, size, v); + + /* set all the parity to the waste v */ + for (i = 0; i < np; ++i) + parity[i] = waste; + + /* all parity levels */ + for (nr = 1; nr <= np; ++nr) { + /* all combinations (nr of nd) disks */ + combination_first(nr, nd, id); + do { + /* all combinations (nr of np) parities */ + combination_first(nr, np, ip); + do { + /* for each recover function */ + for (j = 0; j < nf[nr - 1]; ++j) { + /* set */ + for (i = 0; i < nr; ++i) { + /* remove the missing data */ + data_save[i] = data[id[i]]; + data[id[i]] = test[i]; + /* set the parity to use */ + parity[ip[i]] = parity_save[ip[i]]; + } + + /* recover */ + f[nr - 1][j](nr, id, ip, nd, size, v); + + /* check */ + for (i = 0; i < nr; ++i) { + if (memcmp(test[i], data_save[i], size) != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + } + + /* restore */ + for (i = 0; i < nr; ++i) { + /* restore the data */ + data[id[i]] = data_save[i]; + /* restore the parity */ + parity[ip[i]] = waste; + } + } + } while (combination_next(nr, np, ip)); + } while (combination_next(nr, nd, id)); + } + + free(v_alloc); + free(v); + return 0; + +bail: + /* LCOV_EXCL_START */ + free(v_alloc); + free(v); + return -1; + /* LCOV_EXCL_STOP */ +} + +int raid_test_par(int mode, int nd, size_t size) +{ + void (*f[64])(int nd, size_t size, void **vbuf); + void *v_alloc; + void **v; + int nv; + int i, j; + int nf; + int np; + + raid_mode(mode); + if (mode == RAID_MODE_CAUCHY) + np = RAID_PARITY_MAX; + else + np = 3; + + nv = nd + np * 2; + + v = raid_malloc_vector(nd, nv, size, &v_alloc); + if (!v) { + /* LCOV_EXCL_START */ + return -1; + /* LCOV_EXCL_STOP */ + } + + /* check memory */ + if (raid_mtest_vector(nv, size, v) != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + /* fill with pseudo-random data with the arbitrary seed "2" */ + raid_mrand_vector(2, nv, size, v); + + /* compute the parity */ + raid_gen_ref(nd, np, size, v); + + /* copy in back buffers */ + for (i = 0; i < np; ++i) + memcpy(v[nd + np + i], v[nd + i], size); + + /* load all the available functions */ + nf = 0; + + f[nf++] = raid_gen1_int32; + f[nf++] = raid_gen1_int64; + f[nf++] = raid_gen2_int32; + f[nf++] = raid_gen2_int64; + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSE2 + if (raid_cpu_has_sse2()) { + f[nf++] = raid_gen1_sse2; + f[nf++] = raid_gen2_sse2; +#ifdef CONFIG_X86_64 + f[nf++] = raid_gen2_sse2ext; +#endif + } +#endif + +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + f[nf++] = raid_gen1_avx2; + f[nf++] = raid_gen2_avx2; + } +#endif +#endif /* CONFIG_X86 */ + + if (mode == RAID_MODE_CAUCHY) { + f[nf++] = raid_gen3_int8; + f[nf++] = raid_gen4_int8; + f[nf++] = raid_gen5_int8; + f[nf++] = raid_gen6_int8; + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) { + f[nf++] = raid_gen3_ssse3; + f[nf++] = raid_gen4_ssse3; + f[nf++] = raid_gen5_ssse3; + f[nf++] = raid_gen6_ssse3; +#ifdef CONFIG_X86_64 + f[nf++] = raid_gen3_ssse3ext; + f[nf++] = raid_gen4_ssse3ext; + f[nf++] = raid_gen5_ssse3ext; + f[nf++] = raid_gen6_ssse3ext; +#endif + } +#endif + +#ifdef CONFIG_AVX2 +#ifdef CONFIG_X86_64 + if (raid_cpu_has_avx2()) { + f[nf++] = raid_gen3_avx2ext; + f[nf++] = raid_gen4_avx2ext; + f[nf++] = raid_gen5_avx2ext; + f[nf++] = raid_gen6_avx2ext; + } +#endif +#endif +#endif /* CONFIG_X86 */ + } else { + f[nf++] = raid_genz_int32; + f[nf++] = raid_genz_int64; + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSE2 + if (raid_cpu_has_sse2()) { + f[nf++] = raid_genz_sse2; +#ifdef CONFIG_X86_64 + f[nf++] = raid_genz_sse2ext; +#endif + } +#endif + +#ifdef CONFIG_AVX2 +#ifdef CONFIG_X86_64 + if (raid_cpu_has_avx2()) + f[nf++] = raid_genz_avx2ext; +#endif +#endif +#endif /* CONFIG_X86 */ + } + + /* check all the functions */ + for (j = 0; j < nf; ++j) { + /* compute parity */ + f[j](nd, size, v); + + /* check it */ + for (i = 0; i < np; ++i) { + if (memcmp(v[nd + np + i], v[nd + i], size) != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + } + } + + free(v_alloc); + free(v); + return 0; + +bail: + /* LCOV_EXCL_START */ + free(v_alloc); + free(v); + return -1; + /* LCOV_EXCL_STOP */ +} + diff --git a/raid/test.h b/raid/test.h new file mode 100644 index 0000000..6d902c7 --- /dev/null +++ b/raid/test.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 2 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. + */ + +#ifndef __RAID_TEST_H +#define __RAID_TEST_H + +/** + * Tests insertion function. + * + * Test raid_insert() with all the possible combinations of elements to insert. + * + * Returns 0 on success. + */ +int raid_test_insert(void); + +/** + * Tests sorting function. + * + * Test raid_sort() with all the possible combinations of elements to sort. + * + * Returns 0 on success. + */ +int raid_test_sort(void); + +/** + * Tests combination functions. + * + * Tests combination_first() and combination_next() for all the parity levels. + * + * Returns 0 on success. + */ +int raid_test_combo(void); + +/** + * Tests recovering functions. + * + * All the recovering functions are tested with all the combinations + * of failing disks and recovering parities. + * + * Take care that the test time grows exponentially with the number of disks. + * + * Returns 0 on success. + */ +int raid_test_rec(unsigned mode, int nd, size_t size); + +/** + * Tests parity generation functions. + * + * All the parity generation functions are tested with the specified + * number of disks. + * + * Returns 0 on success. + */ +int raid_test_par(unsigned mode, int nd, size_t size); + +#endif + diff --git a/raid/test/Makefile b/raid/test/Makefile new file mode 100644 index 0000000..229d5ad --- /dev/null +++ b/raid/test/Makefile @@ -0,0 +1,99 @@ +# +# Test programs for the RAID library +# +# selftest - Runs the same selftest and speedtest executed at the module startup. +# fulltest - Runs a more extensive test that checks all the built-in functions. +# speetest - Runs a more complete speed test. +# invtest - Runs an extensive matrix inversion test of all the 377.342.351.231 +# possible square submatrices of the Cauchy matrix used. +# covtest - Runs a coverage test. +# sdecovtest - Runs a coverage test with the sde emulator. +# + +MACHINE = $(shell uname -m) +ifeq ($(MACHINE),i686) +SDE = sde +else +SDE = sde64 +endif +CC = gcc +LD = ld +CFLAGS = -I.. -Wall -Wextra -g +ifeq ($(COVERAGE),) +CFLAGS += -O2 +else +CFLAGS += -O0 --coverage -DCOVERAGE=1 -DNDEBUG=1 +endif +OBJS = raid.o check.o int.o intz.o x86.o x86z.o tables.o memory.o test.o helper.o module.o tag.o + +%.o: ../%.c + $(CC) $(CFLAGS) -c -o $@ $< + +all: fulltest speedtest selftest invtest + +fulltest: $(OBJS) fulltest.o + $(CC) $(CFLAGS) -o fulltest $^ + +speedtest: $(OBJS) speedtest.o + $(CC) $(CFLAGS) -o speedtest $^ + +selftest: $(OBJS) selftest.o + $(CC) $(CFLAGS) -o selftest $^ + +invtest: $(OBJS) invtest.o + $(CC) $(CFLAGS) -o invtest $^ + +mktables: mktables.o + $(CC) $(CFLAGS) -o mktables $^ + +tables.c: mktables + ./mktables > tables.c + +# Use this target to run a coverage test using lcov +covtest: + $(MAKE) clean + $(MAKE) lcov_reset + $(MAKE) COVERAGE=1 all + ./fulltest + ./selftest + ./speedtest + $(MAKE) lcov_capture + $(MAKE) lcov_html + +# Use this target to run a coverage test using lcov and the sde +sdecovtest: + $(MAKE) clean + $(MAKE) lcov_reset + $(MAKE) COVERAGE=1 all + $(SDE) -p4p -- ./fulltest + $(SDE) -mrm -- ./fulltest + $(SDE) -nhm -- ./fulltest + $(SDE) -hsw -- ./fulltest + $(SDE) -p4p -- ./selftest + $(SDE) -mrm -- ./selftest + $(SDE) -nhm -- ./selftest + $(SDE) -hsw -- ./selftest + $(SDE) -hsw -- ./speedtest + $(MAKE) lcov_capture + $(MAKE) lcov_html + +lcov_reset: + lcov --directory . -z + rm -f lcov.info + +lcov_capture: + lcov --directory . --capture --rc lcov_branch_coverage=1 -o lcov.info + +lcov_html: + rm -rf coverage + mkdir coverage + genhtml --branch-coverage -o coverage lcov.info + +clean: + rm -f *.o mktables tables.c + rm -f *.gcda *.gcno lcov.info + rm -rf coverage + +distclean: clean + rm -f fulltest speedtest selftest invtest + diff --git a/raid/test/fulltest.c b/raid/test/fulltest.c new file mode 100644 index 0000000..d484e5a --- /dev/null +++ b/raid/test/fulltest.c @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 2 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. + */ + +/* Full sanity test for the RAID library */ + +#include "internal.h" +#include "test.h" +#include "cpu.h" + +#include +#include + +/* + * Size of the blocks to test. + */ +#define TEST_SIZE 256 + +/** + * Number of disks in the long parity test. + */ +#ifdef COVERAGE +#define TEST_COUNT 10 +#else +#define TEST_COUNT 32 +#endif + +int main(void) +{ + printf("Full sanity test for the RAID Cauchy library\n\n"); + + raid_init(); + +#ifdef CONFIG_X86 + if (raid_cpu_has_sse2()) + printf("Including x86 SSE2 functions\n"); + if (raid_cpu_has_ssse3()) + printf("Including x86 SSSE3 functions\n"); + if (raid_cpu_has_avx2()) + printf("Including x86 AVX2 functions\n"); +#endif +#ifdef CONFIG_X86_64 + printf("Including x64 extended SSE register set\n"); +#endif + + printf("\nPlease wait about 60 seconds...\n\n"); + + printf("Test sorting...\n"); + if (raid_test_sort() != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + printf("Test insertion...\n"); + if (raid_test_insert() != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + printf("Test combinations/permutations...\n"); + if (raid_test_combo() != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + printf("Test Cauchy parity generation with %u data disks...\n", RAID_DATA_MAX); + if (raid_test_par(RAID_MODE_CAUCHY, RAID_DATA_MAX, TEST_SIZE) != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + printf("Test Cauchy parity generation with 1 data disk...\n"); + if (raid_test_par(RAID_MODE_CAUCHY, 1, TEST_SIZE) != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + printf("Test Cauchy recovering with all combinations of %u data and 6 parity blocks...\n", TEST_COUNT); + if (raid_test_rec(RAID_MODE_CAUCHY, TEST_COUNT, TEST_SIZE) != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + printf("Test Vandermonde parity generation with %u data disks...\n", RAID_DATA_MAX); + if (raid_test_par(RAID_MODE_VANDERMONDE, RAID_DATA_MAX, TEST_SIZE) != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + printf("Test Vandermonde recovering with all combinations of %u data and 3 parity blocks...\n", TEST_COUNT); + if (raid_test_rec(RAID_MODE_VANDERMONDE, TEST_COUNT, TEST_SIZE) != 0) { + /* LCOV_EXCL_START */ + goto bail; + /* LCOV_EXCL_STOP */ + } + + + printf("OK\n"); + return 0; + +bail: + /* LCOV_EXCL_START */ + printf("FAILED!\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ +} + diff --git a/raid/test/invtest.c b/raid/test/invtest.c new file mode 100644 index 0000000..abca3b6 --- /dev/null +++ b/raid/test/invtest.c @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 2 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. + */ + +/* Matrix inversion test for the RAID library */ + +#include "internal.h" + +#include "combo.h" +#include "gf.h" + +#include +#include +#include +#include + +/** + * Like raid_invert() but optimized to only check if the matrix is + * invertible. + */ +static __always_inline int raid_invert_fast(uint8_t *M, int n) +{ + int i, j, k; + + /* for each element in the diagonal */ + for (k = 0; k < n; ++k) { + uint8_t f; + + /* the diagonal element cannot be 0 because */ + /* we are inverting matrices with all the square */ + /* submatrices not singular */ + if (M[k * n + k] == 0) + return -1; + + /* make the diagonal element to be 1 */ + f = inv(M[k * n + k]); + for (j = 0; j < n; ++j) + M[k * n + j] = mul(f, M[k * n + j]); + + /* make all the elements over and under the diagonal */ + /* to be zero */ + for (i = 0; i < n; ++i) { + if (i == k) + continue; + f = M[i * n + k]; + for (j = 0; j < n; ++j) + M[i * n + j] ^= mul(f, M[k * n + j]); + } + } + + return 0; +} + +#define TEST_REFRESH (4 * 1024 * 1024) + +/** + * Precomputed number of square submatrices of size nr. + * + * It's bc(np,nr) * bc(nd,nr) + * + * With 1<=nr<=6 and bc(n, r) == binomial coefficient of (n over r). + */ +long long EXPECTED[RAID_PARITY_MAX] = { + 1506LL, + 470625LL, + 52082500LL, + 2421836250LL, + 47855484300LL, + 327012476050LL +}; + +static __always_inline int test_sub_matrix(int nr, long long *total) +{ + uint8_t M[RAID_PARITY_MAX * RAID_PARITY_MAX]; + int np = RAID_PARITY_MAX; + int nd = RAID_DATA_MAX; + int ip[RAID_PARITY_MAX]; + int id[RAID_DATA_MAX]; + long long count; + long long expected; + + printf("\n%ux%u\n", nr, nr); + + count = 0; + expected = EXPECTED[nr - 1]; + + /* all combinations (nr of nd) disks */ + combination_first(nr, nd, id); + do { + /* all combinations (nr of np) parities */ + combination_first(nr, np, ip); + do { + int i, j; + + /* setup the submatrix */ + for (i = 0; i < nr; ++i) + for (j = 0; j < nr; ++j) + M[i * nr + j] = gfgen[ip[i]][id[j]]; + + /* invert */ + if (raid_invert_fast(M, nr) != 0) + return -1; + + if (++count % TEST_REFRESH == 0) { + printf("\r%.3f %%", count * (double)100 / expected); + fflush(stdout); + } + } while (combination_next(nr, np, ip)); + } while (combination_next(nr, nd, id)); + + if (count != expected) + return -1; + + printf("\rTested %" PRIi64 " matrix\n", count); + + *total += count; + + return 0; +} + +int test_all_sub_matrix(void) +{ + long long total; + + printf("Invert all square submatrices of the %dx%d Cauchy matrix\n", + RAID_PARITY_MAX, RAID_DATA_MAX); + + printf("\nPlease wait about 2 days...\n"); + + total = 0; + + /* force inlining of everything */ + if (test_sub_matrix(1, &total) != 0) + return -1; + if (test_sub_matrix(2, &total) != 0) + return -1; + if (test_sub_matrix(3, &total) != 0) + return -1; + if (test_sub_matrix(4, &total) != 0) + return -1; + if (test_sub_matrix(5, &total) != 0) + return -1; + if (test_sub_matrix(6, &total) != 0) + return -1; + + printf("\nTested in total %" PRIi64 " matrix\n", total); + + return 0; +} + +int main(void) +{ + printf("Matrix inversion test for the RAID Cauchy library\n\n"); + + /* required to set the gfgen table */ + raid_init(); + + if (test_all_sub_matrix() != 0) { + printf("FAILED!\n"); + exit(EXIT_FAILURE); + } + printf("OK\n"); + + return 0; +} + diff --git a/raid/test/selftest.c b/raid/test/selftest.c new file mode 100644 index 0000000..32bd5a4 --- /dev/null +++ b/raid/test/selftest.c @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 2 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. + */ + +/* Self sanity test for the RAID library */ + +#include "internal.h" +#include "cpu.h" + +#include +#include + +int main(void) +{ + printf("Self sanity test for the RAID Cauchy library\n\n"); + + raid_init(); + + printf("Self test...\n"); + if (raid_selftest() != 0) { + /* LCOV_EXCL_START */ + printf("FAILED!\n"); + exit(EXIT_FAILURE); + /* LCOV_EXCL_STOP */ + } + printf("OK\n\n"); + + return 0; +} + diff --git a/raid/test/speedtest.c b/raid/test/speedtest.c new file mode 100644 index 0000000..e90b61e --- /dev/null +++ b/raid/test/speedtest.c @@ -0,0 +1,851 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 2 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. + */ + +/* Speed test for the RAID library */ + +#include "internal.h" +#include "memory.h" +#include "cpu.h" + +#include +#include +#include + +/* + * Size of the blocks to test. + */ +#define TEST_SIZE (256 * 1024) + +/* + * Number of data blocks to test. + */ +#define TEST_COUNT (8) + +/** + * Differential us of two timeval. + */ +static int64_t diffgettimeofday(struct timeval *start, struct timeval *stop) +{ + int64_t d; + + d = 1000000LL * (stop->tv_sec - start->tv_sec); + d += stop->tv_usec - start->tv_usec; + + return d; +} + +/** + * Test period. + */ +#ifdef COVERAGE +#define TEST_PERIOD 100000LL +#define TEST_DELTA 1 +#else +#define TEST_PERIOD 1000000LL +#define TEST_DELTA 10 +#endif + +/** + * Start time measurement. + */ +#define SPEED_START \ + count = 0; \ + gettimeofday(&start, 0); \ + do { \ + for (i = 0; i < delta; ++i) + +/** + * Stop time measurement. + */ +#define SPEED_STOP \ + count += delta; \ + gettimeofday(&stop, 0); \ + } while (diffgettimeofday(&start, &stop) < TEST_PERIOD); \ + ds = size * (int64_t)count * nd; \ + dt = diffgettimeofday(&start, &stop); + +void speed(void) +{ + struct timeval start; + struct timeval stop; + int64_t ds; + int64_t dt; + int i, j; + int id[RAID_PARITY_MAX]; + int ip[RAID_PARITY_MAX]; + int count; + int delta = TEST_DELTA; + int size = TEST_SIZE; + int nd = TEST_COUNT; + int nv; + void *v_alloc; + void **v; + + nv = nd + RAID_PARITY_MAX + 1; + + v = raid_malloc_vector(nd, nv, size, &v_alloc); + + /* initialize disks with fixed data */ + for (i = 0; i < nd; ++i) + memset(v[i], i, size); + + /* zero buffer */ + memset(v[nd + RAID_PARITY_MAX], 0, size); + raid_zero(v[nd + RAID_PARITY_MAX]); + + /* basic disks and parity mapping */ + for (i = 0; i < RAID_PARITY_MAX; ++i) { + id[i] = i; + ip[i] = i; + } + + printf("Speed test using %u data buffers of %u bytes, for a total of %u KiB.\n", nd, size, nd * size / 1024); + printf("Memory blocks have a displacement of %u bytes to improve cache performance.\n", RAID_MALLOC_DISPLACEMENT); + printf("The reported values are the aggregate bandwidth of all data blocks in MiB/s,\n"); + printf("not counting parity blocks.\n"); + printf("\n"); + + printf("Memory write speed using the C memset() function:\n"); + printf("%8s", "memset"); + fflush(stdout); + + SPEED_START { + for (j = 0; j < nd; ++j) + memset(v[j], j, size); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + printf("\n"); + printf("\n"); + + /* RAID table */ + printf("RAID functions used for computing the parity:\n"); + printf("%8s", ""); + printf("%8s", "best"); + printf("%8s", "int8"); + printf("%8s", "int32"); + printf("%8s", "int64"); +#ifdef CONFIG_X86 + printf("%8s", "sse2"); +#ifdef CONFIG_X86_64 + printf("%8s", "sse2e"); +#endif + printf("%8s", "ssse3"); +#ifdef CONFIG_X86_64 + printf("%8s", "ssse3e"); +#endif + printf("%8s", "avx2"); +#ifdef CONFIG_X86_64 + printf("%8s", "avx2e"); +#endif +#endif + printf("\n"); + + /* GEN1 */ + printf("%8s", "gen1"); + printf("%8s", raid_gen1_tag()); + fflush(stdout); + + printf("%8s", ""); + + SPEED_START { + raid_gen1_int32(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + + SPEED_START { + raid_gen1_int64(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSE2 + if (raid_cpu_has_sse2()) { + SPEED_START { + raid_gen1_sse2(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + } +#endif + +#ifdef CONFIG_X86_64 + printf("%8s", ""); +#endif + printf("%8s", ""); +#ifdef CONFIG_X86_64 + printf("%8s", ""); +#endif +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + raid_gen1_avx2(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + } +#endif +#endif + printf("\n"); + + /* GEN2 */ + printf("%8s", "gen2"); + printf("%8s", raid_gen2_tag()); + fflush(stdout); + + printf("%8s", ""); + + SPEED_START { + raid_gen2_int32(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + + SPEED_START { + raid_gen2_int64(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSE2 + if (raid_cpu_has_sse2()) { + SPEED_START { + raid_gen2_sse2(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86_64 + SPEED_START { + raid_gen2_sse2ext(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); +#endif + } +#endif + + printf("%8s", ""); +#ifdef CONFIG_X86_64 + printf("%8s", ""); +#endif +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + raid_gen2_avx2(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + } +#endif +#endif + printf("\n"); + + /* GENz */ + printf("%8s", "genz"); + printf("%8s", raid_genz_tag()); + fflush(stdout); + + printf("%8s", ""); + + SPEED_START { + raid_genz_int32(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + + SPEED_START { + raid_genz_int64(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSE2 + if (raid_cpu_has_sse2()) { + SPEED_START { + raid_genz_sse2(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86_64 + SPEED_START { + raid_genz_sse2ext(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); +#endif + } +#endif + + printf("%8s", ""); +#ifdef CONFIG_X86_64 + printf("%8s", ""); +#endif + printf("%8s", ""); + +#ifdef CONFIG_X86_64 +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + raid_genz_avx2ext(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + } +#endif +#endif +#endif + printf("\n"); + + /* GEN3 */ + printf("%8s", "gen3"); + printf("%8s", raid_gen3_tag()); + fflush(stdout); + + SPEED_START { + raid_gen3_int8(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + + printf("%8s", ""); + printf("%8s", ""); + +#ifdef CONFIG_X86 + if (raid_cpu_has_sse2()) { + printf("%8s", ""); + +#ifdef CONFIG_X86_64 + printf("%8s", ""); +#endif + } +#endif + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) { + SPEED_START { + raid_gen3_ssse3(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86_64 + SPEED_START { + raid_gen3_ssse3ext(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); +#endif + } +#endif + + printf("%8s", ""); + +#ifdef CONFIG_X86_64 +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + raid_gen3_avx2ext(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + } +#endif +#endif +#endif + printf("\n"); + + /* GEN4 */ + printf("%8s", "gen4"); + printf("%8s", raid_gen4_tag()); + fflush(stdout); + + SPEED_START { + raid_gen4_int8(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + + printf("%8s", ""); + printf("%8s", ""); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSE2 + if (raid_cpu_has_sse2()) { + printf("%8s", ""); + +#ifdef CONFIG_X86_64 + printf("%8s", ""); +#endif + } +#endif +#endif + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) { + SPEED_START { + raid_gen4_ssse3(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86_64 + SPEED_START { + raid_gen4_ssse3ext(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); +#endif + } +#endif + + printf("%8s", ""); + +#ifdef CONFIG_X86_64 +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + raid_gen4_avx2ext(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + } +#endif +#endif +#endif + printf("\n"); + + /* GEN5 */ + printf("%8s", "gen5"); + printf("%8s", raid_gen5_tag()); + fflush(stdout); + + SPEED_START { + raid_gen5_int8(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + + printf("%8s", ""); + printf("%8s", ""); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSE2 + if (raid_cpu_has_sse2()) { + printf("%8s", ""); + +#ifdef CONFIG_X86_64 + printf("%8s", ""); +#endif + } +#endif +#endif + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) { + SPEED_START { + raid_gen5_ssse3(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86_64 + SPEED_START { + raid_gen5_ssse3ext(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); +#endif + } +#endif + + printf("%8s", ""); + +#ifdef CONFIG_X86_64 +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + raid_gen5_avx2ext(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + } +#endif +#endif +#endif + printf("\n"); + + /* GEN6 */ + printf("%8s", "gen6"); + printf("%8s", raid_gen6_tag()); + fflush(stdout); + + SPEED_START { + raid_gen6_int8(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + + printf("%8s", ""); + printf("%8s", ""); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSE2 + if (raid_cpu_has_sse2()) { + printf("%8s", ""); + +#ifdef CONFIG_X86_64 + printf("%8s", ""); +#endif + } +#endif +#endif + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) { + SPEED_START { + raid_gen6_ssse3(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86_64 + SPEED_START { + raid_gen6_ssse3ext(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); +#endif + } +#endif + + printf("%8s", ""); + +#ifdef CONFIG_X86_64 +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + raid_gen6_avx2ext(nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + } +#endif +#endif +#endif + printf("\n"); + printf("\n"); + + /* recover table */ + printf("RAID functions used for recovering:\n"); + printf("%8s", ""); + printf("%8s", "best"); + printf("%8s", "int8"); +#ifdef CONFIG_X86 + printf("%8s", "ssse3"); + printf("%8s", "avx2"); +#endif + printf("\n"); + + printf("%8s", "rec1"); + printf("%8s", raid_rec1_tag()); + fflush(stdout); + + SPEED_START { + for (j = 0; j < nd; ++j) + /* +1 to avoid GEN1 optimized case */ + raid_rec1_int8(1, id, ip + 1, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) { + SPEED_START { + for (j = 0; j < nd; ++j) + /* +1 to avoid GEN1 optimized case */ + raid_rec1_ssse3(1, id, ip + 1, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + for (j = 0; j < nd; ++j) + /* +1 to avoid GEN1 optimized case */ + raid_rec1_avx2(1, id, ip + 1, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#endif + printf("\n"); + + printf("%8s", "rec2"); + printf("%8s", raid_rec2_tag()); + fflush(stdout); + + SPEED_START { + for (j = 0; j < nd; ++j) + /* +1 to avoid GEN2 optimized case */ + raid_rec2_int8(2, id, ip + 1, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) { + SPEED_START { + for (j = 0; j < nd; ++j) + /* +1 to avoid GEN2 optimized case */ + raid_rec2_ssse3(2, id, ip + 1, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + for (j = 0; j < nd; ++j) + /* +1 to avoid GEN1 optimized case */ + raid_rec2_avx2(2, id, ip + 1, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#endif + printf("\n"); + + printf("%8s", "rec3"); + printf("%8s", raid_recX_tag()); + fflush(stdout); + + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_int8(3, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) { + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_ssse3(3, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_avx2(3, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#endif + printf("\n"); + + printf("%8s", "rec4"); + printf("%8s", raid_recX_tag()); + fflush(stdout); + + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_int8(4, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) { + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_ssse3(4, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_avx2(4, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#endif + printf("\n"); + + printf("%8s", "rec5"); + printf("%8s", raid_recX_tag()); + fflush(stdout); + + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_int8(5, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) { + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_ssse3(5, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_avx2(5, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#endif + printf("\n"); + + printf("%8s", "rec6"); + printf("%8s", raid_recX_tag()); + fflush(stdout); + + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_int8(6, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + fflush(stdout); + +#ifdef CONFIG_X86 +#ifdef CONFIG_SSSE3 + if (raid_cpu_has_ssse3()) { + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_ssse3(6, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#ifdef CONFIG_AVX2 + if (raid_cpu_has_avx2()) { + SPEED_START { + for (j = 0; j < nd; ++j) + raid_recX_avx2(6, id, ip, nd, size, v); + } SPEED_STOP + + printf("%8" PRIu64, ds / dt); + } +#endif +#endif + printf("\n"); + printf("\n"); + + free(v_alloc); + free(v); +} + +int main(void) +{ + printf("Speed test for the RAID Cauchy library\n\n"); + + raid_init(); + +#ifdef CONFIG_X86 + if (raid_cpu_has_sse2()) + printf("Including x86 SSE2 functions\n"); + if (raid_cpu_has_ssse3()) + printf("Including x86 SSSE3 functions\n"); + if (raid_cpu_has_avx2()) + printf("Including x86 AVX2 functions\n"); +#endif +#ifdef CONFIG_X86_64 + printf("Including x64 extended SSE register set\n"); +#endif + + printf("\nPlease wait about 30 seconds...\n\n"); + + speed(); + + return 0; +} + diff --git a/raid/x86.c b/raid/x86.c new file mode 100644 index 0000000..84b12c1 --- /dev/null +++ b/raid/x86.c @@ -0,0 +1,2452 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 2 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. + */ + +#include "internal.h" +#include "gf.h" + +/* + * For x86 optimizations you can see: + * + * Software optimization resources + * http://www.agner.org/optimize/ + * + * x86, x64 Instruction Latency, Memory Latency and CPUID dumps + * http://users.atw.hu/instlatx64/ + */ + +#if defined(CONFIG_X86) && defined(CONFIG_SSE2) +/* + * GEN1 (RAID5 with xor) SSE2 implementation + * + * Intentionally don't process more than 64 bytes because 64 is the typical + * cache block, and processing 128 bytes doesn't increase performance, and in + * some cases it even decreases it. + */ +void raid_gen1_sse2(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + int d, l; + size_t i; + + l = nd - 1; + p = v[nd]; + + raid_sse_begin(); + + for (i = 0; i < size; i += 64) { + asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i])); + asm volatile ("movdqa %0,%%xmm1" : : "m" (v[l][i + 16])); + asm volatile ("movdqa %0,%%xmm2" : : "m" (v[l][i + 32])); + asm volatile ("movdqa %0,%%xmm3" : : "m" (v[l][i + 48])); + for (d = l - 1; d >= 0; --d) { + asm volatile ("pxor %0,%%xmm0" : : "m" (v[d][i])); + asm volatile ("pxor %0,%%xmm1" : : "m" (v[d][i + 16])); + asm volatile ("pxor %0,%%xmm2" : : "m" (v[d][i + 32])); + asm volatile ("pxor %0,%%xmm3" : : "m" (v[d][i + 48])); + } + asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + asm volatile ("movntdq %%xmm1,%0" : "=m" (p[i + 16])); + asm volatile ("movntdq %%xmm2,%0" : "=m" (p[i + 32])); + asm volatile ("movntdq %%xmm3,%0" : "=m" (p[i + 48])); + } + + raid_sse_end(); +} +#endif + +#if defined(CONFIG_X86) && defined(CONFIG_AVX2) +/* + * GEN1 (RAID5 with xor) AVX2 implementation + * + * Intentionally don't process more than 64 bytes because 64 is the typical + * cache block, and processing 128 bytes doesn't increase performance, and in + * some cases it even decreases it. + */ +void raid_gen1_avx2(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + int d, l; + size_t i; + + l = nd - 1; + p = v[nd]; + + raid_avx_begin(); + + for (i = 0; i < size; i += 64) { + asm volatile ("vmovdqa %0,%%ymm0" : : "m" (v[l][i])); + asm volatile ("vmovdqa %0,%%ymm1" : : "m" (v[l][i + 32])); + for (d = l - 1; d >= 0; --d) { + asm volatile ("vpxor %0,%%ymm0,%%ymm0" : : "m" (v[d][i])); + asm volatile ("vpxor %0,%%ymm1,%%ymm1" : : "m" (v[d][i + 32])); + } + asm volatile ("vmovntdq %%ymm0,%0" : "=m" (p[i])); + asm volatile ("vmovntdq %%ymm1,%0" : "=m" (p[i + 32])); + } + + raid_avx_end(); +} +#endif + +#if defined(CONFIG_X86) && defined(CONFIG_SSE2) +static const struct gfconst16 { + uint8_t poly[16]; + uint8_t low4[16]; +} gfconst16 __aligned(32) = { + { + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d + }, + { + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f + }, +}; +#endif + +#if defined(CONFIG_X86) && defined(CONFIG_SSE2) +/* + * GEN2 (RAID6 with powers of 2) SSE2 implementation + */ +void raid_gen2_sse2(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *q; + int d, l; + size_t i; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + + raid_sse_begin(); + + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); + + for (i = 0; i < size; i += 32) { + asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i])); + asm volatile ("movdqa %0,%%xmm1" : : "m" (v[l][i + 16])); + asm volatile ("movdqa %xmm0,%xmm2"); + asm volatile ("movdqa %xmm1,%xmm3"); + for (d = l - 1; d >= 0; --d) { + asm volatile ("pxor %xmm4,%xmm4"); + asm volatile ("pxor %xmm5,%xmm5"); + asm volatile ("pcmpgtb %xmm2,%xmm4"); + asm volatile ("pcmpgtb %xmm3,%xmm5"); + asm volatile ("paddb %xmm2,%xmm2"); + asm volatile ("paddb %xmm3,%xmm3"); + asm volatile ("pand %xmm7,%xmm4"); + asm volatile ("pand %xmm7,%xmm5"); + asm volatile ("pxor %xmm4,%xmm2"); + asm volatile ("pxor %xmm5,%xmm3"); + + asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); + asm volatile ("movdqa %0,%%xmm5" : : "m" (v[d][i + 16])); + asm volatile ("pxor %xmm4,%xmm0"); + asm volatile ("pxor %xmm5,%xmm1"); + asm volatile ("pxor %xmm4,%xmm2"); + asm volatile ("pxor %xmm5,%xmm3"); + } + asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + asm volatile ("movntdq %%xmm1,%0" : "=m" (p[i + 16])); + asm volatile ("movntdq %%xmm2,%0" : "=m" (q[i])); + asm volatile ("movntdq %%xmm3,%0" : "=m" (q[i + 16])); + } + + raid_sse_end(); +} +#endif + +#if defined(CONFIG_X86) && defined(CONFIG_AVX2) +/* + * GEN2 (RAID6 with powers of 2) AVX2 implementation + */ +void raid_gen2_avx2(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *q; + int d, l; + size_t i; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + + raid_avx_begin(); + + asm volatile ("vbroadcasti128 %0, %%ymm7" : : "m" (gfconst16.poly[0])); + asm volatile ("vpxor %ymm6,%ymm6,%ymm6"); + + for (i = 0; i < size; i += 64) { + asm volatile ("vmovdqa %0,%%ymm0" : : "m" (v[l][i])); + asm volatile ("vmovdqa %0,%%ymm1" : : "m" (v[l][i + 32])); + asm volatile ("vmovdqa %ymm0,%ymm2"); + asm volatile ("vmovdqa %ymm1,%ymm3"); + for (d = l - 1; d >= 0; --d) { + asm volatile ("vpcmpgtb %ymm2,%ymm6,%ymm4"); + asm volatile ("vpcmpgtb %ymm3,%ymm6,%ymm5"); + asm volatile ("vpaddb %ymm2,%ymm2,%ymm2"); + asm volatile ("vpaddb %ymm3,%ymm3,%ymm3"); + asm volatile ("vpand %ymm7,%ymm4,%ymm4"); + asm volatile ("vpand %ymm7,%ymm5,%ymm5"); + asm volatile ("vpxor %ymm4,%ymm2,%ymm2"); + asm volatile ("vpxor %ymm5,%ymm3,%ymm3"); + + asm volatile ("vmovdqa %0,%%ymm4" : : "m" (v[d][i])); + asm volatile ("vmovdqa %0,%%ymm5" : : "m" (v[d][i + 32])); + asm volatile ("vpxor %ymm4,%ymm0,%ymm0"); + asm volatile ("vpxor %ymm5,%ymm1,%ymm1"); + asm volatile ("vpxor %ymm4,%ymm2,%ymm2"); + asm volatile ("vpxor %ymm5,%ymm3,%ymm3"); + } + asm volatile ("vmovntdq %%ymm0,%0" : "=m" (p[i])); + asm volatile ("vmovntdq %%ymm1,%0" : "=m" (p[i + 32])); + asm volatile ("vmovntdq %%ymm2,%0" : "=m" (q[i])); + asm volatile ("vmovntdq %%ymm3,%0" : "=m" (q[i + 32])); + } + + raid_avx_end(); +} +#endif + +#if defined(CONFIG_X86_64) && defined(CONFIG_SSE2) +/* + * GEN2 (RAID6 with powers of 2) SSE2 implementation + * + * Note that it uses 16 registers, meaning that x64 is required. + */ +void raid_gen2_sse2ext(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *q; + int d, l; + size_t i; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + + raid_sse_begin(); + + asm volatile ("movdqa %0,%%xmm15" : : "m" (gfconst16.poly[0])); + + for (i = 0; i < size; i += 64) { + asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i])); + asm volatile ("movdqa %0,%%xmm1" : : "m" (v[l][i + 16])); + asm volatile ("movdqa %0,%%xmm2" : : "m" (v[l][i + 32])); + asm volatile ("movdqa %0,%%xmm3" : : "m" (v[l][i + 48])); + asm volatile ("movdqa %xmm0,%xmm4"); + asm volatile ("movdqa %xmm1,%xmm5"); + asm volatile ("movdqa %xmm2,%xmm6"); + asm volatile ("movdqa %xmm3,%xmm7"); + for (d = l - 1; d >= 0; --d) { + asm volatile ("pxor %xmm8,%xmm8"); + asm volatile ("pxor %xmm9,%xmm9"); + asm volatile ("pxor %xmm10,%xmm10"); + asm volatile ("pxor %xmm11,%xmm11"); + asm volatile ("pcmpgtb %xmm4,%xmm8"); + asm volatile ("pcmpgtb %xmm5,%xmm9"); + asm volatile ("pcmpgtb %xmm6,%xmm10"); + asm volatile ("pcmpgtb %xmm7,%xmm11"); + asm volatile ("paddb %xmm4,%xmm4"); + asm volatile ("paddb %xmm5,%xmm5"); + asm volatile ("paddb %xmm6,%xmm6"); + asm volatile ("paddb %xmm7,%xmm7"); + asm volatile ("pand %xmm15,%xmm8"); + asm volatile ("pand %xmm15,%xmm9"); + asm volatile ("pand %xmm15,%xmm10"); + asm volatile ("pand %xmm15,%xmm11"); + asm volatile ("pxor %xmm8,%xmm4"); + asm volatile ("pxor %xmm9,%xmm5"); + asm volatile ("pxor %xmm10,%xmm6"); + asm volatile ("pxor %xmm11,%xmm7"); + + asm volatile ("movdqa %0,%%xmm8" : : "m" (v[d][i])); + asm volatile ("movdqa %0,%%xmm9" : : "m" (v[d][i + 16])); + asm volatile ("movdqa %0,%%xmm10" : : "m" (v[d][i + 32])); + asm volatile ("movdqa %0,%%xmm11" : : "m" (v[d][i + 48])); + asm volatile ("pxor %xmm8,%xmm0"); + asm volatile ("pxor %xmm9,%xmm1"); + asm volatile ("pxor %xmm10,%xmm2"); + asm volatile ("pxor %xmm11,%xmm3"); + asm volatile ("pxor %xmm8,%xmm4"); + asm volatile ("pxor %xmm9,%xmm5"); + asm volatile ("pxor %xmm10,%xmm6"); + asm volatile ("pxor %xmm11,%xmm7"); + } + asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + asm volatile ("movntdq %%xmm1,%0" : "=m" (p[i + 16])); + asm volatile ("movntdq %%xmm2,%0" : "=m" (p[i + 32])); + asm volatile ("movntdq %%xmm3,%0" : "=m" (p[i + 48])); + asm volatile ("movntdq %%xmm4,%0" : "=m" (q[i])); + asm volatile ("movntdq %%xmm5,%0" : "=m" (q[i + 16])); + asm volatile ("movntdq %%xmm6,%0" : "=m" (q[i + 32])); + asm volatile ("movntdq %%xmm7,%0" : "=m" (q[i + 48])); + } + + raid_sse_end(); +} +#endif + +#if defined(CONFIG_X86) && defined(CONFIG_SSSE3) +/* + * GEN3 (triple parity with Cauchy matrix) SSSE3 implementation + */ +void raid_gen3_ssse3(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *q; + uint8_t *r; + int d, l; + size_t i; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + r = v[nd + 2]; + + /* special case with only one data disk */ + if (l == 0) { + for (i = 0; i < 3; ++i) + memcpy(v[1 + i], v[0], size); + return; + } + + raid_sse_begin(); + + /* generic case with at least two data disks */ + asm volatile ("movdqa %0,%%xmm3" : : "m" (gfconst16.poly[0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + + for (i = 0; i < size; i += 16) { + /* last disk without the by two multiplication */ + asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i])); + + asm volatile ("movdqa %xmm4,%xmm0"); + asm volatile ("movdqa %xmm4,%xmm1"); + + asm volatile ("movdqa %xmm4,%xmm5"); + asm volatile ("psrlw $4,%xmm5"); + asm volatile ("pand %xmm7,%xmm4"); + asm volatile ("pand %xmm7,%xmm5"); + + asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][0][0][0])); + asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[l][0][1][0])); + asm volatile ("pshufb %xmm4,%xmm2"); + asm volatile ("pshufb %xmm5,%xmm6"); + asm volatile ("pxor %xmm6,%xmm2"); + + /* intermediate disks */ + for (d = l - 1; d > 0; --d) { + asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); + + asm volatile ("pxor %xmm5,%xmm5"); + asm volatile ("pcmpgtb %xmm1,%xmm5"); + asm volatile ("paddb %xmm1,%xmm1"); + asm volatile ("pand %xmm3,%xmm5"); + asm volatile ("pxor %xmm5,%xmm1"); + + asm volatile ("pxor %xmm4,%xmm0"); + asm volatile ("pxor %xmm4,%xmm1"); + + asm volatile ("movdqa %xmm4,%xmm5"); + asm volatile ("psrlw $4,%xmm5"); + asm volatile ("pand %xmm7,%xmm4"); + asm volatile ("pand %xmm7,%xmm5"); + + asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0])); + asm volatile ("pshufb %xmm4,%xmm6"); + asm volatile ("pxor %xmm6,%xmm2"); + asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][1][0])); + asm volatile ("pshufb %xmm5,%xmm6"); + asm volatile ("pxor %xmm6,%xmm2"); + } + + /* first disk with all coefficients at 1 */ + asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i])); + + asm volatile ("pxor %xmm5,%xmm5"); + asm volatile ("pcmpgtb %xmm1,%xmm5"); + asm volatile ("paddb %xmm1,%xmm1"); + asm volatile ("pand %xmm3,%xmm5"); + asm volatile ("pxor %xmm5,%xmm1"); + + asm volatile ("pxor %xmm4,%xmm0"); + asm volatile ("pxor %xmm4,%xmm1"); + asm volatile ("pxor %xmm4,%xmm2"); + + asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); + asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); + } + + raid_sse_end(); +} +#endif + +#if defined(CONFIG_X86_64) && defined(CONFIG_SSSE3) +/* + * GEN3 (triple parity with Cauchy matrix) SSSE3 implementation + * + * Note that it uses 16 registers, meaning that x64 is required. + */ +void raid_gen3_ssse3ext(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *q; + uint8_t *r; + int d, l; + size_t i; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + r = v[nd + 2]; + + /* special case with only one data disk */ + if (l == 0) { + for (i = 0; i < 3; ++i) + memcpy(v[1 + i], v[0], size); + return; + } + + raid_sse_begin(); + + /* generic case with at least two data disks */ + asm volatile ("movdqa %0,%%xmm3" : : "m" (gfconst16.poly[0])); + asm volatile ("movdqa %0,%%xmm11" : : "m" (gfconst16.low4[0])); + + for (i = 0; i < size; i += 32) { + /* last disk without the by two multiplication */ + asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i])); + asm volatile ("movdqa %0,%%xmm12" : : "m" (v[l][i + 16])); + + asm volatile ("movdqa %xmm4,%xmm0"); + asm volatile ("movdqa %xmm4,%xmm1"); + asm volatile ("movdqa %xmm12,%xmm8"); + asm volatile ("movdqa %xmm12,%xmm9"); + + asm volatile ("movdqa %xmm4,%xmm5"); + asm volatile ("movdqa %xmm12,%xmm13"); + asm volatile ("psrlw $4,%xmm5"); + asm volatile ("psrlw $4,%xmm13"); + asm volatile ("pand %xmm11,%xmm4"); + asm volatile ("pand %xmm11,%xmm12"); + asm volatile ("pand %xmm11,%xmm5"); + asm volatile ("pand %xmm11,%xmm13"); + + asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][0][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0])); + asm volatile ("movdqa %xmm2,%xmm10"); + asm volatile ("movdqa %xmm7,%xmm15"); + asm volatile ("pshufb %xmm4,%xmm2"); + asm volatile ("pshufb %xmm12,%xmm10"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pshufb %xmm13,%xmm15"); + asm volatile ("pxor %xmm7,%xmm2"); + asm volatile ("pxor %xmm15,%xmm10"); + + /* intermediate disks */ + for (d = l - 1; d > 0; --d) { + asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); + asm volatile ("movdqa %0,%%xmm12" : : "m" (v[d][i + 16])); + + asm volatile ("pxor %xmm5,%xmm5"); + asm volatile ("pxor %xmm13,%xmm13"); + asm volatile ("pcmpgtb %xmm1,%xmm5"); + asm volatile ("pcmpgtb %xmm9,%xmm13"); + asm volatile ("paddb %xmm1,%xmm1"); + asm volatile ("paddb %xmm9,%xmm9"); + asm volatile ("pand %xmm3,%xmm5"); + asm volatile ("pand %xmm3,%xmm13"); + asm volatile ("pxor %xmm5,%xmm1"); + asm volatile ("pxor %xmm13,%xmm9"); + + asm volatile ("pxor %xmm4,%xmm0"); + asm volatile ("pxor %xmm4,%xmm1"); + asm volatile ("pxor %xmm12,%xmm8"); + asm volatile ("pxor %xmm12,%xmm9"); + + asm volatile ("movdqa %xmm4,%xmm5"); + asm volatile ("movdqa %xmm12,%xmm13"); + asm volatile ("psrlw $4,%xmm5"); + asm volatile ("psrlw $4,%xmm13"); + asm volatile ("pand %xmm11,%xmm4"); + asm volatile ("pand %xmm11,%xmm12"); + asm volatile ("pand %xmm11,%xmm5"); + asm volatile ("pand %xmm11,%xmm13"); + + asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0])); + asm volatile ("movdqa %xmm6,%xmm14"); + asm volatile ("movdqa %xmm7,%xmm15"); + asm volatile ("pshufb %xmm4,%xmm6"); + asm volatile ("pshufb %xmm12,%xmm14"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pshufb %xmm13,%xmm15"); + asm volatile ("pxor %xmm6,%xmm2"); + asm volatile ("pxor %xmm14,%xmm10"); + asm volatile ("pxor %xmm7,%xmm2"); + asm volatile ("pxor %xmm15,%xmm10"); + } + + /* first disk with all coefficients at 1 */ + asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i])); + asm volatile ("movdqa %0,%%xmm12" : : "m" (v[0][i + 16])); + + asm volatile ("pxor %xmm5,%xmm5"); + asm volatile ("pxor %xmm13,%xmm13"); + asm volatile ("pcmpgtb %xmm1,%xmm5"); + asm volatile ("pcmpgtb %xmm9,%xmm13"); + asm volatile ("paddb %xmm1,%xmm1"); + asm volatile ("paddb %xmm9,%xmm9"); + asm volatile ("pand %xmm3,%xmm5"); + asm volatile ("pand %xmm3,%xmm13"); + asm volatile ("pxor %xmm5,%xmm1"); + asm volatile ("pxor %xmm13,%xmm9"); + + asm volatile ("pxor %xmm4,%xmm0"); + asm volatile ("pxor %xmm4,%xmm1"); + asm volatile ("pxor %xmm4,%xmm2"); + asm volatile ("pxor %xmm12,%xmm8"); + asm volatile ("pxor %xmm12,%xmm9"); + asm volatile ("pxor %xmm12,%xmm10"); + + asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + asm volatile ("movntdq %%xmm8,%0" : "=m" (p[i + 16])); + asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); + asm volatile ("movntdq %%xmm9,%0" : "=m" (q[i + 16])); + asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); + asm volatile ("movntdq %%xmm10,%0" : "=m" (r[i + 16])); + } + + raid_sse_end(); +} +#endif + +#if defined(CONFIG_X86_64) && defined(CONFIG_AVX2) +/* + * GEN3 (triple parity with Cauchy matrix) AVX2 implementation + * + * Note that it uses 16 registers, meaning that x64 is required. + */ +void raid_gen3_avx2ext(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *q; + uint8_t *r; + int d, l; + size_t i; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + r = v[nd + 2]; + + /* special case with only one data disk */ + if (l == 0) { + for (i = 0; i < 3; ++i) + memcpy(v[1 + i], v[0], size); + return; + } + + raid_avx_begin(); + + /* generic case with at least two data disks */ + asm volatile ("vbroadcasti128 %0, %%ymm3" : : "m" (gfconst16.poly[0])); + asm volatile ("vbroadcasti128 %0, %%ymm11" : : "m" (gfconst16.low4[0])); + + for (i = 0; i < size; i += 64) { + /* last disk without the by two multiplication */ + asm volatile ("vmovdqa %0,%%ymm4" : : "m" (v[l][i])); + asm volatile ("vmovdqa %0,%%ymm12" : : "m" (v[l][i + 32])); + + asm volatile ("vmovdqa %ymm4,%ymm0"); + asm volatile ("vmovdqa %ymm4,%ymm1"); + asm volatile ("vmovdqa %ymm12,%ymm8"); + asm volatile ("vmovdqa %ymm12,%ymm9"); + + asm volatile ("vpsrlw $4,%ymm4,%ymm5"); + asm volatile ("vpsrlw $4,%ymm12,%ymm13"); + asm volatile ("vpand %ymm11,%ymm4,%ymm4"); + asm volatile ("vpand %ymm11,%ymm12,%ymm12"); + asm volatile ("vpand %ymm11,%ymm5,%ymm5"); + asm volatile ("vpand %ymm11,%ymm13,%ymm13"); + + asm volatile ("vbroadcasti128 %0,%%ymm10" : : "m" (gfgenpshufb[l][0][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm15" : : "m" (gfgenpshufb[l][0][1][0])); + asm volatile ("vpshufb %ymm4,%ymm10,%ymm2"); + asm volatile ("vpshufb %ymm12,%ymm10,%ymm10"); + asm volatile ("vpshufb %ymm5,%ymm15,%ymm7"); + asm volatile ("vpshufb %ymm13,%ymm15,%ymm15"); + asm volatile ("vpxor %ymm7,%ymm2,%ymm2"); + asm volatile ("vpxor %ymm15,%ymm10,%ymm10"); + + /* intermediate disks */ + for (d = l - 1; d > 0; --d) { + asm volatile ("vmovdqa %0,%%ymm4" : : "m" (v[d][i])); + asm volatile ("vmovdqa %0,%%ymm12" : : "m" (v[d][i + 32])); + + asm volatile ("vpxor %ymm5,%ymm5,%ymm5"); + asm volatile ("vpxor %ymm13,%ymm13,%ymm13"); + asm volatile ("vpcmpgtb %ymm1,%ymm5,%ymm5"); + asm volatile ("vpcmpgtb %ymm9,%ymm13,%ymm13"); + asm volatile ("vpaddb %ymm1,%ymm1,%ymm1"); + asm volatile ("vpaddb %ymm9,%ymm9,%ymm9"); + asm volatile ("vpand %ymm3,%ymm5,%ymm5"); + asm volatile ("vpand %ymm3,%ymm13,%ymm13"); + asm volatile ("vpxor %ymm5,%ymm1,%ymm1"); + asm volatile ("vpxor %ymm13,%ymm9,%ymm9"); + + asm volatile ("vpxor %ymm4,%ymm0,%ymm0"); + asm volatile ("vpxor %ymm4,%ymm1,%ymm1"); + asm volatile ("vpxor %ymm12,%ymm8,%ymm8"); + asm volatile ("vpxor %ymm12,%ymm9,%ymm9"); + + asm volatile ("vpsrlw $4,%ymm4,%ymm5"); + asm volatile ("vpsrlw $4,%ymm12,%ymm13"); + asm volatile ("vpand %ymm11,%ymm4,%ymm4"); + asm volatile ("vpand %ymm11,%ymm12,%ymm12"); + asm volatile ("vpand %ymm11,%ymm5,%ymm5"); + asm volatile ("vpand %ymm11,%ymm13,%ymm13"); + + asm volatile ("vbroadcasti128 %0,%%ymm14" : : "m" (gfgenpshufb[d][0][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm15" : : "m" (gfgenpshufb[d][0][1][0])); + asm volatile ("vpshufb %ymm4,%ymm14,%ymm6"); + asm volatile ("vpshufb %ymm12,%ymm14,%ymm14"); + asm volatile ("vpshufb %ymm5,%ymm15,%ymm7"); + asm volatile ("vpshufb %ymm13,%ymm15,%ymm15"); + asm volatile ("vpxor %ymm6,%ymm2,%ymm2"); + asm volatile ("vpxor %ymm14,%ymm10,%ymm10"); + asm volatile ("vpxor %ymm7,%ymm2,%ymm2"); + asm volatile ("vpxor %ymm15,%ymm10,%ymm10"); + } + + /* first disk with all coefficients at 1 */ + asm volatile ("vmovdqa %0,%%ymm4" : : "m" (v[0][i])); + asm volatile ("vmovdqa %0,%%ymm12" : : "m" (v[0][i + 32])); + + asm volatile ("vpxor %ymm5,%ymm5,%ymm5"); + asm volatile ("vpxor %ymm13,%ymm13,%ymm13"); + asm volatile ("vpcmpgtb %ymm1,%ymm5,%ymm5"); + asm volatile ("vpcmpgtb %ymm9,%ymm13,%ymm13"); + asm volatile ("vpaddb %ymm1,%ymm1,%ymm1"); + asm volatile ("vpaddb %ymm9,%ymm9,%ymm9"); + asm volatile ("vpand %ymm3,%ymm5,%ymm5"); + asm volatile ("vpand %ymm3,%ymm13,%ymm13"); + asm volatile ("vpxor %ymm5,%ymm1,%ymm1"); + asm volatile ("vpxor %ymm13,%ymm9,%ymm9"); + + asm volatile ("vpxor %ymm4,%ymm0,%ymm0"); + asm volatile ("vpxor %ymm4,%ymm1,%ymm1"); + asm volatile ("vpxor %ymm4,%ymm2,%ymm2"); + asm volatile ("vpxor %ymm12,%ymm8,%ymm8"); + asm volatile ("vpxor %ymm12,%ymm9,%ymm9"); + asm volatile ("vpxor %ymm12,%ymm10,%ymm10"); + + asm volatile ("vmovntdq %%ymm0,%0" : "=m" (p[i])); + asm volatile ("vmovntdq %%ymm8,%0" : "=m" (p[i + 32])); + asm volatile ("vmovntdq %%ymm1,%0" : "=m" (q[i])); + asm volatile ("vmovntdq %%ymm9,%0" : "=m" (q[i + 32])); + asm volatile ("vmovntdq %%ymm2,%0" : "=m" (r[i])); + asm volatile ("vmovntdq %%ymm10,%0" : "=m" (r[i + 32])); + } + + raid_avx_end(); +} +#endif + +#if defined(CONFIG_X86) && defined(CONFIG_SSSE3) +/* + * GEN4 (quad parity with Cauchy matrix) SSSE3 implementation + */ +void raid_gen4_ssse3(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *q; + uint8_t *r; + uint8_t *s; + int d, l; + size_t i; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + r = v[nd + 2]; + s = v[nd + 3]; + + /* special case with only one data disk */ + if (l == 0) { + for (i = 0; i < 4; ++i) + memcpy(v[1 + i], v[0], size); + return; + } + + raid_sse_begin(); + + /* generic case with at least two data disks */ + for (i = 0; i < size; i += 16) { + /* last disk without the by two multiplication */ + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i])); + + asm volatile ("movdqa %xmm4,%xmm0"); + asm volatile ("movdqa %xmm4,%xmm1"); + + asm volatile ("movdqa %xmm4,%xmm5"); + asm volatile ("psrlw $4,%xmm5"); + asm volatile ("pand %xmm7,%xmm4"); + asm volatile ("pand %xmm7,%xmm5"); + + asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][0][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0])); + asm volatile ("pshufb %xmm4,%xmm2"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pxor %xmm7,%xmm2"); + + asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][1][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0])); + asm volatile ("pshufb %xmm4,%xmm3"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pxor %xmm7,%xmm3"); + + /* intermediate disks */ + for (d = l - 1; d > 0; --d) { + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); + asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); + + asm volatile ("pxor %xmm5,%xmm5"); + asm volatile ("pcmpgtb %xmm1,%xmm5"); + asm volatile ("paddb %xmm1,%xmm1"); + asm volatile ("pand %xmm7,%xmm5"); + asm volatile ("pxor %xmm5,%xmm1"); + + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + + asm volatile ("pxor %xmm4,%xmm0"); + asm volatile ("pxor %xmm4,%xmm1"); + + asm volatile ("movdqa %xmm4,%xmm5"); + asm volatile ("psrlw $4,%xmm5"); + asm volatile ("pand %xmm7,%xmm4"); + asm volatile ("pand %xmm7,%xmm5"); + + asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0])); + asm volatile ("pshufb %xmm4,%xmm6"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pxor %xmm6,%xmm2"); + asm volatile ("pxor %xmm7,%xmm2"); + + asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0])); + asm volatile ("pshufb %xmm4,%xmm6"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pxor %xmm6,%xmm3"); + asm volatile ("pxor %xmm7,%xmm3"); + } + + /* first disk with all coefficients at 1 */ + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); + asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i])); + + asm volatile ("pxor %xmm5,%xmm5"); + asm volatile ("pcmpgtb %xmm1,%xmm5"); + asm volatile ("paddb %xmm1,%xmm1"); + asm volatile ("pand %xmm7,%xmm5"); + asm volatile ("pxor %xmm5,%xmm1"); + + asm volatile ("pxor %xmm4,%xmm0"); + asm volatile ("pxor %xmm4,%xmm1"); + asm volatile ("pxor %xmm4,%xmm2"); + asm volatile ("pxor %xmm4,%xmm3"); + + asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); + asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); + asm volatile ("movntdq %%xmm3,%0" : "=m" (s[i])); + } + + raid_sse_end(); +} +#endif + +#if defined(CONFIG_X86_64) && defined(CONFIG_SSSE3) +/* + * GEN4 (quad parity with Cauchy matrix) SSSE3 implementation + * + * Note that it uses 16 registers, meaning that x64 is required. + */ +void raid_gen4_ssse3ext(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *q; + uint8_t *r; + uint8_t *s; + int d, l; + size_t i; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + r = v[nd + 2]; + s = v[nd + 3]; + + /* special case with only one data disk */ + if (l == 0) { + for (i = 0; i < 4; ++i) + memcpy(v[1 + i], v[0], size); + return; + } + + raid_sse_begin(); + + /* generic case with at least two data disks */ + for (i = 0; i < size; i += 32) { + /* last disk without the by two multiplication */ + asm volatile ("movdqa %0,%%xmm15" : : "m" (gfconst16.low4[0])); + asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i])); + asm volatile ("movdqa %0,%%xmm12" : : "m" (v[l][i + 16])); + + asm volatile ("movdqa %xmm4,%xmm0"); + asm volatile ("movdqa %xmm4,%xmm1"); + asm volatile ("movdqa %xmm12,%xmm8"); + asm volatile ("movdqa %xmm12,%xmm9"); + + asm volatile ("movdqa %xmm4,%xmm5"); + asm volatile ("movdqa %xmm12,%xmm13"); + asm volatile ("psrlw $4,%xmm5"); + asm volatile ("psrlw $4,%xmm13"); + asm volatile ("pand %xmm15,%xmm4"); + asm volatile ("pand %xmm15,%xmm12"); + asm volatile ("pand %xmm15,%xmm5"); + asm volatile ("pand %xmm15,%xmm13"); + + asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][0][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0])); + asm volatile ("movdqa %xmm2,%xmm10"); + asm volatile ("movdqa %xmm7,%xmm15"); + asm volatile ("pshufb %xmm4,%xmm2"); + asm volatile ("pshufb %xmm12,%xmm10"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pshufb %xmm13,%xmm15"); + asm volatile ("pxor %xmm7,%xmm2"); + asm volatile ("pxor %xmm15,%xmm10"); + + asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][1][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0])); + asm volatile ("movdqa %xmm3,%xmm11"); + asm volatile ("movdqa %xmm7,%xmm15"); + asm volatile ("pshufb %xmm4,%xmm3"); + asm volatile ("pshufb %xmm12,%xmm11"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pshufb %xmm13,%xmm15"); + asm volatile ("pxor %xmm7,%xmm3"); + asm volatile ("pxor %xmm15,%xmm11"); + + /* intermediate disks */ + for (d = l - 1; d > 0; --d) { + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); + asm volatile ("movdqa %0,%%xmm15" : : "m" (gfconst16.low4[0])); + asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); + asm volatile ("movdqa %0,%%xmm12" : : "m" (v[d][i + 16])); + + asm volatile ("pxor %xmm5,%xmm5"); + asm volatile ("pxor %xmm13,%xmm13"); + asm volatile ("pcmpgtb %xmm1,%xmm5"); + asm volatile ("pcmpgtb %xmm9,%xmm13"); + asm volatile ("paddb %xmm1,%xmm1"); + asm volatile ("paddb %xmm9,%xmm9"); + asm volatile ("pand %xmm7,%xmm5"); + asm volatile ("pand %xmm7,%xmm13"); + asm volatile ("pxor %xmm5,%xmm1"); + asm volatile ("pxor %xmm13,%xmm9"); + + asm volatile ("pxor %xmm4,%xmm0"); + asm volatile ("pxor %xmm4,%xmm1"); + asm volatile ("pxor %xmm12,%xmm8"); + asm volatile ("pxor %xmm12,%xmm9"); + + asm volatile ("movdqa %xmm4,%xmm5"); + asm volatile ("movdqa %xmm12,%xmm13"); + asm volatile ("psrlw $4,%xmm5"); + asm volatile ("psrlw $4,%xmm13"); + asm volatile ("pand %xmm15,%xmm4"); + asm volatile ("pand %xmm15,%xmm12"); + asm volatile ("pand %xmm15,%xmm5"); + asm volatile ("pand %xmm15,%xmm13"); + + asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0])); + asm volatile ("movdqa %xmm6,%xmm14"); + asm volatile ("movdqa %xmm7,%xmm15"); + asm volatile ("pshufb %xmm4,%xmm6"); + asm volatile ("pshufb %xmm12,%xmm14"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pshufb %xmm13,%xmm15"); + asm volatile ("pxor %xmm6,%xmm2"); + asm volatile ("pxor %xmm14,%xmm10"); + asm volatile ("pxor %xmm7,%xmm2"); + asm volatile ("pxor %xmm15,%xmm10"); + + asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0])); + asm volatile ("movdqa %xmm6,%xmm14"); + asm volatile ("movdqa %xmm7,%xmm15"); + asm volatile ("pshufb %xmm4,%xmm6"); + asm volatile ("pshufb %xmm12,%xmm14"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pshufb %xmm13,%xmm15"); + asm volatile ("pxor %xmm6,%xmm3"); + asm volatile ("pxor %xmm14,%xmm11"); + asm volatile ("pxor %xmm7,%xmm3"); + asm volatile ("pxor %xmm15,%xmm11"); + } + + /* first disk with all coefficients at 1 */ + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); + asm volatile ("movdqa %0,%%xmm15" : : "m" (gfconst16.low4[0])); + asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i])); + asm volatile ("movdqa %0,%%xmm12" : : "m" (v[0][i + 16])); + + asm volatile ("pxor %xmm5,%xmm5"); + asm volatile ("pxor %xmm13,%xmm13"); + asm volatile ("pcmpgtb %xmm1,%xmm5"); + asm volatile ("pcmpgtb %xmm9,%xmm13"); + asm volatile ("paddb %xmm1,%xmm1"); + asm volatile ("paddb %xmm9,%xmm9"); + asm volatile ("pand %xmm7,%xmm5"); + asm volatile ("pand %xmm7,%xmm13"); + asm volatile ("pxor %xmm5,%xmm1"); + asm volatile ("pxor %xmm13,%xmm9"); + + asm volatile ("pxor %xmm4,%xmm0"); + asm volatile ("pxor %xmm4,%xmm1"); + asm volatile ("pxor %xmm4,%xmm2"); + asm volatile ("pxor %xmm4,%xmm3"); + asm volatile ("pxor %xmm12,%xmm8"); + asm volatile ("pxor %xmm12,%xmm9"); + asm volatile ("pxor %xmm12,%xmm10"); + asm volatile ("pxor %xmm12,%xmm11"); + + asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + asm volatile ("movntdq %%xmm8,%0" : "=m" (p[i + 16])); + asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); + asm volatile ("movntdq %%xmm9,%0" : "=m" (q[i + 16])); + asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); + asm volatile ("movntdq %%xmm10,%0" : "=m" (r[i + 16])); + asm volatile ("movntdq %%xmm3,%0" : "=m" (s[i])); + asm volatile ("movntdq %%xmm11,%0" : "=m" (s[i + 16])); + } + + raid_sse_end(); +} +#endif + +#if defined(CONFIG_X86_64) && defined(CONFIG_AVX2) +/* + * GEN4 (quad parity with Cauchy matrix) AVX2 implementation + * + * Note that it uses 16 registers, meaning that x64 is required. + */ +void raid_gen4_avx2ext(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *q; + uint8_t *r; + uint8_t *s; + int d, l; + size_t i; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + r = v[nd + 2]; + s = v[nd + 3]; + + /* special case with only one data disk */ + if (l == 0) { + for (i = 0; i < 4; ++i) + memcpy(v[1 + i], v[0], size); + return; + } + + raid_avx_begin(); + + /* generic case with at least two data disks */ + for (i = 0; i < size; i += 64) { + /* last disk without the by two multiplication */ + asm volatile ("vbroadcasti128 %0,%%ymm15" : : "m" (gfconst16.low4[0])); + asm volatile ("vmovdqa %0,%%ymm4" : : "m" (v[l][i])); + asm volatile ("vmovdqa %0,%%ymm12" : : "m" (v[l][i + 32])); + + asm volatile ("vmovdqa %ymm4,%ymm0"); + asm volatile ("vmovdqa %ymm4,%ymm1"); + asm volatile ("vmovdqa %ymm12,%ymm8"); + asm volatile ("vmovdqa %ymm12,%ymm9"); + + asm volatile ("vpsrlw $4,%ymm4,%ymm5"); + asm volatile ("vpsrlw $4,%ymm12,%ymm13"); + asm volatile ("vpand %ymm15,%ymm4,%ymm4"); + asm volatile ("vpand %ymm15,%ymm12,%ymm12"); + asm volatile ("vpand %ymm15,%ymm5,%ymm5"); + asm volatile ("vpand %ymm15,%ymm13,%ymm13"); + + asm volatile ("vbroadcasti128 %0,%%ymm10" : : "m" (gfgenpshufb[l][0][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm15" : : "m" (gfgenpshufb[l][0][1][0])); + asm volatile ("vpshufb %ymm4,%ymm10,%ymm2"); + asm volatile ("vpshufb %ymm5,%ymm15,%ymm7"); + asm volatile ("vpshufb %ymm12,%ymm10,%ymm10"); + asm volatile ("vpshufb %ymm13,%ymm15,%ymm15"); + asm volatile ("vpxor %ymm7,%ymm2,%ymm2"); + asm volatile ("vpxor %ymm15,%ymm10,%ymm10"); + + asm volatile ("vbroadcasti128 %0,%%ymm11" : : "m" (gfgenpshufb[l][1][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm15" : : "m" (gfgenpshufb[l][1][1][0])); + asm volatile ("vpshufb %ymm4,%ymm11,%ymm3"); + asm volatile ("vpshufb %ymm5,%ymm15,%ymm7"); + asm volatile ("vpshufb %ymm12,%ymm11,%ymm11"); + asm volatile ("vpshufb %ymm13,%ymm15,%ymm15"); + asm volatile ("vpxor %ymm7,%ymm3,%ymm3"); + asm volatile ("vpxor %ymm15,%ymm11,%ymm11"); + + /* intermediate disks */ + for (d = l - 1; d > 0; --d) { + asm volatile ("vbroadcasti128 %0,%%ymm7" : : "m" (gfconst16.poly[0])); + asm volatile ("vbroadcasti128 %0,%%ymm15" : : "m" (gfconst16.low4[0])); + asm volatile ("vmovdqa %0,%%ymm4" : : "m" (v[d][i])); + asm volatile ("vmovdqa %0,%%ymm12" : : "m" (v[d][i + 32])); + + asm volatile ("vpxor %ymm5,%ymm5,%ymm5"); + asm volatile ("vpxor %ymm13,%ymm13,%ymm13"); + asm volatile ("vpcmpgtb %ymm1,%ymm5,%ymm5"); + asm volatile ("vpcmpgtb %ymm9,%ymm13,%ymm13"); + asm volatile ("vpaddb %ymm1,%ymm1,%ymm1"); + asm volatile ("vpaddb %ymm9,%ymm9,%ymm9"); + asm volatile ("vpand %ymm7,%ymm5,%ymm5"); + asm volatile ("vpand %ymm7,%ymm13,%ymm13"); + asm volatile ("vpxor %ymm5,%ymm1,%ymm1"); + asm volatile ("vpxor %ymm13,%ymm9,%ymm9"); + + asm volatile ("vpxor %ymm4,%ymm0,%ymm0"); + asm volatile ("vpxor %ymm4,%ymm1,%ymm1"); + asm volatile ("vpxor %ymm12,%ymm8,%ymm8"); + asm volatile ("vpxor %ymm12,%ymm9,%ymm9"); + + asm volatile ("vpsrlw $4,%ymm4,%ymm5"); + asm volatile ("vpsrlw $4,%ymm12,%ymm13"); + asm volatile ("vpand %ymm15,%ymm4,%ymm4"); + asm volatile ("vpand %ymm15,%ymm12,%ymm12"); + asm volatile ("vpand %ymm15,%ymm5,%ymm5"); + asm volatile ("vpand %ymm15,%ymm13,%ymm13"); + + asm volatile ("vbroadcasti128 %0,%%ymm14" : : "m" (gfgenpshufb[d][0][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm15" : : "m" (gfgenpshufb[d][0][1][0])); + asm volatile ("vpshufb %ymm4,%ymm14,%ymm6"); + asm volatile ("vpshufb %ymm5,%ymm15,%ymm7"); + asm volatile ("vpshufb %ymm12,%ymm14,%ymm14"); + asm volatile ("vpshufb %ymm13,%ymm15,%ymm15"); + asm volatile ("vpxor %ymm6,%ymm2,%ymm2"); + asm volatile ("vpxor %ymm14,%ymm10,%ymm10"); + asm volatile ("vpxor %ymm7,%ymm2,%ymm2"); + asm volatile ("vpxor %ymm15,%ymm10,%ymm10"); + + asm volatile ("vbroadcasti128 %0,%%ymm14" : : "m" (gfgenpshufb[d][1][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm15" : : "m" (gfgenpshufb[d][1][1][0])); + asm volatile ("vpshufb %ymm4,%ymm14,%ymm6"); + asm volatile ("vpshufb %ymm5,%ymm15,%ymm7"); + asm volatile ("vpshufb %ymm12,%ymm14,%ymm14"); + asm volatile ("vpshufb %ymm13,%ymm15,%ymm15"); + asm volatile ("vpxor %ymm6,%ymm3,%ymm3"); + asm volatile ("vpxor %ymm14,%ymm11,%ymm11"); + asm volatile ("vpxor %ymm7,%ymm3,%ymm3"); + asm volatile ("vpxor %ymm15,%ymm11,%ymm11"); + } + + /* first disk with all coefficients at 1 */ + asm volatile ("vbroadcasti128 %0,%%ymm7" : : "m" (gfconst16.poly[0])); + asm volatile ("vbroadcasti128 %0,%%ymm15" : : "m" (gfconst16.low4[0])); + asm volatile ("vmovdqa %0,%%ymm4" : : "m" (v[0][i])); + asm volatile ("vmovdqa %0,%%ymm12" : : "m" (v[0][i + 32])); + + asm volatile ("vpxor %ymm5,%ymm5,%ymm5"); + asm volatile ("vpxor %ymm13,%ymm13,%ymm13"); + asm volatile ("vpcmpgtb %ymm1,%ymm5,%ymm5"); + asm volatile ("vpcmpgtb %ymm9,%ymm13,%ymm13"); + asm volatile ("vpaddb %ymm1,%ymm1,%ymm1"); + asm volatile ("vpaddb %ymm9,%ymm9,%ymm9"); + asm volatile ("vpand %ymm7,%ymm5,%ymm5"); + asm volatile ("vpand %ymm7,%ymm13,%ymm13"); + asm volatile ("vpxor %ymm5,%ymm1,%ymm1"); + asm volatile ("vpxor %ymm13,%ymm9,%ymm9"); + + asm volatile ("vpxor %ymm4,%ymm0,%ymm0"); + asm volatile ("vpxor %ymm4,%ymm1,%ymm1"); + asm volatile ("vpxor %ymm4,%ymm2,%ymm2"); + asm volatile ("vpxor %ymm4,%ymm3,%ymm3"); + asm volatile ("vpxor %ymm12,%ymm8,%ymm8"); + asm volatile ("vpxor %ymm12,%ymm9,%ymm9"); + asm volatile ("vpxor %ymm12,%ymm10,%ymm10"); + asm volatile ("vpxor %ymm12,%ymm11,%ymm11"); + + asm volatile ("vmovntdq %%ymm0,%0" : "=m" (p[i])); + asm volatile ("vmovntdq %%ymm8,%0" : "=m" (p[i + 32])); + asm volatile ("vmovntdq %%ymm1,%0" : "=m" (q[i])); + asm volatile ("vmovntdq %%ymm9,%0" : "=m" (q[i + 32])); + asm volatile ("vmovntdq %%ymm2,%0" : "=m" (r[i])); + asm volatile ("vmovntdq %%ymm10,%0" : "=m" (r[i + 32])); + asm volatile ("vmovntdq %%ymm3,%0" : "=m" (s[i])); + asm volatile ("vmovntdq %%ymm11,%0" : "=m" (s[i + 32])); + } + + raid_avx_end(); +} +#endif + +#if defined(CONFIG_X86) && defined(CONFIG_SSSE3) +/* + * GEN5 (penta parity with Cauchy matrix) SSSE3 implementation + */ +void raid_gen5_ssse3(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *q; + uint8_t *r; + uint8_t *s; + uint8_t *t; + int d, l; + size_t i; + uint8_t buffer[16+16]; + uint8_t *pd = __align_ptr(buffer, 16); + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + r = v[nd + 2]; + s = v[nd + 3]; + t = v[nd + 4]; + + /* special case with only one data disk */ + if (l == 0) { + for (i = 0; i < 5; ++i) + memcpy(v[1 + i], v[0], size); + return; + } + + raid_sse_begin(); + + /* generic case with at least two data disks */ + for (i = 0; i < size; i += 16) { + /* last disk without the by two multiplication */ + asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i])); + + asm volatile ("movdqa %xmm4,%xmm0"); + asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[0])); + + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + asm volatile ("movdqa %xmm4,%xmm5"); + asm volatile ("psrlw $4,%xmm5"); + asm volatile ("pand %xmm7,%xmm4"); + asm volatile ("pand %xmm7,%xmm5"); + + asm volatile ("movdqa %0,%%xmm1" : : "m" (gfgenpshufb[l][0][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0])); + asm volatile ("pshufb %xmm4,%xmm1"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pxor %xmm7,%xmm1"); + + asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][1][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0])); + asm volatile ("pshufb %xmm4,%xmm2"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pxor %xmm7,%xmm2"); + + asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][2][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][2][1][0])); + asm volatile ("pshufb %xmm4,%xmm3"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pxor %xmm7,%xmm3"); + + /* intermediate disks */ + for (d = l - 1; d > 0; --d) { + asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); + asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); + + asm volatile ("pxor %xmm5,%xmm5"); + asm volatile ("pcmpgtb %xmm0,%xmm5"); + asm volatile ("paddb %xmm0,%xmm0"); + asm volatile ("pand %xmm7,%xmm5"); + asm volatile ("pxor %xmm5,%xmm0"); + + asm volatile ("pxor %xmm4,%xmm0"); + asm volatile ("pxor %xmm4,%xmm6"); + asm volatile ("movdqa %%xmm6,%0" : "=m" (pd[0])); + + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + asm volatile ("movdqa %xmm4,%xmm5"); + asm volatile ("psrlw $4,%xmm5"); + asm volatile ("pand %xmm7,%xmm4"); + asm volatile ("pand %xmm7,%xmm5"); + + asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0])); + asm volatile ("pshufb %xmm4,%xmm6"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pxor %xmm6,%xmm1"); + asm volatile ("pxor %xmm7,%xmm1"); + + asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0])); + asm volatile ("pshufb %xmm4,%xmm6"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pxor %xmm6,%xmm2"); + asm volatile ("pxor %xmm7,%xmm2"); + + asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][2][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][2][1][0])); + asm volatile ("pshufb %xmm4,%xmm6"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pxor %xmm6,%xmm3"); + asm volatile ("pxor %xmm7,%xmm3"); + } + + /* first disk with all coefficients at 1 */ + asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i])); + asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); + + asm volatile ("pxor %xmm5,%xmm5"); + asm volatile ("pcmpgtb %xmm0,%xmm5"); + asm volatile ("paddb %xmm0,%xmm0"); + asm volatile ("pand %xmm7,%xmm5"); + asm volatile ("pxor %xmm5,%xmm0"); + + asm volatile ("pxor %xmm4,%xmm0"); + asm volatile ("pxor %xmm4,%xmm1"); + asm volatile ("pxor %xmm4,%xmm2"); + asm volatile ("pxor %xmm4,%xmm3"); + asm volatile ("pxor %xmm4,%xmm6"); + + asm volatile ("movntdq %%xmm6,%0" : "=m" (p[i])); + asm volatile ("movntdq %%xmm0,%0" : "=m" (q[i])); + asm volatile ("movntdq %%xmm1,%0" : "=m" (r[i])); + asm volatile ("movntdq %%xmm2,%0" : "=m" (s[i])); + asm volatile ("movntdq %%xmm3,%0" : "=m" (t[i])); + } + + raid_sse_end(); +} +#endif + +#if defined(CONFIG_X86_64) && defined(CONFIG_SSSE3) +/* + * GEN5 (penta parity with Cauchy matrix) SSSE3 implementation + * + * Note that it uses 16 registers, meaning that x64 is required. + */ +void raid_gen5_ssse3ext(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *q; + uint8_t *r; + uint8_t *s; + uint8_t *t; + int d, l; + size_t i; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + r = v[nd + 2]; + s = v[nd + 3]; + t = v[nd + 4]; + + /* special case with only one data disk */ + if (l == 0) { + for (i = 0; i < 5; ++i) + memcpy(v[1 + i], v[0], size); + return; + } + + raid_sse_begin(); + + /* generic case with at least two data disks */ + asm volatile ("movdqa %0,%%xmm14" : : "m" (gfconst16.poly[0])); + asm volatile ("movdqa %0,%%xmm15" : : "m" (gfconst16.low4[0])); + + for (i = 0; i < size; i += 16) { + /* last disk without the by two multiplication */ + asm volatile ("movdqa %0,%%xmm10" : : "m" (v[l][i])); + + asm volatile ("movdqa %xmm10,%xmm0"); + asm volatile ("movdqa %xmm10,%xmm1"); + + asm volatile ("movdqa %xmm10,%xmm11"); + asm volatile ("psrlw $4,%xmm11"); + asm volatile ("pand %xmm15,%xmm10"); + asm volatile ("pand %xmm15,%xmm11"); + + asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][0][0][0])); + asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[l][0][1][0])); + asm volatile ("pshufb %xmm10,%xmm2"); + asm volatile ("pshufb %xmm11,%xmm13"); + asm volatile ("pxor %xmm13,%xmm2"); + + asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][1][0][0])); + asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[l][1][1][0])); + asm volatile ("pshufb %xmm10,%xmm3"); + asm volatile ("pshufb %xmm11,%xmm13"); + asm volatile ("pxor %xmm13,%xmm3"); + + asm volatile ("movdqa %0,%%xmm4" : : "m" (gfgenpshufb[l][2][0][0])); + asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[l][2][1][0])); + asm volatile ("pshufb %xmm10,%xmm4"); + asm volatile ("pshufb %xmm11,%xmm13"); + asm volatile ("pxor %xmm13,%xmm4"); + + /* intermediate disks */ + for (d = l - 1; d > 0; --d) { + asm volatile ("movdqa %0,%%xmm10" : : "m" (v[d][i])); + + asm volatile ("pxor %xmm11,%xmm11"); + asm volatile ("pcmpgtb %xmm1,%xmm11"); + asm volatile ("paddb %xmm1,%xmm1"); + asm volatile ("pand %xmm14,%xmm11"); + asm volatile ("pxor %xmm11,%xmm1"); + + asm volatile ("pxor %xmm10,%xmm0"); + asm volatile ("pxor %xmm10,%xmm1"); + + asm volatile ("movdqa %xmm10,%xmm11"); + asm volatile ("psrlw $4,%xmm11"); + asm volatile ("pand %xmm15,%xmm10"); + asm volatile ("pand %xmm15,%xmm11"); + + asm volatile ("movdqa %0,%%xmm12" : : "m" (gfgenpshufb[d][0][0][0])); + asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[d][0][1][0])); + asm volatile ("pshufb %xmm10,%xmm12"); + asm volatile ("pshufb %xmm11,%xmm13"); + asm volatile ("pxor %xmm12,%xmm2"); + asm volatile ("pxor %xmm13,%xmm2"); + + asm volatile ("movdqa %0,%%xmm12" : : "m" (gfgenpshufb[d][1][0][0])); + asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[d][1][1][0])); + asm volatile ("pshufb %xmm10,%xmm12"); + asm volatile ("pshufb %xmm11,%xmm13"); + asm volatile ("pxor %xmm12,%xmm3"); + asm volatile ("pxor %xmm13,%xmm3"); + + asm volatile ("movdqa %0,%%xmm12" : : "m" (gfgenpshufb[d][2][0][0])); + asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[d][2][1][0])); + asm volatile ("pshufb %xmm10,%xmm12"); + asm volatile ("pshufb %xmm11,%xmm13"); + asm volatile ("pxor %xmm12,%xmm4"); + asm volatile ("pxor %xmm13,%xmm4"); + } + + /* first disk with all coefficients at 1 */ + asm volatile ("movdqa %0,%%xmm10" : : "m" (v[0][i])); + + asm volatile ("pxor %xmm11,%xmm11"); + asm volatile ("pcmpgtb %xmm1,%xmm11"); + asm volatile ("paddb %xmm1,%xmm1"); + asm volatile ("pand %xmm14,%xmm11"); + asm volatile ("pxor %xmm11,%xmm1"); + + asm volatile ("pxor %xmm10,%xmm0"); + asm volatile ("pxor %xmm10,%xmm1"); + asm volatile ("pxor %xmm10,%xmm2"); + asm volatile ("pxor %xmm10,%xmm3"); + asm volatile ("pxor %xmm10,%xmm4"); + + asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); + asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); + asm volatile ("movntdq %%xmm3,%0" : "=m" (s[i])); + asm volatile ("movntdq %%xmm4,%0" : "=m" (t[i])); + } + + raid_sse_end(); +} +#endif + +#if defined(CONFIG_X86_64) && defined(CONFIG_AVX2) +/* + * GEN5 (penta parity with Cauchy matrix) AVX2 implementation + * + * Note that it uses 16 registers, meaning that x64 is required. + */ +void raid_gen5_avx2ext(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *q; + uint8_t *r; + uint8_t *s; + uint8_t *t; + int d, l; + size_t i; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + r = v[nd + 2]; + s = v[nd + 3]; + t = v[nd + 4]; + + /* special case with only one data disk */ + if (l == 0) { + for (i = 0; i < 5; ++i) + memcpy(v[1 + i], v[0], size); + return; + } + + raid_avx_begin(); + + /* generic case with at least two data disks */ + asm volatile ("vpxor %ymm8,%ymm8,%ymm8"); + asm volatile ("vbroadcasti128 %0,%%ymm14" : : "m" (gfconst16.poly[0])); + asm volatile ("vbroadcasti128 %0,%%ymm15" : : "m" (gfconst16.low4[0])); + + for (i = 0; i < size; i += 32) { + /* last disk without the by two multiplication */ + asm volatile ("vmovdqa %0,%%ymm10" : : "m" (v[l][i])); + + asm volatile ("vmovdqa %ymm10,%ymm0"); + asm volatile ("vmovdqa %ymm10,%ymm1"); + + asm volatile ("vpsrlw $4,%ymm10,%ymm11"); + asm volatile ("vpand %ymm15,%ymm10,%ymm10"); + asm volatile ("vpand %ymm15,%ymm11,%ymm11"); + + asm volatile ("vbroadcasti128 %0,%%ymm2" : : "m" (gfgenpshufb[l][0][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm13" : : "m" (gfgenpshufb[l][0][1][0])); + asm volatile ("vpshufb %ymm10,%ymm2,%ymm2"); + asm volatile ("vpshufb %ymm11,%ymm13,%ymm13"); + asm volatile ("vpxor %ymm13,%ymm2,%ymm2"); + + asm volatile ("vbroadcasti128 %0,%%ymm3" : : "m" (gfgenpshufb[l][1][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm13" : : "m" (gfgenpshufb[l][1][1][0])); + asm volatile ("vpshufb %ymm10,%ymm3,%ymm3"); + asm volatile ("vpshufb %ymm11,%ymm13,%ymm13"); + asm volatile ("vpxor %ymm13,%ymm3,%ymm3"); + + asm volatile ("vbroadcasti128 %0,%%ymm4" : : "m" (gfgenpshufb[l][2][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm13" : : "m" (gfgenpshufb[l][2][1][0])); + asm volatile ("vpshufb %ymm10,%ymm4,%ymm4"); + asm volatile ("vpshufb %ymm11,%ymm13,%ymm13"); + asm volatile ("vpxor %ymm13,%ymm4,%ymm4"); + + /* intermediate disks */ + for (d = l - 1; d > 0; --d) { + asm volatile ("vmovdqa %0,%%ymm10" : : "m" (v[d][i])); + + asm volatile ("vpcmpgtb %ymm1,%ymm8,%ymm11"); + asm volatile ("vpaddb %ymm1,%ymm1,%ymm1"); + asm volatile ("vpand %ymm14,%ymm11,%ymm11"); + asm volatile ("vpxor %ymm11,%ymm1,%ymm1"); + + asm volatile ("vpxor %ymm10,%ymm0,%ymm0"); + asm volatile ("vpxor %ymm10,%ymm1,%ymm1"); + + asm volatile ("vpsrlw $4,%ymm10,%ymm11"); + asm volatile ("vpand %ymm15,%ymm10,%ymm10"); + asm volatile ("vpand %ymm15,%ymm11,%ymm11"); + + asm volatile ("vbroadcasti128 %0,%%ymm12" : : "m" (gfgenpshufb[d][0][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm13" : : "m" (gfgenpshufb[d][0][1][0])); + asm volatile ("vpshufb %ymm10,%ymm12,%ymm12"); + asm volatile ("vpshufb %ymm11,%ymm13,%ymm13"); + asm volatile ("vpxor %ymm12,%ymm2,%ymm2"); + asm volatile ("vpxor %ymm13,%ymm2,%ymm2"); + + asm volatile ("vbroadcasti128 %0,%%ymm12" : : "m" (gfgenpshufb[d][1][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm13" : : "m" (gfgenpshufb[d][1][1][0])); + asm volatile ("vpshufb %ymm10,%ymm12,%ymm12"); + asm volatile ("vpshufb %ymm11,%ymm13,%ymm13"); + asm volatile ("vpxor %ymm12,%ymm3,%ymm3"); + asm volatile ("vpxor %ymm13,%ymm3,%ymm3"); + + asm volatile ("vbroadcasti128 %0,%%ymm12" : : "m" (gfgenpshufb[d][2][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm13" : : "m" (gfgenpshufb[d][2][1][0])); + asm volatile ("vpshufb %ymm10,%ymm12,%ymm12"); + asm volatile ("vpshufb %ymm11,%ymm13,%ymm13"); + asm volatile ("vpxor %ymm12,%ymm4,%ymm4"); + asm volatile ("vpxor %ymm13,%ymm4,%ymm4"); + } + + /* first disk with all coefficients at 1 */ + asm volatile ("vmovdqa %0,%%ymm10" : : "m" (v[0][i])); + + asm volatile ("vpcmpgtb %ymm1,%ymm8,%ymm11"); + asm volatile ("vpaddb %ymm1,%ymm1,%ymm1"); + asm volatile ("vpand %ymm14,%ymm11,%ymm11"); + asm volatile ("vpxor %ymm11,%ymm1,%ymm1"); + + asm volatile ("vpxor %ymm10,%ymm0,%ymm0"); + asm volatile ("vpxor %ymm10,%ymm1,%ymm1"); + asm volatile ("vpxor %ymm10,%ymm2,%ymm2"); + asm volatile ("vpxor %ymm10,%ymm3,%ymm3"); + asm volatile ("vpxor %ymm10,%ymm4,%ymm4"); + + asm volatile ("vmovntdq %%ymm0,%0" : "=m" (p[i])); + asm volatile ("vmovntdq %%ymm1,%0" : "=m" (q[i])); + asm volatile ("vmovntdq %%ymm2,%0" : "=m" (r[i])); + asm volatile ("vmovntdq %%ymm3,%0" : "=m" (s[i])); + asm volatile ("vmovntdq %%ymm4,%0" : "=m" (t[i])); + } + + raid_avx_end(); +} +#endif + +#if defined(CONFIG_X86) && defined(CONFIG_SSSE3) +/* + * GEN6 (hexa parity with Cauchy matrix) SSSE3 implementation + */ +void raid_gen6_ssse3(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *q; + uint8_t *r; + uint8_t *s; + uint8_t *t; + uint8_t *u; + int d, l; + size_t i; + uint8_t buffer[2*16+16]; + uint8_t *pd = __align_ptr(buffer, 16); + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + r = v[nd + 2]; + s = v[nd + 3]; + t = v[nd + 4]; + u = v[nd + 5]; + + /* special case with only one data disk */ + if (l == 0) { + for (i = 0; i < 6; ++i) + memcpy(v[1 + i], v[0], size); + return; + } + + raid_sse_begin(); + + /* generic case with at least two data disks */ + for (i = 0; i < size; i += 16) { + /* last disk without the by two multiplication */ + asm volatile ("movdqa %0,%%xmm4" : : "m" (v[l][i])); + + asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[0])); + asm volatile ("movdqa %%xmm4,%0" : "=m" (pd[16])); + + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + asm volatile ("movdqa %xmm4,%xmm5"); + asm volatile ("psrlw $4,%xmm5"); + asm volatile ("pand %xmm7,%xmm4"); + asm volatile ("pand %xmm7,%xmm5"); + + asm volatile ("movdqa %0,%%xmm0" : : "m" (gfgenpshufb[l][0][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][0][1][0])); + asm volatile ("pshufb %xmm4,%xmm0"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pxor %xmm7,%xmm0"); + + asm volatile ("movdqa %0,%%xmm1" : : "m" (gfgenpshufb[l][1][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][1][1][0])); + asm volatile ("pshufb %xmm4,%xmm1"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pxor %xmm7,%xmm1"); + + asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][2][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][2][1][0])); + asm volatile ("pshufb %xmm4,%xmm2"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pxor %xmm7,%xmm2"); + + asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][3][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[l][3][1][0])); + asm volatile ("pshufb %xmm4,%xmm3"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pxor %xmm7,%xmm3"); + + /* intermediate disks */ + for (d = l - 1; d > 0; --d) { + asm volatile ("movdqa %0,%%xmm5" : : "m" (pd[0])); + asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[16])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); + + asm volatile ("pxor %xmm4,%xmm4"); + asm volatile ("pcmpgtb %xmm6,%xmm4"); + asm volatile ("paddb %xmm6,%xmm6"); + asm volatile ("pand %xmm7,%xmm4"); + asm volatile ("pxor %xmm4,%xmm6"); + + asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); + + asm volatile ("pxor %xmm4,%xmm5"); + asm volatile ("pxor %xmm4,%xmm6"); + asm volatile ("movdqa %%xmm5,%0" : "=m" (pd[0])); + asm volatile ("movdqa %%xmm6,%0" : "=m" (pd[16])); + + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + asm volatile ("movdqa %xmm4,%xmm5"); + asm volatile ("psrlw $4,%xmm5"); + asm volatile ("pand %xmm7,%xmm4"); + asm volatile ("pand %xmm7,%xmm5"); + + asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][0][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][0][1][0])); + asm volatile ("pshufb %xmm4,%xmm6"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pxor %xmm6,%xmm0"); + asm volatile ("pxor %xmm7,%xmm0"); + + asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][1][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][1][1][0])); + asm volatile ("pshufb %xmm4,%xmm6"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pxor %xmm6,%xmm1"); + asm volatile ("pxor %xmm7,%xmm1"); + + asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][2][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][2][1][0])); + asm volatile ("pshufb %xmm4,%xmm6"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pxor %xmm6,%xmm2"); + asm volatile ("pxor %xmm7,%xmm2"); + + asm volatile ("movdqa %0,%%xmm6" : : "m" (gfgenpshufb[d][3][0][0])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfgenpshufb[d][3][1][0])); + asm volatile ("pshufb %xmm4,%xmm6"); + asm volatile ("pshufb %xmm5,%xmm7"); + asm volatile ("pxor %xmm6,%xmm3"); + asm volatile ("pxor %xmm7,%xmm3"); + } + + /* first disk with all coefficients at 1 */ + asm volatile ("movdqa %0,%%xmm5" : : "m" (pd[0])); + asm volatile ("movdqa %0,%%xmm6" : : "m" (pd[16])); + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.poly[0])); + + asm volatile ("pxor %xmm4,%xmm4"); + asm volatile ("pcmpgtb %xmm6,%xmm4"); + asm volatile ("paddb %xmm6,%xmm6"); + asm volatile ("pand %xmm7,%xmm4"); + asm volatile ("pxor %xmm4,%xmm6"); + + asm volatile ("movdqa %0,%%xmm4" : : "m" (v[0][i])); + asm volatile ("pxor %xmm4,%xmm0"); + asm volatile ("pxor %xmm4,%xmm1"); + asm volatile ("pxor %xmm4,%xmm2"); + asm volatile ("pxor %xmm4,%xmm3"); + asm volatile ("pxor %xmm4,%xmm5"); + asm volatile ("pxor %xmm4,%xmm6"); + + asm volatile ("movntdq %%xmm5,%0" : "=m" (p[i])); + asm volatile ("movntdq %%xmm6,%0" : "=m" (q[i])); + asm volatile ("movntdq %%xmm0,%0" : "=m" (r[i])); + asm volatile ("movntdq %%xmm1,%0" : "=m" (s[i])); + asm volatile ("movntdq %%xmm2,%0" : "=m" (t[i])); + asm volatile ("movntdq %%xmm3,%0" : "=m" (u[i])); + } + + raid_sse_end(); +} +#endif + +#if defined(CONFIG_X86_64) && defined(CONFIG_SSSE3) +/* + * GEN6 (hexa parity with Cauchy matrix) SSSE3 implementation + * + * Note that it uses 16 registers, meaning that x64 is required. + */ +void raid_gen6_ssse3ext(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *q; + uint8_t *r; + uint8_t *s; + uint8_t *t; + uint8_t *u; + int d, l; + size_t i; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + r = v[nd + 2]; + s = v[nd + 3]; + t = v[nd + 4]; + u = v[nd + 5]; + + /* special case with only one data disk */ + if (l == 0) { + for (i = 0; i < 6; ++i) + memcpy(v[1 + i], v[0], size); + return; + } + + raid_sse_begin(); + + /* generic case with at least two data disks */ + asm volatile ("movdqa %0,%%xmm14" : : "m" (gfconst16.poly[0])); + asm volatile ("movdqa %0,%%xmm15" : : "m" (gfconst16.low4[0])); + + for (i = 0; i < size; i += 16) { + /* last disk without the by two multiplication */ + asm volatile ("movdqa %0,%%xmm10" : : "m" (v[l][i])); + + asm volatile ("movdqa %xmm10,%xmm0"); + asm volatile ("movdqa %xmm10,%xmm1"); + + asm volatile ("movdqa %xmm10,%xmm11"); + asm volatile ("psrlw $4,%xmm11"); + asm volatile ("pand %xmm15,%xmm10"); + asm volatile ("pand %xmm15,%xmm11"); + + asm volatile ("movdqa %0,%%xmm2" : : "m" (gfgenpshufb[l][0][0][0])); + asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[l][0][1][0])); + asm volatile ("pshufb %xmm10,%xmm2"); + asm volatile ("pshufb %xmm11,%xmm13"); + asm volatile ("pxor %xmm13,%xmm2"); + + asm volatile ("movdqa %0,%%xmm3" : : "m" (gfgenpshufb[l][1][0][0])); + asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[l][1][1][0])); + asm volatile ("pshufb %xmm10,%xmm3"); + asm volatile ("pshufb %xmm11,%xmm13"); + asm volatile ("pxor %xmm13,%xmm3"); + + asm volatile ("movdqa %0,%%xmm4" : : "m" (gfgenpshufb[l][2][0][0])); + asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[l][2][1][0])); + asm volatile ("pshufb %xmm10,%xmm4"); + asm volatile ("pshufb %xmm11,%xmm13"); + asm volatile ("pxor %xmm13,%xmm4"); + + asm volatile ("movdqa %0,%%xmm5" : : "m" (gfgenpshufb[l][3][0][0])); + asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[l][3][1][0])); + asm volatile ("pshufb %xmm10,%xmm5"); + asm volatile ("pshufb %xmm11,%xmm13"); + asm volatile ("pxor %xmm13,%xmm5"); + + /* intermediate disks */ + for (d = l - 1; d > 0; --d) { + asm volatile ("movdqa %0,%%xmm10" : : "m" (v[d][i])); + + asm volatile ("pxor %xmm11,%xmm11"); + asm volatile ("pcmpgtb %xmm1,%xmm11"); + asm volatile ("paddb %xmm1,%xmm1"); + asm volatile ("pand %xmm14,%xmm11"); + asm volatile ("pxor %xmm11,%xmm1"); + + asm volatile ("pxor %xmm10,%xmm0"); + asm volatile ("pxor %xmm10,%xmm1"); + + asm volatile ("movdqa %xmm10,%xmm11"); + asm volatile ("psrlw $4,%xmm11"); + asm volatile ("pand %xmm15,%xmm10"); + asm volatile ("pand %xmm15,%xmm11"); + + asm volatile ("movdqa %0,%%xmm12" : : "m" (gfgenpshufb[d][0][0][0])); + asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[d][0][1][0])); + asm volatile ("pshufb %xmm10,%xmm12"); + asm volatile ("pshufb %xmm11,%xmm13"); + asm volatile ("pxor %xmm12,%xmm2"); + asm volatile ("pxor %xmm13,%xmm2"); + + asm volatile ("movdqa %0,%%xmm12" : : "m" (gfgenpshufb[d][1][0][0])); + asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[d][1][1][0])); + asm volatile ("pshufb %xmm10,%xmm12"); + asm volatile ("pshufb %xmm11,%xmm13"); + asm volatile ("pxor %xmm12,%xmm3"); + asm volatile ("pxor %xmm13,%xmm3"); + + asm volatile ("movdqa %0,%%xmm12" : : "m" (gfgenpshufb[d][2][0][0])); + asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[d][2][1][0])); + asm volatile ("pshufb %xmm10,%xmm12"); + asm volatile ("pshufb %xmm11,%xmm13"); + asm volatile ("pxor %xmm12,%xmm4"); + asm volatile ("pxor %xmm13,%xmm4"); + + asm volatile ("movdqa %0,%%xmm12" : : "m" (gfgenpshufb[d][3][0][0])); + asm volatile ("movdqa %0,%%xmm13" : : "m" (gfgenpshufb[d][3][1][0])); + asm volatile ("pshufb %xmm10,%xmm12"); + asm volatile ("pshufb %xmm11,%xmm13"); + asm volatile ("pxor %xmm12,%xmm5"); + asm volatile ("pxor %xmm13,%xmm5"); + } + + /* first disk with all coefficients at 1 */ + asm volatile ("movdqa %0,%%xmm10" : : "m" (v[0][i])); + + asm volatile ("pxor %xmm11,%xmm11"); + asm volatile ("pcmpgtb %xmm1,%xmm11"); + asm volatile ("paddb %xmm1,%xmm1"); + asm volatile ("pand %xmm14,%xmm11"); + asm volatile ("pxor %xmm11,%xmm1"); + + asm volatile ("pxor %xmm10,%xmm0"); + asm volatile ("pxor %xmm10,%xmm1"); + asm volatile ("pxor %xmm10,%xmm2"); + asm volatile ("pxor %xmm10,%xmm3"); + asm volatile ("pxor %xmm10,%xmm4"); + asm volatile ("pxor %xmm10,%xmm5"); + + asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); + asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); + asm volatile ("movntdq %%xmm3,%0" : "=m" (s[i])); + asm volatile ("movntdq %%xmm4,%0" : "=m" (t[i])); + asm volatile ("movntdq %%xmm5,%0" : "=m" (u[i])); + } + + raid_sse_end(); +} +#endif + +#if defined(CONFIG_X86_64) && defined(CONFIG_AVX2) +/* + * GEN6 (hexa parity with Cauchy matrix) AVX2 implementation + * + * Note that it uses 16 registers, meaning that x64 is required. + */ +void raid_gen6_avx2ext(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *q; + uint8_t *r; + uint8_t *s; + uint8_t *t; + uint8_t *u; + int d, l; + size_t i; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + r = v[nd + 2]; + s = v[nd + 3]; + t = v[nd + 4]; + u = v[nd + 5]; + + /* special case with only one data disk */ + if (l == 0) { + for (i = 0; i < 6; ++i) + memcpy(v[1 + i], v[0], size); + return; + } + + raid_avx_begin(); + + /* generic case with at least two data disks */ + asm volatile ("vpxor %ymm8,%ymm8,%ymm8"); + asm volatile ("vbroadcasti128 %0,%%ymm14" : : "m" (gfconst16.poly[0])); + asm volatile ("vbroadcasti128 %0,%%ymm15" : : "m" (gfconst16.low4[0])); + + for (i = 0; i < size; i += 32) { + /* last disk without the by two multiplication */ + asm volatile ("vmovdqa %0,%%ymm10" : : "m" (v[l][i])); + + asm volatile ("vmovdqa %ymm10,%ymm0"); + asm volatile ("vmovdqa %ymm10,%ymm1"); + + asm volatile ("vpsrlw $4,%ymm10,%ymm11"); + asm volatile ("vpand %ymm15,%ymm10,%ymm10"); + asm volatile ("vpand %ymm15,%ymm11,%ymm11"); + + asm volatile ("vbroadcasti128 %0,%%ymm2" : : "m" (gfgenpshufb[l][0][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm13" : : "m" (gfgenpshufb[l][0][1][0])); + asm volatile ("vpshufb %ymm10,%ymm2,%ymm2"); + asm volatile ("vpshufb %ymm11,%ymm13,%ymm13"); + asm volatile ("vpxor %ymm13,%ymm2,%ymm2"); + + asm volatile ("vbroadcasti128 %0,%%ymm3" : : "m" (gfgenpshufb[l][1][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm13" : : "m" (gfgenpshufb[l][1][1][0])); + asm volatile ("vpshufb %ymm10,%ymm3,%ymm3"); + asm volatile ("vpshufb %ymm11,%ymm13,%ymm13"); + asm volatile ("vpxor %ymm13,%ymm3,%ymm3"); + + asm volatile ("vbroadcasti128 %0,%%ymm4" : : "m" (gfgenpshufb[l][2][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm13" : : "m" (gfgenpshufb[l][2][1][0])); + asm volatile ("vpshufb %ymm10,%ymm4,%ymm4"); + asm volatile ("vpshufb %ymm11,%ymm13,%ymm13"); + asm volatile ("vpxor %ymm13,%ymm4,%ymm4"); + + asm volatile ("vbroadcasti128 %0,%%ymm5" : : "m" (gfgenpshufb[l][3][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm13" : : "m" (gfgenpshufb[l][3][1][0])); + asm volatile ("vpshufb %ymm10,%ymm5,%ymm5"); + asm volatile ("vpshufb %ymm11,%ymm13,%ymm13"); + asm volatile ("vpxor %ymm13,%ymm5,%ymm5"); + + /* intermediate disks */ + for (d = l - 1; d > 0; --d) { + asm volatile ("vmovdqa %0,%%ymm10" : : "m" (v[d][i])); + + asm volatile ("vpcmpgtb %ymm1,%ymm8,%ymm11"); + asm volatile ("vpaddb %ymm1,%ymm1,%ymm1"); + asm volatile ("vpand %ymm14,%ymm11,%ymm11"); + asm volatile ("vpxor %ymm11,%ymm1,%ymm1"); + + asm volatile ("vpxor %ymm10,%ymm0,%ymm0"); + asm volatile ("vpxor %ymm10,%ymm1,%ymm1"); + + asm volatile ("vpsrlw $4,%ymm10,%ymm11"); + asm volatile ("vpand %ymm15,%ymm10,%ymm10"); + asm volatile ("vpand %ymm15,%ymm11,%ymm11"); + + asm volatile ("vbroadcasti128 %0,%%ymm12" : : "m" (gfgenpshufb[d][0][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm13" : : "m" (gfgenpshufb[d][0][1][0])); + asm volatile ("vpshufb %ymm10,%ymm12,%ymm12"); + asm volatile ("vpshufb %ymm11,%ymm13,%ymm13"); + asm volatile ("vpxor %ymm12,%ymm2,%ymm2"); + asm volatile ("vpxor %ymm13,%ymm2,%ymm2"); + + asm volatile ("vbroadcasti128 %0,%%ymm12" : : "m" (gfgenpshufb[d][1][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm13" : : "m" (gfgenpshufb[d][1][1][0])); + asm volatile ("vpshufb %ymm10,%ymm12,%ymm12"); + asm volatile ("vpshufb %ymm11,%ymm13,%ymm13"); + asm volatile ("vpxor %ymm12,%ymm3,%ymm3"); + asm volatile ("vpxor %ymm13,%ymm3,%ymm3"); + + asm volatile ("vbroadcasti128 %0,%%ymm12" : : "m" (gfgenpshufb[d][2][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm13" : : "m" (gfgenpshufb[d][2][1][0])); + asm volatile ("vpshufb %ymm10,%ymm12,%ymm12"); + asm volatile ("vpshufb %ymm11,%ymm13,%ymm13"); + asm volatile ("vpxor %ymm12,%ymm4,%ymm4"); + asm volatile ("vpxor %ymm13,%ymm4,%ymm4"); + + asm volatile ("vbroadcasti128 %0,%%ymm12" : : "m" (gfgenpshufb[d][3][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm13" : : "m" (gfgenpshufb[d][3][1][0])); + asm volatile ("vpshufb %ymm10,%ymm12,%ymm12"); + asm volatile ("vpshufb %ymm11,%ymm13,%ymm13"); + asm volatile ("vpxor %ymm12,%ymm5,%ymm5"); + asm volatile ("vpxor %ymm13,%ymm5,%ymm5"); + } + + /* first disk with all coefficients at 1 */ + asm volatile ("vmovdqa %0,%%ymm10" : : "m" (v[0][i])); + + asm volatile ("vpcmpgtb %ymm1,%ymm8,%ymm11"); + asm volatile ("vpaddb %ymm1,%ymm1,%ymm1"); + asm volatile ("vpand %ymm14,%ymm11,%ymm11"); + asm volatile ("vpxor %ymm11,%ymm1,%ymm1"); + + asm volatile ("vpxor %ymm10,%ymm0,%ymm0"); + asm volatile ("vpxor %ymm10,%ymm1,%ymm1"); + asm volatile ("vpxor %ymm10,%ymm2,%ymm2"); + asm volatile ("vpxor %ymm10,%ymm3,%ymm3"); + asm volatile ("vpxor %ymm10,%ymm4,%ymm4"); + asm volatile ("vpxor %ymm10,%ymm5,%ymm5"); + + asm volatile ("vmovntdq %%ymm0,%0" : "=m" (p[i])); + asm volatile ("vmovntdq %%ymm1,%0" : "=m" (q[i])); + asm volatile ("vmovntdq %%ymm2,%0" : "=m" (r[i])); + asm volatile ("vmovntdq %%ymm3,%0" : "=m" (s[i])); + asm volatile ("vmovntdq %%ymm4,%0" : "=m" (t[i])); + asm volatile ("vmovntdq %%ymm5,%0" : "=m" (u[i])); + } + + raid_avx_end(); +} +#endif + +#if defined(CONFIG_X86) && defined(CONFIG_SSSE3) +/* + * RAID recovering for one disk SSSE3 implementation + */ +void raid_rec1_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *pa; + uint8_t G; + uint8_t V; + size_t i; + + (void)nr; /* unused, it's always 1 */ + + /* if it's RAID5 uses the faster function */ + if (ip[0] == 0) { + raid_rec1of1(id, nd, size, vv); + return; + } + + /* setup the coefficients matrix */ + G = A(ip[0], id[0]); + + /* invert it to solve the system of linear equations */ + V = inv(G); + + /* compute delta parity */ + raid_delta_gen(1, id, ip, nd, size, vv); + + p = v[nd + ip[0]]; + pa = v[id[0]]; + + raid_sse_begin(); + + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + asm volatile ("movdqa %0,%%xmm4" : : "m" (gfmulpshufb[V][0][0])); + asm volatile ("movdqa %0,%%xmm5" : : "m" (gfmulpshufb[V][1][0])); + + for (i = 0; i < size; i += 16) { + asm volatile ("movdqa %0,%%xmm0" : : "m" (p[i])); + asm volatile ("movdqa %0,%%xmm1" : : "m" (pa[i])); + asm volatile ("movdqa %xmm4,%xmm2"); + asm volatile ("movdqa %xmm5,%xmm3"); + asm volatile ("pxor %xmm0,%xmm1"); + asm volatile ("movdqa %xmm1,%xmm0"); + asm volatile ("psrlw $4,%xmm1"); + asm volatile ("pand %xmm7,%xmm0"); + asm volatile ("pand %xmm7,%xmm1"); + asm volatile ("pshufb %xmm0,%xmm2"); + asm volatile ("pshufb %xmm1,%xmm3"); + asm volatile ("pxor %xmm3,%xmm2"); + asm volatile ("movdqa %%xmm2,%0" : "=m" (pa[i])); + } + + raid_sse_end(); +} +#endif + +#if defined(CONFIG_X86) && defined(CONFIG_SSSE3) +/* + * RAID recovering for two disks SSSE3 implementation + */ +void raid_rec2_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + const int N = 2; + uint8_t *p[N]; + uint8_t *pa[N]; + uint8_t G[N * N]; + uint8_t V[N * N]; + size_t i; + int j, k; + + (void)nr; /* unused, it's always 2 */ + + /* setup the coefficients matrix */ + for (j = 0; j < N; ++j) + for (k = 0; k < N; ++k) + G[j * N + k] = A(ip[j], id[k]); + + /* invert it to solve the system of linear equations */ + raid_invert(G, V, N); + + /* compute delta parity */ + raid_delta_gen(N, id, ip, nd, size, vv); + + for (j = 0; j < N; ++j) { + p[j] = v[nd + ip[j]]; + pa[j] = v[id[j]]; + } + + raid_sse_begin(); + + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + + for (i = 0; i < size; i += 16) { + asm volatile ("movdqa %0,%%xmm0" : : "m" (p[0][i])); + asm volatile ("movdqa %0,%%xmm2" : : "m" (pa[0][i])); + asm volatile ("movdqa %0,%%xmm1" : : "m" (p[1][i])); + asm volatile ("movdqa %0,%%xmm3" : : "m" (pa[1][i])); + asm volatile ("pxor %xmm2,%xmm0"); + asm volatile ("pxor %xmm3,%xmm1"); + + asm volatile ("pxor %xmm6,%xmm6"); + + asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[0]][0][0])); + asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[0]][1][0])); + asm volatile ("movdqa %xmm0,%xmm4"); + asm volatile ("movdqa %xmm0,%xmm5"); + asm volatile ("psrlw $4,%xmm5"); + asm volatile ("pand %xmm7,%xmm4"); + asm volatile ("pand %xmm7,%xmm5"); + asm volatile ("pshufb %xmm4,%xmm2"); + asm volatile ("pshufb %xmm5,%xmm3"); + asm volatile ("pxor %xmm2,%xmm6"); + asm volatile ("pxor %xmm3,%xmm6"); + + asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[1]][0][0])); + asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[1]][1][0])); + asm volatile ("movdqa %xmm1,%xmm4"); + asm volatile ("movdqa %xmm1,%xmm5"); + asm volatile ("psrlw $4,%xmm5"); + asm volatile ("pand %xmm7,%xmm4"); + asm volatile ("pand %xmm7,%xmm5"); + asm volatile ("pshufb %xmm4,%xmm2"); + asm volatile ("pshufb %xmm5,%xmm3"); + asm volatile ("pxor %xmm2,%xmm6"); + asm volatile ("pxor %xmm3,%xmm6"); + + asm volatile ("movdqa %%xmm6,%0" : "=m" (pa[0][i])); + + asm volatile ("pxor %xmm6,%xmm6"); + + asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[2]][0][0])); + asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[2]][1][0])); + asm volatile ("movdqa %xmm0,%xmm4"); + asm volatile ("movdqa %xmm0,%xmm5"); + asm volatile ("psrlw $4,%xmm5"); + asm volatile ("pand %xmm7,%xmm4"); + asm volatile ("pand %xmm7,%xmm5"); + asm volatile ("pshufb %xmm4,%xmm2"); + asm volatile ("pshufb %xmm5,%xmm3"); + asm volatile ("pxor %xmm2,%xmm6"); + asm volatile ("pxor %xmm3,%xmm6"); + + asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[V[3]][0][0])); + asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[V[3]][1][0])); + asm volatile ("movdqa %xmm1,%xmm4"); + asm volatile ("movdqa %xmm1,%xmm5"); + asm volatile ("psrlw $4,%xmm5"); + asm volatile ("pand %xmm7,%xmm4"); + asm volatile ("pand %xmm7,%xmm5"); + asm volatile ("pshufb %xmm4,%xmm2"); + asm volatile ("pshufb %xmm5,%xmm3"); + asm volatile ("pxor %xmm2,%xmm6"); + asm volatile ("pxor %xmm3,%xmm6"); + + asm volatile ("movdqa %%xmm6,%0" : "=m" (pa[1][i])); + } + + raid_sse_end(); +} +#endif + +#if defined(CONFIG_X86) && defined(CONFIG_SSSE3) +/* + * RAID recovering SSSE3 implementation + */ +void raid_recX_ssse3(int nr, int *id, int *ip, int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + int N = nr; + uint8_t *p[RAID_PARITY_MAX]; + uint8_t *pa[RAID_PARITY_MAX]; + uint8_t G[RAID_PARITY_MAX * RAID_PARITY_MAX]; + uint8_t V[RAID_PARITY_MAX * RAID_PARITY_MAX]; + uint8_t buffer[RAID_PARITY_MAX*16+16]; + uint8_t *pd = __align_ptr(buffer, 16); + size_t i; + int j, k; + + /* setup the coefficients matrix */ + for (j = 0; j < N; ++j) + for (k = 0; k < N; ++k) + G[j * N + k] = A(ip[j], id[k]); + + /* invert it to solve the system of linear equations */ + raid_invert(G, V, N); + + /* compute delta parity */ + raid_delta_gen(N, id, ip, nd, size, vv); + + for (j = 0; j < N; ++j) { + p[j] = v[nd + ip[j]]; + pa[j] = v[id[j]]; + } + + raid_sse_begin(); + + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfconst16.low4[0])); + + for (i = 0; i < size; i += 16) { + /* delta */ + for (j = 0; j < N; ++j) { + asm volatile ("movdqa %0,%%xmm0" : : "m" (p[j][i])); + asm volatile ("movdqa %0,%%xmm1" : : "m" (pa[j][i])); + asm volatile ("pxor %xmm1,%xmm0"); + asm volatile ("movdqa %%xmm0,%0" : "=m" (pd[j*16])); + } + + /* reconstruct */ + for (j = 0; j < N; ++j) { + asm volatile ("pxor %xmm0,%xmm0"); + asm volatile ("pxor %xmm1,%xmm1"); + + for (k = 0; k < N; ++k) { + uint8_t m = V[j * N + k]; + + asm volatile ("movdqa %0,%%xmm2" : : "m" (gfmulpshufb[m][0][0])); + asm volatile ("movdqa %0,%%xmm3" : : "m" (gfmulpshufb[m][1][0])); + asm volatile ("movdqa %0,%%xmm4" : : "m" (pd[k*16])); + asm volatile ("movdqa %xmm4,%xmm5"); + asm volatile ("psrlw $4,%xmm5"); + asm volatile ("pand %xmm7,%xmm4"); + asm volatile ("pand %xmm7,%xmm5"); + asm volatile ("pshufb %xmm4,%xmm2"); + asm volatile ("pshufb %xmm5,%xmm3"); + asm volatile ("pxor %xmm2,%xmm0"); + asm volatile ("pxor %xmm3,%xmm1"); + } + + asm volatile ("pxor %xmm1,%xmm0"); + asm volatile ("movdqa %%xmm0,%0" : "=m" (pa[j][i])); + } + } + + raid_sse_end(); +} +#endif + +#if defined(CONFIG_X86) && defined(CONFIG_AVX2) +/* + * RAID recovering for one disk AVX2 implementation + */ +void raid_rec1_avx2(int nr, int *id, int *ip, int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + uint8_t *p; + uint8_t *pa; + uint8_t G; + uint8_t V; + size_t i; + + (void)nr; /* unused, it's always 1 */ + + /* if it's RAID5 uses the faster function */ + if (ip[0] == 0) { + raid_rec1of1(id, nd, size, vv); + return; + } + + /* setup the coefficients matrix */ + G = A(ip[0], id[0]); + + /* invert it to solve the system of linear equations */ + V = inv(G); + + /* compute delta parity */ + raid_delta_gen(1, id, ip, nd, size, vv); + + p = v[nd + ip[0]]; + pa = v[id[0]]; + + raid_avx_begin(); + + asm volatile ("vbroadcasti128 %0,%%ymm7" : : "m" (gfconst16.low4[0])); + asm volatile ("vbroadcasti128 %0,%%ymm4" : : "m" (gfmulpshufb[V][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm5" : : "m" (gfmulpshufb[V][1][0])); + + for (i = 0; i < size; i += 32) { + asm volatile ("vmovdqa %0,%%ymm0" : : "m" (p[i])); + asm volatile ("vmovdqa %0,%%ymm1" : : "m" (pa[i])); + asm volatile ("vpxor %ymm1,%ymm0,%ymm0"); + asm volatile ("vpsrlw $4,%ymm0,%ymm1"); + asm volatile ("vpand %ymm7,%ymm0,%ymm0"); + asm volatile ("vpand %ymm7,%ymm1,%ymm1"); + asm volatile ("vpshufb %ymm0,%ymm4,%ymm2"); + asm volatile ("vpshufb %ymm1,%ymm5,%ymm3"); + asm volatile ("vpxor %ymm3,%ymm2,%ymm2"); + asm volatile ("vmovdqa %%ymm2,%0" : "=m" (pa[i])); + } + + raid_avx_end(); +} +#endif + +#if defined(CONFIG_X86) && defined(CONFIG_AVX2) +/* + * RAID recovering for two disks AVX2 implementation + */ +void raid_rec2_avx2(int nr, int *id, int *ip, int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + const int N = 2; + uint8_t *p[N]; + uint8_t *pa[N]; + uint8_t G[N * N]; + uint8_t V[N * N]; + size_t i; + int j, k; + + (void)nr; /* unused, it's always 2 */ + + /* setup the coefficients matrix */ + for (j = 0; j < N; ++j) + for (k = 0; k < N; ++k) + G[j * N + k] = A(ip[j], id[k]); + + /* invert it to solve the system of linear equations */ + raid_invert(G, V, N); + + /* compute delta parity */ + raid_delta_gen(N, id, ip, nd, size, vv); + + for (j = 0; j < N; ++j) { + p[j] = v[nd + ip[j]]; + pa[j] = v[id[j]]; + } + + raid_avx_begin(); + + asm volatile ("vbroadcasti128 %0,%%ymm7" : : "m" (gfconst16.low4[0])); + + for (i = 0; i < size; i += 32) { + asm volatile ("vmovdqa %0,%%ymm0" : : "m" (p[0][i])); + asm volatile ("vmovdqa %0,%%ymm2" : : "m" (pa[0][i])); + asm volatile ("vmovdqa %0,%%ymm1" : : "m" (p[1][i])); + asm volatile ("vmovdqa %0,%%ymm3" : : "m" (pa[1][i])); + asm volatile ("vpxor %ymm2,%ymm0,%ymm0"); + asm volatile ("vpxor %ymm3,%ymm1,%ymm1"); + + asm volatile ("vpxor %ymm6,%ymm6,%ymm6"); + + asm volatile ("vbroadcasti128 %0,%%ymm2" : : "m" (gfmulpshufb[V[0]][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm3" : : "m" (gfmulpshufb[V[0]][1][0])); + asm volatile ("vpsrlw $4,%ymm0,%ymm5"); + asm volatile ("vpand %ymm7,%ymm0,%ymm4"); + asm volatile ("vpand %ymm7,%ymm5,%ymm5"); + asm volatile ("vpshufb %ymm4,%ymm2,%ymm2"); + asm volatile ("vpshufb %ymm5,%ymm3,%ymm3"); + asm volatile ("vpxor %ymm2,%ymm6,%ymm6"); + asm volatile ("vpxor %ymm3,%ymm6,%ymm6"); + + asm volatile ("vbroadcasti128 %0,%%ymm2" : : "m" (gfmulpshufb[V[1]][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm3" : : "m" (gfmulpshufb[V[1]][1][0])); + asm volatile ("vpsrlw $4,%ymm1,%ymm5"); + asm volatile ("vpand %ymm7,%ymm1,%ymm4"); + asm volatile ("vpand %ymm7,%ymm5,%ymm5"); + asm volatile ("vpshufb %ymm4,%ymm2,%ymm2"); + asm volatile ("vpshufb %ymm5,%ymm3,%ymm3"); + asm volatile ("vpxor %ymm2,%ymm6,%ymm6"); + asm volatile ("vpxor %ymm3,%ymm6,%ymm6"); + + asm volatile ("vmovdqa %%ymm6,%0" : "=m" (pa[0][i])); + + asm volatile ("vpxor %ymm6,%ymm6,%ymm6"); + + asm volatile ("vbroadcasti128 %0,%%ymm2" : : "m" (gfmulpshufb[V[2]][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm3" : : "m" (gfmulpshufb[V[2]][1][0])); + asm volatile ("vpsrlw $4,%ymm0,%ymm5"); + asm volatile ("vpand %ymm7,%ymm0,%ymm4"); + asm volatile ("vpand %ymm7,%ymm5,%ymm5"); + asm volatile ("vpshufb %ymm4,%ymm2,%ymm2"); + asm volatile ("vpshufb %ymm5,%ymm3,%ymm3"); + asm volatile ("vpxor %ymm2,%ymm6,%ymm6"); + asm volatile ("vpxor %ymm3,%ymm6,%ymm6"); + + asm volatile ("vbroadcasti128 %0,%%ymm2" : : "m" (gfmulpshufb[V[3]][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm3" : : "m" (gfmulpshufb[V[3]][1][0])); + asm volatile ("vpsrlw $4,%ymm1,%ymm5"); + asm volatile ("vpand %ymm7,%ymm1,%ymm4"); + asm volatile ("vpand %ymm7,%ymm5,%ymm5"); + asm volatile ("vpshufb %ymm4,%ymm2,%ymm2"); + asm volatile ("vpshufb %ymm5,%ymm3,%ymm3"); + asm volatile ("vpxor %ymm2,%ymm6,%ymm6"); + asm volatile ("vpxor %ymm3,%ymm6,%ymm6"); + + asm volatile ("vmovdqa %%ymm6,%0" : "=m" (pa[1][i])); + } + + raid_avx_end(); +} +#endif + +#if defined(CONFIG_X86) && defined(CONFIG_AVX2) +/* + * RAID recovering AVX2 implementation + */ +void raid_recX_avx2(int nr, int *id, int *ip, int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t **)vv; + int N = nr; + uint8_t *p[RAID_PARITY_MAX]; + uint8_t *pa[RAID_PARITY_MAX]; + uint8_t G[RAID_PARITY_MAX * RAID_PARITY_MAX]; + uint8_t V[RAID_PARITY_MAX * RAID_PARITY_MAX]; + uint8_t buffer[RAID_PARITY_MAX*32+32]; + uint8_t *pd = __align_ptr(buffer, 32); + size_t i; + int j, k; + + /* setup the coefficients matrix */ + for (j = 0; j < N; ++j) + for (k = 0; k < N; ++k) + G[j * N + k] = A(ip[j], id[k]); + + /* invert it to solve the system of linear equations */ + raid_invert(G, V, N); + + /* compute delta parity */ + raid_delta_gen(N, id, ip, nd, size, vv); + + for (j = 0; j < N; ++j) { + p[j] = v[nd + ip[j]]; + pa[j] = v[id[j]]; + } + + raid_avx_begin(); + + asm volatile ("vbroadcasti128 %0,%%ymm7" : : "m" (gfconst16.low4[0])); + + for (i = 0; i < size; i += 32) { + /* delta */ + for (j = 0; j < N; ++j) { + asm volatile ("vmovdqa %0,%%ymm0" : : "m" (p[j][i])); + asm volatile ("vmovdqa %0,%%ymm1" : : "m" (pa[j][i])); + asm volatile ("vpxor %ymm1,%ymm0,%ymm0"); + asm volatile ("vmovdqa %%ymm0,%0" : "=m" (pd[j*32])); + } + + /* reconstruct */ + for (j = 0; j < N; ++j) { + asm volatile ("vpxor %ymm0,%ymm0,%ymm0"); + asm volatile ("vpxor %ymm1,%ymm1,%ymm1"); + + for (k = 0; k < N; ++k) { + uint8_t m = V[j * N + k]; + + asm volatile ("vbroadcasti128 %0,%%ymm2" : : "m" (gfmulpshufb[m][0][0])); + asm volatile ("vbroadcasti128 %0,%%ymm3" : : "m" (gfmulpshufb[m][1][0])); + asm volatile ("vmovdqa %0,%%ymm4" : : "m" (pd[k*32])); + asm volatile ("vpsrlw $4,%ymm4,%ymm5"); + asm volatile ("vpand %ymm7,%ymm4,%ymm4"); + asm volatile ("vpand %ymm7,%ymm5,%ymm5"); + asm volatile ("vpshufb %ymm4,%ymm2,%ymm2"); + asm volatile ("vpshufb %ymm5,%ymm3,%ymm3"); + asm volatile ("vpxor %ymm2,%ymm0,%ymm0"); + asm volatile ("vpxor %ymm3,%ymm1,%ymm1"); + } + + asm volatile ("vpxor %ymm1,%ymm0,%ymm0"); + asm volatile ("vmovdqa %%ymm0,%0" : "=m" (pa[j][i])); + } + } + + raid_avx_end(); +} +#endif + diff --git a/raid/x86z.c b/raid/x86z.c new file mode 100644 index 0000000..1e3fe89 --- /dev/null +++ b/raid/x86z.c @@ -0,0 +1,255 @@ +/* + * Copyright (C) 2013 Andrea Mazzoleni + * + * 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 2 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. + */ + +#include "internal.h" + +#if defined(CONFIG_X86) && defined(CONFIG_SSE2) +static const struct gfzconst16 { + uint8_t poly[16]; + uint8_t half[16]; + uint8_t low7[16]; +} gfzconst16 __aligned(64) = +{ + { + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, + 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d + }, + { + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, + 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e + }, + { + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f + } +}; +#endif + +#if defined(CONFIG_X86) && defined(CONFIG_SSE2) +/* + * GENz (triple parity with powers of 2^-1) SSE2 implementation + */ +void raid_genz_sse2(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t**)vv; + uint8_t *p; + uint8_t *q; + uint8_t *r; + int d, l; + size_t i; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + r = v[nd + 2]; + + raid_sse_begin(); + + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfzconst16.poly[0])); + asm volatile ("movdqa %0,%%xmm3" : : "m" (gfzconst16.half[0])); + asm volatile ("movdqa %0,%%xmm6" : : "m" (gfzconst16.low7[0])); + + for (i = 0; i < size; i += 16) { + asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i])); + asm volatile ("movdqa %xmm0,%xmm1"); + asm volatile ("movdqa %xmm0,%xmm2"); + for (d = l - 1; d >= 0; --d) { + asm volatile ("pxor %xmm4,%xmm4"); + asm volatile ("pcmpgtb %xmm1,%xmm4"); + asm volatile ("paddb %xmm1,%xmm1"); + asm volatile ("pand %xmm7,%xmm4"); + asm volatile ("pxor %xmm4,%xmm1"); + + asm volatile ("movdqa %xmm2,%xmm4"); + asm volatile ("pxor %xmm5,%xmm5"); + asm volatile ("psllw $7,%xmm4"); + asm volatile ("psrlw $1,%xmm2"); + asm volatile ("pcmpgtb %xmm4,%xmm5"); + asm volatile ("pand %xmm6,%xmm2"); + asm volatile ("pand %xmm3,%xmm5"); + asm volatile ("pxor %xmm5,%xmm2"); + + asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); + asm volatile ("pxor %xmm4,%xmm0"); + asm volatile ("pxor %xmm4,%xmm1"); + asm volatile ("pxor %xmm4,%xmm2"); + } + asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); + asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); + } + + raid_sse_end(); +} +#endif + +#if defined(CONFIG_X86_64) && defined(CONFIG_SSE2) +/* + * GENz (triple parity with powers of 2^-1) SSE2 implementation + * + * Note that it uses 16 registers, meaning that x64 is required. + */ +void raid_genz_sse2ext(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t**)vv; + uint8_t *p; + uint8_t *q; + uint8_t *r; + int d, l; + size_t i; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + r = v[nd + 2]; + + raid_sse_begin(); + + asm volatile ("movdqa %0,%%xmm7" : : "m" (gfzconst16.poly[0])); + asm volatile ("movdqa %0,%%xmm3" : : "m" (gfzconst16.half[0])); + asm volatile ("movdqa %0,%%xmm11" : : "m" (gfzconst16.low7[0])); + + for (i = 0; i < size; i += 32) { + asm volatile ("movdqa %0,%%xmm0" : : "m" (v[l][i])); + asm volatile ("movdqa %0,%%xmm8" : : "m" (v[l][i + 16])); + asm volatile ("movdqa %xmm0,%xmm1"); + asm volatile ("movdqa %xmm8,%xmm9"); + asm volatile ("movdqa %xmm0,%xmm2"); + asm volatile ("movdqa %xmm8,%xmm10"); + for (d = l - 1; d >= 0; --d) { + asm volatile ("movdqa %xmm2,%xmm6"); + asm volatile ("movdqa %xmm10,%xmm14"); + asm volatile ("pxor %xmm4,%xmm4"); + asm volatile ("pxor %xmm12,%xmm12"); + asm volatile ("pxor %xmm5,%xmm5"); + asm volatile ("pxor %xmm13,%xmm13"); + asm volatile ("psllw $7,%xmm6"); + asm volatile ("psllw $7,%xmm14"); + asm volatile ("psrlw $1,%xmm2"); + asm volatile ("psrlw $1,%xmm10"); + asm volatile ("pcmpgtb %xmm1,%xmm4"); + asm volatile ("pcmpgtb %xmm9,%xmm12"); + asm volatile ("pcmpgtb %xmm6,%xmm5"); + asm volatile ("pcmpgtb %xmm14,%xmm13"); + asm volatile ("paddb %xmm1,%xmm1"); + asm volatile ("paddb %xmm9,%xmm9"); + asm volatile ("pand %xmm11,%xmm2"); + asm volatile ("pand %xmm11,%xmm10"); + asm volatile ("pand %xmm7,%xmm4"); + asm volatile ("pand %xmm7,%xmm12"); + asm volatile ("pand %xmm3,%xmm5"); + asm volatile ("pand %xmm3,%xmm13"); + asm volatile ("pxor %xmm4,%xmm1"); + asm volatile ("pxor %xmm12,%xmm9"); + asm volatile ("pxor %xmm5,%xmm2"); + asm volatile ("pxor %xmm13,%xmm10"); + + asm volatile ("movdqa %0,%%xmm4" : : "m" (v[d][i])); + asm volatile ("movdqa %0,%%xmm12" : : "m" (v[d][i + 16])); + asm volatile ("pxor %xmm4,%xmm0"); + asm volatile ("pxor %xmm4,%xmm1"); + asm volatile ("pxor %xmm4,%xmm2"); + asm volatile ("pxor %xmm12,%xmm8"); + asm volatile ("pxor %xmm12,%xmm9"); + asm volatile ("pxor %xmm12,%xmm10"); + } + asm volatile ("movntdq %%xmm0,%0" : "=m" (p[i])); + asm volatile ("movntdq %%xmm8,%0" : "=m" (p[i + 16])); + asm volatile ("movntdq %%xmm1,%0" : "=m" (q[i])); + asm volatile ("movntdq %%xmm9,%0" : "=m" (q[i + 16])); + asm volatile ("movntdq %%xmm2,%0" : "=m" (r[i])); + asm volatile ("movntdq %%xmm10,%0" : "=m" (r[i + 16])); + } + + raid_sse_end(); +} +#endif + +#if defined(CONFIG_X86_64) && defined(CONFIG_AVX2) +/* + * GENz (triple parity with powers of 2^-1) AVX2 implementation + * + * Note that it uses 16 registers, meaning that x64 is required. + */ +void raid_genz_avx2ext(int nd, size_t size, void **vv) +{ + uint8_t **v = (uint8_t**)vv; + uint8_t *p; + uint8_t *q; + uint8_t *r; + int d, l; + size_t i; + + l = nd - 1; + p = v[nd]; + q = v[nd + 1]; + r = v[nd + 2]; + + raid_avx_begin(); + + asm volatile ("vbroadcasti128 %0,%%ymm7" : : "m" (gfzconst16.poly[0])); + asm volatile ("vbroadcasti128 %0,%%ymm3" : : "m" (gfzconst16.half[0])); + asm volatile ("vbroadcasti128 %0,%%ymm11" : : "m" (gfzconst16.low7[0])); + asm volatile ("vpxor %ymm15,%ymm15,%ymm15"); + + for (i = 0; i < size; i += 64) { + asm volatile ("vmovdqa %0,%%ymm0" : : "m" (v[l][i])); + asm volatile ("vmovdqa %0,%%ymm8" : : "m" (v[l][i + 32])); + asm volatile ("vmovdqa %ymm0,%ymm1"); + asm volatile ("vmovdqa %ymm8,%ymm9"); + asm volatile ("vmovdqa %ymm0,%ymm2"); + asm volatile ("vmovdqa %ymm8,%ymm10"); + for (d = l - 1; d >= 0; --d) { + asm volatile ("vpsllw $7,%ymm2,%ymm6"); + asm volatile ("vpsllw $7,%ymm10,%ymm14"); + asm volatile ("vpsrlw $1,%ymm2,%ymm2"); + asm volatile ("vpsrlw $1,%ymm10,%ymm10"); + asm volatile ("vpcmpgtb %ymm1,%ymm15,%ymm4"); + asm volatile ("vpcmpgtb %ymm9,%ymm15,%ymm12"); + asm volatile ("vpcmpgtb %ymm6,%ymm15,%ymm5"); + asm volatile ("vpcmpgtb %ymm14,%ymm15,%ymm13"); + asm volatile ("vpaddb %ymm1,%ymm1,%ymm1"); + asm volatile ("vpaddb %ymm9,%ymm9,%ymm9"); + asm volatile ("vpand %ymm11,%ymm2,%ymm2"); + asm volatile ("vpand %ymm11,%ymm10,%ymm10"); + asm volatile ("vpand %ymm7,%ymm4,%ymm4"); + asm volatile ("vpand %ymm7,%ymm12,%ymm12"); + asm volatile ("vpand %ymm3,%ymm5,%ymm5"); + asm volatile ("vpand %ymm3,%ymm13,%ymm13"); + asm volatile ("vpxor %ymm4,%ymm1,%ymm1"); + asm volatile ("vpxor %ymm12,%ymm9,%ymm9"); + asm volatile ("vpxor %ymm5,%ymm2,%ymm2"); + asm volatile ("vpxor %ymm13,%ymm10,%ymm10"); + + asm volatile ("vmovdqa %0,%%ymm4" : : "m" (v[d][i])); + asm volatile ("vmovdqa %0,%%ymm12" : : "m" (v[d][i + 32])); + asm volatile ("vpxor %ymm4,%ymm0,%ymm0"); + asm volatile ("vpxor %ymm4,%ymm1,%ymm1"); + asm volatile ("vpxor %ymm4,%ymm2,%ymm2"); + asm volatile ("vpxor %ymm12,%ymm8,%ymm8"); + asm volatile ("vpxor %ymm12,%ymm9,%ymm9"); + asm volatile ("vpxor %ymm12,%ymm10,%ymm10"); + } + asm volatile ("vmovntdq %%ymm0,%0" : "=m" (p[i])); + asm volatile ("vmovntdq %%ymm8,%0" : "=m" (p[i + 32])); + asm volatile ("vmovntdq %%ymm1,%0" : "=m" (q[i])); + asm volatile ("vmovntdq %%ymm9,%0" : "=m" (q[i + 32])); + asm volatile ("vmovntdq %%ymm2,%0" : "=m" (r[i])); + asm volatile ("vmovntdq %%ymm10,%0" : "=m" (r[i + 32])); + } + + raid_avx_end(); +} +#endif + diff --git a/snapraid.1 b/snapraid.1 new file mode 100644 index 0000000..915df9c --- /dev/null +++ b/snapraid.1 @@ -0,0 +1,1799 @@ +.TH "SnapRAID Backup For Disk Arrays" 1 +.SH NAME +snapraid \- SnapRAID Backup For Disk Arrays +.SH SYNOPSIS +snapraid [\-c, \-\-conf CONFIG] +.PD 0 +.PP +.PD + [\-f, \-\-filter PATTERN] [\-d, \-\-filter\-disk NAME] +.PD 0 +.PP +.PD + [\-m, \-\-filter\-missing] [\-e, \-\-filter\-error] +.PD 0 +.PP +.PD + [\-a, \-\-audit\-only] [\-h, \-\-pre\-hash] [\-i, \-\-import DIR] +.PD 0 +.PP +.PD + [\-p, \-\-plan PERC|bad|new|full] +.PD 0 +.PP +.PD + [\-o, \-\-older\-than DAYS] [\-l, \-\-log FILE] +.PD 0 +.PP +.PD + [\-Z, \-\-force\-zero] [\-E, \-\-force\-empty] +.PD 0 +.PP +.PD + [\-U, \-\-force\-uuid] [\-D, \-\-force\-device] +.PD 0 +.PP +.PD + [\-N, \-\-force\-nocopy] [\-F, \-\-force\-full] +.PD 0 +.PP +.PD + [\-R, \-\-force\-realloc] +.PD 0 +.PP +.PD + [\-S, \-\-start BLKSTART] [\-B, \-\-count BLKCOUNT] +.PD 0 +.PP +.PD + [\-L, \-\-error\-limit NUMBER] +.PD 0 +.PP +.PD + [\-v, \-\-verbose] [\-q, \-\-quiet] +.PD 0 +.PP +.PD + status|smart|up|down|diff|sync|scrub|fix|check|list|dup +.PD 0 +.PP +.PD + |pool|devices|touch|rehash +.PD 0 +.PP +.PD +.PP +snapraid [\-V, \-\-version] [\-H, \-\-help] [\-C, \-\-gen\-conf CONTENT] +.PD 0 +.PP +.PD +.SH DESCRIPTION +SnapRAID is a backup program for disk arrays. It stores parity +information of your data and it recovers from up to six disk +failures. +.PP +SnapRAID is mainly targeted for a home media center, with a lot of +big files that rarely change. +.PP +Beside the ability to recover from disk failures, other +features of SnapRAID are: +.PD 0 +.IP \(bu +All your data is hashed to ensure data integrity and to avoid +silent corruption. +.IP \(bu +If the failed disks are too many to allow a recovery, +you lose the data only on the failed disks. +All the data in the other disks is safe. +.IP \(bu +If you accidentally delete some files in a disk, you can +recover them. +.IP \(bu +You can start with already filled disks. +.IP \(bu +The disks can have different sizes. +.IP \(bu +You can add disks at any time. +.IP \(bu +It doesn\'t lock\-in your data. You can stop using SnapRAID at any +time without the need to reformat or move data. +.IP \(bu +To access a file, a single disk needs to spin, saving power and +producing less noise. +.PD +.PP +The official site of SnapRAID is: +.PP +.RS 4 +http://www.snapraid.it/ +.PD 0 +.PP +.PD +.RE +.SH LIMITATIONS +SnapRAID is in between a RAID and a Backup program trying to get the best +benefits of them. Although it also has some limitations that you should +consider before using it. +.PP +The main one is that if a disk fails, and you haven\'t recently synced, +you may be unable to do a complete recover. +More specifically, you may be unable to recover up to the size of the +amount of the changed or deleted files from the last sync operation. +This happens even if the files changed or deleted are not in the +failed disk. This is the reason because SnapRAID is better suited for +data that rarely change. +.PP +Instead the new added files don\'t prevent the recovering of the already +existing files. You may only lose the just added files, if they are on +the failed disk. +.PP +Other limitations are: +.PD 0 +.IP \(bu +You have different file\-systems for each disk. +Using a RAID you have only a big file\-system. +.IP \(bu +It doesn\'t stripe data. +With RAID you get a speed boost with striping. +.IP \(bu +It doesn\'t support real\-time recovery. +With RAID you do not have to stop working when a disk fails. +.IP \(bu +It\'s able to recover damages only from a limited number of disks. +With a Backup you are able to recover from a complete +failure of the whole disk array. +.IP \(bu +Only file, time\-stamps, symlinks and hardlinks are saved. +Permissions, ownership and extended attributes are not saved. +.PD +.SH GETTING STARTED +To use SnapRAID you need to first select one disk of your disk array +to dedicate at the \[dq]parity\[dq] information. With one disk for parity you +will be able to recover from a single disk failure, like RAID5. +.PP +If you want to be able to recover from more disk failures, like RAID6, +you must reserve additional disks for parity. Any additional parity +disk allow to recover from one more disk failure. +.PP +As parity disks, you have to pick the biggest disks in the array, +as the parity information may grow in size as the biggest data +disk in the array. +.PP +These disks will be dedicated to store the \[dq]parity\[dq] files. +You should not store your data in them. +.PP +Then you have to define the \[dq]data\[dq] disks that you want to protect +with SnapRAID. The protection is more effective if these disks +contain data that rarely change. For this reason it\'s better to +DO NOT include the Windows C:\\ disk, or the Unix /home, /var and /tmp +disks. +.PP +The list of files is saved in the \[dq]content\[dq] files, usually +stored in the data, parity or boot disks. +These files contain the details of your backup, with all the +check\-sums to verify its integrity. +The \[dq]content\[dq] file is stored in multiple copies, and each one must +be in a different disk, to ensure that in even in case of multiple +disk failures at least one copy is available. +.PP +For example, suppose that you are interested only at one parity level +of protection, and that your disks are present in: +.PP +.RS 4 +/mnt/diskp <\- selected disk for parity +.PD 0 +.PP +.PD +/mnt/disk1 <\- first disk to protect +.PD 0 +.PP +.PD +/mnt/disk2 <\- second disk to protect +.PD 0 +.PP +.PD +/mnt/disk3 <\- third disk to protect +.PD 0 +.PP +.PD +.RE +.PP +you have to create the configuration file /etc/snapraid.conf with +the following options: +.PP +.RS 4 +parity /mnt/diskp/snapraid.parity +.PD 0 +.PP +.PD +content /var/snapraid/snapraid.content +.PD 0 +.PP +.PD +content /mnt/disk1/snapraid.content +.PD 0 +.PP +.PD +content /mnt/disk2/snapraid.content +.PD 0 +.PP +.PD +data d1 /mnt/disk1/ +.PD 0 +.PP +.PD +data d2 /mnt/disk2/ +.PD 0 +.PP +.PD +data d3 /mnt/disk3/ +.PD 0 +.PP +.PD +.RE +.PP +If you are in Windows, you should use the Windows path format, with drive +letters and backslashes instead of slashes. +.PP +.RS 4 +parity E:\\snapraid.parity +.PD 0 +.PP +.PD +content C:\\snapraid\\snapraid.content +.PD 0 +.PP +.PD +content F:\\array\\snapraid.content +.PD 0 +.PP +.PD +content G:\\array\\snapraid.content +.PD 0 +.PP +.PD +data d1 F:\\array\\ +.PD 0 +.PP +.PD +data d2 G:\\array\\ +.PD 0 +.PP +.PD +data d3 H:\\array\\ +.PD 0 +.PP +.PD +.RE +.PP +If you have many disks, and you run out of drive letters, you can mount +disks directly in sub folders. See: +.PP +.RS 4 +https://www.google.com/search?q=Windows+mount+point +.PD 0 +.PP +.PD +.RE +.PP +At this point you are ready to start the \[dq]sync\[dq] command to build the +parity information. +.PP +.RS 4 +snapraid sync +.PD 0 +.PP +.PD +.RE +.PP +This process may take some hours the first time, depending on the size +of the data already present in the disks. If the disks are empty +the process is immediate. +.PP +You can stop it at any time pressing Ctrl+C, and at the next run it +will start where interrupted. +.PP +When this command completes, your data is SAFE. +.PP +Now you can start using your array as you like, and periodically +update the parity information running the \[dq]sync\[dq] command. +.SS Scrubbing +To periodically check the data and parity for errors, you can +run the \[dq]scrub\[dq] command. +.PP +.RS 4 +snapraid scrub +.PD 0 +.PP +.PD +.RE +.PP +This command verifies the data in your array comparing it with +the hash computed in the \[dq]sync\[dq] command. +.PP +Every run of the command checks about the 8% of the array, but not data +already scrubbed in the previous 10 days. +You can use the \-p, \-\-plan option to specify a different amount, +and the \-o, \-\-older\-than option to specify a different age in days. +For example, to check 5% of the array older than 20 days use: +.PP +.RS 4 +snapraid \-p 5 \-o 20 scrub +.PD 0 +.PP +.PD +.RE +.PP +If during the process, silent or input/output errors are found, +the corresponding blocks are marked as bad in the \[dq]content\[dq] file, +and listed in the \[dq]status\[dq] command. +.PP +.RS 4 +snapraid status +.PD 0 +.PP +.PD +.RE +.PP +To fix them, you can use the \[dq]fix\[dq] command filtering for bad blocks with +the \-e, \-\-filter\-error options: +.PP +.RS 4 +snapraid \-e fix +.PD 0 +.PP +.PD +.RE +.PP +At the next \[dq]scrub\[dq] the errors will disappear from the \[dq]status\[dq] report +if really fixed. To make it fast, you can use \-p bad to scrub only blocks +marked as bad. +.PP +.RS 4 +snapraid \-p bad scrub +.PD 0 +.PP +.PD +.RE +.PP +Take care that running \[dq]scrub\[dq] on a not synced array may result in +errors caused by removed or modified files. These errors are reported +in the \[dq]scrub\[dq] result, but related blocks are not marked as bad. +.SS Pooling +To have all the files in your array shown in the same directory tree, +you can enable the \[dq]pooling\[dq] feature. It consists in creating a +read\-only virtual view of all the files in your array using symbolic +links. +.PP +You can configure the \[dq]pooling\[dq] directory in the configuration file with: +.PP +.RS 4 +pool /pool +.PD 0 +.PP +.PD +.RE +.PP +or, if you are in Windows, with: +.PP +.RS 4 +pool C:\\pool +.PD 0 +.PP +.PD +.RE +.PP +and then run the \[dq]pool\[dq] command to create or update the virtual view. +.PP +.RS 4 +snapraid pool +.PD 0 +.PP +.PD +.RE +.PP +If you are using a Unix platform and you want to share such directory +in the network to either Windows or Unix machines, you should add +to your /etc/samba/smb.conf the following options: +.PP +.RS 4 +# In the global section of smb.conf +.PD 0 +.PP +.PD +unix extensions = no +.PD 0 +.PP +.PD +.RE +.PP +.RS 4 +# In the share section of smb.conf +.PD 0 +.PP +.PD +[pool] +.PD 0 +.PP +.PD +comment = Pool +.PD 0 +.PP +.PD +path = /pool +.PD 0 +.PP +.PD +read only = yes +.PD 0 +.PP +.PD +guest ok = yes +.PD 0 +.PP +.PD +wide links = yes +.PD 0 +.PP +.PD +follow symlinks = yes +.PD 0 +.PP +.PD +.RE +.PP +In Windows the same sharing operation is not so straightforward, +because Windows shares the symbolic links as they are, and that +requires the network clients to resolve them remotely. +.PP +To make it working, besides sharing in the network the pool directory, +you must also share all the disks independently, using as share points +the disk names as defined in the configuration file. You must also specify in +the \[dq]share\[dq] option of the configure file, the Windows UNC path that remote +clients needs to use to access such shared disks. +.PP +For example, operating from a server named \[dq]darkstar\[dq], you can use +the options: +.PP +.RS 4 +data d1 F:\\array\\ +.PD 0 +.PP +.PD +data d2 G:\\array\\ +.PD 0 +.PP +.PD +data d3 H:\\array\\ +.PD 0 +.PP +.PD +pool C:\\pool +.PD 0 +.PP +.PD +share \\\\darkstar +.PD 0 +.PP +.PD +.RE +.PP +and share the following dirs in the network: +.PP +.RS 4 +\\\\darkstar\\pool \-> C:\\pool +.PD 0 +.PP +.PD +\\\\darkstar\\d1 \-> F:\\array +.PD 0 +.PP +.PD +\\\\darkstar\\d2 \-> G:\\array +.PD 0 +.PP +.PD +\\\\darkstar\\d3 \-> H:\\array +.PD 0 +.PP +.PD +.RE +.PP +to allow remote clients to access all the files at \\\\darkstar\\\\pool. +.PP +You may also need to configure remote clients enabling access at remote +symlinks with the command: +.PP +.RS 4 +fsutil behavior set SymlinkEvaluation L2L:1 R2R:1 L2R:1 R2L:1 +.PD 0 +.PP +.PD +.RE +.SS Undeleting +SnapRAID is more like a backup program than a RAID system, and it +can be used to restore or undelete files to their previous state using +the \-f, \-\-filter option : +.PP +.RS 4 +snapraid fix \-f FILE +.PD 0 +.PP +.PD +.RE +.PP +or for a directory: +.PP +.RS 4 +snapraid fix \-f DIR/ +.PD 0 +.PP +.PD +.RE +.PP +You can also use it to recover only accidentally deleted files inside +a directory using the \-m, \-\-filter\-missing option, that restores +only missing files, leaving untouched all the others. +.PP +.RS 4 +snapraid fix \-m \-f DIR/ +.PD 0 +.PP +.PD +.RE +.PP +Or to recover all the deleted files in all the drives with: +.PP +.RS 4 +snapraid fix \-m +.PD 0 +.PP +.PD +.RE +.SS Recovering +The worst happened, and you lost one or more disks! +.PP +DO NOT PANIC! You will be able to recover them! +.PP +The first thing you have to do is to avoid further changes at your disk array. +Disable any remote connection to it, any scheduled process, including any +scheduled SnapRAID nightly sync or scrub. +.PP +Then proceed with the following steps. +.SS STEP 1 \-> Reconfigure +You need some space to recover, even better if you already have additional +spare disks, but in case, also an external USB or remote disk is enough. +.PP +Change the SnapRAID configuration file to make the \[dq]data\[dq] or \[dq]parity\[dq] +option of the failed disk to point to the place where you have enough empty +space to recover the files. +.PP +For example, if you have that disk \[dq]d1\[dq] failed, you can change from: +.PP +.RS 4 +data d1 /mnt/disk1/ +.PD 0 +.PP +.PD +.RE +.PP +to: +.PP +.RS 4 +data d1 /mnt/new_spare_disk/ +.PD 0 +.PP +.PD +.RE +.PP +If the disk to recover is a parity disk, change the appropriate \[dq]parity\[dq] +option. +If you have more broken disks, change all their configuration options. +.SS STEP 2 \-> Fix +Run the fix command, storing the log in an external file with: +.PP +.RS 4 +snapraid \-d NAME \-l fix.log fix +.PD 0 +.PP +.PD +.RE +.PP +Where NAME is the name of the disk, like \[dq]d1\[dq] as in our previous example. +In case the disk to recover is a parity disk, use the \[dq]parity\[dq], \[dq]2\-parity\[dq] +names. +If you have more broken disks, use multiple \-d options to specify all +of them. +.PP +This command will take a long time. +.PP +Take care that you need also few gigabytes free to store the fix.log file. +Run it from a disk with some free space. +.PP +Now you have recovered all the recoverable. If some file is partially or totally +unrecoverable, it will be renamed adding the \[dq].unrecoverable\[dq] extension. +.PP +You can get a detailed list of all the unrecoverable blocks in the fix.log file +checking all the lines starting with \[dq]unrecoverable:\[dq] +.PP +If you are not satisfied of the recovering, you can retry it as many +time you wish. +.PP +For example, if you have removed files from the array after the last +\[dq]sync\[dq], this may result in some other files not recovered. +In this case, you can retry the \[dq]fix\[dq] using the \-i, \-\-import option, +specifying where these files are now, to include them again in the +recovering process. +.PP +If you are satisfied of the recovering, you can now proceed further, +but take care that after syncing you cannot retry the \[dq]fix\[dq] command +anymore! +.SS STEP 3 \-> Check +As paranoid check, you can now run a \[dq]check\[dq] command to ensure that +everything is OK on the recovered disk. +.PP +.RS 4 +snapraid \-d NAME \-a check +.PD 0 +.PP +.PD +.RE +.PP +Where NAME is the name of the disk, like \[dq]d1\[dq] as in our previous example. +.PP +The options \-d and \-a tell SnapRAID to check only the specified disk, +and ignore all the parity data. +.PP +This command will take a long time, but if you are not paranoid, +you can skip it. +.SS STEP 4 \-> Sync +Run the \[dq]sync\[dq] command to resynchronize the array with the new disk. +.PP +.RS 4 +snapraid sync +.PD 0 +.PP +.PD +.RE +.PP +If everything is recovered, this command is immediate. +.SH COMMANDS +SnapRAID provides a few simple commands that allow to: +.PD 0 +.IP \(bu +Prints the status of the array \-> \[dq]status\[dq] +.IP \(bu +Controls the disks \-> \[dq]smart\[dq], \[dq]up\[dq], \[dq]down\[dq] +.IP \(bu +Makes a backup/snapshot \-> \[dq]sync\[dq] +.IP \(bu +Periodically checks data \-> \[dq]scrub\[dq] +.IP \(bu +Restore the last backup/snapshot \-> \[dq]fix\[dq]. +.PD +.PP +Take care that the commands have to be written in lower case. +.SS status +Prints a summary of the state of the disk array. +.PP +It includes information about the parity fragmentation, how old +are the blocks without checking, and all the recorded silent +errors encountered while scrubbing. +.PP +Note that the information presented refers at the latest time you +run \[dq]sync\[dq]. Later modifications are not taken into account. +.PP +If bad blocks were detected, their block numbers are listed. +To fix them, you can use the \[dq]fix \-e\[dq] command. +.PP +It also shows a graph representing the the last time each block +was scrubbed or synced. Scrubbed blocks are shown with \'*\', +blocks synced but not yet scrubbed with \'o\'. +.PP +Nothing is modified. +.SS smart +Prints a SMART report of all the disks of the array. +.PP +It includes an estimation of the probability of failure in the next +year allowing to plan maintenance replacements of the disks that show +suspicious attributes. +.PP +This probability estimation obtained correlating the SMART attributes +of the disks, with the Backblaze data available at: +.PP +.RS 4 +https://www.backblaze.com/hard\-drive\-test\-data.html +.PD 0 +.PP +.PD +.RE +.PP +If SMART reports that a disk is failing, \[dq]FAIL\[dq] or \[dq]PREFAIL\[dq] is printed +for that disk, and SnapRAID returns with an error. +In this case an immediate replacement of the disk is highly recommended. +.PP +Other possible strings are: +.RS 4 +.PD 0 +.HP 4 +.I logfail +In the past some attributes were lower than +the threshold. +.HP 4 +.I logerr +The device error log contains errors. +.HP 4 +.I selferr +The device self\-test log contains errors. +.PD +.RE +.PP +If the \-v, \-\-verbose option is specified a deeper statistical analysis +is provided. This analysis can help you to decide if you need more +or less parity. +.PP +This command uses the \[dq]smartctl\[dq] tool, and it\'s equivalent to run +\[dq]smartctl \-a\[dq] on all the devices. +.PP +If your devices are not auto\-detected correctly, you can configure +a custom command using the \[dq]smartctl\[dq] option in the configuration +file. +.PP +Nothing is modified. +.SS up +Spins up all the disks of the array. +.PP +You can spin\-up only some specific disks using the \-d, \-\-filter\-disk option. +.PP +Take care that spinniup\-up all the disks at the same time needs a lot of power. +Ensure that your power\-supply can sustain that. +.PP +Nothing is modified. +.SS down +Spins down all the disks of the array. +.PP +This command uses the \[dq]smartctl\[dq] tool, and it\'s equivalent to run +\[dq]smartctl \-s standby,now\[dq] on all the devices. +.PP +You can spin\-down only some specific disks using the \-d, \-\-filter\-disk option. +.PP +Nothing is modified. +.SS diff +Lists all the files modified from the last \[dq]sync\[dq] that need to have +their parity data recomputed. +.PP +This command doesn\'t check the file data, but only the file time\-stamp +size and inode. +.PP +At the end of the command, you\'ll get a summary of the file changes +grouped by: +.RS 4 +.PD 0 +.HP 4 +.I equal +Files equal at before. +.HP 4 +.I added +Files added that were not present before. +.HP 4 +.I removed +Files removed. +.HP 4 +.I updated +Files with a different size or time\-stamp, meaning that +they were modified. +.HP 4 +.I moved +Files moved to a different directory of the same disk. +They are identified by having the same name, size, time\-stamp +and inode, but different directory. +.HP 4 +.I copied +Files copied in the same or different disk. Note that if in +true they are moved to a different disk, you\'ll also have +them counted in \[dq]removed\[dq]. +They are identified by having the same name, size, and +time\-stamp. But if the sub\-second time\-stamp is zero, +then the full path should match, and not only the name. +.HP 4 +.I restored +Files with a different inode but with name, size and time\-stamp +matching. These are usually files restored after being deleted. +.PD +.RE +.PP +If a \[dq]sync\[dq] is required, the process return code is 2, instead of the +default 0. The return code 1 is instead for a generic error condition. +.PP +Nothing is modified. +.SS sync +Updates the parity information. All the modified files +in the disk array are read, and the corresponding parity +data is updated. +.PP +You can stop this process at any time pressing Ctrl+C, +without losing the work already done. +At the next run the \[dq]sync\[dq] process will start where +interrupted. +.PP +If during the process, silent or input/output errors are found, +the corresponding blocks are marked as bad. +.PP +Files are identified by path and/or inode and checked by +size and time\-stamp. +If the file size or time\-stamp are different, the parity data +is recomputed for the whole file. +If the file is moved or renamed in the same disk, keeping the +same inode, the parity is not recomputed. +If the file is moved to another disk, the parity is recomputed, +but the previously computed hash information is kept. +.PP +The \[dq]content\[dq] and \[dq]parity\[dq] files are modified if necessary. +The files in the array are NOT modified. +.SS scrub +Scrubs the array, checking for silent or input/output errors in data +and parity disks. +.PP +For each command invocation, about the 8% of the array is checked, but +nothing that was already scrubbed in the last 10 days. +This means that scrubbing once a week, every bit of data is checked +at least one time every three months. +.PP +You can define a different scrub plan or amount using the \-p, \-\-plan +option that takes as argument: +bad \- Scrub blocks marked bad. +new \- Scrub just synced blocks not yet scrubbed. +full \- Scrub everything. +0\-100 \- Scrub the exact percentage of blocks. +.PP +If you specify a percentage amount, you can also use the \-o, \-\-older\-than +option to define how old the block should be. +The oldest blocks are scrubbed first ensuring an optimal check. +If instead you want to scrub the just synced blocks, not yet scrubbed, +you should use the \[dq]\-p new\[dq] option. +.PP +To get the details of the scrub status use the \[dq]status\[dq] command. +.PP +For any silent or input/output error found the corresponding blocks +are marked as bad in the \[dq]content\[dq] file. +These bad blocks are listed in \[dq]status\[dq], and can be fixed with \[dq]fix \-e\[dq]. +After the fix, at the next scrub they will be rechecked, and if found +corrected, the bad mark will be removed. +To scrub only the bad blocks, you can use the \[dq]scrub \-p bad\[dq] command. +.PP +It\'s recommended to run \[dq]scrub\[dq] only on a synced array, to avoid to +have reported error caused by unsynced data. These errors are recognized +as not being silent errors, and the blocks are not marked as bad, +but such errors are reported in the output of the command. +.PP +Files are identified only by path, and not by inode. +.PP +The \[dq]content\[dq] file is modified to update the time of the last check +of each block, and to mark bad blocks. +The \[dq]parity\[dq] files are NOT modified. +The files in the array are NOT modified. +.SS fix +Fix all the files and the parity data. +.PP +All the files and the parity data are compared with the snapshot +state saved in the last \[dq]sync\[dq]. +If a difference is found, it\'s reverted to the stored snapshot. +.PP +The \[dq]fix\[dq] command doesn\'t differentiate between errors and +intentional modifications. It unconditionally reverts the file state +at the last \[dq]sync\[dq]. +.PP +If no other option is specified the full array is processed. +Use the filter options to select a subset of files or disks to operate on. +.PP +To only fix the blocks marked bad during \[dq]sync\[dq] and \[dq]scrub\[dq], +use the \-e, \-\-filter\-error option. +As difference from other filter options, with this one the fixes are +applied only to files that are not modified from the the latest \[dq]sync\[dq]. +.PP +All the files that cannot be fixed are renamed adding the +\[dq].unrecoverable\[dq] extension. +.PP +Before fixing, the full array is scanned to find any moved file, +after the last \[dq]sync\[dq] operation. +These files are identified by their time\-stamp, ignoring their name +and directory, and are used in the recovering process if necessary. +If you moved some of them outside the array, you can use the \-i, \-\-import +option to specify additional directories to scan. +.PP +Files are identified only by path, and not by inode. +.PP +The \[dq]content\[dq] file is NOT modified. +The \[dq]parity\[dq] files are modified if necessary. +The files in the array are modified if necessary. +.SS check +Verify all the files and the parity data. +.PP +It works like \[dq]fix\[dq], but it only simulates a recovery and no change +is written in the array. +.PP +This command is mostly intended for manual verifications, +like after a recovery process or in other special conditions. +For periodic and scheduled checks uses \[dq]scrub\[dq]. +.PP +If you use the \-a, \-\-audit\-only option, only the file +data is checked, and the parity data is ignored for a +faster run. +.PP +Files are identified only by path, and not by inode. +.PP +Nothing is modified. +.SS list +Lists all the files contained in the array at the time of the +last \[dq]sync\[dq]. +.PP +Nothing is modified. +.SS dup +Lists all the duplicate files. Two files are assumed equal if their +hashes are matching. The file data is not read, but only the +precomputed hashes are used. +.PP +Nothing is modified. +.SS pool +Creates or updates in the \[dq]pooling\[dq] directory a virtual view of all +the files of your disk array. +.PP +The files are not really copied here, but just linked using +symbolic links. +.PP +When updating, all the present symbolic links and empty +subdirectories are deleted and replaced with the new +view of the array. Any other regular file is left in place. +.PP +Nothing is modified outside the pool directory. +.SS devices +Prints the low level devices used by the array. +.PP +This command prints the devices associations in place in the array, +and it\'s mainly intended as a script interface. +.PP +The first two columns are the low level device id and path. +The next two columns are the high level device id and path. +The latest column if the disk name in the array. +.PP +In most cases you have one low level device for each disk in the +array, but in some more complex configurations, you may have multiple +low level devices used by a single disk in the array. +.PP +Nothing is modified. +.SS touch +Sets arbitrarely the sub\-second timestamp of all the files +that have it at zero. +.PP +This improves the SnapRAID capability to recognize moved +and copied files as it makes the timestamp almost unique, +removing possible duplicates. +.PP +More specifically, if the sub\-second timestamp is not zero, +a moved or copied file is identified as such if it matches +the name, size and timestamp. If instead the sub\-second timestamp +is zero, it\'s considered a copy only if it matches the full path, +size and timestamp. +.PP +Note that the second precision timestamp is not modified, +and all the dates and times of your files will be maintained. +.SS rehash +Schedules a rehash of the whole array. +.PP +This command changes the hash kind used, typically when upgrading +from a 32 bits system to a 64 bits one, to switch from +MurmurHash3 to the faster SpookyHash. +.PP +If you are already using the optimal hash, this command +does nothing and tells you that nothing has to be done. +.PP +The rehash isn\'t done immediately, but it takes place +progressively during \[dq]sync\[dq] and \[dq]scrub\[dq]. +.PP +You can get the rehash state using \[dq]status\[dq]. +.PP +During the rehash, SnapRAID maintains full functionality, +with the only exception of \[dq]dup\[dq] not able to detect duplicated +files using a different hash. +.SH OPTIONS +SnapRAID provides the following options: +.TP +.B \-c, \-\-conf CONFIG +Selects the configuration file to use. If not specified in Unix +it\'s used the file \[dq]/usr/local/etc/snapraid.conf\[dq] if it exists, +or \[dq]/etc/snapraid.conf\[dq] otherwise. +In Windows it\'s used the file \[dq]snapraid.conf\[dq] in the same +directory of \[dq]snapraid.exe\[dq]. +.TP +.B \-f, \-\-filter PATTERN +Filters the files to process in \[dq]check\[dq] and \[dq]fix\[dq]. +Only the files matching the entered pattern are processed. +This option can be used many times. +See the PATTERN section for more details in the +pattern specifications. +In Unix, ensure to quote globbing chars if used. +This option can be used only with \[dq]check\[dq] and \[dq]fix\[dq]. +Note that it cannot be used with \[dq]sync\[dq] and \[dq]scrub\[dq], because they always +process the whole array. +.TP +.B \-d, \-\-filter\-disk NAME +Filters the disks to process in \[dq]check\[dq], \[dq]fix\[dq], \[dq]up\[dq] and \[dq]down\[dq]. +You must specify a disk name as named in the configuration +file. +You can also specify parity disks with the names: \[dq]parity\[dq], \[dq]2\-parity\[dq], +\[dq]3\-parity\[dq], ... to limit the operations a specific parity disk. +If you combine more \-\-filter, \-\-filter\-disk and \-\-filter\-missing options, +only files matching all the set of filters are selected. +This option can be used many times. +This option can be used only with \[dq]check\[dq], \[dq]fix\[dq], \[dq]up\[dq] and \[dq]down\[dq]. +Note that it cannot be used with \[dq]sync\[dq] and \[dq]scrub\[dq], because they always +process the whole array. +.TP +.B \-m, \-\-filter\-missing +Filters the files to process in \[dq]check\[dq] and \[dq]fix\[dq]. +Only the files missing/deleted from the array are processed. +When used with \[dq]fix\[dq], this is a kind of \[dq]undelete\[dq] command. +If you combine more \-\-filter, \-\-filter\-disk and \-\-filter\-missing options, +only files matching all the set of filters are selected. +This option can be used only with \[dq]check\[dq] and \[dq]fix\[dq]. +Note that it cannot be used with \[dq]sync\[dq] and \[dq]scrub\[dq], because they always +process the whole array. +.TP +.B \-e, \-\-filter\-error +Filters the blocks to process in \[dq]check\[dq] and \[dq]fix\[dq]. +It processes only the blocks marked with silent or input/output +errors during \[dq]sync\[dq] and \[dq]scrub\[dq], and listed in \[dq]status\[dq]. +This option can be used only with \[dq]check\[dq] and \[dq]fix\[dq]. +.TP +.B \-p, \-\-plan PERC|bad|new|full +Selects the scrub plan. If PERC is a numeric value from 0 to 100, +it\'s interpreted as the percentage of blocks to scrub. +Instead of a percentage, you can also specify a plan: +\[dq]bad\[dq] scrubs bad blocks, \[dq]new\[dq] the blocks not yet scrubbed, +and \[dq]full\[dq] for everything. +This option can be used only with \[dq]scrub\[dq]. +.TP +.B \-o, \-\-older\-than DAYS +Selects the older the part of the array to process in \[dq]scrub\[dq]. +DAYS is the minimum age in days for a block to be scrubbed, +default is 10. +Blocks marked as bad are always scrubbed despite this option. +This option can be used only with \[dq]scrub\[dq]. +.TP +.B \-a, \-\-audit\-only +In \[dq]check\[dq] verifies the hash of the files without +doing any kind of check on the parity data. +If you are interested in checking only the file data this +option can speedup a lot the checking process. +This option can be used only with \[dq]check\[dq]. +.TP +.B \-h, \-\-pre\-hash +In \[dq]sync\[dq] runs a preliminary hashing phase of all the new data +to have an additional verification before the parity computation. +Usually in \[dq]sync\[dq] no preliminary hashing is done, and the new +data is hashed just before the parity computation when it\'s read +for the first time. +Unfortunately, this process happens when the system is under +heavy load, with all disks spinning and with a busy CPU. +This is an extreme condition for the machine, and if it has a +latent hardware problem, it\'s possible to encounter silent errors +what cannot be detected because the data is not yet hashed. +To avoid this risk, you can enable the \[dq]pre\-hash\[dq] mode and have +all the data read two times to ensure its integrity. +This option also verifies the files moved inside the array, +to ensure that the move operation went successfully, and in case +to block the sync and to allow to run a fix operation. +This option can be used only with \[dq]sync\[dq]. +.TP +.B \-i, \-\-import DIR +Imports from the specified directory any file that you deleted +from the array after the last \[dq]sync\[dq]. +If you still have such files, they could be used by \[dq]check\[dq] +and \[dq]fix\[dq] to improve the recover process. +The files are read also in subdirectories and they are +identified regardless of their name. +This option can be used only with \[dq]check\[dq] and \[dq]fix\[dq]. +.TP +.B \-Z, \-\-force\-zero +Forces the insecure operation of syncing a file with zero +size that before was not. +If SnapRAID detects a such condition, it stops proceeding +unless you specify this option. +This allows to easily detect when after a system crash, +some accessed files were truncated. +This is a possible condition in Linux with the ext3/ext4 +file\-systems. +This option can be used only with \[dq]sync\[dq]. +.TP +.B \-E, \-\-force\-empty +Forces the insecure operation of syncing a disk with all +the original files missing. +If SnapRAID detects that all the files originally present +in the disk are missing or rewritten, it stops proceeding +unless you specify this option. +This allows to easily detect when a data file\-system is not +mounted. +This option can be used only with \[dq]sync\[dq]. +.TP +.B \-U, \-\-force\-uuid +Forces the insecure operation of syncing, checking and fixing +with disks that have changed their UUID. +If SnapRAID detects that some disks have changed UUID, +it stops proceeding unless you specify this option. +This allows to detect when your disks are mounted in the +wrong mount points. +It\'s anyway allowed to have a single UUID change with +single parity, and more with multiple parity, because it\'s +the normal case of replacing disks after a recovery. +This option can be used only with \[dq]sync\[dq], \[dq]check\[dq] or +\[dq]fix\[dq]. +.TP +.B \-D, \-\-force\-device +Forces the insecure operation of fixing with inaccessible disks, +or with disks on the same physical device. +Like if you lost two data disks, and you have a spare disk to recover +only the first one, and you want to ignore the second inaccessible disk. +Or if you want to recover a disk in the free space left in an +already used disk, sharing the same physical device. +This option can be used only with \[dq]fix\[dq]. +.TP +.B \-N, \-\-force\-nocopy +In \[dq]sync\[dq], \[dq]check and \[dq]fix\[dq], disables the copy detection heuristic. +Without this option SnapRAID assumes that files with same +attributes, like name, size and time\-stamp are copies with the +same data. +This allows to identify copied or moved files from one disk +to another, and to reuse the already computed hash information +to detect silent errors or to recover missing files. +This behavior, in some rare cases, may result in false positives, +or in a slow process due the many hash verifications, and this +option allows to resolve them. +This option can be used only with \[dq]sync\[dq], \[dq]check\[dq] and \[dq]fix\[dq]. +.TP +.B \-F, \-\-force\-full +In \[dq]sync\[dq] forces a full rebuild of the parity. +This option can be used when you add a new parity level, or if +you reverted back to an old content file using a more recent parity data. +Instead of recomputing the parity from scratch, this allows +to reuse the hashes present in the content file to validate data, +and to maintain data protection during the \[dq]sync\[dq] process using +the parity data you have. +This option can be used only with \[dq]sync\[dq]. +.TP +.B \-R, \-\-force\-realloc +In \[dq]sync\[dq] forces a full reallocation of files and rebuild of the parity. +This option can be used to completely reallocate all the files +removing the fragmentation, but reusing the hashes present in the content +file to validate data. +Compared to \-F, \-\-force\-full, this option reallocates all the parity +not having data protection during the operation. +This option can be used only with \[dq]sync\[dq]. +.TP +.B \-l, \-\-log FILE +Write a detailed log in the specified file. +If this option is not specified, unexpected errors are printed +on the screen, likely resulting in too much output in case of +many errors. When \-l, \-\-log is specified, on the screen, go only +fatal errors that makes SnapRAID to stop progress. +If the path starts with \'>>\' the file is opened +in append mode. Occurrences of \'%D\' and \'%T\' in the name are +replaced with the date and time in the format YYYYMMDD and +HHMMSS. Note that in Windows batch files, you\'ll have to double +the \'%\' char, like result\-%%D.log. And to use \'>>\' you\'ll have +to enclose the name in \[dq], like \[dq]>>result.log\[dq]. +To output the log to standard output or standard error, +you can use respectively \[dq]>&1\[dq] and \[dq]>&2\[dq]. +.TP +.B \-L, \-\-error\-limit +Sets a new error limit before stopping execution. +By default SnapRAID stops if it encounters more than 100 +Input/Output errors, meaning that likely a disk is going to +die. +This options affects \[dq]sync\[dq] and \[dq]scrub\[dq], that are allowed +to continue after the first bunch of disk errors, to try +to complete at most their operations. +Instead, \[dq]check\[dq] and \[dq]fix\[dq] always stop at the first error. +.TP +.B \-S, \-\-start BLKSTART +Starts the processing from the specified +block number. It could be useful to retry to check +or fix some specific block, in case of a damaged disk. +It\'s present mainly for advanced manual recovering. +.TP +.B \-B, \-\-count BLKCOUNT +Processes only the specified number of blocks. +It\'s present mainly for advanced manual recovering. +.TP +.B \-C, \-\-gen\-conf CONTENT_FILE +Generates a dummy configuration file from an existing +content file. +The configuration file is written in the standard output, +and it doesn\'t overwrite an existing one. +This configuration file also contains the information +needed to reconstruct the disk mount points, in case you +lose the entire system. +.TP +.B \-v, \-\-verbose +Prints more information on the screen. +If specified one time, it prints excluded files +and more stats. +This option has no effect on the log files. +.TP +.B \-q, \-\-quiet +Prints less information on the screen. +If specified one time, removes the progress bar, if two +times, the running operations, three times, the info +messages, four times the status messages. +Fatal errors are always printed on the screen. +This option has no effect on the log files. +.TP +.B \-H, \-\-help +Prints a short help screen. +.TP +.B \-V, \-\-version +Prints the program version. +.SH CONFIGURATION +SnapRAID requires a configuration file to know where your disk array +is located, and where storing the parity information. +.PP +In Unix it\'s used the file \[dq]/usr/local/etc/snapraid.conf\[dq] if it exists, +or \[dq]/etc/snapraid.conf\[dq] otherwise. +In Windows it\'s used the file \[dq]snapraid.conf\[dq] in the same +directory of \[dq]snapraid.exe\[dq]. +.PP +It should contain the following options (case sensitive): +.SS parity FILE [,FILE] ... +Defines the files to use to store the parity information. +The parity enables the protection from a single disk +failure, like RAID5. +.PP +You can specify multiples files that should be in different disks. +When a file cannot grow anymore, the next one is used. +The total space available must be as big as the biggest data disk in +the array. +.PP +You can add additional parity files at later time, but you +cannot reorder or remove them. +.PP +Leaving the parity disks reserved for parity ensures that +it doesn\'t get fragmented, improving the performance. +.PP +In Windows 256 MB are left unused in each disk to avoid the +warning about full disks. +.PP +This option is mandatory and it can be used only one time. +.SS (2,3,4,5,6)\-parity FILE [,FILE] ... +Defines the files to use to store extra parity information. +.PP +For each parity specified, one additional level of protection +is enabled: +.PD 0 +.IP \(bu +2\-parity enables RAID6 dual parity. +.IP \(bu +3\-parity enables triple parity +.IP \(bu +4\-parity enables quad (four) parity +.IP \(bu +5\-parity enables penta (five) parity +.IP \(bu +6\-parity enables hexa (six) parity +.PD +.PP +Each parity level requires the precence of all the previous parity +levels. +.PP +The same considerations of the \'parity\' option apply. +.PP +These options are optional and they can be used only one time. +.SS z\-parity FILE [,FILE] ... +Defines an alternate file and format to store the triple parity. +.PP +This option is an alternative at \'3\-parity\' mainly intended for +low\-end CPUs like ARM or AMD Phenom, Athlon and Opteron that don\'t +support the SSSE3 instructions set. In such cases it provides +a better performance. +.PP +This format is similar, but faster, at the one used by the ZFS RAIDZ3. +Like ZFS, it doesn\'t work beyond triple parity. +.PP +When using \'3\-parity\' you will be warned if it\'s recommended to use +the \'z\-parity\' format for a performance improvement. +.PP +It\'s possible to convert from one format to another, adjusting +the configuration file with the wanted z\-parity or 3\-parity file, +and using \'fix\' to recreate it. +.SS content FILE +Defines the file to use to store the list and check\-sums of all the +files present in your disk array. +.PP +It can be placed in the disk used to store data, parity, or +any other disk available. +If you use a data disk, this file is automatically excluded +from the \[dq]sync\[dq] process. +.PP +This option is mandatory and it can be used more times to save +more copies of the same files. +.PP +You have to store at least one copy for each parity disk used +plus one. Using some more doesn\'t hurt. +.SS data NAME DIR +Defines the name and the mount point of the data disks of +the array. NAME is used to identify the disk, and it must +be unique. DIR is the mount point of the disk in the +file\-system. +.PP +You can change the mount point as you like, as long you +keep the NAME fixed. +.PP +You should use one option for each data disk of the array. +.PP +You can rename later a disk, changing the NAME directly +in the configuration file, and then run a \'sync\' command. +In the rename case, the association is done using the stored +UUID of the disks. +.SS nohidden +Excludes all the hidden files and directory. +In Unix hidden files are the ones starting with \[dq].\[dq]. +In Windows they are the ones with the hidden attribute. +.SS exclude/include PATTERN +Defines the file or directory patterns to exclude and include +in the sync process. +All the patterns are processed in the specified order. +.PP +If the first pattern that matches is an \[dq]exclude\[dq] one, the file +is excluded. If it\'s an \[dq]include\[dq] one, the file is included. +If no pattern matches, the file is excluded if the last pattern +specified is an \[dq]include\[dq], or included if the last pattern +specified is an \[dq]exclude\[dq]. +.PP +See the PATTERN section for more details in the pattern +specifications. +.PP +This option can be used many times. +.SS blocksize SIZE_IN_KIBIBYTES +Defines the basic block size in kibi bytes of the parity. +One kibi bytes is 1024 bytes. +.PP +The default blocksize is 256 and it should work for most cases. +.PP +WARNING! This option is for experts only, and it\'s highly +recommended to not change it. To change again this value in +future you\'ll have to recreate the whole parity! +.PP +A reason to use a different hashsize is if you have a lot of small +files. In the order of many millions. +.PP +For each file, even of few bytes, a whole block of parity is allocated, +and with many files this may result in a lot of unused parity space. +And when you completely fill the parity disk, you are not +allowed to add more files in the data disks. +Anyway, the wasted parity doesn\'t sum between data disks. Wasted space +resulting from a high number of files in a data disk, limits only +the amount of data in such data disk and not in others. +.PP +As approximation, you can assume that half of the block size is +wasted for each file. For example, with 100000 files and a 256 KiB +block size, you are going to waste 13 GB of parity, that may result +in 13 GB less space available in the data disk. +.PP +You can get the amount of wasted space in each disk using \[dq]status\[dq]. +This is the amount of space that you must leave free in the data +disks, or use for files not included in the array. +If this value is negative, it means that your are near to fill +the parity, and it represents the space you can still waste. +.PP +To avoid the problem, you can use a bigger partition for parity. +For example, if you have the parity partition bigger than 13 GB +than data disks, you have enough extra space to handle up to 100000 +files in each data disk. +.PP +A trick to get a bigger parity partition in Linux, is to format it +with the command: +.PP +.RS 4 +mkfs.ext4 \-m 0 \-T largefile4 DEVICE +.PD 0 +.PP +.PD +.RE +.PP +This results in about 1.5% of extra space. Meaning about 60 GB for +a 4 TB disk, that allows about 460000 files in each data disk without +any wasted space. +.SS hashsize SIZE_IN_BYTES +Defines the hash size in bytes of the saved blocks. +.PP +The default hashsize is 16 bytes (128 bits), and it should work +for most cases. +.PP +WARNING! This option is for experts only, and it\'s highly +recommended to not change it. To change again this value in +future you\'ll have to recreate the whole parity! +.PP +A reason to use a different hashsize is if your system has +small memory. As a rule of thumb SnapRAID usually requires +1 GiB of RAM memory for each 16 TB of data in the array. +.PP +Specifically, to store the hashes of the data, SnapRAID requires +about TS*(1+HS)/BS bytes of RAM memory. +Where TS is the total size in bytes of your disk array, BS is the +block size in bytes, and HS is the hash size in bytes. +.PP +For example with 8 disks of 4 TB and a block size of 256 KiB +(1 KiB = 1024 bytes), and an hash size of 16, you get: +.PP +RAM = (8 * 4 * 10^12) * (1+16) / (256 * 2^10) = 1.93 GiB +.PD 0 +.PP +.PD +.PP +Switching to a hash size of 8, you get: +.PP +RAM = (8 * 4 * 10^12) * (1+8) / (256 * 2^10) = 1.02 GiB +.PD 0 +.PP +.PD +.PP +Switching to a block size of 512, you get: +.PP +RAM = (8 * 4 * 10^12) * (1+16) / (512 * 2^10) = 0.96 GiB +.PD 0 +.PP +.PD +.PP +Switching to both a hash size of 8, and a block size of 512 you get: +.PP +RAM = (8 * 4 * 10^12) * (1+8) / (512 * 2^10) = 0.51 GiB +.PD 0 +.PP +.PD +.SS autosave SIZE_IN_GIGABYTES +Automatically save the state when syncing or scrubbing after the specified amount +of GB processed. +This option is useful to avoid to restart from scratch long \[dq]sync\[dq] +commands interrupted by a machine crash, or any other event that +may interrupt SnapRAID. +.SS pool DIR +Defines the pooling directory where the virtual view of the disk +array is created using the \[dq]pool\[dq] command. +.PP +The directory must already exist. +.SS share UNC_DIR +Defines the Windows UNC path required to access the disks remotely. +.PP +If this option is specified, the symbolic links created in the pool +directory use this UNC path to access the disks. +Without this option the symbolic links generated use only local paths, +not allowing to share the pool directory in the network. +.PP +The symbolic links are formed using the specified UNC path, adding the +disk name as specified in the \[dq]disk\[dq] option, and finally adding the +file dir and name. +.PP +This option is only required for Windows. +.SS smartctl DISK/PARITY OPTIONS... +Defines a custom smartctl command to obtain the SMART attributes +for each disk. This may be required for RAID controllers and for +some USB disk that cannot be auto\-detected. +.PP +DISK is the same disk name specified in the \[dq]disk\[dq] option. +PARITY is one of the parity name as \[dq]parity,(1,2,3,4,5,6,z)\-parity\[dq]. +.PP +In the specified OPTIONS, the \[dq]%s\[dq] string is replaced by the +device name. Note that in case of RAID controllers the device is likely +fixed, and you don\'t have to use \[dq]%s\[dq]. +.PP +Refers at the smartmontools documentation about the possible options: +.PP +.RS 4 +https://www.smartmontools.org/wiki/Supported_RAID\-Controllers +.PD 0 +.PP +.PD +https://www.smartmontools.org/wiki/Supported_USB\-Devices +.PD 0 +.PP +.PD +.RE +.SS Examples +An example of a typical configuration for Unix is: +.PP +.RS 4 +parity /mnt/diskp/snapraid.parity +.PD 0 +.PP +.PD +content /mnt/diskp/snapraid.content +.PD 0 +.PP +.PD +content /var/snapraid/snapraid.content +.PD 0 +.PP +.PD +data d1 /mnt/disk1/ +.PD 0 +.PP +.PD +data d2 /mnt/disk2/ +.PD 0 +.PP +.PD +data d3 /mnt/disk3/ +.PD 0 +.PP +.PD +exclude /lost+found/ +.PD 0 +.PP +.PD +exclude /tmp/ +.PD 0 +.PP +.PD +smartctl d1 \-d sat %s +.PD 0 +.PP +.PD +smartctl d2 \-d usbjmicron %s +.PD 0 +.PP +.PD +smartctl parity \-d areca,1/1 /dev/sg0 +.PD 0 +.PP +.PD +smartctl 2\-parity \-d areca,2/1 /dev/sg0 +.PD 0 +.PP +.PD +.RE +.PP +An example of a typical configuration for Windows is: +.PP +.RS 4 +parity E:\\snapraid.parity +.PD 0 +.PP +.PD +content E:\\snapraid.content +.PD 0 +.PP +.PD +content C:\\snapraid\\snapraid.content +.PD 0 +.PP +.PD +data d1 G:\\array\\ +.PD 0 +.PP +.PD +data d2 H:\\array\\ +.PD 0 +.PP +.PD +data d3 I:\\array\\ +.PD 0 +.PP +.PD +exclude Thumbs.db +.PD 0 +.PP +.PD +exclude \\$RECYCLE.BIN +.PD 0 +.PP +.PD +exclude \\System Volume Information +.PD 0 +.PP +.PD +smartctl d1 \-d sat %s +.PD 0 +.PP +.PD +smartctl d2 \-d usbjmicron %s +.PD 0 +.PP +.PD +smartctl parity \-d areca,1/1 /dev/arcmsr0 +.PD 0 +.PP +.PD +smartctl 2\-parity \-d areca,2/1 /dev/arcmsr0 +.PD 0 +.PP +.PD +.RE +.SH PATTERN +Patterns are used to select a subset of files to exclude or include in +the process. +.PP +There are four different types of patterns: +.TP +.B FILE +Selects any file named as FILE. You can use any globbing +character like * and ?, and char classes like [a\-z]. +This pattern is applied only to files and not to directories. +.TP +.B DIR/ +Selects any directory named DIR and everything inside. +You can use any globbing character like * and ?. +This pattern is applied only to directories and not to files. +.TP +.B /PATH/FILE +Selects the exact specified file path. You can use any +globbing character like * and ? but they never match a +directory slash. +This pattern is applied only to files and not to directories. +.TP +.B /PATH/DIR/ +Selects the exact specified directory path and everything +inside. You can use any globbing character like * and ? but +they never match a directory slash. +This pattern is applied only to directories and not to files. +.PP +Note that when you specify an absolute path starting with /, it\'s +applied at the array root dir and not at the local file\-system root dir. +.PP +In Windows you can use the backslash \\ instead of the forward slash /. +Note that Windows system directories, junctions, mount points, and any +other Windows special directory are treated just as files, meaning that +to exclude them you must use a file rule, and not a directory one. +.PP +If the file name you want to use really contains a \'*\', \'?\', \'[\', +or \']\' char, you have to escape it to avoid to have interpreted as a +globbing character. In Unix the escape char is \'\\\', in Windows it\'s \'^\'. +Note that when the pattern is on the command line, you have to double the +escape character to avoid to have it interpreted by the command shell. +.PP +In the configuration file, you can use different strategies to filter +the files to process. +The simplest one is to use only \[dq]exclude\[dq] rules to remove all the +files and directories you do not want to process. For example: +.PP +.RS 4 +# Excludes any file named \[dq]*.unrecoverable\[dq] +.PD 0 +.PP +.PD +exclude *.unrecoverable +.PD 0 +.PP +.PD +# Excludes the root directory \[dq]/lost+found\[dq] +.PD 0 +.PP +.PD +exclude /lost+found/ +.PD 0 +.PP +.PD +# Excludes any sub\-directory named \[dq]tmp\[dq] +.PD 0 +.PP +.PD +exclude tmp/ +.PD 0 +.PP +.PD +.RE +.PP +The opposite way is to define only the file you want to process, using +only \[dq]include\[dq] rules. For example: +.PP +.RS 4 +# Includes only some directories +.PD 0 +.PP +.PD +include /movies/ +.PD 0 +.PP +.PD +include /musics/ +.PD 0 +.PP +.PD +include /pictures/ +.PD 0 +.PP +.PD +.RE +.PP +The final way, is to mix \[dq]exclude\[dq] and \[dq]include\[dq] rules. In this case take +care that the order of rules is important. Previous rules have the +precedence over the later ones. +To get things simpler you can first have all the \[dq]exclude\[dq] rules and then +all the \[dq]include\[dq] ones. For example: +.PP +.RS 4 +# Excludes any file named \[dq]*.unrecoverable\[dq] +.PD 0 +.PP +.PD +exclude *.unrecoverable +.PD 0 +.PP +.PD +# Excludes any sub\-directory named \[dq]tmp\[dq] +.PD 0 +.PP +.PD +exclude tmp/ +.PD 0 +.PP +.PD +# Includes only some directories +.PD 0 +.PP +.PD +include /movies/ +.PD 0 +.PP +.PD +include /musics/ +.PD 0 +.PP +.PD +include /pictures/ +.PD 0 +.PP +.PD +.RE +.PP +On the command line, using the \-f option, you can only use \[dq]include\[dq] +patterns. For example: +.PP +.RS 4 +# Checks only the .mp3 files. +.PD 0 +.PP +.PD +# Note the \[dq]\[dq] use to avoid globbing expansion by the shell in Unix. +.PD 0 +.PP +.PD +snapraid \-f \[dq]*.mp3\[dq] check +.PD 0 +.PP +.PD +.RE +.PP +In Unix, when using globbing chars in the command line, you have to +quote them. Otherwise the shell will try to expand them. +.SH CONTENT +SnapRAID stores the list and check\-sums of your files in the content file. +.PP +It\'s a binary file, listing all the files present in your disk array, +with all the check\-sums to verify their integrity. +.PP +This file is read and written by the \[dq]sync\[dq] and \[dq]scrub\[dq] commands, and +read by \[dq]fix\[dq], \[dq]check\[dq] and \[dq]status\[dq]. +.SH PARITY +SnapRAID stores the parity information of your array in the parity +files. +.PP +They are binary files, containing the computed parity of all the +blocks defined in the \[dq]content\[dq] file. +.PP +These files are read and written by the \[dq]sync\[dq] and \[dq]fix\[dq] commands, and +only read by \[dq]scrub\[dq] and \[dq]check\[dq]. +.SH ENCODING +SnapRAID in Unix ignores any encoding. It reads and stores the +file names with the same encoding used by the file\-system. +.PP +In Windows all the names read from the file\-system are converted and +processed in the UTF\-8 format. +.PP +To have the file names printed correctly you have to set the Windows +console in the UTF\-8 mode, with the command \[dq]chcp 65001\[dq], and use +a TrueType font like \[dq]Lucida Console\[dq] as console font. +Note that it has effect only on the printed file names, if you +redirect the console output to a file, the resulting file is always +in the UTF\-8 format. +.SH COPYRIGHT +This file is Copyright (C) 2011 Andrea Mazzoleni +.SH SEE ALSO +rsync(1) diff --git a/snapraid.conf.example b/snapraid.conf.example new file mode 100644 index 0000000..16c8d23 --- /dev/null +++ b/snapraid.conf.example @@ -0,0 +1,93 @@ +# Example configuration for snapraid + +# Defines the file to use as parity storage +# It must NOT be in a data disk +# Format: "parity FILE [,FILE] ..." +parity /mnt/diskp/snapraid.parity + +# Defines the files to use as additional parity storage. +# If specified, they enable the multiple failures protection +# from two to six level of parity. +# To enable, uncomment one parity file for each level of extra +# protection required. Start from 2-parity, and follow in order. +# It must NOT be in a data disk +# Format: "X-parity FILE [,FILE] ..." +#2-parity /mnt/diskq/snapraid.2-parity +#3-parity /mnt/diskr/snapraid.3-parity +#4-parity /mnt/disks/snapraid.4-parity +#5-parity /mnt/diskt/snapraid.5-parity +#6-parity /mnt/disku/snapraid.6-parity + +# Defines the files to use as content list +# You can use multiple specification to store more copies +# You must have least one copy for each parity file plus one. Some more don't hurt +# They can be in the disks used for data, parity or boot, +# but each file must be in a different disk +# Format: "content FILE" +content /var/snapraid.content +content /mnt/disk1/snapraid.content +content /mnt/disk2/snapraid.content + +# Defines the data disks to use +# The name and mount point association is relevant for parity, do not change it +# WARNING: Adding here your /home, /var or /tmp disks is NOT a good idea! +# SnapRAID is better suited for files that rarely changes! +# Format: "data DISK_NAME DISK_MOUNT_POINT" +data d1 /mnt/disk1/ +data d2 /mnt/disk2/ +data d3 /mnt/disk3/ + +# Excludes hidden files and directories (uncomment to enable). +#nohidden + +# Defines files and directories to exclude +# Remember that all the paths are relative at the mount points +# Format: "exclude FILE" +# Format: "exclude DIR/" +# Format: "exclude /PATH/FILE" +# Format: "exclude /PATH/DIR/" +exclude *.unrecoverable +exclude /tmp/ +exclude /lost+found/ + +# Defines the block size in kibi bytes (1024 bytes) (uncomment to enable). +# WARNING: Changing this value is for experts only! +# Default value is 256 -> 256 kibi bytes -> 262144 bytes +# Format: "blocksize SIZE_IN_KiB" +#blocksize 256 + +# Defines the hash size in bytes (uncomment to enable). +# WARNING: Changing this value is for experts only! +# Default value is 16 -> 128 bits +# Format: "hashsize SIZE_IN_BYTES" +#hashsize 16 + +# Automatically save the state when syncing after the specified amount +# of GB processed (uncomment to enable). +# This option is useful to avoid to restart from scratch long 'sync' +# commands interrupted by a machine crash. +# It also improves the recovering if a disk break during a 'sync'. +# Default value is 0, meaning disabled. +# Format: "autosave SIZE_IN_GB" +#autosave 500 + +# Defines the pooling directory where the virtual view of the disk +# array is created using the "pool" command (uncomment to enable). +# The files are not really copied here, but just linked using +# symbolic links. +# This directory must be outside the array. +# Format: "pool DIR" +#pool /pool + +# Defines a custom smartctl command to obtain the SMART attributes +# for each disk. This may be required for RAID controllers and for +# some USB disk that cannot be autodetected. +# In the specified options, the "%s" string is replaced by the device name. +# Refers at the smartmontools documentation about the possible options: +# RAID -> https://www.smartmontools.org/wiki/Supported_RAID-Controllers +# USB -> https://www.smartmontools.org/wiki/Supported_USB-Devices +#smartctl d1 -d sat %s +#smartctl d2 -d usbjmicron %s +#smartctl parity -d areca,1/1 /dev/sg0 +#smartctl 2-parity -d areca,2/1 /dev/sg0 + diff --git a/snapraid.conf.example.windows b/snapraid.conf.example.windows new file mode 100644 index 0000000..6d4f563 --- /dev/null +++ b/snapraid.conf.example.windows @@ -0,0 +1,108 @@ +# Example configuration for snapraid for Windows + +# Defines the file to use as parity storage +# It must NOT be in a data disk +# Format: "parity FILE [,FILE] ..." +parity E:\snapraid.parity + +# Defines the files to use as additional parity storage. +# If specified, they enable the multiple failures protection +# from two to six level of parity. +# To enable, uncomment one parity file for each level of extra +# protection required. Start from 2-parity, and follow in order. +# It must NOT be in a data disk +# Format: "X-parity FILE [,FILE] ..." +#2-parity F:\snapraid.2-parity +#3-parity G:\snapraid.3-parity +#4-parity H:\snapraid.4-parity +#5-parity I:\snapraid.5-parity +#6-parity J:\snapraid.6-parity + +# Defines the files to use as content list +# You can use multiple specification to store more copies +# You must have least one copy for each parity file plus one. Some more don't hurt +# They can be in the disks used for data, parity or boot, +# but each file must be in a different disk +# Format: "content FILE" +content C:\snapraid\snapraid.content +content K:\array\snapraid.content +content L:\array\snapraid.content + +# Defines the data disks to use +# The name and mount point association is relevant for parity, do not change it +# WARNING: Adding here your boot C:\ disk is NOT a good idea! +# SnapRAID is better suited for files that rarely changes! +# Format: "data DISK_NAME DISK_MOUNT_POINT" +data d1 K:\array\ +data d2 L:\array\ +data d3 M:\array\ + +# Excludes hidden files and directories (uncomment to enable). +#nohidden + +# Defines files and directories to exclude +# Remember that all the paths are relative at the mount points +# Format: "exclude FILE" +# Format: "exclude DIR\" +# Format: "exclude \PATH\FILE" +# Format: "exclude \PATH\DIR\" +exclude *.unrecoverable +exclude Thumbs.db +exclude \$RECYCLE.BIN +exclude \System Volume Information +exclude \Program Files\ +exclude \Program Files (x86)\ +exclude \Windows\ + +# Defines the block size in kibi bytes (1024 bytes) (uncomment to enable). +# WARNING: Changing this value is for experts only! +# Default value is 256 -> 256 kibi bytes -> 262144 bytes +# Format: "blocksize SIZE_IN_KiB" +#blocksize 256 + +# Defines the hash size in bytes (uncomment to enable). +# WARNING: Changing this value is for experts only! +# Default value is 16 -> 128 bits +# Format: "hashsize SIZE_IN_BYTES" +#hashsize 16 + +# Automatically save the state when syncing after the specified amount +# of GB processed (uncomment to enable). +# This option is useful to avoid to restart from scratch long 'sync' +# commands interrupted by a machine crash. +# It also improves the recovering if a disk break during a 'sync'. +# Default value is 0, meaning disabled. +# Format: "autosave SIZE_IN_GB" +#autosave 500 + +# Defines the pooling directory where the virtual view of the disk +# array is created using the "pool" command (uncomment to enable). +# The files are not really copied here, but just linked using +# symbolic links. +# This directory must be outside the array. +# Format: "pool DIR" +#pool C:\pool + +# Defines the Windows UNC path required to access disks from the pooling +# directory when shared in the network. +# If present (uncomment to enable), the symbolic links created in the +# pool virtual view, instead of using local paths, are created using the +# specified UNC path, adding the disk names and file path. +# This allows to share the pool directory in the network. +# See the manual page for more details. +# +# Format: "share UNC_DIR" +#share \\server + +# Defines a custom smartctl command to obtain the SMART attributes +# for each disk. This may be required for RAID controllers and for +# some USB disk that cannot be autodetected. +# In the specified options, the "%s" string is replaced by the device name. +# Refers at the smartmontools documentation about the possible options: +# RAID -> https://www.smartmontools.org/wiki/Supported_RAID-Controllers +# USB -> https://www.smartmontools.org/wiki/Supported_USB-Devices +#smartctl d1 -d sat %s +#smartctl d2 -d usbjmicron %s +#smartctl parity -d areca,1/1 /dev/arcmsr0 +#smartctl 2-parity -d areca,2/1 /dev/arcmsr0 + diff --git a/snapraid.d b/snapraid.d new file mode 100644 index 0000000..82ccdb5 --- /dev/null +++ b/snapraid.d @@ -0,0 +1,1336 @@ +Name{number} + snapraid - SnapRAID Backup For Disk Arrays + +Synopsis + :snapraid [-c, --conf CONFIG] + : [-f, --filter PATTERN] [-d, --filter-disk NAME] + : [-m, --filter-missing] [-e, --filter-error] + : [-a, --audit-only] [-h, --pre-hash] [-i, --import DIR] + : [-p, --plan PERC|bad|new|full] + : [-o, --older-than DAYS] [-l, --log FILE] + : [-Z, --force-zero] [-E, --force-empty] + : [-U, --force-uuid] [-D, --force-device] + : [-N, --force-nocopy] [-F, --force-full] + : [-R, --force-realloc] + : [-S, --start BLKSTART] [-B, --count BLKCOUNT] + : [-L, --error-limit NUMBER] + : [-v, --verbose] [-q, --quiet] + : status|smart|up|down|diff|sync|scrub|fix|check|list|dup + : |pool|devices|touch|rehash + + :snapraid [-V, --version] [-H, --help] [-C, --gen-conf CONTENT] + +Description + SnapRAID is a backup program for disk arrays. It stores parity + information of your data and it recovers from up to six disk + failures. + + SnapRAID is mainly targeted for a home media center, with a lot of + big files that rarely change. + + Beside the ability to recover from disk failures, other + features of SnapRAID are: + + * All your data is hashed to ensure data integrity and to avoid + silent corruption. + * If the failed disks are too many to allow a recovery, + you lose the data only on the failed disks. + All the data in the other disks is safe. + * If you accidentally delete some files in a disk, you can + recover them. + * You can start with already filled disks. + * The disks can have different sizes. + * You can add disks at any time. + * It doesn't lock-in your data. You can stop using SnapRAID at any + time without the need to reformat or move data. + * To access a file, a single disk needs to spin, saving power and + producing less noise. + + The official site of SnapRAID is: + + :http://www.snapraid.it/ + +Limitations + SnapRAID is in between a RAID and a Backup program trying to get the best + benefits of them. Although it also has some limitations that you should + consider before using it. + + The main one is that if a disk fails, and you haven't recently synced, + you may be unable to do a complete recover. + More specifically, you may be unable to recover up to the size of the + amount of the changed or deleted files from the last sync operation. + This happens even if the files changed or deleted are not in the + failed disk. This is the reason because SnapRAID is better suited for + data that rarely change. + + Instead the new added files don't prevent the recovering of the already + existing files. You may only lose the just added files, if they are on + the failed disk. + + Other limitations are: + + * You have different file-systems for each disk. + Using a RAID you have only a big file-system. + * It doesn't stripe data. + With RAID you get a speed boost with striping. + * It doesn't support real-time recovery. + With RAID you do not have to stop working when a disk fails. + * It's able to recover damages only from a limited number of disks. + With a Backup you are able to recover from a complete + failure of the whole disk array. + * Only file, time-stamps, symlinks and hardlinks are saved. + Permissions, ownership and extended attributes are not saved. + +Getting Started + To use SnapRAID you need to first select one disk of your disk array + to dedicate at the "parity" information. With one disk for parity you + will be able to recover from a single disk failure, like RAID5. + + If you want to be able to recover from more disk failures, like RAID6, + you must reserve additional disks for parity. Any additional parity + disk allow to recover from one more disk failure. + + As parity disks, you have to pick the biggest disks in the array, + as the parity information may grow in size as the biggest data + disk in the array. + + These disks will be dedicated to store the "parity" files. + You should not store your data in them. + + Then you have to define the "data" disks that you want to protect + with SnapRAID. The protection is more effective if these disks + contain data that rarely change. For this reason it's better to + DO NOT include the Windows C:\ disk, or the Unix /home, /var and /tmp + disks. + + The list of files is saved in the "content" files, usually + stored in the data, parity or boot disks. + These files contain the details of your backup, with all the + check-sums to verify its integrity. + The "content" file is stored in multiple copies, and each one must + be in a different disk, to ensure that in even in case of multiple + disk failures at least one copy is available. + + For example, suppose that you are interested only at one parity level + of protection, and that your disks are present in: + + :/mnt/diskp <- selected disk for parity + :/mnt/disk1 <- first disk to protect + :/mnt/disk2 <- second disk to protect + :/mnt/disk3 <- third disk to protect + + you have to create the configuration file /etc/snapraid.conf with + the following options: + + :parity /mnt/diskp/snapraid.parity + :content /var/snapraid/snapraid.content + :content /mnt/disk1/snapraid.content + :content /mnt/disk2/snapraid.content + :data d1 /mnt/disk1/ + :data d2 /mnt/disk2/ + :data d3 /mnt/disk3/ + + If you are in Windows, you should use the Windows path format, with drive + letters and backslashes instead of slashes. + + :parity E:\snapraid.parity + :content C:\snapraid\snapraid.content + :content F:\array\snapraid.content + :content G:\array\snapraid.content + :data d1 F:\array\ + :data d2 G:\array\ + :data d3 H:\array\ + + If you have many disks, and you run out of drive letters, you can mount + disks directly in sub folders. See: + + :https://www.google.com/search?q=Windows+mount+point + + At this point you are ready to start the "sync" command to build the + parity information. + + :snapraid sync + + This process may take some hours the first time, depending on the size + of the data already present in the disks. If the disks are empty + the process is immediate. + + You can stop it at any time pressing Ctrl+C, and at the next run it + will start where interrupted. + + When this command completes, your data is SAFE. + + Now you can start using your array as you like, and periodically + update the parity information running the "sync" command. + + Scrubbing + To periodically check the data and parity for errors, you can + run the "scrub" command. + + :snapraid scrub + + This command verifies the data in your array comparing it with + the hash computed in the "sync" command. + + Every run of the command checks about the 8% of the array, but not data + already scrubbed in the previous 10 days. + You can use the -p, --plan option to specify a different amount, + and the -o, --older-than option to specify a different age in days. + For example, to check 5% of the array older than 20 days use: + + :snapraid -p 5 -o 20 scrub + + If during the process, silent or input/output errors are found, + the corresponding blocks are marked as bad in the "content" file, + and listed in the "status" command. + + :snapraid status + + To fix them, you can use the "fix" command filtering for bad blocks with + the -e, --filter-error options: + + :snapraid -e fix + + At the next "scrub" the errors will disappear from the "status" report + if really fixed. To make it fast, you can use -p bad to scrub only blocks + marked as bad. + + :snapraid -p bad scrub + + Take care that running "scrub" on a not synced array may result in + errors caused by removed or modified files. These errors are reported + in the "scrub" result, but related blocks are not marked as bad. + + Pooling + To have all the files in your array shown in the same directory tree, + you can enable the "pooling" feature. It consists in creating a + read-only virtual view of all the files in your array using symbolic + links. + + You can configure the "pooling" directory in the configuration file with: + + :pool /pool + + or, if you are in Windows, with: + + :pool C:\pool + + and then run the "pool" command to create or update the virtual view. + + :snapraid pool + + If you are using a Unix platform and you want to share such directory + in the network to either Windows or Unix machines, you should add + to your /etc/samba/smb.conf the following options: + + :# In the global section of smb.conf + :unix extensions = no + + :# In the share section of smb.conf + :[pool] + :comment = Pool + :path = /pool + :read only = yes + :guest ok = yes + :wide links = yes + :follow symlinks = yes + + In Windows the same sharing operation is not so straightforward, + because Windows shares the symbolic links as they are, and that + requires the network clients to resolve them remotely. + + To make it working, besides sharing in the network the pool directory, + you must also share all the disks independently, using as share points + the disk names as defined in the configuration file. You must also specify in + the "share" option of the configure file, the Windows UNC path that remote + clients needs to use to access such shared disks. + + For example, operating from a server named "darkstar", you can use + the options: + + :data d1 F:\array\ + :data d2 G:\array\ + :data d3 H:\array\ + :pool C:\pool + :share \\darkstar + + and share the following dirs in the network: + + :\\darkstar\pool -> C:\pool + :\\darkstar\d1 -> F:\array + :\\darkstar\d2 -> G:\array + :\\darkstar\d3 -> H:\array + + to allow remote clients to access all the files at \\darkstar\\pool. + + You may also need to configure remote clients enabling access at remote + symlinks with the command: + + :fsutil behavior set SymlinkEvaluation L2L:1 R2R:1 L2R:1 R2L:1 + + Undeleting + SnapRAID is more like a backup program than a RAID system, and it + can be used to restore or undelete files to their previous state using + the -f, --filter option : + + :snapraid fix -f FILE + + or for a directory: + + :snapraid fix -f DIR/ + + You can also use it to recover only accidentally deleted files inside + a directory using the -m, --filter-missing option, that restores + only missing files, leaving untouched all the others. + + :snapraid fix -m -f DIR/ + + Or to recover all the deleted files in all the drives with: + + :snapraid fix -m + + Recovering + The worst happened, and you lost one or more disks! + + DO NOT PANIC! You will be able to recover them! + + The first thing you have to do is to avoid further changes at your disk array. + Disable any remote connection to it, any scheduled process, including any + scheduled SnapRAID nightly sync or scrub. + + Then proceed with the following steps. + + STEP 1 -> Reconfigure + You need some space to recover, even better if you already have additional + spare disks, but in case, also an external USB or remote disk is enough. + + Change the SnapRAID configuration file to make the "data" or "parity" + option of the failed disk to point to the place where you have enough empty + space to recover the files. + + For example, if you have that disk "d1" failed, you can change from: + + :data d1 /mnt/disk1/ + + to: + + :data d1 /mnt/new_spare_disk/ + + If the disk to recover is a parity disk, change the appropriate "parity" + option. + If you have more broken disks, change all their configuration options. + + STEP 2 -> Fix + Run the fix command, storing the log in an external file with: + + :snapraid -d NAME -l fix.log fix + + Where NAME is the name of the disk, like "d1" as in our previous example. + In case the disk to recover is a parity disk, use the "parity", "2-parity" + names. + If you have more broken disks, use multiple -d options to specify all + of them. + + This command will take a long time. + + Take care that you need also few gigabytes free to store the fix.log file. + Run it from a disk with some free space. + + Now you have recovered all the recoverable. If some file is partially or totally + unrecoverable, it will be renamed adding the ".unrecoverable" extension. + + You can get a detailed list of all the unrecoverable blocks in the fix.log file + checking all the lines starting with "unrecoverable:" + + If you are not satisfied of the recovering, you can retry it as many + time you wish. + + For example, if you have removed files from the array after the last + "sync", this may result in some other files not recovered. + In this case, you can retry the "fix" using the -i, --import option, + specifying where these files are now, to include them again in the + recovering process. + + If you are satisfied of the recovering, you can now proceed further, + but take care that after syncing you cannot retry the "fix" command + anymore! + + STEP 3 -> Check + As paranoid check, you can now run a "check" command to ensure that + everything is OK on the recovered disk. + + :snapraid -d NAME -a check + + Where NAME is the name of the disk, like "d1" as in our previous example. + + The options -d and -a tell SnapRAID to check only the specified disk, + and ignore all the parity data. + + This command will take a long time, but if you are not paranoid, + you can skip it. + + STEP 4 -> Sync + Run the "sync" command to re-synchronize the array with the new disk. + + :snapraid sync + + If everything is recovered, this command is immediate. + +Commands + SnapRAID provides a few simple commands that allow to: + + * Prints the status of the array -> "status" + * Controls the disks -> "smart", "up", "down" + * Makes a backup/snapshot -> "sync" + * Periodically checks data -> "scrub" + * Restore the last backup/snapshot -> "fix". + + Take care that the commands have to be written in lower case. + + status + Prints a summary of the state of the disk array. + + It includes information about the parity fragmentation, how old + are the blocks without checking, and all the recorded silent + errors encountered while scrubbing. + + Note that the information presented refers at the latest time you + run "sync". Later modifications are not taken into account. + + If bad blocks were detected, their block numbers are listed. + To fix them, you can use the "fix -e" command. + + It also shows a graph representing the the last time each block + was scrubbed or synced. Scrubbed blocks are shown with '*', + blocks synced but not yet scrubbed with 'o'. + + Nothing is modified. + + smart + Prints a SMART report of all the disks of the array. + + It includes an estimation of the probability of failure in the next + year allowing to plan maintenance replacements of the disks that show + suspicious attributes. + + This probability estimation obtained correlating the SMART attributes + of the disks, with the Backblaze data available at: + + :https://www.backblaze.com/hard-drive-test-data.html + + If SMART reports that a disk is failing, "FAIL" or "PREFAIL" is printed + for that disk, and SnapRAID returns with an error. + In this case an immediate replacement of the disk is highly recommended. + + Other possible strings are: + logfail - In the past some attributes were lower than + the threshold. + logerr - The device error log contains errors. + selferr - The device self-test log contains errors. + + If the -v, --verbose option is specified a deeper statistical analysis + is provided. This analysis can help you to decide if you need more + or less parity. + + This command uses the "smartctl" tool, and it's equivalent to run + "smartctl -a" on all the devices. + + If your devices are not auto-detected correctly, you can configure + a custom command using the "smartctl" option in the configuration + file. + + Nothing is modified. + + up + Spins up all the disks of the array. + + You can spin-up only some specific disks using the -d, --filter-disk option. + + Take care that spinning-up all the disks at the same time needs a lot of power. + Ensure that your power-supply can sustain that. + + Nothing is modified. + + down + Spins down all the disks of the array. + + This command uses the "smartctl" tool, and it's equivalent to run + "smartctl -s standby,now" on all the devices. + + You can spin-down only some specific disks using the -d, --filter-disk option. + + Nothing is modified. + + diff + Lists all the files modified from the last "sync" that need to have + their parity data recomputed. + + This command doesn't check the file data, but only the file time-stamp + size and inode. + + At the end of the command, you'll get a summary of the file changes + grouped by: + equal - Files equal at before. + added - Files added that were not present before. + removed - Files removed. + updated - Files with a different size or time-stamp, meaning that + they were modified. + moved - Files moved to a different directory of the same disk. + They are identified by having the same name, size, time-stamp + and inode, but different directory. + copied - Files copied in the same or different disk. Note that if in + true they are moved to a different disk, you'll also have + them counted in "removed". + They are identified by having the same name, size, and + time-stamp. But if the sub-second time-stamp is zero, + then the full path should match, and not only the name. + restored - Files with a different inode but with name, size and time-stamp + matching. These are usually files restored after being deleted. + + If a "sync" is required, the process return code is 2, instead of the + default 0. The return code 1 is instead for a generic error condition. + + Nothing is modified. + + sync + Updates the parity information. All the modified files + in the disk array are read, and the corresponding parity + data is updated. + + You can stop this process at any time pressing Ctrl+C, + without losing the work already done. + At the next run the "sync" process will start where + interrupted. + + If during the process, silent or input/output errors are found, + the corresponding blocks are marked as bad. + + Files are identified by path and/or inode and checked by + size and time-stamp. + If the file size or time-stamp are different, the parity data + is recomputed for the whole file. + If the file is moved or renamed in the same disk, keeping the + same inode, the parity is not recomputed. + If the file is moved to another disk, the parity is recomputed, + but the previously computed hash information is kept. + + The "content" and "parity" files are modified if necessary. + The files in the array are NOT modified. + + scrub + Scrubs the array, checking for silent or input/output errors in data + and parity disks. + + For each command invocation, about the 8% of the array is checked, but + nothing that was already scrubbed in the last 10 days. + This means that scrubbing once a week, every bit of data is checked + at least one time every three months. + + You can define a different scrub plan or amount using the -p, --plan + option that takes as argument: + bad - Scrub blocks marked bad. + new - Scrub just synced blocks not yet scrubbed. + full - Scrub everything. + 0-100 - Scrub the exact percentage of blocks. + + If you specify a percentage amount, you can also use the -o, --older-than + option to define how old the block should be. + The oldest blocks are scrubbed first ensuring an optimal check. + If instead you want to scrub the just synced blocks, not yet scrubbed, + you should use the "-p new" option. + + To get the details of the scrub status use the "status" command. + + For any silent or input/output error found the corresponding blocks + are marked as bad in the "content" file. + These bad blocks are listed in "status", and can be fixed with "fix -e". + After the fix, at the next scrub they will be rechecked, and if found + corrected, the bad mark will be removed. + To scrub only the bad blocks, you can use the "scrub -p bad" command. + + It's recommended to run "scrub" only on a synced array, to avoid to + have reported error caused by unsynced data. These errors are recognized + as not being silent errors, and the blocks are not marked as bad, + but such errors are reported in the output of the command. + + Files are identified only by path, and not by inode. + + The "content" file is modified to update the time of the last check + of each block, and to mark bad blocks. + The "parity" files are NOT modified. + The files in the array are NOT modified. + + fix + Fix all the files and the parity data. + + All the files and the parity data are compared with the snapshot + state saved in the last "sync". + If a difference is found, it's reverted to the stored snapshot. + + The "fix" command doesn't differentiate between errors and + intentional modifications. It unconditionally reverts the file state + at the last "sync". + + If no other option is specified the full array is processed. + Use the filter options to select a subset of files or disks to operate on. + + To only fix the blocks marked bad during "sync" and "scrub", + use the -e, --filter-error option. + As difference from other filter options, with this one the fixes are + applied only to files that are not modified from the the latest "sync". + + All the files that cannot be fixed are renamed adding the + ".unrecoverable" extension. + + Before fixing, the full array is scanned to find any moved file, + after the last "sync" operation. + These files are identified by their time-stamp, ignoring their name + and directory, and are used in the recovering process if necessary. + If you moved some of them outside the array, you can use the -i, --import + option to specify additional directories to scan. + + Files are identified only by path, and not by inode. + + The "content" file is NOT modified. + The "parity" files are modified if necessary. + The files in the array are modified if necessary. + + check + Verify all the files and the parity data. + + It works like "fix", but it only simulates a recovery and no change + is written in the array. + + This command is mostly intended for manual verification, + like after a recovery process or in other special conditions. + For periodic and scheduled checks uses "scrub". + + If you use the -a, --audit-only option, only the file + data is checked, and the parity data is ignored for a + faster run. + + Files are identified only by path, and not by inode. + + Nothing is modified. + + list + Lists all the files contained in the array at the time of the + last "sync". + + Nothing is modified. + + dup + Lists all the duplicate files. Two files are assumed equal if their + hashes are matching. The file data is not read, but only the + pre-computed hashes are used. + + Nothing is modified. + + pool + Creates or updates in the "pooling" directory a virtual view of all + the files of your disk array. + + The files are not really copied here, but just linked using + symbolic links. + + When updating, all the present symbolic links and empty + sub-directories are deleted and replaced with the new + view of the array. Any other regular file is left in place. + + Nothing is modified outside the pool directory. + + devices + Prints the low level devices used by the array. + + This command prints the devices associations in place in the array, + and it's mainly intended as a script interface. + + The first two columns are the low level device id and path. + The next two columns are the high level device id and path. + The latest column if the disk name in the array. + + In most cases you have one low level device for each disk in the + array, but in some more complex configurations, you may have multiple + low level devices used by a single disk in the array. + + Nothing is modified. + + touch + Sets arbitrarily the sub-second time-stamp of all the files + that have it at zero. + + This improves the SnapRAID capability to recognize moved + and copied files as it makes the time-stamp almost unique, + removing possible duplicates. + + More specifically, if the sub-second time-stamp is not zero, + a moved or copied file is identified as such if it matches + the name, size and time-stamp. If instead the sub-second time-stamp + is zero, it's considered a copy only if it matches the full path, + size and time-stamp. + + Note that the second precision time-stamp is not modified, + and all the dates and times of your files will be maintained. + + rehash + Schedules a rehash of the whole array. + + This command changes the hash kind used, typically when upgrading + from a 32 bits system to a 64 bits one, to switch from + MurmurHash3 to the faster SpookyHash. + + If you are already using the optimal hash, this command + does nothing and tells you that nothing has to be done. + + The rehash isn't done immediately, but it takes place + progressively during "sync" and "scrub". + + You can get the rehash state using "status". + + During the rehash, SnapRAID maintains full functionality, + with the only exception of "dup" not able to detect duplicated + files using a different hash. + +Options + SnapRAID provides the following options: + + -c, --conf CONFIG + Selects the configuration file to use. If not specified in Unix + it's used the file "/usr/local/etc/snapraid.conf" if it exists, + or "/etc/snapraid.conf" otherwise. + In Windows it's used the file "snapraid.conf" in the same + directory of "snapraid.exe". + + -f, --filter PATTERN + Filters the files to process in "check" and "fix". + Only the files matching the entered pattern are processed. + This option can be used many times. + See the PATTERN section for more details in the + pattern specifications. + In Unix, ensure to quote globbing chars if used. + This option can be used only with "check" and "fix". + Note that it cannot be used with "sync" and "scrub", because they always + process the whole array. + + -d, --filter-disk NAME + Filters the disks to process in "check", "fix", "up" and "down". + You must specify a disk name as named in the configuration + file. + You can also specify parity disks with the names: "parity", "2-parity", + "3-parity", ... to limit the operations a specific parity disk. + If you combine more --filter, --filter-disk and --filter-missing options, + only files matching all the set of filters are selected. + This option can be used many times. + This option can be used only with "check", "fix", "up" and "down". + Note that it cannot be used with "sync" and "scrub", because they always + process the whole array. + + -m, --filter-missing + Filters the files to process in "check" and "fix". + Only the files missing/deleted from the array are processed. + When used with "fix", this is a kind of "undelete" command. + If you combine more --filter, --filter-disk and --filter-missing options, + only files matching all the set of filters are selected. + This option can be used only with "check" and "fix". + Note that it cannot be used with "sync" and "scrub", because they always + process the whole array. + + -e, --filter-error + Filters the blocks to process in "check" and "fix". + It processes only the blocks marked with silent or input/output + errors during "sync" and "scrub", and listed in "status". + This option can be used only with "check" and "fix". + + -p, --plan PERC|bad|new|full + Selects the scrub plan. If PERC is a numeric value from 0 to 100, + it's interpreted as the percentage of blocks to scrub. + Instead of a percentage, you can also specify a plan: + "bad" scrubs bad blocks, "new" the blocks not yet scrubbed, + and "full" for everything. + This option can be used only with "scrub". + + -o, --older-than DAYS + Selects the older the part of the array to process in "scrub". + DAYS is the minimum age in days for a block to be scrubbed, + default is 10. + Blocks marked as bad are always scrubbed despite this option. + This option can be used only with "scrub". + + -a, --audit-only + In "check" verifies the hash of the files without + doing any kind of check on the parity data. + If you are interested in checking only the file data this + option can speedup a lot the checking process. + This option can be used only with "check". + + -h, --pre-hash + In "sync" runs a preliminary hashing phase of all the new data + to have an additional verification before the parity computation. + Usually in "sync" no preliminary hashing is done, and the new + data is hashed just before the parity computation when it's read + for the first time. + Unfortunately, this process happens when the system is under + heavy load, with all disks spinning and with a busy CPU. + This is an extreme condition for the machine, and if it has a + latent hardware problem, it's possible to encounter silent errors + what cannot be detected because the data is not yet hashed. + To avoid this risk, you can enable the "pre-hash" mode and have + all the data read two times to ensure its integrity. + This option also verifies the files moved inside the array, + to ensure that the move operation went successfully, and in case + to block the sync and to allow to run a fix operation. + This option can be used only with "sync". + + -i, --import DIR + Imports from the specified directory any file that you deleted + from the array after the last "sync". + If you still have such files, they could be used by "check" + and "fix" to improve the recover process. + The files are read also in sub-directories and they are + identified regardless of their name. + This option can be used only with "check" and "fix". + + -Z, --force-zero + Forces the insecure operation of syncing a file with zero + size that before was not. + If SnapRAID detects a such condition, it stops proceeding + unless you specify this option. + This allows to easily detect when after a system crash, + some accessed files were truncated. + This is a possible condition in Linux with the ext3/ext4 + file-systems. + This option can be used only with "sync". + + -E, --force-empty + Forces the insecure operation of syncing a disk with all + the original files missing. + If SnapRAID detects that all the files originally present + in the disk are missing or rewritten, it stops proceeding + unless you specify this option. + This allows to easily detect when a data file-system is not + mounted. + This option can be used only with "sync". + + -U, --force-uuid + Forces the insecure operation of syncing, checking and fixing + with disks that have changed their UUID. + If SnapRAID detects that some disks have changed UUID, + it stops proceeding unless you specify this option. + This allows to detect when your disks are mounted in the + wrong mount points. + It's anyway allowed to have a single UUID change with + single parity, and more with multiple parity, because it's + the normal case of replacing disks after a recovery. + This option can be used only with "sync", "check" or + "fix". + + -D, --force-device + Forces the insecure operation of fixing with inaccessible disks, + or with disks on the same physical device. + Like if you lost two data disks, and you have a spare disk to recover + only the first one, and you want to ignore the second inaccessible disk. + Or if you want to recover a disk in the free space left in an + already used disk, sharing the same physical device. + This option can be used only with "fix". + + -N, --force-nocopy + In "sync", "check and "fix", disables the copy detection heuristic. + Without this option SnapRAID assumes that files with same + attributes, like name, size and time-stamp are copies with the + same data. + This allows to identify copied or moved files from one disk + to another, and to reuse the already computed hash information + to detect silent errors or to recover missing files. + This behavior, in some rare cases, may result in false positives, + or in a slow process due the many hash verification, and this + option allows to resolve them. + This option can be used only with "sync", "check" and "fix". + + -F, --force-full + In "sync" forces a full rebuild of the parity. + This option can be used when you add a new parity level, or if + you reverted back to an old content file using a more recent parity data. + Instead of recomputing the parity from scratch, this allows + to reuse the hashes present in the content file to validate data, + and to maintain data protection during the "sync" process using + the parity data you have. + This option can be used only with "sync". + + -R, --force-realloc + In "sync" forces a full reallocation of files and rebuild of the parity. + This option can be used to completely reallocate all the files + removing the fragmentation, but reusing the hashes present in the content + file to validate data. + Compared to -F, --force-full, this option reallocates all the parity + not having data protection during the operation. + This option can be used only with "sync". + + -l, --log FILE + Write a detailed log in the specified file. + If this option is not specified, unexpected errors are printed + on the screen, likely resulting in too much output in case of + many errors. When -l, --log is specified, on the screen, go only + fatal errors that makes SnapRAID to stop progress. + If the path starts with '>>' the file is opened + in append mode. Occurrences of '%D' and '%T' in the name are + replaced with the date and time in the format YYYYMMDD and + HHMMSS. Note that in Windows batch files, you'll have to double + the '%' char, like result-%%D.log. And to use '>>' you'll have + to enclose the name in ", like ">>result.log". + To output the log to standard output or standard error, + you can use respectively ">&1" and ">&2". + + -L, --error-limit + Sets a new error limit before stopping execution. + By default SnapRAID stops if it encounters more than 100 + Input/Output errors, meaning that likely a disk is going to + die. + This options affects "sync" and "scrub", that are allowed + to continue after the first bunch of disk errors, to try + to complete at most their operations. + Instead, "check" and "fix" always stop at the first error. + + -S, --start BLKSTART + Starts the processing from the specified + block number. It could be useful to retry to check + or fix some specific block, in case of a damaged disk. + It's present mainly for advanced manual recovering. + + -B, --count BLKCOUNT + Processes only the specified number of blocks. + It's present mainly for advanced manual recovering. + + -C, --gen-conf CONTENT_FILE + Generates a dummy configuration file from an existing + content file. + The configuration file is written in the standard output, + and it doesn't overwrite an existing one. + This configuration file also contains the information + needed to reconstruct the disk mount points, in case you + lose the entire system. + + -v, --verbose + Prints more information on the screen. + If specified one time, it prints excluded files + and more stats. + This option has no effect on the log files. + + -q, --quiet + Prints less information on the screen. + If specified one time, removes the progress bar, if two + times, the running operations, three times, the info + messages, four times the status messages. + Fatal errors are always printed on the screen. + This option has no effect on the log files. + + -H, --help + Prints a short help screen. + + -V, --version + Prints the program version. + +Configuration + SnapRAID requires a configuration file to know where your disk array + is located, and where storing the parity information. + + In Unix it's used the file "/usr/local/etc/snapraid.conf" if it exists, + or "/etc/snapraid.conf" otherwise. + In Windows it's used the file "snapraid.conf" in the same + directory of "snapraid.exe". + + It should contain the following options (case sensitive): + + parity FILE [,FILE] ... + Defines the files to use to store the parity information. + The parity enables the protection from a single disk + failure, like RAID5. + + You can specify multiples files that should be in different disks. + When a file cannot grow anymore, the next one is used. + The total space available must be as big as the biggest data disk in + the array. + + You can add additional parity files at later time, but you + cannot reorder or remove them. + + Leaving the parity disks reserved for parity ensures that + it doesn't get fragmented, improving the performance. + + In Windows 256 MB are left unused in each disk to avoid the + warning about full disks. + + This option is mandatory and it can be used only one time. + + (2,3,4,5,6)-parity FILE [,FILE] ... + Defines the files to use to store extra parity information. + + For each parity specified, one additional level of protection + is enabled: + + * 2-parity enables RAID6 dual parity. + * 3-parity enables triple parity + * 4-parity enables quad (four) parity + * 5-parity enables penta (five) parity + * 6-parity enables hexa (six) parity + + Each parity level requires the presence of all the previous parity + levels. + + The same considerations of the 'parity' option apply. + + These options are optional and they can be used only one time. + + z-parity FILE [,FILE] ... + Defines an alternate file and format to store the triple parity. + + This option is an alternative at '3-parity' mainly intended for + low-end CPUs like ARM or AMD Phenom, Athlon and Opteron that don't + support the SSSE3 instructions set. In such cases it provides + a better performance. + + This format is similar, but faster, at the one used by the ZFS RAIDZ3. + Like ZFS, it doesn't work beyond triple parity. + + When using '3-parity' you will be warned if it's recommended to use + the 'z-parity' format for a performance improvement. + + It's possible to convert from one format to another, adjusting + the configuration file with the wanted z-parity or 3-parity file, + and using 'fix' to recreate it. + + content FILE + Defines the file to use to store the list and check-sums of all the + files present in your disk array. + + It can be placed in the disk used to store data, parity, or + any other disk available. + If you use a data disk, this file is automatically excluded + from the "sync" process. + + This option is mandatory and it can be used more times to save + more copies of the same files. + + You have to store at least one copy for each parity disk used + plus one. Using some more doesn't hurt. + + data NAME DIR + Defines the name and the mount point of the data disks of + the array. NAME is used to identify the disk, and it must + be unique. DIR is the mount point of the disk in the + file-system. + + You can change the mount point as you like, as long you + keep the NAME fixed. + + You should use one option for each data disk of the array. + + You can rename later a disk, changing the NAME directly + in the configuration file, and then run a 'sync' command. + In the rename case, the association is done using the stored + UUID of the disks. + + nohidden + Excludes all the hidden files and directory. + In Unix hidden files are the ones starting with ".". + In Windows they are the ones with the hidden attribute. + + exclude/include PATTERN + Defines the file or directory patterns to exclude and include + in the sync process. + All the patterns are processed in the specified order. + + If the first pattern that matches is an "exclude" one, the file + is excluded. If it's an "include" one, the file is included. + If no pattern matches, the file is excluded if the last pattern + specified is an "include", or included if the last pattern + specified is an "exclude". + + See the PATTERN section for more details in the pattern + specifications. + + This option can be used many times. + + blocksize SIZE_IN_KIBIBYTES + Defines the basic block size in kibi bytes of the parity. + One kibi bytes is 1024 bytes. + + The default blocksize is 256 and it should work for most cases. + + WARNING! This option is for experts only, and it's highly + recommended to not change it. To change again this value in + future you'll have to recreate the whole parity! + + A reason to use a different hashsize is if you have a lot of small + files. In the order of many millions. + + For each file, even of few bytes, a whole block of parity is allocated, + and with many files this may result in a lot of unused parity space. + And when you completely fill the parity disk, you are not + allowed to add more files in the data disks. + Anyway, the wasted parity doesn't sum between data disks. Wasted space + resulting from a high number of files in a data disk, limits only + the amount of data in such data disk and not in others. + + As approximation, you can assume that half of the block size is + wasted for each file. For example, with 100000 files and a 256 KiB + block size, you are going to waste 13 GB of parity, that may result + in 13 GB less space available in the data disk. + + You can get the amount of wasted space in each disk using "status". + This is the amount of space that you must leave free in the data + disks, or use for files not included in the array. + If this value is negative, it means that your are near to fill + the parity, and it represents the space you can still waste. + + To avoid the problem, you can use a bigger partition for parity. + For example, if you have the parity partition bigger than 13 GB + than data disks, you have enough extra space to handle up to 100000 + files in each data disk. + + A trick to get a bigger parity partition in Linux, is to format it + with the command: + + :mkfs.ext4 -m 0 -T largefile4 DEVICE + + This results in about 1.5% of extra space. Meaning about 60 GB for + a 4 TB disk, that allows about 460000 files in each data disk without + any wasted space. + + hashsize SIZE_IN_BYTES + Defines the hash size in bytes of the saved blocks. + + The default hashsize is 16 bytes (128 bits), and it should work + for most cases. + + WARNING! This option is for experts only, and it's highly + recommended to not change it. To change again this value in + future you'll have to recreate the whole parity! + + A reason to use a different hashsize is if your system has + small memory. As a rule of thumb SnapRAID usually requires + 1 GiB of RAM memory for each 16 TB of data in the array. + + Specifically, to store the hashes of the data, SnapRAID requires + about TS*(1+HS)/BS bytes of RAM memory. + Where TS is the total size in bytes of your disk array, BS is the + block size in bytes, and HS is the hash size in bytes. + + For example with 8 disks of 4 TB and a block size of 256 KiB + (1 KiB = 1024 bytes), and an hash size of 16, you get: + + :RAM = (8 * 4 * 10^12) * (1+16) / (256 * 2^10) = 1.93 GiB + + Switching to a hash size of 8, you get: + + :RAM = (8 * 4 * 10^12) * (1+8) / (256 * 2^10) = 1.02 GiB + + Switching to a block size of 512, you get: + + :RAM = (8 * 4 * 10^12) * (1+16) / (512 * 2^10) = 0.96 GiB + + Switching to both a hash size of 8, and a block size of 512 you get: + + :RAM = (8 * 4 * 10^12) * (1+8) / (512 * 2^10) = 0.51 GiB + + autosave SIZE_IN_GIGABYTES + Automatically save the state when syncing or scrubbing after the specified amount + of GB processed. + This option is useful to avoid to restart from scratch long "sync" + commands interrupted by a machine crash, or any other event that + may interrupt SnapRAID. + + pool DIR + Defines the pooling directory where the virtual view of the disk + array is created using the "pool" command. + + The directory must already exist. + + share UNC_DIR + Defines the Windows UNC path required to access the disks remotely. + + If this option is specified, the symbolic links created in the pool + directory use this UNC path to access the disks. + Without this option the symbolic links generated use only local paths, + not allowing to share the pool directory in the network. + + The symbolic links are formed using the specified UNC path, adding the + disk name as specified in the "disk" option, and finally adding the + file dir and name. + + This option is only required for Windows. + + smartctl DISK/PARITY OPTIONS... + Defines a custom smartctl command to obtain the SMART attributes + for each disk. This may be required for RAID controllers and for + some USB disk that cannot be auto-detected. + + DISK is the same disk name specified in the "disk" option. + PARITY is one of the parity name as "parity,(1,2,3,4,5,6,z)-parity". + + In the specified OPTIONS, the "%s" string is replaced by the + device name. Note that in case of RAID controllers the device is likely + fixed, and you don't have to use "%s". + + Refers at the smartmontools documentation about the possible options: + + :https://www.smartmontools.org/wiki/Supported_RAID-Controllers + :https://www.smartmontools.org/wiki/Supported_USB-Devices + + Examples + An example of a typical configuration for Unix is: + + :parity /mnt/diskp/snapraid.parity + :content /mnt/diskp/snapraid.content + :content /var/snapraid/snapraid.content + :data d1 /mnt/disk1/ + :data d2 /mnt/disk2/ + :data d3 /mnt/disk3/ + :exclude /lost+found/ + :exclude /tmp/ + :smartctl d1 -d sat %s + :smartctl d2 -d usbjmicron %s + :smartctl parity -d areca,1/1 /dev/sg0 + :smartctl 2-parity -d areca,2/1 /dev/sg0 + + An example of a typical configuration for Windows is: + + :parity E:\snapraid.parity + :content E:\snapraid.content + :content C:\snapraid\snapraid.content + :data d1 G:\array\ + :data d2 H:\array\ + :data d3 I:\array\ + :exclude Thumbs.db + :exclude \$RECYCLE.BIN + :exclude \System Volume Information + :smartctl d1 -d sat %s + :smartctl d2 -d usbjmicron %s + :smartctl parity -d areca,1/1 /dev/arcmsr0 + :smartctl 2-parity -d areca,2/1 /dev/arcmsr0 + +Pattern + Patterns are used to select a subset of files to exclude or include in + the process. + + There are four different types of patterns: + + =FILE + Selects any file named as FILE. You can use any globbing + character like * and ?, and char classes like [a-z]. + This pattern is applied only to files and not to directories. + + =DIR/ + Selects any directory named DIR and everything inside. + You can use any globbing character like * and ?. + This pattern is applied only to directories and not to files. + + =/PATH/FILE + Selects the exact specified file path. You can use any + globbing character like * and ? but they never match a + directory slash. + This pattern is applied only to files and not to directories. + + =/PATH/DIR/ + Selects the exact specified directory path and everything + inside. You can use any globbing character like * and ? but + they never match a directory slash. + This pattern is applied only to directories and not to files. + + Note that when you specify an absolute path starting with /, it's + applied at the array root dir and not at the local file-system root dir. + + In Windows you can use the backslash \ instead of the forward slash /. + Note that Windows system directories, junctions, mount points, and any + other Windows special directory are treated just as files, meaning that + to exclude them you must use a file rule, and not a directory one. + + If the file name you want to use really contains a '*', '?', '[', + or ']' char, you have to escape it to avoid to have interpreted as a + globbing character. In Unix the escape char is '\', in Windows it's '^'. + Note that when the pattern is on the command line, you have to double the + escape character to avoid to have it interpreted by the command shell. + + In the configuration file, you can use different strategies to filter + the files to process. + The simplest one is to use only "exclude" rules to remove all the + files and directories you do not want to process. For example: + + :# Excludes any file named "*.unrecoverable" + :exclude *.unrecoverable + :# Excludes the root directory "/lost+found" + :exclude /lost+found/ + :# Excludes any sub-directory named "tmp" + :exclude tmp/ + + The opposite way is to define only the file you want to process, using + only "include" rules. For example: + + :# Includes only some directories + :include /movies/ + :include /musics/ + :include /pictures/ + + The final way, is to mix "exclude" and "include" rules. In this case take + care that the order of rules is important. Previous rules have the + precedence over the later ones. + To get things simpler you can first have all the "exclude" rules and then + all the "include" ones. For example: + + :# Excludes any file named "*.unrecoverable" + :exclude *.unrecoverable + :# Excludes any sub-directory named "tmp" + :exclude tmp/ + :# Includes only some directories + :include /movies/ + :include /musics/ + :include /pictures/ + + On the command line, using the -f option, you can only use "include" + patterns. For example: + + :# Checks only the .mp3 files. + :# Note the "" use to avoid globbing expansion by the shell in Unix. + :snapraid -f "*.mp3" check + + In Unix, when using globbing chars in the command line, you have to + quote them. Otherwise the shell will try to expand them. + +Content + SnapRAID stores the list and check-sums of your files in the content file. + + It's a binary file, listing all the files present in your disk array, + with all the check-sums to verify their integrity. + + This file is read and written by the "sync" and "scrub" commands, and + read by "fix", "check" and "status". + +Parity + SnapRAID stores the parity information of your array in the parity + files. + + They are binary files, containing the computed parity of all the + blocks defined in the "content" file. + + These files are read and written by the "sync" and "fix" commands, and + only read by "scrub" and "check". + +Encoding + SnapRAID in Unix ignores any encoding. It reads and stores the + file names with the same encoding used by the file-system. + + In Windows all the names read from the file-system are converted and + processed in the UTF-8 format. + + To have the file names printed correctly you have to set the Windows + console in the UTF-8 mode, with the command "chcp 65001", and use + a TrueType font like "Lucida Console" as console font. + Note that it has effect only on the printed file names, if you + redirect the console output to a file, the resulting file is always + in the UTF-8 format. + +Copyright + This file is Copyright (C) 2011 Andrea Mazzoleni + +See Also + rsync(1) + diff --git a/snapraid.txt b/snapraid.txt new file mode 100644 index 0000000..863d8c6 --- /dev/null +++ b/snapraid.txt @@ -0,0 +1,1441 @@ + =============================== + SnapRAID Backup For Disk Arrays + =============================== + + +1 SYNOPSIS +========== + +snapraid [-c, --conf CONFIG] + [-f, --filter PATTERN] [-d, --filter-disk NAME] + [-m, --filter-missing] [-e, --filter-error] + [-a, --audit-only] [-h, --pre-hash] [-i, --import DIR] + [-p, --plan PERC|bad|new|full] + [-o, --older-than DAYS] [-l, --log FILE] + [-Z, --force-zero] [-E, --force-empty] + [-U, --force-uuid] [-D, --force-device] + [-N, --force-nocopy] [-F, --force-full] + [-R, --force-realloc] + [-S, --start BLKSTART] [-B, --count BLKCOUNT] + [-L, --error-limit NUMBER] + [-v, --verbose] [-q, --quiet] + status|smart|up|down|diff|sync|scrub|fix|check|list|dup + |pool|devices|touch|rehash + +snapraid [-V, --version] [-H, --help] [-C, --gen-conf CONTENT] + + +2 DESCRIPTION +============= + +SnapRAID is a backup program for disk arrays. It stores parity +information of your data and it recovers from up to six disk +failures. + +SnapRAID is mainly targeted for a home media center, with a lot of +big files that rarely change. + +Beside the ability to recover from disk failures, other +features of SnapRAID are: + +* All your data is hashed to ensure data integrity and to avoid + silent corruption. +* If the failed disks are too many to allow a recovery, + you lose the data only on the failed disks. + All the data in the other disks is safe. +* If you accidentally delete some files in a disk, you can + recover them. +* You can start with already filled disks. +* The disks can have different sizes. +* You can add disks at any time. +* It doesn't lock-in your data. You can stop using SnapRAID at any + time without the need to reformat or move data. +* To access a file, a single disk needs to spin, saving power and + producing less noise. + +The official site of SnapRAID is: + + http://www.snapraid.it/ + + +3 LIMITATIONS +============= + +SnapRAID is in between a RAID and a Backup program trying to get the best +benefits of them. Although it also has some limitations that you should +consider before using it. + +The main one is that if a disk fails, and you haven't recently synced, +you may be unable to do a complete recover. +More specifically, you may be unable to recover up to the size of the +amount of the changed or deleted files from the last sync operation. +This happens even if the files changed or deleted are not in the +failed disk. This is the reason because SnapRAID is better suited for +data that rarely change. + +Instead the new added files don't prevent the recovering of the already +existing files. You may only lose the just added files, if they are on +the failed disk. + +Other limitations are: + +* You have different file-systems for each disk. + Using a RAID you have only a big file-system. +* It doesn't stripe data. + With RAID you get a speed boost with striping. +* It doesn't support real-time recovery. + With RAID you do not have to stop working when a disk fails. +* It's able to recover damages only from a limited number of disks. + With a Backup you are able to recover from a complete + failure of the whole disk array. +* Only file, time-stamps, symlinks and hardlinks are saved. + Permissions, ownership and extended attributes are not saved. + + +4 GETTING STARTED +================= + +To use SnapRAID you need to first select one disk of your disk array +to dedicate at the "parity" information. With one disk for parity you +will be able to recover from a single disk failure, like RAID5. + +If you want to be able to recover from more disk failures, like RAID6, +you must reserve additional disks for parity. Any additional parity +disk allow to recover from one more disk failure. + +As parity disks, you have to pick the biggest disks in the array, +as the parity information may grow in size as the biggest data +disk in the array. + +These disks will be dedicated to store the "parity" files. +You should not store your data in them. + +Then you have to define the "data" disks that you want to protect +with SnapRAID. The protection is more effective if these disks +contain data that rarely change. For this reason it's better to +DO NOT include the Windows C:\ disk, or the Unix /home, /var and /tmp +disks. + +The list of files is saved in the "content" files, usually +stored in the data, parity or boot disks. +These files contain the details of your backup, with all the +check-sums to verify its integrity. +The "content" file is stored in multiple copies, and each one must +be in a different disk, to ensure that in even in case of multiple +disk failures at least one copy is available. + +For example, suppose that you are interested only at one parity level +of protection, and that your disks are present in: + + /mnt/diskp <- selected disk for parity + /mnt/disk1 <- first disk to protect + /mnt/disk2 <- second disk to protect + /mnt/disk3 <- third disk to protect + +you have to create the configuration file /etc/snapraid.conf with +the following options: + + parity /mnt/diskp/snapraid.parity + content /var/snapraid/snapraid.content + content /mnt/disk1/snapraid.content + content /mnt/disk2/snapraid.content + data d1 /mnt/disk1/ + data d2 /mnt/disk2/ + data d3 /mnt/disk3/ + +If you are in Windows, you should use the Windows path format, with drive +letters and backslashes instead of slashes. + + parity E:\snapraid.parity + content C:\snapraid\snapraid.content + content F:\array\snapraid.content + content G:\array\snapraid.content + data d1 F:\array\ + data d2 G:\array\ + data d3 H:\array\ + +If you have many disks, and you run out of drive letters, you can mount +disks directly in sub folders. See: + + https://www.google.com/search?q=Windows+mount+point + +At this point you are ready to start the "sync" command to build the +parity information. + + snapraid sync + +This process may take some hours the first time, depending on the size +of the data already present in the disks. If the disks are empty +the process is immediate. + +You can stop it at any time pressing Ctrl+C, and at the next run it +will start where interrupted. + +When this command completes, your data is SAFE. + +Now you can start using your array as you like, and periodically +update the parity information running the "sync" command. + +4.1 Scrubbing +------------- + +To periodically check the data and parity for errors, you can +run the "scrub" command. + + snapraid scrub + +This command verifies the data in your array comparing it with +the hash computed in the "sync" command. + +Every run of the command checks about the 8% of the array, but not data +already scrubbed in the previous 10 days. +You can use the -p, --plan option to specify a different amount, +and the -o, --older-than option to specify a different age in days. +For example, to check 5% of the array older than 20 days use: + + snapraid -p 5 -o 20 scrub + +If during the process, silent or input/output errors are found, +the corresponding blocks are marked as bad in the "content" file, +and listed in the "status" command. + + snapraid status + +To fix them, you can use the "fix" command filtering for bad blocks with +the -e, --filter-error options: + + snapraid -e fix + +At the next "scrub" the errors will disappear from the "status" report +if really fixed. To make it fast, you can use -p bad to scrub only blocks +marked as bad. + + snapraid -p bad scrub + +Take care that running "scrub" on a not synced array may result in +errors caused by removed or modified files. These errors are reported +in the "scrub" result, but related blocks are not marked as bad. + +4.2 Pooling +----------- + +To have all the files in your array shown in the same directory tree, +you can enable the "pooling" feature. It consists in creating a +read-only virtual view of all the files in your array using symbolic +links. + +You can configure the "pooling" directory in the configuration file with: + + pool /pool + +or, if you are in Windows, with: + + pool C:\pool + +and then run the "pool" command to create or update the virtual view. + + snapraid pool + +If you are using a Unix platform and you want to share such directory +in the network to either Windows or Unix machines, you should add +to your /etc/samba/smb.conf the following options: + + # In the global section of smb.conf + unix extensions = no + + # In the share section of smb.conf + [pool] + comment = Pool + path = /pool + read only = yes + guest ok = yes + wide links = yes + follow symlinks = yes + +In Windows the same sharing operation is not so straightforward, +because Windows shares the symbolic links as they are, and that +requires the network clients to resolve them remotely. + +To make it working, besides sharing in the network the pool directory, +you must also share all the disks independently, using as share points +the disk names as defined in the configuration file. You must also specify in +the "share" option of the configure file, the Windows UNC path that remote +clients needs to use to access such shared disks. + +For example, operating from a server named "darkstar", you can use +the options: + + data d1 F:\array\ + data d2 G:\array\ + data d3 H:\array\ + pool C:\pool + share \\darkstar + +and share the following dirs in the network: + + \\darkstar\pool -> C:\pool + \\darkstar\d1 -> F:\array + \\darkstar\d2 -> G:\array + \\darkstar\d3 -> H:\array + +to allow remote clients to access all the files at \\darkstar\\pool. + +You may also need to configure remote clients enabling access at remote +symlinks with the command: + + fsutil behavior set SymlinkEvaluation L2L:1 R2R:1 L2R:1 R2L:1 + +4.3 Undeleting +-------------- + +SnapRAID is more like a backup program than a RAID system, and it +can be used to restore or undelete files to their previous state using +the -f, --filter option : + + snapraid fix -f FILE + +or for a directory: + + snapraid fix -f DIR/ + +You can also use it to recover only accidentally deleted files inside +a directory using the -m, --filter-missing option, that restores +only missing files, leaving untouched all the others. + + snapraid fix -m -f DIR/ + +Or to recover all the deleted files in all the drives with: + + snapraid fix -m + +4.4 Recovering +-------------- + +The worst happened, and you lost one or more disks! + +DO NOT PANIC! You will be able to recover them! + +The first thing you have to do is to avoid further changes at your disk array. +Disable any remote connection to it, any scheduled process, including any +scheduled SnapRAID nightly sync or scrub. + +Then proceed with the following steps. + +---- 4.4.1 STEP 1 -> Reconfigure ---- +You need some space to recover, even better if you already have additional +spare disks, but in case, also an external USB or remote disk is enough. + +Change the SnapRAID configuration file to make the "data" or "parity" +option of the failed disk to point to the place where you have enough empty +space to recover the files. + +For example, if you have that disk "d1" failed, you can change from: + + data d1 /mnt/disk1/ + +to: + + data d1 /mnt/new_spare_disk/ + +If the disk to recover is a parity disk, change the appropriate "parity" +option. +If you have more broken disks, change all their configuration options. + +---- 4.4.2 STEP 2 -> Fix ---- +Run the fix command, storing the log in an external file with: + + snapraid -d NAME -l fix.log fix + +Where NAME is the name of the disk, like "d1" as in our previous example. +In case the disk to recover is a parity disk, use the "parity", "2-parity" +names. +If you have more broken disks, use multiple -d options to specify all +of them. + +This command will take a long time. + +Take care that you need also few gigabytes free to store the fix.log file. +Run it from a disk with some free space. + +Now you have recovered all the recoverable. If some file is partially or totally +unrecoverable, it will be renamed adding the ".unrecoverable" extension. + +You can get a detailed list of all the unrecoverable blocks in the fix.log file +checking all the lines starting with "unrecoverable:" + +If you are not satisfied of the recovering, you can retry it as many +time you wish. + +For example, if you have removed files from the array after the last +"sync", this may result in some other files not recovered. +In this case, you can retry the "fix" using the -i, --import option, +specifying where these files are now, to include them again in the +recovering process. + +If you are satisfied of the recovering, you can now proceed further, +but take care that after syncing you cannot retry the "fix" command +anymore! + +---- 4.4.3 STEP 3 -> Check ---- +As paranoid check, you can now run a "check" command to ensure that +everything is OK on the recovered disk. + + snapraid -d NAME -a check + +Where NAME is the name of the disk, like "d1" as in our previous example. + +The options -d and -a tell SnapRAID to check only the specified disk, +and ignore all the parity data. + +This command will take a long time, but if you are not paranoid, +you can skip it. + +---- 4.4.4 STEP 4 -> Sync ---- +Run the "sync" command to resynchronize the array with the new disk. + + snapraid sync + +If everything is recovered, this command is immediate. + + +5 COMMANDS +========== + +SnapRAID provides a few simple commands that allow to: + +* Prints the status of the array -> "status" +* Controls the disks -> "smart", "up", "down" +* Makes a backup/snapshot -> "sync" +* Periodically checks data -> "scrub" +* Restore the last backup/snapshot -> "fix". + +Take care that the commands have to be written in lower case. + +5.1 status +---------- + +Prints a summary of the state of the disk array. + +It includes information about the parity fragmentation, how old +are the blocks without checking, and all the recorded silent +errors encountered while scrubbing. + +Note that the information presented refers at the latest time you +run "sync". Later modifications are not taken into account. + +If bad blocks were detected, their block numbers are listed. +To fix them, you can use the "fix -e" command. + +It also shows a graph representing the the last time each block +was scrubbed or synced. Scrubbed blocks are shown with '*', +blocks synced but not yet scrubbed with 'o'. + +Nothing is modified. + +5.2 smart +--------- + +Prints a SMART report of all the disks of the array. + +It includes an estimation of the probability of failure in the next +year allowing to plan maintenance replacements of the disks that show +suspicious attributes. + +This probability estimation obtained correlating the SMART attributes +of the disks, with the Backblaze data available at: + + https://www.backblaze.com/hard-drive-test-data.html + +If SMART reports that a disk is failing, "FAIL" or "PREFAIL" is printed +for that disk, and SnapRAID returns with an error. +In this case an immediate replacement of the disk is highly recommended. + +Other possible strings are: + logfail - In the past some attributes were lower than + the threshold. + logerr - The device error log contains errors. + selferr - The device self-test log contains errors. + +If the -v, --verbose option is specified a deeper statistical analysis +is provided. This analysis can help you to decide if you need more +or less parity. + +This command uses the "smartctl" tool, and it's equivalent to run +"smartctl -a" on all the devices. + +If your devices are not auto-detected correctly, you can configure +a custom command using the "smartctl" option in the configuration +file. + +Nothing is modified. + +5.3 up +------ + +Spins up all the disks of the array. + +You can spin-up only some specific disks using the -d, --filter-disk option. + +Take care that spinniup-up all the disks at the same time needs a lot of power. +Ensure that your power-supply can sustain that. + +Nothing is modified. + +5.4 down +-------- + +Spins down all the disks of the array. + +This command uses the "smartctl" tool, and it's equivalent to run +"smartctl -s standby,now" on all the devices. + +You can spin-down only some specific disks using the -d, --filter-disk option. + +Nothing is modified. + +5.5 diff +-------- + +Lists all the files modified from the last "sync" that need to have +their parity data recomputed. + +This command doesn't check the file data, but only the file time-stamp +size and inode. + +At the end of the command, you'll get a summary of the file changes +grouped by: + equal - Files equal at before. + added - Files added that were not present before. + removed - Files removed. + updated - Files with a different size or time-stamp, meaning that + they were modified. + moved - Files moved to a different directory of the same disk. + They are identified by having the same name, size, time-stamp + and inode, but different directory. + copied - Files copied in the same or different disk. Note that if in + true they are moved to a different disk, you'll also have + them counted in "removed". + They are identified by having the same name, size, and + time-stamp. But if the sub-second time-stamp is zero, + then the full path should match, and not only the name. + restored - Files with a different inode but with name, size and time-stamp + matching. These are usually files restored after being deleted. + +If a "sync" is required, the process return code is 2, instead of the +default 0. The return code 1 is instead for a generic error condition. + +Nothing is modified. + +5.6 sync +-------- + +Updates the parity information. All the modified files +in the disk array are read, and the corresponding parity +data is updated. + +You can stop this process at any time pressing Ctrl+C, +without losing the work already done. +At the next run the "sync" process will start where +interrupted. + +If during the process, silent or input/output errors are found, +the corresponding blocks are marked as bad. + +Files are identified by path and/or inode and checked by +size and time-stamp. +If the file size or time-stamp are different, the parity data +is recomputed for the whole file. +If the file is moved or renamed in the same disk, keeping the +same inode, the parity is not recomputed. +If the file is moved to another disk, the parity is recomputed, +but the previously computed hash information is kept. + +The "content" and "parity" files are modified if necessary. +The files in the array are NOT modified. + +5.7 scrub +--------- + +Scrubs the array, checking for silent or input/output errors in data +and parity disks. + +For each command invocation, about the 8% of the array is checked, but +nothing that was already scrubbed in the last 10 days. +This means that scrubbing once a week, every bit of data is checked +at least one time every three months. + +You can define a different scrub plan or amount using the -p, --plan +option that takes as argument: +bad - Scrub blocks marked bad. +new - Scrub just synced blocks not yet scrubbed. +full - Scrub everything. +0-100 - Scrub the exact percentage of blocks. + +If you specify a percentage amount, you can also use the -o, --older-than +option to define how old the block should be. +The oldest blocks are scrubbed first ensuring an optimal check. +If instead you want to scrub the just synced blocks, not yet scrubbed, +you should use the "-p new" option. + +To get the details of the scrub status use the "status" command. + +For any silent or input/output error found the corresponding blocks +are marked as bad in the "content" file. +These bad blocks are listed in "status", and can be fixed with "fix -e". +After the fix, at the next scrub they will be rechecked, and if found +corrected, the bad mark will be removed. +To scrub only the bad blocks, you can use the "scrub -p bad" command. + +It's recommended to run "scrub" only on a synced array, to avoid to +have reported error caused by unsynced data. These errors are recognized +as not being silent errors, and the blocks are not marked as bad, +but such errors are reported in the output of the command. + +Files are identified only by path, and not by inode. + +The "content" file is modified to update the time of the last check +of each block, and to mark bad blocks. +The "parity" files are NOT modified. +The files in the array are NOT modified. + +5.8 fix +------- + +Fix all the files and the parity data. + +All the files and the parity data are compared with the snapshot +state saved in the last "sync". +If a difference is found, it's reverted to the stored snapshot. + +The "fix" command doesn't differentiate between errors and +intentional modifications. It unconditionally reverts the file state +at the last "sync". + +If no other option is specified the full array is processed. +Use the filter options to select a subset of files or disks to operate on. + +To only fix the blocks marked bad during "sync" and "scrub", +use the -e, --filter-error option. +As difference from other filter options, with this one the fixes are +applied only to files that are not modified from the the latest "sync". + +All the files that cannot be fixed are renamed adding the +".unrecoverable" extension. + +Before fixing, the full array is scanned to find any moved file, +after the last "sync" operation. +These files are identified by their time-stamp, ignoring their name +and directory, and are used in the recovering process if necessary. +If you moved some of them outside the array, you can use the -i, --import +option to specify additional directories to scan. + +Files are identified only by path, and not by inode. + +The "content" file is NOT modified. +The "parity" files are modified if necessary. +The files in the array are modified if necessary. + +5.9 check +--------- + +Verify all the files and the parity data. + +It works like "fix", but it only simulates a recovery and no change +is written in the array. + +This command is mostly intended for manual verifications, +like after a recovery process or in other special conditions. +For periodic and scheduled checks uses "scrub". + +If you use the -a, --audit-only option, only the file +data is checked, and the parity data is ignored for a +faster run. + +Files are identified only by path, and not by inode. + +Nothing is modified. + +5.10 list +--------- + +Lists all the files contained in the array at the time of the +last "sync". + +Nothing is modified. + +5.11 dup +-------- + +Lists all the duplicate files. Two files are assumed equal if their +hashes are matching. The file data is not read, but only the +precomputed hashes are used. + +Nothing is modified. + +5.12 pool +--------- + +Creates or updates in the "pooling" directory a virtual view of all +the files of your disk array. + +The files are not really copied here, but just linked using +symbolic links. + +When updating, all the present symbolic links and empty +subdirectories are deleted and replaced with the new +view of the array. Any other regular file is left in place. + +Nothing is modified outside the pool directory. + +5.13 devices +------------ + +Prints the low level devices used by the array. + +This command prints the devices associations in place in the array, +and it's mainly intended as a script interface. + +The first two columns are the low level device id and path. +The next two columns are the high level device id and path. +The latest column if the disk name in the array. + +In most cases you have one low level device for each disk in the +array, but in some more complex configurations, you may have multiple +low level devices used by a single disk in the array. + +Nothing is modified. + +5.14 touch +---------- + +Sets arbitrarely the sub-second timestamp of all the files +that have it at zero. + +This improves the SnapRAID capability to recognize moved +and copied files as it makes the timestamp almost unique, +removing possible duplicates. + +More specifically, if the sub-second timestamp is not zero, +a moved or copied file is identified as such if it matches +the name, size and timestamp. If instead the sub-second timestamp +is zero, it's considered a copy only if it matches the full path, +size and timestamp. + +Note that the second precision timestamp is not modified, +and all the dates and times of your files will be maintained. + +5.15 rehash +----------- + +Schedules a rehash of the whole array. + +This command changes the hash kind used, typically when upgrading +from a 32 bits system to a 64 bits one, to switch from +MurmurHash3 to the faster SpookyHash. + +If you are already using the optimal hash, this command +does nothing and tells you that nothing has to be done. + +The rehash isn't done immediately, but it takes place +progressively during "sync" and "scrub". + +You can get the rehash state using "status". + +During the rehash, SnapRAID maintains full functionality, +with the only exception of "dup" not able to detect duplicated +files using a different hash. + + +6 OPTIONS +========= + +SnapRAID provides the following options: + + -c, --conf CONFIG + Selects the configuration file to use. If not specified in Unix + it's used the file "/usr/local/etc/snapraid.conf" if it exists, + or "/etc/snapraid.conf" otherwise. + In Windows it's used the file "snapraid.conf" in the same + directory of "snapraid.exe". + + -f, --filter PATTERN + Filters the files to process in "check" and "fix". + Only the files matching the entered pattern are processed. + This option can be used many times. + See the PATTERN section for more details in the + pattern specifications. + In Unix, ensure to quote globbing chars if used. + This option can be used only with "check" and "fix". + Note that it cannot be used with "sync" and "scrub", because they always + process the whole array. + + -d, --filter-disk NAME + Filters the disks to process in "check", "fix", "up" and "down". + You must specify a disk name as named in the configuration + file. + You can also specify parity disks with the names: "parity", "2-parity", + "3-parity", ... to limit the operations a specific parity disk. + If you combine more --filter, --filter-disk and --filter-missing options, + only files matching all the set of filters are selected. + This option can be used many times. + This option can be used only with "check", "fix", "up" and "down". + Note that it cannot be used with "sync" and "scrub", because they always + process the whole array. + + -m, --filter-missing + Filters the files to process in "check" and "fix". + Only the files missing/deleted from the array are processed. + When used with "fix", this is a kind of "undelete" command. + If you combine more --filter, --filter-disk and --filter-missing options, + only files matching all the set of filters are selected. + This option can be used only with "check" and "fix". + Note that it cannot be used with "sync" and "scrub", because they always + process the whole array. + + -e, --filter-error + Filters the blocks to process in "check" and "fix". + It processes only the blocks marked with silent or input/output + errors during "sync" and "scrub", and listed in "status". + This option can be used only with "check" and "fix". + + -p, --plan PERC|bad|new|full + Selects the scrub plan. If PERC is a numeric value from 0 to 100, + it's interpreted as the percentage of blocks to scrub. + Instead of a percentage, you can also specify a plan: + "bad" scrubs bad blocks, "new" the blocks not yet scrubbed, + and "full" for everything. + This option can be used only with "scrub". + + -o, --older-than DAYS + Selects the older the part of the array to process in "scrub". + DAYS is the minimum age in days for a block to be scrubbed, + default is 10. + Blocks marked as bad are always scrubbed despite this option. + This option can be used only with "scrub". + + -a, --audit-only + In "check" verifies the hash of the files without + doing any kind of check on the parity data. + If you are interested in checking only the file data this + option can speedup a lot the checking process. + This option can be used only with "check". + + -h, --pre-hash + In "sync" runs a preliminary hashing phase of all the new data + to have an additional verification before the parity computation. + Usually in "sync" no preliminary hashing is done, and the new + data is hashed just before the parity computation when it's read + for the first time. + Unfortunately, this process happens when the system is under + heavy load, with all disks spinning and with a busy CPU. + This is an extreme condition for the machine, and if it has a + latent hardware problem, it's possible to encounter silent errors + what cannot be detected because the data is not yet hashed. + To avoid this risk, you can enable the "pre-hash" mode and have + all the data read two times to ensure its integrity. + This option also verifies the files moved inside the array, + to ensure that the move operation went successfully, and in case + to block the sync and to allow to run a fix operation. + This option can be used only with "sync". + + -i, --import DIR + Imports from the specified directory any file that you deleted + from the array after the last "sync". + If you still have such files, they could be used by "check" + and "fix" to improve the recover process. + The files are read also in subdirectories and they are + identified regardless of their name. + This option can be used only with "check" and "fix". + + -Z, --force-zero + Forces the insecure operation of syncing a file with zero + size that before was not. + If SnapRAID detects a such condition, it stops proceeding + unless you specify this option. + This allows to easily detect when after a system crash, + some accessed files were truncated. + This is a possible condition in Linux with the ext3/ext4 + file-systems. + This option can be used only with "sync". + + -E, --force-empty + Forces the insecure operation of syncing a disk with all + the original files missing. + If SnapRAID detects that all the files originally present + in the disk are missing or rewritten, it stops proceeding + unless you specify this option. + This allows to easily detect when a data file-system is not + mounted. + This option can be used only with "sync". + + -U, --force-uuid + Forces the insecure operation of syncing, checking and fixing + with disks that have changed their UUID. + If SnapRAID detects that some disks have changed UUID, + it stops proceeding unless you specify this option. + This allows to detect when your disks are mounted in the + wrong mount points. + It's anyway allowed to have a single UUID change with + single parity, and more with multiple parity, because it's + the normal case of replacing disks after a recovery. + This option can be used only with "sync", "check" or + "fix". + + -D, --force-device + Forces the insecure operation of fixing with inaccessible disks, + or with disks on the same physical device. + Like if you lost two data disks, and you have a spare disk to recover + only the first one, and you want to ignore the second inaccessible disk. + Or if you want to recover a disk in the free space left in an + already used disk, sharing the same physical device. + This option can be used only with "fix". + + -N, --force-nocopy + In "sync", "check and "fix", disables the copy detection heuristic. + Without this option SnapRAID assumes that files with same + attributes, like name, size and time-stamp are copies with the + same data. + This allows to identify copied or moved files from one disk + to another, and to reuse the already computed hash information + to detect silent errors or to recover missing files. + This behavior, in some rare cases, may result in false positives, + or in a slow process due the many hash verifications, and this + option allows to resolve them. + This option can be used only with "sync", "check" and "fix". + + -F, --force-full + In "sync" forces a full rebuild of the parity. + This option can be used when you add a new parity level, or if + you reverted back to an old content file using a more recent parity data. + Instead of recomputing the parity from scratch, this allows + to reuse the hashes present in the content file to validate data, + and to maintain data protection during the "sync" process using + the parity data you have. + This option can be used only with "sync". + + -R, --force-realloc + In "sync" forces a full reallocation of files and rebuild of the parity. + This option can be used to completely reallocate all the files + removing the fragmentation, but reusing the hashes present in the content + file to validate data. + Compared to -F, --force-full, this option reallocates all the parity + not having data protection during the operation. + This option can be used only with "sync". + + -l, --log FILE + Write a detailed log in the specified file. + If this option is not specified, unexpected errors are printed + on the screen, likely resulting in too much output in case of + many errors. When -l, --log is specified, on the screen, go only + fatal errors that makes SnapRAID to stop progress. + If the path starts with '>>' the file is opened + in append mode. Occurrences of '%D' and '%T' in the name are + replaced with the date and time in the format YYYYMMDD and + HHMMSS. Note that in Windows batch files, you'll have to double + the '%' char, like result-%%D.log. And to use '>>' you'll have + to enclose the name in ", like ">>result.log". + To output the log to standard output or standard error, + you can use respectively ">&1" and ">&2". + + -L, --error-limit + Sets a new error limit before stopping execution. + By default SnapRAID stops if it encounters more than 100 + Input/Output errors, meaning that likely a disk is going to + die. + This options affects "sync" and "scrub", that are allowed + to continue after the first bunch of disk errors, to try + to complete at most their operations. + Instead, "check" and "fix" always stop at the first error. + + -S, --start BLKSTART + Starts the processing from the specified + block number. It could be useful to retry to check + or fix some specific block, in case of a damaged disk. + It's present mainly for advanced manual recovering. + + -B, --count BLKCOUNT + Processes only the specified number of blocks. + It's present mainly for advanced manual recovering. + + -C, --gen-conf CONTENT_FILE + Generates a dummy configuration file from an existing + content file. + The configuration file is written in the standard output, + and it doesn't overwrite an existing one. + This configuration file also contains the information + needed to reconstruct the disk mount points, in case you + lose the entire system. + + -v, --verbose + Prints more information on the screen. + If specified one time, it prints excluded files + and more stats. + This option has no effect on the log files. + + -q, --quiet + Prints less information on the screen. + If specified one time, removes the progress bar, if two + times, the running operations, three times, the info + messages, four times the status messages. + Fatal errors are always printed on the screen. + This option has no effect on the log files. + + -H, --help + Prints a short help screen. + + -V, --version + Prints the program version. + + +7 CONFIGURATION +=============== + +SnapRAID requires a configuration file to know where your disk array +is located, and where storing the parity information. + +In Unix it's used the file "/usr/local/etc/snapraid.conf" if it exists, +or "/etc/snapraid.conf" otherwise. +In Windows it's used the file "snapraid.conf" in the same +directory of "snapraid.exe". + +It should contain the following options (case sensitive): + +7.1 parity FILE [,FILE] ... +--------------------------- + +Defines the files to use to store the parity information. +The parity enables the protection from a single disk +failure, like RAID5. + +You can specify multiples files that should be in different disks. +When a file cannot grow anymore, the next one is used. +The total space available must be as big as the biggest data disk in +the array. + +You can add additional parity files at later time, but you +cannot reorder or remove them. + +Leaving the parity disks reserved for parity ensures that +it doesn't get fragmented, improving the performance. + +In Windows 256 MB are left unused in each disk to avoid the +warning about full disks. + +This option is mandatory and it can be used only one time. + +7.2 (2,3,4,5,6)-parity FILE [,FILE] ... +--------------------------------------- + +Defines the files to use to store extra parity information. + +For each parity specified, one additional level of protection +is enabled: + +* 2-parity enables RAID6 dual parity. +* 3-parity enables triple parity +* 4-parity enables quad (four) parity +* 5-parity enables penta (five) parity +* 6-parity enables hexa (six) parity + +Each parity level requires the precence of all the previous parity +levels. + +The same considerations of the 'parity' option apply. + +These options are optional and they can be used only one time. + +7.3 z-parity FILE [,FILE] ... +----------------------------- + +Defines an alternate file and format to store the triple parity. + +This option is an alternative at '3-parity' mainly intended for +low-end CPUs like ARM or AMD Phenom, Athlon and Opteron that don't +support the SSSE3 instructions set. In such cases it provides +a better performance. + +This format is similar, but faster, at the one used by the ZFS RAIDZ3. +Like ZFS, it doesn't work beyond triple parity. + +When using '3-parity' you will be warned if it's recommended to use +the 'z-parity' format for a performance improvement. + +It's possible to convert from one format to another, adjusting +the configuration file with the wanted z-parity or 3-parity file, +and using 'fix' to recreate it. + +7.4 content FILE +---------------- + +Defines the file to use to store the list and check-sums of all the +files present in your disk array. + +It can be placed in the disk used to store data, parity, or +any other disk available. +If you use a data disk, this file is automatically excluded +from the "sync" process. + +This option is mandatory and it can be used more times to save +more copies of the same files. + +You have to store at least one copy for each parity disk used +plus one. Using some more doesn't hurt. + +7.5 data NAME DIR +----------------- + +Defines the name and the mount point of the data disks of +the array. NAME is used to identify the disk, and it must +be unique. DIR is the mount point of the disk in the +file-system. + +You can change the mount point as you like, as long you +keep the NAME fixed. + +You should use one option for each data disk of the array. + +You can rename later a disk, changing the NAME directly +in the configuration file, and then run a 'sync' command. +In the rename case, the association is done using the stored +UUID of the disks. + +7.6 nohidden +------------ + +Excludes all the hidden files and directory. +In Unix hidden files are the ones starting with ".". +In Windows they are the ones with the hidden attribute. + +7.7 exclude/include PATTERN +--------------------------- + +Defines the file or directory patterns to exclude and include +in the sync process. +All the patterns are processed in the specified order. + +If the first pattern that matches is an "exclude" one, the file +is excluded. If it's an "include" one, the file is included. +If no pattern matches, the file is excluded if the last pattern +specified is an "include", or included if the last pattern +specified is an "exclude". + +See the PATTERN section for more details in the pattern +specifications. + +This option can be used many times. + +7.8 blocksize SIZE_IN_KIBIBYTES +------------------------------- + +Defines the basic block size in kibi bytes of the parity. +One kibi bytes is 1024 bytes. + +The default blocksize is 256 and it should work for most cases. + +WARNING! This option is for experts only, and it's highly +recommended to not change it. To change again this value in +future you'll have to recreate the whole parity! + +A reason to use a different hashsize is if you have a lot of small +files. In the order of many millions. + +For each file, even of few bytes, a whole block of parity is allocated, +and with many files this may result in a lot of unused parity space. +And when you completely fill the parity disk, you are not +allowed to add more files in the data disks. +Anyway, the wasted parity doesn't sum between data disks. Wasted space +resulting from a high number of files in a data disk, limits only +the amount of data in such data disk and not in others. + +As approximation, you can assume that half of the block size is +wasted for each file. For example, with 100000 files and a 256 KiB +block size, you are going to waste 13 GB of parity, that may result +in 13 GB less space available in the data disk. + +You can get the amount of wasted space in each disk using "status". +This is the amount of space that you must leave free in the data +disks, or use for files not included in the array. +If this value is negative, it means that your are near to fill +the parity, and it represents the space you can still waste. + +To avoid the problem, you can use a bigger partition for parity. +For example, if you have the parity partition bigger than 13 GB +than data disks, you have enough extra space to handle up to 100000 +files in each data disk. + +A trick to get a bigger parity partition in Linux, is to format it +with the command: + + mkfs.ext4 -m 0 -T largefile4 DEVICE + +This results in about 1.5% of extra space. Meaning about 60 GB for +a 4 TB disk, that allows about 460000 files in each data disk without +any wasted space. + +7.9 hashsize SIZE_IN_BYTES +-------------------------- + +Defines the hash size in bytes of the saved blocks. + +The default hashsize is 16 bytes (128 bits), and it should work +for most cases. + +WARNING! This option is for experts only, and it's highly +recommended to not change it. To change again this value in +future you'll have to recreate the whole parity! + +A reason to use a different hashsize is if your system has +small memory. As a rule of thumb SnapRAID usually requires +1 GiB of RAM memory for each 16 TB of data in the array. + +Specifically, to store the hashes of the data, SnapRAID requires +about TS*(1+HS)/BS bytes of RAM memory. +Where TS is the total size in bytes of your disk array, BS is the +block size in bytes, and HS is the hash size in bytes. + +For example with 8 disks of 4 TB and a block size of 256 KiB +(1 KiB = 1024 bytes), and an hash size of 16, you get: + +RAM = (8 * 4 * 10^12) * (1+16) / (256 * 2^10) = 1.93 GiB + +Switching to a hash size of 8, you get: + +RAM = (8 * 4 * 10^12) * (1+8) / (256 * 2^10) = 1.02 GiB + +Switching to a block size of 512, you get: + +RAM = (8 * 4 * 10^12) * (1+16) / (512 * 2^10) = 0.96 GiB + +Switching to both a hash size of 8, and a block size of 512 you get: + +RAM = (8 * 4 * 10^12) * (1+8) / (512 * 2^10) = 0.51 GiB + +7.10 autosave SIZE_IN_GIGABYTES +------------------------------- + +Automatically save the state when syncing or scrubbing after the specified amount +of GB processed. +This option is useful to avoid to restart from scratch long "sync" +commands interrupted by a machine crash, or any other event that +may interrupt SnapRAID. + +7.11 pool DIR +------------- + +Defines the pooling directory where the virtual view of the disk +array is created using the "pool" command. + +The directory must already exist. + +7.12 share UNC_DIR +------------------ + +Defines the Windows UNC path required to access the disks remotely. + +If this option is specified, the symbolic links created in the pool +directory use this UNC path to access the disks. +Without this option the symbolic links generated use only local paths, +not allowing to share the pool directory in the network. + +The symbolic links are formed using the specified UNC path, adding the +disk name as specified in the "disk" option, and finally adding the +file dir and name. + +This option is only required for Windows. + +7.13 smartctl DISK/PARITY OPTIONS... +------------------------------------ + +Defines a custom smartctl command to obtain the SMART attributes +for each disk. This may be required for RAID controllers and for +some USB disk that cannot be auto-detected. + +DISK is the same disk name specified in the "disk" option. +PARITY is one of the parity name as "parity,(1,2,3,4,5,6,z)-parity". + +In the specified OPTIONS, the "%s" string is replaced by the +device name. Note that in case of RAID controllers the device is likely +fixed, and you don't have to use "%s". + +Refers at the smartmontools documentation about the possible options: + + https://www.smartmontools.org/wiki/Supported_RAID-Controllers + https://www.smartmontools.org/wiki/Supported_USB-Devices + +7.14 Examples +------------- + +An example of a typical configuration for Unix is: + + parity /mnt/diskp/snapraid.parity + content /mnt/diskp/snapraid.content + content /var/snapraid/snapraid.content + data d1 /mnt/disk1/ + data d2 /mnt/disk2/ + data d3 /mnt/disk3/ + exclude /lost+found/ + exclude /tmp/ + smartctl d1 -d sat %s + smartctl d2 -d usbjmicron %s + smartctl parity -d areca,1/1 /dev/sg0 + smartctl 2-parity -d areca,2/1 /dev/sg0 + +An example of a typical configuration for Windows is: + + parity E:\snapraid.parity + content E:\snapraid.content + content C:\snapraid\snapraid.content + data d1 G:\array\ + data d2 H:\array\ + data d3 I:\array\ + exclude Thumbs.db + exclude \$RECYCLE.BIN + exclude \System Volume Information + smartctl d1 -d sat %s + smartctl d2 -d usbjmicron %s + smartctl parity -d areca,1/1 /dev/arcmsr0 + smartctl 2-parity -d areca,2/1 /dev/arcmsr0 + + +8 PATTERN +========= + +Patterns are used to select a subset of files to exclude or include in +the process. + +There are four different types of patterns: + + FILE + Selects any file named as FILE. You can use any globbing + character like * and ?, and char classes like [a-z]. + This pattern is applied only to files and not to directories. + + DIR/ + Selects any directory named DIR and everything inside. + You can use any globbing character like * and ?. + This pattern is applied only to directories and not to files. + + /PATH/FILE + Selects the exact specified file path. You can use any + globbing character like * and ? but they never match a + directory slash. + This pattern is applied only to files and not to directories. + + /PATH/DIR/ + Selects the exact specified directory path and everything + inside. You can use any globbing character like * and ? but + they never match a directory slash. + This pattern is applied only to directories and not to files. + +Note that when you specify an absolute path starting with /, it's +applied at the array root dir and not at the local file-system root dir. + +In Windows you can use the backslash \ instead of the forward slash /. +Note that Windows system directories, junctions, mount points, and any +other Windows special directory are treated just as files, meaning that +to exclude them you must use a file rule, and not a directory one. + +If the file name you want to use really contains a '*', '?', '[', +or ']' char, you have to escape it to avoid to have interpreted as a +globbing character. In Unix the escape char is '\', in Windows it's '^'. +Note that when the pattern is on the command line, you have to double the +escape character to avoid to have it interpreted by the command shell. + +In the configuration file, you can use different strategies to filter +the files to process. +The simplest one is to use only "exclude" rules to remove all the +files and directories you do not want to process. For example: + + # Excludes any file named "*.unrecoverable" + exclude *.unrecoverable + # Excludes the root directory "/lost+found" + exclude /lost+found/ + # Excludes any sub-directory named "tmp" + exclude tmp/ + +The opposite way is to define only the file you want to process, using +only "include" rules. For example: + + # Includes only some directories + include /movies/ + include /musics/ + include /pictures/ + +The final way, is to mix "exclude" and "include" rules. In this case take +care that the order of rules is important. Previous rules have the +precedence over the later ones. +To get things simpler you can first have all the "exclude" rules and then +all the "include" ones. For example: + + # Excludes any file named "*.unrecoverable" + exclude *.unrecoverable + # Excludes any sub-directory named "tmp" + exclude tmp/ + # Includes only some directories + include /movies/ + include /musics/ + include /pictures/ + +On the command line, using the -f option, you can only use "include" +patterns. For example: + + # Checks only the .mp3 files. + # Note the "" use to avoid globbing expansion by the shell in Unix. + snapraid -f "*.mp3" check + +In Unix, when using globbing chars in the command line, you have to +quote them. Otherwise the shell will try to expand them. + + +9 CONTENT +========= + +SnapRAID stores the list and check-sums of your files in the content file. + +It's a binary file, listing all the files present in your disk array, +with all the check-sums to verify their integrity. + +This file is read and written by the "sync" and "scrub" commands, and +read by "fix", "check" and "status". + + +10 PARITY +========= + +SnapRAID stores the parity information of your array in the parity +files. + +They are binary files, containing the computed parity of all the +blocks defined in the "content" file. + +These files are read and written by the "sync" and "fix" commands, and +only read by "scrub" and "check". + + +11 ENCODING +=========== + +SnapRAID in Unix ignores any encoding. It reads and stores the +file names with the same encoding used by the file-system. + +In Windows all the names read from the file-system are converted and +processed in the UTF-8 format. + +To have the file names printed correctly you have to set the Windows +console in the UTF-8 mode, with the command "chcp 65001", and use +a TrueType font like "Lucida Console" as console font. +Note that it has effect only on the printed file names, if you +redirect the console output to a file, the resulting file is always +in the UTF-8 format. + + +12 COPYRIGHT +============ + +This file is Copyright (C) 2011 Andrea Mazzoleni + + +13 SEE ALSO +=========== + +rsync(1) diff --git a/test/test-par1.conf b/test/test-par1.conf new file mode 100644 index 0000000..93d4559 --- /dev/null +++ b/test/test-par1.conf @@ -0,0 +1,17 @@ +# Test configuration file +blocksize 1 +parity bench/parity.0,bench/parity.1,bench/parity.2,bench/parity.3 +content bench/content +content bench/1-content +disk disk1 bench/disk1/ +disk disk2 bench/disk2/ +disk disk3 bench/disk3/ +disk disk4 bench/disk4/ +disk disk5 bench/disk5/ +disk disk6 bench/disk6/ +include *.hidden +exclude *.unrecoverable +pool bench/pool +share \\server\jbod +autosave 1 + diff --git a/test/test-par2.conf b/test/test-par2.conf new file mode 100644 index 0000000..917bab1 --- /dev/null +++ b/test/test-par2.conf @@ -0,0 +1,15 @@ +blocksize 1 +parity bench/parity.0,bench/parity.1,bench/parity.2,bench/parity.3 +2-parity bench/2-parity.0,bench/2-parity.1,bench/2-parity.2,bench/2-parity.3 +content bench/content +content bench/1-content +content bench/2-content +disk disk1 bench/disk1/ +disk disk2 bench/disk2/ +disk disk3 bench/disk3/ +disk disk4 bench/disk4/ +disk disk5 bench/disk5/ +disk disk6 bench/disk6/ +include *.hidden +exclude *.unrecoverable + diff --git a/test/test-par3.conf b/test/test-par3.conf new file mode 100644 index 0000000..af1af7c --- /dev/null +++ b/test/test-par3.conf @@ -0,0 +1,17 @@ +blocksize 1 +parity bench/parity.0,bench/parity.1,bench/parity.2,bench/parity.3 +2-parity bench/2-parity.0,bench/2-parity.1,bench/2-parity.2,bench/2-parity.3 +3-parity bench/3-parity.0,bench/3-parity.1,bench/3-parity.2,bench/3-parity.3 +content bench/content +content bench/1-content +content bench/2-content +content bench/3-content +disk disk1 bench/disk1/ +disk disk2 bench/disk2/ +disk disk3 bench/disk3/ +disk disk4 bench/disk4/ +disk disk5 bench/disk5/ +disk disk6 bench/disk6/ +include *.hidden +exclude *.unrecoverable + diff --git a/test/test-par4.conf b/test/test-par4.conf new file mode 100644 index 0000000..bba81dd --- /dev/null +++ b/test/test-par4.conf @@ -0,0 +1,19 @@ +blocksize 1 +parity bench/parity.0,bench/parity.1,bench/parity.2,bench/parity.3 +2-parity bench/2-parity.0,bench/2-parity.1,bench/2-parity.2,bench/2-parity.3 +3-parity bench/3-parity.0,bench/3-parity.1,bench/3-parity.2,bench/3-parity.3 +4-parity bench/4-parity.0,bench/4-parity.1,bench/4-parity.2,bench/4-parity.3 +content bench/content +content bench/1-content +content bench/2-content +content bench/3-content +content bench/4-content +disk disk1 bench/disk1/ +disk disk2 bench/disk2/ +disk disk3 bench/disk3/ +disk disk4 bench/disk4/ +disk disk5 bench/disk5/ +disk disk6 bench/disk6/ +include *.hidden +exclude *.unrecoverable + diff --git a/test/test-par5.conf b/test/test-par5.conf new file mode 100644 index 0000000..d3bf8e3 --- /dev/null +++ b/test/test-par5.conf @@ -0,0 +1,21 @@ +blocksize 1 +parity bench/parity.0,bench/parity.1,bench/parity.2,bench/parity.3 +2-parity bench/2-parity.0,bench/2-parity.1,bench/2-parity.2,bench/2-parity.3 +3-parity bench/3-parity.0,bench/3-parity.1,bench/3-parity.2,bench/3-parity.3 +4-parity bench/4-parity.0,bench/4-parity.1,bench/4-parity.2,bench/4-parity.3 +5-parity bench/5-parity.0,bench/5-parity.1,bench/5-parity.2,bench/5-parity.3 +content bench/content +content bench/1-content +content bench/2-content +content bench/3-content +content bench/4-content +content bench/5-content +disk disk1 bench/disk1/ +disk disk2 bench/disk2/ +disk disk3 bench/disk3/ +disk disk4 bench/disk4/ +disk disk5 bench/disk5/ +disk disk6 bench/disk6/ +include *.hidden +exclude *.unrecoverable + diff --git a/test/test-par6-hole.conf b/test/test-par6-hole.conf new file mode 100644 index 0000000..00d0945 --- /dev/null +++ b/test/test-par6-hole.conf @@ -0,0 +1,22 @@ +blocksize 1 +parity bench/parity.0,bench/parity.1,bench/parity.2,bench/parity.3 +2-parity bench/2-parity.0,bench/2-parity.1,bench/2-parity.2,bench/2-parity.3 +3-parity bench/3-parity.0,bench/3-parity.1,bench/3-parity.2,bench/3-parity.3 +4-parity bench/4-parity.0,bench/4-parity.1,bench/4-parity.2,bench/4-parity.3 +5-parity bench/5-parity.0,bench/5-parity.1,bench/5-parity.2,bench/5-parity.3 +6-parity bench/6-parity.0,bench/6-parity.1,bench/6-parity.2,bench/6-parity.3 +content bench/content +content bench/1-content +content bench/2-content +content bench/3-content +content bench/4-content +content bench/5-content +content bench/6-content +disk disk1 bench/disk1/ +disk disk3 bench/disk3/ +disk disk4 bench/disk4/ +disk disk5 bench/disk5/ +disk disk6 bench/disk6/ +include *.hidden +exclude *.unrecoverable + diff --git a/test/test-par6-noaccess.conf b/test/test-par6-noaccess.conf new file mode 100644 index 0000000..0f38aee --- /dev/null +++ b/test/test-par6-noaccess.conf @@ -0,0 +1,25 @@ +blocksize 1 +parity bench/parity.0,bench/parity.1,bench/parity.2,bench/parity.3 +2-parity bench/2-parity.0,bench/2-parity.1,bench/2-parity.2,bench/2-parity.3 +3-parity bench/3-parity.0,bench/3-parity.1,bench/3-parity.2,bench/3-parity.3 +4-parity bench/4-parity.0,bench/4-parity.1,bench/4-parity.2,bench/4-parity.3 +5-parity bench/5-parity.0,bench/5-parity.1,bench/5-parity.2,bench/5-parity.3 +6-parity bench/no-access/6-parity.0,bench/no-access/6-parity.1,bench/no-access/6-parity.2,bench/no-access/6-parity.3 +content bench/content +content bench/1-content +content bench/2-content +content bench/3-content +content bench/4-content +content bench/5-content +content bench/no-access/6-content +disk disk1 bench/disk1/ +disk disk2 bench/disk2/ +disk disk3 bench/disk3/ +disk disk4 bench/disk4/ +disk disk5 bench/disk5/ +disk disk6 bench/disk6/no-access/ +include *.hidden +exclude *.unrecoverable +smartctl disk1 %s +smartctl parity /dev/sda + diff --git a/test/test-par6-rename.conf b/test/test-par6-rename.conf new file mode 100644 index 0000000..df9c80a --- /dev/null +++ b/test/test-par6-rename.conf @@ -0,0 +1,24 @@ +blocksize 1 +parity bench/parity.0,bench/parity.1,bench/parity.2,bench/parity.3 +2-parity bench/2-parity.0,bench/2-parity.1,bench/2-parity.2,bench/2-parity.3 +3-parity bench/3-parity.0,bench/3-parity.1,bench/3-parity.2,bench/3-parity.3 +4-parity bench/4-parity.0,bench/4-parity.1,bench/4-parity.2,bench/4-parity.3 +5-parity bench/5-parity.0,bench/5-parity.1,bench/5-parity.2,bench/5-parity.3 +6-parity bench/6-parity.0,bench/6-parity.1,bench/6-parity.2,bench/6-parity.3 +content bench/content +content bench/1-content +content bench/2-content +content bench/3-content +content bench/4-content +content bench/5-content +content bench/6-content +disk disk1-rename bench/disk1/ +disk disk2 bench/disk2/ +disk disk3 bench/disk3/ +disk disk4 bench/disk4/ +disk disk5 bench/disk5/ +disk disk6 bench/disk6/ +include *.hidden +exclude *.unrecoverable + + diff --git a/test/test-par6.conf b/test/test-par6.conf new file mode 100644 index 0000000..15112bc --- /dev/null +++ b/test/test-par6.conf @@ -0,0 +1,25 @@ +blocksize 1 +parity bench/parity.0,bench/parity.1,bench/parity.2,bench/parity.3 +2-parity bench/2-parity.0,bench/2-parity.1,bench/2-parity.2,bench/2-parity.3 +3-parity bench/3-parity.0,bench/3-parity.1,bench/3-parity.2,bench/3-parity.3 +4-parity bench/4-parity.0,bench/4-parity.1,bench/4-parity.2,bench/4-parity.3 +5-parity bench/5-parity.0,bench/5-parity.1,bench/5-parity.2,bench/5-parity.3 +6-parity bench/6-parity.0,bench/6-parity.1,bench/6-parity.2,bench/6-parity.3 +content bench/content +content bench/1-content +content bench/2-content +content bench/3-content +content bench/4-content +content bench/5-content +content bench/6-content +disk disk1 bench/disk1/ +disk disk2 bench/disk2/ +disk disk3 bench/disk3/ +disk disk4 bench/disk4/ +disk disk5 bench/disk5/ +disk disk6 bench/disk6/ +include *.hidden +exclude *.unrecoverable +smartctl disk1 %s +smartctl parity /dev/sda + diff --git a/tommyds/LICENSE b/tommyds/LICENSE new file mode 100644 index 0000000..6c86157 --- /dev/null +++ b/tommyds/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2010, Andrea Mazzoleni. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/tommyds/tommy.c b/tommyds/tommy.c new file mode 100644 index 0000000..b2d22e5 --- /dev/null +++ b/tommyds/tommy.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2010, Andrea Mazzoleni. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* redefine the malloc for tommy use */ +#define tommy_malloc malloc_nofail +#define tommy_calloc calloc_nofail +#define tommy_free free + +#include "cmdline/portable.h" +#include "cmdline/support.h" /* for malloc/calloc_nofail() */ + +#include "tommyhash.c" +#include "tommyarray.c" +#include "tommyarrayblkof.c" +#include "tommylist.c" +#include "tommytree.c" +#include "tommyhashdyn.c" + diff --git a/tommyds/tommyarray.c b/tommyds/tommyarray.c new file mode 100644 index 0000000..a8d946b --- /dev/null +++ b/tommyds/tommyarray.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2011, Andrea Mazzoleni. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tommyarray.h" + +/******************************************************************************/ +/* array */ + +void tommy_array_init(tommy_array* array) +{ + tommy_uint_t i; + + /* fixed initial size */ + array->bucket_bit = TOMMY_ARRAY_BIT; + array->bucket_max = 1 << array->bucket_bit; + array->bucket[0] = tommy_cast(void**, tommy_calloc(array->bucket_max, sizeof(void*))); + for (i = 1; i < TOMMY_ARRAY_BIT; ++i) + array->bucket[i] = array->bucket[0]; + + array->count = 0; +} + +void tommy_array_done(tommy_array* array) +{ + tommy_uint_t i; + + tommy_free(array->bucket[0]); + for (i = TOMMY_ARRAY_BIT; i < array->bucket_bit; ++i) { + void** segment = array->bucket[i]; + tommy_free(&segment[((tommy_ptrdiff_t)1) << i]); + } +} + +void tommy_array_grow(tommy_array* array, tommy_count_t count) +{ + if (array->count >= count) + return; + array->count = count; + + while (count > array->bucket_max) { + void** segment; + + /* allocate one more segment */ + segment = tommy_cast(void**, tommy_calloc(array->bucket_max, sizeof(void*))); + + /* store it adjusting the offset */ + /* cast to ptrdiff_t to ensure to get a negative value */ + array->bucket[array->bucket_bit] = &segment[-(tommy_ptrdiff_t)array->bucket_max]; + + ++array->bucket_bit; + array->bucket_max = 1 << array->bucket_bit; + } +} + +tommy_size_t tommy_array_memory_usage(tommy_array* array) +{ + return array->bucket_max * (tommy_size_t)sizeof(void*); +} + diff --git a/tommyds/tommyarray.h b/tommyds/tommyarray.h new file mode 100644 index 0000000..c04193f --- /dev/null +++ b/tommyds/tommyarray.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2011, Andrea Mazzoleni. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** \file + * Dynamic array based on segments of exponential growing size. + * + * This array is able to grow dynamically upon request, without any reallocation. + * + * The grow operation involves an allocation of a new array segment, without reallocating + * the already used memory, and then not increasing the heap fragmentation. + * This also implies that the address of the stored elements never change. + * + * Allocated segments grow in size exponentially. + */ + +#ifndef __TOMMYARRAY_H +#define __TOMMYARRAY_H + +#include "tommytypes.h" + +#include /* for assert */ + +/******************************************************************************/ +/* array */ + +/** + * Initial and minimal size of the array expressed as a power of 2. + * The initial size is 2^TOMMY_ARRAY_BIT. + */ +#define TOMMY_ARRAY_BIT 6 + +/** \internal + * Max number of elements as a power of 2. + */ +#define TOMMY_ARRAY_BIT_MAX 32 + +/** + * Array container type. + * \note Don't use internal fields directly, but access the container only using functions. + */ +typedef struct tommy_array_struct { + void** bucket[TOMMY_ARRAY_BIT_MAX]; /**< Dynamic array of buckets. */ + tommy_uint_t bucket_bit; /**< Bits used in the bit mask. */ + tommy_count_t bucket_max; /**< Number of buckets. */ + tommy_count_t count; /**< Number of initialized elements in the array. */ +} tommy_array; + +/** + * Initializes the array. + */ +void tommy_array_init(tommy_array* array); + +/** + * Deinitializes the array. + */ +void tommy_array_done(tommy_array* array); + +/** + * Grows the size up to the specified value. + * All the new elements in the array are initialized with the 0 value. + */ +void tommy_array_grow(tommy_array* array, tommy_count_t size); + +/** + * Gets a reference of the element at the specified position. + * You must be sure that space for this position is already + * allocated calling tommy_array_grow(). + */ +tommy_inline void** tommy_array_ref(tommy_array* array, tommy_count_t pos) +{ + tommy_uint_t bsr; + + assert(pos < array->count); + + /* get the highest bit set, in case of all 0, return 0 */ + bsr = tommy_ilog2_u32(pos | 1); + + return &array->bucket[bsr][pos]; +} + +/** + * Sets the element at the specified position. + * You must be sure that space for this position is already + * allocated calling tommy_array_grow(). + */ +tommy_inline void tommy_array_set(tommy_array* array, tommy_count_t pos, void* element) +{ + *tommy_array_ref(array, pos) = element; +} + +/** + * Gets the element at the specified position. + * You must be sure that space for this position is already + * allocated calling tommy_array_grow(). + */ +tommy_inline void* tommy_array_get(tommy_array* array, tommy_count_t pos) +{ + return *tommy_array_ref(array, pos); +} + +/** + * Grows and inserts a new element at the end of the array. + */ +tommy_inline void tommy_array_insert(tommy_array* array, void* element) +{ + tommy_count_t pos = array->count; + + tommy_array_grow(array, pos + 1); + + tommy_array_set(array, pos, element); +} + +/** + * Gets the initialized size of the array. + */ +tommy_inline tommy_count_t tommy_array_size(tommy_array* array) +{ + return array->count; +} + +/** + * Gets the size of allocated memory. + */ +tommy_size_t tommy_array_memory_usage(tommy_array* array); + +#endif + diff --git a/tommyds/tommyarrayblkof.c b/tommyds/tommyarrayblkof.c new file mode 100644 index 0000000..8a491a0 --- /dev/null +++ b/tommyds/tommyarrayblkof.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2013, Andrea Mazzoleni. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tommyarrayblkof.h" + +/******************************************************************************/ +/* array */ + +void tommy_arrayblkof_init(tommy_arrayblkof* array, tommy_size_t element_size) +{ + tommy_array_init(&array->block); + + array->element_size = element_size; + array->count = 0; +} + +void tommy_arrayblkof_done(tommy_arrayblkof* array) +{ + tommy_count_t i; + + for (i = 0; i < tommy_array_size(&array->block); ++i) + tommy_free(tommy_array_get(&array->block, i)); + + tommy_array_done(&array->block); +} + +void tommy_arrayblkof_grow(tommy_arrayblkof* array, tommy_count_t count) +{ + tommy_count_t block_max; + tommy_count_t block_mac; + + if (array->count >= count) + return; + array->count = count; + + block_max = (count + TOMMY_ARRAYBLKOF_SIZE - 1) / TOMMY_ARRAYBLKOF_SIZE; + block_mac = tommy_array_size(&array->block); + + if (block_mac < block_max) { + /* grow the block array */ + tommy_array_grow(&array->block, block_max); + + /* allocate new blocks */ + while (block_mac < block_max) { + void** ptr = tommy_cast(void**, tommy_calloc(TOMMY_ARRAYBLKOF_SIZE, array->element_size)); + + /* set the new block */ + tommy_array_set(&array->block, block_mac, ptr); + + ++block_mac; + } + } +} + +tommy_size_t tommy_arrayblkof_memory_usage(tommy_arrayblkof* array) +{ + return tommy_array_memory_usage(&array->block) + tommy_array_size(&array->block) * TOMMY_ARRAYBLKOF_SIZE * array->element_size; +} + diff --git a/tommyds/tommyarrayblkof.h b/tommyds/tommyarrayblkof.h new file mode 100644 index 0000000..fce6840 --- /dev/null +++ b/tommyds/tommyarrayblkof.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2013, Andrea Mazzoleni. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** \file + * Dynamic array based on blocks of fixed size. + * + * This array is able to grow dynamically upon request, without any reallocation. + * + * This is very similar at ::tommy_arrayblk, but it allows to store elements of any + * size and not just pointers. + * + * Note that in this case tommy_arrayblkof_ref() returns a pointer to the element, + * that should be used for getting and setting elements in the array, + * as generic getter and setter are not available. + */ + +#ifndef __TOMMYARRAYBLKOF_H +#define __TOMMYARRAYBLKOF_H + +#include "tommytypes.h" +#include "tommyarray.h" + +#include /* for assert */ + +/******************************************************************************/ +/* array */ + +/** + * Elements for each block. + */ +#define TOMMY_ARRAYBLKOF_SIZE (4 * 1024) + +/** + * Array container type. + * \note Don't use internal fields directly, but access the container only using functions. + */ +typedef struct tommy_arrayblkof_struct { + tommy_array block; /**< Array of blocks. */ + tommy_size_t element_size; /**< Size of the stored element in bytes. */ + tommy_count_t count; /**< Number of initialized elements in the array. */ +} tommy_arrayblkof; + +/** + * Initializes the array. + * \param element_size Size in byte of the element to store in the array. + */ +void tommy_arrayblkof_init(tommy_arrayblkof* array, tommy_size_t element_size); + +/** + * Deinitializes the array. + */ +void tommy_arrayblkof_done(tommy_arrayblkof* array); + +/** + * Grows the size up to the specified value. + * All the new elements in the array are initialized with the 0 value. + */ +void tommy_arrayblkof_grow(tommy_arrayblkof* array, tommy_count_t size); + +/** + * Gets a reference of the element at the specified position. + * You must be sure that space for this position is already + * allocated calling tommy_arrayblkof_grow(). + */ +tommy_inline void* tommy_arrayblkof_ref(tommy_arrayblkof* array, tommy_count_t pos) +{ + unsigned char* base; + + assert(pos < array->count); + + base = tommy_cast(unsigned char*, tommy_array_get(&array->block, pos / TOMMY_ARRAYBLKOF_SIZE)); + + return base + (pos % TOMMY_ARRAYBLKOF_SIZE) * array->element_size; +} + +/** + * Gets the initialized size of the array. + */ +tommy_inline tommy_count_t tommy_arrayblkof_size(tommy_arrayblkof* array) +{ + return array->count; +} + +/** + * Gets the size of allocated memory. + */ +tommy_size_t tommy_arrayblkof_memory_usage(tommy_arrayblkof* array); + +#endif + diff --git a/tommyds/tommychain.h b/tommyds/tommychain.h new file mode 100644 index 0000000..b15bc6a --- /dev/null +++ b/tommyds/tommychain.h @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2010, Andrea Mazzoleni. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** \file + * Chain of nodes. + * A chain of nodes is an abstraction used to implements complex list operations + * like sorting. + * + * Do not use this directly. Use lists instead. + */ + +#ifndef __TOMMYCHAIN_H +#define __TOMMYCHAIN_H + +#include "tommytypes.h" + +/******************************************************************************/ +/* chain */ + +/** + * Chain of nodes. + * A chain of nodes is a sequence of nodes with the following properties: + * - It contains at least one node. A chains of zero nodes cannot exist. + * - The next field of the tail is of *undefined* value. + * - The prev field of the head is of *undefined* value. + * - All the other inner prev and next fields are correctly set. + */ +typedef struct tommy_chain_struct { + tommy_node* head; /**< Pointer to the head of the chain. */ + tommy_node* tail; /**< Pointer to the tail of the chain. */ +} tommy_chain; + +/** + * Splices a chain in the middle of another chain. + */ +tommy_inline void tommy_chain_splice(tommy_node* first_before, tommy_node* first_after, tommy_node* second_head, tommy_node* second_tail) +{ + /* set the prev list */ + first_after->prev = second_tail; + second_head->prev = first_before; + + /* set the next list */ + first_before->next = second_head; + second_tail->next = first_after; +} + +/** + * Concats two chains. + */ +tommy_inline void tommy_chain_concat(tommy_node* first_tail, tommy_node* second_head) +{ + /* set the prev list */ + second_head->prev = first_tail; + + /* set the next list */ + first_tail->next = second_head; +} + +/** + * Merges two chains. + */ +tommy_inline void tommy_chain_merge(tommy_chain* first, tommy_chain* second, tommy_compare_func* cmp) +{ + tommy_node* first_i = first->head; + tommy_node* second_i = second->head; + + /* merge */ + while (1) { + if (cmp(first_i->data, second_i->data) > 0) { + tommy_node* next = second_i->next; + if (first_i == first->head) { + tommy_chain_concat(second_i, first_i); + first->head = second_i; + } else { + tommy_chain_splice(first_i->prev, first_i, second_i, second_i); + } + if (second_i == second->tail) + break; + second_i = next; + } else { + if (first_i == first->tail) { + tommy_chain_concat(first_i, second_i); + first->tail = second->tail; + break; + } + first_i = first_i->next; + } + } +} + +/** + * Merges two chains managing special degenerated cases. + * It's funtionally equivalent at tommy_chain_merge() but faster with already ordered chains. + */ +tommy_inline void tommy_chain_merge_degenerated(tommy_chain* first, tommy_chain* second, tommy_compare_func* cmp) +{ + /* identify the condition first <= second */ + if (cmp(first->tail->data, second->head->data) <= 0) { + tommy_chain_concat(first->tail, second->head); + first->tail = second->tail; + return; + } + + /* identify the condition second < first */ + /* here we must be strict on comparison to keep the sort stable */ + if (cmp(second->tail->data, first->head->data) < 0) { + tommy_chain_concat(second->tail, first->head); + first->head = second->head; + return; + } + + tommy_chain_merge(first, second, cmp); +} + +/** + * Max number of elements as a power of 2. + */ +#define TOMMY_CHAIN_BIT_MAX 32 + +/** + * Sorts a chain. + * It's a stable merge sort using power of 2 buckets, with O(N*log(N)) complexity, + * similar at the one used in the SGI STL libraries and in the Linux Kernel, + * but faster on degenerated cases like already ordered lists. + * + * SGI STL stl_list.h + * http://www.sgi.com/tech/stl/stl_list.h + * + * Linux Kernel lib/list_sort.c + * http://lxr.linux.no/#linux+v2.6.36/lib/list_sort.c + */ +tommy_inline void tommy_chain_mergesort(tommy_chain* chain, tommy_compare_func* cmp) +{ + /* + * Bit buckets of chains. + * Each bucket contains 2^i nodes or it's empty. + * The chain at address TOMMY_CHAIN_BIT_MAX is an independet variable operating as "carry". + * We keep it in the same "bit" vector to avoid reports from the valgrind tool sgcheck. + */ + tommy_chain bit[TOMMY_CHAIN_BIT_MAX + 1]; + + /** + * Value stored inside the bit bucket. + * It's used to know which bucket is empty of full. + */ + tommy_count_t counter; + tommy_node* node = chain->head; + tommy_node* tail = chain->tail; + tommy_count_t mask; + tommy_count_t i; + + counter = 0; + while (1) { + tommy_node* next; + tommy_chain* last; + + /* carry bit to add */ + last = &bit[TOMMY_CHAIN_BIT_MAX]; + bit[TOMMY_CHAIN_BIT_MAX].head = node; + bit[TOMMY_CHAIN_BIT_MAX].tail = node; + next = node->next; + + /* add the bit, propagating the carry */ + i = 0; + mask = counter; + while ((mask & 1) != 0) { + tommy_chain_merge_degenerated(&bit[i], last, cmp); + mask >>= 1; + last = &bit[i]; + ++i; + } + + /* copy the carry in the first empty bit */ + bit[i] = *last; + + /* add the carry in the counter */ + ++counter; + + if (node == tail) + break; + node = next; + } + + /* merge the buckets */ + i = tommy_ctz_u32(counter); + mask = counter >> i; + while (mask != 1) { + mask >>= 1; + if (mask & 1) + tommy_chain_merge_degenerated(&bit[i + 1], &bit[i], cmp); + else + bit[i + 1] = bit[i]; + ++i; + } + + *chain = bit[i]; +} + +#endif + diff --git a/tommyds/tommyhash.c b/tommyds/tommyhash.c new file mode 100644 index 0000000..05d78d2 --- /dev/null +++ b/tommyds/tommyhash.c @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2010, Andrea Mazzoleni. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tommyhash.h" + +/******************************************************************************/ +/* hash */ + +tommy_inline tommy_uint32_t tommy_le_uint32_read(const void* ptr) +{ + /* allow unaligned read on Intel x86 and x86_64 platforms */ +#if defined(__i386__) || defined(_M_IX86) || defined(_X86_) || defined(__x86_64__) || defined(_M_X64) + /* defines from http://predef.sourceforge.net/ */ + return *(const tommy_uint32_t*)ptr; +#else + const unsigned char* ptr8 = tommy_cast(const unsigned char*, ptr); + return ptr8[0] + ((tommy_uint32_t)ptr8[1] << 8) + ((tommy_uint32_t)ptr8[2] << 16) + ((tommy_uint32_t)ptr8[3] << 24); +#endif +} + +#define tommy_rot(x, k) \ + (((x) << (k)) | ((x) >> (32 - (k)))) + +#define tommy_mix(a, b, c) \ + do { \ + a -= c; a ^= tommy_rot(c, 4); c += b; \ + b -= a; b ^= tommy_rot(a, 6); a += c; \ + c -= b; c ^= tommy_rot(b, 8); b += a; \ + a -= c; a ^= tommy_rot(c, 16); c += b; \ + b -= a; b ^= tommy_rot(a, 19); a += c; \ + c -= b; c ^= tommy_rot(b, 4); b += a; \ + } while (0) + +#define tommy_final(a, b, c) \ + do { \ + c ^= b; c -= tommy_rot(b, 14); \ + a ^= c; a -= tommy_rot(c, 11); \ + b ^= a; b -= tommy_rot(a, 25); \ + c ^= b; c -= tommy_rot(b, 16); \ + a ^= c; a -= tommy_rot(c, 4); \ + b ^= a; b -= tommy_rot(a, 14); \ + c ^= b; c -= tommy_rot(b, 24); \ + } while (0) + +tommy_uint32_t tommy_hash_u32(tommy_uint32_t init_val, const void* void_key, tommy_size_t key_len) +{ + const unsigned char* key = tommy_cast(const unsigned char*, void_key); + tommy_uint32_t a, b, c; + + a = b = c = 0xdeadbeef + ((tommy_uint32_t)key_len) + init_val; + + while (key_len > 12) { + a += tommy_le_uint32_read(key + 0); + b += tommy_le_uint32_read(key + 4); + c += tommy_le_uint32_read(key + 8); + + tommy_mix(a, b, c); + + key_len -= 12; + key += 12; + } + + switch (key_len) { + case 0 : + return c; /* used only when called with a zero length */ + case 12 : + c += tommy_le_uint32_read(key + 8); + b += tommy_le_uint32_read(key + 4); + a += tommy_le_uint32_read(key + 0); + break; + case 11 : c += ((tommy_uint32_t)key[10]) << 16; + case 10 : c += ((tommy_uint32_t)key[9]) << 8; + case 9 : c += key[8]; + case 8 : + b += tommy_le_uint32_read(key + 4); + a += tommy_le_uint32_read(key + 0); + break; + case 7 : b += ((tommy_uint32_t)key[6]) << 16; + case 6 : b += ((tommy_uint32_t)key[5]) << 8; + case 5 : b += key[4]; + case 4 : + a += tommy_le_uint32_read(key + 0); + break; + case 3 : a += ((tommy_uint32_t)key[2]) << 16; + case 2 : a += ((tommy_uint32_t)key[1]) << 8; + case 1 : a += key[0]; + } + + tommy_final(a, b, c); + + return c; +} + +tommy_uint64_t tommy_hash_u64(tommy_uint64_t init_val, const void* void_key, tommy_size_t key_len) +{ + const unsigned char* key = tommy_cast(const unsigned char*, void_key); + tommy_uint32_t a, b, c; + + a = b = c = 0xdeadbeef + ((tommy_uint32_t)key_len) + (init_val & 0xffffffff); + c += init_val >> 32; + + while (key_len > 12) { + a += tommy_le_uint32_read(key + 0); + b += tommy_le_uint32_read(key + 4); + c += tommy_le_uint32_read(key + 8); + + tommy_mix(a, b, c); + + key_len -= 12; + key += 12; + } + + switch (key_len) { + case 0 : + return c + ((tommy_uint64_t)b << 32); /* used only when called with a zero length */ + case 12 : + c += tommy_le_uint32_read(key + 8); + b += tommy_le_uint32_read(key + 4); + a += tommy_le_uint32_read(key + 0); + break; + case 11 : c += ((tommy_uint32_t)key[10]) << 16; + case 10 : c += ((tommy_uint32_t)key[9]) << 8; + case 9 : c += key[8]; + case 8 : + b += tommy_le_uint32_read(key + 4); + a += tommy_le_uint32_read(key + 0); + break; + case 7 : b += ((tommy_uint32_t)key[6]) << 16; + case 6 : b += ((tommy_uint32_t)key[5]) << 8; + case 5 : b += key[4]; + case 4 : + a += tommy_le_uint32_read(key + 0); + break; + case 3 : a += ((tommy_uint32_t)key[2]) << 16; + case 2 : a += ((tommy_uint32_t)key[1]) << 8; + case 1 : a += key[0]; + } + + tommy_final(a, b, c); + + return c + ((tommy_uint64_t)b << 32); +} + +tommy_uint32_t tommy_strhash_u32(tommy_uint64_t init_val, const void* void_key) +{ + const unsigned char* key = tommy_cast(const unsigned char*, void_key); + tommy_uint32_t a, b, c; + tommy_uint32_t m[3] = { 0xff, 0xff00, 0xff0000 }; + + a = b = c = 0xdeadbeef + init_val; + /* this is different than original lookup3 and the result won't match */ + + while (1) { + tommy_uint32_t v = tommy_le_uint32_read(key); + + if (tommy_haszero_u32(v)) { + if (v & m[0]) { + a += v & m[0]; + if (v & m[1]) { + a += v & m[1]; + if (v & m[2]) + a += v & m[2]; + } + } + + break; + } + + a += v; + + v = tommy_le_uint32_read(key + 4); + + if (tommy_haszero_u32(v)) { + if (v & m[0]) { + b += v & m[0]; + if (v & m[1]) { + b += v & m[1]; + if (v & m[2]) + b += v & m[2]; + } + } + + break; + } + + b += v; + + v = tommy_le_uint32_read(key + 8); + + if (tommy_haszero_u32(v)) { + if (v & m[0]) { + c += v & m[0]; + if (v & m[1]) { + c += v & m[1]; + if (v & m[2]) + c += v & m[2]; + } + } + + break; + } + + c += v; + + tommy_mix(a, b, c); + + key += 12; + } + + /* for lengths that are multiplers of 12 we already have called mix */ + /* this is different than the original lookup3 and the result won't match */ + + tommy_final(a, b, c); + + return c; +} + diff --git a/tommyds/tommyhash.h b/tommyds/tommyhash.h new file mode 100644 index 0000000..738e33d --- /dev/null +++ b/tommyds/tommyhash.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2010, Andrea Mazzoleni. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** \file + * Hash functions for the use with ::tommy_hashtable, ::tommy_hashdyn and ::tommy_hashlin. + */ + +#ifndef __TOMMYHASH_H +#define __TOMMYHASH_H + +#include "tommytypes.h" + +/******************************************************************************/ +/* hash */ + +/** + * Hash type used in hashtables. + */ +typedef tommy_key_t tommy_hash_t; + +/** + * Hash function with a 32 bits result. + * Implementation of the Robert Jenkins "lookup3" hash 32 bits version, + * from http://www.burtleburtle.net/bob/hash/doobs.html, function hashlittle(). + * + * This hash is designed to provide a good overall performance in all platforms, + * including 32 bits. If you target only 64 bits, you can use faster hashes, + * like SpookyHash or FarmHash. + * + * \param init_val Initialization value. + * Using a different initialization value, you can generate a completely different set of hash values. + * Use 0 if not relevant. + * \param void_key Pointer to the data to hash. + * \param key_len Size of the data to hash. + * \note + * This function is endianess independent. + * \return The hash value of 32 bits. + */ +tommy_uint32_t tommy_hash_u32(tommy_uint32_t init_val, const void* void_key, tommy_size_t key_len); + +/** + * Hash function with a 64 bits result. + * Implementation of the Robert Jenkins "lookup3" hash 64 bits versions, + * from http://www.burtleburtle.net/bob/hash/doobs.html, function hashlittle2(). + * + * This hash is designed to provide a good overall performance in all platforms, + * including 32 bits. If you target only 64 bits, you can use faster hashes, + * like SpookyHash or FarmHash. + * + * \param init_val Initialization value. + * Using a different initialization value, you can generate a completely different set of hash values. + * Use 0 if not relevant. + * \param void_key Pointer to the data to hash. + * \param key_len Size of the data to hash. + * \note + * This function is endianess independent. + * \return The hash value of 64 bits. + */ +tommy_uint64_t tommy_hash_u64(tommy_uint64_t init_val, const void* void_key, tommy_size_t key_len); + +/** + * String hash function with a 32 bits result. + * Implementation is based on the the Robert Jenkins "lookup3" hash 32 bits version, + * from http://www.burtleburtle.net/bob/hash/doobs.html, function hashlittle(). + * + * This hash is designed to handle strings with an unknown length. If you + * know the string length, the other hash functions are surely faster. + * + * \param init_val Initialization value. + * Using a different initialization value, you can generate a completely different set of hash values. + * Use 0 if not relevant. + * \param void_key Pointer to the string to hash. It has to be 0 terminated. + * \note + * This function is endianess independent. + * \return The hash value of 32 bits. + */ +tommy_uint32_t tommy_strhash_u32(tommy_uint64_t init_val, const void* void_key); + +/** + * Integer reversible hash function for 32 bits. + * Implementation of the Robert Jenkins "4-byte Integer Hashing", + * from http://burtleburtle.net/bob/hash/integer.html + */ +tommy_inline tommy_uint32_t tommy_inthash_u32(tommy_uint32_t key) +{ + key -= key << 6; + key ^= key >> 17; + key -= key << 9; + key ^= key << 4; + key -= key << 3; + key ^= key << 10; + key ^= key >> 15; + + return key; +} + +/** + * Integer reversible hash function for 64 bits. + * Implementation of the Thomas Wang "Integer Hash Function", + * from http://web.archive.org/web/20071223173210/http://www.concentric.net/~Ttwang/tech/inthash.htm + */ +tommy_inline tommy_uint64_t tommy_inthash_u64(tommy_uint64_t key) +{ + key = ~key + (key << 21); + key = key ^ (key >> 24); + key = key + (key << 3) + (key << 8); + key = key ^ (key >> 14); + key = key + (key << 2) + (key << 4); + key = key ^ (key >> 28); + key = key + (key << 31); + + return key; +} + +#endif + diff --git a/tommyds/tommyhashdyn.c b/tommyds/tommyhashdyn.c new file mode 100644 index 0000000..02ef404 --- /dev/null +++ b/tommyds/tommyhashdyn.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2010, Andrea Mazzoleni. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tommyhashdyn.h" +#include "tommylist.h" + +/******************************************************************************/ +/* hashdyn */ + +void tommy_hashdyn_init(tommy_hashdyn* hashdyn) +{ + /* fixed initial size */ + hashdyn->bucket_bit = TOMMY_HASHDYN_BIT; + hashdyn->bucket_max = 1 << hashdyn->bucket_bit; + hashdyn->bucket_mask = hashdyn->bucket_max - 1; + hashdyn->bucket = tommy_cast(tommy_hashdyn_node**, tommy_calloc(hashdyn->bucket_max, sizeof(tommy_hashdyn_node*))); + + hashdyn->count = 0; +} + +void tommy_hashdyn_done(tommy_hashdyn* hashdyn) +{ + tommy_free(hashdyn->bucket); +} + +/** + * Resize the bucket vector. + */ +static void tommy_hashdyn_resize(tommy_hashdyn* hashdyn, tommy_count_t new_bucket_bit) +{ + tommy_count_t bucket_bit; + tommy_count_t bucket_max; + tommy_count_t new_bucket_max; + tommy_count_t new_bucket_mask; + tommy_hashdyn_node** new_bucket; + + bucket_bit = hashdyn->bucket_bit; + bucket_max = hashdyn->bucket_max; + + new_bucket_max = 1 << new_bucket_bit; + new_bucket_mask = new_bucket_max - 1; + + /* allocate the new vector using malloc() and not calloc() */ + /* because data is fully initialized in the update process */ + new_bucket = tommy_cast(tommy_hashdyn_node**, tommy_malloc(new_bucket_max * sizeof(tommy_hashdyn_node*))); + + /* reinsert all the elements */ + if (new_bucket_bit > bucket_bit) { + tommy_count_t i; + + /* grow */ + for (i = 0; i < bucket_max; ++i) { + tommy_hashdyn_node* j; + + /* setup the new two buckets */ + new_bucket[i] = 0; + new_bucket[i + bucket_max] = 0; + + /* reinsert the bucket */ + j = hashdyn->bucket[i]; + while (j) { + tommy_hashdyn_node* j_next = j->next; + tommy_count_t pos = j->key & new_bucket_mask; + if (new_bucket[pos]) + tommy_list_insert_tail_not_empty(new_bucket[pos], j); + else + tommy_list_insert_first(&new_bucket[pos], j); + j = j_next; + } + } + } else { + tommy_count_t i; + + /* shrink */ + for (i = 0; i < new_bucket_max; ++i) { + /* setup the new bucket with the lower bucket*/ + new_bucket[i] = hashdyn->bucket[i]; + + /* concat the upper bucket */ + tommy_list_concat(&new_bucket[i], &hashdyn->bucket[i + new_bucket_max]); + } + } + + tommy_free(hashdyn->bucket); + + /* setup */ + hashdyn->bucket_bit = new_bucket_bit; + hashdyn->bucket_max = new_bucket_max; + hashdyn->bucket_mask = new_bucket_mask; + hashdyn->bucket = new_bucket; +} + +/** + * Grow. + */ +tommy_inline void hashdyn_grow_step(tommy_hashdyn* hashdyn) +{ + /* grow if more than 50% full */ + if (hashdyn->count >= hashdyn->bucket_max / 2) + tommy_hashdyn_resize(hashdyn, hashdyn->bucket_bit + 1); +} + +/** + * Shrink. + */ +tommy_inline void hashdyn_shrink_step(tommy_hashdyn* hashdyn) +{ + /* shrink if less than 12.5% full */ + if (hashdyn->count <= hashdyn->bucket_max / 8 && hashdyn->bucket_bit > TOMMY_HASHDYN_BIT) + tommy_hashdyn_resize(hashdyn, hashdyn->bucket_bit - 1); +} + +void tommy_hashdyn_insert(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node, void* data, tommy_hash_t hash) +{ + tommy_count_t pos = hash & hashdyn->bucket_mask; + + tommy_list_insert_tail(&hashdyn->bucket[pos], node, data); + + node->key = hash; + + ++hashdyn->count; + + hashdyn_grow_step(hashdyn); +} + +void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node) +{ + tommy_count_t pos = node->key & hashdyn->bucket_mask; + + tommy_list_remove_existing(&hashdyn->bucket[pos], node); + + --hashdyn->count; + + hashdyn_shrink_step(hashdyn); + + return node->data; +} + +void* tommy_hashdyn_remove(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash) +{ + tommy_count_t pos = hash & hashdyn->bucket_mask; + tommy_hashdyn_node* node = hashdyn->bucket[pos]; + + while (node) { + /* we first check if the hash matches, as in the same bucket we may have multiples hash values */ + if (node->key == hash && cmp(cmp_arg, node->data) == 0) { + tommy_list_remove_existing(&hashdyn->bucket[pos], node); + + --hashdyn->count; + + hashdyn_shrink_step(hashdyn); + + return node->data; + } + node = node->next; + } + + return 0; +} + +void tommy_hashdyn_foreach(tommy_hashdyn* hashdyn, tommy_foreach_func* func) +{ + tommy_count_t bucket_max = hashdyn->bucket_max; + tommy_hashdyn_node** bucket = hashdyn->bucket; + tommy_count_t pos; + + for (pos = 0; pos < bucket_max; ++pos) { + tommy_hashdyn_node* node = bucket[pos]; + + while (node) { + void* data = node->data; + node = node->next; + func(data); + } + } +} + +void tommy_hashdyn_foreach_arg(tommy_hashdyn* hashdyn, tommy_foreach_arg_func* func, void* arg) +{ + tommy_count_t bucket_max = hashdyn->bucket_max; + tommy_hashdyn_node** bucket = hashdyn->bucket; + tommy_count_t pos; + + for (pos = 0; pos < bucket_max; ++pos) { + tommy_hashdyn_node* node = bucket[pos]; + + while (node) { + void* data = node->data; + node = node->next; + func(arg, data); + } + } +} + +tommy_size_t tommy_hashdyn_memory_usage(tommy_hashdyn* hashdyn) +{ + return hashdyn->bucket_max * (tommy_size_t)sizeof(hashdyn->bucket[0]) + + tommy_hashdyn_count(hashdyn) * (tommy_size_t)sizeof(tommy_hashdyn_node); +} + diff --git a/tommyds/tommyhashdyn.h b/tommyds/tommyhashdyn.h new file mode 100644 index 0000000..ed4a607 --- /dev/null +++ b/tommyds/tommyhashdyn.h @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2010, Andrea Mazzoleni. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** \file + * Dynamic chained hashtable. + * + * This hashtable resizes dynamically. It starts with the minimal size of 16 buckets, it doubles + * the size then it reaches a load factor greater than 0.5 and it halves the size with a load + * factor lower than 0.125. + * + * All the elements are reallocated in a single resize operation done inside + * tommy_hashdyn_insert() or tommy_hashdyn_remove(). + * + * Note that the resize operation takes approximatively 100 [ms] with 1 million of elements, + * and 1 [second] with 10 millions. This could be a problem in real-time applications. + * + * The resize also fragment the heap, as it involves allocating a double-sized table, copy elements, + * and deallocating the older table. Leaving a big hole in the heap. + * + * The ::tommy_hashlin hashtable fixes both problems. + * + * To initialize the hashtable you have to call tommy_hashdyn_init(). + * + * \code + * tommy_hashslin hashdyn; + * + * tommy_hashdyn_init(&hashdyn); + * \endcode + * + * To insert elements in the hashtable you have to call tommy_hashdyn_insert() for + * each element. + * In the insertion call you have to specify the address of the node, the + * address of the object, and the hash value of the key to use. + * The address of the object is used to initialize the tommy_node::data field + * of the node, and the hash to initialize the tommy_node::key field. + * + * \code + * struct object { + * int value; + * // other fields + * tommy_node node; + * }; + * + * struct object* obj = malloc(sizeof(struct object)); // creates the object + * + * obj->value = ...; // initializes the object + * + * tommy_hashdyn_insert(&hashdyn, &obj->node, obj, tommy_inthash_u32(obj->value)); // inserts the object + * \endcode + * + * To find and element in the hashtable you have to call tommy_hashtable_search() + * providing a comparison function, its argument, and the hash of the key to search. + * + * \code + * int compare(const void* arg, const void* obj) + * { + * return *(const int*)arg != ((const struct object*)obj)->value; + * } + * + * int value_to_find = 1; + * struct object* obj = tommy_hashdyn_search(&hashdyn, compare, &value_to_find, tommy_inthash_u32(value_to_find)); + * if (!obj) { + * // not found + * } else { + * // found + * } + * \endcode + * + * To iterate over all the elements in the hashtable with the same key, you have to + * use tommy_hashdyn_bucket() and follow the tommy_node::next pointer until NULL. + * You have also to check explicitely for the key, as the bucket may contains + * different keys. + * + * \code + * int value_to_find = 1; + * tommy_node* i = tommy_hashdyn_bucket(&hashdyn, tommy_inthash_u32(value_to_find)); + * while (i) { + * struct object* obj = i->data; // gets the object pointer + * + * if (obj->value == value_to_find) { + * printf("%d\n", obj->value); // process the object + * } + * + * i = i->next; // goes to the next element + * } + * \endcode + * + * To remove an element from the hashtable you have to call tommy_hashdyn_remove() + * providing a comparison function, its argument, and the hash of the key to search + * and remove. + * + * \code + * struct object* obj = tommy_hashdyn_remove(&hashdyn, compare, &value_to_remove, tommy_inthash_u32(value_to_remove)); + * if (obj) { + * free(obj); // frees the object allocated memory + * } + * \endcode + * + * To destroy the hashtable you have to remove all the elements, and deinitialize + * the hashtable calling tommy_hashdyn_done(). + * + * \code + * tommy_hashdyn_done(&hashdyn); + * \endcode + * + * If you need to iterate over all the elements in the hashtable, you can use + * tommy_hashdyn_foreach() or tommy_hashdyn_foreach_arg(). + * If you need a more precise control with a real iteration, you have to insert + * all the elements also in a ::tommy_list, and use the list to iterate. + * See the \ref multiindex example for more detail. + */ + +#ifndef __TOMMYHASHDYN_H +#define __TOMMYHASHDYN_H + +#include "tommyhash.h" + +/******************************************************************************/ +/* hashdyn */ + +/** \internal + * Initial and minimal size of the hashtable expressed as a power of 2. + * The initial size is 2^TOMMY_HASHDYN_BIT. + */ +#define TOMMY_HASHDYN_BIT 4 + +/** + * Hashtable node. + * This is the node that you have to include inside your objects. + */ +typedef tommy_node tommy_hashdyn_node; + +/** + * Hashtable container type. + * \note Don't use internal fields directly, but access the container only using functions. + */ +typedef struct tommy_hashdyn_struct { + tommy_hashdyn_node** bucket; /**< Hash buckets. One list for each hash modulus. */ + tommy_uint_t bucket_bit; /**< Bits used in the bit mask. */ + tommy_count_t bucket_max; /**< Number of buckets. */ + tommy_count_t bucket_mask; /**< Bit mask to access the buckets. */ + tommy_count_t count; /**< Number of elements. */ +} tommy_hashdyn; + +/** + * Initializes the hashtable. + */ +void tommy_hashdyn_init(tommy_hashdyn* hashdyn); + +/** + * Deinitializes the hashtable. + * + * You can call this function with elements still contained, + * but such elements are not going to be freed by this call. + */ +void tommy_hashdyn_done(tommy_hashdyn* hashdyn); + +/** + * Inserts an element in the hashtable. + */ +void tommy_hashdyn_insert(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node, void* data, tommy_hash_t hash); + +/** + * Searches and removes an element from the hashtable. + * You have to provide a compare function and the hash of the element you want to remove. + * If the element is not found, 0 is returned. + * If more equal elements are present, the first one is removed. + * \param cmp Compare function called with cmp_arg as first argument and with the element to compare as a second one. + * The function should return 0 for equal elements, anything other for different elements. + * \param cmp_arg Compare argument passed as first argument of the compare function. + * \param hash Hash of the element to find and remove. + * \return The removed element, or 0 if not found. + */ +void* tommy_hashdyn_remove(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash); + +/** + * Gets the bucket of the specified hash. + * The bucket is guaranteed to contain ALL the elements with the specified hash, + * but it can contain also others. + * You can access elements in the bucket following the ::next pointer until 0. + * \param hash Hash of the element to find. + * \return The head of the bucket, or 0 if empty. + */ +tommy_inline tommy_hashdyn_node* tommy_hashdyn_bucket(tommy_hashdyn* hashdyn, tommy_hash_t hash) +{ + return hashdyn->bucket[hash & hashdyn->bucket_mask]; +} + +/** + * Searches an element in the hashtable. + * You have to provide a compare function and the hash of the element you want to find. + * If more equal elements are present, the first one is returned. + * \param cmp Compare function called with cmp_arg as first argument and with the element to compare as a second one. + * The function should return 0 for equal elements, anything other for different elements. + * \param cmp_arg Compare argument passed as first argument of the compare function. + * \param hash Hash of the element to find. + * \return The first element found, or 0 if none. + */ +tommy_inline void* tommy_hashdyn_search(tommy_hashdyn* hashdyn, tommy_search_func* cmp, const void* cmp_arg, tommy_hash_t hash) +{ + tommy_hashdyn_node* i = tommy_hashdyn_bucket(hashdyn, hash); + + while (i) { + /* we first check if the hash matches, as in the same bucket we may have multiples hash values */ + if (i->key == hash && cmp(cmp_arg, i->data) == 0) + return i->data; + i = i->next; + } + return 0; +} + +/** + * Removes an element from the hashtable. + * You must already have the address of the element to remove. + * \return The tommy_node::data field of the node removed. + */ +void* tommy_hashdyn_remove_existing(tommy_hashdyn* hashdyn, tommy_hashdyn_node* node); + +/** + * Calls the specified function for each element in the hashtable. + * + * You cannot add or remove elements from the inside of the callback, + * but can use it to deallocate them. + * + * \code + * tommy_hashdyn hashdyn; + * + * // initializes the hashtable + * tommy_hashdyn_init(&hashdyn); + * + * ... + * + * // creates an object + * struct object* obj = malloc(sizeof(struct object)); + * + * ... + * + * // insert it in the hashtable + * tommy_hashdyn_insert(&hashdyn, &obj->node, obj, tommy_inthash_u32(obj->value)); + * + * ... + * + * // deallocates all the objects iterating the hashtable + * tommy_hashdyn_foreach(&hashdyn, free); + * + * // deallocates the hashtable + * tommy_hashdyn_done(&hashdyn); + * \endcode + */ +void tommy_hashdyn_foreach(tommy_hashdyn* hashdyn, tommy_foreach_func* func); + +/** + * Calls the specified function with an argument for each element in the hashtable. + */ +void tommy_hashdyn_foreach_arg(tommy_hashdyn* hashdyn, tommy_foreach_arg_func* func, void* arg); + +/** + * Gets the number of elements. + */ +tommy_inline tommy_count_t tommy_hashdyn_count(tommy_hashdyn* hashdyn) +{ + return hashdyn->count; +} + +/** + * Gets the size of allocated memory. + * It includes the size of the ::tommy_hashdyn_node of the stored elements. + */ +tommy_size_t tommy_hashdyn_memory_usage(tommy_hashdyn* hashdyn); + +#endif + diff --git a/tommyds/tommylist.c b/tommyds/tommylist.c new file mode 100644 index 0000000..1fa1f24 --- /dev/null +++ b/tommyds/tommylist.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2010, Andrea Mazzoleni. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tommylist.h" +#include "tommychain.h" + +/** \internal + * Setup a list. + */ +tommy_inline void tommy_list_set(tommy_list* list, tommy_node* head, tommy_node* tail) +{ + head->prev = tail; + tail->next = 0; + *list = head; +} + +void tommy_list_sort(tommy_list* list, tommy_compare_func* cmp) +{ + tommy_chain chain; + tommy_node* head; + + if (tommy_list_empty(list)) + return; + + head = tommy_list_head(list); + + /* create a chain from the list */ + chain.head = head; + chain.tail = head->prev; + + tommy_chain_mergesort(&chain, cmp); + + /* restore the list */ + tommy_list_set(list, chain.head, chain.tail); +} + diff --git a/tommyds/tommylist.h b/tommyds/tommylist.h new file mode 100644 index 0000000..d88cee7 --- /dev/null +++ b/tommyds/tommylist.h @@ -0,0 +1,399 @@ +/* + * Copyright (c) 2010, Andrea Mazzoleni. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** \file + * Double linked list for collisions into hashtables. + * + * This list is a double linked list mainly targetted for handling collisions + * into an hashtables, but useable also as a generic list. + * + * The main feature of this list is to require only one pointer to represent the + * list, compared to a classic implementation requiring a head an a tail pointers. + * This reduces the memory usage in hashtables. + * + * Another feature is to support the insertion at the end of the list. This allow to store + * collisions in a stable order. Where for stable order we mean that equal elements keep + * their insertion order. + * + * To initialize the list, you have to call tommy_list_init(), or to simply assign + * to it NULL, as an empty list is represented by the NULL value. + * + * \code + * tommy_list list; + * + * tommy_list_init(&list); // initializes the list + * \endcode + * + * To insert elements in the list you have to call tommy_list_insert_tail() + * or tommy_list_insert_head() for each element. + * In the insertion call you have to specify the address of the node and the + * address of the object. + * The address of the object is used to initialize the tommy_node::data field + * of the node. + * + * \code + * struct object { + * int value; + * // other fields + * tommy_node node; + * }; + * + * struct object* obj = malloc(sizeof(struct object)); // creates the object + * + * obj->value = ...; // initializes the object + * + * tommy_list_insert_tail(&list, &obj->node, obj); // inserts the object + * \endcode + * + * To iterate over all the elements in the list you have to call + * tommy_list_head() to get the head of the list and follow the + * tommy_node::next pointer until NULL. + * + * \code + * tommy_node* i = tommy_list_head(&list); + * while (i) { + * struct object* obj = i->data; // gets the object pointer + * + * printf("%d\n", obj->value); // process the object + * + * i = i->next; // go to the next element + * } + * \endcode + * + * To destroy the list you have to remove all the elements, + * as the list is completely inplace and it doesn't allocate memory. + * This can be done with the tommy_list_foreach() function. + * + * \code + * // deallocates all the objects iterating the list + * tommy_list_foreach(&list, free); + * \endcode + */ + +#ifndef __TOMMYLIST_H +#define __TOMMYLIST_H + +#include "tommytypes.h" + +/******************************************************************************/ +/* list */ + +/** + * Double linked list type. + */ +typedef tommy_node* tommy_list; + +/** + * Initializes the list. + * The list is completely inplace, so it doesn't need to be deinitialized. + */ +tommy_inline void tommy_list_init(tommy_list* list) +{ + *list = 0; +} + +/** + * Gets the head of the list. + * \return The head node. For empty lists 0 is returned. + */ +tommy_inline tommy_node* tommy_list_head(tommy_list* list) +{ + return *list; +} + +/** + * Gets the tail of the list. + * \return The tail node. For empty lists 0 is returned. + */ +tommy_inline tommy_node* tommy_list_tail(tommy_list* list) +{ + tommy_node* head = tommy_list_head(list); + + if (!head) + return 0; + + return head->prev; +} + +/** \internal + * Creates a new list with a single element. + * \param list The list to initialize. + * \param node The node to insert. + */ +tommy_inline void tommy_list_insert_first(tommy_list* list, tommy_node* node) +{ + /* one element "circular" prev list */ + node->prev = node; + + /* one element "0 terminated" next list */ + node->next = 0; + + *list = node; +} + +/** \internal + * Inserts an element at the head of a not empty list. + * The element is inserted at the head of the list. The list cannot be empty. + * \param list The list. The list cannot be empty. + * \param node The node to insert. + */ +tommy_inline void tommy_list_insert_head_not_empty(tommy_list* list, tommy_node* node) +{ + tommy_node* head = tommy_list_head(list); + + /* insert in the "circular" prev list */ + node->prev = head->prev; + head->prev = node; + + /* insert in the "0 terminated" next list */ + node->next = head; + + *list = node; +} + +/** \internal + * Inserts an element at the tail of a not empty list. + * The element is inserted at the tail of the list. The list cannot be empty. + * \param head The node at the list head. It cannot be 0. + * \param node The node to insert. + */ +tommy_inline void tommy_list_insert_tail_not_empty(tommy_node* head, tommy_node* node) +{ + /* insert in the "circular" prev list */ + node->prev = head->prev; + head->prev = node; + + /* insert in the "0 terminated" next list */ + node->next = 0; + node->prev->next = node; +} + +/** + * Inserts an element at the head of a list. + * \param node The node to insert. + * \param data The object containing the node. It's used to set the tommy_node::data field of the node. + */ +tommy_inline void tommy_list_insert_head(tommy_list* list, tommy_node* node, void* data) +{ + tommy_node* head = tommy_list_head(list); + + if (head) + tommy_list_insert_head_not_empty(list, node); + else + tommy_list_insert_first(list, node); + + node->data = data; +} + +/** + * Inserts an element at the tail of a list. + * \param node The node to insert. + * \param data The object containing the node. It's used to set the tommy_node::data field of the node. + */ +tommy_inline void tommy_list_insert_tail(tommy_list* list, tommy_node* node, void* data) +{ + tommy_node* head = tommy_list_head(list); + + if (head) + tommy_list_insert_tail_not_empty(head, node); + else + tommy_list_insert_first(list, node); + + node->data = data; +} + +/** \internal + * Removes an element from the head of a not empty list. + * \param list The list. The list cannot be empty. + * \return The node removed. + */ +tommy_inline tommy_node* tommy_list_remove_head_not_empty(tommy_list* list) +{ + tommy_node* head = tommy_list_head(list); + + /* remove from the "circular" prev list */ + head->next->prev = head->prev; + + /* remove from the "0 terminated" next list */ + *list = head->next; /* the new head, in case 0 */ + + return head; +} + +/** + * Removes an element from the list. + * You must already have the address of the element to remove. + * \note The node content is left unchanged, including the tommy_node::next + * and tommy_node::prev fields that still contain pointers at the list. + * \param node The node to remove. The node must be in the list. + * \return The tommy_node::data field of the node removed. + */ +tommy_inline void* tommy_list_remove_existing(tommy_list* list, tommy_node* node) +{ + tommy_node* head = tommy_list_head(list); + + /* remove from the "circular" prev list */ + if (node->next) + node->next->prev = node->prev; + else + head->prev = node->prev; /* the last */ + + /* remove from the "0 terminated" next list */ + if (head == node) + *list = node->next; /* the new head, in case 0 */ + else + node->prev->next = node->next; + + return node->data; +} + +/** + * Concats two lists. + * The second list is concatenated at the first list. + * \param first The first list. + * \param second The second list. After this call the list content is undefined, + * and you should not use it anymore. + */ +tommy_inline void tommy_list_concat(tommy_list* first, tommy_list* second) +{ + tommy_node* first_head; + tommy_node* first_tail; + tommy_node* second_head; + + /* if the second is empty, nothing to do */ + second_head = tommy_list_head(second); + if (second_head == 0) + return; + + /* if the first is empty, copy the second */ + first_head = tommy_list_head(first); + if (first_head == 0) { + *first = *second; + return; + } + + /* tail of the first list */ + first_tail = first_head->prev; + + /* set the "circular" prev list */ + first_head->prev = second_head->prev; + second_head->prev = first_tail; + + /* set the "0 terminated" next list */ + first_tail->next = second_head; +} + +/** + * Sorts a list. + * It's a stable merge sort with O(N*log(N)) worst complexity. + * It's faster on degenerated cases like partially ordered lists. + * \param cmp Compare function called with two elements. + * The function should return <0 if the first element is less than the second, ==0 if equal, and >0 if greather. + */ +void tommy_list_sort(tommy_list* list, tommy_compare_func* cmp); + +/** + * Checks if empty. + * \return If the list is empty. + */ +tommy_inline tommy_bool_t tommy_list_empty(tommy_list* list) +{ + return tommy_list_head(list) == 0; +} + +/** + * Gets the number of elements. + * \note This operation is O(n). + */ +tommy_inline tommy_count_t tommy_list_count(tommy_list* list) +{ + tommy_count_t count = 0; + tommy_node* i = tommy_list_head(list); + + while (i) { + ++count; + i = i->next; + } + + return count; +} + +/** + * Calls the specified function for each element in the list. + * + * You cannot add or remove elements from the inside of the callback, + * but can use it to deallocate them. + * + * \code + * tommy_list list; + * + * // initializes the list + * tommy_list_init(&list); + * + * ... + * + * // creates an object + * struct object* obj = malloc(sizeof(struct object)); + * + * ... + * + * // insert it in the list + * tommy_list_insert_tail(&list, &obj->node, obj); + * + * ... + * + * // deallocates all the objects iterating the list + * tommy_list_foreach(&list, free); + * \endcode + */ +tommy_inline void tommy_list_foreach(tommy_list* list, tommy_foreach_func* func) +{ + tommy_node* node = tommy_list_head(list); + + while (node) { + void* data = node->data; + node = node->next; + func(data); + } +} + +/** + * Calls the specified function with an argument for each element in the list. + */ +tommy_inline void tommy_list_foreach_arg(tommy_list* list, tommy_foreach_arg_func* func, void* arg) +{ + tommy_node* node = tommy_list_head(list); + + while (node) { + void* data = node->data; + node = node->next; + func(arg, data); + } +} + +#endif + diff --git a/tommyds/tommytree.c b/tommyds/tommytree.c new file mode 100644 index 0000000..6b2f1a9 --- /dev/null +++ b/tommyds/tommytree.c @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2015, Andrea Mazzoleni. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tommytree.h" + +#include /* for assert */ + +/******************************************************************************/ +/* tree */ + +void tommy_tree_init(tommy_tree* tree, tommy_compare_func* cmp) +{ + tree->root = 0; + tree->count = 0; + tree->cmp = cmp; +} + +static int tommy_tree_delta(tommy_tree_node* root) +{ + int left_height = root->prev ? root->prev->key : 0; + int right_height = root->next ? root->next->key : 0; + + return left_height - right_height; +} + +/* AVL tree operations */ +static tommy_tree_node* tommy_tree_balance(tommy_tree_node*); + +static tommy_tree_node* tommy_tree_rotate_left(tommy_tree_node* root) +{ + tommy_tree_node* next = root->next; + + root->next = next->prev; + + next->prev = tommy_tree_balance(root); + + return tommy_tree_balance(next); +} + +static tommy_tree_node* tommy_tree_rotate_right(tommy_tree_node* root) +{ + tommy_tree_node* prev = root->prev; + + root->prev = prev->next; + + prev->next = tommy_tree_balance(root); + + return tommy_tree_balance(prev); +} + +static tommy_tree_node* tommy_tree_move_right(tommy_tree_node* root, tommy_tree_node* node) +{ + if (!root) + return node; + + root->next = tommy_tree_move_right(root->next, node); + + return tommy_tree_balance(root); +} + +static tommy_tree_node* tommy_tree_balance(tommy_tree_node* root) +{ + int delta = tommy_tree_delta(root); + + if (delta < -1) { + if (tommy_tree_delta(root->next) > 0) + root->next = tommy_tree_rotate_right(root->next); + return tommy_tree_rotate_left(root); + } + + if (delta > 1) { + if (tommy_tree_delta(root->prev) < 0) + root->prev = tommy_tree_rotate_left(root->prev); + return tommy_tree_rotate_right(root); + } + + /* recompute key */ + root->key = 0; + + if (root->prev && root->prev->key > root->key) + root->key = root->prev->key; + + if (root->next && root->next->key > root->key) + root->key = root->next->key; + + /* count itself */ + root->key += 1; + + return root; +} + +static tommy_tree_node* tommy_tree_insert_node(tommy_compare_func* cmp, tommy_tree_node* root, tommy_tree_node** let) +{ + int c; + + if (!root) + return *let; + + c = cmp((*let)->data, root->data); + + if (c < 0) { + root->prev = tommy_tree_insert_node(cmp, root->prev, let); + return tommy_tree_balance(root); + } + + if (c > 0) { + root->next = tommy_tree_insert_node(cmp, root->next, let); + return tommy_tree_balance(root); + } + + /* already present, set the return pointer */ + *let = root; + + return root; +} + +void* tommy_tree_insert(tommy_tree* tree, tommy_tree_node* node, void* data) +{ + tommy_tree_node* insert = node; + + insert->data = data; + insert->prev = 0; + insert->next = 0; + insert->key = 0; + + tree->root = tommy_tree_insert_node(tree->cmp, tree->root, &insert); + + if (insert == node) + ++tree->count; + + return insert->data; +} + +static tommy_tree_node* tommy_tree_remove_node(tommy_compare_func* cmp, tommy_tree_node* root, void* data, tommy_tree_node** let) +{ + int c; + + if (!root) + return 0; + + c = cmp(data, root->data); + + if (c < 0) { + root->prev = tommy_tree_remove_node(cmp, root->prev, data, let); + return tommy_tree_balance(root); + } + + if (c > 0) { + root->next = tommy_tree_remove_node(cmp, root->next, data, let); + return tommy_tree_balance(root); + } + + /* found */ + *let = root; + + return tommy_tree_move_right(root->prev, root->next); +} + +void* tommy_tree_remove(tommy_tree* tree, void* data) +{ + tommy_tree_node* node = 0; + + tree->root = tommy_tree_remove_node(tree->cmp, tree->root, data, &node); + + if (!node) + return 0; + + --tree->count; + + return node->data; +} + +static tommy_tree_node* tommy_tree_search_node(tommy_compare_func* cmp, tommy_tree_node* root, void* data) +{ + int c; + + if (!root) + return 0; + + c = cmp(data, root->data); + + if (c < 0) + return tommy_tree_search_node(cmp, root->prev, data); + + if (c > 0) + return tommy_tree_search_node(cmp, root->next, data); + + return root; +} + +void* tommy_tree_search(tommy_tree* tree, void* data) +{ + tommy_tree_node* node = tommy_tree_search_node(tree->cmp, tree->root, data); + + if (!node) + return 0; + + return node->data; +} + +void* tommy_tree_search_compare(tommy_tree* tree, tommy_compare_func* cmp, void* cmp_arg) +{ + tommy_tree_node* node = tommy_tree_search_node(cmp, tree->root, cmp_arg); + + if (!node) + return 0; + + return node->data; +} + +void* tommy_tree_remove_existing(tommy_tree* tree, tommy_tree_node* node) +{ + void* data = tommy_tree_remove(tree, node->data); + + assert(data != 0); + + return data; +} + +static void tommy_tree_foreach_node(tommy_tree_node* root, tommy_foreach_func* func) +{ + tommy_tree_node* next; + + if (!root) + return; + + tommy_tree_foreach_node(root->prev, func); + + /* make a copy in case func is free() */ + next = root->next; + + func(root->data); + + tommy_tree_foreach_node(next, func); +} + +void tommy_tree_foreach(tommy_tree* tree, tommy_foreach_func* func) +{ + tommy_tree_foreach_node(tree->root, func); +} + +static void tommy_tree_foreach_arg_node(tommy_tree_node* root, tommy_foreach_arg_func* func, void* arg) +{ + tommy_tree_node* next; + + if (!root) + return; + + tommy_tree_foreach_arg_node(root->prev, func, arg); + + /* make a copy in case func is free() */ + next = root->next; + + func(arg, root->data); + + tommy_tree_foreach_arg_node(next, func, arg); +} + +void tommy_tree_foreach_arg(tommy_tree* tree, tommy_foreach_arg_func* func, void* arg) +{ + tommy_tree_foreach_arg_node(tree->root, func, arg); +} + +tommy_size_t tommy_tree_memory_usage(tommy_tree* tree) +{ + return tommy_tree_count(tree) * sizeof(tommy_tree_node); +} + diff --git a/tommyds/tommytree.h b/tommyds/tommytree.h new file mode 100644 index 0000000..55e4006 --- /dev/null +++ b/tommyds/tommytree.h @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2015, Andrea Mazzoleni. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** \file + * AVL tree. + * + * This tree is a standard AVL tree implementation that stores elements in the + * order defined by the comparison function. + * + * As difference than other tommy containers, duplicate elements cannot be inserted. + * + * To initialize a tree you have to call tommy_tree_init() specifing a comparison + * function that will define the order in the tree. + * + * \code + * tommy_tree tree; + * + * tommy_tree_init(&tree, cmp); + * \endcode + * + * To insert elements in the tree you have to call tommy_tree_insert() for + * each element. + * In the insertion call you have to specify the address of the node and the + * address of the object. + * The address of the object is used to initialize the tommy_node::data field + * of the node. + * + * \code + * struct object { + * int value; + * // other fields + * tommy_tree_node node; + * }; + * + * struct object* obj = malloc(sizeof(struct object)); // creates the object + * + * obj->value = ...; // initializes the object + * + * tommy_tree_insert(&tree, &obj->node, obj); // inserts the object + * \endcode + * + * To find and element in the tree you have to call tommy_tree_search() providing + * the key to search. + * + * \code + * struct object value_to_find = { 1 }; + * struct object* obj = tommy_tree_search(&tree, &value_to_find); + * if (!obj) { + * // not found + * } else { + * // found + * } + * \endcode + * + * To remove an element from the tree you have to call tommy_tree_remove() + * providing the key to search and remove. + * + * \code + * struct object value_to_remove = { 1 }; + * struct object* obj = tommy_tree_remove(&tree, &value_to_remove); + * if (obj) { + * free(obj); // frees the object allocated memory + * } + * \endcode + * + * To destroy the tree you have to remove or destroy all the contained elements. + * The tree itself doesn't have or need a deallocation function. + * + * If you need to iterate over all the elements in the tree, you can use + * tommy_tree_foreach() or tommy_tree_foreach_arg(). + * If you need a more precise control with a real iteration, you have to insert + * all the elements also in a ::tommy_list, and use the list to iterate. + * See the \ref multiindex example for more detail. + */ + +#ifndef __TOMMYTREE_H +#define __TOMMYTREE_H + +#include "tommytypes.h" + +/******************************************************************************/ +/* tree */ + +/** + * Tree node. + * This is the node that you have to include inside your objects. + */ +typedef tommy_node tommy_tree_node; + +/** + * Tree container type. + * \note Don't use internal fields directly, but access the container only using functions. + */ +typedef struct tommy_tree_struct { + tommy_tree_node* root; /**< Root node. */ + tommy_count_t count; /**< Number of elements. */ + tommy_compare_func* cmp; /**< Comparison function. */ +} tommy_tree; + +/** + * Initializes the tree. + * \param cmp The comparison function that defines the orderin the tree. + */ +void tommy_tree_init(tommy_tree* tree, tommy_compare_func* cmp); + +/** + * Inserts an element in the tree. + * If the element is already present, it's not inserted again. + * Check the return value to identify if the element was already present or not. + * You have to provide the pointer of the node embedded into the object and + * the pointer to the object. + * \param node Pointer to the node embedded into the object to insert. + * \param data Pointer to the object to insert. + * \return The element in the tree. Either the already existing one, or the one just inserted. + */ +void* tommy_tree_insert(tommy_tree* tree, tommy_tree_node* node, void* data); + +/** + * Searches and removes an element. + * If the element is not found, 0 is returned. + * \param data Element used for comparison. + * \return The removed element, or 0 if not found. + */ +void* tommy_tree_remove(tommy_tree* tree, void* data); + +/** + * Searches an element in the tree. + * If the element is not found, 0 is returned. + * \param data Element used for comparison. + * \return The first element found, or 0 if none. + */ +void* tommy_tree_search(tommy_tree* tree, void* data); + +/** + * Searches an element in the tree with a specific comparison function. + * + * Like tommy_tree_search() but you can specify a different comparison function. + * Note that this function must define a suborder of the original one. + * + * The ::data argument will be the first argument of the comparison function, + * and it can be of a different type of the objects in the tree. + */ +void* tommy_tree_search_compare(tommy_tree* tree, tommy_compare_func* cmp, void* cmp_arg); + +/** + * Removes an element from the tree. + * You must already have the address of the element to remove. + * \return The tommy_node::data field of the node removed. + */ +void* tommy_tree_remove_existing(tommy_tree* tree, tommy_tree_node* node); + +/** + * Calls the specified function for each element in the tree. + * + * The elements are processed in order. + * + * You cannot add or remove elements from the inside of the callback, + * but can use it to deallocate them. + * + * \code + * tommy_tree tree; + * + * // initializes the tree + * tommy_tree_init(&tree, cmp); + * + * ... + * + * // creates an object + * struct object* obj = malloc(sizeof(struct object)); + * + * ... + * + * // insert it in the tree + * tommy_tree_insert(&tree, &obj->node, obj); + * + * ... + * + * // deallocates all the objects iterating the tree + * tommy_tree_foreach(&tree, free); + * \endcode + */ +void tommy_tree_foreach(tommy_tree* tree, tommy_foreach_func* func); + +/** + * Calls the specified function with an argument for each element in the tree. + */ +void tommy_tree_foreach_arg(tommy_tree* tree, tommy_foreach_arg_func* func, void* arg); + +/** + * Gets the number of elements. + */ +tommy_inline tommy_count_t tommy_tree_count(tommy_tree* tree) +{ + return tree->count; +} + +/** + * Gets the size of allocated memory. + * It includes the size of the ::tommy_tree_node of the stored elements. + */ +tommy_size_t tommy_tree_memory_usage(tommy_tree* tree); + +#endif + diff --git a/tommyds/tommytypes.h b/tommyds/tommytypes.h new file mode 100644 index 0000000..ff834cf --- /dev/null +++ b/tommyds/tommytypes.h @@ -0,0 +1,424 @@ +/* + * Copyright (c) 2010, Andrea Mazzoleni. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** \file + * Generic types. + */ + +#ifndef __TOMMYTYPES_H +#define __TOMMYTYPES_H + +/******************************************************************************/ +/* types */ + +#include + +#if defined(_MSC_VER) +typedef unsigned tommy_uint32_t; /**< Generic uint32_t type. */ +typedef unsigned _int64 tommy_uint64_t; /**< Generic uint64_t type. */ +typedef size_t tommy_uintptr_t; /**< Generic uintptr_t type. */ +#else +#include +typedef uint32_t tommy_uint32_t; /**< Generic uint32_t type. */ +typedef uint64_t tommy_uint64_t; /**< Generic uint64_t type. */ +typedef uintptr_t tommy_uintptr_t; /**< Generic uintptr_t type. */ +#endif +typedef size_t tommy_size_t; /**< Generic size_t type. */ +typedef ptrdiff_t tommy_ptrdiff_t; /**< Generic ptrdiff_t type. */ +typedef int tommy_bool_t; /**< Generic boolean type. */ + +/** + * Generic unsigned integer type. + * + * It has no specific size, as is used to store only small values. + * To make the code more efficient, a full 32 bit integer is used. + */ +typedef tommy_uint32_t tommy_uint_t; + +/** + * Generic unsigned integer for counting objects. + * + * TommyDS doesn't support more than 2^32-1 objects. + */ +typedef tommy_uint32_t tommy_count_t; + +/** \internal + * Type cast required for the C++ compilation. + * When compiling in C++ we cannot convert a void* pointer to another pointer. + * In such case we need an explicit cast. + */ +#ifdef __cplusplus +#define tommy_cast(type, value) static_cast(value) +#else +#define tommy_cast(type, value) (value) +#endif + +/******************************************************************************/ +/* heap */ + +/* by default uses malloc/calloc/realloc/free */ + +/** + * Generic malloc(), calloc(), realloc() and free() functions. + * Redefine them to what you need. By default they map to the C malloc(), calloc(), realloc() and free(). + */ +#if !defined(tommy_malloc) || !defined(tommy_calloc) || !defined(tommy_realloc) || !defined(tommy_free) +#include +#endif +#if !defined(tommy_malloc) +#define tommy_malloc malloc +#endif +#if !defined(tommy_calloc) +#define tommy_calloc calloc +#endif +#if !defined(tommy_realloc) +#define tommy_realloc realloc +#endif +#if !defined(tommy_free) +#define tommy_free free +#endif + +/******************************************************************************/ +/* modificators */ + +/** \internal + * Definition of the inline keyword if available. + */ +#if !defined(tommy_inline) +#if defined(_MSC_VER) || defined(__GNUC__) +#define tommy_inline static __inline +#else +#define tommy_inline static +#endif +#endif + +/** \internal + * Definition of the restrict keyword if available. + */ +#if !defined(tommy_restrict) +#if __STDC_VERSION__ >= 199901L +#define tommy_restrict restrict +#elif defined(_MSC_VER) || defined(__GNUC__) +#define tommy_restrict __restrict +#else +#define tommy_restrict +#endif +#endif + +/** \internal + * Hints the compiler that a condition is likely true. + */ +#if !defined(tommy_likely) +#if defined(__GNUC__) +#define tommy_likely(x) __builtin_expect(!!(x), 1) +#else +#define tommy_likely(x) (x) +#endif +#endif + +/** \internal + * Hints the compiler that a condition is likely false. + */ +#if !defined(tommy_unlikely) +#if defined(__GNUC__) +#define tommy_unlikely(x) __builtin_expect(!!(x), 0) +#else +#define tommy_unlikely(x) (x) +#endif +#endif + +/******************************************************************************/ +/* key */ + +/** + * Key type used in indexed data structures to store the key or the hash value. + */ +typedef tommy_uint32_t tommy_key_t; + +/** + * Bits into the ::tommy_key_t type. + */ +#define TOMMY_KEY_BIT (sizeof(tommy_key_t) * 8) + +/******************************************************************************/ +/* node */ + +/** + * Data structure node. + * This node type is shared between all the data structures and used to store some + * info directly into the objects you want to store. + * + * A typical declaration is: + * \code + * struct object { + * tommy_node node; + * // other fields + * }; + * \endcode + */ +typedef struct tommy_node_struct { + /** + * Next node. + * The tail node has it at 0, like a 0 terminated list. + */ + struct tommy_node_struct* next; + + /** + * Previous node. + * The head node points to the tail node, like a circular list. + */ + struct tommy_node_struct* prev; + + /** + * Pointer to the object containing the node. + * This field is initialized when inserting nodes into a data structure. + */ + void* data; + + /** + * Key used to store the node. + * With hashtables this field is used to store the hash value. + * With lists this field is not used. + */ + tommy_key_t key; +} tommy_node; + +/******************************************************************************/ +/* compare */ + +/** + * Compare function for elements. + * \param obj_a Pointer to the first object to compare. + * \param obj_b Pointer to the second object to compare. + * \return <0 if the first element is less than the second, ==0 equal, >0 if greather. + * + * This function is like the C strcmp(). + * + * \code + * struct object { + * tommy_node node; + * int value; + * }; + * + * int compare(const void* obj_a, const void* obj_b) + * { + * if (((const struct object*)obj_a)->value < ((const struct object*)obj_b)->value) + * return -1; + * if (((const struct object*)obj_a)->value > ((const struct object*)obj_b)->value) + * return 1; + * return 0; + * } + * + * tommy_list_sort(&list, compare); + * \endcode + * + */ +typedef int tommy_compare_func(const void* obj_a, const void* obj_b); + +/** + * Search function for elements. + * \param arg Pointer to the value to search as passed at the search function. + * \param obj Pointer to the object to compare to. + * \return ==0 if the value matches the element. !=0 if different. + * + * The first argument is a pointer to the value to search exactly + * as it's passed at the search function called. + * The second argument is a pointer to the object inside the hashtable to compare. + * + * The return value has to be 0 if the values are equal. != 0 if they are different. + * + * \code + * struct object { + * tommy_node node; + * int value; + * }; + * + * int compare(const void* arg, const void* obj) + * { + * const int* value_to_find = arg; + * const struct object* object_to_compare = obj; + * + * return *value_to_find != object_to_compare->value; + * } + * + * int value_to_find = 1; + * struct object* obj = tommy_hashtable_search(&hashtable, compare, &value_to_find, tommy_inthash_u32(value_to_find)); + * if (!obj) { + * // not found + * } else { + * // found + * } + * \endcode + * + */ +typedef int tommy_search_func(const void* arg, const void* obj); + +/** + * Foreach function. + * \param obj Pointer to the object to iterate. + * + * A typical example is to use free() to deallocate all the objects in a list. + * \code + * tommy_list_foreach(&list, (tommy_foreach_func*)free); + * \endcode + */ +typedef void tommy_foreach_func(void* obj); + +/** + * Foreach function with an argument. + * \param arg Pointer to a generic argument. + * \param obj Pointer to the object to iterate. + */ +typedef void tommy_foreach_arg_func(void* arg, void* obj); + +/******************************************************************************/ +/* bit hacks */ + +#if defined(_MSC_VER) && !defined(__cplusplus) +#include +#pragma intrinsic(_BitScanReverse) +#pragma intrinsic(_BitScanForward) +#endif + +/** \internal + * Integer log2 for constants. + * You can use it only for exact power of 2 up to 256. + */ +#define TOMMY_ILOG2(value) ((value) == 256 ? 8 : (value) == 128 ? 7 : (value) == 64 ? 6 : (value) == 32 ? 5 : (value) == 16 ? 4 : (value) == 8 ? 3 : (value) == 4 ? 2 : (value) == 2 ? 1 : 0) + +/** + * Bit scan reverse or integer log2. + * Return the bit index of the most significant 1 bit. + * + * If no bit is set, the result is undefined. + * To force a return 0 in this case, you can use tommy_ilog2_u32(value | 1). + * + * Other interesting ways for bitscan are at: + * + * Bit Twiddling Hacks + * http://graphics.stanford.edu/~seander/bithacks.html + * + * Chess Programming BitScan + * http://chessprogramming.wikispaces.com/BitScan + * + * \param value Value to scan. 0 is not allowed. + * \return The index of the most significant bit set. + */ +tommy_inline tommy_uint_t tommy_ilog2_u32(tommy_uint32_t value) +{ +#if defined(_MSC_VER) + unsigned long count; + _BitScanReverse(&count, value); + return count; +#elif defined(__GNUC__) + /* + * GCC implements __builtin_clz(x) as "__builtin_clz(x) = bsr(x) ^ 31" + * + * Where "x ^ 31 = 31 - x", but gcc does not optimize "31 - __builtin_clz(x)" to bsr(x), + * but generates 31 - (bsr(x) xor 31). + * + * So we write "__builtin_clz(x) ^ 31" instead of "31 - __builtin_clz(x)", + * to allow the double xor to be optimized out. + */ + return __builtin_clz(value) ^ 31; +#else + /* Find the log base 2 of an N-bit integer in O(lg(N)) operations with multiply and lookup */ + /* from http://graphics.stanford.edu/~seander/bithacks.html */ + static unsigned char TOMMY_DE_BRUIJN_INDEX_ILOG2[32] = { + 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, + 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 + }; + + value |= value >> 1; + value |= value >> 2; + value |= value >> 4; + value |= value >> 8; + value |= value >> 16; + + return TOMMY_DE_BRUIJN_INDEX_ILOG2[(tommy_uint32_t)(value * 0x07C4ACDDU) >> 27]; +#endif +} + +/** + * Bit scan forward or trailing zero count. + * Return the bit index of the least significant 1 bit. + * + * If no bit is set, the result is undefined. + * \param value Value to scan. 0 is not allowed. + * \return The index of the least significant bit set. + */ +tommy_inline tommy_uint_t tommy_ctz_u32(tommy_uint32_t value) +{ +#if defined(_MSC_VER) + unsigned long count; + _BitScanForward(&count, value); + return count; +#elif defined(__GNUC__) + return __builtin_ctz(value); +#else + /* Count the consecutive zero bits (trailing) on the right with multiply and lookup */ + /* from http://graphics.stanford.edu/~seander/bithacks.html */ + static const unsigned char TOMMY_DE_BRUIJN_INDEX_CTZ[32] = { + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 + }; + + return TOMMY_DE_BRUIJN_INDEX_CTZ[(tommy_uint32_t)(((value & - value) * 0x077CB531U)) >> 27]; +#endif +} + +/** + * Rounds up to the next power of 2. + * For the value 0, the result is undefined. + * \return The smallest power of 2 not less than the specified value. + */ +tommy_inline tommy_uint32_t tommy_roundup_pow2_u32(tommy_uint32_t value) +{ + /* Round up to the next highest power of 2 */ + /* from http://graphics.stanford.edu/~seander/bithacks.html */ + + --value; + value |= value >> 1; + value |= value >> 2; + value |= value >> 4; + value |= value >> 8; + value |= value >> 16; + ++value; + + return value; +} + +/** + * Check if the specified word has a byte at 0. + * \return 0 or 1. + */ +tommy_inline int tommy_haszero_u32(tommy_uint32_t value) +{ + return ((value - 0x01010101) & ~value & 0x80808080) != 0; +} +#endif +