jfsutils-1.1.15.orig/0000755000000000000000000000000011534235600011266 5ustar jfsutils-1.1.15.orig/AUTHORS0000644000000000000000000000064611534235035012346 0ustar Barry Arndt Steve Best William Braswell Christoph Hellwig Dave Kleikamp Ross A. Knepper Jim Nance Joe Nuspl Hiten Pandya Terence Rokop Jan Van Sweevelt Karl Rister jfsutils-1.1.15.orig/COPYING0000644000000000000000000010451311460142743012330 0ustar 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 . jfsutils-1.1.15.orig/ChangeLog0000644000000000000000000016674111534235035013061 0ustar 2011-03-04 Dave Kleikamp * configure.in: Bumped version to 1.1.15 * NEWS: likewise * README: likewise * AUTHORS: update email address * jfsutils.spec.in: likewise 2011-02-25 Dave Kleikamp * fsck/fsckdtre.c: directory size reflects size of directory index * fsck/fsckmeta.c: another 64-bit fix 2010-06-04 Dave Kleikamp * fsck/xchkdsk.c: Fix inconsistent timestamp format 2010-06-03 Dave Kleikamp * fsck/fsckpfs.c: use 64-bit value to address extent length * fsck/fsckwsp.c: use 64-bit values for block map size * mkfs/mkfs.c: use 64-bit values for additional structures 2010-01-07 Dave Kleikamp * libfs/log_dump.c: handle positive error value from find_log() 2009-11-30 Dave Kleikamp * mkfs/initmap.c: use 64-bit integers to handle volumes over 32 TB * mkfs/initmap.h: likewise 2009-07-13 Dave Kleikamp * tune/jfs_tune.8: file systems CAN share an external journal 2009-04-06 Dave Kleikamp * configure.in: Bumped version to 1.1.14 * NEWS: likewise * README: likewise * jfsutils.spec.in: update email address 2009-04-03 Dave Kleikamp * fsck/fsck_message.c: Don't call printf with an untrusted format 2009-03-23 Dave Kleikamp * libfs/devices.c: Don't call ioctl(BLKFLSBUF) on a ramdisk 2009-01-09 Dave Kleikamp * mkfs/mkfs.c: increase log size limit from 32 MB to 128 MB 2008-09-13 Dave Kleikamp * libfs/log_read.c: moveWords must handle records that span 3 pages 2008-07-17 Dave Kleikamp * configure.in: Bumped version to 1.1.13 * NEWS: likewise * README: likewise 2008-03-24 Dave Kleikamp * libfs/fsckmsgdef.c: get rid of unhelpful allocation messages * libfs/log_map.c: likewise * libfs/log_work.c: likewise 2008-01-14 Dave Kleikamp * libfs/devices.c: define _LARGEFILE_SOURCE explictly 2007-09-28 Dave Kleikamp * libfs/log_work.c: Sanity check lock list ranges * libfs/logredo.h: Add new error return code 2007-09-17 Dave Kleikamp * libfs/message.c: Rewrite a confusing error message 2007-08-24 Dave Kleikamp * configure.in: Bumped version to 1.1.12 * NEWS: likewise * README: likewise 2007-08-23 Dave Kleikamp * libfs/fssubs.c: open() needs a mode parameter with O_CREAT 2007-08-22 Dave Kleikamp * fsck/fsckpfs.c: Allow -n flag to be used in conjuction with others * fsck/xchkdsk.c: Likewise 2007-07-23 Dave Kleikamp * libfs/open_by_label.c: look for external journal in /proc/mdstat 2007-04-07 Dave Kleikamp * configure.in: Support for netbsd (Submitted by Gary Thorpe) * libfs/devices.c: Likewise * libfs/fssubs.c: Likewise * mkfs/mkfs.c: Likewise 2007-03-20 Dave Kleikamp * libfs/logform.c: Don't close journal file descriptor * mkfs/mkfs.c: caller of jfs_logform() should close file descriptor 2006-11-02 Dave Kleikamp * libfs/jfs_endian.c: Fix bug possible array overflow 2006-08-21 Dave Kleikamp * libfs/jfs_endian.c: Fix bug on legacy partition on big-endian hw 2006-06-05 Dave Kleikamp * configure.in: Add compiler flags to generate useful warnings * mkfs/makefile.am: Likewise * defrag/helpers.h: Eliminate compiler warnings * fsck/fsck_message.c: Likewise * fsck/fsckbmap.c: Likewise * fsck/fsckdire.c: Likewise * fsck/fsckdtre.c: Likewise * fsck/fsckimap.c: Likewise * fsck/fsckino.c: Likewise * fsck/fsckmeta.c: Likewise * fsck/fsckpfs.c: Likewise * fsck/fsckruns.c: Likewise * fsck/fsckwsp.c: Likewise * fsck/fsckxtre.c: Likewise * fsck/xchkdsk.c: Likewise * fscklog/extract.c: Likewise * fscklog/fscklog.c: Likewise * fscklog/jfs_fscklog.h: Likewise * libfs/diskmap.h: Likewise * libfs/fsck_message.h: Likewise * libfs/jfs_endian.c: Likewise * libfs/log_dump.c: Likewise * libfs/super.h: Likewise * libfs/utilsubs.h: Likewise * mkfs/mkfs.c: Likewise * tune/tune.c: Likewise * xpeek/alter.c: Likewise * xpeek/directory.c: Likewise * xpeek/display.c: Likewise * xpeek/dmap.c: Likewise * xpeek/fsckcbbl.c: Likewise * xpeek/help.c: Likewise * xpeek/iag.c: Likewise * xpeek/inode.c: Likewise * xpeek/io.c: Likewise * xpeek/super.c: Likewise * xpeek/super2.c: Likewise * xpeek/ui.c: Likewise * xpeek/xpeek.c: Likewise * README: Bumped version to 1.1.11 * NEWS: Likewise 2006-06-04 Dave Kleikamp * libfs/log_work.c: Fix segfault in markImap 2006-05-26 Dave Kleikamp * fsck/fsckxtre.c: Using incorrect pointer resulted in trap 2006-05-24 Dave Kleikamp * fsck/fsck_message.c: define _GNU_SOURCE to get proto for basename() 2006-05-24 Manuel Menal * configure.in: porting jfsutils to GNU/Hurd * libfs/devices.c: Likewise * mkfs/initmap.c: Likewise * xpeek/directory.c: Likewise 2006-04-15 Dave Kleikamp * fsck/fsckdtre.c: Fix buffer overflow 2006-01-11 Dave Kleikamp * fsck/dirindex.c: dirty_index_page should be void * fsck/fsckxtre.c: avoid infinite loop in xTree_binsrch_page * mkfs/mkfs.c: Remove (Expermental) from usage statement 2005-11-22 Dave Kleikamp * Too many to list: Clean up includes & remove trailing whitespace 2005-11-08 Dave Kleikamp * configure.in: Add AC_CHECK_FUNCS(posix_memalign memalign) * mkfs/initmap.c: Fix infinite loop in verify_last_blocks (mkfs.jfs -c) 2005-11-08 Jon Nelson * libfs/devices.c: Fix invalid assumption that fseeko returns position 2005-10-24 Mads Martin Joergensen * configure.in: Bumped version to 1.1.10 * NEWS: likewise * README: likewise 2005-10-18 Dave Kleikamp * libfs/fssubs.c: fsck not recoginizing root filesystem as jfs 2005-10-04 Dave Kleikamp * libfs/devices.c: Only call rewind on error 2005-10-04 Jon Nelson * libfs/devices.c: More stdio cleanup 2005-10-04 Dave Kleikamp * configure.in: Bumped version to 1.1.9 * NEWS: likewise * README: likewise 2005-10-03 Dave Kleikamp * fsck/fsckdtre.c: Eliminate OS/2 DASD Limits code to save memory * fsck/fsckimap.c: Likewise * fsck/fsckino.c: Likewise * fsck/fsckmeta.c: Likewise * fsck/fsckwsp.c: Likewise * fsck/xchkdsk.c: Likewise * fsck/xfsckint.h: Likewise * libfs/fsckwsp.h: Likewise 2005-10-03 Hiten Pandya Dave Kleikamp * AUTHORS: Add Hiten Pandya * configure.in: Changes for compatibility with Dragonfly BSD * fsck/fsckdire.c: Likewise * fsck/fsckpfs.c: Likewise * fsck/xchkdsk.c: Likewise * fsck/xfsckint.h: Likewise * fscklog/Makefile.am: Likewise * fscklog/extract.c: Likewise * libfs/Makefile.am: Likewise * libfs/devices.c: Likewise * libfs/devices.h: Likewise * libfs/inode.c: Likewise * libfs/inode.h: Likewise * libfs/log_dump.c: Likewise * libfs/log_map.c: Likewise * libfs/log_read.c: Likewise * libfs/log_work.c: Likewise * libfs/logform.c: Likewise * libfs/logform.h: Likewise * libfs/logredo.c: Likewise * libfs/logredo.h: Likewise * libfs/open_by_label.c: Likewise * libfs/super.c: Likewise * libfs/super.h: Likewise * libfs/utilsubs.h: Likewise * logdump/Makefile.am: Likewise * logdump/logdump.c: Likewise * mkfs/Makefile.am: Likewise * mkfs/initmap.c: Likewise * mkfs/initmap.h: Likewise * mkfs/inodemap.c: Likewise * mkfs/inodemap.h: Likewise * mkfs/inodes.c: Likewise * mkfs/inodes.h: Likewise * mkfs/mkfs.c: Likewise * tune/Makefile.am: Likewise * tune/tune.c: Likewise * xpeek/Makefile.am: Likewise * xpeek/alter.c: Likewise * xpeek/display.c: Likewise * xpeek/dmap.c: Likewise * xpeek/fsckcbbl.c: Likewise * xpeek/inode.c: Likewise * xpeek/io.c: Likewise * xpeek/super.c: Likewise * xpeek/super2.c: Likewise * xpeek/xpeek.c: Likewise * xpeek/xpeek.h: Likewise 2005-08-15 Dave Kleikamp * libfs/fssubs.c: Fix stack buffer overflow in Is_Device_Mounted 2005-06-29 Dave Kleikamp * mkfs/mkfs.c: Fix problem with option -J journal_dev 2005-06-20 Dave Kleikamp * fsck/fsckmeta.c: fsck shouldn't quit if unused aggregate inode is bad 2005-06-16 Dave Kleikamp * fsck/fsck_message.c: use basename(file_name) to avoid overlong msgs * libfs/fsck_message.h: add declaration of v_fsck_send_msg to header * libfs/logredo.c: declaration of v_fsck_send_msg is now in header 2005-05-03 Dave Kleikamp * mkfs/initmap.c: Use O_DIRECT when checking for bad blocks * configure.in: Bumped version to 1.1.8 * NEWS: likewise * README: likewise 2005-04-29 Dave Kleikamp * fsck/dirindex.c: Update directory index table when moving entries * fsck/fsckdire.c: Likewise * fsck/fsckdtre.c: Likewise * fsck/xchkdsk.c: Likewise * fsck/xfsckint.h: Likewise * include/jfs_dtree.c: Likewise 2005-04-18 Dave Kleikamp * fsck/fsckmeta.c: ignore errors in inode 1 in phase 3 too 2005-03-22 Dave Kleikamp * libfs/log_work.c: Don't let i_data update wipe out btroot 2005-03-16 Dave Kleikamp * fsck/fsckpfs.c: Make sure data gets flushed to disk * libfs/devices.c: Likewise * libfs/devices.h: Likewise * libfs/logform.c: Likewise * mkfs/mkfs.c: Likewise * xpeek/xpeek.c: Likewise * defrag/helpers.c: Get rid of silly HFILE define * defrag/helpers.h: Likewise * fsck/dirindex.c: Likewise * fsck/fsckbmap.c: Likewise * fsck/fsckcbbl.c: Likewise * fsck/fsckconn.c: Likewise * fsck/fsckdtre.c: Likewise * fsck/fsckimap.c: Likewise * fsck/fsckino.c: Likewise * fsck/fsckmeta.c: Likewise * fsck/fsckwsp.c: Likewise * fsck/fsckxtre.c: Likewise * fsck/xchkdsk.c: Likewise * fsck/xfsckint.h: Likewise * fscklog/extract.c: Likewise * libfs/inode.c: Likewise * libfs/inode.h: Likewise * libfs/super.c: Likewise * libfs/super.h: Likewise * logdump/logdump.c: Likewise * mkfs/initmap.c: Likewise * mkfs/inodemap.c: Likewise * mkfs/inodemap.h: Likewise * mkfs/inodes.c: Likewise * mkfs/inodes.h: Likewise * xpeek/xpeek.h: Likewise 2005-03-09 Dave Kleikamp * fsck/fsck.c: Added blocks pararmeter to specify file system size * fsck/jfs_fsck.8: Likewise. 2005-02-18 Dave Kleikamp * README: Homepage changed to sourceforge.net * jfsutils.spec.in: Likewise. * fsck/jfs_fsck.8: Likewise * fscklog/jfs_fscklog.8: Likewise * logdump/jfs_logdump.8: Likewise * mkfs/jfs_mkfs.8: Likewise * tune/jfs_tune.8: Likewise * xpeek/jfs_debugfs.8: Likewise 2004-12-15 Dave Kleikamp * fsck/dirindex.c: Remove unused variables & eliminate compiler warnings * fsck/fsckbmap.c: Likewise * fsck/fsckcbbl.c: Likewise * fsck/fsckconn.c: Likewise * fsck/fsckdtre.c: Likewise * fsck/fsckimap.c: Likewise * fsck/fsckino.c: Likewise * fsck/fsckmeta.c: Likewise * fsck/fsckpfs.c: Likewise * fsck/fsckwsp.c: Likewise * fsck/fsckxtre.c: Likewise * fsck/xchkdsk.c: Likewise * fscklog/display.c: Likewise * fscklog/extract.c: Likewise * fscklog/fscklog.c: Likewise * libfs/log_dump.c: Likewise * libfs/log_map.c: Likewise * libfs/log_read.c: Likewise * libfs/log_work.c: Likewise * libfs/logredo.c: Likewise * libfs/logredo.h: Likewise * logdump/helpers.c: Likewise * logdump/logdump.c: Likewise 2004-12-02 Dave Kleikamp * libfs/devices.c: print message on read/write errors 2004-11-02 Dave Kleikamp * libfs/logform.c: pad log_sup to 4K since we do 4K reads & writes on it 2004-09-24 Dave Kleikamp * fsck/fsckmeta.c: Don't bail out if reserved inode 1 is bad * fsck/xchkdsk.c: If phase 1 fails, don't act like it's ok * libfs/logredo.c: always rebuild inode map, even if sb is dirty 2004-07-22 Dave Kleikamp * fsck/fsckconn.c: Pass proper number of args to fsck_send_msg * libfs/fsckmsgdef.c: Lots of message corrections * fsck/fsckdtre.c: directory index table fixes for big endian systems * fsck/fsckino.c: Likewise * libfs/jfs_endian.c: Likewise * xpeek/directory.c: Likewise * fsck/xchkdsk.c: Warn that running fsck on mounted fs is not dependable * configure.in: Bumped version to 1.1.7 * NEWS: likewise * README: likewise 2004-07-21 Dave Kleikamp * fsck/fsckea.c: Verify that xattr length is correct * fsck/fsckino.c: Likewise * fsck/xfsck.h: Likewise 2004-06-29 Dave Kleikamp * libfs/logredo.c: Ensure changes to disk occur in proper order 2004-05-24 Dave Kleikamp * fsck/xchkdsk.c: --replay_journal_only shouldn't clear FM_DIRTY 2004-04-26 Dave Kleikamp * configure.in: Bumped version to 1.1.6. * NEWS: likewise * README: likewise * fsck/Makefile.am: Add new source file: dirindex.c * fsck/dirindex.c: verify and reset directory index table * fsck/fsckdtre.c: Likewise * fsck/fsckino.c: Likewise * fsck/fsckpfs.c: Likewise * fsck/fsckwsp.c: Likewise * fsck/fsckxtre.c: Likewise * fsck/xchkdsk.c: Likewise * fsck/xfsckint.h: Likewise * include/jfs_dtree.h: Likewise * libfs/fsck_message.h: Likewise * libfs/fsckmsgdef.c: Likewise * libfs/fsckwsp.h: Likewise 2004-04-26 Dave Kleikamp * fsck/fsckdtre.c: restructure dTree_process_leaf_slots for readability 2004-04-19 Dave Kleikamp * fsck/fsckdtre.c: restructure dTree_processing for readability 2004-04-12 Dave Kleikamp * tune/tune.c: Change superblock version to 2 if setting uuid 2004-03-04 Dave Kleikamp * configure.in: Bumped version to 1.1.5. * NEWS: likewise * README: likewise * fsck/xchkdsk.c: Support multiple volumes sharing journal * libfs/fsck_message.h: Likewise * libfs/fsckmsgdef.c: Likewise * libfs/log_dump.c: Likewise * libfs/log_read.c: Likewise * libfs/log_work.c: Likewise * libfs/logredo.c: Likewise * libfs/logredo.h: Likewise * libfs/open_by_label.c: Likewise * mkfs/mkfs.c: Likewise * tune/tune.c: Likewise 2004-01-29 Dave Kleikamp * tune/tune.c: Don't use O_EXCL unless filesystem should be unmounted * xpeek/xpeek.c: Don't use O_EXCL 2004-01-21 Dave Kleikamp * libfs/devices.h: remove dev_to_kdev * libfs/logredo.c: likewise * mkfs/mkfs.c: likewise * tune/tune.c: likewise * libfs/fsckmsgdef.c: fix errant message that caused a seg fault * fsck/fsckconn.c: likewise 2003-12-17 Dave Kleikamp * fsck/fsckmeta.c: Rework duplicate block checking to avoid horrible performance * fsck/fsckwsp.c: likewise * fsck/xfsckint.h: likewise * libfs/fsckwsp.h: likewise * libfs/fsck_message.h: Remove redundant semicolons 2003-12-10 Dave Kleikamp * libfs/log_work.c: fix replaying of symlink journal records 2003-12-09 Dave Kleikamp * fsck/xchkdsk.c: fix buffer overflow 2003-11-10 Dave Kleikamp * fsck/fsckdire.c: zero directory index field * fsck/fsckdtre.c: shorten names in lost+found 2003-10-30 Dave Kleikamp * configure.in: Bumped version to 1.1.4. * NEWS: likewise * README: likewise 2003-10-21 Dave Kleikamp * libfs/fsckmsgdef.c: Message format fix 2003-10-15 Dave Kleikamp * fscklog/fscklog.c: Add missing prototype, submitted by Stasys Smailys 2003-10-14 Dave Kleikamp * libfs/devices.c: BLKGETSIZE64 definition had incorrect parameter 2003-09-16 Dave Kleikamp * fsck/fsck_message.c: Handle log full without crashing 2003-09-11 Dave Kleikamp * libfs/fsck_message.h: Work around gcc 2.95 bug 2003-09-05 Dave Kleikamp * fsck/fsckpfs.c: Attempt r/w open without O_EXCL * libfs/fsckmsgdef.c: Add back carriage return for heartbeat msgs * configure.in: Bumped version to 1.1.3. * NEWS: likewise * README: likewise * AUTHORS: likewise 2003-08-01 Karl Rister * fsck/xchkdsk.c: Return 0 when the journal is replayed successfully 2003-07-07 Dave Kleikamp * tune/super.c: Do not right-justify when printing volume label * xpeek/super.c: Likewise. 2003-06-25 Karl Rister * Cleaned up fsck messages by making single function call without the use of global variables * libfs/fsck_message.h: New file to cleanup fsck messages * libfs/fsckmsgdef.c: Likewise * fsck/fsck_message.c: Likewise * libfs/fsckmsgc.h: Removed as part of fsck message cleanup * libfs/fsckmsge.h: Likewise * fsck/fsckmsgs.c: Likewise * fsck/fsckmsgp.h: Likewise * fsck/Makefile.am: Modified as part of fsck message cleanup * fsck/fsckbmap.c: Likewise * fsck/fsckcbbl.c: Likewise * fsck/fsckconn.c: Likewise * fsck/fsckdtre.c: Likewise * fsck/fsckimap.c: Likewise * fsck/fsckino.c: Likewise * fsck/fsckmeta.c: Likewise * fsck/fsckpfs.c: Likewise * fsck/fsckruns.c: Likewise * fsck/fsckwsp.c: Likewise * fsck/fsckwsp.c: Likewise * fsck/fsckxtre.c: Likewise * fsck/xchkdsk.c: Likewise * fsck/xfsckint.h: Likewise * fscklog/display.c: Likewise * fscklog/extract.c: Likewise * fscklog/fscklog.c: Likewise * fscklog/jfs_fscklog.h: Likewise * libfs/Makefile.am: Likewise * libfs/fscklog.h: Likewise * libfs/jfs_endian.c: Likewise * libfs/log_map.c: Likewise * libfs/log_read.c: Likewise * libfs/log_work.c: Likewise * libfs/logredo.c: Likewise * logdump/helpers.c: Likewise * logdump/logdump.c: Likewise 2003-05-22 Dave Kleikamp * libfs/open_by_label.c: Look for evms volumes in /dev/evms 2003-04-24 Dave Blaschke * fsck/fsckwsp.c: start_time formatted incorrectly * fsck/xchkdsk.c: end_time stored incorrectly 2003-03-25 Dave Blaschke * README: Updated reference to mailing lists. 2003-03-25 Dave Kleikamp * configure.in: Bumped version to 1.1.2. * NEWS: likewise * README: likewise 2003-03-21 Dave Blaschke * tune/super.c: s_label displayed incorrectly when 16 chars long. * xpeek/super.c: Likewise. * xpeek/super2.c: Likewise. 2003-03-07 Dave Blaschke * fsck/fsckbmap.c: Code cleanup suggested by static analysis tool. * fsck/fsckdire.c: Likewise. * fsck/fsckdtre.c: Likewise. * fsck/fsckimap.c: Likewise. * fsck/fsckino.c: Likewise. * fsck/fsckmeta.c: Likewise. * fsck/fsckpfs.c: Likewise. * fsck/fsckxtre.c: Likewise. * fsck/xchkdsk.c: Likewise. * fscklog/extract.c: Likewise. * libfs/log_dump.c: Likewise. * libfs/log_map.c: Likewise. * libfs/log_work.c: Likewise. * libfs/logredo.c: Likewise. * mkfs/mkfs.c: Likewise. * xpeek/dmap.c: Likewise. 2003-02-07 Dave Kleikamp * libfs/logredo.c: for-loop was going past end of vopen array * fsck/fsckimap: Was not checking for negative this_ag 2003-01-27 Dave Kleikamp * libfs/devices.c: Wrap long lines to 80 columns. * libfs/devices.c: Allow jfs_mkfs to run on regular file. * mkfs/mkfs.c: Likewise. 2003-01-27 Steve Best * README: Remove linuxjfs e-mail id. * jfsutils.spec.in: Likewise. 2003-01-17 Dave Kleikamp * fsck/fsckimap.c: Restructure code to reduce indenting. 2003-01-13 Barry Arndt * fsck/fsckbmap.c: Restructure code to reduce indenting. * fsck/fsckimap.c: Likewise. * fsck/fsckmeta.c: Likewise. * fsck/fsckpfs.c: Likewise. * fsck/fsckwsp.c: Likewise. * fsck/xchkdsk.c: Likewise. 2003-01-06 Steve Best * Fix undefined reference to 'errno' (G. D. Haraldsson) * libfs/fssubs.c: Include instead of extern int errno * libfs/log_dump.c: Likewise. * libfs/log_map.c: Likwwise. * libfs/log_read.c: Likewise. * libfs/logredo.c: Likewise. 2002-12-17 Dave Kleikamp * configure.in: Bumped version to 1.1.1. * README: Likewise. * NEWS: Likewise. 2002-12-11 Barry Arndt * mkfs/mkfs.c (main): Fix seg fault - use proper device_name pointer when printing "not a valid block device" error message. 2002-12-04 Dave Kleikamp * xpeek/directory.c: Show and allow modification of directory index 2002-12-02 Steve Best * Add note about uuid.h file required to build utilities (Bob Cochran) * remove info about 2.5 cvs tree 2002-11-20 Barry Arndt * jfs_fscklog/Makefile.am: add jfs_fscklog.h to SOURCES * configure.in: Bumped version to 1.1.0. * README: Likewise. * NEWS: Likewise. 2002-11-19 Barry Arndt * fsck/fsckconn.c: Remove unused parameter current_fsck_phase. * fsck/fsckdtre.c: Likewise. * fsck/fsckino.c: Likewise. * fsck/fsckpfs.c: Likewise. * fsck/fsckwsp.c: Likewise. * fsck/fsckxtre.c: Likewise. * fsck/xchkdsk.c: Likewise. * fsck/xfsck.h: Likewise. 2002-11-19 Dave Kleikamp * fsck/fsckino.c: Fix off-by-one error validate_data 2002-11-14 Dave Kleikamp * fsck/fsckino.c: Restructure code to reduce indenting. Fix bogus minor format error when inline symlink is greater than 128 bytes. 2002-11-13 Dave Kleikamp * xpeek/inode.c: jfs_debugfs should recognize all inode types 2002-11-12 Dave Kleikamp * fsck/fsckxtre.c: Restructure code to reduce indenting. Allow zero key of intermediate xad, even if first leaf key is non-zero. 2002-10-30 Barry Arndt * jfsutils.spec.in: Rename logdump to jfs_logdump, rename xpeek to jfs_debugfs. * logdump/Makefile.am: Rename logdump to jfs_logdump. * logdump/helpers.c: Likewise. * logdump/logdump.c: Likewise. * logdump/jfs_logdump.8: Add renamed man page. * logdump/logdump.8: Remove. * xpeek/Makefile.am: Rename xpeek to jfs_debugfs. * xpeek/help.c: Likewise. * xpeek/xpeek.c: Likewise. * xpeek/jfs_debugfs.8: Add renamed man page. * xpeek/xpeek.8: Remove. * fsck/jfs_fsck.8: Update 'SEE ALSO' program names with new names. * fscklog/jfs_fscklog.8: Likewise. * mkfs/jfs_mkfs.8: Likewise. * tune/jfs_tune.8: Likewise. * fsck/Makefile.am: Change install-exec-local to install-exec-hook. Change install-data-local to install-data-hook. Add uninstall-local. * mkfs/Makefile.am: Likewise. 2002-10-29 Barry Arndt * configure.in: Add AC_PATH_PROG(LN, ln, ln). * jfsutils.spec.in: Rename fsck.jfs to jfs_fsck, rename mkfs.jfs to jfs_mkfs. * fsck/Makefile.am: Rename fsck.jfs to jfs_fsck. Add install-exec-local to hard link fsck.jfs to jfs_fsck. Add install-exec-data to hard link fsck.jfs.8 to jfs_fsck.8. * fsck/jfs_fsck.8: Add renamed man page. * fsck/fsck.jfs.8: Remove. * fsck/xchkdsk.c: Add program_name and logic to display proper name. Change argc type from int32_t to int. Rename fsck.jfs to jfs_fsck. * mkfs/Makefile.am: Rename mkfs.jfs to jfs_mkfs. Add install-exec-local to hard link mkfs.jfs to jfs_mkfs. Add install-exec-data to hard link mkfs.jfs.8 to jfs_mkfs.8. * mkfs/jfs_mkfs.8: Add renamed man page. * mkfs/mkfs.jfs.8: Remove. * mkfs/mkfs.c: Add program_name and logic to display proper name. Rename mkfs.jfs to jfs_mkfs. 2002-10-29 Dave Kleikamp * libfs/log_work.c: Remove fileset from nodofilehash. xtroot and btroot weren't hashing to the same page as inode. Update both pieces when first two parts of inode are updated in same log record. * libfs/logredo.c: Reset bufhdr[].modify flag to avoid constantly re-writing the same buffers 2002-10-28 Barry Arndt * libfs/fsckwsp.h: Add logredo_only flag to fsck_agg_record. * fsck/xchkdsk.c: Add include getopt.h. * fsck/xchkdsk.c (parse_parms): Add processing for --replay_journal_only option. Change -o to --omit_journal_replay. Allow -o (undocumented) for backwards compat. * fsck/xchkdsk.c (phase0_processing): Likewise. * fsck/xchkdsk.c (fsck_usage): Update usage message with new options. * fsck/fsck.jfs.8: Update man page with new options. * logredo/: Remove logredo. * Makefile.am: Remove logredo, change xchkdmp/xchklog to jfs_fscklog. * configure.in: Likewise. * jfsutils.spec.in: Likewise. * fsck/fsck.jfs.8: Likewise. * logdump/logdump.8: Likewise. * mkfs/mkfs.jfs.8: Likewise. * tune/jfs_tune.8: Likewise. * xchdmp/xchkdmp.8: Likewise. * xchklog/xchklog.8: Likewise. * xpeek/xpeek.8: Likewise. * fscklog/: Add directory and source for new jfs_fscklog tool combining functions of xchkdmp and xchklog. * xchkdmp/: Remove. * xchklog/: Remove. 2002-10-18 Dave Kleikamp * fsck/fsckea.c: Fix big-endian extended attribute checking * libfs/jfs_endian.c: Bounds-check dtree byte-swapping * libfs/log_work.c: Remove incorrect __le32_to_cpu usage. * configure.in: Bumped version to 1.0.24. * README: Likewise. * NEWS: Likewise. 2002-10-16 Barry Arndt * man_html/: Remove from CVS. * tune/super.c: Don't display unused superblock field 'compress'. 2002-10-16 Dave Kleikamp * libfs/log_work.c: xad->len was not being byte-swapped on ppc 2002-09-27 Barry Arndt * libfs/Makefile.am: Remove fssubs.h from libfs_a_SOURCES. * fsck/Makefile.am: Remove fsckxlog.h from fsck_jfs_SOURCES. * configure.in: Bumped version to 1.0.23. * README: Likewise. * NEWS: Likewise. 2002-09-26 Barry Arndt * mkfs/*.c: More code cleanup. * fsck/*.c: Likewise. 2002-09-23 Barry Arndt * defrag/defragfs.c: Remove typedef's. * defrag/helpers.c: Likewise. * defrag/helpers.h: Likewise. * include/*.h: Likewise. * logdump/helpers.c: Likewise. * logredo/helpers.c: Likewise. * mkfs/initmap.c: Likewise. * mkfs/inodemap.c: Likewise. * mkfs/inodes.c: Likewise. * mkfs/mkfs.c: Likewise. * tune/super.c: Likewise. * tune/tune.c: Likewise. * xchkdmp/xchkdmp.c: Likewise. * xchklog/xchklog.c: Likewise. * xpeek/display.c: Likewise. * xpeek/directory.c: Likewise. * xpeek/dmap.c: Likewise. * xpeek/fsckcbbl.c: Likewise. * xpeek/iag.c: Likewise. * xpeek/inode.c: Likewise. * xpeek/xpeek.h: Likewise. * libfs/*.h, *.c: Run through 'indent', remove typedef's, clean up int32_t returns. * fsck/*.h, *.c: Likewise. * fsck/fsckxlog.h: Remove. 2002-09-13 Barry Arndt * logredo/helpers.c: Run through 'indent', clean up int types. * logredo/xlogredo.c: Likewise. * xchkdmp/xchkdmp.c: Likewise. * xpeek/alter.c: Likewise. * xpeek/directory.c: Likewise. * xpeek/display.c: Likewise. * xpeek/dmap.c: Likewise. * xpeek/fsckcbbl.c: Likewise. * xpeek/help.c: Likewise. * xpeek/iag.c: Likewise. * xpeek/inode.c: Likewise. * xpeek/io.c: Likewise. * xpeek/super2.c: Likewise. * xpeek/super.c: Likewise. * xpeek/ui.c: Likewise. * xpeek/xpeek.c: Likewise. * xpeek/xpeek.h: Likewise. 2002-09-12 Barry Arndt * mkfs/initmap.c: Run through 'indent', clean up int types. * mkfs/initmap.h: Likewise. * mkfs/inodemap.c: Likewise. * mkfs/inodemap.h: Likewise. * mkfs/inodes.c: Likewise. * mkfs/inodes.h: Likewise. * mkfs/mkfs.c: Likewise. * xchklog/xchklog.c: Likewise. Remove JFS_INLINELOG from initialization of variable expected_flag in validate_super(). * fsck/xchkdsk.c (initial_processing): Fix fsck.jfs start timestamp. * logdump/helpers.c: Run through 'indent', clean up int types. * logdump/logdump.c: Likewise. Initialize variable prog in main(). 2002-09-11 Barry Arndt * libfs/fssubs.h: Remove. * libfs/fssubs.c: Run through 'indent', change int32_t returns and rc's to int, remove routines and declarations specific to defrag. * defrag/helpers.c: Add. Contains contents of old libfs/fssubs.c specific to defrag. * defrag/helpers.h: Add. Contains contents of old libfs/fssubs.h specific to defrag. * defrag/defragfs.c: Run through 'indent', change int32_t returns and rc's to int, include helpers.h instead of fssubs.h. * defrag/Makefile.am: Add helpers.c and helpers.h to defragfs_SOURCES. 2002-09-10 Barry Arndt * defrag/defragfs.c: Run through 'indent', change int32_t returns and rc's to int, replace countLZ32 and countTZ32 calls with actual function. * libfs/utilsubs.c: Run through 'indent', change more() return from int32_t to int, remove countLZ32() and countTZ32(). * libfs/utilsubs.h: Likewise. 2002-09-09 Barry Arndt * configure.in: Bumped version to 1.0.22. * README: Likewise. * NEWS: Likewise. 2002-09-06 Barry Arndt * mkfs/mkfs.c (main): Change volume_label size from 11 chars to 16 to correctly store a volume label in superblock s_label. 2002-09-05 Barry Arndt * libfs/logform.c (jfs_logform): Pass external journal volume label. * libfs/logform.h: Likewise. * fsck/xchkdsk.c (phase9_processing): Likewise. * libfs/logredo.c: Make LogOpenMode extern for better portability. * libfs/open_by_label.c: Define LogOpenMode here for better portability. (open_by_label): Pass device name. * mkfs/mkfs.c: Update jfs_logform() call to pass external journal volume label. Update open_by_label() call to pass device name. Add -J option to create external journal only or attach existing journal to about-to-be formatted JFS file system. Existing journal can be specified by device name, label, or UUID. Update -L to allow user to set volume label of external journal. * mkfs/mkfs.jfs.8: Update man page with above information. * all of the above: Run through 'indent' to begin code cleanup and style unification. * Makefile.am: Add /tune for jfs_tune utility. * jfsutils.spec.in: Likewise. * configure.in: Likewise. * tune/Makefile.am: Create. * tune/tune.c: Likewise. * tune/super.c: Likewise. * tune/jfs_tune.8: Likewise. 2002-08-12 Barry Arndt * configure.in: Bumped version to 1.0.21. * README: Likewise. * NEWS: Likewise. 2002-08-10 Christoph Hellwig * AUTHORS: Update my email address. * libfs/logform.c (jfs_logform): Calculate log_begin earlier. * libfs/log_work.c (open_device): Fix sprintf format string. * libfs/logredo.h: Don't define NEWLOG. * jfs_logmgr.h: Provide alternative struct identifier for logsuper_t. * libfs/super.c (inrange): Return int instead of int32_t. (validate_sizes): Likewise. (ujfs_validate_super): Likewise. (ujfs_put_superblk): Likewise. (ujfs_get_superblk): Likewise. * libfs/super.h: Update prototypes for the above change, add missing prototypes for ujfs_put_logsuper and ujfs_get_logsuper, add needed struct forward declarations. * xpeek/fsckcbbl.c: Include . 2002-08-08 Barry Arndt * libfs/super.c: Add ujfs_validate_logsuper(), ujfs_put_logsuper(), ujfs_get_logsuper(). * xpeek/fsckcbbl.c: Use ujfs_put_logsuper, ujfs_get_logsuper calls instead of put_logsuper, get_logsuper. Get rid of put_logsuper() and get_logsuper(). 2002-08-07 Barry Arndt * fsck/xchkdsk.c (phase0_processing): Update log device number in superblock after logredo with external log. 2002-07-18 Barry Arndt * xpeek/Makefile.am: Add -luuid to LDADD for external log support. * xpeek/fsckcbbl.c (display_logsuper): Add support for external log. Clean up file. * xpeek/super.c (display_super): Likewise. * xpeek/super2.c (display_super2): Likewise. 2002-07-15 Christoph Hellwig * libfs/logredo.c (jfs_logredo): Remove unused variables. * libfs/log_work.c (logredoInit): Likewise. * libfs/log_dump.c (ldmp_logError): Likewise. * fsck/xchkdsk.c (final_processing): Likewise. * libfs/logredo.h: Add prototype for findLog(). * xpeek/fsckcbbl.c (display_logsuper): Fix printf format specifiers. 2002-07-12 Barry Arndt * Makefile.am (SUBDIRS): Remove defrag and extendfs. * configure.in (AC_OUTPUT): Likewise. * extendfs/: Remove contents. * *.h, *.c: Clean up license boilerplates and comments. 2002-07-10 Barry Arndt * defrag/defragfs.c: Remove register keyword. * fsck/fsckdire.c: Likewise. * include/jfs_unicode.h: Likewise. * libfs/log_dump.c: Likewise. * libfs/logredo.c: Likewise. * libfs/utilsubs.c: Likewise. * include/jfs_logmgr.h: Only include uuid/uuid.h if not already included. * include/jfs_superblock.h: Likewise. * libfs/logform.c: Remove unneeded #include . * libfs/logform.h: Likewise. * libfs/logredo.h: Likewise. * libfs/open_by_label.c: Likewise. 2002-06-24 Barry Arndt * mkfs/mkfs.c (mkfs_usage): Fixed typo in Emergency help. (Bas) 2002-06-21 Barry Arndt * configure.in: Bumped version to 1.0.20. * README: Likewise. * NEWS: Likewise. 2002-06-20 Barry Arndt * libfs/logform.c: Include unistd.h. (jfs_logform): Do not display logform heartbeat if output is redirected. 2002-06-20 peterc@gelato.unsw.edu.au * libfs/devices.c: Add support for BLKGETSIZE64. * mkfs/initmap.c (calc_map_size): Change int32_t vars to int64_t. 2002-06-20 Christoph Hellwig * fsck/fsckimap.c (AIS_replication): Remove unused variables. * fsck/fsckpfs.c (ait_special_read_ext1): Likewise. (blkmap_find_bit): Likewise. (blkmap_get_page): Likewise. (blktbl_dmap_get): Likewise. (blktbl_dmaps_flush): Likewise. (imapleaf_get): Likewise. (inode_get): Likewise. (inode_get_first_fs): Likewise. (inode_get_next): Likewise. (inodes_flush): Likewise. (node_get): Likewise. 2002-06-11 Barry Arndt * mkfs/mkfs.c (create_aggregate): Set version in superblock properly if external log. 2002-06-07 Barry Arndt * configure.in: Bumped version to 1.0.19. * README: Likewise. * NEWS: Likewise. 2002-05-24 Barry Arndt * configure.in: Bumped version to 1.0.18. * README: Likewise. * NEWS: Likewise, and updated with current fixes/features. 2002-05-24 Dave Kleikamp * libfs/logform.c: Set maximum working size of external log at 128 MB 2002-05-24 Dave Kleikamp * fsck/fsck.c: warn user about destroying data on log device 2002-05-21 Dave Kleikamp * configure.in: Add check for uuid library * fsck/Makefile.am: add -luuid * libfs/Makefile.am: Likewise * logdump/Makefile.am: Likewise * logredo/Makefile.am: Likewise * mkfs/Makefile.am: Likewise * include/jfs_logmgr.h: Add uuid and label to superblock, log_superblock * include/jfs_superblock.h: Likewise, bump JFS_VERSION to 2 * fsck/fsckmeta.c: Suport for external log * fsck/xchkdsk.c: Likewise * libfs/devices.h: Likewise * libfs/fssubs.c: Likewise * libfs/jfs_endian.c: Likewise * libfs/log_dump.c: Likewise * libfs/log_read.c: Likewise * libfs/log_work.c: Likewise * libfs/logform.c: Likewise * libfs/logform.h: Likewise * libfs/logredo.c: Likewise * libfs/logredo.h: Likewise * libfs/open_by_label.c: Likewise * libfs/super.c: Likewise * libfs/super.h: Likewise * logdump/logdump.c: Likewise * logredo/xlogredo.c: Likewise * mkfs/mkfs.c: Likewise * xpeek/super.c: Likewise * xpeek/super2.c: Likewise * fsck/fsck.jfs.8: Add -j option * mkfs/mkfs.jfs.8: Likewise * man_html/fsck.jfs.8.html: Likewise * man_html/mkfs.jfs.8.html: Likewise 2002-04-26 Dave Kleikamp * include/jfs_filsys.h: Remove JFS_SWAP_BYTES define * libfs/Makefile.am: add jfs_endian.h to libfs_a_SOURCES * libfs/jfs_endian.c: Remove i386_byteorder & jfs_native_flag Put all swap code in #if block * libfs/jfs_endian.h: Conditional declare swap routines or define noop macros based on __BYTE_ORDER * fsck/xfsckint.h: Include jfs_endian.h * fsck/fsckimap.c: Remove conditionals around swap functions Swap/Write/Swap-back rather than copy/swap/write * fsck/fsckbmap.c: Likewise * fsck/fsckmsgs.c: Likewise * fsck/fsckpfs.c: Likewise * fsck/fsckwps.c: Likewise * fsck/xchkdsk.c: Likewise * libfs/fssubs.c: Likewise * libfs/inode.c: Likewise * libfs/log_dump.c: Likewise * libfs/log_map.c: Likewise * libfs/log_read.c: Likewise * libfs/log_work.c: Likewise * libfs/logform.c: Likewise * libfs/logredo.c: Likewise * libfs/super.c: Likewise * mkfs/initmap.c: Likewise * mkfs/inodemap.c: Likewise * mkfs/inodes.c: Likewise * mkfs/mkfs.c: Likewise * xchklog/xchklog.c: Likewise * xpeek/directory.c: Likewise * xpeek/display.c: Likewise * xpeek/dmap.c: Likewise * xpeek/fsckcbbl.c: Likewise * xpeek/iag.c: Likewise * xpeek/inode.c: Likewise * xpeek/xpeek.c: Likewise 2002-04-24 Barry Arndt * fsck/xchkdsk.c: Fix typo in fsck.jfs Emergency Help. * fsck/fsckpfs.c (blkmap_put_ctl_page): Endian-swap buffer, not original block map control page. 2002-04-02 Dave Kleikamp * include/jfs_logmgr.h: Changed "active" from bitmap to list. Added field for log device number Removed unneeded rsrvd field * include/jfs_superblock.h: Remove never-used DFS fields Added s_device field to superblock * libfs/jfs_endian.c: Reflect changes to superblock and logsuper * libfs/super.c: Likewise * xpeek/super.c: Likewise * xpeek/super2.c: Likewise 2002-04-02 Barry Arndt * configure.in: Bumped version to 1.0.17. * README: Likewise. * NEWS: Likewise, and updated with current fixes/features. 2002-03-28 Barry Arndt * libfs/fsckmsge.h: Remove fsck_PRMUSAGE message 116. * libfs/fsckmsgc.h: Remove fsck_PRMUSAGE #define. * libfs/message.c: Remove MSG_OSO_MKFS_USAGE message. * libfs/message.h: Remove MSG_OSO_MKFS_USAGE #define. * fsck/xchkdsk.c: Add fsck_usage(). (parse_parms): Call fsck_usage() instead of message 116, improve error checking. * mkfs/mkfs.c: Add mkfs_usage(). (main): Call mkfs_usage() instead of MSG_OSO_MKFS_USAGE message, improve error checking. 2002-03-27 Barry Arndt * fsck/xchkdsk.c (parse_parms): Rewrite routine to use getopt() 2002-03-27 Dave Kleikamp * libfs/log_map.c: Run through indent, clean up wrapped comments, etc. * libfs/log_read.c: Likewise * libfs/log_work.c: Likewise * libfs/log_form.c: Likewise * libfs/log_form.h: Likewise * libfs/log_redo.c: Likewise * libfs/log_redo.h: Likewise 2002-03-27 Christoph Hellwig * libfs/message.c (message_user): Remove 'device' and 'response' parameters, change return value to 'void', remove now unused code and update callers. * libfs/message.h: Remove unused defines. * mkfs/mkfs.c (main): Implement Yes/No reply handling ourselves. 2002-03-25 Dave Kleikamp * libfs/jfs_endian.c: Cosmetic: remove carriage returns (^M) 2002-03-24 Christoph Hellwig * configure.in: Don't check for libpthreads. * fsck/fsckruns.c: Rewritten for alarm()-based heartbeat. * fsck/xchkdsk.c: Don't include . 2002-03-22 Barry Arndt * xpeek/super.c (display_super): Display proper endian format of pxd structs. * xpeek/super2.c (display_super2): Likewise. 2002-03-21 Barry Arndt * libfs/jfs_endian.c: Add ujfs_swap_fscklog_entry_hdr_t(). * fsck/fsckmsgs.c (fsck_record_msg): Swap log entry if on big endian. * fsck/fsckwsp.c: Include jfs_byteorder.h. (fscklog_end): Swap entry_length if on big endian. * xchklog/xchklog.c (initial_processing): Detect if big endian. (extract_service_log): Swap log entry if on big endian. 2002-03-19 Dave Kleikamp * fsck/fsckdtre.c: More rigorous dtree validation 2002-03-11 Barry Arndt * configure.in: Bumped version to 1.0.16. * README: Likewise. * NEWS: Likewise, and updated with current fixes/features. 2002-03-07 Barry Arndt * libfs/fsckmsge.h: Add exit code to 'fsck session end' debug message. * fsck/xchkdsk.c (main): Pass exit code to fsck_SESSEND message. * xchkdmp/Makefile.am (INCLUDES): Add -I$(top_srcdir)/fsck. * xchkdmp/xchkdmp.c: Delete dump_msg(), use send_msg() instead. Include xfsck.h. Delete hardcoded fsck_highest_msgid_defined. 2002-03-04 Barry Arndt * fsck/fsckwsp.c (alloc_vlarge_buffer): Add error checking for malloc failure. * fsck/xfsck.h: Add fsck exit codes. * fsck/xchkdsk.c: Set/return appropriate exit codes. Remove unused default_vol, message_buffer_0, terse_msg_ptr, chkdsk32 definition, unnecessary _JFS_DEBUG statements. Check for alloc_vlarge_buffer failure. Update comments. * fsck/fsck.jfs.8: Update man page with new exit code information. 2002-02-26 Barry Arndt * libfs/devices.c: Include jfs_filsys.h, remove BLKSSZGET ioctl. (ujfs_get_dev_size): Use PBSIZE for sector size. 2002-02-25 Barry Arndt * fsck/xfsckint.h: Remove unused second parameter in fsck_send_msg definition. * fsck/fsckbmap.c: Remove unused second parameter in calls to fsck_send_msg. Remove unused extern char *terse_msg_ptr. * fsck/fsckcbbl.c: Likewise. * fsck/fsckconn.c: Likewise. * fsck/fsckdtre.c: Likewise. * fsck/fsckimap.c: Likewise. * fsck/fsckino.c: Likewise. * fsck/fsckmeta.c: Likewise. * fsck/fsckmsgs.c: Likewise. * fsck/fsckpfs.c: Likewise. * fsck/fsckwsp.c: Likewise. * fsck/fsckxtre.c: Likewise. * fsck/xchkdsk.c: Likewise. * libfs/log_map.c: Likewise. * libfs/log_read.c: Likewise. * libfs/log_work.c: Likewise. * libfs/logredo.c: Likewise. * logdump/helpers.c: Likewise. * logdump/logdump.c: Likewise. * logredo/helpers.c: Likewise. * logredo/xlogredo.c: Likewise. * fsck/fsckpfs.c (open_device_read): Init Dev_blksize and Dev_SectorSize to PBSIZE. (open_device_rw_exclusize): Likewise. * xchklog/xchklog.c (open_device_read): Likewise. * libfs/fssubs.c (OpenLV): Init LVMount.pbsize to PBSIZE. * logdump/logdump.c: Remove unused Dev_SectorSize definition. * mkfs/mkfs.c (main): Init phys_block_size to PBSIZE. 2002-02-25 Christoph Hellwig * fsck/fsckpfs.c: Include . (close_volume): Use close instead of ujfs_close. (open_device_read): Use open instead of ujfs_open_device. (open_device_rw_exclusive): Likewise. * libfs/device.c (ujfs_open_device): Removed. (ujfs_close): Likewise. (ujfs_rw_diskblocks): Update comment. * libfs/devices.h: Remove declarations of ujfs_open_device and ujfs_close. * libfs/fssubs.c (openLV): Use open instead of ujfs_open_device. (closeFS): Use close instead of ujfs_close. * logdump/logdump.c: Include . (main): Use open/close instead of ujfs_open_device/ujfs_close. * logredo/xlogredo.c: Include . (main): Use open instead of ujfs_open_device. * mkfs/mkfs.c: Include . (main): Use open/close instead of ujfs_open_device/ujfs_close. * xchklog/xchklog.c: Include . (final_processing): Use close instead of ujfs_close. (open_device_read): Use open instead of ujfs_open_device. * xpeek/xpeek.c: Include , . (main): Use open/close instead of ujfs_open_device/ujfs_close. 2002-02-23 Christoph Hellwig * fsck/fsckcbbl.c: Do not define INCL_TYPES. * fsck/fsckea.c: Do not define INCL_DOSERRORS and INCL_DOSPROCESS. Get rid of remaining OS/2 cdecl handling. * fsck/fsckruns.c: Do not define INCL_DOSPROCESS. 2002-02-18 Barry Arndt * fsck/fsckmsgl.h: Remove. * fsck/fsckmsgp.h: Change MsgProtocol[][3] to MsgProtocol[][2]. Remove 'output stream' field from MsgProtocol[][]. Change fsck_autochk to fsck_quiet, msg 145. * fsck/fsckmsgs.c: Change MsgProtocol[][3] to MsgProtocol[][2]. (fsck_send_msg): Remove dead code using unneeded fsck_terse, fsck_out, MP_STREAM, UFS_CHKDSK_AUTOCHECK, fsck_autochk. * fsck/Makefile.am: Remove fsckmsgl.h. * fsck/xchkdsk.c: Remove unneeded UFS_CHKDSK_AUTOCHECK. * fsck/xchkdsk.h: Likewise. * fsck/xfsck.h: Decrement defines MP_MSGLVL, MP_MSGFILE. Remove unneeded defines MP_STREAM, fsck_suffix, fsck_notqry, fsck_terse, fsck_autochk, fsck_engl_only, fsck_local_lang, fsck_out, fsck_err, fsck_in. * libfs/message.c: Remove unused messages. * libfs/message.h: Remove defines for unused messages. * logdump/helpers.c: Change MsgProtocol[][4] to MsgProtocol[][2]. * logredo/helpers.c: Likewise. * xchklog/xchklog.c: Remove dead code using MP_STREAM, fsck_out. 2002-02-15 Dave Kleikamp * remove complete largefile support changes from 2000-01-28 CH 2002-02-15 Barry Arndt * configure.in: Bumped version to 1.0.15. * README: Likewise. * NEWS: Likewise, and updated with current fixes/features. 2002-02-15 Hiten Pandya * include/jfs_types.h: Include to satisfy BSD systems, for various types, such as caddr_t. 2002-02-15 Christoph Hellwig * fsck/xchkdsk.c: Do not include . * libfs/log_map.c: Make updDmapPage prototype match the declaration. * libfs/fssubs.c (Is_Device_Mounted): Fix typo. (Is_Device_Type_JFS): Likewise. 2002-02-13 Christoph Hellwig * include/jfs_types.h: Don't define MAXPATHLEN. * libfs/log_dump.c: Remove unused variable loglockpath. * libfs/logredo.c: Likewise. * xpeek/directory.c: Include , replace all instances of MAXPATHLEN with PATH_MAX. * configure.in (AC_CHECK_HEADERS): Add mntent.h. (AC_CHECK_FUNCS): Add getmntinfo. * libfs/fssubs.c: Include "config.h", include only if HAVE_MNTENT_H is defined, move Is_Device_Mounted and Is_Device_Type_JFS under if HAVE_MNTENT_H. Move Is_Root_Mounted_RO above Is_Device_Mounted. [HAVE_GETMNTINFO]: Include , , , add getmntinfo based versions of Is_Device_Mounted and Is_Device_Type_JFS. 2002-02-12 Barry Arndt * mkfs/inodes.c (init_fileset_inode_table): Change 'inostamp' to unsigned type. (init_fileset_inodes): Likewise. * mkfs/mkfs.c (create_fileset): Likewise. * mkfs/inodes.h: Change function definitions to match above changes. 2002-02-10 Christoph Hellwig * mkfs/mkfs.c: Don't include and . * xchkdmp/xchkdmp.c: Include instead of . * xchklog/xchklog.c: Likewise. * defrag/defragfs.c (defragfs): Zero-initialize unused variable. (addDtree): Likewise. (fscntlMove): Likewise. * extendfs/extendfs.c (extendfs): Likewise. * mkfs/inodes.c (init_inode): Change 'inostamp' to unsigned type. 2002-02-08 Barry Arndt * fsck/fsckino.c: Don't let xTree_processing error flag influence dTree_processing, could cause fsck.jfs internal error 10. * fsck/fsck.jfs.8: Remove unneeded comments that cause man2html format errors. * xpeek/xpeek.8: Update xpeek man page. * xpeek/help.c: Change output text from chkdsk to fsck. 2002-01-30 Barry Arndt * fsck/fsckmeta.c: add new error message if magic number is not jfs, take out misleading 'superblock corrupt' debug message * libfs/message.c: update message 335, 'not jfs in /etc/fstab'. 2002-01-29 Christoph Hellwig * defrag/defragfs.c: Include instead of "jfs_debug.h". [_JFS_DEBUG] (jFYI, jEVENT, jERROR): New, debugging macros. [!_JFS_DEBUG] (jFYI, jEVENT, jERROR): New, stubs. * extendfs/extendfs.c: Don't include "jfs_debug.h". * fsck/fsckdire.c: Likewise. * libfs/fssubs.c: Likewise. * libfs/log_dump.c: Likewise. * libfs/log_read.c: Likewise. * libfs/log_work.c: Likewise. * libfs/log_map.c: Include instead of "jfs_debug.h". * libfs/logredo.c: Likewise. (recoverExtendFS): Use assert() instead of ASSERT(). * include/Makefile.am (EXTRA_DIST): Remove jfs_debug.h. * include/jfs_debug.h: Removed. 2002-01-28 Christoph Hellwig * configure.in: Check for canonical host name and largefile support. * libfs/Makefile.am: Remove AM_CFLAGS. * xchkdmp/Makefile.am: Likewise. * xchklog/Makefile.am: Likewise. * xpeek/Makefile.am: Likewise. * logdump/Makefile.am (AM_CFLAGS): Remove -D_FILE_OFFSET_BITS=64. * logredo/Makefile.am (AM_CFLAGS): Likewise. * mkfs/Makefile.am (AM_CFLAGS): Likewise. * acinlude.m4: New file. 2002-01-28 Barry Arndt * include/jfs_types.c: remove old types PVOID, UCHAR, USHORT, ULONG. * defrag/defragfs.c: change UCHAR to char*, ULONG to unsigned long. * extendfs/extendfs.c: change PVOID to void*, UCHAR to char*, ULONG to unsigned long. * mkfs/mkfs.c: change UCHAR to char*. * fsck/fsckea.c: change USHORT to unsigned short, ULONG to unsigned long. * fsck/fsckcbbl.c: change ULONG to unsigned long. * fsck/fsckino.c: Likewise. * fsck/fsckmsgs.c: Likewise. * fsck/fsckpfs.c: Likewise. * fsck/fsckruns.c: Likewise. * fsck/xchkdsk.c: Likewise. * fsck/xfsck.h: Likewise. * libfs/fssubs.c: Likewise. * libfs/fssubs.h: Likewise. * logdump/helpers.c: Likewise. * logdump/logdump.c: Likewise. * logredo/helpers.c: Likewise. * logredo/xlogredo.c: Likewise. * xchkdmp/xchkdmp.c: Likewise. * xchklog/xchklog.c: Likewise. * libfs/devices.c (ujfs_get_dev_size): fix typecast problem causing fsck.jfs 'corrupt superblock' error message * configure.in: Bumped version to 1.0.14. * README: Likewise. * NEWS: Likewise, and updated with current fixes/features. 2002-01-25 Barry Arndt * defrag/(*.h *.c): change types uxx and uintxx to C99 type uintxx_t, change types sxx and intxx to C99 type intxx_t. * extendfs/(*.h *.c): Likewise. * fsck/(*.h *.c): Likewise. * include/(*.h): Likewise. * libfs/(*.h *.c): Likewise. * logdump/(*.c): Likewise. * logredo/(*.c): Likewise. * mkfs/(*.h *.c): Likewise. * xchkdmp/(*.c): Likewise. * xchklog/(*.c): Likewise. * xpeek/(*.h *.c): Likewise. * include/jfs_types.h: Remove uxx, uintxx, sxx, intxx typedef's * configure.in: Bumped version to 1.0.13. * README: Likewise. * NEWS: Likewise, and updated with current fixes/features. 2002-01-24 Dave Kleikamp * jfsutils.spec.in: Fixed typo s/RPM_OPTFLAGS/RPM_OPT_FLAGS/ 2002-01-21 Christoph Hellwig * configure.in (AC_CHECK_HEADERS): Check for endian.h, sys/byteorder.h, and machine/endian.h. Use non-prefixed versions of BYTE_ORDER, LITTLE_ENDIAN and BIG_ENDIAN. * include/jfs_byteorder.h: Include "config.h", make inclusion of depending on HAVE_ENDIAN_H. [HAVE_MACHINE_ENDIAN_H]: Include . [HAVE_SYS_BYTEORDER_H]: Include . * fsck/fsckdire.c: Don't define _ULS_UNIDEFK and UNICASERANGE_DEFINED, don't include "jfs_uniupr.h" and remove mess around it. * fsck/fsckdtre.c: Don't define _ULS_UNIDEFK. * fsck/xchkdsk.c: Likewise. * include/Makefile.am (EXTRA_DIST): Remove jfs_uniupr.h. * include/jfs_types.h: Define UniChar in terms of uint16_t. * include/jfs_unicode.h: Remove lots of unused code. * include/jfs_uniupr.h: Removed. * libfs/Makefile.am (libfs_a_SOURCES): Add uniupr.c. * libfs/uniupr.c: New file. * xpeek/directory.c: Don't define UNICASERANGEDEFINED and UNIUPR_NOUPPER. 2002-01-16 Dave Kleikamp * configure.in: Define AM_MAINTAINER_MODE 2002-01-14 Christoph Hellwig * include/Makefile.am (EXTRA_DIST): Remove * include/jfs_types.h: Don't define __BYTEORDER_HAS_U64__, don't include and "endian24.h". * include/jfs_byteorder.h: New file. * include/endian24.h: Removed. * fsck/fsckimap.c: Include "jfs_byteorder.h" instead of and "endian24.h". * fsck/fsckmeta.c: Likewise. * fsck/fsckpfs.c: Likewise. * libfs/jfs_endian.c: Likewise. * libfs/logform.c: Include "jfs_byteorder.h" instead of . * mkfs/inodes.c: Likewise. * defrag/defragfs.c: Include "jfs_byteorder.h". * fsck/fsckdire.c: Likewise. * fsck/fsckdtre.c: Likewise. * fsck/fsckino.c: Likewise. * fsck/fsckxtre.c: Likewise. * fsck/xchkdsk.c: Likewise. * libfs/fssubs.c: Likewise. * libfs/inode.c: Likewise. * libfs/log_dump.c: Likewise. * libfs/log_map.c: Likewise. * libfs/log_read.c: Likewise. * libfs/log_work.c: Likewise. * libfs/logredo.c: Likewise. * libfs/super.c: Likewise. * mkfs/initmap.c: Likewise. * mkfs/inodemap.c: Likewise. * mkfs/mkfs.c: Likewise. * xchklog/xchklog.c: Likewise. * xpeek/directory.c: Likewise. * xpeek/iag.c: Likewise. * xpeek/inode.c: Likewise. * xpeek/super.c: Likewise. * xpeek/super2.c: Likewise. * xpeek/xpeek.c: Likewise. * fsck/fsckwsp.c: Don't include . * include/jfs_unicode.h: Likewise. 2002-01-14 Barry Arndt * libfs/devices.c (ujfs_get_dev_size): use ioctl to find device size, remove unneeded 'hidden' from passed parms, routine. * libfs/devices.h: remove 'hidden' from ujfs_get_dev_size. * libfs/fssubs.c (openLV): remove 'hidden' from ujfs_get_dev_size call. * fsck/fsckmeta.c (validate_super): Likewise. * mkfs/mkfs.c (main): Likewise. * xchklog/xchklog.c (validate_super): Likewise. 2002-01-13 Christoph Hellwig * configure.in (AC_CHECK_HEADERS): add stdint.h. * include/jfs_types.h: Declare primitive types based on C99 inttypes, make inclusion of conditional on !HAVE_STDINT_H, include "config.h". [!HAVE_STDINT_H]: Declare C99 unsigned inttypes based on BSD ones. [HAVE_STDINT_H]: Include . * libfs/unicode_to_utf8.h: Include "jfs_types.h" instead of . * libfs/Makefile.am (AM_CFLAGS): Remove -DONE_FILESET_PER_AGGR. * logdump/Makefile.am (AM_CFLAGS): Likewise. * logredo/Makefile.am (AM_CFLAGS): Likewise. * xchkdmp/Makefile.am (AM_CFLAGS): Likewise. * xchklog/Makefile.am (AM_CFLAGS): Likewise. * xpeek/Makefile.am (AM_CFLAGS): Likewise. 2002-01-11 Barry Arndt * xchklog/xchklog.c (parse_parms): rewrite to make parm parsing better. * xchklog/xchklog.8: update xchklog man page. * xchkdmp/xchkdmp.c (parse_parms): rewrite to make parm parsing better. (main): print xchkdmp version and date. * xchkdmp/xchkdmp.8: update xchkdmp man page. * libfs/fsckmsge.h: update usage messages for xchklog(66), xchkdmp(222). 2002-01-08 Dave Kleikamp * xpeek/Makefile.am: Remove _JFS_UNICODE. * xpeek/directory.c: Likewise. 2002-01-06 Christoph Hellwig * defrag/defragfs.c (main): Convert to ANSI prototype of main(). * extendfs/extendfs.c (main): Likewise. * logdump/logdump.c (main): Likewise. * xchkdmp/xchkdmp.c (main): Likewise. * xchklog/xchklog.c (main): Likewise. 2002-01-05 Christoph Hellwig * configure.in (AC_CHECK_HEADERS): add stdbool.h. * include/jfs_types.h: Remove boolean_t, TRUE and FALSE. [HAVE_STDBOOL_H]: Include . [!HAVE_STDBOOL_H]: Provide a C99 bool type. * defrag/defragfs.c: Remove write-only variable 'Query', Change 'DoIt' type to 'bool'. * extendfs/extendfs.c: Remove unused variable 'Query'. (whatDoYouWant): Change 'devFound' type to 'bool'. * libfs/fssubs.c (xtLMLeaf): Don't use 'TRUE' for infinite loop. * libfs/logredo.c (recoverExtendFS): Likewise. * mkfs/initmap.c (verify_last_blocks): Change 'write_inode' type to 'bool'. * mkfs/mkfs.c (create_aggregate): Change 'verify_blocks' type to bool. (main): Change 'verify_blocks' and 'no_questions_asked' type to bool. 2002-01-05 Christoph Hellwig * libfs/fssubs.c: Include instead of . * fsck/xfsck.c: Don't include . * xpeek/directory.c: [_JFS_UNICODE]: Likewise. 2001-12-20 Dave Kleikamp * libfs/logredo.h: add active flag to vopen structure * libfs/log_dump.c: use active flag instead of testing fd == 0 * libfs/logredo.c: Likewise. 2001-12-19 Christoph Hellwig * include/jfs_version.h: Define JFSUTILS_DATE to __DATE__. 2001-12-19 Dave Kleikamp * autogen.sh: Make sure autoheader runs before automake. 2001-12-18 Christoph Hellwig * Makefile.am (dist-hook): Autocreate jfs_version.h. * jfsutils.spec.in (Files): Add AUTHORS, NEWS and manpages. * fsck/Makefile.am: Add manpages. * logdump/Makefile.am: Likewise. * logredo/Makefile.am: Likewise. * mkfs/Makefile.am: Likewise. * xchkdmp/Makefile.am: Likewise. * xchklog/Makefile.am: Likewise. * xpeek/Makefile.am: Likewise. 2001-12-17 Christoph Hellwig * autogen.sh: Make sure autoheader runs after automake. * configure.in: Add AM_CONFIG_HEADER(). * fsck/xchkdsk.c: Include "config.h". (main): Replace JFSUTILS_VERSION with VERSION. * logdump/logdump.c: Likewise. * logredo/xlogredo.c: Likewise. * mkfs/mkfs.c: Likewise. * xchklog/xchklog.c: Likewise. * xpeek/xpeek.c: Likewise. * libfs/Makefile.am: Trim down DEFS and rename to AM_CFLAGS. * mkfs/Makefile.am: Likewise. * logdump/Makefile.am: Likewise. * logredo/Makefile.am: Likewise. * xchkdmp/Makefile.am: Likewise. * xchklog/Makefile.am: Likewise. * xpeek/Makefile.am: Likewise. * libfs/fssubs.c: Properly include . * include/jfs_version.h: Remove JFSUTILS_VERSION 2001-12-17 Barry Arndt * changelog.jfs: Removed. * Makefile.am: Removed changelog.jfs * jfsutils.spec.in: Removed changelog.jfs * configure.in: Bumped version to 1.0.11. * include/jfs_version.h: Likewise. * README: Added install instructions. * NEWS: Update for 1.0.11. 2001-12-14 Christoph Hellwig * configure.in: Install into system directories by default. * jfsutils.spec.in: Remove --prefix=/usr argument to configure. * NEWS: Add useful content. 2001-12-05 Christoph Hellwig * configure.in: Install tools into /sbin if prefix is /usr. * Makefile.am (EXTRA_DIST): add jfsutils.spec.in. (dist-hook): new rule to copy the specfile. * configure.in (AC_OUTPUT): add jfsutils.spec * jfsutils.spec.in: New file. * SPECS/jfsutils.spec: Removed. 2001-12-05 Christoph Hellwig * AUTHORS: New file. * NEWS: Likewise. * autogen.sh: Likewise. * include/Makefile.am: Likewise. * Makefile.am (EXTRA_DIST): Add changelog.jfs. (SUBDIRS): Add include. * configure.in (AC_OUTPUT): Add include/Makefile * defrag/Makefile.am (SOURCES): Add headers. * extendfs/Makefile.am: Likewise. * fsck/Makefile.am: Likewise. * libfs/Makefile.am: Likewise. * mkfs/Makefile.am: Likewise. * xpeek/Makefile.am: Likewise. jfsutils-1.1.15.orig/INSTALL0000644000000000000000000003633211460142743012331 0ustar Installation Instructions ************************* Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the `make install' phase executed with root privileges. 5. Optionally, type `make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior `make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type `make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide `make distcheck', which can by used by developers to test that all other targets like `make install' and `make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. This is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of `${prefix}', so that specifying just `--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to `configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the `make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, `make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of `${prefix}'. Any directories that were specified during `configure', but not in terms of `${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the `DESTDIR' variable. For example, `make install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before all installation names. The approach of `DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of `${prefix}' at `configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of `make' will be. For these packages, running `./configure --enable-silent-rules' sets the default to minimal output, which can be overridden with `make V=1'; while running `./configure --disable-silent-rules' sets the default to verbose, which can be overridden with `make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf bug. Until the bug is fixed you can use this workaround: CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. jfsutils-1.1.15.orig/Makefile.am0000644000000000000000000000035107557327430013336 0ustar SUBDIRS = libfs include fsck fscklog logdump mkfs tune xpeek EXTRA_DIST = jfsutils.spec.in dist-hook: jfsutils.spec cp jfsutils.spec $(distdir) echo "#define JFSUTILS_DATE \"`date +%d-%b-%Y`\"" > $(distdir)/include/jfs_version.hjfsutils-1.1.15.orig/Makefile.in0000644000000000000000000005311211534235513013340 0ustar # Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@ 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 = : subdir = . DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(srcdir)/config.h.in \ $(srcdir)/jfsutils.spec.in $(top_srcdir)/configure AUTHORS \ COPYING ChangeLog INSTALL NEWS depcomp install-sh missing ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) 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 = jfsutils.spec CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ install-html-recursive install-info-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ distdir dist dist-all distcheck ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ { test ! -d "$(distdir)" \ || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -fr "$(distdir)"; }; } am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best distuninstallcheck_listfiles = find . -type f -print distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_CFLAGS = @AM_CFLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ 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@ LN = @LN@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ 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@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ 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__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ 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@ SUBDIRS = libfs include fsck fscklog logdump mkfs tune xpeek EXTRA_DIST = jfsutils.spec.in all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: am--refresh: @: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile .PRECIOUS: 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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config.h: stamp-h1 @if test ! -f $@; then \ rm -f stamp-h1; \ $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ else :; fi 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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 jfsutils.spec: $(top_builddir)/config.status $(srcdir)/jfsutils.spec.in cd $(top_builddir) && $(SHELL) ./config.status $@ # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" $(RECURSIVE_CLEAN_TARGETS): @fail= failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ 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 CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ 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" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags 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 @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || 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__remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 $(am__remove_distdir) dist-lzma: distdir tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma $(am__remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz $(am__remove_distdir) dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__remove_distdir) dist-shar: distdir shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__remove_distdir) dist dist-all: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__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.lzma*) \ lzma -dc $(distdir).tar.lzma | $(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 a+w $(distdir) mkdir $(distdir)/_build mkdir $(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 \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(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__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: @$(am__cd) '$(distuninstallcheck_dir)' \ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ || { 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 check: check-recursive all-am: Makefile config.h installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install 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) 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-recursive clean-am: clean-generic mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all \ ctags-recursive install-am install-strip tags-recursive .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am am--refresh check check-am clean clean-generic \ ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \ dist-hook dist-lzma dist-shar dist-tarZ dist-xz dist-zip \ distcheck distclean distclean-generic distclean-hdr \ distclean-tags distcleancheck distdir distuninstallcheck dvi \ dvi-am html html-am info info-am install install-am \ 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-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic pdf pdf-am ps ps-am tags tags-recursive \ uninstall uninstall-am dist-hook: jfsutils.spec cp jfsutils.spec $(distdir) echo "#define JFSUTILS_DATE \"`date +%d-%b-%Y`\"" > $(distdir)/include/jfs_version.h # 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: jfsutils-1.1.15.orig/NEWS0000644000000000000000000002733111534235035011775 0ustar NEWS - list of user-visible changes between releases of jfsutils New in 1.1.15 - 2011-03-04 * Several fixes for large filesystems where 64-bit variables are needed * Fix incorrect size check on directories * Make the timestamp format consistent New in 1.1.14 - 2009-04-06 * Fix journal replay to handle records that span 3 pages * Increase the maximum inline journal size from 32 MB to 128 MB * Don't call ioctl(BLKFLSBUF) on a ramdisk. It wipes out everything. * Fix fsck abort New in 1.1.13 - 2008-07-17 * Rewrite a confusing error messages * Improve sanity checking when replaying the journal * Work around _LARGEFILE_SOURCE not getting defined by autoconf * Remove unhelpful allocation debug messages New in 1.1.12 - 2007-08-24 * Fix build break when built against recent glibc with -DFORTIFY_SOURCE * Allow -n flag to be passed to jfs_fsck in conjuction with -f, -a, or -p * Look for external journal in /proc/mdstat in case of raid * netbsd support (Submitted by Gary Thorpe) * Fix double close of external journal descriptor * Fix possible array overflow * Fix big-endian bug with legacy partition New in 1.1.11 - 2006-06-05 * Fix infinite loop when mkfs.jfs is invoked with -c * avoid infinite loop in xTree_binsrch_page * Fix buffer overflow * Fix segfault on s390 * Fix segfault in markImap * Add compiler flags to generate useful warnings * Code cleanup New in 1.1.10 - 2005-10-19 * More stdio cleanup * fsck was not recognizing the root filesystem as jfs New in 1.1.9 - 2005-10-04 * Add support for Dragonfly BSD. I/O to block devices must be done through aligned buffers. Change to use stream I/O to avoid problems. * Reduce memory usage in fsck by removing structure members and code relating to OS/2 DASD limits. * Fix stack buffer overflow in Is_Device_Mounted New in 1.1.8 - 2005-05-03 * fsck should not bail out if reserved (but unused) inode 1 is bad * code cleanup - remove unused variables, eliminate compiler warnings * Added blocks parameter to specify file system size * Ensure that data gets flushed to disk * Fix bug in replaying journal that corrupted inodes * Update directory index table when moving directory entries * Use O_DIRECT when checking for bad blocks (jfs_mkfs -c) New in 1.1.7 - 2004-07-22 * --replay_journal_only shouldn't clear FM_DIRTY * Ensure changes to disk occur in proper order * Message corrections * Directory Index Table corrections for big-endian systems New in 1.1.6 - 2004-04-28 * Verify Directory Index Table and reset if necessary New in 1.1.5 - 2004-03-04 * Fix problem creating entries in lost+found * Fix buffer overflow * Fix replaying symlink journal records * Improve performance of duplicate block checking * Fix segfault printing errant message * Done open volume with O_EXCL unless it's necessary * Support sharing of journal between multiple volumes - Requires 2.6.4-rc2 or later kernel New in 1.1.4 - 2003-10-30 * Work around gcc 2.95 bug * Handle log full without crashing * Message format fix New in 1.1.3 - 2003-09-05 * jfs_fsck can now find external journal on evms release 2 volumes * code cleanup: fsck messaging is much cleaner * Don't right-justify when printing volume label * jfs_fsck should return zero when replaying the journal is successful * jfs_fsck should not require that the device is opened with O_EXCL - A recent change to the 2.6.0 kernel makes O_EXCL fail when the volume is mounted, even if read-only New in 1.1.2 - 2003-03-25 * fix undefined reference to errno (G. D. Haraldsson) * allow jfs_mkfs to run on regular file * fix for-loop going past last element of vopen array * sanity checking on variable this_ag * s_label displayed incorrectly when 16 chars long New in 1.1.1 - 2002-12-17 * fix segmentation fault in mkfs.jfs when given bad block device * fix jfs_debugfs to display directory index with directory entries New in 1.1.0 - 2002-11-20 * rename jfs utilities as follows: fsck.jfs -> jfs_fsck, is hard linked to fsck.jfs upon install mkfs.jfs -> jfs_mkfs, is hard linked to mkfs.jfs upon install jfs_tune remains the same logdump -> jfs_logdump xchklog, xchkdmp combined -> jfs_fscklog xpeek -> jfs_debugfs logredo removed, function added to jfs_fsck via --replay_journal_only option * update man pages appropriately for name changes * change jfs_fsck option -o to --omit_journal_replay * fix log replay errors * fix off-by-one error, minor formatting error in jfs_fsck * keep jfs_fsck from complaining during specific tree restructuring * fix jfs_debugfs to recognize all inode types * code cleanup New in 1.0.24 - 2002-10-18 * byte-swapping fixes for big-endian hardware * code cleanup New in 1.0.23 - 2002-09-27 * print fsck.jfs start timestamp correctly in fsck.jfs log * allow xchklog to run on a JFS file system with an external journal * initialize program name in logdump properly * code cleanup New in 1.0.22 - 2002-09-09 * add jfs_tune utility (see jfs_tune man page for details) jfs_tune allows users to: attach a JFS external journal to a JFS file system set/change volume label, UUID of JFS file system and external log devices view superblock information of JFS file system and external log devices * add option '-J journal_device' to mkfs.jfs to create an external journal only and optionally set its volume label (see mkfs.jfs man page) * add option '-J device=' to mkfs.jfs to attach an existing JFS external journal to the JFS file system that will be created (see mkfs.jfs man page) * fix mkfs.jfs to store 16 character volume labels properly * code cleaup * add extend support to JFS FSIM for EVMS - see http://sourceforge.net/projects/evms/ New in 1.0.21 - 2002-08-12 * add external log support to xpeek * fix fsck.jfs to update log device number in superblock after logredo with external log. * fix typo in mkfs.jfs Emergency help. (Bas) * do not build currently unused defrag, extendfs utilities * eliminate uuid redefinition compiler warnings * add logsuper functions to libfs * fix printf format specifiers. (Christoph Hellwig) * code cleanup (all) * update JFS FSIM for EVMS - see http://sourceforge.net/projects/evms/ New in 1.0.20 - 2002-06-21 * don't display heartbeat during log format if output is redirected (eliminates strange characters in redirected output from mkfs.jfs with external log, fsck.jfs Phase 9) * fix mkfs.jfs to set version in JFS superblock properly if external log is used (enables JFS external log compatibility with EVMS 1.1-pre2 or greater) * enhance jfsutils to support enormous disks like 8TB+ (Peter C.) * remove unused variables (Christoph Hellwig) New in 1.0.19 - 2002-06-07 * fix jfsutils packaging/build error from 1.0.18 New in 1.0.18 - 2002-05-24 * add support for external log * endian code cleanup * fix typo in fsck.jfs help * fix fsck.jfs bug on big endian machines New in 1.0.17 - 2002-04-02 * more rigorous dtree validation in fsck.jfs * fix fsck.jfs to write to the fsck.jfs log properly on big endian machines * fix xchklog to read the fsck.jfs log properly on big endian machines * fix xpeek to display/modify PXD information properly on big endian machines * replace fsck.jfs heartbeat with alarm() based heartbeat (Christoph Hellwig) * improve mkfs.jfs and fsck.jfs parameter parsing and usage alerts * messaging code cleanup, logredo code cleanup, general code cleanup (all) New in 1.0.16 - 2002-03-11 * make fsck.jfs exit codes conform to fsck (see updated fsck.jfs man page) * display/log fsck.jfs exit code in debug exit msg * fix xchkdmp to print logredo messages * make xchkdmp print message text instead of message number * use PBSIZE for physical block size instead of BLKSSZGET ioctl (eliminates MD error msg "used obsolete MD ioctl", fixes S/390 mkfs.jfs) * remove libfs open/close wrappers (Christoph Hellwig) * messaging code cleanup, general code cleanup (all) New in 1.0.15 - 2002-02-15 * eliminate invalid fsck.jfs internal error 10 * update xpeek and fsck.jfs man pages * better error message if device to be fsck.jfs'ed is not jfs * add support for 4.4 BSD-style getmntinfo (Christoph Hellwig) * include sys/types.h for BSD (Hiten Pandya) * use defacto standard autoconf macro for large file support (Christoph Hellwig) * general jfsutils code cleanup (all) New in 1.0.14 - 2002-01-28 * fix typecast problem causing fsck.jfs 'corrupt superblock' error message * remove old types PVOID, UCHAR, USHORT, ULONG (code cleanup) New in 1.0.13 - 2002-01-25 * update xchklog and xchkdump parameters and man pages * reduce/eliminate instances of 'access beyond end of device' error message * compatibility fix for different versions of automake * fix typo in spec file * defines cleanup (Christoph Hellwig) * unicode cleanup (Christoph Hellwig) * endian portability fix (Christoph Hellwig) * convert types uxx, uintxx, sxx, intxx to C99 types (code cleanup) New in 1.0.12 - 2002-01-08 * autoheader must precede automake or config.h doesn't make the tarball * use current date as release date in jfs utils (Christoph Hellwig) * fix fsck to update maps at auto check time (fixes file system corruption). * fix file system utilities to be more portable (Christoph Hellwig) New in 1.0.11 - 2001-12-17 * convert JFS utilities to use autoconf/automake (Christoph Hellwig) * display correct error messages for disk not accessible * have all utilities print version number New in 1.0.10 - 2001-11-28 * fsck shouldn't endian swap dtree struct twice New in 1.0.9 - 2001-11-09 * don't print heartbeat if fsck.jfs output is redirected * make mkfs.jfs options conform to mkfs, clean up parse code * fix typo in mkfs.jfs man_html page * allow xpeek to show us directory xtrees * fix fsck.jfs infinite loop on big endian hardware (jitterbug 182) * fix infinite loop when endian swapping bad directory tree page New in 1.0.8 - 2001-10-17 * install prefix support for jfsutils * cleanup option handling make -y behave (jitterbug 177), -f override -p * Add more informative error message when running fsck.jfs RO, (jitterbug 173) * clean up remove carriage return after new line in messaging * print mkfs.jfs version correctly New in 1.0.7 - 2001-10-10 * improve fsck's 'mounted' detection. * improve utils' checking for fs type jfs * replace __uX with uintX_t * change fsck.jfs options to be similar to e2fsck * set fsck.jfs default to automatically fix the file system New in 1.0.6 - 2001-09-28 * If fsck rebuilds root directory, reset di_next_index to 2 * fsck needs to process, validate inodes with size=0 New in 1.0.5 - 2001-09-14 * Fixed jfsprogs.spec to handle utilities not being in the file system source tree * Cleaned up include files * Fixed inconsistencies in mkfs man, html pages New in 1.0.4 - 2001-08-31 * Fixed typecast problem causing intermittent fsck failures on 64 bit hardware (jitterbug 159) * Fixed pointer calculation problem causing intermittent fsck failures on 64bit hardware * Fixed compiler warnings on s/390 and IA64 * Fixed structure size mismatch between file system and utilities causing fsck problems when large numbers of inodes are used * Fixed seg fault in fsck when logging path lengths greater than 512 characters * Fixed fsck printf format errors New in 1.0.3 - 2001-08-20 * Fixed compiler warnings on 64 bit systems * Created jfsutils package New in 1.0.2 - 2001-08-03 * Fixed mkfs to display the correct error message if device name is not valid or missing * gzip the man pages and place /usr/share/man/man8 * Fixed mkfs to properly setup buf_ai * Fixed fsck to display path correctly New in 1.0.1 - 2001-07-10 * Updated jfsprogs.spec file make it work on more distros * Add force option to mkfs so the confirmation message isn't displayed * Fixed fsck to handle index table on the root directory. * Fixed error message displayed when partition was just created and haven't rebooted (jitterbug 130) * Correctly place the built utilities in /sbin vs. /usr/sbin when using the make install option. New in 1.0.0 - 2001-06-28 * Fixed small logredo problem jfsutils-1.1.15.orig/README0000644000000000000000000000374711534235035012163 0ustar IBM's Journaled File System (JFS) for Linux JFS Utilities Version 1.1.15, March 4, 2011 The NEWS file contains a brief overview of user-visible changes to the utilities. The ChangeLog file contains a list of specific changes to the JFS utilities. INSTALLATION ------------ There are 3 methods to install the JFS utilities: Note: The utilities require the uuid.h file. Most Linux Distributions ship this file in the e2fsprogs-devel package, please install the e2fsprogs-devel package before you build the utilities. A. Installation - RPM --------------------- 1) You can use the RPM distribution to build the JFS utilities: rpmbuild -tb jfsutils-1.1.13.tar.gz B. Installation - Building From Source From Tar Ball ---------------------------------------------------- After the source has been unzipped and untarred: 1) Change directory into the top of the jfsutils source tree. 2) Run the configure script: ./configure 3) Compile the utilities: make 4) Install the utilities: make install C. Installation - Building From Source From CVS Tree ---------------------------------------------------- After the source has been retrieved from the CVS Tree: 1) Change directory into the top of the jfsutils source tree. 2) Run the autogen.sh script: ./autogen.sh 3) Compile the utilities: make 4) Install the utilities: make install CVS ACCESS ---------- anonymous cvs access is available for the JFS utilities from sourceforge.net. To checkout the sources: cvs -d:pserver:anonymous@jfs.cvs.sourceforge.net:/cvsroot/jfs login No password, just press enter cvs -z3 -d:pserver:anonymous@jfs.cvs.sourceforge.net:/cvsroot/jfs co -P jfsutils SEE ALSO -------- man pages for the JFS utilities README file included in the JFS file system http://jfs.sourceforge.net/ Please send bugs, comments, cards and letters to shaggy@kernel.org The JFS mailing lists can be subscribed to by using any of the links containing "subscribe" along the left side of our web page at http://jfs.sourceforge.net jfsutils-1.1.15.orig/aclocal.m40000644000000000000000000010766311534235512013145 0ustar # generated automatically by aclocal 1.11.1 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2007, 2008, 2009 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_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.65],, [m4_warning([this file was generated for autoconf 2.65. 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, 2003, 2005, 2006, 2007, 2008 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.11' 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.11.1], [], [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.11.1])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, 2003, 2005 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], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 # 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. # serial 9 # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ(2.52)dnl ifelse([$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])]) # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009 # 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. # serial 10 # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "GCJ", or "OBJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl ifelse([$1], CC, [depcc="$CC" am_compiler_list=], [$1], CXX, [depcc="$CXX" am_compiler_list=], [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], UPC, [depcc="$UPC" am_compiler_list=], [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvisualcpp | msvcmsys) # This compiler won't grok `-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE(dependency-tracking, [ --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 # 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. #serial 5 # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Autoconf 2.62 quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each `.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 # 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. # serial 8 # AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2008, 2009 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. # serial 16 # 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. # 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.62])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], [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], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, [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([AM_PROG_MKDIR_P])dnl # We need awk for the "check" target. 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)], [define([AC_PROG_CC], defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES(CXX)], [define([AC_PROG_CXX], defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES(OBJC)], [define([AC_PROG_OBJC], defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl ]) _AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl dnl The `parallel-tests' driver may need to know about EXEEXT, so add the dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro dnl 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 ]) 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, 2003, 2005, 2008 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}" != 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, 2005 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. # serial 2 # 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])]) # Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # From Jim Meyering # Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008 # 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. # serial 5 # AM_MAINTAINER_MODE([DEFAULT-MODE]) # ---------------------------------- # Control maintainer-specific portions of Makefiles. # Default is to disable them, unless `enable' is passed literally. # For symmetry, `disable' may be passed as well. Anyway, the user # can override the default with the --enable/--disable switch. AC_DEFUN([AM_MAINTAINER_MODE], [m4_case(m4_default([$1], [disable]), [enable], [m4_define([am_maintainer_other], [disable])], [disable], [m4_define([am_maintainer_other], [enable])], [m4_define([am_maintainer_other], [enable]) m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) AC_MSG_CHECKING([whether to am_maintainer_other maintainer-specific portions of Makefiles]) dnl maintainer-mode's default is 'disable' unless 'enable' is passed AC_ARG_ENABLE([maintainer-mode], [ --][am_maintainer_other][-maintainer-mode am_maintainer_other make rules and dependencies not useful (and sometimes confusing) to the casual installer], [USE_MAINTAINER_MODE=$enableval], [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) AC_MSG_RESULT([$USE_MAINTAINER_MODE]) AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) MAINT=$MAINTAINER_MODE_TRUE AC_SUBST([MAINT])dnl ] ) AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005, 2009 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. # serial 4 # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from `make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 # 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. # serial 6 # 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 supports --run. # If it does, 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 --run true"; then am_missing_run="$MISSING --run " else am_missing_run= AC_MSG_WARN([`missing' script is too old or missing]) fi ]) # Copyright (C) 2003, 2004, 2005, 2006 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_MKDIR_P # --------------- # Check for `mkdir -p'. AC_DEFUN([AM_PROG_MKDIR_P], [AC_PREREQ([2.60])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, dnl while keeping a definition of mkdir_p for backward compatibility. dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of dnl Makefile.ins that do not define MKDIR_P, so we do our own dnl adjustment using top_builddir (which is defined more often than dnl MKDIR_P). AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl case $mkdir_p in [[\\/$]]* | ?:[[\\/]]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005, 2008 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. # serial 4 # _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])]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008 # 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. # serial 5 # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Just in case sleep 1 echo timestamp > conftest.file # 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 ( 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 rm -f conftest.file 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 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)]) # Copyright (C) 2001, 2003, 2005 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, 2008 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. # serial 2 # _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, 2005 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. # serial 2 # _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. AM_MISSING_PROG([AMTAR], [tar]) m4_if([$1], [v7], [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], [m4_case([$1], [ustar],, [pax],, [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' _am_tools=${am_cv_prog_tar_$1-$_am_tools} # Do not fold the above two line into one, because Tru64 sh and # Solaris sh will not grok spaces in the rhs of `-'. 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 jfsutils-1.1.15.orig/config.h.in0000644000000000000000000001002111534235512013305 0ustar /* config.h.in. Generated from configure.in by autoheader. */ /* Define to 1 if you have the header file. */ #undef HAVE_ENDIAN_H /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ #undef HAVE_FSEEKO /* Define to 1 if you have the `getcwd' function. */ #undef HAVE_GETCWD /* Define to 1 if you have the `getmntinfo' function. */ #undef HAVE_GETMNTINFO /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_MACHINE_ENDIAN_H /* Define to 1 if you have the `memalign' function. */ #undef HAVE_MEMALIGN /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the header file. */ #undef HAVE_MNTENT_H /* Define to 1 if you have the `posix_memalign' function. */ #undef HAVE_POSIX_MEMALIGN /* Define to 1 if you have the header file. */ #undef HAVE_STDBOOL_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 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 `strtol' function. */ #undef HAVE_STRTOL /* Define to 1 if you have the `strtoul' function. */ #undef HAVE_STRTOUL /* Define to 1 if `st_rdev' is a member of `struct stat'. */ #undef HAVE_STRUCT_STAT_ST_RDEV /* Define to 1 if your `struct stat' has `st_rdev'. Deprecated, use `HAVE_STRUCT_STAT_ST_RDEV' instead. */ #undef HAVE_ST_RDEV /* Define to 1 if you have the header file. */ #undef HAVE_SYS_BYTEORDER_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_DISKLABEL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MOUNT_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_STATVFS_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_SYSMACROS_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_UNISTD_H /* Define to 1 if you have the header file. */ #undef HAVE_UUID_UUID_H /* 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 your declares `struct tm'. */ #undef TM_IN_SYS_TIME /* Version number of package */ #undef VERSION /* Number of bits in a file offset, on hosts where this is settable. */ #undef _FILE_OFFSET_BITS /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ #undef _LARGEFILE_SOURCE /* Define for large files, on AIX-style hosts. */ #undef _LARGE_FILES /* 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 `int' if does not define. */ #undef mode_t /* Define to `long int' if does not define. */ #undef off_t /* Define to `unsigned int' if does not define. */ #undef size_t jfsutils-1.1.15.orig/configure0000755000000000000000000055156511534235513013221 0ustar #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.65. # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 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. 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 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" 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 : # 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. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} 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_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 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=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&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; } # 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 -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' 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 if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # 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, 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= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= PACKAGE_URL= ac_unique_file="libfs/super.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_default_prefix=/usr ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS AM_CFLAGS LIBOBJS EGREP GREP CPP RANLIB LN_S LN am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC MAINT MAINTAINER_MODE_FALSE MAINTAINER_MODE_TRUE 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_maintainer_mode enable_dependency_tracking enable_largefile ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # 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}' 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=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 $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 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 this package 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/PACKAGE] --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 _ACEOF fi if test -n "$ac_init_help"; then 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-maintainer-mode enable make rules and dependencies not useful (and sometimes confusing) to the casual installer --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors --disable-largefile omit support for large files 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 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. _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 configure generated by GNU Autoconf 2.65 Copyright (C) 2009 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; test "x$as_lineno_stack" = x && { as_lineno=; 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; } >/dev/null && { 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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # 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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_run # 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 { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; 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.$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 { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; 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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_header_mongrel # 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 { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; 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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_header_compile # 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 { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; 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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_type # 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 { as_var=$4; eval "test \"\${$as_var+set}\" = set"; }; 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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} } # ac_fn_c_check_member # 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 || $as_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; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} as_fn_set_status $ac_retval } # ac_fn_c_try_link # 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 { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; 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; test "x$as_lineno_stack" = x && { as_lineno=; 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 $as_me, which was generated by GNU Autoconf 2.65. 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 cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX 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 cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX 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 cat <<\_ASBOX ## ------------------- ## ## File substitutions. ## ## ------------------- ## _ASBOX 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 cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX 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 ac_site_file1=$CONFIG_SITE 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" 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.11' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do for ac_t in install-sh install.sh shtool; do if test -f "$ac_dir/$ac_t"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/$ac_t -c" break 2 fi done 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 test "${ac_cv_path_install+set}" = set; 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 { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$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; } # Just in case sleep 1 echo timestamp > conftest.file # 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 ( 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 rm -f conftest.file 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 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; } 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 --run true"; then am_missing_run="$MISSING --run " 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}" != 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 test "${ac_cv_prog_STRIP+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_STRIP+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_path_mkdir+set}" = set; 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 { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$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; } mkdir_p="$MKDIR_P" case $mkdir_p in [\\/$]* | ?:[\\/]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac 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 test "${ac_cv_prog_AWK+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; 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 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=jfsutils VERSION=1.1.15 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"} # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. AMTAR=${AMTAR-"${am_missing_run}tar"} am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' ac_config_headers="$ac_config_headers config.h" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } # Check whether --enable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then : enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval else USE_MAINTAINER_MODE=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 $as_echo "$USE_MAINTAINER_MODE" >&6; } if test $USE_MAINTAINER_MODE = yes; then MAINTAINER_MODE_TRUE= MAINTAINER_MODE_FALSE='#' else MAINTAINER_MODE_TRUE='#' MAINTAINER_MODE_FALSE= fi MAINT=$MAINTAINER_MODE_TRUE 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 test "${ac_cv_prog_AWK+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 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 test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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 test "${ac_cv_prog_ac_ct_CC+set}" = set; 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$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_set_status 77 as_fn_error "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 test "${ac_cv_objext+set}" = set; 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 test "${ac_cv_c_compiler_gnu+set}" = set; 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 test "${ac_cv_prog_cc_g+set}" = set; 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 test "${ac_cv_prog_cc_c89+set}" = set; 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 #include #include /* 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 DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from `make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvisualcpp | msvcmsys) # This compiler won't grok `-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi # Extract the first word of "ln", so it can be a program name with args. set dummy ln; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_path_LN+set}" = set; then : $as_echo_n "(cached) " >&6 else case $LN in [\\/]* | ?:[\\/]*) ac_cv_path_LN="$LN" # Let the user override the test with a path. ;; *) 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_LN="$as_dir/$ac_word$ac_exec_ext" $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 test -z "$ac_cv_path_LN" && ac_cv_path_LN="ln" ;; esac fi LN=$ac_cv_path_LN if test -n "$LN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LN" >&5 $as_echo "$LN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_RANLIB+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $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 RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_RANLIB="ranlib" $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_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" 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 RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" 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 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 test "${ac_cv_prog_CPP+set}" = set; 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.$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.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f 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.$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.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f 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 test "${ac_cv_path_GREP+set}" = set; 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" { test -f "$ac_path_GREP" && $as_test_x "$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 test "${ac_cv_path_EGREP+set}" = set; 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" { test -f "$ac_path_EGREP" && $as_test_x "$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 test "${ac_cv_header_stdc+set}" = set; 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 " eval as_val=\$$as_ac_Header if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in endian.h fcntl.h mntent.h unistd.h stdbool.h stdint.h machine/endian.h sys/byteorder.h sys/mount.h sys/param.h sys/statvfs.h sys/sysmacros.h sys/disklabel.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" eval as_val=\$$as_ac_Header if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in uuid/uuid.h do : ac_fn_c_check_header_mongrel "$LINENO" "uuid/uuid.h" "ac_cv_header_uuid_uuid_h" "$ac_includes_default" if test "x$ac_cv_header_uuid_uuid_h" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UUID_UUID_H 1 _ACEOF else as_fn_error "'Install e2fsprogs-libs e2fsprogs-devel or uuid-dev'" "$LINENO" 5 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 test "${ac_cv_c_const+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { /* FIXME: Include the comments suggested by Paul. */ #ifndef __cplusplus /* Ultrix mips cc rejects this. */ typedef int charset[2]; const charset cs; /* 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. */ char *t; 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 saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; }; struct s *b; 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 test "${ac_cv_c_inline+set}" = set; 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 ac_fn_c_check_type "$LINENO" "mode_t" "ac_cv_type_mode_t" "$ac_includes_default" if test "x$ac_cv_type_mode_t" = x""yes; then : else cat >>confdefs.h <<_ACEOF #define mode_t 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" = x""yes; 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" = x""yes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi ac_fn_c_check_member "$LINENO" "struct stat" "st_rdev" "ac_cv_member_struct_stat_st_rdev" "$ac_includes_default" if test "x$ac_cv_member_struct_stat_st_rdev" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_STAT_ST_RDEV 1 _ACEOF $as_echo "#define HAVE_ST_RDEV 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5 $as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; } if test "${ac_cv_struct_tm+set}" = set; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { struct tm tm; int *p = &tm.tm_sec; return !p; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_struct_tm=time.h else ac_cv_struct_tm=sys/time.h fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5 $as_echo "$ac_cv_struct_tm" >&6; } if test $ac_cv_struct_tm = sys/time.h; then $as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working memcmp" >&5 $as_echo_n "checking for working memcmp... " >&6; } if test "${ac_cv_func_memcmp_working+set}" = set; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_memcmp_working=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* Some versions of memcmp are not 8-bit clean. */ char c0 = '\100', c1 = '\200', c2 = '\201'; if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0) return 1; /* The Next x86 OpenStep bug shows up only when comparing 16 bytes or more and with at least one buffer not starting on a 4-byte boundary. William Lewis provided this test program. */ { char foo[21]; char bar[21]; int i; for (i = 0; i < 4; i++) { char *a = foo + i; char *b = bar + i; strcpy (a, "--------01111111"); strcpy (b, "--------10000000"); if (memcmp (a, b, 16) >= 0) return 1; } return 0; } ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_memcmp_working=yes else ac_cv_func_memcmp_working=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 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_memcmp_working" >&5 $as_echo "$ac_cv_func_memcmp_working" >&6; } test $ac_cv_func_memcmp_working = no && case " $LIBOBJS " in *" memcmp.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS memcmp.$ac_objext" ;; esac for ac_func in getcwd getmntinfo strtol strtoul posix_memalign memalign 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" eval as_val=\$$as_ac_var if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done # 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 test "${ac_cv_sys_largefile_CC+set}" = set; 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 test "${ac_cv_sys_file_offset_bits+set}" = set; 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 test "${ac_cv_sys_large_files+set}" = set; 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 for _LARGEFILE_SOURCE value needed for large files" >&5 $as_echo_n "checking for _LARGEFILE_SOURCE value needed for large files... " >&6; } if test "${ac_cv_sys_largefile_source+set}" = set; then : $as_echo_n "(cached) " >&6 else while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include /* for off_t */ #include int main () { int (*fp) (FILE *, off_t, int) = fseeko; return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_sys_largefile_source=no; break fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _LARGEFILE_SOURCE 1 #include /* for off_t */ #include int main () { int (*fp) (FILE *, off_t, int) = fseeko; return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_sys_largefile_source=1; break fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_cv_sys_largefile_source=unknown break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_source" >&5 $as_echo "$ac_cv_sys_largefile_source" >&6; } case $ac_cv_sys_largefile_source in #( no | unknown) ;; *) cat >>confdefs.h <<_ACEOF #define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source _ACEOF ;; esac rm -rf conftest* # We used to try defining _XOPEN_SOURCE=500 too, to work around a bug # in glibc 2.1.3, but that breaks too many other things. # If you want fseeko and ftello with glibc, upgrade to a fixed glibc. if test $ac_cv_sys_largefile_source != unknown; then $as_echo "#define HAVE_FSEEKO 1" >>confdefs.h fi if [ "x$CC" = xgcc ]; then AM_CFLAGS="-Wall -Wstrict-prototypes -fno-strict-aliasing" fi if [ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ]; then sbindir="/sbin" fi ac_config_files="$ac_config_files Makefile libfs/Makefile include/Makefile fsck/Makefile fscklog/Makefile logdump/Makefile mkfs/Makefile tune/Makefile xpeek/Makefile jfsutils.spec" 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 test "x$cache_file" != "x/dev/null" && { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file 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= 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 if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then as_fn_error "conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error "conditional \"am__fastdepCC\" 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. 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 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=$?; test $as_status -eq 0 && as_status=1 if test "$3"; then as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 fi $as_echo "$as_me: error: $1" >&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 -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' 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 if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # 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 $as_me, which was generated by GNU Autoconf 2.65. 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" config_commands="$ac_config_commands" _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 Configuration commands: $config_commands Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.65, with options \\"\$ac_cs_config\\" Copyright (C) 2009 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=$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"` ;; 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 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" _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" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "libfs/Makefile") CONFIG_FILES="$CONFIG_FILES libfs/Makefile" ;; "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; "fsck/Makefile") CONFIG_FILES="$CONFIG_FILES fsck/Makefile" ;; "fscklog/Makefile") CONFIG_FILES="$CONFIG_FILES fscklog/Makefile" ;; "logdump/Makefile") CONFIG_FILES="$CONFIG_FILES logdump/Makefile" ;; "mkfs/Makefile") CONFIG_FILES="$CONFIG_FILES mkfs/Makefile" ;; "tune/Makefile") CONFIG_FILES="$CONFIG_FILES tune/Makefile" ;; "xpeek/Makefile") CONFIG_FILES="$CONFIG_FILES xpeek/Makefile" ;; "jfsutils.spec") CONFIG_FILES="$CONFIG_FILES jfsutils.spec" ;; *) 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 test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands 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= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$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 -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 # 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 {' >"$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 >>"\$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 >>"\$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 < "$tmp/subs1.awk" > "$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 $(srcdir), # ${srcdir} and @srcdir@ 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[ ]*=/{ s/:*\$(srcdir):*/:/ s/:*\${srcdir}:*/:/ s/:*@srcdir@:*/:/ s/^\([^=]*=[ ]*\):*/\1/ s/:*$// 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 >"$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_t=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_t"; 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 :C $CONFIG_COMMANDS" 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="$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 "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 >"$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 "$tmp/subs.awk" >$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' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$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 "$tmp/stdin" case $ac_file in -) cat "$tmp/out" && rm -f "$tmp/out";; *) rm -f "$ac_file" && mv "$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 "$tmp/defines.awk"' "$ac_file_inputs" } >"$tmp/config.h" \ || as_fn_error "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$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 "$tmp/config.h" "$ac_file" \ || as_fn_error "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$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 ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Autoconf 2.62 quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; 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 $? 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 jfsutils-1.1.15.orig/configure.in0000644000000000000000000000273011534235035013603 0ustar dnl Process this file with autoconf to produce a configure script. AC_INIT(libfs/super.c) dnl Package name and version AM_INIT_AUTOMAKE(jfsutils, 1.1.15) AM_CONFIG_HEADER(config.h) dnl Don't include maintainer make-rules by default AM_MAINTAINER_MODE dnl Checks for programs. AC_PROG_AWK AC_PROG_CC AC_PROG_INSTALL AC_PATH_PROG(LN, ln, ln) AC_PROG_LN_S AC_PROG_RANLIB dnl Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS(endian.h fcntl.h mntent.h unistd.h stdbool.h stdint.h machine/endian.h sys/byteorder.h sys/mount.h sys/param.h sys/statvfs.h sys/sysmacros.h sys/disklabel.h) AC_CHECK_HEADERS(uuid/uuid.h,,AC_MSG_ERROR('Install e2fsprogs-libs e2fsprogs-devel or uuid-dev')) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_C_INLINE AC_TYPE_MODE_T AC_TYPE_OFF_T AC_TYPE_SIZE_T AC_STRUCT_ST_RDEV AC_STRUCT_TM dnl Checks for library functions. AC_FUNC_MEMCMP AC_CHECK_FUNCS(getcwd getmntinfo strtol strtoul posix_memalign memalign) dnl large file support AC_SYS_LARGEFILE AC_FUNC_FSEEKO dnl additional compiler warnings if [[ "x$CC" = xgcc ]]; then AC_SUBST(AM_CFLAGS, "-Wall -Wstrict-prototypes -fno-strict-aliasing") fi dnl By default install into system location. AC_PREFIX_DEFAULT(/usr) if [[ "x$exec_prefix" = xNONE -a "x$prefix" = xNONE ]]; then sbindir="/sbin" fi AC_OUTPUT([ Makefile libfs/Makefile include/Makefile fsck/Makefile fscklog/Makefile logdump/Makefile mkfs/Makefile tune/Makefile xpeek/Makefile jfsutils.spec ]) jfsutils-1.1.15.orig/depcomp0000755000000000000000000004426711460142743012663 0ustar #! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2009-04-28.21; # UTC # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free # Software Foundation, Inc. # 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. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by `PROGRAMS ARGS'. object Object file output by `PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputing dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u="sed s,\\\\\\\\,/,g" depmode=msvisualcpp fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the `deleted header file' problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. tr ' ' ' ' < "$tmpdepfile" | ## Some versions of gcc put a space before the `:'. On the theory ## that the space means something, we add a space to the output as ## well. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like `#:fec' to the end of the # dependency line. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr ' ' ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts `$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then # Each line is of the form `foo.o: dependent.h'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; icc) # Intel's C compiler understands `-MD -MF file'. However on # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c # ICC 7.0 will fill foo.d with something like # foo.o: sub/foo.c # foo.o: sub/foo.h # which is wrong. We want: # sub/foo.o: sub/foo.c # sub/foo.o: sub/foo.h # sub/foo.c: # sub/foo.h: # ICC 7.1 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using \ : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" # Add `dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in `foo.d' instead, so we check for that too. # Subdirectories are respected. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then # With Tru64 cc, shared objects can also be used to make a # static library. This mechanism is used in libtool 1.4 series to # handle both shared and static libraries in a single compilation. # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. # # With libtool 1.5 this exception was removed, and libtool now # generates 2 separate objects for the 2 libraries. These two # compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 tmpdepfile2=$dir$base.o.d # libtool 1.5 tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.o.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d tmpdepfile4=$dir$base.d "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for `:' # in the target name. This is to cope with DOS-style filenames: # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. "$@" $dashmflag | sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' ' < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' ' ' | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" echo " " >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # 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: jfsutils-1.1.15.orig/fsck/0000755000000000000000000000000011534235600012214 5ustar jfsutils-1.1.15.orig/fsck/Makefile.am0000644000000000000000000000127610340701412014247 0ustar INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/libfs LDADD = ../libfs/libfs.a -luuid sbin_PROGRAMS = jfs_fsck man_MANS = jfs_fsck.8 EXTRA_DIST = $(man_MANS) jfs_fsck_SOURCES = fsckbmap.c fsckconn.c fsckdire.c fsckdtre.c fsckea.c \ fsckimap.c fsckino.c fsckmeta.c fsckpfs.c dirindex.c \ fsckwsp.c fsckxtre.c xchkdsk.c fsckruns.c fsck_message.c \ fsckpfs.h xchkdsk.h xfsck.h xfsckint.h install-exec-hook: $(LN) -f $(DESTDIR)$(sbindir)/jfs_fsck $(DESTDIR)$(sbindir)/fsck.jfs install-data-hook: $(LN) -f $(DESTDIR)$(man8dir)/jfs_fsck.8 $(DESTDIR)$(man8dir)/fsck.jfs.8 uninstall-local: rm -f $(DESTDIR)$(sbindir)/fsck.jfs rm -f $(DESTDIR)$(man8dir)/fsck.jfs.8 jfsutils-1.1.15.orig/fsck/Makefile.in0000644000000000000000000004646011534235513014276 0ustar # Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@ 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 = : sbin_PROGRAMS = jfs_fsck$(EXEEXT) subdir = fsck DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)" PROGRAMS = $(sbin_PROGRAMS) am_jfs_fsck_OBJECTS = fsckbmap.$(OBJEXT) fsckconn.$(OBJEXT) \ fsckdire.$(OBJEXT) fsckdtre.$(OBJEXT) fsckea.$(OBJEXT) \ fsckimap.$(OBJEXT) fsckino.$(OBJEXT) fsckmeta.$(OBJEXT) \ fsckpfs.$(OBJEXT) dirindex.$(OBJEXT) fsckwsp.$(OBJEXT) \ fsckxtre.$(OBJEXT) xchkdsk.$(OBJEXT) fsckruns.$(OBJEXT) \ fsck_message.$(OBJEXT) jfs_fsck_OBJECTS = $(am_jfs_fsck_OBJECTS) jfs_fsck_LDADD = $(LDADD) jfs_fsck_DEPENDENCIES = ../libfs/libfs.a DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(jfs_fsck_SOURCES) DIST_SOURCES = $(jfs_fsck_SOURCES) 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' man8dir = $(mandir)/man8 NROFF = nroff MANS = $(man_MANS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_CFLAGS = @AM_CFLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ 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@ LN = @LN@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ 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@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ 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__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ 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@ INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/libfs LDADD = ../libfs/libfs.a -luuid man_MANS = jfs_fsck.8 EXTRA_DIST = $(man_MANS) jfs_fsck_SOURCES = fsckbmap.c fsckconn.c fsckdire.c fsckdtre.c fsckea.c \ fsckimap.c fsckino.c fsckmeta.c fsckpfs.c dirindex.c \ fsckwsp.c fsckxtre.c xchkdsk.c fsckruns.c fsck_message.c \ fsckpfs.h xchkdsk.h xfsck.h xfsckint.h all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu fsck/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu fsck/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)" @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ 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)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || 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)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) jfs_fsck$(EXEEXT): $(jfs_fsck_OBJECTS) $(jfs_fsck_DEPENDENCIES) @rm -f jfs_fsck$(EXEEXT) $(LINK) $(jfs_fsck_OBJECTS) $(jfs_fsck_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dirindex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsck_message.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsckbmap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsckconn.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsckdire.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsckdtre.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsckea.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsckimap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsckino.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsckmeta.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsckpfs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsckruns.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsckwsp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsckxtre.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xchkdsk.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` install-man8: $(man_MANS) @$(NORMAL_INSTALL) test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)" @list=''; test -n "$(man8dir)" || exit 0; \ { for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | 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,^[^8][0-9a-z]*$$,8,;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)$(man8dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$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)$(man8dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ done; } uninstall-man8: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man8dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ test -z "$$files" || { \ echo " ( cd '$(DESTDIR)$(man8dir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(man8dir)" && rm -f $$files; } ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ 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 CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ 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" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically \`make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi @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 check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(MANS) installdirs: for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"; 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: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install 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) 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-generic clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-man @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-data-hook install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-sbinPROGRAMS @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-exec-hook install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man8 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-local uninstall-man uninstall-sbinPROGRAMS uninstall-man: uninstall-man8 .MAKE: install-am install-data-am install-exec-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-sbinPROGRAMS ctags distclean distclean-compile \ distclean-generic distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-data-hook install-dvi install-dvi-am \ install-exec install-exec-am install-exec-hook install-html \ install-html-am install-info install-info-am install-man \ install-man8 install-pdf install-pdf-am install-ps \ install-ps-am install-sbinPROGRAMS install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ uninstall-am uninstall-local uninstall-man uninstall-man8 \ uninstall-sbinPROGRAMS install-exec-hook: $(LN) -f $(DESTDIR)$(sbindir)/jfs_fsck $(DESTDIR)$(sbindir)/fsck.jfs install-data-hook: $(LN) -f $(DESTDIR)$(man8dir)/jfs_fsck.8 $(DESTDIR)$(man8dir)/fsck.jfs.8 uninstall-local: rm -f $(DESTDIR)$(sbindir)/fsck.jfs rm -f $(DESTDIR)$(man8dir)/fsck.jfs.8 # 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: jfsutils-1.1.15.orig/fsck/dirindex.c0000644000000000000000000001541010361223261014164 0ustar /* * Copyright (C) International Business Machines Corp., 2004,2005 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include /* defines and includes common among the fsck.jfs modules */ #include "xfsckint.h" #include "devices.h" #include "message.h" /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * superblock buffer pointer * * defined in xchkdsk.c */ extern struct superblock *sb_ptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * fsck aggregate info structure pointer * * defined in xchkdsk.c */ extern struct fsck_agg_record *agg_recptr; /* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV * * The following are internal to this file * */ /* * Since access to the directory index may not be sequential, keep a number * of pages resident */ #define NUM_INDEX_BUFS 16 struct dir_index_page { long long address; struct dir_index_page *next; struct dir_index_page *prev; int flag; struct dir_table_slot table[512]; }; #define DIPAGE_DIRTY 1 struct dir_index_page *dir_index_buffers; struct dir_index_page *free_di_page; /* free list */ struct dir_index_page *lru_di_page; /* least-recently-used */ struct dir_index_page *mru_di_page; /* most-recently-used */ int allocate_dir_index_buffers(void) { int i; struct dir_index_page *page, *last; dir_index_buffers = malloc(sizeof(struct dir_index_page) * NUM_INDEX_BUFS); if (! dir_index_buffers) { fsck_send_msg(MSG_OSO_INSUFF_MEMORY); return ENOMEM; } page = dir_index_buffers; last = NULL; for (i = 0; i < NUM_INDEX_BUFS; i++) { page->address = 0; page->next = last; page->prev = NULL; /* Not used on free list */ page->flag = 0; last = page; page++; } free_di_page = last; lru_di_page = mru_di_page = NULL; return FSCK_OK; } static int write_index_page(struct dir_index_page *page) { int rc; rc = ujfs_rw_diskblocks(Dev_IOPort, page->address << sb_ptr->s_l2bsize, PSIZE, page->table, PUT); return rc; } static struct dir_table_slot *read_index_page(struct dinode *inoptr, uint cookie) { long long address; int64_t blkno; int8_t match_found; int64_t offset; struct dir_index_page *page; int rc; xad_t *xad_ptr; offset = (cookie - 2) * sizeof (struct dir_table_slot); blkno = (offset >> L2PSIZE) << (L2PSIZE - sb_ptr->s_l2bsize); rc = xTree_search(inoptr, blkno, &xad_ptr, &match_found); if (rc || !match_found) return NULL; address = addressXAD(xad_ptr); /* Search cache. Is it worthwhile to build a hash? */ for (page = mru_di_page; page; page = page->next) { if (page->address == address) { /* hit! */ if (page != mru_di_page) { /* remove from linked list */ if (page == lru_di_page) lru_di_page = page->prev; else page->next->prev = page->prev; page->prev->next = page->next; /* add back at front (mru) */ mru_di_page->prev = page; page->next = mru_di_page; page->prev = NULL; mru_di_page = page; } return page->table; } } if (free_di_page) { page = free_di_page; free_di_page = page->next; } else { page = lru_di_page; if (page->flag & DIPAGE_DIRTY) write_index_page(page); lru_di_page = page->prev; lru_di_page->next = NULL; } page->address = address; page->flag = 0; rc = ujfs_rw_diskblocks(Dev_IOPort, address << sb_ptr->s_l2bsize, PSIZE, page->table, GET); if (rc) { page->next = free_di_page; free_di_page = page; return NULL; } /* Insert into lru list */ page->next = mru_di_page; page->prev = NULL; mru_di_page = page; if (page->next) page->next->prev = page; else lru_di_page = page; return page->table; } int flush_index_pages() { struct dir_index_page *page; int rc = 0, rc2; for (page = mru_di_page; page; page = page->next) { if (page->flag & DIPAGE_DIRTY) { rc2 = write_index_page(page); if (!rc) rc = rc2; page->flag &= ~DIPAGE_DIRTY; } } return rc; } static void dirty_index_page(struct dir_table_slot *table) { /* Should only be called on most recent page */ if (table != mru_di_page->table) { /* Really shoudn't happen. */ printf("You messed up, Shaggy. write_index_page mismatch.\n"); return; } mru_di_page->flag |= DIPAGE_DIRTY; } void verify_dir_index(struct fsck_inode_record *inorecptr, struct dinode *inoptr, struct dtreeQelem *this_Qel, int dtindex, uint cookie) { int64_t page_addr; struct dir_table_slot *slot; struct dir_table_slot *table; if (!inorecptr->check_dir_index) return; /* * FIXME: Don't treat cookie == 0 as an error right now since the * file system will fix this at runtime. When fsck rebuilds the * index entirely, we will want to go ahead and rebuild if a zero * is found. */ if (cookie == 0) return; if ((cookie < 2) || (cookie >= inoptr->di_next_index)) { fsck_send_msg(fsck_BAD_COOKIE); goto error_found; } if (inoptr->di_next_index <= (MAX_INLINE_DIRTABLE_ENTRY + 1)) { table = inoptr->di_dirtable; slot = &table[cookie - 2]; } else { table = read_index_page(inoptr, cookie); if (!table) { fsck_send_msg(fsck_READ_FAILED); goto error_found; } slot = &table[(cookie - 2) % 512]; } if (this_Qel->node_level) page_addr = this_Qel->node_addr; else page_addr = 0; if ((slot->flag == 0) || (slot->slot != dtindex) || (addressDTS(slot) != page_addr)) { fsck_send_msg(fsck_BAD_ENTRY); goto error_found; } return; error_found: inorecptr->check_dir_index = 0; inorecptr->rebuild_dirtable = 1; agg_recptr->corrections_needed = 1; return; } void modify_index(struct dinode *inoptr, int64_t page_addr, int dtindex, uint cookie) { struct dir_table_slot *slot; struct dir_table_slot *table; if (cookie < 2 || (cookie >= inoptr->di_next_index)) return; if (inoptr->di_next_index <= (MAX_INLINE_DIRTABLE_ENTRY + 1)) { slot = &inoptr->di_dirtable[cookie - 2]; DTSaddress(slot, page_addr); slot->slot = dtindex; return; } table = read_index_page(inoptr, cookie); if (!table) return; slot = &table[(cookie - 2) % 512]; DTSaddress(slot, page_addr); slot->slot = dtindex; dirty_index_page(table); } jfsutils-1.1.15.orig/fsck/fsck_message.c0000644000000000000000000000602111165462440015015 0ustar #define _GNU_SOURCE /* for basename() */ #include #include #include #include #include "fsck_message.h" #include "fsckwsp.h" #include "jfs_endian.h" #include "xfsckint.h" int msg_lvl = fsck_debug; int dbg_output = 0; extern struct fsck_agg_record *agg_recptr; /***************************************************************************** * NAME: fsck_record_msg * * FUNCTION: * * PARAMETERS: * ? - input - * ? - returned - * * RETURNS: * nothing */ void fsck_record_msg(char *msg_txt) { char log_entry[max_log_entry_length]; int entry_length = sizeof(struct fscklog_entry_hdr); struct fscklog_entry_hdr *hdptr; char *msg; int32_t buffer_bytes_left; char *buf_entry_ptr; if (agg_recptr->fscklog_full || !agg_recptr->fscklog_buf_allocated || agg_recptr->fscklog_buf_alloc_err) return; /* logging is active */ hdptr = (struct fscklog_entry_hdr *) log_entry; msg = &log_entry[entry_length]; strncpy(msg, msg_txt, max_log_entry_length - entry_length); entry_length += strlen(msg_txt); /* add null terminator to string */ log_entry[entry_length++] = '\0'; /* pad to the next 4 byte boundary */ entry_length = ((entry_length + 3) / 4) * 4; hdptr->entry_length = entry_length; buffer_bytes_left = agg_recptr->fscklog_buf_length - agg_recptr->fscklog_buf_data_len; if (buffer_bytes_left < entry_length) { agg_recptr->fscklog_last_msghdr->entry_length += buffer_bytes_left; fscklog_put_buffer(); // clear the buffer memset((void *) (agg_recptr->fscklog_buf_ptr), 0, agg_recptr->fscklog_buf_length); } if (!agg_recptr->fscklog_full) { buf_entry_ptr = (char *)((char *)agg_recptr->fscklog_buf_ptr + agg_recptr->fscklog_buf_data_len); // swap if on big endian machine ujfs_swap_fscklog_entry_hdr(hdptr); memcpy((void *) buf_entry_ptr, (void *) hdptr, entry_length); agg_recptr->fscklog_last_msghdr = (struct fscklog_entry_hdr *) buf_entry_ptr; agg_recptr->fscklog_buf_data_len += entry_length; } } /***************************************************************************** * NAME: fsck_send_msg * * FUNCTION: * * PARAMETERS: * ? - input - * ? - returned - * * RETURNS: * 0 on success * Non-zero on error */ int v_fsck_send_msg(int msg_num, const char *file_name, int line_number, ...) { struct fsck_message *message = &msg_defs[msg_num]; char msg_string[max_log_entry_length - 4]; char debug_detail[100]; va_list args; va_start(args, line_number); vsnprintf(msg_string, sizeof(msg_string), message->msg_txt, args); va_end(args); sprintf(debug_detail, " [%s:%d]\n", basename(file_name), line_number); if (message->msg_level <= msg_lvl) { printf("%s", msg_string); if (dbg_output) { printf("%s", debug_detail); } else printf("\n"); } // append file and line number information to string for logging strncat(msg_string, debug_detail, max_log_entry_length - 4 - strlen(msg_string)); fsck_record_msg(msg_string); return 0; } jfsutils-1.1.15.orig/fsck/fsckbmap.c0000644000000000000000000014616010441103233014146 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include /* defines and includes common among the fsck.jfs modules */ #include "xfsckint.h" #include "diskmap.h" /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * superblock buffer pointer * * defined in xchkdsk.c */ extern struct superblock *sb_ptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * fsck aggregate info structure pointer * * defined in xchkdsk.c */ extern struct fsck_agg_record *agg_recptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * fsck block map info structure pointer * * defined in xchkdsk.c */ extern struct fsck_bmap_record *bmap_recptr; /* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV * * The following are internal to this file * */ struct fsck_stree_proc_parms { dmtree_t *buf_tree; int8_t *buf_stree; int8_t *wsp_stree; int32_t nleafs; int32_t l2nleafs; int32_t leafidx; int8_t budmin; int page_level; uint32_t page_ordno; int8_t *lfval_error; int8_t *intval_error; }; int ctlpage_rebuild(int8_t); int ctlpage_verify(int8_t); int dmap_pwmap_rebuild(uint32_t *); int dmap_pmap_verify(uint32_t *); int dmap_tree_rebuild(int8_t *); int dmap_tree_verify(int8_t *); int dmappg_rebuild(int8_t *); int dmappg_verify(int8_t *); int init_bmap_info(void); int Ln_tree_rebuild(int, int64_t, struct dmapctl **, int8_t *); int Ln_tree_verify(int, int64_t, struct dmapctl **, int8_t *); int stree_rebuild(struct fsck_stree_proc_parms *, int8_t *); int stree_verify(struct fsck_stree_proc_parms *, int8_t *); int verify_blkall_summary_msgs(void); /* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV */ /***************************************************************************** * NAME: ctlpage_rebuild * * FUNCTION: Rebuild the control page of the filesystem block map. * * PARAMETERS: * max_buddy - input - the data value in the root of the highest * Lx page in the map. * * RETURNS: * success: FSCK_OK * failure: something else */ int ctlpage_rebuild(int8_t max_buddy) { int bcr_rc = FSCK_OK; int32_t highest_active_AG = 0, num_active_AGs = 0, num_inactive_AGs; int64_t avg_free, actAG_free, inactAG_free; int32_t l2nl, n, agidx, index, aglevel, agheight, agwidth, agstart; bcr_rc = mapctl_get(bmap_recptr->bmpctl_agg_fsblk_offset, (void **) &(bmap_recptr->bmpctl_bufptr)); if (bcr_rc == FSCK_OK) { /* swap if on big endian machine */ ujfs_swap_dbmap((struct dbmap *) bmap_recptr->bmpctl_bufptr); bmap_recptr->bmpctl_bufptr->dn_mapsize = bmap_recptr->total_blocks; bmap_recptr->bmpctl_bufptr->dn_nfree = bmap_recptr->free_blocks; bmap_recptr->bmpctl_bufptr->dn_l2nbperpage = agg_recptr->log2_blksperpg; bmap_recptr->bmpctl_bufptr->dn_numag = agg_recptr->num_ag; bmap_recptr->bmpctl_bufptr->dn_maxlevel = BMAPSZTOLEV(agg_recptr->sb_agg_fsblk_length); /* check out the active AGs */ for (agidx = 0; (agidx < MAXAG); agidx++) { if (bmap_recptr->AGActive[agidx]) { highest_active_AG = agidx; num_active_AGs++; } } /* end check out the active AGs */ bmap_recptr->bmpctl_bufptr->dn_maxag = highest_active_AG; num_inactive_AGs = agg_recptr->num_ag - num_active_AGs; inactAG_free = num_inactive_AGs * sb_ptr->s_agsize; actAG_free = bmap_recptr->free_blocks - inactAG_free; avg_free = actAG_free / num_active_AGs; if ((bmap_recptr->bmpctl_bufptr->dn_agpref > highest_active_AG) || (bmap_recptr->bmpctl_bufptr->dn_agfree[bmap_recptr-> bmpctl_bufptr->dn_agpref] < avg_free)) { /* preferred AG is not valid */ if (avg_free == 0) { bmap_recptr->bmpctl_bufptr->dn_agpref = 0; } else { bmap_recptr->bmpctl_bufptr->dn_agpref = -1; for (agidx = 0; ((agidx < MAXAG) && (bmap_recptr->bmpctl_bufptr-> dn_agpref < 0)); agidx++) { if (bmap_recptr->AGFree_tbl[agidx] >= avg_free) { bmap_recptr->bmpctl_bufptr-> dn_agpref = agidx; } } } } aglevel = BMAPSZTOLEV(sb_ptr->s_agsize); l2nl = agg_recptr->log2_blksperag - (L2BPERDMAP + aglevel * L2LPERCTL); agheight = l2nl >> 1; agwidth = 1 << (l2nl - (agheight << 1)); for (index = 5 - agheight, agstart = 0, n = 1; index > 0; index--) { agstart += n; n <<= 2; } bmap_recptr->bmpctl_bufptr->dn_aglevel = aglevel; bmap_recptr->bmpctl_bufptr->dn_agheigth = agheight; bmap_recptr->bmpctl_bufptr->dn_agwidth = agwidth; bmap_recptr->bmpctl_bufptr->dn_agstart = agstart; bmap_recptr->bmpctl_bufptr->dn_agl2size = agg_recptr->log2_blksperag; bmap_recptr->bmpctl_bufptr->dn_agsize = sb_ptr->s_agsize; bmap_recptr->bmpctl_bufptr->dn_maxfreebud = max_buddy; for (agidx = 0; (agidx < MAXAG); agidx++) { /* rebuild the free list */ bmap_recptr->bmpctl_bufptr->dn_agfree[agidx] = bmap_recptr->AGFree_tbl[agidx]; } /* swap if on big endian machine */ ujfs_swap_dbmap(bmap_recptr->bmpctl_bufptr); /* * write the updated control page back onto the device */ bcr_rc = mapctl_put((void *) bmap_recptr->bmpctl_bufptr); } return (bcr_rc); } /***************************************************************************** * NAME: ctlpage_verify * * FUNCTION: Verify the control page of the filesystem block map. * * PARAMETERS: * max_buddy - input - the data value which should be in the root * of the highest Lx page in the map. * * RETURNS: * success: FSCK_OK * failure: something else */ int ctlpage_verify(int8_t max_buddy) { int bcv_rc = FSCK_OK; unsigned agidx; int32_t max_level = 0; int32_t highest_active_AG = 0; int32_t l2nl, n, index, aglevel, agheight, agwidth, agstart; bcv_rc = mapctl_get(bmap_recptr->bmpctl_agg_fsblk_offset, (void **) &(bmap_recptr->bmpctl_bufptr)); if (bcv_rc == FSCK_OK) { /* got the control page in the buffer */ /* swap if on big endian machine */ ujfs_swap_dbmap((struct dbmap *) bmap_recptr->bmpctl_bufptr); if (bmap_recptr->bmpctl_bufptr->dn_mapsize != bmap_recptr->total_blocks) { /* bad number of blocks in the aggregate */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCASB); } if (bmap_recptr->bmpctl_bufptr->dn_nfree != bmap_recptr->free_blocks) { /* bad number of free blocks in the aggregate */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCNF); } if (bmap_recptr->bmpctl_bufptr->dn_l2nbperpage != agg_recptr->log2_blksperpg) { /* bad log2( blocks per page ) */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCL2BPP); } if (bmap_recptr->bmpctl_bufptr->dn_numag != agg_recptr->num_ag) { /* bad number of alloc groups */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCNAG); } max_level = BMAPSZTOLEV(agg_recptr->sb_agg_fsblk_length); if (bmap_recptr->bmpctl_bufptr->dn_maxlevel != max_level) { /* bad maximum block map level */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCMXLVL); } for (agidx = 0; (agidx < MAXAG); agidx++) { /* check out the active AGs */ if (bmap_recptr->AGActive[agidx]) { highest_active_AG = agidx; } } /* * format does not include blocks allocated to the bad block inode * when it determines the dn_maxag. Subsequent activity may or * may not have altered dn_maxag based on blocks allocated to the * bad block inode. All we know for sure is that dn_maxag shouldn't * be larger than appropriate for the highest allocated block. */ if (bmap_recptr->bmpctl_bufptr->dn_maxag > highest_active_AG) { /* bad highest active alloc group */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCMAAG); } if (bmap_recptr->bmpctl_bufptr->dn_agpref > highest_active_AG) { /* bad preferred alloc group */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCPAG); } aglevel = BMAPSZTOLEV(sb_ptr->s_agsize); l2nl = agg_recptr->log2_blksperag - (L2BPERDMAP + aglevel * L2LPERCTL); agheight = l2nl >> 1; agwidth = 1 << (l2nl - (agheight << 1)); for (index = 5 - agheight, agstart = 0, n = 1; index > 0; index--) { agstart += n; n <<= 2; } /* end for index */ if (bmap_recptr->bmpctl_bufptr->dn_aglevel != aglevel) { /* bad level holding an AG */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCDMCLAG); } if (bmap_recptr->bmpctl_bufptr->dn_agheigth != agheight) { /* bad dmapctl height holding an AG */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCDMCLH); } if (bmap_recptr->bmpctl_bufptr->dn_agwidth != agwidth) { /* bad width at level holding an AG */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCDMCLW); } if (bmap_recptr->bmpctl_bufptr->dn_agstart != agstart) { /* bad start idx at level holding an AG */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCDMCSTI); } if (bmap_recptr->bmpctl_bufptr->dn_agl2size != agg_recptr->log2_blksperag) { /* bad log2(fsblks per AG) */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCL2BPAG); } if (bmap_recptr->bmpctl_bufptr->dn_agsize != sb_ptr->s_agsize) { /* bad fsblks per AG */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCBPAG); } if (bmap_recptr->bmpctl_bufptr->dn_maxfreebud != max_buddy) { /* bad max free buddy system */ bmap_recptr->ctl_other_error = -1; fsck_send_msg(fsck_BMAPCBMXB); } for (agidx = 0; (agidx < MAXAG); agidx++) { /* verify the free list */ if (bmap_recptr->bmpctl_bufptr->dn_agfree[agidx] != bmap_recptr->AGFree_tbl[agidx]) { /* bad free blocks in the AG */ bmap_recptr->ctl_fctl_error = -1; fsck_send_msg(fsck_BMAPCAGNF, agidx); } } } return (bcv_rc); } /***************************************************************************** * NAME: dmap_pwmap_rebuild * * FUNCTION: Rebuild the pmap in the current block map dmap page. * * PARAMETERS: * pmap_freeblks - input - pointer to a variable in which the number * of free blocks described by the dmap page * will be returned. * * RETURNS: * success: FSCK_OK * failure: something else */ int dmap_pwmap_rebuild(uint32_t * pmap_freeblks) { int bdpr_rc = FSCK_OK; uint32_t bitmask; int64_t wsp_pagenum; uint32_t wsp_byteoffset; struct fsck_blk_map_page *wsp_page; uint32_t *wsp_bits = NULL; int32_t map_wordidx, word_bitidx; int8_t max_buddy; /* * locate the section of the workspace bit map which corresponds * to this dmap's pmap */ bdpr_rc = blkmap_find_bit(bmap_recptr->dmap_1stblk, &wsp_pagenum, &wsp_byteoffset, &bitmask); if (bdpr_rc == FSCK_OK) { bdpr_rc = blkmap_get_page(wsp_pagenum, &wsp_page); if (bdpr_rc == FSCK_OK) { wsp_bits = (uint32_t *) ((char *) wsp_page + wsp_byteoffset); } } *pmap_freeblks = 0; if (bdpr_rc == FSCK_OK) { for (map_wordidx = 0; (map_wordidx < LPERDMAP); map_wordidx++) { max_buddy = ujfs_maxbuddy((char *) &(wsp_bits[map_wordidx])); bmap_recptr->dmap_wsp_sleafs[map_wordidx] = max_buddy; bmap_recptr->dmap_bufptr->wmap[map_wordidx] = wsp_bits[map_wordidx]; /* * copy the word from workspace to buffer, * into both the working map and the permanent map. */ bmap_recptr->dmap_bufptr->pmap[map_wordidx] = wsp_bits[map_wordidx]; /* * count the free blocks described by the word */ bitmask = 0x80000000u; for (word_bitidx = 0; (word_bitidx < DBWORD); word_bitidx++) { if (!(wsp_bits[map_wordidx] & bitmask)) { /* it's free */ (*pmap_freeblks)++; agg_recptr->free_blocks_in_aggregate++; } else { /* it's allocated */ agg_recptr->blocks_used_in_aggregate++; } /* end else it's allocated */ bitmask = bitmask >> 1; /* advance to the next bit */ } } } return (bdpr_rc); } /***************************************************************************** * NAME: dmap_pmap_verify * * FUNCTION: Verify the pmap in the current block map dmap page. * * PARAMETERS: * pmap_freeblks - input - pointer to a variable in which the number * of free blocks described by the dmap page * will be returned. * * RETURNS: * success: FSCK_OK * failure: something else */ int dmap_pmap_verify(uint32_t * pmap_freeblks) { int bdpv_rc = FSCK_OK; uint32_t bitmask; int64_t wsp_pagenum; uint32_t wsp_byteoffset; struct fsck_blk_map_page *wsp_page; uint32_t *wsp_bits = NULL; int32_t map_wordidx, word_bitidx; int8_t max_buddy; uint32_t unmarked_range_first_ordno = 0; int32_t unmarked_range_wordidx = 0; int32_t unmarked_range_bitidx = 0; int64_t size_of_unmarked_range = 0; uint32_t marked_range_first_ordno = 0; int32_t marked_range_wordidx = 0; int32_t marked_range_bitidx = 0; int64_t size_of_marked_range = 0; /* * locate the section of the workspace bit map which corresponds * to this dmap's pmap */ bdpv_rc = blkmap_find_bit(bmap_recptr->dmap_1stblk, &wsp_pagenum, &wsp_byteoffset, &bitmask); if (bdpv_rc == FSCK_OK) { bdpv_rc = blkmap_get_page(wsp_pagenum, &wsp_page); if (bdpv_rc == FSCK_OK) { /* got the page */ wsp_bits = (uint32_t *) ((char *) wsp_page + wsp_byteoffset); } } *pmap_freeblks = 0; if (bdpv_rc != FSCK_OK) goto bdpv_exit; for (map_wordidx = 0; (map_wordidx < LPERDMAP); map_wordidx++) { max_buddy = ujfs_maxbuddy((char *) &(wsp_bits[map_wordidx])); bmap_recptr->dmap_wsp_sleafs[map_wordidx] = max_buddy; bitmask = 0x80000000u; for (word_bitidx = 0; (word_bitidx < DBWORD); word_bitidx++) { if (wsp_bits[map_wordidx] & bitmask) { agg_recptr->blocks_used_in_aggregate++; if (!(bmap_recptr->dmap_bufptr-> pmap[map_wordidx] & bitmask)) { /* pmap says not */ bmap_recptr->dmap_pmap_error = -1; if (size_of_unmarked_range == 0) { if (size_of_marked_range != 0) { fsck_send_msg (fsck_PMAPSBOFF, (long long) size_of_marked_range, marked_range_first_ordno, marked_range_wordidx, marked_range_bitidx); size_of_marked_range = 0; } unmarked_range_first_ordno = bmap_recptr->dmappg_ordno; unmarked_range_wordidx = map_wordidx; unmarked_range_bitidx = word_bitidx; size_of_unmarked_range = 1; } else { /* not the first in the range */ size_of_unmarked_range++; } } else { /* pmap agrees */ if (size_of_marked_range != 0) { /* marked range ended */ fsck_send_msg(fsck_PMAPSBOFF, (long long) size_of_marked_range, marked_range_first_ordno, marked_range_wordidx, marked_range_bitidx); size_of_marked_range = 0; } if (size_of_unmarked_range != 0) { /* unmarked range ended */ fsck_send_msg(fsck_PMAPSBON, (long long) size_of_unmarked_range, unmarked_range_first_ordno, unmarked_range_wordidx, unmarked_range_bitidx); size_of_unmarked_range = 0; } } } else { /* fsck says not allocated */ (*pmap_freeblks)++; agg_recptr->free_blocks_in_aggregate++; if ((bmap_recptr->dmap_bufptr->pmap[map_wordidx] & bitmask)) { /* pmap says yes */ bmap_recptr->dmap_pmap_error = -1; if (size_of_marked_range == 0) { if (size_of_unmarked_range != 0) { fsck_send_msg (fsck_PMAPSBON, (long long) size_of_unmarked_range, unmarked_range_first_ordno, unmarked_range_wordidx, unmarked_range_bitidx); size_of_unmarked_range = 0; } marked_range_first_ordno = bmap_recptr->dmappg_ordno; marked_range_wordidx = map_wordidx; marked_range_bitidx = word_bitidx; size_of_marked_range = 1; } else { /* not the first in the range */ size_of_marked_range++; } } else { /* pmap agrees */ if (size_of_marked_range != 0) { fsck_send_msg(fsck_PMAPSBOFF, (long long) size_of_marked_range, marked_range_first_ordno, marked_range_wordidx, marked_range_bitidx); size_of_marked_range = 0; } if (size_of_unmarked_range != 0) { /* unmarked range ended */ fsck_send_msg(fsck_PMAPSBON, (long long) size_of_unmarked_range, unmarked_range_first_ordno, unmarked_range_wordidx, unmarked_range_bitidx); size_of_unmarked_range = 0; } } } /* advance to the next bit */ bitmask = bitmask >> 1; } } if (size_of_marked_range != 0) { /* marked range ended */ fsck_send_msg(fsck_PMAPSBOFF,(long long)size_of_marked_range, marked_range_first_ordno,marked_range_wordidx, marked_range_bitidx); size_of_marked_range = 0; } if (size_of_unmarked_range != 0) { /* unmarked range ended */ fsck_send_msg(fsck_PMAPSBON,(long long)size_of_unmarked_range, unmarked_range_first_ordno,unmarked_range_wordidx, unmarked_range_bitidx); size_of_unmarked_range = 0; } bdpv_exit: return (bdpv_rc); } /***************************************************************************** * NAME: dmap_tree_rebuild * * FUNCTION: Rebuild the tree in the current block map dmap page. * * PARAMETERS: * root_data - input - pointer to a variable in which the data value * stored in the root of the tree will be returned. * * RETURNS: * success: FSCK_OK * failure: something else */ int dmap_tree_rebuild(int8_t * root_data) { int bdsr_rc = FSCK_OK; struct fsck_stree_proc_parms stree_proc_parms; struct fsck_stree_proc_parms *prms_ptr; prms_ptr = &stree_proc_parms; #define ppbt prms_ptr->buf_tree ppbt = (dmtree_t *) & (bmap_recptr->dmap_bufptr->tree); ppbt->dmt_nleafs = prms_ptr->nleafs = LPERDMAP; ppbt->dmt_l2nleafs = prms_ptr->l2nleafs = L2LPERDMAP; ppbt->dmt_leafidx = prms_ptr->leafidx = LEAFIND; ppbt->dmt_height = 4; ppbt->dmt_budmin = prms_ptr->budmin = BUDMIN; prms_ptr->buf_stree = &(ppbt->dmt_stree[0]); prms_ptr->wsp_stree = bmap_recptr->dmap_wsp_stree; bdsr_rc = stree_rebuild(prms_ptr, root_data); return (bdsr_rc); } /***************************************************************************** * NAME: dmap_tree_verify * * FUNCTION: Verify the tree in the current block map dmap page. * * PARAMETERS: * root_data - input - pointer to a variable in which the data value * which should be stored in the root of the tree * will be returned. * * RETURNS: * success: FSCK_OK * failure: something else */ int dmap_tree_verify(int8_t * root_data) { int bdsv_rc = FSCK_OK; int8_t tree_spec_errors = 0; struct fsck_stree_proc_parms stree_proc_parms; struct fsck_stree_proc_parms *prms_ptr; prms_ptr = &stree_proc_parms; prms_ptr->buf_tree = (dmtree_t *) & (bmap_recptr->dmap_bufptr->tree); if (prms_ptr->buf_tree->dmt_nleafs != LPERDMAP) { /* wrong number of leafs */ bmap_recptr->dmap_other_error = -1; tree_spec_errors = -1; fsck_send_msg(fsck_BMAPBADNLF, fsck_ref_msg(fsck_dmap), bmap_recptr->dmappg_ordno); } if (prms_ptr->buf_tree->dmt_l2nleafs != L2LPERDMAP) { /* wrong log2(nleafs) */ bmap_recptr->dmap_other_error = -1; tree_spec_errors = -1; fsck_send_msg(fsck_BMAPBADL2NLF, fsck_ref_msg(fsck_dmap), bmap_recptr->dmappg_ordno); } if (prms_ptr->buf_tree->dmt_leafidx != LEAFIND) { /* wrong 1st leaf index */ bmap_recptr->dmap_other_error = -1; tree_spec_errors = -1; fsck_send_msg(fsck_BMAPBADLFI, fsck_ref_msg(fsck_dmap), bmap_recptr->dmappg_ordno); } if (prms_ptr->buf_tree->dmt_height != 4) { /* wrong stree height */ bmap_recptr->dmap_other_error = -1; tree_spec_errors = -1; fsck_send_msg(fsck_BMAPBADHT, fsck_ref_msg(fsck_dmap), bmap_recptr->dmappg_ordno); } if (prms_ptr->buf_tree->dmt_budmin != BUDMIN) { /* wrong min buddy value */ bmap_recptr->dmap_other_error = -1; tree_spec_errors = -1; fsck_send_msg(fsck_BMAPBADBMN, fsck_ref_msg(fsck_dmap), bmap_recptr->dmappg_ordno); } /* * if we found errors in the fields which specify the summary * tree then we won't take the time to verify the tree itself. * * (The errors already detected would corrupt the summary tree, * so info about the bad tree would only be noise at this point.) */ if (!tree_spec_errors) { /* tree specification fields are ok */ prms_ptr->buf_stree = &(prms_ptr->buf_tree->dmt_stree[0]); prms_ptr->wsp_stree = bmap_recptr->dmap_wsp_stree; prms_ptr->nleafs = LPERDMAP; prms_ptr->l2nleafs = L2LPERDMAP; prms_ptr->leafidx = LEAFIND; prms_ptr->budmin = BUDMIN; prms_ptr->page_level = fsck_dmap; prms_ptr->page_ordno = bmap_recptr->dmappg_ordno; prms_ptr->lfval_error = &(bmap_recptr->dmap_slfv_error); prms_ptr->intval_error = &(bmap_recptr->dmap_slnv_error); bdsv_rc = stree_verify(prms_ptr, root_data); } return (bdsv_rc); } /***************************************************************************** * NAME: dmappg_rebuild * * FUNCTION: Rebuild the current dmap page. * * PARAMETERS: * stree_root_data - input - pointer to a variable in which to return * the the data value in the root of the * tree of the rebuilt page. * * RETURNS: * success: FSCK_OK * failure: something else */ int dmappg_rebuild(int8_t * stree_root_data) { int bdmpr_rc = FSCK_OK; uint32_t nblocks; uint32_t dmap_freeblks; uint32_t ag_num; /* * get the page to verify into the I/O buffer */ bdmpr_rc = blktbl_dmap_get(bmap_recptr->dmap_1stblk, &(bmap_recptr->dmap_bufptr)); if (bdmpr_rc == FSCK_OK) { /* the page is in the buffer */ bmap_recptr->dmap_bufptr->start = bmap_recptr->dmap_1stblk; nblocks = MIN(BPERDMAP, (bmap_recptr->total_blocks - bmap_recptr->dmap_1stblk)); bmap_recptr->dmap_bufptr->nblocks = nblocks; bdmpr_rc = dmap_pwmap_rebuild(&dmap_freeblks); /* * subtract out any blocks which don't really exist but are * described by a dmap (phantom blocks always appear to be in use) */ agg_recptr->blocks_used_in_aggregate = agg_recptr->blocks_used_in_aggregate - (BPERDMAP - nblocks); if (bdmpr_rc == FSCK_OK) { /* nothing strange during pmap rebld */ bmap_recptr->free_blocks += dmap_freeblks; ag_num = bmap_recptr->dmap_1stblk >> agg_recptr->log2_blksperag; bmap_recptr->AGFree_tbl[ag_num] += dmap_freeblks; if (dmap_freeblks != nblocks) { /* not all of them are free */ bmap_recptr->AGActive[ag_num] = -1; } bmap_recptr->dmap_bufptr->nfree = dmap_freeblks; bdmpr_rc = dmap_tree_rebuild(stree_root_data); /* * write the page back to the device */ if (bdmpr_rc == FSCK_OK) { bdmpr_rc = blktbl_dmap_put(bmap_recptr->dmap_bufptr); } } } return (bdmpr_rc); } /***************************************************************************** * NAME: dmappg_verify * * FUNCTION: Validate the current dmap page. * * PARAMETERS: * stree_root_data - input - pointer to a variable in which to return * the the data value which should be stored * in the root of the tree of the page being * validated (and may also be the one stored * in the root of that tree) * * RETURNS: * success: FSCK_OK * failure: something else */ int dmappg_verify(int8_t * stree_root_data) { int bdmpv_rc = FSCK_OK; uint32_t nblocks; uint32_t dmap_freeblks; uint32_t ag_num; /* * get the page to verify into the I/O buffer */ bdmpv_rc = blktbl_dmap_get(bmap_recptr->dmap_1stblk, &(bmap_recptr->dmap_bufptr)); if (bdmpv_rc == FSCK_OK) { /* the page is in the buffer */ if (bmap_recptr->dmap_bufptr->start != bmap_recptr->dmap_1stblk) { /* bad starting block */ bmap_recptr->dmap_other_error = -1; fsck_send_msg(fsck_DMAPBADSTRT, bmap_recptr->dmappg_ordno); } nblocks = MIN(BPERDMAP, (bmap_recptr->total_blocks - bmap_recptr->dmap_1stblk)); if (bmap_recptr->dmap_bufptr->nblocks != nblocks) { /* bad number of blocks */ bmap_recptr->dmap_other_error = -1; fsck_send_msg(fsck_DMAPBADNBLK, bmap_recptr->dmappg_ordno); } bdmpv_rc = dmap_pmap_verify(&dmap_freeblks); /* * subtract out any blocks which don't really exist but are * described by a dmap (phantom blocks always appear to be in use) */ agg_recptr->blocks_used_in_aggregate = agg_recptr->blocks_used_in_aggregate - (BPERDMAP - nblocks); if (bdmpv_rc == FSCK_OK) { /* nothing strange during pmap ver */ bmap_recptr->free_blocks += dmap_freeblks; ag_num = bmap_recptr->dmap_1stblk >> agg_recptr->log2_blksperag; bmap_recptr->AGFree_tbl[ag_num] += dmap_freeblks; if (dmap_freeblks != nblocks) { /* not all of them are free */ bmap_recptr->AGActive[ag_num] = -1; } if (bmap_recptr->dmap_bufptr->nfree != dmap_freeblks) { /* bad number of free blocks */ bmap_recptr->dmap_other_error = -1; fsck_send_msg(fsck_DMAPBADNFREE, bmap_recptr->dmappg_ordno); } bdmpv_rc = dmap_tree_verify(stree_root_data); } } return (bdmpv_rc); } /***************************************************************************** * NAME: init_bmap_info * * FUNCTION: Initialize the bmap fsck global data area, pointed to by * bmap_recptr, used to control JFS bmap processing. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int init_bmap_info() { int bii_rc = FSCK_OK; unsigned agidx; memset(bmap_recptr, 0, sizeof (struct fsck_bmap_record)); memcpy((void *) &(bmap_recptr->eyecatcher), (void *) "bmaprecd", 8); memcpy((void *) &(bmap_recptr->bmpctlinf_eyecatcher), (void *) "bmap ctl", 8); memcpy((void *) &(bmap_recptr->AGinf_eyecatcher), (void *) "AG info ", 8); memcpy((void *) &(bmap_recptr->dmapinf_eyecatcher), (void *) "dmapinfo", 8); memcpy((void *) &(bmap_recptr->L0inf_eyecatcher), (void *) "L0 info ", 8); memcpy((void *) &(bmap_recptr->L1inf_eyecatcher), (void *) "L1 info ", 8); memcpy((void *) &(bmap_recptr->L2inf_eyecatcher), (void *) "L2 info ", 8); bmap_recptr->bmpctl_bufptr = (struct dbmap *) agg_recptr->mapctl_buf_ptr; bmap_recptr->bmpctl_agg_fsblk_offset = BMAP_OFF / sb_ptr->s_bsize; bmap_recptr->AGFree_tbl = &(agg_recptr->blkmap_wsp.AG_free[0]); bmap_recptr->dmap_wsp_stree = &(agg_recptr->blkmap_wsp.dmap_wsp_tree[0]); bmap_recptr->dmap_wsp_sleafs = &(agg_recptr->blkmap_wsp.dmap_wsp_leafs[0]); bmap_recptr->L0_wsp_stree = &(agg_recptr->blkmap_wsp.L0_wsp_tree[0]); bmap_recptr->L0_wsp_sleafs = &(agg_recptr->blkmap_wsp.L0_wsp_leafs[0]); bmap_recptr->L0_bufptr = (struct dmapctl *) &(agg_recptr->bmaplv_buf_ptr); bmap_recptr->L1_wsp_stree = &(agg_recptr->blkmap_wsp.L1_wsp_tree[0]); bmap_recptr->L1_wsp_sleafs = &(agg_recptr->blkmap_wsp.L1_wsp_leafs[0]); bmap_recptr->L1_bufptr = (struct dmapctl *) &(agg_recptr->bmaplv_buf_ptr); bmap_recptr->L2_wsp_stree = &(agg_recptr->blkmap_wsp.L2_wsp_tree[0]); bmap_recptr->L2_wsp_sleafs = &(agg_recptr->blkmap_wsp.L2_wsp_leafs[0]); bmap_recptr->L2_bufptr = (struct dmapctl *) &(agg_recptr->bmaplv_buf_ptr); bmap_recptr->total_blocks = sb_ptr->s_size * sb_ptr->s_pbsize / sb_ptr->s_bsize; bmap_recptr->dmappg_count = (bmap_recptr->total_blocks + BPERDMAP - 1) / BPERDMAP; bmap_recptr->L0pg_count = (bmap_recptr->dmappg_count + LPERCTL - 1) / LPERCTL; if (bmap_recptr->L0pg_count > 1) { bmap_recptr->L1pg_count = (bmap_recptr->L0pg_count + LPERCTL - 1) / LPERCTL; if (bmap_recptr->L1pg_count > 1) { bmap_recptr->L2pg_count = (bmap_recptr->L1pg_count + LPERCTL - 1) / LPERCTL; } else { bmap_recptr->L2pg_count = 0; } } else { bmap_recptr->L1pg_count = 0; } bmap_recptr->free_blocks = 0; bmap_recptr->ctl_fctl_error = 0; bmap_recptr->ctl_other_error = 0; for (agidx = 0; (agidx < MAXAG); agidx++) { bmap_recptr->AGActive[agidx] = 0; } bmap_recptr->dmappg_ordno = bmap_recptr->L0pg_ordno = 0; bmap_recptr->L1pg_ordno = bmap_recptr->L2pg_1stblk = 0; bmap_recptr->dmappg_idx = bmap_recptr->L0pg_idx = 0; bmap_recptr->L1pg_idx = 0; bmap_recptr->dmap_1stblk = bmap_recptr->L0pg_1stblk = 0; bmap_recptr->L1pg_1stblk = bmap_recptr->L2pg_1stblk = 0; bmap_recptr->dmap_pmap_error = 0; bmap_recptr->dmap_slfv_error = bmap_recptr->L0pg_slfv_error = 0; bmap_recptr->L1pg_slfv_error = bmap_recptr->L2pg_slfv_error = 0; bmap_recptr->dmap_slnv_error = bmap_recptr->L0pg_slnv_error = 0; bmap_recptr->L1pg_slnv_error = bmap_recptr->L2pg_slnv_error = 0; bmap_recptr->dmap_other_error = bmap_recptr->L0pg_other_error = 0; bmap_recptr->L1pg_other_error = bmap_recptr->L2pg_other_error = 0; return (bii_rc); } /***************************************************************************** * NAME: Ln_tree_rebuild * * FUNCTION: Rebuild the tree in the current summary page. * * PARAMETERS: * level - input - Summary level of the bmap summary page * containing the tree to rebuild * first_blk - input - First aggregate block described by the bmap * summary page containing the tree to rebuild * addr_buf_ptr - input - pointer to a variable in which to return the * address of the buffer in which the page has * been rebuilt (and then written to the * aggregate) * root_data - input - pointer to a variable in which to return the * data value in the root of the rebuilt tree. * * RETURNS: * success: FSCK_OK * failure: something else */ int Ln_tree_rebuild(int level, int64_t first_blk, struct dmapctl **addr_buf_ptr, int8_t * root_data) { int blsr_rc = FSCK_OK; struct fsck_stree_proc_parms stree_proc_parms; struct fsck_stree_proc_parms *prms_ptr; /* * get the page to verify into the I/O buffer */ blsr_rc = blktbl_Ln_page_get(level, first_blk, addr_buf_ptr); if (blsr_rc == FSCK_OK) { /* the page is in the buffer */ prms_ptr = &stree_proc_parms; /* these are just big trees */ prms_ptr->buf_tree = (dmtree_t *) * addr_buf_ptr; switch (level) { case 0:{ prms_ptr->wsp_stree = bmap_recptr->L0_wsp_stree; break; } case 1:{ prms_ptr->wsp_stree = bmap_recptr->L1_wsp_stree; break; } default:{ prms_ptr->wsp_stree = bmap_recptr->L2_wsp_stree; break; } } prms_ptr->buf_tree->dmt_nleafs = prms_ptr->nleafs = LPERCTL; prms_ptr->buf_tree->dmt_l2nleafs = prms_ptr->l2nleafs = L2LPERCTL; prms_ptr->buf_tree->dmt_leafidx = prms_ptr->leafidx = CTLLEAFIND; prms_ptr->buf_tree->dmt_height = 5; prms_ptr->buf_tree->dmt_budmin = L2BPERDMAP + level * L2LPERCTL; prms_ptr->budmin = prms_ptr->buf_tree->dmt_budmin; prms_ptr->buf_stree = &(prms_ptr->buf_tree->dmt_stree[0]); blsr_rc = stree_rebuild(prms_ptr, root_data); /* * put the page back into the file */ if (blsr_rc == FSCK_OK) { blsr_rc = blktbl_Ln_page_put(*addr_buf_ptr); } } return (blsr_rc); } /***************************************************************************** * NAME: Ln_tree_verify * * FUNCTION: Verify the tree in the current summary page. * * PARAMETERS: * level - input - Summary level of the bmap summary page * containing the tree to verify * first_blk - input - First aggregate block described by the bmap * summary page containing the tree to verify * addr_buf_ptr - input - pointer to a variable in which to return the * address of the buffer into which the page has * been read so that its contents can be verified * root_data - input - pointer to a variable in which to return the * data value which should be in the root of the * tree....and may actually be stored there. * * RETURNS: * success: FSCK_OK * failure: something else */ int Ln_tree_verify(int level, int64_t first_blk, struct dmapctl **addr_buf_ptr, int8_t * root_data) { int blsv_rc = FSCK_OK; int8_t *other_errors; int8_t tree_spec_errors = 0; struct fsck_stree_proc_parms stree_proc_parms; struct fsck_stree_proc_parms *prms_ptr; /* * get the page to verify into the I/O buffer */ blsv_rc = blktbl_Ln_page_get(level, first_blk, addr_buf_ptr); if (blsv_rc == FSCK_OK) { /* the page is in the buffer */ prms_ptr = &stree_proc_parms; /* these are just big trees */ prms_ptr->buf_tree = (dmtree_t *) * addr_buf_ptr; switch (level) { case 0:{ prms_ptr->wsp_stree = bmap_recptr->L0_wsp_stree; prms_ptr->page_ordno = bmap_recptr->L0pg_ordno; prms_ptr->lfval_error = &(bmap_recptr->L0pg_slfv_error); prms_ptr->intval_error = &(bmap_recptr->L0pg_slnv_error); prms_ptr->page_level = fsck_L0; other_errors = &(bmap_recptr->L0pg_other_error); break; } case 1:{ prms_ptr->wsp_stree = bmap_recptr->L1_wsp_stree; prms_ptr->page_ordno = bmap_recptr->L1pg_ordno; prms_ptr->lfval_error = &(bmap_recptr->L1pg_slfv_error); prms_ptr->intval_error = &(bmap_recptr->L1pg_slnv_error); prms_ptr->page_level = fsck_L1; other_errors = &(bmap_recptr->L1pg_other_error); break; } default:{ prms_ptr->wsp_stree = bmap_recptr->L2_wsp_stree; prms_ptr->page_ordno = 0; prms_ptr->lfval_error = &(bmap_recptr->L2pg_slfv_error); prms_ptr->intval_error = &(bmap_recptr->L2pg_slnv_error); prms_ptr->page_level = fsck_L2; other_errors = &(bmap_recptr->L2pg_other_error); break; } } if (prms_ptr->buf_tree->dmt_nleafs != LPERCTL) { /* wrong number of leafs */ *other_errors = -1; tree_spec_errors = -1; fsck_send_msg(fsck_BMAPBADNLF, fsck_ref_msg(prms_ptr->page_level), prms_ptr->page_ordno); } if (prms_ptr->buf_tree->dmt_l2nleafs != L2LPERCTL) { /* wrong log2(nleafs) */ *other_errors = -1; tree_spec_errors = -1; fsck_send_msg(fsck_BMAPBADL2NLF, fsck_ref_msg(prms_ptr->page_level), prms_ptr->page_ordno); } if (prms_ptr->buf_tree->dmt_leafidx != CTLLEAFIND) { /* wrong 1st leaf index */ *other_errors = -1; tree_spec_errors = -1; fsck_send_msg(fsck_BMAPBADLFI, fsck_ref_msg(prms_ptr->page_level), prms_ptr->page_ordno); } if (prms_ptr->buf_tree->dmt_height != 5) { /* wrong stree height */ *other_errors = -1; tree_spec_errors = -1; fsck_send_msg(fsck_BMAPBADHT, fsck_ref_msg(prms_ptr->page_level), prms_ptr->page_ordno); } if (prms_ptr->buf_tree->dmt_budmin != (L2BPERDMAP + level * L2LPERCTL)) { /* wrong min buddy value */ *other_errors = -1; tree_spec_errors = -1; fsck_send_msg(fsck_BMAPBADBMN, fsck_ref_msg(prms_ptr->page_level), prms_ptr->page_ordno); } /* * if we found errors in the fields which specify the summary * tree then we won't take the time to verify the tree itself. * * (The errors already detected would corrupt the summary tree, * so info about the bad tree would only be noise at this point.) */ if (!tree_spec_errors) { /* tree specification fields are ok */ prms_ptr->buf_stree = &(prms_ptr->buf_tree->dmt_stree[0]); prms_ptr->nleafs = LPERCTL; prms_ptr->budmin = (L2BPERDMAP + level * L2LPERCTL); prms_ptr->l2nleafs = L2LPERCTL; prms_ptr->leafidx = CTLLEAFIND; blsv_rc = stree_verify(prms_ptr, root_data); } } return (blsv_rc); } /***************************************************************************** * NAME: rebuild_blkall_map * * FUNCTION: Rebuild the JFS Aggregate Block Map in the aggregate. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int rebuild_blkall_map() { int rbam_rc = FSCK_OK; int8_t sumtree_root_data; uint32_t leafidx; #define MAXIDX (LPERCTL - 1) rbam_rc = init_bmap_info(); /* * since the dmap I/O buffer is really the same storage as the * IAG I/O buffer, flush out any pending writes that may remain * from IAG processing. */ rbam_rc = iags_flush(); /* * rebuild the dmap pages. Rebuild each L0 and L1 page * if and when the information for is complete. */ while ((rbam_rc == FSCK_OK) && (bmap_recptr->dmappg_ordno < bmap_recptr->dmappg_count)) { rbam_rc = dmappg_rebuild(&sumtree_root_data); if (rbam_rc != FSCK_OK) continue; /* * the data in the dmap summary tree root goes into a leaf of * the current L0 page */ bmap_recptr->L0_wsp_sleafs[bmap_recptr->dmappg_idx] = sumtree_root_data; /* move to next dmap page */ bmap_recptr->dmappg_ordno++; bmap_recptr->dmap_1stblk += BPERDMAP; if (bmap_recptr->dmappg_idx < MAXIDX) { /* still gathering info about this L0 page */ bmap_recptr->dmappg_idx++; continue; } /* we have all the info needed for the current L0 page */ bmap_recptr->dmappg_idx = 0; rbam_rc = Ln_tree_rebuild(0, bmap_recptr->L0pg_1stblk, &(bmap_recptr->L0_bufptr), &sumtree_root_data); if (rbam_rc == FSCK_OK) { /* * the data in the L0 summary tree root goes into * a leaf of the current L1 page */ bmap_recptr->L1_wsp_sleafs[bmap_recptr-> L0pg_idx] = sumtree_root_data; /* move to the next L0 page */ bmap_recptr->L0pg_ordno++; bmap_recptr->L0pg_1stblk = bmap_recptr->dmap_1stblk; if (bmap_recptr->L0pg_idx < MAXIDX) { /* still gathering info about this L1 page */ bmap_recptr->L0pg_idx++; } else { /* we have all the info needed for the current L1 page */ bmap_recptr->L0pg_idx = 0; rbam_rc = Ln_tree_rebuild(1, bmap_recptr-> L1pg_1stblk, & (bmap_recptr-> L1_bufptr), &sumtree_root_data); if (rbam_rc == FSCK_OK) { /* * the data in the L1 summary tree root goes into * a leaf of the current L2 page */ bmap_recptr-> L2_wsp_sleafs [bmap_recptr-> L1pg_idx] = sumtree_root_data; /* move to the next L1 page */ bmap_recptr->L1pg_ordno++; bmap_recptr-> L1pg_1stblk = bmap_recptr-> dmap_1stblk; /* * note that there is always AT MOST a single L2 page */ bmap_recptr->L1pg_idx++; } } } } /* * finish up the partial pages */ if (rbam_rc == FSCK_OK) { if (bmap_recptr->dmappg_idx != 0) { /* there's a partial L0 page */ for (leafidx = bmap_recptr->dmappg_idx; (leafidx <= MAXIDX); leafidx++) { bmap_recptr->L0_wsp_sleafs[leafidx] = -1; } rbam_rc = Ln_tree_rebuild(0, bmap_recptr->L0pg_1stblk, &(bmap_recptr->L0_bufptr), &sumtree_root_data); if (rbam_rc == FSCK_OK) { /* * the data in the L0 summary tree root goes into * a leaf of the current L1 page */ bmap_recptr->L1_wsp_sleafs[bmap_recptr-> L0pg_idx] = sumtree_root_data; bmap_recptr->L0pg_idx++; } } } if (rbam_rc == FSCK_OK) { if ((bmap_recptr->L1pg_count > 0) && (bmap_recptr->L0pg_idx != 0)) { /* there's enough data for an L1 level, and there's a partial L1 page */ for (leafidx = bmap_recptr->L0pg_idx; (leafidx <= MAXIDX); leafidx++) { bmap_recptr->L1_wsp_sleafs[leafidx] = -1; } rbam_rc = Ln_tree_rebuild(1, bmap_recptr->L1pg_1stblk, &(bmap_recptr->L1_bufptr), &sumtree_root_data); if (rbam_rc == FSCK_OK) { /* * the data in the L0 summary tree root goes into * a leaf of the current L1 page */ bmap_recptr->L2_wsp_sleafs[bmap_recptr-> L1pg_idx] = sumtree_root_data; bmap_recptr->L1pg_idx++; } } } if (rbam_rc == FSCK_OK) { if ((bmap_recptr->L2pg_count > 0) && (bmap_recptr->L1pg_idx != 0)) { /* there's enough data for an L2 level, and there's a partial L2 page */ for (leafidx = bmap_recptr->L1pg_idx; (leafidx <= MAXIDX); leafidx++) { bmap_recptr->L2_wsp_sleafs[leafidx] = -1; } rbam_rc = Ln_tree_rebuild(2, bmap_recptr->L2pg_1stblk, &(bmap_recptr->L2_bufptr), &sumtree_root_data); } } /* * Now go verify the Block Allocation Map Control page */ if (rbam_rc == FSCK_OK) { rbam_rc = ctlpage_rebuild(sumtree_root_data); } return (rbam_rc); } /***************************************************************************** * NAME: stree_rebuild * * FUNCTION: Rebuild the specified summary tree. * * PARAMETERS: * prms_ptr - input - pointer to a data area describing the tree * to rebuild and containing the dmap which the * tree summarizes. * root_data - input - pointer to a variable in which to return the * data value stored in the root node of the tree * * RETURNS: * success: FSCK_OK * failure: something else */ int stree_rebuild(struct fsck_stree_proc_parms *prms_ptr, int8_t * root_data) { int bsr_rc = FSCK_OK; uint32_t node_idx, last_leaf_idx; /* * copy the leaf data into the buffer */ last_leaf_idx = prms_ptr->leafidx + prms_ptr->nleafs - 1; for (node_idx = prms_ptr->leafidx; (node_idx <= last_leaf_idx); node_idx++) { prms_ptr->buf_stree[node_idx] = prms_ptr->wsp_stree[node_idx]; } /* * build the summary tree from the "raw" leaf values */ *root_data = ujfs_adjtree(prms_ptr->buf_stree, prms_ptr->l2nleafs, prms_ptr->budmin); return (bsr_rc); } /***************************************************************************** * NAME: stree_verify * * FUNCTION: Verify the specified summary tree. * * PARAMETERS: * prms_ptr - input - pointer to a data area describing the tree * to verify and containing the dmap which the * tree summarizes. * root_data - input - pointer to a variable in which to return the * data value which should be in the root node * of the tree (and may in fact be in the root * node of the tree) * * RETURNS: * success: FSCK_OK * failure: something else */ int stree_verify(struct fsck_stree_proc_parms *prms_ptr, int8_t * root_data) { int bsv_rc = FSCK_OK; uint32_t node_idx, last_leaf_idx; /* * build the summary tree from the "raw" leaf values */ *root_data = ujfs_adjtree(prms_ptr->wsp_stree, prms_ptr->l2nleafs, prms_ptr->budmin); /* * Now see if the tree in the buffer matches the one we just * built in the workspace. * * We distinguish between incorrect internal nodes and incorrect * leaf nodes because they can be symptoms of different problems. */ for (node_idx = 0; (node_idx < prms_ptr->leafidx); node_idx++) { if (prms_ptr->buf_stree[node_idx] != prms_ptr->wsp_stree[node_idx]) { /* they don't match! */ *(prms_ptr->intval_error) = -1; fsck_send_msg(fsck_BMAPBADLNV, node_idx, fsck_ref_msg(prms_ptr->page_level), prms_ptr->page_ordno); } } last_leaf_idx = prms_ptr->leafidx + prms_ptr->nleafs - 1; for (node_idx = prms_ptr->leafidx; (node_idx <= last_leaf_idx); node_idx++) { if (prms_ptr->buf_stree[node_idx] != prms_ptr->wsp_stree[node_idx]) { /* they don't match! */ *(prms_ptr->lfval_error) = -1; fsck_send_msg(fsck_BMAPBADLFV, node_idx, fsck_ref_msg(prms_ptr->page_level), prms_ptr->page_ordno); } } return (bsv_rc); } /***************************************************************************** * NAME: verify_blkall_map * * FUNCTION: Validate the JFS Aggregate Block Map for the aggregate. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int verify_blkall_map() { int vbam_rc = FSCK_OK; int8_t sumtree_root_data; uint32_t leafidx; #define MAXIDX (LPERCTL - 1) vbam_rc = init_bmap_info(); /* * since the dmap I/O buffer is really the same storage as the * IAG I/O buffer, flush out any pending writes that may remain * from IAG processing. */ vbam_rc = iags_flush(); /* * Verify the dmap pages. Verify each L0 and L1 page * if and when the information for is complete. */ while ((vbam_rc == FSCK_OK) && (bmap_recptr->dmappg_ordno < bmap_recptr->dmappg_count)) { vbam_rc = dmappg_verify(&sumtree_root_data); if (vbam_rc != FSCK_OK) continue; /* * the data in the dmap summary tree root goes into a leaf of * the current L0 page */ bmap_recptr->L0_wsp_sleafs[bmap_recptr->dmappg_idx] = sumtree_root_data; /* move to next dmap page */ bmap_recptr->dmappg_ordno++; bmap_recptr->dmap_1stblk += BPERDMAP; if (bmap_recptr->dmappg_idx < MAXIDX) { /* still gathering info about this L0 page */ bmap_recptr->dmappg_idx++; continue; } /* we have all the info needed for the current L0 page */ bmap_recptr->dmappg_idx = 0; vbam_rc = Ln_tree_verify(0, bmap_recptr->L0pg_1stblk, &(bmap_recptr->L0_bufptr), &sumtree_root_data); if (vbam_rc != FSCK_OK) continue; /* * the data in the L0 summary tree root goes into * a leaf of the current L1 page */ bmap_recptr->L1_wsp_sleafs[bmap_recptr->L0pg_idx] = sumtree_root_data; /* move to the next L0 page */ bmap_recptr->L0pg_ordno++; bmap_recptr->L0pg_1stblk = bmap_recptr->dmap_1stblk; if (bmap_recptr->L0pg_idx < MAXIDX) { /* still gathering info about this L1 page */ bmap_recptr->L0pg_idx++; continue; } /* we have all the info needed for the current L1 page */ bmap_recptr->L0pg_idx = 0; vbam_rc = Ln_tree_verify(1, bmap_recptr->L1pg_1stblk, &(bmap_recptr->L1_bufptr), &sumtree_root_data); if (vbam_rc == FSCK_OK) { /* * the data in the L1 summary tree root goes into * a leaf of the current L2 page */ bmap_recptr->L2_wsp_sleafs[bmap_recptr->L1pg_idx] = sumtree_root_data; /* move to the next L1 page */ bmap_recptr->L1pg_ordno++; bmap_recptr->L1pg_1stblk = bmap_recptr->dmap_1stblk; /* * note that there is always AT MOST a single L2 page */ bmap_recptr->L1pg_idx++; } } /* * finish up the partial pages */ if (vbam_rc == FSCK_OK) { if (bmap_recptr->dmappg_idx != 0) { /* there's a partial L0 page */ for (leafidx = bmap_recptr->dmappg_idx; (leafidx <= MAXIDX); leafidx++) { bmap_recptr->L0_wsp_sleafs[leafidx] = -1; } vbam_rc = Ln_tree_verify(0, bmap_recptr->L0pg_1stblk, &(bmap_recptr->L0_bufptr), &sumtree_root_data); if (vbam_rc == FSCK_OK) { /* * the data in the L0 summary tree root goes into * a leaf of the current L1 page */ bmap_recptr->L1_wsp_sleafs[bmap_recptr-> L0pg_idx] = sumtree_root_data; bmap_recptr->L0pg_idx++; } } } if (vbam_rc == FSCK_OK) { if ((bmap_recptr->L1pg_count > 0) && (bmap_recptr->L0pg_idx != 0)) { /* there's enough data for an L1 level, and there's a partial L1 page */ for (leafidx = bmap_recptr->L0pg_idx; (leafidx <= MAXIDX); leafidx++) { bmap_recptr->L1_wsp_sleafs[leafidx] = -1; } /* end for leafidx */ vbam_rc = Ln_tree_verify(1, bmap_recptr->L1pg_1stblk, &(bmap_recptr->L1_bufptr), &sumtree_root_data); if (vbam_rc == FSCK_OK) { /* * the data in the L0 summary tree root goes into * a leaf of the current L1 page */ bmap_recptr->L2_wsp_sleafs[bmap_recptr-> L1pg_idx] = sumtree_root_data; bmap_recptr->L1pg_idx++; } } } if (vbam_rc == FSCK_OK) { if ((bmap_recptr->L2pg_count > 0) && (bmap_recptr->L1pg_idx != 0)) { /* there's enough data for an L2 level, and there's a partial L2 page */ for (leafidx = bmap_recptr->L1pg_idx; (leafidx <= MAXIDX); leafidx++) { bmap_recptr->L2_wsp_sleafs[leafidx] = -1; } vbam_rc = Ln_tree_verify(2, bmap_recptr->L2pg_1stblk, &(bmap_recptr->L2_bufptr), &sumtree_root_data); } } /* * Now go verify the Block Allocation Map Control page */ if (vbam_rc == FSCK_OK) { vbam_rc = ctlpage_verify(sumtree_root_data); } /* * issue summary messages about the Block Allocation Map validation */ if (vbam_rc == FSCK_OK) { vbam_rc = verify_blkall_summary_msgs(); } return (vbam_rc); } /***************************************************************************** * NAME: verify_blkall_summary_msgs * * FUNCTION: Issue summary messages with the results of JFS Aggregate Block * Map validation. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int verify_blkall_summary_msgs() { int vbsm_rc = FSCK_OK; if (bmap_recptr->dmap_pmap_error) { fsck_send_msg(fsck_BADDMAPPMAPS); } if (bmap_recptr->dmap_slfv_error) { fsck_send_msg(fsck_BADBMAPSLFV, fsck_ref_msg(fsck_dmap)); } if (bmap_recptr->dmap_slnv_error) { fsck_send_msg(fsck_BADBMAPSLNV, fsck_ref_msg(fsck_dmap)); } if (bmap_recptr->dmap_other_error) { fsck_send_msg(fsck_BADBMAPSOTHER, fsck_ref_msg(fsck_dmap)); } if (bmap_recptr->L0pg_slfv_error) { fsck_send_msg(fsck_BADBMAPSLFV, fsck_ref_msg(fsck_L0)); } if (bmap_recptr->L0pg_slnv_error) { fsck_send_msg(fsck_BADBMAPSLNV, fsck_ref_msg(fsck_L0)); } if (bmap_recptr->L0pg_other_error) { fsck_send_msg(fsck_BADBMAPSOTHER, fsck_ref_msg(fsck_L0)); } if (bmap_recptr->L1pg_slfv_error) { fsck_send_msg(fsck_BADBMAPSLFV, fsck_ref_msg(fsck_L1)); } if (bmap_recptr->L1pg_slnv_error) { fsck_send_msg(fsck_BADBMAPSLNV, fsck_ref_msg(fsck_L1)); } if (bmap_recptr->L1pg_other_error) { fsck_send_msg(fsck_BADBMAPSOTHER, fsck_ref_msg(fsck_L1)); } if (bmap_recptr->L2pg_slfv_error) { fsck_send_msg(fsck_BADBMAPSLFV, fsck_ref_msg(fsck_L2)); } if (bmap_recptr->L2pg_slnv_error) { fsck_send_msg(fsck_BADBMAPSLNV, fsck_ref_msg(fsck_L2)); } if (bmap_recptr->L2pg_other_error) { fsck_send_msg(fsck_BADBMAPSOTHER, fsck_ref_msg(fsck_L2)); } if (bmap_recptr->ctl_fctl_error) { fsck_send_msg(fsck_BADBMAPCAGFCL); } if (bmap_recptr->ctl_other_error) { fsck_send_msg(fsck_BADBMAPCOTH); } if (bmap_recptr->dmap_pmap_error || bmap_recptr->dmap_slfv_error || bmap_recptr->dmap_slnv_error || bmap_recptr->dmap_other_error || bmap_recptr->L0pg_slfv_error || bmap_recptr->L0pg_slnv_error || bmap_recptr->L0pg_other_error || bmap_recptr->L1pg_slfv_error || bmap_recptr->L1pg_slnv_error || bmap_recptr->L1pg_other_error || bmap_recptr->L2pg_slfv_error || bmap_recptr->L2pg_slnv_error || bmap_recptr->L2pg_other_error) { agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_BADBLKALLOC); } if (bmap_recptr->ctl_fctl_error || bmap_recptr->ctl_other_error) { agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_BADBLKALLOCCTL); } return (vbsm_rc); } jfsutils-1.1.15.orig/fsck/fsckconn.c0000644000000000000000000007164610340701412014173 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "xfsckint.h" /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * superblock buffer pointer * * defined in xchkdsk.c */ extern struct superblock *sb_ptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * fsck aggregate info structure pointer * * defined in xchkdsk.c */ extern struct fsck_agg_record *agg_recptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * For directory entry processing * * defined in xchkdsk.c */ extern uint32_t key_len[2]; extern UniChar key[2][JFS_NAME_MAX]; extern UniChar ukey[2][JFS_NAME_MAX]; extern int32_t Uni_Name_len; extern UniChar Uni_Name[JFS_NAME_MAX]; /* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV * * The following are internal to this file * */ int adjust_parent(uint32_t, struct fsck_inode_record *, uint32_t); int reset_parents(struct fsck_inode_record *, uint32_t); /* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV */ /***************************************************************************** * NAME: adjust_parent * * FUNCTION: Add an fsck inode extension record to the parent inode's * fsck inode record so that the directory entry for the * given child will be removed. * * PARAMETERS: * child_ino - input - ordinal number of child inode * child_inorecptr - input - pointer to an fsck record describing the * child inode * parent_ino - input - ordinal number of parent inode * * RETURNS: * success: FSCK_OK * failure: something else */ int adjust_parent(uint32_t child_ino, struct fsck_inode_record *child_inorecptr, uint32_t parent_ino) { int adjp_rc = FSCK_OK; struct fsck_inode_ext_record *this_ext; struct fsck_inode_record *parent_inorecptr; int is_aggregate = 0; int alloc_ifnull = 0; adjp_rc = get_inorecptr(is_aggregate, alloc_ifnull, parent_ino, &parent_inorecptr); if ((adjp_rc == FSCK_OK) && (parent_inorecptr == NULL)) { adjp_rc = FSCK_INTERNAL_ERROR_4; fsck_send_msg(fsck_INTERNALERROR, adjp_rc, child_ino, parent_ino, 0); } else if (adjp_rc == FSCK_OK) { /* located the parent's inode record */ adjp_rc = get_inode_extension(&this_ext); if (adjp_rc == FSCK_OK) { /* got extension */ this_ext->ext_type = rmv_direntry_extension; this_ext->inonum = child_ino; this_ext->next = parent_inorecptr->ext_rec; this_ext->ino_type = child_inorecptr->inode_type; parent_inorecptr->ext_rec = this_ext; parent_inorecptr->adj_entries = 1; agg_recptr->corrections_needed = 1; } } return (adjp_rc); } /***************************************************************************** * NAME: adjust_parents * * FUNCTION: Add an fsck inode extension record, to the fsck inode record * of each of the given inode's parent inodes, so that all * directory entries for the given inode will be removed. The * exception is that, if the given inode is a directory inode, * the expected parent may be omitted from this processing. * * PARAMETERS: * ino_recptr - input - pointer to an fsck record describing the inode * ino_idx - input - ordinal number of the inode * * RETURNS: * success: FSCK_OK * failure: something else */ int adjust_parents(struct fsck_inode_record *ino_recptr, uint32_t ino_idx) { int adjps_rc = FSCK_OK; struct fsck_inode_ext_record *this_ext; struct fsck_inode_ext_record *rest_of_list; int keep_primary_parent = 0; /* * if this is a directory with illegal hard links then the * inode number in the fsck inode record is the one stored in * the inode on disk. Then if the inode isn't being released * and any observed parent matches the stored parent, that * parent will not be adjusted. */ if ((ino_recptr->inode_type == directory_inode) && (ino_recptr->unxpctd_prnts)) { /* dir with multiple parents */ if (!ino_recptr->selected_to_rls) { /* not being released */ if ((ino_recptr->parent_inonum != ROOT_I) || (!agg_recptr->rootdir_rebuilt)) { keep_primary_parent = 1; } } } else { /* not a dir with multiple parents -- this must be either an * inode approved for released or an unallocated inode with * parents observed. */ /* * the 1st parent observed is in the inode record. Any others are * in extension records. */ if (ino_recptr->parent_inonum != 0) { if ((ino_recptr->parent_inonum != ROOT_I) || (!agg_recptr->rootdir_rebuilt)) { /* either this parent isn't the root or else the root dir has not been rebuilt */ adjps_rc = adjust_parent(ino_idx, ino_recptr, ino_recptr->parent_inonum); ino_recptr->parent_inonum = 0; /* clear it */ } } } /* * detach the extensions list from the inode record */ this_ext = ino_recptr->ext_rec; ino_recptr->ext_rec = NULL; while ((adjps_rc == FSCK_OK) && (this_ext != NULL)) { /* there may be more parents */ rest_of_list = this_ext->next; if (this_ext->ext_type != parent_extension) { /* not a parent */ this_ext->next = ino_recptr->ext_rec; ino_recptr->ext_rec = this_ext; } else { /* parent extension */ if ((this_ext->inonum == ROOT_I) && (agg_recptr->rootdir_rebuilt)) { /* * This parent is the root and the root dir has * been rebuilt. This is equivalent to a parent * marked for release. */ release_inode_extension(this_ext); } else if ((keep_primary_parent) && (this_ext->inonum == ino_recptr->parent_inonum)) { /* * We're keeping the entry for the expected parent. * Just drop the extension record and clear the * 'unexpected parents' flag. When we finish this * routine the inode will be all set. */ release_inode_extension(this_ext); ino_recptr->unxpctd_prnts = 0; } else { /* either not keeping the 'primary' or else this isn't it */ adjps_rc = adjust_parent(ino_idx, ino_recptr, this_ext->inonum); release_inode_extension(this_ext); } } this_ext = rest_of_list; } return (adjps_rc); } /***************************************************************************** * NAME: check_connectedness * * FUNCTION: Verify that, after approved corrections are made, all inodes * in use will be connected to the root directory tree. * * PARAMETERS: none * * NOTES: o A directory inode must have exactly one parent inode. * o A non-directory inode must have at least one parent inode. * * RETURNS: * success: FSCK_OK * failure: something else */ int check_connectedness() { int cc_rc = FSCK_OK; uint32_t ino_idx; struct fsck_inode_record *this_inorec; struct fsck_inode_ext_record *new_ext; int aggregate_inode = 0; struct fsck_ino_msg_info ino_msg_info; struct fsck_ino_msg_info *msg_info_ptr; msg_info_ptr = &ino_msg_info; /* all fileset owned */ msg_info_ptr->msg_inopfx = fsck_fset_inode; /* * detect orphan inodes, including ones which we're about to * orphan by releasing inodes. * * if any non-orphan inode was flagged as a directory with illegal * hard links, see if it's going to be true after we release inodes. * If not, make sure the remaining link matches the one stored in * the inode. */ cc_rc = get_inorecptr_first(aggregate_inode, &ino_idx, &this_inorec); while ((cc_rc == FSCK_OK) && (this_inorec != NULL) && (ino_idx < FILESET_OBJECT_I)) { /* * not interesting until we get past the root inode * and the special fileset inodes. */ cc_rc = get_inorecptr_next(aggregate_inode, &ino_idx, &this_inorec); } while ((cc_rc == FSCK_OK) && (this_inorec != NULL)) { if ((this_inorec->in_use) && (!this_inorec->selected_to_rls)) { /* inode in use and not selected to release */ msg_info_ptr->msg_inonum = ino_idx; if (this_inorec->inode_type == directory_inode) { msg_info_ptr->msg_inotyp = fsck_directory; } else if (this_inorec->inode_type == symlink_inode) { msg_info_ptr->msg_inotyp = fsck_symbolic_link; } else if (this_inorec->inode_type == char_special_inode) { msg_info_ptr->msg_inotyp = fsck_char_special; } else if (this_inorec->inode_type == block_special_inode) { msg_info_ptr->msg_inotyp = fsck_block_special; } else if (this_inorec->inode_type == FIFO_inode) { msg_info_ptr->msg_inotyp = fsck_FIFO; } else if (this_inorec->inode_type == SOCK_inode) { msg_info_ptr->msg_inotyp = fsck_SOCK; } else { /* a regular file */ msg_info_ptr->msg_inotyp = fsck_file; } if (this_inorec->parent_inonum == 0) { /* no parents were observed by fsck */ fsck_send_msg(fsck_INONOPATHS, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } else { /* at least one parent observed by fsck */ /* * make adjustments to child records for * parents which will be released */ cc_rc = reset_parents(this_inorec, ino_idx); } if (cc_rc == FSCK_OK) { if (this_inorec->parent_inonum == 0) { /* unconnected !! */ /* * do not issue a message to inform the user about * this condition since it is a side effect of * the (approved) release of some other inode(s) */ this_inorec->reconnect = 1; agg_recptr->corrections_approved = 1; cc_rc = get_inode_extension(&new_ext); if (cc_rc == FSCK_OK) { /* got an extension record */ new_ext->ext_type = add_direntry_extension; new_ext->inonum = ino_idx; new_ext->ino_type = this_inorec->inode_type; new_ext->next = agg_recptr-> inode_reconn_extens; agg_recptr-> inode_reconn_extens = new_ext; /* increment for the link from * parent after reconnect */ this_inorec->link_count++; } } else { /* else still connected */ if (this_inorec->unxpctd_prnts) { /* multiple parents */ cc_rc = display_paths(ino_idx, this_inorec, msg_info_ptr); if (cc_rc == FSCK_OK) { if (agg_recptr-> processing_readwrite) { cc_rc = adjust_parents (this_inorec, ino_idx); fsck_send_msg (fsck_WILLFIXDIRWHDLKS, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } else { /* no write access */ this_inorec-> unxpctd_prnts = 0; agg_recptr-> ag_dirty = 1; fsck_send_msg (fsck_DIRWHDLKS, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } } else if ((cc_rc == FSCK_OK) && (this_inorec-> crrct_prnt_inonum)) { /* * a single parent but not the one * named in the implied '..' entry */ cc_rc = display_paths(ino_idx, this_inorec, msg_info_ptr); if (agg_recptr-> processing_readwrite) { fsck_send_msg (fsck_WILLFIXINCREF, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, fsck_ref_msg(msg_info_ptr->msg_inopfx), this_inorec->parent_inonum); } else { /* no write access */ this_inorec-> crrct_prnt_inonum = 0; agg_recptr->ag_dirty = 1; fsck_send_msg (fsck_INCINOREF, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, fsck_ref_msg(msg_info_ptr->msg_inopfx), this_inorec->parent_inonum); } } } } } if (cc_rc == FSCK_OK) { cc_rc = get_inorecptr_next(aggregate_inode, &ino_idx, &this_inorec); } } return (cc_rc); } /***************************************************************************** * NAME: check_dir_integrity * * FUNCTION: Verify that no directory has more than 1 entry for any * single inode. If a directory does, then that directory * is corrupt. * * RETURNS: * success: FSCK_OK * failure: something else */ int check_dir_integrity() { int cdi_rc = FSCK_OK; uint32_t ino_idx; struct fsck_inode_record *this_inorec; struct fsck_inode_record *that_inorec; int aggregate_inode = 0; int alloc_ifnull = 0; struct fsck_inode_ext_record *this_ext; struct fsck_inode_ext_record *that_ext; int dup_parent_detected = 0; struct fsck_ino_msg_info ino_msg_info; struct fsck_ino_msg_info *msg_info_ptr; msg_info_ptr = &ino_msg_info; /* all fileset owned */ msg_info_ptr->msg_inopfx = fsck_fset_inode; /* * Verify that no inode has multiple links from the same * directory. */ cdi_rc = get_inorecptr_first(aggregate_inode, &ino_idx, &this_inorec); while ((cdi_rc == FSCK_OK) && (this_inorec != NULL) && (ino_idx < FILESET_OBJECT_I)) { /* * not interesting until we get past the root inode * and the special fileset inodes. */ cdi_rc = get_inorecptr_next(aggregate_inode, &ino_idx, &this_inorec); } while ((cdi_rc == FSCK_OK) && (this_inorec != NULL)) { if ((this_inorec->in_use) && (!this_inorec->selected_to_rls) && (this_inorec->inode_type == directory_inode)) { /* directory inode in use and not selected to release */ msg_info_ptr->msg_inotyp = fsck_directory; msg_info_ptr->msg_inonum = ino_idx; if (this_inorec->parent_inonum != 0) { /* at least 1 parent observed by fsck */ if (this_inorec->ext_rec) { /* maybe more parents have been observed */ /* * get the first entry in the extensions * list on the inode record */ this_ext = this_inorec->ext_rec; while ((cdi_rc == FSCK_OK) && (this_ext != NULL)) { /* there may be more parents */ if (this_ext->ext_type == parent_extension) { /* a parent */ cdi_rc = get_inorecptr (aggregate_inode, alloc_ifnull, this_ext->inonum, &that_inorec); if ((cdi_rc == FSCK_OK) && (!that_inorec-> selected_to_rls)) { /* parent isn't marked for release (yet) */ dup_parent_detected = 0; if (this_ext-> inonum == this_inorec-> parent_inonum) { dup_parent_detected = -1; } else { /* need to check for dups in rest of list */ that_ext = this_ext-> next; while ((!dup_parent_detected) && (that_ext != NULL)) { if (that_ext->ext_type == parent_extension) /* another parent extension */ if (this_ext->inonum == that_ext->inonum) { dup_parent_detected = -1; } that_ext = that_ext-> next; } } if (dup_parent_detected) { /* * mark the parent's inode record for release */ that_inorec-> selected_to_rls = 1; /* * notify the user that the directory is bad */ fsck_send_msg (fsck_BADKEYS, fsck_ref_msg(fsck_directory), fsck_ref_msg(msg_info_ptr->msg_inopfx), this_ext->inonum, 37); } } } this_ext = this_ext->next; } } } } if (cdi_rc == FSCK_OK) { cdi_rc = get_inorecptr_next(aggregate_inode, &ino_idx, &this_inorec); } } return (cdi_rc); } /***************************************************************************** * NAME: check_link_counts * * FUNCTION: Count links from child directories to their parents. * * Verify that the link count stored in each in-use inode * matches the number of links fsck observed for the inode. * * RETURNS: * success: FSCK_OK * failure: something else */ int check_link_counts() { int clc_rc = FSCK_OK; uint32_t ino_idx; int num_parents; int invalid_count_seen = 0; int low_stored_count_seen = 0; struct fsck_inode_ext_record *this_ext; struct fsck_inode_record *this_inorec; struct fsck_inode_record *parent_inorec; int done_looking = 0; int aggregate_inode = 0; int alloc_ifnull = 0; struct fsck_ino_msg_info ino_msg_info; struct fsck_ino_msg_info *msg_info_ptr; msg_info_ptr = &ino_msg_info; /* all fileset owned */ msg_info_ptr->msg_inopfx = fsck_fset_inode; /* * count links from child directories to their parents * * (These can't be counted when the parent-child relationship * is observed because that observation occurs while processing * the parent and until the child is processed we don't know * whether the child is a directory or not.) */ clc_rc = get_inorecptr_first(aggregate_inode, &ino_idx, &this_inorec); while ((clc_rc == FSCK_OK) && (this_inorec != NULL)) { if ((this_inorec->in_use) && (!this_inorec->selected_to_rls) && (!this_inorec->ignore_alloc_blks) && (this_inorec->inode_type == directory_inode)) { /* inode is in use, not being released, and is type directory */ /* for the self entry */ this_inorec->link_count++; if ((this_inorec->parent_inonum == ROOT_I) && (agg_recptr->rootdir_rebuilt)) { /* * special case: if the parent is root and root was * rebuilt, then don't increment parent */ if (this_inorec->inonum == ROOT_I) { /* * special case: if this IS the root, then it's * link from itself to itself DOES count */ this_inorec->link_count++; } } else if (this_inorec->parent_inonum != 0) { /* not an orphan */ clc_rc = get_inorecptr(aggregate_inode, alloc_ifnull, this_inorec->parent_inonum, &parent_inorec); if ((clc_rc != FSCK_OK) || (parent_inorec == NULL)) { clc_rc = FSCK_INTERNAL_ERROR_13; fsck_send_msg(fsck_INTERNALERROR, clc_rc, ino_idx, this_inorec->parent_inonum, 0); } else { /* handle the first (and usually the only) parent. */ parent_inorec->link_count++; } if ((clc_rc == FSCK_OK) && (this_inorec->ext_rec != NULL)) { /* there might be more parents */ num_parents = parent_count(this_inorec); if (num_parents > 1) { /* directory with illegal links */ this_inorec->unxpctd_prnts = 1; agg_recptr->corrections_needed = 1; /* * Create an extension record for the parent inode * number now stored in the child inode record. * When we traverse the aggregate on-disk we'll copy * the stored value into this field of the inode record * for use when displaying paths to the inode. */ clc_rc = get_inode_extension (&this_ext); if (clc_rc == FSCK_OK) { /* got extension record */ this_ext->ext_type = parent_extension; this_ext->inonum = this_inorec-> parent_inonum; this_ext->next = this_inorec-> ext_rec; this_inorec->ext_rec = this_ext; this_inorec-> parent_inonum = 0; /* already counted the first * one, back when it was in the * workspace inode record itself */ this_ext = this_ext->next; while ((clc_rc == FSCK_OK) && (this_ext != NULL)) { /* exten records to check */ if (this_ext-> ext_type == parent_extension) { clc_rc = get_inorecptr (aggregate_inode, alloc_ifnull, this_ext-> inonum, &parent_inorec); if ((clc_rc != FSCK_OK) || (parent_inorec == NULL)) { clc_rc = FSCK_INTERNAL_ERROR_14; fsck_send_msg (fsck_INTERNALERROR, clc_rc, ino_idx, this_ext->inonum, 0); } else { parent_inorec-> link_count++; } } this_ext = this_ext-> next; } } } } } } if (clc_rc == FSCK_OK) { clc_rc = get_inorecptr_next(aggregate_inode, &ino_idx, &this_inorec); } } /* * verify that stored link counts match observed link counts * * We have added each observed link and subtracted the stored * count. If the stored count is correct the result is 0. */ if (clc_rc == FSCK_OK) { clc_rc = get_inorecptr_first(aggregate_inode, &ino_idx, &this_inorec); while ((clc_rc == FSCK_OK) && (this_inorec != NULL) && (!done_looking)) { if ((this_inorec->in_use) && (!this_inorec->selected_to_rls) && (!this_inorec->ignore_alloc_blks)) { /* inode is in use and not being released */ if (this_inorec->link_count != 0) { /* stored link count doesn't match fsck's observations */ if (this_inorec->parent_inonum == 0) { /* inode is an orphan */ this_inorec->crrct_link_count = 1; } else { /* not an orphan */ this_inorec->crrct_link_count = 1; if (this_inorec->link_count > 0) { low_stored_count_seen = 1; } invalid_count_seen = 1; fsck_send_msg(fsck_BADINOLKCT, fsck_ref_msg(msg_info_ptr->msg_inopfx), ino_idx); } } } if (clc_rc == FSCK_OK) { clc_rc = get_inorecptr_next(aggregate_inode, &ino_idx, &this_inorec); } } if ((clc_rc == FSCK_OK) && (invalid_count_seen)) { if (agg_recptr->processing_readwrite) { agg_recptr->corrections_approved = 1; fsck_send_msg(fsck_WILLFIXLINKCTS); } else { /* no write access */ if (low_stored_count_seen) { agg_recptr->ag_dirty = 1; } /* * reset all link counts (in the fsck workspace) to * zero so that we won't accidentally correct them * while doing link count adjustments. * * (Link count adjustments are side effects of approved * repairs. For example, if a directory inode is * released, the link count of its parent directory * is decremented.) */ clc_rc = get_inorecptr_first(aggregate_inode, &ino_idx, &this_inorec); while ((clc_rc == FSCK_OK) && (this_inorec != NULL)) { if (this_inorec->in_use) { this_inorec->crrct_link_count = 0; this_inorec->link_count = 0; } clc_rc = get_inorecptr_next(aggregate_inode, &ino_idx, &this_inorec); } fsck_send_msg(fsck_BADLINKCTS); } } } return (clc_rc); } /***************************************************************************** * NAME: reset_parents * * FUNCTION: Adjust the fsck notations about the inode's parent(s) if * the parent(s) are corrupt or approved for release. * * PARAMETERS: * ino_recptr - input - pointer to an fsck record describing the inode * ino_idx - input - ordinal number of the inode * * RETURNS: * success: FSCK_OK * failure: something else */ int reset_parents(struct fsck_inode_record *ino_recptr, uint32_t ino_idx) { int resps_rc = FSCK_OK; struct fsck_inode_ext_record *this_ext; struct fsck_inode_ext_record *rest_of_list; int parent_count = 0; uint32_t stored_parent_inonum = 0; struct fsck_inode_record *parent_inorecptr; int aggregate_inode = 0; int alloc_ifnull = 0; /* * if this is a directory with illegal hard links the inode * number in the fsck inode record is the one stored in the * inode on disk. */ if ((ino_recptr->inode_type == directory_inode) && (ino_recptr->unxpctd_prnts)) { /* dir with multiple parents */ /* * Save the value stored in the inode record and then clear it. */ stored_parent_inonum = ino_recptr->parent_inonum; ino_recptr->parent_inonum = 0; } else { /* not a dir with multiple parents */ /* * the 1st parent observed is in the inode record. * Any others are in extension records. */ resps_rc = get_inorecptr(aggregate_inode, alloc_ifnull, ino_recptr->parent_inonum, &parent_inorecptr); if ((resps_rc == FSCK_OK) && (parent_inorecptr == NULL)) { resps_rc = FSCK_INTERNAL_ERROR_15; fsck_send_msg(fsck_INTERNALERROR, resps_rc, ino_idx, ino_recptr->parent_inonum, 0); } else if (resps_rc == FSCK_OK) { if ((ino_recptr->parent_inonum == ROOT_I) && (agg_recptr->rootdir_rebuilt)) { /* * special case: if the parent is root and root * was rebuilt, then this is an orphan */ ino_recptr->parent_inonum = 0; ino_recptr->link_count--; } else if ((!parent_inorecptr->selected_to_rls) && (!parent_inorecptr->ignore_alloc_blks)) { /* * keeping this parent and haven't found the * tree to be corrupt */ parent_count++; } else { /* releasing this parent */ ino_recptr->parent_inonum = 0; ino_recptr->link_count--; } } } /* * detach the extensions list from the inode record */ this_ext = ino_recptr->ext_rec; ino_recptr->ext_rec = NULL; while ((resps_rc == FSCK_OK) && (this_ext != NULL)) { /* there may be more parents */ rest_of_list = this_ext->next; if (this_ext->ext_type != parent_extension) { /* not a parent */ this_ext->next = ino_recptr->ext_rec; ino_recptr->ext_rec = this_ext; } else { /* parent extension */ resps_rc = get_inorecptr(aggregate_inode, alloc_ifnull, this_ext->inonum, &parent_inorecptr); if ((resps_rc == FSCK_OK) && (parent_inorecptr == NULL)) { resps_rc = FSCK_INTERNAL_ERROR_16; fsck_send_msg(fsck_INTERNALERROR, resps_rc, ino_idx, this_ext->inonum, 0); } else if (resps_rc == FSCK_OK) { if ((ino_recptr->parent_inonum == ROOT_I) && (agg_recptr->rootdir_rebuilt)) { /* * special case: if the parent is root and * root was rebuilt, then this is an orphan */ release_inode_extension(this_ext); ino_recptr->link_count--; } else if ((!parent_inorecptr->selected_to_rls) && (!parent_inorecptr-> ignore_alloc_blks)) { /* keeping this parent */ parent_count++; if (ino_recptr->parent_inonum == 0) { ino_recptr->parent_inonum = this_ext->inonum; release_inode_extension (this_ext); } else { /* put it back on the list */ this_ext->next = ino_recptr->ext_rec; ino_recptr->ext_rec = this_ext; } } else { /* releasing this parent */ release_inode_extension(this_ext); ino_recptr->link_count--; } } } this_ext = rest_of_list; } /* * at this point, if there is at least 1 observed parent which * is not being released, then a parent inode number is stored in * the inode record and any other parents are described in extension * records. * * if this is not a directory inode, we're done. * * if this is a directory inode, need to recheck for illegal hard * links and incorrect parent inode entry. */ if ((resps_rc == FSCK_OK) && (ino_recptr->inode_type == directory_inode)) { /* a directory */ if (parent_count == 1) { /* 1 parent now */ if (ino_recptr->unxpctd_prnts) { /* entered with multiple links */ /* reset flag */ ino_recptr->unxpctd_prnts = 0; if (ino_recptr->parent_inonum != stored_parent_inonum) { /* * Remaining parent doesn't match the one * the on-device inode says owns it. */ ino_recptr->crrct_prnt_inonum = 1; agg_recptr->corrections_needed = 1; agg_recptr->corrections_approved = 1; } } } else if (parent_count == 0) { /* no parents now */ ino_recptr->crrct_prnt_inonum = 0; ino_recptr->unxpctd_prnts = 0; } else { /* multiple parents still */ ino_recptr->unxpctd_prnts = 1; agg_recptr->corrections_needed = 1; resps_rc = get_inode_extension(&this_ext); if (resps_rc == FSCK_OK) { this_ext->ext_type = parent_extension; this_ext->inonum = ino_recptr->parent_inonum; this_ext->next = ino_recptr->ext_rec; ino_recptr->ext_rec = this_ext; ino_recptr->parent_inonum = stored_parent_inonum; } } } return (resps_rc); } jfsutils-1.1.15.orig/fsck/fsckdire.c0000644000000000000000000013376410441103233014160 0ustar /* * Copyright (C) International Business Machines Corp., 2000-2005 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * (created from dtree.c: directory B+-tree manager for fsck) */ #include #include #include #include "xfsckint.h" #include "jfs_byteorder.h" #include "jfs_unicode.h" extern struct superblock *sb_ptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * fsck aggregate info structure pointer * * defined in xchkdsk.c */ extern struct fsck_agg_record *agg_recptr; /* * btree traversal stack * * record the path traversed during the search; * top frame record the leaf page/entry selected. */ #define MAXTREEHEIGHT 8 struct btframe { /* stack frame */ int64_t bn; /* 8: */ int16_t index; /* 2: */ int16_t lastindex; /* 2: */ struct btpage *bp; /* 4: */ }; /* (16) */ struct btstack { struct btframe *top; /* 4: */ int32_t nsplit; /* 4: */ struct btframe stack[MAXTREEHEIGHT]; }; #define BT_CLR(btstack)\ (btstack)->top = (btstack)->stack #define BT_PUSH(BTSTACK, BN, INDEX)\ {\ (BTSTACK)->top->bn = BN;\ (BTSTACK)->top->index = INDEX;\ ++(BTSTACK)->top;\ } #define BT_POP(btstack)\ ( (btstack)->top == (btstack)->stack ? NULL : --(btstack)->top ) #define BT_STACK(btstack)\ ( (btstack)->top == (btstack)->stack ? NULL : (btstack)->top ) /* retrieve search results */ #define BT_GETSEARCH(IP, LEAF, BN, BP, TYPE, P, INDEX)\ {\ BN = (LEAF)->bn;\ BP = (LEAF)->bp;\ if (BN)\ P = (TYPE *)BP;\ else\ P = (TYPE *)&IP->di_btroot;\ INDEX = (LEAF)->index;\ } /* put the page buffer of search */ #define BT_PUTSEARCH(BTSTACK)\ {\ if ((BTSTACK)->top->bn)\ recon_dnode_put((BTSTACK)->top->bp);\ } /* get page from buffer page */ #define FSCK_BT_PAGE(IP, BP, TYPE)\ (BP->flag & BT_ROOT) ? (TYPE *)&IP->di_btroot : (TYPE *)BP /* get the page buffer and the page for specified block address */ #define FSCK_BT_GETPAGE(IP, BN, BP, TYPE, P, RC)\ {\ if ((BN) == 0)\ {\ BP = (struct btpage *)&IP->di_btroot;\ P = (TYPE *)&IP->di_btroot;\ RC = 0;\ }\ else\ {\ RC = recon_dnode_get(BN, (dtpage_t **)&BP);\ if (RC == 0)\ P = (TYPE *)BP;\ }\ } /* put the page buffer */ #define FSCK_BT_PUTPAGE(BP)\ {\ if (!((BP)->flag & BT_ROOT))\ recon_dnode_put((dtpage_t *)BP);\ } #define DO_INDEX() (sb_ptr->s_flag & JFS_DIR_INDEX) /* dtree split parameter */ struct dtsplit { struct btpage *bp; int16_t index; int16_t nslot; struct component_name *key; ddata_t *data; struct pxdlist *pxdlist; }; /* * forward references */ static int dtSplitUp(struct dinode *ip, struct dtsplit *split, struct btstack *btstack); static int dtSplitPage(struct dinode *ip, struct dtsplit *split, struct btpage **rbpp, pxd_t * rxdp); static int dtSplitRoot(struct dinode *ip, struct dtsplit *split, struct btpage **rbpp); static int fsck_dtDeleteUp(struct dinode *ip, struct btpage *fbp, struct btstack *btstack); static int dtRelink(struct dinode *ip, dtpage_t * p); static int dtCompare(struct component_name *key, dtpage_t * p, int32_t si); static void dtGetKey(dtpage_t * p, int32_t i, struct component_name *key); static int ciCompare(struct component_name *key, dtpage_t * p, int32_t si, int32_t flag); static void ciGetLeafPrefixKey(dtpage_t * lp, int32_t li, dtpage_t * rp, int32_t ri, struct component_name *key, int32_t flag); #define ciToUpper(c) UniStrupr((c)->name) static void dtInsertEntry(struct dinode *ip, dtpage_t * p, int32_t index, struct component_name *key, ddata_t * data); static void dtMoveEntry(dtpage_t * sp, int32_t si, dtpage_t * dp); static void fsck_dtDeleteEntry(dtpage_t * p, int32_t fi); void fsck_dtInitRoot(struct dinode *ip, uint32_t idotdot); /* copy memory */ #define bcopy(source, dest, count) memcpy(dest, source, count) /* * fsck_dtSearch() * * function: * Search for the entry with specified key * * parameter: * * return: 0 - search result on stack, leaf page pinned; * errno - I/O error */ int fsck_dtSearch(struct dinode *ip, struct component_name *key, uint32_t * data, struct btstack *btstack, uint32_t flag) { int rc = 0; int32_t cmp = 1; /* init for empty page */ int64_t bn; struct btpage *bp; dtpage_t *p = 0; int8_t *stbl; int32_t base, index, lim; struct btframe *btsp; pxd_t *pxd; uint32_t inumber; UniChar ciKeyName[JFS_NAME_MAX + 1]; struct component_name ciKey = { 0, ciKeyName }; /* uppercase search key for c-i directory */ UniStrcpy(ciKeyName, key->name); ciKey.namlen = key->namlen; /* only uppercase if case-insensitive support is on */ if ((sb_ptr->s_flag & JFS_OS2) == JFS_OS2) { ciToUpper(&ciKey); } BT_CLR(btstack); /* reset stack */ /* init level count for max pages to split */ btstack->nsplit = 1; /* * search down tree from root: * * between two consecutive entries of and of * internal page, child page Pi contains entry with k, Ki <= K < Kj. * * if entry with search key K is not found * internal page search find the entry with largest key Ki * less than K which point to the child page to search; * leaf page search find the entry with smallest key Kj * greater than K so that the returned index is the position of * the entry to be shifted right for insertion of new entry. * for empty tree, search key is greater than any key of the tree. * * by convention, root bn = 0. */ for (bn = 0;;) { /* get/pin the page to search */ FSCK_BT_GETPAGE(ip, bn, bp, dtpage_t, p, rc); if (rc) return rc; /* get sorted entry table of the page */ stbl = DT_GETSTBL(p); /* * binary search with search key K on the current page. */ for (base = 0, lim = p->header.nextindex; lim; lim >>= 1) { index = base + (lim >> 1); if (p->header.flag & BT_LEAF) { /* uppercase leaf name to compare */ cmp = ciCompare(&ciKey, p, stbl[index], sb_ptr->s_flag); } else { /* router key is in uppercase */ cmp = dtCompare(&ciKey, p, stbl[index]); } if (cmp == 0) { /* search hit - leaf page: * return the entry found */ if (p->header.flag & BT_LEAF) { inumber = ((struct ldtentry *) &p-> slot[stbl[index]])->inumber; /* * search for JFS_CREATE */ if (flag == JFS_CREATE) { *data = inumber; rc = EEXIST; goto out; } /* * search for JFS_REMOVE */ if (flag == JFS_REMOVE && *data != inumber) { rc = ESTALE; goto out; } /* * JFS_REMOVE */ /* save search result */ *data = inumber; btsp = btstack->top; btsp->bn = bn; btsp->index = index; btsp->bp = bp; return 0; } /* search hit - internal page: * descend/search its child page */ goto getChild; } if (cmp > 0) { base = index + 1; --lim; } } /* * search miss * * base is the smallest index with key (Kj) greater than * search key (K) and may be zero or (maxindex + 1) index. */ /* * search miss - leaf page * * return location of entry (base) where new entry with * search key K is to be inserted. */ if (p->header.flag & BT_LEAF) { /* * search for JFS_LOOKUP, JFS_REMOVE, or JFS_RENAME */ if (flag == JFS_REMOVE) { rc = ENOENT; goto out; } /* * search for JFS_CREATE * * save search result */ *data = 0; btsp = btstack->top; btsp->bn = bn; btsp->index = base; btsp->bp = bp; return 0; } /* * search miss - internal page * * if base is non-zero, decrement base by one to get the parent * entry of the child page to search. */ index = base ? base - 1 : base; /* * go down to child page */ getChild: /* update max. number of pages to split */ /* assert(btstack->nsplit < 8); */ btstack->nsplit++; /* push (bn, index) of the parent page/entry */ BT_PUSH(btstack, bn, index); /* get the child page block number */ pxd = (pxd_t *) & p->slot[stbl[index]]; bn = addressPXD(pxd); /* unpin the parent page */ FSCK_BT_PUTPAGE(bp); } out: FSCK_BT_PUTPAGE(bp); return rc; } /* * fsck_dtInsert() * * function: insert an entry to directory tree * * parameter: * ip - parent directory * name - entry name; * fsn - entry i_number; * * return: 0 - success; * errno - failure; */ int fsck_dtInsert(struct dinode *ip, struct component_name *name, uint32_t * fsn) { int rc = 0; struct btpage *bp; /* page buffer */ dtpage_t *p; /* base B+-tree index page */ int64_t bn; int32_t index; struct dtsplit split; /* split information */ ddata_t data; int32_t n; struct btstack btstack; uint32_t ino; /* * search for the entry to insert: * * fsck_dtSearch() returns (leaf page pinned, index at which to insert). */ rc = fsck_dtSearch(ip, name, &ino, &btstack, JFS_CREATE); if (rc) return rc; /* * retrieve search result * * fsck_dtSearch() returns (leaf page pinned, index at which to insert). * n.b. fsck_dtSearch() may return index of (maxindex + 1) of * the full page. */ BT_GETSEARCH(ip, btstack.top, bn, bp, dtpage_t, p, index); /* * insert entry for new key */ if (DO_INDEX()) n = NDTLEAF(name->namlen); else n = NDTLEAF_LEGACY(name->namlen); data.leaf.ino = *fsn; /* * leaf page does not have enough room for new entry: * * extend/split the leaf page; * * dtSplitUp() will insert the entry and unpin the leaf page. */ if (n > p->header.freecnt) { split.bp = bp; split.index = index; split.nslot = n; split.key = name; split.data = &data; rc = dtSplitUp(ip, &split, &btstack); return rc; } /* * leaf page does have enough room for new entry: * * insert the new data entry into the leaf page; */ dtInsertEntry(ip, p, index, name, &data); /* unpin the leaf page */ FSCK_BT_PUTPAGE(bp); return 0; } /* * dtSplitUp() * * function: propagate insertion bottom up; * * parameter: * * return: 0 - success; * errno - failure; * leaf page unpinned; */ static int dtSplitUp(struct dinode *ip, struct dtsplit *split, struct btstack *btstack) { int rc = 0; struct btpage *sbp; dtpage_t *sp; /* split page */ struct btpage *rbp; dtpage_t *rp; /* new right page split from sp */ pxd_t rpxd; /* new right page extent descriptor */ struct btpage *lbp; dtpage_t *lp; /* left child page */ int32_t skip; /* index of entry of insertion */ struct btframe *parent; /* parent page entry on traverse stack */ int64_t xaddr; int32_t xlen; struct pxdlist pxdlist; pxd_t *pxd; UniChar name[JFS_NAME_MAX + 1]; struct component_name key = { 0, name }; ddata_t *data = split->data; int32_t n; /* get split page */ sbp = split->bp; sp = FSCK_BT_PAGE(ip, sbp, dtpage_t); /* * split leaf page * * The split routines insert the new entry * * split root leaf page: */ if (sp->header.flag & BT_ROOT) { /* * allocate a single extent child page */ xlen = agg_recptr->blksperpg; rc = fsck_alloc_fsblks(xlen, &xaddr); if (rc) return rc; pxdlist.maxnpxd = 1; pxdlist.npxd = 0; pxd = &pxdlist.pxd[0]; PXDaddress(pxd, xaddr); PXDlength(pxd, xlen); split->pxdlist = &pxdlist; rc = dtSplitRoot(ip, split, &rbp); FSCK_BT_PUTPAGE(rbp); FSCK_BT_PUTPAGE(sbp); ip->di_size = xlen << agg_recptr->log2_blksize; return rc; } /* * split leaf page into and a new right page . * * return pinned and its extent descriptor * * allocate new directory page extent and * new index page(s) to cover page split(s) * * allocation hint: ? */ n = btstack->nsplit; pxdlist.maxnpxd = pxdlist.npxd = 0; xlen = agg_recptr->blksperpg; for (pxd = pxdlist.pxd; n > 0; n--, pxd++) { rc = fsck_alloc_fsblks(xlen, &xaddr); if (rc == 0) { PXDaddress(pxd, xaddr); PXDlength(pxd, xlen); pxdlist.maxnpxd++; continue; } FSCK_BT_PUTPAGE(sbp); /* undo allocation */ goto splitOut; } split->pxdlist = &pxdlist; rc = dtSplitPage(ip, split, &rbp, &rpxd); if (rc) { FSCK_BT_PUTPAGE(sbp); /* undo allocation */ goto splitOut; } ip->di_size += PSIZE; /* * propagate up the router entry for the leaf page just split * * insert a router entry for the new page into the parent page, * propagate the insert/split up the tree by walking back the stack * of (bn of parent page, index of child page entry in parent page) * that were traversed during the search for the page that split. * * the propagation of insert/split up the tree stops if the root * splits or the page inserted into doesn't have to split to hold * the new entry. * * the parent entry for the split page remains the same, and * a new entry is inserted at its right with the first key and * block number of the new right page. * * There are a maximum of 4 pages pinned at any time: * two children, left parent and right parent (when the parent splits). * keep the child pages pinned while working on the parent. * make sure that all pins are released at exit. */ while ((parent = BT_POP(btstack)) != NULL) { /* parent page specified by stack frame */ /* keep current child pages (, ) pinned */ lbp = sbp; lp = sp; rp = FSCK_BT_PAGE(ip, rbp, dtpage_t); /* * insert router entry in parent for new right child page * * get the parent page */ FSCK_BT_GETPAGE(ip, parent->bn, sbp, dtpage_t, sp, rc); if (rc) { FSCK_BT_PUTPAGE(lbp); FSCK_BT_PUTPAGE(rbp); goto splitOut; } /* * The new key entry goes ONE AFTER the index of parent entry, * because the split was to the right. */ skip = parent->index + 1; /* * compute the key for the router entry * * key suffix compression: * for internal pages that have leaf pages as children, * retain only what's needed to distinguish between * the new entry and the entry on the page to its left. * If the keys compare equal, retain the entire key. * * note that compression is performed only at computing * router key at the lowest internal level. * further compression of the key between pairs of higher * level internal pages loses too much information and * the search may fail. * (e.g., two adjacent leaf pages of {a, ..., x} {xx, ...,} * results in two adjacent parent entries (a)(xx). * if split occurs between these two entries, and * if compression is applied, the router key of parent entry * of right page (x) will divert search for x into right * subtree and miss x in the left subtree.) * * the entire key must be retained for the next-to-leftmost * internal key at any level of the tree, or search may fail * (e.g., ?) */ switch (rp->header.flag & BT_TYPE) { case BT_LEAF: /* * compute the length of prefix for suffix compression * between last entry of left page and first entry * of right page */ if ((sp->header.flag & BT_ROOT && skip > 1) || sp->header.prev != 0 || skip > 1) { /* compute uppercase router prefix key */ ciGetLeafPrefixKey(lp, lp->header.nextindex - 1, rp, 0, &key, sb_ptr->s_flag); } else { /* next to leftmost entry of lowest internal level */ /* compute uppercase router key */ dtGetKey(rp, 0, &key); if ((sb_ptr->s_flag & JFS_OS2) == JFS_OS2) ciToUpper(&key); } n = NDTINTERNAL(key.namlen); break; case BT_INTERNAL: dtGetKey(rp, 0, &key); n = NDTINTERNAL(key.namlen); break; default: #ifdef _JFS_DEBUG printf("dtSplitUp(): UFO!\n"); #endif break; } /* unpin left child page */ FSCK_BT_PUTPAGE(lbp); /* * compute the data for the router entry */ /* child page xd */ data->xd = rpxd; /* * parent page is full - split the parent page */ if (n > sp->header.freecnt) { /* init for parent page split */ split->bp = sbp; /* index at insert */ split->index = skip; split->nslot = n; split->key = &key; /* split->data = data; */ /* unpin right child page */ FSCK_BT_PUTPAGE(rbp); /* The split routines insert the new entry, * acquire txLock as appropriate. * return pinned and its block number . */ rc = (sp->header.flag & BT_ROOT) ? dtSplitRoot(ip, split, &rbp) : dtSplitPage(ip, split, &rbp, &rpxd); if (rc) { FSCK_BT_PUTPAGE(sbp); goto splitOut; } /* sbp and rbp are pinned */ } else { /* * parent page is not full - insert router entry in parent page */ dtInsertEntry(ip, sp, skip, &key, data); /* exit propagate up */ break; } } /* unpin current split and its right page */ FSCK_BT_PUTPAGE(sbp); FSCK_BT_PUTPAGE(rbp); /* * free remaining extents allocated for split */ splitOut: n = pxdlist.npxd; pxd = &pxdlist.pxd[n]; for (; n < pxdlist.maxnpxd; n++, pxd++) fsck_dealloc_fsblks(lengthPXD(pxd), (int64_t) addressPXD(pxd)); return rc; } /* * dtSplitPage() * * function: Split a non-root page of a btree. * * parameter: * * return: 0 - success; * errno - failure; * return split and new page pinned; */ static int dtSplitPage(struct dinode *ip, struct dtsplit *split, struct btpage **rbpp, pxd_t * rpxdp) { int rc = 0; struct btpage *sbp; dtpage_t *sp; struct btpage *rbp; dtpage_t *rp; /* new right page allocated */ int64_t rbn; /* new right page block number */ struct btpage *bp; dtpage_t *p = 0; int64_t nextbn; struct pxdlist *pxdlist; pxd_t *pxd; int32_t skip, nextindex, half, left, nxt, off, si; struct ldtentry *ldtentry; struct idtentry *idtentry; uint8_t *stbl; struct dtslot *f; int32_t fsi, stblsize; int32_t n; /* get split page */ sbp = split->bp; sp = FSCK_BT_PAGE(ip, sbp, dtpage_t); /* * allocate the new right page for the split */ pxdlist = split->pxdlist; pxd = &pxdlist->pxd[pxdlist->npxd]; pxdlist->npxd++; rbn = addressPXD(pxd); recon_dnode_assign(rbn, (dtpage_t **) & rbp); /* rbp->b_lblkno = rbn; */ #ifdef _JFS_DEBUG printf("split: ip:0x%08x sbp:0x%08x rbp:0x%08x\n", ip, sbp, rbp); #endif rp = (dtpage_t *) rbp; rp->header.self = *pxd; /* * initialize/update sibling pointers between sp and rp */ nextbn = sp->header.next; rp->header.next = nextbn; rp->header.prev = addressPXD(&sp->header.self); sp->header.next = rbn; /* * initialize new right page */ rp->header.flag = sp->header.flag; /* compute sorted entry table at start of extent data area */ rp->header.nextindex = 0; rp->header.stblindex = 1; n = PSIZE >> L2DTSLOTSIZE; rp->header.maxslot = n; /* in unit of slot */ stblsize = (n + 31) >> L2DTSLOTSIZE; /* init freelist */ fsi = rp->header.stblindex + stblsize; rp->header.freelist = fsi; rp->header.freecnt = rp->header.maxslot - fsi; /* * sequential append at tail: append without split * * If splitting the last page on a level because of appending * a entry to it (skip is maxentry), it's likely that the access is * sequential. Adding an empty page on the side of the level is less * work and can push the fill factor much higher than normal. * If we're wrong it's no big deal, we'll just do the split the right * way next time. * (It may look like it's equally easy to do a similar hack for * reverse sorted data, that is, split the tree left, * but it's not. Be my guest.) */ if (nextbn == 0 && split->index == sp->header.nextindex) { /* * initialize freelist of new right page */ f = &rp->slot[fsi]; for (fsi++; fsi < rp->header.maxslot; f++, fsi++) f->next = fsi; f->next = -1; /* insert entry at the first entry of the new right page */ dtInsertEntry(ip, rp, 0, split->key, split->data); goto out; } /* * non-sequential insert (at possibly middle page) * * update prev pointer of previous right sibling page; */ if (nextbn != 0) { FSCK_BT_GETPAGE(ip, nextbn, bp, dtpage_t, p, rc); if (rc) { recon_dnode_release((dtpage_t *) rbp); return rc; } p->header.prev = rbn; FSCK_BT_PUTPAGE(bp); } /* * split the data between the split and right pages. */ skip = split->index; half = (PSIZE >> L2DTSLOTSIZE) >> 1; /* swag */ left = 0; /* * compute fill factor for split pages * * traces the next entry to move to rp * traces the next entry to stay in sp */ stbl = (uint8_t *) & sp->slot[sp->header.stblindex]; nextindex = sp->header.nextindex; for (nxt = off = 0; nxt < nextindex; ++off) { if (off == skip) /* check for fill factor with new entry size */ n = split->nslot; else { si = stbl[nxt]; switch (sp->header.flag & BT_TYPE) { case BT_LEAF: ldtentry = (struct ldtentry *) &sp->slot[si]; if (DO_INDEX()) n = NDTLEAF(ldtentry->namlen); else n = NDTLEAF_LEGACY(ldtentry->namlen); break; case BT_INTERNAL: idtentry = (struct idtentry *) &sp->slot[si]; n = NDTINTERNAL(idtentry->namlen); break; default: break; } ++nxt; /* advance to next entry to move in sp */ } left += n; if (left >= half) break; } /* poins to the 1st entry to move */ /* * move entries to right page * * dtMoveEntry() initializes rp and reserves entry for insertion */ dtMoveEntry(sp, nxt, rp); sp->header.nextindex = nxt; /* * finalize freelist of new right page */ fsi = rp->header.freelist; f = &rp->slot[fsi]; for (fsi++; fsi < rp->header.maxslot; f++, fsi++) f->next = fsi; f->next = -1; /* * Update directory index table for entries now in right page */ if ((rp->header.flag & BT_LEAF) && DO_INDEX()) { stbl = DT_GETSTBL(rp); for (n = 0; n < rp->header.nextindex; n++) { ldtentry = (struct ldtentry *) &rp->slot[stbl[n]]; modify_index(ip, rbn, n, ldtentry->index); } } /* * the skipped index was on the left page, */ if (skip <= off) { /* insert the new entry in the split page */ dtInsertEntry(ip, sp, skip, split->key, split->data); } else { /* * the skipped index was on the right page, */ /* adjust the skip index to reflect the new position */ skip -= nxt; /* insert the new entry in the right page */ dtInsertEntry(ip, rp, skip, split->key, split->data); } out: *rbpp = rbp; *rpxdp = *pxd; #ifdef _JFS_DEBUG printf("split: ip:0x%08x sbp:0x%08x rbp:0x%08x\n", ip, sbp, rbp); #endif ip->di_nblocks += lengthPXD(pxd); return 0; } /* * dtSplitRoot() * * function: * split the full root page into * original/root/split page and new right page * i.e., root remains fixed in tree anchor (inode) and * the root is copied to a single new right child page * since root page << non-root page, and * the split root page contains a single entry for the * new right child page. * * parameter: * * return: 0 - success; * errno - failure; * return new page pinned; */ static int dtSplitRoot(struct dinode *ip, struct dtsplit *split, struct btpage **rbpp) { dtroot_t *sp; struct btpage *rbp; dtpage_t *rp; int64_t rbn; int32_t xlen; int32_t xsize; struct dtslot *f; int8_t *stbl; int32_t fsi, stblsize, n; struct idtentry *s; pxd_t *ppxd; struct pxdlist *pxdlist; pxd_t *pxd; /* get split root page */ sp = (dtroot_t *) & ip->di_btroot; /* * allocate/initialize a single (right) child page * * N.B. In normal processing, * at first split, a one (or two) block to fit * new entry is allocated; at subsequent split, * a full page is allocated; * During fsck processing, * at first split a full page is allocated. */ pxdlist = split->pxdlist; pxd = &pxdlist->pxd[pxdlist->npxd]; pxdlist->npxd++; rbn = addressPXD(pxd); xlen = lengthPXD(pxd); xsize = xlen << agg_recptr->log2_blksize; recon_dnode_assign(rbn, (dtpage_t **) & rbp); /* rbp->b_lblkno = rbn; */ rp = (dtpage_t *) rbp; rp->header.flag = (sp->header.flag & BT_LEAF) ? BT_LEAF : BT_INTERNAL; rp->header.self = *pxd; /* initialize sibling pointers */ rp->header.next = 0; rp->header.prev = 0; /* * move in-line root page into new right page extent */ n = xsize >> L2DTSLOTSIZE; rp->header.maxslot = n; stblsize = (n + 31) >> L2DTSLOTSIZE; /* copy old stbl to new stbl at start of extended area */ rp->header.stblindex = DTROOTMAXSLOT; stbl = (int8_t *) & rp->slot[DTROOTMAXSLOT]; bcopy(sp->header.stbl, stbl, sp->header.nextindex); rp->header.nextindex = sp->header.nextindex; /* copy old data area to start of new data area */ bcopy(&sp->slot[1], &rp->slot[1], IDATASIZE); /* * append free region of newly extended area at tail of freelist */ /* init free region of newly extended area */ fsi = n = DTROOTMAXSLOT + stblsize; f = &rp->slot[fsi]; for (fsi++; fsi < rp->header.maxslot; f++, fsi++) f->next = fsi; f->next = -1; /* append new free region at tail of old freelist */ fsi = sp->header.freelist; if (fsi == -1) rp->header.freelist = n; else { rp->header.freelist = fsi; do { f = &rp->slot[fsi]; fsi = f->next; } while (fsi != -1); f->next = n; } rp->header.freecnt = sp->header.freecnt + rp->header.maxslot - n; /* * Update directory index table for entries now in right page; */ if ((rp->header.flag & BT_LEAF) && DO_INDEX()) { struct ldtentry *ldtentry; stbl = DT_GETSTBL(rp); for (n = 0; n < rp->header.nextindex; n++) { ldtentry= (struct ldtentry *) &rp->slot[stbl[n]]; modify_index(ip, rbn, n, ldtentry->index); } } /* * insert the new entry into the new right/child page * (skip index in the new right page will not change) */ dtInsertEntry(ip, rp, split->index, split->key, split->data); /* * reset parent/root page * * set the 1st entry offset to 0, which force the left-most key * at any level of the tree to be less than any search key. * * The btree comparison code guarantees that the left-most key on any * level of the tree is never used, so it doesn't need to be filled in. */ /* update page header of root */ if (sp->header.flag & BT_LEAF) { sp->header.flag &= ~BT_LEAF; sp->header.flag |= BT_INTERNAL; } /* init the first entry */ s = (struct idtentry *) &sp->slot[DTENTRYSTART]; ppxd = (pxd_t *) s; *ppxd = *pxd; s->next = -1; s->namlen = 0; stbl = sp->header.stbl; stbl[0] = DTENTRYSTART; sp->header.nextindex = 1; /* init freelist */ fsi = DTENTRYSTART + 1; f = &sp->slot[fsi]; /* init free region of remaining area */ for (fsi++; fsi < DTROOTMAXSLOT; f++, fsi++) f->next = fsi; f->next = -1; sp->header.freelist = DTENTRYSTART + 1; sp->header.freecnt = DTROOTMAXSLOT - (DTENTRYSTART + 1); *rbpp = rbp; ip->di_nblocks += lengthPXD(pxd); return 0; } /* * fsck_dtDelete() * * function: delete the entry(s) referenced by a key. * * parameter: * ip - parent directory * key - entry name; * ino - entry i_number; * * return: */ int fsck_dtDelete(struct dinode *ip, struct component_name *key, uint32_t * ino) { int rc = 0; int64_t bn; struct btpage *bp; dtpage_t *p; int32_t index; struct btstack btstack; /* * search for the entry to delete: * * fsck_dtSearch() returns (leaf page pinned, index at which to delete). */ rc = fsck_dtSearch(ip, key, ino, &btstack, JFS_REMOVE); if (rc) return rc; /* retrieve search result */ BT_GETSEARCH(ip, btstack.top, bn, bp, dtpage_t, p, index); /* * the leaf page becomes empty, delete the page */ if (p->header.nextindex == 1) { /* delete empty page */ rc = fsck_dtDeleteUp(ip, bp, &btstack); } else { /* * the leaf page has other entries remaining: * * delete the entry from the leaf page. */ /* free the leaf entry */ fsck_dtDeleteEntry(p, index); /* * Update directory index table for entries moved in stbl */ if (DO_INDEX() && index < p->header.nextindex) { int i; struct ldtentry *ldtentry; int8_t *stbl; stbl = DT_GETSTBL(p); for (i = index; i < p->header.nextindex; i++) { ldtentry = (struct ldtentry *)&p->slot[stbl[i]]; modify_index(ip, bn, i, ldtentry->index); } } FSCK_BT_PUTPAGE(bp); } return rc; } /* * fsck_dtDeleteUp() * * function: * free empty pages as propagating deletion up the tree * * parameter: * * return: */ static int fsck_dtDeleteUp(struct dinode *ip, struct btpage *fbp, struct btstack *btstack) { int rc = 0; struct btpage *bp; dtpage_t *fp, *p = 0; int32_t index, nextindex; int64_t xaddr; int32_t xlen; struct btframe *parent; /* get page to delete */ fp = FSCK_BT_PAGE(ip, fbp, dtpage_t); /* * keep the root leaf page which has become empty */ if (fp->header.flag & BT_ROOT) { /* * reset the root * * fsck_dtInitRoot() acquires txlock on the root */ fsck_dtInitRoot(ip, ip->di_parent); FSCK_BT_PUTPAGE(fbp); return 0; } /* * free the non-root leaf page */ /* update sibling pointers */ rc = dtRelink(ip, fp); if (rc) return rc; xaddr = addressPXD(&fp->header.self); xlen = lengthPXD(&fp->header.self); ip->di_nblocks -= xlen; /* free backing extent */ fsck_dealloc_fsblks(xlen, xaddr); /* free/invalidate its buffer page */ recon_dnode_release((dtpage_t *) fbp); /* * propagate page deletion up the directory tree * * If the delete from the parent page makes it empty, * continue all the way up the tree. * stop if the root page is reached (which is never deleted) or * if the entry deletion does not empty the page. */ while ((parent = BT_POP(btstack)) != NULL) { /* pin the parent page */ FSCK_BT_GETPAGE(ip, parent->bn, bp, dtpage_t, p, rc); if (rc) return rc; /* * free the extent of the child page deleted */ index = parent->index; /* * delete the entry for the child page from parent */ nextindex = p->header.nextindex; /* * the parent has the single entry being deleted: * * free the parent page which has become empty. */ if (nextindex == 1) { /* * keep the root internal page which has become empty */ if (p->header.flag & BT_ROOT) { /* * reset the root * * fsck_dtInitRoot() acquires txlock on the root */ fsck_dtInitRoot(ip, ip->di_parent); FSCK_BT_PUTPAGE(bp); return 0; } else { /* * free the parent page */ /* update sibling pointers */ rc = dtRelink(ip, p); if (rc) return rc; xaddr = addressPXD(&p->header.self); xlen = lengthPXD(&p->header.self); ip->di_nblocks -= xlen; /* free backing extent */ fsck_dealloc_fsblks(xlen, xaddr); /* free/invalidate its buffer page */ recon_dnode_release((dtpage_t *) bp); /* propagate up */ continue; } } /* * the parent has other entries remaining: * * delete the router entry from the parent page. */ /* free the router entry */ fsck_dtDeleteEntry(p, index); /* unpin the parent page */ FSCK_BT_PUTPAGE(bp); /* exit propagation up */ break; } ip->di_size -= PSIZE; return 0; } /* * dtRelink() * * function: * link around a freed page. * * parameter: * fp: page to be freed * * return: */ static int dtRelink(struct dinode *ip, dtpage_t * p) { int rc; struct btpage *bp; int64_t nextbn, prevbn; nextbn = p->header.next; prevbn = p->header.prev; /* update prev pointer of the next page */ if (nextbn != 0) { FSCK_BT_GETPAGE(ip, nextbn, bp, dtpage_t, p, rc); if (rc) return rc; p->header.prev = prevbn; FSCK_BT_PUTPAGE(bp); } /* update next pointer of the previous page */ if (prevbn != 0) { FSCK_BT_GETPAGE(ip, prevbn, bp, dtpage_t, p, rc); if (rc) return rc; p->header.next = nextbn; FSCK_BT_PUTPAGE(bp); } return 0; } /* * fsck_dtInitRoot() * * initialize directory root (inline in inode) */ void fsck_dtInitRoot(struct dinode *ip, uint32_t idotdot) { dtroot_t *p; int32_t fsi; struct dtslot *f; p = (dtroot_t *) & ip->di_btroot; p->header.flag = DXD_INDEX | BT_ROOT | BT_LEAF; p->header.nextindex = 0; /* init freelist */ fsi = 1; f = &p->slot[fsi]; /* init data area of root */ for (fsi++; fsi < DTROOTMAXSLOT; f++, fsi++) f->next = fsi; f->next = -1; p->header.freelist = 1; p->header.freecnt = 8; /* init '..' entry in btroot */ p->header.idotdot = idotdot; ip->di_size = IDATASIZE; return; } /* * dtCompare() * * function: compare search key with an (leaf/internal) entry * * return: * < 0 if k is < record * = 0 if k is = record * > 0 if k is > record */ static int dtCompare(struct component_name *key, /* search key */ dtpage_t * p, /* directory page */ int32_t si) { /* entry slot index */ int rc; UniChar *kname, *name; int32_t klen, namlen, len; struct ldtentry *lh; struct idtentry *ih; struct dtslot *t; /* * force the left-most key on internal pages, at any level of * the tree, to be less than any search key. * this obviates having to update the leftmost key on an internal * page when the user inserts a new key in the tree smaller than * anything that has been stored. * * (? if/when fsck_dtSearch() narrows down to 1st entry (index = 0), * at any internal page at any level of the tree, * it descends to child of the entry anyway - * ? make the entry as min size dummy entry) * * if (e->index == 0 && h->prevpg == P_INVALID && !(h->flags & BT_LEAF)) * return (1); */ kname = key->name; klen = key->namlen; /* * leaf page entry */ if (p->header.flag & BT_LEAF) { lh = (struct ldtentry *) &p->slot[si]; si = lh->next; name = lh->name; namlen = lh->namlen; if (DO_INDEX()) len = MIN(namlen, DTLHDRDATALEN); else len = MIN(namlen, DTLHDRDATALEN_LEGACY); } else { /* * internal page entry */ ih = (struct idtentry *) &p->slot[si]; si = ih->next; name = ih->name; namlen = ih->namlen; len = MIN(namlen, DTIHDRDATALEN); } /* compare with head/only segment */ len = MIN(klen, len); rc = *kname - *name; if (rc) return rc; rc = UniStrncmp(kname, name, len); if (rc) return rc; klen -= len; namlen -= len; /* compare with additional segment(s) */ kname += len; while (klen > 0 && namlen > 0) { /* compare with next name segment */ t = (struct dtslot *) &p->slot[si]; len = MIN(namlen, DTSLOTDATALEN); len = MIN(klen, len); name = t->name; rc = *kname - *name; if (rc) return rc; rc = UniStrncmp(kname, name, len); if (rc) return rc; klen -= len; namlen -= len; kname += len; si = t->next; } return (klen - namlen); } /* * ciCompare() * * function: compare search key with an (leaf/internal) entry * * return: * < 0 if k is < record * = 0 if k is = record * > 0 if k is > record */ static int ciCompare(struct component_name *key, /* search key */ dtpage_t * p, /* directory page */ int32_t si, /* entry slot index */ int32_t flag) { int rc; UniChar *kname, *name, x; int32_t klen, namlen, len; struct ldtentry *lh; struct idtentry *ih; struct dtslot *t; int32_t i; /* * force the left-most key on internal pages, at any level of * the tree, to be less than any search key. * this obviates having to update the leftmost key on an internal * page when the user inserts a new key in the tree smaller than * anything that has been stored. * * (? if/when fsck_dtSearch() narrows down to 1st entry (index = 0), * at any internal page at any level of the tree, * it descends to child of the entry anyway - * ? make the entry as min size dummy entry) * * if (e->index == 0 && h->prevpg == P_INVALID && !(h->flags & BT_LEAF)) * return (1); */ kname = key->name; klen = key->namlen; /* * leaf page entry */ if (p->header.flag & BT_LEAF) { lh = (struct ldtentry *) &p->slot[si]; si = lh->next; name = lh->name; namlen = lh->namlen; if (DO_INDEX()) len = MIN(namlen, DTLHDRDATALEN); else len = MIN(namlen, DTLHDRDATALEN_LEGACY); } else { /* * internal page entry */ ih = (struct idtentry *) &p->slot[si]; si = ih->next; name = ih->name; namlen = ih->namlen; len = MIN(namlen, DTIHDRDATALEN); } /* compare with head/only segment */ len = MIN(klen, len); for (i = 0; i < len; i++, kname++, name++) { /* uppercase the characer to match */ if ((flag & JFS_OS2) == JFS_OS2) x = UniToupper(*name); /* uppercase the characer to match */ else x = *name; /* leave the character alone */ rc = *kname - x; if (rc) return rc; } klen -= len; namlen -= len; /* compare with additional segment(s) */ while (klen > 0 && namlen > 0) { /* compare with next name segment */ t = (struct dtslot *) &p->slot[si]; len = MIN(namlen, DTSLOTDATALEN); len = MIN(klen, len); name = t->name; for (i = 0; i < len; i++, kname++, name++) { if ((flag & JFS_OS2) == JFS_OS2) x = UniToupper(*name); /* uppercase the characer to match */ else x = *name; /* leave the character alone */ rc = *kname - x; if (rc) return rc; } klen -= len; namlen -= len; si = t->next; } return (klen - namlen); } /* * ciGetLeafPrefixKey() * * function: compute prefix of suffix compression * from two adjacent leaf entries * across page boundary * * return: * Number of prefix bytes needed to distinguish b from a. */ static void ciGetLeafPrefixKey(dtpage_t * lp, /* left page */ int32_t li, /* left entry index */ dtpage_t * rp, /* right page */ int32_t ri, /* right entry index */ struct component_name *key, int32_t flag) { int32_t klen, namlen; UniChar *pl, *pr, *kname; UniChar lname[JFS_NAME_MAX + 1]; struct component_name lkey = { 0, lname }; UniChar rname[JFS_NAME_MAX + 1]; struct component_name rkey = { 0, rname }; /* get left and right key */ dtGetKey(lp, li, &lkey); if ((flag & JFS_OS2) == JFS_OS2) ciToUpper(&lkey); dtGetKey(rp, ri, &rkey); if ((flag & JFS_OS2) == JFS_OS2) ciToUpper(&rkey); /* compute prefix */ klen = 0; kname = key->name; namlen = MIN(lkey.namlen, rkey.namlen); for (pl = lkey.name, pr = rkey.name; namlen; pl++, pr++, namlen--, klen++, kname++) { *kname = *pr; if (*pl != *pr) { key->namlen = klen + 1; return; } } /* l->namlen <= r->namlen since l <= r */ if (lkey.namlen < rkey.namlen) { *kname = *pr; key->namlen = klen + 1; } else /* l->namelen == r->namelen */ key->namlen = klen; return; } /* * dtGetKey() * * function: get key of the entry */ static void dtGetKey(dtpage_t * p, int32_t i, /* entry index */ struct component_name *key) { int32_t si; int8_t *stbl; struct ldtentry *lh; struct idtentry *ih; struct dtslot *t; int32_t namlen, len; UniChar *name, *kname; /* get entry */ stbl = DT_GETSTBL(p); si = stbl[i]; if (p->header.flag & BT_LEAF) { lh = (struct ldtentry *) &p->slot[si]; si = lh->next; namlen = lh->namlen; name = lh->name; if (DO_INDEX()) len = MIN(namlen, DTLHDRDATALEN); else len = MIN(namlen, DTLHDRDATALEN_LEGACY); } else { ih = (struct idtentry *) &p->slot[si]; si = ih->next; namlen = ih->namlen; name = ih->name; len = MIN(namlen, DTIHDRDATALEN); } key->namlen = namlen; kname = key->name; /* * move head/only segment */ UniStrncpy(kname, name, len); /* * bcopy(name, kname, len); */ /* * move additional segment(s) */ while (si >= 0) { /* get next segment */ t = &p->slot[si]; kname += len; namlen -= len; len = MIN(namlen, DTSLOTDATALEN); UniStrncpy(kname, t->name, len); /* * bcopy(t->name, kname, len); */ si = t->next; } } /* * dtInsertEntry() * * function: allocate free slot(s) and * write a leaf/internal entry * * return: entry slot index */ static void dtInsertEntry(struct dinode *ip, dtpage_t * p, /* directory page */ int32_t index, /* new entry index */ struct component_name *key, /* key */ ddata_t * data) { /* data */ struct dtslot *h; struct dtslot *t; struct ldtentry *lh = NULL; struct idtentry *ih = NULL; int32_t hsi, fsi, klen, len, nextindex; UniChar *kname, *name; int8_t *stbl; pxd_t *xd; klen = key->namlen; kname = key->name; /* allocate a free slot */ hsi = fsi = p->header.freelist; h = &p->slot[fsi]; p->header.freelist = h->next; --p->header.freecnt; /* write head/only segment */ if (p->header.flag & BT_LEAF) { lh = (struct ldtentry *) h; lh->next = h->next; lh->inumber = data->leaf.ino; lh->namlen = klen; name = lh->name; if (DO_INDEX()) { len = MIN(klen, DTLHDRDATALEN); lh->index = 0; /* Until we create index properly */ } else len = MIN(klen, DTLHDRDATALEN_LEGACY); } else { ih = (struct idtentry *) h; ih->next = h->next; xd = (pxd_t *) ih; *xd = data->xd; ih->namlen = klen; name = ih->name; len = MIN(klen, DTIHDRDATALEN); } UniStrncpy(name, kname, len); /* * bcopy(kname, name, len); */ /* write additional segment(s) */ t = h; klen -= len; while (klen) { /* get free slot */ fsi = p->header.freelist; t = &p->slot[fsi]; p->header.freelist = t->next; --p->header.freecnt; kname += len; len = MIN(klen, DTSLOTDATALEN); UniStrncpy(t->name, kname, len); /* * bcopy(kname, t->name, len); */ klen -= len; } /* terminate last/only segment */ if (h == t) { /* single segment entry */ if (p->header.flag & BT_LEAF) lh->next = -1; else ih->next = -1; } else /* multi-segment entry */ t->next = -1; /* if insert into middle, shift right succeeding entries in stbl */ stbl = DT_GETSTBL(p); nextindex = p->header.nextindex; if (index < nextindex) { memmove(stbl + index + 1, stbl + index, nextindex - index); /* Fix up directory index table */ if ((p->header.flag & BT_LEAF) && DO_INDEX()) { int i; int64_t bn = 0; if (!(p->header.flag & BT_ROOT)) bn = addressPXD(&p->header.self); for (i = index + 1; i <= nextindex; i++) { lh = (struct ldtentry *) &(p->slot[stbl[i]]); modify_index(ip, bn, i, lh->index); } } } stbl[index] = hsi; /* advance next available entry index of stbl */ ++p->header.nextindex; } /* * dtMoveEntry() * * function: move entries from split/left page to new/right page * * nextindex of dst page and freelist/freecnt of both pages * are updated. */ static void dtMoveEntry(dtpage_t * sp, /* src page */ int32_t si, /* src start entry index to move */ dtpage_t * dp) { /* dst page */ int32_t ssi, next; /* src slot index */ int32_t di; /* dst entry index */ int32_t dsi; /* dst slot index */ int8_t *sstbl, *dstbl; /* sorted entry table */ int32_t snamlen, len; struct ldtentry *slh; struct ldtentry *dlh = NULL; struct idtentry *sih; struct idtentry *dih = NULL; struct dtslot *h; struct dtslot *s; struct dtslot *d; int32_t nd; int32_t sfsi; sstbl = (int8_t *) & sp->slot[sp->header.stblindex]; dstbl = (int8_t *) & dp->slot[dp->header.stblindex]; dsi = dp->header.freelist; /* first (whole page) free slot */ sfsi = sp->header.freelist; /* * move entries */ nd = 0; for (di = 0; si < sp->header.nextindex; si++, di++) { ssi = sstbl[si]; dstbl[di] = dsi; /* * move head/only segment of an entry */ /* get dst slot */ h = d = &dp->slot[dsi]; /* get src slot and move */ s = &sp->slot[ssi]; if (sp->header.flag & BT_LEAF) { /* get source entry */ slh = (struct ldtentry *) s; snamlen = slh->namlen; if (DO_INDEX()) len = MIN(snamlen, DTLHDRDATALEN); else len = MIN(snamlen, DTLHDRDATALEN_LEGACY); dlh = (struct ldtentry *) h; bcopy(slh, dlh, 6 + len * 2); /* * bcopy(slh, dlh, 6 + len); */ next = slh->next; /* update dst head/only segment next field */ dsi++; dlh->next = dsi; } else { sih = (struct idtentry *) s; snamlen = sih->namlen; len = MIN(snamlen, DTIHDRDATALEN); dih = (struct idtentry *) h; bcopy(sih, dih, 10 + len * 2); /* * bcopy(sih, dih, 10 + len); */ next = sih->next; dsi++; dih->next = dsi; } /* free src head/only segment */ s->next = sfsi; s->cnt = 1; sfsi = ssi; nd++; /* * move additional segment(s) of the entry */ snamlen -= len; while ((ssi = next) >= 0) { /* get next source segment */ s = &sp->slot[ssi]; /* get next destination free slot */ d++; len = MIN(snamlen, DTSLOTDATALEN); UniStrncpy(d->name, s->name, len); /* * bcopy(s->name, d->name, len); */ nd++; dsi++; d->next = dsi; /* free source segment */ next = s->next; s->next = sfsi; s->cnt = 1; sfsi = ssi; snamlen -= len; } /* end while */ /* terminate dst last/only segment */ if (h == d) { /* single segment entry */ if (dp->header.flag & BT_LEAF) dlh->next = -1; else dih->next = -1; } else /* multi-segment entry */ d->next = -1; } /* end for */ /* update source header */ sp->header.freelist = sfsi; sp->header.freecnt += nd; /* update destination header */ dp->header.nextindex = di; dp->header.freelist = dsi; dp->header.freecnt -= nd; } /* * fsck_dtDeleteEntry() * * function: free a (leaf/internal) entry * * log freelist header, stbl, and each segment slot of entry * (even though last/only segment next field is modified, * physical image logging requires all segment slots of * the entry logged to avoid applying previous updates * to the same slots) */ static void fsck_dtDeleteEntry(dtpage_t * p, /* directory page */ int32_t fi) { /* free entry index */ int32_t fsi; /* free entry slot index */ int8_t *stbl; struct dtslot *t; int32_t si, freecnt; /* get free entry slot index */ stbl = DT_GETSTBL(p); fsi = stbl[fi]; /* get the head/only segment */ t = &p->slot[fsi]; if (p->header.flag & BT_LEAF) si = ((struct ldtentry *) t)->next; else si = ((struct idtentry *) t)->next; t->next = si; t->cnt = 1; freecnt = 1; /* find the last/only segment */ while (si >= 0) { freecnt++; t = &p->slot[si]; t->cnt = 1; si = t->next; } /* update freelist */ t->next = p->header.freelist; p->header.freelist = fsi; p->header.freecnt += freecnt; /* if delete from middle, * shift left the succedding entries in the stbl */ si = p->header.nextindex; if (fi < si - 1) memmove(&stbl[fi], &stbl[fi + 1], si - fi - 1); p->header.nextindex--; } jfsutils-1.1.15.orig/fsck/fsckdtre.c0000644000000000000000000037600211531746371014206 0ustar /* * Copyright (C) International Business Machines Corp., 2000-2004 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include /* defines and includes common among the fsck.jfs modules */ #include "xfsckint.h" /* * for inline unicode functions */ #include "jfs_byteorder.h" #include "jfs_unicode.h" #include "jfs_filsys.h" #include "devices.h" #include "unicode_to_utf8.h" /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * superblock buffer pointer * * defined in xchkdsk.c */ extern struct superblock *sb_ptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * fsck aggregate info structure pointer * * defined in xchkdsk.c */ extern struct fsck_agg_record *agg_recptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * For directory entry processing * * defined in xchkdsk.c */ extern uint32_t key_len[2]; extern UniChar key[2][JFS_NAME_MAX]; extern UniChar ukey[2][JFS_NAME_MAX]; extern int32_t Uni_Name_len; extern UniChar Uni_Name[JFS_NAME_MAX]; /* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV * * The following are internal to this file * */ #define LEFT_KEY_LOWER -1 #define KEYS_MATCH 0 #define LEFT_KEY_HIGHER 1 struct fsck_Dtree_info { dtroot_t *dtr_ptr; dtpage_t *dtp_ptr; pxd_t *pxd_ptr; int8_t *dtstbl; int16_t last_dtidx; int16_t freelist_first_dtidx; int16_t freelist_count; struct dtslot *slots; int8_t slot_map[DTPAGEMAXSLOT]; int64_t ext_addr; uint32_t ext_length; struct dtreeQelem *this_Qel; struct dtreeQelem *next_Qel; int64_t last_node_addr; int8_t last_level; int8_t leaf_level; int8_t leaf_seen; int16_t max_slotidx; int16_t this_key_idx; int16_t last_key_idx; uint32_t key_len[2]; UniChar key[2][JFS_NAME_MAX]; }; int direntry_get_objnam_node(uint32_t, int8_t *, struct dtslot *, int, int *, UniChar *, int8_t *); int dTree_binsrch_internal_page(struct fsck_Dtree_info *, UniChar *, uint32_t, int8_t, int8_t *, int8_t *, int8_t *, struct fsck_inode_record *); int dTree_binsrch_leaf(struct fsck_Dtree_info *, UniChar *, uint32_t, int8_t, int8_t *, int8_t *, int8_t *, int8_t *, struct fsck_inode_record *); int dTree_key_compare(UniChar *, uint8_t, UniChar *, uint8_t, int *); int dTree_key_compare_leaflvl(UniChar *, uint8_t, UniChar *, uint8_t, int8_t *); int dTree_key_compare_prntchld(struct fsck_Dtree_info *, UniChar *, uint8_t, UniChar *, uint8_t, int8_t *); int dTree_key_compare_samelvl(UniChar *, uint8_t, UniChar *, uint8_t, int8_t *); int dTree_key_extract(struct fsck_Dtree_info *, int, UniChar *, uint32_t *, int8_t, int8_t, struct fsck_inode_record *); int dTree_key_extract_cautiously(struct fsck_Dtree_info *, int, UniChar *, uint32_t *, int8_t, int8_t, struct fsck_inode_record *); int dTree_key_extract_record(struct fsck_Dtree_info *, int, UniChar *, uint32_t *, int8_t, int8_t, struct fsck_inode_record *); int dTree_key_to_upper(UniChar *, UniChar *, int32_t); int dTree_node_first_key(struct fsck_Dtree_info *, struct fsck_inode_record *, struct fsck_ino_msg_info *, int); int dTree_node_first_in_level(struct fsck_Dtree_info *, struct fsck_inode_record *, struct fsck_ino_msg_info *, int); int dTree_node_last_in_level(struct fsck_Dtree_info *, struct fsck_inode_record *, struct fsck_ino_msg_info *, int); int dTree_node_not_first_in_level(struct fsck_Dtree_info *, struct fsck_inode_record *, struct fsck_ino_msg_info *, int); int dTree_node_not_last_in_level(struct fsck_Dtree_info *, struct fsck_inode_record *, struct fsck_ino_msg_info *, int); int dTree_node_size_check(struct fsck_Dtree_info *, int8_t, int8_t, int8_t, struct fsck_inode_record *, struct fsck_ino_msg_info *, int); int dTree_process_internal_slots(struct fsck_Dtree_info *, struct fsck_inode_record *, struct fsck_ino_msg_info *, int); int dTree_process_leaf_slots(struct fsck_Dtree_info *, struct fsck_inode_record *, struct dinode *, struct fsck_ino_msg_info *, int); int dTree_verify_slot_freelist(struct fsck_Dtree_info *, struct fsck_inode_record *, struct fsck_ino_msg_info *, int); int process_valid_dir_node(int8_t *, struct dtslot *, int, struct fsck_inode_record *, struct fsck_ino_msg_info *, int); /* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV */ /***************************************************************************** * NAME: direntry_add * * FUNCTION: Add an entry to a directory. * * PARAMETERS: * parent_inoptr - input - pointer to the directory inode, in an * fsck buffer, to which the entry should * be added. * child_inonum - input - inode number to put in the new directory * entry. * child_name - input - pointer to the file name to put in the * new directory entry. * * RETURNS: * success: FSCK_OK * failure: something else */ int direntry_add(struct dinode *parent_inoptr, uint32_t child_inonum, UniChar * child_name) { int ad_rc = FSCK_OK; struct component_name uniname_struct; uniname_struct.namlen = UniStrlen(child_name); uniname_struct.name = child_name; ad_rc = fsck_dtInsert(parent_inoptr, &uniname_struct, &child_inonum); if (ad_rc == FSCK_OK) { ad_rc = inode_put(parent_inoptr); } else { if (ad_rc < 0) { fsck_send_msg(fsck_INTERNALERROR, FSCK_INTERNAL_ERROR_60, ad_rc, child_inonum, parent_inoptr->di_number); ad_rc = FSCK_INTERNAL_ERROR_60; } else { if (ad_rc == FSCK_BLKSNOTAVAILABLE) { fsck_send_msg(fsck_CANTRECONINSUFSTG, 3); } } } return (ad_rc); } /***************************************************************************** * NAME: direntry_get_inonum * * FUNCTION: Get the inode number for the file whose name is given. * * PARAMETERS: * parent_inonum - input - the inode number of a directory containing * an entry for the inode whose name is * desired. * obj_name_length - input - the length of the file name in mixed case * obj_name - input - pointer to the file name in mixed case * obj_NAME_length - input - the length of the file name in upper case * obj_NAME - input - pointer to the file name in upper case * found_inonum - input - pointer to a variable in which to return * the inode number stored in the (found) entry * * NOTES: A case insensitive search is conducted. * * RETURNS: * success: FSCK_OK * failure: something else */ int direntry_get_inonum(uint32_t parent_inonum, int obj_name_length, UniChar * obj_name, int obj_NAME_length, UniChar * obj_NAME, uint32_t * found_inonum) { int gdi_rc = FSCK_OK; struct dinode *root_inoptr; int is_aggregate = 0; int alloc_ifnull = 0; int which_table = FILESYSTEM_I; struct dtslot *slot_ptr; int8_t entry_found; struct fsck_inode_record *root_inorecptr; gdi_rc = inode_get(is_aggregate, which_table, ROOT_I, &root_inoptr); if (gdi_rc == FSCK_OK) { /* got the root inode */ gdi_rc = get_inorecptr(is_aggregate, alloc_ifnull, ROOT_I, &root_inorecptr); if ((gdi_rc == FSCK_OK) && (root_inorecptr == NULL)) { gdi_rc = FSCK_INTERNAL_ERROR_46; } else if (gdi_rc == FSCK_OK) { gdi_rc = dTree_search(root_inoptr, obj_name, obj_name_length, obj_NAME, obj_NAME_length, &slot_ptr, &entry_found, root_inorecptr); } if ((gdi_rc == FSCK_OK) && (entry_found)) { *found_inonum = ((struct ldtentry *) slot_ptr)->inumber; } } return (gdi_rc); } /***************************************************************************** * NAME: direntry_get_objnam * * FUNCTION: Find the file name for the given inode number in the given * directory inode. * * PARAMETERS: * parent_inonum - input - the inode number of the directory * containing an entry for the object * obj_inonum - input - the inode number of the object for * which the file name is desired * found_name_length - input - pointer to a variable in which to return * the length of the object name * found_name - input - pointer to a buffer in which to return * the object name * * RETURNS: * success: FSCK_OK * failure: something else */ int direntry_get_objnam(uint32_t parent_inonum, uint32_t obj_inonum, int *found_name_length, UniChar * found_name) { int dgon_rc = FSCK_OK; int is_aggregate = 0; int which_it = FILESYSTEM_I; /* in release 1 there's exactly 1 fileset */ uint32_t parent_inoidx; struct dinode *parent_inoptr; dtpage_t *leaf_ptr; int64_t leaf_offset; int8_t dir_inline; int8_t dir_rootleaf; dtroot_t *dtroot_ptr; int8_t *dtstbl; struct dtslot *slots; int last_dtidx; int8_t entry_found; /* assume no match will be found */ *found_name_length = 0; parent_inoidx = (uint32_t) parent_inonum; dgon_rc = inode_get(is_aggregate, which_it, parent_inoidx, &parent_inoptr); if (dgon_rc != FSCK_OK) { /* but we read it before! */ /* this is fatal */ dgon_rc = FSCK_FAILED_CANTREAD_DIRNOW; } else { /* got the parent inode */ dgon_rc = find_first_dir_leaf(parent_inoptr, &leaf_ptr, &leaf_offset, &dir_inline, &dir_rootleaf); if (dgon_rc != FSCK_OK) { /* we already verified the dir! */ dgon_rc = FSCK_FAILED_DIRGONEBAD; } else { /* we found and read the first leaf */ if (dir_rootleaf) { /* rootleaf directory tree */ dtroot_ptr = (dtroot_t *) & (parent_inoptr->di_btroot); dtstbl = (int8_t *) & (dtroot_ptr->header.stbl[0]); slots = &(dtroot_ptr->slot[0]); last_dtidx = dtroot_ptr->header.nextindex - 1; dgon_rc = direntry_get_objnam_node(obj_inonum, dtstbl, slots, last_dtidx, found_name_length, found_name, &entry_found); } else { /* it's a separate node and probably first in a chain */ /* try the first leaf */ dtstbl = (int8_t *) & (leaf_ptr-> slot[leaf_ptr->header. stblindex]); slots = &(leaf_ptr->slot[0]); last_dtidx = leaf_ptr->header.nextindex - 1; dgon_rc = direntry_get_objnam_node(obj_inonum, dtstbl, slots, last_dtidx, found_name_length, found_name, &entry_found); /* try the remaining leaves */ while ((dgon_rc == FSCK_OK) && (!entry_found) && (leaf_ptr->header.next != 0)) { dgon_rc = dnode_get(leaf_ptr->header.next, BYTESPERPAGE, &leaf_ptr); if (dgon_rc != FSCK_OK) { /* this is fatal */ dgon_rc = FSCK_FAILED_READ_NODE4; } else { /* got the sibling leaf node */ dtstbl = (int8_t *) & (leaf_ptr-> slot [leaf_ptr-> header. stblindex]); slots = &(leaf_ptr->slot[0]); last_dtidx = leaf_ptr->header.nextindex - 1; dgon_rc = direntry_get_objnam_node (obj_inonum, dtstbl, slots, last_dtidx, found_name_length, found_name, &entry_found); } } } } } if ((dgon_rc == FSCK_OK) && (!entry_found)) { /* * but we saw this entry earlier! */ dgon_rc = FSCK_FAILED_DIRENTRYGONE; } return (dgon_rc); } /***************************************************************************** * NAME: direntry_get_objnam_node * * FUNCTION: Find the file name, in the given directory leaf node, of the * object whose inode number is given. * * PARAMETERS: * child_inonum - input - the inode number in the directory entry * dtstbl - input - pointer to the sorted entry index table * in the directory node * slots - input - pointer to slot[0] in the directory node * last_dtidx - input - last valid entry in the directory * node's sorted entry index table * found_name_length - input - pointer to a variable in which to return * the length of the filename being returned * in *found_name * found_name - input - pointer to a buffer in which to return * the filename extracted from the node * entry_found - input - pointer to a variable in which to return * !0 if an entry is found with inode number * child_inonum * 0 if no entry is found with inode number * child_inonum * * RETURNS: * success: FSCK_OK * failure: something else */ int direntry_get_objnam_node(uint32_t child_inonum, int8_t * dtstbl, struct dtslot *slots, int last_dtidx, int *found_name_length, UniChar * found_name, int8_t * entry_found) { int dgonn_rc = FSCK_OK; int dtidx; struct ldtentry *entry_ptr = NULL; struct dtslot *contin_entry_ptr; int seg_length, UniChars_left, seg_max; if (sb_ptr->s_flag & JFS_DIR_INDEX) seg_max = DTLHDRDATALEN; else seg_max = DTLHDRDATALEN_LEGACY; /* assume it's not here */ *entry_found = 0; /* * see if this leaf has the entry for the requested child */ for (dtidx = 0; ((dgonn_rc == FSCK_OK) && (dtidx <= last_dtidx) && (!(*entry_found))); dtidx++) { /* for each entry in the dtstbl index to slots */ entry_ptr = (struct ldtentry *) &(slots[dtstbl[dtidx]]); if (entry_ptr->inumber == child_inonum) { *entry_found = -1; } } /* * if the child's entry was found, construct its name */ if (*entry_found) { /* the child's entry was found */ UniChars_left = entry_ptr->namlen; if (UniChars_left > seg_max) { seg_length = seg_max; UniChars_left -= seg_max; } else { seg_length = UniChars_left; UniChars_left = 0; } memcpy((void *) &(found_name[*found_name_length]), (void *) &(entry_ptr->name[0]), (size_t) (seg_length * sizeof (UniChar)) ); *found_name_length = seg_length; if (entry_ptr->next != -1) { /* name is continued */ contin_entry_ptr = (struct dtslot *) &(slots[entry_ptr->next]); } else { contin_entry_ptr = NULL; } seg_max = DTSLOTDATALEN; while ((contin_entry_ptr != NULL) && ((*found_name_length) <= JFS_NAME_MAX)) { /* name is continued */ if (UniChars_left > seg_max) { seg_length = seg_max; UniChars_left -= seg_max; } else { seg_length = UniChars_left; UniChars_left = 0; } memcpy((void *) &(found_name[*found_name_length]), (void *) &(contin_entry_ptr->name[0]), (size_t) (seg_length * sizeof (UniChar)) ); *found_name_length += seg_length; if (contin_entry_ptr->next != -1) { /* still more */ contin_entry_ptr = (struct dtslot *) &(slots[contin_entry_ptr->next]); } else { contin_entry_ptr = NULL; } } if (contin_entry_ptr != NULL) { dgonn_rc = FSCK_FAILED_DIRGONEBAD2; } } return (dgonn_rc); } /***************************************************************************** * NAME: direntry_remove * * FUNCTION: Issue an fsck message, depending on the message's protocol * according to the fsck message arrays (above). Log the * message to fscklog if logging is in effect. * * PARAMETERS: * parent_inoptr - input - pointer to the directory inode in an fsck * buffer * child_inonum - input - the inode number in the directory entry * * RETURNS: * success: FSCK_OK * failure: something else */ int direntry_remove(struct dinode *parent_inoptr, uint32_t child_inonum) { int rd_rc = FSCK_OK; UniChar uniname[JFS_NAME_MAX]; int uniname_length; struct component_name uniname_struct; rd_rc = direntry_get_objnam(parent_inoptr->di_number, child_inonum, &uniname_length, &(uniname[0])); if (rd_rc == FSCK_OK) { uniname_struct.namlen = uniname_length; uniname_struct.name = &(uniname[0]); rd_rc = fsck_dtDelete(parent_inoptr, &uniname_struct, &child_inonum); if (rd_rc == FSCK_OK) { rd_rc = inode_put(parent_inoptr); } else { fsck_send_msg(fsck_INTERNALERROR, FSCK_INTERNAL_ERROR_61, rd_rc, child_inonum, parent_inoptr->di_number); rd_rc = FSCK_INTERNAL_ERROR_61; } } else { fsck_send_msg(fsck_INTERNALERROR, FSCK_INTERNAL_ERROR_62, rd_rc, child_inonum, parent_inoptr->di_number); rd_rc = FSCK_INTERNAL_ERROR_62; } return (rd_rc); } /***************************************************************************** * NAME: dTree_binsrch_internal_page * * FUNCTION: Perform a binary search, on the given dTree internal node, for * the entry which is parent/grandparent/... to the leaf entry * containing the given filename. * * PARAMETERS: * dtiptr - input - pointer to an fsck record describing the * directory tree * given_name - input - pointer to the name to search for * given_name_len - input - number of characters in given_name * is_root - input - !0 => specified node is a B+ Tree root * 0 => specified node is not a B+ Tree root * no_key_match - input - pointer to a variable in which to return * an indication of whether the search has * been completed because it has been * determined that no entry in the directory * matches given_name * !0 if the search should be ended, No * match found * 0 if either the search should continue or * a match has been found * slot_selected - input - pointer to a variable in which to return * an indication of whether the search has * been completed at this level by finding * a match, a prefix match, or reason to * believe we may still find a match. * !0 if a slot has been selected * 0 if either the search should continue or * it has been determined that there is * no match in the directory * selected_slotidx - input - pointer to a variable in which to return * the number n such that slot[n] contains * (or begins) the key which is a match or * a prefix match for given_name * inorecptr - input - pointer to an fsck inode record describing * the inode * * RETURNS: * success: FSCK_OK * failure: something else */ int dTree_binsrch_internal_page(struct fsck_Dtree_info *dtiptr, UniChar * given_name, uint32_t given_name_len, int8_t is_root, int8_t * no_key_match, int8_t * slot_selected, int8_t * selected_slotidx, struct fsck_inode_record *inorecptr) { int dbip_rc = FSCK_OK; UniChar *this_name; uint32_t *this_name_len; int lowidx, mididx, highidx; int prev_idx, next_idx; int8_t is_leaf = 0; int outcome; this_name = &(key[1][0]); this_name_len = &(key_len[1]); *no_key_match = 0; *slot_selected = 0; *selected_slotidx = 0; lowidx = 0; highidx = dtiptr->last_dtidx; dbip_rc = dTree_key_extract(dtiptr, lowidx, this_name, this_name_len, is_root, is_leaf, inorecptr); /* * note that we can proceed with (some) confidence since we never * search a directory until after we've verified it's structure */ if (dbip_rc == FSCK_OK) { dbip_rc = dTree_key_compare(given_name, given_name_len, this_name, (*this_name_len), &outcome); if (outcome == LEFT_KEY_LOWER) { /* given key < 1st in this node */ *no_key_match = -1; } else if (outcome == KEYS_MATCH) { /* given key == 1st in this node */ *slot_selected = -1; *selected_slotidx = dtiptr->dtstbl[lowidx]; } else { /* given key > 1st in this node */ dbip_rc = dTree_key_extract(dtiptr, highidx, this_name, this_name_len, is_root, is_leaf, inorecptr); /* * note that we can proceed with (some) confidence * since we never search a directory until after we've * verified it's structure */ if (dbip_rc == FSCK_OK) { dbip_rc = dTree_key_compare(given_name, given_name_len, this_name, (*this_name_len), &outcome); if (outcome == LEFT_KEY_HIGHER) { /* given key > last in the node */ *slot_selected = -1; *selected_slotidx = dtiptr->dtstbl[highidx]; } else if (outcome == KEYS_MATCH) { *slot_selected = -1; *selected_slotidx = dtiptr->dtstbl[highidx]; } } } } /* * Find the first key equal or, if no exact match exists, find the * last key lower. */ while ((!(*slot_selected)) && (!(*no_key_match)) && (dbip_rc == FSCK_OK)) { /* haven't chosen one but haven't ruled anything out */ mididx = ((highidx - lowidx) >> 1) + lowidx; dbip_rc = dTree_key_extract(dtiptr, mididx, this_name, this_name_len, is_root, is_leaf, inorecptr); /* * note that we can proceed with (some) confidence since we never * search a directory until after we've verified it's structure */ if (dbip_rc == FSCK_OK) { dbip_rc = dTree_key_compare(given_name, given_name_len, this_name, (*this_name_len), &outcome); if (dbip_rc == FSCK_OK) { if (outcome == KEYS_MATCH) { /* given name == mid key */ *slot_selected = -1; *selected_slotidx = dtiptr->dtstbl[mididx]; } else if (outcome == LEFT_KEY_HIGHER) { /* given name > mid key */ next_idx = mididx + 1; dbip_rc = dTree_key_extract(dtiptr, next_idx, this_name, this_name_len, is_root, is_leaf, inorecptr); /* * note that we can proceed with (some) * confidence since we never search a directory * until after we've verified it's structure */ if (dbip_rc == FSCK_OK) { /* got next key */ dbip_rc = dTree_key_compare (given_name, given_name_len, this_name, (*this_name_len), &outcome); if (dbip_rc == FSCK_OK) { if (outcome == LEFT_KEY_LOWER) { /* the next one is higher */ *slot_selected = -1; *selected_slotidx = dtiptr-> dtstbl [mididx]; } else if (outcome == KEYS_MATCH) { /* since we've done the * extract and compare might as well see if * we lucked into a match */ *slot_selected = -1; *selected_slotidx = dtiptr-> dtstbl [next_idx]; } else { /* not on or just before the money */ /* this key is higher than the middle */ lowidx = mididx; } } } } else { /* given name < mid key */ prev_idx = mididx - 1; dbip_rc = dTree_key_extract(dtiptr, prev_idx, this_name, this_name_len, is_root, is_leaf, inorecptr); /* * note that we can proceed with (some) * confidence since we never search a directory * until after we've verified it's structure */ if (dbip_rc == FSCK_OK) { dbip_rc = dTree_key_compare (given_name, given_name_len, this_name, (*this_name_len), &outcome); if (dbip_rc == FSCK_OK) { if (outcome == LEFT_KEY_HIGHER) { /* the prev one is lower */ *slot_selected = -1; *selected_slotidx = dtiptr-> dtstbl [prev_idx]; } else if (outcome == KEYS_MATCH) { /* since we've done the * extract and compare might as well see if * we stumbled onto a match */ *slot_selected = -1; *selected_slotidx = dtiptr-> dtstbl [prev_idx]; } else { /* not on or just after the money */ /* this key is lower than the middle */ highidx = mididx; } } } } } } } return (dbip_rc); } /***************************************************************************** * NAME: dTree_binsrch_leaf * * FUNCTION: Perform a binary search, on the given dTree leaf node, for the * entry (if any) which contains the given filename. * * PARAMETERS: * dtiptr - input - pointer to an fsck record describing the * directory tree * given_name - input - pointer to the name to search for * given_name_len - input - number of characters in given_name * is_root - input - !0 => specified node is a B+ Tree root * 0 => specified node is not a B+ Tree root * no_key_match - input - pointer to a variable in which to return * an indication of whether the search has * been completed because it has been * determined that no entry in the directory * matches given_name * !0 if the search should be ended, No * match found * 0 if either the search should continue or * a match has been found * key_matched - input - pointer to a variable in which to return * !0 if an exact match has been found * 0 if no match has been found * slot_selected - input - pointer to a variable in which to return * an indication of whether the search has * been completed at this level by finding * a match or reason to reason to believe * we may still find a match. * !0 if a slot has been selected * 0 if either the search should continue or * it has been determined that there is * no match in the directory * selected_slotidx - input - pointer to a variable in which to return * the number n such that slot[n] contains * (or begins) the key which is a match for * given_name * inorecptr - input - pointer to an fsck inode record describing * the inode * * RETURNS: * success: FSCK_OK * failure: something else */ int dTree_binsrch_leaf(struct fsck_Dtree_info *dtiptr, UniChar * given_name, uint32_t given_name_len, int8_t is_root, int8_t * no_key_match, int8_t * key_matched, int8_t * slot_selected, int8_t * selected_slotidx, struct fsck_inode_record *inorecptr) { int dbl_rc = FSCK_OK; UniChar *this_name; uint32_t *this_name_len; int lowidx, mididx, highidx; int prev_idx, next_idx; int8_t is_leaf = -1; int outcome; this_name = &(key[1][0]); this_name_len = &(key_len[1]); *no_key_match = 0; *slot_selected = 0; *selected_slotidx = 0; lowidx = 0; highidx = dtiptr->last_dtidx; dbl_rc = dTree_key_extract(dtiptr, lowidx, this_name, this_name_len, is_root, is_leaf, inorecptr); /* * note that we can proceed with (some) confidence since we never * search a directory until after we've verified it's structure */ if (dbl_rc == FSCK_OK) { /* * If this is a case insensitive search, we need to fold the * extracted key to upper case before doing the comparison. * The given key should already be in all upper case. */ dTree_key_to_upper(this_name, &(ukey[0][0]), (*this_name_len)); dbl_rc = dTree_key_compare(given_name, given_name_len, &(ukey[0][0]), (*this_name_len), &outcome); if (outcome == LEFT_KEY_LOWER) { /* given key < 1st in this node */ *no_key_match = -1; } else if (outcome == KEYS_MATCH) { /* given key == 1st in this node */ *no_key_match = 0; *key_matched = -1; *slot_selected = -1; *selected_slotidx = dtiptr->dtstbl[lowidx]; } else { /* given key > 1st in this node */ dbl_rc = dTree_key_extract(dtiptr, highidx, this_name, this_name_len, is_root, is_leaf, inorecptr); /* * note that we can proceed with (some) * confidence since we never search a directory * until after we've verified it's structure */ if (dbl_rc == FSCK_OK) { /* * If this is a case insensitive search, we need to fold the * extracted key to upper case before doing the comparison. * The given key should already be in all upper case. */ dTree_key_to_upper(this_name, &(ukey[0][0]), (*this_name_len)); dbl_rc = dTree_key_compare(given_name, given_name_len, &(ukey[0][0]), (*this_name_len), &outcome); if (outcome == LEFT_KEY_HIGHER) { /* given key > last in the node */ *no_key_match = -1; } else if (outcome == KEYS_MATCH) { *no_key_match = 0; *key_matched = -1; *slot_selected = -1; *selected_slotidx = dtiptr->dtstbl[highidx]; } } } } /* * Try to find a name match */ while ((!(*slot_selected)) && (!(*no_key_match)) && (dbl_rc == FSCK_OK)) { /* * haven't chosen one, haven't seen a match, * but haven't ruled anything out */ mididx = ((highidx - lowidx) >> 1) + lowidx; dbl_rc = dTree_key_extract(dtiptr, mididx, this_name, this_name_len, is_root, is_leaf, inorecptr); /* * note that we can proceed with (some) confidence since we never * search a directory until after we've verified it's structure */ if (dbl_rc == FSCK_OK) { /* * If this is a case insensitive search, we need to fold the * extracted key to upper case before doing the comparison. * The given key should already be in all upper case. */ dTree_key_to_upper(this_name, &(ukey[0][0]), (*this_name_len)); dbl_rc = dTree_key_compare(given_name, given_name_len, &(ukey[0][0]), (*this_name_len), &outcome); if (dbl_rc == FSCK_OK) { if (outcome == KEYS_MATCH) { /* given name == mid key */ *no_key_match = 0; *key_matched = -1; *slot_selected = -1; *selected_slotidx = dtiptr->dtstbl[mididx]; } else if (outcome == LEFT_KEY_HIGHER) { /* given name > mid key */ next_idx = mididx + 1; dbl_rc = dTree_key_extract(dtiptr, next_idx, this_name, this_name_len, is_root, is_leaf, inorecptr); /* * note that we can proceed with (some) * confidence since we never search a directory * until after we've verified it's structure */ if (dbl_rc == FSCK_OK) { /* * If this is a case insensitive search, we need to fold the * extracted key to upper case before doing the comparison. * The given key should already be in all upper case. */ dTree_key_to_upper(this_name, &(ukey[0] [0]), (*this_name_len)); dbl_rc = dTree_key_compare (given_name, given_name_len, &(ukey[0][0]), (*this_name_len), &outcome); if (dbl_rc == FSCK_OK) { if (outcome == LEFT_KEY_LOWER) { /* the next one is higher */ *no_key_match = -1; } else if (outcome == KEYS_MATCH) { /* since we've done the * extract and compare might as well see if * we lucked into a match */ *no_key_match = 0; *key_matched = -1; *slot_selected = -1; *selected_slotidx = dtiptr-> dtstbl [next_idx]; } else { /* not on or just before the money */ /* this key is higher than the middle */ lowidx = mididx; } } /* end nothing untoward */ } } else { /* given name < mid key */ prev_idx = mididx - 1; dbl_rc = dTree_key_extract(dtiptr, prev_idx, this_name, this_name_len, is_root, is_leaf, inorecptr); /* * note that we can proceed with (some) * confidence since we never search a directory * until after we've verified it's structure */ if (dbl_rc == FSCK_OK) { /* * If this is a case insensitive search, we need to fold the * extracted key to upper case before doing the comparison. * The given key should already be in all upper case. */ dTree_key_to_upper(this_name, &(ukey[0] [0]), (*this_name_len)); dbl_rc = dTree_key_compare (given_name, given_name_len, &(ukey[0][0]), (*this_name_len), &outcome); if (dbl_rc == FSCK_OK) { if (outcome == LEFT_KEY_HIGHER) { /* the prev one is lower */ *no_key_match = -1; } else if (outcome == KEYS_MATCH) { /* since we've done the * extract and compare might as well see if * we stumbled onto a match */ *no_key_match = 0; *key_matched = -1; *slot_selected = -1; *selected_slotidx = dtiptr-> dtstbl [prev_idx]; } else { /* not on or just after the money */ /* this key is lower than the middle */ highidx = mididx; } } } } } } } return (dbl_rc); } /***************************************************************************** * NAME: dTree_key_compare * * FUNCTION: Compare the two strings which are given. * * PARAMETERS: * left_key - input - pointer to the first in a pair of keys to * compare * left_key_len - input - number of UniChars in left_key * right_key - input - pointer to the second in a pair of keys to * compare * right_key_len - input - number of UniChars in right_key * keys_relation - input - pointer to a variable in which to return * { LEFT_KEY_LOWER | KEYS_MATCH | LEFT_KEY_HIGHER } * * * RETURNS: * success: FSCK_OK * failure: something else */ int dTree_key_compare(UniChar * left_key, uint8_t left_key_num_unichars, UniChar * right_key, uint8_t right_key_num_unichars, int *keys_relation) { int dkc_rc = FSCK_OK; int outcome; int left_key_len, right_key_len; left_key_len = left_key_num_unichars; right_key_len = right_key_num_unichars; if (right_key_len < left_key_len) { /* right key is shorter */ outcome = UniStrncmp((void *) left_key, (void *) right_key, right_key_len); if (outcome < 0) { /* right key is alphabetically greater */ *keys_relation = LEFT_KEY_LOWER; } else { *keys_relation = LEFT_KEY_HIGHER; } } else if (right_key_len > left_key_len) { /* right key is longer */ outcome = UniStrncmp((void *) left_key, (void *) right_key, left_key_len); if (outcome <= 0) { /* right key is alphabetically greater */ *keys_relation = LEFT_KEY_LOWER; } else { *keys_relation = LEFT_KEY_HIGHER; } } else { /* keys same length */ outcome = UniStrncmp((void *) left_key, (void *) right_key, left_key_len); if (outcome < 0) *keys_relation = LEFT_KEY_LOWER; else if (outcome > 0) *keys_relation = LEFT_KEY_HIGHER; else *keys_relation = KEYS_MATCH; } return (dkc_rc); } /***************************************************************************** * NAME: dTree_key_compare_leaflvl * * FUNCTION: Compare the 2 given strings according to the rules for * sibling entries in a leaf node. * * PARAMETERS: * left_key - input - pointer to the first in a pair of keys to * compare * left_key_len - input - number of UniChars in left_key * right_key - input - pointer to the second in a pair of keys to * compare * right_key_len - input - number of UniChars in right_key * keys_ok - input - pointer to a variable in which to return * !0 if the relation between left_key and * right_key, on the dTree leaf level, * is valid * 0 if the relation between left_key and * right_key, on the dTree leaf level, * is not valid * * RETURNS: * success: FSCK_OK * failure: something else */ int dTree_key_compare_leaflvl(UniChar * left_key, uint8_t left_key_len, UniChar * right_key, uint8_t right_key_len, int8_t * keys_ok) { int dkcl_rc = FSCK_OK; int outcome; /* assume incorrect relation between the keys */ *keys_ok = 0; if (sb_ptr->s_flag & JFS_OS2) { /* case is preserved but ignored */ dkcl_rc = dTree_key_to_upper(left_key, &(ukey[0][0]), (int32_t) left_key_len); if (dkcl_rc == FSCK_OK) { dkcl_rc = dTree_key_to_upper(right_key, &(ukey[1][0]), (int32_t) right_key_len); if (dkcl_rc == FSCK_OK) { dkcl_rc = dTree_key_compare(&(ukey[0][0]), left_key_len, &(ukey[1][0]), right_key_len, &outcome); } } } else { /* case sensitive */ dkcl_rc = dTree_key_compare(left_key, left_key_len, right_key, right_key_len, &outcome); } if (dkcl_rc == FSCK_OK) { if ((outcome == KEYS_MATCH) || (outcome == LEFT_KEY_LOWER)) { /* right key greater */ *keys_ok = -1; } } return (dkcl_rc); } /***************************************************************************** * NAME: dTree_key_compare_prntchld * * FUNCTION: Compare the two given strings according to the rules for * a parent entry key and the first (sorted) entry key in the * node described by the parent entry. * * PARAMETERS: * dtiptr - input - pointer to an fsck record describing the * directory tree * parent_key - input - pointer to the key extracted from the * parent node entry * parent_key_len - input - number of UniChars in parent_key * child_key - input - pointer to the key extracted from the first * (sorted) entry in the child node described * by the entry from which parent_key was * taken * child_key_len - input - number of UniChars in child_key * keys_ok - input - pointer to a variable in which to return * !0 if the relation between parent_key and * child_key, where child_key is the first * key in the child node, is valid * 0 if the relation between parent_key and * child_key, where child_key is the first * key in the child node, is not valid * * RETURNS: * success: FSCK_OK * failure: something else */ int dTree_key_compare_prntchld(struct fsck_Dtree_info *dtiptr, UniChar * parent_key, uint8_t parent_key_len, UniChar * child_key, uint8_t child_key_len, int8_t * keys_ok) { int dnfk_rc = FSCK_OK; int outcome; /* assume incorrect relation between the keys */ *keys_ok = 0; if (dtiptr->leaf_level == dtiptr->this_Qel->node_level) { /* * the child is a leaf so its key is mixed case */ dnfk_rc = dTree_key_to_upper(child_key, &(ukey[0][0]), (int32_t) child_key_len); if (dnfk_rc == FSCK_OK) { dnfk_rc = dTree_key_compare(parent_key, parent_key_len, &(ukey[0][0]), child_key_len, &outcome); } } else { /* the child is not a leaf */ dnfk_rc = dTree_key_compare(parent_key, parent_key_len, child_key, child_key_len, &outcome); } if ((dnfk_rc == FSCK_OK) && ((outcome == KEYS_MATCH) || (outcome == LEFT_KEY_LOWER))) { /* parent is less than or equal to first child */ *keys_ok = -1; } return (dnfk_rc); } /***************************************************************************** * NAME: dTree_key_compare_samelvl * * FUNCTION: Compare the 2 given strings according to the rules for * sibling entries in an internal node. * * PARAMETERS: * left_key - input - pointer to the first in a pair of keys to * compare * left_key_len - input - number of UniChars in left_key * right_key - input - pointer to the second in a pair of keys to * compare * right_key_len - input - number of UniChars in right_key * keys_ok - input - pointer to a variable in which to return * !0 if the relation between left_key and * right_key, on the same dTree level, * is valid * 0 if the relation between left_key and * right_key, on the same dTree level, * is not valid * * RETURNS: * success: FSCK_OK * failure: something else */ int dTree_key_compare_samelvl(UniChar * left_key, uint8_t left_key_len, UniChar * right_key, uint8_t right_key_len, int8_t * keys_ok) { int dkcs_rc = FSCK_OK; int outcome; /* assume incorrect relation between the keys */ *keys_ok = 0; dkcs_rc = dTree_key_compare(left_key, left_key_len, right_key, right_key_len, &outcome); if (dkcs_rc == FSCK_OK) { if (outcome == LEFT_KEY_LOWER) { /* right key greater */ *keys_ok = -1; } } return (dkcs_rc); } /************************************************************************** * NAME: dTree_key_extract * * FUNCTION: Extract the specified directory entry (either internal or * leaf) key and concatenate it's segments (if more than one). * Assume the directory structure has already been validated. * * PARAMETERS: * dtiptr - input - pointer to an fsck record describing the * directory tree * start_dtidx - input - index of the entry in the directory node's * sorted entry index table containing the * slot number of the (first segment of the) * key to extract * key_space - input - pointer to a buffer in which to return * the directory key (a complete filename if * the node is a leaf) extracted * key_length - input - pointer to a variable in which to return * the length of the directory key being returned * in *key_space * is_root - input - !0 => the specified node is a B+ Tree root * 0 => the specified node is not a B+ Tree root * is_leaf - input - !0 => the specified node is a leaf node * 0 => the specified node is not a leaf node * inorecptr - input - pointer to an fsck inode record describing * the inode * * RETURNS: * success: FSCK_OK * failure: something else */ int dTree_key_extract(struct fsck_Dtree_info *dtiptr, int start_dtidx, UniChar * key_space, uint32_t * key_length, int8_t is_root, int8_t is_leaf, struct fsck_inode_record *inorecptr) { int dek_rc = FSCK_OK; int this_slotidx, next_slotidx; struct idtentry *ientry_ptr; struct ldtentry *lentry_ptr; UniChar *name_seg; int seg_length, UniChars_left = 0, seg_max; struct dtslot *contin_entry_ptr; this_slotidx = dtiptr->dtstbl[start_dtidx]; if (is_leaf) { lentry_ptr = (struct ldtentry *) &(dtiptr->slots[this_slotidx]); name_seg = &(lentry_ptr->name[0]); *key_length = lentry_ptr->namlen; next_slotidx = lentry_ptr->next; if (sb_ptr->s_flag & JFS_DIR_INDEX) seg_max = DTLHDRDATALEN; else seg_max = DTLHDRDATALEN_LEGACY; } else { ientry_ptr = (struct idtentry *) &(dtiptr->slots[this_slotidx]); name_seg = &(ientry_ptr->name[0]); *key_length = ientry_ptr->namlen; next_slotidx = ientry_ptr->next; seg_max = DTIHDRDATALEN; } if ((*key_length) > JFS_NAME_MAX) { /* name too long */ inorecptr->ignore_alloc_blks = 1; } else { UniChars_left = *key_length; *key_length = 0; } while ((dek_rc == FSCK_OK) && (this_slotidx != -1) && (!inorecptr->ignore_alloc_blks)) { if ((this_slotidx > dtiptr->max_slotidx) || (this_slotidx < DTENTRYSTART)) { /* idx out of bounds */ inorecptr->ignore_alloc_blks = 1; } else { /* else no reason to think there's a problem */ if (UniChars_left > seg_max) { /* this isn't the last */ seg_length = seg_max; UniChars_left = UniChars_left - seg_max; } else { seg_length = UniChars_left; UniChars_left = 0; } /* copy this section of the name into the buffer */ memcpy((void *) &(key_space[*key_length]), (void *) &(name_seg[0]), (seg_length * sizeof (UniChar)) ); *key_length += seg_length; this_slotidx = next_slotidx; if (next_slotidx != -1) { /* it's not the end of chain marker */ contin_entry_ptr = &(dtiptr->slots[this_slotidx]); name_seg = &(contin_entry_ptr->name[0]); seg_length = contin_entry_ptr->cnt; next_slotidx = contin_entry_ptr->next; seg_max = DTSLOTDATALEN; } } } return (dek_rc); } /***************************************************************************** * NAME: dTree_key_extract_cautiously * * FUNCTION: Extract the specified directory entry (either internal or * leaf) key and concatenate it's segments (if more than one). * Do not assume the directory structure has been validated. * * PARAMETERS: * dtiptr - input - pointer to an fsck record describing the * directory tree * start_dtidx - input - index of the entry in the directory node's * sorted entry index table containing the * slot number of the (first segment of the) * key to extract * key_space - input - pointer to a buffer in which to return * the directory key (a complete filename if * the node is a leaf) extracted * key_length - input - pointer to a variable in which to return * the length of the directory key being returned * in *key_space * is_root - input - !0 => the specified node is a B+ Tree root * 0 => the specified node is not a B+ Tree root * is_leaf - input - !0 => the specified node is a leaf node * 0 => the specified node is not a leaf node * inorecptr - input - pointer to an fsck inode record describing * the inode * * RETURNS: * success: FSCK_OK * failure: something else */ int dTree_key_extract_cautiously(struct fsck_Dtree_info *dtiptr, int start_dtidx, UniChar * key_space, uint32_t * key_length, int8_t is_root, int8_t is_leaf, struct fsck_inode_record *inorecptr) { int deck_rc = FSCK_OK; int8_t temp_slot_map[DTPAGEMAXSLOT]; int this_slotidx, next_slotidx, this_charidx; struct idtentry *ientry_ptr; struct ldtentry *lentry_ptr; UniChar *name_seg; int seg_length, UniChars_left = 0, seg_max; struct dtslot *contin_entry_ptr; memset((void *) &(temp_slot_map[0]), 0, DTPAGEMAXSLOT); this_slotidx = dtiptr->dtstbl[start_dtidx]; if (is_leaf) { lentry_ptr = (struct ldtentry *) &(dtiptr->slots[this_slotidx]); name_seg = &(lentry_ptr->name[0]); *key_length = lentry_ptr->namlen; next_slotidx = lentry_ptr->next; if (sb_ptr->s_flag & JFS_DIR_INDEX) seg_max = DTLHDRDATALEN; else seg_max = DTLHDRDATALEN_LEGACY; } else { ientry_ptr = (struct idtentry *) &(dtiptr->slots[this_slotidx]); name_seg = &(ientry_ptr->name[0]); *key_length = ientry_ptr->namlen; next_slotidx = ientry_ptr->next; seg_max = DTIHDRDATALEN; } if ((*key_length) > JFS_NAME_MAX) { /* name too long */ inorecptr->ignore_alloc_blks = 1; } else { UniChars_left = *key_length; *key_length = 0; } while ((deck_rc == FSCK_OK) && (this_slotidx != -1) && (!inorecptr->ignore_alloc_blks)) { if ((this_slotidx > dtiptr->max_slotidx) || (this_slotidx < DTENTRYSTART) || (temp_slot_map[this_slotidx] != 0)) { /* index is out of bounds OR index was seen earlier this key chain */ /* bad chain */ inorecptr->ignore_alloc_blks = 1; } else { /* else no reason to think there's a problem */ /* mark the slot used */ temp_slot_map[this_slotidx] = -1; if (UniChars_left > seg_max) { /* this isn't the last */ seg_length = seg_max; UniChars_left = UniChars_left - seg_max; } else { seg_length = UniChars_left; UniChars_left = 0; } /* copy this section of the name into the buffer */ memcpy((void *) &(key_space[*key_length]), (void *) &(name_seg[0]), (seg_length * sizeof (UniChar))); *key_length += seg_length; this_slotidx = next_slotidx; if (next_slotidx != -1) { /* it's not the end of chain marker */ if (UniChars_left == 0) /* too many segments */ inorecptr->ignore_alloc_blks = 1; else { contin_entry_ptr = &(dtiptr->slots[this_slotidx]); name_seg = &(contin_entry_ptr->name[0]); seg_length = contin_entry_ptr->cnt; next_slotidx = contin_entry_ptr->next; seg_max = DTSLOTDATALEN; } } } } /* * check for a null character embedded in the name */ this_charidx = 0; while ((deck_rc == FSCK_OK) && (!inorecptr->ignore_alloc_blks) && (this_charidx < *key_length)) { if (((unsigned short *) key_space)[this_charidx] == (unsigned short) NULL) { inorecptr->ignore_alloc_blks = 1; } else { this_charidx++; } } return (deck_rc); } /***************************************************************************** * NAME: dTree_key_extract_record * * FUNCTION: Extract the specified directory entry (either internal or * leaf) key and concatenate it's segments (if more than one). * Directory structure validation is in progress. * * PARAMETERS: * dtiptr - input - pointer to an fsck record describing the * directory tree * start_dtidx - input - index of the entry in the directory node's * sorted entry index table containing the * slot number of the (first segment of the) * key to extract * key_space - input - pointer to a buffer in which to return * the directory key (a complete filename if * the node is a leaf) extracted * key_length - input - pointer to a variable in which to return * the length of the directory key being returned * in *key_space * is_root - input - !0 => the specified node is a B+ Tree root * 0 => the specified node is not a B+ Tree root * is_leaf - input - !0 => the specified node is a leaf node * 0 => the specified node is not a leaf node * inorecptr - input - pointer to an fsck inode record describing * the inode * * RETURNS: * success: FSCK_OK * failure: something else */ int dTree_key_extract_record(struct fsck_Dtree_info *dtiptr, int start_dtidx, UniChar * key_space, uint32_t * key_length, int8_t is_root, int8_t is_leaf, struct fsck_inode_record *inorecptr) { int derk_rc = FSCK_OK; int this_slotidx, next_slotidx, this_charidx; struct idtentry *ientry_ptr; struct ldtentry *lentry_ptr; UniChar *name_seg; int seg_length, UniChars_left = 0, seg_max; struct dtslot *contin_entry_ptr; this_slotidx = dtiptr->dtstbl[start_dtidx]; if (is_leaf) { lentry_ptr = (struct ldtentry *) &(dtiptr->slots[this_slotidx]); name_seg = &(lentry_ptr->name[0]); *key_length = lentry_ptr->namlen; next_slotidx = lentry_ptr->next; if (sb_ptr->s_flag & JFS_DIR_INDEX) seg_max = DTLHDRDATALEN; else seg_max = DTLHDRDATALEN_LEGACY; } else { ientry_ptr = (struct idtentry *) &(dtiptr->slots[this_slotidx]); name_seg = &(ientry_ptr->name[0]); *key_length = ientry_ptr->namlen; next_slotidx = ientry_ptr->next; seg_max = DTIHDRDATALEN; } if ((*key_length) > JFS_NAME_MAX) { /* name too long */ inorecptr->ignore_alloc_blks = 1; } else { UniChars_left = *key_length; *key_length = 0; } while ((derk_rc == FSCK_OK) && (this_slotidx != -1) && (!inorecptr->ignore_alloc_blks)) { if ((this_slotidx > dtiptr->max_slotidx) || (this_slotidx < DTENTRYSTART) || (dtiptr->slot_map[this_slotidx] != 0)) { /* index is out of bounds OR index was seen in a previous key chain */ /* bad chain */ inorecptr->ignore_alloc_blks = 1; } else { /* else no reason to think there's a problem */ /* mark the slot used */ dtiptr->slot_map[this_slotidx] = -1; if (UniChars_left > seg_max) { /* this isn't the last */ seg_length = seg_max; UniChars_left = UniChars_left - seg_max; } else { seg_length = UniChars_left; UniChars_left = 0; } /* copy this section of the name into the buffer */ memcpy((void *) &(key_space[*key_length]), (void *) &(name_seg[0]), (seg_length * sizeof (UniChar))); *key_length += seg_length; this_slotidx = next_slotidx; if (next_slotidx != -1) { /* it's not the end of chain marker */ if (UniChars_left == 0) /* too many segments */ inorecptr->ignore_alloc_blks = 1; else { contin_entry_ptr = &(dtiptr->slots[this_slotidx]); name_seg = &(contin_entry_ptr->name[0]); seg_length = contin_entry_ptr->cnt; next_slotidx = contin_entry_ptr->next; seg_max = DTSLOTDATALEN; } } } } /* * check for a null character embedded in the name */ this_charidx = 0; while ((derk_rc == FSCK_OK) && (!inorecptr->ignore_alloc_blks) && (this_charidx < *key_length)) { if (((unsigned short *) key_space)[this_charidx] == (unsigned short) NULL) { inorecptr->ignore_alloc_blks = 1; } else { this_charidx++; } } return (derk_rc); } /***************************************************************************** * NAME: dTree_key_to_upper * * FUNCTION: Fold the given mixed-case string to upper case. * * PARAMETERS: * given_name - input - pointer to the name which is to be folded to * upper case * name_in_upper - input - pointer to a buffer in which to return the * string which results from folding given_name * to upper case * name_len - input - the number of UniChars in given_name * * RETURNS: * success: FSCK_OK * failure: something else */ int dTree_key_to_upper(UniChar * given_name, UniChar * name_in_upper, int32_t name_len) { int dktu_rc = FSCK_OK; int charidx; for (charidx = 0; (charidx < name_len); charidx++) { if (sb_ptr->s_flag & JFS_OS2) /* only upper case if case-insensitive support is wanted */ name_in_upper[charidx] = UniToupper(given_name[charidx]); else name_in_upper[charidx] = given_name[charidx]; } return (dktu_rc); } /***************************************************************************** * NAME: dTree_node_first_key * * FUNCTION: Assists dTree_processing. * * PARAMETERS: * dtiptr - input - pointer to an fsck record describing the * directory tree * inorecptr - input - pointer to an fsck inode record describing * the inode * msg_info_ptr - input - pointer to data needed to issue messages * about the inode * desired_action - input - { FSCK_RECORD | FSCK_RECORD_DUPCHECK | * FSCK_UNRECORD | FSCK_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */ int dTree_node_first_key(struct fsck_Dtree_info *dtiptr, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr, int desired_action) { int dnfk_rc = FSCK_OK; int8_t keys_ok; dnfk_rc = dTree_key_compare_prntchld(dtiptr, &(dtiptr->this_Qel->node_key[0]), dtiptr->this_Qel->node_key_len, &(dtiptr-> key[dtiptr->this_key_idx][0]), dtiptr->key_len[dtiptr-> this_key_idx], &keys_ok); if (dnfk_rc == FSCK_OK) { if (!keys_ok) { /* invalid key in first slot */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADKEYS, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, 1); } } else { /* 1st slot may be ok */ if (dtiptr->last_level == dtiptr->this_Qel->node_level) { /* * the node is not 1st in its level */ if (dtiptr->leaf_level == dtiptr->this_Qel->node_level) { /* it's a leaf */ dnfk_rc = dTree_key_compare_leaflvl(&(dtiptr-> key [dtiptr-> last_key_idx] [0]), dtiptr-> key_len [dtiptr-> last_key_idx], &(dtiptr-> key [dtiptr-> this_key_idx] [0]), dtiptr-> key_len [dtiptr-> this_key_idx], &keys_ok); } else { /* not a leaf */ dnfk_rc = dTree_key_compare_samelvl(&(dtiptr-> key [dtiptr-> last_key_idx] [0]), dtiptr-> key_len [dtiptr-> last_key_idx], &(dtiptr-> key [dtiptr-> this_key_idx] [0]), dtiptr-> key_len [dtiptr-> this_key_idx], &keys_ok); } if (!keys_ok) { /* keys out of sort order! */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported */ fsck_send_msg(fsck_BADKEYS, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, 2); } } } } } return (dnfk_rc); } /***************************************************************************** * NAME: dTree_node_first_in_level * * FUNCTION: Assists dTree_processing. * * PARAMETERS: * dtiptr - input - pointer to an fsck record describing the * directory tree * inorecptr - input - pointer to an fsck inode record describing * the inode * msg_info_ptr - input - pointer to data needed to issue messages * about the inode * desired_action - input - { FSCK_RECORD | FSCK_RECORD_DUPCHECK | * FSCK_UNRECORD | FSCK_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */ int dTree_node_first_in_level(struct fsck_Dtree_info *dtiptr, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr, int desired_action) { int dnfil_rc = FSCK_OK; if (dtiptr->dtp_ptr->header.prev != 0) { /* bad back pointer! */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported */ fsck_send_msg(fsck_BADBSBLCHN, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } return (dnfil_rc); } /***************************************************************************** * NAME: dTree_node_last_in_level * * FUNCTION: Assists dTree_processing. * * PARAMETERS: * dtiptr - input - pointer to an fsck record describing the * directory tree * inorecptr - input - pointer to an fsck inode record describing * the inode * msg_info_ptr - input - pointer to data needed to issue messages * about the inode * desired_action - input - { FSCK_RECORD | FSCK_RECORD_DUPCHECK | * FSCK_UNRECORD | FSCK_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */ int dTree_node_last_in_level(struct fsck_Dtree_info *dtiptr, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr, int desired_action) { int dnlil_rc = FSCK_OK; if (dtiptr->dtp_ptr->header.next != 0) { /* bad forward pointer! */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported */ fsck_send_msg(fsck_BADFSBLCHN, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } return (dnlil_rc); } /***************************************************************************** * NAME: dTree_node_not_first_in_level * * FUNCTION: Assists dTree_processing. * * PARAMETERS: * dtiptr - input - pointer to an fsck record describing the * directory tree * inorecptr - input - pointer to an fsck inode record describing * the inode * msg_info_ptr - input - pointer to data needed to issue messages * about the inode * desired_action - input - { FSCK_RECORD | FSCK_RECORD_DUPCHECK | * FSCK_UNRECORD | FSCK_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */ int dTree_node_not_first_in_level(struct fsck_Dtree_info *dtiptr, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr, int desired_action) { int dnnfil_rc = FSCK_OK; if (dtiptr->dtp_ptr->header.prev != dtiptr->last_node_addr) { /* bad back pointer! */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported */ fsck_send_msg(fsck_BADBSBLCHN, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } return (dnnfil_rc); } /***************************************************************************** * NAME: dTree_node_not_last_in_level * * FUNCTION: Assists dTree_processing. * * PARAMETERS: * dtiptr - input - pointer to an fsck record describing the * directory tree * inorecptr - input - pointer to an fsck inode record describing * the inode * msg_info_ptr - input - pointer to data needed to issue messages * about the inode * desired_action - input - { FSCK_RECORD | FSCK_RECORD_DUPCHECK | * FSCK_UNRECORD | FSCK_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */ int dTree_node_not_last_in_level(struct fsck_Dtree_info *dtiptr, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr, int desired_action) { int dnnlil_rc = FSCK_OK; int8_t is_leaf = 0; int8_t is_root = 0; /* it can't be the root */ if (dtiptr->dtp_ptr->header.next != dtiptr->next_Qel->node_addr) { /* bad forward pointer! */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported */ fsck_send_msg(fsck_BADFSBLCHN, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } else { /* forward pointer looks fine */ if (dtiptr->leaf_level == dtiptr->this_Qel->node_level) { /* it's a leaf */ is_leaf = -1; } dnnlil_rc = dTree_key_extract_cautiously(dtiptr, dtiptr->last_dtidx, &(dtiptr-> key[dtiptr-> last_key_idx][0]), &(dtiptr-> key_len[dtiptr-> last_key_idx]), is_root, is_leaf, inorecptr); /* * get the last key in the directory. Since this is the first * time we've extracted it, we need to guard against a loop * even though we aren't recording it now. */ if ((dnnlil_rc == FSCK_OK) && (inorecptr->ignore_alloc_blks)) { /* no mishaps but the tree is bad */ if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADKEYS, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, 13); } } } return (dnnlil_rc); } /************************************************************************** * NAME: dTree_node_size_check * * FUNCTION: Validate the size of the given dTree node. * * PARAMETERS: * dtiptr - input - pointer to an fsck record describing the * directory tree * is_leaf - input - !0 => the node is a leaf node * 0 => the node is an internal node * first_in_level - input - !0 => the node is the leftmost in its level * 0 => the node is not leftmost in its level * last_in_level - input - !0 => the node is the rightmost in its level * 0 => the node is not rightmost in its level * inorecptr - input - pointer to an fsck inode record describing * the inode * msg_info_ptr - input - pointer to data needed to issue messages * about the inode * desired_action - input - { FSCK_RECORD | FSCK_RECORD_DUPCHECK | * FSCK_UNRECORD | FSCK_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */ int dTree_node_size_check(struct fsck_Dtree_info *dtiptr, int8_t is_leaf, int8_t first_in_level, int8_t last_in_level, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr, int desired_action) { int dnsc_rc = FSCK_OK; uint32_t ext_length; uint32_t acceptable_size; uint8_t total_slots; ext_length = dtiptr->this_Qel->node_size * sb_ptr->s_bsize; total_slots = dtiptr->dtp_ptr->header.maxslot; if (ext_length == BYTESPERPAGE) { /* it is exactly 1 page long */ if (total_slots != (BYTESPERPAGE / DTSLOTSIZE)) { /* but max slots doesn't work out right */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported */ fsck_send_msg(fsck_BADDINONODESIZ, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } } else { /* it isn't exactly 1 page long */ /* * the only valid directory node which can have a length * different from 1 page is the node which is the only * non-root node in the tree */ if ((!is_leaf) || (!(dtiptr->this_Qel->node_level == 1)) || (!first_in_level) || (!last_in_level)) { /* this node does not qualify */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported */ fsck_send_msg(fsck_BADDINOODDNODESIZ, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } else { /* it might be ok */ /* start at fs blocksize */ acceptable_size = sb_ptr->s_bsize; while ((acceptable_size < BYTESPERPAGE) && (ext_length != acceptable_size)) { /* double it */ acceptable_size = acceptable_size << 1; } if (ext_length != acceptable_size) { /* invalid size */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported */ fsck_send_msg(fsck_BADDINOODDNODESIZ, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } else { /* the size is ok */ if (total_slots != (ext_length / DTSLOTSIZE)) { /* but max slots doesn't work out right */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported */ fsck_send_msg (fsck_BADDINONODESIZ, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } } } } return (dnsc_rc); } /***************************************************************************** * NAME: dTree_process_internal_slots * * FUNCTION: Perform the specified action on the slots in the specified * dTree internal node. * * PARAMETERS: * dtiptr - input - pointer to an fsck record describing the * directory tree * inorecptr - input - pointer to an fsck inode record describing * the inode * msg_info_ptr - input - pointer to data needed to issue messages * about the inode * desired_action - input - { FSCK_RECORD | FSCK_RECORD_DUPCHECK | * FSCK_UNRECORD | FSCK_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */ int dTree_process_internal_slots(struct fsck_Dtree_info *dtiptr, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr, int desired_action) { int dpis_rc = FSCK_OK; int8_t this_key, last_key; int dtidx; struct dtreeQelem *new_Qelptr; uint32_t ext_length, adjusted_length; int64_t ext_addr; int8_t ext_ok, key_ok; int8_t first_entry = -1; int8_t is_EA = 0; int8_t is_ACL = 0; int8_t is_leaf = 0; int8_t is_root = 0; struct idtentry *idtptr; if (dtiptr->this_Qel->node_level == 0) { is_root = -1; } this_key = 0; last_key = 1; key_len[this_key] = 0; key_len[last_key] = 0; for (dtidx = 0; ((dpis_rc == FSCK_OK) && (!inorecptr->ignore_alloc_blks) && (dtidx <= dtiptr->last_dtidx)); dtidx++) { dpis_rc = dTree_key_extract_record(dtiptr, dtidx, &(key[this_key][0]), &(key_len[this_key]), is_root, is_leaf, inorecptr); if (dpis_rc == FSCK_OK) { if (inorecptr->ignore_alloc_blks) { /* but the tree is bad */ if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADKEYS, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, 14); } } else { /* got the key value */ /* * the key for the first entry is verified elsewhere */ if (first_entry) { first_entry = 0; } else { /* it's not the first entry on the page */ dpis_rc = dTree_key_compare_samelvl(& (key [last_key] [0]), key_len[last_key], &(key[this_key] [0]), key_len[this_key], &key_ok); if (dpis_rc == FSCK_OK) { if (!key_ok) { /* but the key is bad */ inorecptr-> ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg (fsck_BADKEYS, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, 3); } } } } } } if ((dpis_rc == FSCK_OK) && (!inorecptr->ignore_alloc_blks)) { /* the key is good */ idtptr = (struct idtentry *) &(dtiptr-> slots[dtiptr->dtstbl[dtidx]]); ext_addr = addressPXD(&(idtptr->xd)); ext_length = lengthPXD(&(idtptr->xd)); dpis_rc = process_extent(inorecptr, ext_length, ext_addr, is_EA, is_ACL, msg_info_ptr, &adjusted_length, &ext_ok, desired_action); if ((dpis_rc == FSCK_OK) && (ext_ok)) { if ((desired_action == FSCK_RECORD) || (desired_action == FSCK_RECORD_DUPCHECK)) { agg_recptr->blocks_this_fset += adjusted_length; agg_recptr->this_inode.all_blks += adjusted_length; if (!(sb_ptr->s_flag & JFS_DIR_INDEX)) agg_recptr->this_inode.data_size += adjusted_length * sb_ptr->s_bsize; } else if (desired_action == FSCK_UNRECORD) { agg_recptr->blocks_this_fset -= adjusted_length; agg_recptr->this_inode.all_blks -= adjusted_length; } dpis_rc = dtreeQ_get_elem(&new_Qelptr); if (dpis_rc == FSCK_OK) { /* got a Queue element */ new_Qelptr->node_pxd = idtptr->xd; new_Qelptr->node_addr = ext_addr; new_Qelptr->node_level = dtiptr->this_Qel->node_level + 1; new_Qelptr->node_size = ext_length; new_Qelptr->node_key_len = key_len[this_key]; memcpy((void *) &(new_Qelptr->node_key[0]), (void *) &(key[this_key][0]), key_len[this_key] * sizeof (UniChar)); dpis_rc = dtreeQ_enqueue(new_Qelptr); if (this_key) { /* this_key == 1 */ this_key = 0; last_key = 1; } else { /* this_key == 0 */ this_key = 1; last_key = 0; } key_len[this_key] = 0; } } } } return (dpis_rc); } /***************************************************************************** * NAME: dTree_process_leaf_slots * * FUNCTION: Perform the specified action on the slots in the specified * dTree leaf node. * * PARAMETERS: * dtiptr - input - pointer to an fsck record describing the * directory tree * inorecptr - input - pointer to an fsck inode record describing * the inode * inoptr - input - the dinode of the directory inode * msg_info_ptr - input - pointer to data needed to issue messages * about the inode * desired_action - input - { FSCK_RECORD | FSCK_RECORD_DUPCHECK | * FSCK_UNRECORD | FSCK_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */ int dTree_process_leaf_slots(struct fsck_Dtree_info *dtiptr, struct fsck_inode_record *inorecptr, struct dinode *inoptr, struct fsck_ino_msg_info *msg_info_ptr, int desired_action) { int dpls_rc = FSCK_OK; int8_t this_key, last_key; int dtidx; int8_t key_ok; int8_t is_leaf = -1; int8_t is_root = 0; int8_t first_entry = -1; struct ldtentry *ldtptr; uint32_t child_inoidx; struct fsck_inode_record *child_inorecptr; struct fsck_inode_ext_record *this_ext; int is_aggregate = 0; int alloc_ifnull = -1; int NumChars = 0; char message_parm[MAXPARMLEN]; int inonum = inoptr->di_number; if (dtiptr->this_Qel->node_level == 0) { is_root = -1; } this_key = 0; last_key = 1; key_len[this_key] = 0; key_len[last_key] = 0; for (dtidx = 0; (dtidx <= dtiptr->last_dtidx); dtidx++) { dpls_rc = dTree_key_extract_record(dtiptr, dtidx, &(key[this_key][0]), &(key_len[this_key]), is_root, is_leaf, inorecptr); if (dpls_rc != FSCK_OK) break; if (inorecptr->ignore_alloc_blks) { /* but the tree is bad */ if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADKEYS, fsck_ref_msg(msg_info_ptr-> msg_inotyp), fsck_ref_msg(msg_info_ptr-> msg_inopfx), msg_info_ptr->msg_inonum, 15); } break; } /* got the key value */ /* * the key for the first entry is verified elsewhere */ if (first_entry) first_entry = 0; else { /* it's not the first entry on the page */ dpls_rc = dTree_key_compare_leaflvl(&(key[last_key][0]), key_len[last_key], &(key[this_key][0]), key_len[this_key], &key_ok); if (dpls_rc != FSCK_OK) break; if (!key_ok) { /* but the key is bad */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADKEYS, fsck_ref_msg (msg_info_ptr-> msg_inotyp), fsck_ref_msg (msg_info_ptr-> msg_inopfx), msg_info_ptr->msg_inonum, 4); } break; } } /* the key is good */ if (this_key) { this_key = 0; last_key = 1; } else { this_key = 1; last_key = 0; } key_len[this_key] = 0; /* * If the desired action is anything besides RECORD_DUPCHECK * then we're really only interested in things that indicate * a bad B+ tree. Since bad inode references in the directory * entries don't imply anything about the tree itself, we only * want to check them if we're doing RECORD_DUPCHECK. */ if (desired_action != FSCK_RECORD_DUPCHECK) continue; /* the inode references haven't been checked yet */ ldtptr = (struct ldtentry *)&(dtiptr->slots[dtiptr->dtstbl[dtidx]]); child_inoidx = (uint32_t) ldtptr->inumber; if (child_inoidx >= agg_recptr->fset_inode_count) { /* it can't be right because it's out of range */ dpls_rc = get_inode_extension(&this_ext); if (dpls_rc != FSCK_OK) break; this_ext->ext_type = rmv_badentry_extension; this_ext->inonum = ldtptr->inumber; this_ext->next = inorecptr->ext_rec; inorecptr->ext_rec = this_ext; inorecptr->adj_entries = 1; key[this_key][key_len[last_key]] = '\0'; #ifdef ORIGINAL if (jfs_strfromUCS(message_parm, key[last_key], MAXPARMLEN, uconv_object) != ULS_SUCCESS) message_parm = "(Conversion Failed)"; #else NumChars = Unicode_String_to_UTF8_String( (uint8_t *)message_parm, key[last_key], MAXPARMLEN); message_parm[NumChars] = '\0'; #endif fsck_send_msg(fsck_BADINOREF, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, message_parm, " ", child_inoidx); } else if (child_inoidx < FILESET_OBJECT_I) { /* * it can't be right because it's in the range * reserved for special metadata and the root dir */ dpls_rc = get_inode_extension(&this_ext); if (dpls_rc != FSCK_OK) break; this_ext->ext_type = rmv_badentry_extension; this_ext->inonum = ldtptr->inumber; this_ext->next = inorecptr->ext_rec; inorecptr->ext_rec = this_ext; inorecptr->adj_entries = 1; key[this_key][key_len[last_key]] = '\0'; NumChars = Unicode_String_to_UTF8_String( (uint8_t *)message_parm, key[last_key], MAXPARMLEN); message_parm[NumChars] = '\0'; fsck_send_msg(fsck_ILLINOREF, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, message_parm, " ", child_inoidx); } else { /* it might be ok */ dpls_rc = get_inorecptr(is_aggregate, alloc_ifnull, child_inoidx, &child_inorecptr); if (dpls_rc != FSCK_OK) break; /* got a record for the child */ child_inorecptr->link_count += 1; if (child_inorecptr->parent_inonum == 0) { /* no parent recorded yet */ child_inorecptr->parent_inonum = inonum; } else { /* this is not the first parent seen */ dpls_rc = get_inode_extension(&this_ext); if (dpls_rc != FSCK_OK) break; /* got extension */ this_ext->ext_type = parent_extension; this_ext->inonum = inonum; this_ext->next = child_inorecptr->ext_rec; child_inorecptr->ext_rec = this_ext; } verify_dir_index(inorecptr, inoptr, dtiptr->this_Qel, dtidx, ldtptr->index); } } return (dpls_rc); } /***************************************************************************** * NAME: dTree_processing * * FUNCTION: Perform the specified action on the dTree rooted in the * specified inode. * * PARAMETERS: * inoptr - input - pointer to the directory inode in an fsck * buffer * inoidx - input - ordinal number of the inode * inorecptr - input - pointer to an fsck inode record describing * the inode * msg_info_ptr - input - pointer to data needed to issue messages * about the inode * desired_action - input - { FSCK_RECORD | FSCK_RECORD_DUPCHECK | * FSCK_UNRECORD | FSCK_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */ int dTree_processing(struct dinode *inoptr, uint32_t inoidx, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr, int desired_action) { int dp_rc = FSCK_OK; int slotidx; int8_t old_ignore_alloc_blks = 0; int ixpxd_unequal = 0; struct fsck_Dtree_info dtinfo; struct fsck_Dtree_info *dtiptr; int8_t first_in_level = 0; int8_t last_in_level = 0; int8_t is_leaf = 0; int8_t is_root = -1; int8_t dtstbl_last_slot; uint32_t nodesize_in_bytes; int8_t msg_reason = 0; dtiptr = &dtinfo; dtiptr->this_Qel = NULL; dtiptr->next_Qel = NULL; /* -1 so the root will be recognized as 1st node in level 0 */ dtiptr->last_level = -1; /* so we won't get a match until the actual leaf level is found */ dtiptr->leaf_level = -1; dtiptr->this_key_idx = 0; dtiptr->last_key_idx = 1; dtiptr->key_len[dtiptr->this_key_idx] = 0; dtiptr->key_len[dtiptr->last_key_idx] = 0; dtiptr->leaf_seen = 0; /* set the flags for all slots in the current page to 'not used' */ memset((void *)&(dtiptr->slot_map[0]), 0, DTPAGEMAXSLOT); dtiptr->dtr_ptr = (dtroot_t *) & (inoptr->di_btroot); dtiptr->max_slotidx = DTROOTMAXSLOT - 1; if (dtiptr->dtr_ptr->header.nextindex == 0) goto out; /* there is at least 1 entry */ if (desired_action != FSCK_RECORD_DUPCHECK) { /* not the first pass */ /* * The first time through we stopped processing allocated * blocks if and when we discovered the tree to be corrupt. * On a 2nd pass we want to stop at the same place. */ if (inorecptr->ignore_alloc_blks) { /* the bit is on */ /* set the flag */ old_ignore_alloc_blks = -1; /* turn the bit off */ inorecptr->ignore_alloc_blks = 0; } } dtiptr->key_len[dtiptr->last_key_idx] = 0; dtiptr->dtstbl = (int8_t *) & (dtiptr->dtr_ptr->header.stbl[0]); dtiptr->slots = &(dtiptr->dtr_ptr->slot[0]); dtiptr->freelist_first_dtidx = dtiptr->dtr_ptr->header.freelist; dtiptr->freelist_count = dtiptr->dtr_ptr->header.freecnt; dtiptr->last_dtidx = dtiptr->dtr_ptr->header.nextindex - 1; /* * Do a sanity check to make sure this looks like a * DTree root node */ if (dtiptr->last_dtidx > dtiptr->max_slotidx) { inorecptr->ignore_alloc_blks = 1; msg_reason = 16; } else if (dtiptr->freelist_count < 0) { inorecptr->ignore_alloc_blks = 1; msg_reason = 17; } else if (dtiptr->freelist_count > dtiptr->max_slotidx) { inorecptr->ignore_alloc_blks = 1; msg_reason = 18; } else if (dtiptr->freelist_first_dtidx < -1) { inorecptr->ignore_alloc_blks = 1; msg_reason = 19; } else if (dtiptr->freelist_first_dtidx > dtiptr->max_slotidx) { inorecptr->ignore_alloc_blks = 1; msg_reason = 20; } else if ((dtiptr->last_dtidx == dtiptr->max_slotidx) && (dtiptr->freelist_count != 0)) { inorecptr->ignore_alloc_blks = 1; msg_reason = 21; } else if ((dtiptr->last_dtidx == dtiptr->max_slotidx) && (dtiptr->freelist_first_dtidx != -1)) { inorecptr->ignore_alloc_blks = 1; msg_reason = 22; } else if ((dtiptr->freelist_first_dtidx != -1) && (dtiptr->freelist_count == 0)) { inorecptr->ignore_alloc_blks = 1; msg_reason = 23; } else if ((dtiptr->freelist_first_dtidx == -1) && (dtiptr->freelist_count != 0)) { inorecptr->ignore_alloc_blks = 1; msg_reason = 24; } if (inorecptr->ignore_alloc_blks && (msg_reason != 0)) { if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADKEYS, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, msg_reason); } goto out; } /* the root looks like it's probably a root */ /* * mark all slots occupied by the header as being in use */ for (slotidx = 0; (slotidx < DTENTRYSTART); slotidx++) { dtiptr->slot_map[slotidx] = -1; } /* * get a queue element and set it up for the root */ dp_rc = dtreeQ_get_elem(&dtiptr->this_Qel); if (dp_rc != FSCK_OK) goto out; /* got a queue element */ dtiptr->this_Qel->node_level = 0; if (dtiptr->dtr_ptr->header.flag & BT_LEAF) { /* root leaf */ dtiptr->leaf_seen = -1; dtiptr->leaf_level = dtiptr->this_Qel->node_level; is_leaf = -1; } else if (!(dtiptr->dtr_ptr->header.flag & BT_INTERNAL)) { /* but it's not an internal node either! */ if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADKEYS, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, 11); } } /* * get the first key, but don't mark the slot_map */ dp_rc = dTree_key_extract_cautiously(dtiptr, 0, &(dtiptr->key[dtiptr->this_key_idx][0]), &(dtiptr->key_len[dtiptr->this_key_idx]), is_root, is_leaf, inorecptr); /* * get the first key in the directory. Since this is the first time * we've extracted it, we need to guard against a loop even though we * aren't recording it now. */ if (dp_rc != FSCK_OK) goto out; if (inorecptr->ignore_alloc_blks) { /* but directory is bad */ if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADKEYS, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, 40); } } else { /* we got the first key */ if (is_leaf) dp_rc = dTree_process_leaf_slots(dtiptr, inorecptr, inoptr, msg_info_ptr, desired_action); else dp_rc = dTree_process_internal_slots(dtiptr, inorecptr, msg_info_ptr, desired_action); if ((dp_rc == FSCK_OK) && (!inorecptr->ignore_alloc_blks)) { /* node is looking good */ dtiptr->key_len[dtiptr->last_key_idx] = 0; dp_rc = dTree_verify_slot_freelist(dtiptr, inorecptr, msg_info_ptr, desired_action); } } while ((dp_rc == FSCK_OK) && (!inorecptr->ignore_alloc_blks) && (agg_recptr->dtreeQ_back != NULL)) { /* nothing fatal and tree looks ok and queue not empty */ dp_rc = dtreeQ_dequeue(&dtiptr->next_Qel); if (dp_rc != FSCK_OK) goto out; /* got another element from the queue */ if (dtiptr->this_Qel->node_level != dtiptr->next_Qel->node_level) { /* it's the last in this level */ last_in_level = -1; if (!is_root) dp_rc = dTree_node_last_in_level(dtiptr, inorecptr, msg_info_ptr, desired_action); } else { /* it's not the last in its level */ last_in_level = 0; dp_rc = dTree_node_not_last_in_level(dtiptr, inorecptr, msg_info_ptr, desired_action); } if ((dp_rc != FSCK_OK) || (inorecptr->ignore_alloc_blks)) break; dtiptr->last_level = dtiptr->this_Qel->node_level; dtiptr->last_node_addr = dtiptr->this_Qel->node_addr; dp_rc = dtreeQ_rel_elem(dtiptr->this_Qel); if (dp_rc != FSCK_OK) { /* don't try again after loop! */ dtiptr->this_Qel = NULL; break; } /* released the older element */ /* promote newer element */ dtiptr->this_Qel = dtiptr->next_Qel; /* to avoid releasing it twice */ dtiptr->next_Qel = NULL; is_root = 0; dp_rc = dnode_get(dtiptr->this_Qel->node_addr, BYTESPERPAGE, &dtiptr->dtp_ptr); if (dp_rc != FSCK_OK) { /* read failed */ /* this isn't an fsck failure -- * it's a symptom of a bad dtree */ dp_rc = FSCK_OK; inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADKEYS, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, 38); } break; } /* got the new node */ /* returns 0 if equal */ ixpxd_unequal = memcmp((void *)&(dtiptr->dtp_ptr->header.self), (void *)&(dtiptr->this_Qel->node_pxd), sizeof(pxd_t)); if (ixpxd_unequal) { /* bad self pxd in header */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) /* not reported yet */ fsck_send_msg(fsck_BADINONODESELF, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); break; } else if (dtiptr->dtp_ptr->header.nextindex == 0) { /* an empty non-root node */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) /* not reported yet */ fsck_send_msg(fsck_BADINOMTNODE, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); break; } /* node is not empty */ dtiptr->max_slotidx = dtiptr->dtp_ptr->header.maxslot - 1; if (dtiptr->dtp_ptr->header.flag & BT_LEAF) { /* a leaf */ dtiptr->leaf_seen = -1; dtiptr->leaf_level = dtiptr->this_Qel->node_level; is_leaf = -1; } else if (!(dtiptr->dtp_ptr->header.flag & BT_INTERNAL)) { /* but it's not an internal node either! */ if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADKEYS, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, 41); } } /* * set the flags for all slots in the * current page to 'not used' */ memset((void *)&(dtiptr->slot_map[0]), 0, DTPAGEMAXSLOT); dtiptr->dtstbl = (int8_t *) & (dtiptr->dtp_ptr-> slot[dtiptr->dtp_ptr->header.stblindex]); dtiptr->slots = &(dtiptr->dtp_ptr->slot[0]); dtiptr->freelist_first_dtidx = dtiptr->dtp_ptr->header.freelist; dtiptr->freelist_count = dtiptr->dtp_ptr->header.freecnt; dtiptr->last_dtidx = dtiptr->dtp_ptr->header.nextindex - 1; /* * mark all slots occupied by the header as being in use */ for (slotidx = 0; (slotidx < DTENTRYSTART); slotidx++) { dtiptr->slot_map[slotidx] = -1; } /* * figure out which slots are occupied by the dtstbl and * mark them as being in use */ nodesize_in_bytes = dtiptr->this_Qel->node_size * sb_ptr->s_bsize; if (nodesize_in_bytes > DTHALFPGNODEBYTES) { dtstbl_last_slot = (DTHALFPGNODETSLOTS << 1) + dtiptr->dtp_ptr->header.stblindex - 1; } else if (nodesize_in_bytes == DTHALFPGNODEBYTES) { dtstbl_last_slot = DTHALFPGNODETSLOTS + dtiptr->dtp_ptr->header.stblindex - 1; } else { dtstbl_last_slot = (DTHALFPGNODETSLOTS >> 1) + dtiptr->dtp_ptr->header.stblindex - 1; } /* * Do a sanity check to make sure this looks like a * DTree root node */ if ((dtiptr->dtp_ptr->header.maxslot != DT8THPGNODESLOTS) && (dtiptr->dtp_ptr->header.maxslot != DTQTRPGNODESLOTS) && (dtiptr->dtp_ptr->header.maxslot != DTHALFPGNODESLOTS) && (dtiptr->dtp_ptr->header.maxslot != DTFULLPGNODESLOTS)) { inorecptr->ignore_alloc_blks = 1; msg_reason = 25; } else if (dtiptr->last_dtidx > dtiptr->max_slotidx) { inorecptr->ignore_alloc_blks = 1; msg_reason = 26; } else if (dtiptr->freelist_count < 0) { inorecptr->ignore_alloc_blks = 1; msg_reason = 27; } else if (dtiptr->freelist_count > dtiptr->max_slotidx) { inorecptr->ignore_alloc_blks = 1; msg_reason = 28; } else if (dtiptr->freelist_first_dtidx < -1) { inorecptr->ignore_alloc_blks = 1; msg_reason = 29; } else if (dtiptr->freelist_first_dtidx > dtiptr->max_slotidx) { inorecptr->ignore_alloc_blks = 1; msg_reason = 30; } else if ((dtiptr->last_dtidx == dtiptr->max_slotidx) && (dtiptr->freelist_count != 0)) { inorecptr->ignore_alloc_blks = 1; msg_reason = 31; } else if ((dtiptr->last_dtidx == dtiptr->max_slotidx) && (dtiptr->freelist_first_dtidx != -1)) { inorecptr->ignore_alloc_blks = 1; msg_reason = 32; } else if ((dtiptr->freelist_first_dtidx != -1) && (dtiptr->freelist_count == 0)) { inorecptr->ignore_alloc_blks = 1; msg_reason = 33; } else if ((dtiptr->freelist_first_dtidx == -1) && (dtiptr->freelist_count != 0)) { inorecptr->ignore_alloc_blks = 1; msg_reason = 34; } else if (dtiptr->dtp_ptr->header.stblindex > dtiptr->max_slotidx) { inorecptr->ignore_alloc_blks = 1; msg_reason = 35; } else if (dtiptr->dtp_ptr->header.stblindex < 1) { inorecptr->ignore_alloc_blks = 1; msg_reason = 36; } if (inorecptr->ignore_alloc_blks && (msg_reason != 0)) { if (desired_action == FSCK_RECORD_DUPCHECK) /* not reported yet */ fsck_send_msg(fsck_BADKEYS, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, msg_reason); break; } /* the node looks like it's probably a real node */ for (slotidx = dtiptr->dtp_ptr->header.stblindex; (slotidx <= dtstbl_last_slot); slotidx++) dtiptr->slot_map[slotidx] = -1; /* * get the first key, but don't mark the slot_map */ dp_rc = dTree_key_extract_cautiously(dtiptr, 0, &(dtiptr->key[dtiptr->this_key_idx][0]), &(dtiptr->key_len[dtiptr->this_key_idx]), is_root, is_leaf, inorecptr); /* * get the first key in the directory. * Since this is the first time we've * extracted it, we need to guard against * a loop even though we aren't recording * it now. */ if (dp_rc != FSCK_OK) break; if (inorecptr->ignore_alloc_blks) { /* but directory is bad */ if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADKEYS, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, 12); } break; } /* we got the first key */ dp_rc = dTree_node_first_key(dtiptr, inorecptr, msg_info_ptr, desired_action); if ((dp_rc != FSCK_OK) || inorecptr->ignore_alloc_blks) break; /* tree still interesting */ if (dtiptr->dtp_ptr->header.flag & BT_LEAF) { is_leaf = -1; } else if (!(dtiptr->dtp_ptr->header.flag & BT_INTERNAL)) { /* but it's not an internal node either! */ if (desired_action == FSCK_RECORD_DUPCHECK) /* not reported yet */ fsck_send_msg(fsck_BADKEYS, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, 42); } else is_leaf = 0; /* tree still looks ok */ if (is_leaf) dp_rc = dTree_process_leaf_slots(dtiptr, inorecptr, inoptr, msg_info_ptr, desired_action); else { /* an internal node */ if (dtiptr->last_level != dtiptr->this_Qel->node_level) { /* this node is the first in a new level of internal nodes. */ /* This is the size of the leaf * nodes, so we only want the total * described by the LAST level of * internal nodes. */ if (!(sb_ptr->s_flag & JFS_DIR_INDEX)) agg_recptr->this_inode.data_size = 0; } /* This is the size of the leaf nodes, so we only want ... */ dp_rc = dTree_process_internal_slots(dtiptr, inorecptr, msg_info_ptr, desired_action); } if ((dp_rc != FSCK_OK) || inorecptr->ignore_alloc_blks) break; if (dtiptr->last_level != dtiptr->this_Qel->node_level) { /* this is a new level */ first_in_level = -1; dtiptr->key_len[dtiptr->last_key_idx] = 0; if (!is_root) dp_rc = dTree_node_first_in_level(dtiptr, inorecptr, msg_info_ptr, desired_action); } else { /* not 1st in level */ first_in_level = 0; dp_rc = dTree_node_not_first_in_level(dtiptr, inorecptr, msg_info_ptr, desired_action); } if ((dp_rc != FSCK_OK) || inorecptr->ignore_alloc_blks) break; dp_rc = dTree_node_size_check(dtiptr, is_leaf, first_in_level, last_in_level, inorecptr, msg_info_ptr, desired_action); if ((dp_rc != FSCK_OK) || inorecptr->ignore_alloc_blks) break; dp_rc = dTree_verify_slot_freelist(dtiptr, inorecptr, msg_info_ptr, desired_action); if ((dp_rc != FSCK_OK) || inorecptr->ignore_alloc_blks) break; if (agg_recptr->dtreeQ_back == NULL) { /* nothing fatal and tree looks ok and queue is now * empty */ last_in_level = -1; if (!is_root) dp_rc = dTree_node_last_in_level(dtiptr, inorecptr, msg_info_ptr, desired_action); } } /* * there's at least 1 more Q element to release for this node, and * if the tree is bad there may still be some on the queue as well. * * (If there's a processing error all the dynamic storage is going * to be released so there's no point in preparing these elements * for reuse.) */ if (dp_rc == FSCK_OK) { if (dtiptr->this_Qel != NULL) { dp_rc = dtreeQ_rel_elem(dtiptr->this_Qel); } } if (dp_rc == FSCK_OK) { if (dtiptr->next_Qel != NULL) { dp_rc = dtreeQ_rel_elem(dtiptr->next_Qel); } } agg_recptr->dtreeQ_back = NULL; while ((dp_rc == FSCK_OK) && (agg_recptr->dtreeQ_front != NULL)) { dtiptr->this_Qel = agg_recptr->dtreeQ_front; agg_recptr->dtreeQ_front = dtiptr->this_Qel->next; dp_rc = dtreeQ_rel_elem(dtiptr->this_Qel); } if (dp_rc == FSCK_OK) { if (desired_action != FSCK_RECORD_DUPCHECK) { /* we altered the corrupt tree bit */ if (old_ignore_alloc_blks && !inorecptr->ignore_alloc_blks) /* * the flag is set but the bit didn't get * turned back on. This means that the first * time we went through this tree we decided * it was corrupt but this time it looked ok. */ dp_rc = FSCK_INTERNAL_ERROR_10; else if (!old_ignore_alloc_blks && inorecptr->ignore_alloc_blks) /* * the flag is off but the bit got turned on. * This means that the first time we went * through this tree it looked ok but this * time we decided that it is corrupt. */ dp_rc = FSCK_INTERNAL_ERROR_11; } } out: return (dp_rc); } /***************************************************************************** * NAME: dTree_search * * FUNCTION: Search the dTree rooted in the specified inode for the given * filename. * * PARAMETERS: * dir_inoptr - input - pointer to the directory inode in * an fsck buffer * given_key - input - pointer to the filename to find, in * mixed case * given_key_length - input - length of the string in given_key * given_key_folded - input - pointer to the given_key in all * upper case * given_key_folded_length - input - length of the string in * given_key_folded * addr_slot_ptr - input - pointer to a variable in which to * return the address of the slot * which contains (or begins) the * the key which is a match for * given_key * match_found - input - pointer to a variable in which to * return !0 if an entry with given_key * or given_key_folded was * found in the given * directory inode * 0 if no entry with given_key * or given_key_folded was * found in the given * directory inode * inorecptr - input - pointer to an fsck inode record * describing the inode * * RETURNS: * success: FSCK_OK * failure: something else */ int dTree_search(struct dinode *dir_inoptr, UniChar * given_key, uint32_t given_key_length, UniChar * given_key_folded, uint32_t given_key_folded_length, struct dtslot **addr_slot_ptr, int8_t * match_found, struct fsck_inode_record *inorecptr) { int ds_rc = FSCK_OK; int8_t slot_selected; int8_t selected_slotidx; int8_t is_root = -1; int8_t leaf_found = 0; int8_t not_there = 0; int8_t key_matched = 0; struct idtentry *intentry; int64_t node_addr; uint32_t node_length; struct fsck_Dtree_info dtinfo; struct fsck_Dtree_info *dtiptr; dtiptr = &dtinfo; dtiptr->dtr_ptr = (dtroot_t *) & (dir_inoptr->di_btroot); dtiptr->dtstbl = (int8_t *) & (dtiptr->dtr_ptr->header.stbl[0]); dtiptr->slots = (struct dtslot *) &(dtiptr->dtr_ptr->slot[0]); if (dtiptr->dtr_ptr->header.nextindex > 0) { /* the directory isn't empty */ dtiptr->last_dtidx = dtiptr->dtr_ptr->header.nextindex - 1; dtiptr->max_slotidx = DTROOTMAXSLOT - 1; if (dtiptr->dtr_ptr->header.flag & BT_LEAF) { /* it's a root leaf */ leaf_found = -1; } while ((!leaf_found) && (!not_there) && (ds_rc == FSCK_OK)) { if (sb_ptr->s_flag & JFS_OS2) { /* case is preserved but ignored */ /* search case insensitive */ ds_rc = dTree_binsrch_internal_page(dtiptr, given_key_folded, given_key_folded_length, is_root, ¬_there, &slot_selected, &selected_slotidx, inorecptr); } else { /* search case sensitive */ ds_rc = dTree_binsrch_internal_page(dtiptr, given_key, given_key_length, is_root, ¬_there, &slot_selected, &selected_slotidx, inorecptr); } if ((slot_selected) && (ds_rc == FSCK_OK)) { intentry = (struct idtentry *) &(dtiptr-> slots [selected_slotidx]); node_addr = addressPXD(&(intentry->xd)); node_length = lengthPXD(&(intentry->xd)); ds_rc = dnode_get(node_addr, BYTESPERPAGE, &(dtiptr->dtp_ptr)); if (ds_rc == FSCK_OK) { is_root = 0; dtiptr->dtstbl = (int8_t *) & (dtiptr->dtp_ptr-> slot[dtiptr->dtp_ptr->header. stblindex]); dtiptr->slots = (struct dtslot *) &(dtiptr-> dtp_ptr-> slot[0]); dtiptr->last_dtidx = dtiptr->dtp_ptr->header.nextindex - 1; dtiptr->max_slotidx = (node_length * sb_ptr->s_bsize) / DTSLOTSIZE; if (dtiptr->dtp_ptr->header. flag & BT_LEAF) { leaf_found = -1; } } } } if ((!not_there) && (ds_rc == FSCK_OK)) { /* might be in there */ if (sb_ptr->s_flag & JFS_OS2) { /* case is preserved but ignored */ /* search case insensitive */ ds_rc = dTree_binsrch_leaf(dtiptr, given_key_folded, given_key_folded_length, is_root, ¬_there, &key_matched, &slot_selected, &selected_slotidx, inorecptr); } else { /* search case sensitive */ ds_rc = dTree_binsrch_leaf(dtiptr, given_key, given_key_length, is_root, ¬_there, &key_matched, &slot_selected, &selected_slotidx, inorecptr); } } } if ((ds_rc == FSCK_OK) && (key_matched)) { /* found it! */ *addr_slot_ptr = &(dtiptr->slots[selected_slotidx]); *match_found = -1; } else { /* no luck */ *addr_slot_ptr = NULL; *match_found = 0; } return (ds_rc); } /***************************************************************************** * NAME: dTree_verify_slot_freelist * * FUNCTION: Verify the structure and contents of the slot freelist in the * specified directory node. * * PARAMETERS: * dtiptr - input - pointer to an fsck record describing the * directory tree * inorecptr - input - pointer to an fsck inode record describing * the inode * msg_info_ptr - input - pointer to data needed to issue messages * about the inode * desired_action - input - { FSCK_RECORD | FSCK_RECORD_DUPCHECK | * FSCK_UNRECORD | FSCK_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */ int dTree_verify_slot_freelist(struct fsck_Dtree_info *dtiptr, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr, int desired_action) { int dvsf_rc = FSCK_OK; uint8_t slotidx; struct dtslot *slot_ptr; int8_t freelist_entry; int8_t freelist_size = 0; if (dtiptr->freelist_first_dtidx == -1) { /* the list is empty */ if (dtiptr->freelist_count > 0) { /* but the counter is nonzero */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADDINOFREELIST1, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } } else { /* the list is not empty */ freelist_entry = dtiptr->freelist_first_dtidx; while ((freelist_entry != -1) && (dvsf_rc == FSCK_OK) && (!inorecptr->ignore_alloc_blks) && (freelist_size <= dtiptr->freelist_count)) { if (dtiptr->slot_map[freelist_entry]) { /* already marked! */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADDINOFREELIST4, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } else { /* not claimed yet */ /* mark this one */ dtiptr->slot_map[freelist_entry] = -1; /* count this one */ freelist_size++; slot_ptr = (struct dtslot *) &(dtiptr-> slots[freelist_entry]); freelist_entry = slot_ptr->next; } } } if (!inorecptr->ignore_alloc_blks) { /* nothing wrong yet */ if (freelist_size != dtiptr->freelist_count) { /* size is wrong */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADDINOFREELIST2, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } } if (!inorecptr->ignore_alloc_blks) { /* still looks good */ for (slotidx = 0; ((slotidx <= dtiptr->max_slotidx) && (!inorecptr->ignore_alloc_blks)); slotidx++) { if (dtiptr->slot_map[slotidx] == 0) { /* a slot which is not in a key chain and is also not on the free list */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADDINOFREELIST3, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } } } return (dvsf_rc); } /***************************************************************************** * NAME: find_first_dir_leaf * * FUNCTION: Locate the leftmost leaf node in the dTree rooted in the * given inode. * * PARAMETERS: * inoptr - input - pointer to the directory inode in an * fsck buffer * addr_leaf_ptr - input - pointer to a variable in which to return * the address, in an fsck buffer, of the * inode's left-most leaf. * leaf_agg_offset - input - pointer to a variable in which to return * the offset, in the aggregate, of the * leftmost leaf in the B+ Tree rooted in * the directory inode. (This has a * special meaning if the directory root is * not an internal node. See the code below.) * is_inline - input - pointer to a variable in which to return * !0 if the directory data is within the * inode * 0 if the directory data is not within * the inode * is_rootleaf - input - pointer to a variable in which to return * !0 if the B+ Tree rooted in the directory * inode has a root leaf * 0 if the B+ Tree rooted in the directory * inode does not have a root leaf * * RETURNS: * success: FSCK_OK * failure: something else */ int find_first_dir_leaf(struct dinode *inoptr, dtpage_t ** addr_leaf_ptr, int64_t * leaf_agg_offset, int8_t * is_inline, int8_t * is_rootleaf) { int ffdl_rc = FSCK_OK; dtpage_t *dtpg_ptr; dtroot_t *dtroot_ptr; struct idtentry *idtentry_ptr; int64_t first_child_addr; int8_t *dtstbl; *is_rootleaf = 0; /* assume inode has no data */ *is_inline = 0; /* assume inode has no data */ *addr_leaf_ptr = NULL; /* assume inode has no data */ *leaf_agg_offset = 0; /* assume inode has no data */ dtroot_ptr = (dtroot_t *) & (inoptr->di_btroot); if (dtroot_ptr->header.flag & BT_LEAF) { /* it's a root-leaf */ *is_rootleaf = -1; *leaf_agg_offset = addressPXD(&(inoptr->di_ixpxd)); } else { /* it's a tree */ idtentry_ptr = (struct idtentry *) &(dtroot_ptr->slot[dtroot_ptr->header.stbl[0]]); /* * the slot number of the entry describing * the first child is in the 0th entry of * the header.stbl array. */ first_child_addr = addressPXD(&(idtentry_ptr->xd)); ffdl_rc = dnode_get(first_child_addr, BYTESPERPAGE, &dtpg_ptr); while ((ffdl_rc == FSCK_OK) && (*leaf_agg_offset == 0)) { if (dtpg_ptr->header.flag & BT_LEAF) { /* found it! */ *addr_leaf_ptr = dtpg_ptr; *leaf_agg_offset = first_child_addr; } else { /* keep moving down the tree */ dtstbl = (int8_t *) & (dtpg_ptr-> slot[dtpg_ptr->header. stblindex]); idtentry_ptr = (struct idtentry *) &(dtpg_ptr->slot[dtstbl[0]]); /* * the address of the idtentry describing * the first child */ first_child_addr = addressPXD(&(idtentry_ptr->xd)); ffdl_rc = dnode_get(first_child_addr, BYTESPERPAGE, &dtpg_ptr); } } } return (ffdl_rc); } /***************************************************************************** * NAME: init_dir_tree * * FUNCTION: Initialize the dTree rooted at the given address. * * PARAMETERS: * btroot_ptr - input - pointer to the root of the B+ Tree rooted in * the directory inode * * RETURNS: * success: FSCK_OK * failure: something else */ void init_dir_tree(dtroot_t * btroot_ptr) { int slot_idx; btroot_ptr->header.flag = (BT_ROOT | BT_LEAF | DXD_INDEX); btroot_ptr->header.nextindex = 0; btroot_ptr->header.freecnt = DTROOTMAXSLOT - 1; btroot_ptr->header.freelist = 1; for (slot_idx = 1; (slot_idx < DTROOTMAXSLOT); slot_idx++) { btroot_ptr->slot[slot_idx].next = slot_idx + 1; } btroot_ptr->slot[DTROOTMAXSLOT - 1].next = -1; return; } /***************************************************************************** * NAME: process_valid_dir_data * * FUNCTION: Perform the specified action on the nodes of the specified dTree. * Assume that the dTree structure has already been validated. * * PARAMETERS: * inoptr - input - pointer to the directory inode in an fsck * buffer * inoidx - input - ordinal number of the inode * inorecptr - input - pointer to an fsck inode record describing * the inode * msg_info_ptr - input - pointer to data needed to issue messages * about the inode * desired_action - input - { FSCK_RECORD | FSCK_UNRECORD | FSCK_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */ int process_valid_dir_data(struct dinode *inoptr, uint32_t inoidx, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr, int desired_action) { int pvdd_rc = FSCK_OK; dtroot_t *dtroot_ptr; dtpage_t *dtpage_ptr; int8_t *dtstbl; struct dtslot *slots; int last_dtidx; struct idtentry *idtentry_ptr; /* internal node entry */ int64_t node_addr_fsblks; int64_t first_child_addr; int8_t all_done = 0; dtroot_ptr = (dtroot_t *) & (inoptr->di_btroot); if (dtroot_ptr->header.flag != 0) { /* there is data for this inode */ if (!(dtroot_ptr->header.flag & BT_LEAF)) { /* not a root-leaf */ dtstbl = (int8_t *) & (dtroot_ptr->header.stbl[0]); slots = &(dtroot_ptr->slot[0]); last_dtidx = dtroot_ptr->header.nextindex - 1; idtentry_ptr = (struct idtentry *) &(slots[dtstbl[0]]); /* slot describing the first child */ first_child_addr = addressPXD(&(idtentry_ptr->xd)); pvdd_rc = process_valid_dir_node(dtstbl, slots, last_dtidx, inorecptr, msg_info_ptr, desired_action); while ((pvdd_rc == FSCK_OK) && (!all_done)) { /* while not done */ /* * We have the address of the first node in the new level. * Get the first node in the new level. */ pvdd_rc = dnode_get(first_child_addr, BYTESPERPAGE, &dtpage_ptr); if (pvdd_rc == FSCK_OK) { /* got the first child */ if (dtpage_ptr->header. flag & BT_LEAF) { /* we're done */ all_done = -1; } else { /* not down to the leaf level yet */ /* * Set up to process this level. */ dtstbl = (int8_t *) & (dtpage_ptr-> slot[dtpage_ptr-> header. stblindex]); slots = &(dtpage_ptr-> slot[0]); last_dtidx = dtpage_ptr->header. nextindex - 1; /* * save the address of this node's first child */ idtentry_ptr = (struct idtentry *) &(slots[dtstbl[0]]); /* slot describing the first child */ first_child_addr = addressPXD(& (idtentry_ptr-> xd)); /* * process everything described by this node */ pvdd_rc = process_valid_dir_node (dtstbl, slots, last_dtidx, inorecptr, msg_info_ptr, desired_action); /* * process everything described by this node's * siblings and cousins (if any) */ while ((pvdd_rc == FSCK_OK) && (dtpage_ptr-> header. next != ((int64_t) 0))) { /* more to process on this level */ node_addr_fsblks = dtpage_ptr-> header.next; /* * Get the next node in this level. */ pvdd_rc = dnode_get (node_addr_fsblks, BYTESPERPAGE, &dtpage_ptr); if (pvdd_rc == FSCK_OK) { /* got the node */ /* * Set up to process this node. */ dtstbl = (int8_t *) & (dtpage_ptr-> slot [dtpage_ptr-> header. stblindex]); slots = & (dtpage_ptr-> slot [0]); last_dtidx = dtpage_ptr-> header. nextindex - 1; pvdd_rc = process_valid_dir_node (dtstbl, slots, last_dtidx, inorecptr, msg_info_ptr, desired_action); } } } } } } } if ((pvdd_rc == FSCK_OK) && (sb_ptr->s_flag & JFS_DIR_INDEX) && (inoptr->di_next_index > MAX_INLINE_DIRTABLE_ENTRY + 1)) { pvdd_rc = process_valid_data(inoptr, inoidx, inorecptr, msg_info_ptr, desired_action); } return (pvdd_rc); } /***************************************************************************** * NAME: process_valid_dir_node * * FUNCTION: Perform the specified action on the specified dTree node. * Assume that the node structure has already been validated. * * PARAMETERS: * dtstbl - input - pointer to the sorted entry index table * in the directory node * slots - input - pointer to slot[0] in the directory node * last_dtidx - input - last valid entry in the directory node's * sorted entry index table * inorecptr - input - pointer to an fsck inode record describing * the inode * msg_info_ptr - input - pointer to data needed to issue messages * about the inode * desired_action - input - { FSCK_RECORD | FSCK_UNRECORD | FSCK_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */ int process_valid_dir_node(int8_t * dtstbl, struct dtslot *slots, int last_dtidx, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr, int desired_action) { int pvdn_rc = FSCK_OK; int dtidx; struct idtentry *idtentry_ptr; /* internal node entry */ int64_t child_addr; uint32_t child_length; int8_t is_EA = 0; int8_t is_ACL = 0; int8_t extent_is_valid; uint32_t block_count; for (dtidx = 0; ((pvdn_rc == FSCK_OK) && (dtidx <= last_dtidx)); dtidx++) { /* for each entry used in the dtstbl */ idtentry_ptr = (struct idtentry *) &(slots[dtstbl[dtidx]]); /* slot describing the first child */ child_addr = addressPXD(&(idtentry_ptr->xd)); child_length = lengthPXD(&(idtentry_ptr->xd)); pvdn_rc = process_extent(inorecptr, child_length, child_addr, is_EA, is_ACL, msg_info_ptr, &block_count, &extent_is_valid, desired_action); agg_recptr->blocks_this_fset -= block_count; agg_recptr->this_inode.all_blks -= block_count; agg_recptr->this_inode.data_blks -= block_count; if ((desired_action == FSCK_RECORD) || (desired_action == FSCK_RECORD_DUPCHECK)) { agg_recptr->blocks_this_fset += block_count; agg_recptr->this_inode.all_blks += block_count; agg_recptr->this_inode.data_blks += block_count; } else if (desired_action == FSCK_UNRECORD) { agg_recptr->blocks_this_fset -= block_count; agg_recptr->this_inode.all_blks -= block_count; agg_recptr->this_inode.data_blks -= block_count; } } return (pvdn_rc); } /***************************************************************************** * NAME: reconnect_fs_inodes * * FUNCTION: Add a directory entry to /lost+found/ for each unconnected * inode in the list at agg_recptr->inode_reconn_extens * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int reconnect_fs_inodes() { int rfsi_rc = FSCK_OK; int intermed_rc = FSCK_OK; char inopfx = ' '; /* fileset inodes */ uint dir_inodes_reconnected = 0; uint dir_inodes_not_reconnected = 0; uint inodes_reconnected = 0; uint inodes_not_reconnected = 0; char inoname[16]; char *ino_name; struct fsck_inode_ext_record *this_ext; struct fsck_inode_record *inorecptr; int aggregate_inode = 0; int alloc_ifnull = 0; int is_aggregate = 0; /* aggregate has no dirs */ int which_it = FILESYSTEM_I; /* only 1 fileset in release 1 */ struct dinode *lsfn_inoptr; ino_name = &(inoname[0]); this_ext = agg_recptr->inode_reconn_extens; intermed_rc = inode_get(is_aggregate, which_it, agg_recptr->lsfn_inonum, &lsfn_inoptr); if (intermed_rc != FSCK_OK) { /* this is unexpected but not fatal to this run or to the filesystem */ agg_recptr->lsfn_ok = 0; } while ((rfsi_rc == FSCK_OK) && (this_ext != NULL)) { rfsi_rc = get_inorecptr(aggregate_inode, alloc_ifnull, this_ext->inonum, &inorecptr); if ((rfsi_rc == FSCK_OK) && (inorecptr == NULL)) { rfsi_rc = FSCK_INTERNAL_ERROR_47; } else if (rfsi_rc == FSCK_OK) { if (agg_recptr->lsfn_ok) { /* /lost+found/ resolved ok */ /* * compute a name for the directory entry */ if (inorecptr->inode_type == directory_inode) { sprintf(ino_name, "%s%06d%s", msg_defs[fsck_dirpfx].msg_txt, this_ext->inonum, msg_defs[fsck_dotext].msg_txt); } else { sprintf(ino_name, "%s%06d%s", msg_defs[fsck_inopfx].msg_txt, this_ext->inonum, msg_defs[fsck_dotext].msg_txt); } UTF8_String_To_Unicode_String(Uni_Name, ino_name, JFS_NAME_MAX); intermed_rc = direntry_add(lsfn_inoptr, this_ext->inonum, Uni_Name); if (intermed_rc != FSCK_OK) { /* couldn't do it */ if (intermed_rc < 0) { /* something fatal */ rfsi_rc = intermed_rc; } else { /* not fatal */ agg_recptr->lsfn_ok = 0; /* * don't move this_ext to next extension record. execute * the loop for this one again so that it will be * handled as one that can't be reconnected. */ } } else { /* entry added */ if (inorecptr->inode_type == directory_inode) { lsfn_inoptr->di_nlink += 1; dir_inodes_reconnected += 1; fsck_send_msg(fsck_INOINLSFND, inopfx, this_ext->inonum); } else { /* not a directory inode */ inodes_reconnected += 1; fsck_send_msg(fsck_INOINLSFNF, inopfx, this_ext->inonum); } this_ext = this_ext->next; } } else { /* /lost+found/ is not ok */ if (inorecptr->inode_type == directory_inode) { dir_inodes_not_reconnected += 1; fsck_send_msg(fsck_MNCNTRCNCTINOD, inopfx, this_ext->inonum); } else { /* not a directory inode */ inodes_not_reconnected += 1; fsck_send_msg(fsck_MNCNTRCNCTINOF, inopfx, this_ext->inonum); } this_ext = this_ext->next; } } } if ((rfsi_rc == FSCK_OK) && ((dir_inodes_reconnected != 0) || (inodes_reconnected != 0))) { rfsi_rc = inode_put(lsfn_inoptr); } /* * put out some summary messages in case we're not processing verbose */ if (rfsi_rc >= FSCK_OK) { if (dir_inodes_not_reconnected > 0) { if (dir_inodes_not_reconnected == 1) { fsck_send_msg(fsck_MNCNTRCNCTINOSD, dir_inodes_not_reconnected); } else { fsck_send_msg(fsck_MNCNTRCNCTINOSDS, dir_inodes_not_reconnected); } } if (dir_inodes_reconnected > 0) { if (dir_inodes_reconnected == 1) { fsck_send_msg(fsck_INOSINLSFND, dir_inodes_reconnected); } else { fsck_send_msg(fsck_INOSINLSFNDS, dir_inodes_reconnected); } } if (inodes_not_reconnected > 0) { if (inodes_not_reconnected == 1) { fsck_send_msg(fsck_MNCNTRCNCTINOSF, inodes_not_reconnected); } else { fsck_send_msg(fsck_MNCNTRCNCTINOSFS, inodes_not_reconnected); } } if (inodes_reconnected > 0) { if (inodes_reconnected == 1) { fsck_send_msg(fsck_INOSINLSFNF, inodes_reconnected); } else { fsck_send_msg(fsck_INOSINLSFNFS, inodes_reconnected); } } } return (rfsi_rc); } /***************************************************************************** * NAME: rebuild_dir_index * * FUNCTION: If the directory index was found to be bad, rebuild it from * scratch. * * PARAMETERS: * inoptr - input - pointer to the directory inode in an fsck * buffer * inorecptr - input - pointer to an fsck inode record describing * the inode * * RETURNS: * success: FSCK_OK * failure: something else */ int rebuild_dir_index(struct dinode *inoptr, struct fsck_inode_record *inorecptr) { int64_t addr; struct dtreeQelem *current_Qel; int dtidx; dtpage_t *dtree; int n; int rc; int8_t *stbl; inoptr->di_next_index = 2; inoptr->di_size = 1; /* Recalculate di_nblocks */ inoptr->di_nblocks = 0; if (inoptr->di_ea.flag == DXD_EXTENT) inoptr->di_nblocks += lengthDXD(&inoptr->di_ea); if (inoptr->di_acl.flag == DXD_EXTENT) inoptr->di_nblocks += lengthDXD(&inoptr->di_acl); rc = dtreeQ_get_elem(¤t_Qel); if (rc) return rc; current_Qel->node_level = 0; dtree = (dtpage_t *)&inoptr->di_btroot; stbl = ((dtroot_t *)dtree)->header.stbl; addr = 0; while (current_Qel) { if (dtree->header.flag & BT_LEAF) { struct ldtentry *ldtptr; for (dtidx = 0; dtidx < dtree->header.nextindex; dtidx++) { n = stbl[dtidx]; ldtptr = (struct ldtentry *)&dtree->slot[n]; /* * TODO: insert entry into dir index table * and add the real cookie here */ ldtptr->index = 0; } if (addr) { /* non-root */ ujfs_swap_dtpage_t(dtree, sb_ptr->s_flag); dtree->header.flag &= ~BT_SWAPPED; rc = ujfs_rw_diskblocks(Dev_IOPort, addr << sb_ptr->s_l2bsize, PSIZE, dtree, PUT); ujfs_swap_dtpage_t(dtree, sb_ptr->s_flag); dtree->header.flag |= BT_SWAPPED; if (rc) return rc; } } else { /* internal node */ struct idtentry *idtptr; struct dtreeQelem *new_Qelptr; for (dtidx = 0; dtidx < dtree->header.nextindex; dtidx++) { n = stbl[dtidx]; idtptr = (struct idtentry *)&dtree->slot[n]; rc = dtreeQ_get_elem(&new_Qelptr); if (rc) return rc; new_Qelptr->node_addr = addressPXD(&idtptr->xd); dtreeQ_enqueue(new_Qelptr); } } dtreeQ_rel_elem(current_Qel); dtreeQ_dequeue(¤t_Qel); if (current_Qel) { inoptr->di_nblocks++; addr = current_Qel->node_addr; rc = dnode_get(addr, PSIZE, &dtree); if (rc) return rc; stbl = (int8_t *)&dtree->slot[dtree->header.stblindex]; } } return FSCK_OK; } jfsutils-1.1.15.orig/fsck/fsckea.c0000644000000000000000000000447710340701412013621 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "xfsck.h" #include "jfs_byteorder.h" /* some macros for dealing with variable length EA lists. */ #define FEA_SIZE(ea) (__le16_to_cpu((ea)->cbValue) + (ea)->cbName + 1 + \ sizeof (struct FEA)) #define NEXT_FEA(ea) ((struct FEA*)(((char *) (ea)) + (FEA_SIZE (ea)))) #define GEA_SIZE(ea) ((ea)->cbName + sizeof (GEA)) #define NEXT_GEA(ea) ((GEA*)(((char *) (ea)) + (GEA_SIZE (ea)))) /* an extended attribute consists of a double with * being restricted to a subset of the 8 bit ASCII character set. this * table both defines valid characters for and provides a lower-case * to upper-case mapping. */ #define CH_BAD_EA '\0' /* * jfs_ValidateFEAList -- validate structure of an FEALIST */ int jfs_ValidateFEAList(struct FEALIST *pfeal, int size, unsigned long *poError) { unsigned int cbLeft; /* count of bytes left in FEA list */ struct FEA *pfea = pfeal->list; /* pointer to current FEA */ unsigned int cbFEA; /* count of bytes in current FEA */ cbLeft = __le32_to_cpu(pfeal->cbList); if (size != cbLeft) return ERROR_EA_LIST_INCONSISTENT; cbLeft -= sizeof (pfeal->cbList); if (cbLeft == 0) return 0; do { /* check for our reserved bits */ if (pfea->fEA & ~(FEA_NEEDEA) || cbLeft < sizeof *pfea) return ERROR_EA_LIST_INCONSISTENT; cbFEA = FEA_SIZE(pfea); pfea = NEXT_FEA(pfea); if (cbLeft < cbFEA) { *poError = (((char *) pfea) - ((char *) pfeal)); return ERROR_EA_LIST_INCONSISTENT; } } while ((cbLeft -= cbFEA) > 0); return 0; } jfsutils-1.1.15.orig/fsck/fsckimap.c0000644000000000000000000040230710441103233014153 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include /* defines and includes common among the fsck.jfs modules */ #include "xfsckint.h" #include "jfs_byteorder.h" #include "devices.h" #include "utilsubs.h" /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * superblock buffer pointer * * defined in xchkdsk.c */ extern struct superblock *sb_ptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * fsck aggregate info structure pointer * * defined in xchkdsk.c */ extern struct fsck_agg_record *agg_recptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * For message processing * * defined in xchkdsk.c */ extern char *Vol_Label; /* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV * * The following are internal to this file * */ struct fsck_iag_info { struct iag *iagptr; struct dinomap *iamctlptr; struct fsck_iam_record *iamrecptr; struct fsck_iag_record *iagtbl; struct fsck_ag_record *agtbl; int8_t agg_inotbl; struct fsck_imap_msg_info *msg_info_ptr; }; struct xtree_buf { struct xtree_buf *down; /* next rightmost child */ struct xtree_buf *up; /* parent */ xtpage_t *page; }; static struct xtree_buf *fsim_node_pages; /* --------------------------------------------------------------*/ int agfrext_lists_scan(int, int, int, struct fsck_iag_info *, int *, struct fsck_imap_msg_info *); int agfrext_lists_validation(int, int, struct fsck_ag_record *, int *, struct fsck_imap_msg_info *); int agfrino_lists_scan(int, int, int, struct fsck_iag_info *, int *, struct fsck_imap_msg_info *); int agfrino_lists_validation(int, int, struct fsck_ag_record *, int *, struct fsck_imap_msg_info *); int AIM_check(xtpage_t *, char *, int *); int AIM_replication(int8_t, xtpage_t *, char *, int8_t *); int AIS_inode_check(struct dinode *, struct dinode *, int32_t, int32_t, int *); int AIS_inode_replication(int8_t, struct dinode *, struct dinode *); int first_refchk_inoexts(int, int, struct fsck_inode_record *, struct fsck_ino_msg_info *); int FSIM_add_extents(xtpage_t *, struct dinode *, int8_t *); int FSIM_check(struct dinode *, struct dinode *, int *); int FSIM_replication(int8_t, struct dinode *, struct dinode *, int8_t *); int iag_alloc_rebuild(int32_t, struct fsck_iag_info *); int iag_alloc_scan(int32_t *, int32_t *, struct fsck_iag_info *, struct fsck_imap_msg_info *); int iag_alloc_ver(int *, int, int32_t, struct fsck_iag_info *, struct fsck_imap_msg_info *); int iagfr_list_scan(int, int, int, struct fsck_iag_info *, int *, struct fsck_imap_msg_info *); int iagfr_list_validation(int *, struct fsck_iam_record *, struct fsck_imap_msg_info *); int iags_finish_lists(int, int, int, struct fsck_iag_info *); int iags_rebuild(int, int, int, struct fsck_iag_info *, struct fsck_imap_msg_info *); int iags_validation(int, int, int, int *, struct fsck_iag_info *, struct fsck_imap_msg_info *); int iamap_rebuild(int, int, int, struct fsck_iag_info *, struct fsck_imap_msg_info *); int iamap_validation(int, int, int, struct fsck_iag_info *, struct fsck_imap_msg_info *); int IM_compare_leaf(xtpage_t *, xtpage_t *, int *); int record_dupchk_inoexts(int, int, int32_t *, struct fsck_inode_record *, struct fsck_ino_msg_info *); int record_imap_info(void); int xtAppend(struct dinode *, int64_t, int64_t, int32_t, struct xtree_buf *); int xtSplitPage(struct dinode *, struct xtree_buf *, int64_t, int32_t, int64_t); int xtSplitRoot(struct dinode *, struct xtree_buf *, int64_t, int32_t, int64_t); /* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV */ /**************************************************************** * NAME: agfrext_lists_scan * * FUNCTION: Scan the Allocation Group free extent lists for the given * inode allocation table. Count the number of iags on each * list. Validate the list structure. * * PARAMETERS: * is_aggregate - input - !0 => aggregate owned * 0 => fileset owned * which_it - input - ordinal number of the aggregate inode * describing the inode table * which_ait - input - the aggregate inode table from which * the it inode should be read * { fsck_primary | fsck_secondary } * iagiptr - input - pointer to a data area describing the * current iag * errors_detected - input - pointer to a variable in which to return * !0 if errors are detected * 0 if no errors are detected * msg_info_ptr - input - pointer to data needed to issue messages * about the current inode allocation map * * NOTES: This routine does NOT attempt to determine whether the iags * on the list belong on the list. It only verifies that the * list is structurally correct, i.e., that the forward and * backward pointers are consistent. * * RETURNS: * success: FSCK_OK * failure: something else */ int agfrext_lists_scan(int is_aggregate, int which_it, int which_ait, struct fsck_iag_info *iagiptr, int *errors_detected, struct fsck_imap_msg_info *msg_info_ptr) { int intermed_rc = FSCK_OK; uint32_t agidx; struct iagctl *agg_agrec; struct fsck_ag_record *wsp_agrec; int end_of_list = -1; int32_t this_iagno, prev_iagno; for (agidx = 0; agidx < MAXAG; agidx++) { agg_agrec = &(iagiptr->iamctlptr->in_agctl[agidx]); wsp_agrec = &(iagiptr->agtbl[agidx]); /* in case list is empty... */ wsp_agrec->frext_list_last = end_of_list; wsp_agrec->frext_list_first = agg_agrec->extfree; wsp_agrec->frext_list_len = 0; prev_iagno = end_of_list; this_iagno = wsp_agrec->frext_list_first; while ((this_iagno != end_of_list) && (!wsp_agrec->frext_list_bad)) { intermed_rc = iag_get(is_aggregate, which_it, which_ait, this_iagno, &(iagiptr->iagptr)); /* * we consider an error here to be an error in the * chain. If it's really something more serious it * will come up again when we go through all allocated * iag's sequentially. */ if (intermed_rc != FSCK_OK) { wsp_agrec->frext_list_bad = -1; break; } /* got the iag */ if (iagiptr->iagptr->extfreeback != prev_iagno) { /* bad back chain */ wsp_agrec->frext_list_bad = -1; break; } /* back chain is correct */ prev_iagno = this_iagno; this_iagno = iagiptr->iagptr->extfreefwd; wsp_agrec->frext_list_len++; } if (wsp_agrec->frext_list_bad) { /* found a problem */ agg_recptr->ag_dirty = 1; *errors_detected = -1; fsck_send_msg(fsck_BADAGFELIST, fsck_ref_msg(msg_info_ptr->msg_mapowner), agidx, "1"); } else { wsp_agrec->frext_list_last = prev_iagno; } } return FSCK_OK; } /**************************************************************** * NAME: agfrext_lists_validation * * FUNCTION: Compare the results of the Allocation Group free extent lists * scan with the results of validating the iags. If the number * of iags seen on a list during the list scan does not equal * the number of iags which appear to be on the list (i.e., which * have non-initialized values for forward and back pointers) * as seen during iag validation, then the list is not structurally * consistent. * * PARAMETERS: * is_aggregate - input - !0 => aggregate owned * 0 => fileset owned * which_it - input - ordinal number of the aggregate inode * describing the inode table * agtbl - input - pointer to the fsck workspace allocation * group table for the specified inode * table * errors_detected - input - pointer to a variable in which to return * !0 if errors are detected * 0 if no errors are detected * msg_info_ptr - input - pointer to data needed to issue messages * about the current inode allocation map * * NOTES: o This routine is only called in the read-only path. * * o This routine is NOT called if any structural errors have * already been detected in the list. * * RETURNS: * success: FSCK_OK * failure: something else */ int agfrext_lists_validation(int is_aggregate, int which_it, struct fsck_ag_record *agtbl, int *errors_detected, struct fsck_imap_msg_info *msg_info_ptr) { uint32_t agidx; struct fsck_ag_record *wsp_agrec; for (agidx = 0; agidx < MAXAG; agidx++) { wsp_agrec = &(agtbl[agidx]); if (!wsp_agrec->frino_list_bad) { /* the list itself looked ok */ if (wsp_agrec->frext_list_len > 0) { /* * fsck observed fewer iag's which belong on * this list than it counted when it scanned * the list. (fsck has already issued messages * about these iag's) */ *errors_detected = -1; agg_recptr->ag_dirty = 1; } else if (wsp_agrec->frext_list_len < 0) { /* * fsck observed more iag's which belong on * this list and which appear to be on the list * than it counted when it scanned the list. * So the chain has somehow lost some of its * links. */ *errors_detected = -1; agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_BADAGFELIST1, fsck_ref_msg(msg_info_ptr->msg_mapowner), agidx); } } } return (FSCK_OK); } /**************************************************************** * NAME: agfrino_lists_scan * * FUNCTION: Scan the Allocation Group free inode lists for the given * inode allocation table. Count the number of iags on each * list. Validate the list structure. * * PARAMETERS: * is_aggregate - input - !0 => aggregate owned * 0 => fileset owned * which_it - input - ordinal number of the aggregate inode * describing the inode table * which_ait - input - the aggregate inode table from which * the it inode should be read * { fsck_primary | fsck_secondary } * iagiptr - input - pointer to a data area describing the * current iag * errors_detected - input - pointer to a variable in which to return * !0 if errors are detected * 0 if no errors are detected * msg_info_ptr - input - pointer to data needed to issue messages * about the current inode allocation map * * NOTES: This routine does NOT attempt to determine whether the iags * on the list belong on the list. It only verifies that the * list is structurally correct, i.e., that the forward and * backward pointers are consistent. * * RETURNS: * success: FSCK_OK * failure: something else */ int agfrino_lists_scan(int is_aggregate, int which_it, int which_ait, struct fsck_iag_info *iagiptr, int *errors_detected, struct fsck_imap_msg_info *msg_info_ptr) { int intermed_rc = FSCK_OK; uint32_t agidx; struct iagctl *agg_agrec; struct fsck_ag_record *wsp_agrec; int end_of_list = -1; int32_t this_iagno, prev_iagno; for (agidx = 0; agidx < MAXAG; agidx++) { agg_agrec = &(iagiptr->iamctlptr->in_agctl[agidx]); wsp_agrec = &(iagiptr->agtbl[agidx]); /* in case list is empty... */ wsp_agrec->frino_list_last = end_of_list; wsp_agrec->frino_list_first = agg_agrec->inofree; wsp_agrec->frino_list_len = 0; prev_iagno = end_of_list; this_iagno = wsp_agrec->frino_list_first; while ((this_iagno != end_of_list) && (!wsp_agrec->frino_list_bad)) { intermed_rc = iag_get(is_aggregate, which_it, which_ait, this_iagno, &(iagiptr->iagptr)); /* * we consider an error here to be an error in the * chain. If it's really something more serious it * will come up again when we go through all allocated * iag's sequentially. */ if (intermed_rc != FSCK_OK) { wsp_agrec->frino_list_bad = -1; break; } /* got the iag */ if (iagiptr->iagptr->inofreeback != prev_iagno) /* bad back chain */ wsp_agrec->frino_list_bad = -1; else { /* back chain is correct */ prev_iagno = this_iagno; this_iagno = iagiptr->iagptr->inofreefwd; wsp_agrec->frino_list_len++; } } if (wsp_agrec->frino_list_bad) { /* found a problem */ agg_recptr->ag_dirty = 1; *errors_detected = -1; fsck_send_msg(fsck_BADAGFILIST, fsck_ref_msg(msg_info_ptr->msg_mapowner), agidx, "1"); } else wsp_agrec->frino_list_last = prev_iagno; } return (FSCK_OK); } /**************************************************************** * NAME: agfrino_lists_validation * * FUNCTION: Compare the results of the Allocation Group free inode lists * scan with the results of validating the iags. If the number * of iags seen on a list during the list scan does not equal * the number of iags which appear to be on the list (i.e., which * have non-initialized values for forward and back pointers) * as seen during iag validation, then the list is not structurally * consistent. * * PARAMETERS: * is_aggregate - input - !0 => aggregate owned * 0 => fileset owned * which_it - input - ordinal number of the aggregate inode * describing the inode table * agtbl - input - pointer to the fsck workspace allocation * group table for the specified inode * table * errors_detected - input - pointer to a variable in which to return * !0 if errors are detected * 0 if no errors are detected * msg_info_ptr - input - pointer to data needed to issue messages * about the current inode allocation map * * NOTES: o This routine is only called in the read-only path. * * o This routine is NOT called if any structural errors have * already been detected in the list. * * RETURNS: * success: FSCK_OK * failure: something else */ int agfrino_lists_validation(int is_aggregate, int which_it, struct fsck_ag_record *agtbl, int *errors_detected, struct fsck_imap_msg_info *msg_info_ptr) { uint32_t agidx; struct fsck_ag_record *wsp_agrec; for (agidx = 0; agidx < MAXAG; agidx++) { wsp_agrec = &(agtbl[agidx]); if (!wsp_agrec->frino_list_bad) { /* the list itself looked ok */ if (wsp_agrec->frino_list_len > 0) { /* * fsck observed fewer iag's which belong on * this list than it counted when it scanned * the list. (fsck has already issued * messages about these iag's) */ *errors_detected = -1; agg_recptr->ag_dirty = 1; } else if (wsp_agrec->frino_list_len < 0) { /* * fsck observed more iag's which belong on * this list and which appear to be on the list * than it counted when it scanned the list. * So the chain has somehow lost some of its * links. */ *errors_detected = -1; agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_BADAGFILIST1, fsck_ref_msg(msg_info_ptr->msg_mapowner), agidx); } } } return (FSCK_OK); } /**************************************************************** * NAME: AIM_check * * FUNCTION: Verify that the Secondary Aggregate Inode Map is correct * and that it is a logical equivalent to the Primary Aggregate * Inode Map. * * PARAMETERS: * secondary_btroot - input - pointer to the root of the B+ Tree * root in of the secondary aggregate * inode table inode in an fsck buffer. * temp_bufptr - input - pointer to a temporary I/O buffer, * large enough for an inode extent. * inconsistency_detected - input - pointer to a variable in which * to return !0 if errors are detected * 0 if no errors are detected * * * NOTES: o This routine reads the Primary Aggregate Inode Map into the * the first page of the fsck temporary inode buffer and reads * the Secondary Aggregate Inode Map into the 3rd page of the * fsck temporary inode buffer. * * o In release 1, there is always exactly 1 iag in the Aggregate * Inode Map and so the inode which represents the map always has * a root-leaf B+ tree rooted in it. * * RETURNS: * success: FSCK_OK * failure: something else */ int AIM_check(xtpage_t * secondary_btroot, char *temp_bufptr, int *inconsistency_detected) { int intermed_rc = FSCK_OK; char *primary_bufptr = NULL, *secondary_bufptr = NULL; struct dinomap *primary_ctlptr, *secondary_ctlptr; struct iag *primary_iagptr; struct iag *secondary_iagptr; uint8_t expected_flag; int64_t sb_aim2_addr, btrt_aim2_addr; uint32_t sb_aim2_length, btrt_aim2_length; int64_t byte_offset; uint32_t bytes_wanted, bytes_read; expected_flag = (BT_ROOT | BT_LEAF | DXD_INDEX); sb_aim2_addr = addressPXD(&(sb_ptr->s_aim2)); sb_aim2_length = lengthPXD(&(sb_ptr->s_aim2)); btrt_aim2_addr = addressXAD(&(secondary_btroot->xad[XTENTRYSTART])); btrt_aim2_length = lengthXAD(&(secondary_btroot->xad[XTENTRYSTART])); if ((secondary_btroot->header.flag != expected_flag) || (secondary_btroot->header.nextindex != (XTENTRYSTART + 1)) || (sb_aim2_addr != btrt_aim2_addr) || (sb_aim2_length != btrt_aim2_length)) goto inconsistency_found; /* descriptors match */ primary_bufptr = temp_bufptr; secondary_bufptr = (char *) (temp_bufptr + (2 * BYTESPERPAGE)); byte_offset = AIMAP_OFF; bytes_wanted = sb_aim2_length * sb_ptr->s_bsize; intermed_rc = readwrite_device(byte_offset, bytes_wanted, &bytes_read, (void *) primary_bufptr, fsck_READ); if ((intermed_rc != FSCK_OK) || (bytes_wanted != bytes_read)) goto inconsistency_found; /* primary AIM is in the buffer */ byte_offset = sb_aim2_addr * sb_ptr->s_bsize; bytes_wanted = sb_aim2_length * sb_ptr->s_bsize; intermed_rc = readwrite_device(byte_offset, bytes_wanted, &bytes_read, (void *) secondary_bufptr, fsck_READ); if ((intermed_rc != FSCK_OK) || (bytes_wanted != bytes_read)) goto inconsistency_found; /* endian - swap not needed as these 2 structs are read * from disk and checked for inconsistencies. * the AIMaps are in the temp buffer */ primary_ctlptr = (struct dinomap *) primary_bufptr; secondary_ctlptr = (struct dinomap *) secondary_bufptr; if ((primary_ctlptr->in_freeiag != secondary_ctlptr->in_freeiag) || (primary_ctlptr->in_nextiag != secondary_ctlptr->in_nextiag) || (primary_ctlptr->in_numinos != secondary_ctlptr->in_numinos) || (primary_ctlptr->in_numfree != secondary_ctlptr->in_numfree) || (primary_ctlptr->in_nbperiext != secondary_ctlptr->in_nbperiext) || (primary_ctlptr->in_l2nbperiext != secondary_ctlptr->in_l2nbperiext)) goto inconsistency_found; if (memcmp((void *) &(primary_ctlptr->in_agctl[0]), (void *) &(secondary_ctlptr->in_agctl[0]), (sizeof (struct iagctl) * MAXAG))) goto inconsistency_found; /* * the AIMaps are in the temp buffer and * the control pages are consistent */ primary_iagptr = (struct iag *) (primary_bufptr + BYTESPERPAGE); secondary_iagptr = (struct iag *) (secondary_bufptr + BYTESPERPAGE); if ((primary_iagptr->agstart != secondary_iagptr->agstart) || (primary_iagptr->iagnum != secondary_iagptr->iagnum) || (primary_iagptr->inofreefwd != secondary_iagptr->inofreefwd) || (primary_iagptr->inofreeback != secondary_iagptr->inofreeback) || (primary_iagptr->extfreefwd != secondary_iagptr->extfreefwd) || (primary_iagptr->extfreeback != secondary_iagptr->extfreeback) || (primary_iagptr->iagfree != secondary_iagptr->iagfree) || (primary_iagptr->nfreeinos != secondary_iagptr->nfreeinos) || (primary_iagptr->nfreeexts != secondary_iagptr->nfreeexts)) goto inconsistency_found; if (memcmp((void *) &(primary_iagptr->inosmap[0]), (void *) &(secondary_iagptr->inosmap[0]), (sizeof (int32_t) * SMAPSZ))) goto inconsistency_found; if (memcmp((void *) &(primary_iagptr->extsmap[0]), (void *) &(secondary_iagptr->extsmap[0]), (sizeof (int32_t) * SMAPSZ))) goto inconsistency_found; if (memcmp((void *) &(primary_iagptr->pmap[0]), (void *) &(secondary_iagptr->pmap[0]), (sizeof (int32_t) * EXTSPERIAG))) goto inconsistency_found; if (memcmp((void *) &(secondary_iagptr->inoext[0]), (void *) &(sb_ptr->s_ait2), sizeof (pxd_t))) goto inconsistency_found; return (FSCK_OK); inconsistency_found: /* * future recover capability is compromised * * Note that we're in read-only mode or we wouldn't be checking * this (because when we have write access we always rebuild it) */ fsck_send_msg(fsck_INCONSIST2NDRY, "1"); *inconsistency_detected = 1; return (FSCK_OK); } /**************************************************************** * NAME: AIM_replication * * FUNCTION: Rebuild specified target Aggregate Inode Map so that it is * a logical equivalent to the specified source Aggregate Inode * Map. * * PARAMETERS: * source_is_primary - input - !0 => replicate from primary to secondary * 0 => replicate from secondary to primary * target_btroot - input - pointer to the B+ Tree root in the * aggregate inode allocation table (either * primary or secondary) inode which is * the target of the replication. * temp_bufptr - input - pointer to a temporary I/O buffer, * large enough for an inode extent. * replication_failure - input - pointer to a variable in which to return * !0 if errors occurred during replication * 0 if the replication was successful * * NOTES: o This routine considers the buffer for the Primary Aggregate * Inode Map to begin at the beginning of the fsck temporary * inode buffer. This routine considers the buffer for the * Secondary Aggregate Inode Map to begin at the 3rd page * of the fsck temporary inode buffer. * * o This routine reads the source Aggregate Inode Map (either * primary or secondary) into its buffer (see note above) and * rebuilds the target Aggregate Inode Map (either secondary * or primary) in its buffer. * * o In release 1, there is always exactly 1 iag in the Aggregate * Inode Map and so the inode which represents the map always has * a root-leaf B+ tree rooted in it. * * RETURNS: * success: FSCK_OK * failure: something else */ int AIM_replication(int8_t source_is_primary, xtpage_t * target_btroot, char *temp_bufptr, int8_t * replication_failure) { int aimr_rc = FSCK_OK; int intermed_rc = FSCK_OK; char *target_bufptr, *source_bufptr; struct iag *target_iagptr; int64_t source_byte_offset = 0, target_byte_offset = 0; uint32_t bytes_wanted, bytes_transferred; target_btroot->header.flag = (BT_ROOT | BT_LEAF | DXD_INDEX); target_btroot->header.nextindex = XTENTRYSTART + 1; source_bufptr = temp_bufptr; target_bufptr = (char *) (temp_bufptr + (2 * BYTESPERPAGE)); target_iagptr = (struct iag *) (target_bufptr + BYTESPERPAGE); if (source_is_primary) { source_byte_offset = AIMAP_OFF; target_byte_offset = addressPXD(&(sb_ptr->s_aim2)) * sb_ptr->s_bsize; XADaddress(&(target_btroot->xad[XTENTRYSTART]), addressPXD(&(sb_ptr->s_aim2))); XADlength(&(target_btroot->xad[XTENTRYSTART]), lengthPXD(&(sb_ptr->s_aim2))); } else { source_byte_offset = addressPXD(&(sb_ptr->s_aim2)) * sb_ptr->s_bsize; target_byte_offset = AIMAP_OFF; XADaddress(&(target_btroot->xad[XTENTRYSTART]), (AIMAP_OFF / sb_ptr->s_bsize)); XADlength(&(target_btroot->xad[XTENTRYSTART]), lengthPXD(&sb_ptr->s_aim2)); } bytes_wanted = lengthPXD(&(sb_ptr->s_aim2)) * sb_ptr->s_bsize; intermed_rc = readwrite_device(source_byte_offset, bytes_wanted, &bytes_transferred, (void *) source_bufptr, fsck_READ); if ((intermed_rc != FSCK_OK) || (bytes_wanted != bytes_transferred)) { aimr_rc = FSCK_FAILED_CANTREADAIMNOW; /* * message to the user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to the debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_CANTREADAIMNOW, intermed_rc, fsck_READ, (long long) source_byte_offset, bytes_wanted, bytes_transferred); goto aimr_exit; } /* the source AIMap is in the temp buffer */ /* * copy the source over the target, then adjust the field(s) which * should be different. */ memcpy((void *) target_bufptr, (void *) source_bufptr, bytes_wanted); memcpy((void *) &(target_iagptr->inoext[0]), (void *) &(sb_ptr->s_ait2), sizeof (pxd_t)); if (!source_is_primary) { XADaddress(&(target_iagptr->inoext[0]), (AITBL_OFF / sb_ptr->s_bsize)); } /* endian - don't need to swap either read or write in this routine. * Basically, source struct is read from disk, copied to target, * changes made, and written back. * * now write the redundant AIMap to the device */ aimr_rc = readwrite_device(target_byte_offset, bytes_wanted, &bytes_transferred, (void *) target_bufptr, fsck_WRITE); agg_recptr->ag_modified = 1; if ((aimr_rc != FSCK_OK) || (bytes_wanted != bytes_transferred)) { /* some or all didn't make it to the device. */ agg_recptr->ait_aim_update_failed = 1; if (!source_is_primary) { /* we're trying to repair the primary * table and can't -- that makes this a * dirty file system. */ agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_CANTREPAIRAIS, "1"); } else { /* trying to repair the secondary table and can't * * We won't stop fsck and we won't mark the file system * dirty on this condition, but we'll issue a warning * and mark the superblock to prevent future attempts * to maintain the flawed table. */ *replication_failure = -1; fsck_send_msg(fsck_INCONSIST2NDRY1, "1"); } } aimr_exit: return (aimr_rc); } /**************************************************************** * NAME: AIS_inode_check * * FUNCTION: Compare the specified Primary Inode Allocation Table inode * to its (specified) Secondary Inode Allocation Table counterpart * to ensure that they are logically equivalent. * * PARAMETERS: * primary_inoptr - input - pointer to an inode in the primary * aggregate inode allocation table * in an fsck buffer * secondary_inoptr - input - pointer to the equivalent inode in * the secondary aggregate inode * allocation table in an fsck buffer * tree_offset - input - the offset of the B+ Tree rooted * in the inode * tree_size - input - the number of inodes bytes occupied * by the B+ tree rooted in the inode * inconsistency_detected - input - pointer to a variable in which * to return !0 if errors are detected * 0 if no errors are detected * * RETURNS: * success: FSCK_OK * failure: something else */ int AIS_inode_check(struct dinode *primary_inoptr, struct dinode *secondary_inoptr, int32_t tree_offset, int32_t tree_size, int *inconsistency_detected) { xtpage_t *primary_root, *secondary_root; int32_t result1, result2, result3, result4, result5, result6; *inconsistency_detected = ((primary_inoptr->di_inostamp != secondary_inoptr->di_inostamp) || (primary_inoptr->di_fileset != secondary_inoptr->di_fileset) || (primary_inoptr->di_number != secondary_inoptr->di_number) || (primary_inoptr->di_gen != secondary_inoptr->di_gen) || (primary_inoptr->di_size != secondary_inoptr->di_size) || (primary_inoptr->di_nblocks != secondary_inoptr->di_nblocks) || (primary_inoptr->di_nlink != secondary_inoptr->di_nlink) || (primary_inoptr->di_uid != secondary_inoptr->di_uid) || (primary_inoptr->di_gid != secondary_inoptr->di_gid) || (primary_inoptr->di_mode != secondary_inoptr->di_mode) || (primary_inoptr->di_next_index != secondary_inoptr->di_next_index)); if (!(*inconsistency_detected)) { if (tree_offset == 0) { result1 = 0; } else { /* tree compare needed */ primary_root = (xtpage_t *) (((char *) primary_inoptr) + tree_offset); secondary_root = (xtpage_t *) (((char *) primary_inoptr) + tree_offset); result1 = memcmp((void *) primary_root, (void *) secondary_root, tree_size); } result2 = memcmp((void *) &(primary_inoptr->di_atime), (void *) &(secondary_inoptr->di_atime), sizeof (primary_inoptr->di_atime)); result3 = memcmp((void *) &(primary_inoptr->di_ctime), (void *) &(secondary_inoptr->di_ctime), sizeof (primary_inoptr->di_ctime)); result4 = memcmp((void *) &(primary_inoptr->di_mtime), (void *) &(secondary_inoptr->di_mtime), sizeof (primary_inoptr->di_mtime)); result5 = memcmp((void *) &(primary_inoptr->di_otime), (void *) &(secondary_inoptr->di_otime), sizeof (primary_inoptr->di_otime)); result6 = memcmp((void *) &(primary_inoptr->di_ea), (void *) &(secondary_inoptr->di_ea), sizeof (primary_inoptr->di_ea)); *inconsistency_detected = (result1 || result2 || result3 || result4 || result5 || result6); } if (!(*inconsistency_detected)) { *inconsistency_detected = memcmp((void *) &(sb_ptr->s_ait2), (void *) &(secondary_inoptr-> di_ixpxd), sizeof (pxd_t)); } if ((*inconsistency_detected)) { /* future recover capability is compromised */ /* * Note that we're in read-only mode or we wouldn't be checking * this (because when we have write access we always rebuild it) */ fsck_send_msg(fsck_INCONSIST2NDRY, "2"); } return (FSCK_OK); } /**************************************************************** * NAME: AIS_inode_replication * * FUNCTION: Rebuild the specified target inode by making it the logical * equivalent of the specified source inode. * * PARAMETERS: * source_is_primary - input - !0 => replicate from primary to secondary * 0 => replicate from secondary to primary * target_inoptr - input - address of an inode in the aggregate * inode allocation table (primary or * secondary) which is the target of the * replication * source_inoptr - input - address of the equivalent inode in the * aggregate inode allocation table (secondary * or primary) which is the source of the * secondary) which is the target of the * replication * * NOTES: o The caller to this routine must ensure that the first extent * of the primary aggregate inode allocation table is at the * beginning of the fsck temporary inode buffer and that the * first extent of the secondary aggregate inode allocation map * immediately follows it in the fsck temporary inode buffer. * * RETURNS: * success: FSCK_OK * failure: something else */ int AIS_inode_replication(int8_t source_is_primary, struct dinode *target_inoptr, struct dinode *source_inoptr) { int aisir_rc = FSCK_OK; int64_t ext_offset; /* * copy the source over the target, then adjust the field(s) which * should be different. */ memcpy((void *) target_inoptr, (void *) source_inoptr, sizeof (struct dinode)); if (source_is_primary) { memcpy((void *) &(target_inoptr->di_ixpxd), (void *) &(sb_ptr->s_ait2), sizeof (pxd_t)); } else { ext_offset = AITBL_OFF / sb_ptr->s_bsize; PXDaddress(&(target_inoptr->di_ixpxd), ext_offset); PXDlength(&(target_inoptr->di_ixpxd), lengthPXD(&sb_ptr->s_ait2)); } return (aisir_rc); } /**************************************************************** * NAME: AIS_redundancy_check * * FUNCTION: Verify that the Secondary Aggregate Inode structures are * logically equivalent to the Primary Aggregate Inode structures. * * PARAMETERS: none * * NOTES: o The "aggregate inode structures" are the Aggregate Inode Map * and the Aggregate Inode Table. * * o This routine reads the first extent of the Primary Aggregate * Inode Table into the first page of the fsck temporary inode * buffer and reads the first extent of the Secondary Aggregate * Inode table into the regular fsck inode buffer. * * RETURNS: * success: FSCK_OK * failure: something else */ int AIS_redundancy_check() { int aisrc_rc = FSCK_OK; struct dinode *primary_inoptr, *secondary_inoptr; xtpage_t *secondary_ait_root = NULL; char *primary_bufptr, *secondary_bufptr; int32_t inode_offset; int inconsistency_detected = 0; int32_t tree_offset, treesize; struct fsck_inode_record temp_inorec; struct fsck_inode_record *temp_inorecptr = &temp_inorec; struct fsck_ino_msg_info temp_msg_info; struct fsck_ino_msg_info *temp_msg_infoptr = &temp_msg_info; aisrc_rc = temp_inode_buf_alloc(&primary_bufptr); if (aisrc_rc != FSCK_OK) goto aisrc_exit; secondary_bufptr = agg_recptr->ino_buf_ptr; tree_offset = (int32_t) &(((struct dinode *)0)->di_btroot); treesize = sizeof (primary_inoptr->di_DASD) + sizeof (primary_inoptr->di_dxd) + sizeof (primary_inoptr->di_inlinedata); /* allocated the temp buffer */ aisrc_rc = ait_special_read_ext1(fsck_primary); if (aisrc_rc != FSCK_OK) { /* read failed */ report_readait_error(aisrc_rc, FSCK_FAILED_CANTREADAITEXT1, fsck_primary); aisrc_rc = FSCK_FAILED_CANTREADAITEXT1; goto aisrc_exit; } /* primary is in the inode buffer */ memcpy((void *) primary_bufptr, (void *) agg_recptr->ino_buf_ptr, INODE_IO_BUFSIZE); aisrc_rc = ait_special_read_ext1(fsck_secondary); if (aisrc_rc != FSCK_OK) { /* read failed */ report_readait_error(aisrc_rc, FSCK_FAILED_CANTREADAITEXT2, fsck_secondary); aisrc_rc = FSCK_FAILED_CANTREADAITEXT2; goto aisrc_exit; } /* the 2 inode extents are in memory */ /* * the self inode */ inode_offset = AGGREGATE_I * sizeof (struct dinode); primary_inoptr = (struct dinode *) (primary_bufptr + inode_offset); secondary_inoptr = (struct dinode *) (secondary_bufptr + inode_offset); aisrc_rc = AIS_inode_check(primary_inoptr, secondary_inoptr, 0, 0, &inconsistency_detected); if ((aisrc_rc != FSCK_OK) || inconsistency_detected) goto aisrc_exit; secondary_ait_root = (xtpage_t *) & (secondary_inoptr->di_btroot); /* * the block map inode */ inode_offset = BMAP_I * sizeof (struct dinode); primary_inoptr = (struct dinode *) (primary_bufptr + inode_offset); secondary_inoptr = (struct dinode *) (secondary_bufptr + inode_offset); aisrc_rc = AIS_inode_check(primary_inoptr, secondary_inoptr, tree_offset, treesize, &inconsistency_detected); if ((aisrc_rc != FSCK_OK) || inconsistency_detected) goto aisrc_exit; /* * the journal log inode */ inode_offset = LOG_I * sizeof (struct dinode); primary_inoptr = (struct dinode *) (primary_bufptr + inode_offset); secondary_inoptr = (struct dinode *) (secondary_bufptr + inode_offset); aisrc_rc = AIS_inode_check(primary_inoptr, secondary_inoptr, tree_offset, treesize, &inconsistency_detected); if ((aisrc_rc != FSCK_OK) || inconsistency_detected) goto aisrc_exit; /* * the bad block inode */ inode_offset = BADBLOCK_I * sizeof (struct dinode); primary_inoptr = (struct dinode *) (primary_bufptr + inode_offset); secondary_inoptr = (struct dinode *) (secondary_bufptr + inode_offset); aisrc_rc = AIS_inode_check(primary_inoptr, secondary_inoptr, tree_offset, treesize, &inconsistency_detected); if ((aisrc_rc != FSCK_OK) || inconsistency_detected) goto aisrc_exit; /* and finally the filesystem inode */ inode_offset = FILESYSTEM_I * sizeof (struct dinode); primary_inoptr = (struct dinode *) (primary_bufptr + inode_offset); secondary_inoptr = (struct dinode *) (secondary_bufptr + inode_offset); aisrc_rc = AIS_inode_check(primary_inoptr, secondary_inoptr, 0, 0, &inconsistency_detected); if ((aisrc_rc != FSCK_OK) || inconsistency_detected) goto aisrc_exit; temp_inorecptr->inonum = FILESYSTEM_I; temp_inorecptr->in_use = 0; temp_inorecptr->selected_to_rls = 0; temp_inorecptr->crrct_link_count = 0; temp_inorecptr->crrct_prnt_inonum = 0; temp_inorecptr->adj_entries = 0; temp_inorecptr->cant_chkea = 0; temp_inorecptr->clr_ea_fld = 0; temp_inorecptr->clr_acl_fld = 0; temp_inorecptr->inlineea_on = 0; temp_inorecptr->inlineea_off = 0; temp_inorecptr->inline_data_err = 0; temp_inorecptr->ignore_alloc_blks = 0; temp_inorecptr->reconnect = 0; temp_inorecptr->unxpctd_prnts = 0; temp_inorecptr->badblk_inode = 0; temp_inorecptr->involved_in_dups = 0; temp_inorecptr->inode_type = metadata_inode; temp_inorecptr->link_count = 0; temp_inorecptr->parent_inonum = 0; temp_inorecptr->ext_rec = NULL; temp_msg_infoptr->msg_inonum = FILESYSTEM_I; temp_msg_infoptr->msg_inopfx = fsck_aggr_inode; temp_msg_infoptr->msg_inotyp = fsck_metadata; temp_msg_infoptr->msg_dxdtyp = 0; /* * need to verify the tree structure in the secondary * aggregate fileset inode and record/dupcheck the * tree nodes (but not the data extents described by * the leaf node(s)). */ aisrc_rc = xTree_processing(secondary_inoptr, FILESYSTEM_I, temp_inorecptr, temp_msg_infoptr, FSCK_FSIM_RECORD_DUPCHECK); if (temp_inorecptr->involved_in_dups || temp_inorecptr->selected_to_rls || temp_inorecptr->ignore_alloc_blks) { inconsistency_detected = -1; aisrc_rc = xTree_processing(secondary_inoptr, FILESYSTEM_I, temp_inorecptr, temp_msg_infoptr, FSCK_FSIM_UNRECORD); /* * Note that we're in read-only mode or we wouldn't be * checking this (because when we have write access we * always rebuild it) */ fsck_send_msg(fsck_INCONSIST2NDRY, "4"); } else { /* the tree is good and its nodes have been recorded */ aisrc_rc = FSIM_check(primary_inoptr, secondary_inoptr, &inconsistency_detected); } if ((aisrc_rc != FSCK_OK) || inconsistency_detected) goto aisrc_exit; /* * no problems detected in the AIT -- * now verify the secondary AIM */ aisrc_rc = AIM_check(secondary_ait_root, primary_bufptr, &inconsistency_detected); aisrc_exit: temp_inode_buf_release(primary_bufptr); return (aisrc_rc); } /**************************************************************** * NAME: AIS_replication * * FUNCTION: Rebuild the aggregate inode structures so that the Secondary * Aggregate Inode structures are logically equivalent to the * Primary Aggregate Inode structures. * * PARAMETERS: none * * NOTES: o Since the roles of source and target AIT can change * during this routine, we read both source and target * so that when we write we preserve the portion of the * target extent which is really a source. * (This is simpler than attempting to write individual * inodes and dealing with the question of device block * size larger than an inode.) * * o The "aggregate inode structures" are the Aggregate Inode Map * and the Aggregate Inode Table. * * o This routine reads the first extent of one Aggregate Inode * Table into the fsck temporary inode buffer and reads the * first extent of the other Aggregate Inode Table into the * regular fsck inode buffer. * * RETURNS: * success: FSCK_OK * failure: something else */ int AIS_replication() { int aisr_rc = FSCK_OK; int intermed_rc = FSCK_OK; struct dinode *source_inoptr, *target_inoptr; int64_t target_byte_offset = 0; xtpage_t *target_ait_root = 0; char *source_bufptr, *target_bufptr; int32_t inode_offset; int8_t source_is_primary, extents_in_memory; int8_t replication_failed = 0; uint32_t bytes_transferred; aisr_rc = temp_inode_buf_alloc(&source_bufptr); target_bufptr = agg_recptr->ino_buf_ptr; if (aisr_rc != FSCK_OK) goto aisr_exit; /* allocated the temp buffer */ /* * the filesystem inode could have different source-target than the * rest of the table, so deal with it first. */ extents_in_memory = 0; if (agg_recptr->primary_ait_4part2) { /* * primary for fileset inode source */ source_is_primary = -1; aisr_rc = ait_special_read_ext1(fsck_primary); if (aisr_rc != FSCK_OK) { /* read failed */ report_readait_error(aisr_rc, FSCK_FAILED_CANTREADAITEXT3, fsck_primary); aisr_rc = FSCK_FAILED_CANTREADAITEXT3; goto aisr_release; } } else { /* secondary for fileset inode source */ source_is_primary = 0; aisr_rc = ait_special_read_ext1(fsck_secondary); if (aisr_rc != FSCK_OK) { /* read failed */ report_readait_error(aisr_rc, FSCK_FAILED_CANTREADAITEXT4, fsck_secondary); aisr_rc = FSCK_FAILED_CANTREADAITEXT4; goto aisr_release; } } /* source is in the inode buffer */ memcpy((void *) source_bufptr, (void *) agg_recptr->ino_buf_ptr, INODE_IO_BUFSIZE); if (agg_recptr->primary_ait_4part2) { /* secondary for fileset inode target */ aisr_rc = ait_special_read_ext1(fsck_secondary); if (aisr_rc != FSCK_OK) { /* read failed */ report_readait_error(aisr_rc, FSCK_FAILED_CANTREADAITEXT5, fsck_secondary); aisr_rc = FSCK_FAILED_CANTREADAITEXT5; goto aisr_release; } target_byte_offset = addressPXD(&(sb_ptr->s_ait2)) * sb_ptr->s_bsize; } else { /* primary for fileset inode target */ aisr_rc = ait_special_read_ext1(fsck_primary); if (aisr_rc != FSCK_OK) { /* read failed */ report_readait_error(aisr_rc, FSCK_FAILED_CANTREADAITEXT6, fsck_primary); aisr_rc = FSCK_FAILED_CANTREADAITEXT6; goto aisr_release; } target_byte_offset = AITBL_OFF; } /* the 2 inode extents for the fileset inode are in memory */ extents_in_memory = -1; inode_offset = FILESYSTEM_I * sizeof (struct dinode); source_inoptr = (struct dinode *) (source_bufptr + inode_offset); target_inoptr = (struct dinode *) (target_bufptr + inode_offset); aisr_rc = AIS_inode_replication(source_is_primary, target_inoptr, source_inoptr); if (aisr_rc != FSCK_OK) goto aisr_release; aisr_rc = init_xtree_root(target_inoptr); if (aisr_rc != FSCK_OK) goto aisr_release; aisr_rc = FSIM_replication(source_is_primary, target_inoptr, source_inoptr, &replication_failed); if ((aisr_rc == FSCK_OK) && (replication_failed)) { if (!source_is_primary) { /* we're trying to repair the primary * table and can't -- that makes this a * dirty file system. */ agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_CANTREPAIRAIS, "2"); } else { /* trying to repair the secondary table and can't * * We won't stop fsck and we won't the file system * dirty on this condition, but we'll issue a warning * and the superblock to prevent future attempts to * maintain the flawed table. */ fsck_send_msg(fsck_INCONSIST2NDRY1, "2"); } } if ((aisr_rc != FSCK_OK) || replication_failed) goto aisr_release; if (agg_recptr->primary_ait_4part1 != agg_recptr->primary_ait_4part2) { /* * we need to switch source and target */ /* swap if on big endian machine */ ujfs_swap_inoext((struct dinode *) target_bufptr, PUT, sb_ptr->s_flag); intermed_rc = readwrite_device(target_byte_offset, INODE_EXTENT_SIZE, &bytes_transferred, (void *) target_bufptr, fsck_WRITE); /* swap back */ ujfs_swap_inoext((struct dinode *) target_bufptr, GET, sb_ptr->s_flag); agg_recptr->ag_modified = 1; if ((intermed_rc != FSCK_OK) || (bytes_transferred != INODE_EXTENT_SIZE)) { /* * some or all didn't make it to the device. * */ agg_recptr->ait_aim_update_failed = 1; if (!source_is_primary) { /* we're trying to repair the primary * table and can't -- that makes this a * dirty file system. */ agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_CANTREPAIRAIS, "3"); } else { /* trying to repair the secondary table and * can't * * We won't stop fsck and we won't the file * system dirty on this condition, but we'll * issue a warning and the superblock to * prevent future attempts to maintain the * flawed table. */ replication_failed = -1; fsck_send_msg(fsck_INCONSIST2NDRY1, "3"); } } extents_in_memory = 0; if (agg_recptr->primary_ait_4part1) { /* primary for remaining inodes source */ source_is_primary = -1; aisr_rc = ait_special_read_ext1(fsck_primary); if (aisr_rc != FSCK_OK) { /* read failed */ report_readait_error(aisr_rc, FSCK_FAILED_CANTREADAITEXT7, fsck_primary); aisr_rc = FSCK_FAILED_CANTREADAITEXT7; goto aisr_release; } } else { /* secondary for remaining inodes source */ source_is_primary = 0; aisr_rc = ait_special_read_ext1(fsck_secondary); if (aisr_rc != FSCK_OK) { /* read failed */ report_readait_error(aisr_rc, FSCK_FAILED_CANTREADAITEXT8, fsck_secondary); aisr_rc = FSCK_FAILED_CANTREADAITEXT8; goto aisr_release; } } /* source is in the inode buffer */ memcpy((void *) source_bufptr, (void *) agg_recptr->ino_buf_ptr, INODE_IO_BUFSIZE); if (agg_recptr->primary_ait_4part1) { /* secondary for remaining inodes target */ intermed_rc = ait_special_read_ext1(fsck_secondary); target_byte_offset = addressPXD(&(sb_ptr->s_ait2)) * sb_ptr->s_bsize; if (intermed_rc != FSCK_OK) { /* * message to debugger */ fsck_send_msg(fsck_ERRONAITRD, FSCK_CANTREADAITEXT3, intermed_rc, fsck_secondary); } } else { /* primary for remaining inodes target */ intermed_rc = ait_special_read_ext1(fsck_primary); target_byte_offset = AITBL_OFF; if (intermed_rc != FSCK_OK) { /* * message to debugger */ fsck_send_msg(fsck_ERRONAITRD, FSCK_CANTREADAITEXT4, intermed_rc, fsck_primary); } } if (intermed_rc == FSCK_OK) /* the 2 inode extents for the * remaining inodes are in memory */ extents_in_memory = -1; } if (replication_failed || !extents_in_memory) goto aisr_release; /* we have the extents for the remaining AIT inodes */ /* * the self inode */ inode_offset = AGGREGATE_I * sizeof (struct dinode); source_inoptr = (struct dinode *) (source_bufptr + inode_offset); target_inoptr = (struct dinode *) (target_bufptr + inode_offset); aisr_rc = AIS_inode_replication(source_is_primary, target_inoptr, source_inoptr); if (aisr_rc != FSCK_OK) goto aisr_release; /* aggregate inode replicated in buffer */ target_ait_root = (xtpage_t *) & (target_inoptr->di_btroot); /* * the bmap inode */ inode_offset = BMAP_I * sizeof (struct dinode); source_inoptr = (struct dinode *) (source_bufptr + inode_offset); target_inoptr = (struct dinode *) (target_bufptr + inode_offset); aisr_rc = AIS_inode_replication(source_is_primary, target_inoptr, source_inoptr); if (aisr_rc != FSCK_OK) goto aisr_release; /* * the journal log inode */ inode_offset = LOG_I * sizeof (struct dinode); source_inoptr = (struct dinode *) (source_bufptr + inode_offset); target_inoptr = (struct dinode *) (target_bufptr + inode_offset); aisr_rc = AIS_inode_replication(source_is_primary, target_inoptr, source_inoptr); if (aisr_rc != FSCK_OK) goto aisr_release; /* * the bad block inode */ inode_offset = BADBLOCK_I * sizeof (struct dinode); source_inoptr = (struct dinode *) (source_bufptr + inode_offset); target_inoptr = (struct dinode *) (target_bufptr + inode_offset); aisr_rc = AIS_inode_replication(source_is_primary, target_inoptr, source_inoptr); if (aisr_rc != FSCK_OK) goto aisr_release; /* the ait is replicated in the buffer * * now finish up the self inode by replicating the aggregate inode * map which it describes. */ aisr_rc = AIM_replication(source_is_primary, target_ait_root, source_bufptr, &replication_failed); if (aisr_rc != FSCK_OK) goto aisr_release; /* ait replication in buffer now complete */ /* swap if on big endian machine */ ujfs_swap_inoext((struct dinode *) target_bufptr, PUT, sb_ptr->s_flag); intermed_rc = readwrite_device(target_byte_offset, INODE_EXTENT_SIZE, &bytes_transferred, (void *) target_bufptr, fsck_WRITE); /* swap back */ ujfs_swap_inoext((struct dinode *) target_bufptr, GET, sb_ptr->s_flag); agg_recptr->ag_modified = 1; if ((intermed_rc != FSCK_OK) || (bytes_transferred != INODE_EXTENT_SIZE)) { /* * some or all didn't make it to the device. */ agg_recptr->ait_aim_update_failed = 1; if (!source_is_primary) { /* we're trying to repair the primary * table and can't -- that makes this a * dirty file system. */ agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_CANTREPAIRAIS, "4"); } else { /* trying to repair the secondary table and can't * * We won't stop fsck and we won't the file system * dirty on this condition, but we'll issue a warning * and the superblock to prevent future attempts to * maintain the flawed table. */ replication_failed = -1; fsck_send_msg(fsck_INCONSIST2NDRY1, "4"); } } aisr_release: temp_inode_buf_release(source_bufptr); if (aisr_rc == FSCK_OK) { if (replication_failed) { sb_ptr->s_flag |= JFS_BAD_SAIT; } else { sb_ptr->s_flag &= (~JFS_BAD_SAIT); } } aisr_exit: return (aisr_rc); } /**************************************************************** * NAME: first_ref_check_inode_extents * * FUNCTION: Determine whether any inode extent in the aggregate (i.e., * in either the Aggregate Inode Table or in the Fileset Inode * Table) contains a reference to any multiply-allocated * aggregate block whose first reference has not yet been * resolved. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int first_ref_check_inode_extents() { int rdie_rc = FSCK_OK; int is_aggregate; int which_it; struct fsck_inode_record *inorecptr; struct fsck_ino_msg_info msg_info; struct fsck_ino_msg_info *msg_info_ptr; msg_info_ptr = &msg_info; msg_info_ptr->msg_inonum = AGGREGATE_I; msg_info_ptr->msg_inopfx = fsck_aggr_inode; msg_info_ptr->msg_inotyp = fsck_metaIAG; /* * check the inode extents in the Aggregate Inode Allocation Map * for first references to multiply allocated blocks. */ is_aggregate = -1; if (agg_recptr->primary_ait_4part1) which_it = fsck_primary; else which_it = fsck_secondary; rdie_rc = get_inorecptr(is_aggregate, 0, AGGREGATE_I, &inorecptr); if ((rdie_rc == FSCK_OK) && (inorecptr == NULL)) rdie_rc = FSCK_INTERNAL_ERROR_18; if (rdie_rc != FSCK_OK) goto rdie_exit; rdie_rc = first_refchk_inoexts(is_aggregate, which_it, inorecptr, msg_info_ptr); if (rdie_rc != FSCK_OK) goto rdie_exit; /* * check the inode extents in the Fileset Inode Allocation Maps * for first references to multiply allocated blocks. * * (In release 1 there is exactly 1 fileset) */ which_it = FILESYSTEM_I; /* aggregate inode */ is_aggregate = -1; rdie_rc = get_inorecptr(is_aggregate, 0, FILESYSTEM_I, &inorecptr); if ((rdie_rc == FSCK_OK) && (inorecptr == NULL)) rdie_rc = FSCK_INTERNAL_ERROR_19; if (rdie_rc != FSCK_OK) goto rdie_exit; /* fileset IAGs */ is_aggregate = 0; rdie_rc = first_refchk_inoexts(is_aggregate, which_it, inorecptr, msg_info_ptr); rdie_exit: return (rdie_rc); } /**************************************************************** * NAME: first_refchk_inoexts * * FUNCTION: Check all inode extents described by IAGs in the specified * inode table to determine whether they contain a reference * to any multiply-allocated aggregate block whose first reference * has not yet been resolved. * * PARAMETERS: * is_aggregate - input - !0 => aggregate owned * 0 => fileset owned * which_it - input - ordinal number of the aggregate inode * describing the inode table * inorecptr - input - pointer to an fsck inode record which * describes the current inode allocation * table inode * msg_info_ptr - input - pointer to data needed to issue messages * about the current inode * * NOTES: o Since this routine completes the fsck workspace * initialization needed by inode_get() (et al), this * routine ensures fsck I/O buffers contain the inode * it needs before invoking inode_get(). * (inode_get() is invoked to locate the inode within * the fsck I/O buffer.) * * RETURNS: * success: FSCK_OK * failure: something else */ int first_refchk_inoexts(int is_aggregate, int which_it, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr) { int ifrie_rc = FSCK_OK; struct iag *iagptr; uint32_t ext_idx; uint32_t ext_idx_max; int64_t ext_addr; uint32_t ext_len; int which_ait; int8_t is_EA = 0; int8_t is_ACL = 0; int8_t extent_is_valid; uint32_t adjusted_length; ext_idx_max = EXTSPERIAG - 1; if (is_aggregate) { if (agg_recptr->primary_ait_4part1) { which_ait = fsck_primary; } else { which_ait = fsck_secondary; } } else { if (agg_recptr->primary_ait_4part2) { which_ait = fsck_primary; } else { which_ait = fsck_secondary; } } ifrie_rc = iag_get_first(is_aggregate, which_it, which_ait, &iagptr); while ((iagptr != NULL) && (agg_recptr->unresolved_1stref_count > 0) && (ifrie_rc == FSCK_OK)) { for (ext_idx = 0; ((ext_idx <= ext_idx_max) && (agg_recptr->unresolved_1stref_count > 0) && (ifrie_rc == FSCK_OK)); ext_idx++) { ext_addr = addressPXD(&(iagptr->inoext[ext_idx])); if (ext_addr != 0) { /* the extent is allocated */ ext_len = lengthPXD(&(iagptr->inoext[ext_idx])); ifrie_rc = process_extent(inorecptr, ext_len, ext_addr, is_EA, is_ACL, msg_info_ptr, &adjusted_length, &extent_is_valid, FSCK_QUERY); } } if (ifrie_rc == FSCK_OK) { ifrie_rc = iag_get_next(&iagptr); } } return (ifrie_rc); } /*-------------------------------------------------------------------- * NAME: FSIM_add_extents * * FUNCTION: Add an extent of to the inode * * NOTES: * o It is not necessary to mark the extent in the block map * since it is an extent already owned by the source * FileSet Inode Map. * * PARAMETERS: * thisblk - block number of bad block to add * bb_inode - Inode to add bad block to * * RETURNS: 0 for success; Other indicates failure */ int FSIM_add_extents(xtpage_t * src_leaf_ptr, struct dinode *target_inode, int8_t * replication_failed) { int fsimae_rc = FSCK_OK; int32_t xad_idx, ext_length, ext_bytes; int64_t ext_addr; *replication_failed = 0; for (xad_idx = XTENTRYSTART; ((fsimae_rc == FSCK_OK) && (!*replication_failed) && (xad_idx < src_leaf_ptr->header.nextindex)); xad_idx++) { ext_addr = addressXAD(&(src_leaf_ptr->xad[xad_idx])); ext_length = lengthXAD(&(src_leaf_ptr->xad[xad_idx])); ext_bytes = ext_length << agg_recptr->log2_blksize; fsimae_rc = xtAppend(target_inode, target_inode->di_size / sb_ptr->s_bsize, ext_addr, ext_length, fsim_node_pages); target_inode->di_size += ext_bytes; target_inode->di_nblocks += ext_length; } if (fsimae_rc > 0) { /* an error, but not fatal */ *replication_failed = -1; fsimae_rc = FSCK_OK; } return (fsimae_rc); } /**************************************************************** * NAME: FSIM_check * * FUNCTION: Compare the specified Primary Fileset Inode Map to its * (specified) Secondary Fileset Inode Map counterpart to * ensure that they are logically equivalent. * * PARAMETERS: * primary_inoptr - input - pointer to an inode in the primary * aggregate inode allocation table * in an fsck buffer * secondary_inoptr - input - pointer to the equivalent inode in * the secondary aggregate inode * allocation table in an fsck buffer * inconsistency_detected - input - pointer to a variable in which * to return !0 if errors are detected * 0 if no errors are detected * * RETURNS: * success: FSCK_OK * failure: something else */ int FSIM_check(struct dinode *primary_inoptr, struct dinode *secondary_inoptr, int *inconsistency_detected) { int fsimc_rc = FSCK_OK; xtpage_t *primary_nodeptr, *secondary_nodeptr, *leaf_node; int8_t primary_is_inline, primary_is_rootleaf; int8_t secondary_is_inline, secondary_is_rootleaf; int leaf_length; int64_t node_agg_offset; /* * allocate 2 buffers to contain the node */ fsimc_rc = temp_node_buf_alloc((char **) (&agg_recptr->prim_nodeptr)); if (fsimc_rc != FSCK_OK) goto fsimc_set_exit; /* first node buffer allocated */ primary_nodeptr = agg_recptr->prim_nodeptr; fsimc_rc = temp_node_buf_alloc((char **) (&agg_recptr->second_nodeptr)); if (fsimc_rc != FSCK_OK) goto fsimc_set_exit; /* second node buffer allocated */ secondary_nodeptr = agg_recptr->second_nodeptr; fsimc_rc = find_first_leaf(primary_inoptr, &leaf_node, &node_agg_offset, &primary_is_inline, &primary_is_rootleaf); if (fsimc_rc != FSCK_OK) { *inconsistency_detected = -1; fsimc_rc = FSCK_OK; goto fsimc_set_exit; } /* got first leaf of primary fs inode map * * copy it into the temp primary node buffer */ if (primary_is_rootleaf) { leaf_length = XTROOTMAXSLOT * sizeof (xad_t); memcpy((void *) primary_nodeptr, (void *) &(primary_inoptr->di_btroot), leaf_length); } else { leaf_length = XTPAGE_SIZE; memcpy((void *) primary_nodeptr, (void *) leaf_node, leaf_length); } fsimc_rc = find_first_leaf(secondary_inoptr, &leaf_node, &node_agg_offset, &secondary_is_inline, &secondary_is_rootleaf); if (fsimc_rc != FSCK_OK) { *inconsistency_detected = -1; fsimc_rc = FSCK_OK; goto fsimc_set_exit; } /* got first leaf of secondary fs inode map * * copy it into the temp secondary node buffer */ if (secondary_is_rootleaf) { leaf_length = XTROOTMAXSLOT * sizeof (xad_t); memcpy((void *) secondary_nodeptr, (void *) &(secondary_inoptr->di_btroot), leaf_length); } else { leaf_length = XTPAGE_SIZE; memcpy((void *) secondary_nodeptr, (void *) leaf_node, leaf_length); } if (*inconsistency_detected) goto fsimc_set_exit; if ((primary_is_rootleaf != secondary_is_rootleaf) || (primary_is_inline != secondary_is_inline)) { *inconsistency_detected = -1; goto fsimc_set_exit; } /* either both or neither is a rootleaf */ if (primary_is_rootleaf) { /* they're root leaf nodes */ fsimc_rc = IM_compare_leaf(primary_nodeptr, secondary_nodeptr, inconsistency_detected); goto fsimc_set_exit; } /* they're not root leaf nodes */ while ((primary_nodeptr != NULL) && (secondary_nodeptr != NULL)) { fsimc_rc = IM_compare_leaf(primary_nodeptr, secondary_nodeptr, inconsistency_detected); if ((fsimc_rc != FSCK_OK) || *inconsistency_detected) break; /* leafs compare as equal */ if (primary_nodeptr->header.next == 0) primary_nodeptr = NULL; else { /* primary leaf has a next */ node_agg_offset = primary_nodeptr->header.next; fsimc_rc = ait_node_get(node_agg_offset, primary_nodeptr); if (fsimc_rc != FSCK_OK) { if (fsimc_rc > 0) { /* error but not fatal */ *inconsistency_detected = -1; fsimc_rc = FSCK_OK; } break; } } if (secondary_nodeptr->header.next == 0) secondary_nodeptr = NULL; else { /* secondary leaf has a next */ node_agg_offset = secondary_nodeptr->header.next; fsimc_rc = ait_node_get(node_agg_offset, secondary_nodeptr); if (fsimc_rc != FSCK_OK) { if (fsimc_rc > 0) { /* error but not fatal */ *inconsistency_detected = -1; fsimc_rc = FSCK_OK; } break; } } } if ((primary_nodeptr != NULL) || (secondary_nodeptr != NULL)) /* on exit these should both be NULL */ *inconsistency_detected = -1; fsimc_set_exit: if ((*inconsistency_detected)) { /* future recovery capability is compromised * * Note that we're in read-only mode or we wouldn't be checking * this (because when we have write access we always rebuild it */ fsck_send_msg(fsck_INCONSIST2NDRY, "3"); } return (fsimc_rc); } /**************************************************************** * NAME: FSIM_replication * * FUNCTION: Replicate the Fileset Inode Map from the given source Aggregate * Map to the given target Aggregate Inode Map so that they are * logically equivalent. That is, so that they have independent * B+Trees, but the leaf level of the 2 trees point to the same "data" * extents (control page and IAGs). * * PARAMETERS: * source_is_primary - input - 0 if secondary FSIM is being replicated * into primary FSIM * !0 if primary FSIM is being replicated into * secondary FSIM * source_inoptr - input - pointer to an inode in the primary * aggregate inode allocation table in an fsck * buffer * target_inoptr - input - pointer to the equivalent inode in the * secondary aggregate inode allocation table in * an fsck buffer * replication_failed - input - ptr to a variable in which to return 0 * if the FSIM is successfully replicated and * !0 if the FSIM is not successfully * replicated * * RETURNS: * success: FSCK_OK * failure: something else */ int FSIM_replication(int8_t source_is_primary, struct dinode *target_inoptr, struct dinode *source_inoptr, int8_t * replication_failed) { int fsimr_rc = FSCK_OK; xtpage_t *source_nodeptr, *leaf_node; int8_t source_is_inline, source_is_rootleaf; int leaf_length = 0; int64_t node_agg_offset; struct xtree_buf *curpage; int I_am_logredo = 0; /* * allocate a buffer to contain the source leaf nodes */ fsimr_rc = temp_node_buf_alloc((char **) (&agg_recptr->prim_nodeptr)); if (fsimr_rc != FSCK_OK) goto fsimr_exit; /* node buffer allocated */ source_nodeptr = agg_recptr->prim_nodeptr; fsimr_rc = find_first_leaf(source_inoptr, &leaf_node, &node_agg_offset, &source_is_inline, &source_is_rootleaf); if (fsimr_rc != FSCK_OK) { *replication_failed = -1; fsimr_rc = FSCK_OK; } else { /* got first leaf of primary fs inode map */ /* * copy it into the temp primary node buffer */ if (source_is_rootleaf) { leaf_length = XTROOTMAXSLOT * sizeof (xad_t); memcpy((void *) source_nodeptr, (void *) &(source_inoptr->di_btroot), leaf_length); } else { /* root is internal */ leaf_length = XTPAGE_SIZE; memcpy((void *) source_nodeptr, (void *) leaf_node, leaf_length); /* * Initialize list of xtree append buffers */ fsimr_rc = alloc_wrksp(sizeof (struct xtree_buf), dynstg_xtreebuf, I_am_logredo, (void **) &fsim_node_pages); if (fsimr_rc == FSCK_OK) { fsim_node_pages->down = fsim_node_pages->up = NULL; fsim_node_pages->page = (xtpage_t *) & target_inoptr->di_btroot; } } } if (*replication_failed || (fsimr_rc != FSCK_OK)) goto fsimr_exit; if (source_is_rootleaf) { target_inoptr->di_size = source_inoptr->di_size; target_inoptr->di_nblocks = source_inoptr->di_nblocks; memcpy((void *) &(target_inoptr->di_btroot), (void *) &(source_inoptr->di_btroot), leaf_length); goto fsimr_exit; } /* source is not a rootleaf */ target_inoptr->di_size = 0; target_inoptr->di_nblocks = 0; while ((source_nodeptr != NULL) && (!(*replication_failed)) && (fsimr_rc == FSCK_OK)) { /* * add the extents described in this xtpage to the * target inode */ fsimr_rc = FSIM_add_extents(source_nodeptr, target_inoptr, replication_failed); if ((fsimr_rc == FSCK_OK) && !(*replication_failed)) { /* leaf replicated */ if (source_nodeptr->header.next == 0) { source_nodeptr = NULL; } else { /* source leaf has a next */ node_agg_offset = source_nodeptr->header.next; fsimr_rc = ait_node_get(node_agg_offset, source_nodeptr); if (fsimr_rc != FSCK_OK) { if (fsimr_rc > 0) { /* error but not fatal */ *replication_failed = -1; fsimr_rc = FSCK_OK; } } } } } /* * If any pages were allocated for the xtree rooted * in the FileSet Inode Map (FSIM) then we need to * write them to the device */ curpage = fsim_node_pages; while ((!(curpage->page->header.flag & BT_ROOT)) && (!(*replication_failed)) && (fsimr_rc == FSCK_OK)) { node_agg_offset = addressPXD(&(curpage->page->header.self)); fsimr_rc = ait_node_put(node_agg_offset, curpage->page); if (fsimr_rc != 0) { *replication_failed = -1; } else { curpage = curpage->up; } } fsimr_exit: return (fsimr_rc); } /**************************************************************** * NAME: iag_alloc_rebuild * * FUNCTION: Rebuild the specified Inode Allocation Group (iag) using data * based on fsck's observations of the aggregate. * * PARAMETERS: * iagnum - input - ordinal number of the current iag * iagiptr - input - pointer to a data area describing the * current iag * * RETURNS: * success: FSCK_OK * failure: something else */ int iag_alloc_rebuild(int32_t iagnum, struct fsck_iag_info *iagiptr) { int iar_rc = FSCK_OK; uint32_t agnum; /* * rebuild IAG's pmap and wmap */ memcpy((void *) &(iagiptr->iagptr->pmap[0]), (void *) &(agg_recptr->amap[0]), AMAPSIZE); memcpy((void *) &(iagiptr->iagptr->wmap[0]), (void *) &(agg_recptr->amap[0]), AMAPSIZE); /* * rebuild the IAG's summary maps */ memcpy((void *) &(iagiptr->iagptr->extsmap[0]), (void *) &(agg_recptr->fextsumm[0]), SMAPSIZE); memcpy((void *) &(iagiptr->iagptr->inosmap[0]), (void *) &(agg_recptr->finosumm[0]), SMAPSIZE); /* * reset the IAG's "free counts" */ iagiptr->iagptr->nfreeinos = iagiptr->iagtbl[iagnum].unused_backed_inodes; iagiptr->iagptr->nfreeexts = iagiptr->iagtbl[iagnum].unbacked_extents; /* * add it to the various lists, as appropriate * * (In the case of doubly linked list, only the forward pointers * are set here. Resetting back pointers involves I/O and will be * done later.) */ if (iagiptr->iagtbl[iagnum].unbacked_extents == EXTSPERIAG) { /* this iag belongs on the imap free IAG list */ iagiptr->iagptr->iagfree = iagiptr->iamctlptr->in_freeiag; iagiptr->iamctlptr->in_freeiag = iagnum; iagiptr->iagptr->extfreefwd = -1; iagiptr->iagptr->extfreeback = -1; iagiptr->iagptr->inofreefwd = -1; iagiptr->iagptr->inofreeback = -1; } else { /* this iag does not belong on the imap free IAG list */ iagiptr->iagptr->iagfree = -1; agnum = iagiptr->iagtbl[iagnum].AG_num; if ((iagiptr->iagtbl[iagnum].unbacked_extents > 0) && (iagiptr->iagtbl[iagnum].unbacked_extents < EXTSPERIAG)) { /* this iag belongs on the AG free extent list */ iagiptr->iagptr->extfreefwd = iagiptr->iamctlptr->in_agctl[agnum].extfree; iagiptr->iamctlptr->in_agctl[agnum].extfree = iagnum; } else { /* this iag doesn't belong on the AG free extent list */ iagiptr->iagptr->extfreefwd = -1; iagiptr->iagptr->extfreeback = -1; } if (iagiptr->iagtbl[iagnum].unused_backed_inodes > 0) { /* this iag belongs on the AG free inode list */ iagiptr->iagptr->inofreefwd = iagiptr->iamctlptr->in_agctl[agnum].inofree; iagiptr->iamctlptr->in_agctl[agnum].inofree = iagnum; } else { /* this iag does not belong on the AG free inode list */ iagiptr->iagptr->inofreefwd = -1; iagiptr->iagptr->inofreeback = -1; } } return (iar_rc); } /**************************************************************** * NAME: iag_alloc_scan * * FUNCTION: Scan data collected by fsck which describes the inodes in * the range described by the current iag. Summarize this * data in a form which will be convenient for use when verifying * or rebuilding the iag. * * PARAMETERS: * iag_alloc_inodes - input - pointer to a variable in which to return * a count of inodes which are described * by the current iag and are both backed and * in use in the filesystem * iag_alloc_exts - input - pointer to a variable in which to return * a count of the inode extents which are * backed and described by the current iag * iagiptr - input - pointer to a data area describing the * current iag * msg_info_ptr - input - pointer to data needed to issue messages * about the current inode allocation map * * RETURNS: * success: FSCK_OK * failure: something else */ int iag_alloc_scan(int32_t * iag_alloc_inodes, int32_t * iag_alloc_exts, struct fsck_iag_info *iagiptr, struct fsck_imap_msg_info *msg_info_ptr) { int ias_rc = FSCK_OK; int32_t iag_smapidx; int32_t iag_extidx, smap_extidx; int32_t inoidx, agg_inoidx; int32_t ext_alloc_inodes; struct fsck_inode_record *this_inorecptr; int64_t ext_addr; uint32_t ext_length; uint32_t map_mask = 0x80000000; int alloc_ifnull = 0; /* * build maps for this iag */ iag_extidx = 0; *iag_alloc_inodes = 0; *iag_alloc_exts = 0; agg_inoidx = (iagiptr->iamrecptr->num_iags - 1) * INOSPERIAG; for (iag_smapidx = 0; (iag_smapidx < SMAPSZ); iag_smapidx++) { for (smap_extidx = 0; (smap_extidx < EXTSPERSUM); smap_extidx++, iag_extidx++) { ext_addr = addressPXD(&(iagiptr->iagptr->inoext[iag_extidx])); if (ext_addr == 0) { /* extent not allocated */ agg_recptr->amap[iag_extidx] = 0; /* turn off the bit */ agg_recptr->fextsumm[iag_smapidx] &= ~(map_mask >> smap_extidx); /* turn on the bit */ agg_recptr->finosumm[iag_smapidx] |= (map_mask >> smap_extidx); agg_inoidx += INOSPEREXT; continue; } /* extent is allocated */ (*iag_alloc_exts)++; /* turn on the bit */ agg_recptr->fextsumm[iag_smapidx] |= (map_mask >> smap_extidx); ext_alloc_inodes = 0; for (inoidx = 0; (inoidx < INOSPEREXT); inoidx++, agg_inoidx++) { ias_rc = get_inorecptr(iagiptr->agg_inotbl, alloc_ifnull, agg_inoidx, &this_inorecptr); if (ias_rc != FSCK_OK) goto ias_exit; if (this_inorecptr == NULL) { /* backed but not referenced */ /* turn off the bit */ agg_recptr->amap[iag_extidx] &= ~(map_mask >> inoidx); continue; } /* either in use or referenced */ if ((this_inorecptr->in_use) && ((agg_recptr->processing_readonly) || (!this_inorecptr->selected_to_rls))) { /* * inode allocated and won't be * released (this session) */ agg_recptr->amap[iag_extidx] |= (map_mask >> inoidx); /* turn on the bit */ ext_alloc_inodes++; if ((this_inorecptr->inode_type == file_inode) || (this_inorecptr->inode_type == block_special_inode) || (this_inorecptr->inode_type == char_special_inode) || (this_inorecptr->inode_type == FIFO_inode) || (this_inorecptr->inode_type == SOCK_inode)) { agg_recptr-> files_in_aggregate++; } else if (this_inorecptr->inode_type == directory_inode) { agg_recptr->dirs_in_aggregate++; } } else { /* inode backed but not allocated */ agg_recptr->amap[iag_extidx] &= ~(map_mask >> inoidx); /* turn off the bit */ } } if (ias_rc != FSCK_OK) goto ias_exit; if ((ext_alloc_inodes == 0) && (agg_recptr->processing_readwrite)) { /* * we have write access (so we'll be rebuilding * the IAGs, not just verifying them) and none * of the inodes in this extent are allocated. * * Release this inode extent. * * turn off the bit because extent slot * available */ agg_recptr->fextsumm[iag_smapidx] &= ~(map_mask >> smap_extidx); /* turn on the bit because no inodes available */ agg_recptr->finosumm[iag_smapidx] |= (map_mask >> smap_extidx); ext_length = lengthPXD( &(iagiptr->iagptr->inoext[iag_extidx])); ias_rc = extent_unrecord(ext_addr, (ext_addr + ext_length - 1)); *iag_alloc_exts -= 1; PXDaddress( &(iagiptr->iagptr->inoext[iag_extidx]), 0); PXDlength( &(iagiptr->iagptr->inoext[iag_extidx]), 0); if (ias_rc != FSCK_OK) goto ias_exit; } else { /* read only or at least one inode is allocated */ *iag_alloc_inodes += ext_alloc_inodes; if (ext_alloc_inodes == INOSPEREXT) { /* all in use */ agg_recptr->finosumm[iag_smapidx] |= (map_mask >> smap_extidx); /* * turn on the bit */ } else { /* some backed but not in use */ agg_recptr->finosumm[iag_smapidx] &= ~(map_mask >> smap_extidx); /* * turn off the bit */ } } } } ias_exit: return (ias_rc); } /**************************************************************** * NAME: iag_alloc_ver * * FUNCTION: Verify that the specified Inode Allocation Group (iag) is * correct according to fsck's observations of the aggregate. * * PARAMETERS: * errors_detected - input - pointer to a variable in which to return * !0 if errors are detected * 0 if no errors are detected * agstrt_is_bad - input - !0 => the iag cannot be associated with * a particular allocation group * 0 => the iag appears to be associated * with a valid allocation group * iagnum - input - ordinal number of the current iag * iagiptr - input - pointer to a data area describing the * current iag * msg_info_ptr - input - pointer to data needed to issue messages * about the current inode allocation map * * RETURNS: * success: FSCK_OK * failure: something else */ int iag_alloc_ver(int *errors_detected, int agstrt_is_bad, int32_t iagnum, struct fsck_iag_info *iagiptr, struct fsck_imap_msg_info *msg_info_ptr) { int outcome; uint32_t agnum; /* * check out the IAG's pmap */ outcome = memcmp((void *) &(agg_recptr->amap[0]), (void *) &(iagiptr->iagptr->pmap[0]), AMAPSIZE); if (outcome != 0) { /* pmaps don't match! */ *errors_detected = -1; fsck_send_msg(fsck_BADIAGPMAP, fsck_ref_msg(msg_info_ptr->msg_mapowner), iagnum); } /* * check out the IAG's free extent summary map */ outcome = memcmp((void *) &(agg_recptr->fextsumm[0]), (void *) &(iagiptr->iagptr->extsmap[0]), SMAPSIZE); if (outcome != 0) { /* free extent maps don't match! */ *errors_detected = -1; fsck_send_msg(fsck_BADIAGFIES, fsck_ref_msg(msg_info_ptr->msg_mapowner), iagnum); } /* * check out the IAG's (extents with) free inodes summary map */ outcome = memcmp((void *) &(agg_recptr->finosumm[0]), (void *) &(iagiptr->iagptr->inosmap[0]), SMAPSIZE); if (outcome != 0) { /* free inode maps don't match! */ *errors_detected = -1; fsck_send_msg(fsck_BADIAGFIS, fsck_ref_msg(msg_info_ptr->msg_mapowner), iagnum); } /* * check out the IAG's "free counts" */ if (iagiptr->iagptr->nfreeinos != iagiptr->iagtbl[iagnum].unused_backed_inodes) { /* free inode count is wrong */ *errors_detected = -1; fsck_send_msg(fsck_BADIAGNFINO, fsck_ref_msg(msg_info_ptr->msg_mapowner), iagnum); } if (iagiptr->iagptr->nfreeexts != iagiptr->iagtbl[iagnum].unbacked_extents) { /* free extent count is wrong */ *errors_detected = -1; fsck_send_msg(fsck_BADIAGNFEXT, fsck_ref_msg(msg_info_ptr->msg_mapowner), iagnum); } /* * verify *inclusion in* / *exclusion from* the various IAG lists */ if (!iagiptr->iamrecptr->friag_list_bad) { /* the list looked good when we scanned it */ if (iagiptr->iagtbl[iagnum].unbacked_extents == EXTSPERIAG) { /* this iag belongs on the imap free IAG list */ if ((iagiptr->iagptr->iagfree == -1) && (iagiptr->iamrecptr->friag_list_last != iagnum)) { /* not on the list! */ *errors_detected = -1; fsck_send_msg(fsck_BADIAGFLIST, fsck_ref_msg(msg_info_ptr->msg_mapowner), "2"); } else { /* it is on the list */ /* we've seen one of them */ iagiptr->iamrecptr->friag_list_len--; } } else { /* this iag does not belong on the imap free IAG list */ if ((iagiptr->iagptr->iagfree != -1) || (iagiptr->iamrecptr->friag_list_last == iagnum)) { /* on the list! */ /* we've seen one of them */ iagiptr->iamrecptr->friag_list_len--; *errors_detected = -1; fsck_send_msg(fsck_BADIAGFLIST, fsck_ref_msg(msg_info_ptr->msg_mapowner), "3"); } } } if (agstrt_is_bad) goto iav_exit; /* we can associate an AG with this IAG */ agnum = iagiptr->iagtbl[iagnum].AG_num; if (!iagiptr->agtbl[agnum].frext_list_bad) { /* the list looked valid when we scanned it */ if ((iagiptr->iagtbl[iagnum].unbacked_extents > 0) && (iagiptr->iagtbl[iagnum].unbacked_extents < EXTSPERIAG)) { /* this iag belongs on the AG free extent list */ if ((iagiptr->iagptr->extfreefwd == -1) && (iagiptr->iagptr->extfreeback == -1) && ((iagiptr->agtbl[agnum].frext_list_first != iagnum) || (iagiptr->agtbl[agnum].frext_list_last != iagnum))) { /* not on the list! */ *errors_detected = -1; fsck_send_msg(fsck_BADAGFELIST, fsck_ref_msg(msg_info_ptr->msg_mapowner), iagnum, "2"); } else /* it is on the list */ /* we've seen one of them */ iagiptr->agtbl[agnum].frext_list_len--; } else { /* this iag doesn't belong on the AG free extent list */ if ((iagiptr->iagptr->extfreefwd != -1) || (iagiptr->iagptr->extfreeback != -1) || ((iagiptr->agtbl[agnum].frext_list_first == iagnum) && (iagiptr->agtbl[agnum].frext_list_last == iagnum))) { /* on the list! */ /* we've seen one of them */ iagiptr->agtbl[agnum].frext_list_len--; *errors_detected = -1; fsck_send_msg(fsck_BADAGFELIST, fsck_ref_msg(msg_info_ptr->msg_mapowner), iagnum, "3"); } } } if (!iagiptr->agtbl[agnum].frino_list_bad) { /* the list looked valid when we scanned it */ if (iagiptr->iagtbl[iagnum].unused_backed_inodes > 0) { /* this iag belongs on the AG free inode list */ if ((iagiptr->iagptr->inofreefwd == -1) && (iagiptr->iagptr->inofreeback == -1) && ((iagiptr->agtbl[agnum].frino_list_first != iagnum) || (iagiptr->agtbl[agnum].frino_list_last != iagnum))) { /* not on the list! */ *errors_detected = -1; fsck_send_msg(fsck_BADAGFILIST, fsck_ref_msg(msg_info_ptr->msg_mapowner), iagnum, "3"); } else /* it is on the list */ /* we've seen one of them */ iagiptr->agtbl[agnum].frino_list_len--; } else { /* this iag does not belong on the AG free inode list */ if ((iagiptr->iagptr->inofreefwd != -1) || (iagiptr->iagptr->inofreeback != -1) || ((iagiptr->agtbl[agnum].frino_list_first == iagnum) && (iagiptr->agtbl[agnum].frino_list_last == iagnum))) { /* on the list! */ /* we've seen one of them */ iagiptr->agtbl[agnum].frino_list_len--; *errors_detected = -1; fsck_send_msg(fsck_BADAGFILIST, fsck_ref_msg(msg_info_ptr->msg_mapowner), iagnum, "3"); } } } iav_exit: return (FSCK_OK); } /**************************************************************** * NAME: iagfr_list_scan * * FUNCTION: Scan the iag list for the specified Inode Allocation Map. * Count the number of iags on the list. Validate the list * structure. * * PARAMETERS: * is_aggregate - input - !0 => aggregate owned * 0 => fileset owned * which_it - input - ordinal number of the aggregate inode * describing the inode table * which_ait - input - the aggregate inode table from which * the it inode should be read * { fsck_primary | fsck_secondary } * iagiptr - input - pointer to a data area describing the * current iag * errors_detected - input - pointer to a variable in which to return * !0 if errors are detected * 0 if no errors are detected * msg_info_ptr - input - pointer to data needed to issue messages * about the current inode allocation map * * RETURNS: * success: FSCK_OK * failure: something else */ int iagfr_list_scan(int is_aggregate, int which_it, int which_ait, struct fsck_iag_info *iagiptr, int *errors_detected, struct fsck_imap_msg_info *msg_info_ptr) { int ifls_rc = FSCK_OK; int intermed_rc = FSCK_OK; int32_t this_iagno; int32_t end_of_list = -1; iagiptr->iamrecptr->friag_list_last = end_of_list; iagiptr->iamrecptr->friag_list_len = 0; this_iagno = iagiptr->iamctlptr->in_freeiag; while ((this_iagno != end_of_list) && (!iagiptr->iamrecptr->friag_list_bad) && (ifls_rc == FSCK_OK)) { intermed_rc = iag_get(is_aggregate, which_it, which_ait, this_iagno, &(iagiptr->iagptr)); /* * we consider an error here to be an error in the chain. If * it's really something more serious it will come up again * when we go through all allocated iag's sequentially. */ if (intermed_rc != FSCK_OK) { iagiptr->iamrecptr->friag_list_bad = -1; } else { /* got the iag */ /* in case it's last... */ iagiptr->iamrecptr->friag_list_last = this_iagno; /* increment the counter */ iagiptr->iamrecptr->friag_list_len++; this_iagno = iagiptr->iagptr->iagfree; } } if (iagiptr->iamrecptr->friag_list_bad) { /* found a problem */ agg_recptr->ag_dirty = 1; *errors_detected = -1; fsck_send_msg(fsck_BADIAGFLIST, fsck_ref_msg(msg_info_ptr->msg_mapowner), "1"); } return (ifls_rc); } /**************************************************************** * NAME: iagfr_list_validation * * FUNCTION: Compare the results of the Inode Allocation Map free iag * list scan with the results of validating the iags. If * the number of iags seen on the list during list scan does * not match the number of iags which appear to be on the * list (i.e., which have a non-initialized value in their * forward pointer) as seen during iag validation, then the * list is not structurally consistent. * * PARAMETERS: * errors_detected - input - pointer to a variable in which to return * !0 if errors are detected * 0 if no errors are detected * iamrecptr - input - pointer to a data area which describes the * current inode allocation map * msg_info_ptr - input - pointer to data needed to issue messages * about the current inode allocation map * * RETURNS: * success: FSCK_OK * failure: something else */ int iagfr_list_validation(int *errors_detected, struct fsck_iam_record *iamrecptr, struct fsck_imap_msg_info *msg_info_ptr) { int iflv_rc = FSCK_OK; if (iamrecptr->friag_list_len > 0) { /* * fsck observed fewer iag's which belong on the free iag * list than it counted when it scanned the free iag list. * (fsck has already issued messages about these iag's) */ *errors_detected = -1; agg_recptr->ag_dirty = 1; } else if (iamrecptr->friag_list_len < 0) { /* * fsck observed more iag's which belong on the free iag * list and which appear to be on the list than it counted * when it scanned the free iag list. So the chain has * somehow lost some of its links. */ *errors_detected = -1; agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_BADIAGFL1, fsck_ref_msg(msg_info_ptr->msg_mapowner)); } return (iflv_rc); } /**************************************************************** * NAME: iags_finish_lists * * FUNCTION: Complete the rebuild process for the Allocation Group (ag) * free extent lists and free inode lists. Specifically, * for each ag, set the back pointer in each iag on its * free extent list and in each iag on its free inode list. * * PARAMETERS: * is_aggregate - input - !0 => aggregate owned * 0 => fileset owned * which_it - input - ordinal number of the aggregate inode * describing the inode table * which_ait - input - the aggregate inode table from which * the it inode should be read * { fsck_primary | fsck_secondary } * iagiptr - input - pointer to a data area describing the * current iag * * NOTES: o When rebuilding the ag free extent lists and the free inode * lists, it is very inconvenient to establish both forward and * backward pointers. * * RETURNS: * success: FSCK_OK * failure: something else */ int iags_finish_lists(int is_aggregate, int which_it, int which_ait, struct fsck_iag_info *iagiptr) { int iifl_rc = FSCK_OK; int32_t prev_iag, this_iag; uint32_t agidx; /* * first set the back pointers in the free inode lists */ for (agidx = 0; ((agidx < MAXAG) && (iifl_rc == FSCK_OK)); agidx++) { prev_iag = -1; this_iag = iagiptr->iamctlptr->in_agctl[agidx].inofree; while ((this_iag != -1) && (iifl_rc == FSCK_OK)) { iifl_rc = iag_get(is_aggregate, which_it, which_ait, this_iag, &(iagiptr->iagptr)); if (iifl_rc == FSCK_OK) { /* got the iag */ iagiptr->iagptr->inofreeback = prev_iag; prev_iag = this_iag; this_iag = iagiptr->iagptr->inofreefwd; iifl_rc = iag_put(iagiptr->iagptr); } } } /* * now set the back pointers in the free extent lists */ for (agidx = 0; ((agidx < MAXAG) && (iifl_rc == FSCK_OK)); agidx++) { prev_iag = -1; this_iag = iagiptr->iamctlptr->in_agctl[agidx].extfree; while ((this_iag != -1) && (iifl_rc == FSCK_OK)) { iifl_rc = iag_get(is_aggregate, which_it, which_ait, this_iag, &(iagiptr->iagptr)); if (iifl_rc == FSCK_OK) { /* got the iag */ iagiptr->iagptr->extfreeback = prev_iag; prev_iag = this_iag; this_iag = iagiptr->iagptr->extfreefwd; iifl_rc = iag_put(iagiptr->iagptr); } } } return (iifl_rc); } /**************************************************************** * NAME: iags_rebuild * * FUNCTION: Rebuild each Inode Allocation Group (iag) in the specified * Inode Allocation Map using data based on fsck's observations * of the aggregate. * * PARAMETERS: * is_aggregate - input - !0 => aggregate owned * 0 => fileset owned * which_it - input - ordinal number of the aggregate inode * describing the inode table * which_ait - input - the aggregate inode table from which * the it inode should be read * { fsck_primary | fsck_secondary } * iagiptr - input - pointer to a data area describing the * current iag * msg_info_ptr - input - pointer to data needed to issue messages * about the current inode allocation map * * RETURNS: * success: FSCK_OK * failure: something else */ int iags_rebuild(int is_aggregate, int which_it, int which_ait, struct fsck_iag_info *iagiptr, struct fsck_imap_msg_info *msg_info_ptr) { int iir_rc = FSCK_OK; int32_t iag_idx = 0; int64_t this_ag; int32_t iag_alloc_inodes, iag_alloc_exts; iir_rc = iag_get_first(is_aggregate, which_it, which_ait, &(iagiptr->iagptr)); iagiptr->iamrecptr->num_iags = 0; iagiptr->iamrecptr->unused_bkd_inodes = 0; iagiptr->iamrecptr->bkd_inodes = 0; while ((iagiptr->iagptr != NULL) && (iir_rc == FSCK_OK)) { /* increment the iag count for this imap */ iagiptr->iamrecptr->num_iags++; iagiptr->iagptr->iagnum = iag_idx; this_ag = iagiptr->iagptr->agstart / ((int64_t) sb_ptr->s_agsize); if (iagiptr->iagptr->agstart != (this_ag * sb_ptr->s_agsize)) { /* not a valid starting block for an AG */ this_ag = 0; iagiptr->iagptr->agstart = 0; fsck_send_msg(fsck_BADIAGAGSTRTCRCTD, fsck_ref_msg(msg_info_ptr->msg_mapowner), iag_idx); } else if ((this_ag < 0) || (this_ag > MAXAG)) { /* not a valid starting block for an AG */ this_ag = 0; iagiptr->iagptr->agstart = 0; fsck_send_msg(fsck_BADIAGAGCRCTD, fsck_ref_msg(msg_info_ptr->msg_mapowner), iag_idx, (long long) this_ag); } /* * count allocations and build maps for this iag */ iir_rc = iag_alloc_scan(&iag_alloc_inodes, &iag_alloc_exts, iagiptr, msg_info_ptr); if (iir_rc != FSCK_OK) break; /* * record the info in the iag record */ iagiptr->iagtbl[iag_idx].backed_inodes = iag_alloc_exts * INOSPEREXT; iagiptr->iagtbl[iag_idx].unused_backed_inodes = (iag_alloc_exts * INOSPEREXT) - iag_alloc_inodes; iagiptr->iagtbl[iag_idx].unbacked_extents = EXTSPERIAG - iag_alloc_exts; /* * update the workspace with the AG-related info. */ iagiptr->iagtbl[iag_idx].AG_num = this_ag; iagiptr->agtbl[this_ag].backed_inodes += iagiptr->iagtbl[iag_idx].backed_inodes; iagiptr->agtbl[this_ag].unused_backed_inodes += iagiptr->iagtbl[iag_idx].unused_backed_inodes; /* * add info for this iag to imap totals */ iagiptr->iamrecptr->unused_bkd_inodes += iagiptr->iagtbl[iag_idx].unused_backed_inodes; iagiptr->iamrecptr->bkd_inodes += iagiptr->iagtbl[iag_idx].backed_inodes; /* * rebuild the allocation maps in the iag */ iir_rc = iag_alloc_rebuild(iag_idx, iagiptr); if (iir_rc != FSCK_OK) break; /* * put this iag and get the next one */ iir_rc = iag_put(iagiptr->iagptr); if (iir_rc != FSCK_OK) break; iir_rc = iag_get_next(&(iagiptr->iagptr)); iag_idx++; /* increment for next iag */ } return (iir_rc); } /**************************************************************** * NAME: iags_validation * * FUNCTION: Validate each Inode Allocation Group (iag) in the specified * Inode Allocation Map based on fsck's observations of the * aggregate. * * PARAMETERS: * is_aggregate - input - !0 => aggregate owned * 0 => fileset owned * which_it - input - ordinal number of the aggregate inode * describing the inode table * which_ait - input - the aggregate inode table from which * the it inode should be read * { fsck_primary | fsck_secondary } * errors_detected - input - pointer to a variable in which to return * !0 if errors are detected * 0 if no errors are detected * iagiptr - input - pointer to a data area describing the * current iag * msg_info_ptr - input - pointer to data needed to issue messages * about the current inode allocation map * * RETURNS: * success: FSCK_OK * failure: something else */ int iags_validation(int is_aggregate, int which_it, int which_ait, int *errors_detected, struct fsck_iag_info *iagiptr, struct fsck_imap_msg_info *msg_info_ptr) { int iiv_rc = FSCK_OK; int32_t iag_idx = 0; int64_t this_ag; int errors_in_iag = 0; int bad_agstrt_in_iag = 0; int32_t iag_alloc_inodes, iag_alloc_exts; uint32_t old_iam_bkd_inodes; iiv_rc = iag_get_first(is_aggregate, which_it, which_ait, &(iagiptr->iagptr)); iagiptr->iamrecptr->num_iags = 0; iagiptr->iamrecptr->unused_bkd_inodes = 0; old_iam_bkd_inodes = iagiptr->iamrecptr->bkd_inodes; iagiptr->iamrecptr->bkd_inodes = 0; while ((iagiptr->iagptr != NULL) && (iiv_rc == FSCK_OK)) { /* increment the iag count for this imap */ iagiptr->iamrecptr->num_iags++; if (iagiptr->iagptr->iagnum != iag_idx) { /* iag number is wrong */ errors_in_iag = -1; fsck_send_msg(fsck_BADIAGIAGNUM, fsck_ref_msg(msg_info_ptr->msg_mapowner), iag_idx); } this_ag = iagiptr->iagptr->agstart / ((int64_t) sb_ptr->s_agsize); if (iagiptr->iagptr->agstart != (this_ag * sb_ptr->s_agsize)) { /* not a valid starting block for an AG */ bad_agstrt_in_iag = -1; errors_in_iag = -1; fsck_send_msg(fsck_BADIAGAGSTRT, fsck_ref_msg(msg_info_ptr->msg_mapowner), iag_idx); } else if ((this_ag < 0) || (this_ag > MAXAG)) { /* not a valid starting block for an AG */ bad_agstrt_in_iag = -1; errors_in_iag = -1; fsck_send_msg(fsck_BADIAGAG, fsck_ref_msg(msg_info_ptr->msg_mapowner), iag_idx, (long long) this_ag); } /* * count allocations and build maps for this iag */ iiv_rc = iag_alloc_scan(&iag_alloc_inodes, &iag_alloc_exts, iagiptr, msg_info_ptr); if (iiv_rc != FSCK_OK) break; /* * record the info in the iag record */ iagiptr->iagtbl[iag_idx].backed_inodes = iag_alloc_exts * INOSPEREXT; iagiptr->iagtbl[iag_idx].unused_backed_inodes = (iag_alloc_exts * INOSPEREXT) - iag_alloc_inodes; iagiptr->iagtbl[iag_idx].unbacked_extents = EXTSPERIAG - iag_alloc_exts; /* * if we can associate an AG with the IAG then update the * workspace with the AG-related info. */ if (!bad_agstrt_in_iag) { /* we have an AG */ iagiptr->iagtbl[iag_idx].AG_num = this_ag; iagiptr->agtbl[this_ag].backed_inodes += iagiptr->iagtbl[iag_idx].backed_inodes; iagiptr->agtbl[this_ag].unused_backed_inodes += iagiptr->iagtbl[iag_idx].unused_backed_inodes; } /* * add info for this iag to imap totals */ iagiptr->iamrecptr->unused_bkd_inodes += iagiptr->iagtbl[iag_idx].unused_backed_inodes; iagiptr->iamrecptr->bkd_inodes += iagiptr->iagtbl[iag_idx].backed_inodes; /* * verify the allocation maps in this iag */ iiv_rc = iag_alloc_ver(&errors_in_iag, bad_agstrt_in_iag, iag_idx, iagiptr, msg_info_ptr); if (iiv_rc != FSCK_OK) break; /* * sum it up for this iag and get the next one */ if (errors_in_iag) { /* found some thing(s) wrong! */ agg_recptr->ag_dirty = 1; *errors_detected = -1; fsck_send_msg(fsck_BADIAG, fsck_ref_msg(msg_info_ptr->msg_mapowner), iag_idx); } iiv_rc = iag_get_next(&(iagiptr->iagptr)); /* increment for next iag */ iag_idx++; /* reset for next iag */ errors_in_iag = 0; } if ((old_iam_bkd_inodes != iagiptr->iamrecptr->bkd_inodes) && (iiv_rc == FSCK_OK)) { /* * we got no fatal errors but we came up with a different count * of backed inodes on this pass than when we went through * recording and dupchecking the extents. */ iiv_rc = FSCK_INTERNAL_ERROR_12; } return (iiv_rc); } /**************************************************************** * NAME: iamap_rebuild * * FUNCTION: Rebuild the Inode Allocation Map which describes the specified * Inode Allocation Table using data based on fsck's observations * of the aggregate. * * PARAMETERS: * is_aggregate - input - !0 => aggregate owned * 0 => fileset owned * which_it - input - ordinal number of the aggregate inode * describing the inode table * which_ait - input - the aggregate inode table from which * the it inode should be read * { fsck_primary | fsck_secondary } * iagiptr - input - pointer to a data area describing the * current iag * msg_info_ptr - input - pointer to data needed to issue messages * about the current inode allocation map * * RETURNS: * success: FSCK_OK * failure: something else */ int iamap_rebuild(int is_aggregate, int which_it, int which_ait, struct fsck_iag_info *iagiptr, struct fsck_imap_msg_info *msg_info_ptr) { int iamr_rc; int agidx; /* * initialize the imap lists and counters */ iagiptr->iamctlptr->in_freeiag = -1; for (agidx = 0; (agidx < MAXAG); agidx++) { iagiptr->iamctlptr->in_agctl[agidx].inofree = -1; iagiptr->iamctlptr->in_agctl[agidx].extfree = -1; iagiptr->iamctlptr->in_agctl[agidx].numinos = 0; iagiptr->iamctlptr->in_agctl[agidx].numfree = 0; } /* * set blocks per inode extent fields */ iagiptr->iamctlptr->in_nbperiext = INODE_EXTENT_SIZE / sb_ptr->s_bsize; iagiptr->iamctlptr->in_l2nbperiext = log2shift(iagiptr->iamctlptr->in_nbperiext); /* * rebuild the IAGs and collect info to finish the iamap */ iamr_rc = iags_rebuild(is_aggregate, which_it, which_ait, iagiptr, msg_info_ptr); if (iamr_rc != FSCK_OK) goto iamr_exit; /* * fill in those pesky IAG list back pointers */ iamr_rc = iags_finish_lists(is_aggregate, which_it, which_ait, iagiptr); if (iamr_rc != FSCK_OK) goto iamr_exit; /* * finish up the control page info and put the control page */ iagiptr->iamctlptr->in_nextiag = iagiptr->iamrecptr->num_iags; iagiptr->iamctlptr->in_numinos = iagiptr->iamrecptr->bkd_inodes; iagiptr->iamctlptr->in_numfree = iagiptr->iamrecptr->unused_bkd_inodes; for (agidx = 0; (agidx < MAXAG); agidx++) { iagiptr->iamctlptr->in_agctl[agidx].numinos = iagiptr->agtbl[agidx].backed_inodes; iagiptr->iamctlptr->in_agctl[agidx].numfree = iagiptr->agtbl[agidx].unused_backed_inodes; } iamr_rc = inotbl_put_ctl_page(is_aggregate, iagiptr->iamctlptr); iamr_exit: return (iamr_rc); } /**************************************************************** * NAME: iamap_validation * * FUNCTION: Validate the Inode Allocation Map which describes the specified * Inode Allocation Table based on fsck's observations of the * aggregate. * * PARAMETERS: * is_aggregate - input - !0 => aggregate owned * 0 => fileset owned * which_it - input - ordinal number of the aggregate inode * describing the inode table * which_ait - input - the aggregate inode table from which * the it inode should be read * { fsck_primary | fsck_secondary } * iagiptr - input - pointer to a data area describing the * current iag * msg_info_ptr - input - pointer to data needed to issue messages * about the current inode allocation map * * RETURNS: * success: FSCK_OK * failure: something else */ int iamap_validation(int is_aggregate, int which_it, int which_ait, struct fsck_iag_info *iagiptr, struct fsck_imap_msg_info *msg_info_ptr) { int iamv_rc; int imapctl_errors_detected = 0; int imap_errors_detected = 0; int32_t blksperinoext; int agidx; blksperinoext = INODE_EXTENT_SIZE / sb_ptr->s_bsize; if (iagiptr->iamctlptr->in_nbperiext != blksperinoext) { imapctl_errors_detected = -1; fsck_send_msg(fsck_BADIAMBPIE, fsck_ref_msg(msg_info_ptr->msg_mapowner)); } if (iagiptr->iamctlptr->in_l2nbperiext != (log2shift(blksperinoext))) { imapctl_errors_detected = -1; fsck_send_msg(fsck_BADIAML2BPIE, fsck_ref_msg(msg_info_ptr->msg_mapowner)); } iamv_rc = iagfr_list_scan(is_aggregate, which_it, which_ait, iagiptr, &imapctl_errors_detected, msg_info_ptr); if (iamv_rc != FSCK_OK) goto iamv_exit; iamv_rc = agfrino_lists_scan(is_aggregate, which_it, which_ait, iagiptr, &imap_errors_detected, msg_info_ptr); if (iamv_rc != FSCK_OK) goto iamv_exit; iamv_rc = agfrext_lists_scan(is_aggregate, which_it, which_ait, iagiptr, &imap_errors_detected, msg_info_ptr); if (iamv_rc != FSCK_OK) goto iamv_exit; iamv_rc = iags_validation(is_aggregate, which_it, which_ait, &imap_errors_detected, iagiptr, msg_info_ptr); if (iamv_rc != FSCK_OK) goto iamv_exit; if (!iagiptr->iamrecptr->friag_list_bad) { /* not already judged invalid */ iamv_rc = iagfr_list_validation(&imapctl_errors_detected, iagiptr->iamrecptr, msg_info_ptr); if (iamv_rc != FSCK_OK) goto iamv_exit; } iamv_rc = agfrino_lists_validation(is_aggregate, which_it, iagiptr->agtbl, &imap_errors_detected, msg_info_ptr); if (iamv_rc != FSCK_OK) goto iamv_exit; iamv_rc = agfrext_lists_validation(is_aggregate, which_it, iagiptr->agtbl, &imap_errors_detected, msg_info_ptr); if (iamv_rc != FSCK_OK) goto iamv_exit; /* * finish up verifying the control page info */ if (iagiptr->iamctlptr->in_nextiag != iagiptr->iamrecptr->num_iags) { imapctl_errors_detected = -1; fsck_send_msg(fsck_BADIAMNXTIAG, fsck_ref_msg(msg_info_ptr->msg_mapowner)); } if (iagiptr->iamctlptr->in_numinos != iagiptr->iamrecptr->bkd_inodes) { imapctl_errors_detected = -1; fsck_send_msg(fsck_BADIAMNBI, fsck_ref_msg(msg_info_ptr->msg_mapowner)); } if (iagiptr->iamctlptr->in_numfree != iagiptr->iamrecptr->unused_bkd_inodes) { imapctl_errors_detected = -1; fsck_send_msg(fsck_BADIAMNFI, fsck_ref_msg(msg_info_ptr->msg_mapowner)); } for (agidx = 0; (agidx < MAXAG); agidx++) { if (iagiptr->iamctlptr->in_agctl[agidx].numinos != iagiptr->agtbl[agidx].backed_inodes) { imapctl_errors_detected = -1; fsck_send_msg(fsck_BADIAMAGNBI, fsck_ref_msg(msg_info_ptr->msg_mapowner), agidx); } if (iagiptr->iamctlptr->in_agctl[agidx].numfree != iagiptr->agtbl[agidx].unused_backed_inodes) { imapctl_errors_detected = -1; fsck_send_msg(fsck_BADIAMAGNFI, fsck_ref_msg(msg_info_ptr->msg_mapowner), agidx); } } /* * if errors have been detected, issue summary message(s) in * case we're not processing verbose. */ if (imapctl_errors_detected) { agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_BADIAMCTL, fsck_ref_msg(msg_info_ptr->msg_mapowner)); } if (imap_errors_detected) { agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_BADIAM, fsck_ref_msg(msg_info_ptr->msg_mapowner)); } iamv_exit: return (iamv_rc); } /**************************************************************** * NAME: IM_compare_leaf * * FUNCTION: Compare the 2 specified Inode Map B+Tree leaf * nodes to ensure that they are logically equivalent. * * PARAMETERS: * primary_leafptr - input - pointer to a leaf node in an inode * in the primary aggregate inode * allocation table in an fsck buffer * secondary_leafptr - input - pointer to a leaf node in an inode * in the secondary aggregate inode * allocation table in an fsck buffer * inconsistency_detected - input - pointer to a variable in which * to return !0 if errors are detected * 0 if no errors are detected * * RETURNS: * success: FSCK_OK * failure: something else */ int IM_compare_leaf(xtpage_t * leaf1ptr, xtpage_t * leaf2ptr, int *inconsistency_detected) { int imcl_rc = FSCK_OK; int16_t entry_idx; int64_t lf1_offset, lf2_offset; int64_t lf1_addr, lf2_addr; int32_t lf1_len, lf2_len; if ((leaf1ptr->header.flag != leaf2ptr->header.flag) || (leaf1ptr->header.nextindex != leaf2ptr->header.nextindex) || (leaf1ptr->header.maxentry != leaf2ptr->header.maxentry)) { *inconsistency_detected = -1; } entry_idx = XTENTRYSTART; while ((imcl_rc == FSCK_OK) && (!(*inconsistency_detected)) && (entry_idx < leaf1ptr->header.nextindex)) { lf1_offset = offsetXAD(&(leaf1ptr->xad[entry_idx])); lf2_offset = offsetXAD(&(leaf2ptr->xad[entry_idx])); if (lf1_offset != lf2_offset) { *inconsistency_detected = -1; } else { /* offsets match */ lf1_addr = addressXAD(&(leaf1ptr->xad[entry_idx])); lf2_addr = addressXAD(&(leaf2ptr->xad[entry_idx])); if (lf1_addr != lf2_addr) { *inconsistency_detected = -1; } else { /* addresses match */ lf1_len = lengthXAD(&(leaf1ptr->xad[entry_idx])); lf2_len = lengthXAD(&(leaf2ptr->xad[entry_idx])); if (lf1_len != lf2_len) { *inconsistency_detected = -1; } else { /* lengths match */ entry_idx++; } } } } return (imcl_rc); } /**************************************************************** * NAME: rebuild_agg_iamap * * FUNCTION: Rebuild the Aggregate Inode Allocation Map using data based * on fsck's observations of the aggregate. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int rebuild_agg_iamap() { int raiam_rc = FSCK_OK; int is_aggregate = -1; int which_it = 0; struct fsck_imap_msg_info imap_msg_info; struct fsck_imap_msg_info *msg_info_ptr; struct fsck_iag_info iag_info; struct fsck_iag_info *iag_info_ptr; if (agg_recptr->primary_ait_4part1) { which_it = fsck_primary; } else { which_it = fsck_secondary; } iag_info_ptr = &iag_info; iag_info_ptr->iamrecptr = &(agg_recptr->agg_imap); iag_info_ptr->iagtbl = agg_recptr->agg_imap.iag_tbl; iag_info_ptr->agtbl = agg_recptr->agg_imap.ag_tbl; iag_info_ptr->agg_inotbl = is_aggregate; msg_info_ptr = &(imap_msg_info); msg_info_ptr->msg_mapowner = fsck_aggregate; raiam_rc = inotbl_get_ctl_page(is_aggregate, &(iag_info_ptr->iamctlptr)); if (raiam_rc == FSCK_OK) { /* got the imap control page */ raiam_rc = iamap_rebuild(is_aggregate, which_it, which_it, iag_info_ptr, msg_info_ptr); } return (raiam_rc); } /**************************************************************** * NAME: rebuild_fs_iamaps * * FUNCTION: Rebuild the Fileset Inode Allocation Map using data based * on fsck's observations of the aggregate. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int rebuild_fs_iamaps() { int rfsiam_rc = FSCK_OK; int is_aggregate = 0; /* release 1 there is exactly 1 fileset */ int which_it = FILESYSTEM_I; int which_ait; struct fsck_imap_msg_info imap_msg_info; struct fsck_imap_msg_info *msg_info_ptr; struct fsck_iag_info iag_info; struct fsck_iag_info *iag_info_ptr; if (agg_recptr->primary_ait_4part2) { which_ait = fsck_primary; } else { which_ait = fsck_secondary; } iag_info_ptr = &iag_info; iag_info_ptr->iamrecptr = &(agg_recptr->fset_imap); iag_info_ptr->iagtbl = agg_recptr->fset_imap.iag_tbl; iag_info_ptr->agtbl = agg_recptr->fset_imap.ag_tbl; iag_info_ptr->agg_inotbl = is_aggregate; msg_info_ptr = &(imap_msg_info); msg_info_ptr->msg_mapowner = fsck_fileset; rfsiam_rc = inotbl_get_ctl_page(is_aggregate, &(iag_info_ptr->iamctlptr)); if (rfsiam_rc == FSCK_OK) { /* got the imap control page */ rfsiam_rc = iamap_rebuild(is_aggregate, which_it, which_ait, iag_info_ptr, msg_info_ptr); } return (rfsiam_rc); } /**************************************************************** * NAME: record_dupchk_inode_extents * * FUNCTION: For each inode extent in the aggregate (i.e., describing * either the Aggregate Inode Table or in the Fileset Inode * Table), for each block in the extent, record (in the * fsck workspace block map) that the block is allocated * and check to see if this is a duplicate allocation. (That * is, check to see if any other file system object has * claimed to own that block.) * * PARAMETERS: none * * NOTES: o Since this routine completes the fsck workspace * initialization needed by inode_get() (et al), this * routine ensures fsck I/O buffers contain the inode * it needs before invoking inode_get(). * (inode_get() is invoked to locate the inode within * the fsck I/O buffer.) * * RETURNS: * success: FSCK_OK * failure: something else */ int record_dupchk_inode_extents() { int rdie_rc = FSCK_OK; int aggregate_IAGs; /* AIT inodes are both aggregate owned */ int aggregate_IA_Inode = -1; int which_it; struct fsck_inode_record *inorecptr; struct fsck_ino_msg_info ino_msg_info; struct fsck_ino_msg_info *msg_info_ptr; msg_info_ptr = &(ino_msg_info); msg_info_ptr->msg_inonum = AGGREGATE_I; msg_info_ptr->msg_inotyp = fsck_metaIAG; msg_info_ptr->msg_dxdtyp = fsck_inoext; msg_info_ptr->msg_inopfx = fsck_aggr_inode; /* inodes representing the Inode Allocation Maps are aggregate inodes */ rdie_rc = record_imap_info(); if (rdie_rc == FSCK_OK) { /* * record (and check for duplicate allocations) the * inode extents described by aggregate IAGs */ /* aggregate IAGs */ aggregate_IAGs = -1; if (agg_recptr->primary_ait_4part1) { which_it = fsck_primary; } else { which_it = fsck_secondary; } msg_info_ptr->msg_inonum = AGGREGATE_I; rdie_rc = get_inorecptr(aggregate_IA_Inode, 0, AGGREGATE_I, &inorecptr); if ((rdie_rc == FSCK_OK) && (inorecptr == NULL)) { rdie_rc = FSCK_INTERNAL_ERROR_45; } else if (rdie_rc == FSCK_OK) { rdie_rc = record_dupchk_inoexts(aggregate_IAGs, which_it, &(agg_recptr->agg_imap. bkd_inodes), inorecptr, msg_info_ptr); } if (rdie_rc == FSCK_OK) { agg_recptr->inodes_in_aggregate = agg_recptr->agg_imap.bkd_inodes; agg_recptr->blocks_for_inodes = (agg_recptr->agg_imap.bkd_inodes * sizeof (struct dinode)) / sb_ptr->s_bsize; /* * record (and check for duplicate allocations) the * inode extents described by fileset IAGs * * (In release 1 there is exactly 1 fileset) */ /* fileset IAGs */ aggregate_IAGs = 0; which_it = FILESYSTEM_I; msg_info_ptr->msg_inonum = FILESYSTEM_I; rdie_rc = get_inorecptr(aggregate_IA_Inode, 0, FILESYSTEM_I, &inorecptr); if ((rdie_rc == FSCK_OK) && (inorecptr == NULL)) { rdie_rc = FSCK_INTERNAL_ERROR_20; } else if (rdie_rc == FSCK_OK) { rdie_rc = record_dupchk_inoexts(aggregate_IAGs, which_it, &(agg_recptr-> fset_imap. bkd_inodes), inorecptr, msg_info_ptr); } if (rdie_rc == FSCK_OK) { agg_recptr->inodes_in_aggregate += agg_recptr->fset_imap.bkd_inodes; agg_recptr->blocks_for_inodes += (agg_recptr->fset_imap.bkd_inodes * sizeof (struct dinode)) / sb_ptr->s_bsize; } } } return (rdie_rc); } /**************************************************************** * NAME: record_dupchk_inoexts * * FUNCTION: For each inode extent in the specified Inode Table (either * the Aggregate Inode Table or in the Fileset Inode Table), * for each block in the extent, record (in the fsck workspace * block map) that the block is allocated and check to see if * this is a duplicate allocation. (That is, check to see if * any other file system object has claimed to own that block.) * * PARAMETERS: * is_aggregate - input - !0 => aggregate owned * 0 => fileset owned * which_it - input - ordinal number of the aggregate inode * describing the inode table * backed_inode_count - input - pointer to a variable in which to return * the count of backed inodes described * by inode extents described by iags in * the current inode allocation table. * inorecptr - input - pointer to an fsck inode record which * describes the current inode allocation * table inode * msginfoptr - input - pointer to data needed to issue messages * about the current inode * * NOTES: o Since this routine completes the fsck workspace * initialization needed by inode_get() (et al), this * routine ensures fsck I/O buffers contain the inode * it needs before invoking inode_get(). * (inode_get() is invoked to locate the inode within * the fsck I/O buffer.) * * RETURNS: * success: FSCK_OK * failure: something else */ int record_dupchk_inoexts(int is_aggregate, int which_it, int32_t * backed_inode_count, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msginfoptr) { int irdie_rc = FSCK_OK; int which_ait; struct iag *iagptr; uint32_t ext_idx; uint32_t ext_idx_max; int64_t ext_addr; uint32_t ext_len; int8_t is_EA = 0; int8_t is_ACL = 0; int8_t extent_is_valid; uint32_t adjusted_length; uint32_t first_inonum, last_inonum; ext_idx_max = EXTSPERIAG - 1; *backed_inode_count = 0; if (is_aggregate) { if (agg_recptr->primary_ait_4part1) { which_ait = fsck_primary; } else { which_ait = fsck_secondary; } } else { if (agg_recptr->primary_ait_4part2) { which_ait = fsck_primary; } else { which_ait = fsck_secondary; } } irdie_rc = ait_special_read_ext1(which_ait); if (irdie_rc == FSCK_OK) { irdie_rc = iag_get_first(is_aggregate, which_it, which_ait, &iagptr); } else { report_readait_error(irdie_rc, FSCK_FAILED_CANTREADAITEXT9, which_ait); irdie_rc = FSCK_FAILED_CANTREADAITEXT9; } while ((irdie_rc == FSCK_OK) && (iagptr != NULL)) { for (ext_idx = 0; ((ext_idx <= ext_idx_max) && (irdie_rc == FSCK_OK)); ext_idx++) { ext_addr = addressPXD(&(iagptr->inoext[ext_idx])); if (ext_addr == 0) continue; /* the extent is allocated */ *backed_inode_count += INOSPEREXT; ext_len = lengthPXD(&(iagptr->inoext[ext_idx])); irdie_rc = process_extent(inorecptr, ext_len, ext_addr, is_EA, is_ACL, msginfoptr, &adjusted_length, &extent_is_valid, FSCK_RECORD_DUPCHECK); if (extent_is_valid) continue; /* yuck! */ irdie_rc = process_extent(inorecptr, ext_len, ext_addr, is_EA, is_ACL, msginfoptr, &adjusted_length, &extent_is_valid, FSCK_UNRECORD); first_inonum = (iagptr->iagnum * INOSPERIAG) + (ext_idx * INOSPEREXT); last_inonum = first_inonum + INOSPEREXT - 1; /* * notify the user */ fsck_send_msg(fsck_BADIAMIAGPXDU, first_inonum, last_inonum); /* * log more details */ fsck_send_msg(fsck_BADIAMIAGPXDL, first_inonum, last_inonum, fsck_ref_msg(msginfoptr->msg_inopfx), msginfoptr->msg_inonum, iagptr->iagnum, ext_idx); /* * fix it if we can */ if (agg_recptr->processing_readwrite) { /* we can fix this */ PXDaddress(&(iagptr->inoext[ext_idx]), 0); PXDlength(&(iagptr->inoext[ext_idx]), 0); irdie_rc = iag_put(iagptr); *backed_inode_count -= INOSPEREXT; fsck_send_msg(fsck_WILLRELEASEINOS, first_inonum, last_inonum); } else { /* we don't have write access */ agg_recptr->ag_dirty = 1; irdie_rc = FSCK_FAILED_IAG_CORRUPT_PXD; fsck_send_msg(fsck_CANTRECOVERINOS, first_inonum, last_inonum); } } if (irdie_rc == FSCK_OK) irdie_rc = iag_get_next(&iagptr); } return (irdie_rc); } /**************************************************************** * NAME: record_imap_info * * FUNCTION: Find and then record, in the fsck global aggregate record, * information describing the Inode Allocation Maps (i.e., * the Aggregate Inode Allocation Map and the Fileset Inode * Allocation Map) which will be used to expedite subsequent * access to the maps. * * PARAMETERS: none * * NOTES: o Since this routine completes the fsck workspace * initialization needed by inode_get() (et al), this * routine ensures fsck I/O buffers contain the inode * it needs before invoking inode_get(). * (inode_get() is invoked to locate the inode within * the fsck I/O buffer.) * * RETURNS: * success: FSCK_OK * failure: something else */ int record_imap_info() { int rii_rc = FSCK_OK; int intermed_rc = FSCK_OK; int aggregate_inode = 1; /* aggregate owned inodes */ int which_ait; uint32_t ino_idx; int64_t leaf_fsblk_offset; struct dinode *ino_ptr; xtpage_t *dummy_page; int8_t inline_data; if (agg_recptr->primary_ait_4part1) { which_ait = fsck_primary; } else { which_ait = fsck_secondary; } intermed_rc = ait_special_read_ext1(which_ait); if (intermed_rc != FSCK_OK) { report_readait_error(intermed_rc, FSCK_FAILED_CANTREADAITEXTA, which_ait); rii_rc = FSCK_FAILED_CANTREADAITEXTA; goto rii_exit; } /* got the inode extension needed for part 1 */ /* the aggregate inode map inode */ ino_idx = AGGREGATE_I; rii_rc = inode_get(aggregate_inode, which_ait, ino_idx, &ino_ptr); if (rii_rc != FSCK_OK) { /* but we read this before! */ rii_rc = FSCK_FAILED_SELF_READ2; goto rii_exit; } /* successful read on aggregate inode map inode */ rii_rc = find_first_leaf(ino_ptr, &dummy_page, &leaf_fsblk_offset, &inline_data, &(agg_recptr->agg_imap.imap_is_rootleaf)); if (rii_rc != FSCK_OK) { /* but it had a valid tree before */ rii_rc = FSCK_FAILED_SELF_NOWBAD; goto rii_exit; } /* got the info for the aggregate imap */ agg_recptr->agg_imap.first_leaf_offset = leaf_fsblk_offset * sb_ptr->s_bsize; if ((agg_recptr->primary_ait_4part1 && !agg_recptr->primary_ait_4part2) || (!agg_recptr->primary_ait_4part1 && agg_recptr->primary_ait_4part2)) { /* * part1 and part2 of the AIT are not being * used from the same table */ if (agg_recptr->primary_ait_4part2) { which_ait = fsck_primary; } else { which_ait = fsck_secondary; } intermed_rc = ait_special_read_ext1(which_ait); if (intermed_rc != FSCK_OK) { report_readait_error(intermed_rc, FSCK_FAILED_CANTREADAITEXTB, which_ait); rii_rc = FSCK_FAILED_CANTREADAITEXTB; goto rii_exit; } } /* inode extent is in the buffer */ /* the aggregate inode map inode */ ino_idx = FILESYSTEM_I; rii_rc = inode_get(aggregate_inode, which_ait, ino_idx, &ino_ptr); if (rii_rc != FSCK_OK) { /* but we read this before! */ rii_rc = FSCK_FAILED_AGFS_READ2; goto rii_exit; } /* successful read on aggregate inode map inode */ rii_rc = find_first_leaf(ino_ptr, &dummy_page, &leaf_fsblk_offset, &inline_data, &(agg_recptr->fset_imap.imap_is_rootleaf)); if (rii_rc != FSCK_OK) { /* but it had a valid tree before */ rii_rc = FSCK_FAILED_AGFS_NOWBAD; goto rii_exit; } /* got the info for the fileset imap */ agg_recptr->fset_imap.first_leaf_offset = leaf_fsblk_offset * sb_ptr->s_bsize; rii_exit: return (rii_rc); } /**************************************************************** * NAME: verify_agg_iamap * * FUNCTION: Verify that the Aggregate Inode Allocation Map is correct * according to fsck's observations of the aggregate. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int verify_agg_iamap() { int vaiam_rc = FSCK_OK; int is_aggregate = -1; int which_it = 0; struct fsck_imap_msg_info imap_msg_info; struct fsck_imap_msg_info *msg_info_ptr; struct fsck_iag_info iag_info; struct fsck_iag_info *iag_info_ptr; if (agg_recptr->primary_ait_4part1) { which_it = fsck_primary; } else { which_it = fsck_secondary; } iag_info_ptr = &iag_info; iag_info_ptr->iamrecptr = &(agg_recptr->agg_imap); iag_info_ptr->iagtbl = agg_recptr->agg_imap.iag_tbl; iag_info_ptr->agtbl = agg_recptr->agg_imap.ag_tbl; iag_info_ptr->agg_inotbl = is_aggregate; msg_info_ptr = &(imap_msg_info); msg_info_ptr->msg_mapowner = fsck_aggregate; vaiam_rc = inotbl_get_ctl_page(is_aggregate, &(iag_info_ptr->iamctlptr)); if (vaiam_rc == FSCK_OK) { /* got the imap control page */ vaiam_rc = iamap_validation(is_aggregate, which_it, which_it, iag_info_ptr, msg_info_ptr); } return (vaiam_rc); } /**************************************************************** * NAME: verify_fs_iamaps * * FUNCTION: Verify that the Fileset Inode Allocation Map is correct * according to fsck's observations of the aggregate. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int verify_fs_iamaps() { int vfsiam_rc = FSCK_OK; int is_aggregate = 0; /* release 1 there is exactly 1 fileset */ int which_it = FILESYSTEM_I; int which_ait; struct fsck_imap_msg_info imap_msg_info; struct fsck_imap_msg_info *msg_info_ptr; struct fsck_iag_info iag_info; struct fsck_iag_info *iag_info_ptr; if (agg_recptr->primary_ait_4part2) { which_ait = fsck_primary; } else { which_ait = fsck_secondary; } iag_info_ptr = &iag_info; iag_info_ptr->iamrecptr = &(agg_recptr->fset_imap); iag_info_ptr->iagtbl = agg_recptr->fset_imap.iag_tbl; iag_info_ptr->agtbl = agg_recptr->fset_imap.ag_tbl; iag_info_ptr->agg_inotbl = is_aggregate; msg_info_ptr = &(imap_msg_info); msg_info_ptr->msg_mapowner = fsck_fileset; vfsiam_rc = inotbl_get_ctl_page(is_aggregate, &(iag_info_ptr->iamctlptr)); if (vfsiam_rc == FSCK_OK) { /* got the imap control page */ vfsiam_rc = iamap_validation(is_aggregate, which_it, which_ait, iag_info_ptr, msg_info_ptr); } return (vfsiam_rc); } /*-------------------------------------------------------------------- * NAME: xtAppend * * FUNCTION: Append an extent to the specified file * * PARAMETERS: * di - Inode to add extent to * offset - offset of extent to add * blkno - block number of start of extent to add * nblocks - number of blocks in extent to add * xpage - xtree page to add extent to * * NOTES: xpage points to its parent in the xtree and its rightmost child (if it * has one). It also points to the buffer for the page. * * RETURNS: 0 for success; Other indicates failure */ int xtAppend(struct dinode *di, int64_t offset, int64_t blkno, int32_t nblocks, struct xtree_buf *xpage) { int rc = 0; int32_t index; xad_t *xad; xtpage_t *cur_page; cur_page = xpage->page; index = cur_page->header.nextindex; /* insert entry for new extent */ if (index == cur_page->header.maxentry) { /* * There is not room in this page to add the entry; Need to * create a new page */ if (cur_page->header.flag & BT_ROOT) { /* This is the root of the xtree; need to split root */ rc = xtSplitRoot(di, xpage, offset, nblocks, blkno); } else { /* * Non-root page: add new page at this level, * xtSplitPage() calls xtAppend again to propogate up * the new page entry */ rc = xtSplitPage(di, xpage, offset, nblocks, blkno); } } else { /* There is room to add the entry to this page */ xad = &cur_page->xad[index]; XADoffset(xad, offset); XADlength(xad, nblocks); XADaddress(xad, blkno); /* advance next available entry index */ ++cur_page->header.nextindex; rc = 0; } return rc; } /*-------------------------------------------------------------------- * NAME: xtSplitPage * * FUNCTION: Split non-root page of xtree * * PARAMETERS: * ip - Inode of xtree splitting * xpage - page to split * offset - offset of new extent to add * nblocks - number of blocks of new extent to add * blkno - starting block number of new extent to add * * RETURNS: 0 for success; Other indicates failure */ int xtSplitPage(struct dinode *ip, struct xtree_buf *xpage, int64_t offset, int32_t nblocks, int64_t blkno) { int rc = 0; int64_t xaddr; /* new right page block number */ xad_t *xad; int32_t xlen; xtpage_t *lastpage, *newpage; int64_t leftbn; /* Allocate disk space for the new xtree page */ xlen = 1 << agg_recptr->log2_blksperpg; rc = fsck_alloc_fsblks(xlen, &xaddr); if (rc) return rc; /* * Modify xpage's next entry to point to the new disk space, * write the xpage to disk since we won't be needing it anymore. */ lastpage = xpage->page; lastpage->header.next = xaddr; leftbn = addressPXD(&(lastpage->header.self)); /* swap if on bid endian machine */ ujfs_swap_xtpage_t(lastpage); rc = ujfs_rw_diskblocks(Dev_IOPort, leftbn * sb_ptr->s_bsize, PSIZE, lastpage, PUT); ujfs_swap_xtpage_t(lastpage); if (rc != 0) return rc; /* * We are now done with the xpage as-is. We can now re-use this buffer * for our new buffer. */ newpage = xpage->page; PXDlength(&(newpage->header.self), xlen); PXDaddress(&(newpage->header.self), xaddr); newpage->header.flag = newpage->header.flag & BT_TYPE; /* initialize sibling pointers of newpage */ newpage->header.next = 0; newpage->header.prev = leftbn; /* insert entry at the first entry of the new right page */ xad = &newpage->xad[XTENTRYSTART]; XADoffset(xad, offset); XADlength(xad, nblocks); XADaddress(xad, blkno); newpage->header.nextindex = XTENTRYSTART + 1; /* Now append new page to parent page */ rc = xtAppend(ip, offset, xaddr, xlen, xpage->up); /* Update inode to account for new page */ ip->di_nblocks += xlen; return rc; } /*-------------------------------------------------------------------- * NAME: xtSplitRoot * * FUNCTION: Split full root of xtree * * PARAMETERS: * ip - Inode of xtree * xroot - Root of xtree * offset - Offset of extent to add * nblocks - number of blocks for extent to add * blkno - starting block of extent to add * * RETURNS: 0 for success; Other indicates failure */ int xtSplitRoot(struct dinode *ip, struct xtree_buf *xroot, int64_t offset, int32_t nblocks, int64_t blkno) { xtpage_t *rootpage; xtpage_t *newpage; int64_t xaddr; int32_t nextindex; xad_t *xad; int rc; struct xtree_buf *newbuf; int32_t xlen; int I_am_logredo = 0; /* Allocate and initialize buffer for new page to accomodate the split */ rc = alloc_wrksp(sizeof (struct xtree_buf), dynstg_xtreebuf, I_am_logredo, (void **) &newbuf); if (rc) return (rc); newbuf->up = xroot; if (xroot->down == NULL) { fsim_node_pages = newbuf; } else { xroot->down->up = newbuf; } newbuf->down = xroot->down; xroot->down = newbuf; rc = alloc_wrksp(PSIZE, dynstg_xtreepagebuf, I_am_logredo, (void **) &newpage); if (rc) return (rc); newbuf->page = newpage; /* Allocate disk blocks for new page */ xlen = 1 << agg_recptr->log2_blksperpg; rc = fsck_alloc_fsblks(xlen, &xaddr); if (rc) return rc; rootpage = xroot->page; /* Initialize new page */ if ((rootpage->header.flag & BT_LEAF) == BT_LEAF) { newpage->header.flag = BT_LEAF; } else { newpage->header.flag = BT_INTERNAL; } PXDlength(&(newpage->header.self), xlen); PXDaddress(&(newpage->header.self), xaddr); newpage->header.nextindex = XTENTRYSTART; newpage->header.maxentry = XTPAGEMAXSLOT; /* initialize sibling pointers */ newpage->header.next = 0; newpage->header.prev = 0; /* copy the in-line root page into new right page extent */ nextindex = rootpage->header.maxentry; memcpy(&newpage->xad[XTENTRYSTART], &rootpage->xad[XTENTRYSTART], (nextindex - XTENTRYSTART) << L2XTSLOTSIZE); /* insert the new entry into the new right/child page */ xad = &newpage->xad[nextindex]; XADoffset(xad, offset); XADlength(xad, nblocks); XADaddress(xad, blkno); /* update page header */ newpage->header.nextindex = nextindex + 1; /* init root with the single entry for the new right page */ xad = &rootpage->xad[XTENTRYSTART]; XADoffset(xad, 0); XADlength(xad, xlen); XADaddress(xad, xaddr); /* update page header of root */ rootpage->header.flag &= ~BT_LEAF; rootpage->header.flag |= BT_INTERNAL; rootpage->header.nextindex = XTENTRYSTART + 1; /* Update nblocks for inode to account for new page */ ip->di_nblocks += xlen; return 0; } jfsutils-1.1.15.orig/fsck/fsckino.c0000644000000000000000000020067510441103234014017 0ustar /* * Copyright (C) International Business Machines Corp., 2000-2004 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include /* defines and includes common among the fsck.jfs modules */ #include "xfsckint.h" #include "jfs_byteorder.h" #include "jfs_unicode.h" #include "unicode_to_utf8.h" /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * superblock buffer pointer * * defined in xchkdsk.c */ extern struct superblock *sb_ptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * fsck aggregate info structure pointer * * defined in xchkdsk.c */ extern struct fsck_agg_record *agg_recptr; extern int32_t Uni_Name_len; extern UniChar Uni_Name[]; extern int32_t Str_Name_len; extern char Str_Name[]; /***************************************************************************** * NAME: backout_ACL * * FUNCTION: Unrecord all storage allocated for the access control list * (ACL) of the current inode. * * PARAMETERS: * ino_ptr - input - pointer to the current inode * ino_recptr - input - pointer to an fsck inode record describing the * current inode * * RETURNS: * success: FSCK_OK * failure: something else */ int backout_ACL(struct dinode *ino_ptr, struct fsck_inode_record *ino_recptr) { int bacl_rc = FSCK_OK; uint32_t block_count = 0; uint32_t extent_length; int64_t extent_address; int8_t extent_is_valid; /* * the following will be passed to extent_unrecord() which will * ignore them. */ int8_t is_EA = 0; int8_t is_ACL = 1; struct fsck_ino_msg_info *msg_info_ptr = NULL; /* * if the ACL is in an out-of-line extent, release the blocks * allocated for it. */ if (ino_ptr->di_acl.flag == DXD_EXTENT) { extent_length = lengthDXD(&(ino_ptr->di_acl)); extent_address = addressDXD(&(ino_ptr->di_acl)); bacl_rc = process_extent(ino_recptr, extent_length, extent_address, is_EA, is_ACL, msg_info_ptr, &block_count, &extent_is_valid, FSCK_UNRECORD); } /* * backout the blocks in the ACL extent from the running totals for * fileset and inode, but not for the object * represented by the object (because they were never added to that). */ agg_recptr->blocks_this_fset -= block_count; agg_recptr->this_inode.all_blks -= block_count; return (bacl_rc); } /***************************************************************************** * NAME: backout_EA * * FUNCTION: Unrecord all storage allocated for the extended attributes * (ea) of the current inode. * * PARAMETERS: * ino_ptr - input - pointer to the current inode * ino_recptr - input - pointer to an fsck inode record describing the * current inode * * RETURNS: * success: FSCK_OK * failure: something else */ int backout_EA(struct dinode *ino_ptr, struct fsck_inode_record *ino_recptr) { int bea_rc = FSCK_OK; uint32_t block_count = 0; uint32_t extent_length; int64_t extent_address; int8_t extent_is_valid; /* * the following will be passed to extent_unrecord() which will * ignore them. */ int8_t is_EA = 1; int8_t is_ACL = 0; struct fsck_ino_msg_info *msg_info_ptr = NULL; /* * if the EA is in an out-of-line extent, release the blocks * allocated for it. */ if (ino_ptr->di_ea.flag == DXD_EXTENT) { extent_length = lengthDXD(&(ino_ptr->di_ea)); extent_address = addressDXD(&(ino_ptr->di_ea)); bea_rc = process_extent(ino_recptr, extent_length, extent_address, is_EA, is_ACL, msg_info_ptr, &block_count, &extent_is_valid, FSCK_UNRECORD); } /* * backout the blocks in the EA extent from the running totals for * fileset and inode, but not for the object * represented by the object (because they were never added to that). */ agg_recptr->blocks_this_fset -= block_count; agg_recptr->this_inode.all_blks -= block_count; return (bea_rc); } /***************************************************************************** * NAME: clear_ACL_field * * FUNCTION: Unrecord all storage allocated for the access control list * (ACL) of the current inode. Clear the inode ACL field to show * the inode owns no ACL. * * PARAMETERS: * ino_recptr - input - pointer to an fsck inode record describing the * current inode * ino_ptr - input - pointer to the current inode * * RETURNS: * success: FSCK_OK * failure: something else */ int clear_ACL_field(struct fsck_inode_record *ino_recptr, struct dinode *ino_ptr) { int caf_rc = FSCK_OK; dxd_t *dxd_ptr; uint32_t block_count = 0; uint32_t extent_length; int64_t extent_address; int8_t extent_is_valid; /* * the following will be passed to extent_unrecord() which will * ignore them. */ int8_t is_EA = 0; int8_t is_ACL = -1; struct fsck_ino_msg_info *msg_info_ptr = NULL; /* locate the EA field in the inode */ dxd_ptr = &(ino_ptr->di_acl); /* * if the ACL is in an out-of-line extent, release the blocks * allocated for it. */ if ((dxd_ptr->flag == DXD_EXTENT) && (!ino_recptr->ignore_acl_blks) && (!ino_recptr->ignore_alloc_blks)) { /* out of line single extent and not flagged to ignore */ extent_length = lengthDXD(dxd_ptr); extent_address = addressDXD(dxd_ptr); caf_rc = process_extent(ino_recptr, extent_length, extent_address, is_EA, is_ACL, msg_info_ptr, &block_count, &extent_is_valid, FSCK_UNRECORD); ino_ptr->di_nblocks -= block_count; agg_recptr->blocks_for_acls -= block_count; } /* * Clear the ACL field */ if (caf_rc == FSCK_OK) { dxd_ptr->flag = DXD_CORRUPT; /* clear the data length */ DXDlength(dxd_ptr, 0); /* clear the data address */ DXDaddress(dxd_ptr, 0); agg_recptr->blocks_this_fset -= block_count; } return (caf_rc); } /***************************************************************************** * NAME: clear_EA_field * * FUNCTION: Unrecord all storage allocated for the extended attributes * (ea) of the current inode. Clear the inode ea field to show * the inode owns no ea. * * PARAMETERS: * ino_recptr - input - pointer to an fsck inode record describing the * current inode * ino_ptr - input - pointer to the current inode * * RETURNS: * success: FSCK_OK * failure: something else */ int clear_EA_field(struct fsck_inode_record *ino_recptr, struct dinode *ino_ptr) { int cef_rc = FSCK_OK; dxd_t *dxd_ptr; uint32_t block_count = 0; uint32_t extent_length; int64_t extent_address; int8_t extent_is_valid; /* * the following will be passed to extent_unrecord() which will * ignore them. */ int8_t is_EA = -1; int8_t is_ACL = 0; struct fsck_ino_msg_info *msg_info_ptr = NULL; /* locate the EA field in the inode */ dxd_ptr = &(ino_ptr->di_ea); /* * if the EA is in an out-of-line extent, release the blocks * allocated for it. */ if ((dxd_ptr->flag == DXD_EXTENT) && (!ino_recptr->ignore_ea_blks) && (!ino_recptr->ignore_alloc_blks)) { /* out of line single extent and not flagged to ignore */ extent_length = lengthDXD(dxd_ptr); extent_address = addressDXD(dxd_ptr); cef_rc = process_extent(ino_recptr, extent_length, extent_address, is_EA, is_ACL, msg_info_ptr, &block_count, &extent_is_valid, FSCK_UNRECORD); agg_recptr->blocks_for_eas -= block_count; } /* * Clear the EA field */ if (cef_rc == FSCK_OK) { dxd_ptr->flag = 0; /* clear the data length */ DXDlength(dxd_ptr, 0); /* clear the data address */ DXDaddress(dxd_ptr, 0); ino_ptr->di_nblocks -= block_count; agg_recptr->blocks_this_fset -= block_count; } return (cef_rc); } /***************************************************************************** * NAME: display_path * * FUNCTION: Issue a message to display the given inode path. * * PARAMETERS: * inoidx - input - ordinal number of the inode as an integer * inopfx - input - index (into message catalog) of prefix for * inode number when displayed in message * { A | } * ino_parent - input - the inode number for the (parent) directory * whose entry to the current inode is described * by the contents of inopath. * inopath - input - pointer to the UniCharacter path which is * to be displayed. * ino_recptr - input - pointer to an fsck inode record describing the * current inode * * RETURNS: * success: FSCK_OK * failure: something else */ int display_path(uint32_t inoidx, int inopfx, uint32_t ino_parent, char *inopath, struct fsck_inode_record *ino_recptr) { int dip_rc = FSCK_OK; if ((!ino_recptr->unxpctd_prnts) || (!(ino_recptr->inode_type == directory_inode))) { /* not directory w/ mult parents */ if (ino_recptr->inode_type == directory_inode) { fsck_send_msg(fsck_INOPATHOK, fsck_ref_msg(fsck_directory), fsck_ref_msg(inopfx), inoidx, inopath); } else if (ino_recptr->inode_type == char_special_inode) { fsck_send_msg(fsck_INOPATHOK, fsck_ref_msg(fsck_char_special), fsck_ref_msg(inopfx), inoidx, inopath); } else if (ino_recptr->inode_type == block_special_inode) { fsck_send_msg(fsck_INOPATHOK, fsck_ref_msg(fsck_block_special), fsck_ref_msg(inopfx), inoidx, inopath); } else if (ino_recptr->inode_type == FIFO_inode) { fsck_send_msg(fsck_INOPATHOK, fsck_ref_msg(fsck_FIFO), fsck_ref_msg(inopfx), inoidx, inopath); } else if (ino_recptr->inode_type == SOCK_inode) { fsck_send_msg(fsck_INOPATHOK, fsck_ref_msg(fsck_SOCK), fsck_ref_msg(inopfx), inoidx, inopath); } else { /* regular file */ fsck_send_msg(fsck_INOPATHOK, fsck_ref_msg(fsck_file), fsck_ref_msg(inopfx), inoidx, inopath); } } else { /* else a directory w/ multiple parents */ if (ino_parent == ino_recptr->parent_inonum) { /* expected parent */ fsck_send_msg(fsck_INOPATHCRCT, inopath, fsck_ref_msg(inopfx), inoidx); } else { /* this is an illegal hard link */ fsck_send_msg(fsck_INOPATHBAD, fsck_ref_msg(fsck_directory), fsck_ref_msg(inopfx), inoidx, inopath); } } return (dip_rc); } /***************************************************************************** * NAME: display_paths * * FUNCTION: Display all paths to the specified inode. * * PARAMETERS: * inoidx - input - ordinal number of the inode as an integer * ino_recptr - input - pointer to an fsck inode record describing the * current inode * msg_info_ptr - input - pointer to a record with information needed * to issue messages about the current inode * * RETURNS: * success: FSCK_OK * failure: something else */ int display_paths(uint32_t inoidx, struct fsck_inode_record *ino_recptr, struct fsck_ino_msg_info *msg_info_ptr) { int dips_rc = FSCK_OK; int intermed_rc; uint32_t this_parent = 0; struct fsck_inode_ext_record *this_ext = NULL; char *this_path_ptr; char **this_path_ptr_ptr; struct fsck_inode_record *parent_inorecptr; int a_path_displayed = 0; this_path_ptr_ptr = &this_path_ptr; if (inoidx == 2) { /* it's the root directory */ intermed_rc = get_path(inoidx, this_parent, this_path_ptr_ptr, ino_recptr); a_path_displayed = -1; dips_rc = display_path(inoidx, msg_info_ptr->msg_inopfx, this_parent, this_path_ptr, ino_recptr); goto out; } else if (ino_recptr->parent_inonum == 0) goto out; /* at least one parent was observed */ /* * if this is a directory with illegal hard links then the * inode number in the fsck inode record is the one stored in * the inode on disk. This routine displays only messages * for parents observed by fsck. */ if ((ino_recptr->inode_type == directory_inode) && (ino_recptr->unxpctd_prnts)) { /* dir with multiple parents */ this_ext = ino_recptr->ext_rec; while ((this_ext != NULL) && (this_ext->ext_type != parent_extension)) { this_ext = this_ext->next; } if (this_ext == NULL) { /* something is terribly wrong! */ dips_rc = FSCK_INTERNAL_ERROR_1; } } else { /* not a dir with multiple parents */ /* * the 1st parent observed is in the inode record. Any * others are in extension records. */ this_parent = ino_recptr->parent_inonum; if ((this_parent != ROOT_I) || (!agg_recptr->rootdir_rebuilt)) { /* * either this parent isn't the root or else * the root dir has not been rebuilt */ intermed_rc = get_inorecptr(0, 0, this_parent, &parent_inorecptr); if (intermed_rc != FSCK_OK) { dips_rc = intermed_rc; } else if ((parent_inorecptr->in_use) && (!parent_inorecptr->selected_to_rls) && (!parent_inorecptr->ignore_alloc_blks)) { /* got parent record and parent ok so far */ intermed_rc = get_path(inoidx, this_parent, this_path_ptr_ptr, ino_recptr); if (intermed_rc != FSCK_OK) { /* unable to obtain 1st path */ fsck_send_msg(fsck_INOCNTGETPATH, fsck_ref_msg(msg_info_ptr->msg_inopfx), this_parent, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), inoidx); if (intermed_rc < 0) { /* it's fatal */ dips_rc = intermed_rc; } } else { /* 1st path obtained */ a_path_displayed = -1; dips_rc = display_path(inoidx, msg_info_ptr-> msg_inopfx, this_parent, this_path_ptr, ino_recptr); /* * if there are any more paths to the * inode, find the next parent */ this_ext = ino_recptr->ext_rec; while ((this_ext != NULL) && (this_ext->ext_type != parent_extension)) { this_ext = this_ext->next; } } } } } while ((dips_rc == FSCK_OK) && (this_ext != NULL)) { /* there may be more parents */ if (this_ext->ext_type == parent_extension) { /* parent extension */ this_parent = this_ext->inonum; if ((this_parent != ROOT_I) || (!agg_recptr->rootdir_rebuilt)) { /* * either this parent isn't the root or else * the root dir has not been rebuilt */ intermed_rc = get_inorecptr(0, 0, this_parent, &parent_inorecptr); if (intermed_rc != 0) { /* it's fatal */ dips_rc = intermed_rc; } else if ((parent_inorecptr->in_use) && (!parent_inorecptr-> selected_to_rls) && (!parent_inorecptr-> ignore_alloc_blks)) { /* got parent record and parent seems * ok so far */ intermed_rc = get_path(inoidx, this_parent, this_path_ptr_ptr, ino_recptr); if (intermed_rc == FSCK_OK) { /* next path obtained */ a_path_displayed = -1; dips_rc = display_path(inoidx, msg_info_ptr-> msg_inopfx, this_parent, this_path_ptr, ino_recptr); } else { /* unable to obtain next path */ fsck_send_msg (fsck_INOCNTGETPATH, fsck_ref_msg(msg_info_ptr->msg_inopfx), this_parent, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), inoidx); if (intermed_rc < 0) { dips_rc = intermed_rc; } } } } } this_ext = this_ext->next; } /* * if nothing unexpected happened but we * couldn't display a path, issue a message * and go on. */ out: if ((dips_rc == FSCK_OK) && (!a_path_displayed)) { fsck_send_msg(fsck_INOCANTNAME, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), inoidx); } return (dips_rc); } /***************************************************************************** * NAME: first_ref_check_inode * * FUNCTION: Determine whether storage allocated to the given inode * includes any multiply-allocated blocks for which the * first reference is still unresolved. * * PARAMETERS: * inoptr - input - pointer to the current inode * inoidx - input - ordinal number of the inode as an integer * inorec_ptr - input - pointer to an fsck inode record describing the * current inode * msginfo_ptr - input - pointer to a record with information needed * to issue messages about the current inode * * RETURNS: * success: FSCK_OK * failure: something else */ int first_ref_check_inode(struct dinode *inoptr, uint32_t inoidx, struct fsck_inode_record *inorec_ptr, struct fsck_ino_msg_info *msginfo_ptr) { int frcvi_rc = FSCK_OK; uint32_t block_count; int64_t first_fsblk; uint32_t num_fsblks; int8_t extent_is_valid; dxd_t *dxd_ptr; int is_EA; int is_ACL; /* * check the extent (if any) containing the EA */ if (inoptr->di_ea.flag == DXD_EXTENT) { /* there is an ea to record */ dxd_ptr = &(inoptr->di_ea); first_fsblk = addressDXD(dxd_ptr); num_fsblks = lengthDXD(dxd_ptr); is_EA = -1; is_ACL = 0; msginfo_ptr->msg_dxdtyp = fsck_EA; frcvi_rc = process_extent(inorec_ptr, num_fsblks, first_fsblk, is_EA, is_ACL, msginfo_ptr, &block_count, &extent_is_valid, FSCK_QUERY); } /* * check the extent (if any) containing the ACL */ if (inoptr->di_acl.flag == DXD_EXTENT) { /* there is an ACL to record */ dxd_ptr = &(inoptr->di_acl); first_fsblk = addressDXD(dxd_ptr); num_fsblks = lengthDXD(dxd_ptr); is_EA = 0; is_ACL = -1; msginfo_ptr->msg_dxdtyp = fsck_ACL; frcvi_rc = process_extent(inorec_ptr, num_fsblks, first_fsblk, is_EA, is_ACL, msginfo_ptr, &block_count, &extent_is_valid, FSCK_QUERY); } /* * check the extents (if any) described as data */ if (frcvi_rc == FSCK_OK) { if (inorec_ptr->inode_type == directory_inode) { frcvi_rc = process_valid_dir_data(inoptr, inoidx, inorec_ptr, msginfo_ptr, FSCK_QUERY); } else if (ISREG(inoptr->di_mode) || ISLNK(inoptr->di_mode)) { frcvi_rc = process_valid_data(inoptr, inoidx, inorec_ptr, msginfo_ptr, FSCK_QUERY); } } return (frcvi_rc); } /***************************************************************************** * NAME: get_path * * FUNCTION: Construct the unicode path from the root directory through * the entry in the specified parent directory. * * PARAMETERS: * inode_idx - input - ordinal number of the inode as an integer * parent_inonum - input - the inode number for the (parent) directory * whose entry to the current inode is to be * described by the contents of inopath. * addr_path_addr - input - pointer to a variable in which to return * the address of the path (in UniChars) * ino_recptr - input - pointer to an fsck inode record describing * the current inode * * RETURNS: * success: FSCK_OK * failure: something else */ int get_path(uint32_t inode_idx, uint32_t parent_inonum, char **addr_path_addr, struct fsck_inode_record *ino_recptr) { int gip_rc = FSCK_OK; uint32_t inode_inonum; uint32_t this_parent_inonum; int bytes_used; int this_name_length = 0; int length_in_UniChars; UniChar uniname[256]; char *path_ptr; int path_idx; int path_completed = 0; uint32_t parent_idx; struct fsck_inode_record *parent_inorecptr; int aggregate_inode = 0; int alloc_ifnull = 0; *addr_path_addr = NULL; bytes_used = sizeof (char); path_idx = JFS_PATH_MAX - 1; agg_recptr->path_buffer[path_idx] = '\0'; path_ptr = &(agg_recptr->path_buffer[path_idx]); /* change the inode index to an inode number */ inode_inonum = (uint32_t) inode_idx; /* the first parent must be given since the object may not be a * directory */ this_parent_inonum = parent_inonum; if (inode_idx == 2) { /* it's the root directory */ path_completed = -1; path_idx--; path_ptr--; agg_recptr->path_buffer[path_idx] = agg_recptr->delim_char; } while ((!path_completed) && (gip_rc == FSCK_OK)) { gip_rc = direntry_get_objnam(this_parent_inonum, inode_inonum, &length_in_UniChars, uniname); uniname[length_in_UniChars] = 0; if (gip_rc != FSCK_OK) { /* didn't get the name */ path_completed = -1; if (path_idx != (JFS_PATH_MAX - 1)) { /* we got part of the path */ /* remove the foreslash from the * beginning of the path we have at this * beginning as now assembled it implies * that the unconnected dir parent is * connected to the fileset root directory. */ path_ptr++; } break; } this_name_length = Unicode_String_to_UTF8_String((uint8_t *) Str_Name, uniname, 256); Str_Name[this_name_length] = '\0'; if ((bytes_used + this_name_length + sizeof (char)) > JFS_PATH_MAX) { /* the path is beyond the legal length */ path_completed = -1; if (path_idx == (JFS_PATH_MAX - 1)) { /* the very first segment * is too long to be valid */ gip_rc = FSCK_FAILED_DIRENTRYBAD; } else { /* we got part of the path */ /* remove the foreslash from the * beginning of the path we have at * this point since as now assembled * it implies that the unconnected dir * parent is connected to the fileset * root directory. */ path_ptr++; } break; } bytes_used += this_name_length; path_idx -= this_name_length; path_ptr -= this_name_length; Str_Name_len = this_name_length; memcpy((void *) path_ptr, (void *) &Str_Name, Str_Name_len); bytes_used += sizeof (char); path_idx--; path_ptr--; agg_recptr->path_buffer[path_idx] = agg_recptr->delim_char; /* * assume that we'll find a parent dir for the * path segment just copied into the path buffer. */ if (this_parent_inonum == ROOT_I) { path_completed = -1; break; } /* haven't gotten up to root yet */ parent_idx = (uint32_t) this_parent_inonum; inode_inonum = this_parent_inonum; gip_rc = get_inorecptr(aggregate_inode, alloc_ifnull, parent_idx, &parent_inorecptr); if ((gip_rc == FSCK_OK) && (parent_inorecptr == NULL)) gip_rc = FSCK_INTERNAL_ERROR_21; if (gip_rc != FSCK_OK) break; this_parent_inonum = parent_inorecptr->parent_inonum; if ((this_parent_inonum == 0) || (parent_inorecptr->selected_to_rls) || (!(parent_inorecptr->in_use)) || (parent_inorecptr->inode_type == metadata_inode)) { path_completed = -1; /* remove the foreslash from the beginning * of the path we have at this point since * as now assembled it implies that the * unconnected dir parent is connected to * the fileset root directory. */ path_ptr++; } } if (gip_rc == FSCK_OK) /* indicate where to find the 1st char of the path just * assembled */ *addr_path_addr = path_ptr; return (gip_rc); } /***************************************************************************** * NAME: in_inode_data_check * * FUNCTION: Verify that the fields in the current inode which describe * inline data (that is, storage within the inode itself) do * not overlap. * * PARAMETERS: * msg_info_ptr - input - pointer to a record with information needed * to issue messages about the current inode * * NOTES: The data regarding inline data for the inode is stored in * the global aggregate record, fields in the this_inode record. * * RETURNS: * success: FSCK_OK * failure: something else */ int in_inode_data_check(struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr) { int iidc_rc = FSCK_OK; int16_t size16; struct dinode an_inode; /* * if in-inode data (or description of data) overflows * this then the EA can NOT be inline */ size16 = sizeof (an_inode.di_inlinedata); if (agg_recptr->this_inode.in_inode_data_length > size16) { /* extra long inline data */ if (agg_recptr->this_inode.ea_inline) { /* conflict */ inorecptr->selected_to_rls = 1; inorecptr->inline_data_err = 1; inorecptr->clr_ea_fld = 1; agg_recptr->corrections_needed = 1; fsck_send_msg(fsck_INOINLINECONFLICT, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, fsck_longdata_and_otherinline); } if (agg_recptr->this_inode.acl_inline) { /* conflict */ inorecptr->selected_to_rls = 1; inorecptr->inline_data_err = 1; inorecptr->clr_acl_fld = 1; agg_recptr->corrections_needed = 1; fsck_send_msg(fsck_INOINLINECONFLICT, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, fsck_longdata_and_otherinline); } } else { if (agg_recptr->this_inode.ea_inline && agg_recptr->this_inode.acl_inline) { /* conflict */ inorecptr->clr_ea_fld = 1; inorecptr->clr_acl_fld = 1; agg_recptr->corrections_needed = 1; fsck_send_msg(fsck_INOINLINECONFLICT, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, fsck_longdata_and_otherinline); } } return (iidc_rc); } /***************************************************************************** * NAME: inode_is_in_use * * FUNCTION: Determine whether the specified inode is currently being * used to represent a file system object. * * PARAMETERS: * inode_ptr - input - pointer to the current inode * inode_num - input - ordinal number of the inode in the internal * JFS format * * RETURNS: * 0: if inode is not in use * 1: if inode is in use */ int inode_is_in_use(struct dinode *inode_ptr, uint32_t inode_num) { int iiiu_result; int ixpxd_unequal = 0; ixpxd_unequal = memcmp((void *) &(inode_ptr->di_ixpxd), (void *) &(agg_recptr->ino_ixpxd), sizeof (pxd_t)); iiiu_result = ((inode_ptr->di_inostamp == agg_recptr->inode_stamp) && (inode_ptr->di_number == inode_num) && (inode_ptr->di_fileset == agg_recptr->ino_fsnum) && (!ixpxd_unequal) && (inode_ptr->di_nlink != 0)); return (iiiu_result); } /***************************************************************************** * NAME: parent_count * * FUNCTION: Count the number of directory entries fsck has observed which * refer to the specified inode. * * PARAMETERS: * this_inorec - input - pointer to an fsck inode record describing the * current inode * * RETURNS: * the number of parent directories observed for the inode */ int parent_count(struct fsck_inode_record *this_inorec) { int pc_result = 0; struct fsck_inode_ext_record *this_ext; if (this_inorec->parent_inonum != 0) { pc_result++; } this_ext = this_inorec->ext_rec; while (this_ext != NULL) { /* extension records to check */ if (this_ext->ext_type == parent_extension) { pc_result++; } this_ext = this_ext->next; } return (pc_result); } /***************************************************************************** * NAME: record_valid_inode * * FUNCTION: Record, in the fsck workspace block map, all aggregate blocks * allocated to the specified inode. The inode structures have * already been validated, no error checking is done. * * PARAMETERS: * inoptr - input - pointer to the current inode * inoidx - input - ordinal number of the inode as an integer * inorecptr - input - pointer to an fsck inode record describing the * current inode * msg_info_ptr - input - pointer to a record with information needed * to issue messages about the current inode * * RETURNS: * success: FSCK_OK * failure: something else */ int record_valid_inode(struct dinode *inoptr, uint32_t inoidx, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr) { int rvi_rc = FSCK_OK; int64_t first_fsblk, last_fsblk; uint32_t num_fsblks; dxd_t *dxd_ptr; /* * record the extent (if any) containing the EA */ if (inoptr->di_ea.flag == DXD_EXTENT) { /* there is an ea to record */ dxd_ptr = &(inoptr->di_ea); first_fsblk = addressDXD(dxd_ptr); num_fsblks = lengthDXD(dxd_ptr); last_fsblk = first_fsblk + num_fsblks - 1; extent_record(first_fsblk, last_fsblk); agg_recptr->this_inode.all_blks += num_fsblks; agg_recptr->blocks_this_fset += num_fsblks; } /* * record the extent (if any) containing the ACL */ if (inoptr->di_acl.flag == DXD_EXTENT) { /* there is an acl to record */ dxd_ptr = &(inoptr->di_acl); first_fsblk = addressDXD(dxd_ptr); num_fsblks = lengthDXD(dxd_ptr); last_fsblk = first_fsblk + num_fsblks - 1; extent_record(first_fsblk, last_fsblk); agg_recptr->this_inode.all_blks += num_fsblks; agg_recptr->blocks_this_fset += num_fsblks; } /* * record the extents (if any) described as data */ process_valid_data(inoptr, inoidx, inorecptr, msg_info_ptr, FSCK_RECORD); return (rvi_rc); } /***************************************************************************** * NAME: release_inode * * FUNCTION: Release all aggregate blocks allocated to the specified inode. * Reset the link count, in the inode on the device, to zero * to make it available for reuse. * * PARAMETERS: * inoidx - input - ordinal number of the inode as an integer * ino_recptr - input - pointer to an fsck inode record describing the * current inode * inoptr - input - pointer to the current inode * * RETURNS: * success: FSCK_OK * failure: something else */ int release_inode(uint32_t inoidx, struct fsck_inode_record *ino_recptr, struct dinode *inoptr) { int ri_rc = FSCK_OK; struct dinode *this_inode; int aggregate_inode = 0; /* going for fileset inodes only */ int which_it = 0; /* in release 1 there is only fileset 0 */ struct fsck_ino_msg_info ino_msg_info; struct fsck_ino_msg_info *msg_info_ptr; msg_info_ptr = &ino_msg_info; msg_info_ptr->msg_inopfx = fsck_fset_inode; msg_info_ptr->msg_inonum = inoidx; if (ino_recptr->inode_type == directory_inode) { msg_info_ptr->msg_inotyp = fsck_directory; } else if (ino_recptr->inode_type == symlink_inode) { msg_info_ptr->msg_inotyp = fsck_symbolic_link; } else if (ino_recptr->inode_type == char_special_inode) { msg_info_ptr->msg_inotyp = fsck_char_special; } else if (ino_recptr->inode_type == block_special_inode) { msg_info_ptr->msg_inotyp = fsck_block_special; } else if (ino_recptr->inode_type == FIFO_inode) { msg_info_ptr->msg_inotyp = fsck_FIFO; } else if (ino_recptr->inode_type == SOCK_inode) { msg_info_ptr->msg_inotyp = fsck_SOCK; } else { /* a regular file */ msg_info_ptr->msg_inotyp = fsck_file; } if (ino_recptr->in_use) { /* the inode is 'in use' */ ri_rc = inode_get(aggregate_inode, which_it, inoidx, &this_inode); if (ri_rc == FSCK_OK) { /* inode read successfully */ this_inode->di_nlink = 0; ri_rc = inode_put(this_inode); if ((ri_rc == FSCK_OK) && (!ino_recptr->ignore_alloc_blks)) { ri_rc = unrecord_valid_inode(this_inode, inoidx, ino_recptr, msg_info_ptr); } } } return (ri_rc); } /***************************************************************************** * NAME: unrecord_valid_inode * * FUNCTION: Unrecord, in the fsck workspace block map, all aggregate blocks * allocated to the specified inode. The inode structures have * already been validated, no error checking is done. * * PARAMETERS: * inoptr - input - pointer to the current inode * inoidx - input - ordinal number of the inode as an integer * inorecptr - input - pointer to an fsck inode record describing * the current inode * msg_info_ptr - input - pointer to a record with information needed * to issue messages about the current inode * * RETURNS: * success: FSCK_OK * failure: something else */ int unrecord_valid_inode(struct dinode *inoptr, uint32_t inoidx, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr) { int uvi_rc = FSCK_OK; int64_t ea_blocks = 0; int64_t acl_blocks = 0; /* * unrecord the extent (if any) containing the EA */ if ((inoptr->di_ea.flag == DXD_EXTENT) && (!inorecptr->ignore_ea_blks)) { ea_blocks = lengthDXD(&(inoptr->di_ea)); agg_recptr->blocks_for_eas -= ea_blocks; uvi_rc = backout_EA(inoptr, inorecptr); } /* * unrecord the extent (if any) containing the ACL */ if ((inoptr->di_acl.flag == DXD_EXTENT) && (!inorecptr->ignore_acl_blks)) { acl_blocks = lengthDXD(&(inoptr->di_acl)); agg_recptr->blocks_for_acls -= acl_blocks; uvi_rc = backout_ACL(inoptr, inorecptr); } /* * unrecord the extents (if any) describing data * * note that the tree is valid or we'd be ignoring these allocated * blocks. */ if (uvi_rc == FSCK_OK) { if (inorecptr->inode_type == directory_inode) { agg_recptr->blocks_for_dirs -= inoptr->di_nblocks - ea_blocks; uvi_rc = process_valid_dir_data(inoptr, inoidx, inorecptr, msg_info_ptr, FSCK_UNRECORD); } else { agg_recptr->blocks_for_files -= inoptr->di_nblocks - ea_blocks; uvi_rc = process_valid_data(inoptr, inoidx, inorecptr, msg_info_ptr, FSCK_UNRECORD); } } return (uvi_rc); } /***************************************************************************** * NAME: validate_ACL * * FUNCTION: Determine whether the structures in the specified inode to * describe ACL data owned by the inode are consistent and (as * far as fsck can tell) correct. * * PARAMETERS: * inoptr - input - pointer to the current inode * inoidx - input - ordinal number of the inode as an integer * inorecptr - input - pointer to an fsck inode record describing * the current inode * msg_info_ptr - input - pointer to a record with information needed * to issue messages about the current inode * * RETURNS: * success: FSCK_OK * failure: something else */ int validate_ACL(struct dinode *inoptr, uint32_t inoidx, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr) { int vacl_rc = FSCK_OK; dxd_t *dxd_ptr; uint32_t recorded_length, shortest_valid, longest_valid; uint32_t ext_length; int64_t ext_address; int8_t extent_is_valid = 0; uint16_t size16; struct dinode an_inode; dxd_ptr = &(inoptr->di_acl); msg_info_ptr->msg_dxdtyp = fsck_ACL; if (dxd_ptr->flag == 0) goto out; /* there is an ACL for this inode */ if ((dxd_ptr->flag != DXD_EXTENT) && (dxd_ptr->flag != DXD_INLINE) && (dxd_ptr->flag != DXD_CORRUPT)) { /* not a single extent AND not inline AND not already * reported */ fsck_send_msg(fsck_BADINODXDFLDD, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, fsck_ref_msg(msg_info_ptr->msg_dxdtyp)); inorecptr->clr_acl_fld = 1; inorecptr->ignore_acl_blks = 1; agg_recptr->corrections_needed = 1; goto out; } /* else the acl flag is ok */ if (dxd_ptr->flag == DXD_INLINE) { /* ACL is inline */ size16 = sizeof (an_inode.di_inlineea); agg_recptr->this_inode.acl_inline = 1; agg_recptr->this_inode.inline_acl_length = (uint16_t) dxd_ptr->size; agg_recptr->this_inode.inline_acl_offset = (uint16_t) addressDXD(dxd_ptr); if ((dxd_ptr->size == 0) || (dxd_ptr->size > (size16 - agg_recptr->this_inode.inline_acl_offset))) { /* * the length extends * beyond the end of the inode */ fsck_send_msg(fsck_BADINODXDFLDL, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, fsck_ref_msg(msg_info_ptr->msg_dxdtyp)); inorecptr->clr_acl_fld = 1; agg_recptr->corrections_needed = 1; } } else if (dxd_ptr->flag == DXD_EXTENT) { /* else the ACL is a single extent */ ext_length = lengthDXD(dxd_ptr); shortest_valid = (ext_length - 1) * sb_ptr->s_bsize + 1; longest_valid = ext_length * sb_ptr->s_bsize; if ((ext_length == 0) || (dxd_ptr->size < shortest_valid) || (dxd_ptr->size > longest_valid)) { /* invalid length */ fsck_send_msg(fsck_BADINODXDFLDL, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, fsck_ref_msg(msg_info_ptr->msg_dxdtyp)); inorecptr->clr_acl_fld = 1; inorecptr->ignore_acl_blks = 1; agg_recptr->corrections_needed = 1; recorded_length = 0; extent_is_valid = 0; } else { /* length and size might be ok */ agg_recptr->this_inode.acl_blks = ext_length; ext_address = addressDXD(dxd_ptr); vacl_rc = process_extent(inorecptr, ext_length, ext_address, 0, -1, msg_info_ptr, &recorded_length, &extent_is_valid, FSCK_RECORD_DUPCHECK); /* * add the blocks in the ACL extent to the running * totals for the fileset and inode, but not for * the object represented by the object. */ agg_recptr->blocks_this_fset += recorded_length; agg_recptr->this_inode.all_blks += recorded_length; } if (!extent_is_valid) { inorecptr->clr_acl_fld = 1; agg_recptr->corrections_needed = 1; } } out: return (vacl_rc); } /***************************************************************************** * NAME: validate_data * * FUNCTION: Determine whether the structures in, or rooted in, the specified * non-directory inode to describe data owned by the inode are * consistent and (as far as fsck can tell) correct. * * PARAMETERS: * inoptr - input - pointer to the current inode * inoidx - input - ordinal number of the inode as an integer * inorecptr - input - pointer to an fsck inode record describing * the current inode * msg_info_ptr - input - pointer to a record with information needed * to issue messages about the current inode * * RETURNS: * success: FSCK_OK * failure: something else */ int validate_data(struct dinode *inoptr, uint32_t inoidx, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr) { int vd_rc = FSCK_OK; int intermed_rc = FSCK_OK; dxd_t *dxd_ptr; xtpage_t *xtp_ptr; dxd_ptr = &(inoptr->di_dxd); /* the data root dxd */ msg_info_ptr->msg_dxdtyp = fsck_objcontents; /* * Symbolic link is a special case. If the value fits within the * inode, the dxd appears to be an empty xtree, but it's unused. * In this case, ignore the dxd. */ if (ISLNK(inoptr->di_mode) && (inoptr->di_size < IDATASIZE)) { /* Null terminator stored but not accounted for in di_size */ agg_recptr->this_inode.in_inode_data_length = inoptr->di_size + 1; goto out; } /* * examine the data field */ if (dxd_ptr->flag == 0) goto out; if ((dxd_ptr->flag == (DXD_INDEX | BT_ROOT | BT_LEAF)) || (dxd_ptr->flag == (DXD_INDEX | BT_ROOT | BT_INTERNAL))) { /* * to be valid, it has to be a B-tree node, * either root-leaf or root-internal */ /* * figure out how much space the root occupies in the inode * itself */ xtp_ptr = (xtpage_t *) (&inoptr->di_btroot); agg_recptr->this_inode.in_inode_data_length = (xtp_ptr->header.maxentry - 2) * sizeof (xad_t); /* * the dxd actually starts 32 bytes (== 2 * length of * an xad) before the boundary. * the 0th and 1st entries in the xad array are * really the header */ /* * validate the tree contents and record the extents it * describes until and unless the tree is found to be corrupt */ vd_rc = xTree_processing(inoptr, inoidx, inorecptr, msg_info_ptr, FSCK_RECORD_DUPCHECK); if (vd_rc <= FSCK_OK) goto out; /* nothing fatal */ if (inorecptr->selected_to_rls && inode_is_metadata(inorecptr)) { vd_rc = FSCK_BADMDDATAIDX; } else if (inorecptr->ignore_alloc_blks) { /* the tree info can't be used */ if (inode_is_metadata(inorecptr)) { vd_rc = FSCK_BADMDDATAIDX; } /* * reverse the notations made when recording the * extents for the tree. Again, stop when the point * of corruption is found since that's where the * recording process was stopped. */ intermed_rc = xTree_processing(inoptr, inoidx, inorecptr, msg_info_ptr, FSCK_UNRECORD); if (intermed_rc < 0) { vd_rc = intermed_rc; goto out; } if (intermed_rc != FSCK_OK) { if (vd_rc == FSCK_OK) { vd_rc = intermed_rc; } } if (!inorecptr->ignore_ea_blks) { intermed_rc = backout_EA(inoptr, inorecptr); if (intermed_rc < 0) { vd_rc = intermed_rc; goto out; } if (intermed_rc != FSCK_OK) { if (vd_rc == FSCK_OK) { vd_rc = intermed_rc; } } if (!inorecptr->ignore_acl_blks) { intermed_rc = backout_ACL(inoptr, inorecptr); if (intermed_rc < 0) { vd_rc = intermed_rc; goto out; } if (intermed_rc != FSCK_OK) { if (vd_rc == FSCK_OK) { vd_rc = intermed_rc; } } } } } } else { /* else not B+ Tree index */ /* * the data root is not valid...the info cannot be trusted */ if (inode_is_metadata(inorecptr)) { vd_rc = FSCK_BADMDDATA; } else { inorecptr->selected_to_rls = 1; inorecptr->ignore_alloc_blks = 1; agg_recptr->corrections_needed = 1; } fsck_send_msg(fsck_BADINODXDFLDD, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, fsck_ref_msg(msg_info_ptr->msg_dxdtyp)); } out: return (vd_rc); } /***************************************************************************** * NAME: validate_dir_data * * FUNCTION: Determine whether the structures in, or rooted in, the * specified directory inode to describe data owned by the * inode are consistent and (as far as fsck can tell) * correct. * * PARAMETERS: * inoptr - input - pointer to the current inode * inoidx - input - ordinal number of the inode as an integer * inorecptr - input - pointer to an fsck inode record describing the * current inode * msg_info_ptr - input - pointer to a record with information needed * to issue messages about the current inode * * RETURNS: * success: FSCK_OK * failure: something else */ int validate_dir_data(struct dinode *inoptr, uint32_t inoidx, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr) { int vdd_rc = FSCK_OK; int intermed_rc = FSCK_OK; int dtree_rc = FSCK_OK; dxd_t *dxd_ptr; int8_t save_ignore_alloc_blks; int8_t xt_ignore_alloc_blks = 0; dxd_ptr = &(inoptr->di_dxd); /* the data root dxd */ msg_info_ptr->msg_dxdtyp = fsck_objcontents; /* * examine the data field */ if (dxd_ptr->flag == 0) goto out; /* Work around bug that used to clear the DXD_INDEX bit */ dxd_ptr->flag |= DXD_INDEX; /* * to be valid, it has to be a B-tree node, * either root-leaf or root-internal */ if ((dxd_ptr->flag != (DXD_INDEX | BT_ROOT | BT_LEAF)) && (dxd_ptr->flag != (DXD_INDEX | BT_ROOT | BT_INTERNAL))) { /* * the data root is not valid...the info cannot be trusted */ inorecptr->selected_to_rls = 1; inorecptr->ignore_alloc_blks = 1; agg_recptr->corrections_needed = 1; fsck_send_msg(fsck_BADINODXDFLDD, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, fsck_ref_msg(msg_info_ptr->msg_dxdtyp)); goto out; } /* * figure out how much space the root occupies in the inode itself */ agg_recptr->this_inode.in_inode_data_length = (DTROOTMAXSLOT - 1) * sizeof (struct dtslot); /* * The root actually starts 32 bytes (aka the length * of 1 slot) before the boundary. * the 1st slot is really the header */ /* * process the xtree if the new directory table is supported * and if the directory table data is not inline (index > 14) */ if (sb_ptr->s_flag & JFS_DIR_INDEX) inorecptr->check_dir_index = 1; if ((sb_ptr->s_flag & JFS_DIR_INDEX) && inoptr->di_next_index > MAX_INLINE_DIRTABLE_ENTRY + 1) { /* * validate the tree contents and record the extents it * describes until and unless the tree is found to be corrupt */ vdd_rc = xTree_processing(inoptr, inoidx, inorecptr, msg_info_ptr, FSCK_RECORD_DUPCHECK); if (vdd_rc < FSCK_OK) goto out; } /* * Check an error bit to see if there was something * wrong but non-fatal with xTree_processing. If * so, reset the bit to give dTree_processing a * clean slate to start with. Set a flag to * indicate that the directory index table is to be rebuilt. */ if (inorecptr->ignore_alloc_blks) { inorecptr->check_dir_index = 0; inorecptr->rebuild_dirtable = 1; inorecptr->ignore_alloc_blks = 0; inorecptr->selected_to_rls = 0; agg_recptr->corrections_needed = 1; xt_ignore_alloc_blks = 1; } /* * validate the tree contents and record the extents it * describes until and unless the tree is found to be corrupt */ dtree_rc = dTree_processing(inoptr, inoidx, inorecptr, msg_info_ptr, FSCK_RECORD_DUPCHECK); if (dtree_rc < FSCK_OK) goto dtree_out; if (inorecptr->ignore_alloc_blks) { /* the tree info can't be used */ /* * reverse the notations made when recording the extents * for the tree. Again, stop when the point of corruption * is found since that's where the recording process was * stopped. */ intermed_rc = dTree_processing(inoptr, inoidx, inorecptr, msg_info_ptr, FSCK_UNRECORD); if (intermed_rc < 0) { dtree_rc = intermed_rc; goto dtree_out; } if (intermed_rc != FSCK_OK) { if (dtree_rc == FSCK_OK) { dtree_rc = intermed_rc; } } if (!inorecptr->ignore_ea_blks) { intermed_rc = backout_EA(inoptr, inorecptr); if (intermed_rc < 0) { dtree_rc = intermed_rc; goto dtree_out; } if (intermed_rc != FSCK_OK) { if (dtree_rc == FSCK_OK) { dtree_rc = intermed_rc; } } if (!inorecptr->ignore_acl_blks) { intermed_rc = backout_ACL(inoptr, inorecptr); if (intermed_rc < 0) { dtree_rc = intermed_rc; goto dtree_out; } if (intermed_rc != FSCK_OK) { if (dtree_rc == FSCK_OK) { dtree_rc = intermed_rc; } } } } } if ((sb_ptr->s_flag & JFS_DIR_INDEX) && (inoptr->di_next_index > MAX_INLINE_DIRTABLE_ENTRY + 1) && (inorecptr->ignore_alloc_blks || inorecptr->rebuild_dirtable)) { /* * ignore_alloc_blks needs to exactly reflect the results * of the xTree_processing step */ save_ignore_alloc_blks = inorecptr->ignore_alloc_blks; inorecptr->ignore_alloc_blks = xt_ignore_alloc_blks; /* * reverse the notations made when recording the * extents for the tree. Again, stop when the point * of corruption is found since that's where the * recording process was stopped. */ intermed_rc = xTree_processing(inoptr, inoidx, inorecptr, msg_info_ptr, FSCK_UNRECORD); if (intermed_rc < 0) { vdd_rc = intermed_rc; goto out; } if (intermed_rc != FSCK_OK) { if (vdd_rc == FSCK_OK) { vdd_rc = intermed_rc; } } inorecptr->ignore_alloc_blks = save_ignore_alloc_blks; /* * If we don't fix di_nblocks now, the inode will be * thrown away (even if dtree is good). */ inoptr->di_nblocks = agg_recptr->this_inode.all_blks; } dtree_out: /* * return the worse of the rc's for xtree and dtree processing */ if (dtree_rc != FSCK_OK) { vdd_rc = dtree_rc; } out: return (vdd_rc); } /***************************************************************************** * NAME: validate_EA * * FUNCTION: Determine whether the structures in the specified inode to * describe ea data owned by the inode are consistent and (as * far as fsck can tell) correct. * * PARAMETERS: * inoptr - input - pointer to the current inode * inoidx - input - ordinal number of the inode as an integer * inorecptr - input - pointer to an fsck inode record describing * the current inode * msg_info_ptr - input - pointer to a record with information needed * to issue messages about the current inode * * RETURNS: * success: FSCK_OK * failure: something else */ int validate_EA(struct dinode *inoptr, uint32_t inoidx, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr) { int vea_rc = FSCK_OK; int intermed_rc = FSCK_OK; dxd_t *dxd_ptr; uint32_t recorded_length, shortest_valid, longest_valid; uint32_t ext_length; int64_t ext_byte_length; int64_t ext_address = 0; int8_t extent_is_valid = 0; int8_t ea_format_bad = 0; uint16_t size16; struct dinode an_inode; unsigned long eafmt_error = 0; dxd_ptr = &(inoptr->di_ea); msg_info_ptr->msg_dxdtyp = fsck_EA; if (dxd_ptr->flag == 0) goto out; /* there is an EA for this inode */ if ((dxd_ptr->flag != DXD_EXTENT) && (dxd_ptr->flag != DXD_INLINE)) { /* not a single extent AND not inline */ fsck_send_msg(fsck_BADINODXDFLDD, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, fsck_ref_msg(msg_info_ptr->msg_dxdtyp)); inorecptr->clr_ea_fld = 1; inorecptr->ignore_ea_blks = 1; agg_recptr->corrections_needed = 1; goto out; } if (dxd_ptr->flag == DXD_INLINE) { /* EA is inline */ size16 = sizeof (an_inode.di_inlineea); agg_recptr->this_inode.ea_inline = 1; agg_recptr->this_inode.inline_ea_length = dxd_ptr->size; agg_recptr->this_inode.inline_ea_offset = (uint16_t) addressDXD(dxd_ptr); if ((dxd_ptr->size == 0) || (dxd_ptr->size > (size16 - agg_recptr->this_inode.inline_ea_offset))) { /* * the length extends * beyond the end of the inode */ fsck_send_msg(fsck_BADINODXDFLDL, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, fsck_ref_msg(msg_info_ptr->msg_dxdtyp)); inorecptr->clr_ea_fld = 1; agg_recptr->corrections_needed = 1; } else { /* the inline ea has a valid length. * verify its format. */ vea_rc = jfs_ValidateFEAList((struct FEALIST *) &(inoptr->di_inlineea), dxd_ptr->size, &eafmt_error); if ((vea_rc != FSCK_OK) || (eafmt_error != 0)) { /* ea format is bad */ ea_format_bad = -1; } } } else { /* else the EA is a single extent */ ext_length = lengthDXD(dxd_ptr); shortest_valid = (ext_length - 1) * sb_ptr->s_bsize + 1; longest_valid = ext_length * sb_ptr->s_bsize; if ((ext_length == 0) || (dxd_ptr->size < shortest_valid) || (dxd_ptr->size > longest_valid)) { /* invalid length */ fsck_send_msg(fsck_BADINODXDFLDL, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, fsck_ref_msg(msg_info_ptr->msg_dxdtyp)); extent_is_valid = 0; inorecptr->ignore_ea_blks = 1; } else { /* length and size might be ok */ agg_recptr->this_inode.ea_blks = ext_length; ext_address = addressDXD(dxd_ptr); vea_rc = process_extent(inorecptr, ext_length, ext_address, -1, 0, msg_info_ptr, &recorded_length, &extent_is_valid, FSCK_RECORD_DUPCHECK); /* * add the blocks in the EA extent to the running * totals for the filese and inode, but not for the * object represented by the object. */ agg_recptr->blocks_this_fset += recorded_length; agg_recptr->this_inode.all_blks += recorded_length; } if (!extent_is_valid) { inorecptr->clr_ea_fld = 1; agg_recptr->corrections_needed = 1; goto out; } /* the extent looks ok so need to check ea data structure */ ext_byte_length = ext_length * sb_ptr->s_bsize; if (ext_byte_length > agg_recptr->ea_buf_length) { /* extra large ea -- can't check it */ inorecptr->cant_chkea = 1; agg_recptr->warning_pending = 1; goto out; } /* regular size ea */ intermed_rc = ea_get(ext_address, ext_byte_length, agg_recptr->ea_buf_ptr, &(agg_recptr->ea_buf_length), &(agg_recptr->ea_buf_data_len), &(agg_recptr->ea_agg_offset)); if (intermed_rc != FSCK_OK) { fsck_send_msg(fsck_BADINODXDFLDO, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, fsck_ref_msg(msg_info_ptr->msg_dxdtyp)); inorecptr->clr_ea_fld = 1; agg_recptr->corrections_needed = 1; goto out; } /* the ea has been read into the regular buffer */ vea_rc = jfs_ValidateFEAList((struct FEALIST *) agg_recptr->ea_buf_ptr, dxd_ptr->size, &eafmt_error); if ((vea_rc != FSCK_OK) || (eafmt_error != 0)) { /* ea format is bad */ ea_format_bad = -1; } } out: if (ea_format_bad) { /* bad ea but haven't notified anyone */ fsck_send_msg(fsck_EAFORMATBAD, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); inorecptr->clr_ea_fld = 1; agg_recptr->corrections_needed = 1; vea_rc = FSCK_OK; } return (vea_rc); } /***************************************************************************** * NAME: validate_record_fileset_inode * * FUNCTION: Determine whether structures in and/or rooted in the specified * fileset owned inode are consistent and (as far as fsck can tell) * correct. Record, in the fsck workspace block map, all storage * allocated to the inode. * * PARAMETERS: * inonum - input - ordinal number of the inode in the * internal JFS format * inoidx - input - ordinal number of the inode as an integer * inoptr - input - pointer to the current inode * ino_msg_info_ptr - input - pointer to a record with information needed * to issue messages about the current inode * * RETURNS: * success: FSCK_OK * failure: something else */ int validate_record_fileset_inode(uint32_t inonum, uint32_t inoidx, struct dinode *inoptr, struct fsck_ino_msg_info *ino_msg_info_ptr) { int vrfi_rc = FSCK_OK; int intermed_rc = FSCK_OK; struct fsck_inode_record *inorecptr; int8_t bad_size = 0; int aggregate_inode = 0; int alloc_ifnull = -1; int64_t min_size, max_size; int16_t size16; int8_t dinode_sect4_avail = 0; struct dinode an_inode; ino_msg_info_ptr->msg_inonum = inonum; vrfi_rc = get_inorecptr(aggregate_inode, alloc_ifnull, inoidx, &inorecptr); if (vrfi_rc != FSCK_OK) goto out; inorecptr->in_use = 1; if (!(inode_type_recognized(inoptr))) { /* bad type */ inorecptr->inode_type = unrecognized_inode; ino_msg_info_ptr->msg_inotyp = fsck_file; inorecptr->selected_to_rls = 1; inorecptr->ignore_alloc_blks = 1; /* no matter what the user * approves or disapproves, we aren't * going to even look to see which * blocks are allocated to this inode * (except for the blocks it occupies * itself) */ agg_recptr->corrections_needed = 1; fsck_send_msg(fsck_BADINOTYP, fsck_ref_msg(ino_msg_info_ptr->msg_inopfx), ino_msg_info_ptr->msg_inonum); goto out; } /* else type is recognized as valid */ /* * clear the workspace area for the current inode */ memset((void *) (&(agg_recptr->this_inode)), '\0', sizeof (agg_recptr->this_inode)); memcpy((void *) &(agg_recptr->this_inode.eyecatcher), (void *) "thisinod", 8); /* * finish filling in the inode's workspace record */ if (ISDIR(inoptr->di_mode)) { inorecptr->inode_type = directory_inode; ino_msg_info_ptr->msg_inotyp = fsck_directory; } else if (ISLNK(inoptr->di_mode)) { inorecptr->inode_type = symlink_inode; ino_msg_info_ptr->msg_inotyp = fsck_symbolic_link; } else if (ISBLK(inoptr->di_mode)) { inorecptr->inode_type = block_special_inode; ino_msg_info_ptr->msg_inotyp = fsck_block_special; } else if (ISCHR(inoptr->di_mode)) { inorecptr->inode_type = char_special_inode; ino_msg_info_ptr->msg_inotyp = fsck_char_special; } else if (ISFIFO(inoptr->di_mode)) { inorecptr->inode_type = FIFO_inode; ino_msg_info_ptr->msg_inotyp = fsck_FIFO; } else if (ISSOCK(inoptr->di_mode)) { inorecptr->inode_type = SOCK_inode; ino_msg_info_ptr->msg_inotyp = fsck_SOCK; } else { /* a regular file */ inorecptr->inode_type = file_inode; ino_msg_info_ptr->msg_inotyp = fsck_file; } inorecptr->link_count -= inoptr->di_nlink; /* * validate the inode's structures */ /* validate the Extended Attributes if any */ vrfi_rc = validate_EA(inoptr, inoidx, inorecptr, ino_msg_info_ptr); if (vrfi_rc != FSCK_OK) goto out; /* validate the Access Control List if any */ vrfi_rc = validate_ACL(inoptr, inoidx, inorecptr, ino_msg_info_ptr); if (vrfi_rc != FSCK_OK) goto out; /* nothing fatal with the EA or ACL */ if (inorecptr->inode_type == directory_inode) { /* * validate the data, if any, whether inline, * a single extent, or a B+ Tree */ vrfi_rc = validate_dir_data(inoptr, inoidx, inorecptr, ino_msg_info_ptr); } else if (ISREG(inoptr->di_mode) || ISLNK(inoptr->di_mode)) { /* * validate the data, if any, whether * inline, a single extent, or a B+ Tree */ vrfi_rc = validate_data(inoptr, inoidx, inorecptr, ino_msg_info_ptr); } if (vrfi_rc != FSCK_OK) goto out; if (inorecptr->ignore_alloc_blks) { inorecptr->selected_to_rls = 1; agg_recptr->corrections_needed = 1; } if (!inorecptr->selected_to_rls) { /* not selected to release yet */ if (inoptr->di_nblocks != agg_recptr->this_inode.all_blks) { /* * number of blocks is wrong. tree must be bad */ #ifdef _JFS_DEBUG printf ("inode: %ld (t) di_nblocks = %lld (t) " "this_inode.all_blks = %lld (t)\n", inonum, inoptr->di_nblocks, agg_recptr->this_inode.all_blks); #endif fsck_send_msg(fsck_BADKEYS, fsck_ref_msg(ino_msg_info_ptr->msg_inotyp), fsck_ref_msg(ino_msg_info_ptr->msg_inopfx), ino_msg_info_ptr->msg_inonum, 9); inorecptr->selected_to_rls = 1; inorecptr->ignore_alloc_blks = 1; agg_recptr->corrections_needed = 1; bad_size = -1; } else { /* * the data size (in bytes) must not exceed the total * size of the blocks allocated for it and must use at * least 1 byte in the last fsblock allocated for it. */ if (agg_recptr->this_inode.data_size == 0) { if (inorecptr->inode_type == directory_inode) { min_size = IDATASIZE; max_size = IDATASIZE; } else { /* not a directory */ min_size = 0; max_size = IDATASIZE; } } else { /* blocks are allocated to data */ min_size = agg_recptr->this_inode.data_size - sb_ptr->s_bsize + 1; max_size = agg_recptr->this_inode.data_size; } /* Don't worry about directory size yet */ if (!ISDIR(inoptr->di_mode) && ((inoptr->di_size < min_size) || (!(inoptr->di_mode & ISPARSE) && (inoptr->di_size > max_size)))) { /* if size is less than min, or if object is * not sparse and size is greater than max, * then object size (in bytes) is is wrong * - tree must be bad. */ #ifdef _JFS_DEBUG printf ("inode: %ld (t) min_size = %lld (t) " "max_size = %lld (t) di_size = %lld (t)\n", inonum, min_size, max_size, inoptr->di_size); #endif fsck_send_msg(fsck_BADKEYS, fsck_ref_msg(ino_msg_info_ptr->msg_inotyp), fsck_ref_msg(ino_msg_info_ptr->msg_inopfx), ino_msg_info_ptr->msg_inonum, 10); inorecptr->selected_to_rls = 1; inorecptr->ignore_alloc_blks = 1; agg_recptr->corrections_needed = 1; bad_size = -1; } } } if (!(inorecptr->ignore_alloc_blks)) { /* the tree looks ok */ intermed_rc = in_inode_data_check(inorecptr, ino_msg_info_ptr); if (inorecptr->selected_to_rls) { fsck_send_msg(fsck_BADKEYS, fsck_ref_msg(ino_msg_info_ptr->msg_inotyp), fsck_ref_msg(ino_msg_info_ptr->msg_inopfx), ino_msg_info_ptr->msg_inonum, 39); goto out; } /* not selected to release */ /* in_inode_data_check came out ok. * now check to be sure the mode bit INLINEEA is set properly * * N.B. if not, we'll correct the mode bit. We won't * release the inode for this. */ dinode_sect4_avail = 0; /* if in-inode data (or * description of data) overflows this then * section 4 of the disk inode is NOT available */ size16 = sizeof (an_inode.di_inlinedata); if (agg_recptr->this_inode.in_inode_data_length > size16) { /* extra long inline data */ if ((inoptr->di_mode & INLINEEA) == INLINEEA) { inorecptr->inlineea_off = 1; } } else { /* not extra long inline data */ if ((!(agg_recptr->this_inode.ea_inline) || (inorecptr->clr_ea_fld)) && (!(agg_recptr->this_inode.acl_inline) || (inorecptr->clr_acl_fld))) { /* * if (either ea isn't inline OR ea being * cleared) AND (either acl isn't inline OR acl * being cleared) */ dinode_sect4_avail = -1; } /* * if we know section 4 is (or will be) available but * the flag is off, then flag it to turn the flag on. */ if ((dinode_sect4_avail) && ((inoptr->di_mode & INLINEEA) != INLINEEA)) { inorecptr->inlineea_on = 1; agg_recptr->corrections_needed = 1; } else if ((!dinode_sect4_avail) && ((inoptr->di_mode & INLINEEA) == INLINEEA)) { /* * if we know section 4 is (or will be) * unavailable but the flag is on, then flag it * to turn the flag off. */ inorecptr->inlineea_off = 1; agg_recptr->corrections_needed = 1; } } } else { /* the tree is not valid */ /* * If bad_size is set then we didn't know that * the tree was bad until we looked at the size * fields. This means that the block usage recorded * for this inode has not been backed out yet. */ if (bad_size) { /* tree is bad by implication */ if (!inorecptr->ignore_ea_blks) { /* remove traces, in * the fsck workspace maps, of the blocks * allocated to this inode */ backout_EA(inoptr, inorecptr); } if (!inorecptr->ignore_acl_blks) { /* remove traces, in * the fsck workspace maps, of the blocks * allocated to this inode */ backout_ACL(inoptr, inorecptr); } if (inorecptr->inode_type == directory_inode) { /* * remove traces, in the fsck workspace * maps, of the blocks allocated to data * for this inode, whether a single * extent or a B+ Tree */ process_valid_dir_data(inoptr, inoidx, inorecptr, ino_msg_info_ptr, FSCK_UNRECORD); } else { /* * remove traces, in the fsck workspace * maps, of the blocks allocated to data * for this inode, whether a single * extent or a B+ Tree */ process_valid_data(inoptr, inoidx, inorecptr, ino_msg_info_ptr, FSCK_UNRECORD); } } } if ((vrfi_rc == FSCK_OK) && (!inorecptr->selected_to_rls)) { /* looks like a keeper */ agg_recptr->blocks_for_eas += agg_recptr->this_inode.ea_blks; agg_recptr->blocks_for_acls += agg_recptr->this_inode.acl_blks; if (inorecptr->inode_type == directory_inode) { /* a directory */ agg_recptr->blocks_for_dirs = agg_recptr->blocks_for_dirs + agg_recptr->this_inode.all_blks - agg_recptr->this_inode.ea_blks - agg_recptr->this_inode.acl_blks; } else { /* a file */ agg_recptr->blocks_for_files = agg_recptr->blocks_for_files + agg_recptr->this_inode.all_blks - agg_recptr->this_inode.ea_blks - agg_recptr->this_inode.acl_blks; } } out: return (vrfi_rc); } jfsutils-1.1.15.orig/fsck/fsckmeta.c0000644000000000000000000036265311531745071014201 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include /* defines and includes common among the fsck.jfs modules */ #include "xfsckint.h" #include "devices.h" #include "diskmap.h" #include "jfs_byteorder.h" #include "message.h" #include "super.h" #include "utilsubs.h" /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * superblock buffer pointer * * defined in xchkdsk.c */ extern struct superblock *sb_ptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * fsck aggregate info structure pointer * * defined in xchkdsk.c */ extern struct fsck_agg_record *agg_recptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * For message processing * * defined in xchkdsk.c */ extern char *Vol_Label; /* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV * * The following are internal to this file * */ int backout_ait_part1(int); int backout_valid_agg_inode(int, uint32_t, struct fsck_ino_msg_info *); int first_ref_check_other_ait(void); int record_ait_part1_again(int); int record_other_ait(void); int rootdir_tree_bad(struct dinode *, int *); int validate_super(int); int validate_super_2ndaryAI(int); int verify_agg_fileset_inode(struct dinode *, uint32_t, int, struct fsck_ino_msg_info *); int verify_ait_inode(struct dinode *, int, struct fsck_ino_msg_info *); int verify_ait_part1(int); int verify_ait_part2(int); int verify_badblk_inode(struct dinode *, int, struct fsck_ino_msg_info *); int verify_bmap_inode(struct dinode *, int, struct fsck_ino_msg_info *); int verify_fs_super_ext(struct dinode *, struct fsck_ino_msg_info *, int *); int verify_log_inode(struct dinode *, int, struct fsck_ino_msg_info *); int verify_metadata_data(struct dinode *, uint32_t, struct fsck_inode_record *, struct fsck_ino_msg_info *); int verify_repair_fs_rootdir(struct dinode *, struct fsck_ino_msg_info *, int *); /* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV */ /***************************************************************************** * NAME: agg_clean_or_dirty * * FUNCTION: Compare the superblock state field (s_state) with fsck's * conclusions about the current state (clean | dirty) of * the aggregate. If write access, attempt to update the * state field if the superblock is incorrect. If read-only, * notify the caller if the superblock is incorrect. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int agg_clean_or_dirty() { int acod_rc = FSCK_OK; if (!agg_recptr->ag_dirty) { /* aggregate is actually clean now */ /* announce this happy news */ fsck_send_msg(fsck_AGGCLN); if (agg_recptr->processing_readonly) { /* don't have write access */ if ((sb_ptr->s_state & FM_DIRTY) == FM_DIRTY) { /* but isn't marked clean */ fsck_send_msg(fsck_AGGCLNNOTDRTY); } } else { /* do have write access to the aggregate */ fsck_send_msg(fsck_ALLFXD); sb_ptr->s_state = FM_CLEAN; acod_rc = replicate_superblock(); if (acod_rc == FSCK_OK) { fsck_send_msg(fsck_AGGMRKDCLN); } } } else { /* aggregate is actually dirty now */ fsck_send_msg(fsck_AGGDRTY); if ((sb_ptr->s_state & FM_DIRTY) != FM_DIRTY) { /* but isn't marked dirty */ if (agg_recptr->processing_readonly) { /* don't have write access */ fsck_send_msg(fsck_AGGDRTYNOTCLN, Vol_Label); } else { /* do have write access to the aggregate */ /* * in keeping with the policy of protecting the system * from a potential panic due to a dirty file system, * if we have write access we'll mark the file system * dirty without asking permission. */ sb_ptr->s_state = FM_DIRTY; acod_rc = replicate_superblock(); if (acod_rc == FSCK_OK) { fsck_send_msg(fsck_AGGMRKDDRTY); } } } } return (acod_rc); } /***************************************************************************** * NAME: backout_ait_part1 * * FUNCTION: Unrecord, in the fsck workspace block map, all storage allocated * to inodes in part 1 (inodes 0 through 15) of the specified * (primary or secondary) aggregate inode table. * * PARAMETERS: * which_ait - input - the Aggregate Inode Table on which to perform * the function. { fsck_primary | fsck_secondary } * * NOTES: o The caller to this routine must ensure that the * calls made by backout_ait_part1 to inode_get() * will not require device I/O. * That is, the caller must ensure that the aggregate * inode extent containing part1 of the target AIT * resides in the fsck inode buffer before calling * this routine. (See inode_get() for more info.) * * RETURNS: * success: FSCK_OK * failure: something else */ int backout_ait_part1(int which_ait) { int baitp1_rc = FSCK_OK; struct fsck_ino_msg_info ino_msg_info; struct fsck_ino_msg_info *msg_info_ptr; msg_info_ptr = &ino_msg_info; msg_info_ptr->msg_inopfx = fsck_aggr_inode; msg_info_ptr->msg_inotyp = fsck_metadata; agg_recptr->inode_stamp = -1; msg_info_ptr->msg_inonum = AGGREGATE_I; baitp1_rc = backout_valid_agg_inode(which_ait, AGGREGATE_I, msg_info_ptr); msg_info_ptr->msg_inonum = BMAP_I; if (baitp1_rc == FSCK_OK) { baitp1_rc = backout_valid_agg_inode(which_ait, BMAP_I, msg_info_ptr); msg_info_ptr->msg_inonum = LOG_I; if (baitp1_rc == FSCK_OK) { baitp1_rc = backout_valid_agg_inode(which_ait, LOG_I, msg_info_ptr); msg_info_ptr->msg_inonum = BADBLOCK_I; if (baitp1_rc == FSCK_OK) { baitp1_rc = backout_valid_agg_inode(which_ait, BADBLOCK_I, msg_info_ptr); } } } return (baitp1_rc); } /***************************************************************************** * NAME: backout_valid_agg_inode * * FUNCTION: Unrecord, in the fsck workspace block map, storage allocated to * the specified aggregate inode, assuming that all data structures * associated with the inode are consistent. (E.g., the B+ Tree * is at least internally consistent.) * * PARAMETERS: * which_ait - input - the Aggregate Inode Table on which to perform * the function. { fsck_primary | fsck_secondary } * inoidx - input - ordinal number of the inode (i.e., inode number * as an int32_t) * msg_info_ptr - input - pointer to a data area with data needed to * issue messages about the inode * * NOTES: o The caller to this routine must ensure that the * calls made by backout_ait_part1 to inode_get() * will not require device I/O. * That is, the caller must ensure that the aggregate * inode extent containing part1 of the target AIT * resides in the fsck inode buffer before calling * this routine. (See inode_get() for more info.) * * RETURNS: * success: FSCK_OK * failure: something else */ int backout_valid_agg_inode(int which_ait, uint32_t inoidx, struct fsck_ino_msg_info *msg_info_ptr) { int bvai_rc = FSCK_OK; int agg_inode = -1; int alloc_ifnull = 0; struct dinode *inoptr; struct fsck_inode_record *inorecptr; bvai_rc = inode_get(agg_inode, which_ait, inoidx, &inoptr); if (bvai_rc != FSCK_OK) { /* didn't get the inode */ bvai_rc = FSCK_FAILED_REREAD_AGGINO; } else { /* got the inode */ bvai_rc = get_inorecptr(agg_inode, alloc_ifnull, inoidx, &inorecptr); if ((bvai_rc == FSCK_OK) && (inorecptr == NULL)) { bvai_rc = FSCK_INTERNAL_ERROR_22; fsck_send_msg(fsck_INTERNALERROR, bvai_rc, 0, 0, 0); } else if (bvai_rc == FSCK_OK) { bvai_rc = unrecord_valid_inode(inoptr, inoidx, inorecptr, msg_info_ptr); } } return (bvai_rc); } /***************************************************************************** * NAME: fatal_dup_check * * FUNCTION: Determine whether any blocks are allocated to more than one * aggregate metadata object. (If so, the aggregate is too * far gone for fsck to correct it, or even to analyze it with * any confidence.) * * PARAMETERS: none * * NOTES: * This routine is called after all the following has been * completed: * - all metadata (aggregate and fileset) has been validated * - all inode extents have been recorded * - all fixed metadata has been recorded * - the block map and inode map have been recorded * * A similar check is done in validate_select_agg_inode_table * when an apparently valid part of the table has been identified. * * RETURNS: * success: FSCK_OK * failure: something else */ int fatal_dup_check() { struct dupall_blkrec *dupblk_ptr; int64_t first_in_range, this_blknum, last_blknum; uint32_t range_size; if (agg_recptr->dup_alloc_lst == NULL) return FSCK_OK; /* duplicate allocations detected during metadata validation */ dupblk_ptr = agg_recptr->dup_alloc_lst; first_in_range = dupblk_ptr->first_blk; last_blknum = dupblk_ptr->last_blk; dupblk_ptr = dupblk_ptr->next; while (dupblk_ptr != NULL) { /* for all multiply allocated blocks */ this_blknum = dupblk_ptr->first_blk; if (last_blknum != (this_blknum - 1)) { range_size = last_blknum - first_in_range + 1; fsck_send_msg(fsck_DUPBLKMDREF, range_size, (long long) first_in_range); first_in_range = this_blknum; } last_blknum = dupblk_ptr->last_blk; dupblk_ptr = dupblk_ptr->next; } range_size = last_blknum - first_in_range + 1; fsck_send_msg(fsck_DUPBLKMDREF, range_size, (long long) first_in_range); fsck_send_msg(fsck_DUPBLKMDREFS); agg_recptr->ag_dirty = 1; return (FSCK_DUPMDBLKREF); } /***************************************************************************** * NAME: first_ref_check_agg_metadata * * FUNCTION: Determine whether the storage allocated for aggregate metadata * includes a reference to any multiply-allocated aggregate blocks * for which the first reference is still unresolved. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int first_ref_check_agg_metadata() { int frcam_rc = FSCK_OK; uint32_t ino_idx; struct dinode *ino_ptr; int aggregate_inode = -1; /* going for aggregate inodes only */ int alloc_ifnull = 0; int which_ait; struct fsck_inode_record *inorec_ptr; struct fsck_ino_msg_info ino_msg_info; struct fsck_ino_msg_info *msg_info_ptr; msg_info_ptr = &ino_msg_info; msg_info_ptr->msg_inopfx = fsck_aggr_inode; msg_info_ptr->msg_inotyp = fsck_metadata; /* * check ait part 1 inodes for first references */ (agg_recptr->primary_ait_4part1) ? (which_ait = fsck_primary) : (which_ait = fsck_secondary); /* try for the self inode */ ino_idx = AGGREGATE_I; frcam_rc = inode_get(aggregate_inode, which_ait, ino_idx, &ino_ptr); if (frcam_rc == FSCK_OK) { /* got the self inode */ msg_info_ptr->msg_inonum = ino_idx; frcam_rc = get_inorecptr(aggregate_inode, alloc_ifnull, ino_idx, &inorec_ptr); if ((frcam_rc == FSCK_OK) && (inorec_ptr == NULL)) { frcam_rc = FSCK_INTERNAL_ERROR_25; fsck_send_msg(fsck_INTERNALERROR, frcam_rc, 0, 0, 0); } else if (frcam_rc == FSCK_OK) { frcam_rc = first_ref_check_inode(ino_ptr, ino_idx, inorec_ptr, msg_info_ptr); } } else { /* couldn't read the inode! * (We read it successfully a little while ago) */ frcam_rc = FSCK_FAILED_SELF_READ3; } if ((frcam_rc == FSCK_OK) && (agg_recptr->unresolved_1stref_count > 0)) { /* no errors and still have 1st refs to resolve */ /* try for the blockmap inode */ ino_idx = BMAP_I; frcam_rc = inode_get(aggregate_inode, which_ait, ino_idx, &ino_ptr); if (frcam_rc == FSCK_OK) { /* got the block map inode */ msg_info_ptr->msg_inonum = ino_idx; frcam_rc = get_inorecptr(aggregate_inode, alloc_ifnull, ino_idx, &inorec_ptr); if ((frcam_rc == FSCK_OK) && (inorec_ptr == NULL)) { frcam_rc = FSCK_INTERNAL_ERROR_26; fsck_send_msg(fsck_INTERNALERROR, frcam_rc, 0, 0, 0); } else if (frcam_rc == FSCK_OK) { frcam_rc = first_ref_check_inode(ino_ptr, ino_idx, inorec_ptr, msg_info_ptr); } } else { /* couldn't read the inode! * (We read it successfully a little while ago) */ frcam_rc = FSCK_FAILED_BMAP_READ2; } } if ((frcam_rc == FSCK_OK) && (agg_recptr->unresolved_1stref_count > 0)) { /* no errors and still have 1st refs to resolve */ /* try for the journal inode */ ino_idx = LOG_I; frcam_rc = inode_get(aggregate_inode, which_ait, ino_idx, &ino_ptr); if (frcam_rc == FSCK_OK) { /* got the journal inode */ msg_info_ptr->msg_inonum = ino_idx; frcam_rc = get_inorecptr(aggregate_inode, alloc_ifnull, ino_idx, &inorec_ptr); if ((frcam_rc == FSCK_OK) && (inorec_ptr == NULL)) { frcam_rc = FSCK_INTERNAL_ERROR_23; fsck_send_msg(fsck_INTERNALERROR, frcam_rc, 0, 0, 0); } else if (frcam_rc == FSCK_OK) { frcam_rc = first_ref_check_inode(ino_ptr, ino_idx, inorec_ptr, msg_info_ptr); } } else { /* couldn't read the inode! * (We read it successfully a little while ago) */ frcam_rc = FSCK_FAILED_LOG_READ2; } } if ((frcam_rc == FSCK_OK) && (agg_recptr->unresolved_1stref_count > 0)) { /* no errors and still have 1st refs to resolve */ /* try for the bad block inode */ ino_idx = BADBLOCK_I; frcam_rc = inode_get(aggregate_inode, which_ait, ino_idx, &ino_ptr); if (frcam_rc == FSCK_OK) { /* got the bad block inode */ msg_info_ptr->msg_inonum = ino_idx; frcam_rc = get_inorecptr(aggregate_inode, alloc_ifnull, ino_idx, &inorec_ptr); if ((frcam_rc == FSCK_OK) && (inorec_ptr == NULL)) { frcam_rc = FSCK_INTERNAL_ERROR_58; fsck_send_msg(fsck_INTERNALERROR, frcam_rc, 0, 0, 0); } else if (frcam_rc == FSCK_OK) { frcam_rc = first_ref_check_inode(ino_ptr, ino_idx, inorec_ptr, msg_info_ptr); } } else { /* couldn't read the inode! * (We read it successfully a little while ago) */ frcam_rc = FSCK_FAILED_BADBLK_READ2; } } /* * check ait part 2 inodes for first references */ (agg_recptr->primary_ait_4part2) ? (which_ait = fsck_primary) : (which_ait = fsck_secondary); if ((frcam_rc == FSCK_OK) && (agg_recptr->unresolved_1stref_count > 0)) { /* no errors and still have 1st refs to resolve */ /* read the aggregate inode */ ino_idx = FILESYSTEM_I; frcam_rc = inode_get(aggregate_inode, which_ait, ino_idx, &ino_ptr); if (frcam_rc == FSCK_OK) { /* got the fileset inode */ msg_info_ptr->msg_inonum = ino_idx; frcam_rc = get_inorecptr(aggregate_inode, alloc_ifnull, ino_idx, &inorec_ptr); if ((frcam_rc == FSCK_OK) && (inorec_ptr == NULL)) { frcam_rc = FSCK_INTERNAL_ERROR_28; fsck_send_msg(fsck_INTERNALERROR, frcam_rc, 0, 0, 0); } else if (frcam_rc == FSCK_OK) { frcam_rc = first_ref_check_inode(ino_ptr, ino_idx, inorec_ptr, msg_info_ptr); } } else { /* couldn't read the inode! * (We read it successfully a little while ago) */ frcam_rc = FSCK_FAILED_AGFS_READ3; } } if ((frcam_rc == FSCK_OK) && (agg_recptr->unresolved_1stref_count > 0)) { /* no errors and still have 1st refs to resolve */ frcam_rc = first_ref_check_other_ait(); } return (frcam_rc); } /************************************************************************** * NAME: first_ref_check_fixed_metadata * * FUNCTION: Certain aggregate metadata is not described by any inode. * This routine determines whether any of the blocks occupied * by this aggregate are multiply-allocated and still have * unresolved first reference. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int first_ref_check_fixed_metadata() { int frcfm_rc = FSCK_OK; int64_t start_block, end_block; uint32_t length_in_agg_blocks; int64_t wsp_blocks_described; /* * the reserved space (at the beginning of the aggregate) */ start_block = 0; length_in_agg_blocks = AGGR_RSVD_BYTES / sb_ptr->s_bsize; end_block = start_block + length_in_agg_blocks - 1; frcfm_rc = blkall_ref_check(start_block, end_block); if (frcfm_rc || (agg_recptr->unresolved_1stref_count == 0)) return frcfm_rc; /* * the superblocks */ length_in_agg_blocks = SIZE_OF_SUPER / sb_ptr->s_bsize; /* * primary */ start_block = SUPER1_OFF / sb_ptr->s_bsize; end_block = start_block + length_in_agg_blocks - 1; frcfm_rc = blkall_ref_check(start_block, end_block); if (frcfm_rc || (agg_recptr->unresolved_1stref_count == 0)) return frcfm_rc; /* * secondary */ start_block = SUPER2_OFF / sb_ptr->s_bsize; end_block = start_block + length_in_agg_blocks - 1; frcfm_rc = blkall_ref_check(start_block, end_block); if (frcfm_rc || (agg_recptr->unresolved_1stref_count == 0)) return frcfm_rc; /* * note that the fsck workspace and journal log (at the end of the * aggregate) are not described by the block map (neither the * Aggregate Block Allocation Map nor the fsck Workspace Block Map) */ /* * the "phantom blocks" described by the last dmap page */ /* * the first page is a control page and scratch area. */ wsp_blocks_described = BITSPERBYTE * (agg_recptr->ondev_wsp_byte_length - BYTESPERPAGE); if (wsp_blocks_described > agg_recptr->sb_agg_fsblk_length) { /* * the dmaps do describe more blocks than * actually exist */ /* since this is * the number of blocks and since blocks are * numbered starting at 0, this is the block * number of the first phantom block; */ start_block = agg_recptr->sb_agg_fsblk_length; end_block = wsp_blocks_described - 1; frcfm_rc = blkall_ref_check(start_block, end_block); } return (frcfm_rc); } /***************************************************************************** * NAME: first_ref_check_fs_metadata * * FUNCTION: Determine whether any blocks occupied by fileset metadata are * are multiply-allocated and still have unresolved first * reference. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int first_ref_check_fs_metadata() { int frcfsm_rc = FSCK_OK; uint32_t ino_idx; struct dinode *ino_ptr; int aggregate_inode = 0; /* going for fileset inodes only */ int alloc_ifnull = 0; int which_fsit; /* which fileset? */ struct fsck_inode_record *inorec_ptr; struct fsck_ino_msg_info ino_msg_info; struct fsck_ino_msg_info *msg_info_ptr; msg_info_ptr = &ino_msg_info; msg_info_ptr->msg_inopfx = fsck_fset_inode; /* all fileset owned */ msg_info_ptr->msg_inotyp = fsck_metadata; /* * in release 1 there is exactly 1 fileset */ which_fsit = 0; /* try for the fileset superinode extension */ ino_idx = FILESET_EXT_I; frcfsm_rc = inode_get(aggregate_inode, which_fsit, ino_idx, &ino_ptr); if (frcfsm_rc == FSCK_OK) { /* got the inode */ msg_info_ptr->msg_inonum = ino_idx; frcfsm_rc = get_inorecptr(aggregate_inode, alloc_ifnull, ino_idx, &inorec_ptr); if ((frcfsm_rc == FSCK_OK) && inorec_ptr) { frcfsm_rc = first_ref_check_inode(ino_ptr, ino_idx, inorec_ptr, msg_info_ptr); } } else { /* couldn't read the inode! * (We read it successfully a little while ago) */ frcfsm_rc = FSCK_FAILED_FSSIEXT_READ2; } if ((frcfsm_rc == FSCK_OK) && (agg_recptr->unresolved_1stref_count > 0)) { /* no errors and still have 1st refs to resolve */ /* try for the root directory inode */ ino_idx = ROOT_I; frcfsm_rc = inode_get(aggregate_inode, which_fsit, ino_idx, &ino_ptr); if (frcfsm_rc == FSCK_OK) { /* got the root dir inode */ msg_info_ptr->msg_inonum = ino_idx; frcfsm_rc = get_inorecptr(aggregate_inode, alloc_ifnull, ino_idx, &inorec_ptr); if ((frcfsm_rc == FSCK_OK) && (inorec_ptr == NULL)) { frcfsm_rc = FSCK_INTERNAL_ERROR_29; fsck_send_msg(fsck_INTERNALERROR, frcfsm_rc, 0, 0, 0); } else if (frcfsm_rc == FSCK_OK) { frcfsm_rc = first_ref_check_inode(ino_ptr, ino_idx, inorec_ptr, msg_info_ptr); } if ((frcfsm_rc == FSCK_OK) && (inorec_ptr->selected_to_rls)) { /* routine doesn't * understand that the root directory is * the special case of a directory which * is also special metadata and might * flag it for release. */ inorec_ptr->selected_to_rls = 0; } } else { /* couldn't read the inode! * (We read it successfully a little while ago) */ frcfsm_rc = FSCK_FAILED_FSRTDIR_READ2; } } return (frcfsm_rc); } /************************************************************************** * NAME: first_ref_check_other_ait * * FUNCTION: Determine whether any blocks occupied by the "other ait" * are multiply-allocated and still have unresolved first * reference. To be more specific, if the primary ait is * being used for fsck processing, the secondary ait is the * "other ait"...and vice versa. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int first_ref_check_other_ait() { int frcoa_rc = FSCK_OK; int64_t start_block, end_block; uint32_t length_in_agg_blocks; /* * first extent of the agg inode map */ if (agg_recptr->primary_ait_4part1) { /* primary already recorded */ start_block = addressPXD(&(sb_ptr->s_aim2)); length_in_agg_blocks = lengthPXD(&(sb_ptr->s_aim2)); } else { /* secondary already recorded */ start_block = AIMAP_OFF / sb_ptr->s_bsize; length_in_agg_blocks = (AITBL_OFF - AIMAP_OFF) / sb_ptr->s_bsize; } end_block = start_block + length_in_agg_blocks - 1; frcoa_rc = blkall_ref_check(start_block, end_block); /* * first extent of the agg inode table */ if (agg_recptr->primary_ait_4part1) { /* primary already recorded */ start_block = addressPXD(&(sb_ptr->s_ait2)); length_in_agg_blocks = lengthPXD(&(sb_ptr->s_ait2)); } else { /* secondary already recorded */ start_block = AITBL_OFF / sb_ptr->s_bsize; length_in_agg_blocks = INODE_EXTENT_SIZE / sb_ptr->s_bsize; } end_block = start_block + length_in_agg_blocks - 1; frcoa_rc = blkall_ref_check(start_block, end_block); return (frcoa_rc); } /***************************************************************************** * NAME: record_ait_part1_again * * FUNCTION: Record, in the fsck workspace block map, all storage allocated * to inodes in part 1 (inodes 0 through 15) of the specified * (primary or secondary) aggregate inode table. Do this with * the knowledge that all these inodes have been verified * completely correct. * * PARAMETERS: * which_ait - input - the Aggregate Inode Table on which to perform * the function. { fsck_primary | fsck_secondary } * * NOTES: o The caller to this routine must ensure that the * calls made by record_ait_part1_again to inode_get() * will not require device I/O. * That is, the caller must ensure that the aggregate * inode extent containing part1 of the target AIT * resides in the fsck inode buffer before calling * this routine. (See inode_get() for more info) * * RETURNS: * success: FSCK_OK * failure: something else */ int record_ait_part1_again(int which_ait) { int raitp1a_rc = FSCK_OK; struct fsck_inode_record *inorecptr; uint32_t ino_idx; struct dinode *ino_ptr; int aggregate_inode = -1; /* going for aggregate inodes only */ int alloc_ifnull = 0; struct fsck_ino_msg_info msg_info; struct fsck_ino_msg_info *msg_info_ptr; msg_info_ptr = &msg_info; msg_info_ptr->msg_inopfx = fsck_aggr_inode; msg_info_ptr->msg_inotyp = fsck_metadata; /* try for the self inode */ ino_idx = AGGREGATE_I; msg_info_ptr->msg_inonum = ino_idx; raitp1a_rc = inode_get(aggregate_inode, which_ait, ino_idx, &ino_ptr); if (raitp1a_rc == FSCK_OK) { /* got the self inode */ agg_recptr->inode_stamp = ino_ptr->di_inostamp; raitp1a_rc = get_inorecptr(aggregate_inode, alloc_ifnull, ino_idx, &inorecptr); if ((raitp1a_rc == FSCK_OK) && (inorecptr == NULL)) { raitp1a_rc = FSCK_INTERNAL_ERROR_39; fsck_send_msg(fsck_INTERNALERROR, raitp1a_rc, 0, 0, 0); } else if (raitp1a_rc == FSCK_OK) { inorecptr->in_use = 0; inorecptr->selected_to_rls = 0; inorecptr->crrct_link_count = 0; inorecptr->crrct_prnt_inonum = 0; inorecptr->adj_entries = 0; inorecptr->cant_chkea = 0; inorecptr->clr_ea_fld = 0; inorecptr->clr_acl_fld = 0; inorecptr->inlineea_on = 0; inorecptr->inlineea_off = 0; inorecptr->inline_data_err = 0; inorecptr->ignore_alloc_blks = 0; inorecptr->reconnect = 0; inorecptr->unxpctd_prnts = 0; inorecptr->badblk_inode = 0; inorecptr->involved_in_dups = 0; inorecptr->inode_type = metadata_inode; inorecptr->link_count = 0; inorecptr->parent_inonum = 0; inorecptr->ext_rec = NULL; raitp1a_rc = record_valid_inode(ino_ptr, ino_idx, inorecptr, msg_info_ptr); } if (raitp1a_rc == FSCK_OK) { /* recorded it successfully */ inorecptr->in_use = 1; } } if (raitp1a_rc == FSCK_OK) { /* self inode recorded ok */ /* try for the blockmap inode */ ino_idx = BMAP_I; msg_info_ptr->msg_inonum = ino_idx; raitp1a_rc = inode_get(aggregate_inode, which_ait, ino_idx, &ino_ptr); if (raitp1a_rc == FSCK_OK) { /* got the block map inode */ raitp1a_rc = get_inorecptr(aggregate_inode, alloc_ifnull, ino_idx, &inorecptr); if ((raitp1a_rc == FSCK_OK) && (inorecptr == NULL)) { raitp1a_rc = FSCK_INTERNAL_ERROR_43; fsck_send_msg(fsck_INTERNALERROR, raitp1a_rc, 0, 0, 0); } else if (raitp1a_rc == FSCK_OK) { inorecptr->in_use = 0; inorecptr->selected_to_rls = 0; inorecptr->crrct_link_count = 0; inorecptr->crrct_prnt_inonum = 0; inorecptr->adj_entries = 0; inorecptr->cant_chkea = 0; inorecptr->clr_ea_fld = 0; inorecptr->clr_acl_fld = 0; inorecptr->inlineea_on = 0; inorecptr->inlineea_off = 0; inorecptr->inline_data_err = 0; inorecptr->ignore_alloc_blks = 0; inorecptr->reconnect = 0; inorecptr->unxpctd_prnts = 0; inorecptr->badblk_inode = 0; inorecptr->involved_in_dups = 0; inorecptr->inode_type = metadata_inode; inorecptr->link_count = 0; inorecptr->parent_inonum = 0; inorecptr->ext_rec = NULL; raitp1a_rc = record_valid_inode(ino_ptr, ino_idx, inorecptr, msg_info_ptr); } if (raitp1a_rc == FSCK_OK) { /* recorded it successfully */ inorecptr->in_use = 1; } } } if (raitp1a_rc == FSCK_OK) { /* self and bmap inodes recorded ok */ /* try for the journal log inode */ ino_idx = LOG_I; msg_info_ptr->msg_inonum = ino_idx; raitp1a_rc = inode_get(aggregate_inode, which_ait, ino_idx, &ino_ptr); if (raitp1a_rc == FSCK_OK) { /* got the journal log inode */ raitp1a_rc = get_inorecptr(aggregate_inode, alloc_ifnull, ino_idx, &inorecptr); if ((raitp1a_rc == FSCK_OK) && (inorecptr == NULL)) { raitp1a_rc = FSCK_INTERNAL_ERROR_44; fsck_send_msg(fsck_INTERNALERROR, raitp1a_rc, 0, 0, 0); } else if (raitp1a_rc == FSCK_OK) { inorecptr->in_use = 0; inorecptr->selected_to_rls = 0; inorecptr->crrct_link_count = 0; inorecptr->crrct_prnt_inonum = 0; inorecptr->adj_entries = 0; inorecptr->cant_chkea = 0; inorecptr->clr_ea_fld = 0; inorecptr->clr_acl_fld = 0; inorecptr->inlineea_on = 0; inorecptr->inlineea_off = 0; inorecptr->inline_data_err = 0; inorecptr->ignore_alloc_blks = 0; inorecptr->reconnect = 0; inorecptr->unxpctd_prnts = 0; inorecptr->badblk_inode = 0; inorecptr->involved_in_dups = 0; inorecptr->inode_type = metadata_inode; inorecptr->link_count = 0; inorecptr->parent_inonum = 0; inorecptr->ext_rec = NULL; raitp1a_rc = record_valid_inode(ino_ptr, ino_idx, inorecptr, msg_info_ptr); } if (raitp1a_rc == FSCK_OK) { /* recorded it successfully */ inorecptr->in_use = 1; } } } if (raitp1a_rc == FSCK_OK) { /* self, bmap, and journal inodes recorded ok */ /* try for the bad block inode */ ino_idx = BADBLOCK_I; msg_info_ptr->msg_inonum = ino_idx; raitp1a_rc = inode_get(aggregate_inode, which_ait, ino_idx, &ino_ptr); if (raitp1a_rc == FSCK_OK) { /* got the bad block inode */ raitp1a_rc = get_inorecptr(aggregate_inode, alloc_ifnull, ino_idx, &inorecptr); if ((raitp1a_rc == FSCK_OK) && (inorecptr == NULL)) { raitp1a_rc = FSCK_INTERNAL_ERROR_59; fsck_send_msg(fsck_INTERNALERROR, raitp1a_rc, 0, 0, 0); } else if (raitp1a_rc == FSCK_OK) { inorecptr->in_use = 0; inorecptr->selected_to_rls = 0; inorecptr->crrct_link_count = 0; inorecptr->crrct_prnt_inonum = 0; inorecptr->adj_entries = 0; inorecptr->cant_chkea = 0; inorecptr->clr_ea_fld = 0; inorecptr->clr_acl_fld = 0; inorecptr->inlineea_on = 0; inorecptr->inlineea_off = 0; inorecptr->inline_data_err = 0; inorecptr->ignore_alloc_blks = 0; inorecptr->reconnect = 0; inorecptr->unxpctd_prnts = 0; inorecptr->badblk_inode = 0; inorecptr->involved_in_dups = 0; inorecptr->inode_type = metadata_inode; inorecptr->link_count = 0; inorecptr->parent_inonum = 0; inorecptr->ext_rec = NULL; raitp1a_rc = record_valid_inode(ino_ptr, ino_idx, inorecptr, msg_info_ptr); } if (raitp1a_rc == FSCK_OK) { /* recorded it successfully */ inorecptr->in_use = 1; } } } return (raitp1a_rc); } /************************************************************************** * NAME: record_fixed_metadata * * FUNCTION: Certain aggregate metadata is not described by any inode. * This routine marks, in the fsck workspace block map, that * the blocks occupied by this aggregate metadata are in use. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int record_fixed_metadata() { int rfm_rc = FSCK_OK; int64_t start_block, end_block; uint32_t length_in_agg_blocks; int64_t wsp_blocks_described; /* * the reserved space (at the beginning of the aggregate) */ start_block = 0; length_in_agg_blocks = AGGR_RSVD_BYTES / sb_ptr->s_bsize; end_block = start_block + length_in_agg_blocks - 1; rfm_rc = blkall_increment_owners(start_block, end_block, NULL); /* * the superblocks */ if (rfm_rc == FSCK_OK) { /* go ahead with superblocks */ length_in_agg_blocks = SIZE_OF_SUPER / sb_ptr->s_bsize; /* * primary */ start_block = SUPER1_OFF / sb_ptr->s_bsize; end_block = start_block + length_in_agg_blocks - 1; rfm_rc = blkall_increment_owners(start_block, end_block, NULL); /* * secondary */ if (rfm_rc == FSCK_OK) { start_block = SUPER2_OFF / sb_ptr->s_bsize; end_block = start_block + length_in_agg_blocks - 1; rfm_rc = blkall_increment_owners(start_block, end_block, NULL); } } /* * note that the fsck workspace and journal log (at the end of the * aggregate) are not described by the block map (neither the * Aggregate Block Allocation Map nor the fsck Workspace Block Map) */ /* * the "phantom blocks" described by the last dmap page */ if (rfm_rc == FSCK_OK) { /* * the first page is a control page and scratch area. */ wsp_blocks_described = BITSPERBYTE * (agg_recptr->ondev_wsp_byte_length - BYTESPERPAGE); if (wsp_blocks_described > agg_recptr->sb_agg_fsblk_length) { /* * the dmaps do describe more blocks than * actually exist */ /* since this is * the number of blocks and since blocks are * numbered starting at 0, this is the block * number of the first phantom block; */ start_block = agg_recptr->sb_agg_fsblk_length; end_block = wsp_blocks_described - 1; rfm_rc = blkall_increment_owners(start_block, end_block, NULL); } } return (rfm_rc); } /************************************************************************** * NAME: record_other_ait * * FUNCTION: Record the blocks occupied by the "other ait" in the fsck * workspace block map. To be more specific, if the primary * ait is being used for fsck processing, the secondary ait * is the "other ait"...and vice versa. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int record_other_ait() { int roa_rc = FSCK_OK; int64_t start_block, end_block; uint32_t length_in_agg_blocks; /* * first extent of the agg inode map */ if (agg_recptr->primary_ait_4part1) { /* primary already recorded */ start_block = addressPXD(&(sb_ptr->s_aim2)); length_in_agg_blocks = lengthPXD(&(sb_ptr->s_aim2)); } else { /* secondary already recorded */ start_block = AIMAP_OFF / sb_ptr->s_bsize; length_in_agg_blocks = (AITBL_OFF - AIMAP_OFF) / sb_ptr->s_bsize; } end_block = start_block + length_in_agg_blocks - 1; roa_rc = blkall_increment_owners(start_block, end_block, NULL); /* * first extent of the agg inode table */ if (agg_recptr->primary_ait_4part1) { /* primary already recorded */ start_block = addressPXD(&(sb_ptr->s_ait2)); length_in_agg_blocks = lengthPXD(&(sb_ptr->s_ait2)); } else { /* secondary already recorded */ start_block = AITBL_OFF / sb_ptr->s_bsize; length_in_agg_blocks = INODE_EXTENT_SIZE / sb_ptr->s_bsize; } end_block = start_block + length_in_agg_blocks - 1; roa_rc = blkall_increment_owners(start_block, end_block, NULL); return (roa_rc); } /***************************************************************************** * NAME: replicate_superblock * * FUNCTION: Refresh both the primary and secondary superblocks in the * aggregate from the correct (and possibly updated) superblock * in the fsck buffer. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int replicate_superblock() { int rs_rc = FSCK_OK; /* write from the buffer to the primary superblock */ rs_rc = ujfs_put_superblk(Dev_IOPort, sb_ptr, 1); /* have to assume something got written */ agg_recptr->ag_modified = 1; if (rs_rc != FSCK_OK) { /* not good here is really bad */ agg_recptr->cant_write_primary_sb = 1; agg_recptr->ag_dirty = 1; /* mark the superblock in the buffer * to show the aggregate is dirty * (in case it isn't already marked * that way) */ sb_ptr->s_state |= FM_DIRTY; fsck_send_msg(fsck_CNTWRTSUPP); } else { /* wrote to the primary superblock */ agg_recptr->cant_write_primary_sb = 0; } /* write from the buffer to the secondary superblock */ rs_rc = ujfs_put_superblk(Dev_IOPort, sb_ptr, 0); /* have to assume something got written */ agg_recptr->ag_modified = 1; if (rs_rc == FSCK_OK) { /* wrote to secondary ok */ agg_recptr->cant_write_secondary_sb = 0; } else { /* not good here is pretty bad */ agg_recptr->cant_write_secondary_sb = 1; fsck_send_msg(fsck_CNTWRTSUPS); if ((sb_ptr->s_state & FM_DIRTY) != FM_DIRTY) { /* superblk not marked dirty now */ /* * This means, among other things, that we just * did a successful write to the primary superblock * and that we marked the primary to say the aggregate * is clean. */ sb_ptr->s_state |= FM_DIRTY; /* write from the buffer to the primary superblock */ rs_rc = ujfs_put_superblk(Dev_IOPort, sb_ptr, 1); /* have to assume something got written */ agg_recptr->ag_modified = 1; if (rs_rc != FSCK_OK) { /* not good here is a disaster */ /* * We may have just taken an aggregate marked dirty and * changed it to clean, but now we discover that it really * does have a serious problem. And all we can do about * it is issue the strongest warning we can think up. */ agg_recptr->cant_write_primary_sb = 1; fsck_send_msg(fsck_CNTWRTSUPP); fsck_send_msg(fsck_AGGDRTYNOTCLN, Vol_Label); } } } if ((agg_recptr->cant_write_primary_sb) && (agg_recptr->cant_write_secondary_sb)) { /* both bad */ rs_rc = FSCK_FAILED_BTHSBLK_WRITE; } else if (agg_recptr->cant_write_primary_sb) { /* primary bad */ rs_rc = FSCK_FAILED_PSBLK_WRITE; } else if (agg_recptr->cant_write_secondary_sb) { /* secondary bad */ rs_rc = FSCK_FAILED_SSBLK_WRITE; } return (rs_rc); } /***************************************************************************** * NAME: rootdir_tree_bad * * FUNCTION: This routine is called if the B+ Tree rooted in the fileset * root directory (aggregate inode FILESET_I) is found to be * corrupt. If the user approves the repair, it makes the * root directory B+ tree a correct, empty tree. * * PARAMETERS: * inoptr - input - pointer to the inode in an fsck buffer * inode_updated - input - pointer to a variable in which to return * !0 if the inode (in the buffer) has been * modified by this routine * 0 if the inode (in the buffer) has not been * modified by this routine * * RETURNS: * success: FSCK_OK * failure: something else */ int rootdir_tree_bad(struct dinode *inoptr, int *inode_updated) { int rtb_rc = FSCK_OK; *inode_updated = 0; fsck_send_msg(fsck_RIBADTREE); init_dir_tree((dtroot_t *) & (inoptr->di_btroot)); inoptr->di_next_index = 2; inoptr->di_nblocks = 0; inoptr->di_nlink = 2; inoptr->di_size = IDATASIZE; *inode_updated = 1; agg_recptr->rootdir_rebuilt = 1; fsck_send_msg(fsck_RICRETREE); return (rtb_rc); } /***************************************************************************** * NAME: validate_fs_metadata * * FUNCTION: Verify the metadata inodes for all filesets in the * aggregate. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int validate_fs_metadata() { int vfm_rc = FSCK_OK; int intermed_rc = FSCK_OK; struct fsck_ino_msg_info ino_msg_info; struct fsck_ino_msg_info *msg_info_ptr; int which_fsit, which_ait; uint32_t ino_idx; struct dinode *ino_ptr; int aggregate_inode = 0; /* going for fileset inodes only */ int alloc_ifnull = -1; int inode_updated; struct fsck_inode_record *inorecptr; msg_info_ptr = &ino_msg_info; /* all fileset owned */ msg_info_ptr->msg_inopfx = fsck_fset_inode; msg_info_ptr->msg_inotyp = fsck_metadata; if (agg_recptr->primary_ait_4part2) { which_ait = fsck_primary; } else { which_ait = fsck_secondary; } vfm_rc = ait_special_read_ext1(which_ait); if (vfm_rc != FSCK_OK) { /* read failed */ report_readait_error(vfm_rc, FSCK_FAILED_CANTREADAITEXTE, which_ait); vfm_rc = FSCK_FAILED_CANTREADAITEXTE; goto vfm_exit; } /* * In release 1 there's exactly 1 fileset */ which_fsit = FILESYSTEM_I; /* read the fileset superinode extension */ ino_idx = FILESET_EXT_I; intermed_rc = inode_get(aggregate_inode, which_fsit, ino_idx, &ino_ptr); if (intermed_rc != FSCK_OK) { /* can't get the inode */ //vfm_rc = FSCK_CANTREADFSEXT; //goto vfm_exit; goto read_root; /* Who really cares? */ } /* got superinode extension inode */ msg_info_ptr->msg_inonum = FILESET_EXT_I; intermed_rc = verify_fs_super_ext(ino_ptr, msg_info_ptr,&inode_updated); if (intermed_rc < 0) { /* something really really bad happened */ //vfm_rc = intermed_rc; //goto vfm_exit; goto read_root; } if (intermed_rc != FSCK_OK) { /* inode is bad */ //vfm_rc = FSCK_FSETEXTBAD; //goto vfm_exit; goto read_root; } /* superinode extension inode is ok */ if (inode_updated) { /* need to write the superinode extension */ vfm_rc = inode_put(ino_ptr); } //if (vfm_rc != FSCK_OK) // goto vfm_exit; read_root: /* read the root directory inode */ ino_idx = ROOT_I; intermed_rc = inode_get(aggregate_inode, which_fsit, ino_idx, &ino_ptr); if (intermed_rc < 0) { /* something really really bad happened */ vfm_rc = intermed_rc; goto vfm_exit; } if (intermed_rc != FSCK_OK) { /* can't get the inode */ vfm_rc = FSCK_CANTREADFSRTDR; goto vfm_exit; } /* got root directory inode */ msg_info_ptr->msg_inonum = ROOT_I; msg_info_ptr->msg_inotyp = fsck_directory; intermed_rc = verify_repair_fs_rootdir(ino_ptr, msg_info_ptr, &inode_updated); if (intermed_rc != FSCK_OK) { /* inode is bad. Couldn't (or * wasn't allowed to) repair it */ vfm_rc = FSCK_FSRTDRBAD; goto vfm_exit; } /* root directory is good */ if (inode_updated) { /* need to write the root directory */ vfm_rc = inode_put(ino_ptr); } /* * now get records as placeholders for * the 2 reserved fileset inodes */ vfm_rc = get_inorecptr(aggregate_inode, alloc_ifnull, FILESET_RSVD_I, &inorecptr); if ((vfm_rc == FSCK_OK) && (inorecptr == NULL)) { vfm_rc = FSCK_INTERNAL_ERROR_34; fsck_send_msg(fsck_INTERNALERROR, vfm_rc, 0, 0, 0); } else if (vfm_rc == FSCK_OK) { /* got first record */ inorecptr->inode_type = metadata_inode; inorecptr->in_use = 1; vfm_rc = get_inorecptr(aggregate_inode, alloc_ifnull, ACL_I, &inorecptr); if ((vfm_rc == FSCK_OK) && (inorecptr == NULL)) { vfm_rc = FSCK_INTERNAL_ERROR_35; fsck_send_msg(fsck_INTERNALERROR, vfm_rc, 0, 0, 0); } else if (vfm_rc == FSCK_OK) { /* got second record */ inorecptr->inode_type = metadata_inode; inorecptr->in_use = 1; } } vfm_exit: return (vfm_rc); } /***************************************************************************** * NAME: validate_repair_superblock * * FUNCTION: Verify that the primary superblock is valid. If it is, * the secondary superblock will be refreshed later in * processing. If the primary superblock is not valid, * verify that the secondary superblock is valid. If the * secondary superblock is found to be valid, copy it * over the primary superblock on the device so that * logredo will find a valid primary superblock. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int validate_repair_superblock() { int vrsb_rc = FSCK_OK; int intermed_rc = FSCK_OK; int primary_sb_bad = 1; /* assume a problem with primary */ int secondary_sb_bad = 1; /* assume a problem with secondary */ int which_sb = 0; /* get primary */ vrsb_rc = ujfs_get_superblk(Dev_IOPort, sb_ptr, 1); if (vrsb_rc != FSCK_OK) { /* if read primary fails */ fsck_send_msg(fsck_CNTRESUPP); } else { /* got primary superblock */ which_sb = fsck_primary; primary_sb_bad = validate_super(fsck_primary); } if (primary_sb_bad) { /* can't use the primary superblock */ /* get 2ndary */ vrsb_rc = ujfs_get_superblk(Dev_IOPort, sb_ptr, 0); if (vrsb_rc != FSCK_OK) { fsck_send_msg(fsck_CNTRESUPS); } else { /* got secondary superblock */ which_sb = fsck_secondary; secondary_sb_bad = validate_super(fsck_secondary); } if (!secondary_sb_bad) { /* secondary is ok */ if (agg_recptr->processing_readonly) { agg_recptr->ag_dirty = 1; agg_recptr->cant_write_primary_sb = 1; fsck_send_msg(fsck_BDSBNWRTACC); } else { /* else processing read/write */ sb_ptr->s_state = (sb_ptr->s_state | FM_DIRTY); /* correct the primary superblock */ intermed_rc = ujfs_put_superblk(Dev_IOPort, sb_ptr, 1); /* must assume something got written */ agg_recptr->ag_modified = 1; if (intermed_rc == FSCK_OK) { agg_recptr->ag_modified = 1; } else { /* write primary superblock failed */ /* * we won't bail out on this condition (so we * don't want to pass back the return code), * but it does leave the aggregate dirty */ agg_recptr->ag_dirty = 1; agg_recptr->cant_write_primary_sb = 1; fsck_send_msg(fsck_CNTWRTSUPP); } } } else { /* can't use the secondary superblock either */ agg_recptr->ag_dirty = 1; vrsb_rc = FSCK_FAILED_BTHSBLK_BAD; if ((primary_sb_bad == FSCK_BADSBMGC) && (secondary_sb_bad == FSCK_BADSBMGC)) { printf ("\nThe superblock does not describe a correct jfs file system.\n" "\nIf device %s is valid and contains a jfs file system,\n" "then both the primary and secondary superblocks are corrupt\n" "and cannot be repaired, and fsck cannot continue.\n" "\nOtherwise, make sure the entered device %s is correct.\n\n", Vol_Label, Vol_Label); } else { fsck_send_msg(fsck_BDSBBTHCRRPT); } if (Is_Device_Type_JFS(Vol_Label) == MSG_JFS_NOT_JFS) { fsck_send_msg(fsck_NOTJFSINFSTAB, Vol_Label); } } } if ((!primary_sb_bad) || (!secondary_sb_bad)) { /* the buffer holds a valid superblock */ /* aggregate block size */ agg_recptr->ag_blk_size = sb_ptr->s_bsize; if (which_sb == fsck_primary) { fsck_send_msg(fsck_SBOKP); } else { fsck_send_msg(fsck_SBOKS); } if ((sb_ptr->s_flag & JFS_SPARSE) == JFS_SPARSE) { fsck_send_msg(fsck_SPARSEFILSYS); } } return (vrsb_rc); } /***************************************************************************** * NAME: validate_select_agg_inode_table * * FUNCTION: Verify the inodes in the Aggregate Inode Table. If all * inodes in the Primary Aggregate Inode Table are valid, * select it. Otherwise, if all inodes in the Secondary * Aggregate Inode Table are valid, select it. Otherwise, * if inodes 0 through 15 are valid in one table and inodes * 16 through 31 are valid in the other, select the valid * 0 through 15 and the valid 16 through 31. * * PARAMETERS: none * * NOTES: o Aggregate inodes 0 through 15 describe the aggregate and * aggregate metadata. Aggregate inodes 16 through 31 each * describe a fileset in the aggregate (In release 1, there * is only 1 fileset in each aggregate and it is described * by aggregate inode 16). When neither Aggregate Inode * Table is completely valid, this suggests the division: * "part 1" is aggregate inodes 0 through 15 * "part 2" is aggregate inodes 16 through 31 * * o While we naturally prefer to use only the Primary Aggregate * Inode Table and, failing that, to use only the Secondary * Aggregate Inode Table, in the interests of avoiding loss * of user data, fsck will continue if it can find a valid * part 1 and a valid part 2. * * o Since this routine is invoked before the fsck workspace * has been completely initialized, this routine ensures * that the fsck I/O buffers contain the data needed by * any routine which it invokes. * * That is, since the workspace does not contain all the * information for inode_get (et al) to calculate device * offsets (needed to perform I/O), this routine ensures * that any invocations of inode_get by routines invoked * here will find the target data already in the fsck * inode buffer. * * RETURNS: * success: FSCK_OK * failure: something else */ int validate_select_agg_inode_table() { int vsait_rc = FSCK_OK; int intermed_rc = FSCK_OK; int aggregate_inode = -1; int alloc_ifnull = -1; struct fsck_inode_record *inorecptr; int cant_read_primary = 0; int cant_read_secondary = 0; int primary_part1_good = 0; int primary_part2_good = 0; int primary_part1_bad = 0; int primary_part2_bad = 0; int secondary_part1_good = 0; int secondary_part2_good = 0; int secondary_part1_bad = 0; int secondary_part2_bad = 0; uint32_t primary_inode_stamp = 0; uint32_t secondary_inode_stamp = 0; uint32_t unknown_stamp = (uint32_t) (-1); /* * try for part 1 and part 2 both from the primary aggregate inode table */ intermed_rc = ait_special_read_ext1(fsck_primary); if (intermed_rc != FSCK_OK) { /* don't have it in the buffer */ primary_part1_bad = -1; primary_part2_bad = -1; cant_read_primary = -1; } else { /* got the 1st extent of primary AIT into the inode buffer */ agg_recptr->inode_stamp = unknown_stamp; intermed_rc = verify_ait_part1(fsck_primary); primary_inode_stamp = agg_recptr->inode_stamp; if (intermed_rc < 0) { /* something fatal */ vsait_rc = intermed_rc; } else if (intermed_rc > 0) { /* primary table part 1 is bad */ primary_part1_bad = -1; } else { /* primary table, part 1 is good */ primary_part1_good = -1; intermed_rc = verify_ait_part2(fsck_primary); if (intermed_rc < 0) { /* something fatal */ vsait_rc = intermed_rc; } else if (intermed_rc > 0) { /* primary table part 2 is bad */ primary_part2_bad = -1; vsait_rc = backout_ait_part1(fsck_primary); } else { /* primary table, part 2 is good */ primary_part2_good = -1; } } } /* * if can't have both part 1 and part 2 from the primary, try for * part 1 and part 2 both from the secondary aggregate inode table */ if ((vsait_rc == FSCK_OK) && (primary_part1_bad || primary_part2_bad)) { /* go for secondary ait */ intermed_rc = ait_special_read_ext1(fsck_secondary); if (intermed_rc != FSCK_OK) { /* don't have it in the buffer */ secondary_part1_bad = -1; secondary_part2_bad = -1; cant_read_secondary = -1; } else { /* got the 1st extent of secondary AIT into the inode buffer */ agg_recptr->inode_stamp = unknown_stamp; intermed_rc = verify_ait_part1(fsck_secondary); secondary_inode_stamp = agg_recptr->inode_stamp; if (intermed_rc < 0) { /* something fatal */ vsait_rc = intermed_rc; } else if (intermed_rc > 0) { /* secondary table part 1 is bad */ secondary_part1_bad = 1; } else { /* secondary table, part 1 is good */ secondary_part1_good = 1; intermed_rc = verify_ait_part2(fsck_secondary); if (intermed_rc < 0) { /* something fatal */ vsait_rc = intermed_rc; } else if (intermed_rc > 0) { /* secondary table part 2 is bad */ secondary_part2_bad = 1; vsait_rc = backout_ait_part1(fsck_secondary); } else { /* secondary table, part 2 is good */ secondary_part2_good = 1; } } } } if ((vsait_rc == FSCK_OK) && (primary_part1_good && primary_part2_good)) { /* normal case, nothing amiss */ agg_recptr->primary_ait_4part1 = 1; agg_recptr->primary_ait_4part2 = 1; agg_recptr->inode_stamp = primary_inode_stamp; } else if ((vsait_rc == FSCK_OK) && (secondary_part1_good && secondary_part2_good)) { /* first safety net held up */ agg_recptr->primary_ait_4part1 = 0; agg_recptr->primary_ait_4part2 = 0; agg_recptr->inode_stamp = secondary_inode_stamp; } else { /* multiple points of failure. */ /* * try to go on by using part1 from one table and part 2 from the other */ if (vsait_rc == FSCK_OK) { /* nothing fatal */ if (primary_part1_good && (!secondary_part2_good) && (!secondary_part2_bad)) { /* * primary part 1 is good and haven't checked * secondary part 2 yet */ agg_recptr->inode_stamp = primary_inode_stamp; intermed_rc = ait_special_read_ext1(fsck_primary); if (intermed_rc == FSCK_OK) { vsait_rc = record_ait_part1_again (fsck_primary); } else { vsait_rc = FSCK_FAILED_CANTREADAITEXT4; } if (vsait_rc == FSCK_OK) { /* primary part1 re-recorded ok */ intermed_rc = ait_special_read_ext1 (fsck_secondary); if (intermed_rc != FSCK_OK) { /* didn't get it */ secondary_part2_bad = 1; cant_read_secondary = -1; } else { /* got the 1st extent of secondary AIT into the buffer */ intermed_rc = verify_ait_part2 (fsck_secondary); if (intermed_rc < 0) { /* something fatal */ vsait_rc = intermed_rc; } else if (intermed_rc > 0) { /* secondary table part 2 is bad */ secondary_part2_bad = 1; } else { /* secondary table, part 2 is good */ secondary_part2_good = -1; } } } } else if (secondary_part1_good && (!primary_part2_good) && (!primary_part2_bad)) { /* * secondary part 1 is good and haven't * checked primary part 2 yet */ agg_recptr->inode_stamp = secondary_inode_stamp; intermed_rc = ait_special_read_ext1(fsck_primary); if (intermed_rc != FSCK_OK) { /* didn't get it */ primary_part2_bad = -1; cant_read_primary = -1; } else { /* got the 1st extent of primary AIT into the buffer */ intermed_rc = verify_ait_part2(fsck_primary); if (intermed_rc < 0) { /* something fatal */ vsait_rc = intermed_rc; } else if (intermed_rc > 0) { /* primary table part 2 is bad */ primary_part2_bad = 1; } else { /* primary table, part 2 is good */ primary_part2_good = 1; intermed_rc = ait_special_read_ext1 (fsck_secondary); if (intermed_rc == FSCK_OK) { vsait_rc = record_ait_part1_again (fsck_secondary); } else { vsait_rc = FSCK_FAILED_CANTREADAITEXT5; } } } } } if (vsait_rc == FSCK_OK) { if (primary_part1_good && secondary_part2_good) { agg_recptr->primary_ait_4part1 = 1; agg_recptr->primary_ait_4part2 = 0; } else if (secondary_part1_good && primary_part2_good) { agg_recptr->primary_ait_4part1 = 0; agg_recptr->primary_ait_4part2 = 1; } else { /* either both have bad part 1 or both have bad part 2 */ vsait_rc = FSCK_FAILED_BOTHAITBAD; } } } if (vsait_rc == FSCK_OK) { /* * get a record as placeholder for the reserved * aggregate inode */ vsait_rc = get_inorecptr(aggregate_inode, alloc_ifnull, 0, &inorecptr); if ((vsait_rc == FSCK_OK) && (inorecptr == NULL)) { vsait_rc = FSCK_INTERNAL_ERROR_36; fsck_send_msg(fsck_INTERNALERROR, vsait_rc, 0, 0, 0); } else if (vsait_rc == FSCK_OK) { /* got the record */ inorecptr->inode_type = metadata_inode; inorecptr->in_use = 1; } } else { if (cant_read_primary && cant_read_secondary) { /* this is fatal */ vsait_rc = FSCK_FAILED_CANTREADAITS; } } /* * Deal with the Aggregate Inode Map (and Table) not chosen * * If we're processing read-only and the primary versions are * ok, we need to verify that the secondary versions are * correctly redundant to the primary versions. */ if (vsait_rc == FSCK_OK) { /* a table is chosen */ if (agg_recptr->processing_readwrite) { /* * have write access so we'll be refreshing * the redundant version later on -- for now * just reserve the blocks for it. */ vsait_rc = record_other_ait(); } else { /* processing read-only */ if (primary_part1_good && primary_part2_good) { /* * need to verify that the secondary table and * map are correct redundant copies of the * primary table and map. */ vsait_rc = AIS_redundancy_check(); } else { /* either part1 or part2 of primary are invalid */ agg_recptr->ag_dirty = 1; } if (vsait_rc == FSCK_OK) { /* if it isn't correct a message has * been issued. Record the blocks they * way that we were unable to record the * occupy to avoid misleading error messages * later when we verify the block allocation * map. */ vsait_rc = record_other_ait(); } } } /* * report problems detected (if any) */ if (cant_read_primary) { fsck_send_msg(fsck_CANTREADAITP); } else if (primary_part1_bad || primary_part2_bad) { fsck_send_msg(fsck_ERRORSINAITP); } if (cant_read_secondary) { fsck_send_msg(fsck_CANTREADAITS); } else if (secondary_part1_bad || secondary_part2_bad) { fsck_send_msg(fsck_ERRORSINAITS); } if (cant_read_primary && cant_read_secondary) { agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_CANTCONTINUE); } else if (primary_part1_bad && secondary_part1_bad) { agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_CANTCONTINUE); } else if (primary_part2_bad && secondary_part2_bad) { agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_CANTCONTINUE); } return (vsait_rc); } /***************************************************************************** * NAME: validate_super * * FUNCTION: This routine validates the JFS superblock currently in the * buffer. If any problem is detected, the which_superblock * input parm is used to tailor the message issued to notify * the user. * * PARAMETERS: * which_super - input - specifies the superblock which is in the * buffer { fsck_primary | fsck_secondary } * * RETURNS: * success: FSCK_OK * failure: something else */ int validate_super(int which_super) { int vs_rc = 0; /* assume the superblock is ok */ int64_t bytes_on_device; int64_t agg_blks_in_aggreg = 0, agg_blks_on_device = 0, dev_blks_on_device; int64_t fsck_start_from_pxd, fsck_blkmap_start_blks; uint32_t fsck_length_from_pxd, fsck_blkmap_size_blks, fsck_blkmap_size_pages; int64_t jlog_start_from_pxd; uint32_t jlog_length_from_pxd; int32_t agl2size; uint32_t expected_flag = JFS_GROUPCOMMIT; uint32_t agsize; int bad_bsize = 0; if (memcmp(sb_ptr->s_magic, JFS_MAGIC, sizeof (sb_ptr->s_magic)) != 0) { vs_rc = FSCK_BADSBMGC; fsck_send_msg(fsck_BADSBMGC, fsck_ref_msg(which_super)); } else if (sb_ptr->s_version > JFS_VERSION) { vs_rc = FSCK_BADSBVRSN; fsck_send_msg(fsck_BADSBVRSN, fsck_ref_msg(which_super)); } else { /* the magic number and version number are correct so it * probably is a JFS superblock with the format we are expecting */ /* get physical device size */ ujfs_get_dev_size(Dev_IOPort, &bytes_on_device); dev_blks_on_device = bytes_on_device / Dev_blksize; if (sb_ptr->s_pbsize != Dev_blksize) { vs_rc = FSCK_BADSBOTHR1; fsck_send_msg(fsck_BADSBOTHR, "1", fsck_ref_msg(which_super)); } if (sb_ptr->s_l2pbsize != log2shift(Dev_blksize)) { vs_rc = FSCK_BADSBOTHR2; fsck_send_msg(fsck_BADSBOTHR, "2", fsck_ref_msg(which_super)); } if (!inrange(sb_ptr->s_bsize, 512, 4096)) { bad_bsize = -1; vs_rc = FSCK_BADSBOTHR3; fsck_send_msg(fsck_BADSBBLSIZ, fsck_ref_msg(which_super)); } else { /* else the filesystem block size is a legal value */ if (sb_ptr->s_l2bsize != log2shift(sb_ptr->s_bsize)) { vs_rc = FSCK_BADSBOTHR4; fsck_send_msg(fsck_BADSBOTHR, "4", fsck_ref_msg(which_super)); } if (sb_ptr->s_l2bfactor != log2shift(sb_ptr->s_bsize / Dev_blksize)) { vs_rc = FSCK_BADSBOTHR5; fsck_send_msg(fsck_BADSBOTHR, "5", fsck_ref_msg(which_super)); } if (sb_ptr->s_bsize < Dev_blksize) { bad_bsize = -1; vs_rc = FSCK_BLSIZLTLVBLSIZ; fsck_send_msg(fsck_BLSIZLTLVBLSIZ, fsck_ref_msg(which_super)); } } if (!bad_bsize) { /* the blocksize looks ok */ agg_blks_on_device = bytes_on_device / sb_ptr->s_bsize; if (sb_ptr->s_size > dev_blks_on_device) { vs_rc = FSCK_BADSBFSSIZ; fsck_send_msg(fsck_BADSBFSSIZ, fsck_ref_msg(which_super)); } #ifdef _JFS_DFS_LFS s_size_inbytes = sb_ptr->s_size * Dev_blksize; sum_inbytes = (int64_t) (sb_ptr->totalUsable * 1024) + (int64_t) (sb_ptr->minFree * 1024); if ((sum_inbytes > s_size_inbytes) || ((s_size_inbytes - sum_inbytes) >= 1024) ) { /* the sum is greater or the difference is at least 1K */ vs_rc = FSCK_BADBLKCTTTL; fsck_send_msg(fsck_BADBLKCTTTL, fsck_ref_msg(which_super)); } #endif /* _JFS_DFS_LFS */ if (((sb_ptr->s_flag & JFS_OS2) == JFS_OS2) || ((sb_ptr->s_flag & JFS_LINUX) == JFS_LINUX)) { /* must have JFS_OS2 or JFS_LINUX */ } else { vs_rc = FSCK_BADSBOTHR6; fsck_send_msg(fsck_BADSBOTHR, "6", fsck_ref_msg(which_super)); } if ((sb_ptr->s_flag & expected_flag) != expected_flag) { vs_rc = FSCK_BADSBOTHR6; fsck_send_msg(fsck_BADSBOTHR, "6", fsck_ref_msg(which_super)); } if (sb_ptr->s_agsize < (1 << L2BPERDMAP)) { vs_rc = FSCK_BADSBAGSIZ; fsck_send_msg(fsck_BADSBAGSIZ, fsck_ref_msg(which_super)); } else { /* else the alloc group size is possibly correct */ agg_blks_in_aggreg = sb_ptr->s_size * sb_ptr->s_pbsize / sb_ptr->s_bsize; agl2size = ujfs_getagl2size(agg_blks_in_aggreg, sb_ptr->s_bsize); agsize = (int64_t) 1 << agl2size; if (sb_ptr->s_agsize != agsize) { vs_rc = FSCK_BADAGFSSIZ; fsck_send_msg(fsck_BADSBAGSIZ, fsck_ref_msg(which_super)); } } } if (!vs_rc) { /* * check out the fsck in-aggregate workspace */ fsck_length_from_pxd = lengthPXD(&(sb_ptr->s_fsckpxd)); fsck_start_from_pxd = addressPXD(&(sb_ptr->s_fsckpxd)); agg_blks_in_aggreg = fsck_length_from_pxd + (sb_ptr->s_size * sb_ptr->s_pbsize / sb_ptr->s_bsize); if (agg_blks_in_aggreg > agg_blks_on_device) { /* wsp length is bad */ vs_rc = FSCK_BADSBFWSL1; fsck_send_msg(fsck_BADSBFWSL1, fsck_ref_msg(which_super)); } else { /* wsp length is plausible */ fsck_blkmap_size_pages = ((agg_blks_in_aggreg + (BITSPERPAGE - 1)) / BITSPERPAGE) + 1 + 50; /* size in aggregate blocks */ fsck_blkmap_size_blks = ((int64_t)fsck_blkmap_size_pages << L2PSIZE) / sb_ptr->s_bsize; /* * aggregate block offset of the fsck * workspace in the aggregate. */ fsck_blkmap_start_blks = agg_blks_in_aggreg - fsck_blkmap_size_blks; if (fsck_length_from_pxd != fsck_blkmap_size_blks) { /* * length of fsck in-aggregate workspace * is incorrect */ vs_rc = FSCK_BADSBFWSL; fsck_send_msg(fsck_BADSBFWSL, fsck_ref_msg(which_super)); } if (fsck_start_from_pxd != fsck_blkmap_start_blks) { /* * address of fsck in-aggregate workspace * is incorrect */ vs_rc = FSCK_BADSBFWSA; fsck_send_msg(fsck_BADSBFWSA, fsck_ref_msg(which_super)); } } } if (!vs_rc) { /* * check out the in-aggregate journal log * * if there is one it starts at the end of the fsck * in-aggregate workspace. */ jlog_length_from_pxd = lengthPXD(&(sb_ptr->s_logpxd)); jlog_start_from_pxd = addressPXD(&(sb_ptr->s_logpxd)); if (jlog_start_from_pxd != 0) { /* there's one in there */ if (jlog_start_from_pxd != agg_blks_in_aggreg) { /* * address of in-aggregate journal log * is incorrect */ vs_rc = FSCK_BADSBFJLA; fsck_send_msg(fsck_BADSBFJLA, fsck_ref_msg(which_super)); } agg_blks_in_aggreg += jlog_length_from_pxd; if (agg_blks_in_aggreg > agg_blks_on_device) { /* log length is bad */ vs_rc = FSCK_BADSBFJLL; fsck_send_msg(fsck_BADSBFJLL, fsck_ref_msg(which_super)); } } } if (!vs_rc) { /* * check out the descriptors for * the Secondary Agg Inode Table and the Secondary Agg Inode Map */ vs_rc = validate_super_2ndaryAI(which_super); } } /* end else the magic number and version number are correct so it * probably is a JFS superblock with the format we are expecting */ return (vs_rc); } /***************************************************************************** * NAME: validate_super_2ndaryAI * * FUNCTION: This routine validates, in the current superblock, the * descriptors for the Secondary Aggregate Inode Table and * the Secondary Aggregate Inode Map. * * If any problem is detected, the which_superblock input parm * is used to tailor the message issued to notify the user. * * PARAMETERS: * which_super - input - specifies the superblock which is in the * buffer { fsck_primary | fsck_secondary } * * RETURNS: * success: FSCK_OK * failure: something else */ int validate_super_2ndaryAI(int which_super) { int vs2AI_rc = 0; /* assume the superblock is ok */ int intermed_rc = 0; int32_t AIM_bytesize, AIT_bytesize, selfIno_bytesize; int32_t expected_AIM_bytesize, expected_AIT_bytesize; int64_t AIM_byte_addr = 0, AIT_byte_addr = 0, fsckwsp_addr = 0; int64_t selfIno_addr = 0, other_sb_AIM_byte_addr = 0, other_sb_AIT_byte_addr = 0; int64_t byte_addr_diff, offset_other_super; struct dinode *AggInodes = NULL; uint32_t bufsize, datasize; xtpage_t *selfIno_xtree; xad_t *selfIno_xad; struct superblock *other_sb_ptr; bufsize = PGSPERIEXT * BYTESPERPAGE; expected_AIM_bytesize = 2 * BYTESPERPAGE; AIM_bytesize = lengthPXD(&(sb_ptr->s_aim2)) * sb_ptr->s_bsize; if (AIM_bytesize != expected_AIM_bytesize) { vs2AI_rc = FSCK_BADSBOTHR7; fsck_send_msg(fsck_BADSBOTHR, "7", fsck_ref_msg(which_super)); goto vs2AI_exit; } /* AIM size ok */ expected_AIT_bytesize = 4 * BYTESPERPAGE; AIT_bytesize = lengthPXD(&(sb_ptr->s_ait2)) * sb_ptr->s_bsize; if (AIT_bytesize != expected_AIT_bytesize) { vs2AI_rc = FSCK_BADSBOTHR8; fsck_send_msg(fsck_BADSBOTHR, "8", fsck_ref_msg(which_super)); goto vs2AI_exit; } /* AIT size ok */ AIM_byte_addr = addressPXD(&(sb_ptr->s_aim2)) * sb_ptr->s_bsize; AIT_byte_addr = addressPXD(&(sb_ptr->s_ait2)) * sb_ptr->s_bsize; byte_addr_diff = AIT_byte_addr - AIM_byte_addr; if (byte_addr_diff != AIM_bytesize) { vs2AI_rc = FSCK_BADSBOTHR9; fsck_send_msg(fsck_BADSBOTHR, "9", fsck_ref_msg(which_super)); goto vs2AI_exit; } /* relative addrs of AIT and AIM are ok */ fsckwsp_addr = addressPXD(&(sb_ptr->s_fsckpxd)) * sb_ptr->s_bsize; byte_addr_diff = fsckwsp_addr - AIT_byte_addr; if (byte_addr_diff <= AIT_bytesize) { vs2AI_rc = FSCK_BADSBOTHR10; fsck_send_msg(fsck_BADSBOTHR, "10", fsck_ref_msg(which_super)); goto vs2AI_exit; } /* relative addrs of fsck workspace and AIT are possible */ /* * Allocate a buffer then read in the alleged secondary * AIT. The self inode should describe the AIM. */ agg_recptr->vlarge_current_use = USED_FOR_SUPER_VALIDATION; AggInodes = (struct dinode *) agg_recptr->vlarge_buf_ptr; intermed_rc = readwrite_device(AIT_byte_addr, bufsize, &datasize, (void *) AggInodes, fsck_READ); if (intermed_rc != FSCK_OK) { vs2AI_rc = FSCK_BADSBOTHR11; fsck_send_msg(fsck_BADSBOTHR, "11", fsck_ref_msg(which_super)); goto vs2AI_exit; } /* alleged secondary AIT is in the buffer */ /* * Check the "data" extent in the self inode in the * alleged Secondary Aggregate Inode Table. * * If it should describes the AIM, all is well. * * If it does NOT describe the AIM, then it might be a bad * superblock, and it might be a bad AIT. Read the other * superblock and compare the AIM and AIT descriptors. * If they match, assume the superblock is ok but the AIT * is bad. * N.B. we can fix a bad AIM and a bad AIT. we cannot do * even continue fsck without a good superblock. */ selfIno_xtree = (xtpage_t *) &(AggInodes[AGGREGATE_I].di_btroot); selfIno_xad = &(selfIno_xtree->xad[XTENTRYSTART]); selfIno_bytesize = lengthXAD(selfIno_xad) * sb_ptr->s_bsize; selfIno_addr = addressXAD(selfIno_xad) * sb_ptr->s_bsize; if ((selfIno_bytesize != AIM_bytesize) || (selfIno_addr != AIM_byte_addr)) { /* inode doesn't describe AIM */ if (which_super == fsck_primary) { offset_other_super = SUPER2_OFF; } else { offset_other_super = SUPER1_OFF; } other_sb_ptr = (struct superblock *) AggInodes; intermed_rc = readwrite_device(offset_other_super, SIZE_OF_SUPER, &datasize, (void *)other_sb_ptr, fsck_READ); if (intermed_rc != FSCK_OK) { vs2AI_rc = FSCK_BADSBOTHR12; fsck_send_msg(fsck_BADSBOTHR, "12", fsck_ref_msg(which_super)); } else { /* other superblock has been read */ other_sb_AIM_byte_addr = addressPXD(&other_sb_ptr->s_aim2) * sb_ptr->s_bsize; other_sb_AIT_byte_addr = addressPXD(&other_sb_ptr->s_ait2) * sb_ptr->s_bsize; if ((AIM_byte_addr != other_sb_AIM_byte_addr) || (AIT_byte_addr != other_sb_AIT_byte_addr)) { vs2AI_rc = FSCK_BADSBOTHR13; fsck_send_msg(fsck_BADSBOTHR, "13", fsck_ref_msg(which_super)); } } } vs2AI_exit: agg_recptr->vlarge_current_use = NOT_CURRENTLY_USED; return (vs2AI_rc); } /***************************************************************************** * NAME: verify_agg_fileset_inode * * FUNCTION: Verify the structures associated with and the content of * the aggregate fileset inode, aggregate inode 16, whose * data is the Fileset Inode Map. * * PARAMETERS: * inoptr - input - pointer to the inode in an fsck buffer * inoidx - input - ordinal number of the inode (i.e., inode number * as an int32_t) * which_ait - input - the Aggregate Inode Table on which to perform * the function. { fsck_primary | fsck_secondary } * msg_info_ptr - input - pointer to a data area with data needed to * issue messages about the inode * * NOTES: o Inode number and inode index are input parameters to facilitate * multiple filesets per aggregate in a later release. * * RETURNS: * success: FSCK_OK * failure: something else */ int verify_agg_fileset_inode(struct dinode *inoptr, uint32_t inoidx, int which_ait, struct fsck_ino_msg_info *msg_info_ptr) { int vafsi_rc = FSCK_OK; int inode_invalid = 0; int ixpxd_unequal = 0; struct fsck_inode_record *inorecptr; int aggregate_inode = -1; int alloc_ifnull = -1; uint32_t unknown_stamp = (uint32_t) (-1); if ((agg_recptr->inode_stamp != unknown_stamp) && (inoptr->di_inostamp != agg_recptr->inode_stamp)) { /* * we got a key from the corresponding AIT but * the one in this inode doesn't match -- so * this is either trashed or residual */ inode_invalid = 1; fsck_send_msg(fsck_BADINOSTAMP, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_fileset != AGGREGATE_I) { /* unexpected fileset # */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "1", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_number != inoidx) { /* unexpected inode # */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "2", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_gen != 1) { /* incorrect generation # */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "2a", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } ixpxd_unequal = memcmp((void *) &(inoptr->di_ixpxd), (void *) &(agg_recptr->ino_ixpxd), sizeof (pxd_t)); if (ixpxd_unequal) { /* incorrect extent descriptor */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "3", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if ((inoptr->di_mode & (IFJOURNAL | IFREG)) != (IFJOURNAL | IFREG)) { /* incorrect mode */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "4", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_nlink != 1) { /* incorrect # of links */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "5", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (!(inoptr->di_dxd.flag & BT_ROOT)) { /* not flagged as B+ Tree root */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "6", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } /* * If any problems detected so far, don't bother trying to validate * the B+ Tree */ if (!inode_invalid) { /* self inode looks ok so far */ vafsi_rc = get_inorecptr(aggregate_inode, alloc_ifnull, inoidx, &inorecptr); if ((vafsi_rc == FSCK_OK) && (inorecptr == NULL)) { vafsi_rc = FSCK_INTERNAL_ERROR_37; fsck_send_msg(fsck_INTERNALERROR, vafsi_rc, 0, 0, 0); } else if (vafsi_rc == FSCK_OK) { vafsi_rc = verify_metadata_data(inoptr, inoidx, inorecptr, msg_info_ptr); if (inorecptr->ignore_alloc_blks || (vafsi_rc != FSCK_OK)) { inode_invalid = -1; } } } /* * wrap it all up for this inode */ if ((inode_invalid) && (vafsi_rc == FSCK_OK)) { vafsi_rc = FSCK_AGGFSINOBAD; } if (inode_invalid) { /* this one's corrupt */ if (which_ait == fsck_primary) { fsck_send_msg(fsck_BADMETAINOP, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } else { fsck_send_msg(fsck_BADMETAINOS, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } return (vafsi_rc); } /***************************************************************************** * NAME: verify_ait_inode * * FUNCTION: Verify the structures associated with and the content of * the aggregate "self" inode, aggregate inode 1, whose * data is the Fileset Inode Map. * * PARAMETERS: * inoptr - input - pointer to the inode in an fsck buffer * which_ait - input - the Aggregate Inode Table on which to perform * the function. { fsck_primary | fsck_secondary } * msg_info_ptr - input - pointer to a data area with data needed to * issue messages about the inode * * RETURNS: * success: FSCK_OK * failure: something else */ int verify_ait_inode(struct dinode *inoptr, int which_ait, struct fsck_ino_msg_info *msg_info_ptr) { int vai_rc = FSCK_OK; int inode_invalid = 0; int ixpxd_unequal = 0; struct fsck_inode_record *inorecptr; int aggregate_inode = -1; int alloc_ifnull = -1; if (inoptr->di_fileset != AGGREGATE_I) { /* unexpected fileset # */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "7", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_fileset != AGGREGATE_I) { /* unexpected fileset # */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "8", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_number != AGGREGATE_I) { /* unexpected inode # */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "9", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_gen != 1) { /* incorrect generation # */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "10", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } ixpxd_unequal = memcmp((void *) &(inoptr->di_ixpxd), (void *) &(agg_recptr->ino_ixpxd), (sizeof (pxd_t))); if (ixpxd_unequal) { /* incorrect extent descriptor */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "11", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if ((inoptr->di_mode & (IFJOURNAL | IFREG)) != (IFJOURNAL | IFREG)) { /* incorrect mode */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "12", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_nlink != 1) { /* incorrect # of links */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "13", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (!(inoptr->di_dxd.flag & BT_ROOT)) { /* not flagged as B+ Tree root */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "14", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } /* * If any problems detected so far, don't bother trying to validate * the B+ Tree */ if (!inode_invalid) { /* self inode looks ok so far */ vai_rc = get_inorecptr(aggregate_inode, alloc_ifnull, AGGREGATE_I, &inorecptr); if ((vai_rc == FSCK_OK) && (inorecptr == NULL)) { vai_rc = FSCK_INTERNAL_ERROR_38; fsck_send_msg(fsck_INTERNALERROR, vai_rc, 0, 0, 0); } else if (vai_rc == FSCK_OK) { vai_rc = verify_metadata_data(inoptr, AGGREGATE_I, inorecptr, msg_info_ptr); if (inorecptr->ignore_alloc_blks || (vai_rc != FSCK_OK)) { inode_invalid = -1; } } } if ((!inode_invalid) && (vai_rc == FSCK_OK)) { agg_recptr->inode_stamp = inoptr->di_inostamp; } /* * wrap it all up for this inode */ if ((inode_invalid) && (vai_rc == FSCK_OK)) { vai_rc = FSCK_AGGAITINOBAD; } if (inode_invalid) { /* this one's corrupt */ if (which_ait == fsck_primary) { fsck_send_msg(fsck_BADMETAINOP, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } else { fsck_send_msg(fsck_BADMETAINOS, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } return (vai_rc); } /***************************************************************************** * NAME: verify_ait_part1 * * FUNCTION: Validate the inodes in "part 1" (inodes 0 through 15) of * the specified Aggregate Inode Table. * * PARAMETERS: * which_ait - input - the Aggregate Inode Table on which to perform * the function. { fsck_primary | fsck_secondary } * * NOTES: o The caller to this routine must ensure that the * calls made by verify_ait_part1 to inode_get() * will not require device I/O. * That is, the caller must ensure that the aggregate * inode extent containing part1 of the target AIT * resides in the fsck inode buffer before calling * this routine. (See inode_get() for more info.) * * RETURNS: * success: FSCK_OK * failure: something else */ int verify_ait_part1(int which_ait) { int vaitp1_rc = FSCK_OK; int intermed_rc = FSCK_OK; struct fsck_ino_msg_info ino_msg_info; struct fsck_ino_msg_info *msg_info_ptr; struct fsck_inode_record *inorecptr; uint32_t ino_idx; struct dinode *ino_ptr; int aggregate_inode = -1; /* going for aggregate inodes only */ int alloc_ifnull = 0; msg_info_ptr = &ino_msg_info; msg_info_ptr->msg_inopfx = fsck_aggr_inode; msg_info_ptr->msg_inotyp = fsck_metadata; /* try for the self inode */ ino_idx = AGGREGATE_I; intermed_rc = inode_get(aggregate_inode, which_ait, ino_idx, &ino_ptr); if (intermed_rc != FSCK_OK) { /* can't get inode */ vaitp1_rc = FSCK_CANTREADSELFINO; goto vaitp1_exit; } /* got aggregate inode */ msg_info_ptr->msg_inonum = AGGREGATE_I; intermed_rc = verify_ait_inode(ino_ptr, which_ait, msg_info_ptr); if (intermed_rc == FSCK_OK) { vaitp1_rc = get_inorecptr(aggregate_inode, alloc_ifnull, ino_idx, &inorecptr); if ((vaitp1_rc == FSCK_OK) && (inorecptr == NULL)) { vaitp1_rc = FSCK_INTERNAL_ERROR_27; fsck_send_msg(fsck_INTERNALERROR, vaitp1_rc, 0, 0, 0); } else if ((vaitp1_rc == FSCK_OK) && (inorecptr->involved_in_dups)) { /* * duplicate allocation(s) detected * while validating the inode */ vaitp1_rc = unrecord_valid_inode(ino_ptr, AGGREGATE_I, inorecptr, msg_info_ptr); if (vaitp1_rc == FSCK_OK) { vaitp1_rc = FSCK_DUPMDBLKREF; } } } if (vaitp1_rc != FSCK_OK) goto vaitp1_exit; if (intermed_rc != FSCK_OK) { /* self inode is bad */ vaitp1_rc = FSCK_SELFINOBAD; goto vaitp1_exit; } /* self inode is good */ /* try for the blockmap inode */ ino_idx = BMAP_I; intermed_rc = inode_get(aggregate_inode, which_ait, ino_idx, &ino_ptr); if (intermed_rc != FSCK_OK) { /* can't get block map inode */ vaitp1_rc = backout_valid_agg_inode(which_ait, AGGREGATE_I, msg_info_ptr); if (vaitp1_rc == FSCK_OK) { vaitp1_rc = FSCK_CANTREADBMINO; } goto vaitp1_exit; } /* got block map inode */ msg_info_ptr->msg_inonum = BMAP_I; intermed_rc = verify_bmap_inode(ino_ptr, which_ait, msg_info_ptr); if (intermed_rc == FSCK_OK) { vaitp1_rc = get_inorecptr(aggregate_inode, alloc_ifnull, BMAP_I, &inorecptr); if ((vaitp1_rc == FSCK_OK) && (inorecptr == NULL)) { vaitp1_rc = FSCK_INTERNAL_ERROR_30; fsck_send_msg(fsck_INTERNALERROR, vaitp1_rc, 0, 0, 0); } else if ((vaitp1_rc == FSCK_OK) && (inorecptr->involved_in_dups)) { /* * duplicate allocation(s) detected * while validating the inode */ vaitp1_rc = unrecord_valid_inode(ino_ptr, BMAP_I, inorecptr, msg_info_ptr); if (vaitp1_rc == FSCK_OK) { vaitp1_rc = FSCK_DUPMDBLKREF; } } } if ((intermed_rc != FSCK_OK) && (vaitp1_rc == FSCK_OK)) { /* block map inode is bad */ msg_info_ptr->msg_inonum = AGGREGATE_I; vaitp1_rc = backout_valid_agg_inode(which_ait, AGGREGATE_I, msg_info_ptr); if (vaitp1_rc == FSCK_OK) { vaitp1_rc = FSCK_BMINOBAD; } goto vaitp1_exit; } if (vaitp1_rc != FSCK_OK) goto vaitp1_exit; /* block map inode is good */ /* try for the journal inode */ ino_idx = LOG_I; intermed_rc = inode_get(aggregate_inode, which_ait, ino_idx, &ino_ptr); if (intermed_rc != FSCK_OK) { /* can't get journal inode */ if (vaitp1_rc == FSCK_OK) { msg_info_ptr->msg_inonum = AGGREGATE_I; vaitp1_rc = backout_valid_agg_inode(which_ait, AGGREGATE_I, msg_info_ptr); if (vaitp1_rc == FSCK_OK) { msg_info_ptr->msg_inonum = BMAP_I; vaitp1_rc = backout_valid_agg_inode(which_ait, BMAP_I, msg_info_ptr); if (vaitp1_rc == FSCK_OK) { vaitp1_rc = FSCK_CANTREADLOGINO; } } } goto vaitp1_exit; } /* got journal inode */ msg_info_ptr->msg_inonum = LOG_I; intermed_rc = verify_log_inode(ino_ptr, which_ait, msg_info_ptr); if (intermed_rc == FSCK_OK) { vaitp1_rc = get_inorecptr(aggregate_inode, alloc_ifnull, LOG_I, &inorecptr); if ((vaitp1_rc == FSCK_OK) && (inorecptr == NULL)) { vaitp1_rc = FSCK_INTERNAL_ERROR_31; fsck_send_msg(fsck_INTERNALERROR, vaitp1_rc, 0, 0, 0); } else if ((vaitp1_rc == FSCK_OK) && (inorecptr->involved_in_dups)) { /* * duplicate allocation(s) detected * while validating the inode */ vaitp1_rc = unrecord_valid_inode(ino_ptr, LOG_I, inorecptr, msg_info_ptr); if (vaitp1_rc == FSCK_OK) { vaitp1_rc = FSCK_DUPMDBLKREF; } } } if ((vaitp1_rc == FSCK_OK) && (intermed_rc != FSCK_OK)) { /* journal inode is bad */ msg_info_ptr->msg_inonum = AGGREGATE_I; vaitp1_rc = backout_valid_agg_inode(which_ait, AGGREGATE_I, msg_info_ptr); if (vaitp1_rc == FSCK_OK) { msg_info_ptr->msg_inonum = BMAP_I; vaitp1_rc = backout_valid_agg_inode(which_ait, BMAP_I, msg_info_ptr); } if (vaitp1_rc == FSCK_OK) { vaitp1_rc = FSCK_LOGINOBAD; } goto vaitp1_exit; } /* journal inode is good */ /* try for the bad block inode */ ino_idx = BADBLOCK_I; intermed_rc = inode_get(aggregate_inode, which_ait, ino_idx, &ino_ptr); if (intermed_rc != FSCK_OK) { /* can't get bad block inode */ if (vaitp1_rc == FSCK_OK) { msg_info_ptr->msg_inonum = AGGREGATE_I; vaitp1_rc = backout_valid_agg_inode(which_ait, AGGREGATE_I, msg_info_ptr); if (vaitp1_rc == FSCK_OK) { msg_info_ptr->msg_inonum = BMAP_I; vaitp1_rc = backout_valid_agg_inode(which_ait, BMAP_I, msg_info_ptr); if (vaitp1_rc == FSCK_OK) { msg_info_ptr->msg_inonum = LOG_I; vaitp1_rc = backout_valid_agg_inode(which_ait, LOG_I, msg_info_ptr); if (vaitp1_rc == FSCK_OK) { vaitp1_rc = FSCK_CANTREADBBINO; } } } } goto vaitp1_exit; } /* got bad block inode */ msg_info_ptr->msg_inonum = BADBLOCK_I; intermed_rc = verify_badblk_inode(ino_ptr, which_ait, msg_info_ptr); if (intermed_rc == FSCK_OK) { vaitp1_rc = get_inorecptr(aggregate_inode, alloc_ifnull, BADBLOCK_I, &inorecptr); if ((vaitp1_rc == FSCK_OK) && (inorecptr == NULL)) { vaitp1_rc = FSCK_INTERNAL_ERROR_56; fsck_send_msg(fsck_INTERNALERROR, vaitp1_rc, 0, 0, 0); } else if ((vaitp1_rc == FSCK_OK) && (inorecptr->involved_in_dups)) { /* * duplicate allocation(s) detected * while validating the inode */ vaitp1_rc = unrecord_valid_inode(ino_ptr, BADBLOCK_I, inorecptr, msg_info_ptr); if (vaitp1_rc == FSCK_OK) { vaitp1_rc = FSCK_DUPMDBLKREF; } } } if ((vaitp1_rc == FSCK_OK) && (intermed_rc != FSCK_OK)) { /* bad block inode is bad */ msg_info_ptr->msg_inonum = AGGREGATE_I; vaitp1_rc = backout_valid_agg_inode(which_ait, AGGREGATE_I, msg_info_ptr); if (vaitp1_rc == FSCK_OK) { msg_info_ptr->msg_inonum = BMAP_I; vaitp1_rc = backout_valid_agg_inode(which_ait, BMAP_I, msg_info_ptr); if (vaitp1_rc == FSCK_OK) { msg_info_ptr->msg_inonum = LOG_I; vaitp1_rc = backout_valid_agg_inode(which_ait, LOG_I, msg_info_ptr); if (vaitp1_rc == FSCK_OK) { vaitp1_rc = FSCK_BBINOBAD; } } } } vaitp1_exit: return (vaitp1_rc); } /***************************************************************************** * NAME: verify_ait_part2 * * FUNCTION: Validate the inodes in "part 2" (inodes 16 through 31) of * the specified Aggregate Inode Table. * * PARAMETERS: * which_ait - input - the Aggregate Inode Table on which to perform * the function. { fsck_primary | fsck_secondary } * * NOTES: o The caller to this routine must ensure that the * calls made by verify_ait_part2 to inode_get() * will not require device I/O. * That is, the caller must ensure that the aggregate * inode extent containing part1 of the target AIT * resides in the fsck inode buffer before calling * this routine. (See inode_get() for more info.) * * RETURNS: * success: FSCK_OK * failure: something else */ int verify_ait_part2(int which_ait) { int vaitp2_rc = FSCK_OK; int intermed_rc = FSCK_OK; struct fsck_ino_msg_info ino_msg_info; struct fsck_ino_msg_info *msg_info_ptr; struct fsck_inode_record *inorecptr; uint32_t ino_idx; struct dinode *ino_ptr; int aggregate_inode = -1; /* going for aggregate inodes only */ int alloc_ifnull = 0; msg_info_ptr = &ino_msg_info; msg_info_ptr->msg_inopfx = fsck_aggr_inode; msg_info_ptr->msg_inotyp = fsck_metadata; /* * In release 1 there is always exactly 1 fileset, described * by aggregate inode FILESYSTEM_I */ /* read the aggregate inode */ ino_idx = FILESYSTEM_I; intermed_rc = inode_get(aggregate_inode, which_ait, ino_idx, &ino_ptr); if (intermed_rc != FSCK_OK) { /* can't get the inode */ vaitp2_rc = FSCK_CANTREADAGGFSINO; } else { /* else got aggregate inode */ msg_info_ptr->msg_inonum = FILESYSTEM_I; vaitp2_rc = verify_agg_fileset_inode(ino_ptr, ino_idx, which_ait, msg_info_ptr); if (vaitp2_rc == FSCK_OK) { vaitp2_rc = get_inorecptr(aggregate_inode, alloc_ifnull, FILESYSTEM_I, &inorecptr); if ((vaitp2_rc == FSCK_OK) && (inorecptr == NULL)) { vaitp2_rc = FSCK_INTERNAL_ERROR_32; fsck_send_msg(fsck_INTERNALERROR, vaitp2_rc, 0, 0, 0); } else if ((vaitp2_rc == FSCK_OK) && (inorecptr->involved_in_dups)) { /* * duplicate allocation(s) detected * while validating the inode */ vaitp2_rc = unrecord_valid_inode(ino_ptr, FILESYSTEM_I, inorecptr, msg_info_ptr); if (vaitp2_rc == FSCK_OK) { vaitp2_rc = FSCK_DUPMDBLKREF; } } } } return (vaitp2_rc); } /***************************************************************************** * NAME: verify_badblk_inode * * FUNCTION: Verify the structures associated with and the content of * the aggregate bad block inode, aggregate inode 4, whose * data is the collection of bad blocks detected in the * aggregate during mkfs processing. * * PARAMETERS: * inoptr - input - pointer to the inode in an fsck buffer * which_ait - input - the Aggregate Inode Table on which to perform * the function. { fsck_primary | fsck_secondary } * msg_info_ptr - input - pointer to a data area with data needed to * issue messages about the inode * * RETURNS: * success: FSCK_OK * failure: something else */ int verify_badblk_inode(struct dinode *inoptr, int which_ait, struct fsck_ino_msg_info *msg_info_ptr) { int vbbi_rc = FSCK_OK; int inode_invalid = 0; int ixpxd_unequal = 0; struct fsck_inode_record *inorecptr; int aggregate_inode = -1; int alloc_ifnull = -1; if (inoptr->di_inostamp != agg_recptr->inode_stamp) { /* * doesn't match the key -- so * this is either trashed or residual */ inode_invalid = 1; fsck_send_msg(fsck_BADINOSTAMP, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_fileset != AGGREGATE_I) { /* unexpected fileset # */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "15", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_number != BADBLOCK_I) { /* unexpected inode # */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "16", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_gen != 1) { /* incorrect generation # */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "17", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } ixpxd_unequal = memcmp((void *) &(inoptr->di_ixpxd), (void *) &(agg_recptr->ino_ixpxd), (sizeof (pxd_t))); if (ixpxd_unequal) { /* incorrect extent descriptor */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "18", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if ((inoptr->di_mode & (IFJOURNAL | IFREG | ISPARSE)) != (IFJOURNAL | IFREG | ISPARSE)) { inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "19", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_nlink != 1) { /* incorrect # of links */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "20", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (!(inoptr->di_dxd.flag & BT_ROOT)) { /* not flagged as B+ Tree root */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "21", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } /* * If any problems detected so far, don't bother trying to validate * the B+ Tree */ if (!inode_invalid) { /* self inode looks ok so far */ vbbi_rc = get_inorecptr(aggregate_inode, alloc_ifnull, BADBLOCK_I, &inorecptr); if ((vbbi_rc == FSCK_OK) && (inorecptr == NULL)) { vbbi_rc = FSCK_INTERNAL_ERROR_57; fsck_send_msg(fsck_INTERNALERROR, vbbi_rc, 0, 0, 0); } else if (vbbi_rc == FSCK_OK) { /* no problems so far */ vbbi_rc = verify_metadata_data(inoptr, BADBLOCK_I, inorecptr, msg_info_ptr); if (inorecptr->ignore_alloc_blks || (vbbi_rc != FSCK_OK)) { inode_invalid = -1; } } } /* * wrap it all up for this inode */ if ((inode_invalid) && (vbbi_rc == FSCK_OK)) { vbbi_rc = FSCK_BMINOBAD; } if (inode_invalid) { /* this one's corrupt */ if (which_ait == fsck_primary) { fsck_send_msg(fsck_BADMETAINOP, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } else { fsck_send_msg(fsck_BADMETAINOS, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } return (vbbi_rc); } /***************************************************************************** * NAME: verify_bmap_inode * * FUNCTION: Verify the structures associated with and the content of * the aggregate block map inode, aggregate inode 2, whose * data is the Aggregate Block Allocation Map. * * PARAMETERS: * inoptr - input - pointer to the inode in an fsck buffer * which_ait - input - the Aggregate Inode Table on which to perform * the function. { fsck_primary | fsck_secondary } * msg_info_ptr - input - pointer to a data area with data needed to * issue messages about the inode * * RETURNS: * success: FSCK_OK * failure: something else */ int verify_bmap_inode(struct dinode *inoptr, int which_ait, struct fsck_ino_msg_info *msg_info_ptr) { int vbi_rc = FSCK_OK; int inode_invalid = 0; int ixpxd_unequal = 0; struct fsck_inode_record *inorecptr; int aggregate_inode = -1; int alloc_ifnull = -1; if (inoptr->di_inostamp != agg_recptr->inode_stamp) { /* doesn't match the key -- so this is either trashed or residual */ inode_invalid = 1; fsck_send_msg(fsck_BADINOSTAMP, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_fileset != AGGREGATE_I) { /* unexpected fileset # */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "22", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_number != BMAP_I) { /* unexpected inode # */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "23", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_gen != 1) { /* incorrect generation # */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "24", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } ixpxd_unequal = memcmp((void *) &(inoptr->di_ixpxd), (void *) &(agg_recptr->ino_ixpxd), (sizeof (pxd_t))); if (ixpxd_unequal) { /* incorrect extent descriptor */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "25", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if ((inoptr->di_mode & (IFJOURNAL | IFREG)) != (IFJOURNAL | IFREG)) { inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "26", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_nlink != 1) { /* incorrect # of links */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "27", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (!(inoptr->di_dxd.flag & BT_ROOT)) { /* not flagged as B+ Tree root */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "28", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } /* * If any problems detected so far, don't bother trying to validate * the B+ Tree */ if (!inode_invalid) { /* self inode looks ok so far */ vbi_rc = get_inorecptr(aggregate_inode, alloc_ifnull, BMAP_I, &inorecptr); if ((vbi_rc == FSCK_OK) && (inorecptr == NULL)) { vbi_rc = FSCK_INTERNAL_ERROR_40; fsck_send_msg(fsck_INTERNALERROR, vbi_rc, 0, 0, 0); } else if (vbi_rc == FSCK_OK) { /* no problems so far */ vbi_rc = verify_metadata_data(inoptr, BMAP_I, inorecptr, msg_info_ptr); if (inorecptr->ignore_alloc_blks || (vbi_rc != FSCK_OK)) { inode_invalid = -1; } } } /* * wrap it all up for this inode */ if ((inode_invalid) && (vbi_rc == FSCK_OK)) { vbi_rc = FSCK_BMINOBAD; } if (inode_invalid) { /* this one's corrupt */ if (which_ait == fsck_primary) { fsck_send_msg(fsck_BADMETAINOP, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } else { fsck_send_msg(fsck_BADMETAINOS, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } return (vbi_rc); } /***************************************************************************** * NAME: verify_fs_super_ext * * FUNCTION: Verify the structures associated with and the content of * the fileset super extension inode, fileset inode 1, whose * data is a logical extension of the aggregate fileset inode. * * PARAMETERS: * inoptr - input - pointer to the inode in an fsck buffer * msg_info_ptr - input - pointer to a data area with data needed to * issue messages about the inode * inode_changed - input - pointer to a variable in which to return * !0 if the inode (in the buffer) has been * modified by this routine * 0 if the inode (in the buffer) has not been * modified by this routine * * NOTES: o In release 1 this inode is allocated and initialized but is * not used. * * RETURNS: * success: FSCK_OK * failure: something else */ int verify_fs_super_ext(struct dinode *inoptr, struct fsck_ino_msg_info *msg_info_ptr, int *inode_changed) { int vfse_rc = FSCK_OK; int inode_invalid = 0; int ixpxd_unequal = 0; struct fsck_inode_record *inorecptr; uint32_t inoidx = FILESET_EXT_I; int aggregate_inode = 0; /* this is a fileset inode */ int alloc_ifnull = -1; *inode_changed = 0; /* assume no changes */ if (inoptr->di_inostamp != agg_recptr->inode_stamp) { /* * doesn't match the key -- so * this is either trashed or residual */ inode_invalid = 1; fsck_send_msg(fsck_BADINOSTAMP, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_fileset != FILESYSTEM_I) { /* unexpected fileset # */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "29", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_number != FILESET_EXT_I) { /* unexpected inode # */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "30", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_gen != 1) { /* incorrect generation # */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "30a", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } ixpxd_unequal = memcmp((void *) &(inoptr->di_ixpxd), (void *) &(agg_recptr->ino_ixpxd), sizeof (pxd_t)); if (ixpxd_unequal) { /* incorrect extent descriptor */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "31", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if ((inoptr->di_mode & (IFJOURNAL | IFREG)) != (IFJOURNAL | IFREG)) { inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "32", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_nlink != 1) { /* incorrect # of links */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "33", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (!(inoptr->di_dxd.flag & BT_ROOT)) { /* not flagged as B+ Tree root */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "34", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } /* * If any problems detected so far, don't bother trying to validate * the B+ Tree */ if (!inode_invalid) { /* self inode looks ok so far */ vfse_rc = get_inorecptr(aggregate_inode, alloc_ifnull, inoidx, &inorecptr); if ((vfse_rc == FSCK_OK) && (inorecptr == NULL)) { vfse_rc = FSCK_INTERNAL_ERROR_41; fsck_send_msg(fsck_INTERNALERROR, vfse_rc, 0, 0, 0); } else if (vfse_rc == FSCK_OK) { /* no problems so far */ vfse_rc = verify_metadata_data(inoptr, inoidx, inorecptr, msg_info_ptr); if (inorecptr->ignore_alloc_blks || (vfse_rc != FSCK_OK)) { inode_invalid = -1; vfse_rc = FSCK_OK; } } } /* at the moment it really doesn't matter * what's in this inode...it's here and * reserved for fileset superinode extension, * but isn't being used and so the data * it contains is irrelevant */ inode_invalid = 0; /* * wrap it all up for this inode */ if ((inode_invalid) && (vfse_rc == FSCK_OK)) { vfse_rc = FSCK_FSETEXTBAD; } if (inode_invalid) { /* this one's corrupt */ fsck_send_msg(fsck_BADMETAINOF, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } return (vfse_rc); } /***************************************************************************** * NAME: verify_log_inode * * FUNCTION: Verify the structures associated with and the content of * the aggregate journal inode, aggregate inode 3, whose * data is (or describes) the aggregate's journal, or log, * of transactions. * * PARAMETERS: * inoptr - input - pointer to the inode in an fsck buffer * which_ait - input - the Aggregate Inode Table on which to perform * the function. { fsck_primary | fsck_secondary } * msg_info_ptr - input - pointer to a data area with data needed to * issue messages about the inode * * RETURNS: * success: FSCK_OK * failure: something else */ int verify_log_inode(struct dinode *inoptr, int which_ait, struct fsck_ino_msg_info *msg_info_ptr) { int vli_rc = FSCK_OK; int inode_invalid = 0; int ixpxd_unequal = 0; struct fsck_inode_record *inorecptr; int aggregate_inode = -1; int alloc_ifnull = -1; if (inoptr->di_inostamp != agg_recptr->inode_stamp) { /* * doesn't match the key -- so * this is either trashed or residual */ inode_invalid = 1; fsck_send_msg(fsck_BADINOSTAMP, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_fileset != AGGREGATE_I) { /* unexpected fileset # */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "35", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_number != LOG_I) { /* unexpected inode # */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "36", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_gen != 1) { /* incorrect generation # */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "37", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } ixpxd_unequal = memcmp((void *) &(inoptr->di_ixpxd), (void *) &(agg_recptr->ino_ixpxd), (sizeof (pxd_t))); if (ixpxd_unequal) { /* incorrect extent descriptor */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "38", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if ((inoptr->di_mode & (IFJOURNAL | IFREG)) != (IFJOURNAL | IFREG)) { inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "39", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (inoptr->di_nlink != 1) { /* incorrect # of links */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "40", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (!(inoptr->di_dxd.flag & BT_ROOT)) { /* not flagged as B+ Tree root */ inode_invalid = 1; fsck_send_msg(fsck_BADINOOTHR, "41", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } /* * If any problems detected so far, don't bother trying to validate * the B+ Tree */ if (!inode_invalid) { /* log inode looks ok so far */ vli_rc = get_inorecptr(aggregate_inode, alloc_ifnull, LOG_I, &inorecptr); if ((vli_rc == FSCK_OK) && (inorecptr == NULL)) { vli_rc = FSCK_INTERNAL_ERROR_42; fsck_send_msg(fsck_INTERNALERROR, vli_rc, 0, 0, 0); } else if (vli_rc == FSCK_OK) { /* no problems so far */ vli_rc = verify_metadata_data(inoptr, LOG_I, inorecptr, msg_info_ptr); if (inorecptr->ignore_alloc_blks || (vli_rc != FSCK_OK)) { inode_invalid = -1; } } } /* * wrap it all up for this inode */ if ((inode_invalid) && (vli_rc == FSCK_OK)) { vli_rc = FSCK_LOGINOBAD; } if (inode_invalid) { /* this one's corrupt */ if (which_ait == fsck_primary) { fsck_send_msg(fsck_BADMETAINOP, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } else { fsck_send_msg(fsck_BADMETAINOS, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } return (vli_rc); } /***************************************************************************** * NAME: verify_metadata_data * * FUNCTION: Initialize the inode record for and verify the data structures * allocated to a JFS metadata inode. * * PARAMETERS: * inoptr - input - pointer to the inode in an fsck buffer * inoidx - input - inode number of the inode in the buffer * inorecptr - input - pointer to record allocated to describe the inode * msg_info_ptr - input - pointer to a data area with data needed to * issue messages about the inode * * RETURNS: * success: FSCK_OK * failure: something else */ int verify_metadata_data(struct dinode *inoptr, uint32_t inoidx, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr) { int vmd_rc = FSCK_OK; int8_t bad_size = 0; int64_t min_size, max_size; /* * clear the workspace area for the current inode */ memset((void *) (&(agg_recptr->this_inode)), '\0', sizeof (agg_recptr->this_inode)); memcpy((void *) &(agg_recptr->this_inode.eyecatcher), (void *) "thisinod", 8); /* * initialize the inode record for this inode */ inorecptr->in_use = 1; inorecptr->selected_to_rls = 0; inorecptr->crrct_link_count = 0; inorecptr->crrct_prnt_inonum = 0; inorecptr->adj_entries = 0; inorecptr->cant_chkea = 0; inorecptr->clr_ea_fld = 0; inorecptr->clr_acl_fld = 0; inorecptr->inlineea_on = 0; inorecptr->inlineea_off = 0; inorecptr->inline_data_err = 0; inorecptr->ignore_alloc_blks = 0; inorecptr->reconnect = 0; inorecptr->unxpctd_prnts = 0; if (inoidx == BADBLOCK_I) { inorecptr->badblk_inode = 1; } else { inorecptr->badblk_inode = 0; } inorecptr->involved_in_dups = 0; inorecptr->inode_type = metadata_inode; inorecptr->link_count = 0; inorecptr->parent_inonum = 0; inorecptr->ext_rec = NULL; /* * verify the B+ Tree and record the blocks it occupies and * also the blocks it describes. * * (If the tree is corrupt any recorded blocks will be unrecorded * before control is returned.) */ vmd_rc = validate_data(inoptr, inoidx, inorecptr, msg_info_ptr); if ((!inorecptr->selected_to_rls) && (!inorecptr->ignore_alloc_blks)) { /* no problems found in the tree yet */ if (inoptr->di_nblocks != agg_recptr->this_inode.all_blks) { /* number of blocks is wrong. tree must be bad */ #ifdef _JFS_DEBUG printf("bad num blocks: agg ino: %ld(t) " "di_nblocks = %lld(t) " "this_inode.all_blks = %lld(t)\n", inoidx, inoptr->di_nblocks, agg_recptr->this_inode.all_blks); #endif inorecptr->selected_to_rls = 1; inorecptr->ignore_alloc_blks = 1; agg_recptr->corrections_needed = 1; bad_size = -1; } else { /* the data size (in bytes) must not exceed the total size * of the blocks allocated for it and must use at least 1 * byte in the last fsblock allocated for it. */ if (agg_recptr->this_inode.data_size == 0) { min_size = 0; max_size = IDATASIZE; } else { /* blocks are allocated to data */ min_size = agg_recptr->this_inode.data_size - sb_ptr->s_bsize + 1; max_size = agg_recptr->this_inode.data_size; } if ((inoptr->di_size > max_size) || (inoptr->di_size < min_size)) { /* * object size (in bytes) is wrong. * tree must be bad. */ #ifdef _JFS_DEBUG printf("bad object size: agg ino: %ld(t) " "minsize = %lld(t) maxsize = %lld(t) " "di_size = %lld(t)\n", inoidx, min_size, max_size, inoptr->di_size); #endif inorecptr->selected_to_rls = 1; inorecptr->ignore_alloc_blks = 1; agg_recptr->corrections_needed = 1; bad_size = -1; } } } /* * If bad_size is set then we didn't know that * the tree was bad until we looked at the size * fields. This means that the block usage recorded * for this inode has not been backed out yet. */ if (bad_size) { /* tree is bad by implication */ /* * remove traces, in the fsck workspace * maps, of the blocks allocated to data * for this inode, whether a single * extent or a B+ Tree */ process_valid_data(inoptr, inoidx, inorecptr, msg_info_ptr, FSCK_UNRECORD); } return (vmd_rc); } /***************************************************************************** * NAME: verify_repair_fs_rootdir * * FUNCTION: Verify the structures associated with and the content of * the fileset root directory inode, fileset inode 2, whose * leaves contain the entries in the root directory. If any * problems are detected then, with the caller's permission, * correct (or reinitialize) the inode. * * PARAMETERS: * inoptr - input - pointer to the inode in an fsck buffer * msg_info_ptr - input - pointer to a data area with data needed to * issue messages about the inode * inode_changed - input - pointer to a variable in which to return * !0 if the inode (in the buffer) has been * modified by this routine * 0 if the inode (in the buffer) has not been * modified by this routine * * RETURNS: * success: FSCK_OK * failure: something else */ int verify_repair_fs_rootdir(struct dinode *inoptr, struct fsck_ino_msg_info *msg_info_ptr, int *inode_changed) { int vrfr_rc = FSCK_OK; int intermed_rc; int bad_root_format = 0; int bad_root_data_format = 0; int ixpxd_unequal = 0; int inode_tree_changed = 0; mode_t expected_mode; struct fsck_inode_record *inorecptr; uint32_t inoidx = ROOT_I; int aggregate_inode = 0; int alloc_ifnull = -1; int8_t bad_size = 0; int64_t max_size; *inode_changed = 0; /* set mode to this function now, synch up with mkfs and jfs as needed */ expected_mode = IFJOURNAL | IFDIR | IREAD | IWRITE | IEXEC; ixpxd_unequal = memcmp((void *)&(inoptr->di_ixpxd), (void *)&(agg_recptr->ino_ixpxd), (sizeof (pxd_t))); vrfr_rc = get_inorecptr(aggregate_inode, alloc_ifnull, ROOT_I, &inorecptr); if (vrfr_rc != FSCK_OK) goto vrfr_set_exit; /* got an inode record */ if ((inoptr->di_inostamp != agg_recptr->inode_stamp) || /* bad stamp or */ (inoptr->di_fileset != FILESYSTEM_I) || /* unexpected fileset # or */ (inoptr->di_number != ROOT_I) || /* unexpected inode # or */ (inoptr->di_gen != 1) || /* unexpected generation # or */ (ixpxd_unequal) /* incorrect extent descriptor */ ) { /* inode is not allocated */ bad_root_format = -1; fsck_send_msg(fsck_RIUNALLOC); if (agg_recptr->processing_readwrite) { /* we can fix this */ /* * If we get this far, the inode is allocated physically, * just isn't in use */ memset(inoptr, 0, sizeof (struct dinode)); inoptr->di_inostamp = agg_recptr->inode_stamp; inoptr->di_fileset = FILESYSTEM_I; inoptr->di_number = ROOT_I; inoptr->di_gen = 1; memcpy((void *) &(inoptr->di_ixpxd), (void *) &(agg_recptr->ino_ixpxd), sizeof (pxd_t)); inoptr->di_mode = expected_mode; /* one from itself to itself as * parent to child and one from * itself to itself as child to parent */ inoptr->di_nlink = 2; inoptr->di_atime.tv_sec = (uint32_t) time(NULL); inoptr->di_ctime.tv_sec = inoptr->di_atime.tv_sec; inoptr->di_mtime.tv_sec = inoptr->di_atime.tv_sec; inoptr->di_otime.tv_sec = inoptr->di_atime.tv_sec; /* * initialize the d-tree */ init_dir_tree((dtroot_t *) &(inoptr->di_btroot)); inoptr->di_next_index = 2; *inode_changed = 1; fsck_send_msg(fsck_ROOTALLOC); } else { /* don't have write access */ vrfr_rc = FSCK_RIUNALLOC; } goto vrfr_set_exit; } /* inode is allocated */ if ((inoptr->di_mode & expected_mode) != expected_mode) { /* wrong type */ bad_root_format = -1; fsck_send_msg(fsck_RINOTDIR); if (agg_recptr->processing_readwrite) { /* we can fix this */ /* * If this is the root directory with a bad value * in the mode field, * then below we'll find the B+ Tree is a valid directory * tree and keep it. * * Else if it really was commandeered for something else, * * If it was taken for a directory, * then we'll find a valid directory tree and keep it as * the root directory. /lost+found/ will be created * here and probably get very full. * * If it was taken for something else * then we won't find a valid directory tree so we'll * either initialize the tree or else mark the file * system dirty. * * Else (it was trashed or was never initialized) * * we won't find a valid directory tree so we'll either * initialize the tree or else mark the file system dirty. */ inoptr->di_mode = expected_mode; *inode_changed = 1; fsck_send_msg(fsck_ROOTNOWDIR); } else { /* don't have write access */ vrfr_rc = FSCK_RINOTDIR; } } if (vrfr_rc == FSCK_OK) { /* we've corrected every problem we've seen to this point */ if (inoptr->di_parent != ROOT_I) { /* doesn't link back to itself correctly */ bad_root_format = -1; fsck_send_msg(fsck_RIINCINOREF); if (agg_recptr->processing_readwrite) { /* we can fix this */ inoptr->di_parent = ROOT_I; *inode_changed = 1; fsck_send_msg(fsck_RICRRCTDREF); } else { /* don't have write access */ agg_recptr->ag_dirty = 1; } } } /* * clear the workspace area for the current inode */ memset((void *) (&(agg_recptr->this_inode)), '\0', sizeof(agg_recptr->this_inode)); memcpy((void *) &(agg_recptr->this_inode.eyecatcher), (void *) "thisinod", 8); /* * verify the root inode's extended attributes (if any) * * If a problem is found, the user is notified and EA cleared. */ intermed_rc = validate_EA(inoptr, inoidx, inorecptr, msg_info_ptr); if (inorecptr->clr_ea_fld) { /* the ea isn't valid */ clear_EA_field(inorecptr, inoptr); *inode_changed = 1; } /* * verify the root inode's access control list (if any) * * If a problem is found, the user is notified and ACL cleared. */ intermed_rc = validate_ACL(inoptr, inoidx, inorecptr, msg_info_ptr); if (inorecptr->clr_acl_fld) { /* the ea isn't valid */ clear_ACL_field(inorecptr, inoptr); *inode_changed = 1; } if (vrfr_rc != FSCK_OK) goto vrfr_set_exit; if (!(inoptr->di_dxd.flag & BT_ROOT)) { /* not a B+ Tree root */ bad_root_data_format = -1; if (agg_recptr->processing_readwrite) { /* we can fix this */ vrfr_rc = rootdir_tree_bad(inoptr, &inode_tree_changed); if (inode_tree_changed) { *inode_changed = 1; } } else { /* don't have write access */ vrfr_rc = FSCK_RIDATAERROR; } goto vrfr_set_exit; } /* the tree looks ok from here... */ /* * check the dtree rooted in the inode */ /* * verify the B+ Tree and the directory entries * contained in its leaf nodes. record the blocks * it occupies. */ intermed_rc = validate_dir_data(inoptr, inoidx, inorecptr,msg_info_ptr); if ((!inorecptr->selected_to_rls) && (!inorecptr->ignore_alloc_blks) && (intermed_rc == FSCK_OK)) { /* no problems found in the tree yet */ if (inoptr->di_nblocks != agg_recptr->this_inode.all_blks) { /* * number of blocks is wrong. tree must * be bad */ #ifdef _JFS_DEBUG printf("bad num blocks: fs ino: %ld(t) " "di_nblocks = %lld(t) " "this_inode.all_blks = %lld(t)\n", inoidx, inoptr->di_nblocks, agg_recptr->this_inode.all_blks); #endif bad_size = -1; } else { /* the data size (in bytes) must not exceed the total size * of the blocks allocated for it. * Blocks allocated for directory index table * make minimum size checking inconclusive */ if (agg_recptr->this_inode.data_size == 0) { max_size = IDATASIZE; } else { /* blocks are allocated to data */ max_size = agg_recptr->this_inode.data_size; } if (inoptr->di_size > max_size) { /* * object size (in bytes) is wrong. * tree must be bad. */ #ifdef _JFS_DEBUG printf("bad obj size: fs ino: %ld(t) " "maxsize = %lld(t) di_size = %lld(t)\n", inoidx, max_size, inoptr->di_size); #endif bad_size = -1; } } /* * If bad_size is set then we didn't know that * the tree was bad until we looked at the size * fields. This means that the block usage recorded * for this inode has not been backed out yet. */ if (bad_size) { /* tree is bad by implication */ /* * remove traces, in the fsck workspace * maps, of the blocks allocated to data * for this inode, whether a single * extent or a B+ Tree */ process_valid_dir_data(inoptr, inoidx, inorecptr, msg_info_ptr, FSCK_UNRECORD); bad_root_data_format = -1; if (agg_recptr->processing_readwrite) { /* we can fix this */ vrfr_rc = rootdir_tree_bad(inoptr, &inode_tree_changed); if (inode_tree_changed) { *inode_changed = 1; } } else { /* don't have write access */ vrfr_rc = FSCK_RIBADTREE; } } else { /* things still look ok */ intermed_rc = in_inode_data_check(inorecptr, msg_info_ptr); if (inorecptr->selected_to_rls) { /* nope, it isn't right */ inorecptr->selected_to_rls = 0; /* * remove traces, in the fsck workspace * maps, of the blocks allocated to data * for this inode, whether a single * extent or a B+ Tree */ process_valid_dir_data(inoptr, inoidx, inorecptr,msg_info_ptr, FSCK_UNRECORD); bad_root_data_format = -1; if (agg_recptr->processing_readwrite) { /* we can fix this */ vrfr_rc = rootdir_tree_bad(inoptr, &inode_tree_changed); if (inode_tree_changed) { *inode_changed = 1; } } else { /* don't have write access */ vrfr_rc = FSCK_RIBADTREE; } } if (inorecptr->clr_ea_fld) { clear_EA_field(inorecptr, inoptr); *inode_changed = 1; } if (inorecptr->clr_acl_fld) { clear_ACL_field(inorecptr, inoptr); *inode_changed = 1; } } } else { /* not a good tree */ if (vrfr_rc == FSCK_OK) { /* but nothing fatal */ bad_root_data_format = -1; if (agg_recptr->processing_readwrite) { /* we can fix this */ vrfr_rc = rootdir_tree_bad(inoptr, &inode_tree_changed); if (inode_tree_changed) { *inode_changed = 1; } } else { /* don't have write access */ vrfr_rc = FSCK_RIBADTREE; } } } vrfr_set_exit: if (bad_root_format) { if (agg_recptr->processing_readwrite) { /* we have fixed this */ fsck_send_msg(fsck_WILLFIXRIBADFMT); } else { /* no write access */ fsck_send_msg(fsck_RIBADFMT); if (vrfr_rc != FSCK_OK) { agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_CANTCONTINUE); fsck_send_msg(fsck_ERRORSDETECTED); } } } if (bad_root_data_format) { if (agg_recptr->processing_readwrite) { /* we have fixed this */ fsck_send_msg(fsck_WILLFIXRIBADDATFMT); } else { /* no write access */ fsck_send_msg(fsck_RIBADDATFMT); if (vrfr_rc != FSCK_OK) { agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_CANTCONTINUE); fsck_send_msg(fsck_ERRORSDETECTED); } } } if (vrfr_rc == FSCK_OK) { vrfr_rc = get_inorecptr(aggregate_inode, alloc_ifnull, inoidx, &inorecptr); if ((vrfr_rc == FSCK_OK) && (inorecptr == NULL)) { vrfr_rc = FSCK_INTERNAL_ERROR_33; fsck_send_msg(fsck_INTERNALERROR, vrfr_rc, 0, 0, 0); } else if (vrfr_rc == FSCK_OK) { /* got a record to describe it */ inorecptr->in_use = 1; inorecptr->inode_type = directory_inode; inorecptr->link_count -= inoptr->di_nlink; inorecptr->parent_inonum = ROOT_I; inorecptr->ignore_alloc_blks = 0; } } return (vrfr_rc); } jfsutils-1.1.15.orig/fsck/fsckpfs.c0000644000000000000000000032344011402027704014023 0ustar /* * Copyright (C) International Business Machines Corp., 2000-2004 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include /* defines and includes common among the fsck.jfs modules */ #include "xfsckint.h" #include "xchkdsk.h" #include "jfs_byteorder.h" #include "devices.h" #include "utilsubs.h" /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * superblock buffer pointer * * defined in xchkdsk.c */ extern struct superblock *sb_ptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * fsck aggregate info structure pointer * * defined in xchkdsk.c */ extern struct fsck_agg_record *agg_recptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * For message processing * * defined in xchkdsk.c */ extern char *Vol_Label; /* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV * * The following are internal to this file * */ int imapleaf_get(int64_t, xtpage_t **); int open_device_read(const char *); int open_device_rw(const char *); uint32_t checksum(uint8_t *, uint32_t); /* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV */ /***************************************************************************** * NAME: ait_node_get * * FUNCTION: Read the specified AIT xTree node into the specified buffer * * PARAMETERS: * node_fsblk_offset - input - offset, in aggregate blocks, into the * aggregate, of the xTree node wanted * xtpage_ptr - input - pointer an fsck buffer into which the * xTree node should be read. * * RETURNS: * success: FSCK_OK * failure: something else */ int ait_node_get(int64_t node_fsblk_offset, xtpage_t * xtpage_ptr) { int anodg_rc = FSCK_OK; int64_t node_start_byte; uint32_t bytes_read; node_start_byte = node_fsblk_offset * sb_ptr->s_bsize; if ((agg_recptr->ondev_wsp_fsblk_offset != 0) && (node_fsblk_offset > agg_recptr->ondev_wsp_fsblk_offset)) { /* the offset is beyond the range valid for fileset objects */ /* * This case is not caused by an I/O error, but by * invalid data in an inode. Let the caller handle * the consequences. */ anodg_rc = FSCK_BADREADTARGET2; } else { anodg_rc = readwrite_device(node_start_byte, XTPAGE_SIZE, &(bytes_read), (void *) xtpage_ptr, fsck_READ); if (anodg_rc == FSCK_OK) { /* read appears successful */ if (bytes_read < XTPAGE_SIZE) { /* didn't get the minimum number of bytes */ /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_BADREAD_NODE1, anodg_rc, fsck_READ, (long long) node_start_byte, XTPAGE_SIZE, bytes_read); anodg_rc = FSCK_FAILED_BADREAD_NODE1; } else { /* swap if on big endian machine */ ujfs_swap_xtpage_t(xtpage_ptr); } } else { /* bad return code from read */ /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_READ_NODE, anodg_rc, fsck_READ, (long long) node_start_byte, XTPAGE_SIZE, bytes_read); anodg_rc = FSCK_FAILED_READ_NODE; } } return (anodg_rc); } /***************************************************************************** * NAME: ait_node_put * * FUNCTION: Write the specified buffer into the specified AIT xTree node * * PARAMETERS: * node_fsblk_offset - input - offset, in aggregate blocks, to which * the buffer is to be written * xtpage_ptr - input - pointer to the buffer to write * * RETURNS: * success: FSCK_OK * failure: something else */ int ait_node_put(int64_t node_fsblk_offset, xtpage_t * xtpage_ptr) { int anodp_rc = FSCK_OK; int64_t node_start_byte; uint32_t bytes_written; node_start_byte = node_fsblk_offset * sb_ptr->s_bsize; ujfs_swap_xtpage_t(xtpage_ptr); anodp_rc = readwrite_device(node_start_byte, PSIZE, &bytes_written, (void *) xtpage_ptr, fsck_WRITE); ujfs_swap_xtpage_t(xtpage_ptr); if (anodp_rc == FSCK_OK) { if (bytes_written != PSIZE) { /* didn't write correct number of bytes */ /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 2); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_BADWRITE_FBLKMP, anodp_rc, fsck_WRITE, (long long) node_start_byte, PSIZE, bytes_written); anodp_rc = FSCK_BADWRITE_FBLKMP; } } else { /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 3); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_BADWRITE_FBLKMP, anodp_rc, fsck_WRITE, (long long) node_start_byte, PSIZE, bytes_written); anodp_rc = FSCK_BADWRITE_FBLKMP; } /* end else the write was not successful */ return (anodp_rc); } /***************************************************************************** * NAME: ait_special_read_ext1 * * FUNCTION: Reads the first extent of either the Primary or Secondary * Aggregate Inode Table into the fsck inode buffer. * * PARAMETERS: * which_ait - input - { fsck_primary | fsck_secondary } * * NOTES: This routine is used during the early stages of fsck processing * when the normal mechanisms for reading inodes have not yet been * established. * * This routine may also be used later in fsck processing as a fast * read routine for the inodes in the first extent of the AIT. * * RETURNS: * success: FSCK_OK * failure: something else */ int ait_special_read_ext1(int which_ait) { int aree_rc = FSCK_OK; int intermed_rc = FSCK_OK; int64_t offset_1stext; aree_rc = inodes_flush(); /* * calculate the byte offset of the first extent */ if ((which_ait == fsck_primary)) { offset_1stext = AITBL_OFF; } else { /* must be secondary */ offset_1stext = addressPXD(&(sb_ptr->s_ait2)) * sb_ptr->s_bsize; } if (agg_recptr->ino_buf_agg_offset != offset_1stext) { /* we don't already have the one we want */ intermed_rc = readwrite_device(offset_1stext, INODE_IO_BUFSIZE, &(agg_recptr->ino_buf_data_len), (void *) agg_recptr->ino_buf_ptr, fsck_READ); if (intermed_rc != FSCK_OK) { /* didn't get anything */ aree_rc = FSCK_CANTREADAITEXT1; fsck_send_msg(fsck_CANTREADAITEXT1, fsck_ref_msg(which_ait)); } else { /* got something */ /* swap if on big endian machine */ ujfs_swap_inoext((struct dinode *) agg_recptr-> ino_buf_ptr, GET, sb_ptr->s_flag); agg_recptr->ino_for_aggregate = -1; agg_recptr->ino_which_it = which_ait; agg_recptr->ino_buf_1st_ino = 0; agg_recptr->ino_fsnum = 0; agg_recptr->ino_buf_agg_offset = offset_1stext; PXDaddress(&(agg_recptr->ino_ixpxd), offset_1stext / sb_ptr->s_bsize); PXDlength(&(agg_recptr->ino_ixpxd), INODE_EXTENT_SIZE / sb_ptr->s_bsize); if (agg_recptr->ino_buf_data_len < INODE_EXTENT_SIZE) { /* didn't get enough */ aree_rc = FSCK_CANTREADAITEXT1; fsck_send_msg(fsck_CANTREADEAITEXT1, fsck_ref_msg(which_ait)); } } } return (aree_rc); } /***************************************************************************** * NAME: blkmap_find_bit * * FUNCTION: Calculate the position, in the fsck workspace block map, * of the bit representing the given aggregate block. * * PARAMETERS: * blk_number - input - ordinal number of the aggregate block whose * bit is to be located * page_number - input - pointer to a variable in which to return * the ordinal number of the page, in the fsck * workspace block map, containing the bit * for the given block * byte_offset - input - pointer to a variable in which to return * the ordinal number of the byte, in page_number * page, containing the bit for the given block * mask_ptr - input - pointer to a variable in which to return * a mask to apply to the byte at byte_offset * in order to reference the bit for the given * block * * RETURNS: * success: FSCK_OK * failure: something else */ int blkmap_find_bit(int64_t blk_number, int64_t * page_number, uint32_t * byte_offset, uint32_t * mask_ptr) { int bfb_rc = FSCK_OK; uint64_t remainder; uint32_t bit_position; *page_number = blk_number >> log2BITSPERPAGE; remainder = blk_number - ((*page_number) << log2BITSPERPAGE); *byte_offset = (remainder >> log2BITSPERDWORD) * BYTESPERDWORD; bit_position = remainder - ((*byte_offset) << log2BITSPERBYTE); *mask_ptr = 0x80000000u >> bit_position; return (bfb_rc); } /***************************************************************************** * NAME: blkmap_flush * * FUNCTION: If the current fsck session has write access to the aggregate * and the current block map buffer has been updated since * the most recent read operation, write the buffer contents to * the device. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int blkmap_flush() { int bmpf_rc = FSCK_OK; uint32_t bytes_written; struct fsck_blk_map_page *fsck_bmpt_ptr; if (agg_recptr->blkmp_buf_write) { /* buffer has been updated since most recent write */ /* swap if on big endian machine */ fsck_bmpt_ptr = agg_recptr->blkmp_buf_ptr; swap_multiple(ujfs_swap_fsck_blk_map_page, fsck_bmpt_ptr, 4); bmpf_rc = readwrite_device(agg_recptr->blkmp_agg_offset, agg_recptr->blkmp_buf_data_len, &bytes_written, (void *) agg_recptr->blkmp_buf_ptr, fsck_WRITE); fsck_bmpt_ptr = agg_recptr->blkmp_buf_ptr; swap_multiple(ujfs_swap_fsck_blk_map_page, fsck_bmpt_ptr, 4); if (bmpf_rc == FSCK_OK) { if (bytes_written == agg_recptr->blkmp_buf_data_len) { /* buffer has been written * to the device and won't need to be * written again unless/until the * buffer contents have been altered. */ agg_recptr->blkmp_buf_write = 0; } else { /* didn't write correct number of bytes */ /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 2); /* * message to debugger */ fsck_send_msg(fsck_ERRONWSP, FSCK_FAILED_FBMAP_BADFLUSH, bmpf_rc, fsck_WRITE, (long long) agg_recptr->blkmp_agg_offset, agg_recptr->blkmp_buf_data_len, bytes_written); bmpf_rc = FSCK_FAILED_FBMAP_BADFLUSH; } } else { /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 3); /* * message to debugger */ fsck_send_msg(fsck_ERRONWSP, FSCK_FAILED_FBMAP_FLUSH, bmpf_rc, fsck_WRITE, (long long) agg_recptr->blkmp_agg_offset, agg_recptr->blkmp_buf_data_len, bytes_written); bmpf_rc = FSCK_FAILED_FBMAP_FLUSH; } } return (bmpf_rc); } /***************************************************************************** * NAME: blkmap_get_ctl_page * * FUNCTION: If the current fsck session has write access to the aggregate, * write the contents of the given buffer over the current fsck * fsck workspace block map control page on the device. * * PARAMETERS: * blk_ctlptr - input - pointer to the buffer into the current fsck * workspace block map control page should be read. * * RETURNS: * success: FSCK_OK * failure: something else */ int blkmap_get_ctl_page(struct fsck_blk_map_hdr *blk_ctlptr) { int bmgcp_rc = FSCK_OK; uint32_t bytes_read; if (agg_recptr->processing_readwrite) { /* have write access */ bmgcp_rc = readwrite_device(agg_recptr->ondev_wsp_byte_offset, BYTESPERPAGE, &bytes_read, (void *) agg_recptr->blkmp_ctlptr, fsck_READ); if (bmgcp_rc == FSCK_OK) { /* swap if on big endian machine */ ujfs_swap_fsck_blk_map_hdr(agg_recptr->blkmp_ctlptr); if (bytes_read != (uint32_t) BYTESPERPAGE) { /* didn't read correct number of bytes */ /* * message to debugger */ fsck_send_msg(fsck_ERRONWSP, FSCK_BADREAD_FBLKMP, bmgcp_rc, fsck_READ, (long long) agg_recptr->ondev_wsp_byte_offset, BYTESPERPAGE, bytes_read); bmgcp_rc = FSCK_BADREAD_FBLKMP; } } else { /* * message to debugger */ fsck_send_msg(fsck_ERRONWSP, FSCK_BADREAD_FBLKMP, bmgcp_rc, fsck_READ, (long long) agg_recptr->ondev_wsp_byte_offset, BYTESPERPAGE, bytes_read); bmgcp_rc = FSCK_BADREAD_FBLKMP; } } return (bmgcp_rc); } /***************************************************************************** * NAME: blkmap_get_page * * FUNCTION: Read the requested fsck workspace block map page into and/or * locate the requested fsck workspace block map page in the * fsck block map buffer. * * PARAMETERS: * page_num - input - ordinal number of the fsck workspace * block map page which is needed * addr_page_ptr - input - pointer to a variable in which to return * the address of the page in an fsck buffer * * RETURNS: * success: FSCK_OK * failure: something else */ int blkmap_get_page(int64_t page_num, struct fsck_blk_map_page **addr_page_ptr) { int bgp_rc = FSCK_OK; int64_t page_start_byte, page_end_byte; struct fsck_blk_map_page *fsck_bmpt_ptr; page_start_byte = page_num * BYTESPERPAGE; page_end_byte = page_start_byte + BYTESPERPAGE - 1; if ((page_start_byte >= agg_recptr->blkmp_blkmp_offset) && (page_end_byte <= (agg_recptr->blkmp_blkmp_offset + agg_recptr->blkmp_buf_data_len))) { /* the desired page is already in the buffer */ *addr_page_ptr = (struct fsck_blk_map_page *) ((char *) agg_recptr-> blkmp_buf_ptr + (page_start_byte - agg_recptr-> blkmp_blkmp_offset)); } else { /* else need to read it in from dasd */ if (!agg_recptr->processing_readwrite) { /* this isn't supposed * to happen. If we don't have write access * to the aggregate then we're always supposed * to get a hit in the buffer! */ bgp_rc = FSCK_INTERNAL_ERROR_6; } else { /* we have read/write access */ /* if the buffer has been modified, write it to dasd */ bgp_rc = blkmap_flush(); if (bgp_rc == FSCK_OK) { /* successful write */ agg_recptr->blkmp_blkmp_offset = page_start_byte; /* * The byte offset in the fsck block map plus * one page of control information plus the * aggregate bytes which precede the on-dasd * fsck workspace */ agg_recptr->blkmp_agg_offset = page_start_byte + (BYTESPERPAGE * 1) + agg_recptr->ondev_wsp_byte_offset; bgp_rc = readwrite_device(agg_recptr-> blkmp_agg_offset, agg_recptr-> blkmp_buf_length, &(agg_recptr-> blkmp_buf_data_len), (void *) agg_recptr-> blkmp_buf_ptr, fsck_READ); if (bgp_rc == FSCK_OK) { /* successful read */ /* swap if on big endian machine */ fsck_bmpt_ptr = agg_recptr->blkmp_buf_ptr; swap_multiple (ujfs_swap_fsck_blk_map_page, fsck_bmpt_ptr, 4); if (agg_recptr->blkmp_buf_data_len >= BYTESPERPAGE) { *addr_page_ptr = agg_recptr->blkmp_buf_ptr; } else { /* but didn't get enough to continue */ /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONWSP, FSCK_FAILED_BADREAD_FBLKMP, bgp_rc, fsck_READ, (long long)agg_recptr->blkmp_agg_offset, agg_recptr->blkmp_buf_length, agg_recptr->blkmp_buf_data_len); bgp_rc = FSCK_FAILED_BADREAD_FBLKMP; } } else { /* read failed */ /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONWSP, FSCK_FAILED_READ_FBLKMP, bgp_rc, fsck_READ, (long long)agg_recptr->blkmp_agg_offset, agg_recptr->blkmp_buf_length, agg_recptr->blkmp_buf_data_len); bgp_rc = FSCK_FAILED_READ_FBLKMP; } } } } return (bgp_rc); } /***************************************************************************** * NAME: blkmap_put_ctl_page * * FUNCTION: If the current fsck session has write access to the aggregate, * write the contents of the given buffer over the current fsck * fsck workspace block map control page on the device. * * PARAMETERS: * blk_ctlptr - input - pointer to the buffer which should be written * over the current fsck workspace block map * control page. * * NOTES: Unlike most _put_ routines in this module, blkmap_put_ctl_page * actually writes to the device. This is done because the block * map control page contains state and footprint information which * provide crucial serviceability should the fsck session be * interrupted. * * RETURNS: * success: FSCK_OK * failure: something else */ int blkmap_put_ctl_page(struct fsck_blk_map_hdr *blk_ctlptr) { int bmpcp_rc = FSCK_OK; uint32_t bytes_written; if (agg_recptr->processing_readwrite) { /* have write access */ /* swap if on big endian machine */ ujfs_swap_fsck_blk_map_hdr(agg_recptr->blkmp_ctlptr); bmpcp_rc = readwrite_device(agg_recptr->ondev_wsp_byte_offset, BYTESPERPAGE, &bytes_written, (void *) agg_recptr->blkmp_ctlptr, fsck_WRITE); ujfs_swap_fsck_blk_map_hdr(agg_recptr->blkmp_ctlptr); if (bmpcp_rc == FSCK_OK) { if (bytes_written != (uint32_t) BYTESPERPAGE) { /* didn't write correct number of bytes */ /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 4); /* * message to debugger */ fsck_send_msg(fsck_ERRONWSP, FSCK_FAILED_BADWRITE_FBLKMP, bmpcp_rc, fsck_WRITE, (long long)agg_recptr->ondev_wsp_byte_offset, BYTESPERPAGE, bytes_written); bmpcp_rc = FSCK_FAILED_BADWRITE_FBLKMP; } } else { /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 5); /* * message to debugger */ fsck_send_msg(fsck_ERRONWSP, FSCK_FAILED_WRITE_FBLKMP, bmpcp_rc, fsck_WRITE, (long long)agg_recptr->ondev_wsp_byte_offset, BYTESPERPAGE, bytes_written); bmpcp_rc = FSCK_FAILED_WRITE_FBLKMP; } /* end else the write was not successful */ } return (bmpcp_rc); } /***************************************************************************** * NAME: blkmap_put_page * * FUNCTION: If the current fsck session has write access to the aggregate, * note, in the fsck workspace, that the current fsck workspace * block map buffer has been modified and should be written to * the device in the next flush operation on this buffer. * * PARAMETERS: * page_num - input - ordinal number of the page in the fsck workspace * block map to write from the buffer to the device * * RETURNS: * success: FSCK_OK * failure: something else */ int blkmap_put_page(int64_t page_num) { int bpp_rc = FSCK_OK; if (agg_recptr->processing_readwrite) { agg_recptr->blkmp_buf_write = 1; } return (bpp_rc); } /***************************************************************************** * NAME: blktbl_ctl_page_put * * FUNCTION: If the current fsck session has write access to the aggregate, * note, in the fsck workspace, that the current JFS Block Map * control page buffer has been modified and should be written * to the device in the next flush operation on this buffer. * * PARAMETERS: * ctlpage_ptr - input - the address, in an fsck buffer, of the page * which has been modified. * * RETURNS: * success: FSCK_OK * failure: something else */ int blktbl_ctl_page_put(struct dbmap *ctlpage_ptr) { int bcpp_rc = FSCK_OK; if (agg_recptr->processing_readwrite) { /* swap if on big endian machine */ ujfs_swap_dbmap(ctlpage_ptr); bcpp_rc = mapctl_put((void *) ctlpage_ptr); } return (bcpp_rc); } /***************************************************************************** * NAME: blktbl_dmap_get * * FUNCTION: Read the JFS Block Table dmap page describing the specified * aggregate block into and/or locate the JFS Block Table dmap * locate the requested page describing the specified * aggregate block in the fsck dmap buffer. * * PARAMETERS: * for_block - input - ordinal number of the aggregate block * whose dmap page is needed * addr_dmap_page_ptr - input - pointer to a variable in which to return * the address of the found dmap page in * an fsck buffer * * RETURNS: * success: FSCK_OK * failure: something else */ int blktbl_dmap_get(int64_t for_block, struct dmap **addr_dmap_page_ptr) { int bdg_rc = FSCK_OK; int64_t dmp_logical_fsblk_offset; int64_t dmp_logical_byte_offset; int64_t ext_logical_byte_offset; int64_t ext_byte_offset; int64_t last_in_buffer; struct dinode *bmap_inoptr; xad_t *xad_ptr; int8_t offset_found; int which_it; uint32_t bytes_read; int64_t ext_bytes, ext_bytes_left, offset_into_extent; struct dmap *dmap_t_ptr; dmp_logical_fsblk_offset = BLKTODMAP(for_block, agg_recptr->log2_blksperpg); dmp_logical_byte_offset = dmp_logical_fsblk_offset * sb_ptr->s_bsize; *addr_dmap_page_ptr = NULL; if (dmp_logical_byte_offset >= agg_recptr->bmapdm_logical_offset) { last_in_buffer = agg_recptr->bmapdm_logical_offset + agg_recptr->bmapdm_buf_data_len - 1; if ((dmp_logical_byte_offset + (int64_t) sizeof (struct dmap) - 1) <= last_in_buffer) { /* * the one we want is already in the buffer */ *addr_dmap_page_ptr = (struct dmap *) (agg_recptr->bmapdm_buf_ptr + dmp_logical_byte_offset - agg_recptr->bmapdm_logical_offset); } } if (*addr_dmap_page_ptr != NULL) goto bdg_exit; /* we have to read it in */ /* perform any pending writes */ bdg_rc = blktbl_dmaps_flush(); if (bdg_rc != FSCK_OK) goto bdg_exit; /* flush worked ok */ if (agg_recptr->primary_ait_4part1) { which_it = fsck_primary; } else { which_it = fsck_secondary; } bdg_rc = ait_special_read_ext1(which_it); if (bdg_rc != FSCK_OK) { report_readait_error(bdg_rc, FSCK_FAILED_CANTREADAITEXTF, which_it); bdg_rc = FSCK_FAILED_CANTREADAITEXTF; goto bdg_exit; } /* got the first agg extent */ bmap_inoptr = (struct dinode *)(agg_recptr->ino_buf_ptr + BMAP_I * sizeof (struct dinode)); bdg_rc = xTree_search(bmap_inoptr, dmp_logical_fsblk_offset, &xad_ptr, &offset_found); if (bdg_rc != FSCK_OK) goto bdg_exit; /* nothing extraordinary happened */ if (!offset_found) { bdg_rc = FSCK_INTERNAL_ERROR_51; goto bdg_exit; } /* we have the xad which describes the dmap */ ext_logical_byte_offset = offsetXAD(xad_ptr) * sb_ptr->s_bsize; ext_byte_offset = addressXAD(xad_ptr) * sb_ptr->s_bsize; agg_recptr->bmapdm_agg_offset = ext_byte_offset + dmp_logical_byte_offset - ext_logical_byte_offset; bdg_rc = readwrite_device(agg_recptr->bmapdm_agg_offset, agg_recptr->bmapdm_buf_length, &bytes_read, (void *) agg_recptr->bmapdm_buf_ptr, fsck_READ); if (bdg_rc == FSCK_OK) { /* swap if on big endian machine */ dmap_t_ptr = (struct dmap *)agg_recptr->bmapdm_buf_ptr; swap_multiple(ujfs_swap_dmap, dmap_t_ptr, 4); agg_recptr->bmapdm_logical_offset = dmp_logical_byte_offset; *addr_dmap_page_ptr = (struct dmap *)agg_recptr->bmapdm_buf_ptr; /* * we need to set the buffer data length to the number of * bytes with actual bmap data. That is, we may have read * beyond the end of the extent, and if so, we need to * ignore the tag-along data. */ ext_bytes = (int64_t)lengthXAD(xad_ptr) * sb_ptr->s_bsize; offset_into_extent = dmp_logical_byte_offset - ext_logical_byte_offset; ext_bytes_left = ext_bytes - offset_into_extent; agg_recptr->bmapdm_buf_data_len = MIN(bytes_read, ext_bytes_left); } else { /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_READ_BMPDM, bdg_rc, fsck_READ, (long long)agg_recptr->bmapdm_agg_offset, agg_recptr->bmapdm_buf_length, agg_recptr->bmapdm_buf_data_len); bdg_rc = FSCK_FAILED_READ_BMPDM; } bdg_exit: return (bdg_rc); } /***************************************************************************** * NAME: blktbl_dmap_put * * FUNCTION: If the current fsck session has write access to the aggregate, * note, in the fsck workspace, that the current fsck dmap * buffer has been modified and should be written to the device * in the next flush operation on this buffer. * * PARAMETERS: * dmap_page_ptr - input - address of the dmap page, in the fsck buffer, * which has been modified. * * RETURNS: * success: FSCK_OK * failure: something else */ int blktbl_dmap_put(struct dmap *dmap_page_ptr) { int bdp_rc = FSCK_OK; if (agg_recptr->processing_readwrite) { agg_recptr->bmapdm_buf_write = 1; } return (bdp_rc); } /***************************************************************************** * NAME: blktbl_dmaps_flush * * FUNCTION: If the current fsck session has write access to the aggregate * and the current dmap buffer has been updated since the most * recent read operation, write the buffer contents to the device. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int blktbl_dmaps_flush() { int bdf_rc = FSCK_OK; uint32_t bytes_written; struct dmap *dmap_t_ptr; if (agg_recptr->bmapdm_buf_write) { /* buffer has been updated since * most recent write */ /* swap if on big endian machine */ dmap_t_ptr = (struct dmap *) agg_recptr->bmapdm_buf_ptr; swap_multiple(ujfs_swap_dmap, dmap_t_ptr, 4); bdf_rc = readwrite_device(agg_recptr->bmapdm_agg_offset, agg_recptr->bmapdm_buf_data_len, &bytes_written, (void *) agg_recptr->bmapdm_buf_ptr, fsck_WRITE); dmap_t_ptr = (struct dmap *) agg_recptr->bmapdm_buf_ptr; swap_multiple(ujfs_swap_dmap, dmap_t_ptr, 4); if (bdf_rc == FSCK_OK) { if (bytes_written == agg_recptr->bmapdm_buf_data_len) { /* buffer has been written to * the device and won't need to be * written again unless/until the * buffer contents have been altered again. */ agg_recptr->bmapdm_buf_write = 0; } else { /* didn't write the correct number of bytes */ /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 6); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_BMPDM_BADFLUSH, bdf_rc, fsck_WRITE, (long long) agg_recptr->bmapdm_agg_offset, agg_recptr->bmapdm_buf_data_len, bytes_written); bdf_rc = FSCK_FAILED_BMPDM_BADFLUSH; } } else { /* else the write was not successful */ /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 7); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_BMPDM_FLUSH, bdf_rc, fsck_WRITE, (long long) agg_recptr->bmapdm_agg_offset, agg_recptr->bmapdm_buf_data_len, agg_recptr->bmapdm_buf_data_len, bytes_written); bdf_rc = FSCK_FAILED_BMPDM_FLUSH; } } return (bdf_rc); } /***************************************************************************** * NAME: blktbl_Ln_page_get * * FUNCTION: Read the JFS Block Map page describing the specified aggregate * block at the specified summary level into and/or locate the * locate the requested JFS Block Map page describing the specified * aggregate block at the specified summary level in the * fsck Level n page buffer. * * PARAMETERS: * level - input - Summary level of the page to get * for_block - input - ordinal number of the aggregate block * whose summary page is needed * addr_Ln_page_ptr - input - pointer to a variable in which to return * the address of the requested page in an * fsck buffer * * RETURNS: * success: FSCK_OK * failure: something else */ int blktbl_Ln_page_get(int8_t level, int64_t for_block, struct dmapctl **addr_Ln_page_ptr) { int blpg_rc = FSCK_OK; int64_t Lnpg_logical_fsblk_offset; int64_t Lnpg_logical_byte_offset; int64_t ext_logical_byte_offset; int64_t ext_byte_offset; int64_t last_in_buffer; struct dinode *bmap_inoptr; xad_t *xad_ptr; int8_t offset_found; int which_it; Lnpg_logical_fsblk_offset = BLKTOCTL(for_block, agg_recptr->log2_blksperpg, level); Lnpg_logical_byte_offset = Lnpg_logical_fsblk_offset * sb_ptr->s_bsize; *addr_Ln_page_ptr = NULL; if (Lnpg_logical_byte_offset >= agg_recptr->bmaplv_logical_offset) { last_in_buffer = agg_recptr->bmaplv_logical_offset + agg_recptr->bmaplv_buf_data_len; if ((Lnpg_logical_byte_offset + (int64_t) sizeof (struct dmapctl)) <= last_in_buffer) { /* * the one we want is already in the buffer */ *addr_Ln_page_ptr = (struct dmapctl *) (agg_recptr->bmaplv_buf_ptr + (Lnpg_logical_byte_offset - agg_recptr->bmaplv_logical_offset)); } } if (*addr_Ln_page_ptr != NULL) goto blpg_exit; /* we have to read it in */ /* perform any pending writes */ blpg_rc = blktbl_Ln_pages_flush(); if (blpg_rc != FSCK_OK) goto blpg_exit; /* flush worked ok */ if (agg_recptr->primary_ait_4part1) { which_it = fsck_primary; } else { which_it = fsck_secondary; } blpg_rc = ait_special_read_ext1(which_it); if (blpg_rc != FSCK_OK) { report_readait_error(blpg_rc, FSCK_FAILED_CANTREADAITEXTG, which_it); blpg_rc = FSCK_FAILED_CANTREADAITEXTG; goto blpg_exit; } /* got the first agg extent */ bmap_inoptr = (struct dinode *)(agg_recptr->ino_buf_ptr + BMAP_I * sizeof (struct dinode)); blpg_rc = xTree_search(bmap_inoptr, Lnpg_logical_fsblk_offset, &xad_ptr, &offset_found); if (blpg_rc != FSCK_OK) goto blpg_exit; /* nothing extraordinary happened */ if (!offset_found) { /* didn't find it! */ blpg_rc = FSCK_INTERNAL_ERROR_52; goto blpg_exit; } /* we have the xad which describes the page */ ext_logical_byte_offset = offsetXAD(xad_ptr) * sb_ptr->s_bsize; ext_byte_offset = addressXAD(xad_ptr) * sb_ptr->s_bsize; agg_recptr->bmaplv_agg_offset = ext_byte_offset + Lnpg_logical_byte_offset - ext_logical_byte_offset; blpg_rc = readwrite_device(agg_recptr->bmaplv_agg_offset, agg_recptr->bmaplv_buf_length, &(agg_recptr->bmaplv_buf_data_len), (void *) agg_recptr->bmaplv_buf_ptr, fsck_READ); if (blpg_rc == FSCK_OK) { /* got the page */ /* swap if on big endian machine */ ujfs_swap_dmapctl((struct dmapctl *)agg_recptr->bmaplv_buf_ptr); agg_recptr->bmaplv_current_level = level; agg_recptr->bmaplv_logical_offset = Lnpg_logical_byte_offset; *addr_Ln_page_ptr = (struct dmapctl *) agg_recptr->bmaplv_buf_ptr; } else { /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_READ_BMPLV, blpg_rc, fsck_READ, (long long)agg_recptr->bmaplv_agg_offset, agg_recptr->bmaplv_buf_length, agg_recptr->bmaplv_buf_data_len); blpg_rc = FSCK_FAILED_READ_BMPLV; } blpg_exit: return (blpg_rc); } /***************************************************************************** * NAME: blktbl_Ln_page_put * * FUNCTION: If the current fsck session has write access to the aggregate, * note, in the fsck workspace, that the current fsck Level n * buffer has been modified and should be written to the device * in the next flush operation on this buffer. * * PARAMETERS: * Ln_page_ptr - input - Address, in an fsck buffer, of the block map * summary page which has been modified. * * RETURNS: * success: FSCK_OK * failure: something else */ int blktbl_Ln_page_put(struct dmapctl *Ln_page_ptr) { int blpp_rc = FSCK_OK; if (agg_recptr->processing_readwrite) { agg_recptr->bmaplv_buf_write = 1; } return (blpp_rc); } /***************************************************************************** * NAME: blktbl_Ln_pages_flush * * FUNCTION: If the current fsck session has write access to the aggregate * and the current Level n Page buffer has been updated since * the most recent read operation, write the buffer contents to * the device. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int blktbl_Ln_pages_flush() { int blpf_rc = FSCK_OK; uint32_t bytes_written; if (!agg_recptr->bmaplv_buf_write) goto blpf_exit; /* buffer has been updated since * most recent write */ /* swap if on big endian machine */ ujfs_swap_dmapctl((struct dmapctl *) agg_recptr->bmaplv_buf_ptr); blpf_rc = readwrite_device(agg_recptr->bmaplv_agg_offset, agg_recptr->bmaplv_buf_data_len, &bytes_written, (void *) agg_recptr->bmaplv_buf_ptr, fsck_WRITE); ujfs_swap_dmapctl((struct dmapctl *) agg_recptr->bmaplv_buf_ptr); if (blpf_rc == FSCK_OK) { if (bytes_written == agg_recptr->bmaplv_buf_data_len) { /* buffer has been written to * the device and won't need to be * written again unless/until the * buffer contents have been altered again. */ agg_recptr->bmaplv_buf_write = 0; } else { /* didn't write the correct number of bytes */ /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 8); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_BMPLV_BADFLUSH, blpf_rc, fsck_WRITE, (long long) agg_recptr->bmaplv_agg_offset, agg_recptr->bmaplv_buf_data_len, bytes_written); blpf_rc = FSCK_FAILED_BMPLV_BADFLUSH; } } else { /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 9); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_BMPLV_FLUSH, blpf_rc, fsck_WRITE, (long long) agg_recptr->bmaplv_agg_offset, agg_recptr->bmaplv_buf_data_len, bytes_written); blpf_rc = FSCK_FAILED_BMPLV_FLUSH; } blpf_exit: return (blpf_rc); } /************************************************************************** * NAME: close_volume * * FUNCTION: Flush all data to disk and close the device containing the * aggregate. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int close_volume() { int rc; rc = ujfs_flush_dev(Dev_IOPort); if (fclose(Dev_IOPort)) return ERROR_INVALID_HANDLE; return rc; } /***************************************************************************** * NAME: dnode_get * * FUNCTION: Read the requested dnode page into and/or locate the requested * dnode page in the fsck dnode buffer. * * PARAMETERS: * dnode_fsblk_offset - input - offset, in aggregate blocks, into the * aggregate of the dnode to read * dnode_length - input - number of bytes in the dnode * addr_dtpage_ptr - input - pointer to a variable in which to return * the address of the requested dnode in an * fsck buffer * * RETURNS: * success: FSCK_OK * failure: something else */ int dnode_get(int64_t dnode_fsblk_offset, uint32_t dnode_length, dtpage_t ** addr_dtpage_ptr) { int dnodg_rc = FSCK_OK; int64_t dnode_start_byte, dnode_end_byte; dtpage_t *dtp; dnode_start_byte = dnode_fsblk_offset * sb_ptr->s_bsize; dnode_end_byte = dnode_start_byte + dnode_length - 1; if ((agg_recptr->ondev_wsp_fsblk_offset != 0) && (dnode_fsblk_offset > agg_recptr->ondev_wsp_fsblk_offset)) { /* * the offset is beyond the range * valid for fileset objects */ /* * This case is not caused by an I/O error, but by * invalid data in an inode. Let the caller handle * the consequences. */ dnodg_rc = FSCK_BADREADTARGET; } else if ((dnode_start_byte >= agg_recptr->dnode_agg_offset) && (dnode_end_byte <= (agg_recptr->dnode_agg_offset + agg_recptr->dnode_buf_data_len))) { /* * the target dir node is already in * the buffer */ dtp = *addr_dtpage_ptr = (dtpage_t *) (agg_recptr->dnode_buf_ptr + dnode_start_byte - agg_recptr->dnode_agg_offset); /* swap if on big endian machine */ if (!(dtp->header.flag & BT_SWAPPED)) { ujfs_swap_dtpage_t(dtp, sb_ptr->s_flag); dtp->header.flag |= BT_SWAPPED; } } else { /* else we'll have to read it from the disk */ agg_recptr->dnode_agg_offset = dnode_start_byte; dnodg_rc = readwrite_device(agg_recptr->dnode_agg_offset, agg_recptr->dnode_buf_length, &(agg_recptr->dnode_buf_data_len), (void *) agg_recptr->dnode_buf_ptr, fsck_READ); if (dnodg_rc == FSCK_OK) { /* read appears successful */ if (agg_recptr->dnode_buf_data_len >= dnode_length) { /* * we may not have gotten all we asked for, * but we got enough to cover the dir node * we were after */ dtp = *addr_dtpage_ptr = (dtpage_t *) agg_recptr->dnode_buf_ptr; /* swap if on big endian machine */ ujfs_swap_dtpage_t(dtp, sb_ptr->s_flag); dtp->header.flag |= BT_SWAPPED; } else { /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_BADREAD_DNODE, dnodg_rc, fsck_READ, (long long) agg_recptr->dnode_agg_offset, agg_recptr->dnode_buf_length, agg_recptr->dnode_buf_data_len); dnodg_rc = FSCK_FAILED_BADREAD_DNODE; } } else { /* bad return code from read */ /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_READ_DNODE, dnodg_rc, fsck_READ, (long long) agg_recptr->dnode_agg_offset, agg_recptr->dnode_buf_length, agg_recptr->dnode_buf_data_len); dnodg_rc = FSCK_FAILED_READ_DNODE; } } return (dnodg_rc); } /***************************************************************************** * NAME: ea_get * * FUNCTION: Read the specified Extended Attributes data (ea) into * the specified buffer. * * PARAMETERS: * ea_fsblk_offset - input - offset, in aggregate blocks, into the * aggregate of the ea to read * ea_byte_length - input - length, in bytes, of the ea to read * eabuf_ptr - input - the address (in dynamic storage) of the * buffer into which to read the ea * eabuf_length - input - pointer to a variable in which contains * the length of the buffer at eabuf_ptr * ea_data_length - input - pointer to a variable in which to return * the number of bytes actually read from the * device * ea_agg_offset - input - pointer to a variable in which to return * the offset, in bytes, into the aggregate * of the ea to read * * RETURNS: * success: FSCK_OK * failure: something else */ int ea_get(int64_t ea_fsblk_offset, uint32_t ea_byte_length, char *eabuf_ptr, uint32_t * eabuf_length, uint32_t * ea_data_length, int64_t * ea_agg_offset) { int ea_rc = FSCK_OK; int64_t start_byte; start_byte = ea_fsblk_offset * sb_ptr->s_bsize; ea_rc = readwrite_device(start_byte, ea_byte_length, ea_data_length, (void *) eabuf_ptr, fsck_READ); /* swap if on big endian machine, currently unused */ if (ea_rc == FSCK_OK) { /* read appears successful */ *ea_agg_offset = start_byte; if ((*ea_data_length) < ea_byte_length) { /* we didn't get enough */ *ea_agg_offset = 0; *ea_data_length = 0; ea_rc = FSCK_BADEADESCRIPTOR; } } else { /* bad return code from read */ ea_rc = FSCK_CANTREADEA; } return (ea_rc); } /***************************************************************************** * NAME: fscklog_put_buffer * * FUNCTION: If the current fsck session has write access to the aggregate, * and if the in-aggregate fsck log is not full, write the * contents of the current fscklog buffer into the in-aggregate * fsck log. * * PARAMETERS: none * * NOTES: o Unlike most _put_ routines in this module, _buffer * actually writes to the device. This is done because the fsck * log contains information which provides crucial serviceability * should the fsck session be interrupted. * * o Errors here are recorded in the control page of the fsck * in-aggregate workspace but never affect other fsck processing. * * RETURNS: * success: FSCK_OK * failure: something else */ int fscklog_put_buffer() { int flpb_rc = FSCK_OK; int io_rc = FSCK_OK; uint32_t bytes_written = 0; uint32_t log_bytes_left; int32_t num_log_errors; struct fscklog_error *log_error_recptr; if ((!agg_recptr->fscklog_full) && (agg_recptr->processing_readwrite)) { /* have write access */ /* swap if on big endian machine in proper format */ io_rc = readwrite_device(agg_recptr->fscklog_agg_offset, agg_recptr->fscklog_buf_length, &bytes_written, (void *) agg_recptr->fscklog_buf_ptr, fsck_WRITE); if ((io_rc != FSCK_OK) || (bytes_written != (uint32_t) agg_recptr->fscklog_buf_length)) { /* * write failed or didn't write correct * number of bytes */ /* This prevents infinite recursion */ agg_recptr->fscklog_full = 1; if (agg_recptr->blkmp_ctlptr) { num_log_errors = agg_recptr->blkmp_ctlptr->hdr. num_logwrite_errors; if (num_log_errors < 120) { log_error_recptr = &(agg_recptr->blkmp_ctlptr->hdr. logerr[num_log_errors]); log_error_recptr->err_offset = agg_recptr->fscklog_agg_offset; log_error_recptr->bytes_written = bytes_written; log_error_recptr->io_retcode = io_rc; } agg_recptr->blkmp_ctlptr->hdr. num_logwrite_errors += 1; } /* * message to debugger * * N.B. This is NOT a fatal condition! */ fsck_send_msg(fsck_ERRONLOG, FSCK_BADWRITE_FSCKLOG, io_rc, fsck_WRITE, (long long) agg_recptr->fscklog_agg_offset, agg_recptr->fscklog_buf_length, bytes_written); } } /* * We want to reset the buffer no matter what. * It is useful to refill the buffer even if logging is not * active because it may provide diagnostic information in * a dump. */ agg_recptr->fscklog_agg_offset += agg_recptr->fscklog_buf_length; agg_recptr->fscklog_log_offset += agg_recptr->fscklog_buf_length; agg_recptr->fscklog_buf_data_len = 0; log_bytes_left = (agg_recptr->ondev_fscklog_byte_length / 2) - agg_recptr->fscklog_log_offset; if (log_bytes_left < agg_recptr->fscklog_buf_length) { /* * can't fit another buffer full * into the log */ if (!agg_recptr->initializing_fscklog) { /* this is a false * condition if doing log initialization */ agg_recptr->fscklog_full = -1; agg_recptr->blkmp_ctlptr->hdr.fscklog_full = -1; } } return (flpb_rc); } /***************************************************************************** * NAME: iag_get * * FUNCTION: Read the requested iag into and/or locate the requested iag * in the fsck iag buffer. * * PARAMETERS: * is_aggregate - input - 0 => the iag is owned by the fileset * !0 => the iag is owned by the aggregate * which_it - input - ordinal number of the aggregate inode * representing the inode table to which the * iag belongs. * which_ait - input - the aggregate inode table { fsck_primary | * fsck_secondary } containing the version of * which_it to use for this operation * iag_num - input - ordinal number of the iag needed * addr_iag_ptr - input - pointer to a variable in which to return * the address, in an fsck buffer, of the * requested iag. * * RETURNS: * success: FSCK_OK * failure: something else */ int iag_get(int is_aggregate, int which_it, int which_ait, int32_t iag_num, struct iag **addr_iag_ptr) { int iagg_rc = FSCK_OK; int64_t imap_logical_block, extent_offset; int64_t offset_in_extent = 0; struct dinode *imap_inoptr; xad_t *xad_ptr; int8_t offset_found; int which_agg_inode = 0; *addr_iag_ptr = NULL; if ((agg_recptr->iag_buf_1st_inode == (iag_num << L2INOSPERIAG)) && (agg_recptr->iag_for_aggregate == is_aggregate) && (agg_recptr->iag_which_it == which_it)) { /* * the target iag is already in the buffer */ *addr_iag_ptr = (struct iag *) agg_recptr->iag_buf_ptr; goto iagg_exit; } /* need to get the iag */ /* perform any pending writes */ iagg_rc = iags_flush(); if (iagg_rc != FSCK_OK) goto iagg_exit; /* flush worked ok */ if (is_aggregate) { /* this is an IAG describing aggregate inodes */ if (iag_num < agg_recptr->agg_imap.num_iags) { /* in bounds */ which_agg_inode = AGGREGATE_I; iagg_rc = ait_special_read_ext1(which_ait); if (iagg_rc != FSCK_OK) { /* read ait failed */ report_readait_error(iagg_rc, FSCK_FAILED_CANTREADAITEXTH, which_ait); iagg_rc = FSCK_FAILED_CANTREADAITEXTH; } } else { /* invalid request */ iagg_rc = FSCK_IAGNOOOAGGBOUNDS; } } else { /* an IAG describing fileset inodes */ if (iag_num < agg_recptr->fset_imap.num_iags) { /* in bounds */ which_agg_inode = FILESYSTEM_I; iagg_rc = ait_special_read_ext1(which_ait); if (iagg_rc != FSCK_OK) { /* read ait failed */ report_readait_error(iagg_rc, FSCK_FAILED_CANTREADAITEXTK, which_ait); iagg_rc = FSCK_FAILED_CANTREADAITEXTK; } } else { /* invalid request */ iagg_rc = FSCK_IAGNOOOFSETBOUNDS; } } if (iagg_rc != FSCK_OK) goto iagg_exit; /* got the extent */ imap_inoptr = (struct dinode *)(agg_recptr->ino_buf_ptr + (which_agg_inode * sizeof (struct dinode))); imap_logical_block = IAGTOLBLK(iag_num, agg_recptr->log2_blksperpg); iagg_rc = xTree_search(imap_inoptr, imap_logical_block, &xad_ptr, &offset_found); if (iagg_rc != FSCK_OK) goto iagg_exit; /* nothing extraordinary happened */ if (!offset_found) { iagg_rc = FSCK_INTERNAL_ERROR_50; } else { /* we have the xad which describes the iag */ extent_offset = offsetXAD(xad_ptr); if (extent_offset != imap_logical_block) { offset_in_extent = imap_logical_block - extent_offset; } agg_recptr->iag_agg_offset = sb_ptr->s_bsize * (addressXAD(xad_ptr) + offset_in_extent); iagg_rc = readwrite_device(agg_recptr->iag_agg_offset, agg_recptr->iag_buf_length, &(agg_recptr->iag_buf_data_len), (void *) agg_recptr->iag_buf_ptr, fsck_READ); if (iagg_rc == FSCK_OK) { /* got the iag */ /* swap if on big endian machine */ ujfs_swap_iag((struct iag *)agg_recptr->iag_buf_ptr); agg_recptr->iag_buf_1st_inode = iag_num << L2INOSPERIAG; agg_recptr->iag_fsnum = imap_inoptr->di_fileset; agg_recptr->iag_for_aggregate = is_aggregate; agg_recptr->iag_which_it = which_it; *addr_iag_ptr = (struct iag *)agg_recptr->iag_buf_ptr; } else { /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_READ_IAG, iagg_rc, fsck_READ, (long long)agg_recptr->iag_agg_offset, agg_recptr->iag_buf_length, agg_recptr->iag_buf_data_len); iagg_rc = FSCK_FAILED_READ_IAG; } } iagg_exit: return (iagg_rc); } /***************************************************************************** * NAME: iag_get_first * * FUNCTION: Read the first iag in the specified inode table into and/or * locate the first iag in the specified inode table in the * fsck iag buffer. Set up for sequential access on the iag's * in this table. * * PARAMETERS: * is_aggregate - input - 0 => the iag is owned by the fileset * !0 => the iag is owned by the aggregate * which_it - input - ordinal number of the aggregate inode * representing the inode table to which the * iag belongs. * which_ait - input - the aggregate inode table { fsck_primary | * fsck_secondary } containing the version of * which_it to use for this operation * addr_iag_ptr - input - pointer to a variable in which to return * * RETURNS: * success: FSCK_OK * failure: something else */ int iag_get_first(int is_aggregate, int it_number, int which_ait, struct iag **addr_iag_ptr) { int iaggf_rc = FSCK_OK; struct dinode *imap_inoptr; xad_t *xadptr; int it_tbl_is_agg_owned = -1; /* the table may not describe the * aggregate inodes, but the inode * describing the table is ALWAYS * an aggregate inode */ agg_recptr->fais.this_iagnum = 0; agg_recptr->fais.this_inoidx = 0; /* assume it's not a rootleaf */ agg_recptr->fais.rootleaf_imap = 0; /* * get the first leaf (xtpage) of the imap into the mapleaf buffer * * Note: if the imap B+ Tree has a root-leaf then the * first (and only) leaf is located in the dinode. */ /* * save inode_get from having to read an * iag as an intermediate step. */ iaggf_rc = ait_special_read_ext1(which_ait); if (iaggf_rc != FSCK_OK) { /* read ait failed */ report_readait_error(iaggf_rc, FSCK_FAILED_CANTREADAITEXTJ, which_ait); iaggf_rc = FSCK_FAILED_CANTREADAITEXTJ; } else { /* got the inode extent */ if (!is_aggregate) { /* after the fileset inode table */ if (agg_recptr->fset_imap.imap_is_rootleaf) { /* it's a root-leaf */ agg_recptr->fais.rootleaf_imap = -1; /* read the imap inode into the inode buffer */ iaggf_rc = inode_get(it_tbl_is_agg_owned, which_ait, it_number, &imap_inoptr); if (iaggf_rc != FSCK_OK) { /* something went wrong */ iaggf_rc = FSCK_FAILED_AGFS_READ5; } } } else { /* want the aggregate inode table */ if (agg_recptr->agg_imap.imap_is_rootleaf) { /* it's a rootleaf */ agg_recptr->fais.rootleaf_imap = -1; /* read the imap inode into the inode buffer */ iaggf_rc = inode_get(it_tbl_is_agg_owned, it_number, AGGREGATE_I, &imap_inoptr); if (iaggf_rc != FSCK_OK) { /* something went wrong */ iaggf_rc = FSCK_FAILED_AGFS_READ5; } } } } if ((iaggf_rc == FSCK_OK) && (agg_recptr->fais.rootleaf_imap)) { /* * root-leaf imap and we have the inode */ /* copy the inode into the imap leaf buf */ memcpy((void *) (agg_recptr->mapleaf_buf_ptr), (void *) imap_inoptr, sizeof (struct dinode)); agg_recptr->mapleaf_buf_data_len = 0; agg_recptr->mapleaf_agg_offset = 0; agg_recptr->mapleaf_for_aggregate = is_aggregate; agg_recptr->mapleaf_which_it = it_number; imap_inoptr = (struct dinode *) (agg_recptr->mapleaf_buf_ptr); agg_recptr->fais.this_mapleaf = (xtpage_t *) & (imap_inoptr->di_btroot); } if ((iaggf_rc == FSCK_OK) && (!agg_recptr->fais.rootleaf_imap)) { /* * something below the root */ if (!is_aggregate) { /* after the fileset inode table */ /* get the first leaf into the mapleaf buffer */ iaggf_rc = imapleaf_get(agg_recptr->fset_imap. first_leaf_offset, &(agg_recptr->fais.this_mapleaf)); } else { /* must want the aggregate inode table */ /* get the first leaf into the mapleaf buffer */ iaggf_rc = imapleaf_get(agg_recptr->agg_imap.first_leaf_offset, &(agg_recptr->fais.this_mapleaf)); } } if (iaggf_rc == FSCK_OK) { /* the first imap leaf is in the buf */ /* first in the leaf */ agg_recptr->fais.iagidx_now = XTENTRYSTART; agg_recptr->fais.iagidx_max = agg_recptr->fais.this_mapleaf->header.nextindex - 1; /* * get the first iag of the imap into the iag buffer */ iaggf_rc = iags_flush(); if (iaggf_rc == FSCK_OK) { /* flushed ok */ xadptr = &(agg_recptr->fais.this_mapleaf-> xad[agg_recptr->fais.iagidx_now]); /* * the first iag is preceded by the IT control page. */ agg_recptr->iag_agg_offset = (sb_ptr->s_bsize * addressXAD(xadptr)) + sizeof (struct dinomap); agg_recptr->iag_buf_1st_inode = agg_recptr->fais.this_inoidx; agg_recptr->iag_fsnum = it_number; agg_recptr->iag_for_aggregate = is_aggregate; agg_recptr->iag_fsnum = it_number; iaggf_rc = readwrite_device(agg_recptr->iag_agg_offset, agg_recptr->iag_buf_length, &(agg_recptr-> iag_buf_data_len), (void *) (agg_recptr-> iag_buf_ptr), fsck_READ); /* swap if on big endian machine */ ujfs_swap_iag((struct iag *) agg_recptr->iag_buf_ptr); } } if (iaggf_rc == FSCK_OK) { /* first iag is in iag buffer */ agg_recptr->fais.iagptr = (struct iag *) agg_recptr->iag_buf_ptr; agg_recptr->fais.extidx_now = 0; agg_recptr->fais.extidx_max = EXTSPERIAG - 1; *addr_iag_ptr = agg_recptr->fais.iagptr; } else { /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_BADREAD_IAG, iaggf_rc, fsck_READ, (long long) agg_recptr->iag_agg_offset, agg_recptr->iag_buf_length, agg_recptr->iag_buf_data_len); iaggf_rc = FSCK_FAILED_BADREAD_IAG; } return (iaggf_rc); } /***************************************************************************** * NAME: iag_get_next * * FUNCTION: Read the next iag in the specified inode table into and/or * locate the next iag in the specified inode table in the * fsck iag buffer. * * PARAMETERS: * addr_iag_ptr - input - pointer to a variable in which to return * the address, in an fsck buffer, of the next * iag in the aggregate inode table currently * being traversed. * * RETURNS: * success: FSCK_OK * failure: something else */ int iag_get_next(struct iag **addr_iag_ptr) { int iaggn_rc = FSCK_OK; int8_t iag_found = 0; int8_t end_of_imap = 0; int64_t leaf_byteaddr; xad_t *xadptr; agg_recptr->fais.this_iagnum++; iaggn_rc = iags_flush(); if (iaggn_rc == FSCK_OK) { /* flushed the iags ok */ while ((!iag_found) && (!end_of_imap) && (iaggn_rc == FSCK_OK)) { agg_recptr->fais.iagidx_now++; if (agg_recptr->fais.iagidx_now <= agg_recptr->fais.iagidx_max) { /* * the imap leaf is in the buffer already */ xadptr = &(agg_recptr->fais.this_mapleaf-> xad[agg_recptr->fais.iagidx_now]); agg_recptr->iag_agg_offset = sb_ptr->s_bsize * addressXAD(xadptr); agg_recptr->iag_buf_1st_inode = agg_recptr->fais.this_inoidx; iaggn_rc = readwrite_device(agg_recptr->iag_agg_offset, agg_recptr->iag_buf_length, &(agg_recptr-> iag_buf_data_len), (void *) (agg_recptr-> iag_buf_ptr), fsck_READ); if (iaggn_rc == FSCK_OK) { /* got the iag */ /* swap if on big endian machine */ ujfs_swap_iag((struct iag *) agg_recptr->iag_buf_ptr); agg_recptr->fais.iagptr = (struct iag *) (agg_recptr-> iag_buf_ptr); agg_recptr->fais.extidx_now = 0; agg_recptr->fais.this_inoidx = agg_recptr->fais.this_iagnum * NUM_INODE_PER_IAG; agg_recptr->iag_buf_1st_inode = agg_recptr->fais.this_inoidx; agg_recptr->fais.extidx_max = EXTSPERIAG - 1; iag_found = -1; } else { /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_BADREAD1_IAG, iaggn_rc, fsck_READ, (long long) agg_recptr->iag_agg_offset, agg_recptr->iag_buf_length, agg_recptr->iag_buf_data_len); iaggn_rc = FSCK_FAILED_BADREAD1_IAG; } } else { /* we need to get the next imap leaf (if any) */ if (agg_recptr->fais.rootleaf_imap) { /* * there aren't any more imap leafs */ end_of_imap = -1; } else if (agg_recptr->fais.this_mapleaf-> header.next == ((int64_t) 0)) { /* * there aren't any more imap leafs */ end_of_imap = -1; } else { /* there is another leaf */ leaf_byteaddr = sb_ptr->s_bsize * agg_recptr->fais.this_mapleaf-> header.next; iaggn_rc = imapleaf_get(leaf_byteaddr, &(agg_recptr->fais. this_mapleaf)); if (iaggn_rc == FSCK_OK) { /* got the imap leaf */ agg_recptr->fais.iagidx_now = XTENTRYSTART - 1; agg_recptr->fais.iagidx_max = agg_recptr->fais. this_mapleaf->header. nextindex - 1; } } } } } if (end_of_imap) { /* there aren't any more iags */ agg_recptr->fais.iagptr = NULL; agg_recptr->fais.iagidx_now = -1; } if (iaggn_rc == FSCK_OK) { /* everything worked! */ *addr_iag_ptr = agg_recptr->fais.iagptr; } return (iaggn_rc); } /***************************************************************************** * NAME: iag_put * * FUNCTION: If the current fsck session has write access to the aggregate, * note, in the fsck workspace, that the current iag buffer * has been modified and should be written to the device in the * next flush operation on this buffer. * * PARAMETERS: * iagptr - input - pointer to the iag, in an fsck buffer, which has * been modified. * * RETURNS: * success: FSCK_OK * failure: something else */ int iag_put(struct iag *iagptr) { int iagp_rc = FSCK_OK; if (agg_recptr->processing_readwrite) { /* we have write access */ agg_recptr->iag_buf_write = 1; } return (iagp_rc); } /***************************************************************************** * NAME: iags_flush * * FUNCTION: If the current fsck session has write access to the aggregate * and the current iag buffer has been updated since * the most recent read operation, write the buffer contents to * the device. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int iags_flush() { int iagf_rc = FSCK_OK; uint32_t bytes_written; if (agg_recptr->iag_buf_write) { /* buffer has been updated since * most recent write */ /* swap if on big endian machine */ ujfs_swap_iag((struct iag *) agg_recptr->iag_buf_ptr); iagf_rc = readwrite_device(agg_recptr->iag_agg_offset, agg_recptr->iag_buf_data_len, &bytes_written, (void *) agg_recptr->iag_buf_ptr, fsck_WRITE); ujfs_swap_iag((struct iag *) agg_recptr->iag_buf_ptr); if (iagf_rc == FSCK_OK) { if (bytes_written == agg_recptr->iag_buf_data_len) { /* buffer has been written to * the device and won't need to be * written again unless/until the * buffer contents have been altered again. */ agg_recptr->iag_buf_write = 0; } else { /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 10); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_IAG_BADFLUSH, iagf_rc, fsck_WRITE, (long long) agg_recptr->iag_agg_offset, agg_recptr->iag_buf_data_len, bytes_written); iagf_rc = FSCK_FAILED_IAG_BADFLUSH; } } else { /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 11); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_IAG_FLUSH, iagf_rc, fsck_WRITE, (long long) agg_recptr->iag_agg_offset, agg_recptr->iag_buf_data_len, bytes_written); iagf_rc = FSCK_FAILED_IAG_FLUSH; } } return (iagf_rc); } /***************************************************************************** * NAME: imapleaf_get * * FUNCTION: Read the specified inode map leaf node into and/or * locate the specified inode map leaf node in the * fsck inode map leaf buffer. * * PARAMETERS: * leaf_start_byte - input - offset, in bytes, in the aggregate, of * the needed map leaf node. * addr_leaf_ptr - input - pointer to a variable in which to return * the address of the map leaf in an fsck * buffer. * * RETURNS: * success: FSCK_OK * failure: something else */ int imapleaf_get(int64_t leaf_start_byte, xtpage_t ** addr_leaf_ptr) { int imlfg_rc = FSCK_OK; int64_t leaf_end_byte; xtpage_t *xtpage_t_ptr; leaf_end_byte = leaf_start_byte + sizeof (xtpage_t) - 1; if ((leaf_start_byte >= agg_recptr->mapleaf_agg_offset) && (leaf_end_byte <= (agg_recptr->mapleaf_agg_offset + agg_recptr->mapleaf_buf_data_len))) { /* * the target leaf is already in * the buffer */ *addr_leaf_ptr = (xtpage_t *) (agg_recptr->mapleaf_buf_ptr + leaf_start_byte - agg_recptr->mapleaf_agg_offset); } else { /* else we'll have to read it from the disk */ agg_recptr->mapleaf_agg_offset = leaf_start_byte; imlfg_rc = readwrite_device(agg_recptr->mapleaf_agg_offset, agg_recptr->mapleaf_buf_length, &(agg_recptr->mapleaf_buf_data_len), (void *) agg_recptr-> mapleaf_buf_ptr, fsck_READ); if (imlfg_rc == FSCK_OK) { /* read appears successful */ if (agg_recptr->mapleaf_buf_data_len >= (sizeof (xtpage_t))) { /* * we may not have gotten all we asked for, * but we got enough to cover the node we * were after */ /* swap if on big endian machine */ xtpage_t_ptr = (xtpage_t *) agg_recptr->mapleaf_buf_ptr; swap_multiple(ujfs_swap_xtpage_t, xtpage_t_ptr, 4); *addr_leaf_ptr = (xtpage_t *) agg_recptr->mapleaf_buf_ptr; } else { /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_BADREAD_IMPLF, imlfg_rc, fsck_READ, (long long) agg_recptr->node_agg_offset, agg_recptr->node_buf_length, agg_recptr->node_buf_data_len); imlfg_rc = FSCK_FAILED_BADREAD_IMPLF; } } else { /* bad return code from read */ /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_READ_IMPLF, imlfg_rc, fsck_READ, (long long) agg_recptr->node_agg_offset, agg_recptr->node_buf_length, agg_recptr->node_buf_data_len); imlfg_rc = FSCK_FAILED_READ_IMPLF; } } return (imlfg_rc); } /***************************************************************************** * NAME: inode_get * * FUNCTION: Read the specified inode into and/or located the specified inode * in the fsck inode buffer. * * PARAMETERS: * is_aggregate - input - 0 => the inode is owned by the fileset * !0 => the inode is owned by the aggregate * which_it - input - ordinal number of the aggregate inode * representing the inode table to which the * inode belongs. * ino_idx - input - ordinal number of the inode to read * addr_ino_ptr - input - pointer to a variable in which to return * * RETURNS: * success: FSCK_OK * failure: something else */ int inode_get(int is_aggregate, int it_number, uint32_t ino_idx, struct dinode **addr_ino_ptr) { int inog_rc = FSCK_OK; int which_ait; int32_t iag_num; struct iag *iag_ptr; int32_t iag_extidx; int64_t inoext_fsblk_addr; int64_t inoext_byte_addr; *addr_ino_ptr = NULL; /* * see if the requested inode is already in the buffer */ if ((is_aggregate && agg_recptr->ino_for_aggregate) || (((!is_aggregate) && (!agg_recptr->ino_for_aggregate)) && (it_number == agg_recptr->ino_fsnum))) { /* * buffer contains inodes from the proper table */ if ((ino_idx >= agg_recptr->ino_buf_1st_ino) && (ino_idx <= (agg_recptr->ino_buf_1st_ino + INOSPEREXT - 1))) { /* * the requested inode number is in the * range for the extent in the buffer now */ *addr_ino_ptr = (struct dinode *) ((ino_idx - agg_recptr->ino_buf_1st_ino) * DISIZE + agg_recptr->ino_buf_ptr); } } if (*addr_ino_ptr != NULL) goto inog_exit; /* it isn't in the buffer */ /* handle any pending deferred writes */ inog_rc = inodes_flush(); /* * get the iag describing its extent */ if (inog_rc != FSCK_OK) goto inog_exit; /* flushed cleanly */ if (is_aggregate) { if (ino_idx < FIRST_FILESET_INO) { /* in part 1 of AIT */ if (agg_recptr->primary_ait_4part1) { which_ait = fsck_primary; } else { which_ait = fsck_secondary; } } else { /* in part 2 of AIT */ if (agg_recptr->primary_ait_4part2) { which_ait = fsck_primary; } else { which_ait = fsck_secondary; } } } else { /* fileset inode */ if (agg_recptr->primary_ait_4part2) { which_ait = fsck_primary; } else { which_ait = fsck_secondary; } } /* figure out which IAG describes the * extent containing the requested inode */ iag_num = INOTOIAG(ino_idx); inog_rc = iag_get(is_aggregate, it_number, which_ait, iag_num, &iag_ptr); if (inog_rc != FSCK_OK) goto inog_exit; /* * this is the index into the ixpxd array (in the * iag) for the entry describing the extent with * the desired inode. */ iag_extidx = (ino_idx - agg_recptr->iag_buf_1st_inode) >> L2INOSPEREXT; inoext_fsblk_addr = addressPXD(&(iag_ptr->inoext[iag_extidx])); if (inoext_fsblk_addr == 0) { /* the extent isn't allocated */ inog_rc = FSCK_INOEXTNOTALLOC; goto inog_exit; } /* the inode extent is allocated */ inoext_byte_addr = inoext_fsblk_addr * sb_ptr->s_bsize; inog_rc = readwrite_device(inoext_byte_addr, agg_recptr->ino_buf_length, &(agg_recptr->ino_buf_data_len), (void *)agg_recptr->ino_buf_ptr, fsck_READ); if (inog_rc == FSCK_OK) { agg_recptr->ino_buf_agg_offset = inoext_byte_addr; agg_recptr->ino_buf_1st_ino = (iag_num << L2INOSPERIAG) + (iag_extidx << L2INOSPEREXT); agg_recptr->ino_fsnum = it_number; memcpy((void *)&(agg_recptr->ino_ixpxd), (void *) &(iag_ptr->inoext[iag_extidx]), sizeof (pxd_t)); is_aggregate ? (agg_recptr->ino_for_aggregate = -1) : (agg_recptr->ino_for_aggregate = 0); agg_recptr->ino_which_it = it_number; *addr_ino_ptr = (struct dinode *)((ino_idx - agg_recptr->ino_buf_1st_ino) * DISIZE + agg_recptr->ino_buf_ptr); /* swap if on big endian machine */ ujfs_swap_inoext((struct dinode *)agg_recptr->ino_buf_ptr, GET, sb_ptr->s_flag); } else { /* bad return code from read */ /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_BADREAD_INODE1, inog_rc, fsck_READ, (long long)inoext_byte_addr, agg_recptr->ino_buf_length, agg_recptr->ino_buf_data_len); inog_rc = FSCK_FAILED_BADREAD_INODE1; } inog_exit: return (inog_rc); } /***************************************************************************** * NAME: inode_get_first_fs * * FUNCTION: Read the first inode in the specified fileset into and/or * locate the first inode in the specified fileset in the * fsck inode buffer. * * PARAMETERS: * it_number - input - ordinal number of the aggregate inode * representing the inode table to which the * inode belongs. * ino_idx - input - pointer to a variable in which to return * the ordinal number of the first inode in * use in the aggregate. * addr_ino_ptr - input - pointer to a variable in which to return * the address, in an fsck buffer, of the first * inode now being used in the aggregate. * * RETURNS: * success: FSCK_OK * failure: something else */ int inode_get_first_fs(int it_number, uint32_t * ino_idx, struct dinode **addr_ino_ptr) { int igff_rc = FSCK_OK; int which_ait; int is_aggregate = 0; pxd_t *pxdptr; struct iag *iagptr; if (agg_recptr->primary_ait_4part2) { which_ait = fsck_primary; } else { which_ait = fsck_secondary; } /* * get the first iag of the imap into the iag buffer */ igff_rc = iag_get_first(is_aggregate, it_number, which_ait, &iagptr); if (igff_rc == FSCK_OK) { /* first iag is in iag buffer */ /* * get the first inode extent described by the iag into the inode buf * * note: the very first one must be allocated since it contains * the root directory inode (which has been verified correct) */ igff_rc = inodes_flush(); if (igff_rc == FSCK_OK) { /* flushed ok */ pxdptr = &(agg_recptr->fais.iagptr-> inoext[agg_recptr->fais.extidx_now]); agg_recptr->ino_buf_agg_offset = sb_ptr->s_bsize * addressPXD(pxdptr); agg_recptr->ino_buf_1st_ino = agg_recptr->fais.this_inoidx; agg_recptr->ino_fsnum = it_number; agg_recptr->ino_for_aggregate = is_aggregate; agg_recptr->ino_which_it = it_number; memcpy((void *) &(agg_recptr->ino_ixpxd), (void *) pxdptr, sizeof (pxd_t)); igff_rc = readwrite_device(agg_recptr->ino_buf_agg_offset, agg_recptr->ino_buf_length, &(agg_recptr->ino_buf_data_len), (void *) (agg_recptr->ino_buf_ptr), fsck_READ); /* swap if on big endian machine */ ujfs_swap_inoext((struct dinode *) agg_recptr-> ino_buf_ptr, GET, sb_ptr->s_flag); } } if (igff_rc == FSCK_OK) { /* the first inode extent is in buf */ agg_recptr->fais.extptr = (struct dinode *) (agg_recptr->ino_buf_ptr); /* * FILESET_OBJECT_I is the inode number for the first * fileset inode not reserved for metadata (excepting the * root directory which is handled as a special case) */ agg_recptr->fais.this_inoidx = FILESET_OBJECT_I; agg_recptr->fais.inoidx_now = FILESET_OBJECT_I; agg_recptr->fais.inoidx_max = INOSPEREXT - 1; /* * locate the first (regular fileset object) inode in the inode buf */ agg_recptr->fais.inoptr = (struct dinode *) ((char *) agg_recptr->fais.extptr + (agg_recptr->fais.inoidx_now * DISIZE)); } else { /* bad return code from read */ /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_READ_INODE, igff_rc, fsck_READ, (long long) agg_recptr->ino_buf_agg_offset, agg_recptr->ino_buf_length, agg_recptr->ino_buf_data_len); igff_rc = FSCK_FAILED_READ_INODE; } if (igff_rc == FSCK_OK) { *ino_idx = agg_recptr->fais.this_inoidx; *addr_ino_ptr = agg_recptr->fais.inoptr; } return (igff_rc); } /***************************************************************************** * NAME: inode_get_next * * FUNCTION: Read the next inode in the specified fileset into and/or * locate the next inode in the specified fileset in the * fsck inode buffer. * * PARAMETERS: * ino_idx - input - pointer to a variable in which to return * the ordinal number of the next inode in the * current inode table traversal. * addr_ino_ptr - input - pointer to a variable in which to return * the address, in an fsck buffer, of the next * inode in the current inode table traversal. * * RETURNS: * success: FSCK_OK * failure: something else */ int inode_get_next(uint32_t * ino_idx, struct dinode **addr_ino_ptr) { int ign_rc = FSCK_OK; int8_t ext_found, end_of_fileset; int64_t ext_blkaddr; pxd_t *pxdptr; struct iag *iagptr; /* increment inode ordinal number. If this one * is allocated then it's the one we want */ agg_recptr->fais.this_inoidx++; /* increment index into current extent */ agg_recptr->fais.inoidx_now++; if (agg_recptr->fais.inoidx_now <= agg_recptr->fais.inoidx_max) { /* * the inode is in the buffer already */ agg_recptr->fais.inoptr = (struct dinode *) ((char *) agg_recptr->fais.inoptr + DISIZE); goto ign_set_exit; } /* we need the next allocated inode extent */ ign_rc = inodes_flush(); if (ign_rc != FSCK_OK) goto ign_set_exit; /* flushed inodes ok */ ext_found = 0; end_of_fileset = 0; /* increment index into current iag */ agg_recptr->fais.extidx_now++; while ((!ext_found) && (!end_of_fileset) && (ign_rc == FSCK_OK)) { if (agg_recptr->fais.extidx_now <= agg_recptr->fais.extidx_max) { /* * the iag is in the buffer already */ pxdptr = &(agg_recptr->fais.iagptr->inoext [agg_recptr->fais.extidx_now]); ext_blkaddr = addressPXD(pxdptr); if (ext_blkaddr == 0) { /* this extent isn't allocated */ agg_recptr->fais.extidx_now++; agg_recptr->fais.this_inoidx += INOSPEREXT; } else { /* this extent is allocated */ agg_recptr->ino_buf_agg_offset = sb_ptr->s_bsize * ext_blkaddr; agg_recptr->ino_buf_1st_ino = agg_recptr->fais.this_inoidx; memcpy((void *)&(agg_recptr->ino_ixpxd), (void *) pxdptr, sizeof (pxd_t)); ign_rc = readwrite_device( agg_recptr->ino_buf_agg_offset, agg_recptr->ino_buf_length, &(agg_recptr->ino_buf_data_len), (void *) (agg_recptr->ino_buf_ptr), fsck_READ); if (ign_rc == FSCK_OK) { /* got the extent */ /* swap if on big endian machine */ ujfs_swap_inoext((struct dinode *) agg_recptr->ino_buf_ptr, GET, sb_ptr->s_flag); ext_found = -1; agg_recptr->fais.extptr = (struct dinode *) (agg_recptr->ino_buf_ptr); agg_recptr->fais.inoidx_now = 0; agg_recptr->fais.inoidx_max = INOSPEREXT - 1; ext_found = -1; agg_recptr->fais.inoptr = (struct dinode*) (agg_recptr->ino_buf_ptr); } else { /* bad return code from read */ /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_BADREAD_INODE, ign_rc, fsck_READ, (long long)agg_recptr->ino_buf_agg_offset, agg_recptr->ino_buf_length, agg_recptr->ino_buf_data_len); ign_rc = FSCK_FAILED_BADREAD_INODE; } } } else { /* we need to get the next iag (if any) */ ign_rc = iag_get_next(&iagptr); if ((ign_rc == FSCK_OK) && (iagptr == NULL)) { end_of_fileset = -1; } } } if (end_of_fileset) { /* there aren't any more extents */ agg_recptr->fais.inoptr = NULL; agg_recptr->fais.this_inoidx = -1; } ign_set_exit: if (ign_rc == FSCK_OK) { /* everything worked! */ *ino_idx = agg_recptr->fais.this_inoidx; *addr_ino_ptr = agg_recptr->fais.inoptr; } return (ign_rc); } /***************************************************************************** * NAME: inode_put * * FUNCTION: If the current fsck session has write access to the aggregate, * note, in the fsck workspace, that the current inode buffer * has been modified and should be written to the device in the * next flush operation on this buffer. * * PARAMETERS: * ino_ptr - input - address, in an fsck buffer, of the inode which has * been updated. * * RETURNS: * success: FSCK_OK * failure: something else */ int inode_put(struct dinode *ino_ptr) { int ip_rc = FSCK_OK; if (agg_recptr->processing_readwrite) { /* buffer has been updated and needs to be written to the device */ agg_recptr->ino_buf_write = -1; } return (ip_rc); } /***************************************************************************** * NAME: inodes_flush * * FUNCTION: If the current fsck session has write access to the aggregate * and the current inode buffer has been updated since the most * recent read operation, write the buffer contents to the device. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int inodes_flush() { int inof_rc = FSCK_OK; uint32_t bytes_written; if (agg_recptr->ino_buf_write) { /* buffer has been updated since * most recent write */ /* swap if on big endian machine */ ujfs_swap_inoext((struct dinode *) agg_recptr->ino_buf_ptr, PUT, sb_ptr->s_flag); inof_rc = readwrite_device(agg_recptr->ino_buf_agg_offset, agg_recptr->ino_buf_data_len, &bytes_written, (void *) agg_recptr->ino_buf_ptr, fsck_WRITE); ujfs_swap_inoext((struct dinode *) agg_recptr->ino_buf_ptr, GET, sb_ptr->s_flag); if (inof_rc == FSCK_OK) { if (bytes_written == agg_recptr->ino_buf_data_len) { /* buffer has been written * to the device and won't need to be * written again unless/until the * buffer contents have been altered. */ agg_recptr->ino_buf_write = 0; } else { /* didn't write the correct number of bytes */ /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 12); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_INODE_BADFLUSH, inof_rc, fsck_WRITE, (long long)agg_recptr->ino_buf_agg_offset, agg_recptr->ino_buf_data_len, bytes_written); inof_rc = FSCK_FAILED_INODE_BADFLUSH; } } else { /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 14); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_INODE_FLUSH, inof_rc, fsck_WRITE, (long long) agg_recptr->ino_buf_agg_offset, agg_recptr->ino_buf_data_len, bytes_written); inof_rc = FSCK_FAILED_INODE_FLUSH; } } return (inof_rc); } /***************************************************************************** * NAME: inotbl_get_ctl_page * * FUNCTION: Read the control page for the specified inode table into and/or * locate the control page for the specified inode table in the * fsck inode table control page buffer. * * PARAMETERS: * is_aggregate - input - 0 => the inode table is fileset owned * !0 => the inode table is aggregate owned * addr_ctlpage_ptr - input - pointer to a variable in which to return * the address of the control page in an * fsck buffer * * RETURNS: * success: FSCK_OK * failure: something else */ int inotbl_get_ctl_page(int is_aggregate, struct dinomap **addr_ctlpage_ptr) { int igcp_rc = FSCK_OK; int intermed_rc = FSCK_OK; int64_t offset_ctlpage = 0; int which_it; int which_ait; struct dinode *inoptr; xtpage_t *xtpg_ptr; /* * get the byte offset of the control page */ if (is_aggregate) { /* aggregate inode table wanted */ if (agg_recptr->primary_ait_4part1) { offset_ctlpage = AIMAP_OFF / sb_ptr->s_bsize; } else { offset_ctlpage = addressPXD(&(sb_ptr->s_aim2)); } } else { /* fileset inode table wanted */ which_it = FILESYSTEM_I; if (agg_recptr->primary_ait_4part2) { which_ait = fsck_primary; } else { which_ait = fsck_secondary; } if (agg_recptr->fset_imap.imap_is_rootleaf) { /* root leaf inode */ intermed_rc = ait_special_read_ext1(which_ait); if (intermed_rc != FSCK_OK) { report_readait_error(intermed_rc, FSCK_FAILED_AGFS_READ4, which_ait); igcp_rc = FSCK_FAILED_AGFS_READ4; } else { /* got the agg inode extent */ inoptr = (struct dinode *) (agg_recptr->ino_buf_ptr + which_it * sizeof (struct dinode)); xtpg_ptr = (xtpage_t *) & (inoptr->di_btroot); offset_ctlpage = addressXAD(&(xtpg_ptr->xad[XTENTRYSTART])); } } else { /* tree doesn't have a root-leaf */ intermed_rc = imapleaf_get(agg_recptr->fset_imap. first_leaf_offset, &xtpg_ptr); if (intermed_rc != FSCK_OK) { /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_READ_NODE3, igcp_rc, fsck_READ, (long long)agg_recptr->ino_buf_agg_offset, agg_recptr->ino_buf_length, agg_recptr->ino_buf_data_len); igcp_rc = FSCK_FAILED_READ_NODE3; } else { /* got the first leaf node */ offset_ctlpage = addressXAD(&(xtpg_ptr->xad[XTENTRYSTART])); } } } /* * read the control page into the buffer */ if (igcp_rc == FSCK_OK) { /* we have an offset */ igcp_rc = mapctl_get(offset_ctlpage, (void **) &xtpg_ptr); if (igcp_rc != FSCK_OK) { /* this is fatal */ igcp_rc = FSCK_FAILED_CANTREADAITCTL; } else { /* the control page is in the buffer */ *addr_ctlpage_ptr = (struct dinomap *) xtpg_ptr; /* swap if on big endian machine */ ujfs_swap_dinomap(*addr_ctlpage_ptr); } } return (igcp_rc); } /***************************************************************************** * NAME: inotbl_put_ctl_page * * FUNCTION: If the current fsck session has write access to the aggregate, * note, in the fsck workspace, that the current fsck inode table * control page buffer has been modified and should be written * to the device in the next flush operation on this buffer. * * PARAMETERS: * is_aggregate - input - 0 => the inode table is fileset owned * !0 => the inode table is aggregate owned * ctlpage_ptr - input - the address, in an fsck buffer, of the * control page which has been updated * * RETURNS: * success: FSCK_OK * failure: something else */ int inotbl_put_ctl_page(int is_aggregate, struct dinomap *ctlpage_ptr) { int ipcp_rc = FSCK_OK; if (agg_recptr->processing_readwrite) { /* swap if on big endian machine */ ujfs_swap_dinomap(ctlpage_ptr); ipcp_rc = mapctl_put((void *) ctlpage_ptr); } return (ipcp_rc); } /***************************************************************************** * NAME: mapctl_get * * FUNCTION: Read the specified map control page into and/or locate the * requested specified map control page in the fsck map control * page buffer. * * PARAMETERS: * mapctl_fsblk_offset - input - offset, in aggregate blocks, into the * aggregate, of the needed map control * page. * addr_mapctl_ptr - input - pointer to a variable in which to return * the address, in an fsck buffer, of the * map control page which has been read. * * RETURNS: * success: FSCK_OK * failure: something else */ int mapctl_get(int64_t mapctl_fsblk_offset, void **addr_mapctl_ptr) { int mg_rc = FSCK_OK; int64_t start_byte; start_byte = mapctl_fsblk_offset * sb_ptr->s_bsize; if (start_byte == agg_recptr->mapctl_agg_offset) { /* * the target control page is already in * the buffer */ *addr_mapctl_ptr = (void *) (agg_recptr->mapctl_buf_ptr); } else { /* else we'll have to read it from the disk */ /* handle any pending deferred writes */ mg_rc = mapctl_flush(); if (mg_rc == FSCK_OK) { /* flushed ok */ agg_recptr->mapctl_agg_offset = start_byte; mg_rc = readwrite_device(agg_recptr->mapctl_agg_offset, agg_recptr->mapctl_buf_length, &(agg_recptr-> mapctl_buf_data_len), (void *) agg_recptr-> mapctl_buf_ptr, fsck_READ); /* endian - can't swap here, don't know if it's struct dmap or struct dinomap. swap before calling this routine. */ if (mg_rc == FSCK_OK) { /* read appears successful */ if (agg_recptr->mapctl_buf_data_len >= BYTESPERPAGE) { /* * we may not have gotten all we asked for, * but we got enough to cover the page we * were after */ *addr_mapctl_ptr = (void *) agg_recptr->mapctl_buf_ptr; } else { /* didn't get the minimum number of bytes */ /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_BADREAD_MAPCTL, mg_rc, fsck_READ, (long long)agg_recptr->mapctl_agg_offset, agg_recptr->mapctl_buf_length, agg_recptr->mapctl_buf_data_len); mg_rc = FSCK_FAILED_BADREAD_MAPCTL; } } else { /* bad return code from read */ /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_READ_MAPCTL, mg_rc, fsck_READ, (long long)agg_recptr->mapctl_agg_offset, agg_recptr->mapctl_buf_length, agg_recptr->mapctl_buf_data_len); mg_rc = FSCK_FAILED_READ_MAPCTL; } } } return (mg_rc); } /***************************************************************************** * NAME: mapctl_put * * FUNCTION: If the current fsck session has write access to the aggregate, * note, in the fsck workspace, that the current fsck map control * page buffer has been modified and should be written to the * device in the next flush operation on this buffer. * * PARAMETERS: * mapctl_ptr - input - address, in an fsck buffer, of the map control * page which has been updated. * * RETURNS: * success: FSCK_OK * failure: something else */ int mapctl_put(void *mapctl_ptr) { int mp_rc = FSCK_OK; if (agg_recptr->processing_readwrite) { /* buffer has been updated and needs to be written to the device */ agg_recptr->mapctl_buf_write = -1; } return (mp_rc); } /***************************************************************************** * NAME: mapctl_flush * * FUNCTION: If the current fsck session has write access to the aggregate * and the current map control buffer has been updated since * the most recent read operation, write the buffer contents to * the device. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int mapctl_flush() { int mf_rc = FSCK_OK; uint32_t bytes_written; if (agg_recptr->mapctl_buf_write) { /* buffer has been updated since * most recent write */ /* endian - swap before calling this routine */ mf_rc = readwrite_device(agg_recptr->mapctl_agg_offset, agg_recptr->mapctl_buf_data_len, &bytes_written, (void *) agg_recptr->mapctl_buf_ptr, fsck_WRITE); if (mf_rc == FSCK_OK) { if (bytes_written == agg_recptr->mapctl_buf_length) { /* buffer has been written to the * device and won't need to be written again * unless/until it the buffer contents have * been altered. */ agg_recptr->mapctl_buf_write = 0; } else { /* didn't write the correct number of bytes */ /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 15); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_MAPCTL_BADFLUSH, mf_rc, fsck_WRITE, (long long)agg_recptr->mapctl_agg_offset, agg_recptr->mapctl_buf_data_len, bytes_written); mf_rc = FSCK_FAILED_MAPCTL_BADFLUSH; } } else { /* else the write was not successful */ /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 16); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_MAPCTL_FLUSH, mf_rc, fsck_WRITE, (long long)agg_recptr->mapctl_agg_offset, agg_recptr->mapctl_buf_data_len, bytes_written); mf_rc = FSCK_FAILED_MAPCTL_FLUSH; } } return (mf_rc); } /***************************************************************************** * NAME: node_get * * FUNCTION: Read the specified xTree node into and/or locate the specified * xTree node in the fsck xTree node buffer. * * PARAMETERS: * node_fsblk_offset - input - offset, in aggregate blocks, into the * aggregate, of the xTree node wanted * addr_xtpage_ptr - input - pointer to a variable in which to return * the address, in an fsck buffer, of the * of the xTree node which has been read. * * RETURNS: * success: FSCK_OK * failure: something else */ int node_get(int64_t node_fsblk_offset, xtpage_t ** addr_xtpage_ptr) { int nodg_rc = FSCK_OK; int64_t node_start_byte, node_end_byte; xtpage_t *xtpage_t_ptr; node_start_byte = node_fsblk_offset * sb_ptr->s_bsize; node_end_byte = node_start_byte + sizeof (xtpage_t) - 1; if ((agg_recptr->ondev_wsp_fsblk_offset != 0) && (node_fsblk_offset > agg_recptr->ondev_wsp_fsblk_offset)) { /* * the offset is beyond the range * valid for fileset objects */ /* * This case is not caused by an I/O error, but by * invalid data in an inode. Let the caller handle * the consequences. */ nodg_rc = FSCK_BADREADTARGET1; } else if ((node_start_byte >= agg_recptr->node_agg_offset) && (node_end_byte <= (agg_recptr->node_agg_offset + agg_recptr->node_buf_data_len))) { /* * the target node is already in * the buffer */ *addr_xtpage_ptr = (xtpage_t *) (agg_recptr->node_buf_ptr + node_start_byte - agg_recptr->node_agg_offset); } else { /* else we'll have to read it from the disk */ agg_recptr->node_agg_offset = node_start_byte; nodg_rc = readwrite_device(agg_recptr->node_agg_offset, agg_recptr->node_buf_length, &(agg_recptr->node_buf_data_len), (void *) agg_recptr->node_buf_ptr, fsck_READ); if (nodg_rc == FSCK_OK) { /* read appears successful */ if (agg_recptr->node_buf_data_len >= (sizeof (xtpage_t))) { /* * we may not have gotten all we asked for, * but we got enough to cover the node we * were after */ /* swap if on big endian machine */ xtpage_t_ptr = (xtpage_t *) agg_recptr->node_buf_ptr; swap_multiple(ujfs_swap_xtpage_t, xtpage_t_ptr, 4); *addr_xtpage_ptr = (xtpage_t *) agg_recptr->node_buf_ptr; } else { /* didn't get the minimum number of bytes */ /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_BADREAD_NODE, nodg_rc, fsck_READ, (long long)agg_recptr->node_agg_offset, agg_recptr->node_buf_length, agg_recptr->node_buf_data_len); nodg_rc = FSCK_FAILED_BADREAD_NODE; } } else { /* bad return code from read */ /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_FAILED_READ_NODE, nodg_rc, fsck_READ, (long long)agg_recptr->node_agg_offset, agg_recptr->node_buf_length, agg_recptr->node_buf_data_len); nodg_rc = FSCK_FAILED_READ_NODE; } } return (nodg_rc); } /***************************************************************************** * NAME: open_device_read * * FUNCTION: Open the specified device for read access. * * PARAMETERS: * Device - input - the device specification * * RETURNS: * success: FSCK_OK * failure: something else */ int open_device_read(const char *Device) { Dev_IOPort = fopen(Device, "r"); fsck_send_msg(fsck_DEVOPENRDRC, (Dev_IOPort == NULL) ? ERROR_FILE_NOT_FOUND : 0); if (Dev_IOPort == NULL) return ERROR_FILE_NOT_FOUND; Dev_blksize = Dev_SectorSize = PBSIZE; return 0; } /*************************************************************************** * NAME: open_device_rw * * FUNCTION: Open the device for read/write access. Lock the device * to prevent others from reading from or writing to the * device, if possible. * * PARAMETERS: * Device - input - The device specification * * RETURNS: * success: FSCK_OK * failure: something else */ int open_device_rw(const char *Device) { Dev_IOPort = fopen_excl(Device, "r+"); /* * The 2.6.0 kernel no longer allows O_EXCL opens on a block device * where a file system is mounted read-only. Try again without the * O_EXCL flag. */ if (Dev_IOPort == NULL) Dev_IOPort = fopen(Device, "r+"); fsck_send_msg(fsck_DEVOPENRDWRRC, (Dev_IOPort == NULL) ? ERROR_FILE_NOT_FOUND : 0); if (Dev_IOPort == NULL) return ERROR_FILE_NOT_FOUND; Dev_blksize = Dev_SectorSize = PBSIZE; return 0; } /***************************************************************************** * NAME: open_volume * * FUNCTION: Open the device on which the aggregate resides. * * PARAMETERS: * volname - input - The device specifier * * RETURNS: * success: FSCK_OK * failure: something else */ int open_volume(char *volname) { int opnvol_rc = FSCK_OK; if (agg_recptr->parm_options[UFS_CHKDSK_LEVEL0] && agg_recptr->parm_options[UFS_CHKDSK_SKIPLOGREDO]) { /* * read-only request */ opnvol_rc = open_device_read(volname); if (opnvol_rc == FSCK_OK) { /* successfully opened for Read */ agg_recptr->processing_readonly = 1; } } else { /* read-write request */ opnvol_rc = open_device_rw(volname); if (opnvol_rc == 0) { /* successfully opened for Read/Write */ agg_recptr->processing_readwrite = 1; } else { /* unable to open for Read/Write */ opnvol_rc = open_device_read(volname); if (opnvol_rc == FSCK_OK) { /* successfully opened for Read */ agg_recptr->processing_readonly = 1; } } } if (opnvol_rc != FSCK_OK) { agg_recptr->fsck_is_done = 1; } return (opnvol_rc); } /***************************************************************************** * NAME: readwrite_device * * FUNCTION: Read data from or write data to the device on which the * aggregate resides. * * PARAMETERS: * dev_offset - input - the offset, in bytes, into the aggregate * of the data to read or to which to write * the data. * requested_data_size - input - the number of bytes requested * actual_data_size - input - pointer to a variable in which to return * the number of bytes actually read or * written * data_buffer - input - the address of the buffer in which to * put the data or from which to write * the data * mode - input - { fsck_READ | fsck_WRITE } * * RETURNS: * success: FSCK_OK * failure: something else */ int readwrite_device(int64_t dev_offset, uint32_t requested_data_size, uint32_t * actual_data_size, void *data_buffer, int mode) { int rwdb_rc = FSCK_OK; if ((ondev_jlog_byte_offset > 0) && (ondev_jlog_byte_offset <= dev_offset)) { /* into jlog! */ #ifdef _JFS_DEBUG printf("READ/WRITE target is in JOURNAL!!\n"); printf(" read/write offset = x%llx\r\n", dev_offset); printf(" jlog offset = x%llx\r\n", ondev_jlog_byte_offset); abort(); #endif rwdb_rc = FSCK_IOTARGETINJRNLLOG; } else { /* not trying to access the journal log */ if ((dev_offset % Dev_SectorSize) || (requested_data_size % Dev_SectorSize)) { rwdb_rc = FSCK_FAILED_SEEK; } else { /* offset seems ok */ switch (mode) { case fsck_READ: rwdb_rc = ujfs_rw_diskblocks(Dev_IOPort, dev_offset, requested_data_size, data_buffer, GET); break; case fsck_WRITE: rwdb_rc = ujfs_rw_diskblocks(Dev_IOPort, dev_offset, requested_data_size, data_buffer, PUT); break; default: rwdb_rc = FSCK_INTERNAL_ERROR_3; break; } } if (rwdb_rc == FSCK_OK) { *actual_data_size = requested_data_size; } else { *actual_data_size = 0; } } return (rwdb_rc); } /***************************************************************************** * NAME: recon_dnode_assign * * FUNCTION: Allocate a buffer for a new dnode at the specified aggregate * offset. * * PARAMETERS: * fsblk_offset - input - The offset, in aggregate blocks, into the * aggregate, of the new dnode. * addr_buf_ptr - input - pointer to a variable in which to return * the address of the buffer allocated. * * * NOTES: The offset of the dnode being created is a required input because * these buffers have a trailer record which contains the offset * at which to write the dnode. If this is not stored when the * buffer is allocated for a new dnode, the other routines would * have to treat a new dnode as a special case. * * * RETURNS: * success: FSCK_OK * failure: something else */ int recon_dnode_assign(int64_t fsblk_offset, dtpage_t ** addr_buf_ptr) { int rda_rc = FSCK_OK; struct recon_buf_record *bufrec_ptr; rda_rc = dire_buffer_alloc(addr_buf_ptr); if (rda_rc != FSCK_OK) { fsck_send_msg(fsck_CANTRECONINSUFSTG, 1); } else { bufrec_ptr = (struct recon_buf_record *) *addr_buf_ptr; bufrec_ptr->dnode_blkoff = fsblk_offset; bufrec_ptr->dnode_byteoff = fsblk_offset * sb_ptr->s_bsize; } return (rda_rc); } /***************************************************************************** * NAME: recon_dnode_get * * FUNCTION: Allocate an fsck dnode buffer and read the JFS dnode page at * the specified offset into it. * * PARAMETERS: * fsblk_offset - input - the offset, in aggregate blocks, into the * aggregate, of the desired dnode. * addr_buf_ptr - input - pointer to a variable in which to return * the fsck dnode buffer which has been allocated * and into which the requested dnode has been * read. * * RETURNS: * success: FSCK_OK * failure: something else */ int recon_dnode_get(int64_t fsblk_offset, dtpage_t ** addr_buf_ptr) { int rdg_rc = FSCK_OK; uint32_t bytes_read; struct recon_buf_record *bufrec_ptr; dtpage_t *dtp; rdg_rc = dire_buffer_alloc(addr_buf_ptr); if (rdg_rc != FSCK_OK) { fsck_send_msg(fsck_CANTRECONINSUFSTG, 2); } else { /* got the buffer */ bufrec_ptr = (struct recon_buf_record *) *addr_buf_ptr; bufrec_ptr->dnode_blkoff = fsblk_offset; bufrec_ptr->dnode_byteoff = fsblk_offset * sb_ptr->s_bsize; rdg_rc = readwrite_device(bufrec_ptr->dnode_byteoff, BYTESPERPAGE, &bytes_read, (void *) (*addr_buf_ptr), fsck_READ); if (rdg_rc != FSCK_OK) { /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_CANTREADRECONDNODE, rdg_rc, fsck_READ, (long long) bufrec_ptr->dnode_byteoff, BYTESPERPAGE, bytes_read); rdg_rc = FSCK_CANTREADRECONDNODE; dire_buffer_release(*addr_buf_ptr); } else if (bytes_read != BYTESPERPAGE) { /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_CANTREADRECONDNODE1, rdg_rc, fsck_READ, (long long) bufrec_ptr->dnode_byteoff, BYTESPERPAGE, bytes_read); rdg_rc = FSCK_CANTREADRECONDNODE1; dire_buffer_release(*addr_buf_ptr); } else { /* swap if on big endian machine */ dtp = *addr_buf_ptr; ujfs_swap_dtpage_t(dtp, sb_ptr->s_flag); dtp->header.flag |= BT_SWAPPED; } } return (rdg_rc); } /***************************************************************************** * NAME: recon_dnode_put * * FUNCTION: Write the dnode in the specified buffer into the aggregate * and then release the buffer. * * PARAMETERS: * buf_ptr - input - the address of the buffer containing the * dnode to write. * * NOTES: Unlike most _put_ routines in this module, blkmap_put_ctl_page * actually writes to the device. * * The buffer has a trailer record which contains the offset * at which to write the dnode. * * RETURNS: * success: FSCK_OK * failure: something else */ int recon_dnode_put(dtpage_t * buf_ptr) { int rdp_rc = FSCK_OK; uint32_t bytes_written; struct recon_buf_record *bufrec_ptr; bufrec_ptr = (struct recon_buf_record *) buf_ptr; /* swap if on big endian machine */ ujfs_swap_dtpage_t(buf_ptr, sb_ptr->s_flag); buf_ptr->header.flag &= ~BT_SWAPPED; rdp_rc = readwrite_device(bufrec_ptr->dnode_byteoff, BYTESPERPAGE, &bytes_written, (void *) buf_ptr, fsck_WRITE); ujfs_swap_dtpage_t(buf_ptr, sb_ptr->s_flag); buf_ptr->header.flag |= BT_SWAPPED; if (rdp_rc != FSCK_OK) { /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 17); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_CANTWRITRECONDNODE, rdp_rc, fsck_WRITE, (long long) bufrec_ptr->dnode_byteoff, BYTESPERPAGE, bytes_written); rdp_rc = FSCK_CANTWRITRECONDNODE; } else if (bytes_written != BYTESPERPAGE) { /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 18); /* * message to debugger */ fsck_send_msg(fsck_ERRONAGG, FSCK_CANTWRITRECONDNODE1, rdp_rc, fsck_WRITE, (long long) bufrec_ptr->dnode_byteoff, BYTESPERPAGE, bytes_written); rdp_rc = FSCK_CANTWRITRECONDNODE1; } bufrec_ptr->dnode_blkoff = 0; bufrec_ptr->dnode_byteoff = 0; dire_buffer_release(buf_ptr); return (rdp_rc); } /***************************************************************************** * NAME: recon_dnode_release * * FUNCTION: Release the specified fsck dnode buffer without writing its * contents to the aggregate. * * PARAMETERS: * buf_ptr - input - Address of the fsck dnode buffer to release. * * RETURNS: * success: FSCK_OK * failure: something else */ int recon_dnode_release(dtpage_t * buf_ptr) { int rdr_rc = FSCK_OK; struct recon_buf_record *bufrec_ptr; bufrec_ptr = (struct recon_buf_record *) buf_ptr; bufrec_ptr->dnode_blkoff = 0; bufrec_ptr->dnode_byteoff = 0; rdr_rc = dire_buffer_release(buf_ptr); return (rdr_rc); } jfsutils-1.1.15.orig/fsck/fsckpfs.h0000644000000000000000000000160510340701412014017 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef H_FSCKPFS #define H_FSCKPFS #define fsck_READ 1 #define fsck_WRITE 2 #endif jfsutils-1.1.15.orig/fsck/fsckruns.c0000644000000000000000000000726610441103234014222 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include /* defines and includes common among the fsck.jfs modules */ #include "xfsckint.h" extern char *MsgText[]; /***************************************************************************** * NAME: fsck_hbeat * * FUNCTION: * * PARAMETERS: none * * NOTES: * This is racy, but we don't care. * * RETURNS: * success: FSCK_OK * failure: something else */ void fsck_hbeat(int unused) { static volatile unsigned long current_heartbeat = 0; switch (current_heartbeat) { case 0: printf("%s", msg_defs[fsck_HEARTBEAT0].msg_txt); current_heartbeat++; break; case 1: printf("%s", msg_defs[fsck_HEARTBEAT1].msg_txt); current_heartbeat++; break; case 2: printf("%s", msg_defs[fsck_HEARTBEAT2].msg_txt); current_heartbeat++; break; case 3: printf("%s", msg_defs[fsck_HEARTBEAT3].msg_txt); current_heartbeat++; break; case 4: printf("%s", msg_defs[fsck_HEARTBEAT4].msg_txt); current_heartbeat++; break; case 5: printf("%s", msg_defs[fsck_HEARTBEAT5].msg_txt); current_heartbeat++; break; case 6: printf("%s", msg_defs[fsck_HEARTBEAT6].msg_txt); current_heartbeat++; break; case 7: printf("%s", msg_defs[fsck_HEARTBEAT7].msg_txt); current_heartbeat++; break; case 8: printf("%s", msg_defs[fsck_HEARTBEAT8].msg_txt); current_heartbeat++; break; case 9: printf("%s", msg_defs[fsck_HEARTBEAT7].msg_txt); current_heartbeat++; break; case 10: printf("%s", msg_defs[fsck_HEARTBEAT6].msg_txt); current_heartbeat++; break; case 11: printf("%s", msg_defs[fsck_HEARTBEAT5].msg_txt); current_heartbeat++; break; case 12: printf("%s", msg_defs[fsck_HEARTBEAT4].msg_txt); current_heartbeat++; break; case 13: printf("%s", msg_defs[fsck_HEARTBEAT3].msg_txt); current_heartbeat++; break; case 14: printf("%s", msg_defs[fsck_HEARTBEAT2].msg_txt); current_heartbeat++; break; case 15: printf("%s", msg_defs[fsck_HEARTBEAT1].msg_txt); current_heartbeat = 0; break; default: printf("%s", msg_defs[fsck_HEARTBEAT0].msg_txt); current_heartbeat = 1; } fflush(stdout); alarm(1); } /***************************************************************************** * NAME: fsck_hbeat_start * * FUNCTION: * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ void fsck_hbeat_start(void) { struct sigaction sa; memset(&sa, 0, sizeof (sa)); sa.sa_handler = &fsck_hbeat; sa.sa_flags = SA_RESTART; sigaction(SIGALRM, &sa, NULL); alarm(1); } /***************************************************************************** * NAME: fsck_hbeat_stop * * FUNCTION: * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ void fsck_hbeat_stop(void) { struct sigaction sa; memset(&sa, 0, sizeof (sa)); sa.sa_handler = SIG_DFL; sigaction(SIGALRM, &sa, NULL); alarm(0); } jfsutils-1.1.15.orig/fsck/fsckwsp.c0000644000000000000000000033103411402027704014042 0ustar /* * Copyright (C) International Business Machines Corp., 2000-2004 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include /* defines and includes common among the fsck.jfs modules */ #include "xfsckint.h" #include "devices.h" #include "message.h" /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * superblock buffer pointer * * defined in xchkdsk.c */ extern struct superblock *sb_ptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * fsck aggregate info structure pointer * * defined in xchkdsk.c */ extern struct fsck_agg_record *agg_recptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * fsck block map info structure and pointer * * defined in xchkdsk.c */ extern struct fsck_bmap_record *bmap_recptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * For message processing * * defined in xchkdsk.c */ extern struct tm *fsck_DateTime; extern char *Vol_Label; extern UniChar uni_LSFN_NAME[]; extern UniChar uni_lsfn_name[]; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * Unicode path strings information. * * values are assigned when the fsck aggregate record is initialized. * accessed via addresses in the fack aggregate record. */ extern UniChar uni_LSFN_NAME[11]; extern UniChar uni_lsfn_name[11]; /* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV * * The following are internal to this file * */ int alloc_wsp_extent(uint32_t, int); void dupall_extract_blkrec(struct dupall_blkrec *); struct dupall_blkrec *dupall_find_blkrec(int64_t, int64_t); struct dupall_blkrec *dupall_get_blkrec(void); int dupall_insert_blkrec(int64_t, int64_t, struct dupall_blkrec **); int establish_wsp_block_map(void); int extent_1stref_chk(int64_t, int64_t, int8_t, int8_t, struct fsck_ino_msg_info *, struct fsck_inode_record *); int extent_record_dupchk(int64_t, int64_t, int8_t, int8_t, int8_t, struct fsck_ino_msg_info *, struct fsck_inode_record *); int fsblk_count_avail(uint32_t *, int32_t *, int32_t *, int32_t, int32_t *); int fsblk_next_avail(uint32_t *, int32_t, int32_t, int32_t *, int32_t *, int *); int inorec_agg_search(uint32_t, struct fsck_inode_record **); int inorec_agg_search_insert(uint32_t, struct fsck_inode_record **); int inorec_fs_search(uint32_t, struct fsck_inode_record **); int inorec_fs_search_insert(uint32_t, struct fsck_inode_record **); void locate_inode(uint32_t, int32_t *, int32_t *, int32_t *); /* * The following are used for reporting storage related errors */ extern int wsp_dynstg_action; extern int wsp_dynstg_object; /* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV */ /**************************************************************************** * NAME: alloc_vlarge_buffer * * FUNCTION: Allocate the very large multi-use buffer * * * PARAMETERS: none * * NOTES: This must be called before logredo since the purpose * is to ensure a buffer which has been obtained via * malloc(), whether we're called from the command line * or during autocheck. * * RETURNS: * success: FSCK_OK * failure: something else */ int alloc_vlarge_buffer() { int avb_rc = FSCK_OK; if ((agg_recptr->vlarge_buf_ptr = (char *) malloc(VLARGE_BUFSIZE)) != NULL) { agg_recptr->vlarge_buf_length = VLARGE_BUFSIZE; agg_recptr->vlarge_current_use = NOT_CURRENTLY_USED; } else { avb_rc = ENOMEM; fsck_send_msg(MSG_OSO_INSUFF_MEMORY); } return (avb_rc); } /**************************************************************************** * NAME: alloc_wrksp * * FUNCTION: Allocates and initializes (to guarantee the storage is backed) * dynamic storage for the caller. * * PARAMETERS: * length - input - the number of bytes of storage which are needed * dynstg_object - input - a constant (see xfsck.h) identifying the purpose * for which the storage is needed (Used in error * message if the request cannot be satisfied. * addr_wrksp_ptr - input - the address of a variable in which this routine * will return the address of the dynamic storage * allocated for the caller * * RETURNS: * success: FSCK_OK * failure: something else */ int alloc_wrksp(uint32_t length, int dynstg_object, int for_logredo, void **addr_wrksp_ptr) { int awsp_rc = FSCK_OK; char *wsp_ptr = NULL; struct wsp_ext_rec *this_fer; uint32_t bytes_avail; uint32_t min_length; *addr_wrksp_ptr = NULL; /* round up to an 8 byte boundary */ min_length = ((length + 7) / 8) * 8; while ((wsp_ptr == NULL) && (awsp_rc == FSCK_OK)) { this_fer = agg_recptr->wsp_extent_list; while ((this_fer != NULL) && (wsp_ptr == NULL) && (awsp_rc == FSCK_OK)) { if ((for_logredo) && !(this_fer->for_logredo)) { /* * requestor is logredo and * fer describes an allocation not for logredo */ this_fer = this_fer->next; } else { /* this fer describes an eligible allocation */ bytes_avail = this_fer->extent_length - this_fer->last_byte_used; if (bytes_avail >= min_length) { /* there's enough here */ wsp_ptr = this_fer->extent_addr + this_fer->last_byte_used + 1; this_fer->last_byte_used += min_length; } else { /* try the next fer */ this_fer = this_fer->next; } } } if ((awsp_rc == FSCK_OK) && (wsp_ptr == NULL)) { /* * nothing fatal but we didn't find the * storage yet */ /* * will allocate some number of memory segments * and put the fer describing it on the beginning * of the list. */ awsp_rc = alloc_wsp_extent(min_length, for_logredo); } } if (awsp_rc == FSCK_OK) { /* we allocated virtual storage */ /* * now initialize the storage */ memset((void *) wsp_ptr, 0, length); /* set the return value */ *addr_wrksp_ptr = (void *) wsp_ptr; } return (awsp_rc); } /**************************************************************************** * NAME: alloc_wsp_extent * * FUNCTION: Extend the workspace * * For optimum use of storage, we'll allocate a whole segment. * Then the alloc_wrksp routine portions it out as needed. * * PARAMETERS: * minimum_length - input - minimum number of bytes of contiguous storage * needed * * RETURNS: * success: FSCK_OK * failure: something else */ int alloc_wsp_extent(uint32_t minimum_length, int for_logredo) { int awe_rc = FSCK_OK; struct wsp_ext_rec *new_fer; size_t extent_length = MEMSEGSIZE; char *extent_addr = NULL; int8_t from_high_memory = 0; /* * the user has specified the minimum needed. We must allocate * at least 16 more than that because we're going to use 16 bytes * at the beginning to keep track of it. */ while (extent_length < (minimum_length + 16)) { extent_length += MEMSEGSIZE; } wsp_dynstg_object = dynstg_iobufs; wsp_dynstg_action = dynstg_allocation; extent_addr = (char *) malloc(extent_length); if (extent_addr == NULL) { /* allocation failure */ awe_rc = FSCK_FAILED_DYNSTG_EXHAUST4; if (!for_logredo) { fsck_send_msg(fsck_EXHDYNSTG, wsp_dynstg_action, dynstg_wspext); } } else { /* got the dynamic storage */ /* * use the first 16 bytes of it to keep track of it */ new_fer = (struct wsp_ext_rec *) extent_addr; new_fer->extent_length = extent_length; new_fer->for_logredo = for_logredo; new_fer->from_high_memory = from_high_memory; new_fer->extent_addr = extent_addr; new_fer->last_byte_used = sizeof (struct wsp_ext_rec) - 1; new_fer->next = agg_recptr->wsp_extent_list; agg_recptr->wsp_extent_list = new_fer; } return (awe_rc); } /**************************************************************************** * NAME: blkall_mark_free * * FUNCTION: Adjust the fsck workspace to show the indicated blocks are no * longer used. * * PARAMETERS: * first_block - input - ordinal number of the first filesystem block * whose owner count is to be adjusted. * last_block - input - ordinal number of the last filesystem block * whose owner count is to be adjusted. * * RETURNS: * success: FSCK_OK * failure: something else * * NOTE: * This could be written to be more efficient, but it's a big * improvement over how it used to be. */ int blkall_mark_free(int64_t first_block, int64_t last_block) { int64_t blk_num; int ddo_rc = FSCK_OK; int64_t page_num; int64_t last_page_num = -1; uint32_t word_offset; uint32_t bit_mask; struct fsck_blk_map_page *this_page; uint32_t *this_word; for (blk_num = first_block; blk_num <= last_block; blk_num++) { blkmap_find_bit(blk_num, &page_num, &word_offset, &bit_mask); if (page_num != last_page_num) { if (last_page_num != -1) blkmap_put_page(last_page_num); ddo_rc = blkmap_get_page(page_num, &this_page); if (ddo_rc) return ddo_rc; last_page_num = page_num; } this_word = (uint32_t *) ((char *) this_page + word_offset); /* mark it not allocated */ (*this_word) &= ~bit_mask; } if (last_page_num != -1) blkmap_put_page(last_page_num); return (FSCK_OK); } /**************************************************************************** * NAME: blkall_increment_owners * * FUNCTION: Adjust the fsck workspace to show one more owner for the * indicated block. * * PARAMETERS: * first_block - input - ordinal number of the first filesystem block * whose owner count is to be adjusted. * last_block - input - ordinal number of the first filesystem block * whose owner count is to be adjusted. * msg_info_ptr - input - information needed to issue messages for this * extent. If NULL, no messages will be issued * * RETURNS: * success: 0, or 1 if multiply-allocated blocks found * failure: something less than 0 */ int blkall_increment_owners(int64_t first_block, int64_t last_block, struct fsck_ino_msg_info *msg_info_ptr) { int dio_rc; int64_t blk_num; int64_t page_num; int64_t last_page_num = -1; uint32_t word_offset; uint32_t bit_mask; struct fsck_blk_map_page *this_page; uint32_t *this_word; int is_a_dup = 0; int64_t first_in_dup_range = 0; int32_t size_of_dup_range = 0; for (blk_num = first_block; blk_num <= last_block; blk_num++) { blkmap_find_bit(blk_num, &page_num, &word_offset, &bit_mask); if (page_num != last_page_num) { if (last_page_num != -1) blkmap_put_page(last_page_num); dio_rc = blkmap_get_page(page_num, &this_page); if (dio_rc) return dio_rc; last_page_num = page_num; } this_word = (uint32_t *) ((char *) this_page + word_offset); if (((*this_word) & bit_mask) != bit_mask) { /* * not allocated yet */ /* mark it allocated */ (*this_word) |= bit_mask; /* Record previously found duplicate range */ if (size_of_dup_range) { if (msg_info_ptr) fsck_send_msg(fsck_DUPBLKREF, size_of_dup_range, (long long) first_in_dup_range, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); dio_rc = dupall_insert_blkrec( first_in_dup_range, first_in_dup_range + size_of_dup_range - 1, NULL); if (dio_rc) return dio_rc; agg_recptr->dup_block_count++; agg_recptr->unresolved_1stref_count++; size_of_dup_range = 0; first_in_dup_range = 0; is_a_dup = 1; } } else { /* already allocated */ if (!size_of_dup_range++) first_in_dup_range = blk_num; } } if (last_page_num != -1) blkmap_put_page(last_page_num); /* Record duplicate range */ if (size_of_dup_range) { if (msg_info_ptr) fsck_send_msg(fsck_DUPBLKREF, size_of_dup_range, (long long) first_in_dup_range, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); dio_rc = dupall_insert_blkrec(first_in_dup_range, first_in_dup_range + size_of_dup_range - 1, NULL); if (dio_rc) return dio_rc; agg_recptr->dup_block_count++; agg_recptr->unresolved_1stref_count++; is_a_dup = 1; } return (is_a_dup); } /**************************************************************************** * NAME: blkall_split_blkrec * * FUNCTION: Split the current duplicate block record * * PARAMETERS: * blkrec - input - duplicate block record to be split * first_block - input - first block of range whose intersection with * blkrec causes the split * last_block - input - last block of range whose intersection with * blkrec causes the split * RETURNS: * success: FSCK_OK * failure: something else */ int blkall_split_blkrec(struct dupall_blkrec *blkrec, int64_t first_block, int64_t last_block) { int bsb_rc = FSCK_OK; struct dupall_blkrec *new_blkrec; int64_t temp; if (blkrec->first_blk < first_block) { temp = blkrec->last_blk; blkrec->last_blk = first_block - 1; bsb_rc = dupall_insert_blkrec(first_block, temp, &new_blkrec); if (bsb_rc) return bsb_rc; new_blkrec->first_ref_resolved = blkrec->first_ref_resolved; new_blkrec->owner_count = blkrec->owner_count; agg_recptr->dup_block_count++; if (!new_blkrec->first_ref_resolved) agg_recptr->unresolved_1stref_count++; blkrec = new_blkrec; } if (blkrec->last_blk > last_block) { temp = blkrec->last_blk; blkrec->last_blk = last_block; bsb_rc = dupall_insert_blkrec(first_block, temp, &new_blkrec); if (bsb_rc) return bsb_rc; new_blkrec->first_ref_resolved = blkrec->first_ref_resolved; new_blkrec->owner_count = blkrec->owner_count; agg_recptr->dup_block_count++; if (!new_blkrec->first_ref_resolved) agg_recptr->unresolved_1stref_count++; } return FSCK_OK; } /**************************************************************************** * NAME: dire_buffer_alloc * * FUNCTION: Allocate an I/O buffer for use during directory entry insertion * and removal processing. * * PARAMETERS: * addr_dnode_ptr - input - pointer to a variable in which to return * the address of the allocated buffer (or * NULL if no buffer could be allocated) * * RETURNS: * success: FSCK_OK * failure: something else */ int dire_buffer_alloc(dtpage_t ** addr_dnode_ptr) { int rba_rc = FSCK_OK; uint32_t bufrec_length, bytes_available; struct recon_buf_record *bufrec_ptr; if (agg_recptr->recon_buf_stack != NULL) { /* stack not empty */ bufrec_ptr = agg_recptr->recon_buf_stack; agg_recptr->recon_buf_stack = bufrec_ptr->stack_next; bufrec_ptr->stack_next = NULL; bufrec_ptr->dnode_blkoff = 0; bufrec_ptr->dnode_byteoff = 0; *addr_dnode_ptr = &(bufrec_ptr->dnode_buf); } else { /* the stack is empty */ bufrec_length = sizeof (struct recon_buf_record); bytes_available = agg_recptr->recon_buf_extent->extent_length - agg_recptr->recon_buf_extent->last_byte_used; if (bytes_available < bufrec_length) { /* we've used up a whole * extent of dynamic storage -- something * strange is going on */ *addr_dnode_ptr = NULL; rba_rc = FSCK_INSUFDSTG4RECON; } else { /* there is enough dynamic storage for another one */ bufrec_ptr = (struct recon_buf_record *) (agg_recptr->recon_buf_extent->extent_addr + agg_recptr->recon_buf_extent->last_byte_used + 1); agg_recptr->recon_buf_extent->last_byte_used += bufrec_length; /* * now initialize the record */ wsp_dynstg_object = dynstg_recondnodebuf; wsp_dynstg_action = dynstg_initialization; memset((void *) bufrec_ptr, 0, bufrec_length); *addr_dnode_ptr = &(bufrec_ptr->dnode_buf); } } return (rba_rc); } /**************************************************************************** * NAME: dire_buffer_release * * FUNCTION: Deallocate (make available for reuse) an I/O buffer for used * during directory entry insertion and removal processing. * * PARAMETERS: * dnode_ptr - input - the address of the buffer to release * * RETURNS: * success: FSCK_OK * failure: something else */ int dire_buffer_release(dtpage_t * dnode_ptr) { int rbr_rc = FSCK_OK; struct recon_buf_record *bufrec_ptr; bufrec_ptr = (struct recon_buf_record *) dnode_ptr; bufrec_ptr->stack_next = agg_recptr->recon_buf_stack; agg_recptr->recon_buf_stack = bufrec_ptr; return (rbr_rc); } /**************************************************************************** * NAME: directory_buffers_alloc * * FUNCTION: Allocate storage for use as I/O buffers while inserting and * removing directory entries during file system repair processing. * FUNCTION: Make use of the VeryLarge Multi-Use Buffer for * I/O buffers while inserting and removing directory entries * during file system repair processing. * * NOTES: The directory buffers are the only use of the VeryLarge Buffer * during Phase 6 processing. * * PARAMETERS: none * * NOTES: The address of the storage allocated for this purpose is stored * in the aggregate record, field: recon_buf_extent * * RETURNS: * success: FSCK_OK * failure: something else */ int directory_buffers_alloc() { int dba_rc = FSCK_OK; agg_recptr->vlarge_current_use = USED_FOR_DIRPAGE_BUFS; agg_recptr->recon_buf_extent = (struct wsp_ext_rec *) agg_recptr->vlarge_buf_ptr; agg_recptr->recon_buf_extent->next = NULL; agg_recptr->recon_buf_extent->extent_length = agg_recptr->vlarge_buf_length; agg_recptr->recon_buf_extent->extent_addr = (char *) agg_recptr->recon_buf_extent; agg_recptr->recon_buf_extent->last_byte_used = sizeof (struct wsp_ext_rec) - 1; return (dba_rc); } /**************************************************************************** * NAME: directory_buffers_release * * FUNCTION: Free storage which was allocated for use as I/O buffers while * inserting and removing directory entries during file system * repair processing. * * PARAMETERS: none * * NOTES: The address of the storage allocated for this purpose is stored * in the aggregate record, field: recon_buf_extent * * RETURNS: * success: FSCK_OK * failure: something else */ int directory_buffers_release() { int dbr_rc = FSCK_OK; if (agg_recptr->recon_buf_extent != NULL) { /* something is allocated */ agg_recptr->recon_buf_extent = NULL; agg_recptr->vlarge_current_use = NOT_CURRENTLY_USED; } return (dbr_rc); } /**************************************************************************** * NAME: dtreeQ_dequeue * * FUNCTION: If the directory tree queue is not empty, remove the front * element and return a pointer to it. Otherwise, return NULL. * * PARAMETERS: * dtreeQ_elptr - input - pointer to a variable in which the address of * the front queue element should be returned * * NOTES: The directory tree queue is described in the aggregate record, * fields: dtreeQ_front, dtreeQ_back * * RETURNS: * success: FSCK_OK * failure: something else */ int dtreeQ_dequeue(struct dtreeQelem **dtreeQ_elptr) { int dQd_rc = FSCK_OK; *dtreeQ_elptr = agg_recptr->dtreeQ_front; if (agg_recptr->dtreeQ_back == agg_recptr->dtreeQ_front) { /* empty */ agg_recptr->dtreeQ_back = agg_recptr->dtreeQ_front = NULL; } else { /* not empty */ agg_recptr->dtreeQ_front = agg_recptr->dtreeQ_front->next; agg_recptr->dtreeQ_front->prev = NULL; } return (dQd_rc); } /**************************************************************************** * NAME: dtreeQ_enqueue * * FUNCTION: Adds the given element to the back of the directory tree queue. * * PARAMETERS: * dtreeQ_elptr - input - address of the element to add to the queue. * * NOTES: The directory tree queue is described in the aggregate record, * fields: dtreeQ_front, dtreeQ_back * * RETURNS: * success: FSCK_OK * failure: something else */ int dtreeQ_enqueue(struct dtreeQelem *dtreeQ_elptr) { int dQe_rc = FSCK_OK; if (agg_recptr->dtreeQ_back == NULL) { /* empty queue */ agg_recptr->dtreeQ_back = agg_recptr->dtreeQ_front = dtreeQ_elptr; dtreeQ_elptr->prev = dtreeQ_elptr->next = NULL; } else { /* queue not empty */ dtreeQ_elptr->next = NULL; dtreeQ_elptr->prev = agg_recptr->dtreeQ_back; agg_recptr->dtreeQ_back->next = dtreeQ_elptr; agg_recptr->dtreeQ_back = dtreeQ_elptr; } return (dQe_rc); } /**************************************************************************** * NAME: dtreeQ_get_elem * * FUNCTION: Allocates workspace storage for an fsck directory tree queue element * * PARAMETERS: * addr_dtreeQ_ptr - input - pointer to a variable in which the address * of the new element should be returned. * * RETURNS: * success: FSCK_OK * failure: something else */ int dtreeQ_get_elem(struct dtreeQelem **addr_dtreeQ_ptr) { int dge_rc = FSCK_OK; int I_am_logredo = 0; if (agg_recptr->free_dtreeQ != NULL) { /* free list isn't empty */ *addr_dtreeQ_ptr = agg_recptr->free_dtreeQ; agg_recptr->free_dtreeQ = agg_recptr->free_dtreeQ->next; memset((void *) (*addr_dtreeQ_ptr), 0, dtreeQ_elem_length); } else { /* else the free list is empty */ dge_rc = alloc_wrksp(dtreeQ_elem_length, dynstg_dtreeQ_elem, I_am_logredo, (void **) addr_dtreeQ_ptr); } return (dge_rc); } /**************************************************************************** * NAME: dtreeQ_rel_elem * * FUNCTION: Makes an fsck directory tree queue element available for reuse * * PARAMETERS: * dtreeQ_elptr - input - the address of the element to release * * RETURNS: * success: FSCK_OK * failure: something else */ int dtreeQ_rel_elem(struct dtreeQelem *dtreeQ_elptr) { int dQre_rc = FSCK_OK; dtreeQ_elptr->next = agg_recptr->free_dtreeQ; agg_recptr->free_dtreeQ = dtreeQ_elptr; return (dQre_rc); } /**************************************************************************** * NAME: dupall_extract_blkrec * * FUNCTION: Remove the given (previously found) record from the list of * duplicate allocation block records. * * PARAMETERS: * block_recptr - input - the address of the record to remove * * NOTES: The duplicate allocation list is described in the aggregate record, * field: dup_alloc_lst */ void dupall_extract_blkrec(struct dupall_blkrec *block_recptr) { /* * remove it from the list of multiply-allocated block */ if (block_recptr->prev) block_recptr->prev->next = block_recptr->next; else /* first in list */ agg_recptr->dup_alloc_lst = block_recptr->next; if (block_recptr->next) block_recptr->next->prev = block_recptr->prev; /* * release it for reuse */ block_recptr->next = agg_recptr->free_dupall_blkrec; agg_recptr->free_dupall_blkrec = block_recptr; } /**************************************************************************** * NAME: dupall_find_blkrec * * FUNCTION: Search for a record with the given block number in the duplicate * allocation list. * * PARAMETERS: * first_block - input - ordinal number of the first filesystem block * last_block - input - ordinal number of the last filesystem block * * NOTES: The duplicate allocation list is described in the aggregate record, * field: dup_alloc_lst * * RETURNS: * success: record found * failure: NULL */ struct dupall_blkrec *dupall_find_blkrec(int64_t first_block, int64_t last_block) { struct dupall_blkrec *this_blkrec; for (this_blkrec = agg_recptr->dup_alloc_lst; this_blkrec && this_blkrec->first_blk <= last_block; this_blkrec = this_blkrec->next) { if (this_blkrec->last_blk >= first_block) return this_blkrec; } return NULL; } /**************************************************************************** * NAME: dupall_get_blkrec * * FUNCTION: Allocates workspace storage for a duplicate allocation * block record. * * PARAMETERS: * none * * RETURNS: * success: address of record * failure: NULL */ struct dupall_blkrec *dupall_get_blkrec(void) { struct dupall_blkrec *addr_blkrec_ptr; int dgb_rc = FSCK_OK; if (agg_recptr->free_dupall_blkrec != NULL) { /* free list isn't empty */ addr_blkrec_ptr = agg_recptr->free_dupall_blkrec; agg_recptr->free_dupall_blkrec = addr_blkrec_ptr->next; } else { /* else the free list is empty */ dgb_rc = alloc_wrksp(dupall_blkrec_length, dynstg_dupall_blkrec, 0, (void **) &addr_blkrec_ptr); } if (dgb_rc == FSCK_OK) return addr_blkrec_ptr; return NULL; } /***************************************************************************** * NAME: dupall_insert_blkrec * * FUNCTION: Allocate a duplicate allocation record for the given blocks and * insert it into the sorted, doubly-linked list of duplicate * allocation records. * * PARAMETERS: * first_block - input - the first block number for which the record is * to be allocated. * last_block - input - the last block number for which the record is * to be allocated. * * NOTES: The duplicate allocation list is described in the aggregate record, * field: dup_alloc_lst * * RETURNS: * success: FSCK_OK * failure: something else */ int dupall_insert_blkrec(int64_t first_block, int64_t last_block, struct dupall_blkrec **blkrec) { struct dupall_blkrec *new_blkrec; struct dupall_blkrec *prev_blkrec; struct dupall_blkrec *this_blkrec; int dib_done = 0; new_blkrec = dupall_get_blkrec(); if (new_blkrec == NULL) return FSCK_FAILED_DYNSTG_EXHAUST1; if (blkrec) *blkrec = new_blkrec; /* got a block record */ new_blkrec->first_blk = first_block; new_blkrec->last_blk = last_block; new_blkrec->owner_count = 2; if (agg_recptr->dup_alloc_lst == NULL) { /* list now empty */ new_blkrec->next = NULL; new_blkrec->prev = NULL; agg_recptr->dup_alloc_lst = new_blkrec; return FSCK_OK; } /* list not empty */ if (agg_recptr->dup_alloc_lst->first_blk > first_block) { /* * goes at front */ new_blkrec->next = agg_recptr->dup_alloc_lst; new_blkrec->prev = NULL; agg_recptr->dup_alloc_lst = new_blkrec; return FSCK_OK; } /* doesn't go at the front */ prev_blkrec = agg_recptr->dup_alloc_lst; this_blkrec = agg_recptr->dup_alloc_lst->next; while (!dib_done) { if (this_blkrec == NULL) { /* goes at the end */ new_blkrec->next = NULL; new_blkrec->prev = prev_blkrec; prev_blkrec->next = new_blkrec; dib_done = 1; } else if (this_blkrec->first_blk > first_block) { /* * goes in front of this one */ new_blkrec->next = this_blkrec; new_blkrec->prev = prev_blkrec; prev_blkrec->next = new_blkrec; this_blkrec->prev = new_blkrec; dib_done = 1; } else { /* try the next one */ prev_blkrec = this_blkrec; this_blkrec = this_blkrec->next; } } return FSCK_OK; } /**************************************************************************** * NAME: establish_agg_workspace * * FUNCTION: Obtain storage for and initialize the fsck aggregate workspace. * * PARAMETERS: none * * NOTES: The various parts of the workspace are described in the aggregate * record. * * RETURNS: * success: FSCK_OK * failure: something else */ int establish_agg_workspace() { int eaw_rc = FSCK_OK; uint32_t mapsize_bytes; int I_am_logredo = 0; /* * establish the fsck workspace block map */ eaw_rc = establish_wsp_block_map(); if (eaw_rc == FSCK_OK) { /* block map has been established */ agg_recptr->agg_imap.num_iags = 1; agg_recptr->agg_imap.bkd_inodes = INOSPEREXT; agg_recptr->agg_imap.unused_bkd_inodes = INOSPEREXT - 4; /* in release 1 there is always * exactly one extent of inodes allocated * for the aggregate */ agg_recptr->inode_count = INOSPEREXT; /* * now establish the fsck aggregate imap workspace */ mapsize_bytes = agg_recptr->agg_imap.num_iags * sizeof (struct fsck_iag_record); eaw_rc = alloc_wrksp(mapsize_bytes, dynstg_agg_iagtbl, I_am_logredo, (void **) &(agg_recptr->agg_imap.iag_tbl)); if (eaw_rc == FSCK_OK) { /* AIM workspace established */ /* * now establish the fsck aggregate inode table workspace * * (since there is always exactly one inode extent, we don't * bother with an IAG table of pointers to extent address tables * or with an extent address table of pointers to inode record * address tables.) */ eaw_rc = alloc_wrksp(inode_tbl_length, dynstg_ait_inotbl, I_am_logredo, (void **) &(agg_recptr->AIT_ext0_tbl)); memcpy((void *) &(agg_recptr->AIT_ext0_tbl->eyecatcher), (void *) "InodeTbl", 8); } } return (eaw_rc); } /**************************************************************************** * NAME: establish_ea_iobuf * * FUNCTION: Make use of the VeryLarge Multi-Use Buffer * for reading and validating EA data. * * PARAMETERS: none * * NOTES: The ea I/O buffer is the only user of the VeryLarge Buffer * during Phase 1 processing. * * RETURNS: * success: FSCK_OK * failure: something else */ int establish_ea_iobuf() { int eei_rc = FSCK_OK; agg_recptr->vlarge_current_use = USED_FOR_EA_BUF; agg_recptr->ea_buf_ptr = agg_recptr->vlarge_buf_ptr; wsp_dynstg_action = dynstg_initialization; memset((void *) (agg_recptr->ea_buf_ptr), '\0', EA_IO_BUFSIZE); agg_recptr->ea_buf_length = agg_recptr->vlarge_buf_length; agg_recptr->ea_buf_data_len = 0; agg_recptr->ea_agg_offset = 0; return (eei_rc); } /**************************************************************************** * NAME: establish_fs_workspace * * FUNCTION: Obtain storage for and initialize the fsck file sets workspace. * * PARAMETERS: none * * NOTES: The various parts of the workspace are described in the aggregate * record. * * RETURNS: * success: FSCK_OK * failure: something else */ int establish_fs_workspace() { int efsw_rc = FSCK_OK; uint32_t mapsize_bytes; uint32_t buffer_size; int aggregate_inode, which_ait = 0; uint32_t inoidx; struct dinode *inoptr; int I_am_logredo = 0; struct IAG_tbl_t *IAGtbl; struct inode_ext_tbl_t *inoexttbl; struct inode_tbl_t *inotbl; /* * allocate a buffer in which path names can be constructed */ buffer_size = (JFS_PATH_MAX + 2) * sizeof (char); efsw_rc = alloc_wrksp(buffer_size, dynstg_fsit_map, I_am_logredo, (void **) &(agg_recptr->path_buffer)); if (efsw_rc == FSCK_OK) { /* got it */ agg_recptr->path_buffer_length = buffer_size; /* * Figure out how many IAGs have been allocated for the fileset. * (Note that in release 1 there is always exactly 1 fileset in the * aggregate) * * At this point the aggregate inode describing the fileset has been * validated. The data described by that inode is 1 page of control * information plus some number of IAGs. di_size is the number of * bytes allocated for that data. */ if (agg_recptr->primary_ait_4part2) { which_ait = fsck_primary; efsw_rc = ait_special_read_ext1(fsck_primary); if (efsw_rc != FSCK_OK) { /* read failed */ report_readait_error(efsw_rc, FSCK_FAILED_CANTREADAITEXTC, fsck_primary); efsw_rc = FSCK_FAILED_CANTREADAITEXTC; } } else { which_ait = fsck_secondary; efsw_rc = ait_special_read_ext1(fsck_secondary); if (efsw_rc != FSCK_OK) { /* read failed */ report_readait_error(efsw_rc, FSCK_FAILED_CANTREADAITEXTD, fsck_secondary); efsw_rc = FSCK_FAILED_CANTREADAITEXTD; } } } if (efsw_rc != FSCK_OK) goto efsw_exit; /* got the first AIT extent */ aggregate_inode = -1; inoidx = FILESYSTEM_I; efsw_rc = inode_get(aggregate_inode, which_ait, inoidx, &inoptr); if (efsw_rc != FSCK_OK) goto efsw_exit; /* got the fileset IT inode */ agg_recptr->fset_imap.num_iags = (inoptr->di_size / SIZE_OF_MAP_PAGE) - 1; /* * a high estimate of the inodes * allocated for the fileset */ agg_recptr->fset_inode_count = agg_recptr->fset_imap.num_iags * INOSPERIAG; /* * now establish the fsck fileset imap workspace */ if (efsw_rc != FSCK_OK) goto efsw_exit; /* inode map established */ mapsize_bytes = agg_recptr->fset_imap.num_iags * sizeof (struct fsck_iag_record); efsw_rc = alloc_wrksp(mapsize_bytes, dynstg_agg_iagtbl, I_am_logredo, (void **) &(agg_recptr->fset_imap.iag_tbl)); if (efsw_rc != FSCK_OK) goto efsw_exit; /* inode map workspace allocated */ /* * now establish the fsck fileset imap workspace * * We start out knowing that IAG 0, extent 0 is allocated and * has an inode in use. We'll allocate enough to cover that. */ mapsize_bytes = 8 + agg_recptr->fset_imap.num_iags * sizeof (struct inode_ext_tbl_t *); efsw_rc = alloc_wrksp(mapsize_bytes, dynstg_fsit_iagtbl, I_am_logredo, (void **) &IAGtbl); if (efsw_rc != FSCK_OK) goto efsw_exit; /* we got the IAG table */ memcpy((void *)&(IAGtbl->eyecatcher), (void *) "FSAITIAG", 8); agg_recptr->FSIT_IAG_tbl = IAGtbl; efsw_rc = alloc_wrksp(inode_ext_tbl_length, dynstg_fsit_inoexttbl, I_am_logredo, (void **) &inoexttbl); if (efsw_rc != FSCK_OK) goto efsw_exit; /* we got the inode extent table */ memcpy((void *)&(inoexttbl->eyecatcher), (void *)"FSAITEXT", 8); IAGtbl->inoext_tbl[0] = inoexttbl; efsw_rc = alloc_wrksp(inode_tbl_length, dynstg_fsit_inotbl, I_am_logredo, (void **) &inotbl); if (efsw_rc == FSCK_OK) { /* we got the inode table */ memcpy((void *)&(inotbl->eyecatcher), (void *)"FSAITINO", 8); inoexttbl->inotbl[0] = inotbl; } efsw_exit: return (efsw_rc); } /**************************************************************************** * NAME: establish_io_buffers * * FUNCTION: Allocate storage for dedicated I/O buffers. * * PARAMETERS: none * * NOTES: The I/O buffers are described in the aggregate record. * * RETURNS: * success: FSCK_OK * failure: something else */ int establish_io_buffers() { int eiob_rc = FSCK_OK; int I_am_logredo = 0; eiob_rc = alloc_wrksp(IAG_IO_BUFSIZE, dynstg_iobufs, I_am_logredo, (void **) &(agg_recptr->iag_buf_ptr)); if (eiob_rc == FSCK_OK) { /* successful IAG allocation */ agg_recptr->iag_buf_length = sizeof (struct iag); agg_recptr->iag_buf_data_len = 0; agg_recptr->iag_agg_offset = 0; agg_recptr->iag_buf_write = 0; agg_recptr->bmapdm_buf_ptr = agg_recptr->iag_buf_ptr; agg_recptr->bmapdm_buf_length = IAG_IO_BUFSIZE; agg_recptr->bmapdm_buf_data_len = 0; agg_recptr->bmapdm_agg_offset = 0; agg_recptr->bmapdm_buf_write = 0; } if (eiob_rc == FSCK_OK) { /* successful IAG allocation */ eiob_rc = alloc_wrksp(INODE_IO_BUFSIZE, dynstg_iobufs, I_am_logredo, (void **) &(agg_recptr->ino_buf_ptr)); } if (eiob_rc == FSCK_OK) { /* successful inode allocation */ agg_recptr->ino_buf_length = INODE_IO_BUFSIZE; agg_recptr->ino_buf_data_len = 0; agg_recptr->ino_buf_agg_offset = 0; agg_recptr->ino_buf_write = 0; eiob_rc = alloc_wrksp(NODE_IO_BUFSIZE, dynstg_iobufs, I_am_logredo, (void **) &(agg_recptr->node_buf_ptr)); } if (eiob_rc == FSCK_OK) { /* successful node allocation */ agg_recptr->node_buf_length = NODE_IO_BUFSIZE; agg_recptr->node_buf_data_len = 0; agg_recptr->node_agg_offset = 0; agg_recptr->node_buf_write = 0; eiob_rc = alloc_wrksp(NODE_IO_BUFSIZE, dynstg_iobufs, I_am_logredo, (void **) &(agg_recptr->dnode_buf_ptr)); } if (eiob_rc == FSCK_OK) { /* successful dnode allocation */ agg_recptr->dnode_buf_length = NODE_IO_BUFSIZE; agg_recptr->dnode_buf_data_len = 0; agg_recptr->dnode_agg_offset = 0; agg_recptr->dnode_buf_write = 0; eiob_rc = alloc_wrksp(MAPLEAF_IO_BUFSIZE, dynstg_iobufs, I_am_logredo, (void **) &(agg_recptr->mapleaf_buf_ptr)); } if (eiob_rc == FSCK_OK) { /* successful mapleaf allocation */ agg_recptr->mapleaf_buf_length = MAPLEAF_IO_BUFSIZE; agg_recptr->mapleaf_buf_data_len = 0; agg_recptr->mapleaf_agg_offset = 0; agg_recptr->mapleaf_buf_write = 0; eiob_rc = alloc_wrksp(MAPCTL_IO_BUFSIZE, dynstg_iobufs, I_am_logredo, (void **) &(agg_recptr->mapctl_buf_ptr)); } if (eiob_rc == FSCK_OK) { /* successful map control allocation */ agg_recptr->mapctl_buf_length = MAPCTL_IO_BUFSIZE; agg_recptr->mapctl_buf_data_len = 0; agg_recptr->mapctl_agg_offset = 0; agg_recptr->mapctl_buf_write = 0; eiob_rc = alloc_wrksp(BMAPLV_IO_BUFSIZE, dynstg_iobufs, I_am_logredo, (void **) &(agg_recptr->bmaplv_buf_ptr)); } if (eiob_rc == FSCK_OK) { /* successful map level allocation */ agg_recptr->bmaplv_buf_length = BMAPLV_IO_BUFSIZE; agg_recptr->bmaplv_buf_data_len = 0; agg_recptr->bmaplv_agg_offset = 0; agg_recptr->bmaplv_buf_write = 0; } return (eiob_rc); } /**************************************************************************** * NAME: establish_wsp_block_map * * FUNCTION: If the in-aggregate fsck workspace is available for use, * initialize it as the fsck workspace block map. * * Otherwise, obtain and initialize dynamic storage for the fsck * workspace block map. * * PARAMETERS: none * * NOTES: The fsck workspace block map is described in the aggregate record. * * If the in-aggregate fsck workspace is used, the aggregate record * fields describe the dedicated I/O buffer used for the fsck workspace * block map. Otherwise, they describe the entire workspace block * map in dynamic storage. * * RETURNS: * success: FSCK_OK * failure: something else */ int establish_wsp_block_map() { int ewbm_rc = FSCK_OK; int64_t blkmap_size_bytes; int64_t blkmap_size_in_pages; int64_t idx; int64_t this_device_offset; int I_am_logredo = 0; ewbm_rc = establish_wsp_block_map_ctl(); if (ewbm_rc != FSCK_OK) goto ewbm_exit; /* allocated and initialized blk map ctl page */ blkmap_size_bytes = agg_recptr->ondev_wsp_byte_length; agg_recptr->blkmp_pagecount = blkmap_size_bytes / BYTESPERPAGE; /* * whether or not we actually write to the on-disk * fsck workspace, this buffer represents it logically. */ agg_recptr->blkmp_agg_offset = agg_recptr->ondev_wsp_byte_offset + BYTESPERPAGE; agg_recptr->blkmp_blkmp_offset = 0; agg_recptr->blkmp_buf_data_len = 0; agg_recptr->blkmp_buf_write = 0; agg_recptr->blkmp_blkmp_offset = 0; agg_recptr->blkmp_buf_data_len = 0; agg_recptr->blkmp_buf_write = 0; if (agg_recptr->processing_readonly) { /* can't touch the aggregate */ ewbm_rc = alloc_wrksp(blkmap_size_bytes, dynstg_blkmap, I_am_logredo, (void **) &(agg_recptr->blkmp_buf_ptr)); if (ewbm_rc == FSCK_OK) { /* allocated and initialized block map */ wsp_dynstg_object = 0; wsp_dynstg_action = 0; agg_recptr->blkmp_buf_length = blkmap_size_bytes; agg_recptr->blkmp_buf_data_len = agg_recptr->blkmp_buf_length; } goto ewbm_exit; } /* use storage reserved for fsck in the aggregate */ ewbm_rc = alloc_wrksp(BLKMP_IO_BUFSIZE, dynstg_blkmap_buf, I_am_logredo, (void **) &(agg_recptr->blkmp_buf_ptr)); if (ewbm_rc != FSCK_OK) goto ewbm_exit; /* allocated and initialized block map */ agg_recptr->blkmp_buf_length = BLKMP_IO_BUFSIZE; agg_recptr->blkmp_buf_data_len = agg_recptr->blkmp_buf_length; ewbm_rc = blkmap_put_ctl_page(agg_recptr->blkmp_ctlptr); if (ewbm_rc != FSCK_OK) goto ewbm_exit; /* successful write to Block Map Control Page */ /* this is guaranteed (by mkfs) to be an even number */ blkmap_size_in_pages = blkmap_size_bytes / BYTESPERPAGE; /* Swap to little-endian */ ujfs_swap_fsck_blk_map_page(agg_recptr->blkmp_buf_ptr); for (idx = 1; ((idx < blkmap_size_in_pages) && (ewbm_rc == FSCK_OK)); idx++) { /* for each map page (after the control page) */ this_device_offset = agg_recptr->ondev_wsp_byte_offset + (idx * BYTESPERPAGE); /* * write the initialized buffer page to * the map page on disk */ ewbm_rc = ujfs_rw_diskblocks(Dev_IOPort, this_device_offset, BYTESPERPAGE, (void *) agg_recptr->blkmp_buf_ptr, PUT); if (ewbm_rc != FSCK_OK) { /* I/O failure */ /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 1); /* * message to debugger */ fsck_send_msg(fsck_ERRONWSP, ewbm_rc, ewbm_rc, fsck_WRITE, (long long)this_device_offset, BYTESPERPAGE, -1); } } /* Swap back to cpu-endian */ ujfs_swap_fsck_blk_map_page(agg_recptr->blkmp_buf_ptr); ewbm_exit: return (ewbm_rc); } /**************************************************************************** * NAME: establish_wsp_block_map_ctl * * FUNCTION: If the in-aggregate fsck workspace is available for use, * initialize the first page as the fsck workspace block map control * page. * * Otherwise, obtain and initialize dynamic storage for the fsck * workspace block map control page. * * PARAMETERS: none * * NOTES: The fsck workspace block map is described in the aggregate record. * * If the in-aggregate fsck workspace is used, the aggregate record * fields describe the dedicated I/O buffer used for the fsck workspace * block map. Otherwise, they describe the entire workspace block * map in dynamic storage. * * RETURNS: * success: FSCK_OK * failure: something else */ int establish_wsp_block_map_ctl() { int ewbmc_rc = FSCK_OK; time_t Current_Time; int64_t this_device_offset = 0; int I_am_logredo = 0; ewbmc_rc = alloc_wrksp(sizeof (struct fsck_blk_map_hdr), dynstg_blkmap_hdr, I_am_logredo, (void **) &(agg_recptr->blkmp_ctlptr)); if (ewbmc_rc == FSCK_OK) { /* allocated and initialized blk map ctl page */ /* fill eyecatcher */ strncpy(agg_recptr->blkmp_ctlptr->hdr.eyecatcher, fbmh_eyecatcher_string, strlen(fbmh_eyecatcher_string)); agg_recptr->blkmp_ctlptr->hdr.super_buff_addr = (char *) sb_ptr; agg_recptr->blkmp_ctlptr->hdr.agg_record_addr = (char *) agg_recptr; agg_recptr->blkmp_ctlptr->hdr.bmap_record_addr = (char *) bmap_recptr; agg_recptr->blkmp_ctlptr->hdr.fscklog_full = agg_recptr->fscklog_full; agg_recptr->blkmp_ctlptr->hdr.fscklog_buf_allocated = agg_recptr->fscklog_buf_allocated; agg_recptr->blkmp_ctlptr->hdr.fscklog_buf_alloc_err = agg_recptr->fscklog_buf_alloc_err; agg_recptr->blkmp_ctlptr->hdr.fscklog_agg_offset = agg_recptr->ondev_fscklog_byte_offset; Current_Time = time(NULL); fsck_DateTime = localtime(&Current_Time); sprintf(&(agg_recptr->blkmp_ctlptr->hdr.start_time[0]), "%d/%d/%d %d:%02d:%02d", fsck_DateTime->tm_mon + 1, fsck_DateTime->tm_mday, (fsck_DateTime->tm_year + 1900), fsck_DateTime->tm_hour, fsck_DateTime->tm_min, fsck_DateTime->tm_sec); if (!(agg_recptr->processing_readonly)) { /* * use storage reserved for fsck in the * aggregate */ ewbmc_rc = blkmap_put_ctl_page(agg_recptr->blkmp_ctlptr); if (ewbmc_rc != FSCK_OK) { /* I/O failure */ /* * message to user */ fsck_send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label, 1); /* * message to debugger */ fsck_send_msg(fsck_ERRONWSP, ewbmc_rc, ewbmc_rc, fsck_WRITE, (long long) this_device_offset, BYTESPERPAGE, -1); } } } return (ewbmc_rc); } /***************************************************************************** * NAME: extent_1stref_chk * * FUNCTION: Determine whether the given extent contains the first reference * to a multiply-allocated block. If it does, perform duplicate * allocation processing on the owning inode. * * PARAMETERS: * first_block - input - ordinal number of the first block in the extent * to check * last_block - input - ordinal number of the last block in the extent * to check * is_EA - input - !0 => the extent contains an inode's EA * 0 => the extent contains something else * msg_info_ptr - input - pointer to a data area containing information * needed to issue messages for this extent * ino_recptr - input - pointer to the fsck inode record describing the * inode to which this extent is allocated * * NOTES: As fsck scans the inodes sequentially, recording the blocks * allocated, it doesn't know a particular block is multiply-allocated * until the second reference is detected. At that time the first * reference to the block is unresolved since no list of owners is * built (only a count of owners, in which a 1 in the bit map * represents a count of 1). * * After all inodes have been scanned and their block allocations * recorded, if any multiply-allocated blocks have been detected, the * inodes are scanned sequentially again until all first references to * multiply-allocated blocks are resolved. This routine is invoked * during that rescan. * * RETURNS: * success: FSCK_OK * failure: something else */ int extent_1stref_chk(int64_t first_block, int64_t last_block, int8_t is_EA, int8_t is_ACL, struct fsck_ino_msg_info *msg_info_ptr, struct fsck_inode_record *ino_recptr) { int eq_rc = FSCK_OK; uint32_t size_of_dup_range = 0; int dups_detected = 0; struct dupall_blkrec *blkrec; while (agg_recptr->unresolved_1stref_count) { blkrec = dupall_find_blkrec(first_block, last_block); if (!blkrec) break; if (blkrec->first_ref_resolved) { if (blkrec->last_blk <= last_block) { first_block = blkrec->last_blk + 1; continue; } break; } /* * If the record goes outside this extent, we need to split * it, since we are only interested in the intersection of * the record and this extent */ if ((blkrec->first_blk < first_block) || (blkrec->last_blk > last_block)) { eq_rc = blkall_split_blkrec(blkrec, first_block, last_block); if (eq_rc) return eq_rc; /* * Check if the split caused the current record to * precede the extent we are processing */ if (blkrec->first_blk < first_block) continue; } dups_detected = 1; blkrec->first_ref_resolved = 1; agg_recptr->unresolved_1stref_count--; if (msg_info_ptr) { size_of_dup_range = blkrec->last_blk - blkrec->first_blk + 1; fsck_send_msg(fsck_DUPBLKREF, size_of_dup_range, (long long) blkrec->first_blk, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } if (dups_detected && msg_info_ptr) { ino_recptr->involved_in_dups = 1; fsck_send_msg(fsck_DUPBLKREFS, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); if (!(inode_is_metadata(ino_recptr))) { agg_recptr->corrections_needed = 1; if (is_EA) ino_recptr->clr_ea_fld = 1; else if (is_ACL) ino_recptr->clr_acl_fld = 1; else ino_recptr->selected_to_rls = 1; } } return (FSCK_OK); } /**************************************************************************** * NAME: blkall_ref_check * * FUNCTION: Determine whether the given blocks are multiply-allocated and, if * so, whether the first reference to it is unresolved. (In this * case, the current reference must be the first reference.) * * PARAMETERS: * first_block - input - ordinal number of the first filesystem block to * be checked * last_block - input - ordinal number of the last filesystem block to * be checked * * RETURNS: * success: FSCK_OK * failure: something else */ int blkall_ref_check(int64_t first_block, int64_t last_block) { return extent_1stref_chk(first_block, last_block, 0, 0, 0, 0); } /***************************************************************************** * NAME: extent_record_dupchk * * FUNCTION: Validate that the block number in the given extent are valid * within the range valid for the aggregate (after the reserved * space and fixed metadata and before the fsck workspace), * record that the blocks are allocated, determine whether any * prior allocations of the blocks have been recorded and, if * so, perform duplicate allocation processing on the owning inode. * * PARAMETERS: * first_block - input - ordinal number of the first block in the extent * to check * last_block - input - ordinal number of the last block in the extent * to check * is_EA - input - !0 => the extent contains an inode's EA * 0 => the extent contains something else * msg_info_ptr - input - information needed to issue messages for this * extent. If NULL, no messages will be issued * ino_recptr - input - pointer to the fsck inode record describing the * inode to which this extent is allocated * * RETURNS: * success: FSCK_OK * failure: something else */ int extent_record_dupchk(int64_t first_block, int64_t last_block, int8_t range_adj, int8_t is_EA, int8_t is_ACL, struct fsck_ino_msg_info *msg_info_ptr, struct fsck_inode_record *ino_recptr) { int erd_rc = FSCK_OK; int dups_detected = 0; struct dupall_blkrec *this_blkrec; if (range_adj) { /* the xad described an invalid range */ fsck_send_msg(fsck_BADBLKNO, fsck_ref_msg(msg_info_ptr->msg_dxdtyp), fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } /* * Look for duplicate blocks already detected for this extent */ while (first_block <= last_block) { this_blkrec = dupall_find_blkrec(first_block, last_block); if (!this_blkrec) break; /* * If this record goes beyond the extent, we need to split it. */ if ((this_blkrec->first_blk < first_block) || (this_blkrec->last_blk > last_block)) { erd_rc = blkall_split_blkrec(this_blkrec, first_block, last_block); if (erd_rc) return erd_rc; /* * Check if the split caused the current record to * precede the extent we are processing */ if (this_blkrec->first_blk < first_block) continue; } /* * Take care of the blocks preceding this record (if any) */ if (first_block < this_blkrec->first_blk) { erd_rc = blkall_increment_owners(first_block, this_blkrec->first_blk - 1, msg_info_ptr); if (erd_rc < 0) return erd_rc; else if (erd_rc) dups_detected = 1; } this_blkrec->owner_count++; first_block = this_blkrec->last_blk + 1; } /* * Take care of any remaining blocks */ if (first_block <= last_block) { erd_rc = blkall_increment_owners(first_block, last_block, msg_info_ptr); if (erd_rc < 0) return erd_rc; else if (erd_rc) dups_detected = 1; } if (dups_detected && msg_info_ptr) { /* claims at least 1 multiply allocated block */ ino_recptr->involved_in_dups = 1; fsck_send_msg(fsck_DUPBLKREFS, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); if (!(inode_is_metadata(ino_recptr))) { agg_recptr->corrections_needed = 1; if (is_EA) ino_recptr->clr_ea_fld = 1; else if (is_ACL) ino_recptr->clr_acl_fld = 1; else ino_recptr->selected_to_rls = 1; } } return (FSCK_OK); } /***************************************************************************** * NAME: extent_record * * FUNCTION: Record that each of the blocks in the given extent is allocated * to some inode. * * PARAMETERS: * first_block - input - ordinal number of the first block in the extent * to check * last_block - input - ordinal number of the last block in the extent * to check * * NOTES: Originally, this was intended to be a streamlined version of * extent_record_dupchk, called only when the extent was known to * not be multilply allocated. However, it really wasn't any more * efficient, so its simpler to just call extent_record_dupchk here. * * RETURNS: * success: FSCK_OK * failure: something else */ int extent_record(int64_t first_block, int64_t last_block) { return extent_record_dupchk(first_block, last_block, 0, 0, 0, 0, 0); } /***************************************************************************** * NAME: extent_unrecord * * FUNCTION: Decrement, in the fsck workspace block record, the owner count * for each block in the given extent. * * PARAMETERS: * first_block - input - ordinal number of the first block in the extent * to check * last_block - input - ordinal number of the last block in the extent * to check * * NOTES: Under certain circumstances, it is necessary to back out the record * of an inode's ownership the recording of some extent already verified * valid. * * This function could be accomplished using other routines which * include extent validation code, but, for performance reasons, * this streamlined routine exists to minimize processing time. * * Examples of these circumstances include: * o Storage allocated for an inode's EA is valid, but the B+Tree * rooted in the inode is structurally corrupt. Then the portions * of the tree which were recorded before the corruption was detected * were backed out using routines which include validation code, and * finally this routine is called to 'unrecord' the storage allocated * for the EA. * * o The B+Tree rooted in an inode was verified structurally correct, * but the di_nblocks in the inode was found to be inconsistent with * the tree. In this case we assume the tree to be corrupt and * back it out of the fsck workspace block map immediately. This * routine would be used for that purpose since the tree has already * been verified structurally correct. * * o An inode has been found to be valid, but claims ownership of at * least one block claimed by another inode. At least one of the * inodes is actually damaged. The user has given permission to * delete this inode, and so we need to decrement the number of * owners for each block allocated to this inode. This routine * would be used for that purpose since the tree has already been * verified structurally correct. * * * RETURNS: * success: FSCK_OK * failure: something else */ int extent_unrecord(int64_t first_block, int64_t last_block) { int eu_rc = FSCK_OK; struct dupall_blkrec *this_blkrec; while (first_block <= last_block) { this_blkrec = dupall_find_blkrec(first_block, last_block); if (!this_blkrec) break; /* * If this record goes beyond the extent, we need to split it. */ if ((this_blkrec->first_blk < first_block) || (this_blkrec->last_blk > last_block)) { eu_rc = blkall_split_blkrec(this_blkrec, first_block, last_block); if (eu_rc) return eu_rc; /* * Check if the split caused the current record to * precede the extent we are processing */ if (this_blkrec->first_blk < first_block) continue; } /* * Take care of the blocks preceding this record (if any) */ if (first_block < this_blkrec->first_blk) { eu_rc = blkall_mark_free(first_block, this_blkrec->first_blk - 1); if (eu_rc) return eu_rc; } this_blkrec->owner_count--; if (this_blkrec->owner_count == 1) { /* No longer a duplicate */ if (!this_blkrec->first_ref_resolved) agg_recptr->unresolved_1stref_count--; agg_recptr->dup_block_count--; dupall_extract_blkrec(this_blkrec); } first_block = this_blkrec->last_blk + 1; } /* * Take care of any remaining blocks */ if (first_block <= last_block) eu_rc = blkall_mark_free(first_block, last_block); return (eu_rc); } /**************************************************************************** * NAME: fsblk_count_avail * * FUNCTION: Count the number of contiguous aggregate blocks which are * available, according to the fsck workspace block map, starting * with the given (available) aggregate block. * * PARAMETERS: * wspbits - input - pointer to a page in the fsck workspace block map * wordidx - input - the ordinal number, in the page pointed to by * wspbits, of the word containing the bit representing * some particular aggregate block. * at routine entry: the block represented is the available * block with which counting should start * at routine exit: the block represented is the 1st block * AFTER the last block counted * bitidx - input - the ordinal number, in the word identified by wordidx, * of the bit representing some particular aggregate block. * at routine entry: the block represented is the available * block with which counting should start * at routine exit: the block represented is the 1st block * AFTER the last block counted * num_wanted - input - number of blocks wanted. (i.e., when to stop counting * even if the run of contiguous, available blocks has * not ended. * num_avail - input - number of contiguous, available blocks counted starting * with the block described by wspbits, wordidx, and * bitidx when the routine was entered. * * RETURNS: * success: FSCK_OK * failure: something else */ int fsblk_count_avail(uint32_t * wspbits, int32_t * wordidx, int32_t * bitidx, int32_t num_wanted, int32_t * num_avail) { int fbca_rc = FSCK_OK; int done_counting = 0; uint32_t bitmask; *num_avail = 0; while (((*wordidx) < LPERDMAP) && (!done_counting)) { bitmask = 0x80000000u; bitmask = bitmask >> (*bitidx); while (((*bitidx) < DBWORD) && (!done_counting)) { if (wspbits[*wordidx] & bitmask) { /* this one's not available */ done_counting = -1; } else { /* this one's available */ (*num_avail)++; if ((*num_avail) == num_wanted) { done_counting = -1; } else { bitmask = bitmask >> 1; } (*bitidx)++; } } /* end while bitidx */ if (!done_counting) { *bitidx = 0; *wordidx += 1; } } return (fbca_rc); } /**************************************************************************** * NAME: fsblk_next_avail * * FUNCTION: Find the next available aggregate block, according to the * fsck workspace block map, starting with the given block. * * PARAMETERS: * wspbits - input - pointer to a page in the fsck workspace block map * startword - input - the ordinal number, in the page pointed to by * wspbits, of the word containing the bit representing * the aggregate block at which to start searching * startbit - input - the ordinal number, in the word identified by wordidx, * of the bit representing the aggregate block at which * to start searching * foundword - input - the ordinal number, in the page pointed to by * wspbits, of the word containing the bit representing * the available aggregate block found, if any * foundbit - input - the ordinal number, in the word identified by wordidx, * of the bit representing the available aggregate block, * if any * block_found - input - pointer to a variable in which the search results are * returned. !0 => an available block was found in the * given page at/after the specified start * 0 => no available block was found in the * given page at/after the specified start * * RETURNS: * success: FSCK_OK * failure: something else */ int fsblk_next_avail(uint32_t * wspbits, int32_t startword, int32_t startbit, int32_t * foundword, int32_t * foundbit, int *block_found) { int fbna_rc = FSCK_OK; int32_t wordidx, bitidx, firstbit; uint32_t bitmask; uint32_t mask_all_on = 0xFFFFFFFFu; *block_found = 0; firstbit = startbit; for (wordidx = startword; ((wordidx < LPERDMAP) && (!(*block_found))); wordidx++) { if (wspbits[wordidx] != mask_all_on) { /* a zero in this map word */ bitmask = 0x80000000u; bitmask = bitmask >> firstbit; for (bitidx = firstbit; ((bitidx < DBWORD) && (!(*block_found))); bitidx++) { if (!(wspbits[wordidx] & bitmask)) { /* it's available */ *foundword = wordidx; *foundbit = bitidx; *block_found = -1; } else { /* it's in use */ bitmask = bitmask >> 1; } } } firstbit = 0; } return (fbna_rc); } /**************************************************************************** * NAME: fsck_alloc_fsblks * * FUNCTION: Allocate storage in the aggregate. * * PARAMETERS: * blocks_wanted - input - the number of contiguous blocks of storage * wanted * blocks - input - pointer to a variable in which the ordinal * number of the first block allocated will be * returned (or 0 if the storage cannot be * allocated) * * NOTES: o This routine is only called when fsck has write access to the * aggregate. * * o This routine can not be called before the end of Phase 1 (that is, * not before all block allocations existing in the aggregate have * been recorded in the fsck workspace block map). * * o The optimum time to call this routine is after all inode repairs * have been performed (a step performed in Phase 6) since aggregates * blocks may be made available by releasing inodes and/or clearing * extents allocated for EAs. * * o This routine can not be called after the beginning of Phase 8 (that * is, not after fsck begins to rebuild the aggregate block map from * the information in the fsck workspace block map). * * o Currently, this routine is only called * - during inode reconnect processing (the last step in Phase 6) to * create new internal nodes for the directory to which the inode(s) * is(are) reconnected. * - during replication of the Aggregate Inode Map (Phase 7) when * building the tree for the fileset AIM inode. * * RETURNS: * success: FSCK_OK * failure: something else */ int fsck_alloc_fsblks(int32_t blocks_wanted, int64_t * blocks) { int fafsb_rc = FSCK_OK; int64_t wsp_pagenum = 0; struct fsck_blk_map_page *wsp_page = NULL; int32_t this_word = 0, this_bit = 0; int32_t found_word = -1, found_bit = -1; int found_a_block; int32_t blocks_found = 0; uint32_t *wsp_bits; *blocks = 0; while ((wsp_pagenum < agg_recptr->blkmp_pagecount) && (blocks_found != blocks_wanted) && (fafsb_rc == FSCK_OK)) { fafsb_rc = blkmap_get_page(wsp_pagenum, &wsp_page); if (fafsb_rc == FSCK_OK) { /* got a page */ wsp_bits = (uint32_t *) wsp_page; this_word = 0; this_bit = 0; found_a_block = 0; blocks_found = 0; fafsb_rc = fsblk_next_avail(wsp_bits, this_word, this_bit, &found_word, &found_bit, &found_a_block); while ((found_a_block) && (fafsb_rc == FSCK_OK) && (blocks_found != blocks_wanted)) { this_word = found_word; this_bit = found_bit; blocks_found = 0; fafsb_rc = fsblk_count_avail(wsp_bits, &found_word, &found_bit, blocks_wanted, &blocks_found); if (fafsb_rc == FSCK_OK) { /* nothing bizarre happened */ if (blocks_found == blocks_wanted) { /* success! */ *blocks = (wsp_pagenum << log2BITSPERPAGE) + (this_word << log2BITSPERDWORD) + this_bit; } else { /* word containing 1st 1 after the zeroes */ this_word = found_word; /* bit postion in that word */ this_bit = found_bit; found_a_block = 0; fafsb_rc = fsblk_next_avail(wsp_bits, this_word, this_bit, &found_word, &found_bit, &found_a_block); } } } if ((fafsb_rc == FSCK_OK) && (!found_a_block)) { /* no avail block found */ /* maybe in the next page */ wsp_pagenum++; } } } if (fafsb_rc == FSCK_OK) { /* nothing fatal along the way */ if ((*blocks) == 0) { /* didn't find the blocks */ fafsb_rc = FSCK_BLKSNOTAVAILABLE; fsck_send_msg(fsck_EXHFILSYSSTG, blocks_wanted); } else if ((*blocks) > agg_recptr->highest_valid_fset_datablk) { /* * the first available blocks were in the work area */ *blocks = 0; fafsb_rc = FSCK_BLKSNOTAVAILABLE; fsck_send_msg(fsck_EXHFILSYSSTG, blocks_wanted); } else { /* we found the requested blocks */ /* * allocate these blocks for the caller * by marking them 'in use' in the fsck * workspace block map */ fafsb_rc = extent_record(*blocks, (*blocks + blocks_wanted - 1)); } } return (fafsb_rc); } /**************************************************************************** * NAME: fsck_dealloc_fsblks * * FUNCTION: Deallocate storage in the aggregate. * * PARAMETERS: * blk_length - input - the number of contiguous aggregate blocks * to release * first_blk - input - the ordinal number of the first allocated * aggregate block to release * * NOTES: o This routine is only called when fsck has write access to the * aggregate. * * o This routine can only be called to release blocks whose allocation * has already been recorded in the fsck workspace block map. * * o This routine can not be called after the beginning of Phase 8 (that * is, not after fsck begins to rebuild the aggregate block map from * the information in the fsck workspace block map). * * o Currently, this routine is only called during Phase 6, during inode * repair processing to release internal nodes from a directory while * removing a directory entry and during reconnect processing to back * out partial processing for directory entry add which cannot be * completed because of a storage allocation failure. * * RETURNS: * success: FSCK_OK * failure: something else */ int fsck_dealloc_fsblks(int32_t blk_length, int64_t first_blk) { int fdfsb_rc = FSCK_OK; /* * deallocate these blocks by marking * them 'available' in the fsck workspace * block map */ fdfsb_rc = extent_unrecord(first_blk, (first_blk + blk_length - 1)); return (fdfsb_rc); } /**************************************************************************** * NAME: fscklog_end * * FUNCTION: Put the last buffer in the fsck service log. Cleanup the * first record in any remaining pages in this service log * on the device so the log reader will know when to stop. * * PARAMETERS: none * * NOTES: If we don't have write access then there's nothing to do. * * RETURNS: * success: FSCK_OK */ int fscklog_end() { int fle_rc = FSCK_OK; int32_t buffer_bytes_left; /* * If there's a partial buffer, write it to the device */ if (agg_recptr->fscklog_buf_data_len > 0) { /* * there's something in there to be written */ buffer_bytes_left = agg_recptr->fscklog_buf_length - agg_recptr->fscklog_buf_data_len; agg_recptr->fscklog_last_msghdr->entry_length += __le16_to_cpu((int16_t) buffer_bytes_left); fscklog_put_buffer(); } /* disable logging for the duration */ agg_recptr->fscklog_buf_allocated = 0; return (fle_rc); } /**************************************************************************** * NAME: fscklog_init * * FUNCTION: Initialize the current fsck service log * * PARAMETERS: none * * NOTES: - If we have write access to the aggregate, write * nulls over all pages in the log so that garbage * from a prior run does not end up appended to the * current service log. * * - This MUST be called before logredo since logredo * will write messages to the fsck service log. * * RETURNS: * success: FSCK_OK */ int fscklog_init() { int fli_rc = FSCK_OK; int64_t log_bytes_left; struct fsck_blk_map_page *tmpbuf_addr = NULL; struct fsck_blk_map_page *tmp_buf_ptr; uint32_t tmp_buf_data_len; int64_t tmp_agg_offset; int64_t tmp_log_offset; if (agg_recptr->processing_readwrite) { /* have write access */ /* * this is safe because we do it before calling logredo */ tmpbuf_addr = (struct fsck_blk_map_page *) malloc(FSCKLOG_BUFSIZE); if (tmpbuf_addr == NULL) { /* didn't get the space */ /* log this fact so that any residual messages will be ignored */ fsck_send_msg(fsck_CANTINITSVCLOG); } else { /* temp buffer allocated */ agg_recptr->initializing_fscklog = 1; memset((void *) tmpbuf_addr, 0, FSCKLOG_BUFSIZE); /* * save the current fscklog values */ tmp_buf_ptr = agg_recptr->fscklog_buf_ptr; tmp_buf_data_len = agg_recptr->fscklog_buf_data_len; tmp_agg_offset = agg_recptr->fscklog_agg_offset; tmp_log_offset = agg_recptr->fscklog_log_offset; /* * store values to describe the temp buffer */ agg_recptr->fscklog_buf_ptr = tmpbuf_addr; agg_recptr->fscklog_buf_data_len = FSCKLOG_BUFSIZE; log_bytes_left = (agg_recptr->ondev_fscklog_byte_length / 2) - agg_recptr->fscklog_log_offset; while (log_bytes_left >= agg_recptr->fscklog_buf_length) { fscklog_put_buffer(); log_bytes_left = (agg_recptr->ondev_fscklog_byte_length / 2) - agg_recptr->fscklog_log_offset; } /* end while */ free((void *) tmpbuf_addr); /* * restore the actual fscklog values */ agg_recptr->fscklog_buf_ptr = tmp_buf_ptr; agg_recptr->fscklog_buf_data_len = tmp_buf_data_len; agg_recptr->fscklog_agg_offset = tmp_agg_offset; agg_recptr->fscklog_log_offset = tmp_log_offset; agg_recptr->initializing_fscklog = 0; } } return (fli_rc); } /**************************************************************************** * NAME: fscklog_start * * FUNCTION: Allocate an I/O buffer and log the fsck start. * * PARAMETERS: none * * NOTES: Even if we don't have write access to the * aggregate we will do all parts of logging except * actually writing to the disk. This is to * provide diagnostic information if a dump is * taken during fsck execution. * * RETURNS: * success: FSCK_OK */ int fscklog_start() { int fls_rc = FSCK_OK; int iml_rc = FSCK_OK; int I_am_logredo = 0; iml_rc = alloc_wrksp(FSCKLOG_BUFSIZE, dynstg_iobufs, I_am_logredo, (void **) &(agg_recptr->fscklog_buf_ptr)); if (iml_rc == FSCK_OK) { /* successful fsck service log buffer alloc */ agg_recptr->fscklog_buf_length = FSCKLOG_BUFSIZE; agg_recptr->fscklog_buf_data_len = 0; agg_recptr->fscklog_log_offset = 0; agg_recptr->fscklog_full = 0; agg_recptr->fscklog_buf_allocated = -1; agg_recptr->fscklog_buf_alloc_err = 0; } else { agg_recptr->fscklog_buf_allocated = 0; agg_recptr->fscklog_buf_alloc_err = -1; } return (fls_rc); } /**************************************************************************** * NAME: get_inode_extension * * FUNCTION: Allocates workspace storage for an fsck inode extension record * * PARAMETERS: * inoext_ptr - input - pointer to a variable in which the address of the * new inode extension will be returned. * * RETURNS: * success: FSCK_OK * failure: something else */ int get_inode_extension(struct fsck_inode_ext_record **inoext_ptr) { int gir_rc = FSCK_OK; int I_am_logredo = 0; if (agg_recptr->free_inode_extens != NULL) { *inoext_ptr = agg_recptr->free_inode_extens; agg_recptr->free_inode_extens = agg_recptr->free_inode_extens->next; memset(*inoext_ptr, 0, sizeof (struct fsck_inode_ext_record)); } else { gir_rc = alloc_wrksp(sizeof (struct fsck_inode_ext_record), dynstg_inoextrec, I_am_logredo, (void **) inoext_ptr); } return (gir_rc); } /**************************************************************************** * NAME: get_inorecptr * * FUNCTION: Return a pointer to the fsck inode record describing the * specified inode. * * If no such record exists, then if allocation is specified, * allocate one, insert it into the fsck workspace inode record * structures, and return the address of the new record. Otherwise, * (no such record exists but allocation was not specified) return * NULL. * * PARAMETERS: * is_aggregate - input - !0 => the requested inode is owned by the aggregate * 0 => the requested inode is owned by the fileset * alloc - input - !0 => do allocate a record if none has yet been * allocated for the inode * 0 => do not allocate a record if none has been * allocated for the inode * inonum - input - ordinal number of the inode whose fsck inode * record is wanted * addr_inorecptr - input - pointer to a variable in which the address of * of the found (or newly allocated) record will * be returned * * RETURNS: * success: FSCK_OK * failure: something else */ int get_inorecptr(int is_aggregate, int alloc, uint32_t inonum, struct fsck_inode_record **addr_inorecptr) { int gir_rc = FSCK_OK; if (is_aggregate) { /* for an aggregate inode */ if (alloc) { /* request is to allocate if not found */ gir_rc = inorec_agg_search_insert(inonum, addr_inorecptr); } else { /* search only */ gir_rc = inorec_agg_search(inonum, addr_inorecptr); } } else { /* for a fileset inode */ if (alloc) { /* request is to allocate if not found */ gir_rc = inorec_fs_search_insert(inonum, addr_inorecptr); } else { /* search only */ gir_rc = inorec_fs_search(inonum, addr_inorecptr); } } return (gir_rc); } /**************************************************************************** * NAME: get_inorecptr_first * * FUNCTION: Return a pointer to the fsck inode record describing the inode * which has the lowest ordinal number of all allocated inodes in * the specified group (i.e., either of all allocated aggregate * inodes or of all allocated fileset inodes). * * Initialize the balanced binary sort tree header record for a * sequential traversal of the nodes in the tree. * * PARAMETERS: * is_aggregate - input - !0 => the requested inode is owned by the aggregate * 0 => the requested inode is owned by the fileset * inonum - input - pointer to a variable in which to return the ordinal * number of the inode whose fsck inode record address * is being returned in addr_inorecptr * addr_inorecptr - input - pointer to a variable in which the address of * of the fsck inode record will be returned * * NOTES: o This routine should not be called before the end of phase 1 during * which an fsck inode record is allocated to describe each inode in * the aggregate (both those owned by the aggregate and those owned by * the fileset in the aggregate). * * o At entry to this routine, if the nodes in the specified balanced binary * sort tree have not yet been linked into a sorted list, this list is * created for the specified balanced binary sort tree. * * o The fsck balanced binary sort tree header record contains the * fields describing the sorted list of nodes in the tree, which * are used to initialize a traversal and to remember the current * list position of the traversal. * * o Currently, this routine is only called for the balanced binary sort tree * containing fsck inode records describing fileset owned inodes. * * RETURNS: * success: FSCK_OK * failure: something else */ int get_inorecptr_first(int is_aggregate, uint32_t * inonum, struct fsck_inode_record **addr_inorecptr) { int girf_rc = FSCK_OK; int32_t iagidx, extidx, inoidx; struct inode_ext_tbl_t *inoexttbl; struct inode_tbl_t *inotbl; /* * find first active aggregate inode record */ if (is_aggregate) { /* for an aggregate inode */ if (agg_recptr->AIT_ext0_tbl == NULL) { girf_rc = FSCK_INTERNAL_ERROR_68; fsck_send_msg(fsck_INTERNALERROR, girf_rc, 0, 0, 0); } else { /* * the first allocated aggregate inode is inode 1, * by definition. */ inoidx = 1; *addr_inorecptr = agg_recptr->AIT_ext0_tbl->inorectbl[inoidx]; agg_recptr->agg_last_inoidx = inoidx; } /* * find first active fileset inode record */ } else { /* for a fileset inode */ if (agg_recptr->FSIT_IAG_tbl == NULL) { girf_rc = FSCK_INTERNAL_ERROR_69; fsck_send_msg(fsck_INTERNALERROR, girf_rc, 0, 0, 0); } else { /* the table is allocated */ /* * IAG 0 is always the first active IAG in the * fileset and extent 0 is always the first active * extent since inode 2 (the root dir) is always * the first active inode. */ iagidx = 0; extidx = 0; inoidx = 2; inoexttbl = agg_recptr->FSIT_IAG_tbl->inoext_tbl[iagidx]; inotbl = inoexttbl->inotbl[extidx]; *addr_inorecptr = inotbl->inorectbl[inoidx]; /* * set things up for find next */ agg_recptr->fs_last_iagidx = iagidx; agg_recptr->fs_last_extidx = extidx; agg_recptr->fs_last_inoidx = inoidx; } } if (girf_rc == FSCK_OK) { /* got one */ *inonum = (*addr_inorecptr)->inonum; } return (girf_rc); } /**************************************************************************** * NAME: get_inorecptr_next * * FUNCTION: Return a pointer to the fsck inode record describing the inode * which has the ordinal number greater than the inode record most * recently returned in the current sequential traversal, and which * describes the lowest ordinal inode number of all records not yet * returned in the current traversal. * * That is, return a pointer to the fsck inode record describing * the 'next' inode in the group (i.e., either next among the * aggregate-owned inodes or next among the fileset-owned inodes). * * PARAMETERS: * is_aggregate - input - !0 => the requested inode is owned by the aggregate * 0 => the requested inode is owned by the fileset * inonum - input - pointer to a variable in which to return the ordinal * number of the inode whose fsck inode record address * is being returned in addr_inorecptr * addr_inorecptr - input - pointer to a variable in which the address of * of the fsck inode record will be returned. If * the most recently returned (in the current * traversal) record described the last inode in * the group, NULL is returned. * * NOTES: o This routine is called iteratively in order to traverse the * inodes in the specified group in ascending key order efficiently. * * o EACH sequential traversal of the inodes in a group (ie inodes * owned by the aggregate or inodes owned by the fileset) MUST be * initialized by an invocation of routine get_inorecptr_first. * * o The fsck balanced binary sort tree header record contains the * fields describing the sorted list of nodes in the tree, which * are used to initialize a traversal and to remember the current * list position of the traversal. * * o fsck inode records can be accessed randomly (via routine * get_inorecptr which accepts inode number as key) independently. * That is, invocations of get_inorecptr may be intermingled with * invocations of this routine (get_inorecptr_next) with no impact * on the sequential traversal in progress. * * RETURNS: * success: FSCK_OK * failure: something else */ int get_inorecptr_next(int is_aggregate, uint32_t * inonum, struct fsck_inode_record **addr_inorecptr) { int girn_rc = FSCK_OK; int32_t iagidx, extidx, inoidx; int32_t extidx_init, inoidx_init; struct inode_ext_tbl_t *inoexttbl; struct inode_tbl_t *inotbl; /* * find next active aggregate inode record */ if (is_aggregate) { /* for an aggregate inode */ if (agg_recptr->AIT_ext0_tbl == NULL) { girn_rc = FSCK_INTERNAL_ERROR_54; fsck_send_msg(fsck_INTERNALERROR, girn_rc, 0, 0, 0); } else { *addr_inorecptr = NULL; for (inoidx = agg_recptr->agg_last_inoidx + 1; ((inoidx < INOSPEREXT) && (*addr_inorecptr == NULL)); inoidx++) { agg_recptr->agg_last_inoidx = inoidx; if (agg_recptr->AIT_ext0_tbl-> inorectbl[inoidx] != NULL) { *addr_inorecptr = agg_recptr->AIT_ext0_tbl-> inorectbl[inoidx]; } } } goto girn_set_exit; } if (agg_recptr->FSIT_IAG_tbl == NULL) { girn_rc = FSCK_INTERNAL_ERROR_55; fsck_send_msg(fsck_INTERNALERROR, girn_rc, 0, 0, 0); goto girn_set_exit; } /* the table is allocated */ extidx_init = agg_recptr->fs_last_extidx; inoidx_init = agg_recptr->fs_last_inoidx + 1; *addr_inorecptr = NULL; for (iagidx = agg_recptr->fs_last_iagidx; ((iagidx < agg_recptr->fset_imap.num_iags) && (*addr_inorecptr == NULL)); iagidx++) { agg_recptr->fs_last_iagidx = iagidx; if (agg_recptr->FSIT_IAG_tbl-> inoext_tbl[iagidx] != NULL) { inoexttbl = agg_recptr->FSIT_IAG_tbl->inoext_tbl[iagidx]; for (extidx = extidx_init; ((extidx < EXTSPERIAG) && (*addr_inorecptr == NULL)); extidx++) { agg_recptr->fs_last_extidx = extidx; if (inoexttbl->inotbl[extidx] != NULL) { inotbl = inoexttbl->inotbl[extidx]; for (inoidx = inoidx_init; ((inoidx < INOSPEREXT) && (*addr_inorecptr == NULL)); inoidx++) { agg_recptr->fs_last_inoidx = inoidx; if (inotbl->inorectbl[inoidx] != NULL) { *addr_inorecptr = inotbl->inorectbl [inoidx]; } } } inoidx_init = 0; } } extidx_init = 0; } girn_set_exit: if (((*addr_inorecptr) != NULL) && (girn_rc == FSCK_OK)) { /* got one */ *inonum = (*addr_inorecptr)->inonum; } return (girn_rc); } /**************************************************************************** * NAME: init_agg_record * * FUNCTION: initializes the global record, fsck_aggregate * * PARAMETERS: none * * NOTES: The fsck aggregate record is pointed to by the global variable * agg_recptr. * * RETURNS: * success: FSCK_OK * failure: something else */ int init_agg_record() { int iar_rc = FSCK_OK; memset(agg_recptr, 0, sizeof (struct fsck_agg_record)); memcpy((void *) &(agg_recptr->eyecatcher), (void *) "fsckagrc", 8); memcpy((void *) &(agg_recptr->this_inode.eyecatcher), (void *) "thisinod", 8); memcpy((void *) &(agg_recptr->agg_imap_eyecatcher), (void *) "agg imap", 8); memcpy((void *) &(agg_recptr->fset_imap_eyecatcher), (void *) "fsetimap", 8); memcpy((void *) &(agg_recptr->AIT_eyecatcher), (void *) "agg ITbl", 8); memcpy((void *) &(agg_recptr->FSIT_eyecatcher), (void *) "fsetITbl", 8); memcpy((void *) &(agg_recptr->flags_eyecatcher), (void *) "aggflags", 8); memcpy((void *) &(agg_recptr->fais.eyecatcher), (void *) "faisinfo", 8); memcpy((void *) &(agg_recptr->vlarge_info_eyecatcher), (void *) "vlargebf", 8); memcpy((void *) &(agg_recptr->fscklog_info_eyecatcher), (void *) "fscklog ", 8); memcpy((void *) &(agg_recptr->blkmp_info_eyecatcher), (void *) "blkmpbuf", 8); memcpy((void *) &(agg_recptr->ea_info_eyecatcher), (void *) "eabuffer", 8); memcpy((void *) &(agg_recptr->iag_info_eyecatcher), (void *) "iag buf ", 8); memcpy((void *) &(agg_recptr->mapctl_info_eyecatcher), (void *) "mapctbuf", 8); memcpy((void *) &(agg_recptr->maplf_info_eyecatcher), (void *) "maplfbuf", 8); memcpy((void *) &(agg_recptr->bmplv_info_eyecatcher), (void *) "bmplvbuf", 8); memcpy((void *) &(agg_recptr->bmpdm_info_eyecatcher), (void *) "bmpdmbuf", 8); memcpy((void *) &(agg_recptr->inobuf_info_eyecatcher), (void *) "inodebuf", 8); memcpy((void *) &(agg_recptr->nodbuf_info_eyecatcher), (void *) "node buf", 8); memcpy((void *) &(agg_recptr->dnodbuf_info_eyecatcher), (void *) "dnodebuf", 8); memcpy((void *) &(agg_recptr->agg_AGTbl_eyecatcher), (void *) "aggAGTbl", 8); memcpy((void *) &(agg_recptr->fset_AGTbl_eyecatcher), (void *) "fs AGTbl", 8); memcpy((void *) &(agg_recptr->amap_eyecatcher), (void *) "iagiamap", 8); memcpy((void *) &(agg_recptr->fextsumm_eyecatcher), (void *) "fextsumm", 8); memcpy((void *) &(agg_recptr->finosumm_eyecatcher), (void *) "finosumm", 8); /* do the conversions from character to UniCharacter */ agg_recptr->delim_char = '/'; agg_recptr->UniChar_LSFN_NAME = uni_LSFN_NAME; agg_recptr->UniChar_lsfn_name = uni_lsfn_name; agg_recptr->agg_imap.ag_tbl = &(agg_recptr->agg_AGTbl[0]); agg_recptr->fset_imap.ag_tbl = &(agg_recptr->fset_AGTbl[0]); /* * start the messaging level out as 'show everything' * It may be reset lower when the parms have been parsed. */ agg_recptr->effective_msg_level = fsck_verbose; /* * check to see whether standard out has been redirected, and * set the flag accordingly. */ if (isatty(STDOUT_FILENO)) agg_recptr->stdout_redirected = 0; else agg_recptr->stdout_redirected = 1; return (iar_rc); } /**************************************************************************** * NAME: inorec_agg_search * * FUNCTION: Search in the aggregate inode record structures for a record * describing the requested inode. * * If found, return the address of the record. * * If not found, return a null record address. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int inorec_agg_search(uint32_t inonum, struct fsck_inode_record **addr_inorecptr) { int ias_rc = FSCK_OK; *addr_inorecptr = NULL; if (agg_recptr->AIT_ext0_tbl == NULL) { ias_rc = FSCK_INTERNAL_ERROR_17; fsck_send_msg(fsck_INTERNALERROR, ias_rc, inonum, 0, 0); } else { *addr_inorecptr = agg_recptr->AIT_ext0_tbl->inorectbl[inonum]; } return (ias_rc); } /**************************************************************************** * NAME: inorec_agg_search_insert * * FUNCTION: Search in the aggregate inode record structures for a record * describing the requested inode. * * If found, return the address of the record. * * If not found, create a record to represent the inode, * insert it into the structure, and return its address. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int inorec_agg_search_insert(uint32_t inonum, struct fsck_inode_record **addr_inorecptr) { int iasi_rc = FSCK_OK; struct fsck_inode_record *new_inorecptr; int I_am_logredo = 0; *addr_inorecptr = NULL; if (agg_recptr->AIT_ext0_tbl == NULL) { iasi_rc = FSCK_INTERNAL_ERROR_48; fsck_send_msg(fsck_INTERNALERROR, iasi_rc, inonum, 0, 0); } else { /* the table is initialized */ if (agg_recptr->AIT_ext0_tbl->inorectbl[inonum] == NULL) { /* not allocated */ iasi_rc = alloc_wrksp(inode_record_length, dynstg_inorec, I_am_logredo, (void **) &new_inorecptr); if (iasi_rc == FSCK_OK) { new_inorecptr->inonum = inonum; agg_recptr->AIT_ext0_tbl->inorectbl[inonum] = new_inorecptr; } } if (iasi_rc == FSCK_OK) { *addr_inorecptr = agg_recptr->AIT_ext0_tbl->inorectbl[inonum]; } } return (iasi_rc); } /**************************************************************************** * NAME: inorec_fs_search * * FUNCTION: Search in the fileset inode record structures for a record * describing the requested inode. * * If found, return the address of the record. * * If not found, return a null record address. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int inorec_fs_search(uint32_t inonum, struct fsck_inode_record **addr_inorecptr) { int ifs_rc = FSCK_OK; int32_t iag_in_agg, ext_in_iag, ino_in_ext; struct inode_ext_tbl_t *inoexttbl; struct inode_tbl_t *inotbl; *addr_inorecptr = NULL; if (agg_recptr->FSIT_IAG_tbl == NULL) { ifs_rc = FSCK_INTERNAL_ERROR_49; fsck_send_msg(fsck_INTERNALERROR, ifs_rc, inonum, 0, 0); } else { /* the IAG table is initialized */ locate_inode(inonum, &iag_in_agg, &ext_in_iag, &ino_in_ext); if (iag_in_agg < agg_recptr->fset_imap.num_iags) { /* IAG num in range */ if (agg_recptr->FSIT_IAG_tbl->inoext_tbl[iag_in_agg] != NULL) { /* ext table alloc */ inoexttbl = agg_recptr->FSIT_IAG_tbl-> inoext_tbl[iag_in_agg]; if (inoexttbl->inotbl[ext_in_iag] != NULL) { /* inode table allocated */ inotbl = inoexttbl->inotbl[ext_in_iag]; *addr_inorecptr = inotbl->inorectbl[ino_in_ext]; } } } } return (ifs_rc); } /**************************************************************************** * NAME: inorec_fs_search_insert * * FUNCTION: Search in the fileset inode record structures for a record * describing the requested inode. * * If found, return the address of the record. * * If not found, create a record to represent the inode, * insert it into the structure, and return its address. * * NOTES: * * RETURNS: * success: FSCK_OK * failure: something else */ int inorec_fs_search_insert(uint32_t inonum, struct fsck_inode_record **addr_inorecptr) { int ifsi_rc = FSCK_OK; int32_t iag_in_agg, ext_in_iag, ino_in_ext; struct inode_ext_tbl_t *inoexttbl = 0; struct inode_ext_tbl_t *new_inoexttbl; struct inode_tbl_t *inotbl = 0; struct inode_tbl_t *new_inotbl; struct fsck_inode_record *new_inorecptr; int I_am_logredo = 0; *addr_inorecptr = NULL; if (agg_recptr->FSIT_IAG_tbl == NULL) { ifsi_rc = FSCK_INTERNAL_ERROR_67; fsck_send_msg(fsck_INTERNALERROR, ifsi_rc, inonum, 0, 0); goto ifsi_exit; } /* the IAG table is initialized */ locate_inode(inonum, &iag_in_agg, &ext_in_iag, &ino_in_ext); if (iag_in_agg >= agg_recptr->fset_imap.num_iags) goto ifsi_exit; /* * the IAG number is in range */ if (agg_recptr->FSIT_IAG_tbl->inoext_tbl[iag_in_agg] == NULL) { /* * extent table not allocated */ ifsi_rc = alloc_wrksp(inode_ext_tbl_length, dynstg_inoexttbl, I_am_logredo, (void **) &new_inoexttbl); if (ifsi_rc == FSCK_OK) { memcpy((void *)&(new_inoexttbl->eyecatcher), (void *) "InoExTbl", 8); agg_recptr->FSIT_IAG_tbl->inoext_tbl[iag_in_agg] = new_inoexttbl; } } if (ifsi_rc == FSCK_OK) { inoexttbl = agg_recptr->FSIT_IAG_tbl->inoext_tbl[iag_in_agg]; if (inoexttbl->inotbl[ext_in_iag] == NULL) { /* * the inode table is not allocated */ ifsi_rc = alloc_wrksp(inode_tbl_length, dynstg_inotbl, I_am_logredo, (void **) &new_inotbl); if (ifsi_rc == FSCK_OK) { memcpy((void *)&(new_inotbl->eyecatcher), (void *) "InodeTbl", 8); inoexttbl->inotbl[ext_in_iag] = new_inotbl; } } } if (ifsi_rc == FSCK_OK) { inotbl = inoexttbl->inotbl[ext_in_iag]; if (inotbl->inorectbl[ino_in_ext] == NULL) { /* * the inode record is not allocated */ ifsi_rc = alloc_wrksp(inode_record_length, dynstg_inorec, I_am_logredo, (void **)&new_inorecptr); if (ifsi_rc == FSCK_OK) { new_inorecptr->inonum = inonum; inotbl->inorectbl[ino_in_ext] = new_inorecptr; } } } if (ifsi_rc == FSCK_OK) { *addr_inorecptr = inotbl->inorectbl[ino_in_ext]; } ifsi_exit: return (ifsi_rc); } /**************************************************************************** * NAME: locate_inode * * FUNCTION: Given an inode number, calculate the corresponding IAG #, * extent number within the IAG, and inode number within the * extent. * * PARAMETERS: none * * RETURNS: none */ void locate_inode(uint32_t inonum, int32_t * iag_in_agg, int32_t * ext_in_iag, int32_t * ino_in_ext) { int32_t extinagg; *iag_in_agg = inonum >> L2INOSPERIAG; extinagg = inonum >> L2INOSPEREXT; *ext_in_iag = extinagg - ((*iag_in_agg) * EXTSPERIAG); *ino_in_ext = inonum - (extinagg << L2INOSPEREXT); } /***************************************************************************** * NAME: process_extent * * FUNCTION: Verify the given extent, if found to be invalid, record * information in the fsck inode record describing the owning * inode for corrective measures. Perform the requested action * on the (adjusted if the bounds were invalid) range of aggregate * blocks in the extent. * * PARAMETERS: * inorecptr - input - pointer to the fsck inode record describing * the inode which owns the extent * extent_length - input - the number of blocks in the extent, as recorded * in the inode structures * extent_addr - input - the ordinal number of the first block in the * extent, as recorded in the inode structures * is_EA - input - 0 => the extent describes the inode's EA * !0 => the extent describes something else for * the inode * msg_info_ptr - input - pointer to a data area containing information * needed to issue messages for this extent * adjusted_length - input - pointer to a variable in which to return the * number of blocks on which the action was actually * performed (if the range was invalid, its bounds * are adjusted as needed to make it valid) * extent_is_valid - input - pointer to a variable in which the results of * validating the extent are returned. * !0 => the extent bounds, as passed in, are * reasonable for the aggregate * 0 => the extent bounds, as passed in, are * obviously incorrect * desired_action - input - { FSCK_RECORD | FSCK_RECORD_DUPCHECK | * FSCK_UNRECORD | FSCK_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */ int process_extent(struct fsck_inode_record *inorecptr, uint32_t extent_length, int64_t extent_addr, int8_t is_EA, int8_t is_ACL, struct fsck_ino_msg_info *msg_info_ptr, uint32_t * adjusted_length, int8_t * extent_is_valid, int desired_action) { int ve_rc = FSCK_OK; int64_t first_valid; int64_t last_valid; int8_t range_adjusted = 0; if (inorecptr->inode_type == metadata_inode) { first_valid = extent_addr; } else { first_valid = (extent_addr < agg_recptr->lowest_valid_fset_datablk) ? agg_recptr->lowest_valid_fset_datablk : extent_addr; } last_valid = ((extent_addr + extent_length) > agg_recptr->highest_valid_fset_datablk) ? agg_recptr->highest_valid_fset_datablk : extent_addr + extent_length - 1; if (((first_valid > agg_recptr->highest_valid_fset_datablk) && (inorecptr->inode_type != metadata_inode)) || /* * starts after end of valid fset area AND * isn't a meta data inode OR */ ((last_valid < agg_recptr->lowest_valid_fset_datablk) && (inorecptr->inode_type != metadata_inode)) || /* * ends before the beginning of valid fset area AND * isn't a meta data inode OR */ (last_valid < first_valid)) { /* ends before it starts */ *adjusted_length = 0; *extent_is_valid = 0; if (is_EA) { /* this is an extended attributes extent */ inorecptr->clr_ea_fld = 1; inorecptr->ignore_ea_blks = 1; agg_recptr->corrections_needed = 1; } else if (is_ACL) { /* this is an access control list extent */ inorecptr->clr_acl_fld = 1; inorecptr->ignore_acl_blks = 1; agg_recptr->corrections_needed = 1; } else { /* either a node (internal or leaf) or data */ inorecptr->selected_to_rls = 1; inorecptr->ignore_alloc_blks = 1; agg_recptr->corrections_needed = 1; } } else { /* not out of the question */ *adjusted_length = last_valid - first_valid + 1; if ((first_valid != extent_addr) || (last_valid != (extent_addr + extent_length - 1))) { /* at least some * blocks are not valid for the fileset */ range_adjusted = -1; *extent_is_valid = 0; if (is_EA) { /* this is an extended attributes extent */ inorecptr->clr_ea_fld = 1; agg_recptr->corrections_needed = 1; } else if (is_ACL) { /* this is an access control list extent */ inorecptr->clr_acl_fld = 1; agg_recptr->corrections_needed = 1; } else { /* either a node (internal or leaf) or data */ inorecptr->selected_to_rls = 1; agg_recptr->corrections_needed = 1; } } else { /* else the extent is ok */ *extent_is_valid = -1; } /* * Finally, depending on the parm passed by the caller, * * either: record the ownership of the blocks which are within * range and keep a count of multiply allocated blocks. * * or: reverse notations made in the workspace for the ownership * of blocks which are within range and decrement the count * of multiply allocated blocks. * * or: check the extent to see if it contains the first reference * to any multiply allocated block for which the first * reference is still unresolved. */ switch (desired_action) { case FSCK_RECORD: ve_rc = extent_record(first_valid, last_valid); break; case FSCK_RECORD_DUPCHECK: ve_rc = extent_record_dupchk(first_valid, last_valid, range_adjusted, is_EA, is_ACL, msg_info_ptr, inorecptr); break; case FSCK_UNRECORD: ve_rc = extent_unrecord(first_valid, last_valid); break; case FSCK_QUERY: ve_rc = extent_1stref_chk(first_valid, last_valid, is_EA, is_ACL, msg_info_ptr, inorecptr); break; default: ve_rc = FSCK_INTERNAL_ERROR_7; } } return (ve_rc); } /**************************************************************************** * NAME: release_inode_extension * * FUNCTION: Make an fsck inode extension record available for reuse. * * PARAMETERS: * inoext_ptr - input - address of the extension record to release * * RETURNS: * success: FSCK_OK * failure: something else */ int release_inode_extension(struct fsck_inode_ext_record *inoext_ptr) { int rir_rc = FSCK_OK; inoext_ptr->next = agg_recptr->free_inode_extens; agg_recptr->free_inode_extens = inoext_ptr; return (rir_rc); } /**************************************************************************** * NAME: release_logredo_allocs * * FUNCTION: Goes through all storage allocation records and, for each * record describing an allocation for logredo, marks all storage * available. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int release_logredo_allocs() { int rla_rc = FSCK_OK; struct wsp_ext_rec *this_fer; this_fer = agg_recptr->wsp_extent_list; while ((this_fer != NULL) && (rla_rc == FSCK_OK)) { if (this_fer->for_logredo) { this_fer->last_byte_used = sizeof (struct wsp_ext_rec) - 1; } this_fer = this_fer->next; } return (rla_rc); } /**************************************************************************** * NAME: temp_inode_buf_alloc * * FUNCTION: Allocate an I/O buffer for use during metadata replication * processing * * PARAMETERS: * addr_buf_ptr - input - pointer to a variable in which to return the * address of the buffer allocated. * * NOTES: o This very large buffer is only needed for a short time. It is * used to hold both the first extent of the primary AIT and the * first extent of the secondary AIT. * * RETURNS: * success: FSCK_OK * failure: something else */ int temp_inode_buf_alloc(char **addr_buf_ptr) { int tiba_rc = FSCK_OK; agg_recptr->vlarge_current_use = USED_FOR_INOEXT_BUF; *addr_buf_ptr = (char *) agg_recptr->vlarge_buf_ptr; memset((void *) (*addr_buf_ptr), '\0', VLARGE_BUFSIZE); return (tiba_rc); } /**************************************************************************** * NAME: temp_inode_buf_release * * FUNCTION: Free storage which was allocated for an I/O buffer for use * during metadata replication processing * * PARAMETERS: * buf_ptr - input - address of the buffer to release * * RETURNS: * success: FSCK_OK * failure: something else */ int temp_inode_buf_release(char *buf_ptr) { int tibr_rc = FSCK_OK; agg_recptr->vlarge_current_use = NOT_CURRENTLY_USED; return (tibr_rc); } /**************************************************************************** * NAME: temp_node_buf_alloc * * FUNCTION: Allocate an I/O buffer for use during metadata replication * processing * * PARAMETERS: * addr_buf_ptr - input - pointer to a variable in which to return the * address of the buffer allocated. * * NOTES: o This very large buffer is only needed for a short time. It is * used to hold both the first extent of the primary AIT and the * first extent of the secondary AIT. * * RETURNS: * success: FSCK_OK * failure: something else */ int temp_node_buf_alloc(char **addr_buf_ptr) { int tnba_rc = FSCK_OK; int I_am_logredo = 0; tnba_rc = alloc_wrksp(XTPAGE_SIZE, dynstg_tmpinoiobuf, I_am_logredo, (void **) addr_buf_ptr); if ((*addr_buf_ptr) == NULL) { /* allocation failure */ tnba_rc = FSCK_FAILED_DYNSTG_EXHAUST7; fsck_send_msg(fsck_EXHDYNSTG, wsp_dynstg_action, dynstg_wspext); } return (tnba_rc); } /**************************************************************************** * NAME: treeQ_dequeue * * FUNCTION: Removes an element from the front of the fsck tree-queue * and returns a pointer to it. * If the queue is empty, NULL is returned. * * PARAMETERS: * treeQ_elptr - input - pointer to a variable in which to return * the address of the element from the front of * the queue will be returned (or NULL if the * queue is empty) * * NOTES: The fsck xTree queue is described in the aggregate record, * fields: treeQ_front, treeQ_back * * RETURNS: * success: FSCK_OK * failure: something else */ int treeQ_dequeue(struct treeQelem **treeQ_elptr) { int tQd_rc = FSCK_OK; *treeQ_elptr = agg_recptr->treeQ_front; if (agg_recptr->treeQ_back == agg_recptr->treeQ_front) { /* empty */ agg_recptr->treeQ_back = agg_recptr->treeQ_front = NULL; } else { /* not empty */ agg_recptr->treeQ_front = agg_recptr->treeQ_front->next; agg_recptr->treeQ_front->prev = NULL; } return (tQd_rc); } /**************************************************************************** * NAME: treeQ_enqueue * * FUNCTION: Adds the given element to the back of the fsck tree-queue * stack. * * PARAMETERS: * treeQ_elptr - input - the address of the element to add to the queue * * NOTES: The fsck xTree queue is described in the aggregate record, * fields: treeQ_front, treeQ_back * * RETURNS: * success: FSCK_OK * failure: something else */ int treeQ_enqueue(struct treeQelem *treeQ_elptr) { int tep_rc = FSCK_OK; if (agg_recptr->treeQ_back == NULL) { /* empty queue */ agg_recptr->treeQ_back = agg_recptr->treeQ_front = treeQ_elptr; treeQ_elptr->prev = treeQ_elptr->next = NULL; } else { /* queue not empty */ treeQ_elptr->next = NULL; treeQ_elptr->prev = agg_recptr->treeQ_back; agg_recptr->treeQ_back->next = treeQ_elptr; agg_recptr->treeQ_back = treeQ_elptr; } return (tep_rc); } /**************************************************************************** * NAME: treeQ_get_elem * * FUNCTION: Allocates workspace storage for an fsck tree-queue element * * PARAMETERS: * addr_treeQ_ptr - input - pointer to a variable in which to return * the address of the element allocated. * * RETURNS: * success: FSCK_OK * failure: something else */ int treeQ_get_elem(struct treeQelem **addr_treeQ_ptr) { int gte_rc = FSCK_OK; int I_am_logredo = 0; if (agg_recptr->free_treeQ != NULL) { /* free list isn't empty */ *addr_treeQ_ptr = agg_recptr->free_treeQ; agg_recptr->free_treeQ = agg_recptr->free_treeQ->next; memset((void *) (*addr_treeQ_ptr), 0, treeQ_elem_length); } else { /* else the free list is empty */ gte_rc = alloc_wrksp(treeQ_elem_length, dynstg_treeQ_elem, I_am_logredo, (void **) addr_treeQ_ptr); } return (gte_rc); } /**************************************************************************** * * NAME: treeQ_rel_elem * * FUNCTION: Makes an fsck tree-queue element available for reuse * * PARAMETERS: * treeQ_elptr - input - the address of the element to release * * RETURNS: * success: FSCK_OK * failure: something else */ int treeQ_rel_elem(struct treeQelem *treeQ_elptr) { int tre_rc = FSCK_OK; treeQ_elptr->next = agg_recptr->free_treeQ; agg_recptr->free_treeQ = treeQ_elptr; return (tre_rc); } /***************************************************************************** * NAME: workspace_release * * FUNCTION: Release the pool of storage allocated for fsck workspace * storage. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int workspace_release() { int wr_rc = FSCK_OK; struct wsp_ext_rec *this_fer; struct wsp_ext_rec *next_fer; /* * If the very large buffer is (still) allocated, release it. */ if (agg_recptr->vlarge_buf_ptr != NULL) { free((void *) agg_recptr->vlarge_buf_ptr); agg_recptr->vlarge_buf_ptr = NULL; agg_recptr->ea_buf_ptr = NULL; agg_recptr->recon_buf_extent = NULL; } /* * release the allocated extents */ this_fer = agg_recptr->wsp_extent_list; while (this_fer != NULL) { /* for each extent record */ /* the one after this one (if any) */ next_fer = this_fer->next; if (!this_fer->from_high_memory) { /* free the extent this * fer describes (and occupies) */ free((void *) this_fer->extent_addr); } /* go on to the next one in the list */ this_fer = next_fer; } return (wr_rc); } jfsutils-1.1.15.orig/fsck/fsckxtre.c0000644000000000000000000013250410441103234014207 0ustar /* * Copyright (C) International Business Machines Corp., 2000-2004 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include /* defines and includes common among the fsck.jfs modules */ #include "xfsckint.h" #include "jfs_byteorder.h" /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * superblock buffer pointer * * defined in xchkdsk.c */ extern struct superblock *sb_ptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * fsck aggregate info structure pointer * * defined in xchkdsk.c */ extern struct fsck_agg_record *agg_recptr; /* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV * * The following are internal to this file * */ struct fsck_Xtree_info { xtpage_t *xtp_ptr; xad_t *xad_ptr; int64_t ext_addr; uint32_t ext_length; struct treeQelem *this_Qel; struct treeQelem *next_Qel; int64_t this_key; int64_t last_key; int64_t last_node_addr; int8_t last_level; int8_t dense_file; int8_t leaf_seen; }; int xTree_binsrch_page(xtpage_t *, int64_t, int8_t *, int16_t *, int8_t *); int xTree_process_internal_extents(xtpage_t *, struct fsck_inode_record *, struct treeQelem *, struct fsck_ino_msg_info *, int); int xTree_node_first_key(struct fsck_Xtree_info *, struct fsck_inode_record *, struct fsck_ino_msg_info *, int); int xTree_node_first_in_level(struct fsck_Xtree_info *, struct fsck_inode_record *, struct fsck_ino_msg_info *, int); int xTree_node_last_in_level(struct fsck_Xtree_info *, struct fsck_inode_record *, struct fsck_ino_msg_info *, int); int xTree_node_not_first_in_level(struct fsck_Xtree_info *, struct fsck_inode_record *, struct fsck_ino_msg_info *, int); int xTree_node_not_last_in_level(struct fsck_Xtree_info *, struct fsck_inode_record *, struct fsck_ino_msg_info *, int); int xTree_process_leaf_extents(xtpage_t *, struct fsck_inode_record *, struct treeQelem *, struct fsck_ino_msg_info *, int8_t, int); /* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV */ /***************************************************************************** * NAME: find_first_leaf * * FUNCTION: Get the ordinal number of the aggregate block containing the * first leaf node in the B+ Tree, type xTree, rooted in the * given inode. * * PARAMETERS: * inoptr - input - pointer to the inode in which the xTree * is rooted * addr_leaf_ptr - input - pointer to a variable in which to return * the address of the leaf in an fsck buffer. * leaf_agg_offset - input - offset, from the beginning of the * aggregate, in aggregate blocks, of the * leftmost leaf in the xTree * is_inline - input - pointer to a variable in which to return: * !0 if the inode's data is inline (no leaf) * 0 if the inode's data is not inline * is_rootleaf - input - pointer to a variable in which to return: * !0 if the xTree's root node is a leaf * 0 if the xTree's root node is an internal * node * * RETURNS: * success: FSCK_OK * failure: something else */ int find_first_leaf(struct dinode *inoptr, xtpage_t ** addr_leaf_ptr, int64_t * leaf_agg_offset, int8_t * is_inline, int8_t * is_rootleaf) { int ffl_rc = FSCK_OK; xtpage_t *xtpg_ptr; xad_t *xad_ptr; int64_t first_child_addr = 0; *is_rootleaf = 0; /* assume inode has no data */ *is_inline = 0; /* assume inode has no data */ *addr_leaf_ptr = NULL; /* assume inode has no data */ *leaf_agg_offset = 0; /* assume inode has no data */ xtpg_ptr = (xtpage_t *) & (inoptr->di_btroot); if (xtpg_ptr->header.flag & BT_LEAF) { /* it's a root-leaf */ *is_rootleaf = -1; *leaf_agg_offset = addressPXD(&(inoptr->di_ixpxd)); } else { /* it's a tree */ while ((ffl_rc == FSCK_OK) && (*addr_leaf_ptr == NULL)) { if (xtpg_ptr->header.flag & BT_LEAF) { /* found it! */ *addr_leaf_ptr = xtpg_ptr; *leaf_agg_offset = first_child_addr; } else { /* keep moving down the tree */ xad_ptr = &(xtpg_ptr->xad[XTENTRYSTART]); first_child_addr = addressXAD(xad_ptr); ffl_rc = node_get(first_child_addr, &xtpg_ptr); } } } return (ffl_rc); } /***************************************************************************** * NAME: init_xtree_root * * FUNCTION: Initialize the btroot in the given inode as an empty (big) * xtree root. Adjust di_nblocks and di_size to match. * * PARAMETERS: * inoptr - input - pointer to the inode in which the xTree * root should be initialized * * RETURNS: * success: FSCK_OK * failure: something else */ int init_xtree_root(struct dinode *inoptr) { int ixr_rc = FSCK_OK; xtpage_t *xtpg_ptr; xtpg_ptr = (xtpage_t *) & (inoptr->di_btroot); xtpg_ptr->header.flag = (DXD_INDEX | BT_ROOT | BT_LEAF); xtpg_ptr->header.maxentry = XTROOTMAXSLOT; xtpg_ptr->header.nextindex = XTENTRYSTART; inoptr->di_nblocks = 0; inoptr->di_size = 0; return (ixr_rc); } /***************************************************************************** * NAME: process_valid_data * * FUNCTION: Perform the desired action on the xTree rooted in the given * inode, assume that the xTree has a valid structure. (I.e., * that the tree has already been validated.) * * PARAMETERS: * inoptr - input - pointer to the inode in which the xTree is * rooted * inoidx - input - ordinal number of the inode * inorecptr - input - pointer to the fsck inode record describing * the inode in which the xTree is rooted * msg_info_ptr - input - pointer to data needed for messages about * the inode in which the xTree is rooted * desired_action - input - { FSCK_RECORD | FSCK_UNRECORD | FSCK_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */ int process_valid_data(struct dinode *inoptr, uint32_t inoidx, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr, int desired_action) { int pvd_rc = FSCK_OK; int xad_idx; xtpage_t *xtpage_ptr; xtpage_t *this_xtpage; xad_t *xad_ptr; int64_t node_addr_fsblks; int64_t first_child_addr; int64_t first_fsblk; int64_t num_fsblks; int8_t extent_is_valid; int8_t is_EA = 0; int8_t is_ACL = 0; int8_t is_rootnode; uint32_t block_count; if (ISDIR(inoptr->di_mode)) xtpage_ptr = (xtpage_t *) & (inoptr->di_dirtable); else xtpage_ptr = (xtpage_t *) & (inoptr->di_btroot); is_rootnode = -1; if (xtpage_ptr->header.flag == 0) goto out; /* there is data for this inode */ while ((pvd_rc == FSCK_OK) && (xtpage_ptr != NULL)) { /* while not done processing the tree */ /* * this node is a first child. if it isn't a leaf, get * the address of its first child */ if (xtpage_ptr->header.flag & BT_LEAF) { /* it's a leaf */ first_child_addr = 0; } else { /* else it's not a leaf */ /* the first child */ xad_ptr = &(xtpage_ptr->xad[XTENTRYSTART]); first_child_addr = addressXAD(xad_ptr); } /* * process the current level */ /* first node in the level */ this_xtpage = xtpage_ptr; while ((pvd_rc == FSCK_OK) && (this_xtpage != NULL)) { /* process all nodes on the level */ for (xad_idx = XTENTRYSTART; ((xad_idx < this_xtpage->header.nextindex) && (pvd_rc == FSCK_OK)); xad_idx++) { /* for each xad in the xtpage */ xad_ptr = &(this_xtpage->xad[xad_idx]); first_fsblk = addressXAD(xad_ptr); num_fsblks = lengthXAD(xad_ptr); pvd_rc = process_extent(inorecptr, num_fsblks, first_fsblk, is_EA, is_ACL, msg_info_ptr, &block_count, &extent_is_valid, desired_action); if ((desired_action == FSCK_RECORD) || (desired_action == FSCK_RECORD_DUPCHECK)) { agg_recptr->blocks_this_fset += block_count; agg_recptr->this_inode.all_blks += block_count; if (first_child_addr == 0) { /* this is a leaf */ agg_recptr-> this_inode.data_blks += block_count; } } else if (desired_action == FSCK_UNRECORD) { agg_recptr->blocks_this_fset -= block_count; agg_recptr->this_inode.all_blks -= block_count; if (first_child_addr == 0) { /* this is a leaf */ agg_recptr-> this_inode.data_blks -= block_count; } } } if (is_rootnode) { /* root has no siblings */ is_rootnode = 0; this_xtpage = NULL; } else if (this_xtpage->header.next == ((int64_t) 0)) { /* this is rightmost */ this_xtpage = NULL; } else { /* else there is a right sibling/cousin */ node_addr_fsblks = this_xtpage->header.next; pvd_rc = node_get(node_addr_fsblks, &this_xtpage); } } /* * if not done, go down to the next level of the tree */ if (first_child_addr == 0) { /* done! */ xtpage_ptr = NULL; } else { /* get the first child/cousin in the next level */ pvd_rc = node_get(first_child_addr, &xtpage_ptr); } } out: return (pvd_rc); } /***************************************************************************** * NAME: xTree_binsrch_page * * FUNCTION: Perform a binary search on the xad's in the given xTree node * * PARAMETERS: * xtpg_ptr - input - pointer to the xTree node to search * given_offset - input - offset to match to an xad key * xad_selected - input - pointer to a variable in which to return: * !0 if the search was successful * 0 if the search was not successful * selected_idx - input - the ordinal value of xad, within the node, * of the xad whose key matches given_offset * (if any) * not_allocated - input - * currently unused * * * RETURNS: * success: FSCK_OK * failure: something else */ int xTree_binsrch_page(xtpage_t * xtpg_ptr, int64_t given_offset, int8_t * xad_selected, int16_t * selected_idx, int8_t * not_allocated) { int xbp_rc = FSCK_OK; int16_t lowidx, mididx, highidx; int64_t this_offset; lowidx = XTENTRYSTART; highidx = xtpg_ptr->header.nextindex - 1; *xad_selected = 0; if (lowidx > highidx) return -EIO; while ((!(*xad_selected)) && (xbp_rc == FSCK_OK)) { if ((highidx == lowidx) || ((highidx - lowidx) == 1)) { /* at most 1 apart */ if (given_offset < offsetXAD(&xtpg_ptr->xad[highidx])) { *selected_idx = lowidx; *xad_selected = -1; } else { *selected_idx = highidx; *xad_selected = -1; } } else { /* far enough apart to continue algorithm */ mididx = ((highidx - lowidx) >> 1) + lowidx; this_offset = offsetXAD(&(xtpg_ptr->xad[mididx])); if (given_offset == this_offset) { /* it's a match */ *selected_idx = mididx; *xad_selected = -1; } else if (given_offset < this_offset) { /* this one is greater */ if (given_offset > offsetXAD(&(xtpg_ptr->xad[mididx - 1]))) { /* the one before this one is less */ *selected_idx = mididx - 1; *xad_selected = -1; } else { /* the one before is not less */ /* reset the range */ highidx = mididx; } } else { /* this one is less */ if (given_offset < offsetXAD(&(xtpg_ptr->xad[mididx + 1]))) { /* the one after this one is greater */ *selected_idx = mididx; *xad_selected = -1; } else { /* the one after is not greater */ /* reset the range */ lowidx = mididx; } } } } return (xbp_rc); } /***************************************************************************** * NAME: xTree_node_first_key * * FUNCTION: Helper routine for xTree_processing * * PARAMETERS: * xtiptr - input - pointer to an fsck record describing the * xTree * inorecptr - input - pointer to the fsck inode record describing * the inode in which the xTree is rooted * msg_info_ptr - input - pointer to data needed for messages about * the inode in which the xTree is rooted * desired_action - input - { FSCK_RECORD | FSCK_RECORD_DUPCHECK | * FSCK_UNRECORD | FSCK_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */ int xTree_node_first_key(struct fsck_Xtree_info *xtiptr, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr, int desired_action) { int xnfk_rc = FSCK_OK; /* * the key in the 1st xad must match the key in the parent * node's xad describing this node */ if (xtiptr->this_Qel->node_first_offset && (xtiptr->this_key != xtiptr->this_Qel->node_first_offset)) { /* invalid key in 1st xad */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADKEYS, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, 5); } goto out; } /* 1st xad might be ok */ if (xtiptr->last_level != xtiptr->this_Qel->node_level) goto out; /* not 1st in level */ if ((xtiptr->dense_file) && (xtiptr->xtp_ptr->header.flag & BT_LEAF)) { /* a leaf node in a dense file */ if (xtiptr->this_key != (xtiptr->last_key + 1)) { /* a gap in a dense file */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADINOINTERNGAP, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, (long long) xtiptr->last_key); } } } else { /* not a leaf node in a dense file */ if (xtiptr->this_key <= xtiptr->last_key) { /* the extents overlap! */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADKEYS, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, 6); } } } out: return (xnfk_rc); } /***************************************************************************** * NAME: xTree_node_first_in_level * * FUNCTION: Helper routine for xTree_processing * * PARAMETERS: * xtiptr - input - pointer to an fsck record describing the * xTree * inorecptr - input - pointer to the fsck inode record describing * the inode in which the xTree is rooted * msg_info_ptr - input - pointer to data needed for messages about * the inode in which the xTree is rooted * desired_action - input - { FSCK_RECORD | FSCK_RECORD_DUPCHECK | * FSCK_UNRECORD | FSCK_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */ int xTree_node_first_in_level(struct fsck_Xtree_info *xtiptr, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr, int desired_action) { int xnfil_rc = FSCK_OK; if (xtiptr->xtp_ptr->header.prev != 0) { /* bad back ptr! */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADBSBLCHN, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } return (xnfil_rc); } /***************************************************************************** * NAME: xTree_node_last_in_level * * FUNCTION: Helper routine for xTree_processing * * PARAMETERS: * xtiptr - input - pointer to an fsck record describing the * xTree * inorecptr - input - pointer to the fsck inode record describing * the inode in which the xTree is rooted * msg_info_ptr - input - pointer to data needed for messages about * the inode in which the xTree is rooted * desired_action - input - { FSCK_RECORD | FSCK_RECORD_DUPCHECK | * FSCK_UNRECORD | FSCK_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */ int xTree_node_last_in_level(struct fsck_Xtree_info *xtiptr, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr, int desired_action) { int xnlil_rc = FSCK_OK; if (xtiptr->xtp_ptr->header.next != 0) { /* bad forward ptr! */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADFSBLCHN, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } return (xnlil_rc); } /***************************************************************************** * NAME: xTree_node_not_first_in_level * * FUNCTION: Helper routine for xTree_processing * * PARAMETERS: * xtiptr - input - pointer to an fsck record describing the * xTree * inorecptr - input - pointer to the fsck inode record describing * the inode in which the xTree is rooted * msg_info_ptr - input - pointer to data needed for messages about * the inode in which the xTree is rooted * desired_action - input - { FSCK_RECORD | FSCK_RECORD_DUPCHECK | * FSCK_UNRECORD | FSCK_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */ int xTree_node_not_first_in_level(struct fsck_Xtree_info *xtiptr, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr, int desired_action) { int xnnfil_rc = FSCK_OK; if (xtiptr->xtp_ptr->header.prev != xtiptr->last_node_addr) { /* bad back ptr! */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADBSBLCHN, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } return (xnnfil_rc); } /***************************************************************************** * NAME: xTree_node_not_last_in_level * * FUNCTION: Helper routine for xTree_processing * * PARAMETERS: * xtiptr - input - pointer to an fsck record describing the * xTree * inorecptr - input - pointer to the fsck inode record describing * the inode in which the xTree is rooted * msg_info_ptr - input - pointer to data needed for messages about * the inode in which the xTree is rooted * desired_action - input - { FSCK_RECORD | FSCK_RECORD_DUPCHECK | * FSCK_UNRECORD | FSCK_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */ int xTree_node_not_last_in_level(struct fsck_Xtree_info *xtiptr, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr, int desired_action) { int xnnlil_rc = FSCK_OK; if (xtiptr->xtp_ptr->header.next != xtiptr->next_Qel->node_addr) { /* bad forward ptr! */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADFSBLCHN, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } else { /* forward sibling pointer is correct */ if (xtiptr->this_Qel->last_ext_uneven) { /* last extent described * by this node is not an even number of * 4096 pages but it can't be the last extent * allocated to the inode */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ xtiptr->xad_ptr = &(xtiptr-> xtp_ptr->xad[xtiptr->xtp_ptr->header. nextindex - 1]); xtiptr->this_key = offsetXAD(xtiptr->xad_ptr); xtiptr->ext_length = lengthXAD(xtiptr->xad_ptr); fsck_send_msg(fsck_BADINOODDINTRNEXT, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, (long long) xtiptr->this_key, xtiptr->ext_length); } } } return (xnnlil_rc); } /***************************************************************************** * NAME: xTree_process_internal_extents * * FUNCTION: Helper routine for xTree_processing * * PARAMETERS: * xtpg_ptr - input - pointer to the internal node in an fsck * buffer * ino_recptr - input - pointer to the fsck inode record describing * the inode in which the xTree is rooted * Q_elptr - input - address of an fsck Q element pointer * describing the internal node * msg_info_ptr - input - pointer to data needed for messages about * the inode in which the xTree is rooted * desired_action - input - { FSCK_RECORD | FSCK_RECORD_DUPCHECK | * FSCK_UNRECORD | FSCK_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */ int xTree_process_internal_extents(xtpage_t * xtpg_ptr, struct fsck_inode_record *ino_recptr, struct treeQelem *Q_elptr, struct fsck_ino_msg_info *msg_info_ptr, int desired_action) { int xpie_rc = FSCK_OK; int64_t last_key, this_key; uint32_t xadidx; struct treeQelem *new_Qelptr; uint32_t ext_length, adjusted_length; int64_t ext_addr; int8_t ext_ok; int8_t is_EA = 0; int8_t is_ACL = 0; xad_t *xad_ptr; uint8_t flag_mask; flag_mask = ~(XAD_NEW | XAD_EXTENDED | XAD_COMPRESSED | XAD_NOTRECORDED | XAD_COW); last_key = -1; for (xadidx = XTENTRYSTART; ((xadidx < xtpg_ptr->header.nextindex) && (xpie_rc == FSCK_OK) && (!ino_recptr->ignore_alloc_blks)); xadidx++) { xad_ptr = &(xtpg_ptr->xad[xadidx]); if ((xad_ptr->flag & flag_mask)) { /* bad flag value */ ino_recptr->ignore_alloc_blks = 1; goto out; } this_key = offsetXAD(xad_ptr); if (this_key <= last_key) { /* these keys MUST ascend */ ino_recptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* first detection */ fsck_send_msg(fsck_BADKEYS, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, 7); } goto out; } /* key looks ok from here */ last_key = this_key; ext_addr = addressXAD(xad_ptr); ext_length = lengthXAD(xad_ptr); xpie_rc = process_extent(ino_recptr, ext_length, ext_addr, is_EA, is_ACL, msg_info_ptr, &adjusted_length, &ext_ok, desired_action); if ((xpie_rc != FSCK_OK) || !ext_ok) goto out; /* extent is good */ if ((desired_action == FSCK_RECORD) || (desired_action == FSCK_RECORD_DUPCHECK)) { agg_recptr->blocks_this_fset += adjusted_length; agg_recptr->this_inode.all_blks += adjusted_length; } else if (desired_action == FSCK_UNRECORD) { agg_recptr->blocks_this_fset -= adjusted_length; agg_recptr->this_inode.all_blks -= adjusted_length; } xpie_rc = treeQ_get_elem(&new_Qelptr); if (xpie_rc != FSCK_OK) goto out; /* got a queue element */ new_Qelptr->node_level = Q_elptr->node_level + 1; new_Qelptr->node_addr = ext_addr; PXDaddress(&(new_Qelptr->node_pxd), ext_addr); PXDlength(&(new_Qelptr->node_pxd), ext_length); new_Qelptr->node_first_offset = this_key; xpie_rc = treeQ_enqueue(new_Qelptr); } out: return (xpie_rc); } /***************************************************************************** * NAME: xTree_process_leaf_extents * * FUNCTION: Helper routine for xTree_processing * * PARAMETERS: * xtpg_ptr - input - pointer to the leaf node in an fsck buffer * inorecptr - input - pointer to the fsck inode record describing * the inode in which the xTree is rooted * Q_elptr - input - address of an fsck Q element pointer * describing the leaf * msg_info_ptr - input - pointer to data needed for messages about the * inode in which the xTree is rooted * dense_file - input - !0 => the xTree describes a dense file * 0 => the xTree describes a file which may * be sparse * desired_action - input - { FSCK_RECORD | FSCK_RECORD_DUPCHECK | * FSCK_UNRECORD | FSCK_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */ int xTree_process_leaf_extents(xtpage_t * xtpg_ptr, struct fsck_inode_record *ino_recptr, struct treeQelem *Q_elptr, struct fsck_ino_msg_info *msg_info_ptr, int8_t dense_file, int desired_action) { int xple_rc = FSCK_OK; int64_t last_key, this_key; uint32_t xadidx; uint32_t ext_length, adjusted_length; int64_t ext_addr; int8_t ext_ok; int8_t is_EA = 0; int8_t is_ACL = 0; xad_t *xad_ptr; uint32_t ext_pages; uint8_t flag_mask; flag_mask = ~(XAD_NEW | XAD_EXTENDED | XAD_COMPRESSED | XAD_NOTRECORDED | XAD_COW); last_key = -1; for (xadidx = XTENTRYSTART; ((xadidx < xtpg_ptr->header.nextindex) && (xple_rc == FSCK_OK) && (!ino_recptr->ignore_alloc_blks)); xadidx++) { xad_ptr = &(xtpg_ptr->xad[xadidx]); if ((xad_ptr->flag & flag_mask)) { /* bad flag value */ ino_recptr->ignore_alloc_blks = 1; } this_key = offsetXAD(xad_ptr); if ((last_key != -1) && (!ino_recptr->ignore_alloc_blks)) { /* not the first key */ if (this_key <= last_key) { /* these keys MUST ascend */ ino_recptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* first detection */ fsck_send_msg(fsck_BADKEYS, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, 8); } goto out; } /* the keys do ascend */ if ((dense_file) && (this_key != (last_key + 1))) { /* a dense file with a gap! */ ino_recptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* first detection */ fsck_send_msg(fsck_BADINOINTERNGAP, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, msg_info_ptr->msg_inonum); } goto out; } } ext_addr = addressXAD(xad_ptr); ext_length = lengthXAD(xad_ptr); last_key = this_key + ext_length - 1; agg_recptr->this_inode.data_size = (last_key + 1) * sb_ptr->s_bsize; /* * all extents (except the very last one for the inode) must * be in full (4096 byte) pages. */ ext_pages = ext_length >> agg_recptr->log2_blksperpg; if ((ext_length != (ext_pages << agg_recptr->log2_blksperpg)) && (!(ino_recptr->badblk_inode))) { /* * this one is an odd size and isn't * owned by the bad block inode */ if (xadidx == (xtpg_ptr->header.nextindex - 1)) { /* * this is the last extent for the node * and might be the last for the inode */ Q_elptr->last_ext_uneven = -1; } else { /* not the last extent for the xtpage */ ino_recptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* first detection */ fsck_send_msg (fsck_BADINOODDINTRNEXT, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, (long long) this_key, ext_length); } goto out; } } xple_rc = process_extent(ino_recptr, ext_length, ext_addr, is_EA, is_ACL, msg_info_ptr, &adjusted_length, &ext_ok, desired_action); if ((desired_action == FSCK_RECORD) || (desired_action == FSCK_RECORD_DUPCHECK)) { agg_recptr->blocks_this_fset += adjusted_length; agg_recptr->this_inode.all_blks += adjusted_length; agg_recptr->this_inode.data_blks += adjusted_length; } else if (desired_action == FSCK_UNRECORD) { agg_recptr->blocks_this_fset -= adjusted_length; agg_recptr->this_inode.all_blks -= adjusted_length; agg_recptr->this_inode.data_blks -= adjusted_length; } } out: return (xple_rc); } /***************************************************************************** * NAME: xTree_processing * * FUNCTION: Validate the structure of the xTree rooted in the given inode * and perform the desired_action on the nodes in the xTree. * Stop processing the xTree if and when any symptom of corruption * is detected. * * PARAMETERS: * inoptr - input - pointer to the inode in which the xTree is * rooted * inoidx - input - ordinal number of the inode * inorecptr - input - pointer to the fsck inode record describing * the inode * msg_info_ptr - input - pointer to data needed for messages about * the inode * desired_action - input - { FSCK_RECORD | FSCK_RECORD_DUPCHECK | * FSCK_UNRECORD | FSCK_QUERY | * FSCK_FSIM_RECORD_DUPCHECK | * FSCK_FSIM_UNRECORD | FSCK_FSIM_QUERY } * * RETURNS: * success: FSCK_OK * failure: something else */ int xTree_processing(struct dinode *inoptr, uint32_t inoidx, struct fsck_inode_record *inorecptr, struct fsck_ino_msg_info *msg_info_ptr, int desired_action) { int xp_rc = FSCK_OK; int8_t old_ignore_alloc_blks = 0; int ixpxd_unequal = 0; int is_root = -1; int not_fsim_tree = -1; struct fsck_Xtree_info xtinfo; struct fsck_Xtree_info *xtiptr; xtiptr = &xtinfo; xtiptr->this_Qel = NULL; xtiptr->next_Qel = NULL; xtiptr->last_level = -1; /* -1 so the root will be recognized * as 1st node in level 0 */ xtiptr->dense_file = 0; xtiptr->leaf_seen = 0; if (!(inoptr->di_mode & ISPARSE)) { xtiptr->dense_file = -1; } switch (desired_action) { case (FSCK_FSIM_RECORD_DUPCHECK): not_fsim_tree = 0; desired_action = FSCK_RECORD_DUPCHECK; break; case (FSCK_FSIM_UNRECORD): not_fsim_tree = 0; desired_action = FSCK_UNRECORD; break; case (FSCK_FSIM_QUERY): not_fsim_tree = 0; desired_action = FSCK_QUERY; break; default: break; } if (ISDIR(inoptr->di_mode)) xtiptr->xtp_ptr = (xtpage_t *) & (inoptr->di_dirtable); else xtiptr->xtp_ptr = (xtpage_t *) & (inoptr->di_btroot); if ((!ISDIR(inoptr->di_mode) && (xtiptr->xtp_ptr->header.maxentry != XTROOTINITSLOT) && (xtiptr->xtp_ptr->header.maxentry != XTROOTMAXSLOT)) || (ISDIR(inoptr->di_mode) && (xtiptr->xtp_ptr->header.maxentry != XTROOTINITSLOT_DIR))) { /* bad maxentry field */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADINOOTHR, "45", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } /* end not reported yet */ goto out; } if (xtiptr->xtp_ptr->header.nextindex > xtiptr->xtp_ptr->header.maxentry) { /* bad nextindex field */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADINOOTHR, "46", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } goto out; } if (xtiptr->xtp_ptr->header.nextindex <= XTENTRYSTART) goto out; /* data length > 0 */ if (desired_action != FSCK_RECORD_DUPCHECK) { /* not the first pass */ /* * The first time through we stopped processing allocated * blocks if and when we discovered the tree to be corrupt. * On a 2nd pass we want to stop at the same place. */ if (inorecptr->ignore_alloc_blks) { /* the bit is on */ old_ignore_alloc_blks = -1; inorecptr->ignore_alloc_blks = 0; } } xtiptr->this_key = offsetXAD(&(xtiptr->xtp_ptr->xad[XTENTRYSTART])); if (xtiptr->dense_file && (xtiptr->this_key != ((int64_t) 0))) { /* a dense file with a gap at the front */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADINOFRONTGAP, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } goto release; } xp_rc = treeQ_get_elem(&xtiptr->this_Qel); if (xp_rc != FSCK_OK) goto out; xtiptr->this_Qel->node_level = 0; if (xtiptr->xtp_ptr->header.flag & BT_LEAF) { /* root leaf */ if (not_fsim_tree) { /* not the FileSet Inode Map tree */ xp_rc = xTree_process_leaf_extents (xtiptr->xtp_ptr, inorecptr, xtiptr->this_Qel, msg_info_ptr, xtiptr->dense_file, desired_action); } xtiptr->xad_ptr = &(xtiptr-> xtp_ptr->xad[xtiptr->xtp_ptr->header.nextindex - 1]); agg_recptr->this_inode.data_size = (int64_t) (offsetXAD(xtiptr->xad_ptr) + lengthXAD(xtiptr->xad_ptr)) * sb_ptr->s_bsize; /* * By definition, a root-leaf is the last leaf * for the inode */ } else { /* root is not a leaf */ if (xtiptr->xtp_ptr->header.flag & BT_INTERNAL) { /* root internal */ xp_rc = xTree_process_internal_extents (xtiptr->xtp_ptr, inorecptr, xtiptr->this_Qel, msg_info_ptr, desired_action); } else { /* invalid flag value! */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADINOOTHR, "50", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } } while ((xp_rc == FSCK_OK) && (!inorecptr->ignore_alloc_blks) && (agg_recptr->treeQ_back != NULL)) { /* nothing fatal and tree looks ok and queue not empty */ xp_rc = treeQ_dequeue(&xtiptr->next_Qel); if (xp_rc != FSCK_OK) break; if (xtiptr->this_Qel->node_level == xtiptr->next_Qel->node_level) /* it's not the last in its level */ xp_rc = xTree_node_not_last_in_level(xtiptr, inorecptr, msg_info_ptr, desired_action); else if (!is_root) /* it is the last in its level */ xp_rc = xTree_node_last_in_level(xtiptr, inorecptr, msg_info_ptr, desired_action); if ((xp_rc != FSCK_OK) || inorecptr->ignore_alloc_blks) break; /* * save some info about the node already processed * and then move on to the new node */ xtiptr->last_level = xtiptr->this_Qel->node_level; xtiptr->last_node_addr = xtiptr->this_Qel->node_addr; xtiptr->xad_ptr = &(xtiptr-> xtp_ptr->xad[xtiptr->xtp_ptr->header.nextindex - 1]); if (xtiptr->xtp_ptr->header.flag & BT_LEAF) { /* it's a leaf */ xtiptr->last_key = offsetXAD(xtiptr->xad_ptr) + lengthXAD(xtiptr->xad_ptr) - 1; } else { /* it's an internal node */ xtiptr->last_key = offsetXAD(xtiptr->xad_ptr); } xp_rc = treeQ_rel_elem(xtiptr->this_Qel); if (xp_rc != FSCK_OK) break; /* released the older element */ /* promote newer element */ xtiptr->this_Qel = xtiptr->next_Qel; /* to avoid releasing it twice */ xtiptr->next_Qel = NULL; is_root = 0; xp_rc = node_get(xtiptr->this_Qel->node_addr, &xtiptr->xtp_ptr); if (xp_rc != FSCK_OK) { /* bad read! */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADINOOTHR, "42", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } break; } /* got the new node */ if (xtiptr->xtp_ptr->header.maxentry != XTPAGEMAXSLOT) { /* bad maxentry field */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADINOOTHR, "43", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } else if (xtiptr->xtp_ptr->header.nextindex > xtiptr->xtp_ptr->header.maxentry) { /* bad nextindex field */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADINOOTHR, "44", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } if (inorecptr->ignore_alloc_blks) break; if (xtiptr->last_level != xtiptr->this_Qel->node_level) { /* this is a new level */ xtiptr->last_key = 0; xp_rc = xTree_node_first_in_level (xtiptr, inorecptr, msg_info_ptr, desired_action); } else { xp_rc = xTree_node_not_first_in_level (xtiptr, inorecptr, msg_info_ptr, desired_action); } ixpxd_unequal = memcmp((void *) &(xtiptr->xtp_ptr->header.self), (void *) &(xtiptr->this_Qel->node_pxd), sizeof (pxd_t)); if (ixpxd_unequal) { /* bad self field in header */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADINONODESELF, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } else if (xtiptr->xtp_ptr->header.nextindex > XTENTRYSTART) { if (xtiptr->xtp_ptr->header.flag & BT_LEAF) { /* it's a leaf */ xtiptr->xad_ptr = & (xtiptr->xtp_ptr->xad [xtiptr->xtp_ptr->header.nextindex - 1]); agg_recptr->this_inode.data_size = (int64_t) (offsetXAD (xtiptr->xad_ptr) + lengthXAD (xtiptr->xad_ptr)) * sb_ptr->s_bsize; /* * Just in case this is the * last leaf for the inode */ } xtiptr->xad_ptr = &(xtiptr->xtp_ptr->xad[XTENTRYSTART]); xtiptr->this_key = offsetXAD(xtiptr->xad_ptr); xtiptr->ext_length = lengthXAD(xtiptr->xad_ptr); } else { /* an empty non-root node */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADINOMTNODE, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } if ((xp_rc != FSCK_OK) || inorecptr->ignore_alloc_blks) break; xp_rc = xTree_node_first_key(xtiptr, inorecptr, msg_info_ptr, desired_action); if ((xp_rc != FSCK_OK) || inorecptr->ignore_alloc_blks) break; if (xtiptr->xtp_ptr->header.flag & BT_LEAF) { /* a leaf node */ if (not_fsim_tree) { /* not the FileSet Inode Map tree */ xp_rc = xTree_process_leaf_extents (xtiptr->xtp_ptr, inorecptr, xtiptr->this_Qel, msg_info_ptr, xtiptr->dense_file, desired_action); } } else { /* not a leaf node */ if (xtiptr->xtp_ptr->header.flag & BT_INTERNAL) { /* an internal node */ xp_rc = xTree_process_internal_extents (xtiptr->xtp_ptr, inorecptr, xtiptr->this_Qel, msg_info_ptr, desired_action); } else { /* an invalid flag value! */ inorecptr->ignore_alloc_blks = 1; if (desired_action == FSCK_RECORD_DUPCHECK) { /* not reported yet */ fsck_send_msg(fsck_BADINOOTHR, "51", fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } } if ((xp_rc == FSCK_OK) && (!inorecptr->ignore_alloc_blks) && (agg_recptr->treeQ_back == NULL)) { /* nothing fatal and tree looks ok and queue is empty */ xp_rc = xTree_node_last_in_level(xtiptr, inorecptr, msg_info_ptr, desired_action); } } release: /* * there's at least 1 more Q element to release for this node, and * if the tree is bad there may still be some on the queue as well. * * (If there's a processing error all the dynamic storage is going * to be released so there's no point in preparing these elements * for reuse.) */ if ((xp_rc == FSCK_OK) && (xtiptr->this_Qel != NULL)) { xp_rc = treeQ_rel_elem(xtiptr->this_Qel); } if ((xp_rc == FSCK_OK) && (xtiptr->next_Qel != NULL)) { xp_rc = treeQ_rel_elem(xtiptr->next_Qel); } agg_recptr->treeQ_back = NULL; while ((xp_rc == FSCK_OK) && (agg_recptr->treeQ_front != NULL)) { xtiptr->this_Qel = agg_recptr->treeQ_front; agg_recptr->treeQ_front = xtiptr->this_Qel->next; xp_rc = treeQ_rel_elem(xtiptr->this_Qel); } /* end while */ if (xp_rc == FSCK_OK) { /* not planning to quit */ if (desired_action != FSCK_RECORD_DUPCHECK) { /* we altered the corrupt tree bit */ if (old_ignore_alloc_blks && !inorecptr->ignore_alloc_blks) { /* * the flag is set but the bit didn't get * turned back on. This means that the first * time we went through this tree we decided * it was corrupt but this time it looked ok. */ xp_rc = FSCK_INTERNAL_ERROR_8; } else if (!old_ignore_alloc_blks && inorecptr->ignore_alloc_blks) { /* * the flag is off but the bit got turned on. * This means that the first time we went * through this tree it looked ok but this * time we decided that it is corrupt. */ xp_rc = FSCK_INTERNAL_ERROR_9; } } } out: return (xp_rc); } /***************************************************************************** * NAME: xTree_search * * FUNCTION: Search the xTree rooted in the given inode for an xad in a * leaf node which describes the given file offset. * * PARAMETERS: * inoptr - input - pointer to the inode in which the xTree is * rooted * given_key - input - the key (file offset) to match * addr_xad_ptr - input - pointer to a variable in which to return the * address of the xad whose key matches given_key * match_found - input - pointer to a variable in which to return * !0 if a matching xad is found * 0 if no match is found * * RETURNS: * success: FSCK_OK * failure: something else */ int xTree_search(struct dinode *inoptr, int64_t given_key, xad_t ** addr_xad_ptr, int8_t * match_found) { int xs_rc = FSCK_OK; xtpage_t *xtpg_ptr; int8_t extent_located = 0; int8_t not_there = 0; int16_t chosen_idx; int8_t xad_chosen; int64_t last_offset; if (ISDIR(inoptr->di_mode)) xtpg_ptr = (xtpage_t *) & (inoptr->di_dirtable); else xtpg_ptr = (xtpage_t *) & (inoptr->di_btroot); while ((!extent_located) && (!not_there) && (xs_rc == FSCK_OK)) { if (given_key > offsetXAD(&xtpg_ptr->xad[xtpg_ptr->header.nextindex - 1])) { /* follows the start of the last allocation described */ chosen_idx = xtpg_ptr->header.nextindex - 1; xad_chosen = -1; } else if (given_key < offsetXAD(&(xtpg_ptr->xad[XTENTRYSTART]))) { /* precedes the 1st allocation described */ not_there = -1; xad_chosen = 0; } else { /* it's somewhere in between */ xs_rc = xTree_binsrch_page(xtpg_ptr, given_key, &xad_chosen, &chosen_idx, ¬_there); } if ((xs_rc == FSCK_OK) && (xad_chosen)) { /* picked one */ if (xtpg_ptr->header.flag & BT_LEAF) { /* it's this one or none */ /* the last offset in the extent described */ last_offset = offsetXAD(&(xtpg_ptr->xad[chosen_idx])) + lengthXAD(&(xtpg_ptr->xad[chosen_idx])) - 1; if (given_key <= last_offset) { /* it's in the range described */ extent_located = -1; } else { not_there = -1; } } else { /* this xad describes a B+ Tree node on the *next level down */ /* read in the next node */ xs_rc = node_get(addressXAD (&xtpg_ptr->xad[chosen_idx]), &xtpg_ptr); } } } if ((extent_located) && (xs_rc == FSCK_OK)) { /* found it! */ *addr_xad_ptr = &(xtpg_ptr->xad[chosen_idx]); *match_found = -1; } else { /* no luck */ *addr_xad_ptr = NULL; *match_found = 0; } return (xs_rc); } jfsutils-1.1.15.orig/fsck/jfs_fsck.80000644000000000000000000001024210340701412014065 0ustar .TH jfs_fsck 8 "October 29, 2002" " " "JFS utility - file system check" .SH NAME .B jfs_fsck \- initiate replay of the JFS transaction log, and check and repair a JFS formatted device .SH SYNOPSIS .B jfs_fsck [ .B -afnpvV ] [ .B -j .I journal_device ] [ .B --omit_journal_replay ] [ .B --replay_journal_only ] .I device .SH DESCRIPTION .PP .B jfs_fsck is used to replay the JFS transaction log, check a JFS formatted device for errors, and fix any errors found. .PP .I device is the special file name corresponding to the actual device to be checked .RB (e.g. " /dev/hdb1" ). .PP .B jfs_fsck must be run as root. .SH WARNING .PP .B jfs_fsck should only be used to check an .B unmounted file system or a file system that is mounted READ ONLY. Using .B jfs_fsck to check a file system mounted other than READ ONLY could seriously damage the file system! .SH OPTIONS .P If no options are selected, the default is .BR "\-p". .TP .B \-a Autocheck mode - Replay the transaction log. Do not continue fsck processing unless the aggregate state is dirty or the log replay failed. Functionally equivalent to .BR "\-p". Autocheck mode is typically the default mode used when .B jfs_fsck is called at boot time. .\" .TP .\" .B \-b .\" *currently unused* Perform Bad Block List utility processing only. .\" .TP .\" .B \-c .\" After a replay of the transaction log completes successfully, only continue fsck processing if the aggregate state is dirty. .TP .B \-f Replay the transaction log and force checking even if the file system appears clean. Repair all problems automatically. .TP .BI \-j " journal_device" Specify the journal device. .TP .B \-n Open the file system read only. Do not replay the transaction log. Report errors, but do not repair them. .TP .B \--omit_journal_replay Omit the replay of the transaction log. This option should not be used unless as a last resort (i.e. the log has been severely corrupted and replaying it causes further problems). .TP .B \-p Automatically repair ("preen") the file system. Replay the transaction log. Do not continue fsck processing unless the aggregate state is dirty or the log replay failed. Functionally equivalent to .BR "\-a". .TP .B \--replay_journal_only Only replay the transaction log. Do not continue with a full file system check if the replay fails or if the file system is still dirty even after a journal replay. In general, this option should only be used for debugging purposes as it could leave the file system in an unmountable state. This option cannot be used with .BR -f "," .BR -n ", or" .BR --omit_journal_replay "." .TP .B \-v Verbose messaging - print details and debug statements to stdout. .TP .B \-V Print version information and exit (regardless of any other chosen options). .SH EXAMPLES .LP Check the 3rd partition on the 2nd hard disk, print extended information to stdout, replay the transaction log, force complete jfs_fsck checking, and give permission to repair all errors: .IP .B jfs_fsck \-v \-f /dev/hdb3 .IP .LP Check the 5th partition on the 1st hard disk, and report, but do not repair, any errors: .IP .B jfs_fsck \-n /dev/hda5 .IP .SH EXIT CODE .P The exit code returned by .B jfs_fsck represents one of the following conditions: .TP .B \ 0 No errors .TP .B \ 1 File system errors corrected and/or transaction log replayed successfully .TP .B \ 2 File system errors corrected, system should be rebooted if file system was mounted .TP .B \ 4 File system errors left uncorrected .TP .B \ 8 Operational error .TP .B \ 16 Usage or syntax error .TP .B \ 128 Shared library error .SH "REPORTING BUGS" .PP If you find a bug in .B JFS or .BR jfs_fsck , please report it via the bug tracking system ("Report Bugs" section) of the JFS project web site: .nf http://jfs.sourceforge.net/ .fi .PP Please send as much pertinent information as possible, including the complete output of running .B jfs_fsck with the .B \-v option on the JFS device. .SH SEE ALSO .BR fsck (8), .BR jfs_mkfs (8), .BR jfs_fscklog (8), .BR jfs_tune (8), .BR jfs_logdump (8), .BR jfs_debugfs (8) .SH AUTHORS .nf Barry Arndt (barndt@us.ibm.com) William Braswell, Jr. .fi .B jfs_fsck is maintained by IBM. .nf See the JFS project web site for more details: http://jfs.sourceforge.net/ .fi jfsutils-1.1.15.orig/fsck/xchkdsk.c0000644000000000000000000025410111402174203014015 0ustar /* * Copyright (C) International Business Machines Corp., 2000-2004 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include /* defines and includes common among the jfs_fsck modules */ #include "xfsckint.h" #include "xchkdsk.h" #include "fsck_message.h" /* message text, all messages, in english */ #include "jfs_byteorder.h" #include "jfs_unicode.h" #include "jfs_version.h" /* version number and date for utils */ #include "logform.h" #include "logredo.h" #include "message.h" #include "super.h" #include "utilsubs.h" int64_t ondev_jlog_byte_offset; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * superblock buffer and pointer * * values are assigned by the xchkdsk routine */ struct superblock aggr_superblock; struct superblock *sb_ptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * fsck aggregate info structure and pointer * * values are assigned by the xchkdsk routine */ struct fsck_agg_record agg_record; struct fsck_agg_record *agg_recptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * fsck block map info structure and pointer * * values are assigned by the xchkdsk routine */ struct fsck_bmap_record bmap_record; struct fsck_bmap_record *bmap_recptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * For message processing * * values are assigned by the xchkdsk routine */ char *Vol_Label; char *program_name; struct tm *fsck_DateTime = NULL; char time_stamp[20]; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * For directory entry processing * */ int32_t key_len[2]; UniChar key[2][JFS_NAME_MAX]; UniChar ukey[2][JFS_NAME_MAX]; int32_t Uni_Name_len; UniChar Uni_Name[JFS_NAME_MAX]; int32_t Str_Name_len; char Str_Name[JFS_NAME_MAX]; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * Device information. * * values are assigned when (if) the device is opened. */ FILE *Dev_IOPort; uint32_t Dev_blksize; int32_t Dev_SectorSize; char log_device[512] = { 0 }; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * Unicode path strings information. * * values are assigned when the fsck aggregate record is initialized. * accessed via addresses in the fack aggregate record. */ UniChar uni_LSFN_NAME[11] = { 'L', 'O', 'S', 'T', '+', 'F', 'O', 'U', 'N', 'D' }; UniChar uni_lsfn_name[11] = { 'l', 'o', 's', 't', '+', 'f', 'o', 'u', 'n', 'd' }; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * fsckwsp error handling fields * * values are assigned when the fsck workspace storage is * allocated. */ int wsp_dynstg_action; int wsp_dynstg_object; /* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV * * The following are internal to this file * */ int check_parents_and_first_refs(void); int create_lost_and_found(void); int final_processing(void); int initial_processing(int, char **); void parse_parms(int, char **); int phase0_processing(void); int phase1_processing(void); int phase2_processing(void); int phase3_processing(void); int phase4_processing(void); int phase5_processing(void); int phase6_processing(void); int phase7_processing(void); int phase8_processing(void); int phase9_processing(void); int repair_fs_inodes(void); int report_problems_setup_repairs(void); int resolve_lost_and_found(void); int validate_fs_inodes(void); int verify_parms(void); void ask_continue(void); void fsck_usage(void); /* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV */ /* exit value */ int exit_value = FSCK_OK; /***************************************************************************** * NAME: main (jfs_fsck) * * FUNCTION: Entry point for jfs check/repair of aggregate * * INTERFACE: * jfs_fsck * * [ -a ] * autocheck mode * replay the transaction log and quit fsck unless * aggregate state is dirty or log replay failed * * [ -f ] * force check * replay the tranaction log and force checking * * [ -j journal_device ] * specify the external journal device * * [ -n ] * read only check * report but do not repair problems * * [ --omit_journal_replay ] * omit replay of the transaction log * * [ -p ] * preen * same functionality as -a * * [ --replay_journal_only ] * only replay the transaction log * * [ -v ] * verbose messaging * * [ -V ] * version information * print version information and exit * * RETURNS: * success: FSCK_OK (0) * log successfully replayed: FSCK_CORRECTED (1) * errors corrected: FSCK_CORRECTED (1) * errors uncorrected: FSCK_ERRORS_UNCORRECTED (4) * operational error: FSCK_OP_ERROR (8) * usage error: FSCK_USAGE_ERROR (16) */ int main(int argc, char **argv) { int rc = FSCK_OK; time_t Current_Time; /* * some basic initializations */ sb_ptr = &aggr_superblock; agg_recptr = &agg_record; bmap_recptr = &bmap_record; #ifdef _JFS_DEBUG printf("sb_ptr = %p agg_recptr = %p bmap_recptr = %p\n", sb_ptr, agg_recptr, bmap_recptr); #endif if (argc && **argv) program_name = *argv; else program_name = "jfs_fsck"; printf("%s version %s, %s\n", program_name, VERSION, JFSUTILS_DATE); wsp_dynstg_action = dynstg_unknown; wsp_dynstg_object = dynstg_unknown; /* init workspace aggregate record * (the parms will be recorded in it) */ rc = init_agg_record(); /* * Allocate the multi-purpose buffer now so that it can be * used during superblock verification. * * This must be done at least before calling logredo to ensure * that the malloc() will succeed. * (In autocheck mode, logredo is likely to eat up all the * low memory. We don't want to use the alloc_wrksp routine * because we want a page boundary without having to burn * 4096 extra bytes. */ if ((rc = alloc_vlarge_buffer()) != FSCK_OK) { /* alloc_vlarge_buffer not OK */ exit_value = FSCK_OP_ERROR; goto main_exit; } if ((rc = initial_processing(argc, argv)) != FSCK_OK) { /* * Something very wrong has happened. We're not * even sure we're checking a JFS file system! * Appropriate messages should already be logged. */ /* initial_processing sets exit value if unsuccessful */ goto main_exit; } if (!agg_recptr->stdout_redirected) { /* begin the "running" indicator */ fsck_hbeat_start(); } #ifdef CLEARBADBLOCK /* * If they specified Clear Bad Blocks List only (aka /B), * release everything that's allocated, close everything * that's open, and then initiate the requested processing. */ if ((agg_recptr->parm_options[UFS_CHKDSK_CLRBDBLKLST]) && (!agg_recptr->fsck_is_done)) { /* bad block list processing only */ /* * this path is taken only when -f not specified, so * fsck processing is readonly, but the clrbblks * processing requires fsck to do some things it only * permits when processing readwrite. So we reset the * switches temporarily and take care what routines we call. */ agg_recptr->processing_readwrite = 1; agg_recptr->processing_readonly = 0; /* * JFS Clear Bad Blocks List processing * * If things go well, this will issue messages and * write to the service log. */ rc = establish_wsp_block_map_ctl(); /* * terminate fsck service logging */ fscklog_end(); /* * restore the original values. */ agg_recptr->processing_readwrite = 0; agg_recptr->processing_readonly = 1; /* * release any workspace that has been allocated */ workspace_release(); /* * Close (Unlock) the device */ if (agg_recptr->device_is_open) { close_volume(); } /* * Then exit */ if (!agg_recptr->stdout_redirected) { /* end the "running" indicator */ fsck_hbeat_stop(); } return (rc); } #endif if (agg_recptr->fsck_is_done) goto phases_complete; rc = phase0_processing(); if (agg_recptr->fsck_is_done) goto phases_complete; /* * If -n flag was specified, disable write processing now */ if (agg_recptr->parm_options[UFS_CHKDSK_LEVEL0]) { agg_recptr->processing_readonly = 1; agg_recptr->processing_readwrite = 0; } rc = phase1_processing(); if (agg_recptr->fsck_is_done) goto phases_complete; rc = phase2_processing(); if (agg_recptr->fsck_is_done) goto phases_complete; rc = phase3_processing(); if (agg_recptr->fsck_is_done) goto phases_complete; rc = phase4_processing(); if (agg_recptr->fsck_is_done) goto phases_complete; rc = phase5_processing(); if (agg_recptr->fsck_is_done) goto phases_complete; rc = phase6_processing(); if (agg_recptr->fsck_is_done) goto phases_complete; rc = phase7_processing(); if (agg_recptr->fsck_is_done) goto phases_complete; rc = phase8_processing(); if (agg_recptr->fsck_is_done) goto phases_complete; rc = phase9_processing(); phases_complete: if (!agg_recptr->superblk_ok) { /* superblock is bad */ exit_value = FSCK_ERRORS_UNCORRECTED; goto close_vol; } /* we at least have a superblock */ if ((rc == FSCK_OK) && (!(agg_recptr->fsck_is_done))) { /* not fleeing an error and not making a speedy exit */ /* finish up and display some information */ rc = final_processing(); /* flush the I/O buffers to complete any pending writes */ if (rc == FSCK_OK) { rc = blkmap_flush(); } else { blkmap_flush(); } if (rc == FSCK_OK) { rc = blktbl_dmaps_flush(); } else { blktbl_dmaps_flush(); } if (rc == FSCK_OK) { rc = blktbl_Ln_pages_flush(); } else { blktbl_Ln_pages_flush(); } if (rc == FSCK_OK) { rc = iags_flush(); } else { iags_flush(); } if (rc == FSCK_OK) { rc = inodes_flush(); } else { inodes_flush(); } if (rc == FSCK_OK) { rc = mapctl_flush(); } else { mapctl_flush(); } if (rc == FSCK_OK) { rc = flush_index_pages(); } else { flush_index_pages(); } } /* * last chance to write to the wsp block map control page... */ Current_Time = time(NULL); fsck_DateTime = localtime(&Current_Time); sprintf(time_stamp, "%d/%d/%d %d:%02d:%02d", fsck_DateTime->tm_mon + 1, fsck_DateTime->tm_mday, (fsck_DateTime->tm_year + 1900), fsck_DateTime->tm_hour, fsck_DateTime->tm_min, fsck_DateTime->tm_sec); if (agg_recptr->processing_readwrite) { /* on-device fsck workspace block map */ if (agg_recptr->blkmp_ctlptr != NULL) { memcpy(&agg_recptr->blkmp_ctlptr->hdr.end_time[0], &time_stamp[0], 20); agg_recptr->blkmp_ctlptr->hdr.return_code = rc; blkmap_put_ctl_page(agg_recptr->blkmp_ctlptr); } } if (rc == FSCK_OK) { /* either all ok or nothing fatal */ if (agg_recptr->processing_readonly) { /* remind the caller not to take * any messages issued too seriously */ fsck_send_msg(fsck_READONLY); if (agg_recptr->corrections_needed || agg_recptr->corrections_approved) { fsck_send_msg(fsck_ERRORSDETECTED); exit_value = FSCK_ERRORS_UNCORRECTED; } } /* may write to superblocks again */ rc = agg_clean_or_dirty(); } if (agg_recptr->ag_modified) { /* wrote to it at least once */ fsck_send_msg(fsck_MODIFIED); } if (agg_recptr->ag_dirty) { exit_value = FSCK_ERRORS_UNCORRECTED; } /* * Log fsck exit */ fsck_send_msg(fsck_SESSEND, time_stamp, rc, exit_value); /* * terminate fsck service logging */ fscklog_end(); /* * release all workspace that has been allocated */ if (rc == FSCK_OK) { rc = workspace_release(); } else { workspace_release(); } close_vol: /* * Close (Unlock) the device */ if (agg_recptr->device_is_open) { if (rc == FSCK_OK) { rc = close_volume(); } else { close_volume(); } } if (!agg_recptr->stdout_redirected) { /* end the "running" indicator */ fsck_hbeat_stop(); } main_exit: return (exit_value); } /***************************************************************************** * NAME: check_parents_and_first_refs * * FUNCTION: If any aggregate blocks are multiply allocated, find the * first reference for each. Verify that the parent inode * number stored in each directory inode matches the parent * inode observed by fsck for that inode. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int check_parents_and_first_refs() { int rc = FSCK_OK; uint32_t ino_idx; int aggregate_inode = 0; /* going for fileset inodes only */ int alloc_ifnull = 0; int which_it = 0; /* in release 1 there is only fileset 0 */ int inode_already_read, done; int dir_w_hlinks_seen = 0; int dir_w_incrrct_prnt_seen = 0; int unalloc_ino_w_prnts_seen = 0; int unconnected_inode_seen = 0; struct dinode *inoptr; struct fsck_inode_ext_record *this_ext; struct fsck_inode_record *this_inorec; struct fsck_inode_record *parent_inorec; struct fsck_ino_msg_info ino_msg_info; struct fsck_ino_msg_info *msg_info_ptr; msg_info_ptr = &ino_msg_info; msg_info_ptr->msg_inopfx = fsck_fset_inode; /* all fileset owned */ rc = get_inorecptr_first(aggregate_inode, &ino_idx, &this_inorec); while ((rc == FSCK_OK) && (this_inorec != NULL)) { msg_info_ptr->msg_inonum = ino_idx; if (this_inorec->inode_type == directory_inode) { msg_info_ptr->msg_inotyp = fsck_directory; } else if (this_inorec->inode_type == symlink_inode) { msg_info_ptr->msg_inotyp = fsck_symbolic_link; } else if (this_inorec->inode_type == char_special_inode) { msg_info_ptr->msg_inotyp = fsck_char_special; } else if (this_inorec->inode_type == block_special_inode) { msg_info_ptr->msg_inotyp = fsck_block_special; } else if (this_inorec->inode_type == FIFO_inode) { msg_info_ptr->msg_inotyp = fsck_FIFO; } else if (this_inorec->inode_type == SOCK_inode) { msg_info_ptr->msg_inotyp = fsck_SOCK; } else { /* a regular file */ msg_info_ptr->msg_inotyp = fsck_file; } if (this_inorec->in_use) goto inode_in_use; /* not in use. A record allocated means some * directory thinks this inode is its parent */ done = 0; if ((this_inorec->parent_inonum != ROOT_I) || (!agg_recptr->rootdir_rebuilt)) { /* * either this parent isn't the root or else * the root dir has not been rebuilt */ rc = get_inorecptr(aggregate_inode, alloc_ifnull, this_inorec->parent_inonum, &parent_inorec); if ((parent_inorec->in_use) && (!parent_inorec->ignore_alloc_blks) && (!parent_inorec->selected_to_rls)) { /* * parent inode in use and not * selected to release */ this_inorec->unxpctd_prnts = 1; agg_recptr->corrections_needed = 1; unalloc_ino_w_prnts_seen = 1; done = -1; if (agg_recptr->processing_readonly) { /* won't be able to fix this */ fsck_send_msg(fsck_ROUALINOREF, fsck_ref_msg(msg_info_ptr->msg_inopfx), ino_idx); } } } this_ext = this_inorec->ext_rec; while ((this_ext != NULL) && (!done)) { if ( (this_ext->ext_type == parent_extension) && ((this_inorec->parent_inonum != ROOT_I) || (!agg_recptr->rootdir_rebuilt)) ) { /* * either this parent isn't the root or * else the root dir hasn't been rebuilt */ rc = get_inorecptr(aggregate_inode, alloc_ifnull, this_ext->inonum, &parent_inorec); if ((parent_inorec->in_use) && (!parent_inorec->ignore_alloc_blks) && (!parent_inorec->selected_to_rls)) { /* * parent inode in use and * not selected to release */ this_inorec->unxpctd_prnts = 1; agg_recptr->corrections_needed = 1; unalloc_ino_w_prnts_seen = 1; done = -1; if (agg_recptr->processing_readonly) { agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_ROUALINOREF, fsck_ref_msg(msg_info_ptr->msg_inopfx), ino_idx); } } } this_ext = this_ext->next; } goto get_next; inode_in_use: /* inode is in use */ inode_already_read = 0; if ((agg_recptr->unresolved_1stref_count != 0) && (!this_inorec->ignore_alloc_blks)) { /* * there are unresolved 1st references * to multiply allocated blocks, and * blocks for this inode are reflected * in the current workspace block map */ rc = inode_get(aggregate_inode, which_it, ino_idx, &inoptr); if (rc == FSCK_OK) { /* got the inode */ inode_already_read = 1; rc = first_ref_check_inode(inoptr, ino_idx, this_inorec, msg_info_ptr); } } if (rc != FSCK_OK) goto get_next; if ((this_inorec->parent_inonum == 0) && (!this_inorec->unxpctd_prnts) && (ino_idx >= FILESET_OBJECT_I)) { /* * no parent recorded and not a dir with * unexpected parents and not a metadata inode */ if (agg_recptr->processing_readonly) { /* * won't be reconnecting this */ fsck_send_msg(fsck_ROUNCONNIO, fsck_ref_msg(msg_info_ptr->msg_inopfx), ino_idx); } } else if (this_inorec->inode_type == directory_inode) { /* * a directory */ if (!inode_already_read) { /* need to read the inode */ rc = inode_get(aggregate_inode, which_it, ino_idx, &inoptr); } /* * if this is a directory with 'unexpected * parents' (aka illegal hard links) then * the inode number which was stored in * parent_inonum has already been stored in * an extension record. Save the parent * inode number stored in the on-disk inode * for use in messages. */ if (rc != FSCK_OK) goto get_next; if (this_inorec->unxpctd_prnts) { /* * unexpected parents seen */ this_inorec->parent_inonum = inoptr->di_parent; dir_w_hlinks_seen = 1; if (agg_recptr->processing_readonly) { agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_RODIRWHLKS, fsck_ref_msg(msg_info_ptr->msg_inopfx), ino_idx); } /* * Otherwise, make sure a parent * was seen and it's the one whose * inode number is stored in the * on-disk inode. */ } else if ((this_inorec->parent_inonum != 0) && (this_inorec->parent_inonum != inoptr->di_parent)) { /* * the stored parent number is wrong */ this_inorec->crrct_prnt_inonum = 1; dir_w_incrrct_prnt_seen = 1; agg_recptr->corrections_needed = 1; agg_recptr->corrections_approved = 1; if (agg_recptr->processing_readonly) { agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_ROINCINOREF, fsck_ref_msg(msg_info_ptr->msg_inopfx), ino_idx, fsck_ref_msg(msg_info_ptr->msg_inopfx), this_inorec->parent_inonum); } } } get_next: if (rc == FSCK_OK) { rc = get_inorecptr_next(aggregate_inode, &ino_idx, &this_inorec); } } if (agg_recptr->processing_readwrite) { /* we can fix these */ if (unalloc_ino_w_prnts_seen) { fsck_send_msg(fsck_WILLFIXROUALINOREFS); } if (unconnected_inode_seen) { fsck_send_msg(fsck_WILLFIXROUNCONNIOS); } if (dir_w_hlinks_seen) { fsck_send_msg(fsck_WILLFIXRODIRSWHLKS); } if (dir_w_incrrct_prnt_seen) { fsck_send_msg(fsck_WILLFIXROINCINOREFS); } } else { /* don't have write access */ if (unalloc_ino_w_prnts_seen) { fsck_send_msg(fsck_ROUALINOREFS); } if (unconnected_inode_seen) { fsck_send_msg(fsck_ROUNCONNIOS); } if (dir_w_hlinks_seen) { fsck_send_msg(fsck_RODIRSWHLKS); } if (dir_w_incrrct_prnt_seen) { fsck_send_msg(fsck_ROINCINOREFS); } } return (rc); } /***************************************************************************** * NAME: create_lost_and_found * * FUNCTION: During previous processing, fsck observed at least one inode * to be available, and saved the ordinal number of an available * inode in the fsck aggregate record. Initialize that inode * (and the fsck inode record describing it) for use as * /lost+found/ * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int create_lost_and_found() { int claf_rc = FSCK_OK; int intermed_rc = FSCK_OK; struct fsck_inode_record *new_inorecptr; int aggregate_inode = 0; /* going for fileset inodes only */ int alloc_ifnull = -1; int which_it = FILESYSTEM_I; /* in release 1 there is only fileset 0 */ struct dinode *inoptr; int ixpxd_unequal = 0; int is_aggregate = 0; /* aggregate has no dirs */ /* * find/allocate the fsck workspace inode record * for this inode. */ claf_rc = get_inorecptr(aggregate_inode, alloc_ifnull, agg_recptr->avail_inonum, &new_inorecptr); if (claf_rc != FSCK_OK) goto claf_setup_exit; /* * initialize the workspace inode record for * the new lost+found/ */ new_inorecptr->in_use = 1; new_inorecptr->inode_type = directory_inode; new_inorecptr->link_count = 0; new_inorecptr->parent_inonum = 0; new_inorecptr->selected_to_rls = 0; new_inorecptr->crrct_link_count = 0; new_inorecptr->crrct_prnt_inonum = 0; new_inorecptr->adj_entries = 0; new_inorecptr->clr_ea_fld = 0; new_inorecptr->clr_acl_fld = 0; new_inorecptr->inlineea_on = 0; new_inorecptr->inlineea_off = 0; new_inorecptr->inline_data_err = 0; new_inorecptr->ignore_alloc_blks = 0; new_inorecptr->reconnect = 0; new_inorecptr->unxpctd_prnts = 0; new_inorecptr->involved_in_dups = 0; /* * get the inode to be used for lost+found */ claf_rc = inode_get(aggregate_inode, which_it, agg_recptr->avail_inonum, &inoptr); if (claf_rc != FSCK_OK) goto claf_setup_exit; /* the new lost+found inode is in the buffer */ ixpxd_unequal = memcmp((void *) &inoptr->di_ixpxd, (void *) &agg_recptr->ino_ixpxd, sizeof (pxd_t)); if ((inoptr->di_inostamp == agg_recptr->inode_stamp) && (!ixpxd_unequal) && (inoptr->di_number == agg_recptr->avail_inonum) && (inoptr->di_fileset == agg_recptr->ino_fsnum)) { /* * inode has been used before */ inoptr->di_gen++; } else { /* this inode hasn't been used before */ /* clear it */ memset(inoptr, 0, sizeof (struct dinode)); /* * initialize the inode */ inoptr->di_inostamp = agg_recptr->inode_stamp; inoptr->di_fileset = agg_recptr->ino_fsnum; inoptr->di_number = agg_recptr->avail_inonum; inoptr->di_gen = 1; memcpy((void *) &(inoptr->di_ixpxd), (void *) &(agg_recptr->ino_ixpxd), sizeof (pxd_t)); } inoptr->di_mode = (IDIRECTORY | IFJOURNAL | IFDIR | IREAD | IWRITE | IEXEC); inoptr->di_parent = ROOT_I; /* one from root and one from self */ inoptr->di_nlink = 2; inoptr->di_nblocks = 0; inoptr->di_size = IDATASIZE; DXDlength(&(inoptr->di_acl), (int32_t) 0); DXDaddress(&(inoptr->di_acl), (int64_t) 0); inoptr->di_acl.flag = 0; inoptr->di_acl.size = 0; DXDlength(&(inoptr->di_ea), (int32_t) 0); DXDaddress(&(inoptr->di_ea), (int64_t) 0); inoptr->di_ea.flag = 0; inoptr->di_ea.size = 0; inoptr->di_next_index = 2; inoptr->di_acltype = 0; inoptr->di_atime.tv_sec = (uint32_t) time(NULL); inoptr->di_ctime.tv_sec = inoptr->di_atime.tv_sec; inoptr->di_mtime.tv_sec = inoptr->di_atime.tv_sec; inoptr->di_otime.tv_sec = inoptr->di_atime.tv_sec; /* * initialize the d-tree */ init_dir_tree((dtroot_t *) & (inoptr->di_btroot)); /* * write the inode */ claf_rc = inode_put(inoptr); if (claf_rc != FSCK_OK) goto claf_setup_exit; new_inorecptr->parent_inonum = ROOT_I; /* The inode is correct. After * this we'll start accumulating adjustments */ new_inorecptr->link_count = 0; /* * add an entry for it to the root directory */ intermed_rc = inode_get(is_aggregate, which_it, ROOT_I, &inoptr); if (intermed_rc == FSCK_OK) { intermed_rc = direntry_add(inoptr, agg_recptr->avail_inonum, agg_recptr->UniChar_lsfn_name); } if (intermed_rc == FSCK_OK) { /* added the entry */ /* increment the link count in the root * inode because we just added a subdirectory. * (Subdirectories point back to parent.) */ inoptr->di_nlink += 1; } else if (intermed_rc < 0) { /* it was fatal */ claf_rc = intermed_rc; } else { /* not successful, but not fatal */ claf_rc = FSCK_CANT_EXTEND_ROOTDIR; new_inorecptr->in_use = 0; } claf_setup_exit: if (claf_rc != FSCK_OK) { /* failed to create */ agg_recptr->lsfn_ok = 0; new_inorecptr->in_use = 0; fsck_send_msg(fsck_LSFNCNTCRE); } return (claf_rc); } /*************************************************************************** * NAME: final_processing * * FUNCTION: If processing read/write, replicate the superblock and the * aggregate inode structures (i.e., the Aggregate Inode Map * and the Aggregate Inode Table). * * Notify the user about various things. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int final_processing() { int pf_rc = FSCK_OK; int64_t observed_total_blocks, recorded_total_blocks; int64_t reportable_total_blocks; int64_t kbytes_for_dirs, kbytes_for_files; int64_t kbytes_for_eas, kbytes_for_acls; int64_t kbytes_total, kbytes_free, kbytes_reserved; int64_t block_surprise; /* * report extra or missing aggregate blocks * * Note that since the agg_record is instantiated in the * module (and not a malloc'ed space) it is still available * after the workspace has been released. * */ reportable_total_blocks = agg_recptr->blocks_used_in_aggregate + agg_recptr->free_blocks_in_aggregate; observed_total_blocks = reportable_total_blocks - agg_recptr->ondev_jlog_fsblk_length - agg_recptr->ondev_fscklog_fsblk_length - agg_recptr->ondev_wsp_fsblk_length; /* size in aggregate blocks */ recorded_total_blocks = sb_ptr->s_size * Dev_blksize / sb_ptr->s_bsize; if (observed_total_blocks > recorded_total_blocks) { block_surprise = observed_total_blocks - recorded_total_blocks; fsck_send_msg(fsck_XTRABLKS, (long long) block_surprise); } else if (recorded_total_blocks > observed_total_blocks) { block_surprise = recorded_total_blocks - observed_total_blocks; fsck_send_msg(fsck_MSSNGBLKS, (long long) block_surprise); } if (agg_recptr->processing_readwrite) { /* * Make sure the s_logdev is up to date in the superblock. */ if ((Log.location & OUTLINELOG) && Log.devnum) sb_ptr->s_logdev = Log.devnum; /* refresh the redundancy of the * aggregate superblock (and verify * successful write to the one we * haven't been using) */ pf_rc = replicate_superblock(); } /* * finish up processing */ fsck_send_msg(fsck_FSSMMRY3); /* * log the summary messages originally defined */ fsck_send_msg(fsck_FSSMMRY4, (long long) agg_recptr->blocks_for_inodes); fsck_send_msg(fsck_FSSMMRY5, (long long) agg_recptr->inodes_in_aggregate); fsck_send_msg(fsck_FSSMMRY6, (long long) agg_recptr->files_in_aggregate); fsck_send_msg(fsck_FSSMMRY9, (long long) agg_recptr->dirs_in_aggregate); fsck_send_msg(fsck_FSSMMRY7, (long long) reportable_total_blocks); fsck_send_msg(fsck_FSSMMRY8, (long long) agg_recptr->free_blocks_in_aggregate); /* * issue (and log) the standard messages */ /* number of blocks times bytes per block divided by bytes per kilobyte */ kbytes_total = reportable_total_blocks << agg_recptr->log2_blksize >> log2BYTESPERKBYTE; /* blocks for file inodes times bytes per block */ /* plus bytes for the file inodes themselves */ /* divided by bytes per kilobyte */ kbytes_for_dirs = ((agg_recptr->blocks_for_dirs << agg_recptr->log2_blksize) + (agg_recptr->dirs_in_aggregate << log2INODESIZE) ) >> log2BYTESPERKBYTE; /* blocks for file inodes times bytes per block */ /* plus bytes for the file inodes themselves */ /* divided by bytes per kilobyte */ kbytes_for_files = ((agg_recptr->blocks_for_files << agg_recptr->log2_blksize) + (agg_recptr->files_in_aggregate << log2INODESIZE) ) >> log2BYTESPERKBYTE; /* number of blocks times bytes per block divided by bytes per kilobyte */ kbytes_for_eas = agg_recptr->blocks_for_eas << agg_recptr->log2_blksize >> log2BYTESPERKBYTE; /* number of blocks times bytes per block divided by bytes per kilobyte */ kbytes_for_acls = agg_recptr->blocks_for_acls << agg_recptr->log2_blksize >> log2BYTESPERKBYTE; /* number of blocks times bytes per block divided by bytes per kilobyte */ kbytes_free = agg_recptr->free_blocks_in_aggregate << agg_recptr->log2_blksize >> log2BYTESPERKBYTE; /* everything else is reserved */ kbytes_reserved = kbytes_total - -kbytes_for_dirs - kbytes_for_files - kbytes_for_eas - kbytes_for_acls - kbytes_free; fsck_send_msg(fsck_STDSUMMARY1, (long long) kbytes_total); fsck_send_msg(fsck_STDSUMMARY2, (long long) kbytes_for_dirs, (long long) agg_recptr->dirs_in_aggregate); fsck_send_msg(fsck_STDSUMMARY3, (long long) kbytes_for_files, (long long) agg_recptr->files_in_aggregate); fsck_send_msg(fsck_STDSUMMARY4, (long long) kbytes_for_eas); fsck_send_msg(fsck_STDSUMMARY4A, (long long) kbytes_for_acls); fsck_send_msg(fsck_STDSUMMARY5, (long long) kbytes_reserved); fsck_send_msg(fsck_STDSUMMARY6, (long long) kbytes_free); if (pf_rc != FSCK_OK) { agg_recptr->fsck_is_done = 1; } return (pf_rc); } /***************************************************************************** * NAME: report_problems_setup_repairs * * FUNCTION: For each inode in the fileset, if fsck has determined that * any repairs are needed, get/verify permission to perform * the repair and, if permission has been given, adjust the * other inodes for implied repairs as appropriate. (E.g., * if inode a is released, then each directory inode parent * of a needs to have the entry for a removed.) * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int report_problems_setup_repairs() { int rc = FSCK_OK; uint32_t ino_idx; int aggregate_inode = 0; /* going for fileset inodes only */ struct fsck_inode_ext_record *this_ext; struct fsck_inode_ext_record *ext_list; struct fsck_inode_record *this_inorec; int8_t other_adjustments; struct fsck_ino_msg_info ino_msg_info; struct fsck_ino_msg_info *msg_info_ptr; msg_info_ptr = &ino_msg_info; msg_info_ptr->msg_inopfx = fsck_fset_inode; /* all fileset owned */ rc = get_inorecptr_first(aggregate_inode, &ino_idx, &this_inorec); while ((rc == FSCK_OK) && (this_inorec != NULL)) { if (!((this_inorec->selected_to_rls) || (this_inorec->clr_ea_fld) || (this_inorec->clr_acl_fld) || (this_inorec->inlineea_on) || (this_inorec->inlineea_off) || (this_inorec->inline_data_err) || (this_inorec->cant_chkea) || (this_inorec->adj_entries) || (this_inorec->rebuild_dirtable) || ((this_inorec->unxpctd_prnts) && (!this_inorec->in_use)))) goto rpsr_next; /* * a record is allocated and flagged * for some repair (other than directory * with illegal hard links) or warning */ msg_info_ptr->msg_inonum = ino_idx; if (this_inorec->inode_type == directory_inode) { msg_info_ptr->msg_inotyp = fsck_directory; } else if (this_inorec->inode_type == symlink_inode) { msg_info_ptr->msg_inotyp = fsck_symbolic_link; } else if (this_inorec->inode_type == char_special_inode) { msg_info_ptr->msg_inotyp = fsck_char_special; } else if (this_inorec->inode_type == block_special_inode) { msg_info_ptr->msg_inotyp = fsck_block_special; } else if (this_inorec->inode_type == FIFO_inode) { msg_info_ptr->msg_inotyp = fsck_FIFO; } else if (this_inorec->inode_type == SOCK_inode) { msg_info_ptr->msg_inotyp = fsck_SOCK; } else { /* a regular file */ msg_info_ptr->msg_inotyp = fsck_file; } rc = display_paths(ino_idx, this_inorec, msg_info_ptr); if (rc != FSCK_OK) goto rpsr_next; if (!this_inorec->in_use) { /* not in use. */ if (this_inorec->unxpctd_prnts) { /* but with parents */ if (agg_recptr->processing_readwrite) { /* we can fix this */ rc = adjust_parents(this_inorec, ino_idx); agg_recptr->corrections_approved = 1; fsck_send_msg(fsck_WILLRMVBADREF); } else { /* don't have write access */ fsck_send_msg(fsck_INOBADREF); agg_recptr->ag_dirty = 1; } } else { /* shouldn't have created a record for it! */ rc = FSCK_INTERNAL_ERROR_2; } goto rpsr_next; } /* inode is in use */ if (this_inorec->selected_to_rls) { /* selected to release */ /* * explain the problem(s) */ if (this_inorec->inode_type == unrecognized_inode) { fsck_send_msg(fsck_BADINOFORMATO); } if (this_inorec->ignore_alloc_blks) { /* corrupt tree */ if (this_inorec->inode_type == file_inode) { fsck_send_msg(fsck_BADINODATAFORMAT); } else if (this_inorec->inode_type == directory_inode) { fsck_send_msg(fsck_BADINODATAFORMATD); } else { fsck_send_msg(fsck_BADINODATAFORMATO); } } if (this_inorec->inline_data_err) { /* invalid inline data spec */ if (this_inorec->inode_type == file_inode) { fsck_send_msg(fsck_BADINODATAFORMAT); } else if (this_inorec->inode_type == directory_inode) { fsck_send_msg(fsck_BADINODATAFORMATD); } else { fsck_send_msg(fsck_BADINODATAFORMATO); } } if (this_inorec->involved_in_dups) { if (this_inorec->inode_type == file_inode) { fsck_send_msg(fsck_BADINOCLAIMSDUPSF); } else if (this_inorec->inode_type == directory_inode) { fsck_send_msg(fsck_BADINOCLAIMSDUPSD); } else { fsck_send_msg(fsck_BADINOCLAIMSDUPSO); } } /* * notify of intentions (if any) */ if (agg_recptr->processing_readwrite) { /* we can fix this */ rc =adjust_parents(this_inorec, ino_idx); agg_recptr->corrections_approved = 1; fsck_send_msg(fsck_WILLRELEASEINO, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } else { /* we don't have write access */ this_inorec->selected_to_rls = 0; /* * If the tree is corrupt, or the type is unrecognized, * keeping it makes the filesystem dirty. * Otherwise it's just the alleged owner of some * multiply allocated block(s). In the latter case, the * aggregate isn't necessarily dirty just because we don't * release this particular inode. If all other alleged * owners are released then this one becomes OK. After * all releases are done we'll check to see if any block(s) * are still multiply allocated, and if so we'll mark the * aggregate dirty. */ if ((this_inorec->inode_type == unrecognized_inode) || (this_inorec->ignore_alloc_blks)) { agg_recptr->ag_dirty =1; } fsck_send_msg(fsck_CANTREPAIRINO, fsck_ref_msg(msg_info_ptr->msg_inotyp), fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } if ( (rc != FSCK_OK) || this_inorec->ignore_alloc_blks || this_inorec->selected_to_rls ) goto rpsr_next; /* not corrupt and */ /* either never selected to release or * selected and release declined */ if ((rc == FSCK_OK) && (this_inorec->clr_ea_fld)) { /* clear EA */ if (agg_recptr->processing_readwrite) { /* we can fix this */ agg_recptr->corrections_approved = 1; fsck_send_msg(fsck_WILLCLEAREA); } else { /* we don't have write access */ this_inorec->clr_ea_fld = 0; agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_INOEA); } } if ((rc == FSCK_OK) && (this_inorec->clr_acl_fld)) { /* clear ACL */ if (agg_recptr->processing_readwrite) { /* we can fix this */ agg_recptr->corrections_approved = 1; fsck_send_msg(fsck_WILLCLEARACL); } else { /* we don't have write access */ this_inorec->clr_acl_fld = 0; agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_INOACL); } } if ((rc == FSCK_OK) && (this_inorec->inlineea_off)) { /* turn off sect 4 avail flag */ if (agg_recptr->processing_readwrite) { /* we can fix this */ agg_recptr->corrections_approved = 1; fsck_send_msg(fsck_WILLFIXINOMINOR); } else { /* we don't have write access */ this_inorec->inlineea_off = 0; agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_INOMINOR); } } if ((rc == FSCK_OK) && (this_inorec->inlineea_on)) { /* turn on sect 4 avail flag */ if (agg_recptr->processing_readwrite) { /* we can fix this */ agg_recptr->corrections_approved = 1; fsck_send_msg(fsck_WILLFIXINOMINOR); } else { /* we don't have write access */ this_inorec->inlineea_on = 0; fsck_send_msg(fsck_INOMINOR); } } if ((rc == FSCK_OK) && (this_inorec->adj_entries)) { /* adjust dir entries */ other_adjustments = 0; ext_list = this_inorec->ext_rec; this_inorec->ext_rec = NULL; while (ext_list != NULL) { this_ext = ext_list; ext_list = ext_list->next; if ((this_ext->ext_type == add_direntry_extension) || (this_ext->ext_type == rmv_direntry_extension)) { other_adjustments = -1; agg_recptr->corrections_approved = 1; } if (this_ext->ext_type != rmv_badentry_extension) { this_ext->next = this_inorec->ext_rec; this_inorec->ext_rec = this_ext; } else { /* it represents a bad entry */ if (agg_recptr->processing_readwrite) { /* we can fix this */ agg_recptr-> corrections_approved = 1; this_ext->next = this_inorec->ext_rec; this_inorec->ext_rec = this_ext; other_adjustments = -1; fsck_send_msg (fsck_WILLRMVBADENTRY, fsck_ref_msg(msg_info_ptr->msg_inopfx), this_ext->inonum); } else { /* we don't have write access */ release_inode_extension (this_ext); agg_recptr->ag_dirty = 1; fsck_send_msg (fsck_BADDIRENTRY, fsck_ref_msg(msg_info_ptr->msg_inopfx), this_ext->inonum); } } } if (!other_adjustments) { this_inorec->adj_entries = 0; } else { this_inorec->adj_entries = 1; agg_recptr->corrections_needed = 1; } } if ((rc == FSCK_OK) && (this_inorec->cant_chkea)) { /* * wasn't able to check the EA format */ fsck_send_msg(fsck_CANTCHKEA); } if ((rc == FSCK_OK) && (this_inorec->rebuild_dirtable)) { if (agg_recptr->processing_readwrite) { /* we can fix this */ agg_recptr->corrections_approved = 1; fsck_send_msg(fsck_WILLFIX_DI_TABLE); } else { /* we don't have write access */ this_inorec->rebuild_dirtable = 0; agg_recptr->ag_dirty = 1; fsck_send_msg(fsck_DI_TABLE); } } rpsr_next: if (rc == FSCK_OK) { rc = get_inorecptr_next(aggregate_inode, &ino_idx, &this_inorec); } } return (rc); } /***************************************************************************** * NAME: initial_processing * * FUNCTION: Parse and verify invocation parameters. Open the device and * verify that it contains a JFS file system. Check and repair * the superblock. Initialize the fsck aggregate record. Refresh * the boot sector on the volume. Issue some opening messages. * * * PARAMETERS: as specified to main() * * NOTES: sets exit_value if other than OK * * RETURNS: * success: FSCK_OK * failure: something else */ int initial_processing(int argc, char **argv) { int pi_rc = FSCK_OK; int iml_rc = FSCK_OK; int64_t fsblk_offset_bak; int64_t byte_offset_bak; time_t Current_Time; char message_parm[MAXPARMLEN]; /* * Initiate fsck service logging */ iml_rc = fscklog_start(); /* * Log the beginning of the fsck session */ Current_Time = time(NULL); fsck_DateTime = localtime(&Current_Time); sprintf(message_parm, "%d/%d/%d %d:%02d:%02d", fsck_DateTime->tm_mon + 1, fsck_DateTime->tm_mday, (fsck_DateTime->tm_year + 1900), fsck_DateTime->tm_hour, fsck_DateTime->tm_min, fsck_DateTime->tm_sec); fsck_send_msg(fsck_SESSSTART, message_parm); /* * Process the parameters given by the user */ /* parse the parms and record them in the aggregate wsp record */ parse_parms(argc, argv); if ((pi_rc = Is_Device_Mounted(Vol_Label)) != FSCK_OK) { switch (pi_rc) { case MSG_JFS_VOLUME_IS_MOUNTED_RO: /* is mounted read only */ if ((agg_recptr->parm_options[UFS_CHKDSK_DEBUG]) || (agg_recptr->parm_options[UFS_CHKDSK_VERBOSE])) printf("\nFSCK Device %s is currently mounted " "READ ONLY.\n", Vol_Label); break; case MSG_JFS_MNT_LIST_ERROR: /* setmntent failed */ if ((agg_recptr->parm_options[UFS_CHKDSK_DEBUG]) || (agg_recptr->parm_options[UFS_CHKDSK_VERBOSE])) printf("\njfs_fsck cannot access file system " "description file to determine mount\n" "status and file system type of device " "%s. jfs_fsck will continue.\n\n", Vol_Label); break; case MSG_JFS_VOLUME_IS_MOUNTED: if (agg_recptr->parm_options[UFS_CHKDSK_LEVEL0]) { /* read only */ fsck_send_msg(fsck_FSMNTD); fsck_send_msg(fsck_MNTFSYS2); } else { /* is mounted */ printf("\n%s is mounted.\n\nWARNING!!!\n" "Running fsck on a mounted file system\n" "may cause SEVERE file system damage." "\n\n", Vol_Label); ask_continue(); } break; case MSG_JFS_NOT_JFS: /* is not JFS */ printf("\n%s is mounted and the file system is not type" " JFS.\n\nWARNING!!!\nRunning jfs_fsck on a " "mounted file system\nor on a file system other " "than JFS\nmay cause SEVERE file system damage." "\n\n", Vol_Label); ask_continue(); break; default: ask_continue(); break; } } /* the parms are good */ pi_rc = verify_parms(); /* * Open the device and verify that it contains a valid JFS aggregate * If it does, check/repair the superblock. */ if (pi_rc != FSCK_OK) { /* verify_parms returned bad rc */ exit_value = FSCK_USAGE_ERROR; goto ip_exit; } /* parms are good */ fsck_send_msg(fsck_DRIVEID, Vol_Label); pi_rc = open_volume(Vol_Label); if (pi_rc != FSCK_OK) { /* device open failed */ fsck_send_msg(fsck_CNTRESUPB); exit_value = FSCK_OP_ERROR; goto ip_exit; } /* device is open */ agg_recptr->device_is_open = 1; pi_rc = validate_repair_superblock(); if (pi_rc != FSCK_OK) { /* superblock invalid */ exit_value = FSCK_OP_ERROR; goto ip_exit; } fsck_send_msg(fsck_DRIVETYPE); /* * add some stuff to the agg_record which is based on * superblock fields */ agg_recptr->log2_blksize = log2shift(sb_ptr->s_bsize); agg_recptr->blksperpg = BYTESPERPAGE / sb_ptr->s_bsize; agg_recptr->log2_blksperpg = log2shift(agg_recptr->blksperpg); agg_recptr->log2_blksperag = log2shift(sb_ptr->s_agsize); /*highest is the last one before the in-aggregate journal log */ agg_recptr->highest_valid_fset_datablk = addressPXD(&(sb_ptr->s_fsckpxd)) - 1; /* lowest is the first after the secondary aggreg inode table */ agg_recptr->lowest_valid_fset_datablk = addressPXD(&(sb_ptr->s_ait2)) + (INODE_EXTENT_SIZE / sb_ptr->s_bsize) + 1; /* * agg size in logical blks is * (size in phys blks times phys blk size divided by log blk size) * number of AGs in the aggregate: * (agg size in log blks plus AG size in log blks minus 1) * divided by (AG size in log blks) */ agg_recptr->num_ag = ((sb_ptr->s_size * sb_ptr->s_pbsize / sb_ptr->s_bsize) + sb_ptr->s_agsize - 1) / sb_ptr->s_agsize; agg_recptr->sb_agg_fsblk_length = sb_ptr->s_size * sb_ptr->s_pbsize / sb_ptr->s_bsize; /* length of the on-device journal log */ agg_recptr->ondev_jlog_fsblk_length = lengthPXD(&(sb_ptr->s_logpxd)); /* aggregate block offset of the on-device journal log */ agg_recptr->ondev_jlog_fsblk_offset = addressPXD(&(sb_ptr->s_logpxd)); ondev_jlog_byte_offset = agg_recptr->ondev_jlog_fsblk_offset * sb_ptr->s_bsize; /* length of the on-device fsck service log */ agg_recptr->ondev_fscklog_byte_length = sb_ptr->s_fsckloglen * sb_ptr->s_bsize; /* length of the on-device fsck service log */ agg_recptr->ondev_fscklog_fsblk_length = sb_ptr->s_fsckloglen; /* length of the on-device fsck workspace */ agg_recptr->ondev_wsp_fsblk_length = lengthPXD(&(sb_ptr->s_fsckpxd)) - agg_recptr->ondev_fscklog_fsblk_length; /* length of the on-device fsck workspace */ agg_recptr->ondev_wsp_byte_length = agg_recptr->ondev_wsp_fsblk_length * sb_ptr->s_bsize; /* aggregate block offset of the on-device fsck workspace */ agg_recptr->ondev_wsp_fsblk_offset = addressPXD(&(sb_ptr->s_fsckpxd)); /* byte offset of the on-device fsck workspace */ agg_recptr->ondev_wsp_byte_offset = agg_recptr->ondev_wsp_fsblk_offset * sb_ptr->s_bsize; /* aggregate block offset of the on-device fsck workspace */ agg_recptr->ondev_fscklog_fsblk_offset = agg_recptr->ondev_wsp_fsblk_offset + agg_recptr->ondev_wsp_fsblk_length; /* byte offset of the on-device fsck workspace */ agg_recptr->ondev_fscklog_byte_offset = agg_recptr->ondev_wsp_byte_offset + agg_recptr->ondev_wsp_byte_length; /* * The offsets now assume the prior log (the one to overwrite) is * 1st in the aggregate fsck service log space. Adjust if needed. */ if (sb_ptr->s_fscklog == 0) { /* first time ever for this aggregate */ fsblk_offset_bak = agg_recptr->ondev_fscklog_fsblk_offset; byte_offset_bak = agg_recptr->ondev_fscklog_byte_offset; /* * initialize the 2nd service log space * * (we'll actually write the log to the 1st space, so * we'll initialize it below) */ agg_recptr->ondev_fscklog_fsblk_offset += agg_recptr->ondev_fscklog_fsblk_length / 2; agg_recptr->ondev_fscklog_byte_offset += agg_recptr->ondev_fscklog_byte_length / 2; agg_recptr->fscklog_agg_offset = agg_recptr->ondev_fscklog_byte_offset; fscklog_init(); sb_ptr->s_fscklog = 1; agg_recptr->ondev_fscklog_fsblk_offset = fsblk_offset_bak; agg_recptr->ondev_fscklog_byte_offset = byte_offset_bak; } else if (sb_ptr->s_fscklog == 1) { /* the 1st is most recent */ sb_ptr->s_fscklog = 2; agg_recptr->ondev_fscklog_fsblk_offset += agg_recptr->ondev_fscklog_fsblk_length / 2; agg_recptr->ondev_fscklog_byte_offset += agg_recptr->ondev_fscklog_byte_length / 2; } else { /* the 1st is the one to overwrite */ sb_ptr->s_fscklog = 1; } agg_recptr->fscklog_agg_offset = agg_recptr->ondev_fscklog_byte_offset; /* * Initialize the service log */ fscklog_init(); /* from the user's perspective, these are in use (by jfs) */ agg_recptr->blocks_used_in_aggregate = agg_recptr->ondev_wsp_fsblk_length + agg_recptr->ondev_fscklog_fsblk_length + agg_recptr->ondev_jlog_fsblk_length; agg_recptr->superblk_ok = 1; if ((!agg_recptr->parm_options[UFS_CHKDSK_LEVEL0]) && (agg_recptr->processing_readonly)) { /* user did not specify check only but we can only * do check because we don't have write access */ fsck_send_msg(fsck_WRSUP); } ip_exit: return (pi_rc); } /***************************************************************************** * NAME: parse_parms * * FUNCTION: Parse the invocation parameters. If any unrecognized * parameters are detected, or if any required parameter is * omitted, issue a message and exit. * * PARAMETERS: as specified to main() * * RETURNS: If there is an error in parse_parms, it calls fsck_usage() * to remind the user of command format and proper options. * fsck_usage then exits with exit code FSCK_USAGE_ERROR. */ void parse_parms(int argc, char **argv) { int c; char *device_name = NULL; FILE *file_p = NULL; char *short_opts = "adfj:noprvVy"; struct option long_opts[] = { { "omit_journal_replay", no_argument, NULL, 'o'}, { "replay_journal_only", no_argument, NULL, 'J'}, { NULL, 0, NULL, 0} }; while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != EOF) { switch (c) { case 'r': /************************* * interactive autocheck * *************************/ /* * jfs_fsck does not support interactive checking, * so -r is undocumented. However, for backwards * compatibility, -r is supported here and functions * similarly as -p. */ case 'a': case 'p': /******************* * preen autocheck * *******************/ agg_recptr->parm_options[UFS_CHKDSK_LEVEL2] = -1; agg_recptr->parm_options[UFS_CHKDSK_IFDIRTY] = -1; break; #if 0 case 'b': /******************************************* * Clear LVM Bad Block List utility option * *******************************************/ agg_recptr->parm_options[UFS_CHKDSK_CLRBDBLKLST] = -1; break; case 'c': /****************** * IfDirty option * ******************/ agg_recptr->parm_options[UFS_CHKDSK_IFDIRTY] = -1; break; #endif case 'f': /******************************** * Force check after log replay * ********************************/ agg_recptr->parm_options[UFS_CHKDSK_LEVEL3] = -1; break; case 'j': /************************** * Specify journal device * **************************/ strncpy(log_device, optarg, sizeof (log_device) - 1); break; case 'J': /*********************** * Replay journal only * ***********************/ agg_recptr->parm_options_logredo_only = 1; break; case 'n': /*********************************** * Level0 (no write access) option * ***********************************/ agg_recptr->parm_options[UFS_CHKDSK_LEVEL0] = -1; break; case 'o': /************************************ * Omit logredo() processing option * ************************************/ agg_recptr->parm_options[UFS_CHKDSK_SKIPLOGREDO] = -1; agg_recptr->parm_options_nologredo = 1; break; case 'd': /**************** * Debug option * ****************/ /* undocumented at this point, it is similar to -v */ dbg_output = 1; case 'v': /****************** * Verbose option * ******************/ agg_recptr->parm_options[UFS_CHKDSK_VERBOSE] = -1; break; case 'V': /********************** * print version only * **********************/ exit(FSCK_OK); break; case 'y': /****************************** * 'yes to everything' option * ******************************/ /* * jfs_fsck does not support interactive checking, * so the -y option isn't necessary here. However, * in striving to have options similar to those * of e2fsck, we will let -y be the same as the * default -p (unless it is overridden), since * the functionality is similar for both -y and -p. */ break; default: fsck_usage(); } } if (agg_recptr->parm_options_logredo_only && (agg_recptr->parm_options_nologredo || agg_recptr->parm_options[UFS_CHKDSK_LEVEL3] || agg_recptr->parm_options[UFS_CHKDSK_LEVEL0]) ) { printf("\nError: --replay_journal_only cannot be used " "with -f, -n, or --omit_journal_replay.\n"); fsck_usage(); } if (optind != argc - 1) { printf("\nError: Device not specified or command format error\n"); fsck_usage(); } device_name = argv[optind]; file_p = fopen(device_name, "r"); if (file_p) { fclose(file_p); } else { printf("\nError: Cannot open device %s\n", device_name); fsck_usage(); } Vol_Label = device_name; return; } /***************************************************************************** * NAME: phase0_processing * * FUNCTION: Log Redo processing. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int phase0_processing() { int p0_rc = FSCK_OK; int64_t agg_blks; int32_t use_2ndary_superblock = 0; agg_recptr->logredo_rc = FSCK_OK; /* * if this flag is set then the primary superblock is * corrupt. The secondary superblock is good, but we * weren't able to fix the primary version. logredo can * run, but must use the secondary version of the * aggregate superblock */ if (agg_recptr->cant_write_primary_sb == 1) { use_2ndary_superblock = -1; } /* * start off phase 0 */ fsck_send_msg(fsck_FSSMMRY1, sb_ptr->s_bsize); /* aggregate size in fs blocks, by the user's point of view. */ agg_blks = agg_recptr->sb_agg_fsblk_length + agg_recptr->ondev_jlog_fsblk_length + agg_recptr->ondev_fscklog_fsblk_length + agg_recptr->ondev_wsp_fsblk_length; fsck_send_msg(fsck_FSSMMRY2, (long long) agg_blks); /* * logredo processing */ if ((agg_recptr->processing_readwrite) && (!agg_recptr->parm_options_nologredo)) { /* read/write access AND user didn't say not to need to invoke logredo */ fsck_send_msg(fsck_PHASE0); #ifdef _JFS_DEBUG printf("JFS fsck calling logredo \n"); #endif /* * write the superblock to commit any changes we have made in it */ if (use_2ndary_superblock) { /* put 2ndary */ ujfs_put_superblk(Dev_IOPort, sb_ptr, 0); } else { /* put primary */ ujfs_put_superblk(Dev_IOPort, sb_ptr, 1); } agg_recptr->logredo_rc = jfs_logredo(Vol_Label, Dev_IOPort, use_2ndary_superblock); #ifdef _JFS_DEBUG printf("JFS fsck back from logredo, rc = %ld \n", agg_recptr->logredo_rc); #endif /* If superblock is clean and log in use, it's okay */ if ((agg_recptr->logredo_rc == LOG_IN_USE) && (sb_ptr->s_state == FM_CLEAN)) agg_recptr->logredo_rc = FSCK_OK; if (agg_recptr->logredo_rc != FSCK_OK) { /* logredo failed */ fsck_send_msg(fsck_LOGREDOFAIL, agg_recptr->logredo_rc); } else { fsck_send_msg(fsck_LOGREDORC, agg_recptr->logredo_rc); } /* * logredo may change the superblock, so read it in again */ if (use_2ndary_superblock) { /* get 2ndary */ ujfs_get_superblk(Dev_IOPort, sb_ptr, 0); } else { /* get primary */ ujfs_get_superblk(Dev_IOPort, sb_ptr, 1); } } if (agg_recptr->parm_options[UFS_CHKDSK_IFDIRTY] && (!agg_recptr->parm_options_nologredo) && ((sb_ptr->s_state & FM_DIRTY) != FM_DIRTY) && (agg_recptr->logredo_rc == FSCK_OK) && ((sb_ptr->s_flag & JFS_BAD_SAIT) != JFS_BAD_SAIT)) { /* * user specified 'only if dirty' * and didn't specify 'omit logredo()' * and logredo was successful * and the aggregate is clean */ agg_recptr->fsck_is_done = 1; exit_value = FSCK_OK; } else if (agg_recptr->parm_options_logredo_only) { /* * User only wants to run logredo, no matter what. * Make sure we leave a dirty superblock marked dirty */ if (sb_ptr->s_state & FM_DIRTY) agg_recptr->ag_dirty = 1; agg_recptr->fsck_is_done = 1; exit_value = FSCK_OK; } /* * if things look ok so far, make storage allocated by logredo() * available to fsck processing. */ if (p0_rc == FSCK_OK) { p0_rc = release_logredo_allocs(); } if (p0_rc != FSCK_OK) { agg_recptr->fsck_is_done = 1; exit_value = FSCK_OP_ERROR; } /* * If we're done, make sure s_logdev is up to date in the superblock. * Otherwise, s_logdev will be updated in final_processing. */ if (agg_recptr->fsck_is_done && (Log.location & OUTLINELOG) && Log.devnum) { sb_ptr->s_logdev = Log.devnum; /* * write the superblock to commit the above change */ if (use_2ndary_superblock) { /* put 2ndary */ ujfs_put_superblk(Dev_IOPort, sb_ptr, 0); } else { /* put primary */ ujfs_put_superblk(Dev_IOPort, sb_ptr, 1); } } return (p0_rc); } /***************************************************************************** * NAME: phase1_processing * * FUNCTION: Initialize the fsck workspace. Process the aggregate-owned * inodes. Process fileset special inodes. * * If any aggregate block is now multiply-allocated, then it * is allocated to more than 1 special inode. Exit. * * Process all remaining inodes. Count links from directories * to their child inodes. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int phase1_processing() { int p1_rc = FSCK_OK; fsck_send_msg(fsck_PHASE1); if ((p1_rc = establish_io_buffers()) != FSCK_OK) goto p1_exit; /* I/O buffers established */ /* establish workspace related to the aggregate */ if ((p1_rc = establish_agg_workspace()) != FSCK_OK) goto p1_exit; /* aggregate workspace established */ if ((p1_rc = record_fixed_metadata()) != FSCK_OK) goto p1_exit; /* fixed metadata recorded */ /* * note that this processing will use the vlarge * buffer and then return it for reuse */ if ((p1_rc = validate_select_agg_inode_table()) != FSCK_OK) goto p1_exit; /* we have an ait to work with */ /* establish workspace related to the fileset */ if ((p1_rc = establish_fs_workspace()) != FSCK_OK) goto p1_exit; if ((p1_rc = record_dupchk_inode_extents()) != FSCK_OK) goto p1_exit; /* fs workspace established */ /* claim the vlarge buffer for * validating EAs. We do this now because * it IS possible that the root directory (validated * in the call that follows) has an EA attached. */ establish_ea_iobuf(); if ((p1_rc = allocate_dir_index_buffers()) != FSCK_OK) goto p1_exit; /* verify the metadata * inodes for all filesets in the aggregate */ if ((p1_rc = validate_fs_metadata()) != FSCK_OK) goto p1_exit; /* check for blocks allocated * to 2 or more metadata objects */ if ((p1_rc = fatal_dup_check()) != FSCK_OK) goto p1_exit; /* validate the fileset inodes */ p1_rc = validate_fs_inodes(); /* return the vlarge buffer for reuse */ agg_recptr->ea_buf_ptr = NULL; agg_recptr->ea_buf_length = 0; agg_recptr->vlarge_current_use = NOT_CURRENTLY_USED; p1_exit: if (p1_rc != FSCK_OK) { agg_recptr->fsck_is_done = 1; exit_value = FSCK_OP_ERROR; } return (p1_rc); } /***************************************************************************** * NAME: phase2_processing * * FUNCTION: Scan the inodes. If any inode has more than 1 link from * any single directory then, in Release I of JFS, the * directory must be corrupt. * * Count the link from each directory inode to its parent inode. * Verify that the link count stored in each in-use inode matches * the link count observed by fsck. If not, get (once to cover * all incorrect link counts) permission to correct them. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int phase2_processing() { int p2_rc = FSCK_OK; fsck_send_msg(fsck_PHASE2); p2_rc = check_dir_integrity(); if (p2_rc == FSCK_OK) { p2_rc = check_link_counts(); } if (p2_rc != FSCK_OK) { agg_recptr->fsck_is_done = 1; exit_value = FSCK_OP_ERROR; } return (p2_rc); } /***************************************************************************** * NAME: phase3_processing * * FUNCTION: If any mulitply-allocated blocks have been detected, find * the first reference to each. For each in-use directory inode, * verify that it has exactly 1 parent and that the parent inode * number stored in the inode matches the parent observed by * fsck. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int phase3_processing() { int p3_rc = FSCK_OK; fsck_send_msg(fsck_PHASE3); if (agg_recptr->unresolved_1stref_count > 0) { /* * there are unresolved first references to * multiply-allocated blocks */ /* see if any first * references are by aggregate fixed metadata */ p3_rc = first_ref_check_fixed_metadata(); } if ((p3_rc == FSCK_OK) && (agg_recptr->unresolved_1stref_count > 0)) { /* * there are still unresolved first references * to multiply-allocated blocks */ /* see if any first references are by aggregate metadata inodes */ p3_rc = first_ref_check_agg_metadata(); } if ((p3_rc == FSCK_OK) && (agg_recptr->unresolved_1stref_count > 0)) { /* * there are still unresolved first references * to multiply-allocated blocks */ /* see if any first references are by fileset metadata inodes */ p3_rc = first_ref_check_fs_metadata(); } if ((p3_rc == FSCK_OK) && (agg_recptr->unresolved_1stref_count > 0)) { /* * there are still unresolved first references * to multiply-allocated blocks */ /* see if any first references are by * inode extents (described in the IAGs) */ p3_rc = first_ref_check_inode_extents(); } if (p3_rc == FSCK_OK) { /* nothing fatal yet */ p3_rc = check_parents_and_first_refs(); } if (p3_rc != FSCK_OK) { agg_recptr->fsck_is_done = 1; exit_value = FSCK_OP_ERROR; } return (p3_rc); } /***************************************************************************** * NAME: phase4_processing * * FUNCTION: For each inode record, in fsck's workspace inode map, which * has been flagged for some repair, get permission to perform * the repair and adjust the map for repairs implied by approved * repairs. (E.g., if an inode is approved for release, then * any directory entry for the inode is approved for removal, * by implication.) * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int phase4_processing() { int p4_rc = FSCK_OK; /* * issue this message whether or not there are any corrections to ask * about so that when the next message comes out the user will know * that notifications are completed. */ fsck_send_msg(fsck_PHASE4); if (agg_recptr->corrections_needed || agg_recptr->warning_pending) { /* * Get permission to perform indicated repairs. */ p4_rc = report_problems_setup_repairs(); } if (p4_rc != FSCK_OK) { agg_recptr->fsck_is_done = 1; exit_value = FSCK_OP_ERROR; } return (p4_rc); } /***************************************************************************** * NAME: phase5_processing * * FUNCTION: Detect problems related to inode connectedness. Identify * each unconnected, in-use inode and flag it for reconnection. * Identify each directory inode with multiple parents and get * permission to repair it. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int phase5_processing() { int p5_rc = FSCK_OK; fsck_send_msg(fsck_PHASE5); if (agg_recptr->processing_readwrite) { /* have read/write access */ p5_rc = check_connectedness(); if (p5_rc != FSCK_OK) { agg_recptr->fsck_is_done = 1; exit_value = FSCK_OP_ERROR; } } return (p5_rc); } /***************************************************************************** * NAME: phase6_processing * * FUNCTION: Perform all approved inode corrections. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int phase6_processing() { int p6_rc = FSCK_OK; int intermed_rc; fsck_send_msg(fsck_PHASE6); if (!agg_recptr->processing_readwrite || !agg_recptr->corrections_approved) goto p6_exit; /* * we're about to write repairs. if something stops * after we start and before we finish, we'll leave the * filesystem in an inconsistent state. * Mark the superblock (and write it to the disk) to * show the filesystem is unmountable. If we complete * successfully and all errors are corrected, we'll * be marking it clean later on. */ sb_ptr->s_state |= FM_DIRTY; /* write to the primary superblock on the device. */ ujfs_put_superblk(Dev_IOPort, sb_ptr, 1); /* * log the fact the the superblock * has just been marked dirty */ fsck_send_msg(fsck_REPAIRSINPROGRESS); if (agg_recptr->inode_reconn_extens != NULL) { /* * there are inodes to reconnect */ intermed_rc = resolve_lost_and_found(); if (intermed_rc < 0) { /* something fatal */ p6_rc = intermed_rc; } } if (p6_rc != FSCK_OK) goto p6_setup_exit; /* nothing fatal */ /* Allocate space for * use during directory entry processing. * (used both to add and to delete entries, * so not restricted to reconnect processing) */ p6_rc = directory_buffers_alloc(); if (p6_rc != FSCK_OK) goto p6_setup_exit; /* reconnect buffers initialized */ p6_rc = repair_fs_inodes(); if (p6_rc == FSCK_OK) { if (agg_recptr->dup_alloc_lst != NULL) { /* * there are unresolved duplicate block * allocations */ agg_recptr->ag_dirty = 1; } if (agg_recptr->inode_reconn_extens != NULL) { /* * there's something to reconnect */ /* * Does /lost+found/ need anything before we start? */ if ((agg_recptr->lsfn_ok) && (agg_recptr->avail_inonum == agg_recptr->lsfn_inonum)) { /* * /lost+found/ needs to be created */ intermed_rc = create_lost_and_found(); if (intermed_rc > 0) { /* can't reconnect anything */ agg_recptr->lsfn_ok = 0; } else if(intermed_rc < 0) { p6_rc = intermed_rc; } } if ((p6_rc == FSCK_OK) && (agg_recptr->lsfn_ok)) { p6_rc = reconnect_fs_inodes(); } } } intermed_rc = directory_buffers_release(); p6_setup_exit: if (p6_rc != FSCK_OK) { agg_recptr->fsck_is_done = 1; exit_value = FSCK_ERRORS_UNCORRECTED; } else { exit_value = FSCK_CORRECTED; } p6_exit: return (p6_rc); } /***************************************************************************** * NAME: phase7_processing * * FUNCTION: Rebuild (or verify, processing read-only) the Aggregate Inode * Allocation Map, the Aggregate Inode Allocation Table, the * Fileset Inode Allocation Map, and the Fileset Inode Allocation * Table. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int phase7_processing() { int p7_rc = FSCK_OK; if (agg_recptr->processing_readwrite) { /* have read/write access */ fsck_send_msg(fsck_PHASE7R); p7_rc = rebuild_agg_iamap(); if (p7_rc >= FSCK_OK) { p7_rc = rebuild_fs_iamaps(); if (p7_rc >= FSCK_OK) { /* * note that this processing will use the vlarge * buffer and then return it for reuse */ /* * refresh the redundancy of the * aggregate inode table and map */ p7_rc = AIS_replication(); } } } else { /* else processing read only */ fsck_send_msg(fsck_PHASE7V); p7_rc = verify_agg_iamap(); if (p7_rc >= FSCK_OK) { p7_rc = verify_fs_iamaps(); } } if (p7_rc != FSCK_OK) { agg_recptr->fsck_is_done = 1; exit_value = FSCK_ERRORS_UNCORRECTED; } return (p7_rc); } /***************************************************************************** * NAME: phase8_processing * * FUNCTION: Rebuild (or verify, processing read-only) the Aggregate Block * Allocation Map. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int phase8_processing() { int p8_rc = FSCK_OK; if (agg_recptr->processing_readwrite) { /* have read/write access */ fsck_send_msg(fsck_PHASE8R); p8_rc = rebuild_blkall_map(); } else { /* else processing read only */ fsck_send_msg(fsck_PHASE8V); p8_rc = verify_blkall_map(); } if (p8_rc != FSCK_OK) { agg_recptr->fsck_is_done = 1; exit_value = FSCK_ERRORS_UNCORRECTED; } return (p8_rc); } /***************************************************************************** * NAME: phase9_processing * * FUNCTION: If logredo failed during its processing, reformat the journal * log. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int phase9_processing() { int p9_rc = FSCK_OK; int logformat_called = 0; agg_recptr->logformat_rc = FSCK_OK; if (!agg_recptr->processing_readwrite || ((agg_recptr->logredo_rc >= 0) && !agg_recptr->parm_options_nologredo)) goto p9_set_exit; /* log needs reformat */ fsck_send_msg(fsck_PHASE9); if (sb_ptr->s_flag & JFS_INLINELOG) { /* log is inline */ logformat_called = -1; #ifdef _JFS_DEBUG printf("JFS fsck calling logformat \n"); #endif agg_recptr->logformat_rc = jfs_logform(Dev_IOPort, sb_ptr->s_bsize, sb_ptr->s_l2bsize, sb_ptr->s_flag, addressPXD(&(sb_ptr->s_logpxd)), lengthPXD(&(sb_ptr->s_logpxd)), NULL, NULL); } else if (Log.fp && !uuid_is_null(sb_ptr->s_loguuid)) { /* External log */ logformat_called = -1; #ifdef _JFS_DEBUG printf("JFS fsck calling logformat \n"); #endif agg_recptr->logformat_rc = jfs_logform(Log.fp, Log.bsize, Log.l2bsize, sb_ptr->s_flag, 0, 0, sb_ptr->s_loguuid, NULL); } else /* Extern log was never opened or null s_loguuid */ printf("External log could not be found\n"); if (logformat_called) { #ifdef _JFS_DEBUG printf("JFS fsck back from logformat, rc = %ld \n", agg_recptr->logformat_rc); #endif if (agg_recptr->logformat_rc != FSCK_OK) { /* logredo failed */ fsck_send_msg(fsck_LOGFORMATFAIL, agg_recptr->logformat_rc); } else { fsck_send_msg(fsck_LOGFORMATRC, agg_recptr->logformat_rc); } } p9_set_exit: if (p9_rc != FSCK_OK) { agg_recptr->fsck_is_done = 1; exit_value = FSCK_OP_ERROR; } return (p9_rc); } /***************************************************************************** * NAME: repair_fs_inodes * * FUNCTION: Perform approved repairs on fileset inodes, including the * implied repairs. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int repair_fs_inodes() { int rfsi_rc = FSCK_OK; uint32_t ino_idx; struct fsck_inode_ext_record *this_ext; struct fsck_inode_ext_record *ext_list; struct fsck_inode_record *this_inorec; int aggregate_inode = 0; /* going for fileset inodes only */ int which_it = 16; /* in release 1 there is only fileset 0 */ struct dinode *ino_ptr; struct fsck_ino_msg_info ino_msg_info; struct fsck_ino_msg_info *msg_info_ptr; msg_info_ptr = &ino_msg_info; /* all fileset owned */ msg_info_ptr->msg_inopfx = fsck_fset_inode; rfsi_rc = get_inorecptr_first(aggregate_inode, &ino_idx, &this_inorec); while ((rfsi_rc == FSCK_OK) && (this_inorec != NULL)) { if (!((this_inorec->in_use) && ((this_inorec->selected_to_rls) || (this_inorec->crrct_prnt_inonum) || (this_inorec->adj_entries) || (this_inorec->clr_ea_fld) || (this_inorec->clr_acl_fld) || (this_inorec->inlineea_on) || (this_inorec->inlineea_off) || (this_inorec->rebuild_dirtable) || (this_inorec->reconnect) || (this_inorec->link_count != 0)))) goto rfsi_get_next; /* flagged for repair */ rfsi_rc = inode_get(aggregate_inode, which_it, ino_idx, &ino_ptr); if (rfsi_rc != FSCK_OK) goto rfsi_get_next; msg_info_ptr->msg_inonum = ino_idx; if (this_inorec->inode_type == directory_inode) { msg_info_ptr->msg_inotyp = fsck_directory; } else if (this_inorec->inode_type == symlink_inode) { msg_info_ptr->msg_inotyp = fsck_symbolic_link; } else if (this_inorec->inode_type == char_special_inode) { msg_info_ptr->msg_inotyp = fsck_char_special; } else if (this_inorec->inode_type == block_special_inode) { msg_info_ptr->msg_inotyp = fsck_block_special; } else if (this_inorec->inode_type == FIFO_inode) { msg_info_ptr->msg_inotyp = fsck_FIFO; } else if (this_inorec->inode_type == SOCK_inode) { msg_info_ptr->msg_inotyp = fsck_SOCK; } else { /* a regular, block special, or char special file */ msg_info_ptr->msg_inotyp = fsck_file; } if (this_inorec->selected_to_rls) { /* release the inode */ rfsi_rc = release_inode(ino_idx, this_inorec, ino_ptr); if (rfsi_rc == FSCK_OK) { fsck_send_msg(fsck_INOCLRD, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } goto rfsi_inode_put; } /* not releasing the inode */ if (this_inorec->link_count != 0) { /* * correct/adjust link count */ ino_ptr->di_nlink += this_inorec->link_count; fsck_send_msg(fsck_INOLKCTFXD, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (this_inorec->crrct_prnt_inonum) { /* * correct parent inode number */ ino_ptr->di_parent = this_inorec->parent_inonum; fsck_send_msg(fsck_INCINOREFCRCT, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (this_inorec->reconnect) { /* * reconnect */ if (this_inorec->inode_type == directory_inode) { /* * only directory inodes point back to their parent */ if (agg_recptr->lsfn_ok) { /* /lost+found/ resolved */ ino_ptr->di_parent = agg_recptr->lsfn_inonum; } else { /* couldn't resolve /lost+found/ */ ino_ptr->di_parent = 0; } } /* * N.B. No message is issued at this time since * reconnect processing for the inode is * not completed. When all other inode * corrections have been processed, a directory * entry will be added to /lost+found/ for * each inode needing reconnection. At that * time a message will be issued (assuming * the verbose messaging switch is * set appropriately for that message). */ } if ((rfsi_rc == FSCK_OK) && (this_inorec->clr_ea_fld)) { /* clear EA */ rfsi_rc = clear_EA_field(this_inorec, ino_ptr); if (rfsi_rc == FSCK_OK) { fsck_send_msg(fsck_INOEACLRD, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } if ((rfsi_rc == FSCK_OK) && (this_inorec->clr_acl_fld)) { /* clear ACL */ rfsi_rc = clear_ACL_field(this_inorec, ino_ptr); if (rfsi_rc == FSCK_OK) { fsck_send_msg(fsck_INOACLCLRD, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } } if ((rfsi_rc == FSCK_OK) && (this_inorec->inlineea_on)) { /* sect 4 available flag on */ ino_ptr->di_mode |= INLINEEA; fsck_send_msg(fsck_INOMINORFXD, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if ((rfsi_rc == FSCK_OK) && (this_inorec->inlineea_off)) { /* sect 4 available flag off */ ino_ptr->di_mode &= ~INLINEEA; fsck_send_msg(fsck_INOMINORFXD, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if ((rfsi_rc == FSCK_OK) && (this_inorec->rebuild_dirtable)) { rfsi_rc = rebuild_dir_index(ino_ptr, this_inorec); if (rfsi_rc == FSCK_OK) fsck_send_msg(fsck_DI_TABLE_FXD, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum); } if (!((rfsi_rc == FSCK_OK) && (this_inorec->adj_entries))) goto rfsi_inode_put; /* adjust dir entries */ ext_list = this_inorec->ext_rec; this_inorec->ext_rec = NULL; while ((ext_list != NULL) && (rfsi_rc == FSCK_OK)) { this_ext = ext_list; ext_list = ext_list->next; if ((this_ext->ext_type == rmv_badentry_extension) || (this_ext->ext_type == rmv_direntry_extension)) { /* * n.b. that the link count adjustment * has already been handled. */ rfsi_rc = direntry_remove(ino_ptr, this_ext->inonum); if (rfsi_rc == FSCK_OK) { fsck_send_msg(fsck_INOREFRMV, fsck_ref_msg(msg_info_ptr->msg_inopfx), msg_info_ptr->msg_inonum, fsck_ref_msg(msg_info_ptr->msg_inopfx), this_ext->inonum); release_inode_extension(this_ext); } } else { this_ext->next = this_inorec->ext_rec; this_inorec->ext_rec = this_ext; } } rfsi_inode_put: if (rfsi_rc == FSCK_OK) { /* write it back to the device */ rfsi_rc = inode_put(ino_ptr); } rfsi_get_next: if (rfsi_rc == FSCK_OK) { rfsi_rc = get_inorecptr_next(aggregate_inode, &ino_idx, &this_inorec); } } return (rfsi_rc); } /***************************************************************************** * NAME: report_dynstg_error * * FUNCTION: Report a failure to allocate dynamic storage. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK */ void report_dynstg_error() { fsck_send_msg(fsck_EXHDYNSTG, wsp_dynstg_action, wsp_dynstg_object); return; } /***************************************************************************** * NAME: report_readait_error * * FUNCTION: Report failure to read the Aggregate Inode Table * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ void report_readait_error(int local_rc, int global_rc, int which_it) { /* * message to user */ fsck_send_msg(fsck_URCVREAD, fsck_ref_msg(fsck_metadata), Vol_Label); /* * message to debugger */ fsck_send_msg(fsck_ERRONAITRD, global_rc, local_rc, which_it); return; } /***************************************************************************** * NAME: resolve_lost_and_found * * FUNCTION: Determine whether /lost+found/ already exists and, if so, * whether it is a valid directory inode. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int resolve_lost_and_found() { int rlaf_rc = FSCK_OK; int intermed_rc = FSCK_OK; uint32_t found_inonum = 0; int found_inoidx; int lsfn_length_in_UniChars; int LSFN_length_in_UniChars; int aggregate_inode = 0; /* going for fileset inodes only */ int alloc_ifnull = 0; struct fsck_inode_record *inorecptr; /* * see if one exists now */ lsfn_length_in_UniChars = UniStrlen(agg_recptr->UniChar_lsfn_name); LSFN_length_in_UniChars = UniStrlen(agg_recptr->UniChar_LSFN_NAME); intermed_rc = direntry_get_inonum(ROOT_I, lsfn_length_in_UniChars, agg_recptr->UniChar_lsfn_name, LSFN_length_in_UniChars, agg_recptr->UniChar_LSFN_NAME, &found_inonum); if (intermed_rc < 0) { rlaf_rc = intermed_rc; } else if (found_inonum == 0) { /* there isn't one yet */ fsck_send_msg(fsck_LSFNNOTFOUND); if (agg_recptr->avail_inonum == 0) { /* and we didn't see any * available inodes laying around */ /* don't have one */ agg_recptr->lsfn_inonum = 0; /* we won't reconnect anything */ agg_recptr->lsfn_ok = 0; fsck_send_msg(fsck_LSFNCNTCRE); } else { /* an available inode was seen */ agg_recptr->lsfn_inonum = agg_recptr->avail_inonum; agg_recptr->lsfn_ok = 1; /* we'll be able to create l+f */ } } else { /* we found an entry for an object named lost+found */ found_inoidx = (uint32_t) found_inonum; agg_recptr->lsfn_inonum = found_inoidx; rlaf_rc = get_inorecptr(aggregate_inode, alloc_ifnull, found_inoidx, &inorecptr); if ((rlaf_rc == FSCK_OK) && (inorecptr == NULL)) { /* * a parent but no record allocated */ rlaf_rc = FSCK_INTERNAL_ERROR_5; } else if (rlaf_rc == FSCK_OK) { /* a record is allocated */ if (!inorecptr->in_use) { /* * Inode not in use. * This is another presentation of the * no inode allocated yet case */ agg_recptr->avail_inonum = agg_recptr->lsfn_inonum; agg_recptr->lsfn_ok = 1; fsck_send_msg(fsck_LSFNNOTFOUND); } else { /* inode is in use */ if (inorecptr->selected_to_rls) { /* * we've released it. * This is another presentation of the * no inode allocated yet case */ agg_recptr->avail_inonum = agg_recptr->lsfn_inonum; agg_recptr->lsfn_ok = 1; fsck_send_msg(fsck_LSFNNOTFOUND); } else if (inorecptr->ignore_alloc_blks) { /* * but we must have tried to release it and * been turned down because we discovered * that its data is corrupt. */ /* don't have one */ agg_recptr->lsfn_inonum = 0; /* and don't have hope */ agg_recptr->lsfn_ok = 0; /* * no message here because we already told them that * /lost+found/ is screwed up and they wouldn't let * us fix it. */ } else if (inorecptr->inode_type != directory_inode) { /* * but it must be user data (or corrupt * in some subtle way) because it's not * a directory */ /* don't have one */ agg_recptr->lsfn_inonum = 0; /* and don't have hope */ agg_recptr->lsfn_ok = 0; fsck_send_msg(fsck_LSFNNOTDIR); } else if ((inorecptr->involved_in_dups) && (agg_recptr->dup_alloc_lst != NULL)) { /* * This inode lays claim to one or more blocks * found to be multiply-allocated. There are * now multiply-allocated blocks which we * were not allowed to correct. It isn't * certain that this inode refers to any * block(s) STILL unresolved, but it might. * Since this filesystem is going to be marked * dirty anyway, don't attempt to reconnect * disconnected inodes. * (N.B. The danger in proceeding is to data * integrity.) */ /* don't have one */ agg_recptr->lsfn_inonum = 0; /* and don't have hope */ agg_recptr->lsfn_ok = 0; /* * no message here because the reasoning is too * conservative to explain easily. They'll be informed * about inodes not reconnected (which isn't the end of * the world anyway). */ } else { /* looks like we're in business here */ agg_recptr->avail_inonum = 0; agg_recptr->lsfn_ok = 1; } } } } return (rlaf_rc); } /***************************************************************************** * NAME: validate_fs_inodes * * FUNCTION: Verify the fileset inodes and structures rooted in them. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int validate_fs_inodes() { int vfi_rc = FSCK_OK; uint32_t ino_idx; struct dinode *ino_ptr; int which_it = FILESYSTEM_I; /* in release 1 there is only 1 fileset */ struct fsck_ino_msg_info ino_msg_info; struct fsck_ino_msg_info *msg_info_ptr; msg_info_ptr = &ino_msg_info; /* all fileset owned */ msg_info_ptr->msg_inopfx = fsck_fset_inode; /* * get the first non-metadata inode after * the fileset root directory */ vfi_rc = inode_get_first_fs(which_it, &ino_idx, &ino_ptr); while ((vfi_rc == FSCK_OK) && (ino_ptr != NULL)) { /* no fatal errors and haven't seen the last inode */ if (inode_is_in_use(ino_ptr, (uint32_t) ino_idx)) { /* inode is in use */ vfi_rc = validate_record_fileset_inode((uint32_t) ino_idx, ino_idx, ino_ptr, msg_info_ptr); } else { /* inode is allocated but is not in use */ if (!agg_recptr->avail_inode_found) { /* * this is the first allocated, available * inode we've seen all day */ agg_recptr->avail_inonum = (uint32_t) ino_idx; agg_recptr->avail_inode_found = 1; } } if (vfi_rc == FSCK_OK) { vfi_rc = inode_get_next(&ino_idx, &ino_ptr); } } return (vfi_rc); } /***************************************************************************** * NAME: verify_parms * * FUNCTION: Verify that mutually exclusive invocation parameters were not * specified. Determine the level of messaging to be used for * this fsck session. * * PARAMETERS: none * * RETURNS: * success: FSCK_OK * failure: something else */ int verify_parms() { /* * If -f was chosen, have it override -a, -p, -r by * turning off UFS_CHKDSK_IFDIRTY to force a check * regardless of the outcome after the log is replayed */ if (agg_recptr->parm_options[UFS_CHKDSK_LEVEL3]) { agg_recptr->parm_options[UFS_CHKDSK_LEVEL2] = -1; agg_recptr->parm_options[UFS_CHKDSK_LEVEL3] = 0; agg_recptr->parm_options[UFS_CHKDSK_IFDIRTY] = 0; } /* * If the -n flag was specified, turn off -p */ if (agg_recptr->parm_options[UFS_CHKDSK_LEVEL0]) { /* * If -n is specified by itself, don't replay the journal. * If -n is specified with -a, -p, or -f, replay the journal * but don't make any other changes */ if (agg_recptr->parm_options[UFS_CHKDSK_LEVEL2] == 0) agg_recptr->parm_options[UFS_CHKDSK_SKIPLOGREDO] = -1; agg_recptr->parm_options[UFS_CHKDSK_LEVEL2] = -1; } else if (agg_recptr->parm_options[UFS_CHKDSK_LEVEL2]) { agg_recptr->parm_options[UFS_CHKDSK_LEVEL1] = 0; agg_recptr->parm_options[UFS_CHKDSK_LEVEL2] = 0; agg_recptr->parm_options[UFS_CHKDSK_LEVEL3] = -1; /* * we'll be doing the Bad Block List function as part * of the -f processing. Turn off the flag that specifies * it. This flag is only used when we're in read-only mode. */ agg_recptr->parm_options[UFS_CHKDSK_CLRBDBLKLST] = 0; } else { /* * Set default value if none was specified. * set the default to same as -p */ agg_recptr->parm_options[UFS_CHKDSK_LEVEL2] = -1; agg_recptr->parm_options[UFS_CHKDSK_IFDIRTY] = -1; fsck_send_msg(fsck_SESSPRMDFLT); } /* * the parms are valid. record the messaging level they imply. */ if ((agg_recptr->parm_options[UFS_CHKDSK_VERBOSE]) || (agg_recptr->parm_options[UFS_CHKDSK_DEBUG])) { agg_recptr->effective_msg_level = fsck_debug; msg_lvl = fsck_debug; } else { agg_recptr->effective_msg_level = fsck_quiet; msg_lvl = fsck_quiet; } return (FSCK_OK); } void ask_continue() { int cont = 0; int c; printf("Do you really want to continue (y/n)? "); while (1) { fflush(stdout); if ((c = getchar()) == EOF) break; c = toupper(c); if (c == 'Y') { cont = 1; break; } else if (c == 'N') break; } if (cont) { printf("yes\n\n"); agg_recptr->aggregate_is_mounted = 1; } else { printf("no\n\nCheck aborted.\n"); exit(exit_value); } return; } void fsck_usage() { printf("\nUsage: %s [-afnpvV] [-j journal_device] [--omit_journal_replay] " "[--replay_journal_only] device\n", program_name); printf("\nEmergency help:\n" " -a Automatic repair.\n" " -f Force check even if file system is marked clean.\n" " -j journal_device Specify external journal device.\n" " -n Check read only, make no changes to the file system.\n" " -p Automatic repair.\n" " -v Be verbose.\n" " -V Print version information only.\n" " --omit_journal_replay Omit transaction log replay.\n" " --replay_journal_only Only replay the transaction log.\n"); exit(FSCK_USAGE_ERROR); } jfsutils-1.1.15.orig/fsck/xchkdsk.h0000644000000000000000000000223210340701412014014 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef H_PUFS_CHKDSK #define H_PUFS_CHKDSK enum xchkdsk_options { UFS_CHKDSK_LEVEL0, UFS_CHKDSK_LEVEL1, UFS_CHKDSK_LEVEL2, UFS_CHKDSK_LEVEL3, UFS_CHKDSK_IFDIRTY, UFS_CHKDSK_VERBOSE, UFS_CHKDSK_DEBUG, UFS_CHKDSK_CLRBDBLKLST, UFS_CHKDSK_SKIPLOGREDO, UFS_CHKDSK_BLOCK_NUMBER, UFS_CHKDSK_INODE_NUMBER, UFS_CHKDSK_FILENAME, UFS_CHKDSK_OPTIONS }; #endif jfsutils-1.1.15.orig/fsck/xfsck.h0000644000000000000000000004651510340701412013507 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef H_XFSCK #define H_XFSCK #include "jfs_types.h" #include "jfs_dmap.h" /* Stuff for handling extended attributes. */ #ifndef OS2 struct FEA { /* fea */ uint8_t fEA; /* flags */ uint8_t cbName; /* name length not including NULL */ uint16_t cbValue; /* value length */ }; /* flags for FEA.fEA */ #define FEA_NEEDEA 0x80 /* need EA bit */ struct FEALIST { /* feal */ uint32_t cbList; /* total bytes of structure including full list */ struct FEA list[1]; /* variable length FEA structures */ }; #define ERROR_EA_LIST_INCONSISTENT 255 #endif extern int jfs_ValidateFEAList(struct FEALIST *, int, unsigned long *); /* ***** IMPORTANT ***** IMPORTANT ***** IMPORTANT ***** IMPORTANT ***** * * fsck_first_msgid * MUST be set to the first message id for fsck, according * to jfs.txt. Will be used to locate the text for any * message which is displayed in the local language. * * fsck_highest_msgid_defined * MUST be maintained in synch with the * message id constants (defined in fsckmsgc.h) since the * message text array and the message attributes array (declared * in fsckmsgp.h) are both dimensioned using it. * * ***** IMPORTANT ***** IMPORTANT ***** IMPORTANT ***** IMPORTANT ***** */ #define fsck_msgid_offset 50 #define fsck_highest_msgid_defined 599 #define MAXPARMLEN 64 #define fscklog_var_text 1 #define fscklog_literal 2 /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * The following are used to access the columns of * MsgProtocol[][], which is defined in fsckmsgp.h * */ #define MP_MSGLVL 0 #define MP_MSGFILE 1 /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * The following are the possible values effective fsck * messaging level and for implied response level. * */ /* * special cases (must not match any other constants in the table) */ #define fsck_hrtbt 130 #define fsck_txtins 131 /* * The lowest messaging level (dictated by input parms) at which * the message is displayed. */ #define fsck_quiet 2 #define fsck_verbose 8 #define fsck_debug 32 /* * The message file to use for local language lookup * * These are determined by the array message_file_name[] * in messages.c */ #define no_msgfile -1 #define jfs_msgfile 1 /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * The following are used for reporting storage allocation * failures. */ void report_dynstg_error(void); #define dynstg_unknown 0 /* the actions */ #define dynstg_allocation 1 #define dynstg_initialization 2 /* the objects */ #define dynstg_unknown_object 0 #define dynstg_blkmap 1 #define dynstg_blkmap_buf 2 #define dynstg_blkmap_hdr 3 #define dynstg_inomap 4 #define dynstg_fer 5 #define dynstg_wspext 6 #define dynstg_pathbuffer 7 #define dynstg_inoextrec 8 #define dynstg_inorec 9 #define dynstg_dtreeQ_elem 10 #define dynstg_treeQ_elem 11 #define dynstg_ait_map 12 #define dynstg_fsit_map 13 #define dynstg_dupall_blkrec 14 #define dynstg_dupall_inorec 15 #define dynstg_agg_agtbl 16 #define dynstg_agg_iagtbl 17 #define dynstg_fs_agtbl 18 #define dynstg_fs_iagtbl 19 #define dynstg_iobufs 20 #define dynstg_eaiobuf 21 #define dynstg_tmpinoiobuf 22 #define dynstg_recondnodebuf 23 #define dynstg_xtreebuf 24 #define dynstg_xtreepagebuf 25 #define dynstg_treeStack_elem 26 #define dynstg_fsckcbblbuf1 27 #define dynstg_fsckcbblbuf2 28 #define dynstg_inotbl 29 #define dynstg_inoexttbl 30 #define dynstg_fsit_iagtbl 31 #define dynstg_fsit_inoexttbl 32 #define dynstg_fsit_inotbl 33 #define dynstg_ait_inotbl 34 /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * used during blockmap verify/rebuild * */ struct fsck_bmap_record { char eyecatcher[8]; int64_t total_blocks; int64_t free_blocks; int8_t ctl_fctl_error; int8_t ctl_other_error; char rsvd0[2]; char bmpctlinf_eyecatcher[8]; struct dbmap *bmpctl_bufptr; int64_t bmpctl_agg_fsblk_offset; char rsvd1[4]; char AGinf_eyecatcher[8]; int64_t *AGFree_tbl; int8_t AGActive[MAXAG]; char dmapinf_eyecatcher[8]; uint32_t dmappg_count; uint32_t dmappg_ordno; uint32_t dmappg_idx; int8_t *dmap_wsp_stree; int8_t *dmap_wsp_sleafs; struct dmap *dmap_bufptr; int64_t dmap_agg_offset; int64_t dmap_1stblk; int8_t dmap_pmap_error; int8_t dmap_slfv_error; int8_t dmap_slnv_error; int8_t dmap_other_error; char rsvd2[4]; char L0inf_eyecatcher[8]; uint32_t L0pg_count; uint32_t L0pg_ordno; uint32_t L0pg_idx; int8_t *L0_wsp_stree; int8_t *L0_wsp_sleafs; struct dmapctl *L0_bufptr; int64_t L0pg_agg_offset; int64_t L0pg_1stblk; int8_t L0_rsvd; int8_t L0pg_slfv_error; int8_t L0pg_slnv_error; int8_t L0pg_other_error; char rsvd3[4]; char L1inf_eyecatcher[8]; uint32_t L1pg_count; uint32_t L1pg_ordno; uint32_t L1pg_idx; int8_t *L1_wsp_stree; int8_t *L1_wsp_sleafs; struct dmapctl *L1_bufptr; int64_t L1pg_agg_offset; int64_t L1pg_1stblk; int8_t L1_rsvd; int8_t L1pg_slfv_error; int8_t L1pg_slnv_error; int8_t L1pg_other_error; char rsvd4[4]; char L2inf_eyecatcher[8]; uint32_t L2pg_count; int8_t *L2_wsp_stree; int8_t *L2_wsp_sleafs; struct dmapctl *L2_bufptr; int64_t L2pg_agg_offset; int64_t L2pg_1stblk; int8_t L2pg_slfv_error; int8_t L2pg_slnv_error; int8_t L2pg_other_error; char rsvd5[5]; }; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * unicharacter name structure */ struct uniname { uint32_t len_in_UniChars; UniChar name_in_UniChars[256]; }; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * used to pass message inserts from one routine to another economically */ struct fsck_ino_msg_info { uint32_t msg_inonum; int msg_inopfx; int msg_inotyp; int msg_dxdtyp; }; struct fsck_imap_msg_info { int32_t msg_iagnum; int32_t msg_agnum; int msg_mapowner; }; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * used to specify what action should be performed by routing * process_extent */ #define FSCK_RECORD 1 #define FSCK_RECORD_DUPCHECK 2 #define FSCK_UNRECORD 3 #define FSCK_QUERY 4 #define FSCK_GET_OBJNAME 5 #define FSCK_FSIM_RECORD_DUPCHECK 6 #define FSCK_FSIM_UNRECORD 7 #define FSCK_FSIM_QUERY 8 /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * The following are the values which may be displayed in * message fsck_INOINLINECONFLICT * */ #define fsck_longdata_and_otherinline 1 /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * The following define exit codes passed back by fsck.jfs * and return codes passed internally in fsck.jfs. * */ /* exit codes */ #define FSCK_OK 0 #define FSCK_CORRECTED 1 #define FSCK_REBOOT 2 #define FSCK_ERRORS_UNCORRECTED 4 #define FSCK_OP_ERROR 8 #define FSCK_USAGE_ERROR 16 /* informational return codes */ #define FSCK_FAILED -00001 #define FSCK_AGFS_INOBAD 10001 #define FSCK_AGGAITINOBAD 10002 #define FSCK_AGGFSINOBAD 10003 #define FSCK_BADAGFSSIZ 10004 #define FSCK_BADBLKCTTTL 10005 #define FSCK_BADEADESCRIPTOR 10006 #define FSCK_BADMDDATA 10007 #define FSCK_BADMDDATAEXT 10008 #define FSCK_BADMDDATAIDX 10009 #define FSCK_BADMDDATAINLN 10010 #define FSCK_BADREAD_FBLKMP 10011 #define FSCK_BADREAD_FSCKLOG 10012 #define FSCK_BADSBAGSIZ 10013 #define FSCK_BADSBFJLA 10014 #define FSCK_BADSBFJLL 10015 #define FSCK_BADSBFSSIZ 10016 #define FSCK_BADSBFWSA 10017 #define FSCK_BADSBFWSL 10018 #define FSCK_BADSBFWSL1 10019 #define FSCK_BADSBMGC 10020 #define FSCK_BADSBVRSN 10021 #define FSCK_BADSBOTHR1 10022 #define FSCK_BADSBOTHR2 10023 #define FSCK_BADSBOTHR3 10024 #define FSCK_BADSBOTHR4 10025 #define FSCK_BADSBOTHR5 10026 #define FSCK_BADSBOTHR6 10027 #define FSCK_BADSBOTHR7 10028 #define FSCK_BADSBOTHR8 10029 #define FSCK_BADSBOTHR9 10030 #define FSCK_BADSBOTHR10 10031 #define FSCK_BADSBOTHR11 10032 #define FSCK_BADSBOTHR12 10033 #define FSCK_BADSBOTHR13 10034 #define FSCK_BADWRITE_FSCKLOG 10035 #define FSCK_BADWRITE_FBLKMP 10036 #define FSCK_BBINOBAD 10037 #define FSCK_BLSIZLTLVBLSIZ 10038 #define FSCK_BMINOBAD 10039 #define FSCK_CANT_ALLOC_INOREC 10040 #define FSCK_CANT_ALLOC_LSFN 10041 #define FSCK_CANT_EXTEND_ROOTDIR 10042 #define FSCK_CANTREADEAITEXT1 10043 #define FSCK_CANTREADAITEXT1 10044 #define FSCK_CANTREADAITEXT2 10045 #define FSCK_CANTREADAITEXT3 10046 #define FSCK_CANTREADAITEXT4 10047 #define FSCK_CANTREADAGGFSINO 10048 #define FSCK_CANTREADBBINO 10049 #define FSCK_CANTREADBMINO 10050 #define FSCK_CANTREADEA 10051 #define FSCK_CANTREADFSEXT 10052 #define FSCK_CANTREADFSRTDR 10053 #define FSCK_CANTREADLOGINO 10054 #define FSCK_CANTREADRECONDNODE 10055 #define FSCK_CANTREADRECONDNODE1 10056 #define FSCK_CANTREADSELFINO 10057 #define FSCK_CANTWRITRECONDNODE 10058 #define FSCK_CANTWRITRECONDNODE1 10059 #define FSCK_DUPMDBLKREF 10060 #define FSCK_FSETEXTBAD 10061 #define FSCK_FSRTDRBAD 10062 #define FSCK_IAGNOOOAGGBOUNDS 10063 #define FSCK_IAGNOOOFSETBOUNDS 10064 #define FSCK_INOEXTNOTALLOC 10065 #define FSCK_INOINLINECONFLICT1 10066 #define FSCK_INOINLINECONFLICT2 10067 #define FSCK_INOINLINECONFLICT3 10068 #define FSCK_INOINLINECONFLICT4 10069 #define FSCK_INOINLINECONFLICT5 10070 #define FSCK_LOGINOBAD 10071 #define FSCK_RIBADTREE 10072 #define FSCK_RIDATAERROR 10073 #define FSCK_RINOTDIR 10074 #define FSCK_RIUNALLOC 10075 #define FSCK_SELFINOBAD 10076 #define FSCK_INSUFDSTG4RECON 10077 #define FSCK_INSUFDSTG4RECON1 10078 #define FSCK_BLKSNOTAVAILABLE 10079 #define FSCK_BADREADTARGET 10080 #define FSCK_BADREADTARGET1 10081 #define FSCK_BADREADTARGET2 10082 #define FSCK_ENOMEMBDBLK1 10083 #define FSCK_ENOMEMBDBLK2 10084 #define FSCK_ENOMEMBDBLK3 10085 #define FSCK_ENOMEMBDBLK4 10086 #define FSCK_PARENTNULLIFIED 10087 #define FSCK_IOTARGETINJRNLLOG 10088 /* fatal condition return codes */ #define FSCK_FAILED_SEEK -10001 #define FSCK_FAILED_BADSEEK -10002 #define FSCK_FAILED_NODE_BADFLUSH -10003 #define FSCK_FAILED_NODE_FLUSH -10004 #define FSCK_FAILED_BADREAD_NODE -10005 #define FSCK_FAILED_BADREAD_NODE1 -10006 #define FSCK_FAILED_READ_NODE -10007 #define FSCK_FAILED_READ_NODE2 -10008 #define FSCK_FAILED_READ_NODE3 -10009 #define FSCK_FAILED_READ_NODE4 -10010 #define FSCK_FAILED_BADREAD_DNODE -10011 #define FSCK_FAILED_READ_DNODE -10012 #define FSCK_FAILED_INODE_BADFLUSH -10013 #define FSCK_FAILED_INODE_FLUSH -10014 #define FSCK_FAILED_BADREAD_INODE -10015 #define FSCK_FAILED_BADREAD_INODE1 -10016 #define FSCK_FAILED_READ_INODE -10017 #define FSCK_FAILED_IAG_BADFLUSH -10018 #define FSCK_FAILED_IAG_FLUSH -10019 #define FSCK_FAILED_BADREAD_IAG -10020 #define FSCK_FAILED_BADREAD1_IAG -10021 #define FSCK_FAILED_READ_IAG -10022 #define FSCK_FAILED_IAG_CORRUPT_PXD -10023 #define FSCK_FAILED_FBMAP_FLUSH -10024 #define FSCK_FAILED_FBMAP_BADFLUSH -10025 #define FSCK_FAILED_BADREAD_FBLKMP -10026 #define FSCK_FAILED_READ_FBLKMP -10027 #define FSCK_FAILED_WRITE_FBLKMP -10028 #define FSCK_FAILED_BADWRITE_FBLKMP -10029 #define FSCK_FAILED_PSBLK_WRITE -10030 #define FSCK_FAILED_SSBLK_WRITE -10031 #define FSCK_FAILED_BTHSBLK_WRITE -10032 #define FSCK_FAILED_BTHSBLK_BAD -10033 #define FSCK_FAILED_FSSIEXT_READ2 -10034 #define FSCK_FAILED_FSRTDIR_READ2 -10035 #define FSCK_FAILED_BADBLK_READ2 -10036 #define FSCK_FAILED_BMAP_READ2 -10037 #define FSCK_FAILED_LOG_READ2 -10038 #define FSCK_FAILED_SELF_READ2 -10039 #define FSCK_FAILED_SELF_READ3 -10040 #define FSCK_FAILED_SELF_READ4 -10041 #define FSCK_FAILED_SELF_READ5 -10042 #define FSCK_FAILED_SELF_NOWBAD -10043 #define FSCK_FAILED_AGFS_READ2 -10044 #define FSCK_FAILED_AGFS_READ3 -10045 #define FSCK_FAILED_AGFS_READ4 -10046 #define FSCK_FAILED_AGFS_READ5 -10047 #define FSCK_FAILED_AGFS_NOWBAD -10048 #define FSCK_FAILED_BOTHAITBAD -10049 #define FSCK_FAILED_CANTREADAITEXT1 -10050 #define FSCK_FAILED_CANTREADAITEXT2 -10051 #define FSCK_FAILED_CANTREADAITEXT3 -10052 #define FSCK_FAILED_CANTREADAITEXT4 -10053 #define FSCK_FAILED_CANTREADAITEXT5 -10054 #define FSCK_FAILED_CANTREADAITEXT6 -10055 #define FSCK_FAILED_CANTREADAITEXT7 -10056 #define FSCK_FAILED_CANTREADAITEXT8 -10057 #define FSCK_FAILED_CANTREADAITEXT9 -10058 #define FSCK_FAILED_CANTREADAITEXTA -10059 #define FSCK_FAILED_CANTREADAITEXTB -10060 #define FSCK_FAILED_CANTREADAITEXTC -10061 #define FSCK_FAILED_CANTREADAITEXTD -10062 #define FSCK_FAILED_CANTREADAITEXTE -10063 #define FSCK_FAILED_CANTREADAITEXTF -10064 #define FSCK_FAILED_CANTREADAITEXTG -10065 #define FSCK_FAILED_CANTREADAITEXTH -10066 #define FSCK_FAILED_CANTREADAITEXTJ -10067 #define FSCK_FAILED_CANTREADAITEXTK -10068 #define FSCK_FAILED_CANTREADAITCTL -10069 #define FSCK_FAILED_CANTREADAITS -10070 #define FSCK_FAILED_CANTREADAIMNOW -10071 #define FSCK_FAILED_IMPLF_BADFLUSH -10072 #define FSCK_FAILED_IMPLF_FLUSH -10073 #define FSCK_FAILED_BADREAD_IMPLF -10074 #define FSCK_FAILED_READ_IMPLF -10075 #define FSCK_FAILED_CANTREAD_DIRNOW -10076 #define FSCK_FAILED_DIRGONEBAD -10077 #define FSCK_FAILED_DIRGONEBAD2 -10078 #define FSCK_FAILED_DIRENTRYGONE -10079 #define FSCK_FAILED_DIRENTRYBAD -10080 #define FSCK_FAILED_MAPCTL_BADFLUSH -10081 #define FSCK_FAILED_MAPCTL_FLUSH -10082 #define FSCK_FAILED_BADREAD_MAPCTL -10083 #define FSCK_FAILED_READ_MAPCTL -10084 #define FSCK_FAILED_CANTREADBMPCTL -10085 #define FSCK_FAILED_BMPLV_BADFLUSH -10086 #define FSCK_FAILED_BMPLV_FLUSH -10087 #define FSCK_FAILED_BADREAD_BMPLV -10088 #define FSCK_FAILED_READ_BMPLV -10089 #define FSCK_FAILED_BMPDM_BADFLUSH -10090 #define FSCK_FAILED_BMPDM_FLUSH -10091 #define FSCK_FAILED_BADREAD_BMPDM -10092 #define FSCK_FAILED_READ_BMPDM -10093 #define FSCK_FAILED_DYNSTG_EXHAUST1 -10094 #define FSCK_FAILED_DYNSTG_EXHAUST2 -10095 #define FSCK_FAILED_DYNSTG_EXHAUST3 -10096 #define FSCK_FAILED_DYNSTG_EXHAUST4 -10097 #define FSCK_FAILED_DYNSTG_EXHAUST5 -10098 #define FSCK_FAILED_DYNSTG_EXHAUST6 -10099 #define FSCK_FAILED_DYNSTG_EXHAUST7 -10100 #define FSCK_FAILED_DYNSTG_EXHAUST8 -10101 #define FSCK_FAILED_DYNSTG_EXHAUST9 -10102 #define FSCK_FAILED_DYNSTG_EXHAUSTA -10103 #define FSCK_FAILED_REREAD_AGGINO -10104 /* catastrophic error return codes */ #define FSCK_INTERNAL_ERROR_1 -11001 #define FSCK_INTERNAL_ERROR_2 -11002 #define FSCK_INTERNAL_ERROR_3 -11003 #define FSCK_INTERNAL_ERROR_4 -11004 #define FSCK_INTERNAL_ERROR_5 -11005 #define FSCK_INTERNAL_ERROR_6 -11006 #define FSCK_INTERNAL_ERROR_7 -11007 #define FSCK_INTERNAL_ERROR_8 -11008 #define FSCK_INTERNAL_ERROR_9 -11009 #define FSCK_INTERNAL_ERROR_10 -11010 #define FSCK_INTERNAL_ERROR_11 -11011 #define FSCK_INTERNAL_ERROR_12 -11012 #define FSCK_INTERNAL_ERROR_13 -11013 #define FSCK_INTERNAL_ERROR_14 -11014 #define FSCK_INTERNAL_ERROR_15 -11015 #define FSCK_INTERNAL_ERROR_16 -11016 #define FSCK_INTERNAL_ERROR_17 -11017 #define FSCK_INTERNAL_ERROR_18 -11018 #define FSCK_INTERNAL_ERROR_19 -11019 #define FSCK_INTERNAL_ERROR_20 -11020 #define FSCK_INTERNAL_ERROR_21 -11021 #define FSCK_INTERNAL_ERROR_22 -11022 #define FSCK_INTERNAL_ERROR_23 -11023 #define FSCK_INTERNAL_ERROR_24 -11024 #define FSCK_INTERNAL_ERROR_25 -11025 #define FSCK_INTERNAL_ERROR_26 -11026 #define FSCK_INTERNAL_ERROR_27 -11027 #define FSCK_INTERNAL_ERROR_28 -11028 #define FSCK_INTERNAL_ERROR_29 -11029 #define FSCK_INTERNAL_ERROR_30 -11030 #define FSCK_INTERNAL_ERROR_31 -11031 #define FSCK_INTERNAL_ERROR_32 -11032 #define FSCK_INTERNAL_ERROR_33 -11033 #define FSCK_INTERNAL_ERROR_34 -11034 #define FSCK_INTERNAL_ERROR_35 -11035 #define FSCK_INTERNAL_ERROR_36 -11036 #define FSCK_INTERNAL_ERROR_37 -11037 #define FSCK_INTERNAL_ERROR_38 -11038 #define FSCK_INTERNAL_ERROR_39 -11039 #define FSCK_INTERNAL_ERROR_40 -11040 #define FSCK_INTERNAL_ERROR_41 -11041 #define FSCK_INTERNAL_ERROR_42 -11042 #define FSCK_INTERNAL_ERROR_43 -11043 #define FSCK_INTERNAL_ERROR_44 -11044 #define FSCK_INTERNAL_ERROR_45 -11045 #define FSCK_INTERNAL_ERROR_46 -11046 #define FSCK_INTERNAL_ERROR_47 -11047 #define FSCK_INTERNAL_ERROR_48 -11048 #define FSCK_INTERNAL_ERROR_49 -11049 #define FSCK_INTERNAL_ERROR_50 -11050 #define FSCK_INTERNAL_ERROR_51 -11051 #define FSCK_INTERNAL_ERROR_52 -11052 #define FSCK_INTERNAL_ERROR_53 -11053 #define FSCK_INTERNAL_ERROR_54 -11054 #define FSCK_INTERNAL_ERROR_55 -11055 #define FSCK_INTERNAL_ERROR_56 -11056 #define FSCK_INTERNAL_ERROR_57 -11057 #define FSCK_INTERNAL_ERROR_58 -11058 #define FSCK_INTERNAL_ERROR_59 -11059 #define FSCK_INTERNAL_ERROR_60 -11060 #define FSCK_INTERNAL_ERROR_61 -11061 #define FSCK_INTERNAL_ERROR_62 -11062 #define FSCK_INTERNAL_ERROR_63 -11063 #define FSCK_INTERNAL_ERROR_64 -11064 #define FSCK_INTERNAL_ERROR_65 -11065 #define FSCK_INTERNAL_ERROR_66 -11066 #define FSCK_INTERNAL_ERROR_67 -11067 #define FSCK_INTERNAL_ERROR_68 -11068 #define FSCK_INTERNAL_ERROR_69 -11069 #define FSCK_INTERNAL_ERROR_70 -11070 #define FSCK_INTERNAL_ERROR_71 -11071 #define FSCK_INTERNAL_ERROR_72 -11072 #define FSCK_INTERNAL_ERROR_73 -11073 #define FSCK_INTERNAL_ERROR_74 -11074 #define FSCK_INTERNAL_ERROR_75 -11075 #define FSCK_INTERNAL_ERROR_76 -11076 #define FSCK_INTERNAL_ERROR_77 -11077 #define FSCK_INTERNAL_ERROR_78 -11078 #define FSCK_INTERNAL_ERROR_79 -11079 #define FSCK_INTERNAL_ERROR_80 -11080 #define FSCK_INTERNAL_ERROR_81 -11081 #define FSCK_INTERNAL_ERROR_82 -11082 #define FSCK_INTERNAL_ERROR_83 -11083 #define FSCK_INTERNAL_ERROR_84 -11084 #define FSCK_INTERNAL_ERROR_85 -11085 #define FSCK_INTERNAL_ERROR_86 -11086 #define FSCK_INTERNAL_ERROR_87 -11087 #define FSCK_INTERNAL_ERROR_88 -11088 #define FSCK_INTERNAL_ERROR_89 -11089 #endif jfsutils-1.1.15.orig/fsck/xfsckint.h0000644000000000000000000002451410340701412014215 0ustar /* * Copyright (C) International Business Machines Corp., 2000-2004 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef H_XFSCKINT #define H_XFSCKINT #include #include "xfsck.h" #include "fsck_message.h" #include "fsckpfs.h" #include "fsckwsp.h" #include "jfs_endian.h" /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * Device information. * * defined in xchkdsk.c */ extern FILE *Dev_IOPort; extern uint32_t Dev_blksize; extern int32_t Dev_SectorSize; extern int64_t ondev_jlog_byte_offset; /* ---------------------- functions defined in dirtable --------------------- */ int allocate_dir_index_buffers(void); void verify_dir_index(struct fsck_inode_record *, struct dinode *, struct dtreeQelem *, int, uint); /* ---------------------- functions defined in fsckbmap --------------------- */ int rebuild_blkall_map(void); int verify_blkall_map(void); /* ---------------------- functions defined in fsckconn --------------------- */ int adjust_parents(struct fsck_inode_record *, uint32_t); int check_connectedness(void); int check_dir_integrity(void); int check_link_counts(void); /* ---------------------- functions defined in fsckdire --------------------- */ int fsck_dtDelete(struct dinode *, struct component_name *, uint32_t *); int fsck_dtInsert(struct dinode *, struct component_name *, uint32_t *); /* ---------------------- functions defined in fsckdtre --------------------- */ int direntry_add(struct dinode *, uint32_t, UniChar *); int direntry_get_inonum(uint32_t, int, UniChar *, int, UniChar *, uint32_t *); int direntry_get_objnam(uint32_t, uint32_t, int *, UniChar *); int direntry_remove(struct dinode *, uint32_t); int dTree_processing(struct dinode *, uint32_t, struct fsck_inode_record *, struct fsck_ino_msg_info *, int); int dTree_search(struct dinode *, UniChar *, uint32_t, UniChar *, uint32_t, struct dtslot **, int8_t *, struct fsck_inode_record *); int find_first_dir_leaf(struct dinode *, dtpage_t **, int64_t *, int8_t *, int8_t *); void init_dir_tree(dtroot_t *); int process_valid_dir_data(struct dinode *, uint32_t, struct fsck_inode_record *, struct fsck_ino_msg_info *, int); int reconnect_fs_inodes(void); int rebuild_dir_index(struct dinode *, struct fsck_inode_record *); /* ---------------------- functions defined in fsckimap --------------------- */ int AIS_redundancy_check(void); int AIS_replication(void); int rebuild_agg_iamap(void); int rebuild_fs_iamaps(void); int record_dupchk_inode_extents(void); int verify_agg_iamap(void); int verify_fs_iamaps(void); /* ---------------------- functions defined in fsckino --------------------- */ #define inode_type_recognized(iptr)\ ( ISDIR(iptr->di_mode) || \ ISREG(iptr->di_mode) || \ ISLNK(iptr->di_mode) || \ ISBLK(iptr->di_mode) || \ ISCHR(iptr->di_mode) || \ ISFIFO(iptr->di_mode)|| \ ISSOCK(iptr->di_mode) ) int backout_ACL(struct dinode *, struct fsck_inode_record *); int backout_EA(struct dinode *, struct fsck_inode_record *); int clear_ACL_field(struct fsck_inode_record *, struct dinode *); int clear_EA_field(struct fsck_inode_record *, struct dinode *); int display_path(uint32_t, int, uint32_t, char *, struct fsck_inode_record *); int display_paths(uint32_t, struct fsck_inode_record *, struct fsck_ino_msg_info *); int first_ref_check_inode(struct dinode *, uint32_t, struct fsck_inode_record *, struct fsck_ino_msg_info *); int get_path(uint32_t, uint32_t, char **, struct fsck_inode_record *); int in_inode_data_check(struct fsck_inode_record *, struct fsck_ino_msg_info *); int inode_is_in_use(struct dinode *, uint32_t); int parent_count(struct fsck_inode_record *); int record_valid_inode(struct dinode *, uint32_t, struct fsck_inode_record *, struct fsck_ino_msg_info *); int release_inode(uint32_t, struct fsck_inode_record *, struct dinode *); int unrecord_valid_inode(struct dinode *, uint32_t, struct fsck_inode_record *, struct fsck_ino_msg_info *); int validate_ACL(struct dinode *, uint32_t, struct fsck_inode_record *, struct fsck_ino_msg_info *); int validate_data(struct dinode *, uint32_t, struct fsck_inode_record *, struct fsck_ino_msg_info *); int validate_dir_data(struct dinode *, uint32_t, struct fsck_inode_record *, struct fsck_ino_msg_info *); int validate_EA(struct dinode *, uint32_t, struct fsck_inode_record *, struct fsck_ino_msg_info *); int validate_record_fileset_inode(uint32_t, uint32_t, struct dinode *, struct fsck_ino_msg_info *); /* ---------------------- functions defined in fsckmeta --------------------- */ int agg_clean_or_dirty(void); int fatal_dup_check(void); int first_ref_check_agg_metadata(void); int first_ref_check_fixed_metadata(void); int first_ref_check_fs_metadata(void); int first_ref_check_inode_extents(void); int record_fixed_metadata(void); int replicate_superblock(void); int validate_fs_metadata(void); int validate_repair_superblock(void); int validate_select_agg_inode_table(void); /* ---------------------- functions defined in fsckpfs --------------------- */ int ait_node_get(int64_t, xtpage_t *); int ait_node_put(int64_t, xtpage_t *); int ait_special_read_ext1(int); int blkmap_find_bit(int64_t, int64_t *, uint32_t *, uint32_t *); int blkmap_flush(void); int blkmap_get_ctl_page(struct fsck_blk_map_hdr *); int blkmap_get_page(int64_t, struct fsck_blk_map_page **); int blkmap_put_ctl_page(struct fsck_blk_map_hdr *); int blkmap_put_page(int64_t); int blktbl_ctl_page_put(struct dbmap *); int blktbl_dmap_get(int64_t, struct dmap **); int blktbl_dmap_put(struct dmap *); int blktbl_dmaps_flush(void); int blktbl_Ln_page_get(int8_t, int64_t, struct dmapctl **); int blktbl_Ln_page_put(struct dmapctl *); int blktbl_Ln_pages_flush(void); int close_volume(void); int default_volume(void); int dnode_get(int64_t, uint32_t, dtpage_t **); int ea_get(int64_t, uint32_t, char *, uint32_t *, uint32_t *, int64_t *); int flush_index_pages(void); int fscklog_put_buffer(void); int iag_get(int, int, int, int32_t, struct iag **); int iag_get_first(int, int, int, struct iag **); int iag_get_next(struct iag **); int iag_put(struct iag *); int iags_flush(void); int inodes_flush(void); int inode_get(int, int, uint32_t, struct dinode **); int inode_get_first_fs(int, uint32_t *, struct dinode **); int inode_get_next(uint32_t *, struct dinode **); int inode_put(struct dinode *); int inotbl_get_ctl_page(int, struct dinomap **); int inotbl_put_ctl_page(int, struct dinomap *); int mapctl_get(int64_t, void **); int mapctl_put(void *); int mapctl_flush(void); void modify_index(struct dinode *, int64_t, int, uint); int node_get(int64_t, xtpage_t **); int open_volume(char *); int readwrite_device(int64_t, uint32_t, uint32_t *, void *, int); int recon_dnode_assign(int64_t, dtpage_t **); int recon_dnode_get(int64_t, dtpage_t **); int recon_dnode_put(dtpage_t *); int recon_dnode_release(dtpage_t *); /* ---------------------- functions defined in fsckruns --------------------- */ void fsck_hbeat_start(void); void fsck_hbeat_stop(void); /* ---------------------- functions defined in fsckwsp --------------------- */ int alloc_vlarge_buffer(void); int alloc_wrksp(uint32_t, int, int, void **); /* called from both fsck modules * and from logredo modules */ int blkall_decrement_owners(int64_t); int blkall_increment_owners(int64_t, int64_t, struct fsck_ino_msg_info *); int blkall_ref_check(int64_t, int64_t); int dire_buffer_alloc(dtpage_t **); int dire_buffer_release(dtpage_t *); int directory_buffers_alloc(void); int directory_buffers_release(void); int dtreeQ_dequeue(struct dtreeQelem **); int dtreeQ_enqueue(struct dtreeQelem *); int dtreeQ_get_elem(struct dtreeQelem **); int dtreeQ_rel_elem(struct dtreeQelem *); int establish_agg_workspace(void); int establish_ea_iobuf(void); int establish_fs_workspace(void); int establish_io_buffers(void); int establish_wsp_block_map_ctl(void); int extent_record(int64_t, int64_t); int extent_unrecord(int64_t, int64_t); int fsck_alloc_fsblks(int32_t, int64_t *); int fsck_dealloc_fsblks(int32_t, int64_t); int fscklog_end(void); int fscklog_init(void); int fscklog_start(void); int get_inode_extension(struct fsck_inode_ext_record **); int get_inorecptr(int, int, uint32_t, struct fsck_inode_record **); int get_inorecptr_first(int, uint32_t *, struct fsck_inode_record **); int get_inorecptr_next(int, uint32_t *, struct fsck_inode_record **); int init_agg_record(void); int process_extent(struct fsck_inode_record *, uint32_t, int64_t, int8_t, int8_t, struct fsck_ino_msg_info *, uint32_t *, int8_t *, int); int release_inode_extension(struct fsck_inode_ext_record *); int release_logredo_allocs(void); int temp_inode_buf_alloc(char **); int temp_inode_buf_release(char *); int temp_node_buf_alloc(char **); int temp_node_buf_release(char *); int treeQ_dequeue(struct treeQelem **); int treeQ_enqueue(struct treeQelem *); int treeQ_get_elem(struct treeQelem **); int treeQ_rel_elem(struct treeQelem *); int workspace_release(void); /* ---------------------- functions defined in fsckxtre --------------------- */ int find_first_leaf(struct dinode *, xtpage_t **, int64_t *, int8_t *, int8_t *); int init_xtree_root(struct dinode *); int process_valid_data(struct dinode *, uint32_t, struct fsck_inode_record *, struct fsck_ino_msg_info *, int); int xTree_processing(struct dinode *, uint32_t, struct fsck_inode_record *, struct fsck_ino_msg_info *, int); int xTree_search(struct dinode *, int64_t, xad_t **, int8_t *); /* ---------------------- functions defined in xchkdsk.c --------------------- */ void report_readait_error(int, int, int); #endif jfsutils-1.1.15.orig/fscklog/0000755000000000000000000000000011534235600012716 5ustar jfsutils-1.1.15.orig/fscklog/Makefile.am0000644000000000000000000000037310320366062014754 0ustar INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/libfs -I$(top_srcdir)/fsck LDADD = ../libfs/libfs.a sbin_PROGRAMS = jfs_fscklog man_MANS = jfs_fscklog.8 EXTRA_DIST = $(man_MANS) jfs_fscklog_SOURCES = fscklog.c display.c extract.c jfs_fscklog.h jfsutils-1.1.15.orig/fscklog/Makefile.in0000644000000000000000000004315011534235513014771 0ustar # Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@ 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 = : sbin_PROGRAMS = jfs_fscklog$(EXEEXT) subdir = fscklog DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)" PROGRAMS = $(sbin_PROGRAMS) am_jfs_fscklog_OBJECTS = fscklog.$(OBJEXT) display.$(OBJEXT) \ extract.$(OBJEXT) jfs_fscklog_OBJECTS = $(am_jfs_fscklog_OBJECTS) jfs_fscklog_LDADD = $(LDADD) jfs_fscklog_DEPENDENCIES = ../libfs/libfs.a DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(jfs_fscklog_SOURCES) DIST_SOURCES = $(jfs_fscklog_SOURCES) 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' man8dir = $(mandir)/man8 NROFF = nroff MANS = $(man_MANS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_CFLAGS = @AM_CFLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ 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@ LN = @LN@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ 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@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ 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__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ 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@ INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/libfs -I$(top_srcdir)/fsck LDADD = ../libfs/libfs.a man_MANS = jfs_fscklog.8 EXTRA_DIST = $(man_MANS) jfs_fscklog_SOURCES = fscklog.c display.c extract.c jfs_fscklog.h all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu fscklog/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu fscklog/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)" @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ 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)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || 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)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) jfs_fscklog$(EXEEXT): $(jfs_fscklog_OBJECTS) $(jfs_fscklog_DEPENDENCIES) @rm -f jfs_fscklog$(EXEEXT) $(LINK) $(jfs_fscklog_OBJECTS) $(jfs_fscklog_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/display.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/extract.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fscklog.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` install-man8: $(man_MANS) @$(NORMAL_INSTALL) test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)" @list=''; test -n "$(man8dir)" || exit 0; \ { for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | 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,^[^8][0-9a-z]*$$,8,;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)$(man8dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$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)$(man8dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ done; } uninstall-man8: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man8dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ test -z "$$files" || { \ echo " ( cd '$(DESTDIR)$(man8dir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(man8dir)" && rm -f $$files; } ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ 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 CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ 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" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically \`make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi @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 check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(MANS) installdirs: for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"; 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: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install 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) 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-generic clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ 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-sbinPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man8 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-man uninstall-sbinPROGRAMS uninstall-man: uninstall-man8 .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-sbinPROGRAMS ctags distclean distclean-compile \ distclean-generic distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am 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-man8 install-pdf \ install-pdf-am install-ps install-ps-am install-sbinPROGRAMS \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-man uninstall-man8 \ uninstall-sbinPROGRAMS # 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: jfsutils-1.1.15.orig/fscklog/display.c0000644000000000000000000002157010340701412014525 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * COMPONENT_NAME: jfs_fscklog (formerly xchkdmp) * * The jfs_fscklog tool provides 2 basic functions - fsck.jfs * service log extraction and display. The code here displays * the extracted log. * */ /* * Define the following to avoid including * a bunch of unnecessary header files */ #define _JFS_XCHKDMP #include #include #include #include #include #include #include "fscklog.h" #include "fsck_message.h" #include "jfs_fscklog.h" extern char *MsgText[]; extern struct fscklog_record fscklog_record; extern struct fscklog_record *local_recptr; extern char file_name[128]; FILE *infp; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * input: fsck service log I/O buffer * output: fsck extracted service log I/O buffer * */ char xchklog_buffer[XCHKLOG_BUFSIZE]; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * For message processing * * values are assigned by the main jfs_fscklog routine */ extern char *msgprms[10]; extern short msgprmidx[10]; /* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV * * The following are internal to this file * */ void dump_service_log(void); int xchkdmp_final_processing(void); int xchkdmp_fscklog_fill_buffer(void); int open_infile(void); /***************************************************************************** * NAME: xchkdmp * * FUNCTION: Entry point for displaying aggregate fsck.jfs service log * * PARAMETERS: * local_recptr - fscklog record * * RETURNS: * success: 0 * failure: something else */ int xchkdmp(struct fscklog_record *local_recptr) { int rc = 0; /* * Initialize the fscklog control block */ local_recptr->infile_buf_length = XCHKLOG_BUFSIZE; local_recptr->infile_buf_ptr = xchklog_buffer; local_recptr->highest_msg_num = fsck_highest_msgid_defined + JFSCHKLOG_FIRSTMSGNUM; rc = open_infile(); if (rc == 0) { /* we have a buffer and the device is open */ dump_service_log(); } if (rc == 0) { /* no errors yet */ rc = xchkdmp_final_processing(); } else { /* something already went wrong */ xchkdmp_final_processing(); } return (rc); } /*************************************************************************** * NAME: dump_service_log * * FUNCTION: * * PARAMETERS: none * * NOTES: o The first read from the input file is done when the * file is opened. (This is done so that the eyecatcher * can be read to verify that the input file is actually * an extracted JFS fsck service log.) * * RETURNS: * success: 0 * failure: something else */ void dump_service_log() { char *msg_txt; int dsl_rc = 0; char *log_entry; int log_entry_pos; int bytes_left; struct chklog_entry_hdr *hdptr; local_recptr->fscklog_last_read = 0; while ((!local_recptr->fscklog_last_read) && (dsl_rc == 0)) { local_recptr->this_buffer_last_message = 0; while ((!local_recptr->this_buffer_last_message) && (dsl_rc == 0)) { hdptr = (struct chklog_entry_hdr *) (local_recptr->infile_buf_ptr + local_recptr->infile_buf_data_len); if (hdptr->entry_length == 0) { /* no more entries in this buffer */ local_recptr->this_buffer_last_message = -1; } else { /* this entry_length != 0 */ log_entry = (char *) hdptr; log_entry_pos = sizeof (struct chklog_entry_hdr); /* * Each FSCKLOG_BUFSIZE boundary starts a new * log record. Otherwise, we depend on a valid * entry_length to locate the next message. */ bytes_left = local_recptr->infile_buf_length - local_recptr->infile_buf_data_len; if ((bytes_left < 0) || (hdptr->entry_length < 0) || (hdptr->entry_length > bytes_left)) { /* this isn't a valid log record length */ send_msg(fsck_CHKLOGINVALRCD); local_recptr->this_buffer_last_message = -1; } else { /* the record looks ok */ msg_txt = &log_entry[log_entry_pos]; printf(msg_txt); /* * set up for the next record */ local_recptr->infile_buf_data_len += hdptr->entry_length; if (local_recptr->infile_buf_data_len >= local_recptr->infile_buf_length) { local_recptr-> this_buffer_last_message = -1; } } } } /* * read some more from the input file */ if ((!local_recptr->fscklog_last_read) && (dsl_rc == 0)) { dsl_rc = xchkdmp_fscklog_fill_buffer(); } } return; } /*************************************************************************** * NAME: xchkdmp_final_processing * * FUNCTION: If processing read/write, replicate the superblock and the * aggregate inode structures (i.e., the Aggregate Inode Map * and the Aggregate Inode Table). * * Notify the user about various things. * * PARAMETERS: none * * RETURNS: * success: 0 * failure: something else */ int xchkdmp_final_processing() { int pf_rc = 0; /* * Close the input file */ if (local_recptr->infile_is_open) { pf_rc = fclose(infp); } return (pf_rc); } /**************************************************************************** * NAME: xchkdmp_fscklog_fill_buffer * * FUNCTION: If the current fsck session has write access to the aggregate, * and if the in-aggregate fsck log is not full, write the * contents of the current fscklog buffer into the in-aggregate * fsck log. * * PARAMETERS: none * * NOTES: o Unlike most _put_ routines in this module, fscklog_put_buffer * actually writes to the device. This is done because the fsck * log contains information which provides crucial serviceability * should the fsck session be interrupted. * * o Errors here are recorded in the control page of the fsck * in-aggregate workspace but never affect other fsck processing. * * RETURNS: * success: 0 * failure: something else */ int xchkdmp_fscklog_fill_buffer() { int flfb_rc = 0; unsigned bytes_read = 0; bytes_read = fread((void *) local_recptr->infile_buf_ptr, sizeof (char), XCHKLOG_BUFSIZE, infp); if (bytes_read != XCHKLOG_BUFSIZE) { if (feof(infp)) { local_recptr->fscklog_last_read = -1; } } /* * We want to reset the buffer no matter what. * It is useful to keep going because the next section may be * readable. */ local_recptr->infile_buf_data_len = 0; return (flfb_rc); } /***************************************************************************** * NAME: open_infile * * FUNCTION: Open the input file. * * PARAMETERS: none * * RETURNS: * success: 0 * failure: something else */ int open_infile() { int openif_rc = 0; unsigned bytes_read = 0; int eyecatcher_incorrect = 0; if (!local_recptr->file_name_specified) { /* no input file name specified */ if (local_recptr->which_log == NEWLOG) { memcpy((void *) file_name, (void *) default_logfile_new, default_logfile_name_len); } else { memcpy((void *) file_name, (void *) default_logfile_old, default_logfile_name_len); } } infp = fopen(file_name, "r"); if (infp == NULL) { /* input file open failed */ openif_rc = XCHKDMP_CANTOPENINFILE; send_msg(fsck_XCHKDMPOPNFAIL, file_name); } else { /* input file is open */ local_recptr->infile_is_open = -1; } if (local_recptr->infile_is_open) { /* * read in the first buffer of data */ bytes_read = fread((void *) local_recptr->infile_buf_ptr, sizeof (char), XCHKLOG_BUFSIZE, infp); if (bytes_read != XCHKLOG_BUFSIZE) { /* there should be at least this much */ openif_rc = XCHKDMP_MTORBADREAD; send_msg(fsck_XCHKDMPMTORBADREAD); } else { /* read was successful */ eyecatcher_incorrect = memcmp((void *) local_recptr->infile_buf_ptr, (void *) jfs_chklog_eyecatcher, 16); if (eyecatcher_incorrect) { /* incorrect 1st 16 chars */ openif_rc = XCHKDMP_BADFORMAT; send_msg(fsck_XCHKDMPBADFORMAT); } else { local_recptr->infile_buf_data_len = 16; } } } return (openif_rc); } jfsutils-1.1.15.orig/fscklog/extract.c0000644000000000000000000006530410441103234014535 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * COMPONENT_NAME: jfs_fscklog (formerly xchklog) * * The jfs_fscklog tool provides 2 basic functions - fsck.jfs * service log extraction and display. The code here extracts * the log. * */ #include #include #include #include #include #include "devices.h" #include "diskmap.h" #include "fsckwsp.h" #include "fsck_message.h" #include "jfs_endian.h" #include "jfs_fscklog.h" #include "super.h" #include "utilsubs.h" #include "xfsck.h" #define fsck_READ 1 #define fsck_WRITE 2 extern char file_name[128]; FILE *outfp; extern struct fscklog_record fscklog_record; extern struct fscklog_record *local_recptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * superblock I/O buffer and pointer * */ struct superblock aggr_superblock; struct superblock *sb_ptr; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * input: fsck service log I/O buffer * output: fsck extracted service log I/O buffer * */ char fscklog_buffer[FSCKLOG_BUFSIZE]; char xchklog_buffer[XCHKLOG_BUFSIZE]; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * For message processing * * values are assigned by the main jfs_fscklog routine */ extern char *Vol_Label; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * Device information. * * values are assigned when (if) the device is opened. */ FILE *Dev_IOPort; unsigned Dev_blksize; int Dev_SectorSize; /* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV * * The following are internal to this file * */ void extract_service_log(void); int xchklog_final_processing(void); int xchklog_fscklog_fill_buffer(void); int xchklog_initial_processing(struct fscklog_record *); int open_device_read(const char *); int open_outfile(void); int readwrite_device(int64_t, unsigned, unsigned *, void *, int); void record_msg(char *); int validate_super(int); int validate_superblock(void); /***************************************************************************** * NAME: xchklog * * FUNCTION: Entry point for jfs read aggregate fsck service log * * PARAMETERS: * local_recptr - fscklog record * * RETURNS: * success: 0 * failure: something else */ int xchklog(struct fscklog_record *local_recptr) { int rc = 0; /* * some basic initializations */ sb_ptr = &aggr_superblock; rc = xchklog_initial_processing(local_recptr); if (rc == 0) { /* we have a buffer and the device is open */ extract_service_log(); } if (rc == 0) { rc = xchklog_final_processing(); } else { xchklog_final_processing(); } return (rc); } /*************************************************************************** * NAME: extract_service_log * * FUNCTION: * * PARAMETERS: none * * RETURNS: * success: 0 * failure: something else */ void extract_service_log() { char *msg_txt; int dsl_rc = 0; char *log_entry; int log_entry_pos; int bytes_left; struct fscklog_entry_hdr *hdptr; local_recptr->fscklog_last_read = 0; while ((!local_recptr->fscklog_last_read) && (dsl_rc == 0)) { dsl_rc = xchklog_fscklog_fill_buffer(); local_recptr->this_buffer_last_message = 0; while ((!local_recptr->this_buffer_last_message) && (dsl_rc == 0)) { hdptr = (struct fscklog_entry_hdr *) (local_recptr->infile_buf_ptr + local_recptr->infile_buf_data_len); if (hdptr->entry_length == 0) { /* no more entries in this buffer */ local_recptr->this_buffer_last_message = -1; } else { /* this entry_length != 0 */ /* swap if on big endian machine */ ujfs_swap_fscklog_entry_hdr(hdptr); log_entry = (char *) hdptr; log_entry_pos = sizeof (struct fscklog_entry_hdr); /* * Each FSCKLOG_BUFSIZE boundary starts a new * log record. Otherwise, we depend on a valid * entry_length to locate the next message. */ bytes_left = local_recptr->infile_buf_length - local_recptr->infile_buf_data_len; if ((bytes_left < 0) || (hdptr->entry_length < 0) || (hdptr->entry_length > bytes_left)) { /* this isn't a valid log record length */ send_msg(fsck_CHKLOGINVALRCD); local_recptr->this_buffer_last_message = -1; } else { /* the log record length looks ok */ msg_txt = &log_entry[log_entry_pos]; /* * record the message in the output file */ record_msg(msg_txt); /* * set up for the next record */ local_recptr->infile_buf_data_len += hdptr->entry_length; /*if (hdptr->msg_num == fsck_SESSEND) { local_recptr-> this_buffer_last_message = -1; }*/ if (local_recptr->infile_buf_data_len >= local_recptr->infile_buf_length) { local_recptr-> this_buffer_last_message = -1; } } } } } return; } /*************************************************************************** * NAME: xchklog_final_processing * * FUNCTION: If processing read/write, replicate the superblock and the * aggregate inode structures (i.e., the Aggregate Inode Map * and the Aggregate Inode Table). * * Notify the user about various things. * * PARAMETERS: none * * RETURNS: * success: 0 * failure: something else */ int xchklog_final_processing() { int pf_rc = 0; /* * Close the device */ if (local_recptr->device_is_open) { pf_rc = fclose(Dev_IOPort); } /* * Close the output file */ if (local_recptr->outfile_is_open) { /* * flush the buffer if necessary */ if (local_recptr->outfile_buf_data_len != 0) { fwrite((const void *) (local_recptr->outfile_buf_ptr), sizeof (char), local_recptr->outfile_buf_length, outfp); } fclose(outfp); } return (pf_rc); } /***************************************************************************** * NAME: fscklog_fill_buffer * * FUNCTION: If the current fsck session has write access to the aggregate, * and if the in-aggregate fsck log is not full, write the * contents of the current fscklog buffer into the in-aggregate * fsck log. * * PARAMETERS: none * * NOTES: o Unlike most _put_ routines in this module, fscklog_put_buffer * actually writes to the device. This is done because the fsck * log contains information which provides crucial serviceability * should the fsck session be interrupted. * * o Errors here are recorded in the control page of the fsck * in-aggregate workspace but never affect other fsck processing. * * RETURNS: * success: 0 * failure: something else */ int xchklog_fscklog_fill_buffer() { int flfb_rc = 0; int io_rc = 0; unsigned bytes_read = 0; unsigned log_bytes_left; io_rc = readwrite_device(local_recptr->infile_agg_offset, local_recptr->infile_buf_length, &bytes_read, (void *) local_recptr->infile_buf_ptr, fsck_READ); if ((io_rc != 0) || (bytes_read != (unsigned) local_recptr->infile_buf_length)) { /* * write failed or didn't read * correct number of bytes */ send_msg(fsck_URCVWRT, fsck_ref_msg(fsck_metadata), Vol_Label); send_msg(fsck_ERRONLOG, FSCK_BADREAD_FSCKLOG, io_rc, fsck_READ, (long long) local_recptr->infile_agg_offset, (long int) local_recptr->infile_buf_length, (long int) bytes_read); } /* * We want to reset the buffer no matter what. If is useful * to keep going because the next section may be readable. */ local_recptr->infile_agg_offset += local_recptr->infile_buf_length; local_recptr->infile_log_offset += local_recptr->infile_buf_length; local_recptr->infile_buf_data_len = 0; log_bytes_left = (local_recptr->ondev_fscklog_byte_length / 2) - local_recptr->infile_log_offset; if (log_bytes_left < local_recptr->infile_buf_length) { /* this is the last one */ local_recptr->fscklog_last_read = -1; } return (flfb_rc); } /***************************************************************************** * NAME: xchklog_initial_processing * * FUNCTION: Parse and verify invocation parameters. * Open the device and verify that it contains a JFS file system. * Read the chkdsk workspace control page. * Calculate interesting aggregate offsets. * * * PARAMETERS: as specified to main() * * NOTES: * * RETURNS: * success: 0 * failure: something else */ int xchklog_initial_processing(struct fscklog_record *local_recptr) { int pi_rc = 0; /* * Initialize the fscklog control block */ local_recptr->infile_buf_length = FSCKLOG_BUFSIZE; local_recptr->infile_buf_ptr = fscklog_buffer; local_recptr->outfile_buf_length = XCHKLOG_BUFSIZE; local_recptr->outfile_buf_ptr = xchklog_buffer; /* * Open the device and verify that it contains a valid JFS aggregate * If it does, check/repair the superblock. */ pi_rc = open_device_read(Vol_Label); if (pi_rc != 0) { /*device open failed */ send_msg(fsck_CNTRESUPB); } else { /* device is open */ local_recptr->device_is_open = 1; pi_rc = validate_superblock(); if (pi_rc == 0) { /* a valid superblock */ /* * add some stuff to the local record which is based on * superblock fields */ /* length of the on-device fsck service log */ local_recptr->ondev_fscklog_byte_length = sb_ptr->s_fsckloglen * sb_ptr->s_bsize; /* length of the on-device fsck service log */ local_recptr->ondev_fscklog_fsblk_length = sb_ptr->s_fsckloglen; /* length of the on-device fsck workspace */ local_recptr->ondev_wsp_fsblk_length = lengthPXD(&(sb_ptr->s_fsckpxd)) - local_recptr->ondev_fscklog_fsblk_length; /* length of the on-device fsck workspace */ local_recptr->ondev_wsp_byte_length = local_recptr->ondev_wsp_fsblk_length * sb_ptr->s_bsize; /* aggregate block offset of the on-device fsck workspace */ local_recptr->ondev_wsp_fsblk_offset = addressPXD(&(sb_ptr->s_fsckpxd)); /* byte offset of the on-device fsck workspace */ local_recptr->ondev_wsp_byte_offset = local_recptr->ondev_wsp_fsblk_offset * sb_ptr->s_bsize; /* aggregate block offset of the on-device fsck workspace */ local_recptr->ondev_fscklog_fsblk_offset = local_recptr->ondev_wsp_fsblk_offset + local_recptr->ondev_wsp_fsblk_length; /* byte offset of the on-device fsck workspace */ local_recptr->ondev_fscklog_byte_offset = local_recptr->ondev_wsp_byte_offset + local_recptr->ondev_wsp_byte_length; /* * The offsets now assume the most recent log is 1st in the * aggregate fsck service log space. Adjust if needed. */ if (local_recptr->which_log == NEWLOG) { /* most recent wanted */ if (sb_ptr->s_fscklog == 2) { /* the 2nd is most recent */ local_recptr-> ondev_fscklog_fsblk_offset += local_recptr-> ondev_fscklog_fsblk_length / 2; local_recptr-> ondev_fscklog_byte_offset += local_recptr-> ondev_fscklog_byte_length / 2; } } else { /* previous log wanted */ if (sb_ptr->s_fscklog != 2) { /* the 2nd is not most recent */ local_recptr-> ondev_fscklog_fsblk_offset += local_recptr-> ondev_fscklog_fsblk_length / 2; local_recptr-> ondev_fscklog_byte_offset += local_recptr-> ondev_fscklog_byte_length / 2; } } local_recptr->infile_agg_offset = local_recptr->ondev_fscklog_byte_offset; pi_rc = open_outfile(); } } if (local_recptr->which_log == NEWLOG) { send_msg(fsck_CHKLOGNEW); } else { send_msg(fsck_CHKLOGOLD); } return (pi_rc); } /***************************************************************************** * NAME: open_device_read * * FUNCTION: Open the specified device for read access. * * PARAMETERS: * Device - input - the device specification * * NOTES: * * RETURNS: * success: 0 * failure: something else */ int open_device_read(const char *Device) { Dev_IOPort = fopen(Device, "r"); if (Dev_IOPort == NULL) { send_msg(fsck_DEVOPENRDRC, ERROR_FILE_NOT_FOUND); return ERROR_FILE_NOT_FOUND; } Dev_blksize = Dev_SectorSize = PBSIZE; return 0; } /***************************************************************************** * NAME: open_outfile * * FUNCTION: Open the output file. * * PARAMETERS: * Device - input - the device specification * * RETURNS: * success: 0 * failure: something else */ int open_outfile() { int openof_rc = 0; if (!local_recptr->file_name_specified) { /* no output file name given */ if (local_recptr->which_log == NEWLOG) { /* most recent wanted */ memcpy((void *) file_name, (void *) default_logfile_new, default_logfile_name_len); } else { /* prior log wanted */ memcpy((void *) file_name, (void *) default_logfile_old, default_logfile_name_len); } } outfp = fopen(file_name, "w"); if (outfp == NULL) { /* output file open failed */ openof_rc = XCHKLOG_CANTOPENOUTFILE; send_msg(fsck_XCHKLOGOPNFAIL, file_name); } else { /* output file is open */ local_recptr->outfile_is_open = -1; /* * write the eyecatcher into the output buffer */ memcpy((void *) (local_recptr->outfile_buf_ptr), (void *) jfs_chklog_eyecatcher, 16); local_recptr->outfile_buf_data_len = 16; /* * announce the output file name */ if (local_recptr->which_log == NEWLOG) { /* most recent */ send_msg(fsck_XCHKLOGNEW, file_name); } else { /* previous */ send_msg(fsck_XCHKLOGOLD, file_name); } } return (openof_rc); } /***************************************************************************** * NAME: readwrite_device * * FUNCTION: Read data from or write data to the device on which the * aggregate resides. * * PARAMETERS: * dev_offset - input - the offset, in bytes, into the aggregate * of the data to read or to which to write * the data. * requested_data_size - input - the number of bytes requested * actual_data_size - input - pointer to a variable in which to return * the number of bytes actually read or * written * data_buffer - input - the address of the buffer in which to * put the data or from which to write * the data * mode - input - { fsck_READ | fsck_WRITE } * * NOTES: This routine also exists in fsck code. When there is time, * examine both copies for differences and put the combined * copy in libfs to eliminate extra code. * * RETURNS: * success: 0 * failure: something else */ int readwrite_device(int64_t dev_offset, unsigned requested_data_size, unsigned *actual_data_size, void *data_buffer, int mode) { int rwdb_rc = 0; if ((dev_offset % Dev_SectorSize) || (requested_data_size % Dev_SectorSize)) { rwdb_rc = FSCK_FAILED_SEEK; } else { switch (mode) { case fsck_READ: rwdb_rc = ujfs_rw_diskblocks(Dev_IOPort, dev_offset, requested_data_size, data_buffer, GET); break; case fsck_WRITE: rwdb_rc = ujfs_rw_diskblocks(Dev_IOPort, dev_offset, requested_data_size, data_buffer, PUT); break; default: rwdb_rc = FSCK_INTERNAL_ERROR_3; break; } } if (rwdb_rc == 0) *actual_data_size = requested_data_size; else *actual_data_size = 0; return (rwdb_rc); } /***************************************************************************** * NAME: record_msg * * FUNCTION: Record an fsck service log message in the output file, * formatted for the common fsck service log display tool. * * PARAMETERS: * ? - input - * ? - returned - * * NOTES: Any message designated fsck_debug is english-only, and * is issued in english, even if it is sent to stdout. * * All other messages are local-language (in the nls context) * and, when sent to stdout or stderr, are issued in the * local language. * * Regardless of the language used to send a message to * stdout and stderr, messages are ALWAYS LOGGED IN ENGLISH. * * RETURNS: * nothing */ void record_msg(char *msg_txt) { char *msg; char log_entry[4096]; int entry_length = sizeof (struct chklog_entry_hdr); struct chklog_entry_hdr *hdptr; int buffer_bytes_left; hdptr = (struct chklog_entry_hdr *) log_entry; msg = &log_entry[entry_length]; strcpy(msg, msg_txt); entry_length += strlen(msg_txt); /* add null terminator to string */ log_entry[entry_length++] = '\0'; /* * round the length up so the next entry will * start on a doubleword (4 byte) boundary */ entry_length = ((entry_length + 3) / 4) * 4; hdptr->entry_length = entry_length; buffer_bytes_left = local_recptr->outfile_buf_length - local_recptr->outfile_buf_data_len; if (buffer_bytes_left < entry_length) { /* won't fit */ local_recptr->last_msghdr->entry_length += buffer_bytes_left; fwrite((const void *) (local_recptr->outfile_buf_ptr), sizeof (char), local_recptr->outfile_buf_length, outfp); /* clear the buffer */ memset((void *) (local_recptr->outfile_buf_ptr), 0, local_recptr->outfile_buf_length); local_recptr->outfile_buf_data_len = 0; } local_recptr->last_msghdr = (struct fscklog_entry_hdr *) (local_recptr->outfile_buf_ptr + local_recptr->outfile_buf_data_len); memcpy((void *) local_recptr->last_msghdr, (void *) hdptr, entry_length); local_recptr->outfile_buf_data_len += entry_length; return; } /***************************************************************************** * NAME: validate_super * * FUNCTION: This routine validates the JFS superblock currently in the * buffer. If any problem is detected, the which_superblock * input parm is used to tailor the message issued to notify * the user. * * PARAMETERS: * which_super - input - specifies the superblock on which is in the * buffer { fsck_primary | fsck_secondary } * * NOTES: This routine also exists in fsck code. When there is time, * examine both copies for differences and put the combined * copy in libfs to eliminate extra code. * * RETURNS: * success: 0 * failure: something else */ int validate_super(int which_super) { int vs_rc = 0; /* assume the superblock is ok */ int64_t bytes_on_device; int64_t agg_blks_in_aggreg = 0, agg_blks_on_device = 0, dev_blks_on_device; int64_t fsck_start_from_pxd, fsck_blkmap_start_blks; uint32_t fsck_length_from_pxd, fsck_blkmap_size_blks, fsck_blkmap_size_pages; int64_t jlog_start_from_pxd; uint32_t jlog_length_from_pxd; int agl2size; unsigned expected_flag = JFS_GROUPCOMMIT; unsigned agsize; int bad_bsize = 0; if (memcmp(sb_ptr->s_magic, JFS_MAGIC, sizeof (sb_ptr->s_magic)) != 0) { vs_rc = FSCK_BADSBMGC; send_msg(fsck_BADSBMGC, fsck_ref_msg(which_super)); } else if (sb_ptr->s_version > JFS_VERSION) { vs_rc = FSCK_BADSBVRSN; send_msg(fsck_BADSBVRSN, fsck_ref_msg(which_super)); } else { /* the magic number and version number are correct so it * probably is a JFS superblock with the format we are expecting */ /* get physical device size */ ujfs_get_dev_size(Dev_IOPort, &bytes_on_device); dev_blks_on_device = bytes_on_device / Dev_blksize; if (sb_ptr->s_pbsize != Dev_blksize) { vs_rc = FSCK_BADSBOTHR1; send_msg(fsck_BADSBOTHR, "1", fsck_ref_msg(which_super)); } if (sb_ptr->s_l2pbsize != log2shift(Dev_blksize)) { vs_rc = FSCK_BADSBOTHR2; send_msg(fsck_BADSBOTHR, "2", fsck_ref_msg(which_super)); } if (!inrange(sb_ptr->s_bsize, 512, 4096)) { bad_bsize = -1; vs_rc = FSCK_BADSBOTHR3; send_msg(fsck_BADSBBLSIZ, fsck_ref_msg(which_super)); } else { /* else the filesystem block size is a legal value */ if (sb_ptr->s_l2bsize != log2shift(sb_ptr->s_bsize)) { vs_rc = FSCK_BADSBOTHR4; send_msg(fsck_BADSBOTHR, "4", fsck_ref_msg(which_super)); } if (sb_ptr->s_l2bfactor != log2shift(sb_ptr->s_bsize / Dev_blksize)) { vs_rc = FSCK_BADSBOTHR5; send_msg(fsck_BADSBOTHR, "5", fsck_ref_msg(which_super)); } if (sb_ptr->s_bsize < Dev_blksize) { bad_bsize = -1; vs_rc = FSCK_BLSIZLTLVBLSIZ; send_msg(fsck_BLSIZLTLVBLSIZ, fsck_ref_msg(which_super)); } } if (!bad_bsize) { agg_blks_on_device = bytes_on_device / sb_ptr->s_bsize; } if (sb_ptr->s_size > dev_blks_on_device) { vs_rc = FSCK_BADSBFSSIZ; send_msg(fsck_BADSBFSSIZ, fsck_ref_msg(which_super)); } #ifdef _JFS_DFS_LFS s_size_inbytes = sb_ptr->s_size * Dev_blksize; sum_inbytes = (int64_t) (sb_ptr->totalUsable * 1024) + (int64_t) (sb_ptr->minFree * 1024); if ((sum_inbytes > s_size_inbytes) || ((s_size_inbytes - sum_inbytes) >= 1024)) { /* the sum is greater or the difference is at least 1K */ vs_rc = FSCK_BADBLKCTTTL; send_msg(fsck_BADBLKCTTTL, fsck_ref_msg(which_super)); } #endif /* must have JFS_OS2 or JFS_LINUX */ if (!(((sb_ptr->s_flag & JFS_OS2) == JFS_OS2) || ((sb_ptr->s_flag & JFS_LINUX) == JFS_LINUX))) { vs_rc = FSCK_BADSBOTHR6; send_msg(fsck_BADSBOTHR, "6", fsck_ref_msg(which_super)); } if ((sb_ptr->s_flag & expected_flag) != expected_flag) { vs_rc = FSCK_BADSBOTHR6; send_msg(fsck_BADSBOTHR, "6", fsck_ref_msg(which_super)); } if (sb_ptr->s_agsize < (1 << L2BPERDMAP)) { vs_rc = FSCK_BADSBAGSIZ; send_msg(fsck_BADSBAGSIZ, fsck_ref_msg(which_super)); } else { /* else the alloc group size is possibly correct */ agg_blks_in_aggreg = sb_ptr->s_size * sb_ptr->s_pbsize / sb_ptr->s_bsize; agl2size = ujfs_getagl2size(agg_blks_in_aggreg, sb_ptr->s_bsize); /* get the allocation group size */ agsize = (int64_t) 1 << agl2size; if (sb_ptr->s_agsize != agsize) { vs_rc = FSCK_BADAGFSSIZ; send_msg(fsck_BADSBAGSIZ, fsck_ref_msg(which_super)); } } if (!vs_rc) { /* * check out the fsck in-aggregate workspace */ fsck_length_from_pxd = lengthPXD(&(sb_ptr->s_fsckpxd)); fsck_start_from_pxd = addressPXD(&(sb_ptr->s_fsckpxd)); agg_blks_in_aggreg = fsck_length_from_pxd + (sb_ptr->s_size * sb_ptr->s_pbsize / sb_ptr->s_bsize); if (agg_blks_in_aggreg > agg_blks_on_device) { /* wsp length is bad */ vs_rc = FSCK_BADSBFWSL1; send_msg(fsck_BADSBFWSL1, fsck_ref_msg(which_super)); } else { fsck_blkmap_size_pages = ((agg_blks_in_aggreg + (BITSPERPAGE - 1)) / BITSPERPAGE) + 1 + 50; /* size in aggregate blocks */ fsck_blkmap_size_blks = (fsck_blkmap_size_pages << L2PSIZE) / sb_ptr->s_bsize; /* * aggregate block offset of the * fsck workspace in the aggregate. */ fsck_blkmap_start_blks = agg_blks_in_aggreg - fsck_blkmap_size_blks; if (fsck_length_from_pxd != fsck_blkmap_size_blks) { /* * length of fsck in-aggregate * workspace is incorrect */ vs_rc = FSCK_BADSBFWSL; send_msg(fsck_BADSBFWSL, fsck_ref_msg(which_super)); } if (fsck_start_from_pxd != fsck_blkmap_start_blks) { /* * address of fsck in-aggregate * workspace is incorrect */ vs_rc = FSCK_BADSBFWSA; send_msg(fsck_BADSBFWSA, fsck_ref_msg(which_super)); } } } if (!vs_rc) { /* * check out the in-aggregate journal log * * if there is one it starts at the end of the fsck * in-aggregate workspace. */ jlog_length_from_pxd = lengthPXD(&(sb_ptr->s_logpxd)); jlog_start_from_pxd = addressPXD(&(sb_ptr->s_logpxd)); if (jlog_start_from_pxd != 0) { /* there's one in there */ if (jlog_start_from_pxd != agg_blks_in_aggreg) { /* * address of in-aggregate * journal log is incorrect */ vs_rc = FSCK_BADSBFJLA; send_msg(fsck_BADSBFJLA, fsck_ref_msg(which_super)); } agg_blks_in_aggreg += jlog_length_from_pxd; if (agg_blks_in_aggreg > agg_blks_on_device) { /* log length is bad */ vs_rc = FSCK_BADSBFJLL; send_msg(fsck_BADSBFJLL, fsck_ref_msg(which_super)); } } } } return (vs_rc); } /***************************************************************************** * NAME: validate_superblock * * FUNCTION: Verify that the primary superblock is valid. * If not, verify that the secondary superblock is valid. * * PARAMETERS: none * * NOTES: If this routine returns 0 then the superblock * I/O buffer contains a valid superblock. * * This routine also exists in fsck code. When there is time, * examine both copies for differences and put the combined * copy in libfs to eliminate extra code. * * RETURNS: * success: 0 * failure: something else */ int validate_superblock() { int vsb_rc = 0; int primary_sb_bad = 1; int secondary_sb_bad = 1; int which_sb = 0; /* get primary */ vsb_rc = ujfs_get_superblk(Dev_IOPort, sb_ptr, 1); if (vsb_rc != 0) { /* if read primary fails */ send_msg(fsck_CNTRESUPP); } else { /* got primary superblock */ which_sb = fsck_primary; primary_sb_bad = validate_super(fsck_primary); } if (primary_sb_bad) { /* can't use the primary superblock */ send_msg(fsck_SBBADP); /* get 2ndary */ vsb_rc = ujfs_get_superblk(Dev_IOPort, sb_ptr, 0); if (vsb_rc != 0) { send_msg(fsck_CNTRESUPS); } else { /* got secondary superblock */ which_sb = fsck_secondary; secondary_sb_bad = validate_super(fsck_secondary); } if (!secondary_sb_bad) { /* secondary is ok */ vsb_rc = 0; } else { send_msg(fsck_SBBADS); } } if ((!primary_sb_bad) || (!secondary_sb_bad)) { /* the buffer holds a valid superblock */ /* aggregate block size */ local_recptr->ag_blk_size = sb_ptr->s_bsize; send_msg(fsck_XCHKLOGSBOK, fsck_ref_msg(which_sb)); } return (vsb_rc); } jfsutils-1.1.15.orig/fscklog/fscklog.c0000644000000000000000000001630410441103234014507 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * COMPONENT_NAME: jfs_fscklog * * This tool extracts the contents of the specified (or implied) * fsck service log on the specified device. The output is * written to a file (name specified or defaulted). * * This routine also displays the contents of an extracted * fsck service log. If no input file name is specified, * a default path and name are used. * * USAGE: * * jfs_fscklog [-d] [-e ] [-f ] [-p] [-V] * * where: o -d displays an fsck.jfs log already extracted with -e * o -e extracts an fsck.jfs log from device * o -f specifies the file name of the extracted log * o is assumed to be in the present working * directory unless it is fully qualified * o must be 127 characters or less in length * o if is not specified, the default path * and name are used: fscklog.new * o -p specifies extracting the prior log * o -V prints the verstion number and date, and exits * * SAMPLE INVOCATIONS: * To extract the most recent log on /dev/hda5 into fscklog.new * jfs_fscklog -e /dev/hda5 * * To extract the most recent log on /dev/hda7 into output.fil * jfs_fscklog -e /dev/hda7 -f output.fil * * To extract and display the most recent log on /dev/hdb3 * jfs_fscklog -e /dev/hdb3 -d * * To extract and display the prior log on /dev/hdb4 into fscklog.old * jfs_fscklog -p -e /dev/hdb4 -d * * To display the contents of the fsck service log in fscklog.new * jfs_fscklog -d * * To display the contents of the fsck service log in input.fil * jfs_fscklog -d -f input.fil * */ #define _GNU_SOURCE /* for basename() */ #include #include #include #include #include #include #include #include "jfs_version.h" #include "jfs_fscklog.h" #include "xfsck.h" #include "fsck_message.h" struct fscklog_record fscklog_record; struct fscklog_record *local_recptr; char file_name[128]; char *Vol_Label = NULL; bool extract_log; bool display_log; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * The following are internal to this file * */ int parse_parms(int, char **); int v_send_msg(int, const char *, int, ...); /* VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV */ void fscklog_usage(void) { printf("\nUsage: jfs_fscklog [-d] [-e device] [-f file.name] [-p] [-V]\n"); printf("\nEmergency help:\n" " -d Display an already extracted fsck.jfs service log.\n" " -e device Extract the fsck.jfs service log from device.\n" " -f file.name Specify the file name that the fsck.jfs log will be extracted into, or\n" " the file name of the already extracted fsck.jfs log that will be displayed.\n" " -p Extract the previous fsck.jfs service log.\n" " -V Print version information only.\n" "NOTE: -e and -d can be used together to extract and display the fsck.jfs service log.\n"); return; } /***************************************************************************** * NAME: main * * FUNCTION: Entry point for jfs read/display aggregate fsck service log * * RETURNS: * success: 0 * failure: something else */ int main(int argc, char **argv) { int rc = 0; printf("jfs_fscklog version %s, %s\n", VERSION, JFSUTILS_DATE); /* * some basic initializations */ local_recptr = &fscklog_record; memset(local_recptr, 0, sizeof (fscklog_record)); local_recptr->which_log = NEWLOG; local_recptr->file_name_specified = 0; extract_log = display_log = 0; memset((void *) file_name, 0, 128); /* * Process the parameters given by the user */ rc = parse_parms(argc, argv); if ((rc == 0) && (extract_log)) { rc = xchklog(local_recptr); } if ((rc == 0) && (display_log)) { rc = xchkdmp(local_recptr); } return (rc); } /***************************************************************************** * NAME: parse_parms * * FUNCTION: Parse the invocation parameters. If any unrecognized * parameters are detected, or if any required parameter is * omitted, issue a message and exit. * * PARAMETERS: as specified to main() * * RETURNS: * success: 0 * failure: something else */ int parse_parms(int argc, char **argv) { int pp_rc = 0; int arg_len = 0; int c; FILE *file_p = NULL; while ((c = getopt(argc, argv, "de:f:pV")) != EOF) { switch (c) { case 'd': /* display extracted log */ display_log = -1; break; case 'e': /* extract fsck.jfs log */ extract_log = -1; Vol_Label = optarg; /* ensure volume is valid */ file_p = fopen(Vol_Label, "r"); if (file_p) { fclose(file_p); } else { send_msg(fsck_XCHKLOGBADDEVICE, Vol_Label); fscklog_usage(); return (FSCK_FAILED); } break; case 'f': /* specify file name */ arg_len = strlen(optarg); if (arg_len > 128) { /* filename too long */ send_msg(fsck_XCHKDMPBADFNAME); return (XCHKDMP_FAILED); } else { /* go with the specified file name */ strncpy(file_name, optarg, arg_len); local_recptr->file_name_specified = -1; } break; case 'p': /* extract old log */ local_recptr->which_log = OLDLOG; break; case 'V': /* print version and exit */ exit(0); break; default: fscklog_usage(); return (XCHKDMP_FAILED); } } if (argc < 2) { fscklog_usage(); return (XCHKDMP_FAILED); } return (pp_rc); } /***************************************************************************** * NAME: v_send_msg * * FUNCTION: according to the fsck message structure * * PARAMETERS: * * RETURNS: * nothing */ int v_send_msg(int msg_num, const char *file_name, int line_number, ...) { struct fsck_message *message = &msg_defs[msg_num]; char msg_string[max_log_entry_length - 4]; char debug_detail[100]; va_list args; va_start(args, line_number); vsnprintf(msg_string, sizeof(msg_string), message->msg_txt, args); va_end(args); sprintf(debug_detail, " [%s:%d]\n", basename(file_name), line_number); printf(msg_string); printf(debug_detail); return 0; } jfsutils-1.1.15.orig/fscklog/jfs_fscklog.80000644000000000000000000000604310340701412015275 0ustar .TH jfs_fscklog 8 "October 28, 2002" " " "Extract/Display JFS fsck Log" .SH NAME .B jfs_fscklog \- extract a JFS fsck service log into a file and/or format and display the extracted file .SH SYNOPSIS .B jfs_fscklog [ .B -d ] [ .BI -e " device" ] [ .BI -f " output.file" ] [ .B -p ] [ .B -V ] .SH DESCRIPTION .PP .B jfs_fscklog with option .BI -e " device" extracts the contents of either the most recent or immediately prior (specified with option .BR -p ) JFS fsck service log from the specified device, and writes the output to a file. The file name may be specified with the .B -f option, or the default file name is .IR fscklog.new "." If the .B -p option is used, the default file name is .IR fscklog.old "." .PP .B jfs_fscklog with option .B -d formats and displays the contents of the extracted file. .PP .B jfs_fscklog with options .B -d and .BI -e " device" extracts and displays the JFS fsck service log. .SH OPTIONS .TP .BI \-d Format and display a previously extracted JFS fsck service log. .TP .BI \-e " device" Extract the JFS fsck service log from .I device and store it in a file. .RI ( device is the special file name corresponding to the actual device from which the fsck log will be extracted (e.g. .BR /dev/hdb1 " )). " .TP .BI \-f " file.name" Specify the file name, overriding the default file name. When used with .B -e .IR device , file.name specifies the name of the file into which the JFS fsck log will be extracted. When used with .BR -d , file.name specifies the name of the extracted file whose contents will be formatted and displayed. .RS .LP .IR file.name " must be 127 characters or less in length." .LP .IR file.name " will be created in the present working directory unless it is fully qualified." .RE .TP .BI \-p Extract the prior log (as opposed to the most recent log). .TP .BI \-V Print version information and exit (regardless of any other chosen options). .SH EXAMPLES .LP Extract the most recent JFS fsck log on /dev/hda5 into .IR fscklog.new : .IP .B jfs_fscklog -e /dev/hda5 .IP .LP Extract the most recent JFS fsck log on /dev/hdb3 into .IR /temp/l9651107.log : .IP .B jfs_fscklog -e /dev/hdb3 -f /temp/l9651107.log .IP .LP Display the JFS fsck log that was extracted into .IR /temp/l9651107.log : .IP .B jfs_fscklog -d -f /temp/l9651107.log .IP .LP Extract and display the previous JFS fsck log from /dev/hda8: .IP .B jfs_fscklog -e /dev/hda8 -d -p .IP .SH "REPORTING BUGS" .PP If you find a bug in .B JFS or .BR jfs_fscklog, please report it via the bug tracking system ("Report Bugs" section) of the JFS project web site: .nf http://jfs.sourceforge.net/ .fi .PP Please send as much pertinent information as possible, including any .B jfs_fscklog error messages and the complete output of running .B jfs_fsck with the .B \-v option on the JFS device. .SH SEE ALSO .BR jfs_fsck (8), .BR jfs_mkfs (8), .BR jfs_tune (8), .BR jfs_logdump (8), .BR jfs_debugfs (8) .SH AUTHOR .nf Barry Arndt (barndt@us.ibm.com) .fi .B jfs_fscklog is maintained by IBM. .nf See the JFS project web site for more details: http://jfs.sourceforge.net/ .fi jfsutils-1.1.15.orig/fscklog/jfs_fscklog.h0000644000000000000000000000434510441103234015360 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "fscklog.h" /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * record for xchklog processing * */ struct fscklog_record { int64_t ondev_wsp_byte_length; int64_t ondev_wsp_byte_offset; uint32_t ondev_wsp_fsblk_length; int64_t ondev_wsp_fsblk_offset; uint32_t ondev_fscklog_fsblk_length; int64_t ondev_fscklog_fsblk_offset; int64_t ondev_fscklog_byte_length; int64_t ondev_fscklog_byte_offset; char *infile_buf_ptr; uint32_t infile_buf_length; uint32_t infile_buf_data_len; int64_t infile_agg_offset; int64_t infile_log_offset; struct fscklog_entry_hdr * last_msghdr; char *outfile_buf_ptr; uint32_t outfile_buf_length; uint32_t outfile_buf_data_len; int ag_blk_size; int8_t which_log; int8_t device_is_open; int8_t outfile_is_open; int8_t this_buffer_last_message; int8_t fscklog_last_read; int8_t file_name_specified; unsigned highest_msg_num; int8_t infile_is_open; }; #define default_logfile_new "fscklog.new" #define default_logfile_old "fscklog.old" #define default_logfile_name_len 11 #define NEWLOG 1 #define OLDLOG 2 /* * module return code and possible values */ #define XCHKDMP_FAILED -1 #define XCHKDMP_CANTOPENINFILE -2 #define XCHKDMP_MTORBADREAD -3 #define XCHKDMP_BADFORMAT -4 #define XCHKLOG_CANTOPENOUTFILE -5 extern int xchklog(struct fscklog_record *local_recptr); extern int xchkdmp(struct fscklog_record *local_recptr); jfsutils-1.1.15.orig/include/0000755000000000000000000000000011534235600012711 5ustar jfsutils-1.1.15.orig/include/Makefile.am0000644000000000000000000000031607425600453014753 0ustar EXTRA_DIST = jfs_byteorder.h jfs_btree.h jfs_dinode.h jfs_dmap.h \ jfs_dtree.h jfs_filsys.h jfs_imap.h jfs_logmgr.h jfs_superblock.h \ jfs_types.h jfs_unicode.h jfs_version.h jfs_xtree.h jfsutils-1.1.15.orig/include/Makefile.in0000644000000000000000000002136011534235513014763 0ustar # Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@ 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 = : subdir = include DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_CFLAGS = @AM_CFLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ 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@ LN = @LN@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ 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@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ 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__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ 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@ EXTRA_DIST = jfs_byteorder.h jfs_btree.h jfs_dinode.h jfs_dmap.h \ jfs_dtree.h jfs_filsys.h jfs_imap.h jfs_logmgr.h jfs_superblock.h \ jfs_types.h jfs_unicode.h jfs_version.h jfs_xtree.h all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu include/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu include/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @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 check-am: all-am check: check-am all-am: Makefile installdirs: 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: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install 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) 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-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: 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 Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic distclean \ distclean-generic distdir dvi dvi-am html html-am info info-am \ install install-am 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-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am # 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: jfsutils-1.1.15.orig/include/jfs_btree.h0000755000000000000000000000314010340701412015017 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _H_JFS_BTREE #define _H_JFS_BTREE /* * jfs_btree.h: B+-tree * * JFS B+-tree (dtree and xtree) common definitions */ /* * basic btree page - btpage */ struct btpage { int64_t next; /* 8: right sibling bn */ int64_t prev; /* 8: left sibling bn */ uint8_t flag; /* 1: */ uint8_t rsrvd[7]; /* 7: type specific */ int64_t self; /* 8: self address */ uint8_t entry[4064]; /* 4064: */ }; /* (4096) */ /* btpage flag */ #define BT_TYPE 0x07 /* B+-tree index */ #define BT_ROOT 0x01 /* root page */ #define BT_LEAF 0x02 /* leaf page */ #define BT_INTERNAL 0x04 /* internal page */ #define BT_RIGHTMOST 0x10 /* rightmost page */ #define BT_LEFTMOST 0x20 /* leftmost page */ #define BT_SWAPPED 0x80 /* endian swapped when read from disk */ #endif /* _H_JFS_BTREE */ jfsutils-1.1.15.orig/include/jfs_byteorder.h0000644000000000000000000000615110340701412015717 0ustar /* * Copyright (c) Christoph Hellwig, 2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _H_JFS_BYTEORDER #define _H_JFS_BYTEORDER #if HAVE_SYS_BYTEORDER_H # include #elif HAVE_MACHINE_ENDIAN_H # include #elif HAVE_ENDIAN_H # include #endif #define __swab16(x) \ ({ \ uint16_t __x = (x); \ ((uint16_t)( \ (((uint16_t)(__x) & (uint16_t)0x00ffU) << 8) | \ (((uint16_t)(__x) & (uint16_t)0xff00U) >> 8) )); \ }) #define __swab24(x) \ ({ \ uint32_t __x = (x); \ ((uint32_t)( \ ((__x & (uint32_t)0x000000ffUL) << 16) | \ (__x & (uint32_t)0x0000ff00UL) | \ ((__x & (uint32_t)0x00ff0000UL) >> 16) )); \ }) #define __swab32(x) \ ({ \ uint32_t __x = (x); \ ((uint32_t)( \ (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \ (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \ (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \ (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \ }) #define __swab64(x) \ ({ \ uint64_t __x = (x); \ ((uint64_t)( \ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) << 8) | \ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \ (uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \ }) #if (BYTE_ORDER == LITTLE_ENDIAN) #define __cpu_to_le16(x) ((uint16_t)(x)) #define __cpu_to_le24(x) ((uint32_t)(x)) #define __cpu_to_le32(x) ((uint32_t)(x)) #define __cpu_to_le64(x) ((uint64_t)(x)) #define __le16_to_cpu(x) ((uint16_t)(x)) #define __le24_to_cpu(x) ((uint32_t)(x)) #define __le32_to_cpu(x) ((uint32_t)(x)) #define __le64_to_cpu(x) ((uint64_t)(x)) #elif (BYTE_ORDER == BIG_ENDIAN) #define __cpu_to_le16(x) __swab16(x) #define __cpu_to_le24(x) __swab24(x) #define __cpu_to_le32(x) __swab32(x) #define __cpu_to_le64(x) __swab64(x) #define __le16_to_cpu(x) __swab16(x) #define __le24_to_cpu(x) __swab24(x) #define __le32_to_cpu(x) __swab32(x) #define __le64_to_cpu(x) __swab64(x) #else # error "JFS works only on big- or littleendian machines" #endif #endif /* !_H_JFS_BYTEORDER */ jfsutils-1.1.15.orig/include/jfs_dinode.h0000755000000000000000000001304510340701412015165 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _H_JFS_DINODE #define _H_JFS_DINODE /* * jfs_dinode.h: on-disk inode manager * */ #include "jfs_types.h" #include "jfs_dtree.h" #include "jfs_xtree.h" #define INODESLOTSIZE 128 #define L2INODESLOTSIZE 7 #define log2INODESIZE 9 /* log2(bytes per dinode) */ /* * on-disk inode (struct dinode): 512 bytes * * note: align 64-bit fields on 8-byte boundary. */ struct dinode { /* * I. base area (128 bytes) * ------------------------ * * define generic/POSIX attributes */ uint32_t di_inostamp; /* 4: stamp to show inode belongs to fileset */ int32_t di_fileset; /* 4: fileset number */ uint32_t di_number; /* 4: inode number, aka file serial number */ uint32_t di_gen; /* 4: inode generation number */ pxd_t di_ixpxd; /* 8: inode extent descriptor */ int64_t di_size; /* 8: size */ int64_t di_nblocks; /* 8: number of blocks allocated */ uint32_t di_nlink; /* 4: number of links to the object */ uint32_t di_uid; /* 4: user id of owner */ uint32_t di_gid; /* 4: group id of owner */ uint32_t di_mode; /* 4: attribute, format and permission */ struct timestruc_t di_atime; /* 8: time last data accessed */ struct timestruc_t di_ctime; /* 8: time last status changed */ struct timestruc_t di_mtime; /* 8: time last data modified */ struct timestruc_t di_otime; /* 8: time created */ dxd_t di_acl; /* 16: acl descriptor */ dxd_t di_ea; /* 16: ea descriptor */ int32_t di_next_index;/* 4: Next available dir_table index */ int32_t di_acltype; /* 4: Type of ACL */ /* * Extension Areas. * * Historically, the inode was partitioned into 4 128-byte areas, * the last 3 being defined as unions which could have multiple * uses. The first 96 bytes had been completely unused until * an index table was added to the directory. It is now more * useful to describe the last 3/4 of the inode as a single * union. We would probably be better off redesigning the * entire structure from scratch, but we don't want to break * commonality with OS/2's JFS at this time. */ union { struct { /* * This table contains the information needed to * find a directory entry from a 32-bit index. * If the index is small enough, the table is inline, * otherwise, an x-tree root overlays this table */ struct dir_table_slot _table[12]; /* 96: inline */ dtroot_t _dtroot; /* 288: dtree root */ } _dir; /* (384) */ #define di_dirtable u._dir._table #define di_dtroot u._dir._dtroot #define di_parent di_dtroot.header.idotdot #define di_DASD di_dtroot.header.DASD struct { union { uint8_t _data[96]; /* 96: unused */ struct { void *_imap; /* 4: unused */ uint32_t _gengen; /* 4: generator */ } _imap; } _u1; /* 96: */ #define di_gengen u._file._u1._imap._gengen union { uint8_t _xtroot[288]; struct { uint8_t unused[16]; /* 16: */ dxd_t _dxd; /* 16: */ union { uint32_t _rdev; /* 4: */ uint8_t _fastsymlink[128]; } _u; uint8_t _inlineea[128]; } _special; } _u2; } _file; #define di_xtroot u._file._u2._xtroot #define di_dxd u._file._u2._special._dxd #define di_btroot di_xtroot #define di_inlinedata u._file._u2._special._u #define di_rdev u._file._u2._special._u._rdev #define di_fastsymlink u._file._u2._special._u._fastsymlink #define di_inlineea u._file._u2._special._inlineea } u; }; /* di_mode */ /* * The utilities that are dealing directly with the disk * i-node define the modes as follows. The filesystem itself * should use the standard S_IFMT, etc. defines in stat.h */ #define IFMT 0xF000 /* S_IFMT - mask of file type */ #define IFDIR 0x4000 /* S_IFDIR - directory */ #define IFREG 0x8000 /* S_IFREG - regular file */ #define IFLNK 0xA000 /* S_IFLNK - symbolic link */ #define IFBLK 0x6000 /* S_IFBLK - block special file */ #define IFCHR 0x2000 /* S_IFCHR - character special file */ #define IFFIFO 0x1000 /* S_IFFIFO - FIFO */ #define IFSOCK 0xC000 /* S_IFSOCK - socket */ #define ISUID 0x0800 /* S_ISUID - set user id when exec'ing */ #define ISGID 0x0400 /* S_ISGID - set group id when exec'ing */ #define IREAD 0x0100 /* S_IRUSR - read permission */ #define IWRITE 0x0080 /* S_IWUSR - write permission */ #define IEXEC 0x0040 /* S_IXUSR - execute permission */ /* extended mode bits (on-disk inode di_mode) */ #define IFJOURNAL 0x00010000 /* journalled file */ #define ISPARSE 0x00020000 /* sparse file enabled */ #define INLINEEA 0x00040000 /* inline EA area free */ #define ISWAPFILE 0x00800000 /* file open for pager swap space */ /* more extended mode bits */ #define IDIRECTORY 0x20000000 /* directory (shadow of real bit) */ #endif /*_H_JFS_DINODE */ jfsutils-1.1.15.orig/include/jfs_dmap.h0000755000000000000000000002065610340701412014652 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _H_JFS_DMAP #define _H_JFS_DMAP #include "jfs_types.h" #define BMAPVERSION 1 /* version number */ #define TREESIZE (256+64+16+4+1) /* size of a dmap tree */ #define LEAFIND (64+16+4+1) /* index of 1st leaf of a dmap tree */ #define LPERDMAP 256 /* num leaves per dmap tree */ #define L2LPERDMAP 8 /* l2 number of leaves per dmap tree */ #define DBWORD 32 /* # of blks covered by a map word */ #define L2DBWORD 5 /* l2 # of blks covered by a mword */ #define BUDMIN L2DBWORD /* max free string in a map word */ #define BPERDMAP (LPERDMAP * DBWORD) /* num of blks per dmap */ #define L2BPERDMAP 13 /* l2 num of blks per dmap */ #define CTLTREESIZE (1024+256+64+16+4+1) /* size of a dmapctl tree */ #define CTLLEAFIND (256+64+16+4+1) /* idx of 1st leaf of a dmapctl tree */ #define LPERCTL 1024 /* num of leaves per dmapctl tree */ #define L2LPERCTL 10 /* l2 num of leaves per dmapctl tree */ #define ROOT 0 /* index of the root of a tree */ #define NOFREE ((int8_t) -1) /* no blocks free */ #define MAXAG 128 /* max number of allocation groups */ #define L2MAXAG 7 /* l2 max num of AG */ #define L2MINAGSZ 25 /* l2 of minimum AG size in bytes */ #define BMAPBLKNO 0 /* lblkno of bmap within the map */ /* * maximum l2 number of disk blocks at the various dmapctl levels. */ #define L2MAXL0SIZE (L2BPERDMAP + 1 * L2LPERCTL) #define L2MAXL1SIZE (L2BPERDMAP + 2 * L2LPERCTL) #define L2MAXL2SIZE (L2BPERDMAP + 3 * L2LPERCTL) /* * maximum number of disk blocks at the various dmapctl levels. */ #define MAXL0SIZE ((int64_t)1 << L2MAXL0SIZE) #define MAXL1SIZE ((int64_t)1 << L2MAXL1SIZE) #define MAXL2SIZE ((int64_t)1 << L2MAXL2SIZE) #define MAXMAPSIZE MAXL2SIZE /* maximum aggregate map size */ /* * determine the maximum free string for four (lower level) nodes * of the tree. */ #define TREEMAX(cp) \ ((signed char)(MAX(MAX(*(cp),*((cp)+1)), \ MAX(*((cp)+2),*((cp)+3))))) /* * convert disk block number to the logical block number of the dmap * describing the disk block. s is the log2(number of logical blocks per page) * * The calculation figures out how many logical pages are in front of the dmap. * - the number of dmaps preceding it * - the number of L0 pages preceding its L0 page * - the number of L1 pages preceding its L1 page * - 3 is added to account for the L2, L1, and L0 page for this dmap * - 1 is added to account for the control page of the map. */ #define BLKTODMAP(b,s) \ ((((b) >> 13) + ((b) >> 23) + ((b) >> 33) + 3 + 1) << (s)) /* * convert disk block number to the logical block number of the LEVEL 0 * dmapctl describing the disk block. s is the log2(number of logical blocks * per page) * * The calculation figures out how many logical pages are in front of the L0. * - the number of dmap pages preceding it * - the number of L0 pages preceding it * - the number of L1 pages preceding its L1 page * - 2 is added to account for the L2, and L1 page for this L0 * - 1 is added to account for the control page of the map. */ #define BLKTOL0(b,s) \ (((((b) >> 23) << 10) + ((b) >> 23) + ((b) >> 33) + 2 + 1) << (s)) /* * convert disk block number to the logical block number of the LEVEL 1 * dmapctl describing the disk block. s is the log2(number of logical blocks * per page) * * The calculation figures out how many logical pages are in front of the L1. * - the number of dmap pages preceding it * - the number of L0 pages preceding it * - the number of L1 pages preceding it * - 1 is added to account for the L2 page * - 1 is added to account for the control page of the map. */ #define BLKTOL1(b,s) \ (((((b) >> 33) << 20) + (((b) >> 33) << 10) + ((b) >> 33) + 1 + 1) << (s)) /* * convert disk block number to the logical block number of the dmapctl * at the specified level which describes the disk block. */ #define BLKTOCTL(b,s,l) \ (((l) == 2) ? 1 : ((l) == 1) ? BLKTOL1((b),(s)) : BLKTOL0((b),(s))) /* * convert aggregate map size to the zero origin dmapctl level of the * top dmapctl. */ #define BMAPSZTOLEV(size) \ (((size) <= MAXL0SIZE) ? 0 : ((size) <= MAXL1SIZE) ? 1 : 2) /* convert disk block number to allocation group number. */ #define BLKTOAG(b,sb) ((b) >> ((sb)->s_jfs_bmap->db_agl2size)) /* convert allocation group number to starting disk block * number. */ #define AGTOBLK(a,ip) \ ((int64_t)(a) << ((ip)->i_sb->s_jfs_bmap->db_agl2size)) /* * dmap summary tree * * struct dmaptree must be consistent with struct dmapctl. */ struct dmaptree { int32_t nleafs; /* 4: number of tree leafs */ int32_t l2nleafs; /* 4: l2 number of tree leafs */ int32_t leafidx; /* 4: index of first tree leaf */ int32_t height; /* 4: height of the tree */ int8_t budmin; /* 1: min l2 tree leaf value to combine */ int8_t stree[TREESIZE]; /* TREESIZE: tree */ uint8_t pad[2]; /* 2: pad to word boundary */ }; /* - 360 - */ /* * dmap page per 8K blocks bitmap */ struct dmap { int32_t nblocks; /* 4: num blks covered by this dmap */ int32_t nfree; /* 4: num of free blks in this dmap */ int64_t start; /* 8: starting blkno for this dmap */ struct dmaptree tree; /* 360: dmap tree */ uint8_t pad[1672]; /* 1672: pad to 2048 bytes */ uint32_t wmap[LPERDMAP]; /* 1024: bits of the working map */ uint32_t pmap[LPERDMAP]; /* 1024: bits of the persistent map */ }; /* - 4096 - */ /* * disk map control page per level. * * struct dmapctl must be consistent with struct dmaptree. */ struct dmapctl { int32_t nleafs; /* 4: number of tree leafs */ int32_t l2nleafs; /* 4: l2 number of tree leafs */ int32_t leafidx; /* 4: index of the first tree leaf */ int32_t height; /* 4: height of tree */ int8_t budmin; /* 1: minimum l2 tree leaf value */ int8_t stree[CTLTREESIZE];/* CTLTREESIZE: dmapctl tree */ uint8_t pad[2714]; /* 2714: pad to 4096 */ }; /* - 4096 - */ /* * common definition for dmaptree within dmap and dmapctl */ typedef union { struct dmaptree t1; struct dmapctl t2; } dmtree_t; /* macros for accessing fields within dmtree_t */ #define dmt_nleafs t1.nleafs #define dmt_l2nleafs t1.l2nleafs #define dmt_leafidx t1.leafidx #define dmt_height t1.height #define dmt_budmin t1.budmin #define dmt_stree t1.stree /* * on-disk aggregate disk allocation map descriptor. */ struct dbmap { int64_t dn_mapsize; /* 8: number of blocks in aggregate */ int64_t dn_nfree; /* 8: num free blks in aggregate map */ int32_t dn_l2nbperpage; /* 4: number of blks per page */ int32_t dn_numag; /* 4: total number of ags */ int32_t dn_maxlevel; /* 4: number of active ags */ int32_t dn_maxag; /* 4: max active alloc group number */ int32_t dn_agpref; /* 4: preferred alloc group (hint) */ int32_t dn_aglevel; /* 4: dmapctl level holding the AG */ int32_t dn_agheigth; /* 4: height in dmapctl of the AG */ int32_t dn_agwidth; /* 4: width in dmapctl of the AG */ int32_t dn_agstart; /* 4: start tree index at AG height */ int32_t dn_agl2size; /* 4: l2 num of blks per alloc group */ int64_t dn_agfree[MAXAG]; /* 8*MAXAG: per AG free count */ int64_t dn_agsize; /* 8: num of blks per alloc group */ int8_t dn_maxfreebud; /* 1: max free buddy system */ uint8_t pad[3007]; /* 3007: pad to 4096 */ }; /* - 4096 - */ #endif /* _H_JFS_DMAP */ jfsutils-1.1.15.orig/include/jfs_dtree.h0000755000000000000000000001362110340701412015026 0ustar /* * Copyright (C) International Business Machines Corp., 2000-2004 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _H_JFS_DTREE #define _H_JFS_DTREE /* * jfs_dtree.h: directory B+-tree manager */ #include "jfs_btree.h" typedef union { struct { int tid; struct inode *ip; uint32_t ino; } leaf; pxd_t xd; } ddata_t; /* * entry segment/slot * * an entry consists of type dependent head/only segment/slot and * additional segments/slots linked vi next field; * N.B. last/only segment of entry is terminated by next = -1; */ /* * directory page slot */ struct dtslot { int8_t next; /* 1: */ int8_t cnt; /* 1: */ UniChar name[15]; /* 30: */ }; /* (32) */ #define DATASLOTSIZE 16 #define L2DATASLOTSIZE 4 #define DTSLOTSIZE 32 #define L2DTSLOTSIZE 5 #define DTSLOTHDRSIZE 2 #define DTSLOTDATASIZE 30 #define DTSLOTDATALEN 15 /* * internal node entry head/only segment */ struct idtentry { pxd_t xd; /* 8: child extent descriptor */ int8_t next; /* 1: */ uint8_t namlen; /* 1: */ UniChar name[11]; /* 22: 2-byte aligned */ }; /* (32) */ #define DTIHDRSIZE 10 #define DTIHDRDATALEN 11 /* compute number of slots for entry */ #define NDTINTERNAL(klen) ( ((4 + (klen)) + (15 - 1)) / 15 ) /* * leaf node entry head/only segment * * For legacy filesystems, name contains 13 unichars -- no index field */ struct ldtentry { uint32_t inumber; /* 4: 4-byte aligned */ int8_t next; /* 1: */ uint8_t namlen; /* 1: */ UniChar name[11]; /* 22: 2-byte aligned */ uint32_t index; /* 4: index into dir_table */ }; /* (32) */ #define DTLHDRSIZE 6 #define DTLHDRDATALEN_LEGACY 13 /* Old (OS/2) format */ #define DTLHDRDATALEN 11 /* * dir_table used for directory traversal during readdir */ /* * Maximum entry in inline directory table */ #define MAX_INLINE_DIRTABLE_ENTRY 13 struct dir_table_slot { uint8_t rsrvd; /* 1: */ uint8_t flag; /* 1: 0 if free */ uint8_t slot; /* 1: slot within leaf page of entry */ uint8_t addr1; /* 1: upper 8 bits of leaf page address */ uint32_t addr2; /* 4: lower 32 bits of leaf page address -OR- index of next entry when this entry was deleted */ }; /* (8) */ /* * flag values */ #define DIR_INDEX_VALID 1 #define DIR_INDEX_FREE 0 #define DTSaddress(dir_table_slot, address64)\ {\ (dir_table_slot)->addr1 = ((uint64_t)address64) >> 32;\ (dir_table_slot)->addr2 = __cpu_to_le32((address64) & 0xffffffff);\ } #define addressDTS(dts)\ ( ((uint64_t)((dts)->addr1)) << 32 | __le32_to_cpu((dts)->addr2) ) /* compute number of slots for entry */ #define NDTLEAF_LEGACY(klen) ( ((2 + (klen)) + (15 - 1)) / 15 ) #define NDTLEAF NDTINTERNAL /* * directory root page (in-line in on-disk inode): * * cf. dtpage_t below. */ typedef union { struct { struct dasd DASD; /* 16: DASD limit/usage info F226941 */ uint8_t flag; /* 1: */ int8_t nextindex;/* 1: next free entry in stbl */ int8_t freecnt; /* 1: free count */ int8_t freelist; /* 1: freelist header */ uint32_t idotdot; /* 4: parent inode number */ int8_t stbl[8]; /* 8: sorted entry index table */ } header; /* (32) */ struct dtslot slot[9]; } dtroot_t; #define DTROOTMAXSLOT 9 /* * directory regular page: * * entry slot array of 32 byte slot * * sorted entry slot index table (stbl): * contiguous slots at slot specified by stblindex, * 1-byte per entry * 512 byte block: 16 entry tbl (1 slot) * 1024 byte block: 32 entry tbl (1 slot) * 2048 byte block: 64 entry tbl (2 slot) * 4096 byte block: 128 entry tbl (4 slot) * * data area: * 512 byte block: 16 - 2 = 14 slot * 1024 byte block: 32 - 2 = 30 slot * 2048 byte block: 64 - 3 = 61 slot * 4096 byte block: 128 - 5 = 123 slot * * N.B. index is 0-based; index fields refer to slot index * except nextindex which refers to entry index in stbl; * end of entry stot list or freelist is marked with -1. */ typedef union { struct { int64_t next; /* 8: next sibling */ int64_t prev; /* 8: previous sibling */ uint8_t flag; /* 1: */ int8_t nextindex; /* 1: next entry index in stbl */ int8_t freecnt; /* 1: */ int8_t freelist; /* 1: slot index of head of freelist */ uint8_t maxslot; /* 1: number of slots in page slot[] */ int8_t stblindex; /* 1: slot index of start of stbl */ uint8_t rsrvd[2]; /* 2: */ pxd_t self; /* 8: self pxd */ } header; /* (32) */ struct dtslot slot[128]; } dtpage_t; #define DTPAGEMAXSLOT 128 #define DT8THPGNODEBYTES 512 #define DT8THPGNODETSLOTS 1 #define DT8THPGNODESLOTS 16 #define DTQTRPGNODEBYTES 1024 #define DTQTRPGNODETSLOTS 1 #define DTQTRPGNODESLOTS 32 #define DTHALFPGNODEBYTES 2048 #define DTHALFPGNODETSLOTS 2 #define DTHALFPGNODESLOTS 64 #define DTFULLPGNODEBYTES 4096 #define DTFULLPGNODETSLOTS 4 #define DTFULLPGNODESLOTS 128 #define DTENTRYSTART 1 /* get sorted entry table of the page */ #define DT_GETSTBL(p) ( ((p)->header.flag & BT_ROOT) ?\ ((dtroot_t *)(p))->header.stbl : \ (int8_t *)&(p)->slot[(p)->header.stblindex] ) /* * Flags for dtSearch */ #define JFS_CREATE 1 #define JFS_LOOKUP 2 #define JFS_REMOVE 3 #define JFS_RENAME 4 #endif /* !_H_JFS_DTREE */ jfsutils-1.1.15.orig/include/jfs_filsys.h0000755000000000000000000002022210340701412015227 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _H_JFS_FILSYS #define _H_JFS_FILSYS /* * jfs_filsys.h * * file system (implementation-dependent) constants * * refer to for system wide implementation-dependent constants */ #include "jfs_types.h" /* * file system option (superblock flag) */ /* platform option (conditional compilation) */ #define JFS_AIX 0x80000000 /* AIX support */ /* POSIX name/directory support */ #define JFS_OS2 0x40000000 /* OS/2 support */ /* case-insensitive name/directory support */ #define JFS_DFS 0x20000000 /* DCE DFS LFS support */ #define JFS_LINUX 0x10000000 /* Linux support */ /* case-sensitive name/directory support */ /* directory option */ #define JFS_UNICODE 0x00000001 /* unicode name */ /* commit option */ #define JFS_COMMIT 0x00000f00 /* commit option mask */ #define JFS_GROUPCOMMIT 0x00000100 /* group (of 1) commit */ #define JFS_LAZYCOMMIT 0x00000200 /* lazy commit */ #define JFS_TMPFS 0x00000400 /* temporary file system - * do not log/commit: */ /* log logical volume option */ #define JFS_INLINELOG 0x00000800 /* inline log within file system */ #define JFS_INLINEMOVE 0x00001000 /* inline log being moved */ /* Secondary aggregate inode table */ #define JFS_BAD_SAIT 0x00010000 /* current secondary ait is bad */ /* sparse regular file support */ #define JFS_SPARSE 0x00020000 /* sparse regular file */ /* DASD Limits F226941 */ #define JFS_DASD_ENABLED 0x00040000 /* DASD limits enabled */ #define JFS_DASD_PRIME 0x00080000 /* Prime DASD usage on boot */ /* Directory index */ #define JFS_DIR_INDEX 0x00200000 /* Persistant index for */ /* directory entries */ /* * buffer cache configuration */ /* page size */ #ifdef PSIZE #undef PSIZE #endif #define PSIZE 4096 /* page size (in byte) */ #define L2PSIZE 12 /* log2(PSIZE) */ #define POFFSET 4095 /* offset within page */ /* buffer page size */ #define BPSIZE PSIZE /* * fs fundamental size * * PSIZE >= file system block size >= PBSIZE >= DISIZE */ #define PBSIZE 512 /* physical block size (in byte) */ #define L2PBSIZE 9 /* log2(PBSIZE) */ #define DISIZE 512 /* on-disk inode size (in byte) */ #define L2DISIZE 9 /* log2(DISIZE) */ #define IDATASIZE 256 /* inode inline data size */ #define IXATTRSIZE 128 /* inode inline extended attribute size */ #define XTPAGE_SIZE 4096 #define log2_PAGESIZE 12 #define IAG_SIZE 4096 #define IAG_EXTENT_SIZE 4096 #define INOSPERIAG 4096 /* number of disk inodes per iag */ #define L2INOSPERIAG 12 /* l2 number of disk inodes per iag */ #define INOSPEREXT 32 /* number of disk inode per extent */ #define L2INOSPEREXT 5 /* l2 number of disk inode per extent */ #define IXSIZE (DISIZE * INOSPEREXT) /* inode extent size */ #define INOSPERPAGE 8 /* number of disk inodes per 4K page */ #define L2INOSPERPAGE 3 /* log2(INOSPERPAGE) */ #define IAGFREELIST_LWM 64 #define INODE_EXTENT_SIZE IXSIZE /* inode extent size */ #define NUM_INODE_PER_EXTENT INOSPEREXT #define NUM_INODE_PER_IAG INOSPERIAG #define MINBLOCKSIZE 512 #define MAXBLOCKSIZE 4096 #define MAXFILESIZE ((int64_t)1 << 52) #define JFS_LINK_MAX 65535 /* nlink_t is unsigned short */ /* Minimum number of bytes supported for a JFS partition */ #define MINJFS (0x1000000) #define MINJFSTEXT "16" /* * fixed physical block address (physical block size = 512 byte) * * NOTE: since we can't guarantee a physical block size of 512 bytes the use of * these macros should be removed and the byte offset macros used instead. */ #define SUPER1_B 64 /* primary superblock */ #define AIMAP_B (SUPER1_B + 8) /* 1st extent of aggregate inode map */ #define AITBL_B (AIMAP_B + 16) /* * 1st extent of aggregate inode table */ #define SUPER2_B (AITBL_B + 32) /* 2ndary superblock pbn */ #define BMAP_B (SUPER2_B + 8) /* block allocation map */ /* * SIZE_OF_SUPER defines the total amount of space reserved on disk for the * superblock. This is not the same as the superblock structure, since all of * this space is not currently being used. */ #define SIZE_OF_SUPER PSIZE /* * SIZE_OF_AG_TABLE defines the amount of space reserved to hold the AG table */ #define SIZE_OF_AG_TABLE PSIZE /* * SIZE_OF_MAP_PAGE defines the amount of disk space reserved for each page of * the inode allocation map (to hold iag) */ #define SIZE_OF_MAP_PAGE PSIZE /* * fixed byte offset address */ #define SUPER1_OFF 0x8000 /* primary superblock */ #define AIMAP_OFF (SUPER1_OFF + SIZE_OF_SUPER) /* * Control page of aggregate inode map * followed by 1st extent of map */ #define AITBL_OFF (AIMAP_OFF + (SIZE_OF_MAP_PAGE << 1)) /* * 1st extent of aggregate inode table */ #define SUPER2_OFF (AITBL_OFF + INODE_EXTENT_SIZE) /* * secondary superblock */ #define BMAP_OFF (SUPER2_OFF + SIZE_OF_SUPER) /* * block allocation map */ /* * The following macro is used to indicate the number of reserved disk blocks at * the front of an aggregate, in terms of physical blocks. This value is * currently defined to be 32K. This turns out to be the same as the primary * superblock's address, since it directly follows the reserved blocks. */ #define AGGR_RSVD_BLOCKS SUPER1_B /* * The following macro is used to indicate the number of reserved bytes at the * front of an aggregate. This value is currently defined to be 32K. This * turns out to be the same as the primary superblock's byte offset, since it * directly follows the reserved blocks. */ #define AGGR_RSVD_BYTES SUPER1_OFF /* * The following macro defines the byte offset for the first inode extent in * the aggregate inode table. This allows us to find the self inode to find the * rest of the table. Currently this value is 44K. */ #define AGGR_INODE_TABLE_START AITBL_OFF /* * fixed reserved inode number */ /* aggregate inode */ #define AGGR_RESERVED_I 0 /* aggregate inode (reserved) */ #define AGGREGATE_I 1 /* aggregate inode map inode */ #define BMAP_I 2 /* aggregate block allocation map inode */ #define LOG_I 3 /* aggregate inline log inode */ #define BADBLOCK_I 4 /* aggregate bad block inode */ #define FILESYSTEM_I 16 /* 1st/only fileset inode in ait: * fileset inode map inode */ /* per fileset inode */ #define FILESET_RSVD_I 0 /* fileset inode (reserved) */ #define FILESET_EXT_I 1 /* fileset inode extension */ #define ROOT_I 2 /* fileset root inode */ #define ACL_I 3 /* fileset ACL inode */ #define FILESET_OBJECT_I 4 /* the first fileset inode available for a file * or directory or link... */ #define FIRST_FILESET_INO 16 /* the first aggregate inode which describes * an inode. (To fsck this is also the first * inode in part 2 of the agg inode table.) */ /* * directory configuration */ #define JFS_NAME_MAX 255 #define JFS_PATH_MAX BPSIZE /* * file system state (superblock state) */ #define FM_CLEAN 0x00000000 /* file system is unmounted and clean */ #define FM_MOUNT 0x00000001 /* file system is mounted cleanly */ #define FM_DIRTY 0x00000002 /* file system was not unmounted and clean * when mounted or * commit failure occurred while being mounted: * fsck() must be run to repair */ #define FM_LOGREDO 0x00000004 /* log based recovery (logredo()) failed: * fsck() must be run to repair */ #define FM_EXTENDFS 0x00000008 /* file system extendfs() in progress */ #endif /* _H_JFS_FILSYS */ jfsutils-1.1.15.orig/include/jfs_imap.h0000755000000000000000000001163110340701412014650 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _H_JFS_IMAP #define _H_JFS_IMAP /* * jfs_imap.h: disk inode manager */ #define EXTSPERIAG 128 /* number of disk inode extent per iag */ #define IMAPBLKNO 0 /* lblkno of dinomap within inode map */ #define SMAPSZ 4 /* number of words per summary map */ #define EXTSPERSUM 32 /* number of extents per summary map entry */ #define L2EXTSPERSUM 5 /* l2 number of extents per summary map */ #define PGSPERIEXT 4 /* number of 4K pages per dinode extent */ #define MAXIAGS ((1<<20)-1) /* maximum number of iags */ #define MAXAG 128 /* maximum number of allocation groups */ #define AMAPSIZE 512 /* bytes in the IAG allocation maps */ #define SMAPSIZE 16 /* bytes in the IAG summary maps */ /* convert inode number to iag number */ #define INOTOIAG(ino) ((ino) >> L2INOSPERIAG) /* convert iag number to logical block number of the iag page */ #define IAGTOLBLK(iagno,l2nbperpg) (((iagno) + 1) << (l2nbperpg)) /* get the starting block number of the 4K page of an inode extent * that contains ino. */ #define INOPBLK(pxd,ino,l2nbperpg) (addressPXD((pxd)) + \ ((((ino) & (INOSPEREXT-1)) >> L2INOSPERPAGE) << (l2nbperpg))) /* * inode allocation map: * * inode allocation map consists of * . the inode map control page and * . inode allocation group pages (per 4096 inodes) * which are addressed by standard JFS xtree. */ /* * inode allocation group page (per 4096 inodes of an AG) */ struct iag { int64_t agstart; /* 8: starting block of ag */ int32_t iagnum; /* 4: inode allocation group number */ int32_t inofreefwd; /* 4: ag inode free list forward */ int32_t inofreeback; /* 4: ag inode free list back */ int32_t extfreefwd; /* 4: ag inode extent free list forward */ int32_t extfreeback; /* 4: ag inode extent free list back */ int32_t iagfree; /* 4: iag free list */ /* summary map: 1 bit per inode extent */ int32_t inosmap[SMAPSZ]; /* 16: sum map of mapwords w/ free inodes; * note: this indicates free and backed * inodes, if the extent is not backed the * value will be 1. if the extent is * backed but all inodes are being used the * value will be 1. if the extent is * backed but at least one of the inodes is * free the value will be 0. */ int32_t extsmap[SMAPSZ]; /* 16: sum map of mapwords w/ free extents */ int32_t nfreeinos; /* 4: number of free inodes */ int32_t nfreeexts; /* 4: number of free extents */ /* (72) */ uint8_t pad[1976]; /* 1976: pad to 2048 bytes */ /* allocation bit map: 1 bit per inode (0 - free, 1 - allocated) */ uint32_t wmap[EXTSPERIAG]; /* 512: working allocation map */ uint32_t pmap[EXTSPERIAG]; /* 512: persistent allocation map */ pxd_t inoext[EXTSPERIAG]; /* 1024: inode extent addresses */ }; /* (4096) */ /* * per AG control information (in inode map control page) */ struct iagctl { int32_t inofree; /* 4: free inode list anchor */ int32_t extfree; /* 4: free extent list anchor */ int32_t numinos; /* 4: number of backed inodes */ int32_t numfree; /* 4: number of free inodes */ }; /* (16) */ /* * per fileset/aggregate inode map control page */ struct dinomap { int32_t in_freeiag; /* 4: free iag list anchor */ int32_t in_nextiag; /* 4: next free iag number */ int32_t in_numinos; /* 4: num of backed inodes */ int32_t in_numfree; /* 4: num of free backed inodes */ int32_t in_nbperiext; /* 4: num of blocks per inode extent */ int32_t in_l2nbperiext; /* 4: l2 of in_nbperiext */ int32_t in_diskblock; /* 4: for standalone test driver */ int32_t in_maxag; /* 4: for standalone test driver */ uint8_t pad[2016]; /* 2016: pad to 2048 */ struct iagctl in_agctl[MAXAG]; /* 2048: AG control information */ }; /* (4096) */ #endif /* _H_JFS_IMAP */ jfsutils-1.1.15.orig/include/jfs_logmgr.h0000644000000000000000000002516010340701412015210 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _H_JFS_LOGMGR #define _H_JFS_LOGMGR #ifndef _H_JFS_SUPERBLOCK #include #endif #include "jfs_types.h" #include "jfs_filsys.h" /* * log manager configuration parameters */ /* log page size */ #define LOGPSIZE 4096 #define L2LOGPSIZE 12 #define LOGPAGES 16 /* Log pages per mounted file system */ /* * log logical volume * * a log is used to make the commit operation on journalled * files within the same logical volume group atomic. * a log is implemented with a logical volume. * there is one log per logical volume group. * * block 0 of the log logical volume is not used (ipl etc). * block 1 contains a log "superblock" and is used by logFormat(), * lmLogInit(), lmLogShutdown(), and logRedo() to record status * of the log but is not otherwise used during normal processing. * blocks 2 - (N-1) are used to contain log records. * * when a volume group is varied-on-line, logRedo() must have * been executed before the file systems (logical volumes) in * the volume group can be mounted. */ /* * log superblock (block 1 of logical volume) */ #define LOGSUPER_B 1 #define LOGSTART_B 2 #define LOGMAGIC 0x87654321 #define LOGVERSION 1 #define MAX_ACTIVE 128 /* Max active file systems sharing log */ struct logsuper { uint32_t magic; /* 4: log lv identifier */ int32_t version; /* 4: version number */ int32_t serial; /* 4: log open/mount counter */ int32_t size; /* 4: size in number of LOGPSIZE blocks */ int32_t bsize; /* 4: logical block size in byte */ int32_t l2bsize; /* 4: log2 of bsize */ uint32_t flag; /* 4: option */ uint32_t state; /* 4: state - see below */ int32_t end; /* 4: addr of last log record set by logredo */ uuid_t uuid; /* 16: 128-bit journal uuid */ char label[16]; /* 16: journal label */ uuid_t active[MAX_ACTIVE]; /* 2048: active file systems list */ }; /* log flag: commit option (see jfs_filsys.h) */ /* log state */ #define LOGMOUNT 0 /* log mounted by lmLogInit() */ #define LOGREDONE 1 /* log shutdown by lmLogShutdown(). * log redo completed by logredo(). */ #define LOGWRAP 2 /* log wrapped */ #define LOGREADERR 3 /* log read error detected in logredo() */ /* * log logical page * * (this comment should be rewritten !) * the header and trailer structures (h,t) will normally have * the same page and eor value. * An exception to this occurs when a complete page write is not * accomplished on a power failure. Since the hardware may "split write" * sectors in the page, any out of order sequence may occur during powerfail * and needs to be recognized during log replay. The xor value is * an "exclusive or" of all log words in the page up to eor. This * 32 bit eor is stored with the top 16 bits in the header and the * bottom 16 bits in the trailer. logredo can easily recognize pages * that were not completed by reconstructing this eor and checking * the log page. * * Previous versions of the operating system did not allow split * writes and detected partially written records in logredo by * ordering the updates to the header, trailer, and the move of data * into the logdata area. The order: (1) data is moved (2) header * is updated (3) trailer is updated. In logredo, when the header * differed from the trailer, the header and trailer were reconciled * as follows: if h.page != t.page they were set to the smaller of * the two and h.eor and t.eor set to 8 (i.e. empty page). if (only) * h.eor != t.eor they were set to the smaller of their two values. */ struct logpage { struct { /* header */ int32_t page; /* 4: log sequence page number */ int16_t rsrvd; /* 2: */ int16_t eor; /* 2: end-of-log offset of lasrt record write */ } h; int32_t data[LOGPSIZE / 4 - 4]; /* log record area */ struct { /* trailer */ int32_t page; /* 4: normally the same as h.page */ int16_t rsrvd; /* 2: */ int16_t eor; /* 2: normally the same as h.eor */ } t; }; #define LOGPHDRSIZE 8 /* log page header size */ #define LOGPTLRSIZE 8 /* log page trailer size */ /* * log record * * (this comment should be rewritten !) * jfs uses only "after" log records (only a single writer is allowed * in a page, pages are written to temporary paging space if * if they must be written to disk before commit, and i/o is * scheduled for modified pages to their home location after * the log records containing the after values and the commit * record is written to the log on disk, undo discards the copy * in main-memory.) * * a log record consists of a data area of variable length followed by * a descriptor of fixed size LOGRDSIZE bytes. * the data area is rounded up to an integral number of 4-bytes and * must be no longer than LOGPSIZE. * the descriptor is of size of multiple of 4-bytes and aligned on a * 4-byte boundary. * records are packed one after the other in the data area of log pages. * (sometimes a DUMMY record is inserted so that at least one record ends * on every page or the longest record is placed on at most two pages). * the field eor in page header/trailer points to the byte following * the last record on a page. */ /* log record types */ #define LOG_COMMIT 0x8000 #define LOG_SYNCPT 0x4000 #define LOG_MOUNT 0x2000 #define LOG_REDOPAGE 0x0800 #define LOG_NOREDOPAGE 0x0080 #define LOG_NOREDOINOEXT 0x0040 #define LOG_UPDATEMAP 0x0008 #define LOG_NOREDOFILE 0x0001 /* REDOPAGE/NOREDOPAGE log record data type */ #define LOG_INODE 0x0001 #define LOG_XTREE 0x0002 #define LOG_DTREE 0x0004 #define LOG_BTROOT 0x0010 #define LOG_EA 0x0020 #define LOG_ACL 0x0040 #define LOG_DATA 0x0080 #define LOG_NEW 0x0100 #define LOG_EXTEND 0x0200 #define LOG_RELOCATE 0x0400 #define LOG_DIR_XTREE 0x0800 /* Xtree is in directory inode */ /* UPDATEMAP log record descriptor type */ #define LOG_ALLOCXADLIST 0x0080 #define LOG_ALLOCPXDLIST 0x0040 #define LOG_ALLOCXAD 0x0020 #define LOG_ALLOCPXD 0x0010 #define LOG_FREEXADLIST 0x0008 #define LOG_FREEPXDLIST 0x0004 #define LOG_FREEXAD 0x0002 #define LOG_FREEPXD 0x0001 struct lrd { /* * type independent area */ int32_t logtid; /* 4: log transaction identifier */ int32_t backchain; /* 4: ptr to prev record of same transaction */ uint16_t type; /* 2: record type */ int16_t length; /* 2: length of data in record (in byte) */ uint32_t aggregate; /* 4: file system lv/aggregate */ /* (16) */ /* * type dependent area (20) */ union { /* * COMMIT: commit * * transaction commit: no type-dependent information; */ /* * REDOPAGE: after-image * * apply after-image; * * N.B. REDOPAGE, NOREDOPAGE, and UPDATEMAP must be same format; */ struct { uint32_t fileset; /* 4: fileset number */ uint32_t inode; /* 4: inode number */ uint16_t type; /* 2: REDOPAGE record type */ int16_t l2linesize; /* 2: log2 of line size */ pxd_t pxd; /* 8: on-disk page pxd */ } redopage; /* (20) */ /* * NOREDOPAGE: the page is freed * * do not apply after-image records which precede this record * in the log with the same page block number to this page. * * N.B. REDOPAGE, NOREDOPAGE, and UPDATEMAP must be same format; */ struct { int32_t fileset; /* 4: fileset number */ uint32_t inode; /* 4: inode number */ uint16_t type; /* 2: NOREDOPAGE record type */ int16_t rsrvd; /* 2: reserved */ pxd_t pxd; /* 8: on-disk page pxd */ } noredopage; /* (20) */ /* * UPDATEMAP: update block allocation map * * either in-line PXD, * or out-of-line XADLIST; * * N.B. REDOPAGE, NOREDOPAGE, and UPDATEMAP must be same format; */ struct { uint32_t fileset; /* 4: fileset number */ uint32_t inode; /* 4: inode number */ uint16_t type; /* 2: UPDATEMAP record type */ int16_t nxd; /* 2: number of extents */ pxd_t pxd; /* 8: pxd */ } updatemap; /* (20) */ /* * NOREDOINOEXT: the inode extent is freed * * do not apply after-image records which precede this * record in the log with the any of the 4 page block * numbers in this inode extent. * * NOTE: The fileset and pxd fields MUST remain in * the same fields in the REDOPAGE record format. * */ struct { int32_t fileset; /* 4: fileset number */ int32_t iagnum; /* 4: IAG number */ int32_t inoext_idx; /* 4: inode extent index */ pxd_t pxd; /* 8: on-disk page pxd */ } noredoinoext; /* (20) */ /* * SYNCPT: log sync point * * replay log upto syncpt address specified; */ struct { int32_t sync; /* 4: syncpt address (0 = here) */ } syncpt; /* * MOUNT: file system mount * * file system mount: no type-dependent information; */ /* * ? FREEXTENT: free specified extent(s) * * free specified extent(s) from block allocation map * N.B.: nextents should be length of data/sizeof(xad_t) */ struct { int32_t type; /* 4: FREEXTENT record type */ int32_t nextent; /* 4: number of extents */ /* data: PXD or XAD list */ } freextent; /* * ? NOREDOFILE: this file is freed * * do not apply records which precede this record in the log * with the same inode number. * * NOREDILE must be the first to be written at commit * (last to be read in logredo()) - it prevents * replay of preceding updates of all preceding generations * of the inumber esp. the on-disk inode itself, * but does NOT prevent * replay of the */ struct { int32_t fileset; /* 4: fileset number */ uint32_t inode; /* 4: inode number */ } noredofile; /* * ? NEWPAGE: * * metadata type dependent */ struct { int32_t fileset; /* 4: fileset number */ uint32_t inode; /* 4: inode number */ int32_t type; /* 4: NEWPAGE record type */ pxd_t pxd; /* 8: on-disk page pxd */ } newpage; /* * ? DUMMY: filler * * no type-dependent information */ } log; }; /* (36) */ #define LOGRDSIZE (sizeof(struct lrd)) #endif /* _H_JFS_LOGMGR */ jfsutils-1.1.15.orig/include/jfs_superblock.h0000755000000000000000000000707610340701412016103 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _H_JFS_SUPERBLOCK #define _H_JFS_SUPERBLOCK #ifndef _H_JFS_LOGMGR #include #endif /* * jfs_superblock.h */ /* * make the magic number something a human could read */ #define JFS_MAGIC "JFS1" /* Magic word: JFS 1 */ #define JFS_VERSION 2 /* Version number: Version 2 */ #define LV_NAME_SIZE 11 /* MUST BE 11 for OS/2 boot sector */ /* * aggregate superblock */ struct superblock { char s_magic[4]; /* 4: magic number */ uint32_t s_version; /* 4: version number */ int64_t s_size; /* 8: aggregate size in hardware/LVM blocks; * VFS: number of blocks */ int32_t s_bsize; /* 4: aggregate block size in bytes; * VFS: fragment size */ int16_t s_l2bsize; /* 2: log2 of s_bsize */ int16_t s_l2bfactor; /* 2: log2(s_bsize/hardware block size) */ int32_t s_pbsize; /* 4: hardware/LVM block size in bytes */ int16_t s_l2pbsize; /* 2: log2 of s_pbsize */ int16_t pad; /* 2: padding necessary for alignment */ uint32_t s_agsize; /* 4: allocation group size in aggr. blocks */ uint32_t s_flag; /* 4: aggregate attributes: * see jfs_filsys.h */ uint32_t s_state; /* 4: mount/unmount/recovery state: * see jfs_filsys.h */ int32_t s_compress; /* 4: > 0 if data compression */ pxd_t s_ait2; /* 8: first extent of secondary * aggregate inode table */ pxd_t s_aim2; /* 8: first extent of secondary * aggregate inode map */ uint32_t s_logdev; /* 4: device address of log */ int32_t s_logserial; /* 4: log serial number at aggregate mount */ pxd_t s_logpxd; /* 8: inline log extent */ pxd_t s_fsckpxd; /* 8: inline fsck work space extent */ struct timestruc_t s_time; /* 8: time last updated */ int32_t s_fsckloglen; /* 4: Number of filesystem blocks reserved for * the fsck service log. * N.B. These blocks are divided among the * versions kept. This is not a per * version size. * N.B. These blocks are included in the * length field of s_fsckpxd. */ int8_t s_fscklog; /* 1: which fsck service log is most recent * 0 => no service log data yet * 1 => the first one * 2 => the 2nd one */ char s_fpack[11]; /* 11: file system volume name * N.B. This must be 11 bytes to * conform with the OS/2 BootSector * requirements * Only used when s_version is 1 */ /* extendfs() parameter under s_state & FM_EXTENDFS */ int64_t s_xsize; /* 8: extendfs s_size */ pxd_t s_xfsckpxd; /* 8: extendfs fsckpxd */ pxd_t s_xlogpxd; /* 8: extendfs logpxd */ /* - 128 byte boundary - */ uuid_t s_uuid; /* 16: 128-bit uuid for volume */ char s_label[16]; /* 16: volume label */ uuid_t s_loguuid; /* 16: 128-bit uuid for log device */ }; #endif /*_H_JFS_SUPERBLOCK */ jfsutils-1.1.15.orig/include/jfs_types.h0000755000000000000000000001057210340701412015071 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _H_JFS_TYPES #define _H_JFS_TYPES #include /* Neccessary for *BSD systems */ /* * jfs_types.h: * * basic type/utility definitions * * note: this header file must be the 1st include file * of JFS include list in all JFS .c file. */ #ifdef HAVE_STDINT_H # include #else # include typedef u_int8_t uint8_t; typedef u_int16_t uint16_t; typedef u_int32_t uint32_t; typedef u_int64_t uint64_t; #endif #ifdef HAVE_STDBOOL_H # include #else typedef enum { false = 0, true = 1 } bool; #endif /* HAVE_STDBOOL_H */ /* * Unicase character. Part of the ondisk format. */ typedef uint16_t UniChar; /* * Almost identical to Linux's timespec, but not quite */ struct timestruc_t { uint32_t tv_sec; uint32_t tv_nsec; }; /* * handy */ #undef MIN #define MIN(a,b) (((a)<(b))?(a):(b)) #undef MAX #define MAX(a,b) (((a)>(b))?(a):(b)) #undef ROUNDUP #define ROUNDUP(x, y) ( ((x) + ((y) - 1)) & ~((y) - 1) ) #define LEFTMOSTONE 0x80000000 #define HIGHORDER 0x80000000u /* high order bit on */ #define ONES 0xffffffffu /* all bit on */ /* * physical xd (pxd) */ typedef struct { unsigned len:24; unsigned addr1:8; uint32_t addr2; } pxd_t; /* xd_t field construction */ #define PXDlength(pxd, length32) ((pxd)->len = __cpu_to_le24(length32)) #define PXDaddress(pxd, address64)\ {\ (pxd)->addr1 = ((int64_t)address64) >> 32;\ (pxd)->addr2 = __cpu_to_le32((address64) & 0xffffffff);\ } /* xd_t field extraction */ #define lengthPXD(pxd) __le24_to_cpu((pxd)->len) #define addressPXD(pxd)\ ( ((int64_t)((pxd)->addr1)) << 32 | __le32_to_cpu((pxd)->addr2)) /* pxd list */ struct pxdlist { int16_t maxnpxd; int16_t npxd; pxd_t pxd[8]; }; /* * data extent descriptor (dxd) */ typedef struct { unsigned flag:8; /* 1: flags */ unsigned rsrvd:24; /* 3: */ uint32_t size; /* 4: size in byte */ unsigned len:24; /* 3: length in unit of fsblksize */ unsigned addr1:8; /* 1: address in unit of fsblksize */ uint32_t addr2; /* 4: address in unit of fsblksize */ } dxd_t; /* - 16 - */ /* dxd_t flags */ #define DXD_INDEX 0x80 /* B+-tree index */ #define DXD_INLINE 0x40 /* in-line data extent */ #define DXD_EXTENT 0x20 /* out-of-line single extent */ #define DXD_FILE 0x10 /* out-of-line file (inode) */ #define DXD_CORRUPT 0x08 /* Inconsistency detected */ /* dxd_t field construction * Conveniently, the PXD macros work for DXD */ #define DXDlength PXDlength #define DXDaddress PXDaddress #define lengthDXD lengthPXD #define addressDXD addressPXD /* * directory entry argument */ struct component_name { int namlen; UniChar *name; }; /* * DASD limit information - stored in directory inode */ struct dasd { uint8_t thresh; /* Alert Threshold (in percent) */ uint8_t delta; /* Alert Threshold delta (in percent) */ uint8_t rsrvd1; uint8_t limit_hi; /* DASD limit (in logical blocks) */ uint32_t limit_lo; /* DASD limit (in logical blocks) */ uint8_t rsrvd2[3]; uint8_t used_hi; /* DASD usage (in logical blocks) */ uint32_t used_lo; /* DASD usage (in logical blocks) */ }; #define DASDLIMIT(dasdp) \ (((uint64_t)((dasdp)->limit_hi) << 32) + __le32_to_cpu((dasdp)->limit_lo)) #define setDASDLIMIT(dasdp, limit)\ {\ (dasdp)->limit_hi = ((uint64_t)limit) >> 32;\ (dasdp)->limit_lo = __cpu_to_le32(limit);\ } #define DASDUSED(dasdp) \ (((uint64_t)((dasdp)->used_hi) << 32) + __le32_to_cpu((dasdp)->used_lo)) #define setDASDUSED(dasdp, used)\ {\ (dasdp)->used_hi = ((uint64_t)used) >> 32;\ (dasdp)->used_lo = __cpu_to_le32(used);\ } #endif /* !_H_JFS_TYPES */ jfsutils-1.1.15.orig/include/jfs_unicode.h0000755000000000000000000000604210340701412015350 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Notes: * These APIs are based on the C library functions. The semantics * should match the C functions but with expanded size operands. * * The upper/lower functions are based on a table created by mkupr. * This is a compressed table of upper and lower case conversion. */ struct UNICASERANGE { UniChar start; UniChar end; signed char *table; }; extern signed char UniUpperTable[512]; extern struct UNICASERANGE UniUpperRange[]; /* * UniStrcpy: Copy a string */ static inline UniChar *UniStrcpy(UniChar * ucs1, const UniChar * ucs2) { UniChar *anchor = ucs1; /* save the start of result string */ while ((*ucs1++ = *ucs2++)); return anchor; } /* * UniStrlen: Return the length of a string */ static inline size_t UniStrlen(const UniChar * ucs1) { int i = 0; while (*ucs1++) i++; return i; } /* * UniStrncmp: Compare length limited string */ static inline int UniStrncmp(const UniChar * ucs1, const UniChar * ucs2, size_t n) { if (!n) return 0; /* Null strings are equal */ while ((*ucs1 == *ucs2) && *ucs1 && --n) { ucs1++; ucs2++; } return (int) *ucs1 - (int) *ucs2; } /* * UniStrncpy: Copy length limited string with pad */ static inline UniChar *UniStrncpy(UniChar * ucs1, const UniChar * ucs2, size_t n) { UniChar *anchor = ucs1; while (n-- && *ucs2) /* Copy the strings */ *ucs1++ = *ucs2++; n++; while (n--) /* Pad with nulls */ *ucs1++ = 0; return anchor; } /* * UniToupper: Convert a unicode character to upper case */ static inline UniChar UniToupper(UniChar uc) { struct UNICASERANGE *rp; if (uc < sizeof(UniUpperTable)) { /* Latin characters */ return uc + UniUpperTable[uc]; /* Use base tables */ } else { rp = UniUpperRange; /* Use range tables */ while (rp->start) { if (uc < rp->start) /* Before start of range */ return uc; /* Uppercase = input */ if (uc <= rp->end) /* In range */ return uc + rp->table[uc - rp->start]; rp++; /* Try next range */ } } return uc; /* Past last range */ } /* * UniStrupr: Upper case a unicode string */ static inline UniChar *UniStrupr(UniChar * upin) { UniChar *up; up = upin; while (*up) { /* For all characters */ *up = UniToupper(*up); up++; } return upin; /* Return input pointer */ } jfsutils-1.1.15.orig/include/jfs_version.h0000755000000000000000000000004411534235600015412 0ustar #define JFSUTILS_DATE "04-Mar-2011" jfsutils-1.1.15.orig/include/jfs_xtree.h0000755000000000000000000000611010340701412015045 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _H_JFS_XTREE #define _H_JFS_XTREE /* * jfs_xtree.h: extent allocation descriptor B+-tree manager */ #include "jfs_btree.h" /* * extent allocation descriptor (xad) */ typedef struct xad { unsigned flag:8; /* 1: flag */ unsigned rsvrd:16; /* 2: reserved */ unsigned off1:8; /* 1: offset in unit of fsblksize */ uint32_t off2; /* 4: offset in unit of fsblksize */ unsigned len:24; /* 3: length in unit of fsblksize */ unsigned addr1:8; /* 1: address in unit of fsblksize */ uint32_t addr2; /* 4: address in unit of fsblksize */ } xad_t; /* (16) */ #define MAXXLEN ((1 << 24) - 1) #define XTSLOTSIZE 16 #define L2XTSLOTSIZE 4 /* xad_t field construction */ #define XADoffset(xad, offset64)\ {\ (xad)->off1 = ((uint64_t)offset64) >> 32;\ (xad)->off2 = __cpu_to_le32((offset64) & 0xffffffff);\ } #define XADaddress(xad, address64)\ {\ (xad)->addr1 = ((uint64_t)address64) >> 32;\ (xad)->addr2 = __cpu_to_le32((address64) & 0xffffffff);\ } #define XADlength(xad, length32) (xad)->len = __cpu_to_le24(length32) /* xad_t field extraction */ #define offsetXAD(xad)\ ( ((int64_t)((xad)->off1)) << 32 | __le32_to_cpu((xad)->off2)) #define addressXAD(xad)\ ( ((int64_t)((xad)->addr1)) << 32 | __le32_to_cpu((xad)->addr2)) #define lengthXAD(xad) __le24_to_cpu((xad)->len) /* xad_t flags */ #define XAD_NEW 0x01 /* new */ #define XAD_EXTENDED 0x02 /* extended */ #define XAD_COMPRESSED 0x04 /* compressed with recorded length */ #define XAD_NOTRECORDED 0x08 /* allocated but not recorded */ #define XAD_COW 0x10 /* copy-on-write */ /* possible values for maxentry */ #define XTROOTINITSLOT_DIR 6 #define XTROOTINITSLOT 10 #define XTROOTMAXSLOT 18 #define XTPAGEMAXSLOT 256 #define XTENTRYSTART 2 /* * xtree page: */ typedef union { struct xtheader { int64_t next; /* 8: */ int64_t prev; /* 8: */ uint8_t flag; /* 1: */ uint8_t rsrvd1; /* 1: */ int16_t nextindex; /* 2: next index = number of entries */ int16_t maxentry; /* 2: max number of entries */ int16_t rsrvd2; /* 2: */ pxd_t self; /* 8: self */ } header; /* (32) */ xad_t xad[XTPAGEMAXSLOT]; /* 16 * maxentry: xad array */ } xtpage_t; #endif /* !_H_JFS_XTREE */ jfsutils-1.1.15.orig/install-sh0000755000000000000000000003253711460142743013307 0ustar #!/bin/sh # install - install a program, script, or datafile scriptversion=2009-04-28.21; # 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. nl=' ' IFS=" "" $nl" # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit=${DOITPROG-} if test -z "$doit"; then doit_exec=exec else doit_exec=$doit fi # 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_glob='?' initialize_posix_glob=' test "$posix_glob" != "?" || { if (set -f) 2>/dev/null; then posix_glob= else posix_glob=: fi } ' 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 no_target_directory= 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 *' '* | *' '* | *' '* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) dst_arg=$2 shift;; -T) no_target_directory=true;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done 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 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 trap '(exit $?); exit' 1 2 13 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 starting with `-'. 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 # Protect names starting with `-'. case $dst in -*) dst=./$dst;; esac # 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 -n "$no_target_directory"; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else # Prefer dirname, but fall back on a substitute if dirname fails. dstdir=` (dirname "$dst") 2>/dev/null || expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$dst" : 'X\(//\)[^/]' \| \ X"$dst" : 'X\(//\)$' \| \ X"$dst" : 'X\(/\)' \| . 2>/dev/null || echo X"$dst" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q' ` 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-writeable 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 eval "$initialize_posix_glob" oIFS=$IFS IFS=/ $posix_glob set -f set fnord $dstdir shift $posix_glob set +f IFS=$oIFS prefixes= for d do test -z "$d" && 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` && eval "$initialize_posix_glob" && $posix_glob set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && $posix_glob 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: jfsutils-1.1.15.orig/jfsutils.spec0000644000000000000000000000213511534235600014006 0ustar Name : jfsutils Version : 1.1.15 Release : 1 Group : System/Kernel Summary : IBM JFS utility programs Copyright : GPL Packager : JFS/Linux team URL : http://jfs.sourceforge.net/ Buildroot : %{_tmppath}/%{name}-%{version} Source : %{name}-%{version}.tar.gz %Description Utilities for managing IBM's Journaled File System (JFS) under Linux. The following utilities are available: jfs_fsck - initiate replay of the JFS transaction log, and check and repair a JFS formatted device. jfs_fscklog - extract a log from the JFS fsck workspace into a file and/or display it. jfs_logdump - dump a JFS formatted device's journal log. jfs_mkfs - create a JFS formatted partition. jfs_tune - adjust tunable parameters of the JFS file system. jfs_debugfs - shell-type JFS file system editor. %Prep %setup -q %Build CFLAGS="${RPM_OPT_FLAGS}" ./configure --mandir=/usr/share/man/en/ make %Install make install DESTDIR=${RPM_BUILD_ROOT} %Clean rm -rf ${RPM_BUILD_ROOT} %Files %defattr(-,root,root) /sbin/* %{_mandir}/en/man8/* %doc AUTHORS COPYING INSTALL NEWS README ChangeLog jfsutils-1.1.15.orig/jfsutils.spec.in0000644000000000000000000000214111534235035014412 0ustar Name : @PACKAGE@ Version : @VERSION@ Release : 1 Group : System/Kernel Summary : IBM JFS utility programs Copyright : GPL Packager : JFS/Linux team URL : http://jfs.sourceforge.net/ Buildroot : %{_tmppath}/%{name}-%{version} Source : %{name}-%{version}.tar.gz %Description Utilities for managing IBM's Journaled File System (JFS) under Linux. The following utilities are available: jfs_fsck - initiate replay of the JFS transaction log, and check and repair a JFS formatted device. jfs_fscklog - extract a log from the JFS fsck workspace into a file and/or display it. jfs_logdump - dump a JFS formatted device's journal log. jfs_mkfs - create a JFS formatted partition. jfs_tune - adjust tunable parameters of the JFS file system. jfs_debugfs - shell-type JFS file system editor. %Prep %setup -q %Build CFLAGS="${RPM_OPT_FLAGS}" ./configure --mandir=/usr/share/man/en/ make %Install make install DESTDIR=${RPM_BUILD_ROOT} %Clean rm -rf ${RPM_BUILD_ROOT} %Files %defattr(-,root,root) /sbin/* %{_mandir}/en/man8/* %doc AUTHORS COPYING INSTALL NEWS README ChangeLog jfsutils-1.1.15.orig/libfs/0000755000000000000000000000000011534235577012402 5ustar jfsutils-1.1.15.orig/libfs/Makefile.am0000644000000000000000000000074310320366063014425 0ustar INCLUDES = -I$(top_srcdir)/include noinst_LIBRARIES = libfs.a libfs_a_SOURCES = fssubs.c unicode_to_utf8.c devices.c utilsubs.c \ super.c inode.c diskmap.c message.c uniupr.c jfs_endian.c \ open_by_label.c log_dump.c logform.c logredo.c log_work.c log_read.c \ log_map.c fsckmsgdef.c \ debug.h devices.h diskmap.h fsck_base.h fsckcbbl.h fscklog.h \ fsckwsp.h inode.h libjufs.h message.h super.h unicode_to_utf8.h \ utilsubs.h jfs_endian.h logform.h logredo.h fsck_message.h jfsutils-1.1.15.orig/libfs/Makefile.in0000644000000000000000000003421011534235513014435 0ustar # Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@ 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 = : subdir = libfs DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LIBRARIES = $(noinst_LIBRARIES) AR = ar ARFLAGS = cru libfs_a_AR = $(AR) $(ARFLAGS) libfs_a_LIBADD = am_libfs_a_OBJECTS = fssubs.$(OBJEXT) unicode_to_utf8.$(OBJEXT) \ devices.$(OBJEXT) utilsubs.$(OBJEXT) super.$(OBJEXT) \ inode.$(OBJEXT) diskmap.$(OBJEXT) message.$(OBJEXT) \ uniupr.$(OBJEXT) jfs_endian.$(OBJEXT) open_by_label.$(OBJEXT) \ log_dump.$(OBJEXT) logform.$(OBJEXT) logredo.$(OBJEXT) \ log_work.$(OBJEXT) log_read.$(OBJEXT) log_map.$(OBJEXT) \ fsckmsgdef.$(OBJEXT) libfs_a_OBJECTS = $(am_libfs_a_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(libfs_a_SOURCES) DIST_SOURCES = $(libfs_a_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_CFLAGS = @AM_CFLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ 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@ LN = @LN@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ 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@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ 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__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ 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@ INCLUDES = -I$(top_srcdir)/include noinst_LIBRARIES = libfs.a libfs_a_SOURCES = fssubs.c unicode_to_utf8.c devices.c utilsubs.c \ super.c inode.c diskmap.c message.c uniupr.c jfs_endian.c \ open_by_label.c log_dump.c logform.c logredo.c log_work.c log_read.c \ log_map.c fsckmsgdef.c \ debug.h devices.h diskmap.h fsck_base.h fsckcbbl.h fscklog.h \ fsckwsp.h inode.h libjufs.h message.h super.h unicode_to_utf8.h \ utilsubs.h jfs_endian.h logform.h logredo.h fsck_message.h all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libfs/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu libfs/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) libfs.a: $(libfs_a_OBJECTS) $(libfs_a_DEPENDENCIES) -rm -f libfs.a $(libfs_a_AR) libfs.a $(libfs_a_OBJECTS) $(libfs_a_LIBADD) $(RANLIB) libfs.a mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/devices.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/diskmap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsckmsgdef.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fssubs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inode.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jfs_endian.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log_dump.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log_map.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log_read.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log_work.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logform.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logredo.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/message.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/open_by_label.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/super.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unicode_to_utf8.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uniupr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utilsubs.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ 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 CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ 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" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @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 check-am: all-am check: check-am all-am: Makefile $(LIBRARIES) installdirs: 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: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install 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) 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-generic clean-noinstLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-noinstLIBRARIES ctags distclean distclean-compile \ distclean-generic distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am 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-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ uninstall-am # 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: jfsutils-1.1.15.orig/libfs/debug.h0000644000000000000000000000224010340701413013614 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __H_DEBUG__ #define __H_DEBUG__ #include #ifdef TRACE #define DBG_TRACE(a) {printf a; fflush(stdout);} #else #define DBG_TRACE(a) ; #endif #ifdef TRACE_IO #define DBG_IO(a) {printf a; fflush(stderr);} #else #define DBG_IO(a) ; #endif #ifdef TRACE_ERROR #define DBG_ERROR(a) {printf a; fflush(stdout);} #else #define DBG_ERROR(a) ; #endif #endif jfsutils-1.1.15.orig/libfs/devices.c0000645000000000000000000003070211161726241014160 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2008 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * autoconf 2.61 causes fseeko to miscompile against glibc-2.3. * Override config.h by defining _LARGEFILE_SOURCE here */ #define _LARGEFILE_SOURCE #include #include #include #include #include #include #include #ifdef HAVE_SYS_MOUNT_H #ifdef HAVE_SYS_PARAM_H #include #endif #include #endif #include #include #include #if defined(__DragonFly__) #include #include #endif #ifdef HAVE_SYS_DISKLABEL_H #include #endif #include "jfs_types.h" #include "jfs_filsys.h" #include "devices.h" #include "debug.h" #if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE64) #define BLKGETSIZE64 _IOR(0x12, 114, size_t) #endif #if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE) #define BLKGETSIZE _IO(0x12,96) /* return device size (sectors) */ #endif /* * NAME: ujfs_device_is_valid * * FUNCTION: Check device validity by examining stat modes. * * PRE CONDITIONS: 'device' must refer to an open device handle. * * PARAMETERS: * device_handle - open device handle to check * st - stat information if device handle not provided * * RETURNS: 0 if successful; anything else indicates failures */ int ujfs_device_is_valid(FILE *device_handle, struct stat *st) { struct stat stat_data; int rc = 0; if (device_handle != NULL) { rc = fstat(fileno(device_handle), &stat_data); if (rc) return -1; st = &stat_data; } else if (st == NULL) { return -1; } /* Do we have a block special device or regular file? */ #if defined(__DragonFly__) if (!S_ISCHR(st->st_mode) && !S_ISREG(st->st_mode)) #else /* __linux__ etc. */ if (!S_ISBLK(st->st_mode) && !S_ISREG(st->st_mode)) #endif return -1; return (rc); } /* * NAME: ujfs_get_dev_size * * FUNCTION: Uses the device driver interface to determine the raw capacity of * the specified device. * * PRE CONDITIONS: * * POST CONDITIONS: * * PARAMETERS: * device - device * size - filled in with size of device; not modified if failure occurs * * NOTES: * * DATA STRUCTURES: * * RETURNS: 0 if successful; anything else indicates failures */ int ujfs_get_dev_size(FILE *device, int64_t *size) { off_t Starting_Position; /* position within file/device upon * entry to this function. */ off_t Current_Position = 16777215; /* position we are attempting * to read from. */ off_t Last_Valid_Position = 0; /* Last position we could successfully * read from. */ off_t First_Invalid_Position; /* first invalid position we attempted * to read from/seek to. */ int Seek_Result; /* value returned by lseek. */ size_t Read_Result = 0; /* value returned by read. */ int rc; struct stat stat_data; int devfd = fileno(device); rc = fstat(devfd, &stat_data); if (!rc && S_ISREG(stat_data.st_mode)) { /* This is a regular file. */ *size = (int64_t) ((stat_data.st_size / 1024) * 1024); return NO_ERROR; } #ifdef BLKGETSIZE64 { uint64_t sz; if (ioctl(devfd, BLKGETSIZE64, &sz) >= 0) { *size = sz; return 0; } } #endif #ifdef BLKGETSIZE { unsigned long num_sectors = 0; if (ioctl(devfd, BLKGETSIZE, &num_sectors) >= 0) { /* for now, keep size as multiple of 1024, * * not 512, so eliminate any odd sector. */ *size = PBSIZE * (int64_t) ((num_sectors / 2) * 2); return NO_ERROR; } } #endif #if defined(__DragonFly__) { struct diskslices dss; struct disklabel dl; struct diskslice *sliceinfo; int slice; dev_t dev = stat_data.st_rdev; rc = ioctl(devfd, DIOCGSLICEINFO, &dss); if (rc < 0) return -1; slice = dkslice(dev); sliceinfo = &dss.dss_slices[slice]; DBG_TRACE(("ujfs_get_device_size: slice = %d\n", slice)); if (sliceinfo) { if (slice == WHOLE_DISK_SLICE || slice == 0) { *size = (int64_t) sliceinfo->ds_size * dss.dss_secsize; DBG_TRACE(("ujfs_get_device_size: slice represents disk\n")); } else { if (sliceinfo->ds_label) { DBG_TRACE(("ujfs_get_device_size: slice has disklabel\n")); rc = ioctl(devfd, DIOCGDINFO, &dl); if (!rc) { *size = (int64_t) dl.d_secperunit * dss.dss_secsize; } else { return (-1); } } } } else { return (-1); } DBG_TRACE(("ujfs_get_device_size: size in bytes = %ld\n", *size)); DBG_TRACE(("ujfs_get_device_size: size in megabytes = %ld\n", *size / (1024 * 1024))); return 0; } #endif #if defined(HAVE_SYS_DISKLABEL_H) && !defined(__DragonFly__) { struct disklabel dl; struct partition * part; dev_t dev = stat_data.st_rdev; rc = ioctl(devfd, DIOCGDINFO, &dl); if (rc < 0) return -1; part = dl.d_partitions + DISKPART(dev); *size = (dl.d_secsize * part->p_size); DBG_TRACE(("ujfs_get_device_size: size in bytes = %ld\n", *size)); DBG_TRACE(("ujfs_get_device_size: size in megabytes = %ld\n", *size / (1024 * 1024))); return NO_ERROR; } #endif /* * If the ioctl above fails or is undefined, use a binary search to * find the last byte in the partition. This works because an lseek to * a position within the partition does not return an error while an * lseek to a position beyond the end of the partition does. Note that * some SCSI drivers may log an 'access beyond end of device' error * message. */ /* Save the starting position so that we can restore it when we are * done! */ Starting_Position = ftello(device); if (Starting_Position < 0) return ERROR_SEEK; /* * Find a position beyond the end of the partition. We will start by * attempting to seek to and read the 16777216th byte in the partition. * We start here because a JFS partition must be at least this big. If * it is not, then we can not format it as JFS. */ do { /* Seek to the location we wish to test. */ Seek_Result = fseeko(device, Current_Position, SEEK_SET); if (Seek_Result == 0) { /* Can we read from this location? */ Read_Result = fgetc(device); if (Read_Result != EOF) { /* The current test position is valid. Save it * for future reference. */ Last_Valid_Position = Current_Position; /* Lets calculate the next location to test. */ Current_Position = ((Current_Position + 1) * 2) - 1; } } } while ((Seek_Result == 0) && (Read_Result == 1)); /* * We have exited the while loop, which means that Current Position is * beyond the end of the partition or is unreadable due to a hardware * problem (bad block). Since the odds of hitting a bad block are very * low, we will ignore that condition for now. If time becomes * available, then this issue can be revisited. */ /* Is the drive greater than 16MB? */ if (Last_Valid_Position == 0) { /* * Determine if drive is readable at all. If it is, the drive * is too small. If not, it could be a newly created partion, * so we need to issue a different error message */ *size = 0; /* Indicates not readable at all */ Seek_Result = fseeko(device, Last_Valid_Position, SEEK_SET); if (Seek_Result == 0) { /* Can we read from this location? */ Read_Result = fgetc(device); if (Read_Result != EOF) /* non-zero indicates readable, but too small */ *size = 1; } goto restore; } /* * The drive is larger than 16MB. Now we must find out exactly how * large. * * We now have a point within the partition and one beyond it. The end * of the partition must lie between the two. We will use a binary * search to find it. */ /* Setup for the binary search. */ First_Invalid_Position = Current_Position; Current_Position = Last_Valid_Position + ((Current_Position - Last_Valid_Position) / 2); /* * Iterate until the difference between the last valid position and the * first invalid position is 2 or less. */ while ((First_Invalid_Position - Last_Valid_Position) > 2) { /* Seek to the location we wish to test. */ Seek_Result = fseeko(device, Current_Position, SEEK_SET); if (Seek_Result == 0) { /* Can we read from this location? */ Read_Result = fgetc(device); if (Read_Result != EOF) { /* The current test position is valid. * Save it for future reference. */ Last_Valid_Position = Current_Position; /* * Lets calculate the next location to test. It * should be half way between the current test * position and the first invalid position that * we know of. */ Current_Position = Current_Position + ((First_Invalid_Position - Last_Valid_Position) / 2); } } else Read_Result = 0; if (Read_Result != 1) { /* Out test position is beyond the end of the partition. * It becomes our first known invalid position. */ First_Invalid_Position = Current_Position; /* Our new test position should be half way between our * last known valid position and our current test * position. */ Current_Position = Last_Valid_Position + ((Current_Position - Last_Valid_Position) / 2); } } /* * The size of the drive should be Last_Valid_Position + 1 as * Last_Valid_Position is an offset from the beginning of the partition. */ *size = Last_Valid_Position + 1; restore: /* Restore the original position. */ if (fseeko(device, Starting_Position, SEEK_SET) != 0) return ERROR_SEEK; return NO_ERROR; } /* * NAME: ujfs_rw_diskblocks * * FUNCTION: Read/Write specific number of bytes for an opened device. * * PRE CONDITIONS: * * POST CONDITIONS: * * PARAMETERS: * dev_ptr - file handle of an opened device to read/write * disk_offset - byte offset from beginning of device for start of disk * block read/write * disk_count - number of bytes to read/write * data_buffer - On read this will be filled in with data read from * disk; on write this contains data to be written * mode - GET: read; PUT: write; VRFY: verify * * NOTES: A disk address is formed by {#cylinder, #head, #sector} * * Also the DSK_READTRACK and DSK_WRITETRACK is a track based * function. If it needs to read/write crossing track boundary, * additional calls are used. * * DATA STRUCTURES: * * RETURNS: */ int ujfs_rw_diskblocks(FILE *dev_ptr, int64_t disk_offset, int32_t disk_count, void *data_buffer, int32_t mode) { int Seek_Result; size_t Bytes_Transferred; int error = NO_ERROR; Seek_Result = fseeko(dev_ptr, disk_offset, SEEK_SET); if (Seek_Result != 0) { error = ERROR_SEEK; goto finished; } if (disk_count == 0) { fprintf(stderr, "ujfs_rw_diskblocks: disk_count is 0\n"); error = ERROR_INVALID_PARAMETER; goto finished; } switch (mode) { case GET: Bytes_Transferred = fread(data_buffer, 1, disk_count, dev_ptr); break; case PUT: Bytes_Transferred = fwrite(data_buffer, 1, disk_count, dev_ptr); break; default: DBG_ERROR(("Internal error: %s(%d): bad mode: %d\n", __FILE__, __LINE__, mode)) error = ERROR_INVALID_HANDLE; goto finished; break; /* Keep the compiler happy. */ } if (Bytes_Transferred != disk_count) { if (Bytes_Transferred == -1) perror("ujfs_rw_diskblocks"); else fprintf(stderr, "ujfs_rw_diskblocks: %s %zd of %d bytes at offset %lld\n", (mode == GET) ? "read" : "wrote", Bytes_Transferred, disk_count, disk_offset); if (mode == GET) error = ERROR_READ_FAULT; else error = ERROR_WRITE_FAULT; goto finished; } finished: if (error) rewind(dev_ptr); return (error); } #define RAMDISK_MAJOR 1 int ujfs_flush_dev(FILE *fp) { int fd = fileno(fp); struct stat buf; if (fsync(fd) == -1) return errno; #ifdef BLKFLSBUF fstat(fd, &buf); if (major(buf.st_rdev) != RAMDISK_MAJOR) return ioctl(fileno(fp), BLKFLSBUF, 0); #endif return 0; } jfsutils-1.1.15.orig/libfs/devices.h0000644000000000000000000000305710340701413014157 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef H_DEVICES #define H_DEVICES #define GET 0 #define PUT 1 #define VRFY 2 /* Macros used for determining open mode */ #define READONLY 0 #define RDWR_EXCL 1 /* Error codes */ #define NO_ERROR 0 #define ERROR_INVALID_FUNCTION 1 #define ERROR_FILE_NOT_FOUND 2 #define ERROR_INVALID_HANDLE 6 #define ERROR_NOT_ENOUGH_MEMORY 8 #define ERROR_INVALID_ACCESS 12 #define ERROR_SEEK 25 #define ERROR_WRITE_FAULT 29 #define ERROR_READ_FAULT 30 #define ERROR_GEN_FAILURE 31 #define ERROR_INVALID_PARAMETER 87 #define ERROR_DISK_FULL 112 struct stat; int ujfs_get_dev_size(FILE *, int64_t * size); int ujfs_rw_diskblocks(FILE *, int64_t, int32_t, void *, int32_t); int ujfs_flush_dev(FILE *); int ujfs_device_is_valid(FILE *, struct stat *); #endif /* H_DEVICES */ jfsutils-1.1.15.orig/libfs/diskmap.c0000644000000000000000000002124110340701413014153 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "jfs_types.h" #include "jfs_dmap.h" #include "diskmap.h" /* * budtab[] * * used to determine the maximum free string in a character * of a wmap word. the actual bit values of the character * serve as the index into this array and the value of the * array at that index is the max free string. * */ static int8_t budtab[256] = { 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -1 }; /* * NAME: ujfs_maxbuddy * * FUNCTION: Determines the maximum string of free blocks within a word of the * wmap or pmap consistent with binary buddy. * * PRE CONDITIONS: * * POST CONDITIONS: * * PARAMETERS: * cp - Pointer to wmap or pmap word. * * NOTES: * * DATA STRUCTURES: * * RETURNS: Maximum string of free blocks within word. */ int8_t ujfs_maxbuddy(unsigned char *cp) { /* * Check if the wmap or pmap word is all free. If so, the free buddy size is * BUDMIN. */ if (*((uint32_t *) cp) == 0) { return (BUDMIN); } /* * Check if the wmap or pmap word is half free. If so, the free buddy size * is BUDMIN-1. */ if (*((uint16_t *) cp) == 0 || *((uint16_t *) cp + 1) == 0) { return (BUDMIN - 1); } /* * Not all free or half free. Determine the free buddy size through table * lookup using quarters of the wmap or pmap word. */ return (MAX(MAX(budtab[*cp], budtab[*(cp + 1)]), MAX(budtab[*(cp + 2)], budtab[*(cp + 3)]))); } /* * NAME: ujfs_adjtree * * FUNCTION: Calculate the tree of a dmap or dmapctl. * * PRE CONDITIONS: * * POST CONDITIONS: * * PARAMETERS: * cp - Pointer to the top of the tree * l2leaves- Number of leaf nodes as a power of 2 * l2min - Number of disk blocks actually covered by a leaf of the tree; * specified as a power of 2 * * NOTES: This routine first works against the leaves of the tree to calculate * the maximum free string for leaf buddys. Once this is accomplished the * values of the leaf nodes are bubbled up the tree. * * DATA STRUCTURES: * * RETURNS: */ int8_t ujfs_adjtree(int8_t * treep, int32_t l2leaves, int32_t l2min) { int32_t nleaves, leaf_index, l2max, nextb, bsize, index; int32_t l2free, leaf, num_this_level, nextp; int8_t *cp0, *cp1, *cp = treep; /* * Determine the number of leaves of the tree and the * index of the first leaf. * Note: I don't know why the leaf_index calculation works, but it does. */ nleaves = (1 << l2leaves); leaf_index = (nleaves - 1) / 3; /* * Determine the maximum free string possible for the leaves. */ l2max = l2min + l2leaves; /* * Try to combine buddies starting with a buddy size of 1 (i.e. two leaves). * At a buddy size of 1 two buddy leaves can be combined if both buddies * have a maximum free of l2min; the combination will result in the * left-most buddy leaf having a maximum free of l2min+1. After processing * all buddies for a certain size, process buddies at the next higher buddy * size (i.e. current size * 2) and the next maximum free * (current free + 1). This continues until the maximum possible buddy * combination yields maximum free. */ for (l2free = l2min, bsize = 1; l2free < l2max; l2free++, bsize = nextb) { nextb = bsize << 1; for (cp0 = cp + leaf_index, index = 0; index < nleaves; index += nextb, cp0 += nextb) { if (*cp0 == l2free && *(cp0 + bsize) == l2free) { *cp0 = l2free + 1; *(cp0 + bsize) = -1; } } } /* * With the leaves reflecting maximum free values bubble this information up * the tree. Starting at the leaf node level, the four nodes described by * the higher level parent node are compared for a maximum free and this * maximum becomes the value of the parent node. All lower level nodes are * processed in this fashion then we move up to the next level (parent * becomes a lower level node) and continue the process for that level. */ for (leaf = leaf_index, num_this_level = nleaves >> 2; num_this_level > 0; num_this_level >>= 2, leaf = nextp) { nextp = (leaf - 1) >> 2; /* * Process all lower level nodes at this level setting the value of the * parent node as the maximum of the four lower level nodes. */ for (cp0 = cp + leaf, cp1 = cp + nextp, index = 0; index < num_this_level; index++, cp0 += 4, cp1++) { *cp1 = TREEMAX(cp0); } } return (*cp); } /* * NAME: ujfs_complete_dmap * * FUNCTION: Fill in rest of dmap fields from wmap/pmap already initialized. * * PARAMETERS: * dmap_page - dmap to complete * blkno - starting block number for this dmap * treemax - will be filled in with max free for this dmap * * RETURNS: NONE */ void ujfs_complete_dmap(struct dmap *dmap_page, int64_t blkno, int8_t *treemax) { struct dmaptree *tp; int8_t *cp; int32_t index; dmap_page->start = blkno; tp = &dmap_page->tree; tp->height = 4; tp->leafidx = LEAFIND; tp->nleafs = LPERDMAP; tp->l2nleafs = L2LPERDMAP; tp->budmin = BUDMIN; /* * Pick up the pointer to the first leaf of the dmap tree. */ cp = tp->stree + tp->leafidx; /* * Set the initial state for the leaves of the dmap tree. They will reflect * the current allocation state of the wmap words. */ for (index = 0; index < LPERDMAP; index++) { *(cp + index) = ujfs_maxbuddy((unsigned char *) &dmap_page->wmap[index]); } /* * With the leaves of the dmap initialized adjust (initialize) the dmap's * tree. */ *treemax = ujfs_adjtree(tp->stree, L2LPERDMAP, BUDMIN); } /* * NAME: ujfs_idmap_page * * FUNCTION: Initialize one dmap page * * POST CONDITIONS: Blocks which don't actually exist in the aggregate will be * marked as allocated in the dmap page. The total number of blocks will * only account for the actually existing blocks. * * PARAMETERS: * map_page - pointer to page of map * nblocks - number of blocks this page * * RETURNS: NONE */ void ujfs_idmap_page(struct dmap *map_page, uint32_t nblocks) { uint32_t index, nwords, bit; map_page->nblocks = map_page->nfree = nblocks; /* * Partial dmap page? * If there are not enough blocks to cover an entire dmap page the ones * which represent blocks which don't exist will be marked as allocated. * * nwords will indicate the first word beyond the end of existing blocks * bit will indicate if this block does not fall on a 32-bit boundary */ nwords = nblocks / DBWORD; bit = nblocks % DBWORD; if (bit) { /* * Need to mark a partial word allocated */ map_page->wmap[nwords] = map_page->pmap[nwords] = ONES >> bit; nwords++; } /* * Set the rest of the words in the page to ONES. */ for (index = nwords; index < LPERDMAP; index++) { map_page->pmap[index] = map_page->wmap[index] = ONES; } } /* * NAME: ujfs_getagl2size * * FUNCTION: Determine log2(allocation group size) based on size of aggregate * * PARAMETERS: * size - Number of blocks in aggregate * aggr_block_size - Aggregate block size * * RETURNS: log2(allocation group size) in aggregate blocks */ int32_t ujfs_getagl2size(int64_t size, int32_t aggr_block_size) { int64_t sz; int64_t m; int32_t l2sz; if (size < BPERDMAP * MAXAG) { return (L2BPERDMAP); } m = ((uint64_t) 1 << (64 - 1)); for (l2sz = 64; l2sz >= 0; l2sz--, m >>= 1) { if (m & size) { break; } } sz = (int64_t) 1 << l2sz; if (sz < size) { l2sz += 1; } return (l2sz - L2MAXAG); } jfsutils-1.1.15.orig/libfs/diskmap.h0000644000000000000000000000225410441103234014162 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef H_DISKMAP #define H_DISKMAP #include /* int8_t, int32_t, int64_t, uint32_t */ struct dmap; int8_t ujfs_maxbuddy(unsigned char *); int8_t ujfs_adjtree(int8_t *, int32_t, int32_t); void ujfs_complete_dmap(struct dmap *, int64_t, int8_t *); void ujfs_idmap_page(struct dmap *, uint32_t); int32_t ujfs_getagl2size(int64_t, int32_t); #endif /* H_DISKMAP */ jfsutils-1.1.15.orig/libfs/fsck_base.h0000644000000000000000000000332310340701413014451 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _FSCK_BASE_H_ #define _FSCK_BASE_H_ /* --------- Defines shared among the fsck modules --------- */ #define ISDIR(m) (((m)&(IFMT)) == (IFDIR)) #define ISREG(m) (((m)&(IFMT)) == (IFREG)) #define ISLNK(m) (((m)&(IFMT)) == (IFLNK)) #define ISBLK(m) (((m)&(IFMT)) == (IFBLK)) #define ISCHR(m) (((m)&(IFMT)) == (IFCHR)) #define ISFIFO(m) (((m)&(IFMT)) == (IFFIFO)) #define ISSOCK(m) (((m)&(IFMT)) == (IFSOCK)) /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * some useful constants */ #define BYTESPERPAGE 4096 #define log2BYTESPERPAGE 12 #define BITSPERPAGE (4096*8) #define log2BITSPERPAGE 15 #define BITSPERDWORD 32 #define log2BITSPERDWORD 5 #define BYTESPERDWORD 4 #define log2BYTESPERDWORD 2 #define BITSPERBYTE 8 #define log2BITSPERBYTE 3 #define MEMSEGSIZE (64*1024) #define log2BYTESPERKBYTE 10 #endif jfsutils-1.1.15.orig/libfs/fsck_message.h0000644000000000000000000006404610441103234015173 0ustar #ifndef H_FSCK_MESSAGE #define H_FSCK_MESSAGE #include extern int msg_lvl; extern int dbg_output; #define fsck_ref_msg(msg_num) msg_defs[msg_num].msg_txt extern int v_fsck_send_msg(int, const char *, int, ...); extern int v_send_msg(int, const char *, int, ...); #define fsck_send_msg(msg_num, arg...) \ v_fsck_send_msg(msg_num, __FILE__ , __LINE__ , ## arg) #define send_msg(msg_num, arg...) \ v_send_msg(msg_num, __FILE__ , __LINE__ , ## arg) // Define the maximum number of messages #define fsck_highest_msgid_defined 599 // Definition of constants for message flags #define avail_116 116 #define avail_304 304 #define avail_305 305 #define avail_306 306 #define avail_307 307 #define avail_308 308 #define avail_311 311 #define avail_373 373 #define avail_374 374 #define avail_375 375 #define avail_376 376 #define avail_377 377 #define avail_378 378 #define avail_379 379 #define avail_380 380 #define avail_381 381 #define avail_382 382 #define avail_383 383 #define avail_for_debug_only_590 590 #define avail_for_debug_only_591 591 #define avail_for_debug_only_592 592 #define avail_for_debug_only_593 593 #define avail_for_debug_only_594 594 #define avail_for_debug_only_595 595 #define avail_for_debug_only_596 596 #define avail_for_debug_only_597 597 #define avail_for_debug_only_598 598 #define avail_for_debug_only_599 599 // symbolic constants for text message inserts #define fsck_block_special 384 #define fsck_ACL 385 #define fsck_aggr_inode 385 #define fsck_aggregate 385 #define fsck_directory 386 #define fsck_dirpfx 386 #define fsck_dmap 387 #define fsck_dotext 399 #define fsck_EA 388 #define fsck_FIFO 389 #define fsck_file 389 #define fsck_fileset 389 #define fsck_fset_inode 389 #define fsck_inoext 390 #define fsck_inopfx 390 #define fsck_L0 391 #define fsck_L1 392 #define fsck_L2 393 #define fsck_metadata 394 #define fsck_metaIAG 390 #define fsck_objcontents 395 #define fsck_char_special 395 #define fsck_primary 396 #define fsck_secondary 397 #define fsck_SOCK 397 #define fsck_symbolic_link 398 // symbolic constants for message text #define fsck_MSGOK 0 #define fsck_AGGCLN 186 #define fsck_AGGCLNNOTDRTY 187 #define fsck_AGGDRTY 188 #define fsck_AGGDRTYNOTCLN 189 #define fsck_AGGMRKDCLN 190 #define fsck_AGGMRKDDRTY 191 #define fsck_ALLFXD 1 #define fsck_ALLOCHIGHMEM 422 #define fsck_ALLOCHIGHMEMRSLT 423 #define fsck_BAD_COOKIE 286 #define fsck_BAD_ENTRY 289 #define fsck_BADAGFELIST 69 #define fsck_BADAGFELIST1 196 #define fsck_BADAGFILIST 197 #define fsck_BADAGFILIST1 198 #define fsck_BADBLKALLOC 229 #define fsck_BADBLKALLOCCTL 230 #define fsck_BADBLKCTTTL 3 #define fsck_BADBLKNO 4 #define fsck_BADBMAPCAGFCL 256 #define fsck_BADBMAPCOTH 257 #define fsck_BADBMAPSLFV 225 #define fsck_BADBMAPSLNV 226 #define fsck_BADBMAPSOTHER 227 #define fsck_BADBSBLCHN 5 #define fsck_BADDINOFREELIST1 161 #define fsck_BADDINOFREELIST2 204 #define fsck_BADDINOFREELIST3 205 #define fsck_BADDINOFREELIST4 203 #define fsck_BADDINONODESIZ 201 #define fsck_BADDINOODDNODESIZ 202 #define fsck_BADDIRENTRY 200 #define fsck_BADDMAPPMAPS 228 #define fsck_BADFSBLCHN 6 #define fsck_BADIAG 123 #define fsck_BADIAGAG 199 #define fsck_BADIAGAGCRCTD 223 #define fsck_BADIAGAGSTRT 206 #define fsck_BADIAGAGSTRTCRCTD 224 #define fsck_BADIAGFIES 207 #define fsck_BADIAGFIS 208 #define fsck_BADIAGFLIST 209 #define fsck_BADIAGFL1 210 #define fsck_BADIAGIAGNUM 211 #define fsck_BADIAGNFEXT 212 #define fsck_BADIAGNFINO 213 #define fsck_BADIAGPMAP 214 #define fsck_BADIAM 215 #define fsck_BADIAMA 295 #define fsck_BADIAMAGNBI 96 #define fsck_BADIAMAGNFI 97 #define fsck_BADIAMBPIE 216 #define fsck_BADIAMCTL 217 #define fsck_BADIAMCTLA 294 #define fsck_BADIAMIAGPXDL 112 #define fsck_BADIAMIAGPXDU 124 #define fsck_BADIAML2BPIE 218 #define fsck_BADIAMNBI 219 #define fsck_BADIAMNFI 220 #define fsck_BADIAMNXTIAG 221 #define fsck_BADINOCLAIMSDUPSD 271 #define fsck_BADINOCLAIMSDUPSF 141 #define fsck_BADINOCLAIMSDUPSO 272 #define fsck_BADINODATAFORMAT 142 #define fsck_BADINODATAFORMATD 278 #define fsck_BADINODATAFORMATO 280 #define fsck_BADINODXDFLDD 8 #define fsck_BADINODXDFLDL 368 #define fsck_BADINODXDFLDO 369 #define fsck_BADINOFORMAT 143 #define fsck_BADINOFORMATD 279 #define fsck_BADINOFORMATO 281 #define fsck_BADINOFRONTGAP 194 #define fsck_BADINOINTERNGAP 195 #define fsck_BADINOLKCT 9 #define fsck_BADINOMTNODE 192 #define fsck_BADINONODESELF 357 #define fsck_BADINOODDINTRNEXT 193 #define fsck_BADINOOTHR 54 #define fsck_BADINOREF 10 #define fsck_BADINOSTAMP 179 #define fsck_BADINOTYP 7 #define fsck_BADKEYS 13 #define fsck_BADLINKCTS 95 #define fsck_BADMETAINOF 49 #define fsck_BADMETAINOP 290 #define fsck_BADMETAINOS 291 #define fsck_BADSBAGSIZ 15 #define fsck_BADSBBLSIZ 16 #define fsck_BADSBFJLA 260 #define fsck_BADSBFJLL 261 #define fsck_BADSBFSSIZ 17 #define fsck_BADSBFWSL 81 #define fsck_BADSBFWSL1 259 #define fsck_BADSBFWSA 82 #define fsck_BADSBMGC 21 #define fsck_BADSBOTHR 14 #define fsck_BADSBVRSN 22 #define fsck_BDSBBTHCRRPT 18 #define fsck_BDSBNWRTACC 19 #define fsck_BLSIZLTLVBLSIZ 25 #define fsck_BMAPBADHT 231 #define fsck_BMAPBADL2NLF 232 #define fsck_BMAPBADLFI 233 #define fsck_BMAPBADLFV 234 #define fsck_BMAPBADLNV 235 #define fsck_BMAPBADBMN 236 #define fsck_BMAPBADNLF 237 #define fsck_BMAPCAGNF 238 #define fsck_BMAPCASB 239 #define fsck_BMAPCBMXB 23 #define fsck_BMAPCBPAG 240 #define fsck_BMAPCDMCLAG 241 #define fsck_BMAPCDMCLH 242 #define fsck_BMAPCDMCLW 243 #define fsck_BMAPCDMCSTI 258 #define fsck_BMAPCL2BPAG 244 #define fsck_BMAPCL2BPP 245 #define fsck_BMAPCMAAG 246 #define fsck_BMAPCMXLVL 247 #define fsck_BMAPCNAG 248 #define fsck_BMAPCNF 24 #define fsck_BMAPCPAG 249 #define fsck_BOOTSECFXD 12 #define fsck_CANTCHKEA 84 #define fsck_CANTCONTINUE 326 #define fsck_CANTINITSVCLOG 327 #define fsck_CANTREADAITP 324 #define fsck_CANTREADAITS 293 #define fsck_CANTREADAITEXT1 163 #define fsck_CANTREADEAITEXT1 162 #define fsck_CANTRECONINSUFSTG 359 #define fsck_CANTRECOVERINOS 136 #define fsck_CANTREPAIRAIS 37 #define fsck_CANTREPAIRINO 144 #define fsck_CHKDSKFSSYNCHRC 341 #define fsck_CHKDSKSYSALLOC 336 #define fsck_CHKDSKSYSCALLRC 338 #define fsck_CHKDSKSYSOPENRC 337 #define fsck_CHKLOGINVALRCD 41 #define fsck_CHKLOGNEW 31 #define fsck_CHKLOGNOVOL 328 #define fsck_CHKLOGOLD 35 #define fsck_CLRBBACTIVITY 348 #define fsck_CLRBBLKSRC 353 #define fsck_CLRBBLVMLISTDATA 349 #define fsck_CLRBBLVMNUMLISTS 350 #define fsck_CLRBBOPENFAILED 356 #define fsck_CLRBBRANGE 351 #define fsck_CLRBBRESULTS 352 #define fsck_CNTRDDEVCHAR 121 #define fsck_CNTRESUPB 312 #define fsck_CNTRESUPP 40 #define fsck_CNTRESUPS 297 #define fsck_CNTWRTBS 93 #define fsck_CNTWRTBSMBR 28 #define fsck_CNTWRTSUPP 44 #define fsck_CNTWRTSUPS 156 #define fsck_DASDLIMITSPRIMED 586 #define fsck_DASDUSEDPRIMED 587 #define fsck_DEFAULTVOL 27 #define fsck_DEVBEGINFMTRC 339 #define fsck_DEVCLOSERC 132 #define fsck_DEVGETCHARRC 52 #define fsck_DEVLOCKRC 77 #define fsck_DEVOPENRDRC 83 #define fsck_DEVOPENRDWRRC 134 #define fsck_DEVOPENRDWRSRC 355 #define fsck_DEVREDETERMRC 90 #define fsck_DEVUNLOCKRC 129 #define fsck_DI_TABLE 298 #define fsck_DI_TABLE_FXD 299 #define fsck_DIRWHDLKS 46 #define fsck_DMAPBADNBLK 251 #define fsck_DMAPBADNFREE 252 #define fsck_DMAPBADSTRT 253 #define fsck_DOSEXECPGMRC 354 #define fsck_DRIVEID 145 #define fsck_DRIVETYPE 146 #define fsck_DUPBLKMDREF 160 #define fsck_DUPBLKMDREFS 159 #define fsck_DUPBLKREF 48 #define fsck_DUPBLKREFS 62 #define fsck_EAFORMATBAD 113 #define fsck_ERRONAGG 45 #define fsck_ERRONAITRD 110 #define fsck_ERRONLOG 11 #define fsck_ERRONWSP 50 #define fsck_ERRORSDETECTED 171 #define fsck_ERRORSINAITP 325 #define fsck_ERRORSINAITS 296 #define fsck_EXHDYNSTG 51 #define fsck_EXHFILSYSSTG 364 #define fsck_FSMNTD 53 #define fsck_FSSMMRY1 55 #define fsck_FSSMMRY2 56 #define fsck_FSSMMRY3 57 #define fsck_FSSMMRY4 58 #define fsck_FSSMMRY5 59 #define fsck_FSSMMRY6 60 #define fsck_FSSMMRY7 63 #define fsck_FSSMMRY8 64 #define fsck_FSSMMRY9 61 #define fsck_HEARTBEAT0 262 #define fsck_HEARTBEAT1 263 #define fsck_HEARTBEAT2 264 #define fsck_HEARTBEAT3 265 #define fsck_HEARTBEAT4 266 #define fsck_HEARTBEAT5 267 #define fsck_HEARTBEAT6 268 #define fsck_HEARTBEAT7 269 #define fsck_HEARTBEAT8 270 #define fsck_ILLINOREF 65 #define fsck_INOCANTNAME 33 #define fsck_INCDASDUSEDCRCT 274 #define fsck_INCINOREF 71 #define fsck_INCINOREFCRCT 72 #define fsck_INCONSIST2NDRY 29 #define fsck_INCONSIST2NDRY1 30 #define fsck_INOACL 360 #define fsck_INOACLCLRD 362 #define fsck_INOBADREF 34 #define fsck_INOCLRD 73 #define fsck_INOCNTGETPATH 67 #define fsck_INOEA 68 #define fsck_INOEACLRD 74 #define fsck_INOINLINECONFLICT 158 #define fsck_INOINLSFND 309 #define fsck_INOINLSFNF 75 #define fsck_INOLKCTFXD 76 #define fsck_INOMINOR 365 #define fsck_INOMINORFXD 366 #define fsck_INONOPATHS 78 #define fsck_INOPATHBAD 358 #define fsck_INOPATHCRCT 167 #define fsck_INOPATHOK 79 #define fsck_INOREFRMV 80 #define fsck_INOSINLSFND 173 #define fsck_INOSINLSFNDS 275 #define fsck_INOSINLSFNF 276 #define fsck_INOSINLSFNFS 277 #define fsck_INTERNALERROR 347 #define fsck_LOGFORMATFAIL 119 #define fsck_LOGFORMATRC 120 #define fsck_LOGREDOFAIL 85 #define fsck_LOGREDORC 86 #define fsck_LOGSPECINVALID 47 #define fsck_LSFNCNTCRE 32 #define fsck_LSFNNOTDIR 87 #define fsck_LSFNNOTFOUND 94 #define fsck_LVMFOUNDBDBLKS 342 #define fsck_LVMFSNOWAVAIL 345 #define fsck_LVMGETBBLKINFORC 343 #define fsck_LVMGETTBLSIZERC 344 #define fsck_LVMTRNSBBLKSTOJFS 346 #define fsck_MNCNTRCNCTINOD 310 #define fsck_MNCNTRCNCTINOF 70 #define fsck_MNCNTRCNCTINOSD 174 #define fsck_MNCNTRCNCTINOSDS 301 #define fsck_MNCNTRCNCTINOSF 302 #define fsck_MNCNTRCNCTINOSFS 303 #define fsck_MNTFSYS2 88 #define fsck_MODIFIED 89 #define fsck_MRKSBDONE 91 #define fsck_MSSNGBLKS 92 #define fsck_NOTJFSINFSTAB 285 #define fsck_PAGE_NOT_FOUND 287 #define fsck_PARMAUTOCHK 333 #define fsck_PARMCLRBDBLKLST 340 #define fsck_PARMDEBUG 335 #define fsck_PARMFIXLVL 330 #define fsck_PARMIFDRTY 331 #define fsck_PARMOMITLOGREDO 284 #define fsck_PARMPMCHK 334 #define fsck_PARMVERBOSE 332 #define fsck_PHASE0 99 #define fsck_PHASE1 100 #define fsck_PHASE2 101 #define fsck_PHASE3 102 #define fsck_PHASE4 103 #define fsck_PHASE5 104 #define fsck_PHASE6 105 #define fsck_PHASE7R 106 #define fsck_PHASE7V 282 #define fsck_PHASE8R 107 #define fsck_PHASE8V 283 #define fsck_PHASE9 108 #define fsck_PMAPSBOFF 254 #define fsck_PMAPSBON 255 #define fsck_PRMMUTEXCLLEVELS 115 #define fsck_PRMUNRECOPTION 117 #define fsck_PRMUNSUPPENUM 118 #define fsck_PRMBADDEVICE 371 #define fsck_PRMNODEVICE 372 #define fsck_READ_FAILED 288 #define fsck_READONLY 370 #define fsck_REPAIRSINPROGRESS 114 #define fsck_RIBADDATFMT 2 #define fsck_RIBADFMT 26 #define fsck_RIBADTREE 38 #define fsck_RICRETREE 39 #define fsck_RICRRCTDREF 166 #define fsck_RIINCINOREF 172 #define fsck_RINOTDIR 125 #define fsck_RIUNALLOC 126 #define fsck_RODIRSWHLKS 153 #define fsck_RODIRWHLKS 168 #define fsck_ROINCINOREF 169 #define fsck_ROINCINOREFS 154 #define fsck_ROOTALLOC 127 #define fsck_ROOTNOWDIR 128 #define fsck_ROUALINOREF 170 #define fsck_ROUALINOREFS 155 #define fsck_ROUNCONNIO 175 #define fsck_ROUNCONNIOS 180 #define fsck_SBBADP 122 #define fsck_SBBADS 292 #define fsck_SBOKP 130 #define fsck_SBOKS 148 #define fsck_SEPARATOR 43 #define fsck_SESSEND 131 #define fsck_SESSPRMDFLT 133 #define fsck_SESSSTART 42 #define fsck_SPARSEFILSYS 273 #define fsck_STDSUMMARY1 313 #define fsck_STDSUMMARY2 314 #define fsck_STDSUMMARY3 315 #define fsck_STDSUMMARY4 316 #define fsck_STDSUMMARY4A 363 #define fsck_STDSUMMARY5 317 #define fsck_STDSUMMARY6 318 #define fsck_UALINOREF 135 #define fsck_URCVCLOSE 165 #define fsck_URCVREAD 98 #define fsck_URCVUNLCK 164 #define fsck_URCVWRT 137 #define fsck_WILLCLEARACL 361 #define fsck_WILLCLEAREA 111 #define fsck_WILLFIX_DI_TABLE 300 #define fsck_WILLFIXDIRWHDLKS 150 #define fsck_WILLFIXINCREF 151 #define fsck_WILLFIXINOMINOR 367 #define fsck_WILLFIXLINKCTS 157 #define fsck_WILLFIXRIBADDATFMT 138 #define fsck_WILLFIXRIBADFMT 139 #define fsck_WILLFIXRODIRSWHLKS 183 #define fsck_WILLFIXROINCINOREFS 184 #define fsck_WILLFIXROUALINOREFS 181 #define fsck_WILLFIXROUNCONNIOS 182 #define fsck_WILLRELEASEINO 147 #define fsck_WILLRELEASEINOS 140 #define fsck_WILLRMVBADENTRY 109 #define fsck_WILLRMVBADREF 36 #define fsck_WRSUP 149 #define fsck_XCHKLOGBADDEVICE 321 #define fsck_XCHKLOGBADPARM 20 #define fsck_XCHKDMPBADFNAME 323 #define fsck_XCHKDMPBADFORMAT 320 #define fsck_XCHKDMPMTORBADREAD 319 #define fsck_XCHKDMPOPNFAIL 185 #define fsck_XCHKDMPUSAGE 222 #define fsck_XCHKLOGBADFNAME 322 #define fsck_XCHKLOGNEW 176 #define fsck_XCHKLOGNOVOL 329 #define fsck_XCHKLOGOLD 177 #define fsck_XCHKLOGOPNFAIL 178 #define fsck_XCHKLOGSBOK 250 #define fsck_XCHKLOGUSAGE 66 #define fsck_XTRABLKS 152 #define lrdo_ALLOC4BMAP 424 #define lrdo_ALLOC4BMAPFAIL 431 #define lrdo_ALLOC4DOBLK 426 #define lrdo_ALLOC4DOBLKFAIL 433 #define lrdo_ALLOC4EXTDTPG 430 #define lrdo_ALLOC4EXTDTPGFAIL 437 #define lrdo_ALLOC4IMAP 425 #define lrdo_ALLOC4IMAPFAIL 432 #define lrdo_ALLOC4NODOFL 429 #define lrdo_ALLOC4NODOFLFAIL 436 #define lrdo_ALLOC4NOREDOFL 427 #define lrdo_ALLOC4NOREDOFLFAIL 434 #define lrdo_ALLOC4REDOPG 428 #define lrdo_ALLOC4REDOPGFAIL 435 #define lrdo_ALREADYREDONE 400 #define lrdo_BADCOMMIT 450 #define lrdo_BADDISKBLKNUM 484 #define lrdo_BADINODENUM 485 #define lrdo_BADNOREDOPAGE 454 #define lrdo_BADNOREDOINOEXT 455 #define lrdo_BADLOGSER 489 #define lrdo_BADMOUNT 451 #define lrdo_BADREDOPAGE 453 #define lrdo_BADUPDATEMAP 456 #define lrdo_BADUPDMAPREC 488 #define lrdo_BRDBADBLOCK 545 #define lrdo_BRDREADBLKFAIL 546 #define lrdo_BUFFLUSHFAIL 475 #define lrdo_CANTINITMAPS 483 #define lrdo_CANTREADBLK 486 #define lrdo_CANTREADFSSUPER 463 #define lrdo_CANTREADLOGSUP 444 #define lrdo_CANTUPDLOGSUP 445 #define lrdo_CANTWRITELOGSUPER 462 #define lrdo_DAFTMRKBMPFAILED 549 #define lrdo_DAFTUPDPGFAILED 548 #define lrdo_DEDPBREADFAILED 550 #define lrdo_DEVOPNREADERROR 452 #define lrdo_DNRIFNDNOREDORECFAIL 556 #define lrdo_DNRPFNDDTPGPGREDOFAIL 552 #define lrdo_DNRPFNDDTRTPGREDOFAIL 551 #define lrdo_DNRPFNDXTPGPGREDOFAIL 554 #define lrdo_DNRPFNDXTRTPGREDOFAIL 553 #define lrdo_DNRPUNKNOWNTYPE 555 #define lrdo_DPRFBADSLOTNXTIDX 559 #define lrdo_DPRFBADSTBLENTRY 558 #define lrdo_DRRFBADSLOTNXTIDX 561 #define lrdo_DRRFBADSTBLENTRY 560 #define lrdo_DUMPUNKNOWNTYPE 557 #define lrdo_ERRORCANTCONTIN 459 #define lrdo_ERRORCANTUPDMAPS 460 #define lrdo_ERRORCANTUPDFSSUPER 461 #define lrdo_ERRORNEEDREFORMAT 458 #define lrdo_ERRORONVOL 481 #define lrdo_EXTFSREADBLKFAIL1 497 #define lrdo_EXTFSREADBLKFAIL2 498 #define lrdo_EXTFSREADBLKFAIL3 502 #define lrdo_EXTFSREADBLKFAIL4 503 #define lrdo_EXTFSREADBLKFAIL5 505 #define lrdo_EXTFSREADBLKMAPINOFAIL 496 #define lrdo_EXTFSREADFSSUPERFAIL 495 #define lrdo_EXTFSREADLOGSUPFAIL 508 #define lrdo_EXTFSINITLOGREDOFAIL 504 #define lrdo_EXTFSWRITEBLKFAIL1 499 #define lrdo_EXTFSWRITEBLKFAIL2 500 #define lrdo_EXTFSWRITEBLKFAIL3 501 #define lrdo_EXTFSWRITEBLKFAIL4 506 #define lrdo_EXTFSWRITEFSSUPERFAIL 507 #define lrdo_EXTFSWRITELOGSUPFAIL 509 #define lrdo_FEOLPGV1FAIL 574 #define lrdo_FEOLPGV2FAIL 575 #define lrdo_FEOLPGV3FAIL 576 #define lrdo_FEOLPGV4FAIL 577 #define lrdo_FEOLPGV4AFAIL 578 #define lrdo_FINDLOGENDFAIL 490 #define lrdo_FSSUPERBADLOGLOC 466 #define lrdo_FSSUPERBADLOGSER 467 #define lrdo_FSSUPERBADMAGIC 464 #define lrdo_FSSUPERBADVERS 465 #define lrdo_INITFAILED 410 #define lrdo_INITMAPSFAIL 468 #define lrdo_IOERRONLOG 493 #define lrdo_IOERRREADINGBLK 487 #define lrdo_LOGEND 401 #define lrdo_LOGENDBAD1 409 #define lrdo_LOGENDBAD2 414 #define lrdo_LOGNOTINLINE1 477 #define lrdo_LOGNOTINLINE2 479 #define lrdo_LOGOPEN 480 #define lrdo_LOGREADFAIL 491 #define lrdo_LOGSUPBADBLKSZ 411 #define lrdo_LOGSUPBADL2BLKSZ 412 #define lrdo_LOGSUPBADLOGSZ 413 #define lrdo_LOGSUPBADMGC 407 #define lrdo_LOGSUPBADVER 408 #define lrdo_LOGWRAP 494 #define lrdo_LOGWRAPPED 449 #define lrdo_LRLOGWRAP 581 #define lrdo_LRREADFAIL 582 #define lrdo_LRMWFAIL1 583 #define lrdo_LRMWFAIL2 584 #define lrdo_LRMWFAIL3 588 #define lrdo_LOGINUSE 589 #define lrdo_MBMPBLKOUTRANGE 562 #define lrdo_MOUNTRECORD 421 #define lrdo_MWREADFAIL 585 #define lrdo_NEXTADDRINVALID 446 #define lrdo_NEXTADDROUTRANGE 447 #define lrdo_NOTAFSDEV 478 #define lrdo_NOTAFSDEVNUM 476 #define lrdo_NEXTADDRSAME 448 #define lrdo_OPENFAILED 482 #define lrdo_PVGETPGFAIL 579 #define lrdo_RBLDGDMAPERROR 538 #define lrdo_RBLDGIMAPERROR1 535 #define lrdo_RBLDGIMAPERROR2 547 #define lrdo_RBMPREADDATFAIL 515 #define lrdo_RBMPREADNXTLFFAIL 516 #define lrdo_RBMPREADXTFAIL 514 #define lrdo_READBMAPFAIL 511 #define lrdo_READBMAPINOFAIL 510 #define lrdo_READFS2NDSBFAIL 472 #define lrdo_READFSPRIMSBFAIL 471 #define lrdo_READFSSUPERFAIL 469 #define lrdo_READIMAPFAIL 513 #define lrdo_READIMAPINOFAIL 512 #define lrdo_REXTNDBEGIN 402 #define lrdo_REXTNDDONE 403 #define lrdo_REXTNDFAIL 406 #define lrdo_REXTNDTOPOST 405 #define lrdo_REXTNDTOPRE 404 #define lrdo_RIMPREADCTLFAIL 518 #define lrdo_RIMPREADDATFAIL 520 #define lrdo_RIMPREADNXTLFFAIL 519 #define lrdo_RIMPREADXTFAIL 517 #define lrdo_RPTNUMDOBLK 418 #define lrdo_RPTNUMLOGREC 417 #define lrdo_RPTNUMNODOBLK 419 #define lrdo_RPTSYNCADDR 416 #define lrdo_RPTSYNCNUM 415 #define lrdo_RXTREADLFFAIL 544 #define lrdo_SLPWRITEFAIL 580 #define lrdo_SYNCRECORD 420 #define lrdo_UMPREADBMAPINOFAIL 523 #define lrdo_UMPREADIMAPINOFAIL 521 #define lrdo_UMPWRITEIMAPCTLFAIL 522 #define lrdo_UMPWRITEBMAPCTLFAIL 524 #define lrdo_UNKNOWNTYPE 457 #define lrdo_UNRECOGTYPE 492 #define lrdo_UPDMPBADLFIDX 543 #define lrdo_UPPGBADINODESEGOFFSET 564 #define lrdo_UPPGBREADFAIL1 565 #define lrdo_UPPGBREADFAIL2 566 #define lrdo_UPPGBREADFAIL3 567 #define lrdo_UPPGBREADFAIL4 568 #define lrdo_UPPGDTRTRFLFAIL 571 #define lrdo_UPPGDTPGRFLFAIL 572 #define lrdo_UPPGFNDPGREDOFAIL 563 #define lrdo_UPPGMBMPFAIL 570 #define lrdo_UPPGMIMPFAIL 569 #define lrdo_UPPGSEDPFAIL 573 #define lrdo_USINGBMAPALLOC4DOBLK 440 #define lrdo_USINGBMAPALLOC4EDPG 443 #define lrdo_USINGBMAPALLOC4IMAP 438 #define lrdo_USINGBMAPALLOC4NDFL 442 #define lrdo_USINGBMAPALLOC4NRFL 439 #define lrdo_USINGBMAPALLOC4RDPG 441 #define lrdo_WRBMPBADLFIDX0 537 #define lrdo_WRBMPBADMAPSIZE 536 #define lrdo_WRBMPBADTOTPG 542 #define lrdo_WRBMPBLKWRITEFAIL 540 #define lrdo_WRBMPDONE 532 #define lrdo_WRBMPNOTRBLDGBMAP 534 #define lrdo_WRBMPREADLFFAIL 541 #define lrdo_WRBMPRXTFAIL 539 #define lrdo_WRBMPSTART 533 #define lrdo_WRIMPBADNPAGES 529 #define lrdo_WRIMPBLKWRITEFAIL 527 #define lrdo_WRIMPDONE 530 #define lrdo_WRIMPNOTRBLDGIMAP 525 #define lrdo_WRIMPREADLFFAIL 528 #define lrdo_WRIMPRXTFAIL 526 #define lrdo_WRIMPSTART 531 #define lrdo_WRITEFS2NDSBFAIL 474 #define lrdo_WRITEFSPRIMSBFAIL 473 #define lrdo_WRITEFSSUPERFAIL 470 // message levels #define fsck_hrtbt 130 #define fsck_txtins 131 #define fsck_quiet 2 #define fsck_verbose 8 #define fsck_debug 32 // Data structure to define a message #define max_log_entry_length 512 #define max_msg_txt_length 300 #define max_msg_parm_length 30 #define max_msg_parms 10 struct fsck_message { int16_t msg_num; char msg_txt[max_msg_txt_length]; int16_t msg_level; }; // Array to hold the messages that are defined by the struct fsck_message extern struct fsck_message msg_defs[]; #endif jfsutils-1.1.15.orig/libfs/fsckcbbl.h0000644000000000000000000000537510340701413014313 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _H_JFS_FSCKCBBL #define _H_JFS_FSCKCBBL /* * This structure resides in the first page (aka the block map control page) * of the fsck in-aggregate workspace. JFS Clear Bad Block List utility * processing writes to this record, then fsck reads it and reports to the * caller. */ struct fsckcbbl_record { char eyecatcher[8]; char avail_1[4]; /* 4 */ int32_t cbbl_retcode; /* JFS Clear Bad Block List utility * return code */ int32_t fs_blksize; /* aggregate block size */ int32_t lv_blksize; /* device block size */ int32_t fs_lv_ratio; /* fs_blksize/lv_blksize */ int64_t fs_last_metablk; /* * last fs block we won't try to relocate * because it holds fixed-location metadata */ int64_t fs_first_wspblk; /* * first fs block we won't try to relocate * because it holds fsck workspace or the * inline journal log */ int32_t total_bad_blocks; /* count of bad blocks in LVM's list * at beginning of Bad Block List utility * processing */ int32_t resolved_blocks; /* count of bad blocks: * - for which the data has been relocated, * - which are now allocated to the bad block * inode, and * - which the LVM has been told to forget */ int32_t reloc_extents; /* count of relocated extents */ int64_t reloc_blocks; /* count of blocks in relocated extents */ int32_t LVM_lists; /* count of bad block lists maintained by LVM * according to the last query */ char bufptr_eyecatcher[8]; void *clrbblks_agg_recptr; /* addr of clrbblks aggregate record */ void *ImapInoPtr; /* addr of imap inode buffer */ void *ImapCtlPtr; /* addr of imap control page buffer */ void *ImapLeafPtr; /* addr of imap leaf page buffer */ void *iagPtr; /* addr of iag buffer */ void *InoExtPtr; /* addr of inode extent buffer */ char avail_2[28]; /* 28 */ }; /* total = 128 bytes */ #endif /* _H_JFS_FSCKCBBL */ jfsutils-1.1.15.orig/libfs/fscklog.h0000644000000000000000000000374710340701413014173 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef H_FSCKLOG #define H_FSCKLOG #include /*---------------------------------------------------------------------------- * * The in-aggregate fsck service log */ #define flog_eyecatcher_string "fscklog " struct fscklog_entry_hdr { int16_t entry_length; }; struct fscklog_error { int64_t err_offset; /* 8 -- start of attempted write */ int32_t bytes_written; /* 4 -- number actually written */ int32_t io_retcode; /* 4 -- return code from write */ }; /* total: 16 bytes */ /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * The first log message number for the JFS fsck Service Log * * */ #define JFSCHKLOG_FIRSTMSGNUM 10000 /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * The format of the log entry in the file created by * extracting the contents of the fsck service log * (stored in the fsck workspace) into a file. * * * N.B. The log entries are blocked such that no log entry crosses * an XCHKLOG_BUFSIZE byte boundary in the file. */ #define XCHKLOG_BUFSIZE 8192 #define jfs_chklog_eyecatcher "JFS chkdskSvcLog" struct chklog_entry_hdr { int16_t entry_length; }; #endif jfsutils-1.1.15.orig/libfs/fsckmsgdef.c0000644000000000000000000016670510772001331014657 0ustar #include #include "fsck_message.h" struct fsck_message msg_defs[fsck_highest_msgid_defined+1] = { /* 0 */ { fsck_MSGOK, "Operation was successful.", fsck_debug}, /* 1 */ { fsck_ALLFXD, "All observed inconsistencies have been repaired.", fsck_debug}, /* 2 */ { fsck_RIBADDATFMT, "Invalid data format detected in root directory.", fsck_quiet}, /* 3 */ { fsck_BADBLKCTTTL, "A combination of Minimum Free Blocks and Total Usable Blocks which is invalid for the filesystem size was detected in the superblock (%s).", fsck_debug}, /* 4 */ { fsck_BADBLKNO, "Invalid block number(s) (%s) detected for file system object %s%s%u.", fsck_debug}, /* 5 */ { fsck_BADBSBLCHN, "File system object %s%s%u has a corrupt backward sibling chain.", fsck_debug}, /* 6 */ { fsck_BADFSBLCHN, "File system object %s%s%u has a corrupt forward sibling chain.", fsck_debug}, /* 7 */ { fsck_BADINOTYP, "Inode %s%u has unrecognized type.", fsck_debug}, /* 8 */ { fsck_BADINODXDFLDD, "File system object %s%s%u has invalid descriptor (%s).", fsck_debug}, /* 9 */ { fsck_BADINOLKCT, "Inode %s%u has incorrect link count.", fsck_debug}, /* 10 */ { fsck_BADINOREF, "Directory inode %s%u refers to a nonexistent inode %s%s (entry %u).", fsck_debug}, /* 11 */ { fsck_ERRONLOG, "Error (%d,%d) writing to the fsck service log (%d,%lld,%ld,%ld). Continuing.", fsck_debug}, /* 12 */ { fsck_BOOTSECFXD, "The boot sector has been refreshed.", fsck_debug}, /* 13 */ { fsck_BADKEYS, "File system object %s%s%u has corrupt data (%d).", fsck_debug}, /* 14 */ { fsck_BADSBOTHR, "Invalid data (%s) detected in the superblock (%s).", fsck_debug}, /* 15 */ { fsck_BADSBAGSIZ, "Invalid allocation group size in the superblock (%s).", fsck_debug}, /* 16 */ { fsck_BADSBBLSIZ, "Invalid filesystem block size in the superblock (%s).", fsck_debug}, /* 17 */ { fsck_BADSBFSSIZ, "Invalid filesystem size in the superblock (%s).", fsck_debug}, /* 18 */ { fsck_BDSBBTHCRRPT, "Superblock is corrupt and cannot be repaired \nsince both primary and secondary copies are corrupt. \n\n CANNOT CONTINUE.", fsck_quiet}, /* 19 */ { fsck_BDSBNWRTACC, "Primary superblock is corrupt and cannot be repaired without write access. Continuing.", fsck_quiet}, /* 20 */ { fsck_XCHKLOGBADPARM, "XCHKLOG Unsupported XCHKLOG parameter: %s", fsck_debug}, /* 21 */ { fsck_BADSBMGC, "Invalid magic number in the superblock (%s).", fsck_debug}, /* 22 */ { fsck_BADSBVRSN, "Invalid version number in the superblock (%s).", fsck_debug}, /* 23 */ { fsck_BMAPCBMXB, "Incorrect maxbud AG detected in Block Map Control Page.", fsck_debug}, /* 24 */ { fsck_BMAPCNF, "Incorrect number of free blocks detected in Block Map Control Page.", fsck_debug}, /* 25 */ { fsck_BLSIZLTLVBLSIZ, "In superblock (%s) filesystem block size smaller than volume block size.", fsck_debug}, /* 26 */ { fsck_RIBADFMT, "Invalid format detected in Root directory.", fsck_quiet}, /* 27 */ { fsck_DEFAULTVOL, "Device parm defaulting to current volume: %s", fsck_debug}, /* 28 */ { fsck_CNTWRTBSMBR, "Unable to write to boot sector Master Boot Record. Continuing.", fsck_debug}, /* 29 */ { fsck_INCONSIST2NDRY, "Secondary file/directory allocation structure (%s) is not a correct redundant copy of primary structure.", fsck_quiet}, /* 30 */ { fsck_INCONSIST2NDRY1, "Unable to replicate primary file/directory allocation structure (%s) to secondary. FUTURE RECOVERY CAPABILITY IS COMPROMISED.", fsck_quiet}, /* 31 */ { fsck_CHKLOGNEW, "XCHKLOG fsck service log selected: MOST RECENT", fsck_debug}, /* 32 */ { fsck_LSFNCNTCRE, "MINOR: Cannot create directory lost+found in root directory. mkdir lost+found in the root directory then run fsck with the -f parameter to reconnect lost files and/or directories.", fsck_quiet}, /* 33 */ { fsck_INOCANTNAME, "Fileset object %s%s%u: No paths found.", fsck_quiet}, /* 34 */ { fsck_INOBADREF, "The path(s) refer to an unallocated file.", fsck_quiet}, /* 35 */ { fsck_CHKLOGOLD, "XCHKLOG fsck service log selected: PREVIOUS", fsck_debug}, /* 36 */ { fsck_WILLRMVBADREF, "The path(s) refer to an unallocated file. Will remove.", fsck_quiet}, /* 37 */ { fsck_CANTREPAIRAIS, "Unable to repair primary inode allocation structure (%s). Continuing.", fsck_debug}, /* 38 */ { fsck_RIBADTREE, "Root directory has a corrupt tree.", fsck_debug}, /* 39 */ { fsck_RICRETREE, "Initialized tree created for root directory.", fsck_debug}, /* 40 */ { fsck_CNTRESUPP, "Unable to read primary superblock.", fsck_debug}, /* 41 */ { fsck_CHKLOGINVALRCD, "fsck service log: INVALID LOG RECORD: SKIPPING ONE OR MORE LOG RECORDS.", fsck_debug}, /* 42 */ { fsck_SESSSTART, "processing started: %s", fsck_debug}, /* 43 */ { fsck_SEPARATOR, "\n**********************************************************", fsck_debug}, /* 44 */ { fsck_CNTWRTSUPP, "Unable to write primary superblock.", fsck_quiet}, /* 45 */ { fsck_ERRONAGG, "Fatal error (%d,%d) accessing the filesystem (%d,%lld,%d,%d).", fsck_debug}, /* 46 */ { fsck_DIRWHDLKS, "Multiple parent directories for directory %s%u.", fsck_quiet}, /* 47 */ { fsck_LOGSPECINVALID, "External journal log not supported.", fsck_debug}, /* 48 */ { fsck_DUPBLKREF, "Duplicate reference to %d block(s) beginning at offset %lld found in file system object %s%s%u.", fsck_debug}, /* 49 */ { fsck_BADMETAINOF, "File set metadata inode %s%u is corrupt.", fsck_debug}, /* 50 */ { fsck_ERRONWSP, "Fatal error (%d,%d) accessing the workspace (%d,%lld,%d,%d).", fsck_debug}, /* 51 */ { fsck_EXHDYNSTG, "Insufficient dynamic storage available for required workspace (%d,%d). CANNOT CONTINUE", fsck_quiet}, /* 52 */ { fsck_DEVGETCHARRC, "IOCtl(...DSK_GETDEVICEPARAMS...) returned rc = %s", fsck_debug}, /* 53 */ { fsck_FSMNTD, "Filesystem is currently mounted.", fsck_quiet}, /* 54 */ { fsck_BADINOOTHR, "Invalid data (%s) detected in file system object %s%s%u.", fsck_debug}, /* 55 */ { fsck_FSSMMRY1, "Block size in bytes: %d", fsck_quiet}, /* 56 */ { fsck_FSSMMRY2, "Filesystem size in blocks: %lld", fsck_quiet}, /* 57 */ { fsck_FSSMMRY3, "Filesystem Summary:", fsck_debug}, /* 58 */ { fsck_FSSMMRY4, "Blocks in use for inodes: %lld", fsck_debug}, /* 59 */ { fsck_FSSMMRY5, "Inode count: %lld", fsck_debug}, /* 60 */ { fsck_FSSMMRY6, "File count: %lld", fsck_debug}, /* 61 */ { fsck_FSSMMRY9, "Directory count: %lld", fsck_debug}, /* 62 */ { fsck_DUPBLKREFS, "Inode %s%u has references to cross linked blocks.", fsck_debug}, /* 63 */ { fsck_FSSMMRY7, "Block count: %lld", fsck_debug}, /* 64 */ { fsck_FSSMMRY8, "Free block count: %lld", fsck_debug}, /* 65 */ { fsck_ILLINOREF, "Directory inode %s%u entry %s refers to an illegal inode %s%u.", fsck_debug}, /* 66 */ { fsck_XCHKLOGUSAGE, "Usage: xchklog [-f filename] [-p] [-V] ", fsck_debug}, /* 67 */ { fsck_INOCNTGETPATH, "Unable to get path for link from directory %s%u to fileset object %s%s%u.", fsck_quiet}, /* 68 */ { fsck_INOEA, "Format error in Extended Attributes Space or descriptor.", fsck_quiet}, /* 69 */ { fsck_BADAGFELIST, "Discrepancies detected in the Free Inode Extent List for Allocation Group %s%d. (%s)", fsck_debug}, /* 70 */ { fsck_MNCNTRCNCTINOF, "MINOR: Unable to reconnect file inode %c%u. Continuing.", fsck_debug}, /* 71 */ { fsck_INCINOREF, "Directory %s%u entry \"..\" refers to an incorrect parent directory (%s%u).", fsck_quiet}, /* 72 */ { fsck_INCINOREFCRCT, "Directory inode %s%u entry \"..\" reference to incorrect inode corrected.", fsck_debug}, /* 73 */ { fsck_INOCLRD, "Storage allocated to inode %s%u has been cleared.", fsck_debug}, /* 74 */ { fsck_INOEACLRD, "Storage allocated to extended attributes for inode %s%u has been cleared.", fsck_debug}, /* 75 */ { fsck_INOINLSFNF, "File inode %c%u has been reconnected to /lost+found/.", fsck_debug}, /* 76 */ { fsck_INOLKCTFXD, "Link count for inode %s%u has been adjusted/corrected.", fsck_debug}, /* 77 */ { fsck_DEVLOCKRC, "IOCtl(...DSK_LOCKDRIVE...) returned rc = %s", fsck_debug}, /* 78 */ { fsck_INONOPATHS, "No paths were found for inode %s%u.", fsck_debug}, /* 79 */ { fsck_INOPATHOK, "File system object %s%s%u is linked as: %s", fsck_quiet}, /* 80 */ { fsck_INOREFRMV, "Directory inode %s%u entry reference to inode %s%u removed.", fsck_debug}, /* 81 */ { fsck_BADSBFWSL, "Invalid fwsp length detected in the superblock (%s).", fsck_debug}, /* 82 */ { fsck_BADSBFWSA, "Invalid fwsp address detected in the superblock (%s).", fsck_debug}, /* 83 */ { fsck_DEVOPENRDRC, "Open(...READONLY...) returned rc = %d", fsck_debug}, /* 84 */ { fsck_CANTCHKEA, "MINOR: Insufficient dynamic storage to validate extended attributes format.", fsck_quiet}, /* 85 */ { fsck_LOGREDOFAIL, "logredo failed (rc=%d). fsck continuing.", fsck_quiet}, /* 86 */ { fsck_LOGREDORC, "logredo returned rc = %d", fsck_debug}, /* 87 */ { fsck_LSFNNOTDIR, "Unable to create a lost+found directory in root because root already contains a non-directory object named lost+found. Rename the existing lost+found object in root, mkdir lost+found in the root directory, then run fsck with the -f parameter to reconnect lost files and/or directories.", fsck_quiet}, /* 88 */ { fsck_MNTFSYS2, "WARNING: Checking a mounted filesystem does not produce dependable results.", fsck_quiet}, /* 89 */ { fsck_MODIFIED, "**** Filesystem was modified. ****", fsck_debug}, /* 90 */ { fsck_DEVREDETERMRC, "ujfs_redeterminemedia() returned rc = %s", fsck_debug}, /* 91 */ { fsck_MRKSBDONE, "Superblock marked.", fsck_debug}, /* 92 */ { fsck_MSSNGBLKS, "%lld blocks are missing.", fsck_quiet}, /* 93 */ { fsck_CNTWRTBS, "Unable to write to boot sector. Continuing.", fsck_quiet}, /* 94 */ { fsck_LSFNNOTFOUND, "No \\lost+found directory found in the filesystem.", fsck_debug}, /* 95 */ { fsck_BADLINKCTS, "Incorrect link counts detected in the aggregate.", fsck_quiet}, /* 96 */ { fsck_BADIAMAGNBI, "The Inode Allocation Map control information has an incorrect number of backed inodes value for AG %s%d.", fsck_debug}, /* 97 */ { fsck_BADIAMAGNFI, "The Inode Allocation Map control information has an incorrect number of free inodes value for AG %s%d.", fsck_debug}, /* 98 */ { fsck_URCVREAD, "Unrecoverable error reading %s from %s. CANNOT CONTINUE.", fsck_quiet}, /* 99 */ { fsck_PHASE0, "**Phase 0 - Replay Journal Log", fsck_quiet}, /* 100 */ { fsck_PHASE1, "**Phase 1 - Check Blocks, Files/Directories, and Directory Entries", fsck_quiet}, /* 101 */ { fsck_PHASE2, "**Phase 2 - Count links", fsck_quiet}, /* 102 */ { fsck_PHASE3, "**Phase 3 - Duplicate Block Rescan and Directory Connectedness", fsck_quiet}, /* 103 */ { fsck_PHASE4, "**Phase 4 - Report Problems", fsck_quiet}, /* 104 */ { fsck_PHASE5, "**Phase 5 - Check Connectivity", fsck_quiet}, /* 105 */ { fsck_PHASE6, "**Phase 6 - Perform Approved Corrections", fsck_quiet}, /* 106 */ { fsck_PHASE7R, "**Phase 7 - Rebuild File/Directory Allocation Maps", fsck_quiet}, /* 107 */ { fsck_PHASE8R, "**Phase 8 - Rebuild Disk Allocation Maps", fsck_quiet}, /* 108 */ { fsck_PHASE9, "**Phase 9 - Reformat File System Log", fsck_quiet}, /* 109 */ { fsck_WILLRMVBADENTRY, "Directory has entry for unallocated file %s%u. Will remove.", fsck_quiet}, /* 110 */ { fsck_ERRONAITRD, "FATAL ERROR (%d,%d) ON READ Aggregate Inode Table (%d) first extent.", fsck_debug}, /* 111 */ { fsck_WILLCLEAREA, "Format error in Extended Attributes Space or descriptor. Will clear.", fsck_quiet}, /* 112 */ { fsck_BADIAMIAGPXDL, "The extent descriptor for inodes %d through %d is invalid. (Inode Allocation Map %s%d, Inode Allocation Group %d, Extent Index %d).", fsck_debug}, /* 113 */ { fsck_EAFORMATBAD, "Extended attributes for file set object %s%s%u have an invalid format.", fsck_debug}, /* 114 */ { fsck_REPAIRSINPROGRESS, "Superblock marked dirty because repairs are about to be written.", fsck_debug}, /* 115 */ { fsck_PRMMUTEXCLLEVELS, "Mutually exclusive 'check READ ONLY' and 'fix file system' options specified.", fsck_quiet}, /* 116 */ { avail_116, "*undefined*", fsck_quiet}, /* 117 */ { fsck_PRMUNRECOPTION, "Unrecognized -f parameter value detected: %s", fsck_quiet}, /* 118 */ { fsck_PRMUNSUPPENUM, "Unsupported parameter: %s", fsck_quiet}, /* 119 */ { fsck_LOGFORMATFAIL, "logformat failed (rc=%d). fsck continuing.", fsck_quiet}, /* 120 */ { fsck_LOGFORMATRC, "logformat returned rc = %d", fsck_debug}, /* 121 */ { fsck_CNTRDDEVCHAR, "Unable to read device characteristics. Boot sector cannot be refreshed. Continuing.", fsck_quiet}, /* 122 */ { fsck_SBBADP, "Primary superblock is corrupt.", fsck_debug}, /* 123 */ { fsck_BADIAG, "Inode Allocation Group %s%d is inconsistent.", fsck_debug}, /* 124 */ { fsck_BADIAMIAGPXDU, "cannot repair an allocation error for files and/or directories %d through %d.", fsck_quiet}, /* 125 */ { fsck_RINOTDIR, "Root inode is not a directory.", fsck_debug}, /* 126 */ { fsck_RIUNALLOC, "Root inode is not allocated.", fsck_debug}, /* 127 */ { fsck_ROOTALLOC, "Root inode allocated.", fsck_debug}, /* 128 */ { fsck_ROOTNOWDIR, "Root inode changed to directory.", fsck_debug}, /* 129 */ { fsck_DEVUNLOCKRC, "IOCtl(...DSK_UNLOCKDRIVE...) returned rc = %d", fsck_debug}, /* 130 */ { fsck_SBOKP, "Primary superblock is valid.", fsck_debug}, /* 131 */ { fsck_SESSEND, "processing terminated: %s with return code: %d exit code: %d.", fsck_debug}, /* 132 */ { fsck_DEVCLOSERC, "Close returned rc = %d", fsck_debug}, /* 133 */ { fsck_SESSPRMDFLT, "Using default parameter: -p", fsck_debug}, /* 134 */ { fsck_DEVOPENRDWRRC, "Open(...READ/WRITE EXCLUSIVE...) returned rc = %d", fsck_debug}, /* 135 */ { fsck_UALINOREF, "One or more directory entry found for unallocated inode %s%s.", fsck_debug}, /* 136 */ { fsck_CANTRECOVERINOS, "cannot recover files and/or directories %d through %d. CANNOT CONTINUE.", fsck_quiet}, /* 137 */ { fsck_URCVWRT, "Unrecoverable error writing %s to %s. CANNOT CONTINUE.", fsck_quiet}, /* 138 */ { fsck_WILLFIXRIBADDATFMT, "The root directory has an invalid data format. Will correct.", fsck_quiet}, /* 139 */ { fsck_WILLFIXRIBADFMT, "The root directory has an invalid format. Will correct.", fsck_quiet}, /* 140 */ { fsck_WILLRELEASEINOS, "cannot recover files and/or directories %d through %d. Will release.", fsck_quiet}, /* 141 */ { fsck_BADINOCLAIMSDUPSF, "File claims cross linked block(s).", fsck_quiet}, /* 142 */ { fsck_BADINODATAFORMAT, "cannot repair the data format error(s) in this file.", fsck_quiet}, /* 143 */ { fsck_BADINOFORMAT, "cannot repair the format error(s) in this file.", fsck_quiet}, /* 144 */ { fsck_CANTREPAIRINO, "cannot repair %s%s%u.", fsck_quiet}, /* 145 */ { fsck_DRIVEID, "The current device is: %s", fsck_quiet}, /* 146 */ { fsck_DRIVETYPE, "The type of file system for the device is JFS.", fsck_debug}, /* 147 */ { fsck_WILLRELEASEINO, "cannot repair %s%s%u. Will release.", fsck_quiet}, /* 148 */ { fsck_SBOKS, "Secondary superblock is valid.", fsck_debug}, /* 149 */ { fsck_WRSUP, "Unable to open for write access. Proceeding in read-only mode.", fsck_quiet}, /* 150 */ { fsck_WILLFIXDIRWHDLKS, "Multiple parent directories for directory %s%u. Will correct.", fsck_quiet}, /* 151 */ { fsck_WILLFIXINCREF, "Directory %s%u entry \"..\" refers to an incorrect parent directory (%s%u). Will correct.", fsck_quiet}, /* 152 */ { fsck_XTRABLKS, "%lld unexpected blocks detected.", fsck_quiet}, /* 153 */ { fsck_RODIRSWHLKS, "Directories with illegal hard links have been detected.", fsck_quiet}, /* 154 */ { fsck_ROINCINOREFS, "Directory entries (entries \"..\") referring to incorrect parent directories have been detected.", fsck_quiet}, /* 155 */ { fsck_ROUALINOREFS, "Directory entries for unallocated files have been detected.", fsck_quiet}, /* 156 */ { fsck_CNTWRTSUPS, "Unable to write secondary superblock.", fsck_quiet}, /* 157 */ { fsck_WILLFIXLINKCTS, "Incorrect link counts have been detected. Will correct.", fsck_quiet}, /* 158 */ { fsck_INOINLINECONFLICT, "File set object %s%s%u has inline data conflict (type %d).", fsck_debug}, /* 159 */ { fsck_DUPBLKMDREFS, "Duplicate block references have been detected in Metadata. CANNOT CONTINUE.", fsck_quiet}, /* 160 */ { fsck_DUPBLKMDREF, "Multiple metadata references to %d blocks beginning at offset %lld have been detected.", fsck_debug}, /* 161 */ { fsck_BADDINOFREELIST1, "Directory inode %s%u has a node with empty freelist and nonzero freecount.", fsck_debug}, /* 162 */ { fsck_CANTREADEAITEXT1, "Unable to read entire first extent of AIT (%s).", fsck_debug}, /* 163 */ { fsck_CANTREADAITEXT1, "Unable to read first extent of AIT (%s).", fsck_debug}, /* 164 */ { fsck_URCVUNLCK, "Unrecoverable error during UNLOCK processing.", fsck_quiet}, /* 165 */ { fsck_URCVCLOSE, "Unrecoverable error during CLOSE processing.", fsck_quiet}, /* 166 */ { fsck_RICRRCTDREF, "The root directory reference (entry \"..\") has been corrected.", fsck_debug}, /* 167 */ { fsck_INOPATHCRCT, "%s appears to be the correct path for directory %s%u.", fsck_quiet}, /* 168 */ { fsck_RODIRWHLKS, "Directory inode %s%u has illegal hard links.", fsck_debug}, /* 169 */ { fsck_ROINCINOREF, "Directory inode %s%u refers (entry \"..\") to an incorrect inode (%s%u).", fsck_debug}, /* 170 */ { fsck_ROUALINOREF, "One or more directory entry found for unallocated inode %s%u.", fsck_debug}, /* 171 */ { fsck_ERRORSDETECTED, "ERRORS HAVE BEEN DETECTED. Run fsck with the -f parameter to repair.", fsck_quiet}, /* 172 */ { fsck_RIINCINOREF, "The root directory refers (entry \"..\") to an incorrect inode.", fsck_debug}, /* 173 */ { fsck_INOSINLSFND, "%u directory reconnected to /lost+found/.", fsck_quiet}, /* 174 */ { fsck_MNCNTRCNCTINOSD, "MINOR: Unable to reconnect %u directory. Continuing.", fsck_quiet}, /* 175 */ { fsck_ROUNCONNIO, "Inode %s%u is not connected to the root directory tree.", fsck_debug}, /* 176 */ { fsck_XCHKLOGNEW, "XCHKLOG Most recent fsck service log extracted into: %s", fsck_debug}, /* 177 */ { fsck_XCHKLOGOLD, "XCHKLOG Prior fsck service log extracted into: %s", fsck_debug}, /* 178 */ { fsck_XCHKLOGOPNFAIL, "XCHKLOG Can't open output file: %s", fsck_debug}, /* 179 */ { fsck_BADINOSTAMP, "Invalid stamp detected in file system object %s%s%u.", fsck_debug}, /* 180 */ { fsck_ROUNCONNIOS, "Files and/or directories not connected to the root directory tree have been detected.", fsck_quiet}, /* 181 */ { fsck_WILLFIXROUALINOREFS, "Directory entries for unallocated files have been detected. Will remove.", fsck_quiet}, /* 182 */ { fsck_WILLFIXROUNCONNIOS, "Files and/or directories not connected to the root directory tree have been detected. Will reconnect.", fsck_quiet}, /* 183 */ { fsck_WILLFIXRODIRSWHLKS, "Directories with illegal hard links have been detected. Will correct.", fsck_quiet}, /* 184 */ { fsck_WILLFIXROINCINOREFS, "Directories (entries \"..\") referring to incorrect parent directories have been detected. Will correct.", fsck_quiet}, /* 185 */ { fsck_XCHKDMPOPNFAIL, "XCHKDMP Can't open input file: %s", fsck_debug}, /* 186 */ { fsck_AGGCLN, "Filesystem is clean.", fsck_quiet}, /* 187 */ { fsck_AGGCLNNOTDRTY, "Filesystem is clean but is marked dirty. Run fsck with the -f parameter to fix.", fsck_quiet}, /* 188 */ { fsck_AGGDRTY, "Filesystem is dirty.", fsck_quiet}, /* 189 */ { fsck_AGGDRTYNOTCLN, "Filesystem is dirty but is marked clean. In its present state,\nthe results of accessing %s (except by this utility) are undefined.", fsck_quiet}, /* 190 */ { fsck_AGGMRKDCLN, "Filesystem has been marked clean.", fsck_debug}, /* 191 */ { fsck_AGGMRKDDRTY, "Filesystem has been marked dirty because it contains critical errors. Filesystem may be unrecoverable.", fsck_quiet}, /* 192 */ { fsck_BADINOMTNODE, "File system object %s%s%u has an illegal empty node.", fsck_debug}, /* 193 */ { fsck_BADINOODDINTRNEXT, "File system object %s%s%u -- extent at offset %lld has an invalid size (%d).", fsck_debug}, /* 194 */ { fsck_BADINOFRONTGAP, "Dense file (inode %s%u) begins with an unallocated section.", fsck_debug}, /* 195 */ { fsck_BADINOINTERNGAP, "Dense file (inode %s%u) has an unallocated section after offset %lld.", fsck_debug}, /* 196 */ { fsck_BADAGFELIST1, "The Free Inode Extent List is inconsistent for Allocation Group %s%d.", fsck_debug}, /* 197 */ { fsck_BADAGFILIST, "Discrepancies detected in the Free Inode List for Allocation Group %s%d. (%s)", fsck_debug}, /* 198 */ { fsck_BADAGFILIST1, "The Free Inode List is inconsistent for Allocation Group %s%d.", fsck_debug}, /* 199 */ { fsck_BADIAGAG, "Inode Allocation Group %s%d has an invalid Allocation Group (%lld).", fsck_debug}, /* 200 */ { fsck_BADDIRENTRY, "Directory has an entry for an unallocated file %s%u.", fsck_quiet}, /* 201 */ { fsck_BADDINONODESIZ, "Directory inode %s%u has a node with incorrect size.", fsck_debug}, /* 202 */ { fsck_BADDINOODDNODESIZ, "Directory inode %s%u has a node with invalid size.", fsck_debug}, /* 203 */ { fsck_BADDINOFREELIST4, "Directory inode %s%u has a node with an invalid freelist.", fsck_debug}, /* 204 */ { fsck_BADDINOFREELIST2, "Directory inode %s%u has a node with an incorrect freecount.", fsck_debug}, /* 205 */ { fsck_BADDINOFREELIST3, "Directory inode %s%u has a node with an incorrect freelist.", fsck_debug}, /* 206 */ { fsck_BADIAGAGSTRT, "Inode Allocation Group %s%d has an invalid AG Start.", fsck_debug}, /* 207 */ { fsck_BADIAGFIES, "Inode Allocation Group %s%d has an invalid Free Extent Summary.", fsck_debug}, /* 208 */ { fsck_BADIAGFIS, "Inode Allocation Group %d%d has an invalid Free Inode Summary.", fsck_debug}, /* 209 */ { fsck_BADIAGFLIST, "Discrepancies detected in the Free IAG List. (%s,%s)", fsck_debug}, /* 210 */ { fsck_BADIAGFL1, "The Free Inode Allocation Group List is inconsistent (%s).", fsck_debug}, /* 211 */ { fsck_BADIAGIAGNUM, "Inode Allocation Group %s%d has an incorrect IAG number value.", fsck_debug}, /* 212 */ { fsck_BADIAGNFEXT, "Inode Allocation Group %s%d has an inconsistent count for number of free extents.", fsck_debug}, /* 213 */ { fsck_BADIAGNFINO, "Inode Allocation Group %s%d has an inconsistent count for number of free inodes.", fsck_debug}, /* 214 */ { fsck_BADIAGPMAP, "Discrepancies detected in the pmap for Inode Allocation Group %s%d.", fsck_debug}, /* 215 */ { fsck_BADIAM, "Errors detected in the Fileset File/Directory Allocation Map. (%s)", fsck_quiet}, /* 216 */ { fsck_BADIAMBPIE, "The Inode Allocation Map blocks per inode extent is incorrect (%s).", fsck_debug}, /* 217 */ { fsck_BADIAMCTL, "Errors detected in the Fileset File/Directory Allocation Map control information. (%s)", fsck_quiet}, /* 218 */ { fsck_BADIAML2BPIE, "The Inode Allocation Map log2(blocks per inode extent) is incorrect (%s).", fsck_debug}, /* 219 */ { fsck_BADIAMNBI, "The Inode Allocation Map has an incorrect number of backed inodes value (%s).", fsck_debug}, /* 220 */ { fsck_BADIAMNFI, "The Inode Allocation Map has an incorrect number of free inodes value (%s).", fsck_debug}, /* 221 */ { fsck_BADIAMNXTIAG, "The Inode Allocation Map has an incorrect next IAG value (%s).", fsck_debug}, /* 222 */ { fsck_XCHKDMPUSAGE, "Usage: xchkdmp [-f filename] [-V]", fsck_debug}, /* 223 */ { fsck_BADIAGAGCRCTD, "Correcting Inode Allocation Group %s%d invalid Allocation Group (%lld).", fsck_debug}, /* 224 */ { fsck_BADIAGAGSTRTCRCTD, "Correcting Inode Allocation Group %s%d invalid AG Start.", fsck_debug}, /* 225 */ { fsck_BADBMAPSLFV, "Inconsistencies detected in leaf values (%s).", fsck_debug}, /* 226 */ { fsck_BADBMAPSLNV, "Inconsistencies detected in internal values (%s).", fsck_debug}, /* 227 */ { fsck_BADBMAPSOTHER, "Incorrect data detected in pages (%s).", fsck_debug}, /* 228 */ { fsck_BADDMAPPMAPS, "Descrepancies detected between observed block allocations and pmaps.", fsck_debug}, /* 229 */ { fsck_BADBLKALLOC, "Incorrect data detected in disk allocation structures.", fsck_quiet}, /* 230 */ { fsck_BADBLKALLOCCTL, "Incorrect data detected in disk allocation control structures.", fsck_quiet}, /* 231 */ { fsck_BMAPBADHT, "Incorrect height detected in in page %s,%d.", fsck_debug}, /* 232 */ { fsck_BMAPBADL2NLF, "Incorrect l2 number of leafs detected in in page %s,%d.", fsck_debug}, /* 233 */ { fsck_BMAPBADLFI, "Incorrect leaf index detected in in page %s,%d.", fsck_debug}, /* 234 */ { fsck_BMAPBADLFV, "Incorrect leaf (%d) value detected in %s page %d.", fsck_debug}, /* 235 */ { fsck_BMAPBADLNV, "Incorrect internal (%d) value detected in %s page %d.", fsck_debug}, /* 236 */ { fsck_BMAPBADBMN, "Incorrect budmin detected in in page %s,%d.", fsck_debug}, /* 237 */ { fsck_BMAPBADNLF, "Incorrect number of leafs detected in page %s,%d.", fsck_debug}, /* 238 */ { fsck_BMAPCAGNF, "Incorrect number of free blocks in AG %d detected in Block Map Control Page.", fsck_debug}, /* 239 */ { fsck_BMAPCASB, "Incorrect aggregate size detected in Block Map Control Page.", fsck_debug}, /* 240 */ { fsck_BMAPCBPAG, "Incorrect blocks per AG detected in Block Map Control Page.", fsck_debug}, /* 241 */ { fsck_BMAPCDMCLAG, "Incorrect dmap control level detected in Block Map Control Page.", fsck_debug}, /* 242 */ { fsck_BMAPCDMCLH, "Incorrect dmap control height detected in Block Map Control Page.", fsck_debug}, /* 243 */ { fsck_BMAPCDMCLW, "Incorrect dmap control width detected in Block Map Control Page.", fsck_debug}, /* 244 */ { fsck_BMAPCL2BPAG, "Incorrect l2 blocks per AG detected in Block Map Control Page.", fsck_debug}, /* 245 */ { fsck_BMAPCL2BPP, "Incorrect l2 blocks per page detected in Block Map Control Page.", fsck_debug}, /* 246 */ { fsck_BMAPCMAAG, "Incorrect maximum active AGs detected in Block Map Control Page.", fsck_debug}, /* 247 */ { fsck_BMAPCMXLVL, "Incorrect maximum level detected in Block Map Control Page.", fsck_debug}, /* 248 */ { fsck_BMAPCNAG, "Incorrect number of AGs detected in Block Map Control Page.", fsck_debug}, /* 249 */ { fsck_BMAPCPAG, "Invalid preferred AG detected in Block Map Control Page.", fsck_debug}, /* 250 */ { fsck_XCHKLOGSBOK, "XCHKLOG %s superblock is valid.", fsck_debug}, /* 251 */ { fsck_DMAPBADNBLK, "Incorrect number of blocks detected in dmap %d.", fsck_debug}, /* 252 */ { fsck_DMAPBADNFREE, "Incorrect number free detected in dmap %d.", fsck_debug}, /* 253 */ { fsck_DMAPBADSTRT, "Incorrect start detected in dmap %d.", fsck_debug}, /* 254 */ { fsck_PMAPSBOFF, "%lld consecutive blocks observed available but pmap (%d, %d, %d) indicates they are allocated.", fsck_debug}, /* 255 */ { fsck_PMAPSBON, "%lld consecutive blocks observed allocated but pmap (%d, %d, %d) indicates they are available.", fsck_debug}, /* 256 */ { fsck_BADBMAPCAGFCL, "Discrepancies detected in the Block Map Control Page AG free count list.", fsck_debug}, /* 257 */ { fsck_BADBMAPCOTH, "Incorrect data detected in the Block Map Control Page.", fsck_debug}, /* 258 */ { fsck_BMAPCDMCSTI, "Incorrect dmap control start index detected in Block Map Control Page.", fsck_debug}, /* 259 */ { fsck_BADSBFWSL1, "Incorrect fwsp length detected in the superblock (%s).", fsck_debug}, /* 260 */ { fsck_BADSBFJLA, "Incorrect jlog address detected in the superblock (%s).", fsck_debug}, /* 261 */ { fsck_BADSBFJLL, "Incorrect jlog length detected in the superblock (%s).", fsck_debug}, /* 262 */ { fsck_HEARTBEAT0, "|........\r", fsck_hrtbt}, /* 263 */ { fsck_HEARTBEAT1, ".|.......\r", fsck_hrtbt}, /* 264 */ { fsck_HEARTBEAT2, "..|......\r", fsck_hrtbt}, /* 265 */ { fsck_HEARTBEAT3, "...|.....\r", fsck_hrtbt}, /* 266 */ { fsck_HEARTBEAT4, "....|....\r", fsck_hrtbt}, /* 267 */ { fsck_HEARTBEAT5, ".....|...\r", fsck_hrtbt}, /* 268 */ { fsck_HEARTBEAT6, "......|..\r", fsck_hrtbt}, /* 269 */ { fsck_HEARTBEAT7, ".......|.\r", fsck_hrtbt}, /* 270 */ { fsck_HEARTBEAT8, "........|\r", fsck_hrtbt}, /* 271 */ { fsck_BADINOCLAIMSDUPSD, "Directory claims cross linked block(s).", fsck_quiet}, /* 272 */ { fsck_BADINOCLAIMSDUPSO, "File system object claims cross linked block(s).", fsck_quiet}, /* 273 */ { fsck_SPARSEFILSYS, "File system is formatted for sparse files.", fsck_quiet}, /* 274 */ { fsck_INCDASDUSEDCRCT, "Directory inode %s%u incorrect DASD used value corrected.", fsck_debug}, /* 275 */ { fsck_INOSINLSFNDS, "%u directories reconnected to /lost+found/.", fsck_quiet}, /* 276 */ { fsck_INOSINLSFNF, "%u file reconnected to /lost+found/.", fsck_quiet}, /* 277 */ { fsck_INOSINLSFNFS, "%u files reconnected to /lost+found/.", fsck_quiet}, /* 278 */ { fsck_BADINODATAFORMATD, "cannot repair the data format error(s) in this directory.", fsck_quiet}, /* 279 */ { fsck_BADINOFORMATD, "cannot repair the format error(s) in this directory.", fsck_quiet}, /* 280 */ { fsck_BADINODATAFORMATO, "cannot repair the data format error(s) in this file system object.", fsck_quiet}, /* 281 */ { fsck_BADINOFORMATO, "cannot repair the format error(s) in this file system object.", fsck_quiet}, /* 282 */ { fsck_PHASE7V, "**Phase 7 - Verify File/Directory Allocation Maps", fsck_quiet}, /* 283 */ { fsck_PHASE8V, "**Phase 8 - Verify Disk Allocation Maps", fsck_quiet}, /* 284 */ { fsck_PARMOMITLOGREDO, "parameter detected: Omit logredo()", fsck_debug}, /* 285 */ { fsck_NOTJFSINFSTAB, "The file system type for %s is not listed as jfs \nin the file system description file /etc/fstab.", fsck_quiet}, /* 286 */ { fsck_BAD_COOKIE, "Bad directory cookie found.", fsck_debug}, /* 287 */ { fsck_PAGE_NOT_FOUND, "Directory Index page not found", fsck_debug}, /* 288 */ { fsck_READ_FAILED, "Cannot read Directory Index page.", fsck_debug}, /* 289 */ { fsck_BAD_ENTRY, "Invalid Directory Index Table entry found.", fsck_debug}, /* 290 */ { fsck_BADMETAINOP, "Primary metadata inode %s%d is corrupt.", fsck_debug}, /* 291 */ { fsck_BADMETAINOS, "Secondary metadata inode %s%d is corrupt.", fsck_debug}, /* 292 */ { fsck_SBBADS, "Secondary superblock is corrupt.", fsck_debug}, /* 293 */ { fsck_CANTREADAITS, "Unable to read the Secondary File/Directory Allocation Table.", fsck_quiet}, /* 294 */ { fsck_BADIAMCTLA, "Errors detected in the File System File/Directory Allocation Map.", fsck_quiet}, /* 295 */ { fsck_BADIAMA, "Errors detected in the File System File/Directory Allocation Map control information.", fsck_quiet}, /* 296 */ { fsck_ERRORSINAITS, "Errors detected in the Secondary File/Directory Allocation Table.", fsck_quiet}, /* 297 */ { fsck_CNTRESUPS, "Unable to read secondary superblock.", fsck_debug}, /* 298 */ { fsck_DI_TABLE, "Errors detected in Directory Index Table.", fsck_quiet}, /* 299 */ { fsck_DI_TABLE_FXD, "Directory Index Table for inode %s%u has been reset.", fsck_debug}, /* 300 */ { fsck_WILLFIX_DI_TABLE, "Errors detected in Directory Index Table. Will Fix.", fsck_quiet}, /* 301 */ { fsck_MNCNTRCNCTINOSDS, "MINOR: Unable to reconnect %u directories. Continuing.", fsck_quiet}, /* 302 */ { fsck_MNCNTRCNCTINOSF, "MINOR: Unable to reconnect %u file. Continuing.", fsck_quiet}, /* 303 */ { fsck_MNCNTRCNCTINOSFS, "MINOR: Unable to reconnect %u files. Continuing.", fsck_quiet}, /* 304 */ { avail_304, "*undefined*", fsck_debug}, /* 305 */ { avail_305, "*undefined*", fsck_debug}, /* 306 */ { avail_306, "*undefined*", fsck_debug}, /* 307 */ { avail_307, "*undefined*", fsck_debug}, /* 308 */ { avail_308, "*undefined*", fsck_debug}, /* 309 */ { fsck_INOINLSFND, "Directory inode %c%u has been reconnected to /lost+found/.", fsck_debug}, /* 310 */ { fsck_MNCNTRCNCTINOD, "MINOR: Unable to reconnect directory inode %c%u. Continuing.", fsck_debug}, /* 311 */ { avail_311, "*undefined*", fsck_debug}, /* 312 */ { fsck_CNTRESUPB, "Unable to read either superblock.", fsck_debug}, /* 313 */ { fsck_STDSUMMARY1, "%9lld kilobytes total disk space.", fsck_quiet}, /* 314 */ { fsck_STDSUMMARY2, "%9lld kilobytes in %lld directories.", fsck_quiet}, /* 315 */ { fsck_STDSUMMARY3, "%9lld kilobytes in %lld user files.", fsck_quiet}, /* 316 */ { fsck_STDSUMMARY4, "%9lld kilobytes in extended attributes", fsck_quiet}, /* 317 */ { fsck_STDSUMMARY5, "%9lld kilobytes reserved for system use.", fsck_quiet}, /* 318 */ { fsck_STDSUMMARY6, "%9lld kilobytes are available for use.", fsck_quiet}, /* 319 */ { fsck_XCHKDMPMTORBADREAD, "XCHKDMP Can't read input file: %s", fsck_debug}, /* 320 */ { fsck_XCHKDMPBADFORMAT, "XCHKDMP Input file (%s) not recognized as an extracted JFS fsck service log.", fsck_debug}, /* 321 */ { fsck_XCHKLOGBADDEVICE, "XCHKLOG Cannot open device %s", fsck_debug}, /* 322 */ { fsck_XCHKLOGBADFNAME, "XCHKLOG Output file path and name must be less than 128 characters.", fsck_debug}, /* 323 */ { fsck_XCHKDMPBADFNAME, "XCHKDMP Input file path and name must be less than 128 characters.", fsck_debug}, /* 324 */ { fsck_CANTREADAITP, "Unable to read the Primary File/Directory Allocation Table.", fsck_quiet}, /* 325 */ { fsck_ERRORSINAITP, "Errors detected in the Primary File/Directory Allocation Table.", fsck_quiet}, /* 326 */ { fsck_CANTCONTINUE, "CANNOT CONTINUE.", fsck_quiet}, /* 327 */ { fsck_CANTINITSVCLOG, "********** CANNOT INITIALIZE THIS SERVICE LOG. DISREGARD RESIDUAL LOG MESSAGES WHICH MAY BE APPENDED. **********", fsck_debug}, /* 328 */ { fsck_CHKLOGNOVOL, "CHKLOG Required parameter missing: device specification", fsck_debug}, /* 329 */ { fsck_XCHKLOGNOVOL, "XCHKLOG Required parameter missing: device specification", fsck_debug}, /* 330 */ { fsck_PARMFIXLVL, "parameter detected: FixLevel: %s", fsck_debug}, /* 331 */ { fsck_PARMIFDRTY, "parameter detected: IfDirty", fsck_debug}, /* 332 */ { fsck_PARMVERBOSE, "parameter detected: VerboseMessaging", fsck_debug}, /* 333 */ { fsck_PARMAUTOCHK, "parameter detected: AutoCheck mode", fsck_debug}, /* 334 */ { fsck_PARMPMCHK, "parameter detected: PMchkdsk mode", fsck_debug}, /* 335 */ { fsck_PARMDEBUG, "parameter detected: Debug mode", fsck_debug}, /* 336 */ { fsck_CHKDSKSYSALLOC, "CHKDSK.SYS returned %s bytes of high memory at %s", fsck_debug}, /* 337 */ { fsck_CHKDSKSYSOPENRC, "Open(CHKDSK.SYS,...) returned rc = %s", fsck_debug}, /* 338 */ { fsck_CHKDSKSYSCALLRC, "IOCtl( ... ) to call CHKDSK.SYS returned rc = %s, data.rc = %s", fsck_debug}, /* 339 */ { fsck_DEVBEGINFMTRC, "ujfs_beginformat() returned rc = %s", fsck_debug}, /* 340 */ { fsck_PARMCLRBDBLKLST, "parameter detected: Clear LVM Bad Block List", fsck_debug}, /* 341 */ { fsck_CHKDSKFSSYNCHRC, "(JFSCTL_CHKDSK, ... ) returned rc = %s", fsck_debug}, /* 342 */ { fsck_LVMFOUNDBDBLKS, "warning: The LVM has detected bad blocks in the partition. Run /B to transfer entries from the LVM bad block table to the JFS bad block table.", fsck_quiet}, /* 343 */ { fsck_LVMGETBBLKINFORC, "LVM GetBadBlockInformation returned rc = %s", fsck_debug}, /* 344 */ { fsck_LVMGETTBLSIZERC, "LVM GetTableSize rc = %s", fsck_debug}, /* 345 */ { fsck_LVMFSNOWAVAIL, "THE FILE SYSTEM IS NOW AVAILABLE.", fsck_quiet}, /* 346 */ { fsck_LVMTRNSBBLKSTOJFS, "Transferring entries from the LVM Bad Block Table for this file system to the JFS Bad Block Table for this file system.", fsck_quiet}, /* 347 */ { fsck_INTERNALERROR, "INTERNAL ERROR (%d,%d,%d,%d). CANNOT CONTINUE.", fsck_quiet}, /* 348 */ { fsck_CLRBBACTIVITY, "CLRBBLKS: relocated %s extents, for total %s relocated blocks.", fsck_debug}, /* 349 */ { fsck_CLRBBLVMLISTDATA, "CLRBBLKS: LVM List #%s num entries = %s num active entries = %s", fsck_debug}, /* 350 */ { fsck_CLRBBLVMNUMLISTS, "CLRBBLKS: number of LVM Lists = %s", fsck_debug}, /* 351 */ { fsck_CLRBBRANGE, "CLRBBLKS: Attempted to relocate bad blocks in range %s to %s.", fsck_debug}, /* 352 */ { fsck_CLRBBRESULTS, "LVM reports %s bad blocks. Of these, %s have been transferred to the JFS Bad Block List.", fsck_quiet}, /* 353 */ { fsck_CLRBBLKSRC, "CLRBBLKS rc = %s", fsck_debug}, /* 354 */ { fsck_DOSEXECPGMRC, "DosExecPgm(...clrbblks...) rc = %s", fsck_debug}, /* 355 */ { fsck_DEVOPENRDWRSRC, "Open(...OPEN_SHARE_DENYNONE|OPEN_ACCESS_READWRITE...) returned rc = %s", fsck_debug}, /* 356 */ { fsck_CLRBBOPENFAILED, "Device unavailable or locked by another process. CANNOT CONTINUE.", fsck_quiet}, /* 357 */ { fsck_BADINONODESELF, "File system object %s%s%u has a node with an invalid self field.", fsck_debug}, /* 358 */ { fsck_INOPATHBAD, "File system object %s%s%u is illegally linked as: %s", fsck_quiet}, /* 359 */ { fsck_CANTRECONINSUFSTG, "Insufficient storage (%d) available to continue reconnecting lost files and/or directories. Continuing.", fsck_quiet}, /* 360 */ { fsck_INOACL, "Format error in Access Control List space or descriptor.", fsck_quiet}, /* 361 */ { fsck_WILLCLEARACL, "Format error in Access Control List space or descriptor. Will clear.", fsck_quiet}, /* 362 */ { fsck_INOACLCLRD, "Storage allocated to Access Control List for inode %s%u has been cleared.", fsck_debug}, /* 363 */ { fsck_STDSUMMARY4A, "%9lld kilobytes in access control lists", fsck_debug}, /* 364 */ { fsck_EXHFILSYSSTG, "File system is full or too fragmented to allocated requested %d blocks.", fsck_debug}, /* 365 */ { fsck_INOMINOR, "Minor format error detected.", fsck_quiet}, /* 366 */ { fsck_INOMINORFXD, "Minor format error in inode %s%u has been corrected.", fsck_debug}, /* 367 */ { fsck_WILLFIXINOMINOR, "Minor format error detected. Will fix.", fsck_quiet}, /* 368 */ { fsck_BADINODXDFLDL, "File system object %s%s%u has invalid length in descriptor (%s).", fsck_debug}, /* 369 */ { fsck_BADINODXDFLDO, "File system object %s%s%u has invalid offset in descriptor (%s).", fsck_debug}, /* 370 */ { fsck_READONLY, "File system checked READ ONLY.", fsck_quiet}, /* 371 */ { fsck_PRMBADDEVICE , "Device does not exist.", fsck_quiet}, /* 372 */ { fsck_PRMNODEVICE , "No device given.", fsck_quiet}, /* 373 */ { avail_373, "*undefined*", fsck_debug}, /* 374 */ { avail_374, "*undefined*", fsck_debug}, /* 375 */ { avail_375, "*undefined*", fsck_debug}, /* 376 */ { avail_376, "*undefined*", fsck_debug}, /* 377 */ { avail_377, "*undefined*", fsck_debug}, /* 378 */ { avail_378, "*undefined*", fsck_debug}, /* 379 */ { avail_379, "*undefined*", fsck_debug}, /* 380 */ { avail_380, "*undefined*", fsck_debug}, /* 381 */ { avail_381, "*undefined*", fsck_debug}, /* 382 */ { avail_382, "*undefined*", fsck_debug}, /* 383 */ { avail_383, "*undefined*", fsck_debug}, /* 384 */ { fsck_block_special, "B", fsck_txtins}, /* 385 */ { fsck_aggregate, "A", fsck_txtins}, /* 386 */ { fsck_dirpfx, "D", fsck_txtins}, /* 387 */ { fsck_dmap, "DM", fsck_txtins}, /* 388 */ { fsck_EA, "E", fsck_txtins}, /* 389 */ { fsck_fset_inode, "F", fsck_txtins}, /* 390 */ { fsck_metaIAG, "I", fsck_txtins}, /* 391 */ { fsck_L0, "L0", fsck_txtins}, /* 392 */ { fsck_L1, "L1", fsck_txtins}, /* 393 */ { fsck_L2, "L2", fsck_txtins}, /* 394 */ { fsck_metadata, "M", fsck_txtins}, /* 395 */ { fsck_char_special, "C", fsck_txtins}, /* 396 */ { fsck_primary, "P", fsck_txtins}, /* 397 */ { fsck_SOCK, "S", fsck_txtins}, /* 398 */ { fsck_symbolic_link, "L", fsck_txtins}, /* 399 */ { fsck_dotext, ".RCN", fsck_txtins}, /* 400 */ { lrdo_ALREADYREDONE, "LOGREDO: Log already redone!", fsck_debug}, /* 401 */ { lrdo_LOGEND, "LOGREDO: End of log found at logend = 0x0%x", fsck_debug}, /* 402 */ { lrdo_REXTNDBEGIN, "LOGREDO: Beginning to recover File System Extend processing.", fsck_debug}, /* 403 */ { lrdo_REXTNDDONE, "LOGREDO: Done recovering File System Extend processing.", fsck_debug}, /* 404 */ { lrdo_REXTNDTOPRE, "LOGREDO: File System Extend recovered to prior size.", fsck_debug}, /* 405 */ { lrdo_REXTNDTOPOST, "LOGREDO: File System Extend recovered and completed.", fsck_debug}, /* 406 */ { lrdo_REXTNDFAIL, "LOGREDO: Recovery of File System Extend failed. Error = %s", fsck_debug}, /* 407 */ { lrdo_LOGSUPBADMGC, "LOGREDO: Log superblock contains invalid magic number.", fsck_debug}, /* 408 */ { lrdo_LOGSUPBADVER, "LOGREDO: Log superblock contains invalid version number.", fsck_debug}, /* 409 */ { lrdo_LOGENDBAD1, "LOGREDO: Unable to find valid end of log.", fsck_debug}, /* 410 */ { lrdo_INITFAILED, "LOGREDO: Initialization failed. rc = %d error num = %d", fsck_debug}, /* 411 */ { lrdo_LOGSUPBADBLKSZ, "LOGREDO: Log superblock contains invalid block size.", fsck_debug}, /* 412 */ { lrdo_LOGSUPBADL2BLKSZ, "LOGREDO: Log superblock contains invalid log2(block size).", fsck_debug}, /* 413 */ { lrdo_LOGSUPBADLOGSZ, "LOGREDO: Log superblock contains invalid log size.", fsck_debug}, /* 414 */ { lrdo_LOGENDBAD2, "LOGREDO: Log end is not in valid range.", fsck_debug}, /* 415 */ { lrdo_RPTSYNCNUM, "LOGREDO: Synch point record number: 0x0%x", fsck_debug}, /* 416 */ { lrdo_RPTSYNCADDR, "LOGREDO: Synch point record address: 0x0%x", fsck_debug}, /* 417 */ { lrdo_RPTNUMLOGREC, "LOGREDO: Number of log records: (d) %d", fsck_debug}, /* 418 */ { lrdo_RPTNUMDOBLK, "LOGREDO: Number of Do blocks: (d) %d", fsck_debug}, /* 419 */ { lrdo_RPTNUMNODOBLK, "LOGREDO: Number of NoDo blocks: (d) %d", fsck_debug}, /* 420 */ { lrdo_SYNCRECORD, "LOGREDO: Log record for Sync Point at: 0x0%x", fsck_debug}, /* 421 */ { lrdo_MOUNTRECORD, "LOGREDO: Log record for Volume Mount at: 0x0%x", fsck_debug}, /* 422 */ { fsck_ALLOCHIGHMEM, "Calling CHKDSK.SYS to allocate high memory....", fsck_debug}, /* 423 */ { fsck_ALLOCHIGHMEMRSLT, "CHKDSK.SYS returned addr= %s length= %s", fsck_debug}, /* * Stop using 424-430. They are annoying. Leave them defined so that * fscklog works against older versions */ /* 424 */ { lrdo_ALLOC4BMAP, "LOGREDO: Allocating for BMap: (d) %d bytes", fsck_debug}, /* 425 */ { lrdo_ALLOC4IMAP, "LOGREDO: Allocating for IMap: (d) %d bytes", fsck_debug}, /* 426 */ { lrdo_ALLOC4DOBLK, "LOGREDO: Allocating for DoBLk: (d) %d bytes", fsck_debug}, /* 427 */ { lrdo_ALLOC4NOREDOFL, "LOGREDO: Allocating for NoReDoFile: (d) %d bytes", fsck_debug}, /* 428 */ { lrdo_ALLOC4REDOPG, "LOGREDO: Allocating for ReDoPage: (d) %d bytes", fsck_debug}, /* 429 */ { lrdo_ALLOC4NODOFL, "LOGREDO: Allocating for NoDoFile: (d) %d bytes", fsck_debug}, /* 430 */ { lrdo_ALLOC4EXTDTPG, "LOGREDO: Allocating for ExtendDtPg: (d) %d bytes", fsck_debug}, /* 431 */ { lrdo_ALLOC4BMAPFAIL, "LOGREDO: Failed trying to allocate for BMap: (d) %lld bytes", fsck_debug}, /* 432 */ { lrdo_ALLOC4IMAPFAIL, "LOGREDO: Failed trying to allocate for IMap: (d) %d bytes", fsck_debug}, /* 433 */ { lrdo_ALLOC4DOBLKFAIL, "LOGREDO: Failed trying to allocate for DoBLk: (d) %d bytes", fsck_debug}, /* 434 */ { lrdo_ALLOC4NOREDOFLFAIL, "LOGREDO: Failed trying to allocate for NoReDoFile: (d) %d bytes", fsck_debug}, /* 435 */ { lrdo_ALLOC4REDOPGFAIL, "LOGREDO: Failed trying to allocate for ReDoPage: (d) %d bytes", fsck_debug}, /* 436 */ { lrdo_ALLOC4NODOFLFAIL, "LOGREDO: Failed trying to allocate for NoDoFile: (d) %d bytes", fsck_debug}, /* 437 */ { lrdo_ALLOC4EXTDTPGFAIL, "LOGREDO: Failed trying to allocate for ExtendDtPg: (d) %d bytes", fsck_debug}, /* 438 */ { lrdo_USINGBMAPALLOC4IMAP, "LOGREDO: Working IMap will occupy storage originally allocated for BMap.", fsck_debug}, /* 439 */ { lrdo_USINGBMAPALLOC4NRFL, "LOGREDO: Some storage allocated for BMap now used for NoRedoFile records.", fsck_debug}, /* 440 */ { lrdo_USINGBMAPALLOC4DOBLK, "LOGREDO: Some storage allocated for BMap now used for DoBLock records.", fsck_debug}, /* 441 */ { lrdo_USINGBMAPALLOC4RDPG, "LOGREDO: Some storage allocated for BMap now used for RedoPage records.", fsck_debug}, /* 442 */ { lrdo_USINGBMAPALLOC4NDFL, "LOGREDO: Some storage allocated for BMap now used for NoDoFile records.", fsck_debug}, /* 443 */ { lrdo_USINGBMAPALLOC4EDPG, "LOGREDO: Some storage allocated for BMap now used for ExtendDtPage records.", fsck_debug}, /* 444 */ { lrdo_CANTREADLOGSUP, "LOGREDO: Unable to read Journal Log superblock.", fsck_debug}, /* 445 */ { lrdo_CANTUPDLOGSUP, "LOGREDO: Unable to update Journal Log superblock.", fsck_debug}, /* 446 */ { lrdo_NEXTADDRINVALID, "LOGREDO: Address of next log record is invalid.", fsck_debug}, /* 447 */ { lrdo_NEXTADDROUTRANGE, "LOGREDO: Address (0x0%x) of next log record is out of range.", fsck_debug}, /* 448 */ { lrdo_NEXTADDRSAME, "LOGREDO: Address (%s) of next log record is the same as address of current log record.", fsck_debug}, /* 449 */ { lrdo_LOGWRAPPED, "LOGREDO: The Journal Log has wrapped around and written over itself.", fsck_debug}, /* 450 */ { lrdo_BADCOMMIT, "LOGREDO: Invalid Commit record at 0x0%x.", fsck_debug}, /* 451 */ { lrdo_BADMOUNT, "LOGREDO: Invalid Mount record at 0x0%x.", fsck_debug}, /* 452 */ { lrdo_DEVOPNREADERROR, "LOGREDO: Device open/read error", fsck_debug}, /* 453 */ { lrdo_BADREDOPAGE, "LOGREDO: Invalid RedoPage record at 0x0%x.", fsck_debug}, /* 454 */ { lrdo_BADNOREDOPAGE, "LOGREDO: Invalid NoRedoPage record at 0x0%x.", fsck_debug}, /* 455 */ { lrdo_BADNOREDOINOEXT, "LOGREDO: Invalid NoRedoInoExt record at 0x0%x.", fsck_debug}, /* 456 */ { lrdo_BADUPDATEMAP, "LOGREDO: Invalid UpdateMap record at 0x0%x.", fsck_debug}, /* 457 */ { lrdo_UNKNOWNTYPE, "LOGREDO: Unrecognized log record type at 0x0%x.", fsck_debug}, /* 458 */ { lrdo_ERRORNEEDREFORMAT, "LOGREDO: Errors encountered imply the log is corrupt. Reformat needed.", fsck_debug}, /* 459 */ { lrdo_ERRORCANTCONTIN, "LOGREDO: Errors encountered prevent logredo() from continuing.", fsck_debug}, /* 460 */ { lrdo_ERRORCANTUPDMAPS, "LOGREDO: Unable to update map(s).", fsck_debug}, /* 461 */ { lrdo_ERRORCANTUPDFSSUPER, "LOGREDO: Unable to update file system superblock.", fsck_debug}, /* 462 */ { lrdo_CANTWRITELOGSUPER, "LOGREDO: Unable to write to log superblock.", fsck_debug}, /* 463 */ { lrdo_CANTREADFSSUPER, "LOGREDO: Unable to read file system superblock.", fsck_debug}, /* 464 */ { lrdo_FSSUPERBADMAGIC, "LOGREDO: File system superblock has invalid magic number.", fsck_debug}, /* 465 */ { lrdo_FSSUPERBADVERS, "LOGREDO: File system superblock has invalid version number.", fsck_debug}, /* 466 */ { lrdo_FSSUPERBADLOGLOC, "LOGREDO: File system superblock has invalid log location.", fsck_debug}, /* 467 */ { lrdo_FSSUPERBADLOGSER, "LOGREDO: File system superblock has invalid log serial number.", fsck_debug}, /* 468 */ { lrdo_INITMAPSFAIL, "LOGREDO: Unable to initialize map(s).", fsck_debug}, /* 469 */ { lrdo_READFSSUPERFAIL, "LOGREDO: Attempt to read file system superblock failed.", fsck_debug}, /* 470 */ { lrdo_WRITEFSSUPERFAIL, "LOGREDO: Attempt to write file system superblock failed.", fsck_debug}, /* 471 */ { lrdo_READFSPRIMSBFAIL, "LOGREDO: Attempt to read file system primary superblock failed.", fsck_debug}, /* 472 */ { lrdo_READFS2NDSBFAIL, "LOGREDO: Attempt to read file system secondary superblock failed.", fsck_debug}, /* 473 */ { lrdo_WRITEFSPRIMSBFAIL, "LOGREDO: Attempt to write file system primary superblock failed.", fsck_debug}, /* 474 */ { lrdo_WRITEFS2NDSBFAIL, "LOGREDO: Attempt to write file system secondary superblock failed.", fsck_debug}, /* 475 */ { lrdo_BUFFLUSHFAIL, "LOGREDO: Attempt to flush buffers failed.", fsck_debug}, /* 476 */ { lrdo_NOTAFSDEVNUM, "LOGREDO: Not a valid file system device number.", fsck_debug}, /* 477 */ { lrdo_LOGNOTINLINE1, "LOGREDO: Journal log must be inline.", fsck_debug}, /* 478 */ { lrdo_NOTAFSDEV, "LOGREDO: Device is not a file system device.", fsck_debug}, /* 479 */ { lrdo_LOGNOTINLINE2, "LOGREDO: Journal log is not inline.", fsck_debug}, /* 480 */ { lrdo_LOGOPEN, "LOGREDO: Journal log is now open. (major = %s, minor = %s)", fsck_debug}, /* 481 */ { lrdo_ERRORONVOL, "LOGREDO: Error in volume (d) %d.", fsck_debug}, /* 482 */ { lrdo_OPENFAILED, "LOGREDO: Device open failed.", fsck_debug}, /* 483 */ { lrdo_CANTINITMAPS, "LOGREDO: Failed attempting to initialize map(s).", fsck_debug}, /* 484 */ { lrdo_BADDISKBLKNUM, "LOGREDO: Invalid volume block number (0x0%llx).", fsck_debug}, /* 485 */ { lrdo_BADINODENUM, "LOGREDO: Invalid inode number ((d) %lld).", fsck_debug}, /* 486 */ { lrdo_CANTREADBLK, "LOGREDO: Failed attempt to read block 0x0%llx.", fsck_debug}, /* 487 */ { lrdo_IOERRREADINGBLK, "LOGREDO: I/O error attempting to read block 0x0%llx.", fsck_debug}, /* 488 */ { lrdo_BADUPDMAPREC, "LOGREDO: Invalid UpdateMap record (nxd = (d) %lld).", fsck_debug}, /* 489 */ { lrdo_BADLOGSER, "LOGREDO: Invalid log serial number.", fsck_debug}, /* 490 */ { lrdo_FINDLOGENDFAIL, "LOGREDO: Failed attempt to find the current end of the Journal Log.", fsck_debug}, /* 491 */ { lrdo_LOGREADFAIL, "LOGREDO: Failed attempting to read the Journal Log (logaddr = 0x0%x).", fsck_debug}, /* 492 */ { lrdo_UNRECOGTYPE, "LOGREDO: Unrecognized log record type (logaddr = 0x0%x).", fsck_debug}, /* 493 */ { lrdo_IOERRONLOG, "LOGREDO: I/O error on Journal Log (logaddr = 0x0%x).", fsck_debug}, /* 494 */ { lrdo_LOGWRAP, "LOGREDO: The Journal Log has wrapped.", fsck_debug}, /* 495 */ { lrdo_EXTFSREADFSSUPERFAIL, "LOGREDO: RecovExtFS: Attempt to read file system superblock failed.", fsck_debug}, /* 496 */ { lrdo_EXTFSREADBLKMAPINOFAIL, "LOGREDO: RecovExtFS: Attempt to read block map inode failed.", fsck_debug}, /* 497 */ { lrdo_EXTFSREADBLKFAIL1, "LOGREDO: RecovExtFS: Read aggregate block 0x0%llx failed (1).", fsck_debug}, /* 498 */ { lrdo_EXTFSREADBLKFAIL2, "LOGREDO: RecovExtFS: Read aggregate block 0x0%llx failed (2).", fsck_debug}, /* 499 */ { lrdo_EXTFSWRITEBLKFAIL1, "LOGREDO: RecovExtFS: Write aggregate block 0x0%x failed (1).", fsck_debug}, /* 500 */ { lrdo_EXTFSWRITEBLKFAIL2, "LOGREDO: RecovExtFS: Write aggregate block 0x0%llx failed (2).", fsck_debug}, /* 501 */ { lrdo_EXTFSWRITEBLKFAIL3, "LOGREDO: RecovExtFS: Write aggregate block 0x0%llx failed (3).", fsck_debug}, /* 502 */ { lrdo_EXTFSREADBLKFAIL3, "LOGREDO: RecovExtFS: Read aggregate block 0x0%llx failed (3).", fsck_debug}, /* 503 */ { lrdo_EXTFSREADBLKFAIL4, "LOGREDO: RecovExtFS: Read aggregate block 0x0%llx failed (4).", fsck_debug}, /* 504 */ { lrdo_EXTFSINITLOGREDOFAIL, "LOGREDO: RecovExtFS: Error in initLogredo().", fsck_debug}, /* 505 */ { lrdo_EXTFSREADBLKFAIL5, "LOGREDO: RecovExtFS: Read aggregate block 0x0%llx failed (5).", fsck_debug}, /* 506 */ { lrdo_EXTFSWRITEBLKFAIL4, "LOGREDO: RecovExtFS: Write aggregate block 0x0%llx failed (4).", fsck_debug}, /* 507 */ { lrdo_EXTFSWRITEFSSUPERFAIL, "LOGREDO: RecovExtFS: Attempt to write file system superblock failed.", fsck_debug}, /* 508 */ { lrdo_EXTFSREADLOGSUPFAIL, "LOGREDO: RecovExtFS: Attempt to read Journal Log superblock failed.", fsck_debug}, /* 509 */ { lrdo_EXTFSWRITELOGSUPFAIL, "LOGREDO: RecovExtFS: Attempt to write Journal Log superblock failed.", fsck_debug}, /* 510 */ { lrdo_READBMAPINOFAIL, "LOGREDO: Read Block Map inode failed.", fsck_debug}, /* 511 */ { lrdo_READBMAPFAIL, "LOGREDO: Read Block Map failed.", fsck_debug}, /* 512 */ { lrdo_READIMAPINOFAIL, "LOGREDO: Read Inode Alloc Map inode failed.", fsck_debug}, /* 513 */ { lrdo_READIMAPFAIL, "LOGREDO: Read Inode Alloc Map failed.", fsck_debug}, /* 514 */ { lrdo_RBMPREADXTFAIL, "LOGREDO: Read Block Map leftmost leaf failed.", fsck_debug}, /* 515 */ { lrdo_RBMPREADDATFAIL, "LOGREDO: Read Block Map data extents failed.", fsck_debug}, /* 516 */ { lrdo_RBMPREADNXTLFFAIL, "LOGREDO: Read Block Map next leaf failed.", fsck_debug}, /* 517 */ { lrdo_RIMPREADXTFAIL, "LOGREDO: Read Inode Alloc Map leftmost leaf failed.", fsck_debug}, /* 518 */ { lrdo_RIMPREADCTLFAIL, "LOGREDO: Read Inode Alloc Map control page failed.", fsck_debug}, /* 519 */ { lrdo_RIMPREADNXTLFFAIL, "LOGREDO: Read Inode Alloc Map next leaf failed.", fsck_debug}, /* 520 */ { lrdo_RIMPREADDATFAIL, "LOGREDO: Read Inode Alloc Map data extents failed.", fsck_debug}, /* 521 */ { lrdo_UMPREADIMAPINOFAIL, "LOGREDO: Read Inode Alloc Map inode failed in UpdateMaps().", fsck_debug}, /* 522 */ { lrdo_UMPWRITEIMAPCTLFAIL, "LOGREDO: Write Inode Alloc Map control page failed in UpdateMaps().", fsck_debug}, /* 523 */ { lrdo_UMPREADBMAPINOFAIL, "LOGREDO: Read Block Map inode failed in UpdateMaps().", fsck_debug}, /* 524 */ { lrdo_UMPWRITEBMAPCTLFAIL, "LOGREDO: Write Block Map control page failed in UpdateMaps().", fsck_debug}, /* 525 */ { lrdo_WRIMPNOTRBLDGIMAP, "LOGREDO: Not rebuilding the Inode Alloc Map because fsck will be doing it.", fsck_debug}, /* 526 */ { lrdo_WRIMPRXTFAIL, "LOGREDO: Write Inode Alloc Map, rXtree() failed.", fsck_debug}, /* 527 */ { lrdo_WRIMPBLKWRITEFAIL, "LOGREDO: Write block (blk=0x0%llx) failed when updating the Inode Alloc Mapl.", fsck_debug}, /* 528 */ { lrdo_WRIMPREADLFFAIL, "LOGREDO: Read next leaf (addr=%s) failed when updating the Inode Alloc Map.", fsck_debug}, /* 529 */ { lrdo_WRIMPBADNPAGES, "LOGREDO: Incorrect npages detected when updating the Inode Alloc Map.", fsck_debug}, /* 530 */ { lrdo_WRIMPDONE, "LOGREDO: Done updating the Inode Allocation Map.", fsck_debug}, /* 531 */ { lrdo_WRIMPSTART, "LOGREDO: Beginning to update the Inode Allocation Map.", fsck_debug}, /* 532 */ { lrdo_WRBMPDONE, "LOGREDO: Done updating the Block Map.", fsck_debug}, /* 533 */ { lrdo_WRBMPSTART, "LOGREDO: Beginning to update the Block Map.", fsck_debug}, /* 534 */ { lrdo_WRBMPNOTRBLDGBMAP, "LOGREDO: Not rebuilding the Block Map because fsck will be doing it.", fsck_debug}, /* 535 */ { lrdo_RBLDGIMAPERROR1, "LOGREDO: Error for pmap and inoext when rebuilding the Inode Allocation Map (1).", fsck_debug}, /* 536 */ { lrdo_WRBMPBADMAPSIZE, "LOGREDO: Inconsistent map size in Block Map.", fsck_debug}, /* 537 */ { lrdo_WRBMPBADLFIDX0, "LOGREDO: Incorrect leaf index detected (k=(d) %d, j=(d) %d, idx=(d) %d) while writing Block Map.", fsck_debug}, /* 538 */ { lrdo_RBLDGDMAPERROR, "LOGREDO: Error rebuilding DMap page (k=(d) %d, j=(d) %d, i=(d) %d).", fsck_debug}, /* 539 */ { lrdo_WRBMPRXTFAIL, "LOGREDO: rXtree() failed when called while writing Block Map.", fsck_debug}, /* 540 */ { lrdo_WRBMPBLKWRITEFAIL, "LOGREDO: Write block (at 0x0%llx) failed while writing Block Map.", fsck_debug}, /* 541 */ { lrdo_WRBMPREADLFFAIL, "LOGREDO: Read next leaf (at %s) failed while writing Block Map.", fsck_debug}, /* 542 */ { lrdo_WRBMPBADTOTPG, "LOGREDO: Incorrect total pages while writing Block Map.", fsck_debug}, /* 543 */ { lrdo_UPDMPBADLFIDX, "LOGREDO: Invalid leaf index detected while updating dmap page.", fsck_debug}, /* 544 */ { lrdo_RXTREADLFFAIL, "LOGREDO: rXtree() Read first leaf failed.", fsck_debug}, /* 545 */ { lrdo_BRDBADBLOCK, "LOGREDO: bread() Invalid block number specified (0x0%llx).", fsck_debug}, /* 546 */ { lrdo_BRDREADBLKFAIL, "LOGREDO: bread() Read block (0x0%llx) failed.", fsck_debug}, /* 547 */ { lrdo_RBLDGIMAPERROR2, "LOGREDO: Error for pmap and inoext when rebuilding the Inode Allocation Map (2).", fsck_debug}, /* 548 */ { lrdo_DAFTUPDPGFAILED, "LOGREDO: doAfter: updatePage failed. (logaddr = 0x0%x, rc = (d) %d)", fsck_debug}, /* 549 */ { lrdo_DAFTMRKBMPFAILED, "LOGREDO: doAfter: markBmap failed. (logaddr = 0x0%x, rc = (d) %d)", fsck_debug}, /* 550 */ { lrdo_DEDPBREADFAILED, "LOGREDO: doExtDtPg: bread failed. (offset = 0x0%llx, rc = (d) %d)", fsck_debug}, /* 551 */ { lrdo_DNRPFNDDTRTPGREDOFAIL, "LOGREDO: doNoRedoPage: type dtpage: findPageRedo failed. (rc = (d) %d)", fsck_debug}, /* 552 */ { lrdo_DNRPFNDDTPGPGREDOFAIL, "LOGREDO: doNoRedoPage: type dtroot: findPageRedo failed. (rc = %s)", fsck_debug}, /* 553 */ { lrdo_DNRPFNDXTRTPGREDOFAIL, "LOGREDO: doNoRedoPage: type xtroot: findPageRedo failed. (rc = (d) %d)", fsck_debug}, /* 554 */ { lrdo_DNRPFNDXTPGPGREDOFAIL, "LOGREDO: doNoRedoPage: type xtpage: findPageRedo failed. (rc = (d) %d)", fsck_debug}, /* 555 */ { lrdo_DNRPUNKNOWNTYPE, "LOGREDO: doNoRedoPage: Unknown NoRedoPage record type.", fsck_debug}, /* 556 */ { lrdo_DNRIFNDNOREDORECFAIL, "LOGREDO: doNoRedoInoExt: findPageRedo failed. (rc = (d) %d)", fsck_debug}, /* 557 */ { lrdo_DUMPUNKNOWNTYPE, "LOGREDO: doUpdateMap: Unknown updateMap record type.", fsck_debug}, /* 558 */ { lrdo_DPRFBADSTBLENTRY, "LOGREDO: dtpg_resetFreeList: Invalid stbl entry.", fsck_debug}, /* 559 */ { lrdo_DPRFBADSLOTNXTIDX, "LOGREDO: dtpg_resetFreeList: Invalid slot next index.", fsck_debug}, /* 560 */ { lrdo_DRRFBADSTBLENTRY, "LOGREDO: dtrt_resetFreeList: Invalid stbl entry.", fsck_debug}, /* 561 */ { lrdo_DRRFBADSLOTNXTIDX, "LOGREDO: dtrt_resetFreeList: Invalid slot next index.", fsck_debug}, /* 562 */ { lrdo_MBMPBLKOUTRANGE, "LOGREDO: markBmap: Block number(s) out of range (start=0x0%llx, length=(d)%d).", fsck_debug}, /* 563 */ { lrdo_UPPGFNDPGREDOFAIL, "LOGREDO: updatePage: findPageRedo failed. (rc = (d) %d)", fsck_debug}, /* 564 */ { lrdo_UPPGBADINODESEGOFFSET, "LOGREDO: updatePage: type=INODE. Invalid segment offset. (offset = (d) %d)", fsck_debug}, /* 565 */ { lrdo_UPPGBREADFAIL1, "LOGREDO: updatePage: bread failed (1). (rc = (d) %d)", fsck_debug}, /* 566 */ { lrdo_UPPGBREADFAIL2, "LOGREDO: updatePage: bread failed (2). (rc = (d) %d)", fsck_debug}, /* 567 */ { lrdo_UPPGBREADFAIL3, "LOGREDO: updatePage: bread failed (3). (rc = (d) %d)", fsck_debug}, /* 568 */ { lrdo_UPPGBREADFAIL4, "LOGREDO: updatePage: bread failed (4). (rc = (d) %d)", fsck_debug}, /* 569 */ { lrdo_UPPGMIMPFAIL, "LOGREDO: updatePage: markImap failed. (rc = (d) %d)", fsck_debug}, /* 570 */ { lrdo_UPPGMBMPFAIL, "LOGREDO: updatePage: markBmap failed. (rc = (d) %d)", fsck_debug}, /* 571 */ { lrdo_UPPGDTRTRFLFAIL, "LOGREDO: updatePage: dtrt_resetFreeList failed. (rc = (d) %d)", fsck_debug}, /* 572 */ { lrdo_UPPGDTPGRFLFAIL, "LOGREDO: updatePage: dtpg_resetFreeList failed. (rc = (d) %d)", fsck_debug}, /* 573 */ { lrdo_UPPGSEDPFAIL, "LOGREDO: updatePage: saveExtDtPg failed. (rc = (d) %d)", fsck_debug}, /* 574 */ { lrdo_FEOLPGV1FAIL, "LOGREDO: fineEndOfLog: pageVal[1] failed (rc = (d) %d).", fsck_debug}, /* 575 */ { lrdo_FEOLPGV2FAIL, "LOGREDO: fineEndOfLog: pageVal[2] failed (rc = (d) %d).", fsck_debug}, /* 576 */ { lrdo_FEOLPGV3FAIL, "LOGREDO: fineEndOfLog: pageVal[3] failed (rc = (d) %d).", fsck_debug}, /* 577 */ { lrdo_FEOLPGV4FAIL, "LOGREDO: fineEndOfLog: pageVal[4] failed (rc = (d) %d).", fsck_debug}, /* 578 */ { lrdo_FEOLPGV4AFAIL, "LOGREDO: fineEndOfLog: pageVal[4(a)] failed (rc = (d) %d).", fsck_debug}, /* 579 */ { lrdo_PVGETPGFAIL, "LOGREDO: pageVal: getLogpage failed (pno = (d) %d, rc = (d) %d).", fsck_debug}, /* 580 */ { lrdo_SLPWRITEFAIL, "LOGREDO: setLogpage: Write log page failed (pno = (d) %d, rc = (d) %d).", fsck_debug}, /* 581 */ { lrdo_LRLOGWRAP, "LOGREDO: logRead: Log wrapped over itself (lognumread = (d) %d).", fsck_debug}, /* 582 */ { lrdo_LRREADFAIL, "LOGREDO: logRead: Read log page failed (pno = (d) %d, rc = (d) %d).", fsck_debug}, /* 583 */ { lrdo_LRMWFAIL1, "LOGREDO: logRead: MoveWords[1] failed (rc = (d) %d).", fsck_debug}, /* 584 */ { lrdo_LRMWFAIL2, "LOGREDO: logRead: MoveWords[2] failed (rc = (d) %d).", fsck_debug}, /* 585 */ { lrdo_MWREADFAIL, "LOGREDO: moveWords: getLogpage failed (pno = (d) %d, rc = (d) %d).", fsck_debug}, /* 586 */ { fsck_DASDLIMITSPRIMED, "DASD Limit has been primed for directories on the volume.", fsck_debug}, /* 587 */ { fsck_DASDUSEDPRIMED, "DASD Used has been primed for directories on the volume.", fsck_debug}, /* 588 */ { lrdo_LRMWFAIL3, "LOGREDO: logRead: Log data must not exceed LOGPSIZE (pno = (d) %d).", fsck_debug}, /* 589 */ { lrdo_LOGINUSE, "LOGREDO: Log is in use.", fsck_debug}, /* 590 */ { avail_for_debug_only_590, "*undefined*", fsck_debug}, /* 591 */ { avail_for_debug_only_591, "*undefined*", fsck_debug}, /* 592 */ { avail_for_debug_only_592, "*undefined*", fsck_debug}, /* 593 */ { avail_for_debug_only_593, "*undefined*", fsck_debug}, /* 594 */ { avail_for_debug_only_594, "*undefined*", fsck_debug}, /* 595 */ { avail_for_debug_only_595, "*undefined*", fsck_debug}, /* 596 */ { avail_for_debug_only_596, "*undefined*", fsck_debug}, /* 597 */ { avail_for_debug_only_597, "*undefined*", fsck_debug}, /* 598 */ { avail_for_debug_only_598, "*undefined*", fsck_debug}, /* 599 */ { avail_for_debug_only_599, "*undefined*", fsck_debug}, }; jfsutils-1.1.15.orig/libfs/fsckwsp.h0000644000000000000000000006644310340701413014225 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef H_FSCKWSP #define H_FSCKWSP #include "fscklog.h" #include #include #include #include #include #include #include "fsck_base.h" #include "fsckcbbl.h" /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * * fsck uses the structures and types in this file to define its workspace. * *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ /*---------------------------------------------------------------------------- * type dtree_Q_elem describes one node which is to be visited in the * traversal of a directory B+ Tree * */ struct dtreeQelem { struct dtreeQelem *next; struct dtreeQelem *prev; int64_t node_addr; pxd_t node_pxd; uint8_t node_key_len; UniChar node_key[JFS_NAME_MAX]; int8_t node_level; uint32_t node_size; }; #define dtreeQ_elem_length sizeof(struct dtreeQelem) /*---------------------------------------------------------------------------- * type tree_Q_elem describes one node which is to be visited in the * traversal of a non-directory B+ Tree * */ struct treeQelem { struct treeQelem *next; struct treeQelem *prev; int64_t node_addr; int64_t node_first_offset; pxd_t node_pxd; int8_t node_level; int8_t last_ext_uneven; }; #define treeQ_elem_length sizeof(struct treeQelem) /*---------------------------------------------------------------------------- * type dupall_blkrec describes range of aggregate blocks which has been * found to have more than 1 inode claiming to own it. * */ struct dupall_blkrec { int64_t first_blk; int64_t last_blk; uint8_t first_ref_resolved; uint8_t avail_byte; uint16_t owner_count; struct dupall_blkrec *next; struct dupall_blkrec *prev; }; #define dupall_blkrec_length sizeof(struct dupall_blkrec) /*---------------------------------------------------------------------------- * * Each (4096 byte) page in the block map describes 32768 * blocks in the aggregate. */ /* * the fsck Workspace Block Map control page * */ struct fsck_blk_map_hdr { /* * the 1st 1024 bytes are the clrbblks to fsck * communication area */ struct fsckcbbl_record cbblrec; /* 128 */ char avail_0[896]; /* 896 */ /* 1024 byte boundary */ /* * the next 2048 bytes are the fsck block map * header area */ struct { char eyecatcher[8]; /* 8 */ int32_t last_entry_pos; /* 4 */ int32_t next_entry_pos; /* 4 */ char start_time[20]; /* 20 */ char end_time[20]; /* 20 */ int32_t return_code; /* 4 */ char *super_buff_addr; /* 4 -- for the dump reader */ char *agg_record_addr; /* 4 -- for the dump reader */ char *bmap_record_addr; /* 4 -- for the dump reader */ char avail_1[8]; /* 8 */ int64_t fscklog_agg_offset; /* 8 */ int8_t fscklog_full; /* 1 */ int8_t fscklog_buf_allocated; /* 1 */ int8_t fscklog_buf_alloc_err; /* 1 */ char avail_2[1]; /* 1 */ int32_t num_logwrite_errors; /* 4 */ char avail_3[32]; /* 32 */ struct fscklog_error logerr[125]; /* 1920 = 120 * 16 */ } hdr; /* subtotal, 2048 bytes */ /* * the last 1024 bytes are available */ char avail_5[1024]; /* 1024 */ }; /* total: 4096 bytes */ #define fbmh_eyecatcher_string "wspblkmp" /* * a page in the fsck Workspace Block Map */ struct fsck_blk_map_page { uint32_t fsck_blkmap_words[1024]; /* 4096 bytes */ }; /*---------------------------------------------------------------- * structure blkmap_wspace describes the portion of the aggregate * record allocated for use when verifying * the aggregate block map. * */ struct blkmap_wspace { uint32_t dmap_map[LPERDMAP]; /* bit map of blk allocations */ int8_t dmap_wsp_tree[TREESIZE - LPERDMAP]; int8_t dmap_wsp_leafs[LPERDMAP]; int8_t L0_wsp_tree[CTLTREESIZE - LPERCTL]; int8_t L0_wsp_leafs[LPERCTL]; int8_t L1_wsp_tree[CTLTREESIZE - LPERCTL]; int8_t L1_wsp_leafs[LPERCTL]; int8_t L2_wsp_tree[CTLTREESIZE - LPERCTL]; int8_t L2_wsp_leafs[LPERCTL]; int64_t AG_free[MAXAG]; }; /*---------------------------------------------------------------- * structure fsck_iag_record describes one Inode Allocation * Group belonging to an inode table in * the aggregate * */ struct fsck_iag_record { uint32_t AG_num; uint32_t backed_inodes; uint32_t unused_backed_inodes; uint32_t unbacked_extents; }; #define iag_record_length sizeof(struct fsck_iag_record) /*---------------------------------------------------------------- * structure fsck_ag_record describes one Allocation Group * as it relates to an inode table in the * aggregate * */ struct fsck_ag_record { uint32_t backed_inodes; uint32_t unused_backed_inodes; int32_t frext_list_first; int32_t frext_list_last; int32_t frext_list_len; int32_t frino_list_first; int32_t frino_list_last; int32_t frino_list_len; int8_t frext_list_bad; int8_t frino_list_bad; char unused[14]; }; #define ag_record_length sizeof(struct fsck_ag_record) /*---------------------------------------------------------------- * structure fsck_iam_record describes one Inode Allocation Map * in the aggregate * */ struct fsck_iam_record { int64_t first_leaf_offset; /* offset of first leaf for imap inode */ int8_t imap_is_rootleaf; int8_t friag_list_bad; char unused[2]; int32_t bkd_inodes; /* count of backed inodes */ int32_t unused_bkd_inodes; /* count of available backed inodes */ int32_t num_iags; /* number of IAGs in the inode tbl */ int32_t friag_list_last; int32_t friag_list_len; struct fsck_iag_record *iag_tbl; /* ptr to info by iag */ struct fsck_ag_record *ag_tbl; /* ptr to info by ag */ }; #define iam_record_length sizeof(struct fsck_iam_record) /*---------------------------------------------------------------- * structure fsck_inode_record describes one inode belonging to * the aggregate or to a fileset * in the aggregate * */ /* * the possible values for inode_type * (since inode_type is 4 bits wide, valid range is 0-15) */ #define unused_inode 0 #define file_inode 1 #define strm_descr_inode 2 #define stream_inode 3 #define directory_inode 4 #define symlink_inode 5 #define block_special_inode 6 #define char_special_inode 7 #define FIFO_inode 8 #define SOCK_inode 9 #define metadata_inode 14 #define unrecognized_inode 15 #define add_direntry_extension 'A' #define rmv_direntry_extension 'R' #define rmv_badentry_extension 'B' #define parent_extension 'P' struct fsck_inode_ext_record { char ext_type; /* 1 : extens type (see constants above) */ unsigned ino_type:4; /* .5: see constants above * describes the inonum inode. * This is only interesting when * type is rmv_direntry_extension. */ unsigned unused_byte:20; /* 2.5: unused */ struct fsck_inode_ext_record *next; /* * 4 : addr next extension record */ uint32_t inonum; /* 4 : inode number */ }; /* * the inode record data */ struct fsck_inode_record { uint32_t inonum; /* 4.0 : key */ /* 3 : 24 flag bits */ unsigned in_use:1; unsigned selected_to_rls:1; unsigned crrct_link_count:1; unsigned crrct_prnt_inonum:1; unsigned adj_entries:1; unsigned cant_chkea:1; unsigned clr_ea_fld:1; unsigned clr_acl_fld:1; unsigned ignore_ea_blks:1; unsigned ignore_acl_blks:1; unsigned ignore_alloc_blks:1; unsigned inline_data_err:1; unsigned reconnect:1; unsigned unxpctd_prnts:1; unsigned badblk_inode:1; unsigned involved_in_dups:1; unsigned rebuild_dirtable:1; unsigned inlineea_on:1; unsigned inlineea_off:1; unsigned check_dir_index:1; unsigned avail_flagbits:4; /* end of flag bits */ int8_t inode_type; /* 1 : see constants above */ int32_t link_count; /* 4 : Stored link count is added to this. * Decremented for each observed link. */ uint32_t parent_inonum; /* 4 : If this is a directory inode and * the unxpctd_prnts bit is set, then * this field contains the inode number * stored in the parent field on disk. * Otherwise, this is the inode number * of the first observed parent. */ struct fsck_inode_ext_record *ext_rec; /* 4.0: extension record address */ }; #define inode_record_length sizeof(struct fsck_inode_record) #define inode_is_metadata( X ) \ ( (int8_t) ((X)->inode_type) == (int8_t) metadata_inode ) /*---------------------------------------------------------------------------- * type inode_tbl_t is an array of pointers to inode records * * There is one of these tables for each allocated inode extent which * has at least one inode in use. * */ struct inode_tbl_t { char eyecatcher[8]; /* 8.0 */ struct fsck_inode_record *inorectbl[32]; /* 128 */ }; #define inode_tbl_length sizeof( struct inode_tbl_t ) /*---------------------------------------------------------------------------- * type inode_ext_tbl_t is an array of pointers to inode tables * * There is one of these tables for each allocated IAG which * has at least one allocated extent with an inode in use. * */ struct inode_ext_tbl_t { char eyecatcher[8]; /* 8.0 */ struct inode_tbl_t *inotbl[128]; /* 512 */ }; #define inode_ext_tbl_length sizeof( struct inode_ext_tbl_t ) /*---------------------------------------------------------------------------- * type IAG_tbl_t is an array of pointers to inode extent tables * * There is one of these tables for each fileset in the aggregate, * and is allocated dynamically when the number of IAGs in the * fileset Inode Map is known. * */ struct IAG_tbl_t { char eyecatcher[8]; /* 8.0 */ struct inode_ext_tbl_t *inoext_tbl[1]; /* 4.0 */ }; /*---------------------------------------------------------------------------- * type wsp_ext_rec describes one extent of storage which fsck * has allocated for its workspace. * */ struct wsp_ext_rec { struct wsp_ext_rec *next; int8_t from_high_memory; int8_t for_logredo; char avail[2]; uint32_t extent_length; char *extent_addr; uint32_t last_byte_used; }; /*---------------------------------------------------------------------------- * type recon_buf_record describes one dnode I/O buffer used during * inode reconnect processing * */ struct recon_buf_record { dtpage_t dnode_buf; struct recon_buf_record *stack_next; int64_t dnode_blkoff; int64_t dnode_byteoff; char reserved[12]; }; /*---------------------------------------------------------------------------- * structure fsck_agg_record describes the aggregate */ struct fsck_agg_record { char eyecatcher[8]; uint32_t ondev_jlog_fsblk_length; int64_t ondev_jlog_fsblk_offset; int64_t ondev_wsp_byte_length; int64_t ondev_wsp_byte_offset; uint32_t ondev_wsp_fsblk_length; int64_t ondev_wsp_fsblk_offset; uint32_t ondev_fscklog_fsblk_length; int64_t ondev_fscklog_fsblk_offset; int64_t ondev_fscklog_byte_length; int64_t ondev_fscklog_byte_offset; uint32_t log2_blksize; uint32_t blksperpg; uint32_t log2_blksperpg; uint32_t log2_blksperag; int64_t sb_agg_fsblk_length; uint32_t inode_stamp; /* taken from the agg self inode, every * in-use, valid inode must have a * matching di_inostamp. */ int inode_count; /* num inodes owned by the aggregate */ int inodes_inuse; /* num aggregate nodes now in use */ int fset_inodes_inuse; /* num fileset inodes in use */ int fset_inodes_seen; /* num fileset inodes scanned. */ int fset_inode_count; /* num inodes in the filesets */ int64_t dup_block_count; /* num multiply-allocated * blocks seen */ int64_t unresolved_1stref_count; /* num unresolved first * references to multiply allocated * blocks */ char aggrec_rsvd0[4]; int64_t blocks_for_inodes; /* by fsck's count */ int64_t blocks_for_files; /* by fsck's count */ int64_t blocks_for_dirs; /* by fsck's count */ int64_t blocks_for_eas; /* by fsck's count */ int64_t blocks_for_acls; /* by fsck's count */ uint64_t inodes_in_aggregate; /* by fsck's count */ uint64_t files_in_aggregate; /* by fsck's count */ uint64_t dirs_in_aggregate; /* by fsck's count */ int64_t free_blocks_in_aggregate; /* by fsck's count */ int64_t blocks_used_in_aggregate; /* by fsck's count */ uint64_t blocks_this_fset; /* by fsck's count */ int32_t logredo_rc; /* logredo return code */ int32_t logformat_rc; /* logformat return code */ char aggrec_rsvd2[8]; struct { /* data for the current inode */ char eyecatcher[8]; int64_t all_blks; /* all blocks allocated */ int64_t data_blks; /* blocks allocated to data */ uint64_t data_size; /* byte offset of last data if file */ int64_t ea_blks; /* blocks allocated to EAs */ int64_t acl_blks; /* blocks allocated to ACLs */ uint16_t ea_inline; uint16_t inline_ea_offset; uint16_t inline_ea_length; uint16_t acl_inline; uint16_t inline_acl_offset; uint16_t inline_acl_length; uint16_t in_inode_data_length; /* length of inline data or of * xad list in the inode */ char aggrec_rsvd4[2]; } this_inode; struct wsp_ext_rec *recon_buf_extent; struct recon_buf_record *recon_buf_stack; char agg_imap_eyecatcher[8]; struct fsck_iam_record agg_imap; /* describes the aggregate imap */ char fset_imap_eyecatcher[8]; struct fsck_iam_record fset_imap; /* describes the fileset imap */ uint32_t num_ag; /* number of AGs in the aggregate */ int ag_blk_size; /* aggregate block size */ short int aggrec_rsvd6[1]; char delim_char; /* path delimiter char */ /* unicharacter equivalents */ UniChar *UniChar_lsfn_name; /* equiv to lost+found */ UniChar *UniChar_LSFN_NAME; /* equiv to LOST+FOUND */ /* end of unicharacter equivalents */ uint32_t lsfn_inonum; /* inode number of /lost+found/ */ uint32_t avail_inonum; /* inode number of an inode * observed to be allocated and not * in use (if any) */ short int parm_options[16]; /* parms specified */ char aggrec_rsvd7[2]; /* pad to quadword boundary */ char effective_msg_level; char aggrec_rsvd8[7]; /* pad to quadword boundary */ char flags_eyecatcher[8]; /* 4 bytes of flags */ unsigned parm_options_nologredo:1; /* first byte, first nibble */ unsigned processing_readonly:1; unsigned processing_readwrite:1; unsigned messaging_verbose:1; unsigned superblk_ok:1; /* first byte, second nibble */ unsigned aggregate_is_mounted:1; unsigned ag_modified:1; unsigned ag_dirty:1; unsigned lsfn_ok:1; /* second byte, first nibble */ unsigned cant_write_primary_sb:1; unsigned cant_write_secondary_sb:1; unsigned cant_write_primary_ait:1; unsigned nonmeta_write_error_msg:1; /* second byte, second nibble */ unsigned fsck_is_done:1; unsigned device_is_open:1; unsigned device_is_locked:1; unsigned primary_ait_4part1:1; /* third byte, first nibble */ unsigned primary_ait_4part2:1; unsigned ait_aim_update_failed:1; unsigned corrections_needed:1; unsigned corrections_approved:1; /* third byte, second nibble */ unsigned avail_inode_found:1; unsigned initializing_fscklog:1; unsigned warning_pending:1; unsigned high_mem_allocated:1; /* fourth byte, first nibble */ unsigned rootdir_rebuilt:1; unsigned stdout_redirected:1; unsigned parm_options_logredo_only:1; unsigned unused_4_2:4; /* end of flag bytes */ int path_buffer_length; /* length of path_buffer */ char *path_buffer; /* storage allocated (if any) for * assembling the string containing * an inode's path for a message */ xtpage_t *prim_nodeptr; /* storage allocated (if any) for * an xtpage of an inode in the Primary Agg * Inode table */ xtpage_t *second_nodeptr; /* storage allocated (if any) for * an xtpage of an inode in the Secondary * Agg Inode table */ int64_t lowest_valid_fset_datablk; /* the lowest (aggregate * blocksized) block in the aggregate * AFTER the blocks used for initial * metadata */ int64_t highest_valid_fset_datablk; /* the highest (aggregate * blocksized) block in the aggregate before * the beginning of the fsck workspace */ struct fsck_inode_ext_record *free_inode_extens; /* available workspace inode record * extensions. */ struct fsck_inode_ext_record *inode_reconn_extens; /* list of inode record * extensions describing the directory * entries to be added when reconnecting * inodes */ struct dtreeQelem *dtreeQ_front; struct dtreeQelem *dtreeQ_back; struct dtreeQelem *free_dtreeQ; /* available dtree stack elements */ struct treeQelem *treeQ_front; struct treeQelem *treeQ_back; struct treeQelem *free_treeQ; /* available tree stack elements */ struct dupall_blkrec *dup_alloc_lst; /* list of multiply allocated blocks */ struct dupall_blkrec *free_dupall_blkrec; /* free dupall_blkrec records */ struct wsp_ext_rec *wsp_extent_list; /* linked list of records describing * the workspace extents. */ char aggrec_rsvda[4]; /* pad to quadword boundary */ char AIT_eyecatcher[8]; /* */ struct inode_tbl_t *AIT_ext0_tbl; /* ptr to table for Agg Inode Extent 0 */ int32_t agg_last_inoidx; /* used for find first, find next */ char FSIT_eyecatcher[8]; struct IAG_tbl_t *FSIT_IAG_tbl; /* ptr to table for FSet IAGs */ int32_t fs_last_iagidx; /* used for find first, find next */ int32_t fs_last_extidx; /* used for find first, find next */ int32_t fs_last_inoidx; /* used for find first, find next */ struct { /* data for accessing all allocated inodes in an * inode table sequentially */ char eyecatcher[8]; int32_t this_iagnum; /* ordinal of the current iag */ uint32_t this_inoidx; /* ordinal of the current inode */ uint32_t rootleaf_imap; /* 0 => not a rootleaf imap */ xtpage_t *this_mapleaf; /* current mapleaf in buffer */ int32_t iagidx_now; /* index into current mapleaf */ int32_t iagidx_max; struct iag *iagptr; /* current iag in buffer */ uint32_t extidx_now; /* index into current iag */ uint32_t extidx_max; struct dinode *extptr; /* current inode extent in buffer */ uint32_t inoidx_now; /* index into current inode extent */ uint32_t inoidx_max; struct dinode *inoptr; /* current inode in buffer */ } fais; /* (For Allocated Inodes Sequentially */ char aggrec_rsvde[4]; /* pad to quadword boundary */ /* * The fsck I/O buffer information is below. Certain information * is kept for each of the buffers: * * %_buf_ptr = buffer address * %_buf_length = buffer length * %_buf_data_len = length of data read into buffer at last read * %_agg_offset = byte offset in aggregate of buffer contents * %_buf_write = flag: !0 => buffer contents modified since * last write to device * * where % = {blkmp, iag, mapleaf, ino, node, wsp} * * * N.B. To ensure proper boundary alignment, each IO buffersize * must be an even number of pages (i.e. 4096 byte pages). * */ /* ****** very large, multi purpose BUFFER ***** */ #define VLARGE_BUFSIZE (2 * MEMSEGSIZE) #define NOT_CURRENTLY_USED 0 #define USED_FOR_EA_BUF 1 /* phase 1 late */ #define USED_FOR_DIRPAGE_BUFS 2 /* phase 6 */ #define USED_FOR_INOEXT_BUF 3 /* phase 1 early, phase 7 */ #define USED_FOR_SUPER_VALIDATION 4 /* initial processing */ char vlarge_info_eyecatcher[8]; char *vlarge_buf_ptr; uint32_t vlarge_buf_length; uint32_t vlarge_current_use; char aggrec_rsvdf[4]; /* pad to quadword boundary */ /* ****** fsck log BUFFER ***** */ #define FSCKLOG_BUFSIZE (2 * BYTESPERPAGE) char fscklog_info_eyecatcher[8]; struct fsck_blk_map_page *fscklog_buf_ptr; uint32_t fscklog_buf_length; uint32_t fscklog_buf_data_len; int64_t fscklog_agg_offset; int64_t fscklog_log_offset; struct fscklog_entry_hdr *fscklog_last_msghdr; int8_t fscklog_full; int8_t fscklog_buf_allocated; int8_t fscklog_buf_alloc_err; char aggrec_rsvdg[5]; /* pad to quadword boundary */ /* ****** fsck block map BUFFER ***** * * N.B. If the fsck workspace block map is instantiated in * dynamic storage, then the following describe the entire * block map. However, if the fsck workspace block map * is instantiated within the aggregate, then the following * describe the I/O buffer associated with it. */ #define BLKMP_IO_BUFSIZE 4 * BYTESPERPAGE char blkmp_info_eyecatcher[8]; struct fsck_blk_map_page *blkmp_buf_ptr; uint32_t blkmp_buf_length; uint32_t blkmp_buf_data_len; int64_t blkmp_agg_offset; int64_t blkmp_blkmp_offset; int8_t blkmp_buf_write; struct fsck_blk_map_hdr *blkmp_ctlptr; int32_t blkmp_pagecount; /* ****** BLOCK MAP DMAP PAGE I/O BUFFER ****** */ /* * note: The EA buffer is treated differently from the * other I/O buffers allocated for fsck. * Specifically, * * - it is larger than any other fsck I/O buffer * (sized to accomodate the largest legal ea) * - since it is exactly 1 memory segment, it is * not allocated as a normal wsp extent (described * by an fer on the wsp_extent_list) but is * allocated as a special case. * - this buffer is released as soon as phase 1 is * completed (does not persist until fsck has * finished processing) * - BTW the EA data is read by fsck, but never * written. */ #define EA_IO_BUFSIZE 16*BYTESPERPAGE char ea_info_eyecatcher[8]; char *ea_buf_ptr; uint32_t ea_buf_length; uint32_t ea_buf_data_len; int64_t ea_agg_offset; char aggrec_rsvdh[4]; /* pad to quadword boundary */ /* ****** IAG I/O BUFFER ****** */ /* * note: This is not actually a unique buffer. Since * the Inode Allocation Maps verification is * completed before the Block Allocation Map * verification, buffer space is allocated and * used first for Inode Alloc Map verification * processing and then for Block Allocation Map * verification. */ #define IAG_IO_BUFSIZE 4 * BYTESPERPAGE char iag_info_eyecatcher[8]; char *iag_buf_ptr; uint32_t iag_buf_length; uint32_t iag_buf_data_len; int64_t iag_agg_offset; uint32_t iag_buf_1st_inode; /* inode number of 1st in buffer */ uint32_t iag_fsnum; int8_t iag_for_aggregate; int8_t iag_which_it; int8_t iag_buf_write; char aggrec_rsvdi[9]; /* pad to quadword boundary */ /* ****** MAP CONTROL PAGE I/O BUFFER ****** */ #define MAPCTL_IO_BUFSIZE BYTESPERPAGE char mapctl_info_eyecatcher[8]; char *mapctl_buf_ptr; uint32_t mapctl_buf_length; uint32_t mapctl_buf_data_len; int64_t mapctl_agg_offset; int8_t mapctl_buf_write; char aggrec_rsvdk[3]; /* pad to quadword boundary */ /* ****** MAP LEAF I/O BUFFER ****** */ #define MAPLEAF_IO_BUFSIZE \ ((((XTPAGE_SIZE*4)+BYTESPERPAGE-1)/BYTESPERPAGE)*BYTESPERPAGE) char maplf_info_eyecatcher[8]; char *mapleaf_buf_ptr; uint32_t mapleaf_buf_length; uint32_t mapleaf_buf_data_len; int64_t mapleaf_agg_offset; int8_t mapleaf_for_aggregate; int8_t mapleaf_which_it; int8_t mapleaf_buf_write; char aggrec_rsvdm[1]; /* pad to quadword boundary */ /* ****** BLOCK MAP LEVEL PAGE I/O BUFFER ****** */ #define BMAPLV_IO_BUFSIZE BYTESPERPAGE char bmplv_info_eyecatcher[8]; char *bmaplv_buf_ptr; uint32_t bmaplv_buf_length; uint32_t bmaplv_buf_data_len; int64_t bmaplv_agg_offset; int64_t bmaplv_logical_offset; int8_t bmaplv_current_level; int8_t bmaplv_buf_write; char aggrec_rsvdo[10]; /* pad to quadword boundary */ /* ****** BLOCK MAP DMAP PAGE I/O BUFFER ****** */ /* * note: This is not actually a unique buffer. Since * the Inode Allocation Maps verification is * completed before the Block Allocation Map * verification, buffer space is allocated and * used first for Inode Alloc Map verification * processing and then for Block Allocation Map * verification. */ #define BMAPDMP_IO_BUFSIZE IAG_IO_BUFSIZE char bmpdm_info_eyecatcher[8]; char *bmapdm_buf_ptr; uint32_t bmapdm_buf_length; uint32_t bmapdm_buf_data_len; int64_t bmapdm_agg_offset; int64_t bmapdm_logical_offset; int8_t bmapdm_buf_write; char aggrec_rsvdq[11]; /* pad to quadword boundary */ /* ****** INODE I/O BUFFER ****** */ #define INODE_IO_BUFSIZE \ (((INODE_EXTENT_SIZE+BYTESPERPAGE-1)/BYTESPERPAGE)*BYTESPERPAGE) char inobuf_info_eyecatcher[8]; char *ino_buf_ptr; uint32_t ino_buf_length; uint32_t ino_buf_data_len; int64_t ino_buf_agg_offset; /* agg byte offset of buf contents */ uint32_t ino_buf_1st_ino; /* 1st inode number in buffer */ uint32_t ino_fsnum; pxd_t ino_ixpxd; int8_t ino_for_aggregate; int8_t ino_which_it; int8_t ino_buf_write; char aggrec_rsvds[1]; /* pad to quadword boundary */ /* ****** INTERNAL/LEAF NODE I/O BUFFER ****** */ #define NODE_IO_BUFSIZE \ ((((XTPAGE_SIZE*4)+BYTESPERPAGE-1)/BYTESPERPAGE)*BYTESPERPAGE) char nodbuf_info_eyecatcher[8]; char *node_buf_ptr; uint32_t node_buf_length; uint32_t node_buf_data_len; int64_t node_agg_offset; int8_t node_buf_write; char aggrec_rsvdu[3]; /* pad to quadword boundary */ /* ****** INTERNAL/LEAF DNODE I/O BUFFER ****** */ char dnodbuf_info_eyecatcher[8]; char *dnode_buf_ptr; uint32_t dnode_buf_length; uint32_t dnode_buf_data_len; int64_t dnode_agg_offset; int8_t dnode_buf_write; char aggrec_rsvduu[3]; /* pad to quadword boundary */ /* **************************** instantiation of imap AG tables */ char agg_AGTbl_eyecatcher[8]; char aggrec_rsvdw[8]; /* pad to quadword boundary */ struct fsck_ag_record agg_AGTbl[MAXAG]; char fset_AGTbl_eyecatcher[8]; char aggrec_rsvdy[8]; /* pad to quadword boundary */ struct fsck_ag_record fset_AGTbl[MAXAG]; /* ********************** instantiation of imap IAG workspace */ char amap_eyecatcher[8]; uint32_t amap[EXTSPERIAG]; /* 512 : inode allocation map */ char aggrec_rsvd00[8]; /* pad to quadword boundary */ char fextsumm_eyecatcher[8]; int32_t fextsumm[SMAPSZ]; /* 16 : free extent summary map */ char aggrec_rsvd02[8]; /* pad to quadword boundary */ char finosumm_eyecatcher[8]; int32_t finosumm[SMAPSZ]; /* 16 : free inode summary map */ /* ********************** instantiation of blockmap workspace */ struct blkmap_wspace blkmap_wsp; }; #endif jfsutils-1.1.15.orig/libfs/fssubs.c0000644000000000000000000002213310663326207014045 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #if HAVE_MNTENT_H #include #undef HAVE_GETMNTINFO /* we don't want both */ #endif #if HAVE_GETMNTINFO #include #include #include #endif #if HAVE_SYS_STATVFS_H #include #define STATFS statvfs #define NOWAIT ST_NOWAIT #else #define STATFS statfs #define NOWAIT MNT_NOWAIT #endif #include "devices.h" #include "message.h" /* forward references */ int Is_Root_Mounted_RO(void); /*-------------------------------------------------------------------- * NAME: Is_Root_Mounted_RO * * FUNCTION: Determine if root is mounted read only * * RETURNS: * 0 if root is not mounted READ ONLY * > 0 if root is mounted READ ONLY * * NOTES: borrowed some of this routine from e2fsck */ int Is_Root_Mounted_RO() { int fd, rc = 0; #define TEST_FILE "/.ismount-test-file" fd = open(TEST_FILE, O_RDWR | O_CREAT, S_IRWXU); if (fd < 0) { if (errno == EROFS) rc = MSG_JFS_VOLUME_IS_MOUNTED_RO; } else { close(fd); (void) unlink(TEST_FILE); } return rc; } #if HAVE_MNTENT_H /*-------------------------------------------------------------------- * NAME: Is_Device_Mounted * * FUNCTION: Determine if the device specified is mounted. * * PRE CONDITIONS: Device_Name must be the name of the device. * * POST CONDITIONS: * * PARAMETERS: Device_Name - The name of the device. * * RETURNS: * 0 if the device is not mounted. * > 0 if the device is mounted or an error occurs. * * NOTES: borrowed some of this routine from e2fsck */ int Is_Device_Mounted(char *Device_Name) { FILE *Mount_Records; /* Pointer for system's mount records */ struct mntent *Mount_Data; /* Holds data for entry in mount list */ int Mounted_RC = 0; /* Holds return code. */ int root_not_jfs = 0; #define ROOT_DIR "/" /* Attempt to open /proc/mounts for access. */ if ((Mount_Records = setmntent("/proc/mounts", "r")) == NULL) { /* Unable to access list of mounted devices in /proc/mounts! */ /* Attempt to open /etc/mtab for access. */ if ((Mount_Records = setmntent(MOUNTED, "r")) == NULL) { /* Unable to access list of mounted devices in /etc/mtab! */ return MSG_JFS_MNT_LIST_ERROR; } } /* Attempt to find specified device name in mount records */ while ((Mount_Data = getmntent(Mount_Records)) != NULL) { /* * There may be more than one entry for /. Trust the * latest one */ if (strcmp(ROOT_DIR, Mount_Data->mnt_dir) == 0) { if (strcmp("jfs", Mount_Data->mnt_type) == 0) root_not_jfs = 0; else root_not_jfs = 1; } if (strcmp(Device_Name, Mount_Data->mnt_fsname) == 0) break; } if (Mount_Data == 0) { #ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */ struct stat st_root, st_file; /* * If the specified device name was not found in the mount records, * do an extra check to see if this is the root device. We can't * trust /etc/mtab, and /proc/mounts will only list /dev/root for * the root filesystem. Argh. Instead we will check if the given * device has the same major/minor number as the device that the * root directory is on. */ if (stat("/", &st_root) == 0 && stat(Device_Name, &st_file) == 0) { if (st_root.st_dev == st_file.st_rdev) { if (Is_Root_Mounted_RO()) Mounted_RC = MSG_JFS_VOLUME_IS_MOUNTED_RO; else Mounted_RC = MSG_JFS_VOLUME_IS_MOUNTED; /* * Make a best effort to ensure that * the root file system type is jfs */ if (root_not_jfs) /* is mounted, found type, is not type jfs */ Mounted_RC = MSG_JFS_NOT_JFS; } } #endif } else { if (strcmp(Mount_Data->mnt_type, "jfs") == 0) { /* is mounted, is type jfs */ Mounted_RC = MSG_JFS_VOLUME_IS_MOUNTED; /* See if we're mounted 'ro' (read only) */ /* If we are booting on a jfs device, hasmntopt */ /* may return 'rw' even though we're mounted 'ro' */ /* so let's check for that situation */ if (!strcmp(Mount_Data->mnt_dir, "/")) { if (Is_Root_Mounted_RO()) Mounted_RC = MSG_JFS_VOLUME_IS_MOUNTED_RO; } else { /* Check to see if the 'ro' option is set */ if (hasmntopt(Mount_Data, MNTOPT_RO)) Mounted_RC = MSG_JFS_VOLUME_IS_MOUNTED_RO; } } else { /* is mounted, is not type jfs */ Mounted_RC = MSG_JFS_NOT_JFS; } } /* Close the stream. */ endmntent(Mount_Records); /* Return the appropriate value. */ return Mounted_RC; } /*-------------------------------------------------------------------- * NAME: Is_Device_Type_JFS * * FUNCTION: Determine if the device specified is of type JFS in /etc/fstab * * PRE CONDITIONS: Device_Name must be the name of the device. * * POST CONDITIONS: * * PARAMETERS: Device_Name - The name of the device. * * RETURNS: * 0 if the device is type JFS in /etc/fstab * > 0 if the device is not type JFS or an error occurs. * */ int Is_Device_Type_JFS(char *Device_Name) { FILE *FS_Info_File; /* Pointer for system's mount records */ struct mntent *FS_Data; /* Holds data for entry in mount list */ int Is_JFS_RC = 0; /* Holds return code. */ /* Attempt to open /etc/fstab for access. */ if ((FS_Info_File = setmntent(_PATH_MNTTAB, "r")) == NULL) { /* Unable to access mount description file /etc/fstab! */ return MSG_JFS_MNT_LIST_ERROR; } /* Attempt to find specified device name in filesystem records */ while ((FS_Data = getmntent(FS_Info_File)) != NULL) if (strcmp(Device_Name, FS_Data->mnt_fsname) == 0) break; if (FS_Data) { if (strcmp(FS_Data->mnt_type, "jfs") != 0) /* is mounted, is type jfs */ Is_JFS_RC = MSG_JFS_NOT_JFS; } else { Is_JFS_RC = MSG_JFS_DEV_NOT_IN_TABLE; } /* Close the stream. */ endmntent(FS_Info_File); /* Return the appropriate value. */ return Is_JFS_RC; } #endif /* HAVE_MNTENT_H */ #if HAVE_GETMNTINFO /*-------------------------------------------------------------------- * NAME: Is_Device_Mounted * * FUNCTION: Determine if the device specified is mounted. * * PRE CONDITIONS: Device_Name must be the name of the device. * * POST CONDITIONS: * * PARAMETERS: Device_Name - The name of the device. * * RETURNS: * 0 if the device is not mounted. * > 0 if the device is mounted or an error occurs. * * NOTES: borrowed some of this routine from e2fsck */ int Is_Device_Mounted(char *Device_Name) { struct STATFS *mp; int len, n; char *s1, *s2; n = getmntinfo(&mp, NOWAIT); if (!n) return MSG_JFS_MNT_LIST_ERROR; len = sizeof (_PATH_DEV) - 1; s1 = Device_Name; if (strncmp(_PATH_DEV, s1, len) == 0) s1 += len; while (--n >= 0) { s2 = mp->f_mntfromname; if (strncmp(_PATH_DEV, s2, len) == 0) { s2 += len - 1; *s2 = 'r'; } if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) { if (strcmp(mp->f_fstypename, "jfs") == 0) { /* is mounted, is type jfs */ /* XXX check for read-only somehow */ return MSG_JFS_VOLUME_IS_MOUNTED; } else { /* is mounted, is not type jfs */ return MSG_JFS_NOT_JFS; } } ++mp; } return 0; } /*-------------------------------------------------------------------- * NAME: Is_Device_Type_JFS * * FUNCTION: Determine if the device specified is of type JFS in /etc/fstab * * PRE CONDITIONS: Device_Name must be the name of the device. * * POST CONDITIONS: * * PARAMETERS: Device_Name - The name of the device. * * RETURNS: * 0 if the device is type JFS in /etc/fstab * > 0 if the device is not type JFS or an error occurs. * */ int Is_Device_Type_JFS(char *Device_Name) { struct STATFS *mp; int len, n; char *s1, *s2; n = getmntinfo(&mp, NOWAIT); if (!n) return MSG_JFS_MNT_LIST_ERROR; len = sizeof (_PATH_DEV) - 1; s1 = Device_Name; if (strncmp(_PATH_DEV, s1, len) == 0) s1 += len; while (--n >= 0) { s2 = mp->f_mntfromname; if (strncmp(_PATH_DEV, s2, len) == 0) { s2 += len - 1; *s2 = 'r'; } if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) { if (strcmp(mp->f_fstypename, "jfs") == 0) { /* is mounted, is type jfs */ /* XXX check for read-only somehow */ return 0; } else { /* is mounted, is not type jfs */ return MSG_JFS_NOT_JFS; } } ++mp; } return MSG_JFS_DEV_NOT_IN_TABLE; } #endif /* HAVE_GETMNTINFO */ jfsutils-1.1.15.orig/libfs/inode.c0000644000000000000000000002105210340701413013621 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include "jfs_types.h" #include "jfs_endian.h" #include "jfs_filsys.h" #include "jfs_dinode.h" #include "devices.h" #include "jfs_imap.h" #include "inode.h" #include "utilsubs.h" #include "message.h" /* * NAME: ujfs_rwinode * * FUNCTION: Read or write a specific aggregate or fileset inode. * * PRE CONDITIONS: * * POST CONDITIONS: * * PARAMETERS: * fp - open port for device to read/write * di - For read, filled in with inode read. For write, contains * inode to write. * inum - number of inode to read/write * mode - are we reading or writing * fs_block_size - Block size for the aggregate * which_table - Aggregate Inode number describing Inode Allocation Map * which describes the specified inode. * * NOTES: * Eventually when we have multiple filesets per aggregate we will need to * determine the correct inode extent where the inode exists, and read the * self inode to determine where that inode extent is on disk. However, * our first release we only support one fileset per aggregate, so we will * never have more than NUM_INODE_PER_EXTENT aggregate inodes. This first * release of this function simply reads the inode from the necessary * offset into the Aggregate Inode Table. * * RECOVERY OPERATION: * * DATA STRUCTURES: * * RETURNS: 0 for success * Failure, any other value */ int ujfs_rwinode(FILE *fp, struct dinode *di, uint32_t inum, int32_t mode, int32_t fs_block_size, uint32_t which_table, uint32_t sb_flag) { struct dinode map_inode; int rc; int64_t inode_extent_address, inode_address; int64_t map_inode_address; uint32_t iag_key; int32_t iag_inode_num, inode_ext_index; struct iag iag_for_inode; int64_t iag_address; int32_t l2nbperpage = log2shift(PSIZE / fs_block_size); /* * Determine disk address for the inode to be read or written. * * If the inode we want is from the Aggregate Inode Table we can just * determine the address for the inode directly since we know where this * table lives. If the inode we want is from the Fileset Inode Table we * will need to read the Fileset Inode first and then follow its B+-tree to * determine where the inode we want is. */ if (which_table == AGGREGATE_I) { /* * Since the Aggregate Inode Table is just one inode extent for the * first release we won't attempt to read an inode which is outside of * this extent */ if (inum >= NUM_INODE_PER_EXTENT) { fprintf(stderr, "Internal error: %s(%d): Aggregate inode out of range (%d)\n", __FILE__, __LINE__, inum); return ERROR_INVALID_ACCESS; } inode_address = (inum * sizeof (struct dinode)) + AGGR_INODE_TABLE_START; } else if (which_table == FILESYSTEM_I) { /* * Find the IAG which describes this inode. */ iag_key = INOTOIAG(inum); /* * Read Fileset inode describing the Fileset Inode Allocation Map so we * have the B+-tree information */ map_inode_address = AGGR_INODE_TABLE_START + (which_table * sizeof (struct dinode)); rc = ujfs_rw_diskblocks(fp, map_inode_address, sizeof (struct dinode), &map_inode, GET); /* swap if on big endian machine */ ujfs_swap_dinode(&map_inode, GET, sb_flag); if (rc != 0) return (rc); /* * Get address for IAG describing this inode */ rc = ujfs_rwdaddr(fp, &iag_address, &map_inode, IAGTOLBLK(iag_key, l2nbperpage), GET, fs_block_size); if (rc != 0) return (rc); /* * Read iag which describes the specified inode. */ rc = ujfs_rw_diskblocks(fp, iag_address, sizeof (struct iag), &iag_for_inode, GET); /* swap if on big endian machine */ ujfs_swap_iag(&iag_for_inode); if (rc != 0) return (rc); /* * Determine which inode within the found IAG is being referenced */ iag_inode_num = inum % NUM_INODE_PER_IAG; /* * Find the inode extent descriptor within the found IAG which describes * the inode extent containing the specified inode. */ inode_ext_index = iag_inode_num / NUM_INODE_PER_EXTENT; /* * From the correct inode extent descriptor in the IAG we can determine * the disk address for the specified inode. */ inode_extent_address = addressPXD(&(iag_for_inode.inoext[inode_ext_index])); inode_extent_address *= fs_block_size; inode_address = (inum % NUM_INODE_PER_EXTENT * sizeof (struct dinode)) + inode_extent_address; } else { fprintf(stderr, "Internal error: %s(%d): Bad map inode number (%d)\n", __FILE__, __LINE__, which_table); return ERROR_INVALID_HANDLE; } /* * Now read/write the actual inode */ /* swap if on big endian machine */ if (mode == PUT) ujfs_swap_dinode(di, PUT, sb_flag); rc = ujfs_rw_diskblocks(fp, inode_address, sizeof (struct dinode), di, mode); /* swap if on big endian machine */ ujfs_swap_dinode(di, GET, sb_flag); return rc; } /* * NAME: ujfs_rwdaddr * * FUNCTION: read/write offset from/to an inode * * PRE CONDITIONS: * * POST CONDITIONS: * * PARAMETERS: * fp - device file descriptor * offset - where we put the offset that corresponds to * di - disk inode to get offset from * lbno - logical block number * mode - GET or PUT (read/write block from/to inode) * fs_block_size - block size for aggregate * * NOTES: * * RECOVERY OPERATION: * * DATA STRUCTURES: * * RETURNS: 0 for success * Failure, any other value */ int ujfs_rwdaddr(FILE *fp, int64_t * offset, struct dinode * di, int64_t lbno, int32_t mode, int32_t fs_block_size) { xad_t *disk_extent; int64_t disk_extent_offset; xtpage_t *page; int32_t lim, base, index; int rc; int32_t cmp; char buffer[PSIZE]; int64_t offset64; page = (xtpage_t *) & (di->di_btroot); descend: /* Binary search */ for (base = XTENTRYSTART, lim = page->header.nextindex - XTENTRYSTART; lim; lim >>= 1) { index = base + (lim >> 1); offset64 = offsetXAD(&(page->xad[index])); cmp = (lbno >= offset64 + lengthXAD(&(page->xad[index]))) ? 1 : (lbno < offset64) ? -1 : 0; if (cmp == 0) { /* HIT! */ if (page->header.flag & BT_LEAF) { *offset = (addressXAD(&(page->xad[index])) + (lbno - offsetXAD(&(page->xad[index])))) * fs_block_size; return 0; } else { rc = ujfs_rw_diskblocks(fp, addressXAD(&(page->xad[index])) * fs_block_size, PSIZE, buffer, GET); /* swap if on big endian machine */ ujfs_swap_xtpage_t((xtpage_t *) buffer); if (rc) { fprintf(stderr, "Internal error: %s(%d): Error reading btree node\n", __FILE__, __LINE__); return rc; } page = (xtpage_t *) buffer; goto descend; } } else if (cmp > 0) { base = index + 1; --lim; } } if (page->header.flag & BT_INTERNAL) { /* Traverse internal page, it might hit down there * If base is non-zero, decrement base by one to get the parent * entry of the child page to search. */ index = base ? base - 1 : base; rc = ujfs_rw_diskblocks(fp, addressXAD(&(page->xad[index])) * fs_block_size, PSIZE, buffer, GET); /* swap if on big endian machine */ ujfs_swap_xtpage_t((xtpage_t *) buffer); if (rc) { fprintf(stderr, "Internal error: %s(%d): Error reading btree node\n", __FILE__, __LINE__); return rc; } page = (xtpage_t *) buffer; goto descend; } /* Not found! */ fprintf(stderr, "Internal error: %s(%d): Block %lld not found!\n", __FILE__, __LINE__, (long long) lbno); return EINVAL; /* * This is really stupid right now, doesn't understand multiple extents */ switch (mode) { case GET: disk_extent = &(((xtpage_t *) & (di->di_DASD))->xad[XTENTRYSTART]); disk_extent_offset = addressXAD(disk_extent); *offset = (disk_extent_offset + lbno) * fs_block_size; break; case PUT: fprintf(stderr, "Internal error: %s(%d): does not handle PUT\n", __FILE__, __LINE__); return EPERM; break; default: return EINVAL; } return 0; } jfsutils-1.1.15.orig/libfs/inode.h0000644000000000000000000000206010340701413013624 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef H_INODE #define H_INODE #include #include "devices.h" int ujfs_rwinode(FILE *, struct dinode *, uint32_t, int32_t, int32_t, uint32_t, uint32_t); int ujfs_rwdaddr(FILE *, int64_t *, struct dinode *, int64_t, int32_t, int32_t); #endif jfsutils-1.1.15.orig/libfs/jfs_endian.c0000644000000000000000000004574310522471431014646 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include "jfs_endian.h" #include "devices.h" #if __BYTE_ORDER == __BIG_ENDIAN /*-------------------------------------------------------------------- * NAME: ujfs_swap_dbmap * * FUNCTION: Change endianness of dbmap structure * * PARAMETERS: * dbm_t - dbmap structure * * RETURNS: NONE */ void ujfs_swap_dbmap(struct dbmap *dbm_t) { int i; /* struct dbmap in jfs_dmap.h */ dbm_t->dn_mapsize = __le64_to_cpu(dbm_t->dn_mapsize); dbm_t->dn_nfree = __le64_to_cpu(dbm_t->dn_nfree); dbm_t->dn_l2nbperpage = __le32_to_cpu(dbm_t->dn_l2nbperpage); dbm_t->dn_numag = __le32_to_cpu(dbm_t->dn_numag); dbm_t->dn_maxlevel = __le32_to_cpu(dbm_t->dn_maxlevel); dbm_t->dn_maxag = __le32_to_cpu(dbm_t->dn_maxag); dbm_t->dn_agpref = __le32_to_cpu(dbm_t->dn_agpref); dbm_t->dn_aglevel = __le32_to_cpu(dbm_t->dn_aglevel); dbm_t->dn_agheigth = __le32_to_cpu(dbm_t->dn_agheigth); dbm_t->dn_agwidth = __le32_to_cpu(dbm_t->dn_agwidth); dbm_t->dn_agstart = __le32_to_cpu(dbm_t->dn_agstart); dbm_t->dn_agl2size = __le32_to_cpu(dbm_t->dn_agl2size); for (i = 0; i < MAXAG; i++) dbm_t->dn_agfree[i] = __le64_to_cpu(dbm_t->dn_agfree[i]); dbm_t->dn_agsize = __le64_to_cpu(dbm_t->dn_agsize); } /*-------------------------------------------------------------------- * NAME: ujfs_swap_dinode * * FUNCTION: Change endianness of dinode structure * * PARAMETERS: * dinode - dinode structure * * RETURNS: NONE */ void ujfs_swap_dinode(struct dinode *di, int32_t mode, uint32_t sb_flag) { dtpage_t *p; /* struct dinode in jfs_dinode.h */ di->di_inostamp = __le32_to_cpu(di->di_inostamp); di->di_fileset = __le32_to_cpu(di->di_fileset); di->di_number = __le32_to_cpu(di->di_number); di->di_gen = __le32_to_cpu(di->di_gen); di->di_size = __le64_to_cpu(di->di_size); di->di_nblocks = __le64_to_cpu(di->di_nblocks); di->di_nlink = __le32_to_cpu(di->di_nlink); di->di_uid = __le32_to_cpu(di->di_uid); di->di_gid = __le32_to_cpu(di->di_gid); /* struct timestruc_t */ di->di_atime.tv_sec = __le32_to_cpu(di->di_atime.tv_sec); di->di_atime.tv_nsec = __le32_to_cpu(di->di_atime.tv_nsec); /* struct timestruc_t */ di->di_ctime.tv_sec = __le32_to_cpu(di->di_ctime.tv_sec); di->di_ctime.tv_nsec = __le32_to_cpu(di->di_ctime.tv_nsec); /* struct timestruc_t */ di->di_mtime.tv_sec = __le32_to_cpu(di->di_mtime.tv_sec); di->di_mtime.tv_nsec = __le32_to_cpu(di->di_mtime.tv_nsec); /* struct timestruc_t */ di->di_otime.tv_sec = __le32_to_cpu(di->di_otime.tv_sec); di->di_otime.tv_nsec = __le32_to_cpu(di->di_otime.tv_nsec); /* dxd_t di_acl; */ di->di_acl.size = __le32_to_cpu(di->di_acl.size); /* dxd_t di_ea; */ di->di_ea.size = __le32_to_cpu(di->di_ea.size); di->di_acltype = __le32_to_cpu(di->di_acltype); if (mode == GET) { /* if reading from disk, swap before use in 'if' that follows */ di->di_mode = __le32_to_cpu(di->di_mode); di->di_next_index = __le32_to_cpu(di->di_next_index); } if (ISDIR(di->di_mode)) { /* cast di_btroot to dtree and swap it */ p = (dtpage_t *) & (di->di_btroot); if (p->header.flag & BT_ROOT) ujfs_swap_dtpage_t(p, sb_flag); if ((sb_flag & JFS_DIR_INDEX) == JFS_DIR_INDEX) { if (di->di_next_index > MAX_INLINE_DIRTABLE_ENTRY + 1) /* cast di_dirtable to xtree and swap it */ ujfs_swap_xtpage_t((xtpage_t *) & (di->di_dirtable)); } } else if (ISREG(di->di_mode) || ISLNK(di->di_mode)) { /* cast di_btroot to xtree and swap it */ ujfs_swap_xtpage_t((xtpage_t *) & (di->di_btroot)); } if (mode == PUT) { di->di_mode = __le32_to_cpu(di->di_mode); di->di_next_index = __le32_to_cpu(di->di_next_index); } } /*-------------------------------------------------------------------- * NAME: ujfs_swap_dinomap * * FUNCTION: Change endianness of struct dinomap structure * * PARAMETERS: * dim_t - struct dinomap structure * * RETURNS: NONE */ void ujfs_swap_dinomap(struct dinomap *dim_t) { int i; /* struct dinomap in jfs_imap.h */ dim_t->in_freeiag = __le32_to_cpu(dim_t->in_freeiag); dim_t->in_nextiag = __le32_to_cpu(dim_t->in_nextiag); dim_t->in_numinos = __le32_to_cpu(dim_t->in_numinos); dim_t->in_numfree = __le32_to_cpu(dim_t->in_numfree); dim_t->in_nbperiext = __le32_to_cpu(dim_t->in_nbperiext); dim_t->in_l2nbperiext = __le32_to_cpu(dim_t->in_l2nbperiext); dim_t->in_diskblock = __le32_to_cpu(dim_t->in_diskblock); dim_t->in_maxag = __le32_to_cpu(dim_t->in_maxag); for (i = 0; i < MAXAG; i++) { dim_t->in_agctl[i].inofree = __le32_to_cpu(dim_t->in_agctl[i].inofree); dim_t->in_agctl[i].extfree = __le32_to_cpu(dim_t->in_agctl[i].extfree); dim_t->in_agctl[i].numinos = __le32_to_cpu(dim_t->in_agctl[i].numinos); dim_t->in_agctl[i].numfree = __le32_to_cpu(dim_t->in_agctl[i].numfree); } } /*-------------------------------------------------------------------- * NAME: ujfs_swap_dmap * * FUNCTION: Change endianness of dmap structure * * PARAMETERS: * dm_t - dmap structure * * RETURNS: NONE */ void ujfs_swap_dmap(struct dmap *dm_t) { int i; /* struct dmap in jfs_dmap.h */ dm_t->nblocks = __le32_to_cpu(dm_t->nblocks); dm_t->nfree = __le32_to_cpu(dm_t->nfree); dm_t->start = __le64_to_cpu(dm_t->start); /* struct dmaptree tree; */ dm_t->tree.nleafs = __le32_to_cpu(dm_t->tree.nleafs); dm_t->tree.l2nleafs = __le32_to_cpu(dm_t->tree.l2nleafs); dm_t->tree.leafidx = __le32_to_cpu(dm_t->tree.leafidx); dm_t->tree.height = __le32_to_cpu(dm_t->tree.height); for (i = 0; i < LPERDMAP; i++) { dm_t->wmap[i] = __le32_to_cpu(dm_t->wmap[i]); dm_t->pmap[i] = __le32_to_cpu(dm_t->pmap[i]); } } /*-------------------------------------------------------------------- * NAME: ujfs_swap_dmapctl * * FUNCTION: Change endianness of dmapctl structure * * PARAMETERS: * dmc_t - dmapctl structure * * RETURNS: NONE */ void ujfs_swap_dmapctl(struct dmapctl *dmc_t) { /* struct dmapctl in jfs_dmap.h */ dmc_t->nleafs = __le32_to_cpu(dmc_t->nleafs); dmc_t->l2nleafs = __le32_to_cpu(dmc_t->l2nleafs); dmc_t->leafidx = __le32_to_cpu(dmc_t->leafidx); dmc_t->height = __le32_to_cpu(dmc_t->height); } /*-------------------------------------------------------------------- * NAME: ujfs_swap_dtpage_t * * FUNCTION: Change endianness of dtpage_t structure * * PARAMETERS: * dtp_t - dtpage_t structure * * RETURNS: NONE */ void ujfs_swap_dtpage_t(dtpage_t * dtp_t, uint32_t sb_flag) { struct dtslot *dtslot; int index, i, j, DtlHdrDataLen, len; int8_t *stbl; int lastslot; /* dtpage_t in jfs_dtree.h */ if (dtp_t->header.flag & BT_ROOT) { /* root page */ dtroot_t *dtroot = (dtroot_t *) dtp_t; dtroot->header.idotdot = __le32_to_cpu(dtroot->header.idotdot); stbl = dtroot->header.stbl; lastslot = DTROOTMAXSLOT - 1; } else { /* non-root page */ dtp_t->header.next = __le64_to_cpu(dtp_t->header.next); dtp_t->header.prev = __le64_to_cpu(dtp_t->header.prev); stbl = (int8_t *) & dtp_t->slot[dtp_t->header.stblindex]; lastslot = DTPAGEMAXSLOT - 1; } /* * Make sure we don't dereference beyond the end of stbl. * We can keep quiet here. The problem will be reported elsewhere. */ if (dtp_t->header.nextindex > lastslot + 1) return; if (dtp_t->header.flag & BT_LEAF) { struct ldtentry *ldtentry; for (i = 0; i < dtp_t->header.nextindex; i++) { /* * leaf node entry head-only segment */ index = stbl[i]; /* Don't let bad dtree make us go outside of page */ if (index > lastslot) continue; ldtentry = (struct ldtentry *) &dtp_t->slot[index]; ldtentry->inumber = __le32_to_cpu(ldtentry->inumber); if ((sb_flag & JFS_DIR_INDEX) == JFS_DIR_INDEX) { DtlHdrDataLen = DTLHDRDATALEN; ldtentry->index = __le32_to_cpu(ldtentry->index); } else DtlHdrDataLen = DTLHDRDATALEN_LEGACY; len = ldtentry->namlen; for (j = 0; j < MIN(ldtentry->namlen, DtlHdrDataLen); j++) ldtentry->name[j] = __le16_to_cpu(ldtentry->name[j]); len -= DtlHdrDataLen; index = ldtentry->next; /* * additional segments */ while ((index != -1) && (len > 0)) { if (index > lastslot) break; dtslot = &dtp_t->slot[index]; for (j = 0; j < DTSLOTDATALEN; j++) dtslot->name[j] = __le16_to_cpu(dtslot->name[j]); len -= DTSLOTDATALEN; index = dtslot->next; } } } else { /* BT_INTERNAL */ struct idtentry *idtentry; for (i = 0; i < dtp_t->header.nextindex; i++) { /* * internal node entry head-only segment */ index = stbl[i]; /* Don't let bad dtree make us go outside of page */ if (index > lastslot) continue; idtentry = (struct idtentry *) &dtp_t->slot[index]; len = idtentry->namlen; for (j = 0; j < MIN(idtentry->namlen, DTIHDRDATALEN); j++) idtentry->name[j] = __le16_to_cpu(idtentry->name[j]); len -= DTIHDRDATALEN; index = idtentry->next; /* * additional segments */ while ((index != -1) && (len > 0)) { if (index > lastslot) break; dtslot = &dtp_t->slot[index]; for (j = 0; j < DTSLOTDATALEN; j++) dtslot->name[j] = __le16_to_cpu(dtslot->name[j]); len -= DTSLOTDATALEN; index = dtslot->next; } } } } /*-------------------------------------------------------------------- * NAME: ujfs_swap_fsck_blk_map_hdr * * FUNCTION: Change endianness of fsck_blk_map_hdr structure * * PARAMETERS: * fsck_bmap_h - fsck block map header structure * * RETURNS: NONE */ void ujfs_swap_fsck_blk_map_hdr(struct fsck_blk_map_hdr *fsck_bmap_h) { int i; /* fsck_blk_map_hdr in libfs/fsckwsp.h */ /* struct fsckcbbl_record cbblrec */ fsck_bmap_h->cbblrec.cbbl_retcode = __le32_to_cpu(fsck_bmap_h->cbblrec.cbbl_retcode); fsck_bmap_h->cbblrec.fs_blksize = __le32_to_cpu(fsck_bmap_h->cbblrec.fs_blksize); fsck_bmap_h->cbblrec.lv_blksize = __le32_to_cpu(fsck_bmap_h->cbblrec.lv_blksize); fsck_bmap_h->cbblrec.fs_lv_ratio = __le32_to_cpu(fsck_bmap_h->cbblrec.fs_lv_ratio); fsck_bmap_h->cbblrec.fs_last_metablk = __le64_to_cpu(fsck_bmap_h->cbblrec.fs_last_metablk); fsck_bmap_h->cbblrec.fs_first_wspblk = __le64_to_cpu(fsck_bmap_h->cbblrec.fs_first_wspblk); fsck_bmap_h->cbblrec.total_bad_blocks = __le32_to_cpu(fsck_bmap_h->cbblrec.total_bad_blocks); fsck_bmap_h->cbblrec.resolved_blocks = __le32_to_cpu(fsck_bmap_h->cbblrec.resolved_blocks); fsck_bmap_h->cbblrec.reloc_extents = __le32_to_cpu(fsck_bmap_h->cbblrec.reloc_extents); fsck_bmap_h->cbblrec.reloc_blocks = __le64_to_cpu(fsck_bmap_h->cbblrec.reloc_blocks); fsck_bmap_h->cbblrec.LVM_lists = __le32_to_cpu(fsck_bmap_h->cbblrec.LVM_lists); fsck_bmap_h->hdr.last_entry_pos = __le32_to_cpu(fsck_bmap_h->hdr.last_entry_pos); fsck_bmap_h->hdr.next_entry_pos = __le32_to_cpu(fsck_bmap_h->hdr.next_entry_pos); fsck_bmap_h->hdr.return_code = __le32_to_cpu(fsck_bmap_h->hdr.return_code); fsck_bmap_h->hdr.fscklog_agg_offset = __le64_to_cpu(fsck_bmap_h->hdr.fscklog_agg_offset); fsck_bmap_h->hdr.num_logwrite_errors = __le32_to_cpu(fsck_bmap_h->hdr.num_logwrite_errors); /* struct fscklog_error logerr[125] */ for (i = 0; i < 125; i++) { fsck_bmap_h->hdr.logerr[i].err_offset = __le64_to_cpu(fsck_bmap_h->hdr.logerr[i].err_offset); fsck_bmap_h->hdr.logerr[i].bytes_written = __le32_to_cpu(fsck_bmap_h->hdr.logerr[i].bytes_written); fsck_bmap_h->hdr.logerr[i].io_retcode = __le32_to_cpu(fsck_bmap_h->hdr.logerr[i].io_retcode); } } /*-------------------------------------------------------------------- * NAME: ujfs_swap_fsck_blk_map_page * * FUNCTION: Change endianness of fsck_blk_map_page structure * * PARAMETERS: * fsck_bmap_p - fsck block map page structure * * RETURNS: NONE */ void ujfs_swap_fsck_blk_map_page(struct fsck_blk_map_page *fsck_bmap_p) { int i; /* fsck_blk_map_page in libfs/fsckwsp.h */ for (i = 0; i < 1024; i++) fsck_bmap_p->fsck_blkmap_words[i] = __le32_to_cpu(fsck_bmap_p->fsck_blkmap_words[i]); } /*-------------------------------------------------------------------- * NAME: ujfs_swap_iag * * FUNCTION: Change endianness of iag structure * * PARAMETERS: * ia_t - iag structure * * RETURNS: NONE */ void ujfs_swap_iag(struct iag *ia_t) { int i; /* iag in jfs_logmgr.h */ ia_t->agstart = __le64_to_cpu(ia_t->agstart); ia_t->iagnum = __le32_to_cpu(ia_t->iagnum); ia_t->inofreefwd = __le32_to_cpu(ia_t->inofreefwd); ia_t->inofreeback = __le32_to_cpu(ia_t->inofreeback); ia_t->extfreefwd = __le32_to_cpu(ia_t->extfreefwd); ia_t->extfreeback = __le32_to_cpu(ia_t->extfreeback); ia_t->iagfree = __le32_to_cpu(ia_t->iagfree); for (i = 0; i < SMAPSZ; i++) { ia_t->inosmap[i] = __le32_to_cpu(ia_t->inosmap[i]); ia_t->extsmap[i] = __le32_to_cpu(ia_t->extsmap[i]); } ia_t->nfreeinos = __le32_to_cpu(ia_t->nfreeinos); ia_t->nfreeexts = __le32_to_cpu(ia_t->nfreeexts); for (i = 0; i < EXTSPERIAG; i++) { ia_t->wmap[i] = __le32_to_cpu(ia_t->wmap[i]); ia_t->pmap[i] = __le32_to_cpu(ia_t->pmap[i]); } } /*-------------------------------------------------------------------- * NAME: ujfs_swap_logpage * * FUNCTION: Change endianness of logpage structure * * PARAMETERS: * lpage_t - logpage structure * numpages - number of pages to swap * * RETURNS: NONE */ void ujfs_swap_logpage(struct logpage *lpage_t, uint8_t numpages) { uint8_t i; struct logpage *lp_t; /* struct logpage in jfs_logmgr.h */ lp_t = lpage_t; for (i = 0; i < numpages; i++) { lp_t->h.page = __le32_to_cpu(lp_t->h.page); lp_t->h.rsrvd = __le16_to_cpu(lp_t->h.rsrvd); lp_t->h.eor = __le16_to_cpu(lp_t->h.eor); lp_t->t.page = __le32_to_cpu(lp_t->t.page); lp_t->t.rsrvd = __le16_to_cpu(lp_t->t.rsrvd); lp_t->t.eor = __le16_to_cpu(lp_t->t.eor); lp_t++; } } /*-------------------------------------------------------------------- * NAME: ujfs_swap_logsuper * * FUNCTION: Change endianness of logsuper structure * * PARAMETERS: * lsup_t - logsuper structure * * RETURNS: NONE */ void ujfs_swap_logsuper(struct logsuper *lsup_t) { /* struct logsuper in jfs_logmgr.h */ lsup_t->magic = __le32_to_cpu(lsup_t->magic); lsup_t->version = __le32_to_cpu(lsup_t->version); lsup_t->serial = __le32_to_cpu(lsup_t->serial); lsup_t->size = __le32_to_cpu(lsup_t->size); lsup_t->bsize = __le32_to_cpu(lsup_t->bsize); lsup_t->l2bsize = __le32_to_cpu(lsup_t->l2bsize); lsup_t->flag = __le32_to_cpu(lsup_t->flag); lsup_t->state = __le32_to_cpu(lsup_t->state); lsup_t->end = __le32_to_cpu(lsup_t->end); } /*-------------------------------------------------------------------- * NAME: ujfs_swap_lrd * * FUNCTION: Change endianness of lrd structure * * PARAMETERS: * lrd - lrd structure * * RETURNS: NONE */ void ujfs_swap_lrd(struct lrd *lrd) { lrd->logtid = __le32_to_cpu(lrd->logtid); lrd->backchain = __le32_to_cpu(lrd->backchain); lrd->type = __le16_to_cpu(lrd->type); lrd->length = __le16_to_cpu(lrd->length); lrd->aggregate = __le32_to_cpu(lrd->aggregate); switch (lrd->type) { case LOG_COMMIT: break; case LOG_SYNCPT: lrd->log.syncpt.sync = __le32_to_cpu(lrd->log.syncpt.sync); break; case LOG_MOUNT: break; case LOG_REDOPAGE: case LOG_NOREDOPAGE: lrd->log.redopage.fileset = __le32_to_cpu(lrd->log.redopage.fileset); lrd->log.redopage.inode = __le32_to_cpu(lrd->log.redopage.inode); lrd->log.redopage.type = __le16_to_cpu(lrd->log.redopage.type); lrd->log.redopage.l2linesize = __le16_to_cpu(lrd->log.redopage.l2linesize); break; case LOG_UPDATEMAP: lrd->log.updatemap.fileset = __le32_to_cpu(lrd->log.updatemap.fileset); lrd->log.updatemap.inode = __le32_to_cpu(lrd->log.updatemap.inode); lrd->log.updatemap.type = __le16_to_cpu(lrd->log.updatemap.type); lrd->log.updatemap.nxd = __le16_to_cpu(lrd->log.updatemap.nxd); break; case LOG_NOREDOINOEXT: lrd->log.noredoinoext.fileset = __le32_to_cpu(lrd->log.noredoinoext.fileset); lrd->log.noredoinoext.iagnum = __le32_to_cpu(lrd->log.noredoinoext.iagnum); lrd->log.noredoinoext.inoext_idx = __le32_to_cpu(lrd->log.noredoinoext.inoext_idx); break; } } /*-------------------------------------------------------------------- * NAME: ujfs_swap_superblock * * FUNCTION: Change endianness of superblock structure * * PARAMETERS: * sblk - superblock structure * * RETURNS: NONE */ void ujfs_swap_superblock(struct superblock *sblk) { /* superblock in jfs_superblock.h */ sblk->s_version = __le32_to_cpu(sblk->s_version); sblk->s_size = __le64_to_cpu(sblk->s_size); sblk->s_bsize = __le32_to_cpu(sblk->s_bsize); sblk->s_l2bsize = __le16_to_cpu(sblk->s_l2bsize); sblk->s_l2bfactor = __le16_to_cpu(sblk->s_l2bfactor); sblk->s_pbsize = __le32_to_cpu(sblk->s_pbsize); sblk->s_l2pbsize = __le16_to_cpu(sblk->s_l2pbsize); sblk->pad = __le16_to_cpu(sblk->pad); sblk->s_agsize = __le32_to_cpu(sblk->s_agsize); sblk->s_flag = __le32_to_cpu(sblk->s_flag); sblk->s_state = __le32_to_cpu(sblk->s_state); sblk->s_compress = __le32_to_cpu(sblk->s_compress); sblk->s_logdev = __le32_to_cpu(sblk->s_logdev); sblk->s_logserial = __le32_to_cpu(sblk->s_logserial); /* struct timestruc_t s_time; */ sblk->s_time.tv_sec = __le32_to_cpu(sblk->s_time.tv_sec); sblk->s_time.tv_nsec = __le32_to_cpu(sblk->s_time.tv_nsec); sblk->s_fsckloglen = __le32_to_cpu(sblk->s_fsckloglen); sblk->s_xsize = __le64_to_cpu(sblk->s_xsize); } /*-------------------------------------------------------------------- * NAME: ujfs_swap_xtpage_t * * FUNCTION: Change endianness of xtpage_t structure * * PARAMETERS: * xtp_t - xtpage_t structure * mode - PUT or GET * * RETURNS: NONE */ void ujfs_swap_xtpage_t(xtpage_t * xtp_t) { /* xtpage_t in jfs_xtree.h */ /* struct xtheader header; */ xtp_t->header.next = __le64_to_cpu(xtp_t->header.next); xtp_t->header.prev = __le64_to_cpu(xtp_t->header.prev); xtp_t->header.maxentry = __le16_to_cpu(xtp_t->header.maxentry); xtp_t->header.rsrvd2 = __le16_to_cpu(xtp_t->header.rsrvd2); xtp_t->header.nextindex = __le16_to_cpu(xtp_t->header.nextindex); } /*-------------------------------------------------------------------- * NAME: ujfs_swap_fscklog_entry_hdr * * FUNCTION: Change endianness of fscklog_entry_hdr structure * * PARAMETERS: * hdptr - pointer to fscklog_entry_hdr structure * * RETURNS: NONE */ void ujfs_swap_fscklog_entry_hdr(struct fscklog_entry_hdr *hdptr) { /* fscklog_entry_hdr in fscklog.h */ hdptr->entry_length = __le16_to_cpu(hdptr->entry_length); } #endif /* BIG ENDIAN */ jfsutils-1.1.15.orig/libfs/jfs_endian.h0000644000000000000000000000603210340701413014631 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _H_UJFS_ENDIAN #define _H_UJFS_ENDIAN #include "jfs_types.h" #include "jfs_byteorder.h" #include "jfs_superblock.h" #include "jfs_dmap.h" #include "jfs_imap.h" #include "jfs_dinode.h" #include "jfs_logmgr.h" #include "fsckwsp.h" #if __BYTE_ORDER == __BIG_ENDIAN void ujfs_swap_dbmap(struct dbmap *); void ujfs_swap_dinode(struct dinode *, int32_t, uint32_t); void ujfs_swap_dinomap(struct dinomap *); void ujfs_swap_dmap(struct dmap *); void ujfs_swap_dmapctl(struct dmapctl *); void ujfs_swap_dtpage_t(dtpage_t *, uint32_t); void ujfs_swap_fsck_blk_map_hdr(struct fsck_blk_map_hdr *); void ujfs_swap_fsck_blk_map_page(struct fsck_blk_map_page *); void ujfs_swap_fscklog_entry_hdr(struct fscklog_entry_hdr *); void ujfs_swap_iag(struct iag *); void ujfs_swap_logpage(struct logpage *, uint8_t); void ujfs_swap_logsuper(struct logsuper *); void ujfs_swap_lrd(struct lrd *); void ujfs_swap_superblock(struct superblock *); void ujfs_swap_xtpage_t(xtpage_t *); static inline void ujfs_swap_inoext(struct dinode *ptr, int32_t mode, uint32_t flag) { int i; for (i = 0; i < INOSPEREXT; i++, ptr++) ujfs_swap_dinode(ptr, mode, flag); } #define swap_multiple(swap_func, ptr, num) \ do { \ int i; \ for (i = 0; i < num; i++, (ptr)++) \ swap_func(ptr); \ } while (0) #else /* Little endian */ #define ujfs_swap_dbmap(dbmap) do {} while (0) #define ujfs_swap_dinode(dinode, mode, flag) do {} while (0) #define ujfs_swap_dinomap(dinomap) do {} while (0) #define ujfs_swap_dmap(dmap) do {} while (0) #define ujfs_swap_dmapctl(dmapctl) do {} while (0) #define ujfs_swap_dtpage_t(dtpage, flag) do {} while (0) #define ujfs_swap_fsck_blk_map_hdr(map_hdr) do {} while (0) #define ujfs_swap_fsck_blk_map_page(map_page) do {} while (0) #define ujfs_swap_fscklog_entry_hdr(ent_hdr) do {} while (0) #define ujfs_swap_iag(iag) do {} while (0) #define ujfs_swap_inoext(inoext, mode, flag) do {} while (0) #define ujfs_swap_logpage(logpage, pages) do {} while (0) #define ujfs_swap_logsuper(logsuper) do {} while (0) #define ujfs_swap_lrd(lrd) do {} while (0) #define ujfs_swap_superblock(sb) do {} while (0) #define ujfs_swap_xtpage_t(xtpage) do {} while (0) #define swap_multiple(swap_func, ptr, num) do {} while (0) #endif #endif /* _H_UJFS_ENDIAN */ jfsutils-1.1.15.orig/libfs/libjufs.h0000644000000000000000000000206310340701413014167 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef H_LIBFS #define H_LIBFS #define LIBFS_BADMAGIC -5 /* magic number not recognized */ #define LIBFS_BADVERSION -6 /* magic num ok, incompatible vers */ #define LIBFS_CORRUPTSUPER -10 /* fragsize, agsize, or iagsize bad */ #endif /* H_LIBFS */ jfsutils-1.1.15.orig/libfs/log_dump.c0000644000000000000000000007120611321360767014354 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include "jfs_types.h" #include "jfs_endian.h" #include "jfs_filsys.h" #include "jfs_superblock.h" #include "jfs_dinode.h" #include "jfs_dtree.h" #include "jfs_xtree.h" #include "jfs_logmgr.h" #include "jfs_dmap.h" #include "jfs_imap.h" #include "logredo.h" #include "devices.h" #include "debug.h" extern int LogOpenMode; #define LOGDMP_OK 0 #define LOGDMP_FAILED -1 #define MAKEDEV(__x,__y) (dev_t)(((__x)<<16) | (__y)) #define LOGPNTOB(x) ((x)< 1 )\ {\ L2NUM++;\ (NUM) >>= 1;\ }\ }\ } /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * things for the log. */ int32_t logend; /* address of the end of last log record */ struct logsuper logsup; /* log super block */ int32_t numdoblk; /* number of do blocks used */ int32_t numnodofile; /* number of nodo file blocks used */ /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * The output file. * */ FILE *outfp; #define output_filename "./jfslog.dmp" int logdmp_outfile_is_open = 0; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * open file system aggregate/lv array * * logredo() processes a single log. * at the first release, logredo will process a single log * related to one aggregate. But the future release, logredo needs to * to process one single log related to multiple agreegates. * In both cases, the aggregate(logical volume) where the log stays * will be different from the file system aggregate/lv. * * There will be one imap for the aggregate inode allocation map * and a list of imap pointers to multiple fileset inode allocation maps. * * There is one block allocation map per aggregate and shared by all the * filesets within the aggregate. * * the log and related aggregates (logical volumes) are all in * the same volume group, i.e., each logical volume is uniquely specified * by their minor number with the same major number, * the maximum number of lvs in a volume group is NUMMINOR (256). */ /* * We only deal with the log here. No need for vopen array */ struct vopen volume; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * file system page buffer cache * * for k > 0, bufhdr[k] describes contents of buffer[k-1]. * bufhdr[0] is reserved as anchor for free/lru list: * bufhdr[0].next points to the MRU buffer (head), * bufhdr[0].prev points to the LRU buffer (tail); */ /* buffer header table */ struct bufhdr { int16_t next; /* 2: next on free/lru list */ int16_t prev; /* 2: previous on free/lru list */ int16_t hnext; /* 2: next on hash chain */ int16_t hprev; /* 2: previous on hash chain */ char modify; /* 1: buffer was modified */ char inuse; /* 1: buffer on hash chain */ int16_t reserve; /* 2 */ int32_t vol; /* 4: minor of agrregate/lv number */ pxd_t pxd; /* 8: on-disk page pxd */ } bufhdr[NBUFPOOL]; /* (24) */ /* buffer table */ struct bufpool { char bytes[PSIZE]; } buffer[NBUFPOOL - 1]; /* * log page buffer cache * * log has its own 4 page buffer pool. */ uint8_t afterdata[LOGPSIZE * 2]; /* buffer to read in redopage data */ /* * Miscellaneous */ caddr_t prog; /* Program name */ int32_t mntcnt, bufsize; char *mntinfo; int32_t retcode; /* return code from logredo */ /* * external references */ extern char *optarg; extern int optind; extern int initMaps(int32_t); extern int updateMaps(int); extern int findEndOfLog(void); extern int logRead(int32_t, struct lrd *, char *); extern int logredoInit(void); extern int alloc_wrksp(uint32_t, int, int, void **); /* defined in fsckwsp.c */ /* * forward references */ int open_outfile(void); int ldmp_readSuper(FILE *, struct superblock *); int ldmp_isLogging(caddr_t, int32_t, char *, int32_t); int ldmp_logError(int, int); int usage(void); int disp_updatemap(struct lrd *); int disp_redopage(struct lrd *); int disp_noredopage(struct lrd *); int disp_noredoinoext(struct lrd *); void ldmp_xdump(char *, int); int ldmp_x_scmp(char *, char *); void ldmp_x_scpy(char *, char *); int prtdesc(struct lrd *); /* -------------------------------------------------------------------- * * NAME: jfs_logdump() * * FUNCTION: * */ int jfs_logdump(caddr_t pathname, FILE *fp, int32_t dump_all) { int rc; int32_t logaddr, nextaddr, lastaddr, nlogrecords; struct lrd ld; int32_t lowest_lr_byte = 2 * LOGPSIZE + LOGPHDRSIZE; int32_t highest_lr_byte = 0; int log_has_wrapped = 0; int in_use; rc = open_outfile(); if (rc == 0) { /* output file is open */ /* * loop until we get enough memory to read vmount struct */ mntinfo = (char *) &bufsize; bufsize = sizeof (int); /* * Find and open the log */ LogOpenMode = O_RDONLY; rc = findLog(fp, &in_use); if (rc != 0) { printf("JFS_LOGDUMP:Error occurred when open/read device\n"); fprintf(outfp, "??????????????????????????????????????????????????????\n"); fprintf(outfp, "JFS_LOGDUMP:Error occurred when open/read device\n"); fprintf(outfp, "??????????????????????????????????????????????????????\n"); return (rc); } /* * validate log superblock * * aggregate block size is for log file as well. */ rc = ujfs_rw_diskblocks(Log.fp, (uint64_t) (Log.xaddr + LOGPNTOB(LOGSUPER_B)), (unsigned) sizeof (struct logsuper), (char *) &logsup, GET); if (rc != 0) { printf("JFS_LOGDUMP:couldn't read log superblock:failure in %s\n", prog); fprintf(outfp, "??????????????????????????????????????????????????????\n"); fprintf(outfp, "JFS_LOGDUMP:couldn't read log superblock:failure in %s\n", prog); fprintf(outfp, "??????????????????????????????????????????????????????\n"); return (LOGSUPER_READ_ERROR); } ujfs_swap_logsuper(&logsup); fprintf(outfp, "JOURNAL SUPERBLOCK: \n"); fprintf(outfp, "------------------------------------------------------\n"); fprintf(outfp, " magic number: x %x \n", logsup.magic); fprintf(outfp, " version : x %x \n", logsup.version); fprintf(outfp, " serial : x %x \n", logsup.serial); fprintf(outfp, " size : t %d pages (4096 bytes/page)\n", logsup.size); fprintf(outfp, " bsize : t %d bytes/block\n", logsup.bsize); fprintf(outfp, " l2bsize : t %d \n", logsup.l2bsize); fprintf(outfp, " flag : x %x \n", logsup.flag); fprintf(outfp, " state : x %x \n", logsup.state); fprintf(outfp, " end : x %x \n", logsup.end); fprintf(outfp, "\n"); fprintf(outfp, "======================================================\n"); fprintf(outfp, "\n"); if (logsup.magic != LOGMAGIC) { fprintf(outfp, "\n"); fprintf(outfp, "**WARNING** %s: %s is not a log file\n", prog, pathname); fprintf(outfp, "\n"); fprintf(outfp, "======================================================\n"); fprintf(outfp, "\n"); } if (logsup.version != LOGVERSION) { fprintf(outfp, "\n"); fprintf(outfp, "**WARNING** %s and log file %s version mismatch\n", prog, pathname); fprintf(outfp, "\n"); fprintf(outfp, "======================================================\n"); fprintf(outfp, "\n"); } if (logsup.state == LOGREDONE) { fprintf(outfp, "\n"); fprintf(outfp, "**WARNING** %s and log file %s state is LOGREDONE\n", prog, pathname); fprintf(outfp, "\n"); fprintf(outfp, "======================================================\n"); fprintf(outfp, "\n"); } Log.size = logsup.size; Log.serial = logsup.serial; /* * find the end of log */ logend = findEndOfLog(); if (logend < 0) { printf("logend < 0\n"); ldmp_logError(LOGEND, 0); ujfs_swap_logsuper(&logsup); rc = ujfs_rw_diskblocks(Log.fp, (uint64_t) (Log.xaddr + LOGPNTOB(LOGSUPER_B)), (unsigned long) LOGPSIZE, (char *) &logsup, PUT); rc = logend; goto loopexit; } highest_lr_byte = logsup.size * LOGPSIZE - LOGRDSIZE; if ((logend < lowest_lr_byte) || (logend > highest_lr_byte)) { fprintf(outfp, "\n"); fprintf(outfp, "**ERROR** logend address is not valid for a logrec. logend: 0x0%x\n", logend); fprintf(outfp, "\n"); fprintf(outfp, "======================================================\n"); fprintf(outfp, "\n"); return (INVALID_LOGEND); } /* * replay log * * read log backwards and process records as we go. * reading stops at place specified by first SYNCPT we * encounter. */ nlogrecords = lastaddr = 0; nextaddr = logend; do { logaddr = nextaddr; nextaddr = logRead(logaddr, &ld, afterdata); fprintf(outfp, "logrec d %d Logaddr= x %x Nextaddr= x %x Backchain = x %x\n", nlogrecords, logaddr, nextaddr, ld.backchain); fprintf(outfp, "\n"); nlogrecords += 1; /* * * Validate the nextaddr as much as possible * */ if (nextaddr < 0) { ldmp_logError(READERR, logaddr); if (nextaddr == REFORMAT_ERROR) { rc = nextaddr; goto loopexit; } break; } /* * Certain errors we'll assume signal the end of the log * since we're just dumping everything from the latest * commit record to the earliest valid record. */ if ((nextaddr < lowest_lr_byte) || (nextaddr > highest_lr_byte)) { lastaddr = logaddr; } if (nextaddr == logaddr) { lastaddr = logaddr; } if (nextaddr > logaddr) { if (log_has_wrapped) { fprintf(outfp, "\n"); fprintf(outfp, "**ERROR** log wrapped twice. logaddr:0x0%x nextaddr:0x0%x\n", logaddr, nextaddr); fprintf(outfp, "\n"); fprintf(outfp, "======================================================\n"); fprintf(outfp, "\n"); lastaddr = logaddr; } else { log_has_wrapped = -1; } } /* * * The addresses seem ok. Process the current record. * */ if (lastaddr != logaddr) { switch (ld.type) { case LOG_COMMIT: fprintf(outfp, "LOG_COMMIT (type = d %d) logtid = d %d aggregate = d %d\n", ld.type, ld.logtid, ld.aggregate); fprintf(outfp, "\n"); fprintf(outfp, "\tdata length = d %d\n", ld.length); break; case LOG_MOUNT: fprintf(outfp, "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"); fprintf(outfp, "LOG_MOUNT (type = d %d) logtid = d %d aggregate = d %d\n", ld.type, ld.logtid, ld.aggregate); fprintf(outfp, "\n"); fprintf(outfp, "\tdata length = d %d\n", ld.length); fprintf(outfp, "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"); break; case LOG_SYNCPT: fprintf(outfp, "****************************************************************\n"); fprintf(outfp, "LOG_SYNCPT (type = d %d) logtid = d %d aggregate = d %d\n", ld.type, ld.logtid, ld.aggregate); fprintf(outfp, "\n"); fprintf(outfp, "\tdata length = d %d\n", ld.length); fprintf(outfp, "\tsync = x %x\n", ld.log.syncpt.sync); fprintf(outfp, "****************************************************************\n"); rc = 0; if (!dump_all) { /* user just wants from last synch point forward */ if (lastaddr == 0) { lastaddr = (ld.log.syncpt.sync == 0) ? logaddr : ld.log.syncpt.sync; } } /* end user just wants from last synch point forward */ break; case LOG_REDOPAGE: fprintf(outfp, "LOG_REDOPAGE (type = d %d) logtid = d %d aggregate = d %d\n", ld.type, ld.logtid, ld.aggregate); fprintf(outfp, "\n"); fprintf(outfp, "\tdata length = d %d ", ld.length); disp_redopage(&ld); break; case LOG_NOREDOPAGE: fprintf(outfp, "LOG_NOREDOPAGE (type = d %d) logtid = d %d aggregate = d %d\n", ld.type, ld.logtid, ld.aggregate); fprintf(outfp, "\n"); fprintf(outfp, "\tdata length = d %d ", ld.length); disp_noredopage(&ld); break; case LOG_NOREDOINOEXT: fprintf(outfp, "LOG_NOREDOINOEXT (type = d %d) logtid = d %d aggregate = d %d\n", ld.type, ld.logtid, ld.aggregate); fprintf(outfp, "\n"); fprintf(outfp, "\tdata length = d %d ", ld.length); disp_noredoinoext(&ld); break; case LOG_UPDATEMAP: fprintf(outfp, "LOG_UPDATEMAP (type = d %d) logtid = d %d aggregate = d %d\n", ld.type, ld.logtid, ld.aggregate); fprintf(outfp, "\n"); fprintf(outfp, "\tdata length = d %d ", ld.length); disp_updatemap(&ld); break; default: fprintf(outfp, "*UNRECOGNIZED* (type = d %d) logtid = d %d aggregate = d %d\n", ld.type, ld.logtid, ld.aggregate); fprintf(outfp, "\n"); fprintf(outfp, "\tdata length = d %d\n", ld.length); fprintf(outfp, "\n"); fprintf(outfp, "**ERROR** unrecognized log record type\n"); fprintf(outfp, "\n"); fprintf(outfp, "======================================================\n"); fprintf(outfp, "\n"); return (UNRECOG_LOGRECTYP); } if (rc == 0) { fprintf(outfp, "\n"); if (ld.length > 0) { ldmp_xdump((char *) afterdata, ld.length); } } fprintf(outfp, "\n"); fprintf(outfp, "----------------------------------------------------------------------\n"); } /* end if( lastaddr != logaddr ) */ } while (logaddr != lastaddr); loopexit: /* * Close the output file */ if (logdmp_outfile_is_open) { fclose(outfp); } if (rc == 0) { /* log has been dumped successfully */ printf ("JFS_LOGDUMP: The current JFS log has been dumped into ./jfslog.dmp\n"); } else { printf("JFS_LOGDUMP:Failed in %s\n", prog); fprintf(outfp, "??????????????????????????????????????????????????????\n"); fprintf(outfp, "JFS_LOGDUMP:Failed in %s\n", prog); fprintf(outfp, "??????????????????????????????????????????????????????\n"); } } /* end output file is open */ return (rc < 0) ? (rc) : (0); } /*---------------------------------------------------------------- * * NAME: ldmp_readSuper(fp, sb) * * FUNCTION: read the superblock for the file system described * by the file descriptor of the opened aggregate/lv. * if a read of primary superblock fails, * try to read the secondary superblock. report error only * when both reads failed. */ int ldmp_readSuper(FILE *fp, /* file descriptor */ struct superblock * sb) { /* superblock of the opened aggregate/lv */ int rc; union { struct superblock super; char block[PSIZE]; } super; /* * seek to the postion of the primary superblock. * since at this time we don't know the aggregate/lv * logical block size yet, we have to use the fixed * byte offset address SUPER1_OFF to seek for. */ /* * read super block */ rc = ujfs_rw_diskblocks(fp, SUPER1_OFF, (unsigned) SIZE_OF_SUPER, super.block, GET); if (rc != 0) { printf ("ldmp_readSuper: read primary agg superblock failed. errno=%d Continuing.\n", errno); fprintf(outfp, "??????????????????????????????????????????????????????\n"); fprintf(outfp, "ldmp_readSuper: read primary agg superblock failed. errno=%d Continuing\n", errno); fprintf(outfp, "??????????????????????????????????????????????????????\n"); /* read failed for the primary superblock: * try to read the secondary superblock */ rc = ujfs_rw_diskblocks(fp, SUPER2_OFF, (unsigned) SIZE_OF_SUPER, super.block, GET); if (rc != 0) { printf ("ldmp_readSuper: read 2ndary agg superblock failed. errno=%d Cannot continue.\n", errno); fprintf(outfp, "??????????????????????????????????????????????????????\n"); fprintf(outfp, "ldmp_readSuper: read 2ndary agg superblock failed. errno=%d Cannot continue.\n", errno); fprintf(outfp, "??????????????????????????????????????????????????????\n"); return (MAJOR_ERROR); } } *sb = super.super; ujfs_swap_superblock(sb); return (0); } extern void exit(int); /*---------------------------------------------------------------- * * ldmp_logError(type) * * error handling for log read errors. */ int ldmp_logError(int type, int logaddr) { retcode = -1; logsup.state = LOGREADERR; switch (type) { case LOGEND: printf("ldmp_logError:find end of log failed \n"); fprintf(outfp, "??????????????????????????????????????????????????????\n"); fprintf(outfp, "ldmp_logError:find end of log failed \n"); fprintf(outfp, "??????????????????????????????????????????????????????\n"); break; case READERR: printf("log read failed 0x%x\n", logaddr); fprintf(outfp, "??????????????????????????????????????????????????????\n"); fprintf(outfp, "log read failed 0x%x\n", logaddr); fprintf(outfp, "??????????????????????????????????????????????????????\n"); break; case UNKNOWNR: printf("unknown log record type \nlog read failed 0x%x\n", logaddr); fprintf(outfp, "??????????????????????????????????????????????????????\n"); fprintf(outfp, "unknown log record type \nlog read failed 0x%x\n", logaddr); fprintf(outfp, "??????????????????????????????????????????????????????\n"); break; case IOERROR: printf("i/o error log reading page 0x%x\n", logaddr); fprintf(outfp, "??????????????????????????????????????????????????????\n"); fprintf(outfp, "i/o error log reading page 0x%x\n", logaddr); fprintf(outfp, "??????????????????????????????????????????????????????\n"); break; case LOGWRAP: printf("log wrapped...\n"); fprintf(outfp, "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"); fprintf(outfp, "log wrapped...\n"); fprintf(outfp, "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n"); } return (0); } /*---------------------------------------------------------------- * * ldmp_xdump() * * hex dump */ void ldmp_xdump(char *saddr, int count) { #define LINESZ 60 #define ASCIISTRT 40 #define HEXEND 36 int i, j, k, hexdigit; int c; char *hexchar; char linebuf[LINESZ + 1]; char prevbuf[LINESZ + 1]; char *linestart; int asciistart; char asterisk = ' '; hexchar = "0123456789ABCDEF"; prevbuf[0] = '\0'; i = (int) saddr % 4; if (i != 0) saddr = saddr - i; for (i = 0; i < count;) { for (j = 0; j < LINESZ; j++) linebuf[j] = ' '; linestart = saddr; asciistart = ASCIISTRT; for (j = 0; j < HEXEND;) { for (k = 0; k < 4; k++) { c = *(saddr++) & 0xFF; if ((c >= 0x20) && (c <= 0x7e)) linebuf[asciistart++] = (char) c; else linebuf[asciistart++] = '.'; hexdigit = c >> 4; linebuf[j++] = hexchar[hexdigit]; hexdigit = c & 0x0f; linebuf[j++] = hexchar[hexdigit]; i++; } if (i >= count) break; linebuf[j++] = ' '; } linebuf[LINESZ] = '\0'; if (((j = ldmp_x_scmp(linebuf, prevbuf)) == 0) && (i < count)) { if (asterisk == ' ') { asterisk = '*'; fprintf(outfp, " *\n"); } } else { fprintf(outfp, " %p %s\n", linestart, linebuf); asterisk = ' '; ldmp_x_scpy(prevbuf, linebuf); } } return; } /*---------------------------------------------------------------- * * ldmp_x_scmp() * */ int ldmp_x_scmp(char *s1, char *s2) { while ((*s1) && (*s1 == *s2)) { s1++; s2++; } if (*s1 || *s2) return (-1); else return (0); } /*---------------------------------------------------------------- * * ldmp_x_scpy() * */ void ldmp_x_scpy(char *s1, char *s2) { while ((*s1 = *s2) != '\0') { s1++; s2++; } } /*************************************************************************** * * NAME: disp_noredopage * * FUNCTION: * * PARAMETERS: none * * NOTES: * * RETURNS: * success: LOGDMP_OK * failure: something else */ int disp_noredopage(struct lrd *lrd_ptr) { fprintf(outfp, "fileset = d %d inode = d %d (x %x)\n", lrd_ptr->log.noredopage.fileset, lrd_ptr->log.noredopage.inode, lrd_ptr->log.noredopage.inode); switch (lrd_ptr->log.noredopage.type) { case LOG_INODE: fprintf(outfp, "\ttype = d %d NOREDOPAGE:INODE\n", lrd_ptr->log.noredopage.type); break; case LOG_XTREE: fprintf(outfp, "\ttype = d %d NOREDOPAGE:XTREE\n ", lrd_ptr->log.noredopage.type); break; case (LOG_XTREE | LOG_NEW): fprintf(outfp, "\ttype = d %d NOREDOPAGE:XTREE_NEW\n ", lrd_ptr->log.noredopage.type); break; case (LOG_BTROOT | LOG_XTREE): fprintf(outfp, "\ttype = d %d NOREDOPAGE:BTROOT_XTREE\n ", lrd_ptr->log.noredopage.type); break; case LOG_DTREE: fprintf(outfp, "\ttype = d %d NOREDOPAGE:DTREE\n ", lrd_ptr->log.noredopage.type); break; case (LOG_DTREE | LOG_NEW): fprintf(outfp, "\ttype = d %d NOREDOPAGE:DTREE_NEW \n ", lrd_ptr->log.noredopage.type); break; case (LOG_DTREE | LOG_EXTEND): fprintf(outfp, "\ttype = d %d NOREDOPAGE:DTREE_EXTEND\n ", lrd_ptr->log.noredopage.type); break; case (LOG_BTROOT | LOG_DTREE): fprintf(outfp, "\ttype = d %d NOREDOPAGE:BTROOT_DTREE\n ", lrd_ptr->log.noredopage.type); break; case (LOG_BTROOT | LOG_DTREE | LOG_NEW): fprintf(outfp, "\ttype = d %d NOREDOPAGE:BTROOT_DTREE.NEW\n ", lrd_ptr->log.noredopage.type); break; case LOG_EA: fprintf(outfp, "\ttype = d %d NOREDOPAGE:EA\n", lrd_ptr->log.noredopage.type); break; case LOG_ACL: fprintf(outfp, "\ttype = d %d NOREDOPAGE:ACL\n", lrd_ptr->log.noredopage.type); break; case LOG_DATA: fprintf(outfp, "\ttype = d %d NOREDOPAGE:DATA\n", lrd_ptr->log.noredopage.type); break; /* case LOG_NOREDOFILE: fprintf( outfp, "\ttype = d %d NOREDOPAGE:NOREDOFILE\n", lrd_ptr->log.noredopage.type ); break; */ default: fprintf(outfp, "\ttype = d %d ***UNRECOGNIZED***\n", lrd_ptr->log.noredopage.type); break; } fprintf(outfp, "\tpxd length = d %d phys offset = x %llx (d %lld)\n", lengthPXD(&(lrd_ptr->log.noredopage.pxd)), (long long) addressPXD(&(lrd_ptr->log.noredopage.pxd)), (long long) addressPXD(&(lrd_ptr->log.noredopage.pxd))); return (LOGDMP_OK); } /* end of disp_noredopage() */ /*************************************************************************** * * NAME: disp_noredoinoext * * FUNCTION: * * PARAMETERS: none * * NOTES: * * RETURNS: * success: LOGDMP_OK * failure: something else */ int disp_noredoinoext(struct lrd * lrd_ptr) { fprintf(outfp, "fileset = d %d \n", lrd_ptr->log.noredoinoext.fileset); fprintf(outfp, "\tiag number = d %d extent index = d %d\n", lrd_ptr->log.noredoinoext.iagnum, lrd_ptr->log.noredoinoext.inoext_idx); fprintf(outfp, "\tpxd length = d %d phys offset = x %llx (d %lld)\n", lengthPXD(&(lrd_ptr->log.noredoinoext.pxd)), (long long) addressPXD(&(lrd_ptr->log.noredoinoext.pxd)), (long long) addressPXD(&(lrd_ptr->log.noredoinoext.pxd))); return (LOGDMP_OK); } /* end of disp_noredopage() */ /*************************************************************************** * * NAME: disp_redopage * * FUNCTION: * * PARAMETERS: none * * NOTES: * * RETURNS: * success: LOGDMP_OK * failure: something else */ int disp_redopage(struct lrd * lrd_ptr) { fprintf(outfp, "fileset = d %d inode = d %d (x %x)\n", lrd_ptr->log.redopage.fileset, lrd_ptr->log.redopage.inode, lrd_ptr->log.redopage.inode); switch (lrd_ptr->log.redopage.type) { case LOG_INODE: fprintf(outfp, "\ttype = d %d REDOPAGE:INODE\n", lrd_ptr->log.redopage.type); break; case LOG_XTREE: fprintf(outfp, "\ttype = d %d REDOPAGE:XTREE\n ", lrd_ptr->log.redopage.type); break; case (LOG_XTREE | LOG_NEW): fprintf(outfp, "\ttype = d %d REDOPAGE:XTREE_NEW\n ", lrd_ptr->log.redopage.type); break; case (LOG_BTROOT | LOG_XTREE): fprintf(outfp, "\ttype = d %d REDOPAGE:BTROOT_XTREE\n ", lrd_ptr->log.redopage.type); break; case LOG_DTREE: fprintf(outfp, "\ttype = d %d REDOPAGE:DTREE\n ", lrd_ptr->log.redopage.type); break; case (LOG_DTREE | LOG_NEW): fprintf(outfp, "\ttype = d %d REDOPAGE:DTREE_NEW \n ", lrd_ptr->log.redopage.type); break; case (LOG_DTREE | LOG_EXTEND): fprintf(outfp, "\ttype = d %d REDOPAGE:DTREE_EXTEND\n ", lrd_ptr->log.redopage.type); break; case (LOG_BTROOT | LOG_DTREE): fprintf(outfp, "\ttype = d %d REDOPAGE:BTROOT_DTREE\n ", lrd_ptr->log.redopage.type); break; case (LOG_BTROOT | LOG_DTREE | LOG_NEW): fprintf(outfp, "\ttype = d %d REDOPAGE:BTROOT_DTREE.NEW\n ", lrd_ptr->log.redopage.type); break; case LOG_EA: fprintf(outfp, "\ttype = d %d REDOPAGE:EA\n", lrd_ptr->log.redopage.type); break; case LOG_ACL: fprintf(outfp, "\ttype = d %d REDOPAGE:ACL\n", lrd_ptr->log.redopage.type); break; case LOG_DATA: fprintf(outfp, "\ttype = d %d REDOPAGE:DATA\n", lrd_ptr->log.redopage.type); break; /* case LOG_NOREDOFILE: fprintf( outfp, "\ttype = d %d REDOPAGE:NOREDOFILE\n", lrd_ptr->log.redopage.type ); break; */ default: fprintf(outfp, "\ttype = d %d ***UNRECOGNIZED***\n", lrd_ptr->log.redopage.type); break; } fprintf(outfp, "\tl2linesize = d %d ", lrd_ptr->log.redopage.l2linesize); fprintf(outfp, "pxd length = d %d phys offset = x %llx (d %lld)\n", lengthPXD(&(lrd_ptr->log.redopage.pxd)), (long long) addressPXD(&(lrd_ptr->log.redopage.pxd)), (long long) addressPXD(&(lrd_ptr->log.redopage.pxd))); return (LOGDMP_OK); } /* end of disp_redopage() */ /*************************************************************************** * * NAME: disp_updatemap * * FUNCTION: * * PARAMETERS: none * * NOTES: * * RETURNS: * success: LOGDMP_OK * failure: something else */ int disp_updatemap(struct lrd * lrd_ptr) { int flag_unrecognized = -1; fprintf(outfp, "fileset = d %d inode = d %d (x %x)\n", lrd_ptr->log.updatemap.fileset, lrd_ptr->log.updatemap.inode, lrd_ptr->log.updatemap.inode); fprintf(outfp, "\ttype = x %x UPDATEMAP: ", lrd_ptr->log.updatemap.type); if ((lrd_ptr->log.updatemap.type & LOG_ALLOCXADLIST) == LOG_ALLOCXADLIST) { flag_unrecognized = 0; fprintf(outfp, " ALLOCXADLIST"); } if ((lrd_ptr->log.updatemap.type & LOG_ALLOCPXDLIST) == LOG_ALLOCPXDLIST) { flag_unrecognized = 0; fprintf(outfp, " ALLOCPXDLIST"); } if ((lrd_ptr->log.updatemap.type & LOG_ALLOCXAD) == LOG_ALLOCXAD) { flag_unrecognized = 0; fprintf(outfp, " ALLOCXAD"); } if ((lrd_ptr->log.updatemap.type & LOG_ALLOCPXD) == LOG_ALLOCPXD) { flag_unrecognized = 0; fprintf(outfp, " ALLOCPXD"); } if ((lrd_ptr->log.updatemap.type & LOG_FREEXADLIST) == LOG_FREEXADLIST) { flag_unrecognized = 0; fprintf(outfp, " FREEXADLIST"); } if ((lrd_ptr->log.updatemap.type & LOG_FREEPXDLIST) == LOG_FREEPXDLIST) { flag_unrecognized = 0; fprintf(outfp, " FREEPXDLIST"); } if ((lrd_ptr->log.updatemap.type & LOG_FREEXAD) == LOG_FREEXAD) { flag_unrecognized = 0; fprintf(outfp, " FREEXAD"); } if ((lrd_ptr->log.updatemap.type & LOG_FREEPXD) == LOG_FREEPXD) { flag_unrecognized = 0; fprintf(outfp, " FREEPXD"); } if (flag_unrecognized) { fprintf(outfp, " *** UNRECOGNIZED ***"); } fprintf(outfp, "\n"); fprintf(outfp, "\tnxd = d %d (number of extents)\n", lrd_ptr->log.updatemap.nxd); fprintf(outfp, "\tpxd length = d %d phys offset = x %llx (d %lld)\n", lengthPXD(&(lrd_ptr->log.updatemap.pxd)), (long long) addressPXD(&(lrd_ptr->log.updatemap.pxd)), (long long) addressPXD(&(lrd_ptr->log.updatemap.pxd))); return (LOGDMP_OK); } /* end of disp_updatemap() */ /***************************************************************************** * NAME: open_outfile * * FUNCTION: Open the output file. * * PARAMETERS: * Device - input - the device specification * * NOTES: * * RETURNS: * success: XCHKLOG_OK * failure: something else */ int open_outfile() { int openof_rc = 0; outfp = fopen(output_filename, "w"); if (outfp == NULL) { /* output file open failed */ printf("LOG_DUMP: unable to open output file: ./jfslog.dmp\n"); openof_rc = -1; } else { logdmp_outfile_is_open = -1; } return (openof_rc); } /* end of open_outfile ( ) */ jfsutils-1.1.15.orig/libfs/log_map.c0000644000000000000000000016111010772001331014142 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * FUNCTION: log_map.c: recovery manager */ #include #include #include #include #include #include #include #include #include "jfs_types.h" #include "jfs_endian.h" #include "jfs_filsys.h" #include "jfs_superblock.h" #include "jfs_dinode.h" #include "jfs_dtree.h" #include "jfs_xtree.h" #include "jfs_logmgr.h" #include "jfs_dmap.h" #include "jfs_imap.h" #include "logredo.h" #include "devices.h" #include "debug.h" #include "fsck_message.h" /* for fsck message logging facility */ /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * R E M E M B E R M E M O R Y A L L O C F A I L U R E * */ extern int32_t Insuff_memory_for_maps; extern char *available_stg_addr; extern int32_t available_stg_bytes; extern char *bmap_stg_addr; extern int32_t bmap_stg_bytes; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * L O C A L M A C R O D E F I N I T I O N S * */ #define UZBIT_32 ((uint32_t) (1 << 31 )) /* The following define is for aggregate block allocation map */ #define SIZEOFDMAPCTL sizeof(struct dmapctl) /* * At the logredo time, the dmap read into memory to form an array * of file pages. The first page is always the aggregate disk allocation * map descriptor ( i.e. the bmap control page), the remaining pages are * either dmap control pages or dmap pages. * given zero origin dmapctl level of the top dmapctl, tlvl, * if tlvl == 2, L2 page exists; * if tlvl == 1, L2 does not exist, * but L1.n and L0.n pages exist (0 <= n <= 1023); * if tlvl == 0, L2 and L1 pages do not exist, * only L0.n pages exist (0 <= n <= 1023); */ /* convert disk block number to bmap file page number */ #define BLKTODMAPN(b)\ (((b) >> 13) + ((b) >> 23) + ((b) >> 33) + 3 + 1) /* convert dmap block number to bmap file page number */ #define DMAPTOBMAPN(d)\ ((d) + ((d) >> 10) + ((d) >> 20) + 3 + 1) /* convert disk block number to allocation group number */ #define BLKNOTOAG(b,l2agsize) ((b) >> l2agsize) /* things for the block allocation map */ int16_t top_dmapctl_lvl; /* zero origin level of the top dmapctl */ /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * S T U F F F O R T H E L O G * * externals defined in logredo.c */ extern struct vopen vopen[]; /* (88) */ #define fs_next fsimap_lst.next #define fs_fileset fsimap_lst.fileset #define fsimap_ctrl fsimap_lst.fsimapctrl /* * file system page buffer cache * * for k > 0, bufhdr[k] describes contents of buffer[k-1]. * bufhdr[0] is reserved as anchor for free/lru list: * bufhdr[0].next points to the MRU buffer (head), * bufhdr[0].prev points to the LRU buffer (tail); */ int32_t bhmask = (NBUFPOOL - 1); /* hash mask for bhash */ int16_t bhash[NBUFPOOL]; /* hashlist anchor table */ /* buffer header table */ extern struct bufhdr { int16_t next; /* 2: next on free/lru list */ int16_t prev; /* 2: previous on free/lru list */ int16_t hnext; /* 2: next on hash chain */ int16_t hprev; /* 2: previous on hash chain */ char modify; /* 1: buffer was modified */ char inuse; /* 1: buffer on hash chain */ int16_t reserve; /* 2 */ int32_t vol; /* 4: minor of agrregate/lv number */ pxd_t pxd; /* 8: on-disk page pxd */ } bufhdr[]; /* (24) */ /* buffer table */ extern struct bufpool { char bytes[PSIZE]; } buffer[]; /* * maptab[] * * maptab is used for imap. It determines number of zeroes within * characters of imap bitmap words. The character values serve * as indexes into the table * e.g. if char has value of "3", maptab[2] = 6 which indicates there * are 6 zeroes in "3". */ unsigned char maptab[256] = { 8, 7, 7, 6, 7, 6, 6, 5, 7, 6, 6, 5, 6, 5, 5, 4, 7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3, 7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3, 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3, 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 5, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1, 7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3, 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 5, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1, 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, 5, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1, 5, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1, 4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0 }; /* * budtab[] * * used to determine the maximum free string(i.e. buddy size) * in a character of a dmap bitmap word. the values of the character * serve as the index into this array and the value of the budtab[] * array at that index is the max binary buddy of free bits within * the character. * e.g. when char = "15" (i.e. 00001111), budtab[15] = 2 because * the max free bits is 2**2 (=4). * */ signed char budtab[256] = { 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -1 }; /* * external references */ extern int fsError(int, int, int64_t); extern int markBmap(struct dmap *, pxd_t, int, int); extern int bflush(int32_t, struct bufpool *); extern int alloc_storage(int32_t, void **, int32_t *); extern int alloc_dmap_bitrec(struct dmap_bitmaps **); extern int alloc_wrksp(uint32_t, int, int, void **); /* * forward references */ int initMaps(int32_t); int bMapInit(int, struct dinode *); int bMapRead(int, int32_t, void *); int bMapWrite(int, int32_t, void *); int dMapGet(int, int32_t); int iMapInit(int, struct dinode *); int iMapRead(int, int32_t, void *); int iMapWrite(int, int32_t, void *); int iagGet(int, int32_t); int updateMaps(int); int writeImap(int, struct fsimap_lst, struct dinode *); int updateImapPage(int32_t, struct iag *, int16_t *, int16_t *); int writeBmap(int, struct dbmap *, struct dinode *); int updDmapPage(struct dmap *, int32_t, int8_t *); int rXtree(int32_t, struct dinode *, xtpage_t **); signed char adjTree(struct dmapctl *, int32_t, int32_t); static int32_t maxBud(unsigned char *); int bread(int32_t, pxd_t, void **, int32_t); /* * NAME: initMaps() * * FUNCTION: Logredo() needs to reconstruct fileset imap and Blk alloc map. * In the first release, the aggregate imap is regarding as * static. * In XJFS, the imaps and bmap are dynamically allocated. * At the beginning of logredo, the xtrees for these maps are * the only trustable things. The xtree is rooted * at the inode. So read the inodes first. then call * readMap() to allocate storage for inode and disk maps and * read them into memory. initialize workmaps to zeros. */ int initMaps(int32_t vol) { /* index in vopen array = minor(volid) */ int rc; struct dinode *dip; pxd_t pxd1; /* * initialize in-memory block allocation map */ /* read in the bmap inode (i_number = 2) in a buffer: */ PXDaddress(&pxd1, AITBL_OFF >> vopen[vol].l2bsize); PXDlength(&pxd1, vopen[vol].lbperpage); if ((rc = bread(vol, pxd1, (void **) &dip, PB_READ)) != 0) { fsck_send_msg(lrdo_READBMAPINOFAIL, errno); return (BREAD_BMAPINIT); } /* locate the inode in the buffer page */ dip += BMAP_I; /* read block map into memory and init workmap to zeros */ if ((rc = bMapInit(vol, dip)) != 0) { fsck_send_msg(lrdo_READBMAPFAIL); return (rc); } /* * initialize in-memory fileset inode allocation map */ /* read in the fileset imap inode (i_number = 16) in a buffer: */ PXDaddress(&pxd1, (AITBL_OFF + (SIZE_OF_MAP_PAGE << 1)) >> vopen[vol].l2bsize); if ((rc = bread(vol, pxd1, (void **) &dip, PB_READ)) != 0) { fsck_send_msg(lrdo_READIMAPINOFAIL, errno); return (BREAD_IMAPINIT); } /* locate the inode in the buffer page */ dip += FILESYSTEM_I & 0x07; /* read inode map into memory and init workmap to zeros */ if ((rc = iMapInit(vol, dip)) != 0) { fsck_send_msg(lrdo_READIMAPFAIL); return (rc); } /* Return 0 */ return (rc); } /*************************************************************** * NAME: bMapInit() * * FUNCTION: Calculate the number of pages in the block map. Allocate * an array of records so there is one for each page in the * Aggregate Block Map. Initialize each array element with the * aggregate offset of the page it describes. * * Allocate page buffers for the control page, one dmap page, * and one control page at each Ln level used in this BMap. * * Read in the map control page. * * Get the bitmaps for the last dMap page and set the * 'excess bits' to ones. * * NOTES: In order to minimize logredo storage usage (because we * must be able to run during autocheck when there is no * paging space available), we won't actually read in a dmap * page unless/until we need to touch it. At that point we'll * allocate enough storage to accomodate the dmap's wmap * and pmap only. * * MORE NOTES: * There are two fields are trustable at the beginning of * the logredo. One is fssize, which is the s_size field in * aggregate superblock converting to number of aggregate * blocks. This size only tells how many struct dmap pages are * need for the bmap. Another is di_size field in struct dinode. * In XJFS, the aggre. bmap xtree is rooted at aggregate * inode #2. The xtree for map is journaled. * Since a COMMIT_FORCE is used for the transaction of * xtree update, index pages are synced written out at * commit time, we can assume that the xtree as well as * the di_size for map is ok for reading the map pages * at the logredo time. * * Allocate storage according to di_size for bmap file. * * In XJFS, the bmap is dynamically allocated. Its xtree * is rooted at aggregate inode #2. The xtree for map is * journaled. Since a COMMIT_FORCE is used for the * transaction of xtree update, index pages are synced * (i.e., written out at commit time), we can assume that * the xtree for map is ok for reading the map pages at * the logredo */ int bMapInit(int vol, /* index in vopen array */ struct dinode *dip) { /* disk inode of bmap */ int bmi_rc = 0; int32_t ndmaps; int I_am_logredo = -1; uint32_t bytes_needed = 0; caddr_t p0 = NULL; xtpage_t *xp; int i, j, k, w, pgidx; int32_t nbytes, npages, this_page; uint32_t *pmap, mask; pxd_t pxd; int64_t xaddr; /* * compute the number pages in the Aggregate Block Map, then * allocate an array of records to describe them. * * Note that we also allocate * a page so we can start on a page boundary. * a page for the BMap control page * a page buffer for reading and writing dmap pages * a page buffer for reading and writing L0 pages * a page buffer for reading and writing L1 pages * a page buffer for reading and writing the L2 page */ vopen[vol].bmap_page_count = __le64_to_cpu(dip->di_size) / PSIZE; bytes_needed = (6 * PSIZE) + (vopen[vol].bmap_page_count * sizeof (struct bmap_wsp)); ndmaps = ((vopen[vol].fssize + BPERDMAP - 1) >> L2BPERDMAP); bmi_rc = alloc_wrksp((uint32_t) bytes_needed, 0, I_am_logredo, (void **) &p0); /* * note that failure to allocate the bmap is a special case. * * We can replay the log without updating the bmap and * then tell fsck to run a full check/repair which will * rebuild the bmap. This would not work with the imap. */ if ((bmi_rc == 0) && (p0 != NULL)) { /* we got the storage */ bmap_stg_addr = p0; bmap_stg_bytes = bytes_needed; } else { fsck_send_msg(lrdo_ALLOC4BMAPFAIL, (long long) __le64_to_cpu(dip->di_size)); Insuff_memory_for_maps = -1; return (0); } /* * we got the storage. * find the first page boundary and parcel it out. */ p0 = (char *) (((((size_t) p0) + PSIZE - 1) / PSIZE) * PSIZE); vopen[vol].bmap_ctl = (struct dbmap *) p0; p0 = (char *) (p0 + PSIZE); vopen[vol].L2_pbuf = (struct dmapctl *) p0; p0 = (char *) (p0 + PSIZE); vopen[vol].L1_pbuf = (struct dmapctl *) p0; p0 = (char *) (p0 + PSIZE); vopen[vol].L0_pbuf = (struct dmapctl *) p0; p0 = (char *) (p0 + PSIZE); vopen[vol].dmap_pbuf = (struct dmap *) p0; p0 = (char *) (p0 + PSIZE); vopen[vol].bmap_wsp = (struct bmap_wsp *) p0; /* * set the record to say they are currently empty. */ vopen[vol].L2_pagenum = -1; vopen[vol].L1_pagenum = -1; vopen[vol].L0_pagenum = -1; vopen[vol].dmap_pagenum = -1; /* * Initialize the BMap workspace array with aggregate offsets */ pgidx = 0; /* * read in the leftmost leaf page of the * block allocation map xtree */ if (rXtree(vol, dip, &xp)) { fsck_send_msg(lrdo_RBMPREADXTFAIL); return (BMAP_READERROR1); } /* * in case of leaf root, init next sibling pointer so it will * appear as last non-root leaf page termination */ if (xp->header.flag & BT_ROOT) xp->header.next = 0; /* * the leaf pages contain the aggregate offsets we need */ PXDlength(&pxd, vopen[vol].lbperpage); do { /* * get extent descriptors from the current leaf */ for (i = XTENTRYSTART; i < __le16_to_cpu(xp->header.nextindex); i++) { xaddr = addressXAD(&xp->xad[i]) << vopen[vol].l2bsize; nbytes = lengthXAD(&xp->xad[i]) << vopen[vol].l2bsize; npages = nbytes / PSIZE; /* * get page offsets from the current extent descriptor */ for (j = 0; j < npages; j++) { vopen[vol].bmap_wsp[pgidx].page_offset = xaddr + (j * PSIZE); pgidx++; } } /* * read in the next leaf (if any) */ xaddr = __le64_to_cpu(xp->header.next); if (xaddr) { PXDaddress(&pxd, xaddr); if (bread(vol, pxd, (void **) &xp, PB_READ)) { fsck_send_msg(lrdo_RBMPREADNXTLFFAIL); return (BMAP_READERROR3); } } } while (xaddr); /* * Now read in the map control page */ bmi_rc = bMapRead(vol, 0, (void *) vopen[vol].bmap_ctl); if (bmi_rc != 0) { return (bmi_rc); } ujfs_swap_dbmap(vopen[vol].bmap_ctl); /* * And the last dmap page */ bmi_rc = dMapGet(vol, (ndmaps - 1)); if (bmi_rc || Insuff_memory_for_maps) return bmi_rc; /* * init persistent bit map of last/partial dmap page * * if the last dmap may have bits that are beyond mapsize, * the pmap[] bits for these non-existing blocks have to be * inited as allocated. */ k = vopen[vol].fssize & (BPERDMAP - 1); if (k > 0) { this_page = DMAPTOBMAPN(ndmaps - 1); pmap = (uint32_t *) & (vopen[vol].bmap_wsp[this_page].dmap_bitmaps->pmap); i = k & (DBWORD - 1); /* valid bits in partial word */ w = k >> L2DBWORD; /* number of valid full words */ /* init last valid/first invalid partial word */ if (i) { mask = ((uint32_t) (ONES << i)) >> i; pmap[w] |= mask; w++; } /* init full invalid words */ for (; w < LPERDMAP; w++) pmap[w] = ONES; } return 0; } /*************************************************************** * NAME: bMapRead() * * FUNCTION: Read the requested block map page from the device * into the specified buffer. * * NOTES: * */ int bMapRead(int vol, /* index in vopen array */ int32_t page_number, /* block map page offset to read */ void *page_buffer) { /* where to put the page read */ int bmr_rc = 0; /* * read in the map page */ bmr_rc = ujfs_rw_diskblocks(vopen[vol].fp, vopen[vol].bmap_wsp[page_number]. page_offset, PSIZE, page_buffer, GET); if (bmr_rc != 0) { fsck_send_msg(lrdo_RBMPREADDATFAIL); return (BMAP_READERROR7); } return (bmr_rc); } /*************************************************************** * NAME: bMapWrite() * * FUNCTION: Write the contents of the given buffer to the specified * block map page on the device * * NOTES: * */ int bMapWrite(int vol, /* index in vopen array */ int32_t page_number, /* where to write the page */ void *page_buffer) { /* where get the data to write */ int bmw_rc = 0; /* * write out the map page */ bmw_rc = ujfs_rw_diskblocks(vopen[vol].fp, vopen[vol].bmap_wsp[page_number]. page_offset, PSIZE, page_buffer, PUT); if (bmw_rc != 0) { fsck_send_msg(lrdo_WRBMPBLKWRITEFAIL, (long long)vopen[vol].bmap_wsp[page_number].page_offset); return (BMAP_WRITEERROR2); } return (bmw_rc); } /*************************************************************** * NAME: dMapGet() * * FUNCTION: Calculate the page position (in the block map) of the * requested dmap page. Read it into the dmap buffer, * allocate a bit map record for it, copy the pmap from the * page read into the bit map record and then initialize the * wmap in the bit map record. * * NOTES: If we are unable to allocate storage, we'll reset some * stuff so that the storage already allocated to the block * map is released (for other use by logredo) and then * continue processing without further updates to the block * map. (In this case, when we return to fsck we'll pass * a return code which will ensure that full fsck will be * done. The full fsck includes rebuilding the block map, * so this provides the data protection of logredo even if not * the performance of logredo alone.) * */ int dMapGet(int vol, /* index in vopen array */ int32_t dmap_num) { /* the ordinal dmap page wanted */ int dmg_rc = 0; int64_t page_needed; struct dmap_bitmaps *dmap_bitrec; struct dmap *dmap_pg; int32_t maplen; /* * figure out the map page needed */ page_needed = DMAPTOBMAPN(dmap_num); /* * read in the map page */ dmg_rc = bMapRead(vol, page_needed, (void *) vopen[vol].dmap_pbuf); if (dmg_rc != 0) { return (dmg_rc); } ujfs_swap_dmap(vopen[vol].dmap_pbuf); vopen[vol].dmap_pagenum = page_needed; /* * allocate and set up a bitmap workspace for this page */ dmg_rc = alloc_dmap_bitrec(&dmap_bitrec); if ((dmg_rc == 0) && !Insuff_memory_for_maps) { dmap_pg = vopen[vol].dmap_pbuf; maplen = sizeof (uint32_t) * LPERDMAP; memset((void *) &(dmap_bitrec->wmap), 0, maplen); memcpy((void *) &(dmap_bitrec->pmap), (void *) &(dmap_pg->pmap), maplen); vopen[vol].bmap_wsp[page_needed].dmap_bitmaps = dmap_bitrec; } return (dmg_rc); } /* * NAME: iMapInit() * * FUNCTION: Calculate the number of pages in the fileset Inode Map. * Allocate an array of records so there is one for each * page in the map. Initialize each array element with the * aggregate offset of the page it describes. * * Allocate a page buffer for IAGs. * * Read in the map control page. * * * NOTES: * Regarding extendfs, * allocate storage for a map, read it into memory, and * initialize workmap to zeros. recompute on the basis of * the file system size and allocation group sizes in the filesystem * superblock the number of allocation groups and the size of map. * (ie the size info in the map is not trusted). this is done to * recover from a crash in the middle of extending a filesystem. * depending on where the crash occurred, the extendfs will be * completed here, or backed-out. in backing out, the map * considered as files may be bigger than neceassry, but logically * this causes no problem: extendfs can be re-run, and the extra * data not accessed before then. */ int iMapInit(int vol, /* index in vopen array */ struct dinode *dp) { /* disk inode of map */ int imi_rc; int32_t bytes_needed, map_pages; int32_t allocated_from_bmap = 0; int64_t nbytes, xaddr; char *ptr0 = NULL; int32_t i, j, pgidx; xtpage_t *p; /* xtree page */ pxd_t pxd; /* * figure out how many pages there are in the map, and * from that the size array we need, and from that the * number of bytes to allocate now. * * Note that we also allocate * a page so we fcan start on a page boundary * a page for the IMap control page * a page buffer for reading and writing IAGs * a page buffer for reading and writing IAGs * (when rebuilding the by-AG lists we need a 2nd buffer) */ vopen[vol].fsimap_lst.fileset = __le32_to_cpu(dp->di_number); vopen[vol].fsimap_lst.next = NULL; /* in rel 1, only one fileset */ vopen[vol].fsimap_lst.imap_page_count = __le64_to_cpu(dp->di_size) / PSIZE; bytes_needed = (4 * PSIZE) + (vopen[vol].fsimap_lst.imap_page_count * sizeof (struct imap_wsp)); /* allocate storage for imap. the size is always a multiple * of PSIZE so we don't have to round it up. * di_size is number of bytes */ imi_rc = alloc_storage((uint32_t) bytes_needed, (void **) &ptr0, &allocated_from_bmap); if ((imi_rc != 0) || (ptr0 == NULL)) { /* imap allocation failed */ fsck_send_msg(lrdo_ALLOC4IMAPFAIL, bytes_needed); return (ENOMEM2); } else if (ptr0 != NULL) { /* imap allocation successful */ if (allocated_from_bmap) { fsck_send_msg(lrdo_USINGBMAPALLOC4IMAP); } } /* end imap allocation successful */ /* * take it to a page boundary and parcel it out */ ptr0 = (char *) (((((size_t) ptr0) + PSIZE - 1) / PSIZE) * PSIZE); vopen[vol].fsimap_lst.fsimapctrl = (struct dinomap *) ptr0; ptr0 = (char *) (ptr0 + PSIZE); vopen[vol].fsimap_lst.iag_pbuf = (struct iag *) ptr0; ptr0 = (char *) (ptr0 + PSIZE); vopen[vol].fsimap_lst.iag_pbuf2 = (struct iag *) ptr0; ptr0 = (char *) (ptr0 + PSIZE); vopen[vol].fsimap_lst.imap_wsp = (struct imap_wsp *) ptr0; /* * set the record to say the buffer is currently empty */ vopen[vol].fsimap_lst.imap_pagenum = -1; /* * Initialize the IMap workspace array with aggregate offsets */ /* * from the xtroot, go down to the xtree leaves * which have the xad's for the map data */ if (rXtree(vol, dp, &p)) { fsck_send_msg(lrdo_RIMPREADXTFAIL); return (IMAP_READERROR1); } /* * Initialize the IMap workspace array with aggregate offsets */ pgidx = 0; /* * read in the leftmost leaf page of the * inode allocation map xtree */ if (rXtree(vol, dp, &p)) { fsck_send_msg(lrdo_RIMPREADXTFAIL); return (IMAP_READERROR2); } /* * in case of leaf root, init next sibling pointer so it will * appear as last non-root leaf page termination */ if (p->header.flag & BT_ROOT) p->header.next = 0; /* * the leaf pages contain the aggregate offsets we need */ PXDlength(&pxd, vopen[vol].lbperpage); do { /* * get extent descriptors from the current leaf */ for (i = XTENTRYSTART; i < __le16_to_cpu(p->header.nextindex); i++) { xaddr = addressXAD(&p->xad[i]) << vopen[vol].l2bsize; nbytes = lengthXAD(&p->xad[i]) << vopen[vol].l2bsize; map_pages = nbytes / PSIZE; /* * get page offsets from the current extent descriptor */ for (j = 0; j < map_pages; j++) { vopen[vol].fsimap_lst.imap_wsp[pgidx]. page_offset = xaddr + (j * PSIZE); pgidx++; } } /* * read in the next leaf (if any) */ xaddr = __le64_to_cpu(p->header.next); if (xaddr) { PXDaddress(&pxd, xaddr); if (bread(vol, pxd, (void **) &p, PB_READ)) { fsck_send_msg(lrdo_RIMPREADNXTLFFAIL); return (IMAP_READERROR3); } } } while (xaddr); /* * Now read in the map control page */ imi_rc = iMapRead(vol, 0, (void *) vopen[vol].fsimap_lst.fsimapctrl); if (imi_rc != 0) { return (imi_rc); } ujfs_swap_dinomap(vopen[vol].fsimap_lst.fsimapctrl); return (0); } /*************************************************************** * NAME: iMapRead() * * FUNCTION: Read the requested inode map page from the device * into the specified buffer. * * NOTES: * */ int iMapRead(int vol, /* index in vopen array */ int32_t page_number, /* map page offset to read */ void *page_buffer) { /* where to put the page read */ int imr_rc = 0; /* * read in the map page */ imr_rc = ujfs_rw_diskblocks(vopen[vol].fp, vopen[vol].fsimap_lst.imap_wsp[page_number].page_offset, PSIZE, page_buffer, GET); if (imr_rc != 0) { fsck_send_msg(lrdo_RIMPREADDATFAIL); return (IMAP_READERROR4); } return (imr_rc); } /*************************************************************** * NAME: iMapWrite() * * FUNCTION: Write the contents of the given buffer to the specified * inode map page on the device * * NOTES: * */ int iMapWrite(int vol, /* index in vopen array */ int32_t page_number, /* where to write the page */ void *page_buffer) { /* where get the data to write */ int imw_rc = 0; /* * write out the map page */ imw_rc = ujfs_rw_diskblocks(vopen[vol].fp, vopen[vol].fsimap_lst.imap_wsp[page_number].page_offset, PSIZE, page_buffer, PUT); if (imw_rc != 0) { fsck_send_msg(lrdo_WRIMPBLKWRITEFAIL, (long long)vopen[vol].bmap_wsp[page_number].page_offset); return (IMAP_WRITEERROR2); } return (imw_rc); } /*************************************************************** * NAME: iagGet() * * FUNCTION: Read the requested iag into the iag page buffer, allocate * a data record for it, copy the pmap and inoext array from * the page read into the data and then initialize the wmap * in the data record. * * NOTES: * */ int iagGet(int vol, /* index in vopen array */ int32_t iag_num) { /* the iag number of the iag wanted */ int ig_rc = 0; int32_t bytes_needed; int32_t allocated_from_bmap = 0; struct iag_data *iag_datarec; struct iag *iag_pg; int32_t maplen, inoext_arrlen; /* * read in the map page */ ig_rc = iMapRead(vol, (iag_num + 1), (void *) vopen[vol].fsimap_lst.iag_pbuf); if (ig_rc != 0) { return (ig_rc); } ujfs_swap_iag(vopen[vol].fsimap_lst.iag_pbuf); vopen[vol].fsimap_lst.imap_pagenum = iag_num + 1; /* * allocate and set up a data workspace for this page */ bytes_needed = sizeof (struct iag_data); ig_rc = alloc_storage((uint32_t) bytes_needed, (void **) &iag_datarec, &allocated_from_bmap); if ((ig_rc != 0) || (iag_datarec == NULL)) { fsck_send_msg(lrdo_ALLOC4IMAPFAIL, bytes_needed); return (ENOMEM2); } if (allocated_from_bmap) { fsck_send_msg(lrdo_USINGBMAPALLOC4IMAP); } iag_pg = vopen[vol].fsimap_lst.iag_pbuf; maplen = sizeof (uint32_t) * LPERDMAP; inoext_arrlen = sizeof (pxd_t) * EXTSPERIAG; memset((void *) &(iag_datarec->wmap), 0, maplen); memcpy((void *) &(iag_datarec->pmap), (void *) &(iag_pg->pmap), maplen); memcpy((void *) &(iag_datarec->inoext), (void *) &(iag_pg->inoext), inoext_arrlen); vopen[vol].fsimap_lst.imap_wsp[(iag_num + 1)].imap_data = iag_datarec; return 0; } /* * NAME: updateMaps(vol) * * FUNCTION: finalize and write out both imap and bmap. * * NOTE: Imaps update must be before the bmap update * because we need to change bmap while rebuild the imaps. */ int updateMaps(int32_t vol) { /* index in vopen array */ int rc; struct dinode *dip; pxd_t pxd1; /* * update fileset inode allocation map */ /* read in the fileset imap inode (i_number = 16) in a buffer: */ PXDaddress(&pxd1, (AITBL_OFF + (SIZE_OF_MAP_PAGE << 1)) >> vopen[vol].l2bsize); PXDlength(&pxd1, vopen[vol].lbperpage); if ((rc = bread(vol, pxd1, (void **) &dip, PB_READ)) != 0) { fsck_send_msg(lrdo_UMPREADIMAPINOFAIL); return (IMAP_READERROR5); } /* locate the inode in the buffer page */ dip += FILESYSTEM_I & 0x07; /* finalize the imap and write it out */ if ((rc = writeImap(vol, vopen[vol].fsimap_lst, dip)) != 0) { fsck_send_msg(lrdo_UMPWRITEIMAPCTLFAIL); return (rc); } /* * if we were able to allocate enough storage for the BMap, * update file system block allocation map * * (Otherwise we'll let fsck be responsible for the BMap) */ if (!Insuff_memory_for_maps) { /* we do have a local BMap image */ /* read in the bmap inode (i_number = 2) in a buffer: */ PXDaddress(&pxd1, AITBL_OFF >> vopen[vol].l2bsize); if ((rc = bread(vol, pxd1, (void **) &dip, PB_READ)) != 0) { fsck_send_msg(lrdo_UMPREADBMAPINOFAIL); return (BMAP_READERROR4); } /* locate the inode in the buffer page */ dip += BMAP_I; /* finalize the bmap and write it out */ if ((rc = writeBmap(vol, vopen[vol].bmap_ctl, dip)) != 0) { fsck_send_msg(lrdo_UMPWRITEBMAPCTLFAIL); } } /* end we do have a local BMap image */ return (rc); } /* * NAME: writeImap() * * FUNCTION: copy permanent map to work map. Rebuild control information * for each iag page. Then rebuild the imap control page. * We assume the iagnum is correct at the beginning of logredo. * */ int writeImap(int vol, /* index in vopen array */ struct fsimap_lst fsimap, /* fileset imap workspace */ struct dinode *dp) { /* disk inode of imap */ struct dinomap *imap_ctl; int rc; int32_t k, iagpages, npages, next_iag; int16_t iagfree, numinos, agno; struct iag *iagp; struct iag *iag_pg; int32_t next_imap_page = 1; struct iag_data *iag_datarec; int32_t maplen, inoext_arrlen; if (vopen[vol].status == FM_LOGREDO) { fsck_send_msg(lrdo_WRIMPNOTRBLDGIMAP); return (NOTREBUILDING_IMAP); } fsck_send_msg(lrdo_WRIMPSTART); imap_ctl = fsimap.fsimapctrl; iagp = fsimap.iag_pbuf; iag_pg = fsimap.iag_pbuf2; maplen = sizeof (uint32_t) * LPERDMAP; inoext_arrlen = sizeof (pxd_t) * EXTSPERIAG; npages = __le64_to_cpu(dp->di_size) >> L2PSIZE; /* the first page is imap control page, so the number of * iag pages is one less of npages. */ iagpages = npages - 1; /* initialize the struct dinomap page */ imap_ctl->in_freeiag = -1; /* iag.iagnum is zero origin. They are in order in the * imap file. So in_nextiag should be the last iag page * plus one. The last iag.iagnum is (npages - 2). */ imap_ctl->in_nextiag = iagpages; imap_ctl->in_numinos = 0; imap_ctl->in_numfree = 0; /* init imap_ctl->in_agctl[]. Although the aggregate * has only vopen[vol].numag, since the structure * has defined MAXAG, the initializarion will do * against MAXAG */ for (k = 0; k < MAXAG; k++) { imap_ctl->in_agctl[k].inofree = -1; imap_ctl->in_agctl[k].extfree = -1; imap_ctl->in_agctl[k].numinos = 0; imap_ctl->in_agctl[k].numfree = 0; } /* process each iag page of the map. * rebuild AG Free Inode List, AG Free Inode Extent List, * and IAG Free List from scratch */ for (k = 0; k < iagpages; k++) { /* * read in the IAG */ if (fsimap.imap_pagenum != next_imap_page) { rc = iMapRead(vol, next_imap_page, iagp); if (rc != 0) { return (rc); } ujfs_swap_iag(iagp); } fsimap.imap_pagenum = next_imap_page; /* * if the bit maps and inoext arrary for this iag are * in memory, copy the pmap and inoext into the page */ iag_datarec = fsimap.imap_wsp[next_imap_page].imap_data; if (iag_datarec != NULL) { memcpy((void *) &(iagp->pmap), (void *) &(iag_datarec->pmap), maplen); memcpy((void *) &(iagp->inoext), (void *) &(iag_datarec->inoext), inoext_arrlen); } next_imap_page++; iagfree = 0; agno = BLKNOTOAG(iagp->agstart, vopen[vol].l2agsize); updateImapPage(vol, iagp, &numinos, &iagfree); if (iagfree) { /* all inodes are free, then this iag should * be inserted into iag free list. */ iagp->inofreefwd = iagp->inofreeback = -1; iagp->extfreefwd = iagp->extfreeback = -1; iagp->iagfree = imap_ctl->in_freeiag; imap_ctl->in_freeiag = iagp->iagnum; } else if (iagp->nfreeinos > 0) { if ((next_iag = imap_ctl->in_agctl[agno].inofree) == -1) iagp->inofreefwd = iagp->inofreeback = -1; else { /* * read in the IAG */ if (fsimap.imap_pagenum2 != (next_iag + 1)) { rc = iMapRead(vol, (next_iag + 1), iag_pg); if (rc != 0) { return (rc); } fsimap.imap_pagenum2 = next_iag + 1; } iagp->inofreefwd = next_iag; iag_pg->inofreeback = __cpu_to_le32(iagp->iagnum); iagp->inofreeback = -1; /* * write out the IAG */ rc = iMapWrite(vol, fsimap.imap_pagenum2, iag_pg); if (rc != 0) { return (rc); } } imap_ctl->in_agctl[agno].inofree = iagp->iagnum; imap_ctl->in_agctl[agno].numfree += iagp->nfreeinos; imap_ctl->in_numfree += iagp->nfreeinos; } if (numinos) { imap_ctl->in_agctl[agno].numinos += numinos; imap_ctl->in_numinos += numinos; } if (iagp->nfreeexts > 0 && !iagfree) { /* When an IAG is on the IAG free list, its nfreeexts * is EXTSPERIAG which is > 0. But here we only consider * those IAGs that are not on the IAG free list */ if ((next_iag = imap_ctl->in_agctl[agno].extfree) == -1) iagp->extfreefwd = iagp->extfreeback = -1; else { /* * read in the IAG */ if (fsimap.imap_pagenum2 != (next_iag + 1)) { rc = iMapRead(vol, (next_iag + 1), iag_pg); if (rc != 0) { return (rc); } fsimap.imap_pagenum2 = next_iag + 1; } iagp->extfreefwd = next_iag; iag_pg->extfreeback = __cpu_to_le32(iagp->iagnum); iagp->extfreeback = -1; /* * write out the IAG */ rc = iMapWrite(vol, fsimap.imap_pagenum2, iag_pg); if (rc != 0) { return (rc); } } imap_ctl->in_agctl[agno].extfree = iagp->iagnum; } /* * write out the IAG */ ujfs_swap_iag(iagp); rc = iMapWrite(vol, fsimap.imap_pagenum, iagp); if (rc != 0) { return (rc); } } /* * And now, write the control page to the device */ ujfs_swap_dinomap(fsimap.fsimapctrl); rc = iMapWrite(vol, 0, fsimap.fsimapctrl); if (rc != 0) { return (rc); } fsck_send_msg(lrdo_WRIMPDONE); return (0); } /* * NAME: updateImapPage() * * FUNCTION: copies the pmap to the wmap in each iag since pmap is * updated at the logredo process. Now we need to * reconstruct the nfreeinos and nfreeexts fields in iag. */ int updateImapPage(int32_t vol, /* index in vopen array */ struct iag *p, /* pointer to the current iag page */ int16_t * numinos, /* no. of backed inodes for this iag */ int16_t * iagfree) { /* set on return if all inodes free */ int rc = 0; uint i, sword, mask; uint16_t allfree; uint8_t *cp; /* copy the perm map to the work map. */ p->nfreeinos = 0; p->nfreeexts = 0; allfree = 0; *numinos = 0; for (i = 0; i < EXTSPERIAG; i++) { p->wmap[i] = p->pmap[i]; sword = i >> L2EXTSPERSUM; mask = UZBIT_32 >> (i & (EXTSPERSUM - 1)); if (p->pmap[i] == 0) { /* There can be the cases that p->pmap[i == 0 but * addressPXD(&p->inoext[i]) != 0. * This could happen that the log sync point has passed * the lastinode free log rec for this ino extent, but * we have not reach the hwm so that no NOREDOPAGE * log rec is written out yet before the system crash. * At the logredo time, we have to null out the * address of p->inoext[i] if p->pmap[i] is zero. */ if (addressPXD(&p->inoext[i]) != 0) { rc = markBmap((struct dmap *) vopen[vol]. bmap_ctl, p->inoext[i], 0, vol); if (rc != 0) { return (rc); } PXDaddress(&p->inoext[i], 0); } p->extsmap[sword] &= ~mask; p->inosmap[sword] |= mask; p->nfreeexts++; allfree++; } else if (p->pmap[i] == ONES) { if (addressPXD(&p->inoext[i]) != 0) { p->inosmap[sword] |= mask; p->extsmap[sword] |= mask; *numinos += INOSPEREXT; } else fsck_send_msg(lrdo_RBLDGIMAPERROR2); } else if (~p->pmap[i] && (addressPXD(&p->inoext[i]) != 0)) { /* there is some bits are zeroes */ p->extsmap[sword] |= mask; p->inosmap[sword] &= ~mask; *numinos += INOSPEREXT; cp = (uint8_t *) & p->pmap[i]; p->nfreeinos += (maptab[*cp] + maptab[*(cp + 1)] + maptab[*(cp + 2)] + maptab[*(cp + 3)]); } else fsck_send_msg(lrdo_RBLDGIMAPERROR1); } if (allfree == EXTSPERIAG) *iagfree = 1; return (0); } /* * NAME: writeBmap() * * FUNCTION: copy pmap to wmap in dmap pages, * rebuild summary tree of dmap and dmap control pages, and * rebuild bmap control page. */ int writeBmap(int32_t vol, /* index in vopen array */ struct dbmap *bmap, /* pointer to the bmap control page */ struct dinode *dip) { /* disk inode of map */ int rc; int32_t i, j, k, n; int64_t fssize, h_fssize, nblocks; int32_t npages; char *p; struct dmapctl *l2ptr; struct dmapctl *l1ptr; struct dmapctl *l0ptr; struct dmap *dmap; int8_t *l0leaf, *l1leaf, *l2leaf; int32_t agno, l2agsize; int32_t actags, inactags, l2nl; int64_t ag_rem, actfree, inactfree, avgfree; int32_t next_bmap_page = 1; struct dmap_bitmaps *dmap_bitrec; int32_t bitmaplen; if (vopen[vol].status == FM_LOGREDO) { fsck_send_msg(lrdo_WRBMPNOTRBLDGBMAP); return (NOTREBUILDING_BMAP); } fsck_send_msg(lrdo_WRBMPSTART); /* * set the pointers to the corresponding page buffers */ l2ptr = vopen[vol].L2_pbuf; l1ptr = vopen[vol].L1_pbuf; l0ptr = vopen[vol].L0_pbuf; dmap = vopen[vol].dmap_pbuf; bitmaplen = sizeof (uint32_t) * LPERDMAP; /* * validate file system size and bmap file size * * Since the di_size includes the mkfs hidden dmap page * and its related control pages, when calculate the * l_totalpages we pretend fs size is fssize plus BPERDMAP. * The macro give the page index # (zero origin ) * so the (+ 1) gives the total pages. */ h_fssize = vopen[vol].fssize + BPERDMAP; npages = BLKTODMAPN(h_fssize - 1) + 1; if (npages > (__le64_to_cpu(dip->di_size) >> L2PSIZE)) { fsck_send_msg(lrdo_WRBMPBADMAPSIZE); return (BMAP_WRITEERROR1); } /* * reconstruct bmap extended information from bit map */ fssize = vopen[vol].fssize; /* * initialize bmap control page. * * all the data in bmap control page should exclude * the mkfs hidden dmap page. */ bmap->dn_mapsize = fssize; bmap->dn_maxlevel = BMAPSZTOLEV(bmap->dn_mapsize); bmap->dn_nfree = 0; bmap->dn_agl2size = vopen[vol].l2agsize; l2agsize = bmap->dn_agl2size; bmap->dn_agsize = vopen[vol].agsize; bmap->dn_numag = vopen[vol].numag; for (agno = 0; agno < bmap->dn_numag; agno++) bmap->dn_agfree[agno] = 0; /* * reconstruct summary tree and control information * in struct dmap pages and dmapctl pages */ nblocks = fssize; p = (char *) bmap + sizeof (struct dbmap); if (vopen[vol].L2_pagenum != next_bmap_page) { rc = bMapRead(vol, next_bmap_page, l2ptr); if (rc != 0) { return (rc); } ujfs_swap_dmapctl(l2ptr); } vopen[vol].L2_pagenum = next_bmap_page; next_bmap_page++; l2leaf = l2ptr->stree + CTLLEAFIND; /* reconstruct each L1 in L2 */ p += SIZEOFDMAPCTL; /* the L1.0 */ for (k = 0; k < LPERCTL; k++) { if (vopen[vol].L1_pagenum != next_bmap_page) { rc = bMapRead(vol, next_bmap_page, l1ptr); if (rc != 0) { return (rc); } ujfs_swap_dmapctl(l1ptr); } vopen[vol].L1_pagenum = next_bmap_page; next_bmap_page++; l1leaf = l1ptr->stree + CTLLEAFIND; /* reconstruct each L0 in L1 */ p += SIZEOFDMAPCTL; /* 1st L0 of L1.k */ for (j = 0; j < LPERCTL; j++) { if (vopen[vol].L0_pagenum != next_bmap_page) { rc = bMapRead(vol, next_bmap_page, l0ptr); if (rc != 0) { return (rc); } ujfs_swap_dmapctl(l0ptr); } vopen[vol].L0_pagenum = next_bmap_page; next_bmap_page++; if (l0ptr->leafidx != CTLLEAFIND) { fsck_send_msg(lrdo_WRBMPBADLFIDX0, k, j, l0ptr->leafidx); return ILLEGAL_LEAF_IND0; } l0leaf = l0ptr->stree + l0ptr->leafidx; /* * reconstruct each dmap in L0 */ for (i = 0; i < LPERCTL; i++) { /* * read in the dmap page */ if (vopen[vol].dmap_pagenum != next_bmap_page) { rc = bMapRead(vol, next_bmap_page, dmap); if (rc != 0) { return (rc); } ujfs_swap_dmap(dmap); } vopen[vol].dmap_pagenum = next_bmap_page; /* * if the bit maps for this dmap page are * in memory, copy the pmap into the page */ dmap_bitrec = vopen[vol].bmap_wsp[next_bmap_page].dmap_bitmaps; if (dmap_bitrec != NULL) { memcpy((void *) &(dmap->pmap), (void *) &(dmap_bitrec->pmap), bitmaplen); } next_bmap_page++; /* * reconstruct the dmap page, and * initialize corresponding parent L0 leaf */ n = MIN(nblocks, BPERDMAP); rc = updDmapPage(dmap, n, l0leaf); if (rc != 0) { fsck_send_msg(lrdo_RBLDGDMAPERROR, k, j, i); return (DMAP_UPDATEFAIL); } bmap->dn_nfree += dmap->nfree; agno = dmap->start >> l2agsize; bmap->dn_agfree[agno] += dmap->nfree; l0leaf++; /* * write out the dmap page */ ujfs_swap_dmap(dmap); rc = bMapWrite(vol, vopen[vol].dmap_pagenum, dmap); if (rc != 0) { return (rc); } vopen[vol].dmap_pagenum = -1; nblocks -= n; if (nblocks == 0) break; } /* for each dmap in a L0 */ /* * build current L0 page from its leaves, and * initialize corresponding parent L1 leaf */ *l1leaf = adjTree(l0ptr, L2LPERCTL, L2BPERDMAP); /* * write out the L0 page */ ujfs_swap_dmapctl(l0ptr); rc = bMapWrite(vol, vopen[vol].L0_pagenum, l0ptr); if (rc != 0) { return (rc); } vopen[vol].L0_pagenum = -1; if (nblocks) l1leaf++; /* continue for next L0 */ else { /* more than 1 L0 ? */ if (j > 0) break; /* build L1 page */ else { /* initialize global bmap page */ bmap->dn_maxfreebud = *l1leaf; goto finalize; } } } /* for each L0 in a L1 */ /* * build current L1 page from its leaves, and * initialize corresponding parent L2 leaf */ *l2leaf = adjTree(l1ptr, L2LPERCTL, L2MAXL0SIZE); /* * write out the L1 page to disk */ ujfs_swap_dmapctl(l1ptr); rc = bMapWrite(vol, vopen[vol].L1_pagenum, l1ptr); if (rc != 0) { return (rc); } vopen[vol].L1_pagenum = -1; if (nblocks) l2leaf++; /* continue for next L1 */ else { /* more than 1 L1 ? */ if (k > 0) break; /* build L2 page */ else { /* initialize global bmap page */ bmap->dn_maxfreebud = *l2leaf; goto finalize; } } } /* for each L1 in a L2 */ /* initialize global bmap page */ bmap->dn_maxfreebud = adjTree(l2ptr, L2LPERCTL, L2MAXL1SIZE); /* * write out the L2 page to disk */ ujfs_swap_dmapctl(l2ptr); rc = bMapWrite(vol, vopen[vol].L2_pagenum, l2ptr); if (rc != 0) { return (rc); } vopen[vol].L2_pagenum = -1; /* * finalize bmap control page */ finalize: /* * compute dn_maxag: highest active ag number * (the rightmost allocation group with blocks allocated in it); */ /* get last ag number: assert(bmap->dn_numag >= 1); */ i = bmap->dn_numag - 1; /* is last ag partial ag ? */ ag_rem = bmap->dn_mapsize & (bmap->dn_agsize - 1); if (ag_rem) { /* is last ag active ? */ if (bmap->dn_agfree[i] < ag_rem) { bmap->dn_maxag = i; goto agpref; } else i--; } /* scan backward for first ag with blocks allocated: * (ag0 must be active from allocation of map itself) */ for (; i >= 0; i--) { if (bmap->dn_agfree[i] < bmap->dn_agsize) break; } bmap->dn_maxag = i; /* * compute db_agpref: preferred ag to allocate from * (the leftmost ag with average free space in it); */ agpref: /* get the number of active ags and inacitve ags */ actags = bmap->dn_maxag + 1; inactags = bmap->dn_numag - actags; /* determine how many blocks are in the inactive allocation * groups. in doing this, we must account for the fact that * the rightmost group might be a partial group (i.e. file * system size is not a multiple of the group size). */ inactfree = (inactags && ag_rem) ? ((inactags - 1) << l2agsize) + ag_rem : inactags << l2agsize; /* determine how many free blocks are in the active * allocation groups plus the average number of free blocks * within the active ags. */ actfree = bmap->dn_nfree - inactfree; avgfree = actfree / actags; /* if the preferred allocation group has not average free space. * re-establish the preferred group as the leftmost * group with average free space. */ if (bmap->dn_agfree[bmap->dn_agpref] < avgfree) { for (bmap->dn_agpref = 0; bmap->dn_agpref < actags; bmap->dn_agpref++) { if (bmap->dn_agfree[bmap->dn_agpref] >= avgfree) break; } assert(bmap->dn_agpref < bmap->dn_numag); } /* * compute db_aglevel, db_agheigth, db_width, db_agstart: * an ag is covered in aglevel dmapctl summary tree, * at agheight level height (from leaf) with agwidth number of nodes * each, which starts at agstart index node of the smmary tree node * array; */ bmap->dn_aglevel = BMAPSZTOLEV(bmap->dn_agsize); l2nl = bmap->dn_agl2size - (L2BPERDMAP + bmap->dn_aglevel * L2LPERCTL); bmap->dn_agheigth = l2nl >> 1; bmap->dn_agwidth = 1 << (l2nl - (bmap->dn_agheigth << 1)); for (i = 5 - bmap->dn_agheigth, bmap->dn_agstart = 0, n = 1; i > 0; i--) { bmap->dn_agstart += n; n <<= 2; } /* * write out the control page to disk */ ujfs_swap_dbmap(bmap); rc = bMapWrite(vol, 0, (void *) bmap); if (rc != 0) { return (rc); } fsck_send_msg(lrdo_WRBMPDONE); return (0); } /* * NAME: updDmapPage() * * FUNCTION: copies the pmap to the wmap in the dmap. * Rebuild the summary tree for this dmap. * initializes the other fields for struct dmap. */ int updDmapPage(struct dmap *p0, /* pointer to this struct dmap page */ int32_t nblk, /* num blks covered by this dmap */ int8_t * treemax) { /* filled in with max free for this dmap */ struct dmaptree *tp; /* pointer to dmap tree */ int8_t *cp; uint8_t *ucp; int16_t w; /* update nblock field according to nblk. * Note that all the dmap page have the same nblock (BPERDMAP) * except the last dmap. Without the extendfs the * last dmap nblock is set properly by mkfs. * With the extendfs, logredo need to take care of * nblock field in case the system crashed after * the transaction for extendfs is committed, but * before the fs superblock was sync-written out. * In that case, we need to reset the last dmap * nblock field according to the fssize in the * unchanged fs superblock. */ p0->nblocks = nblk; tp = &p0->tree; /* copy the perm map to the work map. * count the num of free blks in this dmap * Set the initial state for the leaves of the dmap tree * according to the current state of pmap/wmap words. */ p0->nfree = 0; /* init nfree field */ if ((int32_t) (tp->leafidx) != (int32_t) (LEAFIND)) { fsck_send_msg(lrdo_UPDMPBADLFIDX); return ILLEGAL_LEAF_IND1; } cp = tp->stree + tp->leafidx; /*cp points to first leaf of dmap tree */ for (w = 0; w < LPERDMAP; w++) { p0->wmap[w] = p0->pmap[w]; *(cp + w) = maxBud((unsigned char *) &p0->wmap[w]); if (~p0->wmap[w]) { ucp = (uint8_t *) & p0->wmap[w]; p0->nfree += (maptab[*ucp] + maptab[*(ucp + 1)] + maptab[*(ucp + 2)] + maptab[*(ucp + 3)]); } } /* * With the leaves of the dmap initialized * rebuild the dmap's tree. */ *treemax = adjTree((struct dmapctl *) tp, L2LPERDMAP, BUDMIN); return (0); } /* * NAME: rXtree() * * FUNCTION: return buffer page of leftmost leaf page of the xtree * by traversing down leftmost path of xtree; * * RETURN: buffer pointer to the first leaf of the xtree. */ int rXtree(int32_t vol, /* index in vopen array */ struct dinode *dp, /* disk inode of map */ xtpage_t ** first_leaf) { /* pointer to first leaf page of map xtree */ xtpage_t *p; caddr_t buf_ptr; pxd_t pxd; /* start from root in dinode */ p = (xtpage_t *) & dp->di_btroot; /* is this page leaf ? */ if (p->header.flag & BT_LEAF) goto out; /* get the pxd of leftmost child page */ PXDlength(&pxd, vopen[vol].lbperpage); PXDaddress(&pxd, addressXAD(&p->xad[XTENTRYSTART])); /* * traverse down leftmost child node to the leftmost leaf of xtree */ do { /* read in the leftmost child page */ if (bread(vol, pxd, (void **) &buf_ptr, PB_READ) != 0) { fsck_send_msg(lrdo_RXTREADLFFAIL); return (MINOR_ERROR); } p = (xtpage_t *) buf_ptr; /* is this page leaf ? */ if (p->header.flag & BT_LEAF) break; else { PXDlength(&pxd, vopen[vol].lbperpage); PXDaddress(&pxd, addressXAD(&p->xad[XTENTRYSTART])); } } while (!(p->header.flag & BT_LEAF)); out: *first_leaf = p; return (0); } /* * NAME: adjTree * * FUNCTION: rebuild the tree of a dmap or dmapctl. the tree is fixed size. * * for dmap tree, the number of leaf nodes are always LPERDMAP * for a fixed aggregate size, the last dmap page may not * used fully. The the partial unused pmap/wmap bits are marked * as allocated. * For dmapctl tree, the number of leaf nodes are always * LPERCTL. If not 1024 dmaps exist, then the unused leaf * nodes are marked as "-1". * * PARAMETERS: * tp - pointer to the current dmap page or dmapctl page * l2leaves- Number of leaf nodes as a power of 2: * for dmap, this is always L2LPERDMAP, * for dmapctl, this is always L2LPERCTL; * l2min - Number of blocks actually covered by a leaf of the tree * as a power of 2 * * NOTES: This routine first works against the leaves of the tree to calculate * the maximum free string for leaf buddys. Once this is accomplished the * values of the leaf nodes are bubbled up the tree. * * RETURNS: */ signed char adjTree(struct dmapctl *tp, int32_t l2leaves, int32_t l2min) { int nleaves, l2max, nextbud, budsz, index; int l2free, leaf, firstp; int16_t nparents; signed char *cp0, *pp; signed char *cp = tp->stree; /* Pointer to the top of the stree */ /* * Determine the number of leaves of the tree */ nleaves = (1 << l2leaves); /* * Determine the maximum free string possible for the leaves. */ l2max = l2min + l2leaves; /* * Combine buddies starting with a buddy size of 1 (i.e. two leaves). * * At a buddy size of 1 two buddy leaves can be combined if both buddies * have a maximum free of l2min; the combination will result in the * left buddy leaf having a maximum free of l2min+1 and the right * buddy leaf changing value to '-1'. * * After processing all buddies for a current size, process buddies * at the next higher buddy size (i.e. current size * 2) against * the next maximum free level (i.e. current free + 1 ). * * This continues until the maximum possible buddy * combination yields maximum free. * * since the stree is fixed size, the index of the first leaf * is in fixed position, tp->leafidx has this value. */ for (l2free = l2min, budsz = 1; l2free < l2max; l2free++, budsz = nextbud) { nextbud = budsz << 1; for (cp0 = cp + tp->leafidx, index = 0; index < nleaves; index += nextbud, cp0 += nextbud) { if (*cp0 == l2free && *(cp0 + budsz) == l2free) { *cp0 = l2free + 1; *(cp0 + budsz) = -1; } } } /* * With the leaves having maximum free values, * bubble this information up the stree. * Starting at the leaf node level, each four nodes form a group and * have a parent in the higher level. The parent holds the maximum * free value among its four children. * All lower level nodes are processed in this fashion until we * reach the root. */ for (leaf = tp->leafidx, nparents = nleaves >> 2; nparents > 0; nparents >>= 2, leaf = firstp) { /* get the index of the first parent of the current * leaf level */ firstp = (leaf - 1) >> 2; /* * Process all nodes at the current leaf level. * Parent node pp has the maximum value of its * four children nodes. */ for (cp0 = cp + leaf, pp = cp + firstp, index = 0; index < nparents; index++, cp0 += 4, pp++) { *pp = TREEMAX(cp0); } } return (*cp); } /* * NAME: maxBud * * FUNCTION: Determines the maximum binary buddy string of free * bits within a 32-bits word of the pmap/wmap. * * PARAMETERS: * cp - Pointer to wmap or pmap word. * * RETURNS: Maximum binary buddy of free bits within a dmap word. */ static int32_t maxBud(unsigned char *cp) { /* check if the dmap word is all free. if so, the * free buddy size is BUDMIN. */ if (*((uint32_t *) cp) == 0) return (BUDMIN); /* check if the dmap word is half free. if so, the * free buddy size is BUDMIN-1. */ if (*((unsigned short *) cp) == 0 || *((unsigned short *) cp + 1) == 0) return (BUDMIN - 1); /* not all free or half free. determine the free buddy * size thru table lookup using quarters of the dmap word. */ return (MAX(MAX(budtab[*cp], budtab[*(cp + 1)]), MAX(budtab[*(cp + 2)], budtab[*(cp + 3)]))); } /* * NAME: bread () * * FUNCTION: return with buf set to pointer of page in buffer pool * containing disk page specified by pxd. * the parameter update specifies the caller's intentions. * * NOTE: offset_t is "long long" type. */ int bread(int32_t vol, /* index in vopen (minor of aggregate) */ pxd_t pxd, /* on-disk page pxd */ void **buf, /* set to point to buffer pool page */ int32_t update) { /* true if buffer will be modified */ FILE *fp; int rc; int32_t k, hash, oldhash, nxt, prv, found, head; int32_t nblocks, nbytes; int64_t blkno; /* number of agge. blks in pxd */ /* verify that pxd is within aggregate range */ nblocks = lengthPXD(&pxd); blkno = addressPXD(&pxd); if (vopen[vol].bmap_ctl != NULL && (blkno + nblocks) > vopen[vol].fssize) { fsError(DBTYPE, vol, blkno); fsck_send_msg(lrdo_BRDBADBLOCK, (long long) blkno); return (MINOR_ERROR); } /* search buffer pool for specified page */ hash = (blkno ^ vol) & bhmask; for (k = bhash[hash]; k != 0; k = bufhdr[k].hnext) { if (addressPXD(&bufhdr[k].pxd) == blkno && lengthPXD(&bufhdr[k].pxd) >= nblocks && bufhdr[k].vol == vol) break; } /* was it in buffer pool ? */ found = (k != 0); k = (found) ? k : bufhdr[0].prev; /* remove k from current position in lru list */ nxt = bufhdr[k].next; prv = bufhdr[k].prev; bufhdr[nxt].prev = prv; bufhdr[prv].next = nxt; /* move k to head of lru list */ head = bufhdr[0].next; bufhdr[k].next = head; bufhdr[head].prev = k; bufhdr[k].prev = 0; bufhdr[0].next = k; /* bufhdr[k] describes buffer[k-1] */ *buf = &buffer[k - 1]; /* * buffer has been reclaimed: update modify bit and return */ if (found) { bufhdr[k].modify |= update; return (0); } /* * buffer is to be recycled: */ /* write it out if it was modified */ if (bufhdr[k].inuse && bufhdr[k].modify) { if ((rc = bflush(k, &buffer[k - 1])) != 0) return (rc); } /* remove it from hash chain if necessary. * hprev is 0 if it is at head of hash chain. */ if (bufhdr[k].inuse) { nxt = bufhdr[k].hnext; prv = bufhdr[k].hprev; if (prv == 0) { oldhash = (bufhdr[k].vol ^ addressPXD(&bufhdr[k].pxd)) & bhmask; bhash[oldhash] = nxt; } else { bufhdr[prv].hnext = nxt; } /* next assign is ok even if nxt is 0 */ bufhdr[nxt].hprev = prv; } /* insert k at head of new hash chain */ head = bhash[hash]; bufhdr[k].hnext = head; bufhdr[k].hprev = 0; bufhdr[head].hprev = k; /* ok even if head = 0 */ bhash[hash] = k; /* fill in bufhdr with new data and read the page in */ bufhdr[k].vol = vol; bufhdr[k].pxd = pxd; bufhdr[k].inuse = 1; bufhdr[k].modify = update; fp = vopen[vol].fp; nbytes = nblocks << vopen[vol].l2bsize; rc = ujfs_rw_diskblocks(fp, (uint64_t) (blkno << vopen[vol].l2bsize), (unsigned) nbytes, (char *) &buffer[k - 1], GET); if (rc != 0) { fsError(IOERROR, vol, blkno); fsck_send_msg(lrdo_BRDREADBLKFAIL, (long long) blkno); return (MINOR_ERROR); } return (0); } jfsutils-1.1.15.orig/libfs/log_read.c0000644000000000000000000003657511062757773014345 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include "jfs_types.h" #include "jfs_endian.h" #include "jfs_filsys.h" #include "jfs_superblock.h" #include "jfs_dinode.h" #include "jfs_dtree.h" #include "jfs_xtree.h" #include "jfs_logmgr.h" #include "jfs_dmap.h" #include "jfs_imap.h" #include "logredo.h" #include "devices.h" #include "debug.h" #include "fsck_message.h" /* for fsck message logging facility */ /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * R E M E M B E R M E M O R Y A L L O C F A I L U R E * */ extern int32_t Insuff_memory_for_maps; extern char *available_stg_addr; extern int32_t available_stg_bytes; extern char *bmap_stg_addr; extern int32_t bmap_stg_bytes; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * L O C A L M A C R O D E F I N I T I O N S * */ #define BTOLOGPN(x) ((unsigned)(x) >> L2LOGPSIZE) #define LOGPNTOB(x) ((x)< 8 (i.e. a record ends on the page). * Page numbers are compared by comparing their difference * with zero (necessary because page numbers are allowed to wrap.) * * RETURNS: >0 - byte offset of last record * REFORMAT_ERROR(-3) - i/o error, reformat the log * MAJOR_ERROR(-2) - other major errors other than EIO. */ int findEndOfLog() { int rc; int32_t left, right, pmax, pval, eormax, eorval, k; /* binary search for logend */ left = 2; /* first page containing log records since page 0 is never used, page 1 is log superblock */ right = Log.size - 1; /* last page containing log records */ if ((rc = pageVal(left, &eormax, &pmax)) < 0) { fsck_send_msg(lrdo_FEOLPGV1FAIL, rc); return (rc); } while ((right - left) > 1) { k = (left + right) >> 1; if ((rc = pageVal(k, &eorval, &pval)) < 0) { fsck_send_msg(lrdo_FEOLPGV2FAIL, rc); return (rc); } if (pval - pmax > 0) { left = k; pmax = pval; eormax = eorval; } else right = k; } if ((rc = pageVal(right, &eorval, &pval)) < 0) { fsck_send_msg(lrdo_FEOLPGV3FAIL, rc); return (rc); } /* * the last thing to determine is whether it is the first page of * the last long log record and system was crashed when its second * page is written. If the eor of the chosen page is LOGPHDRSIZE, * then this page contains a partial log record, ( otherwise, the * the long log record's second page should be chosen ). * This page should be thrown away. its previous page will be * the real last log page. */ if ((pval - pmax) > 0) { if (eorval == LOGPHDRSIZE) { if ((rc = pageVal(right - 1, &eorval, &pval)) < 0) { fsck_send_msg(lrdo_FEOLPGV4FAIL, rc); return (rc); } return (LOGPNTOB(right - 1) + eorval); } else return (LOGPNTOB(right) + eorval); } else { if (eormax == LOGPHDRSIZE) { left = (left == 2) ? Log.size - 1 : left - 1; if ((rc = pageVal(left, &eormax, &pmax)) < 0) { fsck_send_msg(lrdo_FEOLPGV4AFAIL, rc); return (rc); } } return (LOGPNTOB(left) + eormax); } } /* * NAME: pageVal(pno, eor, pmax) * * FUNCTION: Read the page into the log buffer pool and call setLogpage * to form consistent log page. * * RETURNS: 0 - ok * REFORMAT_ERROR(-3) - I/O error, reformat the log * MAJOR_ERROR(-2) - other major errors other than EIO. */ int pageVal(int pno, /* page number in log */ int *eor, /* corresponding eor value */ int *pmax) { /* pointer to returned page number */ int buf0; /* logp[] buffer element number */ /* Read the page into the log buffer pool. */ if ((buf0 = getLogpage(pno)) < 0) { fsck_send_msg(lrdo_PVGETPGFAIL, pno, buf0); return (buf0); } return (setLogpage(pno, eor, pmax, buf0)); } /* * NAME: getLogpage(pno) * * FUNCTION: if the specified log page is in buffer pool, return its * index. Otherwise read log page into buffer pool. * * PARAMETERS: pno - log page number to look for. * * RETURNS: 0 - 3 - index of the buffer pool the page located * REFORMAT_ERROR(-3) - I/O error, reformat the log * MAJOR_ERROR(-2) - other major errors other than EIO. */ int getLogpage(int pno) { /* page of log */ int k, rc; /* * is it in buffer pool ? */ for (k = 0; k <= 3; k++) if (logptr[k] == pno) return (k); /* * read page into buffer pool into next slot * don't have to use llseek() here. log dev will never be > 2 gig */ nextrep = (nextrep + 1) % 4; if (Log.location & INLINELOG) rc = ujfs_rw_diskblocks(Log.fp, (uint64_t) (Log.xaddr + LOGPNTOB(pno)), (unsigned) LOGPSIZE, (char *) &logp[nextrep], GET); else rc = ujfs_rw_diskblocks(Log.fp, (uint64_t) LOGPNTOB(pno), (unsigned) LOGPSIZE, (char *) &logp[nextrep], GET); if (rc != 0) { return (JLOG_READERROR1); } logptr[nextrep] = pno; return (nextrep); } /* * NAME: setLogpage(pno, eor, pmax, buf) * * FUNCTION: Forms consistent log page and returns eor and pmax values. * * During the first release the following conditions are * assumed: * 1) No corrupted write during power failure * 2) No split write * 3) No out-of-order sector write * * If the header and trailer in the page are not equal, a * system crash happened during this page write. It * is reconciled as follows: * * 1) if h.page != t.page, the smaller value is taken and * the eor fields set to LOGPHDSIZE. * reason: This can happen when a old page is over-written * by a new page and the system crashed. So this page * should be considered not written. * 2) if h.eor != t.eor, the smaller value is taken. * reason: The last log page was rewritten for each * commit record. A system crash happened during the * page rewriting. Since we assume that no corrupted write * no split write and out-of-order sector write, the * previous successfuly writing is still good * 3) if no record ends on the page (eor = 8), still return it. * Let the caller determine whether a) a good long log record * ends on the next log page. or b) it is the first page of the * last long log record and system was crashed when its second * page is written. * * * RETURNS: 0 - ok * REFORMAT_ERROR(-3) - I/O error, reformat log * MAJOR_ERROR(-2) - other major error */ int setLogpage(int32_t pno, /* page number of log */ int32_t *eor, /* log header eor to return */ int32_t *pmax, /* log header page number to return */ int32_t buf) { /* logp[] index number for page */ int rc; int32_t diff1, diff2; /* check that header and trailer are the same */ if ((diff1 = (__le32_to_cpu(logp[buf].h.page) - __le32_to_cpu(logp[buf].t.page))) != 0) { if (diff1 > 0) /* Both little-endian */ logp[buf].h.page = logp[buf].t.page; else /* Both little-endian */ logp[buf].t.page = logp[buf].h.page; logp[buf].h.eor = logp[buf].t.eor = __cpu_to_le16(LOGPHDRSIZE); /* empty page */ } if ((diff2 = (__le16_to_cpu(logp[buf].h.eor) - __le16_to_cpu(logp[buf].t.eor))) != 0) { if (diff2 > 0) /* Both little-endian */ logp[buf].h.eor = logp[buf].t.eor; else /* Both little-endian */ logp[buf].t.eor = logp[buf].h.eor; } /* if any difference write the page out */ if (diff1 || diff2) { rc = ujfs_rw_diskblocks(Log.fp, (uint64_t) (Log.xaddr + LOGPNTOB(pno)), (unsigned long) LOGPSIZE, (char *) &logp[buf], PUT); if (rc != 0) { fsck_send_msg(lrdo_SLPWRITEFAIL, pno, rc); return (JLOG_WRITEERROR1); } } /* * At this point, it is still possible that logp[buf].h.eor * is LOGPHDRSIZE, but we return it anyway. The caller will make * decision. */ *eor = __le16_to_cpu(logp[buf].h.eor); *pmax = __le32_to_cpu(logp[buf].h.page); return (0); } /* * NAME: logRead(logaddr , ld, dataptr) * * FUNCTION: reads the log record addressed by logaddr and * returns the address of the preceding log record. * * PARAMETERS: logaddr - address of the end of log record to read * Note: log is read backward, so this is * the address starting to read * ld - pointer to a log record descriptor * dataptr - pointer to data buffer * * RETURNS: < 0 - there is an i/o error in reading * > 0 - the address of the end of the preceding log record */ int logRead(int32_t logaddr, /* address of log record to read */ struct lrd *ld, /* pointer to a log record descriptor */ char *dataptr) { /* pointer to buffer. LOGPSIZE*2 long */ int buf, off, rc, nwords, pno; /* get page containing logaddr into log buffer pool */ pno = BTOLOGPN(logaddr); if (pno != loglastp) { loglastp = pno; lognumread += 1; if (lognumread > Log.size - 2) { logError(LOGWRAP, 0); fsck_send_msg(lrdo_LRLOGWRAP, lognumread); return (JLOG_LOGWRAP); } } buf = getLogpage(pno); if (buf < 0) { fsck_send_msg(lrdo_LRREADFAIL, pno, buf); return (buf); } /* read the descriptor */ off = logaddr & (LOGPSIZE - 1); /* offset just past desc. */ rc = moveWords(LOGRDSIZE / 4, (int32_t *) ld, &buf, &off); if (rc < 0) { fsck_send_msg(lrdo_LRMWFAIL1, rc); return (rc); } ujfs_swap_lrd(ld); /* * Legacy code used device number in ld->aggegate. This code only * supported a single volume attached to the journal */ if (ld->aggregate > MAX_ACTIVE) ld->aggregate = 0; /* read the data if there is any */ if (ld->length > 0) { if (ld->length > LOGPSIZE * 2) { rc = READLOGERROR; fsck_send_msg(lrdo_LRMWFAIL3, pno); return (rc); } /* if length is partial word, still read it */ nwords = (ld->length + 3) / 4; rc = moveWords(nwords, (int32_t *) dataptr, &buf, &off); if (rc < 0) { fsck_send_msg(lrdo_LRMWFAIL2, rc); return (rc); } } return (LOGPNTOB(logptr[buf]) + off); } /* * NAME: moveWords() * * FUNCTION: moves nwords from buffer pool to target. data * is moved in backwards direction starting at offset. * If partial log record is on the previous page, * or we have exhaust the current page (all bytes were read), * the previous page is read into the buffer pool. * On exit buf will point to this page in the buffer pool * and offset to where the move stopped. * * Note: the previous page is fetched whenever * the current page is exhausted (all bytes were read) * even if all the words required to satisfy this move * are on the current page. * * PARAMETERS: nwords - number of 4-byte words to move * target - address of target (begin address) * buf - index in buffer pool of current page * offset - initial offset in buffer pool page, this offset * includes the page head size * * RETURNS: = 0 - ok * < 0 - error returned from getLogpage */ int moveWords(int32_t nwords, /* number of 4-byte words to move */ int32_t *target, /* address of target (begin address) */ int32_t *buf, /* index in buffer pool of curr page */ int32_t *offset) { /* initial offset in buffer pool page */ int n, j, words, pno; int *ptr; j = (*offset - LOGPHDRSIZE) / 4 - 1; /* index in log page data area of first word to move */ words = min(nwords, j + 1); /* words on this page to move */ ptr = target + nwords - 1; /* last word of target */ for (n = 0; n < words; n++) { *ptr = logp[*buf].data[j]; j = j - 1; ptr = ptr - 1; } *offset = *offset - 4 * words; /* * If partial log record is on the previous page, * or we have read all the log records in the current page, * get the previous page */ while (words != nwords /* we get less than nwords */ || j < 0) { /* or exhaust the page, so offset is just */ nwords -= words; /* the page head, then j < 0 */ /* get previous page */ pno = logptr[*buf]; pno = pno - 1; /* if we hit beginning location of the log, go wrapped, read log record from the end location of the log */ if (pno == 1) pno = Log.size - 1; *buf = getLogpage(pno); if (*buf < 0) { fsck_send_msg(lrdo_MWREADFAIL, pno, (*buf)); return (*buf); } *offset = LOGPSIZE - LOGPTLRSIZE; /* index last word of data area */ j = LOGPSIZE / 4 - 4 - 1; /* move rest of nwords if any. */ for (n = 0; n < nwords; n++) { if (j < 0) break; *ptr = logp[*buf].data[j]; j = j - 1; ptr = ptr - 1; } words = n; *offset = *offset - 4 * nwords; } return (0); } jfsutils-1.1.15.orig/libfs/log_work.c0000645000000000000000000031103510772001331014353 0ustar /* * Copyright (C) International Business Machines Corp., 2000-2005 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include "jfs_types.h" #include "jfs_filsys.h" #include "jfs_superblock.h" #include "jfs_dinode.h" #include "jfs_dtree.h" #include "jfs_xtree.h" #include "jfs_logmgr.h" #include "jfs_dmap.h" #include "jfs_imap.h" #include "jfs_endian.h" #include "logredo.h" #include "devices.h" #include "debug.h" #include "fsck_message.h" /* for fsck message logging facility */ /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * R E M E M B E R M E M O R Y A L L O C F A I L U R E * */ extern int32_t Insuff_memory_for_maps; extern char *available_stg_addr; extern int32_t available_stg_bytes; extern char *bmap_stg_addr; extern int32_t bmap_stg_bytes; extern int end_of_transaction; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * L O C A L M A C R O D E F I N I T I O N S * */ #define UZBIT_8 ((uint8_t) (1 << 7)) #define UZBIT_16 ((uint16_t) (1 << 15 )) #define UZBIT_32 ((uint32_t) (1 << 31 )) #define DTPGWORD 32 #define L2DTPGWORD 5 #define DATAPGWORD 32 #define L2DATAPGWORD 5 /* convert disk block number to bmap file page number */ #define BLKTODMAPN(b)\ (((b) >> 13) + ((b) >> 23) + ((b) >> 33) + 3 + 1) /* The following MACRO update bmap for extents that have * XAD_NEW | XAD_EXTENDED flag in Xadlist. Then reset * the XAD_NEW | XAD_EXTENDED bits in the flag */ #define MARKXADNEW(PXD, XADP, BMAPT, VOL)\ {\ PXDlength((&PXD), lengthXAD(XADP));\ PXDaddress((&PXD), addressXAD((XADP)));\ markBmap((struct dmap*)(BMAPT), (PXD), 1, (VOL));\ (XADP)->flag &= ~(XAD_NEW|XAD_EXTENDED);\ } /* * * T R A N S A C T I O N H A S H T A B L E * * each entry represents a committed transaction in recovery-in-progress * * An entry stays in the commit table until the first (in time, last seen * by logredo) record of a transaction is seen. (It is recognized because * its backchain == 0) */ #define COMSIZE 512 int comfree; /* index of a free com structure */ int comhmask = 63; /* hash mask for comhash */ int comhash[64]; /* head of hash chains */ struct com { int tid; /* 4: committed tid. */ int next; /* 4: next on free list or hash chain */ } com[COMSIZE]; /* (8) */ /* * * R E D O P A G E H A S H T A B L E * * each entry represents a disk page that have been updated * by LOG_REDOPAGE records. * * When replay the LOG_REDOPAGE log rec, we should track which portion of the * disk page has been updated by the LOG_REDOPAGE log records. * When log is read in backwards direction, a LOG_REDOPAGE log record is * only applied to disk page image that has not been updated by any earlier * log records. So that only the last update to a portion is applied. * * There are many types of data for LOG_REDOPAGE log rec. Fields * ino_base, ino_ea, ino_data, summary1 and summary2 use different * way to do the track according to log.redopage.type: * * 1) Xtree page -- since the log record carries at most 2 segments, * the first one is header, if any, the second one is the * updated contigous xtree entries starting from offset. * The number of entries specified in the length. * If there is only one segment, it must be header. * * For xtree, the new entry either inserts or appends. * If it appends, then the log rec contains only the * new entry data. If it is inserted, all the entries * after the insertion need to shift. Then the log rec * contains all entries starting from the new insertion. * So only low water mark (lwm) offset needs to be recorded * in summary2. At logredo time, only the log rec having * offset lower than lwm will apply to page and only apply * the difference between offset and lwm. * Header of the xtree page should be only applied once * in logredo. So another field in summzry2 track header. * 2) Dtree page -- A dtree page has 128 slots including header. the slot size * is 32 byte. A 4 words(32 byte) array is used as a bit * vector to track the 128 slots. * 3) inode page -- There are 3 slot sizes and 5 sub-types for inode page. * Each type is in a separate log record. * * a) type == INODE * Section I (128 byte) of the dinode is logged. Offset is * counted from the beginning of the inode page. * A 8-bit vector tracks 8 inodes in inode page. * the slot size for this type is 128 byte. * Note: Each inode has 512 bytes, the INODE type only refers * to the first 128 section. so the offset should * be always a multiply of 4, i.e. 0, 4, 8, 12, etc.. * b) type == EA ( extended attribute ) * it is the top 16 bytes of section II of the dinode. * offset should be always ???. * A 8-bit vector tracks 8 inodes in inode page. * the slot size is 16 bytes. * c) type == DATA ( in-line data for symlink ) * A real xt data file starts from the 16 bytes above * section III of the dinode. * offset should be always ???. * A 8-bit vector tracks 8 inodes in inode page. * the slot size is 16 bytes. * d) type == BTROOT + DTREE * It starts from the 32 bytes above section III of the dinode. * Offset is counted from the beginning of BTROOT. * An array of 8 uint16_t, each is used as a bit vector to track * one dtroot. * the slot size for this type is 32 byte. * e) type == BTROOT + XTREE * It starts from the 32 bytes above section III of the dinode. * Offset is counted from the beginning of BTROOT. * an array of 8 structrues, each tracks one xtroot for lwm and * header of xtroot. * the slot size for this type is 16 byte. * * Note1: The slot size is stored in lrd.redopage.l2linesize field. * * Note2: The hash key for doblk is aggregate+pxd. * The same pxd can be used for an INODE log record, * a BTROOT+DTREE log rec, a BTROOT+XTREE log rec, * a EA log rec, and a in-line DATA log rec. So for these * five types, we cannot overlay them each other. * But the same pxd can be used for either a BTROOT+DTREE log rec * or a DTREE page log rec, not both. The same pxd can be used * for either a BTROOT+XTREE log rec or a XTREE page log rec, * not both. * Note3: xtpage_lwm and i_xtroot[] have a different initialization value * from rest of the types. They have to be inited to the * highest value. */ #define BHASHSIZE 1024 /* must be a power of two */ struct doblk { int32_t aggregate; /* file system aggregate/lv number */ pxd_t pxd; /* on-disk page pxd */ uint16_t type; /* doblk type (inode, xtree, dtree, data) */ #define LOG_NONE 0X1000 /* Invalid doblk type to guarantee noredo */ uint16_t reserved; union { struct { uint8_t ino_base; /* each bit tracks one dinode * for section I of the dinode * (128 bytes.) Each inode has * 4 128-byte slots, with one * base slot. A total of 8 * bits that need to be marked * for 8 dinodes in one inode * page */ uint8_t ino_ea; /* extended attribute */ uint8_t ino_data; /* in-line data */ uint8_t xtrt_hd; /* xtroot header */ uint8_t xtrt_lwm[8]; /* xtroot lwm value. */ uint16_t ino_dtroot[8]; /* dtree root. each dinode has * 9 dtree-root slots, including * 1 slot header. Each slot is * 32-byte. Each element of * i_dtroot[] monitors one dtree * root of the dinode. For each * 16-bit, only 9-bit is used. */ uint8_t ino_link; /* in-line symlink */ uint8_t dtree; /* flag per ino whether dtree * has been logged */ uint8_t reserved[2]; } inode; uint32_t dtpage_word[4]; /* dtree page. a total of 128 * slots including header */ struct { uint8_t xtpage_hd; /* xtree page header */ uint8_t xtpage_lwm; /* xtree page. the lowest offset * among non-header segments */ } xtpg; uint32_t data_word[8]; /* data page has 256 16-byte slots */ } summary; struct doblk *next; /* next entry on hash chain */ }; #define db_ibase summary.inode.ino_base #define db_iea summary.inode.ino_ea #define db_idata summary.inode.ino_data #define db_dtroot summary.inode.ino_dtroot #define db_xtrt_hd summary.inode.xtrt_hd #define db_xtrt_lwm summary.inode.xtrt_lwm #define db_idtree summary.inode.dtree #define db_ilink summary.inode.ino_link #define db_dtpagewd summary.dtpage_word #define db_xtpagelwm summary.xtpg.xtpage_lwm #define db_xtpghd summary.xtpg.xtpage_hd #define db_datawd summary.data_word extern int32_t numdoblk; /* number of do blocks used */ int32_t blkhmask = (BHASHSIZE - 1); /* hash mask for blkhash */ struct doblk *blkhash[BHASHSIZE]; /* head of doblk hash chains */ int32_t Freedoblk; /* number of unused doblk struct */ struct doblk *Blkpage; /* beginning address of doblk hash table page */ /* * * N O R E D O F I L E H A S H T A B L E * * each entry represents a file system object which has been deleted * (entry is added when the log record describing the delete is processed) */ #define NODOFILEHASHSIZE 512 struct nodofile { int32_t aggregate; /* 4: file system aggregate/lv number */ uint32_t inode; /* 4: inode number */ struct nodofile *next; /* 4: next entry on nodo hash chain */ }; /* (16) */ extern int32_t numnodofile; /* number of nodo file blocks used */ int32_t nodofilehmask = (NODOFILEHASHSIZE - 1); /* hash mask for nodohash */ struct nodofile *nodofilehash[NODOFILEHASHSIZE]; /* head of nodo hash chains */ int32_t Freenodofile; /* number of unused nodofile struct */ struct nodofile *Nodofilep; /* the beginning address of nodo hash table page */ struct ExtDtPg { int32_t pg_vol; /* 4: volume containing the dtpage */ int64_t pg_off; /* 8: dtpage offset, in fsblocks */ struct ExtDtPg *next; /* 4: next entry on list */ }; /* (16) */ extern int32_t numExtDtPg; /* number of extended dtpage blocks used */ int32_t FreeExtDtPg = 0; /* number of unused extended dtpage blocks */ struct ExtDtPg *DtPgPage = NULL; /* storage available for new blocks */ struct ExtDtPg *DtPgList = NULL; /* list of extended dtpages */ /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * S T U F F F O R T H E L O G * * externals defined in logredo.c */ /* * * O P E N F I L E S Y S T E M A G G R E G A T E / L V A R R A Y * * Defined in logredo.c */ extern struct vopen vopen[]; /* (88) */ /* * * B U F F E R H E A D E R T A B L E * */ extern struct bufhdr { int16_t next; /* 2: next on free/lru list */ int16_t prev; /* 2: previous on free/lru list */ int16_t hnext; /* 2: next on hash chain */ int16_t hprev; /* 2: previous on hash chain */ char modify; /* 1: buffer was modified */ char inuse; /* 1: buffer on hash chain */ int16_t reserve; /* 2 */ int32_t vol; /* 4: minor of agrregate/lv number */ pxd_t pxd; /* 8: on-disk page pxd */ } bufhdr[]; /* (24) */ /* * * L O G P A G E B U F F E R C A C H E * * log has its own 4 page buffer pool. * --> afterdata defined in logredo.c <-- */ extern uint8_t afterdata[LOGPSIZE]; /* buffer to read in redopage data */ extern struct logsuper logsup; /* log super block */ /* * * E X T E R N A L A N D F O R W A R D R E F E R E N C E S * */ /* * external references */ extern int bread(int32_t, pxd_t, void **, int32_t); extern int fsError(int, int, int64_t); extern int openVol(int32_t); extern int alloc_storage(int32_t, void **, int32_t *); extern int dMapGet(int, int); extern int iagGet(int, int32_t); /* * forward references */ int deleteCommit(int32_t); int doAfter(struct lrd *, int32_t); int doCommit(struct lrd *); int doExtDtPg(void); int doNoRedoFile(struct lrd *, uint32_t); int doNoRedoInoExt(struct lrd *); int doNoRedoPage(struct lrd *); int doUpdateMap(struct lrd *); int dtpg_resetFreeList(int32_t, int *); int dtrt_resetFreeList(int32_t, struct doblk *, struct lrd *, caddr_t); int findCommit(int32_t); int findPageRedo(int32_t, pxd_t, struct doblk **); int logredoInit(void); int markBmap(struct dmap *, pxd_t, int, int); int markImap(struct fsimap_lst *, uint32_t, pxd_t, int, int); int updatePage(struct lrd *, int32_t); int saveExtDtPg(int32_t, int64_t); /* =================================================================== */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: deleteCommit(tid) * * FUNCTION: Search in the commit array for a commit record with * transaction id (tid) matching the given tid. If a * match is found, delete the array entry containing it. */ int deleteCommit(int32_t tid) { /* transaction id to be deleted */ int k, n, hash; hash = tid & comhmask; /* hash class */ n = 0; /* previous entry on hash chain */ for (k = comhash[hash]; com[k].tid != tid; k = com[k].next) n = k; /* remove k from hash chain and put it on free list * Special case when 1st on the hash list */ if (n == 0) comhash[hash] = com[k].next; else com[n].next = com[k].next; com[k].next = comfree; comfree = k; /* note that the end of the transaction has been seen so * that the log records it contains will be written to the * device. */ end_of_transaction = -1; return (0); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: doAfter(ld) * * FUNCTION: processing for LOG_REDOPAGE record types. * * IN GENERAL * ---------- * The redopage log rec has many sub-types defined in * ld->log.redopage.type, but in general, the data belonging * to the REDOPAGE log record is applied to the disk pages * described by the address in ld->log.redopage.pxd. * * Also, depending on the redopage.type, * - the block map (bmap) may be updated * - the applicable inode map (imap) may be updated * - a NoRedoFile filter may be established * - a NoRedoPage filter may be established * * IN PARTICULAR * ------------- * LOG_BTROOT | LOG_DTREE | LOG_NEW -- describes a dtree root * which has been reset * * The log record data is applied to dtroot slots. The * dtree root's freelist needs to be initialized. The * LOG_NEW flag indicates that a dtree root which was a * leaf is now an internal node. * Specifically: * - the dtroot was full and was copied into a new * dtree (non-root) node. * - after the log record data is applied to this * dtree root, only 1 slot will be in use -- it * will point to the new dtree node. * * One log record of this type describes a single dtree * root. * * LOG_BTROOT | LOG_DTREE --describes an updated dtree root * * The log record data is applied to dtroot slots. This * covers the case of dtree root initialization, since * dtInitRoot() writes all slots (including free slots) * for a dtree root node into the log record. * * One log record of this type describes a single dtree * root. * * LOG_DTREE -- describes an updated dtree (non-root) node * * The log record data is applied to the storage defined * by the pxd. * * One log record of this type describes a single dtree * root. * * LOG_DTREE | LOG_NEW -- describes a new dtree (non-root) node * * The log record data is applied to the storage defined * by the pxd. The node's freelist is initialized. The * block map is updated for the storage allocated for the * new node. * * One log record of this type describes a single dtree * (non-root) node. * * LOG_DTREE | LOG_EXTEND -- describes a (non-root) dtree node * which has been extended. * * The log record data is applied to the storage defined * by the pxd. The node's freelist is initialized. The * block map is updated for the storage allocated for the * extended node. * * One log record of this type describes a single dtree * (non-root) node. * * LOG_BTROOT | LOG_XTREE -- describes an updated xtree root * * The log record data is applied to the xtree root's * slots. The block map is updated to show blocks defined * by the pxd's in updated slots are now in use. * * One log record of this type describes a single xtree * root. * * LOG_XTREE | LOG_NEW -- describes a new xtree (non-root) node * * The log record data is applied to the xtree node's * slots. The block map is updated to show blocks defined * by the pxd's in updated slots are now in use. The block * map is also updated to show that the blocks occupied by * the xtree node itself are now in use. * * One log record of this type describes a single xtree * (non-root) node. * * LOG_XTREE -- describes an xtree (non-root) node which * which has been changed. * * The log record data is applied to the xtree node's * slots. The block map is updated to show blocks defined * by the pxd's in updated slots are now in use. * (Note that when a file is truncated, the slots describing * the now deleted blocks are not updated. File truncation * affects the slot containing the xtree header nextindex * field.) * * One log record of this type describes a single xtree * (non-root) node. * * LOG_INODE -- describes one (4096 byte) page of an inode * extent (that is, a page actually containing * inodes) which has been updated. * * The log record data is applied to the inode extent page, * updating from 1 to all of the inodes contained in the * page. (Note that this may include updates to inline * EA data.) * * ** for this log record, log.redopage.inode contains the * inode number of the inode map which owns the page. * That is, not the inode number of any inode being * changed by the contents of this log record. * The inode number of each inode being changed by this * log record can be found in the inode's after image * in the log record data. * * For each inode affected by the log record: * - If the portion of the inode affected by this * log data has not been updated by an earlier * log record in this session, the log data is * copied over the appropriate portion of the * inode. * - If the nlink count == 0, * o the inode map (imap) is updated to show the * inode is free * o a NoRedoFile filter is started for the inode * - Otherwise (nlink != 0), * o the inode map (imap) is updated to show the inode * is allocated. * * If at least 1 inode affected by the current log record * has nlink != 0, the block map is updated to show that * the block(s) containing the inode extent (of which this * page is a part) are allocated. * * (It is obvious that from this log record we don't have * enough information to consider marking the blocks * containing the inode extent free.) * * One log record of this type describes from 1 to all 8 * inodes contained in the page. * * LOG_DATA -- ** may be used in a future release ** * * This is for in-line data (i.e. symlink.) * (TBD) * */ int doAfter(struct lrd *ld, /* pointer to log record descriptor */ int32_t logaddr) { int vol, rc = 0; int32_t hash; struct nodofile *nodoptr; /* * If it's not part of a committed transaction then it * should be ignored, so just return. */ if (!findCommit(ld->logtid)) return (0); /* * if it's the last entry for the current committed transaction, * remove the commit record from the commit list because we won't * be needing it any more. */ if (ld->backchain == 0) deleteCommit(ld->logtid); /* * if the filesystem was cleanly unmounted or if the last * thing that happened was a logredo failure, skip this * record. (Necessary for the case of logredo a log shared * by multiple filesystems. We want to process log records * for those filesystems which don't meet this criteria, but * skip log records for those which do.) */ vol = ld->aggregate; if (vopen[vol].status == FM_CLEAN || vopen[vol].status == FM_LOGREDO) return (0); /* * If the redopage.type != LOG_INODE, then if there is a * NoRedoFile filter in effect for the inode we can skip this * log record. * * N.B. When redopage.type == LOG_INODE, log.redopage.inode is * the owning imap's inode number. We'll check for NoRedoFile * filter(s) on the inode(s) actually affected by the log * record when we examine the log record data in updatePage(). */ if (!(ld->log.redopage.type & LOG_INODE)) { hash = (ld->aggregate + ld->log.redopage.inode) & nodofilehmask; for (nodoptr = nodofilehash[hash]; nodoptr != NULL; nodoptr = nodoptr->next) { if (ld->aggregate == nodoptr->aggregate && ld->log.redopage.inode == nodoptr->inode) return (0); } } /* * updatePage() takes care of applying the log data. * This includes: * - applying log data to the affected page * - updates to the inode map for inodes allocated/free * - updates to the block map for an allocated inode extent * - establishing NoRedoFile or NoRedoExtent filters * - updates to the block map for extents described in an * xtree root or node xadlist */ if ((rc = updatePage(ld, logaddr)) != 0) { fsck_send_msg(lrdo_DAFTUPDPGFAILED, logaddr, rc); return (rc); } /* * If this isn't a REDOPAGE log record, we're done */ if (ld->type != LOG_REDOPAGE) return (0); /* * update the block map for a new or extended dtree page and * for a new xtree page */ switch (ld->log.redopage.type) { case (LOG_DTREE | LOG_NEW): /* * the pxd describes the (non-root) dtree page */ case (LOG_DTREE | LOG_EXTEND): /* * The pxd describes the entire (non-root) dtree page, not * just the new extension, but it's always ok to mark allocated * something which is already marked that way. * * (And we don't really know how many of the trailing blocks * were newly added here anyway.) */ case (LOG_XTREE | LOG_NEW): /* * the pxd describes the (non-root) xtree page */ rc = markBmap((struct dmap *) vopen[vol].bmap_ctl, ld->log.redopage.pxd, 1, vol); if (rc) { fsck_send_msg(lrdo_DAFTMRKBMPFAILED, logaddr, rc); } break; } return (rc); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: doCommit(ld) * * FUNCTION: Insert the transaction ID (tid) from the given commit * record into the commit array */ int doCommit(struct lrd *ld) { /* pointer to record descriptor */ int k, hash; DBG_TRACE(("logredo:Docommit\n")) if (comfree == 0) return (JLOG_NOCOMFREE); k = comfree; comfree = com[k].next; hash = ld->logtid & comhmask; com[k].next = comhash[hash]; com[k].tid = ld->logtid; comhash[hash] = k; return (0); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: doExtDtPg() * * FUNCTION: Rebuild the freelist for each dtpage which has been * extended in the current logredo session. * */ int doExtDtPg() { struct ExtDtPg *edpp; int dedp_rc = 0; int *buf; pxd_t a_pxd; while ((DtPgList != NULL) && (dedp_rc == 0)) { edpp = DtPgList; PXDaddress(&a_pxd, edpp->pg_off); PXDlength(&a_pxd, vopen[edpp->pg_vol].lbperpage); dedp_rc = bread(edpp->pg_vol, a_pxd, (void **) &buf, PB_UPDATE); if (dedp_rc) { fsck_send_msg(lrdo_DEDPBREADFAILED, (long long)edpp->pg_off, dedp_rc); dedp_rc = DTPAGE_READERROR1; } else { dedp_rc = dtpg_resetFreeList(edpp->pg_vol, buf); DtPgList = DtPgList->next; } } /* end while */ return (dedp_rc); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: doNoRedoFile() * * FUNCTION: Add a record for the specified inode to the * NoRedoFile array. */ int doNoRedoFile(struct lrd *ld, /* pointer to record descriptor */ uint32_t inum) { /* the inode number for noredofile */ int rc = 0; struct nodofile *ndptr; int32_t hash; int32_t allocated_from_bmap = 0; /* * If it's not part of a committed transaction then it * should be ignored, so just return. */ if (!findCommit(ld->logtid)) return (0); /* * if it's the last entry for the current committed transaction, * remove the commit record from the commit list because we won't * be needing it any more. */ if (ld->backchain == 0) deleteCommit(ld->logtid); /* * start NoRedoFile filter for the specified inode by * adding a record to the NoRedoFile hash list. * */ hash = (ld->aggregate + inum) & nodofilehmask; if (Freenodofile == 0) { #ifdef _JFS_DEBUG printf("logredo:alloc (d)%d bytes for NoRedoFile filter\n", PSIZE); #endif rc = alloc_storage((uint32_t) PSIZE, (void **) &Nodofilep, &allocated_from_bmap); if ((rc != 0) || (Nodofilep == NULL)) { /* * NoRedoFile filter allocation failed */ #ifdef _JFS_DEBUG printf("logredo:alloc (d)%lld bytes for NoRedoFile filter failed\n", PSIZE); #endif fsck_send_msg(lrdo_ALLOC4NOREDOFLFAIL, PSIZE); return (ENOMEM3); } else if (Nodofilep != NULL) { /* NoRedoFile filter allocation successful */ if (allocated_from_bmap) { #ifdef _JFS_DEBUG printf ("logredo:alloc (d)%lld bytes for NoRedoFile filter out of bmap allocation\n", PSIZE); #endif fsck_send_msg(lrdo_USINGBMAPALLOC4NRFL); } } /* end NoRedoFile filter allocation successful */ Freenodofile = PSIZE / sizeof (struct nodofile); } ndptr = Nodofilep++; numnodofile++; Freenodofile--; ndptr->next = nodofilehash[hash]; nodofilehash[hash] = ndptr; ndptr->aggregate = ld->aggregate; ndptr->inode = inum; return (0); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: doNoRedoPage() * * FUNCTION: Processing for LOG_NOREDOPAGE rec type. * * This routine starts a NoRedoPage filter for the * specified xtree or dtree node (may be root). * * This routine updates the bmap when the freed node * is NOT the root node. * (ld->log.noredopage.pxd = old page extent) * * NOTE: This routine only updates the block map when the * extent being freed describes a dtree page. * Block map updates for a freed xtree page are handled * when the UPDATEMAP log record is seen. * */ int doNoRedoPage(struct lrd *ld) { /* pointer to log record descriptor */ int vol, rc = 0; int32_t hash; struct nodofile *nodoptr; pxd_t pxd1; struct doblk *db; int32_t inonum; uint8_t mask_8; /* * If it's not part of a committed transaction then it * should be ignored, so just return. */ if (!findCommit(ld->logtid)) return (0); /* * if it's the last entry for the current committed transaction, * remove the commit record from the commit list because we won't * be needing it any more. */ if (ld->backchain == 0) deleteCommit(ld->logtid); /* * if the filesystem was cleanly unmounted or if the last * thing that happened was a logredo failure, skip this * record. (Necessary for the case of logredo a log shared * by multiple filesystems. We want to process log records * for those filesystems which don't meet this criteria, but * skip log records for those which do.) */ vol = ld->aggregate; if (vopen[vol].status == FM_CLEAN || vopen[vol].status == FM_LOGREDO) return (0); /* * We may already have a NoRedoPage filter in effect. * If one is found on the NoRedoFile hash chain, goto update * map. * * N.B. The log.noredopage.inode in the log record is the * inode number of the applicable imap. We NEVER * NoRedoFile for an imap inode. */ hash = (ld->aggregate + ld->log.noredopage.inode) & nodofilehmask; for (nodoptr = nodofilehash[hash]; nodoptr != NULL; nodoptr = nodoptr->next) { if (ld->aggregate == nodoptr->aggregate && ld->log.noredopage.inode == nodoptr->inode) goto updmap; } /* * start NoRedoPage filter for LOG_NOREDOPAGE log rec. * */ pxd1 = ld->log.noredopage.pxd; /* * DTREE ROOT * * Do not process any further log records for * the root of the specified (directory) inode's dtree. */ if ((ld->log.noredopage.type & (LOG_BTROOT | LOG_DTREE)) == (LOG_BTROOT | LOG_DTREE)) { /* * get the noredopage record for this page * (one is created if none exists) */ rc = findPageRedo(ld->aggregate, pxd1, &db); if (rc != 0) { fsck_send_msg(lrdo_DNRPFNDDTRTPGREDOFAIL, rc); return (rc); } /* * mark the appropriate slot in the noredopage for * no further updates to this (directory) inode's * dtree root. */ inonum = ld->log.redopage.inode & 0x07; db->db_dtroot[inonum] = 0x01ff; /* * This inode is identified as a dtroot. So mark * the appropriate slot in the noredopage for * NO updates to this inode as an xtroot. */ mask_8 = UZBIT_8 >> inonum; db->db_xtrt_lwm[inonum] = XTENTRYSTART; db->db_xtrt_hd |= mask_8; /* * XTREE ROOT * * Do not process any further log records for * the root of the specified inode's xtree. */ } else if ((ld->log.redopage.type & (LOG_BTROOT | LOG_XTREE)) == (LOG_BTROOT | LOG_XTREE)) { /* * get the noredopage record for this page * (one is created if none exists) */ rc = findPageRedo(ld->aggregate, pxd1, &db); if (rc != 0) { fsck_send_msg(lrdo_DNRPFNDXTRTPGREDOFAIL, rc); return (rc); } /* * mark the appropriate slot in the noredopage for no * further updates to this inode's xtree root. */ inonum = ld->log.redopage.inode & 0x07; mask_8 = UZBIT_8 >> inonum; db->db_xtrt_lwm[inonum] = XTENTRYSTART; db->db_xtrt_hd |= mask_8; /* * This inode is identified as an xtree root. So * mark the appropriate slot in the noredopage for * NO updates to this inode's root as a dtree. */ db->db_dtroot[inonum] = 0x01ff; /* * DTREE, XTREE, or DATA NODE * * Do not process any further log records for * the specified page. */ } else if (ld->log.redopage.type & (LOG_XTREE | LOG_DTREE | LOG_DATA)) { /* * get the noredopage record for this page * (one is created if none exists) */ rc = findPageRedo(ld->aggregate, pxd1, &db); if (rc != 0) { fsck_send_msg(lrdo_DNRPFNDXTPGPGREDOFAIL, rc); return (rc); } db->type = LOG_NONE; /* * UNRECOGNIZED TYPE * * We don't ever expect to get here! */ } else { fsck_send_msg(lrdo_DNRPUNKNOWNTYPE); } /* * If this is a (non-root) dtree page update the bmap. */ updmap: if (ld->log.noredopage.type == LOG_DTREE) { rc = markBmap((struct dmap *) vopen[vol].bmap_ctl, ld->log.noredopage.pxd, 0, vol); if (rc != 0) { return (rc); } } return (0); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: doNoRedoInoExt() * * FUNCTION: Processing for LOG_NOREDOINOEXT rec type. * * This routine starts a NoRedoPage filter for each * page in the inode extent being released. * * This routine may updates the bmap and the imap. * * NOTE: The noredoinoext.pxd describes a 4 (4096-byte) page * inode extent. * * * NOTE: This log record was written when an inode extent was * released. * * At this point, there are 3 possibilities: * * o the extent could have been reallocated for an inode * extent (possibly even for the same inode number range. * If this is true, then there is already a NoRedoExtent * filter in effect. * * o the extent could now be allocated for user data or for * JFS metadata. If this is true, then further updates * to the blocks in the extent would violate data * integrity. Therefore, we establish a NoRedoExtent * filter (i.e., a NoRedoPage filter for each of the * 4 pages in the extent). * * o the extent could be unallocated. That is, none of the * blocks in the extent pages are in use. If this is * true, then further updates to the blocks in the extent * are a waste of processing time. Therefore, we establish * a NoRedoExtent filter (i.e., a NoRedoPage filter for * each of the 4 pages in the extent). * */ int doNoRedoInoExt(struct lrd *ld) { /* pointer to log record descriptor */ int pg_idx, vol, rc = 0; pxd_t pxd1; struct doblk *db; int32_t iagnum, iagext_idx; struct iag_data *imp; /* * If it's not part of a committed transaction then it * should be ignored, so just return. */ if (!findCommit(ld->logtid)) return (0); /* * if it's the last entry for the current committed transaction, * remove the commit record from the commit list because we won't * be needing it any more. */ if (ld->backchain == 0) deleteCommit(ld->logtid); /* * if the filesystem was cleanly unmounted or if the last * thing that happened was a logredo failure, skip this * record. (Necessary for the case of logredo a log shared * by multiple filesystems. We want to process log records * for those filesystems which don't meet this criteria, but * skip log records for those which do.) */ vol = ld->aggregate; if (vopen[vol].status == FM_CLEAN || vopen[vol].status == FM_LOGREDO) return (0); /* * Establish the 4 NoRedoPage filters which together * form the NoRedoExtent filter. */ pxd1 = ld->log.noredoinoext.pxd; for (pg_idx = 0; pg_idx < 4; pg_idx++) { /* * find the noredo record for this page. * (or create one if not found) */ rc = findPageRedo(ld->aggregate, pxd1, &db); if (rc != 0) { fsck_send_msg(lrdo_DNRIFNDNOREDORECFAIL, rc); return (rc); } /* * mark for no inode updates to the page, no matter what * format it might appear to have */ db->type = LOG_NONE; /* * set up for the next page in the extent */ PXDaddress(&pxd1, (addressPXD(&pxd1) + vopen[vol].lbperpage) ); } /* end for */ /* * Now go update the block map if appropriate. * * Note: * If any of these blocks has been allocated LATER * (in time) than this extent release then we don't * want to mark them unallocated, but if not then * we must mark them unallocated. Since we process * log records in LIFO order, we have already * processed the log record(s) (if any) describing * reallocation of the block(s). * * The markBmap routine only marks the block map * for blocks whose status has not already been * set by markBmap in the current logredo session. * */ rc = markBmap((struct dmap *) vopen[vol].bmap_ctl, ld->log.noredoinoext.pxd, 0, vol); if (rc != 0) { return (rc); } /* * Now, if no extent has been reallocated for * the inodes in the range which the extent being * released describes, then the IAG needs to be * updated to show that this extent is not * allocated. * * NOTE: It is not necessary to adjust the IAG * Free Extent List, the IAG Free Inodes List, * or the Free IAG List because they will be * rebuilt from scratch before the filesystem * is remounted (either near the end of logredo * processing or by fsck after logredo returns * control to it with rc != 0) * * NOTE: The wmap of the IAG tells whether logredo * has already encountered a log record for * one of these inodes. This would mean * activity for the inode(s) LATER IN TIME * than the current transaction. If no such * record has been seen, then the IAG[extno] * needs to be cleared. */ iagnum = ld->log.noredoinoext.iagnum; imp = vopen[vol].fsimap_lst.imap_wsp[(iagnum + 1)].imap_data; if (imp == NULL) { /* first touch to this IAG */ rc = iagGet(vol, iagnum); if (rc != 0) { return (rc); } imp = vopen[vol].fsimap_lst.imap_wsp[(iagnum + 1)].imap_data; } /* end first touch to this IAG */ iagext_idx = ld->log.noredoinoext.inoext_idx; if (imp->wmap[iagext_idx] == 0) { /* no later activity for * the inodes in the range for this * inode extent. */ /* all of them are now in a determined state */ imp->wmap[iagext_idx] = 0xFFFFFFFF; /* and that state is 'not allocated' */ imp->pmap[iagext_idx] = 0x00000000; PXDlength(&(imp->inoext[iagext_idx]), 0); PXDaddress(&(imp->inoext[iagext_idx]), 0); } /* end no activity for the inodes in the range for ... */ return (0); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: doUpdateMap(ld) * * FUNCTION: processing for LOG_UPDATEMAP record types. * * IN GENERAL * ---------- * The updatemap log record has many sub-types defined in * ld->log.updatemap.type, but in general, the log record * data describes file system block extent(s) for which * the block map (bmap) needs to be marked. * * IN PARTICULAR * ------------- * LOG_ALLOCPXD -- is written when an outline EA is allocated * * The log record data is a single PXD describing the * filesystem blocks to be marked allocated in the block map. * * LOG_ALLOCPXDLIST -- is not used in release 1 of JFS * * LOG_ALLOCXAD -- is not used in release 1 of JFS * * LOG_ALLOCXADLIST -- is not used in release 1 of JFS * * LOG_FREEPXD -- is written when a file is truncated and * a portion of the extent described by a * PXD is released * -- is written when an outline EA is freed * * The log record data is a single PXD describing the * filesystem blocks to be marked free in the block map. * * LOG_FREEPXDLIST -- is written when a file is compressed * -- is written when a file grows and the tail * cannot be extended in-place. **see note * * The log record data is a list of PXD's describing the * extents to be marked free in the block map. * * LOG_FREEXAD -- is not used in release 1 of JFS * * LOG_FREEXADLIST -- is written when a file is truncated * * The log record data is a list of XAD's describing the * extents to be marked free in the block map. * * **note: (see reference in LOG_FREEPXDLIST above) * * Each extent of a file MUST be an even multiple of 4096 byte * pages, except the last extent, which need only be an even * multiple of filesystem blocks. This means that, if the last * extent is not a whole page, then it must be extended to a * whole page before another extent can be added. If the * filesystem blocks immediately following the current last * extent are not available, then it is necessary to select * a larger storage area and copy the contents of the current * last extent and the new data (the reason the file is being * extended in the first place) into it. * * To illustrate: * suppose the filesystem block size is 1024 and a particular * files is 9216 bytes long, stored as * 1 extent 8 fs blocks (8192 bytes = 2 * 4096) and * 1 extent 1 fs block (1024 bytes) * now suppose another 5120 bytes are appended to the file. * The 2nd extent must be extended because it must either * become an even multiple of 4096 or it must remain the last * extent in the file. * Both: * 1 extent 8 fs blocks (8192 bytes) * 1 extent 6 fs blocks (6144 bytes) * and: * 1 extent 8 fs blocks (8192 bytes) * 1 extent 4 fs blocks (4096 bytes) * 1 extent 2 fs blocks (2048 bytes) * are possible and correct outcomes. * * * NOTE: Since UPDATEMAP log records only affect the block map, * the noredofile hash chain is not checked and the transaction * should not be skipped. * * When a file system object is deleted, UPDATEMAP log records * are created (as appropriate) to release storage from (and * possibly for) metadata xtree pages. No NoRedoPage log records * are written for these pages. * */ int doUpdateMap(struct lrd *ld) { /* pointer to log record descriptor */ int i, vol, rc = 0; xad_t *l_xad; pxd_t *l_pxd; pxd_t pxd1; /* * If it's not part of a committed transaction then it * should be ignored, so just return. */ if (!findCommit(ld->logtid)) return (0); /* * if it's the last entry for the current committed transaction, * remove the commit record from the commit list because we won't * be needing it any more. */ if (ld->backchain == 0) deleteCommit(ld->logtid); /* * if the filesystem was cleanly unmounted or if the last * thing that happened was a logredo failure, skip this * record. (Necessary for the case of logredo a log shared * by multiple filesystems. We want to process log records * for those filesystems which don't meet this criteria, but * skip log records for those which do.) */ vol = ld->aggregate; if (vopen[vol].status == FM_CLEAN || vopen[vol].status == FM_LOGREDO) return (0); if (ld->log.updatemap.type & LOG_FREEXADLIST) { /* * The data area contains an array of XAD's, with * updatemap.nxd elements. */ l_xad = (xad_t *) afterdata; for (i = 0; i < ld->log.updatemap.nxd; i++) { PXDaddress(&pxd1, addressXAD(l_xad)); PXDlength(&pxd1, lengthXAD(l_xad)); rc = markBmap((struct dmap *) vopen[vol].bmap_ctl, pxd1, 0, vol); if (rc != 0) { return (rc); } l_xad += 1; } } else if (ld->log.updatemap.type & LOG_FREEPXDLIST) { /* * The data area contains an array of PXD's, with * updatemap.nxd elements. */ l_pxd = (pxd_t *) afterdata; for (i = 0; i < ld->log.updatemap.nxd; i++, l_pxd++) rc = markBmap((struct dmap *) vopen[vol].bmap_ctl, *l_pxd, 0, vol); if (rc != 0) { return (rc); } } else if (ld->log.updatemap.type & LOG_FREEPXD) { /* * The updatemap.nxd should be 1 in this case. */ if (ld->log.updatemap.nxd > 1) fsError(LOGRCERR, vol, ld->log.updatemap.nxd); rc = markBmap((struct dmap *) vopen[vol].bmap_ctl, ld->log.updatemap.pxd, 0, vol); if (rc != 0) { return (rc); } } else if (ld->log.updatemap.type & LOG_ALLOCPXD) { /* * The updatemap.nxd should be 1 in this case. */ if (ld->log.updatemap.nxd > 1) fsError(LOGRCERR, vol, ld->log.updatemap.nxd); rc = markBmap((struct dmap *) vopen[vol].bmap_ctl, ld->log.updatemap.pxd, 1, vol); if (rc != 0) { return (rc); } } else fsck_send_msg(lrdo_DUMPUNKNOWNTYPE); return (0); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: dtpg_resetFreeList(ld) * * FUNCTION: Reset the freelist in the given Directory Btree (nonroot) * node. * * NOTE: none * */ int dtpg_resetFreeList(int32_t vol, int *buf) { /* buf contains on-disk page image */ int16_t pxd_len; int16_t nslots; /* number of slots in log.redopage.pxd */ dtpage_t *dtpg; int16_t stbl_nslots; /* number of slots occupied by * the stbl for the page */ int8_t slot_map[DTPAGEMAXSLOT]; int8_t *slot_table; int16_t sidx, slot_idx = 0; struct dtslot *this_slot; struct dtslot *last_slot = 0; struct idtentry *intern_hdr_slot; struct ldtentry *leaf_hdr_slot; dtpg = (dtpage_t *) buf; if (dtpg->header.nextindex == -1) { /* * the stbl is full, no slots * can be available */ dtpg->header.freecnt = 0; dtpg->header.freelist = -1; return 0; } /* the stbl isn't full. slots may be free. */ /* * The dtree page size is 512, 1024, 2048, or 4096 bytes. * We need to know how many slots it contains and how many * slots are occupied by its slot table (stbl). */ pxd_len = (lengthPXD(&dtpg->header.self)) << vopen[vol].l2bsize; switch (pxd_len) { case DT8THPGNODEBYTES: /* 512 bytes */ nslots = DT8THPGNODESLOTS; stbl_nslots = DT8THPGNODETSLOTS; break; case DTQTRPGNODEBYTES: /* 1024 bytes */ nslots = DTQTRPGNODESLOTS; stbl_nslots = DTQTRPGNODETSLOTS; break; case DTHALFPGNODEBYTES: /* 2048 bytes */ nslots = DTHALFPGNODESLOTS; stbl_nslots = DTHALFPGNODETSLOTS; break; default: /* 4096 bytes */ nslots = DTFULLPGNODESLOTS; stbl_nslots = DTFULLPGNODETSLOTS; break; } /* end switch */ /* * clear the slot map */ for (sidx = 0; sidx < nslots; sidx++) { slot_map[sidx] = 0; } /* * account for the header and for the stbl slots */ slot_map[0] = -1; /* the header */ for (sidx = 0; sidx < stbl_nslots; sidx++) { slot_map[dtpg->header.stblindex + sidx] = -1; } /* end for */ slot_table = (int8_t *) & (dtpg->slot[dtpg->header.stblindex]); /* * figure out which slots are in use */ for (sidx = 0; sidx < dtpg->header.nextindex; sidx++) { /* * the dir entry header slot */ /* * If the index is out of bounds or if we've * already seen it in use then something is * seriously wrong and we need a full fsck. * Since the problem could have been caused * by something in this logredo session, * signal fsck to reformat the log. */ if ((slot_table[sidx] >= nslots) || (slot_map[slot_table[sidx]] != 0)) { fsck_send_msg(lrdo_DPRFBADSTBLENTRY, (long long) (addressPXD(&dtpg->header.self))); return (DTPAGE_BADSTBLENTRY1); } /* endif */ slot_map[slot_table[sidx]] = -1; /* * any continuation slots for the dir entry */ if ((dtpg->header.flag & BT_LEAF) == BT_LEAF) { leaf_hdr_slot = (struct ldtentry *) &(dtpg->slot[slot_table[sidx]]); slot_idx = leaf_hdr_slot->next; } else { /* internal page */ intern_hdr_slot = (struct idtentry *) &(dtpg->slot[slot_table[sidx]]); slot_idx = intern_hdr_slot->next; } /* end else internal page */ while (slot_idx != -1) { /* * if the index is out of bounds or * if we've already seen it in use then * something is seriously wrong and we * need a full fsck. * Since the problem could have been caused * by something in this logredo session, * signal fsck to reformat the log. */ if ((slot_idx >= nslots) || (slot_map[slot_idx] != 0)) { fsck_send_msg(lrdo_DPRFBADSLOTNXTIDX, (long long) (addressPXD(&dtpg->header.self))); return (DTPAGE_BADSLOTNEXTIDX1); } /* endif */ slot_map[slot_idx] = -1; this_slot = &(dtpg->slot[slot_idx]); slot_idx = this_slot->next; } /* end while slot_idx */ } /* end for sidx */ /* * find the first available slot */ dtpg->header.freecnt = 0; /* assume none free */ dtpg->header.freelist = -1; /* assume none free */ for (sidx = 0; ((sidx < nslots) && (dtpg->header.freecnt == 0)); sidx++) { if (slot_map[sidx] == 0) { dtpg->header.freecnt = 1; dtpg->header.freelist = sidx; slot_idx = sidx; last_slot = &(dtpg->slot[sidx]); } /* end if */ } /* end for */ /* * count and chain together all available slots */ if (dtpg->header.freecnt != 0) { /* found a free one */ for (sidx = (slot_idx + 1); sidx < nslots; sidx++) { if (slot_map[sidx] == 0) { last_slot->next = sidx; dtpg->header.freecnt += 1; last_slot = &(dtpg->slot[sidx]); } /* end if */ } /* end for */ last_slot->next = -1; /* terminate the chain */ } /* end found a free one */ return (0); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: dtrt_resetFreeList(ld) * * FUNCTION: Reset the freelist in the given Directory inode Btree root. * * NOTE: none */ int dtrt_resetFreeList(int32_t vol, struct doblk *db, struct lrd *ld, caddr_t buf_btroot) { dtroot_t *dtrt; int8_t slot_map[DTROOTMAXSLOT]; int16_t sidx, slot_idx = 0; struct dtslot *this_slot; struct dtslot *last_slot = 0; struct idtentry *intern_hdr_slot; struct ldtentry *leaf_hdr_slot; /* * The doblk.i_dtroot (or doblk.dtpage_word) tracks which slots * slots have been updated, but since some of those updates may * be deletions, we can't use it to create the freelist. */ dtrt = (dtroot_t *) buf_btroot; if (dtrt->header.nextindex == -1) { /* * the stbl is full, no slots * can be available */ dtrt->header.freecnt = 0; dtrt->header.freelist = -1; return 0; } /* the stbl isn't full. slots may be free. */ /* * clear the slot map */ for (sidx = 0; sidx < DTROOTMAXSLOT; sidx++) { slot_map[sidx] = 0; } slot_map[0] = -1; /* the header occupies this space */ /* * figure out which slots are in use */ for (sidx = 0; sidx < dtrt->header.nextindex; sidx++) { /* * the dir entry header slot */ /* * If the index is out of bounds or if we've * already seen it in use then something is * seriously wrong and we need a full fsck. * Since the problem could have been caused * by something in this logredo session, * signal fsck to reformat the log. */ if ((dtrt->header.stbl[sidx] >= DTROOTMAXSLOT) || (slot_map[dtrt->header.stbl[sidx]] != 0)) { fsck_send_msg(lrdo_DRRFBADSTBLENTRY); return (DTPAGE_BADSTBLENTRY2); } /* endif */ slot_map[dtrt->header.stbl[sidx]] = -1; /* * any continuation slots for the dir entry */ if ((dtrt->header.flag & BT_LEAF) == BT_LEAF) { leaf_hdr_slot = (struct ldtentry *) &(dtrt->slot[dtrt->header.stbl[sidx]]); slot_idx = leaf_hdr_slot->next; } else { /* internal page */ intern_hdr_slot = (struct idtentry *) &(dtrt->slot[dtrt->header.stbl[sidx]]); slot_idx = intern_hdr_slot->next; } /* end else internal page */ while (slot_idx != -1) { /* * if the index is out of bounds or if we've * already seen it in use then something is * seriously wrong and we need a full fsck. * * Since the problem could have been caused by * something in this logredo session, signal * fsck to reformat the log. */ if ((slot_idx >= DTROOTMAXSLOT) || (slot_map[slot_idx] != 0)) { fsck_send_msg(lrdo_DRRFBADSLOTNXTIDX); return (DTPAGE_BADSLOTNEXTIDX2); } /* endif */ slot_map[slot_idx] = -1; this_slot = &(dtrt->slot[slot_idx]); slot_idx = this_slot->next; } /* end while slot_idx */ } /* end for sidx */ /* * find the first available slot */ dtrt->header.freecnt = 0; /* assume none free */ dtrt->header.freelist = -1; /* assume none free */ for (sidx = 0; ((sidx < DTROOTMAXSLOT) && (dtrt->header.freecnt == 0)); sidx++) { if (slot_map[sidx] == 0) { dtrt->header.freecnt = 1; dtrt->header.freelist = sidx; slot_idx = sidx; last_slot = &(dtrt->slot[sidx]); } } /* * count and chain together all available slots */ if (dtrt->header.freecnt != 0) { /* found a free one */ for (sidx = (slot_idx + 1); sidx < DTROOTMAXSLOT; sidx++) { if (slot_map[sidx] == 0) { last_slot->next = sidx; dtrt->header.freecnt += 1; last_slot = &(dtrt->slot[sidx]); } /* end if */ } /* end for */ last_slot->next = -1; /* terminate the chain */ } /* end found a free one */ return (0); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: findCommit(tid) * * FUNCTION: Search in the commit array for a commit record with * transaction id (tid) matching the given tid. * Return the commit array index where found, or 0 * if not found. */ int findCommit(int32_t tid) { /* transaction id */ int32_t k, hash; hash = tid & comhmask; /* hash class */ for (k = comhash[hash]; k != 0; k = com[k].next) if (com[k].tid == tid) return (k); return (0); /* not found */ } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: findPageRedo() * * FUNCTION: Search in the RedoPage hash table for a record * containing the block address in the given pxd. * If no match is found, such a record is created and * inserted into the table. * * The address of the found (or created) doblk is * returned. * */ int findPageRedo(int32_t aggregate, /* file system aggregate/lv number */ pxd_t pxd, /* on-disk page pxd */ struct doblk **doptr) { int rc = 0; int32_t hash; struct doblk *dp; int32_t allocated_from_bmap = 0; /* * Search for a record with matching aggregate, and block offset. */ hash = (aggregate + addressPXD(&pxd)) & blkhmask; for (dp = blkhash[hash]; dp != NULL; dp = dp->next) if (dp->aggregate == aggregate && addressPXD(&dp->pxd) == addressPXD(&pxd)) { /* * match found. return its address to caller */ *doptr = dp; return (0); } /* * No match was found. */ /* * if there are no available doblk records, * allocate some storage */ if (Freedoblk == 0) { rc = alloc_storage((uint32_t) PSIZE, (void **) &Blkpage, &allocated_from_bmap); if ((rc != 0) || (Blkpage == NULL)) { fsck_send_msg(lrdo_ALLOC4DOBLKFAIL, PSIZE); return (ENOMEM4); } if (allocated_from_bmap) { fsck_send_msg(lrdo_USINGBMAPALLOC4DOBLK); } Freedoblk = PSIZE / sizeof (struct doblk); } dp = Blkpage; /* * Allocate a doblk record and initialize it * with the given aggregate and block * offset. Insert the record into the RedoPage * hash table. */ numdoblk++; Blkpage++; Freedoblk--; dp->next = blkhash[hash]; blkhash[hash] = dp; dp->aggregate = aggregate; dp->pxd = pxd; dp->type = 0; memset(&dp->summary, 0, sizeof (dp->summary)); /* * return the address of the created doblk to caller */ *doptr = dp; return (0); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: logredoInit() * * FUNCTION: allocate/initialize runtime data structures and * initialize for file systems sharing the log. */ int logredoInit() { int rc = 0; int k; int allocated_from_bmap = 0; /* * init free list for com. index 0 is not used. */ comfree = 1; for (k = 1; k < COMSIZE; k++) com[k].next = k + 1; /* * init comhash chains */ for (k = 0; k < 64; k++) comhash[k] = 0; /* * init block hash chains */ numdoblk = 0; for (k = 0; k < BHASHSIZE; k++) blkhash[k] = NULL; /* * allocate one page space for redo page hash table */ rc = alloc_storage((uint32_t) PSIZE, (void **) &Blkpage, &allocated_from_bmap); if ((rc != 0) || (Blkpage == NULL)) { /* RedoPage record allocation failed */ fsck_send_msg(lrdo_ALLOC4REDOPGFAIL, PSIZE); return (ENOMEM5); } if (allocated_from_bmap) { fsck_send_msg(lrdo_USINGBMAPALLOC4RDPG); } Freedoblk = PSIZE / sizeof (struct doblk); /* * init nodofile hash chains , and counts */ numnodofile = 0; for (k = 0; k < NODOFILEHASHSIZE; k++) nodofilehash[k] = NULL; /* * allocate one page space for nodo file hash table */ rc = alloc_storage((uint32_t) PSIZE, (void **) &Nodofilep, &allocated_from_bmap); if ((rc != 0) || (Nodofilep == NULL)) { /* RedoPage record allocation failed */ fsck_send_msg(lrdo_ALLOC4NODOFLFAIL, PSIZE); return (ENOMEM6); } if (allocated_from_bmap) { fsck_send_msg(lrdo_USINGBMAPALLOC4NDFL); } Freenodofile = PSIZE / sizeof (struct nodofile); /* init buffer pool */ for (k = 0; k < NBUFPOOL; k++) { bufhdr[k].next = k + 1; bufhdr[k].prev = k - 1; } bufhdr[0].prev = NBUFPOOL - 1; bufhdr[NBUFPOOL - 1].next = 0; /* * initialize file systems * For outlinelog, * open all file system lvs which were in the log active list; * validate superblock and allocation map of file systems; * For inlinelog, only one file system to be processed at one time, * so open just this file system. logmajor and logminor is the file * system's major and minor numbers. */ if (Log.location & INLINELOG) { if (openVol(0) != 0) return (CANTOPEN_INLINELOG); } else { int success = 0; for (k = 0; k < MAX_ACTIVE; k++) { if (!uuid_is_null(logsup.active[k])) { uuid_copy(vopen[k].uuid, logsup.active[k]); if (openVol(k)) vopen[k].status = FM_LOGREDO; else success = 1; } } if (!success) return CANTOPEN_OUTLINELOG; } return (0); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: markBmap() * * FUNCTION: This routine updates the Aggregate Block Map * for each block described by the given pxd unless * it has already been done. That is, on a block-by-block * basis, if the Aggregate Block Map has not been updated * for the block in the current session, then it is * updated now. * * Specifically, if the Block Map persistent map (pmap) * bit representing the block has not already been * updated by this routine, that bit is updated as * requested by the caller * * NOTES: This routine uses the Block Map page working map (wmap) * to keep track of which IAG pmap bits have already been * updated by this routine. */ int markBmap(struct dmap *dmappg, /* the beginning of bmap file */ pxd_t pxd, /* descriptor for the blocks of interest */ int val, /* 1 to allocate, 0 to free */ int vol) { int rc = 0; int64_t blkno, dmap_pg; struct dmap_bitmaps *dp; uint32_t rem, nblocks, word, dbitno, nblks, rbits, nwords; uint16_t wbitno, nbits, n, j; int32_t dmap_number; if (Insuff_memory_for_maps) return 0; nblocks = lengthPXD(&pxd); /* number of blocks described */ blkno = addressPXD(&pxd); /* the first block number */ if ((blkno + nblocks) > vopen[vol].fssize) { fsck_send_msg(lrdo_MBMPBLKOUTRANGE, (long long) blkno, nblocks); fsError(DBTYPE, vol, blkno); return (BLOCK_OUTOFRANGE); } /* * nblocks may be large enough to span several struct dmap pages. * Update the block state one struct dmap page at a time. */ for (rem = nblocks; rem > 0; rem -= nblks, blkno += nblks) { dmap_pg = BLKTODMAPN(blkno); dp = vopen[vol].bmap_wsp[dmap_pg].dmap_bitmaps; if (dp == NULL) { /* first touch to this dmap */ dmap_number = blkno >> L2BPERDMAP; rc = dMapGet(vol, dmap_number); if (rc != 0) { return (rc); } dp = vopen[vol].bmap_wsp[dmap_pg].dmap_bitmaps; } /* the bit position, within the current dmap page, * representing the current aggregate block. */ dbitno = blkno & (BPERDMAP - 1); /* the word, within the current dmap page, which contains * the bit for the block. */ word = dbitno >> L2DBWORD; /* number of blocks which are in the extent and are * described by the current dmap. */ nblks = MIN(rem, BPERDMAP - dbitno); /* * Mark the dmap bitmap. */ for (rbits = nblks; rbits > 0; rbits -= nbits, dbitno += nbits) { wbitno = dbitno & (DBWORD - 1); nbits = MIN(rbits, DBWORD - wbitno); /* * only part of the word is implicated */ if (nbits < DBWORD) { for (n = 0; n < nbits; n++, wbitno++) { /* * If bit already updated in this * logredo session, nothing to do. */ if (dp->wmap[word] & (UZBIT_32 >> wbitno)) continue; /* update pmap according to val. * set wmap to indicate state is * determined. */ dp->wmap[word] |= (UZBIT_32 >> wbitno); if (val) /* request to turn on */ dp->pmap[word] |= (UZBIT_32 >> wbitno); else /* request to turn off */ dp->pmap[word] &= ~(UZBIT_32 >> wbitno); } word += 1; } else { /* nbits == DBWORD. One or more words * are to have all their bits updated. */ nwords = rbits >> L2DBWORD; nbits = nwords << L2DBWORD; for (n = 0; n < nwords; n++, word++) for (j = 0; j < DBWORD; j++) { /* * If bit already updated in * this logredo session, * nothing to do. */ if (dp->wmap[word] & (UZBIT_32 >> j)) continue; /* note (in the wmap) that the * bits have been updated in * this session. */ dp->wmap[word] |= (UZBIT_32 >> j); if (val) /* turn on request */ dp->pmap[word] |= (UZBIT_32 >> j); else /* turn off request */ dp->pmap[word] &= ~(UZBIT_32 >> j); } /* end for j */ } } } return (0); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: markImap() * * FUNCTION: This routine updates the inode allocation map * for the specified inode unless it has already * been done. * * Specifically, if the IAG persistent map (pmap) * bit representing the inode has not already been * updated by this routine, * * - that bit is updated as requested by the caller * * - If the bit is being set to '1', the descriptor * for the extent containing the inode is refreshed. * * NOTES: This routine uses the IAG working map (wmap) to keep * track of which IAG pmap bits have already been updated * by this routine. */ int markImap(struct fsimap_lst *fsimap, /* data for the inode table */ uint32_t inum, /* inode number */ pxd_t inopxd, /* inode extent descriptor this inode */ int val, /* 1 to allocate, 0 to free */ int vol) { int rc; struct iag_data *imp; int32_t iag_num, ino, extno, bitno; iag_num = INOTOIAG(inum); if (iag_num > fsimap->imap_page_count) return -1; imp = fsimap->imap_wsp[(iag_num + 1)].imap_data; if (imp == NULL) { /* first touch to this IAG */ rc = iagGet(vol, iag_num); if (rc != 0) { return (rc); } imp = fsimap->imap_wsp[(iag_num + 1)].imap_data; } /* end first touch to this IAG */ ino = inum & (INOSPERIAG - 1); extno = ino >> L2INOSPEREXT; bitno = ino & (INOSPEREXT - 1); /* process it only if the state is not determined */ if (!(imp->wmap[extno] & (UZBIT_32 >> bitno))) { /* update pmap according to val, * set wmap to indicate state is determined. */ imp->wmap[extno] |= (UZBIT_32 >> bitno); if (val) { imp->pmap[extno] |= (UZBIT_32 >> bitno); imp->inoext[extno] = inopxd; /* ???? */ } else { imp->pmap[extno] &= ~(UZBIT_32 >> bitno); } } return (0); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: saveExtDtPg() * * FUNCTION: Add an entry to the list of extended dtpages * for the dtpage whose length and offset are given. * */ int saveExtDtPg(int32_t pageVol, int64_t pageOff) { int rc = 0; struct ExtDtPg *edpp; int32_t allocated_from_bmap = 0; /* * if there are no available records, * allocate some storage */ if (FreeExtDtPg == 0) { rc = alloc_storage((uint32_t) PSIZE, (void **) &DtPgPage, &allocated_from_bmap); if ((rc != 0) || (DtPgPage == NULL)) { /* * ExtDtPg record allocation failed */ fsck_send_msg(lrdo_ALLOC4EXTDTPGFAIL, PSIZE); return (ENOMEM7); } /* ExtDtPg record allocation successful */ if (allocated_from_bmap) { fsck_send_msg(lrdo_USINGBMAPALLOC4EDPG); } FreeExtDtPg = PSIZE / sizeof (struct ExtDtPg); } /* * allocate a block, assign the given values to it, * and add it to the list */ edpp = DtPgPage; numExtDtPg++; DtPgPage++; FreeExtDtPg--; edpp->pg_vol = pageVol; edpp->pg_off = pageOff; edpp->next = DtPgList; DtPgList = edpp; return (0); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * * NAME: updatePage(ld) * * FUNCTION: This routine performs the following functions: * * 1) APPLY LOGREC DATA (in buffer afterdata[]) * * This is copied into the disk page specified by redopage.pxd. * * We apply only the portion(s) of the disk page not already * updated by a log record in the current logredo session. * logredo sees the disk page as a series of segments, and * handles the segments affected by the current logrec data * individually. * * It is possible that, if the data in a particular log record * contains several segments, the segments may overlay each * other. In order to insure that the last (in time) image * logged is the image applied by logredo, the segments in * the log record are read in right-to-left order. (That is, * in last-in-first-out or LIFO order.) * * The doblk fields summary1 and summary2 track updates to * page segments. These are marked as the log record data * is applied. This ensures that data logged earlier (which * is processed later by logredo) for a particular segment * will be ignored. * * 2) INITIALIZE/RESET DTREE FREELIST * * 3) UPDATE THE AGGREGATE BLOCK MAP * * We update the block map for extents described by the * xadlist in an xtree or xtree_root page. * * We reset the XAD_NEW|XAD_EXTENDED flags in the xad in * case they happen to be on. (The block map has been updated * regardless of their state.) * * 4) IF log.redopage.type == LOG_INODE * * then all work necessary is finished with this log record * because all the information needed is contained in the * log record data area. * * Specifically: * - update the inode base image. This is needed even for an * inode which is being released in order to set nlink = 0. * - update the Inode Allocation Map (imap) if the inode * is being allocated or released. * - update the Aggregate Block Map (bmap) if a new inode * extent is allocated. * * NOTE: o The field lrd.length describes the redopage data area only. * That is, it does not include the length of the lrd itself. * * * o Since the slot size differs, log.redopage.l2linesize * contains log2 of the slot size for the current log record. * * * o As transactions are processed by the JFS IFS, they are * logged from left to right (physically) in the log file, * but that because we process them in LIFO (last-in-first-out) * order, logredo reads and processes them from right to left * (physically) This applies to both the transactions in the * log and to the records in each transaction. * N.B. The exception to this is that the log is circular * and may wrap during a particular session. * * A log record consists of 3 parts: * type independent area (16 bytes) * type dependent area (20 bytes) * data area (variable length) * and, although they are processed in the order listed, they * occur physically (in the log file) in the opposite order. * That is, if you were to examine the storage in a log page, * reading from left to right, a general log record would * appear * * * * o The FORMAT OF THE REDOPAGE DATA AREA depends on the * redopage type: * * REDOPAGE:DIRECTORY data format * a series of 1 or more * * each is * * is * *** These are expressed in number of slots. * Stored as * *** A directory slot is 32 bytes in length * *** slot[0] begins at beginning of the * directory tree page specified by pxd. * is the byte image of * slots, starting with slot * in the directory node (or root) specified. * * N.B. The s may overlay slots. * ====== * FOR EXAMPLE: Suppose we need to insert an entry * into the first half of a particular directory page * which does not have enough available slots to * accomodate it. * - We split the existing directory page, moving 1/2 * the entries into a new page * - We free the slots which the moved entries occupied * before the split. * - We insert the new entry, using the (newly) free * slot(s). * Thus some slots have been freed and then allocated * again, all in a single transaction. * * When a transaction is logged, the segments are written * as they occur, from left to right in the log. * (So in the example, the 'free slot(s) segment' would * be written, then the 'allocate slot(s) segment' would * be written.) * * Since logredo processes the log from right to left * (i.e. even the records with a transaction are processed * from right to left), it processes the 'allocate * slot(s) segment', noting the slots which have been * updated. Then logredo encounters the 'free slot(s) * segment' and ignores updates to slots which have * already been updated. * * REDOPAGE:XTREE data format * a series of 1 or more * * each is * * is * *** These are expressed in number of slots. * Stored as * *** An index tree slot is 16 bytes in length * *** slot[0] begins at beginning of the * index tree page specified by pxd. * is the byte image of * slots, starting with slot * in the directory node (or root) specified. * * N.B. The data area of this type of log record contains, * at most, two segments. The header segment is * always included and logged as one segment (even if * the slot(s) described by the second segment are * contiguous to the header segment). There may * also be a second segment containing the after-image * of non-header slot(s). * * REDOPAGE:INODE data format * a series of 1 or more * * each is * * is * *** These are expressed in number of slots. * Stored as * *** The length of an inode slot in this * record type is 128 bytes * *** slot[0] begins at beginning of the * (4096 byte) inode extent page * specified by pxd. * is the byte image of * slots, starting with slot * in the inode extent page specified. * * N.B. In this type of log record, redopage.inode is the * inode number of the inode which owns the IAG which * describes the extent which contains the inode * actually being changed. (For example, an update * to inode x in fileset 0 would show lrd.inode==16 * because aggregate inode 16 is the Inode Allocation * Table inode for fileset 0.) * * Also, lrd.pxd defines the (4096 byte) page of * storage which contains the inode being changed. * * Since each inode extent contains 4 pages, this may * or may not also be the first page of an inode extent. * * Since each page contains 8 inodes, some more work is * needed to determine the inode number of the inode * actually being changed. * * N.B. In this type of log record data, there may be several * segments. Each segment is either the base image of * one inode or the byte image of one inlineEA. * * If a particular segment describes an inode base image, * then / 4 has no remainder * else if the segment describes an inlineEA * then / 4 has remainder 3 * * REDOPAGE:BTROOT|XTREE data format * a series of 1 or more * * each is * * is * INDEX TREE slots. * Stored as * *** The length of an index tree slot * 16 bytes * *** slot[0] begins at di_btroot (32 bytes * before Section III of the dinode) * is the byte image of * slots, starting with slot * in the inode extent page specified. * * N.B. In this type of log record, redopage.inode is the * inode number of the inode actually being changed. * * Also, lrd.pxd defines the (4096 byte) page of * storage which contains the inode being changed. * * Since each inode extent contains 4 pages, this may * or may not also be the first page of an inode extent. * * Since each page contains 8 inodes, some more work is * needed to determine the starting offset (within the * page specified by pxd) of the inode actually being * changed. * * REDOPAGE:BTROOT|DTREE data format * a series of 1 or more * * each is * * is * *** These are expressed in number of * DIRECTORY TREE slots. * Stored as * *** The length of a directory tree slot * is 32 bytes * *** slot[0] begins at di_btroot (32 bytes * before Section III of the dinode) * is the byte image of * slots, starting with slot * in the inode extent page specified. * * N.B. In this type of log record, redopage.inode is the * inode number of the inode actually being changed. * * Also, lrd.pxd defines the (4096 byte) page of * storage which contains the inode being changed. * * Since each inode extent contains 4 pages, this may * or may not also be the first page of an inode extent. * * Since each page contains 8 inodes, some more work is * needed to determine the starting offset (within the * page specified by pxd) of the inode actually being * changed. * * REDOPAGE:DATA (i.e. inline data) data format * a series of 1 or more * * each is * * N.B. This type is used for inline data, currently only * defined for symbolic links (symlinks) which * are ** NOT IMPLEMENTED IN RELEASE I OF JFS/WARP ** * * * o Since * - logredo only updates the first segment of an inode * by applying a REDOPAGE:INODE log record * - a REDOPAGE_INODE log record pxd describes a page * in an inode extent (that is, 4096 bytes containing * 8 inodes) * - a REDOPAGE_INODE log record contains the inode number * of the Inode Alloc Table, not the affected inode * (indeed there may be more than 1 affected inode in * the data for the record) * - segmentData contains only the after-image of the * inode(s) being changed * logredo cannot determine which, if any, inode(s) in the * page have just been allocated (nlink was 0, now is not) * and/or have just been released (nlink was not 0, now is). * * Therefore, for the purposes of updating the Inode Allocation * Map, logredo assumes that all inodes in the page which * are allocated, are newly allocated, and all inodes in the * page which are not allocated have just been released. * */ int updatePage(struct lrd *ld, int32_t logaddr) { int rc; int32_t vol; int *buf; struct doblk *db; uint8_t mask_8 = 0, xtroot_lwm = 0; uint16_t mask_9, dtroot_9 = 0; uint32_t mask_32, dtpg_32, datapg_32; int16_t l2linesize; /* log2 of the slot size */ int32_t i, j, k, seglen, linesize, segnum, inonum = 0; int32_t iag_num, ino, extno; int16_t off, ln, inoext_alloc, allocate, delta_len, s_index, ino_rem; int16_t *segdata, wbitno, nbits, nslots, size_dinode; caddr_t data, buf_ptr, buf_btroot = 0; xad_t *xad_p; pxd_t pxd1; struct iag_data *imp; struct dinode *dip = 0; int32_t xlen, xlength; int16_t nword; int8_t upd_possible = 0; if (ld->length <= 0) return (0); vol = ld->aggregate; /* * segdata points to the end of afterdata */ size_dinode = sizeof (struct dinode); segdata = (int16_t *) ((caddr_t) afterdata + ld->length); l2linesize = ld->log.redopage.l2linesize; linesize = 1 << l2linesize; j = 0; seglen = 0; segnum = 0; /* * find doblk for the specified pxd */ if ((rc = findPageRedo(ld->aggregate, ld->log.redopage.pxd, &db)) != 0) { fsck_send_msg(lrdo_UPPGFNDPGREDOFAIL, rc); return (rc); } /* * check to see if there is anything to do for this page */ if (ld->log.redopage.type == LOG_INODE) { if (db->type && !(db->type & LOG_INODE)) { db->type = LOG_NONE; /* mark page noredo */ return 0; } db->type |= LOG_INODE; if (db->db_ibase == 0xFF && db->db_idata == 0xFF && db->db_iea == 0xFF && db->db_ilink == 0xFF) /* for each inode in the page, base image, inline * data and the EA have already been refreshed in * this logredo session */ return (0); } else if ((ld->log.redopage.type & (LOG_BTROOT | LOG_DTREE)) == (LOG_BTROOT | LOG_DTREE)) { /* * * Dtree Root Node * */ if (db->type && !(db->type & LOG_INODE)) { db->type = LOG_NONE; /* mark page noredo */ return 0; } db->type |= LOG_INODE; /* * log.redopage.inode is the inode number of the inode * whose tree will be refreshed. * inonum is the position of that inode in the inode * extent (4096 byte) page described by the pxd. * (Each page has 8 inodes.) */ inonum = ld->log.redopage.inode & 0x07; mask_8 = UZBIT_8 >> inonum; /* * Has this inode already been updated as a symbollic link? */ if (db->db_ilink & mask_8) return 0; /* * This inode is identified as a dtroot. So, first * mark the appropriate bit to insure * NO updates to this inode's root as a normal xtree. */ db->db_idtree |= mask_8; dtroot_9 = db->db_dtroot[inonum]; if (dtroot_9 == 0x01ff) /* all slots in the dtree root have * already been refreshed in this * logredo session */ return (0); } else if ((ld->log.redopage.type & (LOG_BTROOT | LOG_XTREE)) == (LOG_BTROOT | LOG_XTREE)) { /* * * Xtree Root Node * */ if (db->type && !(db->type & LOG_INODE)) { db->type = LOG_NONE; /* mark page noredo */ return 0; } db->type |= LOG_INODE; /* * log.redopage.inode is the inode number of the inode * whose tree will be refreshed. * inonum is the position of that inode in the inode * extent (4096 byte) page described by the pxd. * (Each page has 8 inodes.) */ inonum = ld->log.redopage.inode & 0x07; mask_8 = UZBIT_8 >> inonum; /* * If this inode was previously marked as a symlink, we * can't update it as an xtree */ if (db->db_ilink & mask_8) return 0; /* * This inode is identified as an xtroot. So, first * mark the appropriate slot in the noredopage for * NO updates to this inode's root as a dtree. */ if (ld->log.redopage.type & LOG_DIR_XTREE) { /* This must be a directory */ db->db_idtree |= mask_8; /* directory x-tree shares space with db_idata */ if (db->db_idata & mask_8) return 0; else db->db_idata |= mask_8; } else { db->db_dtroot[inonum] = 0x01ff; /* * If this inode was previously marked as a dtree, we * can't update it as an xtree */ if (db->db_idtree & mask_8) return 0; } xtroot_lwm = db->db_xtrt_lwm[inonum]; if ((xtroot_lwm == XTENTRYSTART) && db->db_xtrt_hd & mask_8) /* The header slot and at least the 1st slot after * the header have already been refreshed in this * logredo session. */ return (0); else if (xtroot_lwm == 0) /* First time */ xtroot_lwm = db->db_xtrt_lwm[inonum] = 0xFF; } else if ((ld->log.redopage.type & LOG_DTREE) == LOG_DTREE) { /* * * Dtree Non-Root Node * */ if (db->type && !(db->type & LOG_DTREE)) { db->type = LOG_NONE; /* mark page noredo */ return 0; } db->type |= LOG_DTREE; /* * This extent may not be a full page (4096 bytes in length) * * Figure out its size, the number of slots it * covers, the number words used to track those slots, * and the number of bits in the last of those words. */ xlen = lengthPXD((&ld->log.redopage.pxd)); xlength = xlen << vopen[vol].l2bsize; nslots = xlength >> L2DTSLOTSIZE; nword = nslots >> L2DBWORD; nbits = nslots & (DBWORD - 1); upd_possible = 0; for (i = 0; i < nword; i++) { if (db->db_dtpagewd[i] != ONES) { upd_possible = -1; } } if (nbits) { i = DBWORD - nbits; mask_32 = ((uint32_t) (ONES >> i)) << i; if (db->db_dtpagewd[nword] != mask_32) { upd_possible = -1; } } if (!upd_possible) { /* all slots in the dtree node have * already been refreshed in this logredo session. */ return (0); } } else if ((ld->log.redopage.type & LOG_XTREE) == LOG_XTREE) { /* * Xtree Non-Root Node */ if (db->type && !(db->type & LOG_XTREE)) { db->type = LOG_NONE; /* mark page noredo */ return 0; } db->type |= LOG_XTREE; if ((db->db_xtpagelwm == XTENTRYSTART) && db->db_xtpghd) /* the header slot and at least the first slot after * the header have been refreshed in this logredo * session. */ return (0); else if (db->db_xtpagelwm == 0) db->db_xtpagelwm = 0xFF; /* First time */ } else if ((ld->log.redopage.type & LOG_DATA) == LOG_DATA) { /* * Data Page */ if (db->type && !(db->type & LOG_DATA)) { db->type = LOG_NONE; /* mark page noredo */ return 0; } db->type |= LOG_DATA; /* * This extent may not be a full page (4096 bytes in length) * * Figure out its size, the number of slots it * covers, the number words used to track those slots, * and the number of bits in the last of those words. */ xlen = lengthPXD((&ld->log.redopage.pxd)); xlength = xlen << vopen[vol].l2bsize; nslots = xlength >> L2DATASLOTSIZE; nword = nslots >> L2DBWORD; upd_possible = 0; for (i = 0; i < nword; i++) { if (db->db_dtpagewd[i] != ONES) { upd_possible = -1; } } if (!upd_possible) { /* all slots in the dtree node have * already been refreshed in this logredo session. */ return (0); } } /* * * There is actually some work to do * */ buf = NULL; inoext_alloc = 0; /* init ino extent allocation state */ while (j < ld->length) { /* while data segments unprocessed */ ln = __le16_to_cpu(*--segdata); /* get length */ off = __le16_to_cpu(*--segdata); /* get offset */ segnum++; seglen = ln << ld->log.redopage.l2linesize; /* Sanity check */ if ((off < 0) || (ln <= 0) || ((off + ln) << ld->log.redopage.l2linesize > PSIZE)) return UPDATEPAGE_BAD_RANGE; /* * segdata points to the beginning of the segment */ segdata = (int16_t *) ((caddr_t) segdata - seglen); data = (caddr_t) segdata; j += seglen + 4; /* * * INODE * */ if ((ld->log.redopage.type & LOG_INODE) == LOG_INODE) { /* check to see if the current inode base image has * been updated by an earlier log rec * Note: we don't need to check if the current inode * base image is on noredofile hash chain since the * doblk does the same job for us. An inode is on the * noredofile hash chain only if it is processed by * an earlier log rec */ inonum = off >> 2; /* inode seq. no in the inode * page zero origin */ mask_8 = UZBIT_8 >> inonum; ino_rem = off & 3; /* don't update dip if the segment is for inlineEA. * When an update involves EA, the base inode image * is always out too, so dip can always catch some * base inode image data */ if (ino_rem == 0) { /* inode base segment */ dip = (struct dinode *) data; if (ln == 1) { /* ibase only */ if (db->db_ibase & mask_8) /* already updated */ continue; db->db_ibase |= mask_8; } else { /* ibase & idata */ if ((db->db_ibase & mask_8) && (db->db_idata & mask_8)) /* already updated */ continue; if (db->db_ibase & mask_8) { /* Only update idata */ db->db_idata |= mask_8; ino_rem = 1; off += 1; data += linesize; seglen -= linesize; /* * i_data overlaps btroot. * Strip off 32 bytes */ seglen -= 32; } else if (db->db_idata & mask_8) { /* Only update ibase */ db->db_ibase |= mask_8; seglen -= linesize; } else { /* update both */ db->db_ibase |= mask_8; db->db_idata |= mask_8; /* * i_data overlaps btroot. * Strip off 32 bytes */ seglen -= 32; } } /* * We mess around with seglen. Make sure * it doesn't go negative. */ if (seglen < 0) return UPDATEPAGE_BAD_RANGE; } else if (ino_rem == 1) { /* inline data */ if (db->db_idata & mask_8) continue; db->db_idata |= mask_8; } else if (ino_rem == 2) { /* inline symlink */ if (db->db_ilink & mask_8) continue; if (db->db_idtree & mask_8) continue; if (db->db_xtrt_lwm[inonum] || db->db_xtrt_hd & mask_8) continue; db->db_ilink |= mask_8; } else if (ino_rem == 3) { /* inlineEA */ if (db->db_iea & mask_8) /* already updated */ continue; db->db_iea |= mask_8; } else { fsck_send_msg(lrdo_UPPGBADINODESEGOFFSET, off); } /* * read the inode extent page into a buffer */ if (buf == NULL) { rc = bread(vol, ld->log.redopage.pxd, (void **) &buf, PB_UPDATE); if (rc) { fsck_send_msg(lrdo_UPPGBREADFAIL1, rc); return (INOEXT_READERROR1); } } /* * refresh the appropriate slot in the inode extent * page in the buffer with the data in the current * segment. */ buf_ptr = (caddr_t) buf + (off << l2linesize); memcpy(buf_ptr, data, seglen); if (!ino_rem) { /* inode base image */ /* inoext_alloc will be nonzero if at least * one inode in the page is allocated. In * this case, we will mark block map to show * the whole inode extent (all 4 pages) as * allocated */ allocate = (dip->di_nlink != 0); inoext_alloc |= allocate; /* * There is only one fileset per aggregate, so * the inode extent is always owned by inode * FILESYSTEM_I */ if (ld->log.redopage.inode == FILESYSTEM_I) { rc = markImap(&vopen[vol].fsimap_lst, __le32_to_cpu(dip->di_number), dip->di_ixpxd, allocate, vol); if (rc) { fsck_send_msg(lrdo_UPPGMIMPFAIL, rc); return (rc); } } /* if zero link count, start NoRedoFile filter * Note: for the first release, we ensure that * the nlink for the aggregate inode * FILESYSTEM_I will be non-zero. If more * filesets are processed in the later release, * then nlink could be zero for the aggregate * inodes. */ if (!allocate) doNoRedoFile(ld, __le32_to_cpu(dip->di_number)); } } else if ((ld->log.redopage.type & (LOG_BTROOT | LOG_XTREE)) == (LOG_BTROOT | LOG_XTREE)) { /* * * Xtree Root Node * */ if ((off != 0 && xtroot_lwm <= (uint8_t) off) || (off == 0 && db->db_xtrt_hd & mask_8)) continue; /* * read in the inode extent page */ if (buf == NULL) { rc = bread(vol, ld->log.redopage.pxd, (void **) &buf, PB_UPDATE); if (rc) { fsck_send_msg(lrdo_UPPGBREADFAIL2, rc); return (INOEXT_READERROR2); } } if (ld->log.redopage.type & LOG_DIR_XTREE) { buf_btroot = (caddr_t) buf + size_dinode * inonum + (8 << l2linesize); } else { /* * for BTROOT (either xtree or dtree), off * starts from di_btroot, not from the * beginning of inode, not from beginning of * page. Slot number is zero origin. di_btroot * starts from slot #14 for xtroot * * First let buf_ptr points to the beginning * of off */ buf_btroot = (caddr_t) buf + size_dinode * inonum + (14 << l2linesize); /* if xtroot has taken the inode section IV, * indicate in db_iea so that later inlineEA * data won't apply to it */ if ((off + ln) > 10) { mask_8 = UZBIT_8 >> inonum; db->db_iea |= mask_8; } } if (off == 0) { /* header segment and the first time */ memcpy((caddr_t) buf_btroot, data, ln << l2linesize); db->db_xtrt_hd |= mask_8; } else { if (xtroot_lwm == 0xFF) /* the first time */ delta_len = ln; else delta_len = xtroot_lwm - off; xad_p = (xad_t *) data; for (i = 0; i < delta_len; i++) { MARKXADNEW(pxd1, xad_p, vopen[vol].bmap_ctl, vol); xad_p += 1; } buf_ptr = buf_btroot + (off << l2linesize); memcpy((caddr_t) buf_ptr, data, delta_len << l2linesize); db->db_xtrt_lwm[inonum] = xtroot_lwm = off; } } else if ((ld->log.redopage.type & LOG_XTREE) == LOG_XTREE) { /* * * Xtree Non-Root Node * */ /* * log rec for xtree has two segments. * the first is the header. The second * segment for xtpage slots update. * * The log rec data area contains a list of * xad's. Each XAD may has a flag of XAD_NEW * or XAD_EXTENDED. If it shows up, then * logredo needs to reset the flag and mark * on bmap, then update the on-disk xtree image. */ /* if the lwm less than offset or it is a header * segment but header had been updated previously, * ignore this segment. * Note: every log rec has the header data. But xtpage * header should be only updated once at logredo. */ if ((off != 0 && db->db_xtpagelwm <= (uint8_t) off) || (off == 0 && db->db_xtpghd)) continue; /* read the on-disk page into buffer pool. */ if (buf == NULL) { rc = bread(vol, ld->log.redopage.pxd, (void **) &buf, PB_UPDATE); if (rc) { fsck_send_msg(lrdo_UPPGBREADFAIL3, rc); return (XTPAGE_READERROR1); } } if (off == 0) { /* it is header segment and the first time */ memcpy((caddr_t) buf, data, ln << l2linesize); db->db_xtpghd = 1; } else { if (db->db_xtpagelwm == 0xff) /* the first time */ delta_len = ln; else delta_len = db->db_xtpagelwm - off; xad_p = (xad_t *) data; for (i = 0; i < delta_len; i++) { MARKXADNEW(pxd1, xad_p, vopen[vol].bmap_ctl, vol); xad_p += 1; } buf_ptr = (caddr_t) buf + (off << l2linesize); memcpy((caddr_t) buf_ptr, data, delta_len << l2linesize); db->db_xtpagelwm = (uint8_t) off; } } else { /* * * Data or Dtree Node -- Root and Non-Root * */ /* read the on-disk page into buffer pool. */ if (buf == NULL) { rc = bread(vol, ld->log.redopage.pxd, (void **) &buf, PB_UPDATE); if (rc) { fsck_send_msg(lrdo_UPPGBREADFAIL4, rc); return (DTREE_READERROR1); } } if ((ld->log.redopage.type & (LOG_BTROOT | LOG_DTREE)) == (LOG_BTROOT | LOG_DTREE)) { /* * If more than one slot in a segment, we apply * slots one at a time. * for BTROOT (either xtree or dtree), off * starts from di_btroot, not from the * beginning of inode, not from beginning of * page. Slot number is zero origin. * di_btroot starts from slot #8 for dtroot. * * First let buf_ptr points to the beginning * of off */ buf_btroot = (caddr_t) buf + size_dinode * inonum + (7 << l2linesize); buf_ptr = buf_btroot + (off << l2linesize); for (i = 0; i < ln; i++) { mask_9 = UZBIT_16 >> (7 + (off & 0x000f)); if (!(mask_9 & dtroot_9)) { memcpy((caddr_t) buf_ptr, data, linesize); dtroot_9 |= mask_9; } buf_ptr += linesize; data += linesize; /* off incremented for next slot if * ln > 1. In the dtroot case, ln will * never > 9 */ off++; } db->db_dtroot[inonum] = dtroot_9; } else if ((ld->log.redopage.type & LOG_DTREE) == LOG_DTREE) { /* update bits of words in dtpage_word[]. * starting from "off" and cover a range of * "ln". Each word tracks 32 slots. The first * and last words may only have a subset of * their bits updated. */ /* start word in dtpage_word[]. */ s_index = off >> L2DTPGWORD; dtpg_32 = db->db_dtpagewd[s_index]; for (nslots = ln; nslots > 0; nslots -= nbits, off += nbits) { /* determine the start bit number * within the word and the number of * bits to be updated within the word */ wbitno = off & (DTPGWORD - 1); nbits = MIN(nslots, DTPGWORD - wbitno); for (i = 0, k = wbitno; i < nbits; i++, k++) { mask_32 = UZBIT_32 >> k; if (!(mask_32 & dtpg_32)) { buf_ptr = (caddr_t) buf + (off << l2linesize) + (i << l2linesize); memcpy((caddr_t) buf_ptr, data, linesize); dtpg_32 |= mask_32; } data += linesize; } db->db_dtpagewd[s_index] = dtpg_32; dtpg_32 = db->db_dtpagewd[++s_index]; } db->db_dtpagewd[s_index] = dtpg_32; } else if ((ld->log.redopage.type & LOG_DATA) == LOG_DATA) { /* update bits of words in data_word[]. * starting from "off" and cover a range of * "ln". Each word tracks 32 slots. The first * and last words may only have a subset of * their bits updated. */ /* start word in data_word[]. */ s_index = off >> L2DATAPGWORD; datapg_32 = db->db_datawd[s_index]; for (nslots = ln; nslots > 0; nslots -= nbits, off += nbits) { /* determine the start bit number * within the word and the number of * bits to be updated within the word */ wbitno = off & (DATAPGWORD - 1); nbits = MIN(nslots, DATAPGWORD - wbitno); for (i = 0, k = wbitno; i < nbits; i++, k++) { mask_32 = UZBIT_32 >> k; if (!(mask_32 & datapg_32)) { buf_ptr = (caddr_t) buf + (off << l2linesize) + (i << l2linesize); memcpy((caddr_t) buf_ptr, data, linesize); datapg_32 |= mask_32; } data += linesize; } db->db_datawd[s_index] = datapg_32; datapg_32 = db->db_datawd[++s_index]; } db->db_datawd[s_index] = datapg_32; } } } /* end of while ( j < ld->length ) */ /* for LOG_INODE, we need to process bmap because we need * to be absolutely certain that the inode extent is allocated. * * This log record may have several segments, each for a * different inode (base image), however, these inodes MUST * all reside in the same inode extent page to be included * in the same log record. Therefore, they MUST belong to the * same inode extent (4 pages, each 4096 bytes). Therefore, * it doesn't matter which segment we use to determine the * particulars about the extent. * */ if (ld->log.redopage.type & LOG_INODE) { /* * If at least 1 inode in the current log record is * marked as allocated, then we must be sure that * the inode extent containing it (them) is allocated * and properly hooked into the IAG. * * Since logredo processes log records LIFO and * processes the base image of any inode only once, * we are assured that the inode status is final * (for this logredo session). */ if (inoext_alloc) { /* * If it IS a fileset-owned inode extent * (and not an aggregate-owned inode extent) */ if (ld->log.redopage.inode == FILESYSTEM_I) { /* * figure out which IAG and which extent */ iag_num = INOTOIAG(__le32_to_cpu(dip->di_number)); imp = vopen[vol].fsimap_lst.imap_wsp[(iag_num + 1) ].imap_data; if (imp == NULL) { /* first touch to this IAG */ rc = iagGet(vol, iag_num); if (rc != 0) { return (rc); } imp = vopen[vol].fsimap_lst.imap_wsp[(iag_num + 1) ].imap_data; } /* end first touch to this IAG */ ino = __le32_to_cpu(dip->di_number) & (INOSPERIAG - 1); extno = ino >> L2INOSPEREXT; /* * make sure the IAG points to it correctly */ imp->inoext[extno] = dip->di_ixpxd; } /* end fileset owned */ /* * make sure the block map shows it allocated */ rc = markBmap((struct dmap *) vopen[vol].bmap_ctl, dip->di_ixpxd, 1, vol); if (rc) { fsck_send_msg(lrdo_UPPGMBMPFAIL, rc); return (rc); } } } /* * init freelist for a new dtroot */ if (ld->log.redopage.type == (LOG_DTREE | LOG_BTROOT | LOG_NEW)) { rc = dtrt_resetFreeList(vol, db, ld, buf_btroot); if (rc) { fsck_send_msg(lrdo_UPPGDTRTRFLFAIL, rc); return (rc); } } /* * init freelist for a new dtpage */ if (ld->log.redopage.type == (LOG_DTREE | LOG_NEW)) { rc = dtpg_resetFreeList(vol, buf); if (rc) { fsck_send_msg(lrdo_UPPGDTPGRFLFAIL, rc); return (rc); } } /* * make a note to rebuild freelist for an extended dtpage */ if (ld->log.redopage.type == (LOG_DTREE | LOG_EXTEND)) { rc = saveExtDtPg(vol, addressPXD(&(ld->log.redopage.pxd))); if (rc) { fsck_send_msg(lrdo_UPPGSEDPFAIL, rc); return (rc); } } return (0); } jfsutils-1.1.15.orig/libfs/logform.c0000644000000000000000000002023110577765666014226 0ustar /* * Copyright (C) International Business Machines Corp., 2000-2004 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * format log - called from mkfs or logredo */ #include #include #include #include #include #include #include #include "jfs_types.h" #include "jfs_endian.h" #include "devices.h" #include "jfs_logmgr.h" #include "message.h" /* * NAME: jfs_logform * FUNCTION: format file system log * * RETURN: 0 - successful * -1 - error occur * */ int jfs_logform(FILE *fp, /* this is a file descriptor * for an opened device to write log. */ int aggr_blk_size, /* aggregate block size in bytes */ int s_l2bsize, /* log2 of aggr block size in bytes */ uint s_flag, /* fs superblock s_flag is passed in */ int64_t log_start, /* offset of the start of inline log in * number of aggr blocks. For outline * log it is set as zero */ int log_len, /* inline log length in number of aggr * blks. For outline log, it is zero */ uuid_t uuid, /* extern log: uuid of log, if null * create new, else verify that * this device's uuid matches */ char *label) { /* volume label for external log, none if NULL */ int64_t log_len_in_bytes; int npages, rc, k; char logpages[4 * LOGPSIZE]; struct logpage *logp; /* array of 4 log pages */ static struct logsuper *log_sup; struct lrd *lrd_ptr; int64_t log_begin; /* the location of the beginning of the log * inside of the file system. ( in bytes ) */ int64_t log_contwt; int16_t inlinelog = (s_flag & JFS_INLINELOG); int Working_counter; char *Working[5]; log_sup = calloc(1, LOGPSIZE); if (log_sup == NULL) { printf("logform: calloc failed!\n"); return -1; } /* find the log superblock location */ log_begin = log_start << s_l2bsize; #define LOGBUFSIZE 4 * LOGPSIZE logp = (struct logpage *) &logpages; Working[0] = " |\r"; Working[1] = " /\r"; Working[2] = " -\r"; Working[3] = " \\\r"; if (inlinelog) { log_len_in_bytes = ((int64_t) log_len) << s_l2bsize; npages = log_len_in_bytes / LOGPSIZE; } else { if (ujfs_get_dev_size(fp, &log_len_in_bytes)) return -1; #define MAX_LOG_SIZE 128*1048576 /* 128 MB */ if (log_len_in_bytes > MAX_LOG_SIZE) { printf("External journal size is excessive.\n" "Working size set to 128 MB.\n"); log_len_in_bytes = MAX_LOG_SIZE; } npages = log_len_in_bytes / LOGPSIZE; if (uuid_is_null(uuid)) /* NULL uuid indicates format new log */ uuid_generate(uuid); else { /* Verify existing uuid matches uuid passed in */ rc = ujfs_rw_diskblocks(fp, (log_begin + LOGPSIZE), (unsigned) LOGPSIZE, (char *) log_sup, GET); if (rc) return -1; ujfs_swap_logsuper(log_sup); if (!uuid_compare(log_sup->uuid, uuid)) { printf("Invalid log device\n"); return -1; } } } /* npages must be an even multiple of 4 since we write pages 4 at * a time. */ npages &= ~3; /* * init log superblock: log page 1 */ log_sup->magic = LOGMAGIC; log_sup->version = LOGVERSION; log_sup->state = LOGREDONE; /* Assign fs s_flag to log superblock. * Currently s_flag carries the inlinelog info and commit option * ( i.e. group commit or lazy commit, etc.. ) */ log_sup->flag = s_flag; log_sup->size = npages; log_sup->bsize = aggr_blk_size; log_sup->l2bsize = s_l2bsize; log_sup->end = 2 * LOGPSIZE + LOGPHDRSIZE + LOGRDSIZE; if (uuid) uuid_copy(log_sup->uuid, uuid); else uuid_clear(log_sup->uuid); /* Inline log */ if (label) { strncpy((char *) &log_sup->label, label, sizeof (log_sup->label)); } for (k = 0; k < MAX_ACTIVE; k++) uuid_clear(log_sup->active[k]); /* swap if on big endian machine */ ujfs_swap_logsuper(log_sup); rc = ujfs_rw_diskblocks(fp, (log_begin + LOGPSIZE), (unsigned) LOGPSIZE, (char *) log_sup, PUT); if (rc != 0) return -1; /* * init device pages 2 to npages-1 as log data pages: * * log page sequence number (lpsn) initialization: * the N (= npages-2) data pages of the log is maintained as * a circular file for the log records; * lpsn grows by 1 monotonically as each log page is written * to the circular file of the log; * Since the AIX DUMMY log record is dropped for this XJFS, * and setLogpage() will not reset the page number even if * the eor is equal to LOGPHDRSIZE. In order for binary search * still work in find log end process, we have to simulate the * log wrap situation at the log format time. * The 1st log page written will have the highest lpsn. Then * the succeeding log pages will have ascending order of * the lspn starting from 0, ... (N-2) */ /* initialize 1st 2 log pages to be written: lpsn = N-1, 0 and also a SYNCPT log record is written to the N-1 page Since the log is always an even number of meg, if we write 2 pages before entering the loop, we are assured that the log will end after a 4 page buffer. */ logp[0].h.eor = logp[0].t.eor = LOGPHDRSIZE + LOGRDSIZE; logp[0].h.page = logp[0].t.page = npages - 3; lrd_ptr = (struct lrd *) &logp[0].data; lrd_ptr->logtid = 0; lrd_ptr->backchain = 0; /* swap log page data here if needed */ lrd_ptr->type = __le16_to_cpu(LOG_SYNCPT); lrd_ptr->length = 0; lrd_ptr->log.syncpt.sync = 0; logp[1].h.eor = logp[1].t.eor = LOGPHDRSIZE; logp[1].h.page = logp[1].t.page = 0; lrd_ptr = (struct lrd *) &logp[1].data; lrd_ptr->logtid = 0; lrd_ptr->backchain = 0; /* swap log page data here if needed */ lrd_ptr->type = __le16_to_cpu(LOG_SYNCPT); lrd_ptr->length = 0; lrd_ptr->log.syncpt.sync = 0; /* swap if on big endian machine */ ujfs_swap_logpage(logp, 2); rc = ujfs_rw_diskblocks(fp, (log_begin + 2 * LOGPSIZE), (unsigned) 2 * LOGPSIZE, (char *) &(logp[0]), PUT); ujfs_swap_logpage(logp, 2); /* Swap back */ if (rc != 0) return -1; /* initialize buffer to write 4 pages at a time */ logp[0].h.eor = logp[0].t.eor = LOGPHDRSIZE; logp[2].h.eor = logp[2].t.eor = LOGPHDRSIZE; lrd_ptr = (struct lrd *) &logp[2].data; lrd_ptr->logtid = 0; lrd_ptr->backchain = 0; /* swap log page data here if needed */ lrd_ptr->type = __le16_to_cpu(LOG_SYNCPT); lrd_ptr->length = 0; lrd_ptr->log.syncpt.sync = 0; logp[3].h.eor = logp[3].t.eor = LOGPHDRSIZE; lrd_ptr = (struct lrd *) &logp[3].data; lrd_ptr->logtid = 0; lrd_ptr->backchain = 0; /* swap log page data here if needed */ lrd_ptr->type = __le16_to_cpu(LOG_SYNCPT); lrd_ptr->length = 0; lrd_ptr->log.syncpt.sync = 0; /* initialize succeeding log pages: lpsn = 1, 2, ..., (N-2) */ Working_counter = 0; log_contwt = log_begin + LOGBUFSIZE; for (k = 1; k < npages - 4; k += 4) { logp[0].h.page = logp[0].t.page = k; logp[1].h.page = logp[1].t.page = k + 1; logp[2].h.page = logp[2].t.page = k + 2; logp[3].h.page = logp[3].t.page = k + 3; /* swap if on big endian machine */ ujfs_swap_logpage(logp, 4); rc = ujfs_rw_diskblocks(fp, log_contwt, (unsigned) LOGBUFSIZE, (char *) &(logp[0]), PUT); if (rc != 0) return -1; log_contwt += LOGBUFSIZE; /* display heartbeat, but only if output not redirected */ if (isatty(STDOUT_FILENO)) { Working_counter++; switch (Working_counter) { case (100): printf("%s", Working[0]); fflush(stdout); break; case (200): printf("%s", Working[1]); fflush(stdout); break; case (300): printf("%s", Working[2]); fflush(stdout); break; case (400): printf("%s", Working[3]); fflush(stdout); Working_counter = 0; break; default: break; } } } ujfs_flush_dev(fp); return (0); } jfsutils-1.1.15.orig/libfs/logform.h0000644000000000000000000000166510340701413014205 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef H_LOGFORM #define H_LOGFORM int jfs_logform(FILE *, int, int, uint, int64_t, int, uuid_t, char *); #endif /* H_LORFORM */ jfsutils-1.1.15.orig/libfs/logredo.c0000644000000000000000000015074510340701413014172 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include #include "jfs_types.h" #include "jfs_endian.h" #include "jfs_filsys.h" #include "jfs_superblock.h" #include "jfs_dinode.h" #include "jfs_dtree.h" #include "jfs_xtree.h" #include "jfs_logmgr.h" #include "jfs_dmap.h" #include "jfs_imap.h" #include "logredo.h" #include "logform.h" #include "devices.h" #include "debug.h" #include "utilsubs.h" #include "fsck_message.h" /* for chkdsk message logging facility */ /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * L O C A L M A C R O D E F I N I T I O N S * */ #define MAKEDEV(__x,__y) (dev_t)(((__x)<<16) | (__y)) #define LOGPNTOB(x) ((x)< 1 )\ {\ L2NUM++;\ (NUM) >>= 1;\ }\ }\ } /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * R E M E M B E R M E M O R Y A L L O C F A I L U R E * */ int32_t Insuff_memory_for_maps = 0; char *available_stg_addr = NULL; int32_t available_stg_bytes = 0; char *bmap_stg_addr = NULL; int32_t bmap_stg_bytes = 0; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * S T U F F F O R T H E L O G * */ struct logsuper logsup; /* log super block */ int32_t numdoblk; /* number of do blocks used */ int32_t numnodofile; /* number of nodo file blocks used */ int32_t numExtDtPg = 0; /* number of extended dtpage blocks used */ /* * open file system aggregate/lv array * * logredo() processes a single log. * * In the first release, logredo will process a single log which relates * to the single fileset in a single aggregate. In some future release, * a single log may be used for multiple filesets which may or may not all * reside in the same aggregate. * */ struct vopen vopen[MAX_ACTIVE]; struct log_info Log; struct { uuid_t uuid; FILE *fp; } primary_vol; extern int LogOpenMode; /* logdump sets this to O_RDONLY */ /* * if this flag is set then the primary superblock is * corrupt. The secondary superblock is good, but chkdsk * wasn't able to fix the primary version. logredo can * run, but must use the secondary version of the * aggregate superblock */ int32_t use_2ndary_agg_superblock; /* * file system page buffer cache * * for k > 0, bufhdr[k] describes contents of buffer[k-1]. * bufhdr[0] is reserved as anchor for free/lru list: * bufhdr[0].next points to the MRU buffer (head), * bufhdr[0].prev points to the LRU buffer (tail); */ /* buffer header table */ struct bufhdr { int16_t next; /* 2: next on free/lru list */ int16_t prev; /* 2: previous on free/lru list */ int16_t hnext; /* 2: next on hash chain */ int16_t hprev; /* 2: previous on hash chain */ char modify; /* 1: buffer was modified */ char inuse; /* 1: buffer on hash chain */ int16_t reserve; /* 2 */ int32_t vol; /* 4: minor of agrregate/lv number */ pxd_t pxd; /* 8: on-disk page pxd */ } bufhdr[NBUFPOOL]; /* (24) */ /* buffer table */ struct bufpool { char bytes[PSIZE]; } buffer[NBUFPOOL - 1]; /* * log page buffer cache * * log has its own 4 page buffer pool. */ uint8_t afterdata[LOGPSIZE * 2]; /* buffer to read in redopage data */ /* * Miscellaneous */ caddr_t prog; /* Program name */ int32_t mntcnt, bufsize; char *mntinfo; int32_t retcode; /* return code from logredo */ int end_of_transaction = 0; /* * external references */ extern char *optarg; extern int optind; extern int initMaps(int32_t); extern int updateMaps(int); extern int findEndOfLog(void); extern int logRead(int32_t, struct lrd *, char *); extern int logredoInit(void); extern int doCommit(struct lrd *); extern int doExtDtPg(void); extern int doNoRedoFile(struct lrd *, uint32_t); extern int doNoRedoPage(struct lrd *); extern int doNoRedoInoExt(struct lrd *); extern int doAfter(struct lrd *, int32_t); extern int doUpdateMap(struct lrd *); extern int alloc_wrksp(uint32_t, int, int, void **); extern FILE * open_by_label(uuid_t, int, int, char *, int *); extern char log_device[]; /* * forward references */ int doMount(struct lrd *); int openVol(int32_t); int updateSuper(int vol); int rdwrSuper(FILE *, struct superblock *, int32_t); int bflush(int32_t, struct bufpool *); int logOpen(void); int fsError(int, int, int64_t); int logError(int, int); static int recoverExtendFS(FILE *); int alloc_storage(int32_t, void **, int32_t *); int alloc_dmap_bitrec(struct dmap_bitmaps **); /* * debug control */ #ifdef _JFS_DEBUG int32_t dflag = 1; time_t *Tp; uint32_t tp_start, tp_end; int xdump(char *, int); int x_scmp(char *, char *); void x_scpy(char *, char *); int prtdesc(struct lrd *); #else int32_t dflag = 0; #endif /* * NAME: jfs_logredo() * * FUNCTION: Replay all transactions committed since the most * recent synch point. * * NOTES: * >>>>>> The log replay is accomplished in one pass over the * log, reading backwards from logend to the first synch * point record encountered. This means that the log * entries are read and processed in LIFO (Last-In-First-Out) * order. In other words, the records logged latest in * time are the first records processed during log replay. * * >>>>>> Inodes, index trees, and directory trees * * Inodes, index tree structures, and directory tree * structures are handled by processing committed redopage * records which have not been superceded by noredo records. * This processing copies data from the log record into the * appropriate disk extent page(s). * * To ensure that only the last (in time) updates to any * given disk page are applied during log replay, logredo * maintains a record (union structure summary1/summary2), * for each disk page which it has processed, of which * portions have been updated by log records encountered. * * >>>>>> Inode Allocation Map processing * The xtree for the Inode Allocation Map is journaled, and * a careful write is used to update it during commit * processing. * The imap index tree is also duplicated at the known location. (TBD) * So at logredo time, the xtree for imap is always readable and correct. * This is the basic requirement from logredo. * * the inode map control page (struct dinomap) is only flushed to disk at * the umount time. For iag, pmap will go to disk at commit time. * iagnum will not change in run-time. * agstart field will stable without extendfs utility. It is TBD for * how to handle agstart when extendfs utility is available. * Other fields ( wmap. inosmap, extsmap ino free list pointers, * ino ext free list pointers ) are at working status ( i.e they are * updated in run-time. So the following * meta-data of the imap need to be reconstructed at the logredo time: * 1) IAGs, the pmap of imap and inoext array are contained in IAGs. * 2) AG Free inode list * 3) AG Free Inode Extent list * 4) IAG Free list * * There are two imaps need to take care of : * 1) aggregate imap * 2) fileset imap * For the first release, the aggregate imap is stable and we only * need to deal with the fileset imap. * * Block Allocation Map (bmap file) is for an aggregate/lv. There are * three fields related to the size of bmap file. * 1) superblock.s_size: This field indicates aggregate size. It * tells number of sector-size blocks for this * aggregate. The size of aggregate determines * the size of its bmap file. * Since the aggregate's superblock is updated * using sync-write, superblock.s_size is trustable * at logredo time. * note1: mkfs reserves the fsck space. So s_size really * inidcate (size_of_aggregate - fsck_reserve_space) * note2: At the mkfs time, "-s" parameter could be used * to indicate how large the aggregate/filesystem is. * One lv contains at most one aggregate/filesystem. * If "-s" gives the value is smaller than the size * of lv, it is ok. The space is just wasted. * * Without "-s" parameter, mkfs wil use the whole * size of lv to make an aggregate/filesystem. * That is usually the case. So we can also say * an aggregate/lv. "-s" is often used for test. * * 2) dbmap.dn_mapsize: This field also indicates aggregate/lv size. * It tells number of aggre. blocks in the * aggregate/lv. Without extendfs, this field should * be equivalent to superblock.s_size. * With extendfs, this field may not be updated * before a system crash happens. So logredo * need to update it. * 3) dinode.di_size: For an inode of bmap file, this field indicates * the logical size of the file. I.e. it contains * the offset value of the last byte written * in the file plus one. * So di_size will include the bmap control page, * the dmap control pages and dmap pages. * In the JFS, if a file is a sparse file, the logical * size is different from its physical size. * The bmap file is a sparse file if the total of * dmap pages is ( < 1024) or ( < 1024 * 1024). * In that case, physically L1.0, and/or L2 does * not exist, but di_size will include their page * size. * * Note: The di_size does NOT contain the logical * structure of the file, i.e. the space allocated * for the xtree stuff is not indicated in di_size. * It is indicated in di_nblocks. * * In addition, the mkfs always put one more dmap * page into the bmap file for preparing extendfs. * This hidden dmap page cannot be figured out from * superblock.s_size, but di_size includes it. Any * dmapctl pages caused by this hidden dmap page * are also included in di_size. * * The bmap control page, dmap control pages and dmap pages are all * needed to rebuild at logredo time. * * In overall, the following actions are taken at logredo time: * 1) apply log rec data to the specified page. * 2) initialize freelist for dtree page or root. * 3) rebuilt imap * 4) rebuilt bmap * in addition, in order to ensure the log record only applying to a * certain portion of page one time, logredo will start NoRedoFile, * NoRedoExtent/NoRedoPage filter in the process for accuracy and * efficiency. * * The three log rec types: REDOPAGE, NOREDOPAGE, NOREDOINOEXT, and * UPDATEMAP, are the main force to initiate these actions. See * comments on doAfter(), updatePage(), doNoRedoPage(), doNoRedoInoExt, * and doUpdateMap() for detailed information. * * If the aggregate/lv has state of FM_DIRTY, then fsck will run * after the logredo process since logredo could not get 100% * recovery. Currently bmap rebuild is slow ( 1 min per 32 GB), * so logredo will NOT rebuild imap and bmap if fsck will do it * anyway. But logredo still read maps in and mark them for starting * NoRedoExtent/NoRedoPage filter. * * The maps are rebuilt in the following way: * at the init phase, storage is allocated for the whole map file for * both imap and bmap. Reading in the map files from the disk. * The wmap is inited to zero. At the logredo time, the wmap is used * to track the bits in pmap. In the beginning of the logredo process * the allocation status of every block is in doubt. As log records * are processed, the allocation state is determined and the bit of pmap * is updated. This fact is recorded in the corresponding bits in wmap. * So a pmap bit is only updated once at logredo time and only updated * by the latest in time log record. * At the end of logredo, the control information, the freelist, etc. * are built from the value of pmap; then pmap is copied to wmap and * the whole map is written back to disk. * * the status field s_state in the superblock of each file-system is * set to FM_CLEAN provided the initial status was either FM_CLEAN * or FM_MOUNT and logredo processing was successful. If an error * is detected in logredo the status is set to FM_LOGREDO. the status * is not changed if its initial value was FM_MDIRTY. fsck should be * run to clean-up the probable damage if the status after logredo * is either FM_LOGREDO or FM_MDIRTY. * * The log record has the format: * * At logredo time, the log is read backward. So for every log rec, * we read LogRecLRD, which tells how long the LogRecordData is. * see comments on updatePage() for detailed info of log record format. * *..................................................................... * The logredo handles the log-within-file-system (aka inline log) issue: *..................................................................... * For AIX, we always deal with the outline log, i.e. the log resides * in a separate logical volume. A log is associated with one volume * group and can be shared by many file systems with this volume group. * In AIX, the logredo received a device name. It then determines if * this device is a log name or a filesystem name. If it is a filesustem * name, get the log minor number for this filesystem. If it is a log name, * get its minor number. * * XJFS decided to put log inside the file system * * For supporting the inline log, the above AIX logic should be changed. * * Here is the outline: * * When the logredo received a device name, it first read the SIZE_OF_SUPER * bytes from SUPER1_OFF offset to see if it is a file system superblock. * If yes, check the s_flag to see if it has a inline log or outline log. * for an inline log the s_logdev should match the input device name's * major and minor number. If not, an error is returned and logredo exit. * If no error, the logredo read the log superblock according the log info * in the fs superblock. * If the device name does not represent a filesystem device, then logredo * read the LOGPSIZE bytes from the log page 1 location. If it indicates * a log device, then open the filesystems according to the log superblock's * active list. For each filesystem in the active list, read its superblock * if one of the superblock indicates that it uses an inline log, return * an error. It is a system code bug if some filesystems use inline log * and some use outline log. * If the superblock indicates it used an outline log, check the superblock's * s_logdev to match the input device name's major and minor numbers. * If one of them does not match, return error. -- It is a system code bug, * if some match and some not match; -- It should either match all or non of * them match. The AIX logredo never check s_logdev with the input log device. * We should check here. * * for outline log, logredo will be called once to cover all the file * systems in the log superblock's active list. * For inline log, logredo will be called many times. Each time is for * one file system. The log superblock's active list has nothing. The * logmajor and logminor contains file system's major and minor number. * *..................................................................... * logredo handles support EA: *..................................................................... * There is 16-byte EA descriptor which is located in the section I of * dinode. * The EA can be inline or outline. If it is inlineEA then the data will * occupy the section IV of the dinode. The dxd_t.flag will indicate so. * If it is outlineEA, dxd_t.flag will indicate so and the single extent * is described by EA descriptor. * * The section IV of dinode has 128 byte. It is shared by the xtroot and * inlineEA. The sharing is in FCFS style. If xtree gets the section IV, * xtree will never give it away even if xtree is shrink or split. * If inlineEA gets it, there is a chance that later inlineEA is freed and * so xtree still can get it. * * for outlineEA, the XJFS will syncly write the data portion out so there * is no log rec for the data, but there is still an INODE log rec for EA * descriptor changes and there is a UPDATEMAP log rec for the allocated * pxd. If an outlineEA is freed, there are also two log records for it: * one is INODE with EA descriptor zeroed out, another is the UPDATEMAP * log rec for the freed pxd. * For inlineEA, it has to be recorded in the log rec. It is not in a * separate log rec. Just one additional segment is added into the * INODE log rec. So an INODE log rec can have at most three segments: * when the parent and child inodes are in the same page, then there are * one segment for parent base inode; one segment for child base inode; * and maybe the third one for the child inlineEA data. *.................................................................... * 32-bit vs 64-bit * At the first release. assume that a file system will not be larger * than 32-bit. *.................................................................... * TBD: * the method for handling crashes in the middle of extending a file * system is as follows. the size of a filesystem is established from * the superblock.s_size field (i.e the sizes in the diskmap * and inodemaps are ignored). in extendfs (jfs_cntl.c) the superblock * is not updated before the maps have been extended and the new inodes * formatted to zeros. no allocations in the new part of the filesystem * occur prior to the change in map sizes. if a crash occurs just * before updating the superblock, the map sizes will be their old * values. in this case the maps as files may be bigger than necessary. * if the crash occurs just after writing the super block, the map sizes * are fixed up here. */ int jfs_logredo(caddr_t pathname, FILE *fp, int32_t use_2nd_aggSuper) { int rc; int k, logaddr, nextaddr, lastaddr, nlogrecords; int syncrecord = 0; struct lrd ld; int lowest_lr_byte = 2 * LOGPSIZE + LOGPHDRSIZE; int highest_lr_byte = 0; int log_has_wrapped = 0; int logend; int in_use; /* * store away the indicator of which aggregate superblock * to use */ use_2ndary_agg_superblock = use_2nd_aggSuper; /* * loop until we get enough memory to read vmount struct */ mntinfo = (char *) &bufsize; bufsize = sizeof (int); /* * validate that the log is not currently in use; */ rc = findLog(fp, &in_use); if (rc < 0) { fsck_send_msg(lrdo_DEVOPNREADERROR); return (rc); } /* recover from extendfs() ? */ if (Log.location & INLINELOG && (vopen[0].status & FM_EXTENDFS)) { fsck_send_msg(lrdo_REXTNDBEGIN); rc = recoverExtendFS(fp); fsck_send_msg(lrdo_REXTNDDONE); return rc; } /* * validate log superblock * * aggregate block size is for log file as well. */ rc = ujfs_rw_diskblocks(Log.fp, (uint64_t) (Log.xaddr + LOGPNTOB(LOGSUPER_B)), (unsigned) sizeof (struct logsuper), (char *) &logsup, GET); if (rc != 0) { fsck_send_msg(lrdo_CANTREADLOGSUP); rc = LOGSUPER_READ_ERROR; goto error_out; } ujfs_swap_logsuper(&logsup); if (logsup.magic != LOGMAGIC) { fsck_send_msg(lrdo_LOGSUPBADMGC); rc = NOT_LOG_FILE_ERROR; goto error_out; } if (logsup.version > LOGVERSION) { fsck_send_msg(lrdo_LOGSUPBADVER); rc = JFS_VERSION_ERROR; goto error_out; } if (Log.location & OUTLINELOG) { struct stat st; if ((rc = fstat(fileno(Log.fp), &st))) goto error_out; Log.devnum = st.st_rdev; if (in_use) { fsck_send_msg(lrdo_LOGINUSE); return LOG_IN_USE; } } if (logsup.state == LOGREDONE) { fsck_send_msg(lrdo_ALREADYREDONE); if (Log.location & INLINELOG) if ((rc = updateSuper(0)) != 0) { fsck_send_msg(lrdo_CANTUPDLOGSUP); return (rc); } return (0); } Log.size = logsup.size; Log.serial = logsup.serial; /* * find the end of log */ logend = findEndOfLog(); if (logend < 0) { fsck_send_msg(lrdo_LOGEND, logend); fsck_send_msg(lrdo_LOGENDBAD1); logError(LOGEND, 0); ujfs_swap_logsuper(&logsup); rc = ujfs_rw_diskblocks(Log.fp, (Log.xaddr + LOGPNTOB(LOGSUPER_B)), (unsigned long) LOGPSIZE, (char *) &logsup, PUT); rc = logend; goto error_out; } /* * allocate/initialize logredo runtime data structures and * initialize each file system associated with the log based on * the contents of its superblock */ if ((rc = logredoInit()) != 0) { fsck_send_msg(lrdo_INITFAILED, rc, errno); goto error_out; } highest_lr_byte = logsup.size * LOGPSIZE - LOGRDSIZE; if ((logend < lowest_lr_byte) || (logend > highest_lr_byte)) { fsck_send_msg(lrdo_LOGEND, logend); fsck_send_msg(lrdo_LOGENDBAD2); rc = INVALID_LOGEND; goto error_out; } /* * replay log * * read log backwards and process records as we go. * reading stops at place specified by first SYNCPT we * encounter. */ nlogrecords = lastaddr = 0; nextaddr = logend; do { logaddr = nextaddr; nextaddr = logRead(logaddr, &ld, afterdata); DBG_TRACE(("Logaddr=%x\nNextaddr=%x\n", logaddr, nextaddr)) nlogrecords += 1; /* * * Validate the nextaddr as much as possible * */ if (nextaddr < 0) { fsck_send_msg(lrdo_NEXTADDRINVALID); rc = nextaddr; goto error_out; } if ((nextaddr < lowest_lr_byte) || (nextaddr > highest_lr_byte)) { fsck_send_msg(lrdo_NEXTADDROUTRANGE, nextaddr); rc = INVALID_NEXTADDR; goto error_out; } if (nextaddr == logaddr) { fsck_send_msg(lrdo_NEXTADDRSAME, nextaddr); rc = NEXTADDR_SAME; goto error_out; } if (nextaddr > logaddr) { if (log_has_wrapped) { fsck_send_msg(lrdo_LOGWRAPPED); rc = LOG_WRAPPED_TWICE; goto error_out; } else { log_has_wrapped = -1; } } /* * * The addresses seem ok. Process the current record. * */ switch (ld.type) { case LOG_COMMIT: rc = doCommit(&ld); if (rc) { fsck_send_msg(lrdo_BADCOMMIT, logaddr); goto error_out; } break; case LOG_MOUNT: fsck_send_msg(lrdo_MOUNTRECORD, logaddr); rc = doMount(&ld); if (rc) { fsck_send_msg(lrdo_BADMOUNT, logaddr); goto error_out; } break; case LOG_SYNCPT: fsck_send_msg(lrdo_SYNCRECORD, logaddr); rc = 0; if (lastaddr == 0) { syncrecord = logaddr; lastaddr = (ld.log.syncpt.sync == 0) ? logaddr : ld.log.syncpt.sync; } break; case LOG_REDOPAGE: DBG_TRACE(("jfs_logredo:Case Log_redoPage")) rc = doAfter(&ld, logaddr); if (rc) { fsck_send_msg(lrdo_BADREDOPAGE, logaddr); goto error_out; } break; case LOG_NOREDOPAGE: DBG_TRACE(("jfs_logredo:Case Log_noredopage")) rc = doNoRedoPage(&ld); if (rc) { fsck_send_msg(lrdo_BADNOREDOPAGE, logaddr); goto error_out; } break; case LOG_NOREDOINOEXT: DBG_TRACE(("jfs_logredo:Case Log_noredoinoext")) rc = doNoRedoInoExt(&ld); if (rc) { fsck_send_msg(lrdo_BADNOREDOINOEXT, logaddr); goto error_out; } break; case LOG_UPDATEMAP: rc = doUpdateMap(&ld); if (rc) { fsck_send_msg(lrdo_BADUPDATEMAP, logaddr); goto error_out; } break; default: fsck_send_msg(lrdo_UNKNOWNTYPE, logaddr); rc = UNRECOG_LOGRECTYP; goto error_out; break; } if (rc < 0) { fsck_send_msg(lrdo_ERRORNEEDREFORMAT); goto error_out; } if (rc != 0) { fsck_send_msg(lrdo_ERRORCANTCONTIN); goto error_out; } /* * If the transaction just completed was the last * for the current transaction, then flush the * buffers. */ if (end_of_transaction != 0) { for (k = 1; k < NBUFPOOL; k++) { if ((rc = bflush(k, &buffer[k - 1])) != 0) goto error_out; } end_of_transaction = 0; } } while (logaddr != lastaddr); /* * If any 'dtpage extend' records were processed, then we need * to go back and rebuild their freelists. This cannot be done * when the 'dtpage extend' record is processed, since there may * be records processed later which affect the previous (shorter) * version of the dtpage. Only after all these records are processed * can we safely and accurately rebuild the freelist. */ if (numExtDtPg != 0) { rc = doExtDtPg(); } /* * flush data page buffer cache */ for (k = 1; k < NBUFPOOL; k++) { if ((rc = bflush(k, &buffer[k - 1])) != 0) break; } /* * finalize file systems * * update allocation map and superblock of file systems * of volumes which are open if they were modified here. * i.e. if they were not previously unmounted cleanly. */ for (k = 0; k < MAX_ACTIVE; k++) { if (vopen[k].state != VOPEN_OPEN) continue; if ((rc = updateMaps(k)) != 0) { fsck_send_msg(lrdo_ERRORCANTUPDMAPS); goto error_out; } /* Make sure all changes are committed to disk before we * mark the superblock clean */ ujfs_flush_dev(vopen[k].fp); if ((rc = updateSuper(k)) != 0) { fsck_send_msg(lrdo_ERRORCANTUPDFSSUPER); goto error_out; } /* sync superblock before journal is finalized */ ujfs_flush_dev(vopen[k].fp); } /* * finalize log. * * clear active list. * If this is a fully replayed log then it can be moved to earlier * versions of the operating system. Therefore switch the magic * number to the earliest level. */ if (logsup.state != LOGREADERR) { for (k = 0; k < MAX_ACTIVE; k++) uuid_clear(logsup.active[k]); logsup.end = logend; logsup.state = LOGREDONE; logsup.magic = LOGMAGIC; } ujfs_swap_logsuper(&logsup); rc = ujfs_rw_diskblocks(Log.fp, (Log.xaddr + LOGPNTOB(LOGSUPER_B)), LOGPSIZE, (char *) &logsup, PUT); /* * now log some info for the curious */ fsck_send_msg(lrdo_LOGEND, logend); fsck_send_msg(lrdo_RPTSYNCNUM, syncrecord); fsck_send_msg(lrdo_RPTSYNCADDR, lastaddr); fsck_send_msg(lrdo_RPTNUMLOGREC, nlogrecords); fsck_send_msg(lrdo_RPTNUMDOBLK, numdoblk); fsck_send_msg(lrdo_RPTNUMNODOBLK, numnodofile); error_out: if (rc > 0) { rc = rc * (-1); } /* * If everything went ok except that we didn't have * enough memory to deal with the block map, tell chkdsk * to be sure to do a full check and repair, but that a log * format is not necessary */ if ((rc == 0) && Insuff_memory_for_maps) { rc = ENOMEM25; } return (rc); } /* * NAME: doMount(ld) * * FUNCTION: a log mount record is the first-in-time record which is * put in the log so it is the last we want to process in * logredo. so we mark volume as cleanly unmounted in vopen * array. the mount record is imperative when the volume * is a newly made filesystem. */ int doMount(struct lrd *ld) { /* pointer to record descriptor */ int vol, status; vol = ld->aggregate; status = vopen[vol].status; DBG_TRACE(("Logredo:domount: status=%d\n", status)) if (!(status & (FM_LOGREDO | FM_DIRTY))) vopen[vol].status = FM_CLEAN; return (0); } /* * NAME: openVol(vol) * * FUNCTION: open the aggregate/volume specified. * check if it was cleanly unmounted. also check log * serial number. initialize disk and inode mpas. */ int openVol(int vol) { /* device minor number of aggregate/lv */ int rc, l2agsize, agsize; int64_t fssize; /* number of aggr blks in the aggregate/lv */ struct superblock sb; int aggsb_numpages; if (Log.location & OUTLINELOG) { /* First check if this is the already opened volume */ if (!uuid_compare(vopen[vol].uuid, primary_vol.uuid)) vopen[vol].fp = primary_vol.fp; else { vopen[vol].fp = open_by_label(vopen[vol].uuid, 0, 0, NULL, NULL); if (vopen[vol].fp == NULL) return ENOENT; } } /* read superblock of the aggregate/volume */ if ((rc = rdwrSuper(vopen[vol].fp, &sb, PB_READ)) != 0) { fsck_send_msg(lrdo_CANTREADFSSUPER); fsError(READERR, vol, SUPER1_B); vopen[vol].state = VOPEN_CLOSED; return (FSSUPER_READERROR1); } /* check magic number and initialize version specific * values in the vopen struct for this vol. */ if (strncmp(sb.s_magic, JFS_MAGIC, (unsigned) strlen(JFS_MAGIC))) { fsck_send_msg(lrdo_FSSUPERBADMAGIC); vopen[vol].state = VOPEN_CLOSED; return (LOGSUPER_BADMAGIC); } if (sb.s_version > JFS_VERSION) { fsck_send_msg(lrdo_FSSUPERBADMAGIC); vopen[vol].state = VOPEN_CLOSED; return (LOGSUPER_BADVERSION); } if (Log.location & OUTLINELOG && (sb.s_flag & (JFS_INLINELOG == JFS_INLINELOG))) { fsck_send_msg(lrdo_FSSUPERBADLOGLOC); vopen[vol].state = VOPEN_CLOSED; return (LOGSUPER_BADLOGLOC); } vopen[vol].lblksize = sb.s_bsize; vopen[vol].l2bsize = sb.s_l2bsize; vopen[vol].l2bfactor = sb.s_l2bfactor; fssize = sb.s_size >> sb.s_l2bfactor; vopen[vol].fssize = fssize; vopen[vol].agsize = sb.s_agsize; /* LOG2NUM will alter agsize, so use local var (Then why don't we fix LOG2NUM?) */ agsize = vopen[vol].agsize; LOG2NUM(agsize, l2agsize); vopen[vol].numag = fssize >> l2agsize; if (fssize & (vopen[vol].agsize - 1)) vopen[vol].numag += 1; vopen[vol].l2agsize = l2agsize; if (Log.location & INLINELOG) { /* * Now that the aggregate superblock has been read, do some * more validation of the log superblock */ if (logsup.bsize != vopen[vol].lblksize) { fsck_send_msg(lrdo_LOGSUPBADBLKSZ); return JFS_BLKSIZE_ERROR; } if (logsup.l2bsize != vopen[vol].l2bsize) { fsck_send_msg(lrdo_LOGSUPBADL2BLKSZ); return JFS_L2BLKSIZE_ERROR; } aggsb_numpages = lengthPXD(&sb.s_logpxd) * logsup.bsize / LOGPSIZE; if (logsup.size != aggsb_numpages) { fsck_send_msg(lrdo_LOGSUPBADLOGSZ); return JFS_LOGSIZE_ERROR; } } /* *set lbperpage in vopen. */ vopen[vol].lbperpage = PSIZE >> vopen[vol].l2bsize; /* * was it cleanly umounted ? */ if (sb.s_state == FM_CLEAN) { vopen[vol].status = FM_CLEAN; vopen[vol].state = VOPEN_CLOSED; return (0); } /* * get status of volume */ vopen[vol].status = sb.s_state; vopen[vol].is_fsdirty = (sb.s_state & FM_DIRTY); /* *check log serial number */ if (sb.s_logserial != Log.serial) { fsck_send_msg(lrdo_FSSUPERBADLOGSER); vopen[vol].state = VOPEN_CLOSED; fsError(SERIALNO, vol, SUPER1_B); return (LOGSUPER_BADSERIAL); } /* initialize the disk and inode maps */ if ((rc = initMaps(vol)) != 0) { fsck_send_msg(lrdo_INITMAPSFAIL); fsError(MAPERR, vol, 0); return (rc); } vopen[vol].state = VOPEN_OPEN; return 0; } /* * NAME: updateSuper(vol) * * FUNCTION: updates primary aggregate/lv's superblock status and * writes it out. */ int updateSuper(int vol) { /* device minor number of aggregate/lv */ int rc, status; struct superblock sb; /* read in superblock of the volume */ if ((rc = rdwrSuper(vopen[vol].fp, &sb, PB_READ)) != 0) { fsck_send_msg(lrdo_READFSSUPERFAIL); return (FSSUPER_READERROR2); } /* mark superblock state. write it out */ status = vopen[vol].status; if (status & (FM_DIRTY | FM_LOGREDO)) sb.s_state = status & ~FM_EXTENDFS; else sb.s_state = FM_CLEAN; if ((rc = rdwrSuper(vopen[vol].fp, &sb, PB_UPDATE)) != 0) { fsck_send_msg(lrdo_WRITEFSSUPERFAIL); } return (rc); } /* * NAME: rdwrSuper(fp, sb, rwflag) * * FUNCTION: read or write the superblock for the file system described * by the file descriptor of the opened aggregate/lv. * for read, if a read of primary superblock is failed, * try to read the secondary superblock. report error only * when both reads failed. * for write, any write failure should be reported. */ int rdwrSuper(FILE *fp, struct superblock * sb, int32_t rwflag) { int rc; uint64_t super_offset; union { struct superblock super; char block[PSIZE]; } super; if (use_2ndary_agg_superblock) { super_offset = SUPER2_OFF; } else { super_offset = SUPER1_OFF; } /* * seek to the postion of the primary superblock. * since at this time we don't know the aggregate/lv * logical block size yet, we have to use the fixed * byte offset address super_offset to seek for. */ /* * read super block */ if (rwflag == PB_READ) { rc = ujfs_rw_diskblocks(fp, super_offset, (unsigned) SIZE_OF_SUPER, super.block, GET); if (rc != 0) { if (!use_2ndary_agg_superblock) { fsck_send_msg(lrdo_READFSPRIMSBFAIL); return (CANTREAD_PRIMFSSUPER); } else { fsck_send_msg(lrdo_READFS2NDSBFAIL); return (CANTREAD_2NDFSSUPER); } } *sb = super.super; ujfs_swap_superblock(sb); /* * write superblock */ } else { /* PB_UPDATE */ /* ? memset(super.block, 0, SIZE_OF_SUPER); */ super.super = *sb; ujfs_swap_superblock(&super.super); /* * write whichever superblock we're working with. * chkdsk will take care of replicating it. */ rc = ujfs_rw_diskblocks(fp, super_offset, (unsigned) SIZE_OF_SUPER, super.block, PUT); if (rc != 0) { if (!use_2ndary_agg_superblock) { fsck_send_msg(lrdo_WRITEFSPRIMSBFAIL); return (CANTWRITE_PRIMFSSUPER); } else { fsck_send_msg(lrdo_WRITEFS2NDSBFAIL); return (CANTWRITE_2NDFSSUPER); } } } return (0); } /* * NAME: bflush() * * FUNCTION: write out appropriate portion of buffer page if its modified. * Note that a dtree page may not be 4k, depending on the length * field specified in pxd. Write out only length that is needed. */ int bflush(int32_t k, /* The index in bufhdr that describes buf */ struct bufpool *buf) { /* pointer to buffer pool page */ FILE *fp = NULL; int rc; int32_t vol; int32_t nbytes; int64_t blkno; /* nothing to do ? */ if (bufhdr[k].modify == 0) return (0); /* write it out */ vol = bufhdr[k].vol; fp = vopen[vol].fp; blkno = addressPXD(&bufhdr[k].pxd); nbytes = lengthPXD(&bufhdr[k].pxd) << vopen[vol].l2bsize; rc = ujfs_rw_diskblocks(fp, (uint64_t) (blkno << vopen[vol].l2bsize), (unsigned) nbytes, (char *) buf, PUT); if (rc != 0) { fsck_send_msg(lrdo_BUFFLUSHFAIL); return (BFLUSH_WRITEERROR); } bufhdr[k].modify = 0; return (0); } /* * NAME: findLog() * * FUNCTION: open the device to see if it's a valid filesystem * or journal. If it is a filesystem, determine whether * the log is inline or external. If external, find * the log device. * */ int findLog(FILE *fp, int *in_use) { struct logsuper logsup; struct superblock sb; *in_use = 0; /* * try the LV as file system with in-line log */ if (rdwrSuper(fp, &sb, PB_READ)) { fsck_send_msg(lrdo_NOTAFSDEV); return NOT_FSDEV_ERROR; } /* * is the LV a file system ? */ if (memcmp(sb.s_magic, JFS_MAGIC, sizeof (sb.s_magic)) == 0) { /* * does file system contains its in-line log ? */ if ((sb.s_flag & JFS_INLINELOG) == JFS_INLINELOG) { Log.location = INLINELOG; Log.fp = fp; //Log.status = sb.s_state; Log.l2bsize = sb.s_l2bsize; Log.xaddr = addressPXD(&sb.s_logpxd) << sb.s_l2bsize; /* vopen[0] represents fs if inline log */ vopen[0].status = sb.s_state; vopen[0].fp = fp; return 0; } /* Save fp and uuid */ primary_vol.fp = fp; uuid_copy(primary_vol.uuid, sb.s_uuid); /* * External log * * First check device specified on * command line */ Log.xaddr = 0; if (log_device[0]) { Log.fp = NULL; if (LogOpenMode != O_RDONLY) { Log.fp = fopen_excl(log_device, "r+"); if (Log.fp == NULL) *in_use = 1; } if (Log.fp == NULL) { Log.fp = fopen(log_device, "r"); if (Log.fp == NULL) { printf("Invalid journal specified (%s)\n", log_device); goto by_uuid; } } ujfs_rw_diskblocks(Log.fp, LOGPNTOB(LOGSUPER_B), sizeof (struct logsuper), &logsup, GET); ujfs_swap_logsuper(&logsup); if ((logsup.magic != LOGMAGIC) || (uuid_compare(logsup.uuid, sb.s_loguuid))) { fclose(Log.fp); *in_use = 0; goto by_uuid; } Log.location = OUTLINELOG; return 0; } by_uuid: Log.fp = open_by_label(sb.s_loguuid, 0, 1, NULL, in_use); if (Log.fp != NULL) { Log.location |= OUTLINELOG; return 0; } return NOT_INLINELOG_ERROR; } /* * is this an external log? */ ujfs_rw_diskblocks(fp, LOGPNTOB(LOGSUPER_B), sizeof (struct logsuper), &logsup, GET); ujfs_swap_logsuper(&logsup); if (logsup.magic != LOGMAGIC) { fsck_send_msg(lrdo_NOTAFSDEV); return NOT_FSDEV_ERROR; } Log.fp = fp; Log.location = OUTLINELOG; return 0; } extern void exit(int); /* * NAME: fsError(type,vol,bn) * * FUNCTION: error handling code for the specified * aggregate/lv (filesystem). */ int fsError(int type, /* error types */ int vol, /* the minor number of the aggregate/lv */ int64_t bn) { /* aggregate block No. */ fsck_send_msg(lrdo_ERRORONVOL, vol); retcode = -1; vopen[vol].status = FM_LOGREDO; switch (type) { case OPENERR: fsck_send_msg(lrdo_OPENFAILED); break; case MAPERR: fsck_send_msg(lrdo_CANTINITMAPS); break; case DBTYPE: fsck_send_msg(lrdo_BADDISKBLKNUM, (long long) bn); break; case INOTYPE: fsck_send_msg(lrdo_BADINODENUM, (long long) bn); break; case READERR: fsck_send_msg(lrdo_CANTREADBLK, (long long) bn); break; case SERIALNO: fsck_send_msg(lrdo_BADLOGSER); break; case IOERROR: fsck_send_msg(lrdo_IOERRREADINGBLK, (long long) bn); break; case LOGRCERR: fsck_send_msg(lrdo_BADUPDMAPREC, (long long) bn); break; } return (0); } /* * logError(type) * * error handling for log read errors. */ int logError(int type, int logaddr) { int k; retcode = -1; logsup.state = LOGREADERR; switch (type) { case LOGEND: fsck_send_msg(lrdo_FINDLOGENDFAIL); break; case READERR: fsck_send_msg(lrdo_LOGREADFAIL, logaddr); break; case UNKNOWNR: fsck_send_msg(lrdo_UNRECOGTYPE, logaddr); break; case IOERROR: fsck_send_msg(lrdo_IOERRONLOG, logaddr); break; case LOGWRAP: fsck_send_msg(lrdo_LOGWRAP); } /* mark all open volumes in error */ for (k = 0; k < MAX_ACTIVE; k++) { if ((vopen[k].state == VOPEN_OPEN) && vopen[k].status != FM_CLEAN) vopen[k].status = FM_LOGREDO; } return (0); } /* * recoverExtendFS() * * function: recover crash while in extendfs() for inline log; * * note: fs superblock fields remains pre-extendfs state, * while that bmap file, fsck and inline log area may be in * unknown state; * * at entry, only log type/lv has been validated; * for inline log: vopen[0], fs fp = log fp; */ static int recoverExtendFS(FILE *fp) { struct superblock *sbp; struct dinode *dip1, *dip2; struct dbmap *bgcp; xtpage_t *p; int64_t lmchild = 0, xaddr, xoff, barrier, t64, agsize; uint8_t lmxflag; int32_t i; char *dip, *bp; pxd_t temp_pxd; /* * read bmap global control page */ /* read superblock yet again */ sbp = (struct superblock *) &buffer[0]; if (rdwrSuper(fp, sbp, PB_READ)) goto errout; /* read primary block allocation map inode */ dip = (char *) &buffer[1]; if (ujfs_rw_diskblocks(fp, AITBL_OFF, PSIZE, dip, GET)) { fsck_send_msg(lrdo_EXTFSREADFSSUPERFAIL); goto errout; } /* locate the inode in the buffer page */ dip1 = (struct dinode *) dip; dip1 += BMAP_I; bp = (char *) &buffer[2]; /* utility buffer */ /* start from root in dinode */ p = (xtpage_t *) & dip1->di_btroot; /* is this page leaf ? */ if (p->header.flag & BT_LEAF) goto rdbgcp; /* traverse down leftmost child node to leftmost leaf of xtree */ do { /* read in the leftmost child page */ t64 = addressXAD(&p->xad[XTENTRYSTART]) << sbp->s_l2bsize; if (ujfs_rw_diskblocks(fp, t64, PSIZE, bp, GET)) { fsck_send_msg(lrdo_EXTFSREADBLKMAPINOFAIL); goto errout; } p = (xtpage_t *) bp; /* is this page leaf ? */ if (p->header.flag & BT_LEAF) break; } while (1); rdbgcp: t64 = addressXAD(&p->xad[XTENTRYSTART]) << sbp->s_l2bsize; if (ujfs_rw_diskblocks(fp, t64, PSIZE, bp, GET)) { fsck_send_msg(lrdo_EXTFSREADBLKFAIL1, (long long) t64); goto errout; } bgcp = (struct dbmap *) bp; /* * recover to pre- or post-extendfs state ?: */ if (__le64_to_cpu(bgcp->dn_mapsize) > (sbp->s_size >> sbp->s_l2bfactor)) { agsize = __le64_to_cpu(bgcp->dn_agsize); goto postx; } /* * recover pre-extendfs state */ /* * reset block allocation map inode (xtree root) */ /* read 2ndary block allocation map inode */ t64 = addressPXD(&sbp->s_ait2) << sbp->s_l2bsize; if (ujfs_rw_diskblocks(fp, t64, PSIZE, bp, GET)) { fsck_send_msg(lrdo_EXTFSREADBLKFAIL2, (long long) t64); goto errout; } dip2 = (struct dinode *) bp; dip2 += BMAP_I; /* * Reset primary bam inode with 2ndary bam inode * * Not forgetting to reset di_ixpxd since they are in different * inode extents. */ memcpy((void *) &temp_pxd, (void *) &(dip1->di_ixpxd), sizeof (pxd_t)); memcpy(dip1, dip2, DISIZE); memcpy((void *) &(dip1->di_ixpxd), (void *) &temp_pxd, sizeof (pxd_t)); if (ujfs_rw_diskblocks(fp, AITBL_OFF, PSIZE, dip, PUT)) { fsck_send_msg(lrdo_EXTFSWRITEBLKFAIL1, AITBL_OFF); goto errout; } /* * backout bmap file to fs size: * * trim xtree to range specified by i_size: * xtree has been grown in append mode and * written from right to left, bottom-up; */ barrier = __le64_to_cpu(dip1->di_size) >> sbp->s_l2bsize; /* start with root */ xaddr = 0; p = (xtpage_t *) & dip1->di_btroot; lmxflag = p->header.flag; p->header.next = 0; if (lmxflag & BT_INTERNAL) { /* save leftmost child xtpage xaddr */ lmchild = addressXAD(&p->xad[XTENTRYSTART]); } /* * scan each level of xtree via leftmost descend */ while (1) { /* * scan each xtpage of current level of xtree */ while (1) { /* * scan each xad in current xtpage */ for (i = XTENTRYSTART; i < p->header.nextindex; i++) { /* test if extent is of interest */ xoff = offsetXAD(&p->xad[i]); if (xoff < barrier) continue; /* * barrier met in current page */ assert(i > XTENTRYSTART); /* update current page */ p->header.nextindex = i; if (xaddr) { /* discard further right sibling * pages */ p->header.next = 0; if (ujfs_rw_diskblocks(fp, t64, PSIZE, p, PUT)) { fsck_send_msg(lrdo_EXTFSWRITEBLKFAIL2, (long long) t64); goto errout; } } goto nextLevel; } /* end for current xtpage scan */ /* barrier was not met in current page */ /* read in next/right sibling xtpage */ xaddr = p->header.next; if (xaddr) { if (xaddr >= barrier) { p->header.next = 0; if (ujfs_rw_diskblocks(fp, t64, PSIZE, p, PUT)) { fsck_send_msg(lrdo_EXTFSWRITEBLKFAIL3, (long long) t64); break; } } t64 = xaddr << sbp->s_l2bsize; if (ujfs_rw_diskblocks(fp, t64, PSIZE, bp, GET)) { fsck_send_msg(lrdo_EXTFSREADBLKFAIL3, (long long) t64); goto errout; } p = (xtpage_t *) bp; } else break; } /* end while current level scan */ /* * descend: read leftmost xtpage of next lower level of xtree */ nextLevel: if (lmxflag & BT_INTERNAL) { /* get the leftmost child page */ xaddr = lmchild; t64 = xaddr << sbp->s_l2bsize; if (ujfs_rw_diskblocks(fp, t64, PSIZE, bp, GET)) { fsck_send_msg(lrdo_EXTFSREADBLKFAIL4, (long long) t64); goto errout; } p = (xtpage_t *) bp; lmxflag = p->header.flag; if (lmxflag & BT_INTERNAL) { /* save leftmost child xtpage xaddr */ lmchild = addressXAD(&p->xad[XTENTRYSTART]); } } else break; } /* end while level scan */ /* * reconstruct map; * * readBmap() init blocks beyond fs size in the last * partial dmap page as allocated which might have been * marked as free by extendfs(); */ /* fake log opend/validated */ Log.serial = sbp->s_logserial; /* * reconstruct maps */ /* open LV and initialize maps */ if (logredoInit()) { fsck_send_msg(lrdo_EXTFSINITLOGREDOFAIL); goto errout; } /* bypass log replay */ /* update/write maps */ updateMaps(0); /* * reformat log * * request reformat original log (which might have been * overwritten by extendfs() and set superblock clean */ jfs_logform(fp, sbp->s_bsize, sbp->s_l2bsize, sbp->s_flag, addressPXD(&sbp->s_logpxd), lengthPXD(&sbp->s_logpxd), NULL, NULL); /* update superblock */ updateSuper(0); fsck_send_msg(lrdo_REXTNDTOPRE); return 0; /* * recover post-extendfs state */ postx: /* * update 2ndary bam inode */ /* read 2ndary block allocation map inode */ t64 = addressPXD(&sbp->s_ait2) << sbp->s_l2bsize; if (ujfs_rw_diskblocks(fp, t64, PSIZE, bp, GET)) { fsck_send_msg(lrdo_EXTFSREADBLKFAIL5, (long long) t64); goto errout; } dip2 = (struct dinode *) bp; dip2 += BMAP_I; /* * Reset 2ndary bam inode with primary bam inode * Not forgetting to reset di_ixpxd since they are in different * inode extents. */ memcpy((void *) &temp_pxd, (void *) &(dip2->di_ixpxd), sizeof (pxd_t)); memcpy(dip2, dip1, DISIZE); memcpy((void *) &(dip2->di_ixpxd), (void *) &temp_pxd, sizeof (pxd_t)); if (ujfs_rw_diskblocks(fp, t64, PSIZE, bp, PUT)) { fsck_send_msg(lrdo_EXTFSWRITEBLKFAIL4, (long long) t64); goto errout; } /* * update superblock */ if (!(sbp->s_state & (FM_DIRTY | FM_LOGREDO))) sbp->s_state = FM_CLEAN; else sbp->s_state &= ~FM_EXTENDFS; sbp->s_size = sbp->s_xsize; sbp->s_agsize = agsize; sbp->s_fsckpxd = sbp->s_xfsckpxd; sbp->s_fscklog = 0; sbp->s_logpxd = sbp->s_xlogpxd; sbp->s_logserial = 1; if (rdwrSuper(fp, sbp, PB_UPDATE)) { fsck_send_msg(lrdo_EXTFSWRITEFSSUPERFAIL); goto errout; } /* * finalize log * * note: new log is valid; */ /* read log superblock */ t64 = (addressPXD(&sbp->s_logpxd) << sbp->s_l2bsize) + LOGPSIZE; if (ujfs_rw_diskblocks(fp, t64, LOGPSIZE, &logsup, GET)) { fsck_send_msg(lrdo_EXTFSREADLOGSUPFAIL); goto errout; } logsup.end = findEndOfLog(); logsup.state = LOGREDONE; if (ujfs_rw_diskblocks(fp, t64, LOGPSIZE, &logsup, PUT)) { fsck_send_msg(lrdo_EXTFSWRITELOGSUPFAIL); goto errout; } fsck_send_msg(lrdo_REXTNDTOPOST); return 0; errout: fsck_send_msg(lrdo_REXTNDFAIL, errno); return (EXTENDFS_FAILRECOV); } /* * * NAME: alloc_dmap_bitrec * * FUNCTION: This routine allocates memory by calling the chkdsk * alloc_wrksp() routine (because that will allocate high * memory during autocheck). If that fails then logredo * cannot continue bmap processing, so it will set a flag * and make the storage aleady allocated to the bmap * available for other uses. * was successfully allocated and there's enough of it left, * this routine will return a piece of it. */ int alloc_dmap_bitrec(struct dmap_bitmaps ** dmap_bitrec) { int adb_rc = 0; int intermed_rc = 0; *dmap_bitrec = NULL; intermed_rc = alloc_wrksp((uint32_t) (sizeof (struct dmap_bitmaps)), 0, /* not meaningful from logredo */ -1, /* I am logredo */ (void **) dmap_bitrec); if ((intermed_rc != 0) || ((*dmap_bitrec) == NULL)) { Insuff_memory_for_maps = -1; available_stg_addr = bmap_stg_addr; available_stg_bytes = bmap_stg_bytes; /* * initialize the storage for its new use */ memset((void *) available_stg_addr, 0, available_stg_bytes); } return (adb_rc); } /* end alloc_dmap_bitrec() */ /* * * NAME: alloc_storage * * FUNCTION: This routine allocates memory by calling the chkdsk * alloc_wrksp() routine (because that will allocate high * memory during autocheck). If that fails and the bmap * was successfully allocated and there's enough of it left, * this routine will return a piece of it. */ int alloc_storage(int32_t size_in_bytes, void **addr_stg_ptr, int32_t * bmap_stg_returned) { int as_rc = 0; int intermed_rc = 0; *bmap_stg_returned = 0; /* assume we'll get it the usual way */ *addr_stg_ptr = NULL; intermed_rc = alloc_wrksp((uint32_t) size_in_bytes, 0, -1, addr_stg_ptr); if ((intermed_rc != 0) || ((*addr_stg_ptr) == NULL)) { if ((!Insuff_memory_for_maps) && (bmap_stg_addr != NULL)) { /* * we did allocate storage for the bmap * and haven't started cannibalizing it yet */ Insuff_memory_for_maps = -1; available_stg_addr = bmap_stg_addr; available_stg_bytes = bmap_stg_bytes; /* * initialize the storage for its new use */ memset((void *) available_stg_addr, 0, available_stg_bytes); } /* end we did allocate storage for the bmap... */ if (Insuff_memory_for_maps & (available_stg_bytes != 0)) { /* * we may be able to go on anyway */ if (available_stg_bytes < size_in_bytes) { /* * not enough here */ return (ENOMEM0); } else { /* we can scavenge the memory we need */ *addr_stg_ptr = available_stg_addr; available_stg_bytes -= size_in_bytes; available_stg_addr = (char *) (available_stg_addr + size_in_bytes); *bmap_stg_returned = -1; } } else { return (ENOMEM1); } } return (as_rc); } #ifdef _JFS_WIP /* * nfsisloaded() * * check whether nfs is loaded */ static int nfsisloaded() { int sav_errno; int (*entry) (); if (entry = load("/usr/sbin/probe", 0, 0)) return (1); if (errno == ENOEXEC) { DBG_TRACE(("%s: nfs is not loaded\n", prog)) return (0); } sav_errno = errno; DBG_TRACE(("%s: ", prog)) errno = sav_errno; perror("load"); return (0); } #endif /* _JFS_WIP */ #ifdef _JFS_DEBUG /* * xdump() * * hex dump */ xdump(char *saddr, int count) { #define LINESZ 60 #define ASCIISTRT 40 #define HEXEND 36 int i, j, k, hexdigit; int c; char *hexchar; char linebuf[LINESZ + 1]; char prevbuf[LINESZ + 1]; char *linestart; int asciistart; char asterisk = ' '; void x_scpy(); int x_scmp(); hexchar = "0123456789ABCDEF"; prevbuf[0] = '\0'; i = (int) saddr % 4; if (i != 0) saddr = saddr - i; for (i = 0; i < count;) { for (j = 0; j < LINESZ; j++) linebuf[j] = ' '; linestart = saddr; asciistart = ASCIISTRT; for (j = 0; j < HEXEND;) { for (k = 0; k < 4; k++) { c = *(saddr++) & 0xFF; if ((c >= 0x20) && (c <= 0x7e)) linebuf[asciistart++] = (char) c; else linebuf[asciistart++] = '.'; hexdigit = c >> 4; linebuf[j++] = hexchar[hexdigit]; hexdigit = c & 0x0f; linebuf[j++] = hexchar[hexdigit]; i++; } if (i >= count) break; linebuf[j++] = ' '; } linebuf[LINESZ] = '\0'; if (((j = x_scmp(linebuf, prevbuf)) == 0) && (i < count)) { if (asterisk == ' ') { asterisk = '*'; DBG_TRACE((" *\n")) } } else { DBG_TRACE((" %x %s\n", linestart, linebuf)) asterisk = ' '; x_scpy(prevbuf, linebuf); } } return (0); } int x_scmp(char *s1, char *s2) { while ((*s1) && (*s1 == *s2)) { s1++; s2++; } if (*s1 || *s2) return (-1); else return (0); } void x_scpy(char *s1, char *s2) { while ((*s1 = *s2) != '\0') { s1++; s2++; } } prtdesc(struct lrd *ld) { switch (ld->log.redopage.type) { case LOG_XTREE: DBG_TRACE((" REDOPAGE:XTREE\n ")) break; case (LOG_XTREE | LOG_NEW): DBG_TRACE((" REDOPAGE:XTREE_NEW\n ")) break; case (LOG_BTROOT | LOG_XTREE): DBG_TRACE((" REDOPAGE:BTROOT_XTREE\n ")) break; case LOG_DTREE: DBG_TRACE((" REDOPAGE:DTREE\n ")) break; case (LOG_DTREE | LOG_NEW): DBG_TRACE((" REDOPAGE:DTREE_NEW \n ")) break; case (LOG_DTREE | LOG_EXTEND): DBG_TRACE((" REDOPAGE:DTREE_EXTEND\n ")) break; case (LOG_BTROOT | LOG_DTREE): DBG_TRACE((" REDOPAGE:BTROOT_DTREE\n ")) break; case (LOG_BTROOT | LOG_DTREE | LOG_NEW): DBG_TRACE((" REDOPAGE:BTROOT_DTREE.NEW\n ")) break; case LOG_INODE: /* * logredo() updates imap for alloc of inode. */ DBG_TRACE((" REDOPAGE:INODE\n ")) break; case LOG_EA: DBG_TRACE((" REDOPAGE:EA\n ")) break; case LOG_DATA: DBG_TRACE((" REDOPAGE:DATA\n ")) break; } return (0); } #endif /* _JFS_DEBUG */ jfsutils-1.1.15.orig/libfs/logredo.h0000644000000000000000000002340610677240307014205 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef H_LOGREDO #define H_LOGREDO /* * NOTE: * If logredo passes rc > 0 to fsck, * fsck will do a full check and repair process * * but if logredo passes rc < 0 to fsck, * fsck will do a full check and repair process AND * fsck will reformat the log */ #define MINOR_ERROR 1 /* error that will not abort the program */ #define MAJOR_ERROR -2 /* return code to force abort of logredo */ #define REFORMAT_ERROR -3 /* return code to force logform of log */ #define ENOMEM0 100 /* insufficient dynamic storage, location 0 */ #define ENOMEM1 101 /* insufficient dynamic storage, location 1 */ #define ENOMEM2 102 /* insufficient dynamic storage, location 2 */ #define ENOMEM3 103 /* insufficient dynamic storage, location 3 */ #define ENOMEM4 104 /* insufficient dynamic storage, location 4 */ #define ENOMEM5 105 /* insufficient dynamic storage, location 5 */ #define ENOMEM6 106 /* insufficient dynamic storage, location 6 */ #define ENOMEM7 107 /* insufficient dynamic storage, location 7 */ #define ENOMEM8 108 /* insufficient dynamic storage, location 8 */ #define ENOMEM9 109 /* insufficient dynamic storage, location 9 */ #define ENOMEM10 110 /* insufficient dynamic storage, location 10 */ #define ENOMEM11 111 /* insufficient dynamic storage, location 11 */ #define ENOMEM12 112 /* insufficient dynamic storage, location 12 */ #define ENOMEM25 175 /* insufficient dynamic storage for BMap */ #define BFLUSH_WRITEERROR 201 #define BLOCK_OUTOFRANGE 202 #define BMAP_READERROR1 203 #define BMAP_READERROR2 204 #define BMAP_READERROR3 205 #define BMAP_READERROR4 206 #define BMAP_READERROR5 207 #define BMAP_READERROR6 208 #define BMAP_WRITEERROR1 209 #define BMAP_WRITEERROR2 210 #define BMAP_WRONGTOTPAGES 211 #define BREAD_BMAPINIT 212 #define BREAD_IMAPINIT 213 #define CANTOPEN_INLINELOG -214 #define CANTOPEN_OUTLINELOG -215 #define CANTREAD_2NDFSSUPER 216 #define CANTREAD_PRIMFSSUPER 217 #define CANTWRITE_2NDFSSUPER 218 #define CANTWRITE_PRIMFSSUPER 219 #define DMAP_UPDATEFAIL 220 #define DOSFSCTL_ERROR -221 #define DTPAGE_BADSLOTNEXTIDX1 -222 #define DTPAGE_BADSLOTNEXTIDX2 -223 #define DTPAGE_BADSTBLENTRY1 -224 #define DTPAGE_BADSTBLENTRY2 -225 #define DTPAGE_READERROR1 226 #define DTREE_READERROR1 227 #define EXTENDFS_FAILRECOV 228 #define FSSUPER_READERROR1 229 #define FSSUPER_READERROR2 230 #define ILLEGAL_LEAF_IND0 231 #define ILLEGAL_LEAF_IND1 232 #define IMAP_READERROR1 233 #define IMAP_READERROR2 234 #define IMAP_READERROR3 235 #define IMAP_READERROR4 236 #define IMAP_READERROR5 237 #define IMAP_READERROR6 238 #define IMAP_WRITEERROR1 239 #define IMAP_WRITEERROR2 240 #define IMAP_WRONGNPAGES 241 #define INOEXT_READERROR1 242 #define INOEXT_READERROR2 243 #define INVALID_LOGEND -244 #define INVALID_NEXTADDR -245 #define JFS_BLKSIZE_ERROR -246 #define JFS_LOGSIZE_ERROR -247 #define JFS_L2BLKSIZE_ERROR -248 #define JFS_VERSION_ERROR -249 #define JLOG_LOGWRAP -250 #define JLOG_NOCOMFREE -251 #define JLOG_READERROR1 -252 #define JLOG_WRITEERROR1 -253 #define LOG_OPEN_ERROR -254 #define LOGSUPER_BADLOGLOC -255 #define LOGSUPER_LOGNOTINLINE -256 #define LOGSUPER_BADMAGIC -257 #define LOGSUPER_BADSERIAL -258 #define LOGSUPER_BADVERSION -259 #define LOGSUPER_READ_ERROR -260 #define LOGSUPER_WRITEERROR1 -261 #define LOG_WRAPPED_TWICE -262 #define NEXTADDR_SAME -263 #define NOTREBUILDING_BMAP 264 #define NOTREBUILDING_IMAP 265 #define NOT_FSDEV_ERROR 266 #define NOT_INLINELOG_ERROR 267 #define NOT_LOG_FILE_ERROR -268 #define UNRECOG_LOGRECTYP -269 #define XTPAGE_READERROR1 270 #define BMAP_READERROR7 271 #define READLOGERROR -272 #define LOG_IN_USE 273 #define UPDATEPAGE_BAD_RANGE 274 /* error types */ #define MAPERR 0 #define DBTYPE 1 #define INOTYPE 2 #define READERR 3 #define UNKNOWNR 4 #define LOGEND 5 #define SERIALNO 6 #define OPENERR 7 #define IOERROR 8 #define LOGRCERR 9 #define PB_READ 0 #define PB_UPDATE 1 /* log.location */ #define INLINELOG 0x1 #define OUTLINELOG 0x2 #define NBUFPOOL 128 /* * the following are used to map the bmap_wsp array elements * which describe block map pages */ struct dmap_bitmaps { uint32_t wmap[LPERDMAP]; /* 1024: bits of the working map */ uint32_t pmap[LPERDMAP]; /* 1024: bits of the persistent map */ }; /* - 2048 - */ struct bmap_wsp { int64_t page_offset; /* aggregate offset for the page */ struct dmap_bitmaps *dmap_bitmaps; /* * IF this record describes a dmap page, * AND IF that dmap page is affected by * transactions processed in this * logredo session, THEN this field is * a ptr to bit maps for the page. * Otherwise this field is null. */ uint32_t available; /* unused at this time */ }; /* * the following are used to map the imap_wsp array elements * which describe the inode map pages */ struct iag_data { uint32_t wmap[EXTSPERIAG]; /* 512: working allocation map */ uint32_t pmap[EXTSPERIAG]; /* 512: persistent allocation map */ pxd_t inoext[EXTSPERIAG]; /* 1024: inode extent addresses */ }; /* - 2048 - */ struct imap_wsp { int64_t page_offset; /* aggregate offset for the page */ struct iag_data *imap_data; /* IF this record describes an IAG * AND IF that IAG is affected by * transactions processed in this * logredo session, THEN this field * is a ptr to data for the IAG. * Otherwise this field is null. */ uint32_t available; /* unused at this time */ }; /* * Information about the log device */ struct log_info { FILE *fp; /* file descriptor */ int32_t serial; /* log serial number */ int location; /* INLINELOG or OUTLINELOG */ int64_t xaddr; /* log address in bytes offset */ int64_t size; /* log size in 4K blocks */ int bsize; /* Logical Block size */ int l2bsize; /* log2 of bsize */ uuid_t uuid; /* 128-bit device uuid */ int32_t devnum; /* Kernel-style device number */ }; extern struct log_info Log; /* * open file system aggregate/lv array */ struct vopen { dev_t device; /* device major/minor */ int state; /* see below */ int next_hash; /* Next vopen index in hash list */ FILE *fp; /* file descriptor for the opened aggregate */ uuid_t uuid; /* 128-bit device uuid */ int32_t status; /* status of aggregate/volume */ int64_t fssize; /* fs size, total number of aggre. blks */ int32_t lblksize; /* aggre. blksize (ie fs blksize) in bytes */ int16_t lbperpage; /* aggregate blocks per page */ int16_t is_fsdirty; /* true if superblock.state is FM_DIRTY */ int16_t l2bsize; /* log2 of s_bsize */ int16_t l2bfactor; /* log2(s_bsize/physical block size) */ int32_t agsize; /* num of aggre. blks per alloc group */ int32_t l2agsize; /* Log2 of agsize */ int32_t numag; /* total num of ags in this aggregate. */ struct dinomap *aggimap_ctrl; /* pointer to the control page of aggregate inode map */ struct iag *aggimap_iag; /* ptr to aggregate inode map iag pages */ struct fsimap_lst { int32_t fileset; /* fileset number, which is the inode * number of this fileset imap inode in * the aggregate inode table. */ int imap_page_count; /* number of pages in the imap, * including the control page */ struct dinomap *fsimapctrl; /* ptr to ctrl page of fileset imap */ struct imap_wsp *imap_wsp; /* * ptr to an array of IAG workspaces */ struct iag *iag_pbuf; /* ptr to an iag page buffer */ int imap_pagenum; /* page offset, in inode map, * of buffer contents */ struct iag *iag_pbuf2; /* ptr to another iag page buffer */ int imap_pagenum2; /* page offset, in inode map, * of buffer contents */ struct fsimap_lst *next; /* ptr to next fileset imap */ } fsimap_lst; /* the list of multiple fileset imap */ int bmap_page_count; /* number of pages in the bmap, * including the control page */ struct dbmap *bmap_ctl; /* ptr to control page of aggregate block * allocate map (i.e. bmap) file */ struct bmap_wsp *bmap_wsp; /* * ptr to an array of blockmap page workspaces */ struct dmap *dmap_pbuf; /* ptr to a dmap page buffer */ int dmap_pagenum; /* page offset, in block map, of * buffer contents */ struct dmapctl *L0_pbuf; /* ptr to a dmap page buffer */ int L0_pagenum; /* page offset, in block map, of * buffer contents */ struct dmapctl *L1_pbuf; /* ptr to a dmap page buffer */ int L1_pagenum; /* page offset, in block map, of * buffer contents */ struct dmapctl *L2_pbuf; /* ptr to a dmap page buffer */ int L2_pagenum; /* page offset, in block map, of * buffer contents */ }; /* vopen state */ #define VOPEN_EMPTY 0 /* Unused slot */ #define VOPEN_OPEN 1 /* Device is open */ #define VOPEN_CLOSED 2 /* Device is closed */ #define fsimap_iag fsimap_lst.fsimapiag int jfs_logredo(caddr_t, FILE *, int32_t); int findLog(FILE *, int *); #endif /* H_LOGREDO */ jfsutils-1.1.15.orig/libfs/message.c0000645000000000000000000004716710673507604014206 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include "message.h" #include "debug.h" #define MAX_STRING_ACCEPTED 80 char Current_String[MAX_STRING_ACCEPTED + 1]; /* *** message_user - * * This function is * * message_user (mesg_no, param, param_cnt, msg_file) * * ENTRY mesg_no - index into the array of messages * param - list of pointers to parameters in the message * param_cnt - count of parameters in the param variable * msg_file - OSO_MSG/JFS_MSG which message file to use * * EXIT Returns pointer to buffer contain the user's response * or NULL if no response needed. * * CALLS */ void message_user(unsigned mesg_no, char **param, unsigned param_cnt, int msg_file) { if (msg_file == OSO_MSG) { switch (mesg_no) { case MSG_OSO_NOT_ENOUGH_MEMORY: printf("There is not enough memory available to process this command.\n"); break; case MSG_OSO_CANT_FIND_DRIVE: printf("\nThe system cannot find the specified device.\n"); break; case MSG_OSO_CANT_OPEN: printf("The system cannot open the device or file specified.\n"); break; case MSG_OSO_ERR_ACCESSING_DISK: printf(" An error occurred when accessing the hard disk.\n"); break; case MSG_OSO_DISK_LOCKED: printf(" The specified disk is being used by another process.\n"); break; case MSG_OSO_VALUE_NOT_ALLOWED: printf("The value %s is not allowed for parameter %s.\n", param[0], param[1]); break; case MSG_OSO_FORMAT_FAILED: printf("The specified disk did not finish formatting.\n"); break; case MSG_OSO_INSUFF_MEMORY: printf("Not enough memory is available to run mkfs.jfs.\n"); break; case MSG_OSO_DESTROY_DATA: printf("Warning! All data on device %s will be lost!\n", param[0]); break; case MSG_OSO_FORMAT_COMPLETE: printf("\n\nFormat completed successfully.\n\n"); break; case MSG_OSO_DISK_SPACE: printf("\n%s kilobytes of total disk space.\n", param[0]); break; case MSG_OSO_DISK_SPACE2: printf("%s kilobytes total disk space.\n", param[0]); break; case MSG_OSO_FREE_SPACE: printf("%s kilobytes are available.\n", param[0]); break; case MSG_OSO_PERCENT_FORMAT: printf("%s percent of the disk has been formatted.\r", param[0]); break; case MSG_OSO_READ_ERROR: printf("An error occurred when reading data from the hard disk.\n"); break; case MSG_OSO_NOT_VALID_BLOCK_DEVICE: printf("%s is not a valid block device.\n", param[0]); break; default: /* Error! Unknown message number! */ break; } } else { switch (mesg_no) { case MSG_JFS_PART_SMALL: printf("Partition must be at least %s megabytes.\n", param[0]); break; case MSG_JFS_LOG_LARGE: printf("Log too large, no space for file system.\n"); break; case MSG_JFS_BAD_PART: /* This message is basically from ext2 */ printf("Device size reported to be zero. Invalid partition specified, or\n" "\tpartition table wasn't reread after running fsck, fdisk, etc.\n" "\tYou may need to reboot to re-read your partition table.\n"); break; case 52: printf("Invalid data format detected in root directory.\n"); break; case 68: printf ("Superblock is corrupt and cannot be repaired because \nboth primary and secondary copies are corrupt.\n\nFSCK CANNOT CONTINUE.\n\n"); break; case 69: printf ("Primary superblock is corrupt and cannot be repaired without write access. FSCK continuing.\n"); break; case 76: printf("Invalid format detected in root directory.\n"); break; case 79: printf ("Secondary file/directory allocation structure (%s) is not a correct redundant copy of primary structure.\n", param[0]); break; case 80: printf ("Unable to replicate primary file/directory allocation structure (%s) \nto secondary. FUTURE RECOVERY CAPABILITY MAY BE COMPROMISED.\n", param[0]); break; case 82: printf ("Cannot create directory lost+found in root directory. \nMKDIR lost+found in the root directory then start FSCK with the -f parameter \nto reconnect lost files and/or directories.\n"); break; case 83: printf("Fileset object %s%s%s: No paths found.\n", param[0], param[1], param[2]); break; case 84: printf("The paths refer to an unallocated file.\n"); break; case 86: printf("The paths refer to an unallocated file. Will remove.\n"); break; case 94: printf("Unable to write primary superblock.\n"); break; case 96: printf("Multiple parent directories for directory %s%s.\n", param[0], param[1]); break; case 101: printf ("Insufficient dynamic storage available for required workspace\n(%s,%s). FSCK CANNOT CONTINUE.\n", param[0], param[1]); break; case 103: printf("File system is currently mounted.\n"); break; case 105: printf("Block size in bytes: %s\n", param[0]); break; case 106: printf("File system size in blocks: %s\n", param[0]); break; case 117: printf ("Unable to get path for link from directory %s%s to fileset object %s%s%s.\n", param[0], param[1], param[2], param[3], param[4]); break; case 118: printf("Format error in Extended Attributes Space or descriptor.\n"); break; case 121: printf ("Directory %s%s entry '..' refers to an incorrect parent directory (%s%s).\n", param[0], param[1], param[2], param[3]); break; case 129: printf("File system object %s%s%s is linked as: %s\n", param[0], param[1], param[2], param[3]); break; case 134: printf ("Insufficient dynamic storage to validate extended attributes format.\n"); break; case 135: printf("logredo failed (rc=%s). FSCK continuing.\n", param[0]); break; case 137: printf("Unable to create a lost+found directory in root directory.\n"); break; case 138: printf ("Checking a mounted file system does not produce dependable results.\n"); break; case 142: printf("%s blocks are missing.\n", param[0]); break; case 143: printf("Unable to write to boot sector. FSCK continuing.\n"); break; case 145: printf("Incorrect link counts detected in the file system.\n"); break; case 148: printf("Unrecoverable error reading %s from %s. FSCK CANNOT CONTINUE.\n", param[0], param[1]); break; case 149: printf("Phase 0 - Replay Journal Log\n"); break; case 150: printf ("Phase 1 - Check Blocks, Files/Directories, and Directory Entries.\n"); break; case 151: printf("Phase 2 - Count Links.\n"); break; case 152: printf ("Phase 3 - Rescan for Duplicate Blocks and Verify Directory Tree.\n"); break; case 153: printf("Phase 4 - Report Problems.\n"); break; case 154: printf("Phase 5 - Check Connectivity.\n"); break; case 155: printf("Phase 6 - Perform Approved Corrections.\n"); break; case 156: printf("Phase 7 - Rebuild File/Directory Allocation Maps.\n"); break; case 157: printf("Phase 8 - Rebuild Disk Allocation Maps.\n"); break; case 158: printf("Phase 9 - Reformat File System Log.\n"); break; case 159: printf("Directory has entry for unallocated file %s%s. Will remove.\n", param[0], param[1]); break; case 161: printf ("Format error in Extended Attributes Space or descriptor. Will clear.\n"); break; case 165: printf ("Mutually exclusive 'check READ ONLY' and 'fix file system' options specified.\n"); break; case 166: printf("Usage: fsck.jfs [-a] [-f] [-n] [-o] [-p] [-v] [-V] \n"); break; case 167: printf("Unrecognized -f parameter value detected: %s\n", param[0]); break; case 168: printf("Unsupported parameter: %s\n", param[0]); break; case 169: printf("logformat failed (rc=%s). FSCK continuing.\n", param[0]); break; case 171: printf ("Unable to read device characteristics. Boot sector cannot be refreshed. FSCK continuing.\n"); break; case 174: printf ("Cannot repair an allocation error for files and/or directories %s through %s.\n", param[0], param[1]); break; case 186: printf ("Cannot recover files and/or directories %s through %s. FSCK CANNOT CONTINUE.\n", param[0], param[1]); break; case 187: printf("Unrecoverable error writing %s to %s. FSCK CANNOT CONTINUE.\n", param[0], param[1]); break; case 188: printf("The root directory has an invalid data format. Will correct.\n"); break; case 189: printf("The root directory has an invalid format. Will correct.\n"); break; case 190: printf ("Cannot recover files and/or directories %s through %s. Will release.\n", param[0], param[1]); break; case 191: printf("File claims cross linked blocks.\n"); break; case 192: printf("Cannot repair the data format error(s) in this file.\n"); break; case 193: printf("Cannot repair the format error(s) in this file.\n"); break; case 194: printf("Cannot repair %s%s%s.\n", param[0], param[1], param[2]); break; case 195: printf("The current device is: %s\n", param[0]); break; case 197: printf("Cannot repair %s%s%s. Will release.\n", param[0], param[1], param[2]); break; case 200: printf("Multiple parent directories for directory %s%s. Will correct.\n", param[0], param[1]); break; case 201: printf ("Directory %s%s entry '..' refers to an incorrect parent directory\n(%s%s). Will correct.\n", param[0], param[1], param[2], param[3]); break; case 202: printf("%s unexpected blocks detected.\n", param[0]); break; case 203: printf("Directories with illegal hard links have been detected.\n"); break; case 204: printf ("Directory entries ('..') referring to incorrect parent directories have been detected.\n"); break; case 205: printf ("Directory entries for unallocated files and/or directories were detected.\n"); break; case 206: printf("Unable to write secondary superblock.\n"); break; case 207: printf("Incorrect link counts have been detected. Will correct.\n"); break; case 209: printf ("Duplicate block references have been detected in meta-data. \nFSCK CANNOT CONTINUE.\n"); break; case 214: printf("Unrecoverable error during UNLOCK processing.\n"); break; case 215: printf("Unrecoverable error during CLOSE processing!\n"); break; case 217: printf("%s appears to be the correct path for directory %s%s.\n", param[0], param[1], param[2]); break; case 221: printf ("ERRORS HAVE BEEN DETECTED. Run fsck with the -f\nparameter to repair.\n"); break; case 223: printf("%s directory reconnected to /lost+found/.\n", param[0]); break; case 224: printf("Unable to reconnect %s directory. FSCK continuing.\n", param[0]); break; case 230: printf ("Files and/or directories not connected to the directory tree\nhave been detected.\n"); break; case 231: printf ("Directory entries for unallocated files have been detected. Will remove.\n"); break; case 232: printf ("Files and/or directories not connected to the directory tree\nhave been detected. Will reconnect.\n"); break; case 233: printf ("Directories with illegal hard links have been detected. Will correct.\n"); break; case 234: printf ("Directories (entries '..') referring to incorrect files have been detected. Will correct.\n"); break; case 236: printf("File system is clean.\n"); break; case 237: printf ("File system is clean but is marked dirty. Start FSCK with the\n-f parameter to fix.\n"); break; case 238: printf("File system is dirty.\n"); break; case 239: printf ("File system is dirty but is marked clean. In its present state, the\nresults of accessing %s (except by this utility) are undefined.\n", param[0]); break; case 241: printf ("FSCK has marked the file system dirty because it contains critical errors.\nFile system may be unrecoverable.\n"); break; case 250: printf("Directory has an entry for unallocated file %s%s.\n", param[0], param[1]); break; case 265: printf("Errors detected in the Fileset File/Directory Allocation Map.\n"); break; case 267: printf ("Errors detected in the Fileset File/Directory Allocation Map control information.\n"); break; case 279: printf("Incorrect data detected in disk allocation structures.\n"); break; case 280: printf("Incorrect data detected in disk allocation control structures.\n"); break; case 321: printf("Directory claims cross linked blocks.\n"); break; case 322: printf("File system object claims cross linked blocks.\n"); break; case 323: printf("File system is formatted for sparse files.\n"); break; case 325: printf("%s directories reconnected to /lost+found/.\n", param[0]); break; case 326: printf("%s file reconnected to /lost+found/.\n", param[0]); break; case 327: printf("%s files reconnected to /lost+found/.\n", param[0]); break; case 328: printf("Cannot repair the data format error(s) in this directory.\n"); break; case 329: printf("Cannot repair the data error(s) in this directory.\n"); break; case 330: printf ("Cannot repair the data format error(s) in this file system object.\n"); break; case 331: printf("Cannot repair the format error(s) in this file system object.\n"); break; case 332: printf("Phase 7 - Verify File/Directory Allocation Maps.\n"); break; case 333: printf("Phase 8 - Verify Disk Allocation Maps.\n"); break; case 335: printf ("NOTE: The file system type for %s is not listed \nas jfs in the file system description file /etc/fstab.\n\n", param[0]); break; case 343: printf("Unable to read the secondary File/Directory Allocation Table.\n"); break; case 344: printf ("Errors detected in the File System File/Directory Allocation Map.\n"); break; case 345: printf ("Errors detected in the File System File/Directory Allocation Map control information.\n"); break; case 346: printf ("Errors detected in the secondary File/Directory Allocation Table.\n"); break; case 351: printf("Unable to reconnect %s directories. FSCK continuing.\n", param[0]); break; case 352: printf("Unable to reconnect %s file. FSCK continuing.\n", param[0]); break; case 353: printf("Unable to reconnect %s files. FSCK continuing.\n", param[0]); break; case 374: printf("Unable to read the primary File/Directory Allocation Table.\n"); break; case 375: printf("Errors detected in the primary File/Directory Allocation Table.\n"); break; case 376: printf("CANNOT CONTINUE.\n"); break; case 392: printf ("The LVM has detected bad blocks in the partition.\nStart FSCK with the -b parameter to transfer entries from the LVM bad block\ntable to the JFS bad block table.\n"); break; case 395: printf("THE FILE SYSTEM IS NOW AVAILABLE.\n"); break; case 396: printf ("Transferring entries from the LVM Bad Block Table for this file system to the JFS Bad Block Table for this file system.\n"); break; case 397: printf("INTERNAL ERROR (%s,%s,%s,%s). FSCK CANNOT CONTINUE.\n", param[0], param[1], param[2], param[3]); break; case 402: printf ("LVM reports %s bad blocks. Of these, %s have been transferred to the JFS Bad Block List.\n", param[0], param[1]); break; case 406: printf ("Device unavailable or locked by another process. FSCK CANNOT CONTINUE.\n"); break; case 408: printf("File system object %s%s%s is illegally linked as: %s\n", param[0], param[1], param[2], param[3]); break; case 409: printf ("Insufficient storage (%s) available to continue reconnecting lost files and/or directories. Continuing.\n", param[0]); break; case 410: printf("Format error in Access Control List space or descriptor.\n"); break; case 411: printf ("Format error in Access Control List space or descriptor. Will clear.\n"); break; case 415: printf("Minor format error detected.\n"); break; case 417: printf("Minor format error detected. Will fix.\n"); break; case 420: printf("File system checked READ ONLY.\n"); break; case 421: printf("Error: device does not exist.\n"); break; case 422: printf("Error: no device given.\n"); break; case MSG_JFS_NOT_JFS: printf("The specified device is mounted, but is not a JFS file system.\n"); break; case MSG_JFS_BAD_SUPERBLOCK: printf ("The file system version is incompatible with this program, or the superblock is corrupted.\n"); break; case MSG_JFS_DIRTY: printf("The file system is marked dirty.\n"); break; case MSG_JFS_EXTENDFS_COMPLETE: printf("EXTENDFS completed successfully.\n"); break; case MSG_JFS_EXTENDFS_USAGE: printf(" Usage: EXTENDFS [-LS:logSize] .\n"); break; case MSG_JFS_EXTENDFS_FAILED: printf("The system failed to extend the file system.\n"); break; case MSG_JFS_DEFRAGMENTING: printf("Defragmenting device %s. Please wait.\n", param[0]); break; case MSG_JFS_DEFRAGFS_COMPLETE: printf("\nDEFRAGFS completed successfully.\n"); break; case MSG_JFS_NUM_DEFRAGED: printf("%s allocation groups defragmented.\n", param[0]); break; case MSG_JFS_SKIPPED_FREE: printf("%s allocation groups skipped - entirely free.\n", param[0]); break; case MSG_JFS_SKIPPED_FULL: printf("%s allocation groups skipped - too few free blocks.\n", param[0]); break; case MSG_JFS_SKIPPED_CONTIG: printf ("%s allocation groups skipped - contains a large contiguous free space.\n", param[0]); break; case MSG_JFS_TOTAL_AGS: printf("\nTotal allocation groups: %s\n", param[0]); break; case MSG_JFS_DEFRAGFS_USAGE: printf("Usage: defragfs [-q] \n"); break; case MSG_JFS_NUM_CANDIDATE: printf("%s allocation groups are candidates for defragmenting.\n", param[0]); break; case MSG_JFS_AVG_FREE_RUNS: printf("Average number of free runs in candidate allocation groups: %s.\n", param[0]); break; case MSG_JFS_UNEXPECTED_ERROR: printf("\n DEFRAGFS FATAL ERROR (%s). DEFRAGFS CANNOT CONTINUE.\n", param[0]); break; case MSG_JFS_VOLUME_IS_MOUNTED: printf ("\nThe specified device is currently mounted! Please unmount the device and try again.\n"); break; case MSG_JFS_MNT_LIST_ERROR: printf ("\nError accessing the list of mounted devices! Operation aborted!\n"); break; case MSG_JFS_VOLUME_IS_MOUNTED_RO: printf ("\nThe specified device is currently mounted read only!\nfsck will report, but not repair, any errors.\n"); break; default: /* Error! Unknown message number! */ break; } } } jfsutils-1.1.15.orig/libfs/message.h0000645000000000000000000000552510340701413014164 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _MESSAGE_H_ #define _MESSAGE_H_ /* * message_user (mesg_no, param, param_cnt, msg_file) * * ENTRY mesg_no - index into the array of messages * param - list of pointers to parameters in the message * param_cnt - count of parameters in the param variable * msg_file - OSO_MSG/JFS_MSG which message file to use * */ extern void message_user(unsigned, char **, unsigned, int); #define OSO_MSG 0 #define JFS_MSG 1 #define MSG_JFS_PART_SMALL 1 #define MSG_JFS_LOG_LARGE 2 #define MSG_JFS_BAD_PART 5 #define MSG_JFS_NOT_JFS 450 #define MSG_JFS_BAD_SUPERBLOCK 451 #define MSG_JFS_DIRTY 452 #define MSG_JFS_EXTENDFS_COMPLETE 453 #define MSG_JFS_EXTENDFS_USAGE 454 #define MSG_JFS_EXTENDFS_FAILED 455 #define MSG_JFS_DEFRAGMENTING 456 #define MSG_JFS_DEFRAGFS_COMPLETE 457 #define MSG_JFS_NUM_DEFRAGED 458 #define MSG_JFS_SKIPPED_FREE 459 #define MSG_JFS_SKIPPED_FULL 460 #define MSG_JFS_SKIPPED_CONTIG 461 #define MSG_JFS_TOTAL_AGS 462 #define MSG_JFS_DEFRAGFS_USAGE 463 #define MSG_JFS_NUM_CANDIDATE 464 #define MSG_JFS_AVG_FREE_RUNS 465 #define MSG_JFS_UNEXPECTED_ERROR 466 #define MSG_JFS_VOLUME_IS_MOUNTED 467 #define MSG_JFS_MNT_LIST_ERROR 468 #define MSG_JFS_VOLUME_IS_MOUNTED_RO 469 #define MSG_JFS_DEV_NOT_IN_TABLE 470 #define MSG_OSO_NOT_ENOUGH_MEMORY 8 #define MSG_OSO_CANT_FIND_DRIVE 15 #define MSG_OSO_CANT_OPEN 110 #define MSG_OSO_DISK_FULL 112 #define MSG_OSO_FORMAT_FAILED 528 #define MSG_OSO_INSUFF_MEMORY 529 #define MSG_OSO_DISK_SPACE 535 #define MSG_OSO_FREE_SPACE 537 #define MSG_OSO_PERCENT_FORMAT 538 #define MSG_OSO_DISK_LOCKED 566 #define MSG_OSO_DISK_SPACE2 568 #define MSG_OSO_FORMAT_COMPLETE 635 #define MSG_OSO_ERR_ACCESSING_DISK 868 #define MSG_OSO_VALUE_NOT_ALLOWED 873 #define MSG_OSO_DESTROY_DATA 1271 #define MSG_OSO_READ_ERROR 1566 #define MSG_OSO_NOT_VALID_BLOCK_DEVICE 1567 #endif jfsutils-1.1.15.orig/libfs/open_by_label.c0000644000000000000000000001667110651212653015340 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2007 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include "jfs_types.h" #include "jfs_endian.h" #include "jfs_filsys.h" #include "jfs_superblock.h" #include "jfs_logmgr.h" #include "devices.h" #include "utilsubs.h" /* * LogOpenMode is kind of clunky, but it avoids passing a flag through several * layers of functions. It should be either O_RDWR|O_EXCL or O_RDONLY. * Nothing should be writing to the journal device if any mounted file system * is using it. */ int LogOpenMode = O_RDWR|O_EXCL; FILE * open_check_label(char *device, uuid_t uuid, int is_label, int is_log, int *in_use) { FILE *fp = NULL; struct logsuper logsup; struct superblock super; if (in_use) *in_use = 0; if (LogOpenMode == O_RDONLY) fp = fopen(device, "r"); else { fp = fopen_excl(device, "r+"); if ((fp == NULL) && in_use) { *in_use = 1; fp = fopen(device, "r"); } } if (fp == NULL) return fp; if (is_log) { ujfs_rw_diskblocks(fp, LOGSUPER_B << L2LOGPSIZE, sizeof (struct logsuper), &logsup, GET); ujfs_swap_logsuper(&logsup); if (logsup.magic == LOGMAGIC) { if (is_label) { if (!strncmp(uuid, logsup.label, 16)) return fp; } else { if (!uuid_compare(uuid, logsup.uuid)) return fp; } } } else { ujfs_rw_diskblocks(fp, SUPER1_OFF, sizeof (super), &super, GET); ujfs_swap_superblock(&super); if (!memcmp(super.s_magic, JFS_MAGIC, 4)) { if (is_label) { if (!strncmp(uuid, super.s_label, 16)) return fp; } else { if (!uuid_compare(uuid, super.s_uuid)) return fp; } } } fclose(fp); return (NULL); } /*-------------------------------------------------------------------- * NAME: walk_dir * * FUNCTION: Helper for open_by_label to recursively search a directory * for block devices with the specified label or uuid * * PARAMETERS: path - path of directory to search, returns found device * uuid - label or uuid * is_label - 1 if label, 0 if uuid * is_log - 0 if filesystem, 1 if external log * * RETURNS: * >= 0 file descriptor of matching volume * < 0 matching volume not found */ FILE * walk_dir(char *path, uuid_t uuid, int is_label, int is_log, int *in_use) { FILE *fp = NULL; DIR *lv_dir; struct dirent *lv_ent; int path_len; struct stat st; lv_dir = opendir(path); if (lv_dir) { strcat(path, "/"); path_len = strlen(path); while ((lv_ent = readdir(lv_dir))) { path[path_len] = 0; if (!strcmp(lv_ent->d_name, ".") || !strcmp(lv_ent->d_name, "..") || !strcmp(lv_ent->d_name, ".nodes")) continue; strcat(path, lv_ent->d_name); if (stat(path, &st)) continue; if (S_ISBLK(st.st_mode)) fp = open_check_label(path, uuid, is_label, is_log, in_use); else if (S_ISDIR(st.st_mode)) fp = walk_dir(path, uuid, is_label, is_log, in_use); else continue; if (fp) { closedir(lv_dir); return fp; } } closedir(lv_dir); } return NULL; } /*-------------------------------------------------------------------- * NAME: open_by_label * * FUNCTION: Search /proc/partitions for volume having specified * label or uuid * * PARAMETERS: uuid - label or uuid * is_label - 1 if label, 0 if uuid * is_log - 0 if filesystem, 1 if external log * dev - if not null, returns copy of device path * * RETURNS: * >= 0 file descriptor of matching volume * < 0 matching volume not found * * NOTE: We may want to cache the uuids already found */ FILE *open_by_label(uuid_t uuid, int is_label, int is_log, char *dev, int *in_use) { char device[100]; FILE *fp; char line[100]; DIR *lv_dir; char lv_dirname[100]; struct dirent *lv_ent; int size; FILE *part_fd; char part_name[95]; DIR *vg_dir; struct dirent *vg_ent; // #ifndef __DragonFly__ /* * Check for EVMS Release 1 volumes */ part_fd = fopen("/proc/evms/volumes", "r"); if (part_fd) { /* evms/volumes should be complete. If it exists, don't * search /proc/partitions or /proc/lvm */ while (fgets(line, sizeof (line), part_fd)) { if (sscanf(line, " %*d %*d %*d %*s %*s %s", device) != 1) continue; fp = open_check_label(device, uuid, is_label, is_log, in_use); if (fp != NULL) { if (dev) strcpy(dev, device); fclose(part_fd); return fp; } } fclose(part_fd); printf("Could not locate device by label or uuid!\n"); return (NULL); } /* * Check for evms release 2 volumes */ strcpy(device, "/dev/evms"); fp = walk_dir(device, uuid, is_label, is_log, in_use); if (fp != NULL) { if (dev) strcpy(dev, device); return fp; } /* * For RAID, check /proc/mdstat before /proc/partitions. * We don't want to find a device in /proc/partitions that is a * subset of a journal on a raid device */ part_fd = fopen("/proc/mdstat", "r"); if (part_fd) { while (fgets(line, sizeof(line), part_fd)) { char tmp[4]; /* reading tmp requires matching "active" */ if (sscanf(line, "%s : active %1s", part_name, tmp) != 2) continue; sprintf(device, "/dev/%s", part_name); fp = open_check_label(device, uuid, is_label, is_log, in_use); if (fp != NULL) { if (dev) strcpy(dev, device); fclose(part_fd); return fp; } } fclose(part_fd); } /* Nothing yet. Check /proc/partitions */ part_fd = fopen("/proc/partitions", "r"); if (part_fd) { while (fgets(line, sizeof (line), part_fd)) { if (sscanf(line, " %*d %*d %d %s", &size, part_name) != 2) continue; if (size == 1) /* extended partition */ continue; sprintf(device, "/dev/%s", part_name); fp = open_check_label(device, uuid, is_label, is_log, in_use); if (fp != NULL) { if (dev) strcpy(dev, device); fclose(part_fd); return fp; } } fclose(part_fd); } else printf("Could not open /proc/partitions!\n"); /* Not found yet. Check for lvm volumes */ vg_dir = opendir("/proc/lvm/VGs"); if (vg_dir) { seekdir(vg_dir, 2); while ((vg_ent = readdir(vg_dir))) { sprintf(lv_dirname, "/proc/lvm/VGs/%s/LVs", vg_ent->d_name); lv_dir = opendir(lv_dirname); if (lv_dir == NULL) { printf("can't open %s\n", lv_dirname); continue; } seekdir(lv_dir, 2); while ((lv_ent = readdir(lv_dir))) { sprintf(device, "/dev/%s/%s", vg_ent->d_name, lv_ent->d_name); fp = open_check_label(device, uuid, is_label, is_log, in_use); if (fp != NULL) { if (dev) strcpy(dev, device); closedir(lv_dir); closedir(vg_dir); return fp; } } closedir(lv_dir); } closedir(vg_dir); } printf("Could not locate device by label or uuid!\n"); /* #endif */ return (NULL); } jfsutils-1.1.15.orig/libfs/super.c0000644000000000000000000001576010340701413013672 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include "jfs_endian.h" #include "jfs_types.h" #include "jfs_filsys.h" #include "jfs_superblock.h" #include "libjufs.h" #include "devices.h" #include "jfs_dmap.h" #include "utilsubs.h" /* * NAME: inrange * * FUNCTION: Checks to see that is a power-of-2 multiple of that is * less than or equal to . * * PRE CONDITIONS: * * POST CONDITIONS: * * PARAMETERS: * * NOTES: * * DATA STRUCTURES: * * RETURNS: If it is, it returns 1, else 0 */ int inrange(uint32_t num, uint32_t low, uint32_t high) { if (low) { for (; low <= high; low <<= 1) { if (low == num) { return 1; } } } return 0; } /* * NAME: validate_sizes * * FUNCTION: Ensure that all configurable sizes fall within their respective * version specific limits. * * PRE CONDITIONS: * * POST CONDITIONS: * * PARAMETERS: * sb - superblock to check sizes * * NOTES: * * RECOVERY OPERATION: * * DATA STRUCTURES: * * RETURNS: * success: 0 * failure: any other value */ static int validate_sizes(struct superblock *sb) { /* * Make sure AG size is at least 32M */ if (sb->s_agsize >= (1 << L2BPERDMAP)) { return 0; } return EINVAL; } /* * NAME: ujfs_validate_super * * FUNCTION: Check if superblock is valid * * PRE CONDITIONS: * * POST CONDITIONS: * * PARAMETERS: * sb - superblock to validate * * NOTES: * * RECOVERY OPERATION: * * DATA STRUCTURES: * * RETURNS: * success: 0 * failure: LIBFS_CORRUPTSUPER, LIBFS_BADVERSION, LIBFS_BADMAGIC */ int ujfs_validate_super(struct superblock *sb) { if (memcmp(sb->s_magic, JFS_MAGIC, sizeof (sb->s_magic)) == 0) { if (sb->s_version > JFS_VERSION) return LIBFS_BADVERSION; if (validate_sizes(sb) == EINVAL) return LIBFS_CORRUPTSUPER; } else { return LIBFS_BADMAGIC; } return 0; } /* * NAME: ujfs_put_superblk * * FUNCTION: Write primary or secondary aggregate superblock * * PRE CONDITIONS: * * POST CONDITIONS: * * PARAMETERS: * fp - open port for device to write superblock to * sb - pointer to struct superblock to be written * is_primary - 0 value means we are putting the secondary superblock; * non-zero value means we are putting the primary * superblock. * * NOTES: The sizeof(struct superblock) is less than the amount of disk space * being allowed for the superblock (SIZE_OF_SUPER). This function will * write 0's to the space following the actual superblock structure to fill * the entire allocated disk space. * * RECOVERY OPERATION: * * DATA STRUCTURES: * * RETURNS: * success: 0 * failure: any other value */ int ujfs_put_superblk(FILE *fp, struct superblock *sb, int16_t is_primary) { char buf[SIZE_OF_SUPER]; int rc; memset(buf, 0, SIZE_OF_SUPER); memcpy(buf, sb, sizeof (*sb)); /* swap if on big endian machine */ ujfs_swap_superblock((struct superblock *) buf); rc = ujfs_rw_diskblocks(fp, (is_primary ? SUPER1_OFF : SUPER2_OFF), SIZE_OF_SUPER, buf, PUT); return rc; } /* * NAME: ujfs_get_superblk * * FUNCTION: read either the primary or secondary superblock from the specified * device * * PRE CONDITIONS: * * POST CONDITIONS: * * PARAMETERS: * fp - open port for device to read superblock from * sb - pointer to struct superblock to be filled in on return * is_primary - 0 indicates to retrieve secondary superblock, * otherwise retrieve primary superblock * * NOTES: * * RECOVERY OPERATION: * * DATA STRUCTURES: * * RETURNS: * success: 0 * failure: any other value */ int ujfs_get_superblk(FILE *fp, struct superblock *sb, int32_t is_primary) { int rc; char buf[SIZE_OF_SUPER]; struct superblock *sblk = (struct superblock *) buf; rc = ujfs_rw_diskblocks(fp, (is_primary ? SUPER1_OFF : SUPER2_OFF), SIZE_OF_SUPER, sblk, GET); ujfs_swap_superblock(sblk); if (rc != 0) return rc; memcpy(sb, sblk, sizeof (*sb)); return 0; } /* * NAME: ujfs_validate_logsuper * * FUNCTION: Check if log superblock is valid * * PRE CONDITIONS: * * POST CONDITIONS: * * PARAMETERS: * logsup - log superblock to validate * * NOTES: * * RECOVERY OPERATION: * * DATA STRUCTURES: * * RETURNS: * success: 0 * failure: LIBFS_BADVERSION, LIBFS_BADMAGIC */ int ujfs_validate_logsuper(struct logsuper *logsup) { /* see if superblock is JFS log superblock */ if (logsup->magic == LOGMAGIC) { if (logsup->version != LOGVERSION) { return LIBFS_BADVERSION; } } else { return LIBFS_BADMAGIC; } return 0; } /* * NAME: ujfs_put_logsuper * * FUNCTION: Write log superblock to disk * * PRE CONDITIONS: * * POST CONDITIONS: * * PARAMETERS: * fp - open port for device to write superblock to * logsup - pointer to log superblock to be written * * NOTES: * * RECOVERY OPERATION: * * DATA STRUCTURES: * * RETURNS: * success: 0 * failure: any other value */ int ujfs_put_logsuper(FILE *fp, struct logsuper *logsup) { char buf[sizeof (struct logsuper)]; int rc = 0; memcpy(buf, logsup, sizeof (struct logsuper)); /* swap if on big endian machine */ ujfs_swap_logsuper((struct logsuper *) buf); rc = ujfs_rw_diskblocks(fp, LOGPSIZE, sizeof (struct logsuper), buf, PUT); return rc; } /* * NAME: ujfs_get_logsuper * * FUNCTION: read the log superblock from the specified device * * PRE CONDITIONS: * * POST CONDITIONS: * * PARAMETERS: * fp - open port for device to read superblock from * logsup - pointer to log superblock to be filled in on return * * NOTES: * * RECOVERY OPERATION: * * DATA STRUCTURES: * * RETURNS: * success: 0 * failure: any other value */ int ujfs_get_logsuper(FILE *fp, struct logsuper *logsup) { int rc = 0; char buf[sizeof (struct logsuper)]; struct logsuper *logsup_buf = (struct logsuper *) buf; rc = ujfs_rw_diskblocks(fp, LOGPSIZE, sizeof (struct logsuper), logsup_buf, GET); if (!rc) { ujfs_swap_logsuper(logsup_buf); memcpy(logsup, logsup_buf, sizeof (struct logsuper)); } return rc; } jfsutils-1.1.15.orig/libfs/super.h0000644000000000000000000000245210441103235013671 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef H_SUPER #define H_SUPER #include "utilsubs.h" struct superblock; struct logsuper; extern int ujfs_validate_logsuper(struct logsuper *); extern int ujfs_validate_super(struct superblock *); extern int ujfs_put_superblk(FILE *, struct superblock *, int16_t); extern int ujfs_get_superblk(FILE *, struct superblock *, int32_t); extern int ujfs_put_logsuper(FILE *, struct logsuper *); extern int ujfs_get_logsuper(FILE *, struct logsuper *); extern int inrange(uint32_t, uint32_t, uint32_t); #endif jfsutils-1.1.15.orig/libfs/unicode_to_utf8.c0000644000000000000000000000522410340701413015624 0ustar /* The code in this module was taken from: * * linux/fs/nls.c * * Native language support--charsets and unicode translations. * By Gordon Chaffee 1996, 1997 * */ #include #include "unicode_to_utf8.h" /* * Sample implementation from Unicode home page. * http://www.stonehand.com/unicode/standard/fss-utf.html */ struct utf8_table { int cmask; int cval; int shift; long lmask; long lval; }; static struct utf8_table utf8_table[] = { {0x80, 0x00, 0 * 6, 0x7F, 0, /* 1 byte sequence */ }, {0xE0, 0xC0, 1 * 6, 0x7FF, 0x80, /* 2 byte sequence */ }, {0xF0, 0xE0, 2 * 6, 0xFFFF, 0x800, /* 3 byte sequence */ }, {0xF8, 0xF0, 3 * 6, 0x1FFFFF, 0x10000, /* 4 byte sequence */ }, {0xFC, 0xF8, 4 * 6, 0x3FFFFFF, 0x200000, /* 5 byte sequence */ }, {0xFE, 0xFC, 5 * 6, 0x7FFFFFFF, 0x4000000, /* 6 byte sequence */ }, {0, /* end of table */ } }; int Unicode_Character_to_UTF8_Character(uint8_t * s, uint16_t wc, int maxlen) { long l; int c, nc; struct utf8_table *t; if (s == 0) return 0; l = wc; nc = 0; for (t = utf8_table; t->cmask && maxlen; t++, maxlen--) { nc++; if (l <= t->lmask) { c = t->shift; *s = t->cval | (l >> c); while (c > 0) { c -= 6; s++; *s = 0x80 | ((l >> c) & 0x3F); } return nc; } } return -1; } int Unicode_String_to_UTF8_String(uint8_t * s, const uint16_t * pwcs, int maxlen) { const uint16_t *ip; uint8_t *op; int size; op = s; ip = pwcs; while (*ip && maxlen > 0) { if (*ip > 0x7f) { size = Unicode_Character_to_UTF8_Character(op, *ip, maxlen); if (size == -1) { /* Ignore character and move on */ maxlen--; } else { op += size; maxlen -= size; } } else { *op++ = (uint8_t) * ip; maxlen--; } ip++; } return (op - s); } int UTF8_Character_To_Unicode_Character(uint16_t * p, const uint8_t * s, int maxLen) { long l; int c0, c, nc; struct utf8_table *t; nc = 0; c0 = *s; l = c0; for (t = utf8_table; t->cmask; t++) { nc++; if ((c0 & t->cmask) == t->cval) { l &= t->lmask; if (l < t->lval) return -1; *p = l; return nc; } if (maxLen <= nc) return -1; s++; c = (*s ^ 0x80) & 0xFF; if (c & 0xC0) return -1; l = (l << 6) | c; } return -1; } int UTF8_String_To_Unicode_String(uint16_t * pwcs, const uint8_t * s, int maxLen) { uint16_t *op; const uint8_t *ip; int size; op = pwcs; ip = s; while (*ip && maxLen > 0) { if (*ip & 0x80) { size = UTF8_Character_To_Unicode_Character(op, ip, maxLen); if (size == -1) { /* Ignore character and move on */ ip++; maxLen--; } else { op += size; ip += size; maxLen -= size; } } else { *op++ = *ip++; } } return (op - pwcs); } jfsutils-1.1.15.orig/libfs/unicode_to_utf8.h0000644000000000000000000000111707543701237015645 0ustar /* The code in this module was taken from: * * linux/fs/nls.c * * Native language support--charsets and unicode translations. * By Gordon Chaffee 1996, 1997 * */ #ifndef _UNICODE_TO_UTF8_H #define _UNICODE_TO_UTF8_H #include "jfs_types.h" int Unicode_Character_to_UTF8_Character(uint8_t * s, uint16_t wc, int maxlen); int Unicode_String_to_UTF8_String(uint8_t * s, const uint16_t * pwcs, int maxlen); int UTF8_String_To_Unicode_String(uint16_t * pwcs, const uint8_t * s, int maxLen); int UTF8_Character_To_Unicode_Character(uint16_t * p, const uint8_t * s, int maxLen); #endif jfsutils-1.1.15.orig/libfs/uniupr.c0000644000000000000000000001561110340701413014051 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include "jfs_types.h" #include "jfs_unicode.h" /* * Latin upper case */ signed char UniUpperTable[512] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 000-00f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 010-01f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 020-02f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 030-03f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 040-04f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 050-05f */ 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 060-06f */ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, 0, 0, 0, 0, 0, /* 070-07f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 080-08f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 090-09f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0a0-0af */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0b0-0bf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0c0-0cf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0d0-0df */ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 0e0-0ef */ -32, -32, -32, -32, -32, -32, -32, 0, -32, -32, -32, -32, -32, -32, -32, 121, /* 0f0-0ff */ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 100-10f */ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 110-11f */ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 120-12f */ 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 130-13f */ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, /* 140-14f */ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 150-15f */ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 160-16f */ 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1, 0, -1, 0, /* 170-17f */ 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, /* 180-18f */ 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, /* 190-19f */ 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, /* 1a0-1af */ -1, 0, 0, 0, -1, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, /* 1b0-1bf */ 0, 0, 0, 0, 0, -1, -2, 0, -1, -2, 0, -1, -2, 0, -1, 0, /* 1c0-1cf */ -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -79, 0, -1, /* 1d0-1df */ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e0-1ef */ 0, 0, -1, -2, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1, /* 1f0-1ff */ }; /* Upper case range - Greek */ static signed char UniCaseRangeU03a0[47] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -38, -37, -37, -37, /* 3a0-3af */ 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 3b0-3bf */ -32, -32, -31, -32, -32, -32, -32, -32, -32, -32, -32, -32, -64, -63, -63, }; /* Upper case range - Cyrillic */ static signed char UniCaseRangeU0430[48] = { -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 430-43f */ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* 440-44f */ 0, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, 0, -80, -80, /* 450-45f */ }; /* Upper case range - Extended cyrillic */ static signed char UniCaseRangeU0490[61] = { 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 490-49f */ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4a0-4af */ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 4b0-4bf */ 0, 0, -1, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, }; /* Upper case range - Extended latin and greek */ static signed char UniCaseRangeU1e00[509] = { 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e00-1e0f */ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e10-1e1f */ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e20-1e2f */ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e30-1e3f */ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e40-1e4f */ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e50-1e5f */ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e60-1e6f */ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e70-1e7f */ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1e80-1e8f */ 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, -59, 0, -1, 0, -1, /* 1e90-1e9f */ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ea0-1eaf */ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1eb0-1ebf */ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ec0-1ecf */ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ed0-1edf */ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, /* 1ee0-1eef */ 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, /* 1ef0-1eff */ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f00-1f0f */ 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f10-1f1f */ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f20-1f2f */ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f30-1f3f */ 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f40-1f4f */ 0, 8, 0, 8, 0, 8, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f50-1f5f */ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f60-1f6f */ 74, 74, 86, 86, 86, 86, 100, 100, 0, 0, 112, 112, 126, 126, 0, 0, /* 1f70-1f7f */ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f80-1f8f */ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1f90-1f9f */ 8, 8, 8, 8, 8, 8, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fa0-1faf */ 8, 8, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fb0-1fbf */ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fc0-1fcf */ 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fd0-1fdf */ 8, 8, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1fe0-1fef */ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; /* Upper case range - Wide latin */ static signed char UniCaseRangeUff40[27] = { 0, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, /* ff40-ff4f */ -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, -32, }; /* * Upper Case Range */ struct UNICASERANGE UniUpperRange[] = { {0x03a0, 0x03ce, UniCaseRangeU03a0}, {0x0430, 0x045f, UniCaseRangeU0430}, {0x0490, 0x04cc, UniCaseRangeU0490}, {0x1e00, 0x1ffc, UniCaseRangeU1e00}, {0xff40, 0xff5a, UniCaseRangeUff40}, {0, 0, 0} }; jfsutils-1.1.15.orig/libfs/utilsubs.c0000644000000000000000000000313210340701413014374 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include "jfs_types.h" #include "utilsubs.h" /* * log2shift() */ int32_t log2shift(uint32_t n) { uint32_t shift = 0; while (n > 1) { /* n is not power of 2 */ if (n & 1) return -1; shift++; n >>= 1; } return shift; } /* * ui * == */ /* * prompt() */ char prompt(char *str) { char cmd[81]; fputs(str, stdout); fflush(stdout); /* get NULL terminated input */ fgets(cmd, 81, stdin); return cmd[0]; /* return response letter */ } /* * more() */ int more(void) { char cmd[81]; fputs("- hit Enter to continue, e[x]it -", stdout); fflush(stdout); /* get NULL terminated input */ fgets(cmd, 80, stdin); if (cmd[0] == 'x') return 1; /* do NOT continue */ else return 0; /* continue */ } jfsutils-1.1.15.orig/libfs/utilsubs.h0000644000000000000000000000253010441103235014402 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _H_UJFS_UTILSUBS #define _H_UJFS_UTILSUBS #include #include /* * utilsubs.h */ /* * function prototypes */ int32_t log2shift(uint32_t n); char prompt(char *str); int more(void); static inline FILE *fopen_excl(const char *path, const char *mode) { int fd; /* Yeah, mode is ignored, we only use this to open for read/write */ fd = open(path, O_RDWR | O_EXCL, 0); if (fd < 0) return NULL; return fdopen(fd, mode); } int Is_Device_Mounted(char *); int Is_Device_Type_JFS(char *); #endif /* _H_UJFS_UTILSUBS */ jfsutils-1.1.15.orig/logdump/0000755000000000000000000000000011534235600012735 5ustar jfsutils-1.1.15.orig/logdump/Makefile.am0000644000000000000000000000032510320366063014771 0ustar INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/libfs LDADD = ../libfs/libfs.a -luuid sbin_PROGRAMS = jfs_logdump man_MANS = jfs_logdump.8 EXTRA_DIST = $(man_MANS) jfs_logdump_SOURCES = logdump.c helpers.c jfsutils-1.1.15.orig/logdump/Makefile.in0000644000000000000000000004274611534235513015022 0ustar # Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@ 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 = : sbin_PROGRAMS = jfs_logdump$(EXEEXT) subdir = logdump DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)" PROGRAMS = $(sbin_PROGRAMS) am_jfs_logdump_OBJECTS = logdump.$(OBJEXT) helpers.$(OBJEXT) jfs_logdump_OBJECTS = $(am_jfs_logdump_OBJECTS) jfs_logdump_LDADD = $(LDADD) jfs_logdump_DEPENDENCIES = ../libfs/libfs.a DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(jfs_logdump_SOURCES) DIST_SOURCES = $(jfs_logdump_SOURCES) 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' man8dir = $(mandir)/man8 NROFF = nroff MANS = $(man_MANS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_CFLAGS = @AM_CFLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ 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@ LN = @LN@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ 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@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ 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__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ 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@ INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/libfs LDADD = ../libfs/libfs.a -luuid man_MANS = jfs_logdump.8 EXTRA_DIST = $(man_MANS) jfs_logdump_SOURCES = logdump.c helpers.c all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu logdump/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu logdump/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)" @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ 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)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || 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)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) jfs_logdump$(EXEEXT): $(jfs_logdump_OBJECTS) $(jfs_logdump_DEPENDENCIES) @rm -f jfs_logdump$(EXEEXT) $(LINK) $(jfs_logdump_OBJECTS) $(jfs_logdump_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/helpers.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logdump.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` install-man8: $(man_MANS) @$(NORMAL_INSTALL) test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)" @list=''; test -n "$(man8dir)" || exit 0; \ { for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | 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,^[^8][0-9a-z]*$$,8,;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)$(man8dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$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)$(man8dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ done; } uninstall-man8: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man8dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ test -z "$$files" || { \ echo " ( cd '$(DESTDIR)$(man8dir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(man8dir)" && rm -f $$files; } ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ 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 CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ 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" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically \`make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi @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 check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(MANS) installdirs: for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"; 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: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install 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) 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-generic clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ 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-sbinPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man8 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-man uninstall-sbinPROGRAMS uninstall-man: uninstall-man8 .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-sbinPROGRAMS ctags distclean distclean-compile \ distclean-generic distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am 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-man8 install-pdf \ install-pdf-am install-ps install-ps-am install-sbinPROGRAMS \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ tags uninstall uninstall-am uninstall-man uninstall-man8 \ uninstall-sbinPROGRAMS # 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: jfsutils-1.1.15.orig/logdump/helpers.c0000644000000000000000000000610610340701413014540 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * FUNCTIONS: no-frills substitutes for fsck routines * used by logredo modules outside of fsck */ #include #include #include #include #include #include "fsck_message.h" #include "jfs_types.h" #define STDOUT_HANDLE 1 #define STDERR_HANDLE 2 extern short MsgProtocol[][2]; extern char *msgprms[]; extern short msgprmidx[]; extern unsigned long msgs_txt_maxlen; /**************************************************************************** * NAME: alloc_wrksp * * FUNCTION: Allocates and initializes (to guarantee the storage is backed) * dynamic storage for the caller. * * PARAMETERS: * length - input - the number of bytes of storage which are needed * dynstg_object - input - a constant (see xfsck.h) identifying the purpose * for which the storage is needed (Used in error * message if the request cannot be satisfied. * addr_wrksp_ptr - input - the address of a variable in which this routine * will return the address of the dynamic storage * allocated for the caller * * RETURNS: * success: 0 * failure: something else */ int alloc_wrksp(unsigned length, int dynstg_object, int for_logredo, void **addr_wrksp_ptr) { int awsp_rc = 0; unsigned min_length; *addr_wrksp_ptr = NULL; /* initialize return value */ min_length = ((length + 7) / 4) * 4; /* round up to an 4 byte boundary */ *addr_wrksp_ptr = (char *) malloc(min_length); return (awsp_rc); } /***************************************************************************** * NAME: v_fsck_send_msg * * FUNCTION: * * PARAMETERS: * ? - input - * ? - returned - * * RETURNS: * nothing */ int v_fsck_send_msg(int msg_num, const char *file_name, int line_number, ...) { struct fsck_message *message = &msg_defs[msg_num]; char msg_string[max_log_entry_length - 4]; char debug_detail[100]; va_list args; va_start(args, line_number); vsnprintf(msg_string, sizeof(msg_string), message->msg_txt, args); va_end(args); sprintf(debug_detail, " [%s:%d]\n", file_name, line_number); printf(msg_string); printf(debug_detail); return 0; } jfsutils-1.1.15.orig/logdump/jfs_logdump.80000644000000000000000000000276310340701413015341 0ustar .TH jfs_logdump 8 "October 29, 2002" " " "JFS utility - journal log dump" .SH NAME .B jfs_logdump \- dump a JFS formatted device's journal log .SH SYNOPSIS .B jfs_logdump [ -a ] .I device .SH DESCRIPTION .PP .B jfs_logdump dumps the contents of the journal log from the specified JFS formatted device into output file .IR ./jfslog.dmp "." .PP .I device is the special file name corresponding to the actual device from which the journal log will be dumped (e.g. .BR /dev/hdb1 " ). " .PP .B jfs_logdump must be run as root. .SH OPTIONS .TP .B -a Dump the entire contents of the journal log instead of just the committed transactions since the last synch point. .SH EXAMPLE .LP Dump the entire JFS journal log from the 3rd partition of the 2nd hard disk into .IR ./jfslog.dmp : .IP .B jfs_logdump -a /dev/hdb3 .IP .SH REPORTING BUGS .PP If you find a bug in .B JFS or .BR jfs_logdump "," please report it via the bug tracking system ("Report Bugs" section) of the JFS project web site: .nf http://jfs.sourceforge.net/ .fi .PP Please send as much pertinent information as possible, including any .B jfs_logdump error messages and the complete output of running .B jfs_fsck with the .B \-v option on the JFS device. .SH SEE ALSO .BR jfs_fsck (8), .BR jfs_mkfs (8), .BR jfs_fscklog (8), .BR jfs_tune (8), .BR jfs_debugfs (8) .SH AUTHORS .nf Barry Arndt (barndt@us.ibm.com) William Braswell, Jr. .fi .B jfs_logdump is maintained by IBM. .nf See the JFS project web site for more details: http://jfs.sourceforge.net/ .fi jfsutils-1.1.15.orig/logdump/logdump.c0000644000000000000000000001021110340701413014535 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * FUNCTION: dumps the contents of the journal log on the * specified JFS partition into "./jfslog.dmp" */ #include #include #include #include #include #include #include #include #include #include "jfs_types.h" #include "devices.h" #include "jfs_version.h" #define LOGDMP_OK 0 #define LOGDMP_FAILED -1 #define FULLLOG -1 #define CURRLOG 1 int jfs_logdump(char *, FILE *, int); int parse_parms(int, char **); char log_device[1]; /* This avoids linker error */ /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * Device information. * * values are assigned when (if) the device is opened. */ FILE *Dev_IOPort; unsigned Dev_blksize; char *Vol_Label = NULL; int dump_all = 0; /* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * * For message processing in called routines * */ extern caddr_t prog; extern void fsck_send_msg(int, int); /* defined in fsckmsg.c */ extern int alloc_wrksp(unsigned, int, int, void **); /* defined in fsckwsp.c */ /**************************************************************************** * * NAME: main * * FUNCTION: call jfs_logdump() * * INTERFACE: * jfs_logdump [-a] * * where -a => dump entire contents of log instead of just * committed transactions since last synch point. * * RETURNS: * success: 0 * failure: something else */ int main(int argc, char **argv) { int rc = LOGDMP_OK; printf("jfs_logdump version %s, %s\n", VERSION, JFSUTILS_DATE); prog = "jfs_logdump"; rc = parse_parms(argc, argv); /* parse the parms and record * them in the aggregate wsp record */ if (rc != 0) return 0; printf("Device Name: %s\n", Vol_Label); Dev_IOPort = fopen(Vol_Label, "r"); if (Dev_IOPort == NULL) { fprintf(stderr, "Error: Cannot open device %s, rc = %d.\n", Vol_Label, rc); return (-1); } jfs_logdump(Vol_Label, Dev_IOPort, dump_all); return fclose(Dev_IOPort); } /***************************************************************************** * NAME: parse_parms * * FUNCTION: Parse the invocation parameters. If any unrecognized * parameters are detected, or if any required parameter is * omitted, issue a message and exit. * * PARAMETERS: as specified to main() * * RETURNS: * success: LOGDMP_OK * failure: something else */ int parse_parms(int argc, char **argv) { int pp_rc = LOGDMP_OK; int i = 0; char *argp; for (i = 1; i < argc; i++) { /* for all parms on command line */ argp = argv[i]; if (*argp == '-') { /* leading - */ argp++; if (*argp == 'a' || *argp == 'A') { /* debug */ /* * Dump entire log Option */ dump_all = -1; } else { /* * unrecognized keyword parm */ printf("JFS_LOGDUMP: unrecognized keyword detected: %s\n", argp); return (LOGDMP_FAILED); } } else if (argp[0] == '/') { /* 2nd char is / */ Vol_Label = argp; } else { /* unrecognized parm */ printf("JFS_LOGDUMP: unsupported parameter detected: %s\n", argp); return (LOGDMP_FAILED); } } if (Vol_Label == NULL) { /* no device specified */ printf("Error: no device given.\n"); printf("Usage: jfs_logdump [-a] \n"); return (LOGDMP_FAILED); } return (pp_rc); } jfsutils-1.1.15.orig/missing0000755000000000000000000002623311460142743012676 0ustar #! /bin/sh # Common stub for a few missing GNU programs while installing. scriptversion=2009-04-28.21; # UTC # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, # 2008, 2009 Free Software Foundation, Inc. # Originally 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 run=: sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' sed_minuso='s/.* -o \([^ ]*\).*/\1/p' # In the cases where this matters, `missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi msg="missing on your system" case $1 in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 # Exit code 63 means version mismatch. This often happens # when the user try to use an ancient version of a tool on # a file that requires a minimum version. In this case we # we should proceed has if the program had been absent, or # if --run hadn't been passed. if test $? = 63; then run=: msg="probably too old" fi ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' autom4te touch the output file, or create a stub one automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file tar try tar, gnutar, gtar, then tar without non-portable flags yacc create \`y.tab.[ch]', if possible, from existing .[ch] 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 # normalize program name to check for. program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` # Now exit if we have it, but it failed. Also exit now if we # don't have it and --version was passed (most likely to detect # the program). This is about non-GNU programs, so use $1 not # $program. case $1 in lex*|yacc*) # Not GNU programs, they don't have --version. ;; tar*) if test -n "$run"; then echo 1>&2 "ERROR: \`tar' requires --run" exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then exit 1 fi ;; *) if test -z "$run" && ($1 --version) > /dev/null 2>&1; then # We have it, but it failed. exit 1 elif test "x$2" = "x--version" || test "x$2" = "x--help"; then # Could not run --version or --help. This is probably someone # running `$TOOL --version' or `$TOOL --help' to check whether # $TOOL exists and not knowing $TOOL uses missing. exit 1 fi ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case $program in aclocal*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case $f in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; autom4te*) echo 1>&2 "\ WARNING: \`$1' is needed, but is $msg. You might have modified some files without having the proper tools for further handling them. You can get \`$1' as part of \`Autoconf' from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo "#! /bin/sh" echo "# Created by GNU Automake missing as a replacement of" echo "# $ $@" echo "exit 0" chmod +x $file exit 1 fi ;; bison*|yacc*) echo 1>&2 "\ WARNING: \`$1' $msg. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if test $# -ne 1; then eval LASTARG="\${$#}" case $LASTARG in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if test -f "$SRCFILE"; then cp "$SRCFILE" y.tab.h fi ;; esac fi if test ! -f y.tab.h; then echo >y.tab.h fi if test ! -f y.tab.c; then echo 'main() { return 0; }' >y.tab.c fi ;; lex*|flex*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if test $# -ne 1; then eval LASTARG="\${$#}" case $LASTARG in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if test -f "$SRCFILE"; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if test ! -f lex.yy.c; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a dependency of a manual page. You may need the \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -f "$file"; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit $? fi ;; makeinfo*) echo 1>&2 "\ WARNING: \`$1' is $msg. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." # The file to touch is that specified with -o ... file=`echo "$*" | sed -n "$sed_output"` test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` if test -z "$file"; then # ... or it is the one specified with @setfilename ... infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n ' /^@setfilename/{ s/.* \([^ ]*\) *$/\1/ p q }' $infile` # ... or it is derived from the source name (dir/f.texi becomes f.info) test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info fi # If the file does not exist, the user really needs makeinfo; # let's fail without touching anything. test -f $file || exit 1 touch $file ;; tar*) shift # We have already tried tar in the generic part. # Look for gnutar/gtar before invocation to avoid ugly error # messages. if (gnutar --version > /dev/null 2>&1); then gnutar "$@" && exit 0 fi if (gtar --version > /dev/null 2>&1); then gtar "$@" && exit 0 fi firstarg="$1" if shift; then case $firstarg in *o*) firstarg=`echo "$firstarg" | sed s/o//` tar "$firstarg" "$@" && exit 0 ;; esac case $firstarg in *h*) firstarg=`echo "$firstarg" | sed s/h//` tar "$firstarg" "$@" && exit 0 ;; esac fi echo 1>&2 "\ WARNING: I can't seem to be able to run \`tar' with the given arguments. You may want to install GNU tar or Free paxutils, or check the command line arguments." exit 1 ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and is $msg. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequisites for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 # 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: jfsutils-1.1.15.orig/mkfs/0000755000000000000000000000000011534235600012226 5ustar jfsutils-1.1.15.orig/mkfs/Makefile.am0000644000000000000000000000111210441103235014247 0ustar INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/libfs LDADD = ../libfs/libfs.a -luuid AM_CPPFLAGS = -DONE_FILESET_PER_AGGR sbin_PROGRAMS = jfs_mkfs man_MANS = jfs_mkfs.8 EXTRA_DIST = $(man_MANS) jfs_mkfs_SOURCES = initmap.c inodemap.c inodes.c mkfs.c initmap.h \ inodemap.h inodes.h install-exec-hook: $(LN) -f $(DESTDIR)$(sbindir)/jfs_mkfs $(DESTDIR)$(sbindir)/mkfs.jfs install-data-hook: $(LN) -f $(DESTDIR)$(man8dir)/jfs_mkfs.8 $(DESTDIR)$(man8dir)/mkfs.jfs.8 uninstall-local: rm -f $(DESTDIR)$(sbindir)/mkfs.jfs rm -f $(DESTDIR)$(man8dir)/mkfs.jfs.8 jfsutils-1.1.15.orig/mkfs/Makefile.in0000644000000000000000000004427511534235513014312 0ustar # Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@ 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 = : sbin_PROGRAMS = jfs_mkfs$(EXEEXT) subdir = mkfs DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)" PROGRAMS = $(sbin_PROGRAMS) am_jfs_mkfs_OBJECTS = initmap.$(OBJEXT) inodemap.$(OBJEXT) \ inodes.$(OBJEXT) mkfs.$(OBJEXT) jfs_mkfs_OBJECTS = $(am_jfs_mkfs_OBJECTS) jfs_mkfs_LDADD = $(LDADD) jfs_mkfs_DEPENDENCIES = ../libfs/libfs.a DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(jfs_mkfs_SOURCES) DIST_SOURCES = $(jfs_mkfs_SOURCES) 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' man8dir = $(mandir)/man8 NROFF = nroff MANS = $(man_MANS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_CFLAGS = @AM_CFLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ 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@ LN = @LN@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ 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@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ 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__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ 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@ INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/libfs LDADD = ../libfs/libfs.a -luuid AM_CPPFLAGS = -DONE_FILESET_PER_AGGR man_MANS = jfs_mkfs.8 EXTRA_DIST = $(man_MANS) jfs_mkfs_SOURCES = initmap.c inodemap.c inodes.c mkfs.c initmap.h \ inodemap.h inodes.h all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu mkfs/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu mkfs/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)" @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ 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)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || 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)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) jfs_mkfs$(EXEEXT): $(jfs_mkfs_OBJECTS) $(jfs_mkfs_DEPENDENCIES) @rm -f jfs_mkfs$(EXEEXT) $(LINK) $(jfs_mkfs_OBJECTS) $(jfs_mkfs_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initmap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inodemap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inodes.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkfs.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` install-man8: $(man_MANS) @$(NORMAL_INSTALL) test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)" @list=''; test -n "$(man8dir)" || exit 0; \ { for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | 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,^[^8][0-9a-z]*$$,8,;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)$(man8dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$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)$(man8dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ done; } uninstall-man8: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man8dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ test -z "$$files" || { \ echo " ( cd '$(DESTDIR)$(man8dir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(man8dir)" && rm -f $$files; } ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) set x; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ 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 CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ 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" distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @list='$(MANS)'; if test -n "$$list"; then \ list=`for p in $$list; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ if test -n "$$list" && \ grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ echo " typically \`make maintainer-clean' will remove them" >&2; \ exit 1; \ else :; fi; \ else :; fi @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 check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) $(MANS) installdirs: for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"; 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: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install 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) 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-generic clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-man @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-data-hook install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-sbinPROGRAMS @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-exec-hook install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man8 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-local uninstall-man uninstall-sbinPROGRAMS uninstall-man: uninstall-man8 .MAKE: install-am install-data-am install-exec-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-sbinPROGRAMS ctags distclean distclean-compile \ distclean-generic distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-data-hook install-dvi install-dvi-am \ install-exec install-exec-am install-exec-hook install-html \ install-html-am install-info install-info-am install-man \ install-man8 install-pdf install-pdf-am install-ps \ install-ps-am install-sbinPROGRAMS install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ uninstall-am uninstall-local uninstall-man uninstall-man8 \ uninstall-sbinPROGRAMS install-exec-hook: $(LN) -f $(DESTDIR)$(sbindir)/jfs_mkfs $(DESTDIR)$(sbindir)/mkfs.jfs install-data-hook: $(LN) -f $(DESTDIR)$(man8dir)/jfs_mkfs.8 $(DESTDIR)$(man8dir)/mkfs.jfs.8 uninstall-local: rm -f $(DESTDIR)$(sbindir)/mkfs.jfs rm -f $(DESTDIR)$(man8dir)/mkfs.jfs.8 # 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: jfsutils-1.1.15.orig/mkfs/initmap.c0000644000000000000000000010741611304744426014052 0ustar /* * Copyright (C) International Business Machines Corp., 2000-2005 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define _GNU_SOURCE /* FOR O_DIRECT */ #include #include "jfs_types.h" #include #include #include #include #include #include #include #include "jfs_endian.h" #include "jfs_filsys.h" #include "jfs_dinode.h" #include "devices.h" #include "inodes.h" #include "jfs_dmap.h" #include "diskmap.h" #include "inode.h" #include "initmap.h" #include "message.h" #include "utilsubs.h" extern unsigned type_jfs; #define UZWORD (0x80000000u) #define DBBYTE 8 /* number of bits per byte */ #define L2DBBYTE 3 /* log2 of number of bits per byte */ #define CHAR_ONES (0xffu) static struct dmap **block_map_array; static unsigned sz_block_map_array; static unsigned cur_dmap_index; static struct dbmap *control_page; static int64_t last_allocated; static struct dmap *empty_page; struct xtree_buf { struct xtree_buf *down; /* next rightmost child */ struct xtree_buf *up; /* parent */ xtpage_t *page; }; static struct xtree_buf *badblock_pages; static int xtAppend(FILE *, struct dinode *, int64_t, int64_t, int, struct xtree_buf *, int); /*-------------------------------------------------------------------- * NAME: initdmap() * * FUNCTION: Initialize a dmap for the specified block range * (blkno thru blkno+nblocks-1). * * PARAMETERS: * dev_ptr - device to write map page to * blkno - Starting disk block number to be covered by this dmap. * nblocks - Number of blocks covered by this dmap. * treemax - Return value set as maximum free string found in this dmap * start - Logical block address of where this dmap should live on disk. * * NOTES: The wmap and pmap words along the leaves of the dmap tree are * initialized, with the leaves initialized to the maximum free string of * the wmap word they describe. With this complete ujfs_adjtree() is * called to combine all appropriate buddies and update the higher level of * the tree to reflect the result of the buddy combination. The maximum * free string of the dmap (i.e. the root value of the tree) is returned * in treemax. * * RETURNS: NONE */ static int initdmap(FILE *dev_ptr, int64_t blkno, int64_t nblocks, int8_t * treemax, int64_t start) { int rc = 0; /* * Determine if the dmap already exists */ if (block_map_array[cur_dmap_index] == NULL) { if (nblocks == BPERDMAP) { /* * alloc/init a template empty full page buffer */ if (empty_page == NULL) { empty_page = malloc(sizeof (struct dmap)); if (empty_page == NULL) { message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, OSO_MSG); return (ENOMEM); } memset(empty_page, 0, sizeof (struct dmap)); ujfs_idmap_page(empty_page, nblocks); ujfs_complete_dmap(empty_page, blkno, treemax); } else { /* * customize/reuse the template empty page */ empty_page->start = blkno; *treemax = empty_page->tree.stree[0]; } block_map_array[cur_dmap_index] = empty_page; } else { /* * alloc/init a special dmap page with the correct size */ block_map_array[cur_dmap_index] = malloc(sizeof (struct dmap)); if (block_map_array[cur_dmap_index] == NULL) { message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, OSO_MSG); return (ENOMEM); } memset(block_map_array[cur_dmap_index], 0, sizeof (struct dmap)); ujfs_idmap_page(block_map_array[cur_dmap_index], nblocks); ujfs_complete_dmap(block_map_array[cur_dmap_index], blkno, treemax); } } else { /* * Fill in rest of fields of special existing dmap page */ ujfs_complete_dmap(block_map_array[cur_dmap_index], blkno, treemax); } /* * Write the dmap page and free if special buffer */ /* swap if on big endian machine */ ujfs_swap_dmap(block_map_array[cur_dmap_index]); rc = ujfs_rw_diskblocks(dev_ptr, start, PSIZE, block_map_array[cur_dmap_index], PUT); ujfs_swap_dmap(block_map_array[cur_dmap_index]); if (rc != 0) return rc; if (block_map_array[cur_dmap_index] != empty_page) { free(block_map_array[cur_dmap_index]); } cur_dmap_index++; return (rc); } /*-------------------------------------------------------------------- * NAME: initctl() * * FUNCTION: Initialize a dmapctl for the specified block range * (blkno thru blkno+nblocks-1) and * level and initialize all dmapctls and dmaps under this dmapctl. * * PARAMETERS: * dev_ptr - device to write page to * blkno - Starting disk block number to be covered by this dmapctl. * nblocks - Number of blocks covered by this dmapctl. * level - The level of this dmapctl. * treemax - Return value set as the maximum free string found in this * dmapctl. * start - Logical block address of where this page should live on disk. * * NOTES: This routine is called recursively. On first invocation it is called * for the top level dmapctl of the tree. For each leaf of the dmapctl, * the lower level dmap (level == 0) or dmapctl (level > 0) is created for * the block range covered by the leaf and the leaf is set to the maximum * free string found in the lower level object. If the lower level object * is a dmap, initdmap() is called to handle it's initialization. * Otherwise, initctl() is called recursively to initialize the lower level * dmapctl with the level specified as the current level - 1; once all * leaves have been initialized ujfs_adjtree() is called to combine all * appropriate buddies and update the higher level of the tree to reflect * the result of the buddy combination. The maximum free string of the * dmapctl (i.e. the root value of the tree) is returned in treemax. * * RETURNS: None. */ static int initctl(FILE *dev_ptr, int64_t blkno, int64_t nblocks, int level, int8_t * treemax, int64_t * start) { int index, rc = 0, l2cblks, nchild; int8_t *cp, max; struct dmapctl *dcp; int64_t nb, cblks; int64_t next_page; /* * alloc/init current level dmapctl page buffer */ dcp = malloc(sizeof (struct dmapctl)); if (dcp == NULL) { message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, OSO_MSG); return (ENOMEM); } memset(dcp, 0, sizeof (struct dmapctl)); dcp->height = 5; dcp->leafidx = CTLLEAFIND; dcp->nleafs = LPERCTL; dcp->l2nleafs = L2LPERCTL; dcp->budmin = L2BPERDMAP + level * L2LPERCTL; /* Pick up the pointer to the first leaf of the dmapctl tree */ cp = dcp->stree + dcp->leafidx; /* * Determine how many lower level dmapctls or dmaps will be described by * this dmapctl based upon the number of blocks covered by this dmapctl. */ l2cblks = L2BPERDMAP + level * L2LPERCTL; cblks = (1LL << l2cblks); nchild = nblocks >> l2cblks; nchild = (nblocks & (cblks - 1)) ? nchild + 1 : nchild; next_page = *start + PSIZE; for (index = 0; index < nchild; index++, nblocks -= nb, blkno += nb) { /* * Determine how many blocks the lower level dmapctl or dmap will cover. */ nb = MIN(cblks, nblocks); /* * If this is a level 0 dmapctl, initialize the dmap for the * block range (i.e. blkno thru blkno+nb-1). Otherwise, * initialize the lower level dmapctl for this block range. * In either case, the pointer to the leaf covering this block * range is passed down and will be set to the length of the * maximum free string of blocks found at the lower level. */ if (level == 0) { rc += initdmap(dev_ptr, blkno, nb, cp + index, next_page); next_page += PSIZE; } else { rc += initctl(dev_ptr, blkno, nb, level - 1, cp + index, &next_page); } } /* * Initialize the leaves for this dmapctl that were not covered by the * specified input block range (i.e. the leaves have no low level * dmapctl or dmap. */ for (; index < LPERCTL; index++) { *(cp + index) = NOFREE; } /* * With the leaves initialized, adjust the tree for this dmapctl. */ max = ujfs_adjtree(dcp->stree, L2LPERCTL, l2cblks); /* * Write and release the dmapctl page */ /* swap if on big endian machine */ ujfs_swap_dmapctl(dcp); rc += ujfs_rw_diskblocks(dev_ptr, *start, PSIZE, dcp, PUT); free(dcp); /* * Set the treemax return value with the maximum free described by * this dmapctl. */ *treemax = max; *start = next_page; return (rc); } /*-------------------------------------------------------------------- * NAME: initbmap() * * FUNCTION: Initialize the disk block allocation map for an aggregate. * * PARAMETERS: * dev_ptr - device to write page to * nblocks - Number of blocks within the aggregate. * * NOTES: The bmap control page is created. Next, the number dmapctl level * required to described the aggregate size (number of blocks within the * aggregate) is determined. initctl() is then called to initialize the * appropriate dmapctl levels and corresponding dmaps. * * RETURNS: */ static int initbmap(FILE *dev_ptr, int64_t nblocks) { int level, rc = 0; int64_t next_page; /* * get the level for the actual top dmapctl for the aggregate and * its physical address (N.B. map file has been allocated * to cover full control level hierarchy); */ level = BMAPSZTOLEV(nblocks); next_page = BMAP_OFF + PSIZE + PSIZE * (2 - level); /* * initialize only the dmapctls and the dmaps they describe * that covers the actual aggregate size. */ rc = initctl(dev_ptr, 0, nblocks, level, &control_page->dn_maxfreebud, &next_page); if (rc != 0) return (rc); /* * Write the control page to disk. */ /* swap if on big endian machine */ ujfs_swap_dbmap(control_page); rc = ujfs_rw_diskblocks(dev_ptr, BMAP_OFF, PSIZE, control_page, PUT); ujfs_swap_dbmap(control_page); return (rc); } /*-------------------------------------------------------------------- * NAME: alloc_map() * * FUNCTION: Allocate and initialize to zero the memory for dmap pages * and the control page of block map. * * PARAMETERS: * num_dmaps - Indicates number of dmaps to allocate * * DATA STRUCTURES: Initializes file static variable block_map * * RETURNS: 0 for success */ static int alloc_map(int num_dmaps) { if (num_dmaps <= 0) return EINVAL; /* alloc/init dmap page pointer array */ block_map_array = malloc(num_dmaps * sizeof (struct dmap *)); if (block_map_array == NULL) { message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, OSO_MSG); return ENOMEM; } sz_block_map_array = num_dmaps; memset(block_map_array, 0, num_dmaps * sizeof (struct dmap *)); /* alloc/init control page */ control_page = malloc(sizeof (struct dbmap)); if (control_page == NULL) { message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, OSO_MSG); return ENOMEM; } memset(control_page, 0, sizeof (struct dbmap)); return 0; } /*-------------------------------------------------------------------- * NAME: initmap() * * FUNCTION: Initialize control page * * PARAMETERS: * nblocks - Number of blocks covered by this map * ag_size - Will be filled in with AG size in blocks * aggr_block_size - Aggregate block size * * RETURNS: NONE */ static void initmap(int64_t nblocks, int *ag_size, int aggr_block_size) { int index, l2nl, n; int64_t nb; /* * Initialize base information */ control_page->dn_l2nbperpage = log2shift(PSIZE / aggr_block_size); control_page->dn_mapsize = control_page->dn_nfree = nblocks; control_page->dn_maxlevel = BMAPSZTOLEV(nblocks); /* control_page->dn_maxfreebud is computed at finalization */ /* * Initialize allocation group information. */ control_page->dn_agl2size = ujfs_getagl2size(nblocks, aggr_block_size); *ag_size = control_page->dn_agsize = (int64_t) 1 << control_page->dn_agl2size; control_page->dn_numag = nblocks / control_page->dn_agsize; control_page->dn_numag += (nblocks % control_page->dn_agsize) ? 1 : 0; for (index = 0, nb = nblocks; index < control_page->dn_numag; index++, nb -= *ag_size) { control_page->dn_agfree[index] = MIN(nb, *ag_size); } control_page->dn_aglevel = BMAPSZTOLEV(control_page->dn_agsize); l2nl = control_page->dn_agl2size - (L2BPERDMAP + control_page->dn_aglevel * L2LPERCTL); control_page->dn_agheigth = l2nl >> 1; control_page->dn_agwidth = 1 << (l2nl - (control_page->dn_agheigth << 1)); for (index = 5 - control_page->dn_agheigth, control_page->dn_agstart = 0, n = 1; index > 0; index--) { control_page->dn_agstart += n; n <<= 2; } /* control_page->dn_maxag is computed at finalization */ control_page->dn_agpref = 0; } /*-------------------------------------------------------------------- * NAME: calc_map_size() * * FUNCTION: Calculates the size of a block map and * initializes memory for dmap pages of map. * Later when we are ready to write the map to disk * we will initialize the rest of the map pages. * * N.B. map file is ALLOCATED as a single extent * of physical pages covering full control level (L2) * tree control pages for the dmap pages required: * the tree will be INITIALIZED to cover only the * the dmap pages required; * * PARAMETERS: * number_of_blocks - Number of blocks in aggregate * aggr_inodes - Array of aggregate inodes * aggr_block_size - Aggregate block size * ag_size - Will be filled in with AG size in blocks * inostamp - Inode stamp value to be used. * * RETURNS: 0 for success */ int calc_map_size(int64_t number_of_blocks, struct dinode *aggr_inodes, int aggr_block_size, int *ag_size, unsigned inostamp) { int rc = 0; int64_t npages, ndmaps, nl0pages; int64_t nb_diskmap; int64_t size_of_map; int64_t location; /* * compute the number dmap pages required to cover number_of_blocks; * add one extra dmap page for extendfs(): this is added before * we figure out how many control pages are needed, so we get * the correct number of control pages. */ npages = ndmaps = ((number_of_blocks + BPERDMAP - 1) >> L2BPERDMAP) + 1; /* * Make sure the number of dmaps needed is within the supported range */ if ((((int64_t) ndmaps) << L2BPERDMAP) > MAXMAPSIZE) return (EINVAL); /* * compute number of (logical) control pages at each level of the map */ /* account for L0 pages to cover dmap pages */ nl0pages = (ndmaps + LPERCTL - 1) >> L2LPERCTL; npages += nl0pages; if (nl0pages > 1) { /* account for one L2 and actual L1 pages to cover L0 pages */ npages += 1 + ((nl0pages + LPERCTL - 1) >> L2LPERCTL); } else { /* account for one logical L2 and one logical L1 pages */ npages += 2; } /* account for global control page of map */ npages++; /* * init the block allocation map inode */ size_of_map = npages << L2PSIZE; nb_diskmap = size_of_map / aggr_block_size; location = BMAP_OFF / aggr_block_size; init_inode(&(aggr_inodes[BMAP_I]), AGGREGATE_I, /* di_fileset */ BMAP_I, /* di_number */ nb_diskmap, /* di_nblocks */ size_of_map, /* di_size */ location, IFJOURNAL | IFREG, /* di_mode */ max_extent_data, AITBL_OFF / aggr_block_size, aggr_block_size, inostamp); /* * Allocate dmap pages and initialize them for the aggregate blocks */ if ((rc = alloc_map(ndmaps)) != 0) return rc; initmap(number_of_blocks, ag_size, aggr_block_size); /* * reset last_allocated to ignore the fsck working space */ last_allocated = 0; return 0; } /*-------------------------------------------------------------------- * NAME: markit() * * FUNCTION: Mark specified block allocated/unallocated in block map * * PARAMETERS: * block - Map object to set or clear * flag - Indicates ALLOCATE or FREE of block. Indicates if block is * bad. * * RETURNS: NONE */ int markit(int64_t block, unsigned flag) { int page, rem, word, bit; struct dmap *p1; int agno; int64_t num_blocks_left, nb; /* * Keep track of the last allocated block to be filled into block map * inode. Don't update last allocated for bad blocks. */ if (block > last_allocated && !(flag & BADBLOCK)) { last_allocated = block; } /* * calculate page number in map, and word and bit number in word. */ page = block / BPERDMAP; rem = block - page * BPERDMAP; word = rem >> L2DBWORD; bit = rem - (word << L2DBWORD); if (page > sz_block_map_array) { fprintf(stderr, "Internal error: %s(%d): Trying to mark block which doesn't exist.\n", __FILE__, __LINE__); return (-1); } /* * Determine if this dmap page has been allocated yet */ if (block_map_array[page] == NULL) { num_blocks_left = control_page->dn_mapsize - (page * BPERDMAP); nb = MIN(BPERDMAP, num_blocks_left); block_map_array[page] = malloc(sizeof (struct dmap)); if (block_map_array[page] == NULL) { message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, OSO_MSG); return (ENOMEM); } memset(block_map_array[page], 0, sizeof (struct dmap)); ujfs_idmap_page(block_map_array[page], nb); } p1 = block_map_array[page]; agno = block >> control_page->dn_agl2size; /* * now we process the first word. */ if (flag & ALLOC) { p1->pmap[word] |= (UZWORD >> bit); p1->wmap[word] |= (UZWORD >> bit); /* * Update the stats */ p1->nfree--; control_page->dn_nfree--; control_page->dn_agfree[agno]--; } else { p1->pmap[word] &= ~(UZWORD >> bit); p1->wmap[word] &= ~(UZWORD >> bit); /* * Update the stats */ p1->nfree++; control_page->dn_nfree++; control_page->dn_agfree[agno]++; } return (0); } /*-------------------------------------------------------------------- * NAME: write_block_map() * * FUNCTION: Update tree part of block map to match rest of map and * then write the block map to disk. * Also write the block map inode to disk. * * PARAMETERS: * dev_ptr - open port of device to write map to * size_of_map - size of map * aggr_block_size - size of an aggregate block in bytes * * RETURNS: 0 for success */ int write_block_map(FILE *dev_ptr, int64_t number_of_blocks, int aggr_block_size) { int rc = 0; /* * At this point all of the dmaps have been initialized except for their * trees. Now we need to build the other levels of the map and adjust * the tree for each of the dmaps. */ cur_dmap_index = 0; control_page->dn_maxag = last_allocated / control_page->dn_agsize; rc = initbmap(dev_ptr, number_of_blocks); return rc; } /*-------------------------------------------------------------------- * NAME: dbAlloc * * FUNCTION: Allocate the specified number of blocks * * PARAMETERS: * xlen - Number of blocks to allocate * xaddr - On return, filled in with starting block number of allocated * blocks * * NOTES: * This function is only called when adding blocks to the Bad Block Inode * required a page for an xtree node. LVM Bad Block processing must * be in effect during this allocation. This will not be the case if format * is processing /L. So, at entry to this routine, we check to see whether * the LVM Bad Block processing is enabled and, if not, we enable it. * At exit from this routine the LVM Bad Block processing will be as it * was (i.e., enabled or disabled) on entry. * * RETURNS: 0 for success; Other indicates failure */ static int dbAlloc(FILE *dev_ptr, int64_t xlen, int64_t * xaddr) { int rc = 0; int page, word; struct dmap *p1; int64_t last_block, index; unsigned mask, cmap; int bitno; int l2nb; int8_t leafw; /* * Start looking at last block allocated for a contiguous extent of xlen * blocks. Since we may have bad blocks intermixed we can't just * take blocks starting at the last block allocated. However, * last_allocated won't be updated with bad blocks, so it will be the * start of the real last place to start looking. Once found, mark them * allocated and return the starting address in xaddr */ l2nb = log2shift(xlen); for (page = last_allocated / BPERDMAP, word = (last_allocated & (BPERDMAP - 1)) >> L2DBWORD; page < sz_block_map_array; page++, word = 0) { /* * Determine if this dmap page has been allocated yet; if not we * can take the first blocks from it for our allocation since we * know all the blocks in it are free. (markit will handle * allocating the page for us, so we don't have to do that here.) */ if (block_map_array[page] == NULL) { *xaddr = page << L2BPERDMAP; last_block = *xaddr + xlen; for (index = *xaddr; ((index < last_block) && (rc == 0)); index++) { rc = markit(index, ALLOC); } if (rc != 0) { return rc; } return 0; } /* * We have a dmap page which has had allocations before, we need * to check for free blocks starting with to the end of * this dmap page. If we don't find it in this page we will go * on to the next page. */ p1 = block_map_array[page]; for (; word < LPERDMAP; word++) { /* * Determine if the leaf describes sufficient free space. * Since we have not yet completed the block map * initialization we will have to compute this on the-fly. */ leafw = ujfs_maxbuddy((char *) &p1->wmap[word]); if (leafw < l2nb) continue; /* * We know this word has sufficient free space, find it * and allocate it */ *xaddr = (page << L2BPERDMAP) + (word << L2DBWORD); if (leafw < BUDMIN) { mask = ONES << (DBWORD - xlen); cmap = ~(p1->wmap[word]); /* scan the word for xlen free bits */ for (bitno = 0; mask != 0; bitno++, mask >>= 1) { if ((mask & cmap) == mask) break; } *xaddr += bitno; } /* Allocate the blocks */ last_block = *xaddr + xlen; for (index = *xaddr; ((index < last_block) && (rc == 0)); index++) { rc = markit(index, ALLOC); } if (rc != 0) { return (rc); } return 0; } } return 1; } /*-------------------------------------------------------------------- * NAME: xtSplitRoot * * FUNCTION: Split full root of xtree * * PARAMETERS: * dev_ptr - Device handle * ip - Inode of xtree * xroot - Root of xtree * offset - Offset of extent to add * nblocks - number of blocks for extent to add * blkno - starting block of extent to add * * RETURNS: 0 for success; Other indicates failure */ static int xtSplitRoot(FILE *dev_ptr, struct dinode *ip, struct xtree_buf *xroot, int64_t offset, int nblocks, int64_t blkno) { xtpage_t *rootpage; xtpage_t *newpage; int64_t xaddr; int nextindex; xad_t *xad; int rc = 0; struct xtree_buf *newbuf; int xlen; /* Allocate and initialize buffer for new page to accomodate the split */ newbuf = malloc(sizeof (struct xtree_buf)); if (newbuf == NULL) { message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, OSO_MSG); return (ENOMEM); } newbuf->up = xroot; if (xroot->down == NULL) { badblock_pages = newbuf; } else { xroot->down->up = newbuf; } newbuf->down = xroot->down; xroot->down = newbuf; newpage = newbuf->page = malloc(PSIZE); if (newpage == NULL) { message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, OSO_MSG); return (ENOMEM); } /* Allocate disk blocks for new page */ xlen = 1 << control_page->dn_l2nbperpage; if ((rc = dbAlloc(dev_ptr, xlen, &xaddr))) return rc; rootpage = xroot->page; /* Initialize new page */ newpage->header.flag = (rootpage->header.flag & BT_LEAF) ? BT_LEAF : BT_INTERNAL; PXDlength(&(newpage->header.self), xlen); PXDaddress(&(newpage->header.self), xaddr); newpage->header.nextindex = XTENTRYSTART; newpage->header.maxentry = PSIZE >> L2XTSLOTSIZE; /* initialize sibling pointers */ newpage->header.next = 0; newpage->header.prev = 0; /* copy the in-line root page into new right page extent */ nextindex = rootpage->header.maxentry; memcpy(&newpage->xad[XTENTRYSTART], &rootpage->xad[XTENTRYSTART], (nextindex - XTENTRYSTART) << L2XTSLOTSIZE); /* insert the new entry into the new right/child page */ xad = &newpage->xad[nextindex]; XADoffset(xad, offset); XADlength(xad, nblocks); XADaddress(xad, blkno); /* update page header */ newpage->header.nextindex = nextindex + 1; /* init root with the single entry for the new right page */ xad = &rootpage->xad[XTENTRYSTART]; XADoffset(xad, 0); XADlength(xad, xlen); XADaddress(xad, xaddr); /* update page header of root */ rootpage->header.flag &= ~BT_LEAF; rootpage->header.flag |= BT_INTERNAL; rootpage->header.nextindex = XTENTRYSTART + 1; /* Update nblocks for inode to account for new page */ ip->di_nblocks += xlen; return 0; } /*-------------------------------------------------------------------- * NAME: xtSplitPage * * FUNCTION: Split non-root page of xtree * * PARAMETERS: * ip - Inode of xtree splitting * xpage - page to split * offset - offset of new extent to add * nblocks - number of blocks of new extent to add * blkno - starting block number of new extent to add * dev_ptr - Device handle * aggr_block_size - aggregate block size * * RETURNS: 0 for success; Other indicates failure */ static int xtSplitPage(struct dinode *ip, struct xtree_buf *xpage, int64_t offset, int nblocks, int64_t blkno, FILE *dev_ptr, int aggr_block_size) { int rc = 0; int64_t xaddr; /* new right page block number */ xad_t *xad; int xlen; xtpage_t *lastpage, *newpage; int64_t leftbn; /* Allocate disk space for the new xtree page */ xlen = 1 << control_page->dn_l2nbperpage; if ((rc = dbAlloc(dev_ptr, xlen, &xaddr))) return rc; /* * Modify xpage's next entry to point to the new disk space, * write the xpage to disk since we won't be needing it anymore. */ lastpage = xpage->page; lastpage->header.next = xaddr; leftbn = addressPXD(&(lastpage->header.self)); /* swap if on big endian machine */ ujfs_swap_xtpage_t(lastpage); rc = ujfs_rw_diskblocks(dev_ptr, leftbn * aggr_block_size, PSIZE, lastpage, PUT); ujfs_swap_xtpage_t(lastpage); if (rc != 0) return rc; /* * We are now done with the xpage as-is. We can now re-use this buffer * for our new buffer. */ newpage = xpage->page; PXDlength(&(newpage->header.self), xlen); PXDaddress(&(newpage->header.self), xaddr); newpage->header.flag = newpage->header.flag & BT_TYPE; /* initialize sibling pointers of newpage */ newpage->header.next = 0; newpage->header.prev = leftbn; /* insert entry at the first entry of the new right page */ xad = &newpage->xad[XTENTRYSTART]; XADoffset(xad, offset); XADlength(xad, nblocks); XADaddress(xad, blkno); newpage->header.nextindex = XTENTRYSTART + 1; /* Now append new page to parent page */ rc = xtAppend(dev_ptr, ip, offset, xaddr, xlen, xpage->up, aggr_block_size); /* Update inode to account for new page */ ip->di_nblocks += xlen; return rc; } /*-------------------------------------------------------------------- * NAME: xtAppend * * FUNCTION: Append an extent to the specified file * * PARAMETERS: * dev_ptr - Device handle * di - Inode to add extent to * offset - offset of extent to add * blkno - block number of start of extent to add * nblocks - number of blocks in extent to add * xpage - xtree page to add extent to * aggr_block_size - aggregate block size in bytes * * NOTES: xpage points to its parent in the xtree and its rightmost child (if it * has one). It also points to the buffer for the page. * * RETURNS: 0 for success; Other indicates failure */ static int xtAppend(FILE *dev_ptr, struct dinode *di, int64_t offset, int64_t blkno, int nblocks, struct xtree_buf *xpage, int aggr_block_size) { int rc = 0; int index; xad_t *xad; xtpage_t *cur_page; cur_page = xpage->page; index = cur_page->header.nextindex; /* insert entry for new extent */ if (index == cur_page->header.maxentry) { /* * There is not room in this page to add the entry; Need to * create a new page */ if (cur_page->header.flag & BT_ROOT) { /* This is the root of the xtree; need to split root */ rc = xtSplitRoot(dev_ptr, di, xpage, offset, nblocks, blkno); } else { /* * Non-root page: add new page at this level, xtSplitPage() * calls xtAppend again to propogate up the new page entry */ rc = xtSplitPage(di, xpage, offset, nblocks, blkno, dev_ptr, aggr_block_size); } } else { /* There is room to add the entry to this page */ xad = &cur_page->xad[index]; XADoffset(xad, offset); XADlength(xad, nblocks); XADaddress(xad, blkno); /* advance next available entry index */ ++cur_page->header.nextindex; rc = 0; } return rc; } /*-------------------------------------------------------------------- * NAME: add_bad_block * * FUNCTION: Add an extent of to the inode * * PRE CONDITIONS: badblock_pages has been initialized * * PARAMETERS: * dev_ptr - Device handle * thisblk - block number of bad block to add * aggr_block_size - Size of an aggregate block * bb_inode - Inode to add bad block to * * RETURNS: 0 for success; Other indicates failure */ static int add_bad_block(FILE *dev_ptr, int64_t thisblk, int aggr_block_size, struct dinode *bb_inode) { int rc = 0; /* Mark block allocated in map */ rc = markit(thisblk, ALLOC | BADBLOCK); if (rc != 0) { return (rc); } /* Add to inode: add an extent for this block to the inode's tree */ rc = xtAppend(dev_ptr, bb_inode, bb_inode->di_size / aggr_block_size, thisblk, 1, badblock_pages, aggr_block_size); if (!rc) { /* append was successful */ bb_inode->di_size += aggr_block_size; bb_inode->di_nblocks++; } return rc; } /*-------------------------------------------------------------------- * NAME: verify_last_blocks * * FUNCTION: Verify blocks in aggregate not initialized * * PARAMETERS: * dev_ptr - Device handle * aggr_block_size - aggregate block size in bytes * bb_inode - Inode for bad blocks * * NOTES: Any bad blocks found will be added to the bad block inode * * RETURNS: 0 for success; Other indicates failure */ #define L2MEGABYTE 20 #define MEGABYTE (1 << L2MEGABYTE) /* Define a parameter array for messages */ #define MAXPARMS 1 #define MAXSTR 128 static char *msg_parms[MAXPARMS]; static char msgstr[MAXSTR]; int verify_last_blocks(FILE *dev_ptr, int aggr_block_size, struct dinode *bb_inode) { int rc = 0; int error; void *buffer = NULL; int bufsize = PSIZE << 5; int nbufblks; int64_t nblocks, nb; int64_t blkno, thisblk; int percent, section, index; bool write_inode = false; struct xtree_buf *curpage; long flags; if (badblock_pages == NULL) { /* * Initialize list of xtree append buffers */ badblock_pages = malloc(sizeof (struct xtree_buf)); if (badblock_pages == NULL) { message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, OSO_MSG); return (ENOMEM); } badblock_pages->down = badblock_pages->up = NULL; badblock_pages->page = (xtpage_t *) & bb_inode->di_btroot; } /* Allocate and clear a buffer */ while ((bufsize >= aggr_block_size) && #ifdef HAVE_POSIX_MEMALIGN posix_memalign(&buffer, aggr_block_size, bufsize)) #else #ifdef HAVE_MEMALIGN (buffer = memalign(aggr_block_size, bufsize)) == NULL) #else (buffer = valloc(bufsize)) == NULL) #endif #endif bufsize >>= 1; if (buffer == NULL) { message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, OSO_MSG); return (ENOMEM); } memset(buffer, 0, bufsize); nbufblks = bufsize / aggr_block_size; #ifdef O_DIRECT /* * Must do direct-io to avoid the page cache */ flags = fcntl(fileno(dev_ptr), F_GETFL); fcntl(fileno(dev_ptr), F_SETFL, flags | O_DIRECT); #endif /* * Starting from the last allocated block to the end of the aggregate * write the empty buffer to disk. */ blkno = last_allocated + 1; nblocks = control_page->dn_mapsize - blkno; section = MAX(control_page->dn_mapsize >> 7, MEGABYTE / aggr_block_size); for (index = section; nblocks > 0; index += nb) { if (index > section) { percent = blkno * 100 / control_page->dn_mapsize; sprintf(msgstr, "%d", percent); msg_parms[0] = msgstr; message_user(MSG_OSO_PERCENT_FORMAT, msg_parms, 1, OSO_MSG); fprintf(stdout, "\r"); fflush(stdout); index = 0; } nb = MIN(nblocks, nbufblks); error = ujfs_rw_diskblocks(dev_ptr, blkno * aggr_block_size, nb * aggr_block_size, buffer, PUT); /* * most devices don't report an error on write, so we have to * verify explicitly to be sure. */ if (error == 0) { error = ujfs_rw_diskblocks(dev_ptr, blkno * aggr_block_size, nb * aggr_block_size, buffer, GET); } if (error != 0) { /* * At least one of the blocks we just tried to write was * bad. To narrow down the problem, we will write each * block individually and add any bad ones to our bad * block inode. */ for (thisblk = blkno; thisblk < blkno + nb; thisblk++) { error = ujfs_rw_diskblocks(dev_ptr, thisblk * aggr_block_size, aggr_block_size, buffer, PUT); /* * most devices don't report an error on write, * so we have to verify explicitly to be sure. */ if (error == 0) { error = ujfs_rw_diskblocks(dev_ptr, thisblk * aggr_block_size, aggr_block_size, buffer, GET); } if (error != 0) { /* add_bad_block may do unaligned I/O */ #ifdef O_DIRECT fcntl(fileno(dev_ptr), F_SETFL, flags); #endif /* Add this block to bad list */ if ((rc = add_bad_block(dev_ptr, thisblk, aggr_block_size, bb_inode))) continue; write_inode = true; #ifdef O_DIRECT fcntl(fileno(dev_ptr), F_SETFL, flags | O_DIRECT); #endif /* * In case we allocated blocks for our * addressing structure after our current * bad block, we need to move our block * number up so we don't overwrite any * changes we have just done. */ thisblk = MAX(last_allocated, thisblk); } } /* * In case we allocated blocks for the bad block map * inode's addressing structure, skip past them so we * don't wipe out our work. */ blkno += nb; if (blkno != thisblk) { blkno = thisblk; nblocks = control_page->dn_mapsize - blkno; } else { nblocks -= nb; } } else { blkno += nb; nblocks -= nb; } } #ifdef O_DIRECT fcntl(fileno(dev_ptr), F_SETFL, flags); #endif msg_parms[0] = "100"; message_user(MSG_OSO_PERCENT_FORMAT, msg_parms, 1, OSO_MSG); fprintf(stdout, "\n"); free(buffer); if (write_inode == true) { /* We added bad blocks, flush pages to disk */ curpage = badblock_pages; while (!(curpage->page->header.flag & BT_ROOT)) { blkno = addressPXD(&(curpage->page->header.self)); /* swap if on big endian machine */ ujfs_swap_xtpage_t(curpage->page); rc = ujfs_rw_diskblocks(dev_ptr, blkno * aggr_block_size, PSIZE, curpage->page, PUT); ujfs_swap_xtpage_t(curpage->page); if (rc != 0) return rc; curpage = curpage->up; } /* Write the bad block inode itself */ rc = ujfs_rwinode(dev_ptr, bb_inode, BADBLOCK_I, PUT, aggr_block_size, AGGREGATE_I, type_jfs); } return rc; } jfsutils-1.1.15.orig/mkfs/initmap.h0000644000000000000000000000225611304744426014053 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef H_INITMAP #define H_INITMAP #define ALLOC 0x1 #define FREE 0x2 #define BADBLOCK 0x4 int calc_map_size(int64_t, struct dinode *, int, int *, unsigned); int markit(int64_t, unsigned); int record_LVM_BadBlks( int, int, int, struct dinode *, int64_t ); int verify_last_blocks( FILE *, int, struct dinode * ); int write_block_map(FILE *, int64_t, int); #endif /* H_INITMAP */ jfsutils-1.1.15.orig/mkfs/inodemap.c0000644000000000000000000001776710340701413014202 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include "jfs_types.h" #include "jfs_endian.h" #include "jfs_filsys.h" #include "jfs_dinode.h" #include "initmap.h" #include "devices.h" #include "jfs_imap.h" #include "message.h" #include "utilsubs.h" /* * NAME: init_AG_free_list * * FUNCTION: Initialize AG dependent part of inode map control page * * PARAMETERS: * aggr_block_size - block size for aggregate * inode_table_loc - block offset for first extent of inode allocation map, * this will be added to the table at the appropriate * location * AGsize - Number of logical blocks in an allocation group, used * to determine AG boundary for inode extent * in_agctl - Part of map control page to be initialized * num_inode_init - Number of inodes initialized for inode map * iagnum - IAG number of IAG with the allocated inodes * * RETURNS: * success: 0 * failure: any other value */ static int init_AG_free_list(int aggr_block_size, int64_t inode_table_loc, int AGsize, struct iagctl *in_agctl, unsigned num_inode_init, int iagnum) { int AG_num; int index; int64_t end_AG; struct iagctl empty_entry; /* * Figure out which AG the inode extent belongs in and initialize * AG free list entry to point to it * * All other entries will point to an empty entry */ end_AG = AGsize; for (AG_num = 0; AG_num < MAXAG; AG_num++) { if (inode_table_loc < end_AG) { break; } end_AG += AGsize; } if (inode_table_loc >= end_AG) { /* * Broke out of for loop by hitting maximum number of aggregates. * Either AGsize is wrong, or the inode_table_loc value is wrong. */ fprintf(stderr, "Internal error: %s(%d): inode table location does not fall in correct range\n", __FILE__, __LINE__); fprintf(stderr, "\tAGsize = %d\tinode_table_loc = %lld\tend_AG = %lld\n", AGsize, (long long) inode_table_loc, (long long) end_AG); return ERROR_INVALID_ACCESS; } empty_entry.inofree = -1; empty_entry.extfree = -1; empty_entry.numinos = 0; empty_entry.numfree = 0; for (index = 0; index < MAXAG; index++) { if (index == AG_num) { /* * This is where the initial inode extent lives */ in_agctl[index].inofree = iagnum; in_agctl[index].extfree = iagnum; in_agctl[index].numinos = NUM_INODE_PER_EXTENT; in_agctl[index].numfree = NUM_INODE_PER_EXTENT - num_inode_init; } else { /* * No inode extents allocated for this AG */ memcpy(&(in_agctl[index]), &(empty_entry), sizeof (empty_entry)); } } return (0); } /* * NAME: init_inode_map * * FUNCTION: Initialize first extent of inode allocation map * * PARAMETERS: * aggr_block_size - block size for aggregate * dev_ptr - open port for device to write to * inode_table_loc - byte offset of first extent of inode table * inode_table_size - byte count of first extent of inode table * inode_map_loc - aggregate block offset of first extent of map * inode_map_size - byte count of first extent of inode map * num_inode_init - Number of initialized fileset inodes * AGsize - Size of allocation groups * which_map - Indicates either fileset or aggregate * * RETURNS: * success: 0 * failure: any other value */ int init_inode_map(int aggr_block_size, FILE *dev_ptr, int64_t inode_table_loc, int inode_table_size, int64_t inode_map_loc, int inode_map_size, unsigned short num_inode_init, int AGsize, unsigned which_map) { struct iag *first_iag; struct dinomap *control_page; char *imap; int64_t index, first_block, last_block; int rc = 0; unsigned *wmap_word; int *inosmap_ptr, *extsmap_ptr; short mapindex, bitindex; pxd_t *inoext_ptr; short numbits; /* * Initialize space to hold control page for inode allocation map as * well as the initial page of inode allocation map */ imap = (char *) calloc(1, inode_map_size); if (imap == NULL) { message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, OSO_MSG); return (ENOMEM); } /* * Initialize control page */ control_page = (struct dinomap *) imap; control_page->in_freeiag = -1; control_page->in_nextiag = 1; control_page->in_numinos = NUM_INODE_PER_EXTENT; control_page->in_numfree = NUM_INODE_PER_EXTENT - num_inode_init; control_page->in_nbperiext = INODE_EXTENT_SIZE / aggr_block_size; control_page->in_l2nbperiext = log2shift(control_page->in_nbperiext); /* * Initialize space for first extent of fileset inode map */ first_iag = (struct iag *) &(imap[SIZE_OF_MAP_PAGE]); /* * Initialize control section of first IAG of inode allocation map */ first_iag->iagnum = 0; first_iag->agstart = ((inode_table_loc / aggr_block_size) / AGsize) * AGsize; first_iag->inofreefwd = -1; first_iag->inofreeback = -1; first_iag->extfreefwd = -1; first_iag->extfreeback = -1; first_iag->iagfree = -1; first_iag->nfreeinos = NUM_INODE_PER_EXTENT - num_inode_init; first_iag->nfreeexts = EXTSPERIAG - 1; /* * Initialize working and persistent maps of first IAG */ if (which_map == AGGREGATE_I) { first_iag->wmap[0] = first_iag->pmap[0] = 0xf8008000; } else { first_iag->wmap[0] = first_iag->pmap[0] = 0xf0000000; } /* * Initialize first inode extent of IAG */ PXDlength(&(first_iag->inoext[0]), inode_table_size / aggr_block_size); PXDaddress(&(first_iag->inoext[0]), inode_table_loc / aggr_block_size); /* * Initialize extent summary map from the inode extents of the iag * Initialize inode summary map from working/permanent map of the iag */ numbits = sizeof (first_iag->extsmap[0]) << 3; for (inoext_ptr = &(first_iag->inoext[0]), wmap_word = &(first_iag->wmap[0]), mapindex = 0; mapindex < SMAPSZ; mapindex++) { extsmap_ptr = &(first_iag->extsmap[mapindex]); inosmap_ptr = &(first_iag->inosmap[mapindex]); for (bitindex = 0; bitindex < numbits; bitindex++, inoext_ptr++, wmap_word++) { *extsmap_ptr <<= 1; *inosmap_ptr <<= 1; if (addressPXD(inoext_ptr) != 0) { /* * Extent allocated */ *extsmap_ptr |= 1; if ((*wmap_word ^ 0xffffffff) == 0) { /* * All allocated */ *inosmap_ptr |= 1; } } else { /* * Extent is not allocated; want to mark the inode * summary map as allocated to simplify the searching * in the runtime filesystem code. This allows just * the inosmap to be searched when looking for a free * backed inode. */ *inosmap_ptr |= 1; } } } /* * Initialize the AG free list */ rc = init_AG_free_list(aggr_block_size, inode_table_loc / aggr_block_size, AGsize, control_page->in_agctl, num_inode_init, first_iag->iagnum); if (rc != 0) return (rc); /* swap if on big endian machine */ ujfs_swap_iag(first_iag); ujfs_swap_dinomap((struct dinomap *) imap); /* * Write control page and first extent of inode map to disk */ rc = ujfs_rw_diskblocks(dev_ptr, inode_map_loc * aggr_block_size, inode_map_size, imap, PUT); free(imap); if (rc != 0) return rc; /* * Mark blocks allocated in block allocation map */ first_block = inode_map_loc; last_block = inode_map_loc + inode_map_size / aggr_block_size; for (index = first_block; ((index < last_block) && (rc == 0)); index++) { rc = markit(index, ALLOC); } return (rc); } jfsutils-1.1.15.orig/mkfs/inodemap.h0000644000000000000000000000171710340701413014173 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef H_INODEMAP #define H_INODEMAP #include "devices.h" int init_inode_map(int, FILE *, int64_t, int, int64_t, int, unsigned short, int, unsigned); #endif jfsutils-1.1.15.orig/mkfs/inodes.c0000644000000000000000000003644210340701413013656 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include "jfs_types.h" #include "jfs_endian.h" #include "jfs_filsys.h" #include "jfs_dinode.h" #include "initmap.h" #include "inode.h" #include "devices.h" #include "inodes.h" #include "debug.h" #include "message.h" /* endian routines */ extern unsigned type_jfs; /* * NAME: init_aggr_inode_table * * FUNCTION: Initialize aggregate inodes to disk * * PARAMETERS: * aggr_block_size - block size for aggregate * dev_ptr - open port for device to write to * aggr_inodes - Array of initial aggregate inodes. They have been * initialized elsewhere. * num_aggr_inodes - Number of aggregate inodes initialized. * table_loc - Byte offset of table location * inode_map_loc - Block offset of inode map * inode_map_sz - Byte count of inode map * inostamp - Inode stamp to be used for aggregate inodes * * RETURNS: * success: 0 * failure: any other value */ int init_aggr_inode_table(int aggr_block_size, FILE *dev_ptr, struct dinode *aggr_inodes, int num_aggr_inodes, int64_t table_loc, int64_t inode_map_loc, int inode_map_sz, unsigned inostamp) { void *buffer; int64_t first_block, last_block, index; int i, rc; struct dinode *buf_ai; /* * Allocate space for first inode extent, and clear */ buffer = calloc(INODE_EXTENT_SIZE, sizeof (char)); if (buffer == NULL) { message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, OSO_MSG); return (ENOMEM); } /* * Initialize inodes: 0, 1, 3, and 4 * Inode 2 has already been initialized; */ DBG_TRACE(("size of dinode = %d\n", sizeof (struct dinode))) aggr_inodes[AGGR_RESERVED_I].di_nlink = 1; /* * Initialize inode 1: "self" inode */ init_inode(&(aggr_inodes[AGGREGATE_I]), AGGREGATE_I, AGGREGATE_I, inode_map_sz / aggr_block_size, inode_map_sz, inode_map_loc, IFJOURNAL | IFREG, max_extent_data, table_loc / aggr_block_size, aggr_block_size, inostamp); aggr_inodes[AGGREGATE_I].di_gengen = 1; /* * Initialize inode 3: inline log inode */ init_inode(&(aggr_inodes[LOG_I]), AGGREGATE_I, LOG_I, 0, 0, 0, IFJOURNAL | IFREG, no_data, table_loc / aggr_block_size, aggr_block_size, inostamp); /* * Initialize inode 4: bad block inode */ init_inode(&(aggr_inodes[BADBLOCK_I]), AGGREGATE_I, BADBLOCK_I, 0, 0, 0, IFJOURNAL | IFREG | ISPARSE, no_data, table_loc / aggr_block_size, aggr_block_size, inostamp); /* * Copy initialized inodes to buffer */ memcpy(buffer, aggr_inodes, num_aggr_inodes * sizeof (struct dinode)); /* * Write Inode extent to disk */ /* swap if on big endian machine */ /* swap gengen from aggr_inodes[AGGREGATE_I] in buffer */ buf_ai = ((struct dinode *) buffer) + AGGREGATE_I; buf_ai->di_gengen = __le32_to_cpu(buf_ai->di_gengen); for (i = 0; i < num_aggr_inodes; i++) { ujfs_swap_dinode((struct dinode *) buffer, PUT, type_jfs); buffer = (char *) buffer + sizeof (struct dinode); } buffer = (char *) buffer - (num_aggr_inodes * sizeof (struct dinode)); rc = ujfs_rw_diskblocks(dev_ptr, table_loc, INODE_EXTENT_SIZE, buffer, PUT); free(buffer); if (rc != 0) return rc; /* * Mark blocks allocated in block allocation map */ first_block = table_loc / aggr_block_size; last_block = first_block + (INODE_EXTENT_SIZE / aggr_block_size); for (index = first_block; ((index < last_block) && (rc == 0)); index++) { rc = markit(index, ALLOC); } return (rc); } /* * NAME: init_fileset_inode_table * * FUNCTION: Initialize fileset inodes and write to disk * * PARAMETERS: * aggr_block_size - block size for aggregate * dev_ptr - open port for device to write to * inode_location - Filled in with byte offset of first extent of fileset * inode table * inode_size - Filled in with byte count of first extent of fileset * inode table * fileset_start - First block for fileset, will use this to determine * where to put the inodes on disk * fileset_inode_map_loc - First block of fileset inode map * inostamp - stamp for inode * * RETURNS: * success: 0 * failure: any other value */ int init_fileset_inode_table(int aggr_block_size, FILE *dev_ptr, int64_t * inode_location, int *inode_size, int64_t fileset_start, int64_t fileset_inode_map_loc, unsigned inostamp) { void *buffer, *bp; struct dinode inode_buffer; int64_t first_block, last_block, index; int i, rc; int root_size; dtroot_t *root_header; /* * Find space for the inode extent * * Release 1 will not support multiple filesets per aggregate, so the * location of the inode extent can be fixed. However in future releases * this will have to be modified to find the space for this extent using * the block allocation map. */ #ifdef ONE_FILESET_PER_AGGR /* * The first fileset inode extent is the first thing written for the * fileset, so its location is the start of the fileset */ *inode_location = fileset_start * aggr_block_size; #else *inode_location = get_space(*inode_size); #endif /* ONE_FILESET_PER_AGGR */ /* * Allocate space for first inode extent, and clear */ *inode_size = INODE_EXTENT_SIZE; bp = buffer = calloc(*inode_size, sizeof (char)); if (bp == NULL) { message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, OSO_MSG); return (ENOMEM); } /* * Inode 0 - Reserved Inode */ memset(&inode_buffer, 0, sizeof (inode_buffer)); init_inode(&inode_buffer, FILESYSTEM_I, FILESET_RSVD_I, 0, 0, 0, IFJOURNAL | IFREG, no_data, fileset_start, aggr_block_size, inostamp); memcpy(bp, &inode_buffer, sizeof (inode_buffer)); bp = (char *) bp + sizeof (inode_buffer); /* * Inode 1 - 2nd half of fileset superblock information * * When we add support for VFS this will be a special inode with * different information. For now we will just make it look like an * empty inode to reserve it. */ memset(&inode_buffer, 0, sizeof (inode_buffer)); init_inode(&inode_buffer, FILESYSTEM_I, FILESET_EXT_I, 0, 0, 0, IFJOURNAL | IFREG, no_data, fileset_start, aggr_block_size, inostamp); memcpy(bp, &inode_buffer, sizeof (inode_buffer)); bp = (char *) bp + sizeof (inode_buffer); /* * Inode 2 - Root directory */ memset(&inode_buffer, 0, sizeof (inode_buffer)); root_size = sizeof (struct dinode) - offsetof(struct dinode, di_inlinedata); init_inode(&inode_buffer, FILESYSTEM_I, ROOT_I, 0, root_size, 0, IFJOURNAL | IFDIR | 0755, no_data, fileset_start, aggr_block_size, inostamp); /* Set number of links for root to account for '.' entry */ inode_buffer.di_nlink = 2; /* * Initialize the directory B+-tree header for the root inode * Since the root directory has no entries the nextindex is 0; nextindex * is for the stbl index not the slot index. */ root_header = (dtroot_t *) & (inode_buffer.di_DASD); root_header->header.flag = DXD_INDEX | BT_ROOT | BT_LEAF; setDASDLIMIT(&(root_header->header.DASD), 0); setDASDUSED(&(root_header->header.DASD), 0); root_header->header.nextindex = 0; /* * Determine how many slots will fit */ root_header->header.freecnt = DTROOTMAXSLOT - 1; root_header->header.freelist = DTENTRYSTART; root_header->header.idotdot = 2; for (index = DTENTRYSTART; index < DTROOTMAXSLOT; index++) { root_header->slot[index].cnt = 1; root_header->slot[index].next = index + 1; } /* * Last entry should end the free list. */ index--; root_header->slot[index].next = -1; memcpy(bp, &inode_buffer, sizeof (inode_buffer)); bp = (char *) bp + sizeof (inode_buffer); /* * Inode 3 - ACL File */ memset(&inode_buffer, 0, sizeof (inode_buffer)); init_inode(&inode_buffer, FILESYSTEM_I, ACL_I, 0, 0, 0, IFJOURNAL | IFREG, no_data, fileset_start, aggr_block_size, inostamp); memcpy(bp, &inode_buffer, sizeof (inode_buffer)); /* * Write Inode extent to disk */ /* swap if on big endian machine */ bp = buffer; for (i = 0; i < 4; i++) { ujfs_swap_dinode((struct dinode *) bp, PUT, type_jfs); bp = (char *) bp + sizeof (inode_buffer); } rc = ujfs_rw_diskblocks(dev_ptr, *inode_location, *inode_size, buffer, PUT); free(buffer); if (rc != 0) return rc; /* * Mark blocks allocated in block allocation map */ first_block = *inode_location / aggr_block_size; last_block = (*inode_location + *inode_size) / aggr_block_size; for (index = first_block; ((index < last_block) && (rc == 0)); index++) { rc = markit(index, ALLOC); } return (rc); } /* * NAME: init_fileset_inodes * * FUNCTION: Initialize fileset inodes in aggregate inode table * * PARAMETERS: * aggr_block_size - block size for aggregate * dev_ptr - open port for device to write to * inode_map_loc - byte offset for first extent of fileset's inode map * inode_map_size - byte count for first extent of fileset's inode map * fileset_start - First block of fileset. Will be used to determine * location of the AG table. * inostamp - time stamp for inodes in this fileset * * RETURNS: * success: 0 * failure: any other value */ int init_fileset_inodes(int aggr_block_size, FILE *dev_ptr, int64_t inode_map_loc, int inode_map_size, int64_t fileset_start, unsigned inostamp) { struct dinode inode_buffer; unsigned inode_num; int rc; /* * Figure out which is the next free aggregate fileset inode * * Release 1 only supports one fileset per aggregate, so we know this * will always be inode FILESYSTEM_I in the aggregate inode table. In * future releases we will need to modify this code to look in the * aggregate inode table for the next available free inode. */ #ifdef ONE_FILESET_PER_AGGR inode_num = FILESYSTEM_I; #else inode_num = get_next_free(); #endif /* ONE_FILESET_PER_AGGR */ /* * Initialize Fileset Inode: Fileset Inode Allocation Map */ memset(&inode_buffer, 0, sizeof (inode_buffer)); init_inode(&inode_buffer, AGGREGATE_I, inode_num, inode_map_size / aggr_block_size, inode_map_size, inode_map_loc, IFJOURNAL | IFREG, max_extent_data, AITBL_OFF / aggr_block_size, aggr_block_size, inostamp); /* swap here if necessary for big endian */ inode_buffer.di_gengen = __le32_to_cpu(1); /* * Write fileset inode to disk */ rc = ujfs_rwinode(dev_ptr, &inode_buffer, inode_num, PUT, aggr_block_size, AGGREGATE_I, type_jfs); return (rc); } /* * NAME: init_inode * * FUNCTION: Initialize inode fields for an inode with a single extent or inline * data or a directory inode * * PARAMETERS: * new_inode - Pointer to inode to be initialized * fileset_num - Fileset number for inode * inode_num - Inode number of inode * num_blocks - Number of aggregate blocks allocated to inode * size - Size in bytes allocated to inode * first_block - Offset of first block of inode's extent * mode - Mode for inode * inode_type - Indicates the type of inode to be initialized. * Currently supported types are inline data, extents, * and no data. The other parameters to this function * will provide the necessary information. * inoext_address - Address of inode extent containing this inode * aggr_block_size - Aggregate block size * inostamp - Stamp used to identify inode as belonging to fileset * * RETURNS: None */ void init_inode(struct dinode *new_inode, int fileset_num, unsigned inode_num, int64_t num_blocks, int64_t size, int64_t first_block, mode_t mode, ino_data_type inode_type, int64_t inoext_address, int aggr_block_size, unsigned inostamp) { /* * Initialize inode with where this stuff lives */ new_inode->di_inostamp = inostamp; new_inode->di_fileset = fileset_num; new_inode->di_number = inode_num; new_inode->di_gen = 1; PXDaddress(&(new_inode->di_ixpxd), inoext_address); PXDlength(&(new_inode->di_ixpxd), INODE_EXTENT_SIZE / aggr_block_size); new_inode->di_mode = mode; new_inode->di_nblocks = num_blocks; new_inode->di_size = size; new_inode->di_nlink = 1; new_inode->di_next_index = 2; switch (inode_type) { case inline_data: new_inode->di_dxd.flag = DXD_INLINE; DXDlength(&(new_inode->di_dxd), sizeof (struct dinode) - offsetof(struct dinode, di_inlinedata)); DXDaddress(&(new_inode->di_dxd), 0); break; case extent_data: case max_extent_data: ((xtpage_t *) & (new_inode->di_DASD))->header.flag = DXD_INDEX | BT_ROOT | BT_LEAF; /* * Since this is the root, we don't actually use the next and * prev entries. Set to 0 in case we decide to use this space * for something in the future. */ ((xtpage_t *) & (new_inode->di_DASD))->header.next = 0; ((xtpage_t *) & (new_inode->di_DASD))->header.prev = 0; ((xtpage_t *) & (new_inode->di_DASD))->header.nextindex = XTENTRYSTART + 1; ((xtpage_t *) & (new_inode->di_DASD))->header.maxentry = XTROOTMAXSLOT; ((xtpage_t *) & (new_inode->di_DASD))->xad[XTENTRYSTART].flag = 0; ((xtpage_t *) & (new_inode->di_DASD))->xad[XTENTRYSTART].rsvrd = 0; XADoffset(&((xtpage_t *) & (new_inode->di_DASD))-> xad[XTENTRYSTART], 0); XADlength(&((xtpage_t *) & (new_inode->di_DASD))-> xad[XTENTRYSTART], num_blocks); XADaddress(&((xtpage_t *) & (new_inode->di_DASD))-> xad[XTENTRYSTART], first_block); break; case no_data: /* * No data to be filled in here, don't do anything */ ((xtpage_t *) & (new_inode->di_DASD))->header.flag = DXD_INDEX | BT_ROOT | BT_LEAF; /* * Since this is the root, we don't actually use the next and * prev entries. Set to 0 in case we decide to use this space * for something in the future. */ ((xtpage_t *) & (new_inode->di_DASD))->header.next = 0; ((xtpage_t *) & (new_inode->di_DASD))->header.prev = 0; ((xtpage_t *) & (new_inode->di_DASD))->header.nextindex = XTENTRYSTART; ((xtpage_t *) & (new_inode->di_DASD))->header.maxentry = XTROOTMAXSLOT; ((xtpage_t *) & (new_inode->di_DASD))->xad[XTENTRYSTART].flag = 0; ((xtpage_t *) & (new_inode->di_DASD))->xad[XTENTRYSTART].rsvrd = 0; break; default: DBG_ERROR(("Internal error: %s(%d): Unrecognized inode data type %d\n", __FILE__, __LINE__, inode_type)) break; } new_inode->di_atime.tv_sec = new_inode->di_ctime.tv_sec = new_inode->di_mtime.tv_sec = new_inode->di_otime.tv_sec = (unsigned) time(NULL); return; } jfsutils-1.1.15.orig/mkfs/inodes.h0000645000000000000000000000250010340701413013650 0ustar /* * Copyright (c) International Business Machines Corp., 2000-2002 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef H_INODES #define H_INODES #include "devices.h" typedef enum { inline_data, extent_data, max_extent_data, no_data } ino_data_type; int init_aggr_inode_table(int, FILE *, struct dinode *, int, int64_t, int64_t, int, unsigned); int init_fileset_inode_table(int, FILE *, int64_t *, int *, int64_t, int64_t, unsigned); int init_fileset_inodes(int, FILE *, int64_t, int, int64_t, unsigned); void init_inode(struct dinode *, int, unsigned, int64_t, int64_t, int64_t, mode_t, ino_data_type, int64_t, int, unsigned); #endif jfsutils-1.1.15.orig/mkfs/jfs_mkfs.80000644000000000000000000001166410340701413014123 0ustar .TH jfs_mkfs 8 "March 9, 2005" " " "JFS file system creation" .SH NAME .B jfs_mkfs \- create a JFS formatted partition .SH SYNOPSIS .B jfs_mkfs [options] .I device [ blocks ] .SH DESCRIPTION .PP .B jfs_mkfs is used to create (format) a JFS partition. .B jfs_mkfs must be run as root. .PP .I device is the special file name corresponding to the actual device .RI (e.g. " /dev/hdb1" ) on which a JFS file system and/or JFS journal will be created. .I blocks is the number of blocks to be used for the file system. If omitted, .B jfs_mkfs automatically figures the file system size. .PP The default block size is .BR 4096 "." .SH WARNING .PP .B jfs_mkfs will destroy all data on the specified device! .SH OPTIONS ./"********************************************* ./"* block size has not been implemented yet * ./"********************************************* ./".TP ./".BI \-b " block_size" ./"Set the block size for a new JFS partition ./".RS ./" ./"Options for ./".I block_size ./"are: ./".BR 512 "," ./".BR 1024 "," ./".BR 2048 ", or" ./".BR 4096 "." ./" ./"Using small blocks (rather than large blocks) is more space efficient because it ./"reduces the amount of internal fragmentation within files and directories. ./"However, using large blocks (rather than small blocks) is more performance efficient ./"because block allocation activities may occur less often . ./" ./"If the ./".B \-b ./"option is not used, the default block size is ./".BR 4096 "." ./".RE .TP .BI \-c Check the device for bad blocks before building the file system. ./"********************************** ./"* use -q (quiet) instead of -f * ./"********************************** ./".TP ./".BI \-f ./"Force - do not ask for confirmation before creating the file system. .TP .BI -j " journal_device" Create the external JFS journal on .I journal_device , create the JFS file system on .I device , and attach the external journal to the file system. .TP .BI \-J " journal-options" Create the JFS journal on its own device or attach an external JFS journal to the JFS file system using options specified on the command-line. The following journal options are supported: .RS 1.2i .TP .BI journal_dev Create an external JFS journal on the given device. .TP .BI device= external-journal Attach an existing external JFS journal located on .I external-journal to the JFS file system that will be created on .IR device . The external journal must already have been created using the command .IP .B jfs_mkfs -J journal_dev .I external-journal .IP Attach the external journal to the file system being created by using the command .IP .BI "jfs_mkfs -J device="external-journal .I device .IP Instead of specifying a device name directly, .I external-journal can also be specified by either .BI LABEL= label or .BI UUID= UUID to locate the external journal by either the volume label or UUID stored in the JFS external log superblock at the start of the journal. Use .BR jfs_tune (8) to display a journal device's volume label and UUID. (See the .BR -l , .BR -L , and .B -U options of .BR jfs_tune (8).) .RE .IP Only one of the .BR journal_dev " or " device= options can be given per .B jfs_mkfs issuance. .TP .BI -L " volume_label" Set the volume label for the newly formatted device. .IP If .BI -L " volume_label" is used along with .BR "-J journal_device" , the volume label of the specified external journal device will be set to .IR volume_label . Otherwise, the volume label of the JFS file system will be set to .IR volume_label . .TP .B \-O Provide case-insensitive support for compatibility with OS/2. .TP .BI \-q Quiet execution - do not ask for confirmation before creating the file system. .TP .BI -s " log_size" Set the log size (in megabytes) of the inline log. If the .B \-s option is not used, the default log size is 0.4% of the aggregate size. .TP .BI \-V Print version information and exit (regardless of any other chosen options). .SH EXAMPLES .LP Format 3rd partition on 2nd hard disk with the volume label "JFS_hdb3": .IP .B jfs_mkfs -L JFS_hdb3 /dev/hdb3 .IP .LP Format 5th partition on 1st hard disk, verifying each block created: .IP .B jfs_mkfs -c /dev/hda5 .IP .LP Format 3rd partition on 2nd hard disk as external journal, format 4th partition on 1st hard disk as JFS file system, and attach the external journal to the file system: .IP .B jfs_mkfs -j /dev/hdb3 /dev/hda4 .IP .SH "REPORTING BUGS" .PP If you find a bug in .B JFS or .BR jfs_mkfs , please report it via the bug tracking system ("Report Bugs" section) of the JFS project web site: .nf http://jfs.sourceforge.net/ .fi .PP Please send as much pertinent information as possible including any error messages resulting from running .BR jfs_mkfs . .SH SEE ALSO .BR mkfs (8) , .BR jfs_fsck (8) , .BR jfs_fscklog (8) , .BR jfs_tune (8) , .BR jfs_logdump (8) , .BR jfs_debugfs (8) .SH AUTHORS .nf Barry Arndt (barndt@us.ibm.com) William Braswell, Jr. .fi .B jfs_mkfs is maintained by IBM. .nf See the JFS project web site for more details: http://jfs.sourceforge.net/ .fi jfsutils-1.1.15.orig/mkfs/mkfs.c0000645000000000000000000007675011402027704013350 0ustar /* * Copyright (C) International Business Machines Corp., 2000-2009 * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #if HAVE_SYS_SYSMACROS_H #include #endif #include #include #include #include #include #include #include #include "jfs_endian.h" #include "jfs_filsys.h" #include "jfs_dinode.h" #include "jfs_superblock.h" #include "initmap.h" #include "inodes.h" #include "inode.h" #include "inodemap.h" #include "super.h" #include "logform.h" #include "jfs_dmap.h" #include "message.h" #include "debug.h" #include "jfs_version.h" #include "utilsubs.h" unsigned type_jfs; char *program_name; extern int LogOpenMode; FILE *open_by_label(uuid_t, int, int, char *, int *); static int AGsize; /* Define a parameter array for messages */ #define MAXPARMS 9 #define MAXSTR 128 char *msg_parms[MAXPARMS]; char msgstr[MAXSTR]; #define L2MEGABYTE 20 #define MEGABYTE (1 << L2MEGABYTE) #define MAX_LOG_PERCENTAGE 10 /* Log can be at most 10% of disk */ #define create_journal_only 1 #define use_existing_journal 2 /* * The following macro defines the initial number of aggregate inodes which * are initialized when a new aggregate is created. This does not include * any fileset inodes as those are initialized separately. */ #define INIT_NUM_AGGR_INODES (BADBLOCK_I + 1) static struct dinode aggr_inodes[INIT_NUM_AGGR_INODES]; void mkfs_usage(void) { printf("\nUsage: %s [-cOqV] [-j log_device] [-J options] " "[-L vol_label] [-s log_size] device [ blocks ]\n", program_name); printf("\nEmergency help:\n" " -c Check device for bad blocks before building file system.\n" " -O Provide case-insensitive support for OS/2 compatability.\n" " -q Quiet execution.\n" " -V Print version information only.\n" " -j log_device Set external journal device.\n" " -J options Set external journal options.\n" " -L vol_label Set volume label for the file system.\n" " -s log_size Set log size (in megabytes).\n\n" "NOTE: -j and -J cannot be used at the same time.\n"); return; } /*-------------------------------------------------------------------- * NAME: create_fileset * * FUNCTION: Do all work to create a fileset in an aggregate * * PARAMETERS: * dev_ptr - open port of device to write to * aggr_block_size - block size for aggregate * start_block - Number of blocks used by aggregate metadata, indicates * first block available for writing fileset metadata. * All fileset writes will be offsets from this. * inostamp - Inode stamp value to be used. * * RETURNS: * success: 0 * failure: any other value */ static int create_fileset(FILE *dev_ptr, int aggr_block_size, int64_t start_block, unsigned inostamp) { int rc; int64_t inode_table_loc, inode_map_loc; int inode_table_size, inode_map_size; /* * Find space for the inode allocation map page * * Also find the fileset inode map location on disk (inode_map_loc). * We need to know this in order to initialize the fileset inodes * with the proper iag value. * * Since we only have one fileset per aggregate in the first release, * we always know where the inode map will start. Therefore, currently * we use a hard-coded value. When we add multiple filesets per * aggregate this will need to be modified to find the space for the * inode map by looking in the block allocation map for available space. */ inode_map_size = SIZE_OF_MAP_PAGE << 1; #ifdef ONE_FILESET_PER_AGGR /* * The first extent of the fileset inode allocation map follows the * first extent of the first extent of the fileset inodes at the * beginning of the fileset */ inode_map_loc = start_block + INODE_EXTENT_SIZE / aggr_block_size; #else inode_map_loc = get_space(inode_map_size); #endif /* * Allocate Aggregate Inodes for Fileset */ rc = init_fileset_inodes(aggr_block_size, dev_ptr, inode_map_loc, inode_map_size, start_block, inostamp); if (rc != 0) return (rc); /* * Create Fileset Inode Table - first extent */ rc = init_fileset_inode_table(aggr_block_size, dev_ptr, &inode_table_loc, &inode_table_size, start_block, inode_map_loc, inostamp); if (rc != 0) return (rc); /* * Create Fileset Inode Allocation Map - first extent */ rc = init_inode_map(aggr_block_size, dev_ptr, inode_table_loc, inode_table_size, inode_map_loc, inode_map_size, (ACL_I + 1), AGsize, FILESYSTEM_I); return rc; } /*-------------------------------------------------------------------- * NAME: create_aggregate * * FUNCTION: Do all work to create an aggregate * * PARAMETERS: * dev_ptr - open port of device to write to * volume_label - label for volume * number_of_blocks - number of blocks for aggregate * aggr_block_size - block size for aggregate * phys_block_size - physical block size of device * type_jfs - JFS type to create * verify_blocks - indicates if we should verify every block * log_uuid - uuid of log device * * NOTES: The superblocks are the last things written to disk. In the event * of a system crash during mkfs this device will not appear to have * a real JFS filesystem. This should prevent us from attempting to * mount a partially initialized filesystem. * * RETURNS: * success: 0 * failure: any other value */ static int create_aggregate(FILE *dev_ptr, char *volume_label, int64_t number_of_blocks, int aggr_block_size, int phys_block_size, unsigned type_jfs, char *logdev, int64_t logloc, int logsize, bool verify_blocks, uuid_t log_uuid) { struct superblock aggr_superblock; void *buffer; int rc; int64_t index; int64_t first_block, last_block; int64_t reserved_size; int64_t aggr_inode_map_loc; int aggr_inode_map_sz; xad_t inode_map_dscr; int64_t secondary_ait_address, secondary_aimap_address; int64_t secondary_ait_end; int64_t fsck_wspace_address, num_bits; int64_t fsck_wspace_length, fsck_svclog_length, npages; unsigned inostamp; struct dinode fileset_inode; /* * Find where fsck working space will live on disk and mark those * blocks. The fsck working space is always at the very end of the * aggregate so once we know how big it is we can back up from the * end to determine where it needs to start. * * Need enough 4k pages to cover: * - 1 bit per block in aggregate rounded up to BPERDMAP boundary * - 1 extra 4k page to handle control page, intermediate level pages * - 50 extra 4k pages for the chkdsk service log */ num_bits = ((number_of_blocks + BPERDMAP - 1) >> L2BPERDMAP) << L2BPERDMAP; npages = ((num_bits + (BITSPERPAGE - 1)) / BITSPERPAGE) + 1 + 50; fsck_wspace_length = (npages << L2PSIZE) / aggr_block_size; fsck_wspace_address = number_of_blocks - fsck_wspace_length; fsck_svclog_length = (50 << L2PSIZE) / aggr_block_size; /* * Now we want the fsck working space to be ignored as actually being * part of the filesystem */ number_of_blocks -= fsck_wspace_length; /* * Initialize disk block map, so blocks can be marked as they are used * Blocks used for fsck working space will be marked here since we * don't want those blocks to be accounted for when maxag is set */ inostamp = (unsigned) time(NULL); rc = calc_map_size(number_of_blocks, aggr_inodes, aggr_block_size, &AGsize, inostamp); if (rc != 0) return rc; /* * Initialize and clear reserved disk blocks */ reserved_size = AGGR_RSVD_BYTES; buffer = calloc(reserved_size, sizeof (char)); if (buffer == NULL) { message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, OSO_MSG); return (ENOMEM); } rc = ujfs_rw_diskblocks(dev_ptr, 0, reserved_size, buffer, PUT); if (rc != 0) return rc; for (index = 0; ((index < reserved_size / aggr_block_size) && (rc == 0)); index++) { rc = markit(index, ALLOC); } if (rc != 0) return rc; /* * In case mkfs does not complete, but we have an old superblock * already on this device, we will zero the superblock disk blocks at * the beginning and then write the real superblock to disk last. * (This keeps the device from appearing to have a complete filesystem * when initialization is not complete.) */ rc = ujfs_rw_diskblocks(dev_ptr, SUPER1_OFF, SIZE_OF_SUPER, buffer, PUT); if (rc != 0) { free(buffer); return rc; } rc = ujfs_rw_diskblocks(dev_ptr, SUPER2_OFF, SIZE_OF_SUPER, buffer, PUT); if (rc != 0) { free(buffer); return rc; } free(buffer); /* Mark blocks allocated for superblocks. */ first_block = SUPER1_OFF / aggr_block_size; last_block = first_block + (SIZE_OF_SUPER / aggr_block_size); for (index = first_block; ((index < last_block) && (rc == 0)); index++) { rc = markit(index, ALLOC); } if (rc != 0) return rc; first_block = SUPER2_OFF / aggr_block_size; last_block = first_block + (SIZE_OF_SUPER / aggr_block_size); for (index = first_block; ((index < last_block) && (rc == 0)); index++) { rc = markit(index, ALLOC); } if (rc != 0) return rc; /* * Initialize First Extent of Aggregate Inode Allocation Map */ aggr_inode_map_loc = AIMAP_OFF; aggr_inode_map_sz = SIZE_OF_MAP_PAGE << 1; rc = init_inode_map(aggr_block_size, dev_ptr, AITBL_OFF, INODE_EXTENT_SIZE, aggr_inode_map_loc / aggr_block_size, aggr_inode_map_sz, INIT_NUM_AGGR_INODES + 1, AGsize, AGGREGATE_I); if (rc != 0) return rc; /* * Initialize first inode extent of Aggregate Inode Table */ rc = init_aggr_inode_table(aggr_block_size, dev_ptr, aggr_inodes, INIT_NUM_AGGR_INODES, AITBL_OFF, aggr_inode_map_loc / aggr_block_size, aggr_inode_map_sz, inostamp); if (rc != 0) return rc; /* * Now initialize the secondary aggregate inode table and map * * We can use the same aggr_inodes we already initialized except for * the aggregate self inode. This will be updated by the call to * init_aggr_inode_table() to point to the secondary table instead of * the primary table. * * First we need to determine the location; it will follow the block * map. Since the block map might be sparse we need to use the number * of blocks instead of the length of the extents. This works since * the extents are in the inode for mkfs */ inode_map_dscr = ((xtpage_t *) & (aggr_inodes[BMAP_I].di_DASD))->xad[XTENTRYSTART]; secondary_aimap_address = addressXAD(&inode_map_dscr) + aggr_inodes[BMAP_I].di_nblocks; secondary_ait_address = (secondary_aimap_address * aggr_block_size) + (SIZE_OF_MAP_PAGE << 1); secondary_ait_end = (secondary_ait_address + INODE_EXTENT_SIZE) / aggr_block_size; rc = init_inode_map(aggr_block_size, dev_ptr, secondary_ait_address, INODE_EXTENT_SIZE, secondary_aimap_address, aggr_inode_map_sz, INIT_NUM_AGGR_INODES + 1, AGsize, AGGREGATE_I); if (rc != 0) return rc; /* * Modify the aggregate inodes ixpxd fields */ PXDaddress(&(aggr_inodes[BMAP_I].di_ixpxd), secondary_ait_address / aggr_block_size); rc = init_aggr_inode_table(aggr_block_size, dev_ptr, aggr_inodes, INIT_NUM_AGGR_INODES, secondary_ait_address, secondary_aimap_address, aggr_inode_map_sz, inostamp); if (rc != 0) return rc; /* * Mark blocks for the block map */ first_block = BMAP_OFF / aggr_block_size; last_block = first_block + aggr_inodes[BMAP_I].di_nblocks; for (index = first_block; ((index < last_block) && (rc == 0)); index++) { rc = markit(index, ALLOC); } if (rc != 0) return rc; /* * Now we will create a fileset as necessary. * * Determine the end of the metadata written for the aggregate to tell * where to put the fileset to be created. Since the secondary * aggregate inode table is the last thing written to the aggregate, * the fileset will start following it. */ rc = create_fileset(dev_ptr, aggr_block_size, secondary_ait_end, inostamp); if (rc != 0) return rc; /* * Copy the fileset inode to the secondary aggregate inode table */ rc = ujfs_rwinode(dev_ptr, &fileset_inode, FILESYSTEM_I, GET, aggr_block_size, AGGREGATE_I, type_jfs); if (rc != 0) return rc; PXDaddress(&(fileset_inode.di_ixpxd), secondary_ait_address / aggr_block_size); /* swap if on big endian machine */ ujfs_swap_dinode(&fileset_inode, PUT, type_jfs); rc = ujfs_rw_diskblocks(dev_ptr, secondary_ait_address + FILESYSTEM_I * sizeof (struct dinode), sizeof (fileset_inode), &fileset_inode, PUT); ujfs_swap_dinode(&fileset_inode, GET, type_jfs); if (rc != 0) return rc; /* * If we are supposed to verify all blocks, now is the time to do it * * First we tell the LVM to stop doing Bad Block Relocation so we can * catch (and record) any bad blocks ourselves. Next we run through * the available file system space looking for bad blocks. Finally * we tell the LVM to go back to doing Bad Block Relocation. */ PXDaddress(&(aggr_inodes[BADBLOCK_I].di_ixpxd), AITBL_OFF / aggr_block_size); if (verify_blocks == true) { rc = verify_last_blocks(dev_ptr, aggr_block_size, &(aggr_inodes[BADBLOCK_I])); if (rc != 0) return rc; } /* * Copy the bad block inode to the secondary aggregate inode table */ PXDaddress(&(aggr_inodes[BADBLOCK_I].di_ixpxd), secondary_ait_address / aggr_block_size); /* swap if on big endian machine */ ujfs_swap_dinode(&aggr_inodes[BADBLOCK_I], PUT, type_jfs); rc = ujfs_rw_diskblocks(dev_ptr, secondary_ait_address + BADBLOCK_I * sizeof (struct dinode), sizeof (struct dinode), &(aggr_inodes[BADBLOCK_I]), PUT); ujfs_swap_dinode(&aggr_inodes[BADBLOCK_I], GET, type_jfs); if (rc != 0) return rc; /* * Now our block allocation map should be complete, write to disk */ rc = write_block_map(dev_ptr, number_of_blocks, aggr_block_size); if (rc != 0) return rc; /* * Initialize Aggregate Superblock - Both primary and secondary */ memcpy(aggr_superblock.s_magic, JFS_MAGIC, strlen(JFS_MAGIC)); /* * JFS_VERSION should have been upped to 2 when the linux-native format * split from OS/2. However, we don't want to force the use of the * latest JFS kernel code unless we're using an outline log. In that * case we want to set s_version to 2 to mandate a recent JFS driver. */ aggr_superblock.s_version = (type_jfs & JFS_INLINELOG) ? 1 : JFS_VERSION; aggr_superblock.s_size = number_of_blocks * (aggr_block_size / phys_block_size); aggr_superblock.s_bsize = aggr_block_size; aggr_superblock.s_l2bsize = log2shift(aggr_block_size); aggr_superblock.s_l2bfactor = log2shift(aggr_block_size / phys_block_size); aggr_superblock.s_pbsize = phys_block_size; aggr_superblock.s_l2pbsize = log2shift(phys_block_size); aggr_superblock.pad = 0; aggr_superblock.s_agsize = AGsize; aggr_superblock.s_flag = type_jfs; aggr_superblock.s_state = FM_CLEAN; aggr_superblock.s_compress = 0; PXDaddress(&aggr_superblock.s_ait2, secondary_ait_address / aggr_block_size); PXDlength(&aggr_superblock.s_ait2, INODE_EXTENT_SIZE / aggr_block_size); PXDaddress(&aggr_superblock.s_aim2, secondary_aimap_address); PXDlength(&aggr_superblock.s_aim2, aggr_inode_map_sz / aggr_block_size); if (logdev[0]) { struct stat st; if (stat(logdev, &st)) return errno; aggr_superblock.s_logdev = st.st_rdev; memset(&aggr_superblock.s_logpxd, 0, sizeof (pxd_t)); uuid_copy(aggr_superblock.s_loguuid, log_uuid); } else { aggr_superblock.s_logdev = 0; PXDaddress(&aggr_superblock.s_logpxd, logloc); PXDlength(&aggr_superblock.s_logpxd, logsize); } aggr_superblock.s_logserial = 0; PXDaddress(&aggr_superblock.s_fsckpxd, fsck_wspace_address); PXDlength(&aggr_superblock.s_fsckpxd, fsck_wspace_length); aggr_superblock.s_time.tv_sec = time(NULL); aggr_superblock.s_time.tv_nsec = 0; aggr_superblock.s_fsckloglen = fsck_svclog_length; aggr_superblock.s_fscklog = 0; strncpy(aggr_superblock.s_fpack, volume_label, LV_NAME_SIZE); /* extendfs stuff */ aggr_superblock.s_xsize = 0; memset(&aggr_superblock.s_xfsckpxd, 0, sizeof (pxd_t)); memset(&aggr_superblock.s_xlogpxd, 0, sizeof (pxd_t)); uuid_generate(aggr_superblock.s_uuid); strncpy(aggr_superblock.s_label, volume_label, 16); /* TODO: store log uuid */ /* Write both the primary and secondary superblocks to disk */ rc = ujfs_validate_super(&aggr_superblock); if (rc) return rc; rc = ujfs_put_superblk(dev_ptr, &aggr_superblock, 1); if (rc) return rc; rc = ujfs_put_superblk(dev_ptr, &aggr_superblock, 0); return rc; } /*-------------------------------------------------------------------- * NAME: parse_journal_opts * * FUNCTION: parse journal (-J) options * set log device name (global logdev) * set appropriate external journal flag * * PARAMETERS: * opts - options string * ext_journal_opt - external journal flag * journal_device - external journal device name */ void parse_journal_opts(const char *opts, int *ext_journal_opt, char *journal_device) { int journal_usage = 0; FILE *log_fd = NULL; uuid_t log_uuid; int in_use; /* * -J device= means we're going to attach an existing * external journal to a newly formatted file system */ if (strncmp(opts, "device=", 7) == 0) { LogOpenMode = O_RDONLY; /* see if device is specified by UUID */ if (strncmp(opts + 7, "UUID=", 5) == 0) { if (uuid_parse((char *) opts + 7 + 5, log_uuid)) { fprintf(stderr, "\nError: UUID entered in improper format.\n"); exit(-1); } else { log_fd = open_by_label(log_uuid, 0, 1, journal_device, &in_use); /* * If successful, open_by_label returns a file * descriptor to an open file. For jfs_mkfs * purposes, we do not yet need that file to be * open, so close it here. */ if (log_fd == NULL) { fclose(log_fd); } else { fprintf(stderr, "\nError: Could not find/open device specified by UUID %s.\n", (char *) opts + 7 + 5); exit(-1); } } /* see if device is specified by volume label */ } else if (strncmp(opts + 7, "LABEL=", 6) == 0) { log_fd = open_by_label((char *) opts + 7 + 6, 1, 1, journal_device, &in_use); /* * If successful, open_by_label returns a file descriptor * to an open file. For jfs_mkfs purposes, we do not yet * need that file to be open, so close it here. */ if (log_fd == NULL) { fclose(log_fd); } else { fprintf(stderr, "\nError: Could not find/open device specified by LABEL %s.\n", (char *) opts + 7 + 6); exit(-1); } /* device is specified by device name */ } else { strcpy(journal_device, ((char *) opts + 7)); } if (journal_device) { *ext_journal_opt = use_existing_journal; } else { journal_usage++; } /* * -J journal_dev means we're going to * format a new external journal ONLY */ } else if (strncmp(opts, "journal_dev", 11) == 0) { *ext_journal_opt = create_journal_only; } else /* error in specified options */ journal_usage++; if (journal_usage) { fprintf(stderr, "\nInvalid journal options specified.\n\n" "Valid options for -J are:\n" "\tdevice=\n" "\tdevice=UUID=\n" "\tdevice=LABEL=