From 8d2a0b593ed03c6880bd668af6ea33b8128a3408 Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Mon, 7 Jan 2019 14:06:15 +0100 Subject: [PATCH] Imported Upstream version 11.2 --- .version | 1 + AUTHORS | 27 + CHECK | 32 + COPYING | 674 ++ HISTORY | 763 ++ INSTALL | 31 + INSTALL.windows | 9 + Makefile.am | 1039 +++ Makefile.in | 1934 +++++ README | 32 + TODO | 360 + acinclude.m4 | 19 + aclocal.m4 | 838 ++ autogen.sh | 10 + autover.sh | 19 + cmdline/check.c | 2049 +++++ cmdline/device.c | 1001 +++ cmdline/dry.c | 470 + cmdline/dup.c | 160 + cmdline/elem.c | 1461 ++++ cmdline/elem.h | 1234 +++ cmdline/fnmatch.c | 500 ++ cmdline/fnmatch.h | 82 + cmdline/handle.c | 403 + cmdline/handle.h | 88 + cmdline/import.c | 322 + cmdline/import.h | 74 + cmdline/io.c | 1006 +++ cmdline/io.h | 400 + cmdline/list.c | 123 + cmdline/mingw.c | 2797 ++++++ cmdline/mingw.h | 418 + cmdline/mkstream.c | 269 + cmdline/mktest.c | 794 ++ cmdline/murmur3.c | 180 + cmdline/murmur3test.c | 264 + cmdline/parity.c | 899 ++ cmdline/parity.h | 132 + cmdline/pool.c | 470 + cmdline/portable.h | 492 ++ cmdline/rehash.c | 98 + cmdline/scan.c | 1926 +++++ cmdline/scrub.c | 902 ++ cmdline/search.c | 287 + cmdline/search.h | 64 + cmdline/selftest.c | 640 ++ cmdline/snapraid.c | 1511 ++++ cmdline/snapraid.h | 28 + cmdline/speed.c | 948 ++ cmdline/spooky2.c | 162 + cmdline/spooky2test.c | 264 + cmdline/state.c | 4706 ++++++++++ cmdline/state.h | 385 + cmdline/status.c | 531 ++ cmdline/stream.c | 757 ++ cmdline/stream.h | 416 + cmdline/support.c | 1716 ++++ cmdline/support.h | 437 + cmdline/sync.c | 1610 ++++ cmdline/touch.c | 146 + cmdline/unix.c | 1563 ++++ cmdline/unix.h | 67 + cmdline/util.c | 641 ++ cmdline/util.h | 224 + compile | 347 + config.guess | 1421 +++ config.h.in | 422 + config.sub | 1807 ++++ configure | 8191 ++++++++++++++++++ configure.ac | 372 + configure.windows-x64 | 3 + configure.windows-x86 | 3 + install-sh | 501 ++ missing | 215 + raid/COPYING | 339 + raid/check.c | 185 + raid/combo.h | 155 + raid/cpu.h | 331 + raid/gf.h | 137 + raid/helper.c | 94 + raid/helper.h | 43 + raid/int.c | 556 ++ raid/internal.h | 274 + raid/intz.c | 119 + raid/memory.c | 154 + raid/memory.h | 96 + raid/module.c | 473 + raid/raid.c | 586 ++ raid/raid.h | 229 + raid/tables.c | 14696 ++++++++++++++++++++++++++++++++ raid/tag.c | 145 + raid/test.c | 452 + raid/test.h | 68 + raid/test/Makefile | 99 + raid/test/fulltest.c | 124 + raid/test/invtest.c | 176 + raid/test/selftest.c | 40 + raid/test/speedtest.c | 851 ++ raid/x86.c | 2452 ++++++ raid/x86z.c | 255 + snapraid.1 | 1799 ++++ snapraid.conf.example | 93 + snapraid.conf.example.windows | 108 + snapraid.d | 1336 +++ snapraid.txt | 1441 ++++ test/test-par1.conf | 17 + test/test-par2.conf | 15 + test/test-par3.conf | 17 + test/test-par4.conf | 19 + test/test-par5.conf | 21 + test/test-par6-hole.conf | 22 + test/test-par6-noaccess.conf | 25 + test/test-par6-rename.conf | 24 + test/test-par6.conf | 25 + tommyds/LICENSE | 24 + tommyds/tommy.c | 42 + tommyds/tommyarray.c | 83 + tommyds/tommyarray.h | 151 + tommyds/tommyarrayblkof.c | 83 + tommyds/tommyarrayblkof.h | 114 + tommyds/tommychain.h | 224 + tommyds/tommyhash.c | 241 + tommyds/tommyhash.h | 140 + tommyds/tommyhashdyn.c | 224 + tommyds/tommyhashdyn.h | 296 + tommyds/tommylist.c | 60 + tommyds/tommylist.h | 399 + tommyds/tommytree.c | 292 + tommyds/tommytree.h | 228 + tommyds/tommytypes.h | 424 + 130 files changed, 86303 insertions(+) create mode 100644 .version create mode 100644 AUTHORS create mode 100644 CHECK create mode 100644 COPYING create mode 100644 HISTORY create mode 100644 INSTALL create mode 100644 INSTALL.windows create mode 100644 Makefile.am create mode 100644 Makefile.in create mode 100644 README create mode 100644 TODO create mode 100644 acinclude.m4 create mode 100644 aclocal.m4 create mode 100755 autogen.sh create mode 100755 autover.sh create mode 100644 cmdline/check.c create mode 100644 cmdline/device.c create mode 100644 cmdline/dry.c create mode 100644 cmdline/dup.c create mode 100644 cmdline/elem.c create mode 100644 cmdline/elem.h create mode 100644 cmdline/fnmatch.c create mode 100644 cmdline/fnmatch.h create mode 100644 cmdline/handle.c create mode 100644 cmdline/handle.h create mode 100644 cmdline/import.c create mode 100644 cmdline/import.h create mode 100644 cmdline/io.c create mode 100644 cmdline/io.h create mode 100644 cmdline/list.c create mode 100644 cmdline/mingw.c create mode 100644 cmdline/mingw.h create mode 100644 cmdline/mkstream.c create mode 100644 cmdline/mktest.c create mode 100644 cmdline/murmur3.c create mode 100644 cmdline/murmur3test.c create mode 100644 cmdline/parity.c create mode 100644 cmdline/parity.h create mode 100644 cmdline/pool.c create mode 100644 cmdline/portable.h create mode 100644 cmdline/rehash.c create mode 100644 cmdline/scan.c create mode 100644 cmdline/scrub.c create mode 100644 cmdline/search.c create mode 100644 cmdline/search.h create mode 100644 cmdline/selftest.c create mode 100644 cmdline/snapraid.c create mode 100644 cmdline/snapraid.h create mode 100644 cmdline/speed.c create mode 100644 cmdline/spooky2.c create mode 100644 cmdline/spooky2test.c create mode 100644 cmdline/state.c create mode 100644 cmdline/state.h create mode 100644 cmdline/status.c create mode 100644 cmdline/stream.c create mode 100644 cmdline/stream.h create mode 100644 cmdline/support.c create mode 100644 cmdline/support.h create mode 100644 cmdline/sync.c create mode 100644 cmdline/touch.c create mode 100644 cmdline/unix.c create mode 100644 cmdline/unix.h create mode 100644 cmdline/util.c create mode 100644 cmdline/util.h create mode 100755 compile create mode 100755 config.guess create mode 100644 config.h.in create mode 100755 config.sub create mode 100755 configure create mode 100644 configure.ac create mode 100755 configure.windows-x64 create mode 100755 configure.windows-x86 create mode 100755 install-sh create mode 100755 missing create mode 100644 raid/COPYING create mode 100644 raid/check.c create mode 100644 raid/combo.h create mode 100644 raid/cpu.h create mode 100644 raid/gf.h create mode 100644 raid/helper.c create mode 100644 raid/helper.h create mode 100644 raid/int.c create mode 100644 raid/internal.h create mode 100644 raid/intz.c create mode 100644 raid/memory.c create mode 100644 raid/memory.h create mode 100644 raid/module.c create mode 100644 raid/raid.c create mode 100644 raid/raid.h create mode 100644 raid/tables.c create mode 100644 raid/tag.c create mode 100644 raid/test.c create mode 100644 raid/test.h create mode 100644 raid/test/Makefile create mode 100644 raid/test/fulltest.c create mode 100644 raid/test/invtest.c create mode 100644 raid/test/selftest.c create mode 100644 raid/test/speedtest.c create mode 100644 raid/x86.c create mode 100644 raid/x86z.c create mode 100644 snapraid.1 create mode 100644 snapraid.conf.example create mode 100644 snapraid.conf.example.windows create mode 100644 snapraid.d create mode 100644 snapraid.txt create mode 100644 test/test-par1.conf create mode 100644 test/test-par2.conf create mode 100644 test/test-par3.conf create mode 100644 test/test-par4.conf create mode 100644 test/test-par5.conf create mode 100644 test/test-par6-hole.conf create mode 100644 test/test-par6-noaccess.conf create mode 100644 test/test-par6-rename.conf create mode 100644 test/test-par6.conf create mode 100644 tommyds/LICENSE create mode 100644 tommyds/tommy.c create mode 100644 tommyds/tommyarray.c create mode 100644 tommyds/tommyarray.h create mode 100644 tommyds/tommyarrayblkof.c create mode 100644 tommyds/tommyarrayblkof.h create mode 100644 tommyds/tommychain.h create mode 100644 tommyds/tommyhash.c create mode 100644 tommyds/tommyhash.h create mode 100644 tommyds/tommyhashdyn.c create mode 100644 tommyds/tommyhashdyn.h create mode 100644 tommyds/tommylist.c create mode 100644 tommyds/tommylist.h create mode 100644 tommyds/tommytree.c create mode 100644 tommyds/tommytree.h create mode 100644 tommyds/tommytypes.h 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 +